Defines | Functions | Variables

proxylib.c File Reference

#include <stdlib.h>
#include <errno.h>
#include "portability.h"
#include "utility.h"
#include "proxylib.h"
Include dependency graph for proxylib.c:

Go to the source code of this file.

Defines

#define INADDR_NONE   ((unsigned int) 0xffffffff)
#define MAXLEN   256

Functions

int proxy_get_fd_limit ()
void proxy_get_id (char *cp)
void proxy_print_local_info ()
void proxy_print_componentID (FILE *f, char *id)
PROXY_COMPONENTADDR proxy_get_local_addr ()
ipaddr_t proxy_get_proxy_ip ()
int proxy_set_cid_from_str (char *id)
in_port_t proxy_get_proxy_port ()
SOCKET proxy_socket (int domain, int type, int protocol)
int proxy_bind (SOCKET s, const struct sockaddr *name, int namelen)
int proxy_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
int proxy_listen (SOCKET s, int backlog)
int proxy_accept_x (SOCKET s, struct sockaddr *addr, socklen_t *addrlen)
int proxy_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen)
int proxy_connect (SOCKET s, PROXY_COMPONENTADDR *name)
int proxy_connect_nonb (SOCKET sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec)
int proxy_ip_to_str (ipaddr_t IP, char *dottedIP)
int proxy_str_to_ip (ipaddr_t *IP, char *dottedIP)
int proxy_do_auth (ipaddr_t proxy_ip, SOCKET s)
int proxy_close (SOCKET fildes)
void proxy_init (char *configFile)
int proxy_str_to_cid (char *dest, char *src)
int proxy_cid_to_str (char *dest, char *src)
int proxy_cidcmp (char *src, char *dest)

Variables

PROXY_COMPONENTADDR localInfo
PROXY_BINDING * bindInfo
int errno

Detailed Description

This file contains the implementation of a communications library that works in conjuction with a proxy server to allow NAT traversal. This API is meant to mimic the sockets API except that addressing is done based on globally unique component IDs rather than IP addresses, which are not unique in the presence of NATs.

Definition in file proxylib.c.


Define Documentation

#define INADDR_NONE   ((unsigned int) 0xffffffff)

Definition at line 37 of file proxylib.c.

#define MAXLEN   256

Function Documentation

int proxy_accept ( SOCKET  s,
struct sockaddr *  addr,
socklen_t *  addrlen 
)

Proxy replacement for the accept() function, which accepts a connection on a socket.

Parameters:
s -- socket to accept the connection on
addr -- filled in with the address of the connecting entity
addrlen -- length of sockaddr structure
Returns:
on success, returns the descriptor for the accepted socket. on failure, returns -1.

Definition at line 720 of file proxylib.c.

