示例#1
0
/*********************************************************************
 *
 * Function    :  acl_addr
 *
 * Description :  Called from `load_config' to parse an ACL address.
 *
 * Parameters  :
 *          1  :  aspec = String specifying ACL address.
 *          2  :  aca = struct access_control_addr to fill in.
 *
 * Returns     :  0 => Ok, everything else is an error.
 *
 *********************************************************************/
int acl_addr(char *aspec, struct access_control_addr *aca)
{
   int i, masklength, port;
   char *p;

   masklength = 32;
   port       =  0;

   if ((p = strchr(aspec, '/')) != NULL)
   {
      *p++ = '\0';

      if (ijb_isdigit(*p) == 0)
      {
         return(-1);
      }
      masklength = atoi(p);
   }

   if ((masklength < 0) || (masklength > 32))
   {
      return(-1);
   }

   if ((p = strchr(aspec, ':')) != NULL)
   {
      *p++ = '\0';

      if (ijb_isdigit(*p) == 0)
      {
         return(-1);
      }
      port = atoi(p);
   }

   aca->port = port;

   aca->addr = ntohl(resolve_hostname_to_ip(aspec));

   if (aca->addr == INADDR_NONE)
   {
      return(-1);
   }

   /* build the netmask */
   aca->mask = 0;
   for (i=1; i <= masklength ; i++)
   {
      aca->mask |= (1 << (32 - i));
   }

   /* now mask off the host portion of the ip address
    * (i.e. save on the network portion of the address).
    */
   aca->addr = aca->addr & aca->mask;

   return(0);

}
示例#2
0
/*********************************************************************
 *
 * Function    :  bind_port
 *
 * Description :  Call socket, set socket options, and listen.
 *                Called by listen_loop to "boot up" our proxy address.
 *
 * Parameters  :
 *          1  :  hostnam = TCP/IP address to bind/listen to
 *          2  :  portnum = port to listen on
 *          3  :  pfd = pointer used to return file descriptor.
 *
 * Returns     :  if success, returns 0 and sets *pfd.
 *                if failure, returns -3 if address is in use,
 *                                    -2 if address unresolvable,
 *                                    -1 otherwise
 *********************************************************************/
