## modules/sk/sk_socket.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. SK_atoport
2. SK_close
3. SK_getsock
4. SK_accept_connection
5. SK_connect
6. SK_read
7. SK_write
8. SK_gets
9. SK_puts
10. SK_putc
11. SK_getc
12. SK_getpeername
13. SK_getpeerip

       1 /***************************************
       2   $Revision: 1.18 $
       3
       4   Socket module - routines facilitating calls to socket library.
       5
       6   Status: NOT REVUED, TESTED
       7
       8   Basic code adapted by Chris Ottrey from
       9       http://www.ibrado.com/sock-faq/sfaq.html#faq65 - sample source code.
      10   ******************/ /******************
      11   Modification History:
      12         ottrey (08/03/1999) Created from sockhelp.c.
      13         ottrey (08/03/1998) Heavily butchered.
      14         joao   (22/06/1999) Modified socket creation and accepts.
      15         marek  (December 2000) Added connection function w/timeout.
      16   ******************/ /******************
      17   Copyright (c) 1999, 2000                           RIPE NCC
      18
      19   All Rights Reserved
      20
      21   Permission to use, copy, modify, and distribute this software and its
      22   documentation for any purpose and without fee is hereby granted,
      23   provided that the above copyright notice appear in all copies and that
      24   both that copyright notice and this permission notice appear in
      25   supporting documentation, and that the name of the author not be
      26   used in advertising or publicity pertaining to distribution of the
      27   software without specific, written prior permission.
      28
      29   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
      30   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
      31   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
      32   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      33   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      34   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      35   ***************************************/
      36
      37 #include "sk.h"
      38 #include "constants.h"
      39 #include "stubs.h"
      40
      41 #include "memwrap.h"
      42
      43 /*+ String sizes +*/
      44 #define STR_S   63
      45 #define STR_XXL 16383
      46
      47 /* SK_atoport() */
      48 /*++++++++++++++++++++++++++++++++++++++
      49    Take a service name, and a service type, and return a port number.  If the
      50    service name is not found, it tries it as a decimal number.  The number
      51    returned is byte ordered for the network.
      52
      53   char *service   Service name (or port number).
      54
      55   char *proto     Protocol (eg "tcp").
      56
      57   Author:
      58         ottrey.
      59
      60   ++++++++++++++++++++++++++++++++++++++*/
      61 int SK_atoport(const char *service, const char *proto) {
         /* [<][>][^][v][top][bottom][index][help] */
      62   unsigned port;
      63   long int lport;
      64   struct servent *serv;
      65   char *errpos;
      66   struct servent result;
      67   char buffer[STR_XXL];
      68
      69   /* First try to read it from /etc/services */
      70
      71 #ifdef __linux__
      72   if(getservbyname_r(service, proto, &result, buffer, sizeof(buffer), &serv) < 0) serv = NULL;
      73 #else
      74   serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer));
      75 #endif
      76
      77   if (serv != NULL)
      78     port = serv->s_port;
      79   else { /* Not in services, maybe a number? */
      80     lport = strtol(service,&errpos,0);
      81     if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
      82       return -1; /* Invalid port address */
      83     port = htons(lport);
      84   }
      85   return port;
      86 } /* SK_atoport() */
      87
      88
      89 /* SK_close() */
      90 /*++++++++++++++++++++++++++++++++++++++
      91
      92   int SK_close     wrapper around closing the socket. Returns the value
      93                    returned by close(2)
      94
      95   int socket       socket to be closed
      96
      97   Author:
      98         ottrey
      99   ++++++++++++++++++++++++++++++++++++++*/
     100 int SK_close(int socket) {
         /* [<][>][^][v][top][bottom][index][help] */
     101   ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
     102
     103   return close(socket);
     104 }
     105
     106 /* SK_getsock() */
     107 /*++++++++++++++++++++++++++++++++++++++
     108
     109    int  SK_getsock        This function creates a socket and binds to it.
     110                           Returns the number of the created
     111                           descriptor/listening socket.
     112
     113    int socket_type        SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
     114
     115    unsigned  port         The port to listen on. Ports < 1024 are
     116                           reserved for the root user. Host byte order.
     117
     118    int backlog            Size of the backlog queue to be set on that
     119                           socket.
     120
     121    uint32_t bind_address  Address to bind to, in network order.
     122
     123   Authors:
     124         ottrey,
     125         joao,
     126         marek (added htons conversion for port).
     127
     128   ++++++++++++++++++++++++++++++++++++++*/
     129 int  SK_getsock(int socket_type, unsigned h_port, int backlog,
         /* [<][>][^][v][top][bottom][index][help] */
     130                 uint32_t bind_address) {
     131   struct sockaddr_in address;
     132   int listening_socket;
     133   int reuse_addr = 1;
     134   u_short port = htons(h_port);
     135
     136   /* Setup internet address information.
     137      This is used with the bind() call */
     138   memset((char *) &address, 0, sizeof(address));
     139   address.sin_family = AF_INET;
     140   address.sin_port = port;
     141   address.sin_addr.s_addr = bind_address;
     142
     143   /* Map all of the signals and exit routine */
     144
     145   listening_socket = socket(AF_INET, socket_type, 0);
     146   if (listening_socket < 0) {
     147     perror("socket");
     148     exit(EXIT_FAILURE);
     149   }
     150
     151   setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr));
     152
     153   if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
     154     perror("bind");
     155     close(listening_socket);
     156     exit(EXIT_FAILURE);
     157   }
     158
     159
     160   if (socket_type == SOCK_STREAM) {
     161     listen(listening_socket, backlog); /* Queue up to five connections before
     162                                   having them automatically rejected. */
     163   }
     164
     165   return listening_socket;
     166 } /* SK_getsock() */
     167
     168 /*++++++++++++++++++++++++++++++++++++++
     169
     170    Wait for an incoming connection on the specified socket
     171
     172    int  SK_accept_connection The socket for communicating to the client
     173
     174    int  listening_socket     The socket that the server is bound to
     175
     176   Authors:
     177         joao,
     178         marek.
     179   ++++++++++++++++++++++++++++++++++++++*/
     180 int SK_accept_connection(int listening_socket) {
         /* [<][>][^][v][top][bottom][index][help] */
     181   int connected_socket = -1;
     182   int num_errors = 0;
     183
     184 #define MAX_ACCEPT_ERRORS 3
     185
     186   for (;;) {
     187
     188     ER_dbg_va(FAC_SK, ASP_SK_GEN,
     189               "Going to accept connections on socket : %d",listening_socket);
     190
     191     connected_socket = accept(listening_socket, NULL, NULL);
     192     if (connected_socket < 0) {
     193       /* Either a real error occured, or blocking was interrupted for
     194          some reason.  Only abort execution if a real error occured. */
     195       switch(errno) {
     196       case EINTR:        /* Interrupted system call */
     197       case ECONNABORTED: /* Software caused connection abort */
     198         /* no warning */
     199         continue;    /* don't return - do the accept again */
     200       default:
     201         /* special case: shutdown of the server - just return */
     202         if( CO_get_do_server() == 0 ) {
     203           return -1;
     204         }
     205         else { /* real error */
     206           if( ++num_errors < MAX_ACCEPT_ERRORS ) {
     207             /* warn */
     208             ER_perror(FAC_SK, SK_ACERW, "(%d) %s", errno, strerror(errno));
     209           }
     210           else {
     211             /* crash */
     212             ER_perror(FAC_SK, SK_ACERF,
     213                 "too many accept() errors (maximum is %d)", MAX_ACCEPT_ERRORS);
     214             die;
     215           }
     216         }
     217       }
     218     }
     219     else { /* success */
     220        ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d",
     221             connected_socket
     222             );
     223
     224        return connected_socket;
     225     }
     226
     227   }
     228 }
     229
     230
     231 /*++++++++++++++++++++++++++++++++++++++
     232
     233   er_ret_t SK_connect       wrapper around connect(), doing non-blocking
     234                             connection with timeout
     235
     236   int *sock         pointer to the storage for socket descriptor
     237
     238   char *hostname    host to connect to
     239
     240   int port          port to connect to
     241
     242   int timeout       in seconds
     243
     244   Author: marek
     245
     246   ++++++++++++++++++++++++++++++++++++++*/
     247 er_ret_t SK_connect(int  *sock, char *hostname, unsigned int port, unsigned int timeout)
         /* [<][>][^][v][top][bottom][index][help] */
     248 {
     249   struct sockaddr_in sin;
     250   struct hostent *hp;
     251   int s;
     252   int flags;
     253   struct timeval ptm;
     254   fd_set rset, wset;
     255   int gs, sel, er, erlen=sizeof(er);
     256   int error;
     257   struct hostent result;
     258   char aliasbuf[8192]; /* Stevens, UNIX net. prog., p.304 */
     259
     260   /* look up the host name */
     261 #ifdef __linux__
     262   er = (gethostbyname_r(hostname,  &result, aliasbuf,
     263                         sizeof(aliasbuf), &hp, &error) < 0 );
     264 #else /* default is Solaris implementation */
     265   hp = gethostbyname_r(hostname,  &result, aliasbuf,
     266                        sizeof(aliasbuf), &error);
     267   er = ( hp == NULL );
     268 #endif
     269
     270   if( er ) {
     271     return SK_BADHOST;
     272   }
     273
     274   /* create a socket */
     275   s = socket(AF_INET, SOCK_STREAM, 0);
     276   if (s < 0) {
     277     return SK_SOCKET;
     278   }
     279
     280   /* bind to it */
     281   bzero((caddr_t)&sin, sizeof (sin));
     282   sin.sin_family = hp->h_addrtype;
     283   if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
     284     close(s);
     285     return SK_BIND;
     286   }
     287   bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
     288   sin.sin_port=htons(port);
     289
     290   /* connect in non-blocking mode */
     291   flags = fcntl(s, F_GETFL, 0);
     292   fcntl(s, F_SETFL, flags | O_NONBLOCK );
     293
     294   if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0
     295       && errno != EINPROGRESS ) {
     296     close(s);
     297     return SK_CONNECT;
     298   }
     299
     300   /* now wait for success */
     301   FD_ZERO( &rset );
     302   FD_SET( s, &rset );
     303   wset = rset;
     304   ptm.tv_usec = 0;
     305   ptm.tv_sec = timeout;
     306
     307   if( (sel=select(s+1,  &rset, &wset, NULL, &ptm)) == 0 ) {
     308     /* timeout */
     309     close(s);
     310     return SK_TIMEOUT;
     311   }
     312   if (sel < 0) {
     313     close(s);
     314     return SK_CONNECT;
     315   }
     316
     317   gs = getsockopt(s, SOL_SOCKET, SO_ERROR, &er, &erlen);
     318
     319   if( gs < 0 || er ) {   /* Stevens code, p.411 is exceptionally crappy */
     320     close(s);
     321     return SK_CONNECT;
     322   } /* if error */
     323
     324   fcntl(s, F_SETFL, flags);
     325   *sock = s;
     326
     327   return SK_OK;
     328 }
     329
     330
     331 /* SK_read() */
     332 /*++++++++++++++++++++++++++++++++++++++
     333
     334    This is just like the read() system call, except that it will make
     335    sure that all your data goes through the socket.
     336
     337    int    SK_read   Returns the number of bytes read.
     338
     339    int    sockfd    The socket file descriptor.
     340
     341    char   *buf      The buffer to be read from the socket.
     342
     343    size_t count     The number of bytes in the buffer.
     344
     345   Author:
     346         ottrey
     347
     348   ++++++++++++++++++++++++++++++++++++++*/
     349 int SK_read(int sockfd, char *buf, size_t count) {
         /* [<][>][^][v][top][bottom][index][help] */
     350   size_t bytes_read = 0;
     351   int this_read;
     352
     353   while (bytes_read < count) {
     354     do
     355       this_read = read(sockfd, buf, count - bytes_read);
     356     while ( (this_read < 0) && (errno == EINTR) );
     357     if (this_read < 0)
     358       return this_read;
     359     else if (this_read == 0)
     360       return bytes_read;
     361     bytes_read += this_read;
     362     buf += this_read;
     363   }
     364
     365   return count;
     366
     367 } /* SK_read() */
     368
     369
     370 /* SK_write() */
     371 /*++++++++++++++++++++++++++++++++++++++
     372
     373    int SK_write   Returns:
     374                      -1 on error
     375                       0 on timeout
     376                       1 on success (all bytes written)
     377
     378    int sockfd                      The socket file descriptor.
     379
     380    const char *buf                 The buffer to be written to the socket.
     381
     382    int count                       The number of bytes in the buffer.
     383
     384    const struct timeval *timeout   Maximum time to wait between each
     385                                    write() call, or NULL for "forever".
     386
     387    int *count_sent                 Set to the number of bytes sucessfully
     388                                    written.  This value is always valid,
     389                                    although it will be less than the
     390                                    total number of bytes to send if
     391                                    the function returns -1 or 0.  NULL
     392                                    may be sent if the caller does not
     393                                    care about the number of bytes sent on
     394                                    failure.
     395
     396   ++++++++++++++++++++++++++++++++++++++*/
     397
     398 int
     399 SK_write(int sockfd,
         /* [<][>][^][v][top][bottom][index][help] */
     400          const char *buf,
     401          int count,
     402          const struct timeval *timeout,
     403          int *count_sent)
     404 {
     405   int     local_count_sent;    /* only used if caller passes NULL */
     406   fd_set  fds;
     407   int     select_ret;
     408   struct  timeval tv;
     409   int     write_ret;
     410
     411   /* copious logging never hurt anybody (well, except people with slow
     412      computers or small hard disks) */
     413   ER_dbg_va(FAC_SK, ASP_SK_WRIT,
     414             "SK_write = { sockfd=[%d], buf=[%s], count=[%d]",
     415             sockfd, buf, count);
     416
     417   /* allow caller to pass NULL if it doesn't care about the count sent */
     418   if (count_sent == NULL) {
     419       count_sent = &local_count_sent;
     420   }
     421
     422   /* loop around until we send all of our data, or we get a timeout or
     423      disconnect */
     424   *count_sent = 0;
     425   while (*count_sent < count) {
     426
     427     /* first, call select() and see if we can write without blocking */
     428     FD_ZERO(&fds);
     429     FD_SET(sockfd, &fds);
     430     if (timeout == NULL) {
     431         select_ret = select(sockfd+1, NULL, &fds, NULL, NULL);
     432     } else {
     433         /* make a copy of timeout, because it's value is undefined
     434            on return from select() */
     435         tv = *timeout;
     436         select_ret = select(sockfd+1, NULL, &fds, NULL, &tv);
     437     }
     438     /* check for error */
     439     if (select_ret < 0) {
     440         /* log the error and return "timeout" */
     441         ER_perror(FAC_SK, SK_SELECT, "(%d) %s", errno, strerror(errno));
     442         return -1;
     443     }
     444     /* check for timeout */
     445     if ((select_ret == 0) || !FD_ISSET(sockfd, &fds)) {
     446         return -1;
     447     }
     448
     449
     450     /* at this point we can safely write */
     451     write_ret = write(sockfd, buf, count - *count_sent);
     452
     453     /* if write failed, assume other side disconnected */
     454     if (write_ret <= 0) {
     455         return 0;
     456     }
     457
     458     /* update our current status */
     459     *count_sent += write_ret;
     460     buf += write_ret;
     461
     462   }
     463
     464   /* all bytes sent, return success */
     465   return 1;
     466 } /* SK_write() */
     467
     468
     469 /* SK_gets() */
     470 /*++++++++++++++++++++++++++++++++++++++
     471
     472    This function reads from a socket, until it recieves a linefeed
     473    character.  It fills the buffer "str" up to the maximum size "count".
     474
     475    int SK_gets      Returns the total_count of bytes read.
     476
     477    int    sockfd    The socket file descriptor.
     478
     479    char   *str      The buffer to be written from the socket.
     480
     481    size_t count     The number of bytes in the buffer.
     482
     483
     484   Authors:
     485         ottrey,
     486         marek (modified for meaningful error codes).
     487
     488   Side Effects:
     489         This function will return -1 if the socket is closed during the read operation.
     490
     491         Note that if a single line exceeds the length of count, the extra data
     492         will be read and discarded!  You have been warned.
     493
     494   ++++++++++++++++++++++++++++++++++++++*/
     495 int SK_gets(int  sockfd, char *str, size_t count) {
         /* [<][>][^][v][top][bottom][index][help] */
     496   int bytes_read;
     497   int total_count = 0;
     498   char *current_position;
     499   char last_read = 0;
     500
     501   int control_c = 0;
     502
     503   current_position = str;
     504   while (last_read != 10) {
     505
     506     bytes_read = read(sockfd, &last_read, 1);
     507     if (bytes_read <= 0) {
     508       /* The other side may have closed unexpectedly */
     509       return SK_DISCONNECT;
     510       /* Is this effective on other platforms than linux? */
     511     }
     512     if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
     513       *current_position = last_read;
     514       current_position++;
     515       total_count++;
     516     }
     517
     518     if (last_read == -1) {
     519       bytes_read = read(sockfd, &last_read, 1);
     520       if (last_read == -12) {
     521         ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c");
     522         control_c = 1;
     523         ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT");
     524         return SK_INTERRUPT;
     525       }
     526     }
     527   }
     528   if (count > 0) {
     529     *current_position = 0;
     530   }
     531
     532   return total_count;
     533
     534 } /* SK_gets() */
     535
     536
     537 /* SK_puts() */
     538 /*++++++++++++++++++++++++++++++++++++++
     539
     540    This function writes a character string out to a socket.
     541
     542    int SK_puts  The total_count of bytes written,
     543                 or -1 on hangup, error, or timeout
     544
     545    int    sockfd    The socket file descriptor.
     546
     547    char   *str      The buffer to be written from the socket.
     548
     549    const struct timeval *timeout   Maximum time to wait between each
     550                                    write() call, or NULL for "forever".
     551
     552   ++++++++++++++++++++++++++++++++++++++*/
     553 int
     554 SK_puts(int sockfd, const char *str, const struct timeval *timeout)
         /* [<][>][^][v][top][bottom][index][help] */
     555 {
     556   int count_sent;
     557   if (SK_write(sockfd, str, strlen(str), timeout, &count_sent) <= 0) {
     558       return -1;
     559   } else {
     560       return count_sent;
     561   }
     562 } /* SK_puts() */
     563
     564 /* SK_putc() */
     565 /*++++++++++++++++++++++++++++++++++++++
     566
     567   This function writes a single character out to a socket.
     568
     569    int SK_putc       Returns the number of characters written.
     570
     571    int sockfd        socket
     572
     573    char ch           character
     574
     575    const struct timeval *timeout   Maximum time to wait between each
     576                                    write() call, or NULL for "forever".
     577
     578   ++++++++++++++++++++++++++++++++++++++*/
     579 int
     580 SK_putc(int sockfd, char ch, const struct timeval *timeout)
         /* [<][>][^][v][top][bottom][index][help] */
     581 {
     582   int count_sent;
     583   SK_write(sockfd, &ch, 1, timeout, &count_sent);
     584   return count_sent;
     585 }/* SK_putc() */
     586
     587 /*++++++++++++++++++++++++++++++++++++++
     588
     589    This function reads a single character from a socket.
     590
     591    returns EOF when no character can be read.
     592
     593   ++++++++++++++++++++++++++++++++++++++*/
     594 int SK_getc(int  sockfd) {
         /* [<][>][^][v][top][bottom][index][help] */
     595   char ch;
     596
     597   if( read(sockfd, &ch, 1) <= 0 ) {
     598     return EOF;
     599   }
     600   else {
     601     return ch;
     602   }
     603 }/* SK_getc() */
     604
     605 /* SK_getpeername() */
     606 /*++++++++++++++++++++++++++++++++++++++
     607
     608   This function will tell you who is at the other end of a connected stream socket.
     609
     610   char *SK_getpeername     Returns allocated string with the IP in it,
     611                            or "--" if the descriptor is not a socket,
     612                            or NULL on error.
     613
     614   int    sockfd            The socket or file descriptor.
     615
     616   +html+ <PRE>
     617   Authors:
     618         ottrey,
     619         marek (modified error handling, made MT-Safe).
     620   +html+ </PRE>
     621
     622   ++++++++++++++++++++++++++++++++++++++*/
     623 char *SK_getpeername(int  sockfd)
         /* [<][>][^][v][top][bottom][index][help] */
     624 {
     625   char *hostaddress=NULL;
     626   struct sockaddr_in addr_in;
     627   int namelen=sizeof(addr_in);
     628
     629   if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) == 0) {
     630
     631     dieif( wr_malloc((void **)&hostaddress, INET_ADDRSTRLEN) != UT_OK);
     632     inet_ntop(AF_INET, &(addr_in.sin_addr),  hostaddress, INET_ADDRSTRLEN);
     633   }
     634   else {
     635     int er = errno;
     636
     637     if( er == ENOTSOCK ) {
     638       hostaddress = wr_string("--");
     639     }
     640     else {
     641       /* XXX: hack to avoid crash in the case where peer disconnects */
     642       /* To fix this, the socket interface needs to deal with a structure
     643          containing not only the file descriptor, but also the address of
     644          the host and the peer.  Other goodies, like the current time,
     645          time of last operation, and last errno could also be included
     646          for good measure. */
     647       hostaddress = UT_strdup("127.0.0.1");
     648     }
     649   }
     650
     651   return hostaddress;
     652
     653 } /* SK_getpeername() */
     654
     655
     656 /* SK_getpeerip */
     657 /*++++++++++++++++++++++++++++++++++++++
     658
     659   This function will check the ip of the connected peer and store it in the
     660   ip_addr_t structure defined in the IP module.
     661
     662   int SK_getpeerip    returns 0 on success, -1 on failure.
     663
     664   int  sockfd         The socket descriptor (file will result in -1)
     665
     666   ip_addr_t *ip       Pointer to where the address should be stored.
     667
     668   +html+ <PRE>
     669   Author:
     670         marek
     671   +html+ </PRE>
     672   ++++++++++++++++++++++++++++++++++++++*/
     673
     674 int SK_getpeerip(int  sockfd, ip_addr_t *ip) {
         /* [<][>][^][v][top][bottom][index][help] */
     675   struct sockaddr_in addr_in;
     676   int namelen=sizeof(addr_in);
     677   int ret=-1;
     678
     679   memset(& addr_in, 0, sizeof(struct sockaddr_in));
     680
     681   if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) {
     682     ret=0;
     683     IP_addr_s2b(ip, &addr_in, namelen);
     684   } else {
     685       /* XXX: hack to avoid crash in the case where peer disconnects */
     686       /* To fix this, the socket interface needs to deal with a structure
     687          containing not only the file descriptor, but also the address of
     688          the host and the peer.  Other goodies, like the current time,
     689          time of last operation, and last errno could also be included
     690          for good measure. */
     691       ret = 0;
     692       addr_in.sin_family = AF_INET;
     693       addr_in.sin_addr.s_addr = INADDR_LOOPBACK;
     694       addr_in.sin_port = 0;
     695       IP_addr_s2b(ip, &addr_in, namelen);
     696   }
     697
     698   return ret;
     699 }
     700

/* [<][>][^][v][top][bottom][index][help] */