modules/sk/sk_socket.c

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

DEFINITIONS

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.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) {
     /* [<][>][^][v][top][bottom][index][help] */
  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) {
     /* [<][>][^][v][top][bottom][index][help] */
  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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) 
     /* [<][>][^][v][top][bottom][index][help] */
 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) 
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) 
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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 

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