int bind_port(const char *hostnam, int portnum, jb_socket *pfd)
{
#ifdef HAVE_RFC2553
   struct addrinfo hints;
   struct addrinfo *result, *rp;
   /*
    * XXX: portnum should be a string to allow symbolic service
    * names in the configuration file and to avoid the following
    * int2string.
    */
   char servnam[6];
   int retval;
#else
   struct sockaddr_in inaddr;
#endif /* def HAVE_RFC2553 */
   jb_socket fd = JB_INVALID_SOCKET;
#ifndef _WIN32
   int one = 1;
#endif /* ndef _WIN32 */

   *pfd = JB_INVALID_SOCKET;

#ifdef HAVE_RFC2553
   retval = snprintf(servnam, sizeof(servnam), "%d", portnum);
   if ((-1 == retval) || (sizeof(servnam) <= retval))
   {
      log_error(LOG_LEVEL_ERROR,
         "Port number (%d) ASCII decimal representation doesn't fit into 6 bytes",
         portnum);
      return -1;
   }

   memset(&hints, 0, sizeof(struct addrinfo));
   if (hostnam == NULL)
   {
      /*
       * XXX: This is a hack. The right thing to do
       * would be to bind to both AF_INET and AF_INET6.
       * This will also fail if there is no AF_INET
       * version available.
       */
      hints.ai_family = AF_INET;
   }
   else
   {
      hints.ai_family = AF_UNSPEC;
   }
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_flags = AI_PASSIVE;
   hints.ai_protocol = 0; /* Really any stream protocol or TCP only */
   hints.ai_canonname = NULL;
   hints.ai_addr = NULL;
   hints.ai_next = NULL;

   if ((retval = getaddrinfo(hostnam, servnam, &hints, &result)))
   {
      log_error(LOG_LEVEL_ERROR,
         "Can not resolve %s: %s", hostnam, gai_strerror(retval));
      return -2;
   }
#else
   memset((char *)&inaddr, '\0', sizeof inaddr);

   inaddr.sin_family      = AF_INET;
   inaddr.sin_addr.s_addr = resolve_hostname_to_ip(hostnam);

   if (inaddr.sin_addr.s_addr == INADDR_NONE)
   {
      return(-2);
   }

#ifndef _WIN32
   if (sizeof(inaddr.sin_port) == sizeof(short))
#endif /* ndef _WIN32 */
   {
      inaddr.sin_port = htons((unsigned short) portnum);
   }
#ifndef _WIN32
   else
   {
      inaddr.sin_port = htonl((unsigned long) portnum);
   }
#endif /* ndef _WIN32 */
#endif /* def HAVE_RFC2553 */

#ifdef HAVE_RFC2553
   for (rp = result; rp != NULL; rp = rp->ai_next)
   {
      fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
#else
   fd = socket(AF_INET, SOCK_STREAM, 0);
#endif /* def HAVE_RFC2553 */

#ifdef _WIN32
   if (fd == JB_INVALID_SOCKET)
#else
   if (fd < 0)
#endif
   {
#ifdef HAVE_RFC2553
      continue;
#else
      return(-1);
#endif
   }

#ifdef FEATURE_EXTERNAL_FILTERS
   mark_socket_for_close_on_execute(fd);
#endif

#ifndef _WIN32
   /*
    * This is not needed for Win32 - in fact, it stops
    * duplicate instances of Privoxy from being caught.
    *
    * On UNIX, we assume the user is sensible enough not
    * to start Privoxy multiple times on the same IP.
    * Without this, stopping and restarting Privoxy
    * from a script fails.
    * Note: SO_REUSEADDR is meant to only take over
    * sockets which are *not* in listen state in Linux,
    * e.g. sockets in TIME_WAIT. YMMV.
    */
   setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
   setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, (char *)&one, sizeof(one));
#endif /* ndef _WIN32 */

#ifdef HAVE_RFC2553
   if (bind(fd, rp->ai_addr, rp->ai_addrlen) < 0)
#else
   if (bind(fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
#endif
   {
#ifdef _WIN32
      errno = WSAGetLastError();
      if (errno == WSAEADDRINUSE)
#else
      if (errno == EADDRINUSE)
#endif
      {
#ifdef HAVE_RFC2553
         freeaddrinfo(result);
#endif
         close_socket(fd);
         return(-3);
      }
      else
      {
         close_socket(fd);
#ifndef HAVE_RFC2553
         return(-1);
      }
   }
#else
      }
   }
示例#3
0
static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct client_state *csp)
{
   struct sockaddr_in inaddr;
   jb_socket fd;
   unsigned int addr;
   fd_set wfds;
   struct timeval tv[1];
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
   int   flags;
#endif

#ifdef FEATURE_ACL
   struct access_control_addr dst[1];
#endif /* def FEATURE_ACL */

   /* Don't leak memory when retrying. */
   freez(csp->http->host_ip_addr_str);

   memset((char *)&inaddr, 0, sizeof inaddr);

   if ((addr = resolve_hostname_to_ip(host)) == INADDR_NONE)
   {
      csp->http->host_ip_addr_str = strdup("unknown");
      return(JB_INVALID_SOCKET);
   }

#ifdef FEATURE_ACL
   dst->addr = ntohl(addr);
   dst->port = portnum;

   if (block_acl(dst, csp))
   {
#ifdef __OS2__
      errno = SOCEPERM;
#else
      errno = EPERM;
#endif
      return(JB_INVALID_SOCKET);
   }
#endif /* def FEATURE_ACL */

   inaddr.sin_addr.s_addr = addr;
   inaddr.sin_family      = AF_INET;
   csp->http->host_ip_addr_str = strdup(inet_ntoa(inaddr.sin_addr));

#ifndef _WIN32
   if (sizeof(inaddr.sin_port) == sizeof(short))
#endif /* ndef _WIN32 */
   {
      inaddr.sin_port = htons((unsigned short) portnum);
   }
#ifndef _WIN32
   else
   {
      inaddr.sin_port = htonl((unsigned long)portnum);
   }
#endif /* ndef _WIN32 */

   fd = socket(inaddr.sin_family, SOCK_STREAM, 0);
#ifdef _WIN32
   if (fd == JB_INVALID_SOCKET)
#else
   if (fd < 0)
#endif
   {
      return(JB_INVALID_SOCKET);
   }

#ifndef _WIN32
   if (fd >= FD_SETSIZE)
   {
      log_error(LOG_LEVEL_ERROR,
         "Server socket number too high to use select(): %d >= %d",
         fd, FD_SETSIZE);
      close_socket(fd);
      return JB_INVALID_SOCKET;
   }
#endif

   set_no_delay_flag(fd);
    int yes = 1;
    setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, (char *) &yes, sizeof (yes));

