00001
00011
00012
00013
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017
00018
00019 #ifdef SOLARIS
00020 #define BSD_COMP
00021 #endif
00022
00023 #include <stdlib.h>
00024 #include <errno.h>
00025
00026 #include "portability.h"
00027 #include "utility.h"
00028 #include "proxylib.h"
00029
00030 #ifdef KERBEROS5
00031 #include "krb5auth.h"
00032 #include <krb5.h>
00033 #include <com_err.h>
00034 #endif
00035
00036 #ifndef INADDR_NONE
00037 #define INADDR_NONE ((unsigned int) 0xffffffff)
00038 #endif
00039
00040
00041 PROXY_COMPONENTADDR localInfo;
00042
00043
00044 PROXY_BINDING * bindInfo;
00045
00046
00047 extern int errno;
00048
00049 int proxy_get_fd_limit();
00050
00057 void
00058 proxy_get_id(char *cp)
00059 {
00060 struct timeval tv;
00061 int i;
00062
00063 if (!cp)
00064 return;
00065
00066 gettimeofday(&tv, NULL);
00067
00068 srandom(tv.tv_usec);
00069
00070 for(i=0;i<CID_LEN;i++)
00071 cp[i] = random() % 256;
00072 }
00073
00078 void
00079 proxy_print_local_info()
00080 {
00081 printf("Proxy IP port: %u %d\n",
00082 (unsigned int)localInfo.proxyIP, ntohs(localInfo.proxyPort));
00083 printf("My ID IP: ");
00084 proxy_print_componentID(stdout, localInfo.ID);
00085 printf(" %d\n", (int)localInfo.IP);
00086 }
00087
00095 void
00096 proxy_print_componentID(FILE * f, char *id)
00097 {
00098 int i;
00099
00100 for (i = 0; i < CID_LEN; i++)
00101 fprintf(f, "%x%x", (id[i] >> 4) & 0x0F, id[i] & 0x0F);
00102 }
00103
00110 PROXY_COMPONENTADDR
00111 proxy_get_local_addr()
00112 {
00113 return localInfo;
00114 }
00115
00122 ipaddr_t
00123 proxy_get_proxy_ip()
00124 {
00125 return localInfo.proxyIP;
00126 }
00127
00136 int
00137 proxy_set_cid_from_str(char *id)
00138 {
00139 return proxy_str_to_cid(localInfo.ID, id);
00140 }
00141
00148 in_port_t
00149 proxy_get_proxy_port()
00150 {
00151 return localInfo.proxyPort;
00152 }
00153
00165 SOCKET
00166 proxy_socket(int domain, int type, int protocol)
00167 {
00168 return socket(domain, type, protocol);
00169 }
00170
00182 int
00183 proxy_bind(SOCKET s, const struct sockaddr *name, int namelen)
00184 {
00185 struct sockaddr_in *sockin;
00186 int i;
00187 int ret_val;
00188
00189 ret_val = bind(s, name, namelen);
00190
00191 if (localInfo.proxyIP != 0) {
00192
00193 #ifdef WIN32
00194 if (s == INVALID_SOCKET) {
00195 #else
00196 if (s < 0 || s > proxy_get_fd_limit()) {
00197 #endif
00198 errno = EBADF;
00199 return -1;
00200 }
00201
00202 i = 0;
00203 while (bindInfo[i].sock != INVALID_SOCKET) {
00204 if (s == bindInfo[i].sock) {
00205 errno = EINVAL;
00206 return -1;
00207 }
00208 i++;
00209 }
00210 bindInfo[i].sock = s;
00211 sockin = (struct sockaddr_in *) name;
00212
00213 if(sockin->sin_port == 0) {
00214 struct sockaddr_in addr;
00215 socklen_t addr_length;
00216
00217 addr_length = sizeof(addr);
00218
00219 if ((getsockname(s, (struct sockaddr *) &addr, &addr_length)) == -1) {
00220 errno = EINVAL;
00221 return -1;
00222 }
00223 bindInfo[i].port = addr.sin_port;
00224 }
00225 else
00226 bindInfo[i].port = sockin->sin_port;
00227
00228 bindInfo[i + 1].sock = INVALID_SOCKET;
00229
00230 return 0;
00231 }
00232 return ret_val;
00233 }
00234
00245 int
00246 proxy_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
00247 {
00248 int i;
00249
00250 if(getsockname(s, name, namelen) < 0)
00251 return -1;
00252
00253 if (localInfo.proxyIP != 0) {
00254 i = 0;
00255 while(bindInfo[i].sock != INVALID_SOCKET) {
00256 if(s == bindInfo[i].sock)
00257 break;
00258 i++;
00259 }
00260
00261 if(bindInfo[i].sock == INVALID_SOCKET) {
00262 errno = EINVAL;
00263 return -1;
00264 }
00265
00266 ((struct sockaddr_in *)name)->sin_port = bindInfo[i].port;
00267 }
00268
00269 return 0;
00270 }
00271
00284 int
00285 proxy_listen(SOCKET s, int backlog)
00286 {
00287 proxy_tag_t tag;
00288 int ret_val;
00289 struct sockaddr_in proxyaddr;
00290
00291 ret_val = listen(s, backlog);
00292
00293 if (localInfo.proxyIP != 0) {
00294 int i, flag = 1;
00295
00296 #ifdef WIN32
00297 if (s == INVALID_SOCKET) {
00298 #else
00299 if (s < 0 || s > proxy_get_fd_limit()) {
00300 #endif
00301 errno = EBADF;
00302 return -1;
00303 }
00304
00305 i = 0;
00306 while (bindInfo[i].sock != INVALID_SOCKET) {
00307 if (s == bindInfo[i].sock) {
00308 break;
00309 }
00310 i++;
00311 }
00312
00313 if (bindInfo[i].sock == INVALID_SOCKET) {
00314 errno = EINVAL;
00315 return -1;
00316 }
00317
00318 bindInfo[i].control_sock = socket(AF_INET, SOCK_STREAM, 0);
00319
00320 setsockopt(bindInfo[i].control_sock, IPPROTO_TCP, TCP_NODELAY,
00321 (char *) &flag, sizeof(int));
00322
00323 proxyaddr.sin_family = AF_INET;
00324 proxyaddr.sin_addr.s_addr = localInfo.proxyIP;
00325 proxyaddr.sin_port = localInfo.proxyPort;
00326
00327 #ifdef PROXY_DEBUG
00328 fprintf(stderr,"listen: addr = %d\n", (int)localInfo.proxyIP);
00329 fprintf(stderr,"listen: port = %d\n", (int)ntohs(localInfo.proxyPort));
00330 #endif
00331
00332
00333
00334 ret_val = proxy_connect_nonb(bindInfo[i].control_sock,
00335 (struct sockaddr *) (&proxyaddr), sizeof(proxyaddr), PROXY_CONN_TIMEOUT);
00336
00337 if (ret_val < 0) {
00338 perror("proxy_listen: connect1");
00339 return -1;
00340 }
00341
00342 if (proxy_do_auth(localInfo.proxyIP, bindInfo[i].control_sock) < 0)
00343 return -1;
00344
00345 tag = PROXY_CONTROL_CONNECTION;
00346 ret_val = write_socket(bindInfo[i].control_sock, &tag, sizeof(tag));
00347 if (ret_val == SOCKET_ERROR) {
00348 perror("proxy_listen: write");
00349 return -1;
00350 }
00351
00352
00353 ret_val = write_socket(bindInfo[i].control_sock, localInfo.ID, CID_LEN);
00354 if (ret_val == SOCKET_ERROR) {
00355 perror("proxy_listen: write");
00356 return -1;
00357 }
00358
00359
00360 ret_val = write_socket(bindInfo[i].control_sock, (char *)&(bindInfo[i].port),
00361 sizeof(bindInfo[i].port));
00362 if (ret_val == SOCKET_ERROR) {
00363 perror("proxy_listen: write");
00364 return -1;
00365 }
00366
00367 return 0;
00368 }
00369
00370 return ret_val;
00371 }
00372
00385 int
00386 proxy_accept_x(SOCKET s, struct sockaddr *addr, socklen_t * addrlen)
00387 {
00388 struct timeval last_keepalive, tv_timeout;
00389 int ret_val, maxfd;
00390 SOCKET connfd;
00391 int i = -1;
00392 fd_set rset;
00393 proxy_tag_t tag;
00394 in_port_t clientPort;
00395 char clientID[CID_LEN];
00396 struct sockaddr_in proxyaddr;
00397 char destID[CID_LEN];
00398 in_port_t destPort;
00399 SOCKET c = INVALID_SOCKET;
00400
00401 last_keepalive.tv_sec = 0;
00402 last_keepalive.tv_usec = 0;
00403
00404 if (localInfo.proxyIP != 0) {
00405
00406 #ifdef WIN32
00407 if (s == INVALID_SOCKET) {
00408 #else
00409 if (s < 0 || s > proxy_get_fd_limit()) {
00410 #endif
00411 errno = EBADF;
00412 return -1;
00413 }
00414
00415 i = 0;
00416 while (bindInfo[i].sock != INVALID_SOCKET) {
00417 if (s == bindInfo[i].sock) {
00418 break;
00419 }
00420 i++;
00421 }
00422
00423 if (bindInfo[i].sock == INVALID_SOCKET) {
00424 errno = EINVAL;
00425 return -1;
00426 }
00427
00428 if (s > bindInfo[i].control_sock) {
00429 maxfd = s;
00430 } else {
00431 maxfd = bindInfo[i].control_sock;
00432 }
00433
00434 do {
00435 FD_ZERO(&rset);
00436 FD_SET(s, &rset);
00437 FD_SET(bindInfo[i].control_sock, &rset);
00438
00439 tv_timeout.tv_sec = PROXY_KEEPALIVE_FREQ;
00440 tv_timeout.tv_usec = 0;
00441
00442 ret_val = select(maxfd + 1, &rset, NULL, NULL, &tv_timeout);
00443
00444 if(ret_val == 0) {
00445
00446
00447 if(last_keepalive.tv_sec > 0) {
00448 long time_since_keepalive;
00449
00450 gettimeofday(&tv_timeout, NULL);
00451 time_since_keepalive = tv_timeout.tv_sec - last_keepalive.tv_sec;
00452
00453 if(time_since_keepalive > PROXY_KEEPALIVE_FREQ * 2) {
00454 printf("have not received a keepalive from the proxy recently.\n");
00455 errno = EIO;
00456 return -1;
00457 }
00458 }
00459 }
00460 } while((ret_val == 0) || ((ret_val == -1) && (errno_socket() == EINTR)));
00461
00462 if(ret_val < 0) {
00463 perror("proxy_accept_x: select");
00464 errno = EIO;
00465 return -1;
00466 }
00467
00468 if(FD_ISSET(bindInfo[i].control_sock, &rset)) {
00469 int flag = 1;
00470
00471
00472 #ifdef PROXY_DEBUG
00473 fprintf(stderr,"proxy_accept: reading tag from proxy\n");
00474 #endif
00475
00476
00477 ret_val = proxy_tread(bindInfo[i].control_sock, (char *)&tag,
00478 sizeof(tag), PROXY_TIMEOUT_DEFAULT);
00479 if (ret_val < 0) {
00480 perror("proxy_accept_x: read5");
00481 errno = EIO;
00482 return -1;
00483 }
00484 #ifdef PROXY_DEBUG
00485 fprintf(stderr,"proxy_accept: tag = %d\n", tag);
00486 #endif
00487 if (tag == PROXY_KEEPALIVE) {
00488 gettimeofday(&last_keepalive, NULL);
00489 ret_val = write_socket(bindInfo[i].control_sock, &tag, sizeof(tag));
00490 if (ret_val == SOCKET_ERROR)
00491 perror("proxy_accept_x: write");
00492 errno = EINTR;
00493 return -1;
00494 }
00495
00496 if (tag != PROXY_CONNECT_REQUEST) {
00497 errno = EIO;
00498 return -1;
00499 }
00500 #ifdef PROXY_DEBUG
00501 fprintf(stderr,"proxy_accept: read client ID from proxy\n");
00502 #endif
00503
00504 ret_val = proxy_tread(bindInfo[i].control_sock, clientID,
00505 sizeof(clientID), PROXY_TIMEOUT_DEFAULT);
00506 if (ret_val < 0) {
00507 perror("proxy_accept_x: read6");
00508 errno = EIO;
00509 return -1;
00510 }
00511 #ifdef PROXY_DEBUG
00512 fprintf(stderr,"proxy_accept: read client port from proxy\n");
00513 #endif
00514
00515 ret_val = proxy_tread(bindInfo[i].control_sock, (char *)&clientPort,
00516 sizeof(clientPort), PROXY_TIMEOUT_DEFAULT);
00517 if (ret_val < 0) {
00518 perror("proxy_accept_x: read7");
00519 errno = EIO;
00520 return -1;
00521 }
00522
00523
00524 memset(&proxyaddr, 0, sizeof(proxyaddr));
00525 proxyaddr.sin_family = AF_INET;
00526 proxyaddr.sin_port = clientPort;
00527 proxyaddr.sin_addr.s_addr = localInfo.proxyIP;
00528
00529 connfd = socket(AF_INET, SOCK_STREAM, 0);
00530
00531 setsockopt(bindInfo[i].control_sock, IPPROTO_TCP, TCP_NODELAY,
00532 (char *) &flag, sizeof(int));
00533
00534 #ifdef PROXY_DEBUG
00535 fprintf(stderr,"proxy_accept: connect to proxy on 2nd port\n");
00536 #endif
00537 ret_val = proxy_connect_nonb(connfd, (struct sockaddr *) (&proxyaddr),
00538 sizeof(proxyaddr), PROXY_CONN_TIMEOUT);
00539 if (ret_val < 0) {
00540
00541 perror("proxy_accept_x: connect2");
00542 errno = EIO;
00543 return -1;
00544 }
00545
00546 if (proxy_do_auth(localInfo.proxyIP, connfd) < 0) {
00547 errno = EIO;
00548 return -1;
00549 }
00550
00551 #ifdef PROXY_DEBUG
00552 fprintf(stderr,"proxy_accept: sending reply\n");
00553 #endif
00554 tag = PROXY_CONNECT_REPLY;
00555 ret_val = write_socket(connfd, &tag, sizeof(tag));
00556 if (ret_val == SOCKET_ERROR) {
00557 perror("proxy_accept_x: write");
00558 errno = EIO;
00559 return -1;
00560 }
00561 #ifdef PROXY_DEBUG
00562 fprintf(stderr,"proxy_accept: send client's ID to proxy\n");
00563 #endif
00564
00565 ret_val = write_socket(connfd, clientID, sizeof(clientID));
00566 if (ret_val == SOCKET_ERROR) {
00567 perror("proxy_accept_x: write");
00568 errno = EIO;
00569 return -1;
00570 }
00571 #ifdef PROXY_DEBUG
00572 fprintf(stderr,"proxy_accept: write client port to proxy\n");
00573 #endif
00574 ret_val = write_socket(connfd, (char *)&clientPort, sizeof(clientPort));
00575 if (ret_val == SOCKET_ERROR) {
00576 perror("proxy_accept_x: write");
00577 errno = EIO;
00578 return -1;
00579 }
00580 #ifdef PROXY_DEBUG
00581 fprintf(stderr,"proxy_accept: going to read tag (%d bytes) from proxy\n", sizeof(tag));
00582 #endif
00583 ret_val = proxy_tread(connfd, (char *)&tag, sizeof(tag),
00584 PROXY_TIMEOUT_DEFAULT);
00585 if (ret_val < 0) {
00586 perror("proxy_accept_x: read8");
00587 errno = EIO;
00588 return -1;
00589 }
00590 #ifdef PROXY_DEBUG
00591 fprintf(stderr,"proxy_accept: tag = %d\n", tag);
00592 #endif
00593 if (tag == PROXY_CONNECTION_REFUSED) {
00594 errno = ECONNABORTED;
00595 return -1;
00596 }
00597
00598 return connfd;
00599 }
00600 else if(FD_ISSET(s, &rset)) {
00601
00602
00603
00604 }
00605 else {
00606
00607
00608
00609 errno = ECONNABORTED;
00610 return -1;
00611 }
00612 }
00613
00614 c = accept(s, addr, addrlen);
00615
00616 if (c == INVALID_SOCKET)
00617 return c;
00618
00619 #ifdef PROXY_DEBUG
00620 fprintf(stderr,"proxy_accept: reading tag from proxy\n");
00621 #endif
00622
00623 ret_val = proxy_tread(c, (char *) &tag, sizeof(tag), PROXY_TIMEOUT_DEFAULT);
00624 if (ret_val < 0) {
00625 proxy_close(c);
00626 perror("proxy_accept_x: read1");
00627 errno = EIO;
00628 return -1;
00629 }
00630 #ifdef PROXY_DEBUG
00631 fprintf(stderr,"proxy_accept: tag = %d\n", tag);
00632 #endif
00633
00634 if (tag != PROXY_CONNECT) {
00635 errno = EIO;
00636 return -1;
00637 }
00638 #ifdef PROXY_DEBUG
00639 fprintf(stderr,"proxy_accept: read client ID from proxy\n");
00640 #endif
00641
00642
00643 ret_val = proxy_tread(c, clientID, sizeof(clientID), PROXY_TIMEOUT_DEFAULT);
00644 if (ret_val < 0) {
00645 proxy_close(c);
00646 perror("proxy_accept_x: read2");
00647 errno = EIO;
00648 return -1;
00649 }
00650 #ifdef PROXY_DEBUG
00651 fprintf(stderr,"proxy_accept: read dest ID from proxy\n");
00652 #endif
00653
00654
00655 ret_val = proxy_tread(c, destID, sizeof(destID), PROXY_TIMEOUT_DEFAULT);
00656 if (ret_val < 0) {
00657 proxy_close(c);
00658 perror("proxy_accept_x: read3");
00659 errno = EIO;
00660 return -1;
00661 }
00662
00663 #ifdef PROXY_DEBUG
00664 fprintf(stderr,"proxy_accept: read dest port from proxy\n");
00665 #endif
00666
00667
00668 ret_val = proxy_tread(c, (char *)&destPort, sizeof(destPort),
00669 PROXY_TIMEOUT_DEFAULT);
00670 if (ret_val < 0) {
00671 proxy_close(c);
00672 perror("proxy_accept_x: read4");
00673 errno = EIO;
00674 return -1;
00675 }
00676 #ifdef PROXY_DEBUG
00677 fprintf(stderr,"proxy_accept: checking IDs/sending reply\n");
00678 fprintf(stderr,"local ID = ");
00679 proxy_print_componentID(stdout, localInfo.ID);
00680 fprintf(stderr,"\ndest ID = ");
00681 proxy_print_componentID(stdout, destID);
00682 fprintf(stderr,"\n");
00683 #endif
00684
00685 if (proxy_cidcmp(localInfo.ID, destID)) {
00686 fprintf(stderr,"proxy_accept: Dest ID does not match!\n");
00687
00688 tag = PROXY_CONNECTION_REFUSED;
00689 write_socket(c, &tag, sizeof(tag));
00690 proxy_close(c);
00691 errno = EIO;
00692 return -1;
00693 }
00694
00695 tag = PROXY_CONNECTION_ACCEPTED;
00696 ret_val = write_socket(c, &tag, sizeof(tag));
00697 if (ret_val == SOCKET_ERROR) {
00698 proxy_close(c);
00699 perror("proxy_accept_x: write");
00700 errno = EIO;
00701 return -1;
00702 }
00703
00704 return c;
00705 }
00706
00719 int
00720 proxy_accept(SOCKET s, struct sockaddr *addr, socklen_t * addrlen)
00721 {
00722 int i, rv;
00723
00724 for(;;) {
00725 rv = proxy_accept_x(s, addr, addrlen);
00726
00727
00728 if(rv >= 0)
00729 return rv;
00730
00731
00732 if(localInfo.proxyIP == 0)
00733 return rv;
00734
00735
00736 if((rv < 0) && ((errno=errno_socket()) == EINTR))
00737 return rv;
00738
00739
00740
00741
00742
00743
00744
00745
00746 printf("proxy_accept failed, errno = %d\n", errno);
00747 printf("trying to reconnect to the proxy\n");
00748
00749 i = 0;
00750 while (bindInfo[i].sock != -1) {
00751 if (s == bindInfo[i].sock) {
00752 break;
00753 }
00754 i++;
00755 }
00756
00757 if(bindInfo[i].control_sock >= 0) {
00758 close(bindInfo[i].control_sock);
00759 bindInfo[i].control_sock = -1;
00760 }
00761
00762 while(proxy_listen(s, PROXY_MAX_CONNECTIONS) < 0) {
00763 printf("Warning: failed to reconnect to the proxy!\n");
00764 sleep(2);
00765 }
00766 }
00767 }
00768
00779 int
00780 proxy_connect(SOCKET s, PROXY_COMPONENTADDR * name)
00781 {
00782 proxy_tag_t tag, connect_return;
00783 int ret_val;
00784 struct sockaddr_in addr;
00785
00786
00787
00788 memset(&addr, 0, sizeof(addr));
00789 addr.sin_family = AF_INET;
00790
00791 if (name->proxyIP != 0) {
00792
00793 addr.sin_addr.s_addr = name->proxyIP;
00794 addr.sin_port = name->proxyPort;
00795
00796
00797
00798 ret_val = proxy_connect_nonb(s, (struct sockaddr *) (&addr),
00799 sizeof(addr), PROXY_CONN_TIMEOUT);
00800
00801
00802 if(ret_val < 0) {
00803 perror("proxy_connect: connect");
00804 return -1;
00805 }
00806
00807
00808 if(proxy_do_auth(name->proxyIP, s) < 0)
00809 return -1;
00810 }
00811 else {
00812
00813
00814 addr.sin_addr.s_addr = name->IP;
00815 addr.sin_port = name->port;
00816
00817 ret_val = proxy_connect_nonb(s, (struct sockaddr *) (&addr),
00818 sizeof(addr), PROXY_CONN_TIMEOUT);
00819
00820 if (ret_val < 0) {
00821 fprintf(stderr, "connect failure\n");
00822 return -1;
00823 }
00824
00825 }
00826
00827
00828
00829
00830
00831 tag = PROXY_CONNECT;
00832 #ifdef PROXY_DEBUG
00833 fprintf(stderr,"write tag %c %d %u sizeof(tag) %d \n", tag, tag, tag, sizeof(tag));
00834 #endif
00835 ret_val = write_socket(s, &tag, sizeof(tag));
00836 if (ret_val == SOCKET_ERROR) {
00837
00838 perror("proxy_connect: write");
00839 close_socket(s);
00840 return -1;
00841 }
00842
00843
00844 #ifdef PROXY_DEBUG
00845 fprintf(stderr,"write my id\n");
00846 #endif
00847 ret_val = write_socket(s, localInfo.ID, sizeof(localInfo.ID));
00848 if (ret_val == SOCKET_ERROR) {
00849 perror("proxy_connect: write");
00850 close_socket(s);
00851 return -1;
00852 }
00853 #ifdef PROXY_DEBUG
00854 fprintf(stderr,"write dest id\n");
00855 #endif
00856 ret_val = write_socket(s, name->ID, sizeof(name->ID));
00857 if (ret_val == SOCKET_ERROR) {
00858 perror("proxy_connect: write");
00859 close_socket(s);
00860 return -1;
00861 }
00862 #ifdef PROXY_DEBUG
00863 fprintf(stderr,"write dest port\n");
00864 #endif
00865 ret_val = write_socket(s, (char *)&(name->port), sizeof(name->port));
00866 if (ret_val == SOCKET_ERROR) {
00867 perror("proxy_connect: write");
00868 close_socket(s);
00869 return -1;
00870 }
00871 #ifdef PROXY_DEBUG
00872 fprintf(stderr,"wat for proxy reply\n");
00873 #endif
00874
00875 ret_val = proxy_tread(s, (char *)&connect_return, sizeof(connect_return),
00876 PROXY_TIMEOUT_DEFAULT);
00877 if (ret_val < 0) {
00878 perror("proxy_connect: read");
00879 close_socket(s);
00880 return -1;
00881 }
00882 #ifdef PROXY_DEBUG
00883 fprintf(stderr,"proxy reply = %d\n", ret_val);
00884 #endif
00885 if (connect_return == PROXY_CONNECTION_REFUSED) {
00886 errno = ECONNREFUSED;
00887 close_socket(s);
00888 return -1;
00889 }
00890
00891
00892 return 0;
00893 }
00894
00911 int
00912 proxy_connect_nonb(SOCKET sockfd, const struct sockaddr *saptr, socklen_t salen,
00913 int nsec)
00914 {
00915 int n;
00916 int error;
00917 socklen_t len;
00918 fd_set rset, wset;
00919 struct timeval tval;
00920 #ifndef WIN32
00921 int flags;
00922 #endif
00923
00924 #ifdef WIN32
00925 {
00926 ULONG NonBlock = 1;
00927 if (ioctlsocket(sockfd, FIONBIO, &NonBlock) == SOCKET_ERROR) {
00928 fprintf(stderr, "ioctlsocket() failed to set socket to non-blocking \n");
00929 return -1;
00930 }
00931 }
00932 #else
00933 {
00934 if (((flags = fcntl(sockfd, F_GETFL, 0)) < 0) ||
00935 ((fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0))) {
00936 errno = EIO;
00937 return -1;
00938 }
00939 }
00940 #endif
00941
00942 error = 0;
00943 if ( (n = connect(sockfd, saptr, salen)) == SOCKET_ERROR) {
00944 errno = errno_socket();
00945
00946
00947 if (errno != EINPROGRESS && errno != EWOULDBLOCK )
00948 return -1;
00949 }
00950
00951
00952
00953 if (n == 0)
00954 goto done;
00955
00956 do {
00957 FD_ZERO(&rset);
00958 FD_SET(sockfd, &rset);
00959
00960 wset = rset;
00961 tval.tv_sec = nsec;
00962 tval.tv_usec = 0;
00963
00964 n = select(sockfd+1, &rset, &wset, NULL, nsec ? &tval : NULL);
00965
00966 if ( n == 0) {
00967 close_socket(sockfd);
00968 errno = ETIMEDOUT;
00969 return -1;
00970 }
00971 else if ((n < 0) && ((errno=errno_socket()) != EINTR)) {
00972 close_socket(sockfd);
00973 return -1;
00974 }
00975 } while((n<0) && ((errno=errno_socket()) == EINTR));
00976
00977 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
00978 len = sizeof(error);
00979 if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) < 0)
00980 return -1;
00981 } else {
00982 fprintf(stderr,"select error: sockfd not set");
00983 errno = EIO;
00984 return -1;
00985 }
00986
00987 done:
00988 #ifdef WIN32
00989 {
00990 ULONG NonBlock = 0;
00991 if (ioctlsocket(sockfd, FIONBIO, &NonBlock) == SOCKET_ERROR) {
00992 fprintf(stderr, "ioctlsocket() failed to set socket to nonblocking \n");
00993 return -1;
00994 }
00995 }
00996 #else
00997 if (fcntl(sockfd, F_SETFL, flags) < 0) {
00998 errno = EIO;
00999 return -1;
01000 }
01001 #endif
01002
01003 if(error) {
01004 close_socket(sockfd);
01005 errno = error;
01006 return -1;
01007 }
01008
01009 return 0;
01010 }
01011
01021 int
01022 proxy_ip_to_str(ipaddr_t IP, char *dottedIP)
01023 {
01024 unsigned char *uptr = (unsigned char *)&IP;
01025
01026 if (IP == 0)
01027 strcpy(dottedIP, "0.0.0.0");
01028 else
01029 sprintf(dottedIP, "%d.%d.%d.%d", uptr[0] & 0xff, uptr[1] & 0xff,
01030 uptr[2] & 0xff, uptr[3] & 0xff);
01031
01032 return 0;
01033 }
01034
01044 int
01045 proxy_str_to_ip(ipaddr_t *IP, char *dottedIP)
01046 {
01047 unsigned int b1,b2,b3,b4;
01048 sscanf(dottedIP, "%u.%u.%u.%u", &b1,&b2,&b3,&b4);
01049 *IP = htonl((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
01050 return 0;
01051 }
01052
01062 int
01063 proxy_do_auth(ipaddr_t proxy_ip, SOCKET s)
01064 {
01065 proxy_tag_t tag;
01066 int ret_val;
01067 char proxy_host_ip[16];
01068
01069 proxy_ip_to_str(proxy_ip, proxy_host_ip);
01070
01071 ret_val = proxy_tread(s, (char *)&tag, sizeof(tag), PROXY_TIMEOUT_DEFAULT);
01072 if (ret_val < 0) {
01073 errno = ECONNRESET;
01074 return -1;
01075 }
01076 #ifdef KERBEROS5
01077 if (tag == PROXY_KRB5_AUTH_REQUIRED) {
01078 if (proxy_send_krb5_credentials(proxy_host_ip, s) < 0) {
01079 errno = EACCES;
01080 close_socket(s);
01081 return -1;
01082 }
01083 ret_val = proxy_tread(s, (char *)&tag, sizeof(tag), PROXY_TIMEOUT_DEFAULT);
01084 if (ret_val < 0) {
01085 errno = ECONNRESET;
01086 close_socket(s);
01087 return -1;
01088 }
01089 }
01090
01091
01092
01093
01094
01095 if (tag == PROXY_AUTH_FAILED) {
01096 errno = EACCES;
01097 close_socket(s);
01098 return -1;
01099 }
01100 #endif
01101
01102 if (tag == PROXY_KRB5_AUTH_REQUIRED) {
01103 errno = EACCES;
01104 close_socket(s);
01105 return -1;
01106 } else if (tag != PROXY_AUTH_ACCEPTED) {
01107 errno = EACCES;
01108 close_socket(s);
01109 return -1;
01110 }
01111
01112 return 0;
01113 }
01114
01124 int
01125 proxy_close(SOCKET fildes)
01126 {
01127 int i, found;
01128 if (localInfo.proxyIP != 0) {
01129 found = 0;
01130 i = 0;
01131 while (bindInfo[i].sock != -1) {
01132 if (fildes == bindInfo[i].sock) {
01133 found = 1;
01134 break;
01135 }
01136 i++;
01137 }
01138 if (found == 1) {
01139 close_socket(bindInfo[i].control_sock);
01140 bindInfo[i].sock = -1;
01141 }
01142 }
01143 return close_socket(fildes);
01144 }
01145
01153 void
01154 proxy_init(char *configFile)
01155 {
01156 #define MAXLEN 256
01157
01158 char line[MAXLEN];
01159 char proxy_string[MAXLEN];
01160 char proxy_port_string[MAXLEN];
01161 FILE *fconfig;
01162 struct hostent *hp;
01163
01164
01165 proxy_get_id(localInfo.ID);
01166
01167
01168 strcpy(proxy_string, "0");
01169 strcpy(proxy_port_string, "0");
01170
01171 if ((strlen(configFile) >= 1) &&
01172 (fconfig = fopen(configFile, "r")) != NULL) {
01173
01174
01175 fgets(line, MAXLEN, fconfig);
01176 while (!feof(fconfig)) {
01177 if (strncmp(line, "proxyPort", strlen("proxyPort")) == 0) {
01178 strtok(line, "=");
01179 strcpy(proxy_port_string, (char *) strtok(NULL, " "));
01180 proxy_port_string[strlen(proxy_port_string) - 1] = '\0';
01181
01182 } else if (strncmp(line, "proxy", strlen("proxy")) == 0) {
01183 strtok(line, "=");
01184 strcpy(proxy_string, strtok(NULL, " "));
01185 proxy_string[strlen(proxy_string) - 1] = '\0';
01186 }
01187 fgets(line, MAXLEN, fconfig);
01188 }
01189 fclose(fconfig);
01190
01191 } else if ((getenv("GRIDSOLVE_PROXY")) != NULL) {
01192
01193
01194 strncpy(line, getenv("GRIDSOLVE_PROXY"), MAXLEN);
01195 fprintf(stderr,"Could not open proxy config file %s \n", configFile);
01196 fprintf(stderr,"Trying environment variable GRIDSOLVE_PROXY=%s\n",line);
01197 strcpy(proxy_string, strtok(line, ":"));
01198 strcpy(proxy_port_string, strtok(NULL, ":"));
01199 }
01200
01201
01202 if (strcasecmp(proxy_string, "0") == 0) {
01203 localInfo.proxyIP = 0;
01204 } else {
01205 if ((hp = gethostbyname(proxy_string)) == NULL) {
01206 fprintf(stderr, "Could not gethostbyname for proxy %s\n", proxy_string);
01207 perror("proxy_connect: gethostbyname()");
01208 return;
01209 }
01210 memcpy((void *) &(localInfo.proxyIP), hp->h_addr_list[0], sizeof(ipaddr_t));
01211 }
01212
01213
01214 if (strcasecmp(proxy_port_string, "0") == 0) {
01215 localInfo.proxyPort = 0;
01216 } else {
01217 localInfo.proxyPort = htons(atoi((char *) strdup(proxy_port_string)));
01218 }
01219
01220 localInfo.IP = proxy_get_my_ipaddr();
01221
01222 if (localInfo.proxyIP != 0) {
01223
01224
01225 bindInfo =
01226 (PROXY_BINDING *) malloc(sizeof(PROXY_BINDING) * proxy_get_fd_limit());
01227 bindInfo[0].sock = INVALID_SOCKET;
01228 }
01229 }
01230
01240 int
01241 proxy_str_to_cid(char *dest, char *src) {
01242 int i,j;
01243
01244 if(!src || !dest)
01245 return -1;
01246
01247
01248 memset(dest, 0, CID_LEN);
01249
01250 for(i=strlen(src)-1, j=CID_LEN-1;i>=0;i-=2, j--) {
01251 char tmp[2];
01252
01253 if((src[i] == 'x') || (src[i] == 'X'))
01254 break;
01255
01256 tmp[1] = 0;
01257
01258 tmp[0] = src[i];
01259 dest[j] = (char)strtol(tmp,NULL,16);
01260
01261 if(i > 0) {
01262 tmp[0] = src[i-1];
01263 dest[j] |= (char)strtol(tmp,NULL,16) << 4;
01264 }
01265 }
01266
01267 return 0;
01268 }
01269
01270
01280 int
01281 proxy_cid_to_str(char *dest, char *src) {
01282 char temp_string[CID_LEN*2+1];
01283 int i;
01284
01285 for(i=0;i<CID_LEN;i++){
01286 sprintf(temp_string, "%x%x", (src[i] >> 4) & 0x0F, src[i] & 0x0F);
01287 if(i==0){
01288 strcpy(dest, temp_string);
01289 }
01290 else{
01291 strcat(dest, temp_string);
01292 }
01293 }
01294
01295 return 0;
01296 }
01297
01309 int
01310 proxy_cidcmp(char *src, char *dest)
01311 {
01312 char any[CID_LEN];
01313
01314
01315 memset(any, 0xFF, CID_LEN);
01316
01317 if(memcmp(any, dest, CID_LEN) == 0)
01318 return 0;
01319
01320 return memcmp(src,dest,CID_LEN);
01321 }
01322
01333 int
01334 proxy_get_fd_limit()
01335 {
01336 #ifdef WIN32
01337 return 256;
01338 #else
01339 struct rlimit rlp;
01340
01341 if(getrlimit(RLIMIT_NOFILE, &rlp) < 0)
01342 return PROXY_BIND_MAXFD;
01343
01344 if((rlp.rlim_max <= 0) || (rlp.rlim_max > PROXY_BIND_MAXFD))
01345 return PROXY_BIND_MAXFD;
01346
01347 return (int)rlp.rlim_max;
01348 #endif
01349 }