{
  int i, rv;

  for(;;) {
    rv = proxy_accept_x(s, addr, addrlen);

    /* if successful, return now */
    if(rv >= 0)
      return rv;

    /* if not successful, but not proxied, return now */
    if(localInfo.proxyIP == 0)
      return rv;
 
    /* if not successful, not proxied, and EINTR, return now */
    if((rv < 0) && ((errno=errno_socket()) == EINTR))
      return rv;

    /* If we reach here, then this server is proxied and 
     * proxy_accept() failed for some reason other than EINTR.
     * Thus we need to try to reconnect to the proxy server.
     * First close the old control socket descriptor so we don't
     * build up a lot of unused descriptors.
     */

    printf("proxy_accept failed, errno = %d\n", errno);
    printf("trying to reconnect to the proxy\n");

    i = 0;
    while (bindInfo[i].sock != -1) {
      if (s == bindInfo[i].sock) {
        break;
      }
      i++;
    }

    if(bindInfo[i].control_sock >= 0) {
      close(bindInfo[i].control_sock);
      bindInfo[i].control_sock = -1;
    }

    while(proxy_listen(s, PROXY_MAX_CONNECTIONS) < 0) {
      printf("Warning: failed to reconnect to the proxy!\n");
      sleep(2);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_accept_x ( SOCKET  s,
struct sockaddr *  addr,
socklen_t *  addrlen 
)

Proxy replacement for the accept() function, which accepts a connection on a socket.

Parameters:
s -- socket to accept the connection on
addr -- filled in with the address of the connecting entity
addrlen -- length of sockaddr structure
Returns:
on success, returns the descriptor for the accepted socket. on failure, returns -1.

Definition at line 386 of file proxylib.c.

{
  struct timeval last_keepalive, tv_timeout;
  int ret_val, maxfd;
  SOCKET connfd;
  int i = -1;
  fd_set rset;
  proxy_tag_t tag;
  in_port_t clientPort;
  char clientID[CID_LEN];
  struct sockaddr_in proxyaddr;
  char destID[CID_LEN];
  in_port_t destPort;
  SOCKET c = INVALID_SOCKET;
  
  last_keepalive.tv_sec = 0;
  last_keepalive.tv_usec = 0;

  if (localInfo.proxyIP != 0) {

#ifdef WIN32
    if (s == INVALID_SOCKET) {
#else
   if (s < 0 || s > proxy_get_fd_limit()) {
#endif
     errno = EBADF;
     return -1;
   }
   
   i = 0;
   while (bindInfo[i].sock != INVALID_SOCKET) {
     if (s == bindInfo[i].sock) {
       break;
     }
     i++;
   }
   
    if (bindInfo[i].sock == INVALID_SOCKET) {
      errno = EINVAL;
      return -1;
    }

    if (s > bindInfo[i].control_sock) {
      maxfd = s;
    } else {
      maxfd = bindInfo[i].control_sock;
    }

    do {
      FD_ZERO(&rset);
      FD_SET(s, &rset);
      FD_SET(bindInfo[i].control_sock, &rset);

      tv_timeout.tv_sec = PROXY_KEEPALIVE_FREQ;
      tv_timeout.tv_usec = 0;

      ret_val = select(maxfd + 1, &rset, NULL, NULL, &tv_timeout);

      if(ret_val == 0) {
        /* check whether we've recently received a keepalive */

        if(last_keepalive.tv_sec > 0) {
          long time_since_keepalive;
  
          gettimeofday(&tv_timeout, NULL);
          time_since_keepalive = tv_timeout.tv_sec - last_keepalive.tv_sec;
  
          if(time_since_keepalive > PROXY_KEEPALIVE_FREQ * 2) {
            printf("have not received a keepalive from the proxy recently.\n");
            errno = EIO;
            return -1;
          }
        }
      }
    } while((ret_val == 0) || ((ret_val == -1) && (errno_socket() == EINTR)));

    if(ret_val < 0) {
      perror("proxy_accept_x: select");
      errno = EIO;
      return -1;
    }

    if(FD_ISSET(bindInfo[i].control_sock, &rset)) {
      int flag = 1;
      /* Need to go through proxy */
      
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: reading tag from proxy\n");
#endif
      
      /* read message from proxy */
      ret_val = proxy_tread(bindInfo[i].control_sock, (char *)&tag, 
                sizeof(tag), PROXY_TIMEOUT_DEFAULT);
      if (ret_val < 0) {
        perror("proxy_accept_x: read5");
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: tag = %d\n", tag);
#endif
      if (tag == PROXY_KEEPALIVE) {
        gettimeofday(&last_keepalive, NULL);
        ret_val = write_socket(bindInfo[i].control_sock, &tag, sizeof(tag));
        if (ret_val == SOCKET_ERROR)
          perror("proxy_accept_x: write");
        errno = EINTR;
        return -1;
      }

      if (tag != PROXY_CONNECT_REQUEST) {
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: read client ID from proxy\n");
#endif
      /* read client ID from proxy */
      ret_val = proxy_tread(bindInfo[i].control_sock, clientID, 
         sizeof(clientID), PROXY_TIMEOUT_DEFAULT);
      if (ret_val < 0) {
        perror("proxy_accept_x: read6");
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: read client port from proxy\n");
#endif
      /* read client port from proxy */
      ret_val = proxy_tread(bindInfo[i].control_sock, (char *)&clientPort, 
         sizeof(clientPort), PROXY_TIMEOUT_DEFAULT);
      if (ret_val < 0) {
        perror("proxy_accept_x: read7");
        errno = EIO;
        return -1;
      }

      /* connect to proxy */
      memset(&proxyaddr, 0, sizeof(proxyaddr));
      proxyaddr.sin_family = AF_INET;
      proxyaddr.sin_port = clientPort;
      proxyaddr.sin_addr.s_addr = localInfo.proxyIP;

      connfd = socket(AF_INET, SOCK_STREAM, 0);

      setsockopt(bindInfo[i].control_sock, IPPROTO_TCP, TCP_NODELAY, 
          (char *) &flag, sizeof(int));

#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: connect to proxy on 2nd port\n");
#endif
      ret_val = proxy_connect_nonb(connfd, (struct sockaddr *) (&proxyaddr), 
         sizeof(proxyaddr), PROXY_CONN_TIMEOUT);
      if (ret_val < 0) {

        perror("proxy_accept_x: connect2");
        errno = EIO;
        return -1;
      }

      if (proxy_do_auth(localInfo.proxyIP, connfd) < 0) {
        errno = EIO;
        return -1;
      }

#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: sending reply\n");
#endif
      tag = PROXY_CONNECT_REPLY;
      ret_val = write_socket(connfd, &tag, sizeof(tag));
      if (ret_val == SOCKET_ERROR) {
        perror("proxy_accept_x: write");
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: send client's ID to proxy\n");
#endif
      /* send client's ID to proxy */
      ret_val = write_socket(connfd, clientID, sizeof(clientID));
      if (ret_val == SOCKET_ERROR) {
        perror("proxy_accept_x: write");
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: write client port to proxy\n");
#endif
      ret_val = write_socket(connfd, (char *)&clientPort, sizeof(clientPort));
      if (ret_val == SOCKET_ERROR) {
        perror("proxy_accept_x: write");
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: going to read tag (%d bytes) from proxy\n", sizeof(tag));
#endif
      ret_val = proxy_tread(connfd, (char *)&tag, sizeof(tag), 
         PROXY_TIMEOUT_DEFAULT);
      if (ret_val < 0) {
        perror("proxy_accept_x: read8");
        errno = EIO;
        return -1;
      }
#ifdef PROXY_DEBUG
      fprintf(stderr,"proxy_accept: tag = %d\n", tag);
#endif
      if (tag == PROXY_CONNECTION_REFUSED) {
        errno = ECONNABORTED;
        return -1;
      }

      return connfd;
    }
    else if(FD_ISSET(s, &rset)) {
      /* else if it was not the control sock we got a connection on, then 
       * fall through and do a normal accept below.
       */
    }
    else {
      /* neither of the descriptors are ready for reading, which seems like
       * a bad thing.
       */
      errno = ECONNABORTED;
      return -1;
    }
  }
    
  c = accept(s, addr, addrlen);

  if (c == INVALID_SOCKET)
    return c;

#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy_accept: reading tag from proxy\n");
#endif

  ret_val = proxy_tread(c, (char *) &tag, sizeof(tag), PROXY_TIMEOUT_DEFAULT);
  if (ret_val < 0) {
    proxy_close(c);
    perror("proxy_accept_x: read1");
    errno = EIO;
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy_accept: tag = %d\n", tag);
#endif

  if (tag != PROXY_CONNECT) {
    errno = EIO;
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy_accept: read client ID from proxy\n");
#endif

  /* read client ID from proxy */
  ret_val = proxy_tread(c, clientID, sizeof(clientID), PROXY_TIMEOUT_DEFAULT);
  if (ret_val < 0) {
    proxy_close(c);
    perror("proxy_accept_x: read2");
    errno = EIO;
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy_accept: read dest ID from proxy\n");
#endif

  /* read dest ID from proxy */
  ret_val = proxy_tread(c, destID, sizeof(destID), PROXY_TIMEOUT_DEFAULT);
  if (ret_val < 0) {
    proxy_close(c);
    perror("proxy_accept_x: read3");
    errno = EIO;
    return -1;
  }

#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy_accept: read dest port from proxy\n");
#endif

  /* read dest port from proxy */
  ret_val = proxy_tread(c, (char *)&destPort, sizeof(destPort), 
      PROXY_TIMEOUT_DEFAULT);
  if (ret_val < 0) {
    proxy_close(c);
    perror("proxy_accept_x: read4");
    errno = EIO;
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy_accept: checking IDs/sending reply\n");
  fprintf(stderr,"local ID = ");
  proxy_print_componentID(stdout, localInfo.ID);
  fprintf(stderr,"\ndest ID = ");
  proxy_print_componentID(stdout, destID);
  fprintf(stderr,"\n");
#endif

  if (proxy_cidcmp(localInfo.ID, destID)) {
    fprintf(stderr,"proxy_accept: Dest ID does not match!\n");

    tag = PROXY_CONNECTION_REFUSED;
    write_socket(c, &tag, sizeof(tag));
    proxy_close(c);
    errno = EIO;
    return -1;
  }

  tag = PROXY_CONNECTION_ACCEPTED;
  ret_val = write_socket(c, &tag, sizeof(tag));
  if (ret_val == SOCKET_ERROR) {
    proxy_close(c);
    perror("proxy_accept_x: write");
    errno = EIO;
    return -1;
  }

  return c;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_bind ( SOCKET  s,
const struct sockaddr *  name,
int  namelen 
)

Proxy replacement for the bind() function, which binds a name to a socket.

Parameters:
s -- the socket to bind
name -- the local address for the socket
namelen -- length of the local address in bytes
Returns:
0 on success, -1 on failure (errno is set).

Definition at line 183 of file proxylib.c.

{
  struct sockaddr_in *sockin;
  int i;
  int ret_val;

  ret_val = bind(s, name, namelen);

  if (localInfo.proxyIP != 0) {

#ifdef WIN32
    if (s == INVALID_SOCKET) {
#else
    if (s < 0 || s > proxy_get_fd_limit()) {
#endif
      errno = EBADF;
      return -1;
    }

    i = 0;
    while (bindInfo[i].sock != INVALID_SOCKET) {
      if (s == bindInfo[i].sock) {
    errno = EINVAL;
    return -1;
      }
      i++;
    }
    bindInfo[i].sock = s;
    sockin = (struct sockaddr_in *) name;

    if(sockin->sin_port == 0) {
      struct sockaddr_in addr;
      socklen_t addr_length;
 
      addr_length = sizeof(addr);

      if ((getsockname(s, (struct sockaddr *) &addr, &addr_length)) == -1) {
    errno = EINVAL;
    return -1;
      }
      bindInfo[i].port = addr.sin_port;
    }
    else
      bindInfo[i].port = sockin->sin_port;

    bindInfo[i + 1].sock = INVALID_SOCKET;

    return 0;
  }
  return ret_val;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_cid_to_str ( char *  dest,
char *  src 
)

Convert componentID (src CID_LEN) to a string (dest CID_LEN*2+1)

Parameters:
dest -- the string representation of the component ID (set on return)
src -- the binary component ID
Returns:
0 on success, -1 on failure

Definition at line 1281 of file proxylib.c.

                                        {
  char temp_string[CID_LEN*2+1];
  int i;

  for(i=0;i<CID_LEN;i++){
    sprintf(temp_string, "%x%x", (src[i] >> 4) & 0x0F, src[i] & 0x0F);
    if(i==0){
      strcpy(dest, temp_string);
    }
    else{
      strcat(dest, temp_string);
    }
  }

  return 0;
}

Here is the caller graph for this function:

int proxy_cidcmp ( char *  src,
char *  dest 
)

Compares two component IDs.

Parameters:
src -- component ID to compare
dest -- component ID to compare
Returns:
0 if the component IDs match, otherwise returns a non-zero number (see the man page for memcmp for details).

Definition at line 1310 of file proxylib.c.

{
  char any[CID_LEN];

  /* all ones will match any component ID */
  memset(any, 0xFF, CID_LEN);

  if(memcmp(any, dest, CID_LEN) == 0)
    return 0;

  return memcmp(src,dest,CID_LEN);
}

Here is the caller graph for this function:

int proxy_close ( SOCKET  fildes  ) 

Proxy replacement for the close() function, which closes the specified socket.

Parameters:
fildes -- the socket to be closed
Returns:
0 on success, -1 on failure

Definition at line 1125 of file proxylib.c.

{
  int i, found;
  if (localInfo.proxyIP != 0) {
    found = 0;
    i = 0;
    while (bindInfo[i].sock != -1) {
      if (fildes == bindInfo[i].sock) {
    found = 1;
    break;
      }
      i++;
    }
    if (found == 1) {
      close_socket(bindInfo[i].control_sock);
      bindInfo[i].sock = -1;
    }
  }
  return close_socket(fildes);
}

Here is the caller graph for this function:

int proxy_connect ( SOCKET  s,
PROXY_COMPONENTADDR *  name 
)

Proxy replacement for connect() function, which initiates a connection on a socket.

Parameters:
s -- socket to use to connect
name -- component address to connect to
Returns:
0 on success, -1 on failure (errno is set)

Definition at line 780 of file proxylib.c.

{
  proxy_tag_t tag, connect_return;
  int ret_val;
  struct sockaddr_in addr;

  /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */

  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;

  if (name->proxyIP != 0) {

    addr.sin_addr.s_addr = name->proxyIP;
    addr.sin_port = name->proxyPort;
    
    /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); fflush(NULL); */
    
    ret_val = proxy_connect_nonb(s, (struct sockaddr *) (&addr), 
                 sizeof(addr), PROXY_CONN_TIMEOUT);

    /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
    if(ret_val < 0) {
      perror("proxy_connect: connect");
      return -1;
    }

    /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
    if(proxy_do_auth(name->proxyIP, s) < 0)
      return -1;
  }
  else {
    /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */

    addr.sin_addr.s_addr = name->IP;
    addr.sin_port = name->port;

    ret_val = proxy_connect_nonb(s, (struct sockaddr *) (&addr), 
      sizeof(addr), PROXY_CONN_TIMEOUT);

    if (ret_val < 0) {
      fprintf(stderr, "connect failure\n");
      return -1;
    }
    /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
  }

  /* send some stuff over the connection */

  /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */

  tag = PROXY_CONNECT;
#ifdef PROXY_DEBUG
  fprintf(stderr,"write tag %c %d %u sizeof(tag) %d \n", tag, tag, tag, sizeof(tag));
#endif
  ret_val = write_socket(s, &tag, sizeof(tag));
  if (ret_val == SOCKET_ERROR) {
    /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
    perror("proxy_connect: write");
    close_socket(s);
    return -1;
  }

  /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */
#ifdef PROXY_DEBUG
  fprintf(stderr,"write my id\n");
#endif
  ret_val = write_socket(s, localInfo.ID, sizeof(localInfo.ID));
  if (ret_val == SOCKET_ERROR) {
    perror("proxy_connect: write");
    close_socket(s);
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"write dest id\n");
#endif
  ret_val = write_socket(s, name->ID, sizeof(name->ID));
  if (ret_val == SOCKET_ERROR) {
    perror("proxy_connect: write");
    close_socket(s);
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"write dest port\n");
#endif
  ret_val = write_socket(s, (char *)&(name->port), sizeof(name->port));
  if (ret_val == SOCKET_ERROR) {
    perror("proxy_connect: write");
    close_socket(s);
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"wat for proxy reply\n");
#endif
  /* wait for reply from proxy */
  ret_val = proxy_tread(s, (char *)&connect_return, sizeof(connect_return), 
     PROXY_TIMEOUT_DEFAULT);
  if (ret_val < 0) {
    perror("proxy_connect: read");
    close_socket(s);
    return -1;
  }
#ifdef PROXY_DEBUG
  fprintf(stderr,"proxy reply = %d\n", ret_val);
#endif
  if (connect_return == PROXY_CONNECTION_REFUSED) {
    errno = ECONNREFUSED;
    close_socket(s);
    return -1;
  }
  /* fprintf(stderr, "%s:%d \n", __FILE__, __LINE__); */

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_connect_nonb ( SOCKET  sockfd,
const struct sockaddr *  saptr,
socklen_t  salen,
int  nsec 
)

This is a replacement for connect that handles interruptions from signals. It also provides a timeout parameter for limiting the amount of time we block on a connection attempt. This code was adapted from Stevens' "UNIX Network Programming" page 411.

Parameters:
sockfd -- socket descriptor to use for connection
saptr -- pointer to address structure
salen -- length of address struct
nsec -- number of seconds to wait before timing out
Returns:
0 on success. on failure returns -1 and sets errno.

Definition at line 912 of file proxylib.c.

{
  int n;
  int error;
  socklen_t               len;
  fd_set                  rset, wset;
  struct timeval  tval;
#ifndef WIN32
  int flags;
#endif

#ifdef WIN32
  { 
    ULONG NonBlock = 1;
    if (ioctlsocket(sockfd, FIONBIO, &NonBlock) == SOCKET_ERROR)  {
      fprintf(stderr, "ioctlsocket() failed to set socket to non-blocking \n");
      return -1;
    }
  }
#else
 {
   if (((flags = fcntl(sockfd, F_GETFL, 0)) < 0) ||
       ((fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0))) {
     errno = EIO;
     return -1;
   }
 }
#endif

  error = 0;
  if ( (n = connect(sockfd, saptr, salen)) == SOCKET_ERROR) {
    errno = errno_socket();

    /* The EWOULDBLOCK may be WIN32 specific */
    if (errno != EINPROGRESS && errno != EWOULDBLOCK )
      return -1;
  }

  /* Do whatever we want while the connect is taking place. */

  if (n == 0)
    goto done;      /* connect completed immediately */

  do {
    FD_ZERO(&rset);
    FD_SET(sockfd, &rset);
  
    wset = rset;
    tval.tv_sec = nsec;
    tval.tv_usec = 0;

    n = select(sockfd+1, &rset, &wset, NULL, nsec ? &tval : NULL);

    if ( n == 0) {
      close_socket(sockfd);          /* timeout */
      errno = ETIMEDOUT;
      return -1;
    }
    else if ((n < 0) && ((errno=errno_socket()) != EINTR)) {
      close_socket(sockfd);
      return -1;
    }
  } while((n<0) && ((errno=errno_socket()) == EINTR));

  if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
    len = sizeof(error);
    if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) < 0)
      return -1;                     /* Solaris pending error */
  } else {
    fprintf(stderr,"select error: sockfd not set");
    errno = EIO;
    return -1;
  }

done:
#ifdef WIN32
  { 
    ULONG NonBlock = 0;
    if (ioctlsocket(sockfd, FIONBIO, &NonBlock) == SOCKET_ERROR)  {
      fprintf(stderr, "ioctlsocket() failed to set socket to nonblocking \n");
      return -1;
    }
  }
#else
  if (fcntl(sockfd, F_SETFL, flags) < 0) { /* restore file status flags */
    errno = EIO;
    return -1;
  }
#endif

  if(error) {
    close_socket(sockfd);          /* just in case */
    errno = error;
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_do_auth ( ipaddr_t  proxy_ip,
SOCKET  s 
)

Perform component-to-proxy authentication (if enabled).

Parameters:
proxy_ip -- proxy IP address
s -- the connected socket
Returns:
0 on success, -1 on failure.

Definition at line 1063 of file proxylib.c.

{
  proxy_tag_t tag;
  int ret_val;
  char proxy_host_ip[16];

  proxy_ip_to_str(proxy_ip, proxy_host_ip);

  ret_val = proxy_tread(s, (char *)&tag, sizeof(tag), PROXY_TIMEOUT_DEFAULT);
  if (ret_val < 0) {
    errno = ECONNRESET;
    return -1;
  }
#ifdef KERBEROS5
  if (tag == PROXY_KRB5_AUTH_REQUIRED) {
    if (proxy_send_krb5_credentials(proxy_host_ip, s) < 0) {
      errno = EACCES;
      close_socket(s);
      return -1;
    }
    ret_val = proxy_tread(s, (char *)&tag, sizeof(tag), PROXY_TIMEOUT_DEFAULT);
    if (ret_val < 0) {
      errno = ECONNRESET;
      close_socket(s);
      return -1;
    }
  }

  /* 
   * check for authentication-specific error codes here
   * before falling through to the problem-specific error codes
   */
  if (tag == PROXY_AUTH_FAILED) {
    errno = EACCES;
    close_socket(s);
    return -1;
  }
#endif

  if (tag == PROXY_KRB5_AUTH_REQUIRED) {
    errno = EACCES;
    close_socket(s);
    return -1;
  } else if (tag != PROXY_AUTH_ACCEPTED) {
    errno = EACCES;
    close_socket(s);
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_get_fd_limit (  ) 

Get the maximum number of descriptors we can use. This is used to allocate the table of bound connections. On some systems, the maximum number returned by getrlimit is pretty huge, so we use PROXY_BIND_MAXFD in that situation (to avoid trying to malloc an extremely large chunk of memory).

Returns:
the maximum number of descriptors we can use.

Definition at line 1334 of file proxylib.c.

{
#ifdef WIN32
  return 256;
#else
  struct rlimit rlp;

  if(getrlimit(RLIMIT_NOFILE, &rlp) < 0)
    return PROXY_BIND_MAXFD;

  if((rlp.rlim_max <= 0) || (rlp.rlim_max > PROXY_BIND_MAXFD))
    return PROXY_BIND_MAXFD;

  return (int)rlp.rlim_max;
#endif
}

Here is the caller graph for this function:

void proxy_get_id ( char *  cp  ) 

Generates a random component ID.

Parameters:
cp -- on return contains the new component ID

Definition at line 58 of file proxylib.c.

{
  struct timeval tv;
  int i;

  if (!cp)
    return;

  gettimeofday(&tv, NULL);

  srandom(tv.tv_usec);

  for(i=0;i<CID_LEN;i++)
    cp[i] = random() % 256;
}

Here is the caller graph for this function:

PROXY_COMPONENTADDR proxy_get_local_addr (  ) 

Gets this component's address.

Returns:
the component address

Definition at line 111 of file proxylib.c.

{
  return localInfo;
}

Here is the caller graph for this function:

ipaddr_t proxy_get_proxy_ip (  ) 

Gets the IP address of the proxy server.

Returns:
the proxy IP address

Definition at line 123 of file proxylib.c.

{
  return localInfo.proxyIP;
}

Here is the caller graph for this function:

in_port_t proxy_get_proxy_port (  ) 

Gets the proxy server port.

Returns:
the proxy port

Definition at line 149 of file proxylib.c.

{
  return localInfo.proxyPort;
}

Here is the caller graph for this function:

int proxy_getsockname ( int  s,
struct sockaddr *  name,
socklen_t *  namelen 
)

proxy replacement for the getsockname() function.

Parameters:
s --
name --
namelen --
Returns:
0 on success, -1 on failure.

Definition at line 246 of file proxylib.c.

{
  int i;

  if(getsockname(s, name, namelen) < 0)
    return -1;

  if (localInfo.proxyIP != 0) {
    i = 0;
    while(bindInfo[i].sock != INVALID_SOCKET) {
      if(s == bindInfo[i].sock)
        break;
      i++;
    }

    if(bindInfo[i].sock == INVALID_SOCKET) {
      errno = EINVAL;
      return -1;
    }

    ((struct sockaddr_in *)name)->sin_port = bindInfo[i].port;
  }

  return 0;
}

Here is the caller graph for this function:

void proxy_init ( char *  configFile  ) 

Initializes the proxy library.

Parameters:
configFile -- name of the configuration file, which specifies such things as the proxy IP address

Definition at line 1154 of file proxylib.c.

{
#define MAXLEN 256
  /* int const MAXLEN = 256; */
  char line[MAXLEN];
  char proxy_string[MAXLEN];
  char proxy_port_string[MAXLEN];
  FILE *fconfig;
  struct hostent *hp;

  /* generate an ID */
  proxy_get_id(localInfo.ID);

  /* default to no proxy */
  strcpy(proxy_string, "0");
  strcpy(proxy_port_string, "0");

  if ((strlen(configFile) >= 1) &&
      (fconfig = fopen(configFile, "r")) != NULL) {
    /* get parameters from config file */
    
    fgets(line, MAXLEN, fconfig);
    while (!feof(fconfig)) {
      if (strncmp(line, "proxyPort", strlen("proxyPort")) == 0) {
    strtok(line, "=");
    strcpy(proxy_port_string, (char *) strtok(NULL, " "));
    proxy_port_string[strlen(proxy_port_string) - 1] = '\0';
    
      } else if (strncmp(line, "proxy", strlen("proxy")) == 0) {
    strtok(line, "=");
    strcpy(proxy_string, strtok(NULL, " "));
    proxy_string[strlen(proxy_string) - 1] = '\0';
      }
      fgets(line, MAXLEN, fconfig);
    }
    fclose(fconfig);
    
  } else if ((getenv("GRIDSOLVE_PROXY")) != NULL) {
    /* Get proxy from environment */

    strncpy(line, getenv("GRIDSOLVE_PROXY"), MAXLEN);
    fprintf(stderr,"Could not open proxy config file %s \n", configFile);
    fprintf(stderr,"Trying environment variable GRIDSOLVE_PROXY=%s\n",line);    
    strcpy(proxy_string, strtok(line, ":"));
    strcpy(proxy_port_string, strtok(NULL, ":"));
  } 

  /* store proxy IP */
  if (strcasecmp(proxy_string, "0") == 0) {
    localInfo.proxyIP = 0;
  } else {
    if ((hp = gethostbyname(proxy_string)) == NULL) {
      fprintf(stderr, "Could not gethostbyname for proxy %s\n", proxy_string);
      perror("proxy_connect: gethostbyname()");
      return;
    }
    memcpy((void *) &(localInfo.proxyIP), hp->h_addr_list[0], sizeof(ipaddr_t));
  }

  /* store proxy port */
  if (strcasecmp(proxy_port_string, "0") == 0) {
    localInfo.proxyPort = 0;
  } else {
    localInfo.proxyPort = htons(atoi((char *) strdup(proxy_port_string)));
  }
  /* get my IP */
  localInfo.IP = proxy_get_my_ipaddr();

  if (localInfo.proxyIP != 0) {
    /* intialize bindinfo */

    bindInfo = 
      (PROXY_BINDING *) malloc(sizeof(PROXY_BINDING) * proxy_get_fd_limit());
    bindInfo[0].sock = INVALID_SOCKET;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_ip_to_str ( ipaddr_t  IP,
char *  dottedIP 
)

Unparse the IP into string with dotted notation.

Parameters:
IP -- IP address to be converted to string representation
dottedIP -- string where the dotted version is stored
Returns:
0 on success, -1 on failure

Definition at line 1022 of file proxylib.c.

{
  unsigned char *uptr = (unsigned char *)&IP;

  if (IP == 0)
    strcpy(dottedIP, "0.0.0.0");
  else
    sprintf(dottedIP, "%d.%d.%d.%d", uptr[0] & 0xff, uptr[1] & 0xff,
                uptr[2] & 0xff, uptr[3] & 0xff);
  
  return 0;
}

Here is the caller graph for this function:

int proxy_listen ( SOCKET  s,
int  backlog 
)

Proxy replacement for the listen() function, which specifies a willingness to accept incoming connections on the given socket.

Parameters:
s -- the socket to listen on
backlog -- maximum length the queue of pending connections may grow to
Returns:
0 on success, -1 on failure (errno is set).

Definition at line 285 of file proxylib.c.

{
  proxy_tag_t tag;
  int ret_val;
  struct sockaddr_in proxyaddr;

  ret_val = listen(s, backlog);

  if (localInfo.proxyIP != 0) {
    int i, flag = 1;

#ifdef WIN32
    if (s == INVALID_SOCKET) {
#else
    if (s < 0 || s > proxy_get_fd_limit()) {
#endif
      errno = EBADF;
      return -1;
    }

    i = 0;
    while (bindInfo[i].sock != INVALID_SOCKET) {
      if (s == bindInfo[i].sock) {
    break;
      }
      i++;
    }

    if (bindInfo[i].sock == INVALID_SOCKET) {
      errno = EINVAL;
      return -1;
    }

    bindInfo[i].control_sock = socket(AF_INET, SOCK_STREAM, 0);

    setsockopt(bindInfo[i].control_sock, IPPROTO_TCP, TCP_NODELAY, 
        (char *) &flag, sizeof(int));

    proxyaddr.sin_family = AF_INET;
    proxyaddr.sin_addr.s_addr = localInfo.proxyIP;
    proxyaddr.sin_port = localInfo.proxyPort;

#ifdef PROXY_DEBUG
    fprintf(stderr,"listen: addr = %d\n", (int)localInfo.proxyIP);
    fprintf(stderr,"listen: port = %d\n", (int)ntohs(localInfo.proxyPort));
#endif
    /* Form control collection with proxy */
    /* connect to proxy and form control connection */

    ret_val = proxy_connect_nonb(bindInfo[i].control_sock, 
       (struct sockaddr *) (&proxyaddr), sizeof(proxyaddr), PROXY_CONN_TIMEOUT);

    if (ret_val < 0) {
      perror("proxy_listen: connect1");
      return -1;
    }

    if (proxy_do_auth(localInfo.proxyIP, bindInfo[i].control_sock) < 0)
      return -1;

    tag = PROXY_CONTROL_CONNECTION;
    ret_val = write_socket(bindInfo[i].control_sock, &tag, sizeof(tag));
    if (ret_val == SOCKET_ERROR) {
      perror("proxy_listen: write");
      return -1;
    }

    /* send my ID to proxy */
    ret_val = write_socket(bindInfo[i].control_sock, localInfo.ID, CID_LEN);
    if (ret_val == SOCKET_ERROR) {
      perror("proxy_listen: write");
      return -1;
    }

    /* send the bind port to proxy */
    ret_val = write_socket(bindInfo[i].control_sock, (char *)&(bindInfo[i].port),
               sizeof(bindInfo[i].port));
    if (ret_val == SOCKET_ERROR) {
      perror("proxy_listen: write");
      return -1;
    }

    return 0;
  }

  return ret_val;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void proxy_print_componentID ( FILE *  f,
char *  id 
)

Prints the component ID to the specified file.

Parameters:
f -- the file to which the component ID should be printed
id -- the component id to print

Definition at line 96 of file proxylib.c.

{
  int i;

  for (i = 0; i < CID_LEN; i++)
    fprintf(f, "%x%x", (id[i] >> 4) & 0x0F, id[i] & 0x0F);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void proxy_print_local_info (  ) 

Prints proxy IP address, proxy port, and component ID to stdout.

Definition at line 79 of file proxylib.c.

{
  printf("Proxy IP port: %u %d\n", 
     (unsigned int)localInfo.proxyIP, ntohs(localInfo.proxyPort));
  printf("My ID IP: ");
  proxy_print_componentID(stdout, localInfo.ID);
  printf(" %d\n", (int)localInfo.IP);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_set_cid_from_str ( char *  id  ) 

Sets the component ID to the specified value.

Parameters:
id -- the ID to set (note this is the string form of the ID)
Returns:
0 on success, -1 on failure.

Definition at line 137 of file proxylib.c.

{
  return proxy_str_to_cid(localInfo.ID, id);
}

Here is the call graph for this function:

Here is the caller graph for this function:

SOCKET proxy_socket ( int  domain,
int  type,
int  protocol 
)

Proxy replacement for the socket() function, which creates an endpoint for communication.

Parameters:
domain -- the protocol family to use
type -- socket type (SOCK_STREAM, SOCK_DGRAM, etc)
protocol -- protocol to be used with the socket
Returns:
the descriptor for the opened socket

Definition at line 166 of file proxylib.c.

{
  return socket(domain, type, protocol);
}

Here is the caller graph for this function:

int proxy_str_to_cid ( char *  dest,
char *  src 
)

Convert string (src CID_LEN*2+1) to a componentID (dest CID_LEN)

Parameters:
dest -- the binary component ID (set on return)
src -- the string representation of the component ID
Returns:
0 on success, -1 on failure

Definition at line 1241 of file proxylib.c.

                                        {
  int i,j;

  if(!src || !dest)
    return -1;

  /* clear out destination */
  memset(dest, 0, CID_LEN);

  for(i=strlen(src)-1, j=CID_LEN-1;i>=0;i-=2, j--) {
    char tmp[2];

    if((src[i] == 'x') || (src[i] == 'X'))
      break;

    tmp[1] = 0;

    tmp[0] = src[i];
    dest[j] = (char)strtol(tmp,NULL,16);

    if(i > 0) {
      tmp[0] = src[i-1];
      dest[j] |= (char)strtol(tmp,NULL,16) << 4;
    }
  }

  return 0;
}

Here is the caller graph for this function:

int proxy_str_to_ip ( ipaddr_t *  IP,
char *  dottedIP 
)

Parse the string with dotted notation into an IP address.

Parameters:
IP -- the binary representation of the dotted IP string
dottedIP -- the dotted IP string to be converted
Returns:
0 on success, -1 on failure

Definition at line 1045 of file proxylib.c.

{
  unsigned int b1,b2,b3,b4;
  sscanf(dottedIP, "%u.%u.%u.%u", &b1,&b2,&b3,&b4);
  *IP = htonl((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
  return 0;
}

Here is the caller graph for this function:


Variable Documentation

PROXY_BINDING* bindInfo

Definition at line 44 of file proxylib.c.

int errno
PROXY_COMPONENTADDR localInfo

Definition at line 41 of file proxylib.c.