#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
   if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
   {
      flags |= O_NDELAY;
      fcntl(fd, F_SETFL, flags);
#ifdef FEATURE_EXTERNAL_FILTERS
      mark_socket_for_close_on_execute(fd);
#endif
   }
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */

   while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == JB_INVALID_SOCKET)
   {
#ifdef _WIN32
      if (errno == WSAEINPROGRESS)
#elif __OS2__
      if (sock_errno() == EINPROGRESS)
#else /* ifndef _WIN32 */
      if (errno == EINPROGRESS)
#endif /* ndef _WIN32 || __OS2__ */
      {
         break;
      }

#ifdef __OS2__
      if (sock_errno() != EINTR)
#else
      if (errno != EINTR)
#endif /* __OS2__ */
      {
         close_socket(fd);
         return(JB_INVALID_SOCKET);
      }
   }

#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
   if (flags != -1)
   {
      flags &= ~O_NDELAY;
      fcntl(fd, F_SETFL, flags);
   }
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */

   /* wait for connection to complete */
   FD_ZERO(&wfds);
   FD_SET(fd, &wfds);

   tv->tv_sec  = 30;
   tv->tv_usec = 0;

   /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */
   if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0)
   {
      close_socket(fd);
      return(JB_INVALID_SOCKET);
   }
   return(fd);

}
示例#4
0
/*********************************************************************
 *
 * Function    :  acl_addr
 *
 * Description :  Called from `load_config' to parse an ACL address.
 *
 * Parameters  :
 *          1  :  aspec = String specifying ACL address.
 *          2  :  aca = struct access_control_addr to fill in.
 *
 * Returns     :  0 => Ok, everything else is an error.
 *
 *********************************************************************/
int filters::acl_addr(const char *aspec, access_control_addr *aca)
{
    int masklength;
#ifdef HAVE_RFC2553
    struct addrinfo hints, *result;
    uint8_t *mask_data;
    in_port_t *mask_port;
    unsigned int addr_len;
#else
    long port;
#endif /* def HAVE_RFC2553 */
    char *p;
    char *acl_spec = NULL;

#ifdef HAVE_RFC2553
    /* XXX: Depend on ai_family */
    masklength = 128;
#else
    masklength = 32;
    port       =  0;
#endif

    /*
     * Use a temporary acl spec copy so we can log
     * the unmodified original in case of parse errors.
     */
    acl_spec = strdup(aspec);
    if (acl_spec == NULL)
    {
        /* XXX: This will be logged as parse error. */
        return(-1);
    }

    if ((p = strchr(acl_spec, '/')) != NULL)
    {
        *p++ = '\0';
        if (ijb_isdigit(*p) == 0)
        {
            freez(acl_spec);
            acl_spec = NULL;
            return(-1);
        }
        masklength = atoi(p);
    }

    if ((masklength < 0) ||
#ifdef HAVE_RFC2553
            (masklength > 128)
#else
            (masklength > 32)
#endif
       )
    {
        freez(acl_spec);
        acl_spec = NULL;
        return(-1);
    }

    if ((*acl_spec == '[') && (NULL != (p = strchr(acl_spec, ']'))))
    {
        *p = '\0';
        std::memmove(acl_spec, acl_spec + 1, (size_t)(p - acl_spec));

        if (*++p != ':')
        {
            p = NULL;
        }
    }
    else
    {
        p = strchr(acl_spec, ':');
    }

#ifdef HAVE_RFC2553
    std::memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    int i = getaddrinfo(acl_spec, ((p) ? ++p : NULL), &hints, &result);
    freez(acl_spec);
    acl_spec = NULL;

    if (i != 0)
    {
        errlog::log_error(LOG_LEVEL_ERROR, "Can not resolve [%s]:%s: %s",
                          acl_spec, p, gai_strerror(i));
        return(-1);
    }

    /* TODO: Allow multihomed hostnames */
    std::memcpy(&(aca->_addr), result->ai_addr, result->ai_addrlen);
    freeaddrinfo(result);
#else
    if (p != NULL)
    {
        char *endptr;

        *p++ = '\0';
        port = strtol(p, &endptr, 10);

        if (port <= 0 || port > 65535 || *endptr != '\0')
        {
            freez(acl_spec);
            acl_spec = NULL;
            return(-1);
        }
    }

    aca->_port = (unsigned long)port;

    aca->_addr = ntohl(resolve_hostname_to_ip(acl_spec));
    freez(acl_spec);
    acl_spec = NULL;

    if (aca->_addr == INADDR_NONE)
    {
        /* XXX: This will be logged as parse error. */
        return(-1);
    }
#endif /* def HAVE_RFC2553 */

    /* build the netmask */
#ifdef HAVE_RFC2553
    /* Clip masklength according to current family. */
    if ((aca->_addr.ss_family == AF_INET) && (masklength > 32))
    {
        masklength = 32;
    }

    aca->_mask.ss_family = aca->_addr.ss_family;
    if (sockaddr_storage_to_ip(&aca->_mask, &mask_data, &addr_len, &mask_port))
    {
        return(-1);
    }

    if (p)
    {
        /* ACL contains a port number, check ports in the future. */
        *mask_port = 1;
    }
    else ((struct sockaddr_in*)&aca->_mask)->sin_port = 0;

    /*
     * XXX: This could be optimized to operate on whole words instead
     * of octets (128-bit CPU could do it in one iteration).
     */
    /*
     * Octets after prefix can be ommitted because of
     * previous initialization to zeros.
     */
    for (size_t i = 0; (i < addr_len) && masklength; i++)
    {
        if (masklength >= 8)
        {
            mask_data[i] = 0xFF;
            masklength -= 8;
        }
        else
        {
            /*
             * XXX: This assumes MSB of octet is on the left side.
             * This should be true for all architectures or solved
             * by the link layer.
             */
            mask_data[i] = (uint8_t)~((1 << (8 - masklength)) - 1);
            masklength = 0;
        }
    }

#else
    aca->mask = 0;
    for (i=1; i <= masklength ; i++)
    {
        aca->mask |= (1U << (32 - i));
    }

    /* now mask off the host portion of the ip address
     * (i.e. save on the network portion of the address).
     */
    aca->addr = aca->addr & aca->mask;
#endif /* def HAVE_RFC2553 */

    return(0);
}
/*********************************************************************
 *
 * Function    :  bind_port
 *
 * Description :  Call socket, set socket options, and listen.
 *                Called by listen_loop to "boot up" our proxy address.
 *
 * Parameters  :
 *          1  :  hostnam = TCP/IP address to bind/listen to
 *          2  :  portnum = port to listen on
 *          3  :  pfd = pointer used to return file descriptor.
 *
 * Returns     :  if success, returns 0 and sets *pfd.
 *                if failure, returns -3 if address is in use,
 *                                    -2 if address unresolvable,
 *                                    -1 otherwise
 *********************************************************************/
