Source File sk/sk_socket.c

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