proxylib.c

Go to the documentation of this file.
00001 
00011 /* $Id: proxylib.c,v 1.54 2007/05/07 18:59:55 yarkhan Exp $ */
00012 /* $UTK_Copyright: $ */
00013 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif /* HAVE_CONFIG_H */
00017 
00018 /* Solaris needs this */
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              /* KERBEROS5 */
00035 
00036 #ifndef INADDR_NONE
00037 #define INADDR_NONE ((unsigned int) 0xffffffff)
00038 #endif
00039 
00040 /* This structure holds information about the connection */
00041 PROXY_COMPONENTADDR localInfo;
00042 
00043 /* This structure holds information about local bindings */
00044 PROXY_BINDING * bindInfo;
00045 
00046 /* global errno */
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     /* Form control collection with proxy */
00332     /* connect to proxy and form control connection */
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     /* send my ID to proxy */
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     /* send the bind port to proxy */
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         /* check whether we've recently received a keepalive */
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       /* Need to go through proxy */
00471       
00472 #ifdef PROXY_DEBUG
00473       fprintf(stderr,"proxy_accept: reading tag from proxy\n");
00474 #endif
00475       
00476       /* read message from proxy */
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       /* read client ID from proxy */
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       /* read client port from proxy */
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       /* connect to proxy */
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       /* send client's ID to proxy */
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       /* else if it was not the control sock we got a connection on, then 
00602        * fall through and do a normal accept below.
00603        */
00604     }
00605     else {
00606       /* neither of the descriptors are ready for reading, which seems like
00607        * a bad thing.
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   /* read client ID from proxy */
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   /* read dest ID from proxy */
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   /* read dest port from proxy */
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     /* if successful, return now */
00728     if(rv >= 0)
00729       return rv;
00730 
00731     /* if not successful, but not proxied, return now */
00732     if(localInfo.proxyIP == 0)
00733       return rv;
00734  
00735     /* if not successful, not proxied, and EINTR, return now */
00736     if((rv < 0) && ((errno=errno_socket()) == EINTR))
00737       return rv;
00738 
00739     /* If we reach here, then this server is proxied and 
00740      * proxy_accept() failed for some reason other than EINTR.
00741      * Thus we need to try to reconnect to the proxy server.
00742      * First close the old control socket descriptor so we don't
00743      * build up a lot of unused descriptors.
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   /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
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     /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); fflush(NULL); */
00797     
00798     ret_val = proxy_connect_nonb(s, (struct sockaddr *) (&addr), 
00799                  sizeof(addr), PROXY_CONN_TIMEOUT);
00800 
00801     /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
00802     if(ret_val < 0) {
00803       perror("proxy_connect: connect");
00804       return -1;
00805     }
00806 
00807     /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
00808     if(proxy_do_auth(name->proxyIP, s) < 0)
00809       return -1;
00810   }
00811   else {
00812     /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
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     /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
00825   }
00826 
00827   /* send some stuff over the connection */
00828 
00829   /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
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     /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
00838     perror("proxy_connect: write");
00839     close_socket(s);
00840     return -1;
00841   }
00842 
00843   /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
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   /* wait for reply from proxy */
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   /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
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     /* The EWOULDBLOCK may be WIN32 specific */
00947     if (errno != EINPROGRESS && errno != EWOULDBLOCK )
00948       return -1;
00949   }
00950 
00951   /* Do whatever we want while the connect is taking place. */
00952 
00953   if (n == 0)
00954     goto done;      /* connect completed immediately */
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);          /* timeout */
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;                     /* Solaris pending error */
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) { /* restore file status flags */
00998     errno = EIO;
00999     return -1;
01000   }
01001 #endif
01002 
01003   if(error) {
01004     close_socket(sockfd);          /* just in case */
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    * check for authentication-specific error codes here
01093    * before falling through to the problem-specific error codes
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   /* int const MAXLEN = 256; */
01158   char line[MAXLEN];
01159   char proxy_string[MAXLEN];
01160   char proxy_port_string[MAXLEN];
01161   FILE *fconfig;
01162   struct hostent *hp;
01163 
01164   /* generate an ID */
01165   proxy_get_id(localInfo.ID);
01166 
01167   /* default to no proxy */
01168   strcpy(proxy_string, "0");
01169   strcpy(proxy_port_string, "0");
01170 
01171   if ((strlen(configFile) >= 1) &&
01172       (fconfig = fopen(configFile, "r")) != NULL) {
01173     /* get parameters from config file */
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     /* Get proxy from environment */
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   /* store proxy IP */
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   /* store proxy port */
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   /* get my IP */
01220   localInfo.IP = proxy_get_my_ipaddr();
01221 
01222   if (localInfo.proxyIP != 0) {
01223     /* intialize bindinfo */
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   /* clear out destination */
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   /* all ones will match any component ID */
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 }