int bind_port(const char *hostnam, int portnum, jb_socket *pfd)
{
   struct sockaddr_in inaddr;
   jb_socket fd;
#ifndef _WIN32
   int one = 1;
#endif /* ndef _WIN32 */

   *pfd = JB_INVALID_SOCKET;

   memset((char *)&inaddr, '\0', sizeof inaddr);

   inaddr.sin_family      = AF_INET;
   inaddr.sin_addr.s_addr = resolve_hostname_to_ip(hostnam);

   if (inaddr.sin_addr.s_addr == INADDR_NONE)
   {
      return(-2);
   }

#ifndef _WIN32
   if (sizeof(inaddr.sin_port) == sizeof(short))
#endif /* ndef _WIN32 */
   {
      inaddr.sin_port = htons((unsigned short) portnum);
   }
#ifndef _WIN32
   else
   {
      inaddr.sin_port = htonl((unsigned long) portnum);
   }
#endif /* ndef _WIN32 */

   fd = socket(AF_INET, SOCK_STREAM, 0);

#ifdef _WIN32
   if (fd == JB_INVALID_SOCKET)
#else
   if (fd < 0)
#endif
   {
      return(-1);
   }

#ifndef _WIN32
   /*
    * This is not needed for Win32 - in fact, it stops
    * duplicate instances of Privoxy from being caught.
    *
    * On UNIX, we assume the user is sensible enough not
    * to start Junkbuster multiple times on the same IP.
    * Without this, stopping and restarting Privoxy
    * from a script fails.
    * Note: SO_REUSEADDR is meant to only take over
    * sockets which are *not* in listen state in Linux,
    * e.g. sockets in TIME_WAIT. YMMV.
    */
   setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
#endif /* ndef _WIN32 */

   if (bind(fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
   {
#ifdef _WIN32
      errno = WSAGetLastError();
      if (errno == WSAEADDRINUSE)
#else
      if (errno == EADDRINUSE)
#endif
      {
         close_socket(fd);
         return(-3);
      }
      else
      {
         close_socket(fd);
         return(-1);
      }
   }

   while (listen(fd, 5) == -1)
   {
      if (errno != EINTR)
      {
         return(-1);
      }
   }

   *pfd = fd;
   return 0;

}
/*********************************************************************
 *
 * Function    :  connect_to
 *
 * Description :  Open a socket and connect to it.  Will check
 *                that this is allowed according to ACL.
 *
 * Parameters  :
 *          1  :  host = hostname to connect to
 *          2  :  portnum = port to connent on
 *          3  :  csp = Current client state (buffers, headers, etc...)
 *                      Not modified, only used for source IP and ACL.
 *
 * Returns     :  JB_INVALID_SOCKET => failure, else it is the socket
 *                file descriptor.
 *
 *********************************************************************/
jb_socket connect_to(const char *host, int portnum, struct client_state *csp)
{
#define	MAX_EVENTS	1024
   struct sockaddr_in inaddr;
   jb_socket fd, epollfd;
   int addr;
   //fd_set wfds;
   //struct timeval tv[1];
   struct epoll_event ev;
   struct epoll_event evlist[MAX_EVENTS];
   
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
   int   flags;
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */

#ifdef FEATURE_ACL
   struct access_control_addr dst[1];
#endif /* def FEATURE_ACL */

   memset((char *)&inaddr, 0, sizeof inaddr);

   if ((addr = resolve_hostname_to_ip(host)) == INADDR_NONE)
   {
      csp->http->host_ip_addr_str = strdup("unknown");
      return(JB_INVALID_SOCKET);
   }

   log_error(LOG_LEVEL_GPC, "host == %s, port == %d", host, portnum);
   
   
#ifdef FEATURE_ACL
   dst->addr = ntohl((unsigned long) addr);
   dst->port = portnum;

   if (block_acl(dst, csp))
   {
#ifdef __OS2__
      errno = SOCEPERM;
#else
      errno = EPERM;
#endif
      return(JB_INVALID_SOCKET);
   }
#endif /* def FEATURE_ACL */

   inaddr.sin_addr.s_addr = addr;
   inaddr.sin_family      = AF_INET;
   csp->http->host_ip_addr_str = strdup(inet_ntoa(inaddr.sin_addr));

#ifndef _WIN32
   if (sizeof(inaddr.sin_port) == sizeof(short))
#endif /* ndef _WIN32 */
   {
      inaddr.sin_port = htons((unsigned short) portnum);
   }
#ifndef _WIN32
   else
   {
      inaddr.sin_port = htonl((unsigned long)portnum);
   }
#endif /* ndef _WIN32 */

#ifdef _WIN32
   if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) == JB_INVALID_SOCKET)
#else
   if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) < 0)
#endif
   {
      return(JB_INVALID_SOCKET);
   }

#ifdef TCP_NODELAY
   {  /* turn off TCP coalescence */
      int mi = 1;
      setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int));
   }
#endif /* def TCP_NODELAY */

#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
   if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
   {
      flags |= O_NDELAY;
      fcntl(fd, F_SETFL, flags);
   }
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */

   while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == JB_INVALID_SOCKET)
   {
#ifdef _WIN32
      if (errno == WSAEINPROGRESS)
#elif __OS2__ 
      if (sock_errno() == EINPROGRESS)
#else /* ifndef _WIN32 */
      if (errno == EINPROGRESS)
#endif /* ndef _WIN32 || __OS2__ */
      {
         break;
      }

#ifdef __OS2__ 
      if (sock_errno() != EINTR)
#else
      if (errno != EINTR)
#endif /* __OS2__ */
      {
         close_socket(fd);
         return(JB_INVALID_SOCKET);
      }
   }

#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
   if (flags != -1)
   {
      flags &= ~O_NDELAY;
      fcntl(fd, F_SETFL, flags);
   }
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */

   /* wait for connection to complete */
   //FD_ZERO(&wfds);
   //FD_SET(fd, &wfds);

   //tv->tv_sec  = 30;
   //tv->tv_usec = 0;
   
   epollfd = epoll_create(MAX_EVENTS);
   if (epollfd == -1)
   {
		log_error(LOG_LEVEL_GPC, "epoll_create error");
		return JB_INVALID_SOCKET;
   }

   ev.data.fd = fd;
   ev.events = EPOLLIN | EPOLLOUT;
   
   if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1)
   {
		log_error(LOG_LEVEL_GPC, "epoll_ctl error");
		return JB_INVALID_SOCKET;
   }
 
   log_error(LOG_LEVEL_GPC, "int connect() : before select");
   

   /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Wierd! */
#if 0
   if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0)
#endif
	if (epoll_wait(epollfd, evlist, MAX_EVENTS, -1) <= 0)
   {
      log_error(LOG_LEVEL_GPC, "in select");
      close_socket(fd);
      return(JB_INVALID_SOCKET);
   }
   
   log_error(LOG_LEVEL_GPC, "int connect()  : after select");
   
   return(fd);

}