ext/socket/socket.c


DEFINITIONS

This source file includes following functions.
  1. ruby_getaddrinfo
  2. sock_finalize
  3. init_sock
  4. bsock_s_for_fd
  5. bsock_shutdown
  6. bsock_close_read
  7. bsock_close_write
  8. bsock_setsockopt
  9. bsock_getsockopt
  10. bsock_getsockname
  11. bsock_getpeername
  12. bsock_send
  13. s_recvfrom
  14. bsock_recv
  15. bsock_do_not_rev_lookup
  16. bsock_do_not_rev_lookup_set
  17. mkipaddr0
  18. mkipaddr
  19. mkinetaddr
  20. str_isnumber
  21. sock_addrinfo
  22. setipaddr
  23. ipaddr
  24. ruby_socket
  25. thread_read_select
  26. thread_write_select
  27. ruby_connect
  28. load_addr_info
  29. inetsock_cleanup
  30. init_inetsock_internal
  31. init_inetsock
  32. tcp_init
  33. socks_init
  34. socks_s_close
  35. sock_hostbyname
  36. tcp_s_gethostbyname
  37. tcp_svr_init
  38. s_accept
  39. tcp_accept
  40. tcp_sysaccept
  41. unixsock_connect_internal
  42. init_unixsock
  43. ip_addr
  44. ip_peeraddr
  45. ip_recvfrom
  46. ip_s_getaddress
  47. udp_init
  48. udp_connect_internal
  49. udp_connect
  50. udp_bind
  51. udp_send
  52. unix_init
  53. unix_path
  54. unix_svr_s_open
  55. unix_svr_init
  56. unix_recvfrom
  57. unix_send_io
  58. unix_recv_io
  59. unix_accept
  60. unix_sysaccept
  61. unixaddr
  62. unix_addr
  63. unix_peeraddr
  64. setup_domain_and_type
  65. sock_init
  66. sock_s_socketpair
  67. unix_s_socketpair
  68. sock_connect
  69. sock_bind
  70. sock_listen
  71. sock_recvfrom
  72. sock_accept
  73. sock_sysaccept
  74. sock_gethostname
  75. sock_gethostname
  76. sock_gethostname
  77. sock_mkhostent
  78. mkaddrinfo
  79. sock_s_gethostbyname
  80. sock_s_gethostbyaddr
  81. sock_s_getservbyaname
  82. sock_s_getaddrinfo
  83. sock_s_getnameinfo
  84. sock_s_pack_sockaddr_in
  85. sock_s_unpack_sockaddr_in
  86. sock_s_pack_sockaddr_un
  87. sock_s_unpack_sockaddr_un
  88. sock_define_const
  89. Init_socket


   1  /************************************************
   2  
   3    socket.c -
   4  
   5    $Author: eban $
   6    $Date: 2002/08/30 14:34:57 $
   7    created at: Thu Mar 31 12:21:29 JST 1994
   8  
   9    Copyright (C) 1993-2001 Yukihiro Matsumoto
  10  
  11  ************************************************/
  12  
  13  #include "ruby.h"
  14  #include "rubyio.h"
  15  #include "rubysig.h"
  16  #include <stdio.h>
  17  #include <sys/types.h>
  18  
  19  #ifdef HAVE_UNISTD_H
  20  #include <unistd.h>
  21  #endif
  22  
  23  #ifdef HAVE_SYS_UIO_H
  24  #include <sys/uio.h>
  25  #endif
  26  
  27  #ifndef NT
  28  #if defined(__BEOS__)
  29  # include <net/socket.h>
  30  #else
  31  # include <sys/socket.h>
  32  #endif
  33  #include <netinet/in.h>
  34  #ifdef HAVE_NETINET_TCP_H
  35  # include <netinet/tcp.h>
  36  #endif
  37  #ifdef HAVE_NETINET_UDP_H
  38  # include <netinet/udp.h>
  39  #endif
  40  #include <netdb.h>
  41  #endif
  42  #include <errno.h>
  43  #ifdef HAVE_SYS_UN_H
  44  #include <sys/un.h>
  45  #endif
  46  
  47  #if defined(HAVE_FCNTL)
  48  #ifdef HAVE_SYS_SELECT_H
  49  #include <sys/select.h>
  50  #endif
  51  #include <sys/types.h>
  52  #include <sys/time.h>
  53  #include <fcntl.h>
  54  #endif
  55  #ifndef EWOULDBLOCK
  56  #define EWOULDBLOCK EAGAIN
  57  #endif
  58  #ifndef HAVE_GETADDRINFO
  59  # include "addrinfo.h"
  60  #endif
  61  #include "sockport.h"
  62  
  63  static int do_not_reverse_lookup = 0;
  64  
  65  VALUE rb_cBasicSocket;
  66  VALUE rb_cIPSocket;
  67  VALUE rb_cTCPSocket;
  68  VALUE rb_cTCPServer;
  69  VALUE rb_cUDPSocket;
  70  #ifdef AF_UNIX
  71  VALUE rb_cUNIXSocket;
  72  VALUE rb_cUNIXServer;
  73  #endif
  74  VALUE rb_cSocket;
  75  
  76  static VALUE rb_eSocket;
  77  
  78  #ifdef SOCKS
  79  VALUE rb_cSOCKSSocket;
  80  #ifdef SOCKS5
  81  #include <socks.h>
  82  #else
  83  void SOCKSinit();
  84  int Rconnect();
  85  #endif
  86  #endif
  87  
  88  #define INET_CLIENT 0
  89  #define INET_SERVER 1
  90  #define INET_SOCKS  2
  91  
  92  #ifndef HAVE_SOCKADDR_STORAGE
  93  /*
  94   * RFC 2553: protocol-independent placeholder for socket addresses
  95   */
  96  #define _SS_MAXSIZE     128
  97  #define _SS_ALIGNSIZE   (sizeof(double))
  98  #define _SS_PAD1SIZE    (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
  99  #define _SS_PAD2SIZE    (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
 100                                  _SS_PAD1SIZE - _SS_ALIGNSIZE)
 101  
 102  struct sockaddr_storage {
 103  #ifdef HAVE_SA_LEN
 104          unsigned char ss_len;           /* address length */
 105          unsigned char ss_family;        /* address family */
 106  #else
 107          unsigned short ss_family;
 108  #endif
 109          char    __ss_pad1[_SS_PAD1SIZE];
 110          double  __ss_align;     /* force desired structure storage alignment */
 111          char    __ss_pad2[_SS_PAD2SIZE];
 112  };
 113  #endif
 114  
 115  #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
 116  #define LOOKUP_ORDERS           3
 117  static int lookup_order_table[LOOKUP_ORDERS] = {
 118  #if defined(LOOKUP_ORDER_HACK_INET)
 119      PF_INET, PF_INET6, PF_UNSPEC,
 120  #elif defined(LOOKUP_ORDER_HACK_INET6)
 121      PF_INET6, PF_INET, PF_UNSPEC,
 122  #else
 123      /* should not happen */
 124  #endif
 125  };
 126  
 127  static int
 128  ruby_getaddrinfo(nodename, servname, hints, res)
 129       char *nodename;
 130       char *servname;
 131       struct addrinfo *hints;
 132       struct addrinfo **res;
 133  {
 134      struct addrinfo tmp_hints;
 135      int i, af, error;
 136  
 137      if (hints->ai_family != PF_UNSPEC) {
 138          return getaddrinfo(nodename, servname, hints, res);
 139      }
 140  
 141      for (i = 0; i < LOOKUP_ORDERS; i++) {
 142          af = lookup_order_table[i];
 143          MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
 144          tmp_hints.ai_family = af;
 145          error = getaddrinfo(nodename, servname, &tmp_hints, res);
 146          if (error) {
 147              if (tmp_hints.ai_family == PF_UNSPEC) {
 148                  break;
 149              }
 150          }
 151          else {
 152              break;
 153          }
 154      }
 155  
 156      return error;
 157  }
 158  #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
 159  #endif
 160  
 161  #ifdef HAVE_CLOSESOCKET
 162  #undef close
 163  #define close closesocket
 164  #endif
 165  
 166  #ifdef NT
 167  static void sock_finalize _((OpenFile *fptr));
 168  
 169  static void
 170  sock_finalize(fptr)
 171      OpenFile *fptr;
 172  {
 173      SOCKET s;
 174  
 175      if (!fptr->f) return;
 176      s = get_osfhandle(fileno(fptr->f));
 177      rb_w32_fdclose(fptr->f);
 178      if (fptr->f2) rb_w32_fdclose(fptr->f2);
 179      closesocket(s);
 180  }
 181  #endif
 182  
 183  static VALUE
 184  init_sock(sock, fd)
 185      VALUE sock;
 186      int fd;
 187  {
 188      OpenFile *fp;
 189  
 190      MakeOpenFile(sock, fp);
 191      fp->f = rb_fdopen(fd, "r");
 192  #ifdef NT
 193      fp->finalize = sock_finalize;
 194  #endif
 195      fp->f2 = rb_fdopen(fd, "w");
 196      fp->mode = FMODE_READWRITE;
 197      rb_io_synchronized(fp);
 198  
 199      return sock;
 200  }
 201  
 202  static VALUE
 203  bsock_s_for_fd(klass, fd)
 204      VALUE klass, fd;
 205  {
 206      OpenFile *fptr;
 207      VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
 208  
 209      GetOpenFile(sock, fptr);
 210  
 211      return sock;
 212  }
 213  
 214  static VALUE
 215  bsock_shutdown(argc, argv, sock)
 216      int argc;
 217      VALUE *argv;
 218      VALUE sock;
 219  {
 220      VALUE howto;
 221      int how;
 222      OpenFile *fptr;
 223  
 224      if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
 225          rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
 226      }
 227      rb_scan_args(argc, argv, "01", &howto);
 228      if (howto == Qnil)
 229          how = 2;
 230      else {
 231          how = NUM2INT(howto);
 232          if (how < 0 || 2 < how) {
 233              rb_raise(rb_eArgError, "`how' should be either 0, 1, 2");
 234          }
 235      }
 236      GetOpenFile(sock, fptr);
 237      if (shutdown(fileno(fptr->f), how) == -1)
 238          rb_sys_fail(0);
 239  
 240      return INT2FIX(0);
 241  }
 242  
 243  static VALUE
 244  bsock_close_read(sock)
 245      VALUE sock;
 246  {
 247      OpenFile *fptr;
 248  
 249      if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
 250          rb_raise(rb_eSecurityError, "Insecure: can't close socket");
 251      }
 252      GetOpenFile(sock, fptr);
 253      shutdown(fileno(fptr->f), 0);
 254      if (!(fptr->mode & FMODE_WRITABLE)) {
 255          return rb_io_close(sock);
 256      }
 257      fptr->mode &= ~FMODE_READABLE;
 258  
 259      return Qnil;
 260  }
 261  
 262  static VALUE
 263  bsock_close_write(sock)
 264      VALUE sock;
 265  {
 266      OpenFile *fptr;
 267  
 268      if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
 269          rb_raise(rb_eSecurityError, "Insecure: can't close socket");
 270      }
 271      GetOpenFile(sock, fptr);
 272      if (!(fptr->mode & FMODE_READABLE)) {
 273          return rb_io_close(sock);
 274      }
 275      shutdown(fileno(fptr->f2), 1);
 276      fptr->mode &= ~FMODE_WRITABLE;
 277  
 278      return Qnil;
 279  }
 280  
 281  static VALUE
 282  bsock_setsockopt(sock, lev, optname, val)
 283      VALUE sock, lev, optname, val;
 284  {
 285      int level, option;
 286      OpenFile *fptr;
 287      int i;
 288      char *v;
 289      int vlen;
 290  
 291      rb_secure(2);
 292      level = NUM2INT(lev);
 293      option = NUM2INT(optname);
 294      switch (TYPE(val)) {
 295        case T_FIXNUM:
 296          i = FIX2INT(val);
 297          goto numval;
 298        case T_FALSE:
 299          i = 0;
 300          goto numval;
 301        case T_TRUE:
 302          i = 1;
 303        numval:
 304          v = (char*)&i; vlen = sizeof(i);
 305          break;
 306        default:
 307          StringValue(val);
 308          v = RSTRING(val)->ptr;
 309          vlen = RSTRING(val)->len;
 310          break;
 311      }
 312  
 313      GetOpenFile(sock, fptr);
 314      if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0)
 315          rb_sys_fail(fptr->path);
 316  
 317      return INT2FIX(0);
 318  }
 319  
 320  static VALUE
 321  bsock_getsockopt(sock, lev, optname)
 322      VALUE sock, lev, optname;
 323  {
 324  #if !defined(__BEOS__)
 325      int level, option;
 326      socklen_t len;
 327      char *buf;
 328      OpenFile *fptr;
 329  
 330      level = NUM2INT(lev);
 331      option = NUM2INT(optname);
 332      len = 256;
 333      buf = ALLOCA_N(char,len);
 334  
 335      GetOpenFile(sock, fptr);
 336      if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
 337          rb_sys_fail(fptr->path);
 338  
 339      return rb_str_new(buf, len);
 340  #else
 341      rb_notimplement();
 342  #endif
 343  }
 344  
 345  static VALUE
 346  bsock_getsockname(sock)
 347     VALUE sock;
 348  {
 349      char buf[1024];
 350      socklen_t len = sizeof buf;
 351      OpenFile *fptr;
 352  
 353      GetOpenFile(sock, fptr);
 354      if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
 355          rb_sys_fail("getsockname(2)");
 356      return rb_str_new(buf, len);
 357  }
 358  
 359  static VALUE
 360  bsock_getpeername(sock)
 361     VALUE sock;
 362  {
 363      char buf[1024];
 364      socklen_t len = sizeof buf;
 365      OpenFile *fptr;
 366  
 367      GetOpenFile(sock, fptr);
 368      if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
 369          rb_sys_fail("getpeername(2)");
 370      return rb_str_new(buf, len);
 371  }
 372  
 373  static VALUE
 374  bsock_send(argc, argv, sock)
 375      int argc;
 376      VALUE *argv;
 377      VALUE sock;
 378  {
 379      VALUE mesg, to;
 380      VALUE flags;
 381      OpenFile *fptr;
 382      FILE *f;
 383      int fd, n;
 384  
 385      rb_secure(4);
 386      rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
 387  
 388      GetOpenFile(sock, fptr);
 389      f = GetWriteFile(fptr);
 390      fd = fileno(f);
 391    retry:
 392      rb_thread_fd_writable(fd);
 393      StringValue(mesg);
 394      if (!NIL_P(to)) {
 395          StringValue(to);
 396          n = sendto(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
 397                     (struct sockaddr*)RSTRING(to)->ptr, RSTRING(to)->len);
 398      }
 399      else {
 400          n = send(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags));
 401      }
 402      if (n < 0) {
 403          switch (errno) {
 404            case EINTR:
 405              rb_thread_schedule();
 406              goto retry;
 407          }
 408          rb_sys_fail("send(2)");
 409      }
 410      return INT2FIX(n);
 411  }
 412  
 413  static VALUE ipaddr _((struct sockaddr*));
 414  #ifdef HAVE_SYS_UN_H
 415  static VALUE unixaddr _((struct sockaddr_un*));
 416  #endif
 417  
 418  enum sock_recv_type {
 419      RECV_RECV,                  /* BasicSocket#recv(no from) */
 420      RECV_IP,                    /* IPSocket#recvfrom */
 421      RECV_UNIX,                  /* UNIXSocket#recvfrom */
 422      RECV_SOCKET                 /* Socket#recvfrom */
 423  };
 424  
 425  static VALUE
 426  s_recvfrom(sock, argc, argv, from)
 427      VALUE sock;
 428      int argc;
 429      VALUE *argv;
 430      enum sock_recv_type from;
 431  {
 432      OpenFile *fptr;
 433      VALUE str;
 434      char buf[1024];
 435      socklen_t alen = sizeof buf;
 436      VALUE len, flg;
 437      long slen;
 438      int fd, flags;
 439  
 440      rb_scan_args(argc, argv, "11", &len, &flg);
 441  
 442      if (flg == Qnil) flags = 0;
 443      else             flags = NUM2INT(flg);
 444  
 445      GetOpenFile(sock, fptr);
 446      if (rb_read_pending(fptr->f)) {
 447          rb_raise(rb_eIOError, "recv for buffered IO");
 448      }
 449      fd = fileno(fptr->f);
 450  
 451      slen = NUM2INT(len);
 452      str = rb_tainted_str_new(0, slen);
 453  
 454    retry:
 455      rb_thread_wait_fd(fd);
 456      TRAP_BEG;
 457      slen = recvfrom(fd, RSTRING(str)->ptr, slen, flags, (struct sockaddr*)buf, &alen);
 458      TRAP_END;
 459  
 460      if (slen < 0) {
 461          switch (errno) {
 462            case EINTR:
 463              rb_thread_schedule();
 464              goto retry;
 465          }
 466          rb_sys_fail("recvfrom(2)");
 467      }
 468      if (slen < RSTRING(str)->len) {
 469          RSTRING(str)->len = slen;
 470          RSTRING(str)->ptr[slen] = '\0';
 471      }
 472      rb_obj_taint(str);
 473      switch (from) {
 474        case RECV_RECV:
 475          return (VALUE)str;
 476        case RECV_IP:
 477  #if 0
 478          if (alen != sizeof(struct sockaddr_in)) {
 479              rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
 480          }
 481  #endif
 482          return rb_assoc_new(str, ipaddr((struct sockaddr*)buf));
 483  #ifdef HAVE_SYS_UN_H
 484        case RECV_UNIX:
 485          return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf));
 486  #endif
 487        case RECV_SOCKET:
 488          return rb_assoc_new(str, rb_str_new(buf, alen));
 489        default:
 490          rb_bug("s_recvfrom called with bad value");
 491      }
 492  }
 493  
 494  static VALUE
 495  bsock_recv(argc, argv, sock)
 496      int argc;
 497      VALUE *argv;
 498      VALUE sock;
 499  {
 500      return s_recvfrom(sock, argc, argv, RECV_RECV);
 501  }
 502  
 503  static VALUE
 504  bsock_do_not_rev_lookup()
 505  {
 506      return do_not_reverse_lookup?Qtrue:Qfalse;
 507  }
 508  
 509  static VALUE
 510  bsock_do_not_rev_lookup_set(self, val)
 511  {
 512      rb_secure(4);
 513      do_not_reverse_lookup = RTEST(val);
 514      return val;
 515  }
 516  
 517  static void
 518  mkipaddr0(addr, buf, len)
 519      struct sockaddr *addr;
 520      char *buf;
 521      size_t len;
 522  {
 523      int error;
 524  
 525      error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
 526      if (error) {
 527          rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
 528      }
 529  }
 530  
 531  static VALUE
 532  mkipaddr(addr)
 533      struct sockaddr *addr;
 534  {
 535      char buf[1024];
 536  
 537      mkipaddr0(addr, buf, sizeof(buf));
 538      return rb_str_new2(buf);
 539  }
 540  
 541  static void
 542  mkinetaddr(host, buf, len)
 543      long host;
 544      char *buf;
 545      size_t len;
 546  {
 547      struct sockaddr_in sin;
 548  
 549      MEMZERO(&sin, struct sockaddr_in, 1);
 550      sin.sin_family = AF_INET;
 551      SET_SIN_LEN(&sin, sizeof(sin));
 552      sin.sin_addr.s_addr = host;
 553      mkipaddr0((struct sockaddr*)&sin, buf, len);
 554  }
 555  
 556  static int
 557  str_isnumber(p)
 558          const char *p;
 559  {
 560      char *ep;
 561  
 562      if (!p || *p == '\0')
 563         return 0;
 564      ep = NULL;
 565      (void)strtoul(p, &ep, 10);
 566      if (ep && *ep == '\0')
 567         return 1;
 568      else
 569         return 0;
 570  }
 571  
 572  static struct addrinfo*
 573  sock_addrinfo(host, port, socktype, flags)
 574      VALUE host, port;
 575      int socktype, flags;
 576  {
 577      struct addrinfo hints, *hintsp, *res;
 578      char *hostp, *portp;
 579      int error;
 580      char hbuf[1024], pbuf[16];
 581  
 582      if (NIL_P(host)) {
 583          hostp = NULL;
 584      }
 585      else if (rb_obj_is_kind_of(host, rb_cInteger)) {
 586          long i = NUM2LONG(host);
 587  
 588          mkinetaddr(htonl(i), hbuf, sizeof(hbuf));
 589          hostp = hbuf;
 590      }
 591      else {
 592          char *name;
 593  
 594          SafeStringValue(host);
 595          name = RSTRING(host)->ptr;
 596          if (*name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) {
 597              mkinetaddr(INADDR_ANY, hbuf, sizeof(hbuf));
 598          }
 599          else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
 600              mkinetaddr(INADDR_BROADCAST, hbuf, sizeof(hbuf));
 601          }
 602          else if (strlen(name) >= sizeof(hbuf)) {
 603              rb_raise(rb_eArgError, "hostname too long (%d)", strlen(name));
 604          }
 605          else {
 606              strcpy(hbuf, name);
 607          }
 608          hostp = hbuf;
 609      }
 610      if (NIL_P(port)) {
 611          portp = 0;
 612      }
 613      else if (FIXNUM_P(port)) {
 614          snprintf(pbuf, sizeof(pbuf), "%d", FIX2INT(port));
 615          portp = pbuf;
 616      }
 617      else {
 618          SafeStringValue(port);
 619          portp = RSTRING(port)->ptr;
 620      }
 621  
 622      if (socktype == 0 && flags == 0 && str_isnumber(portp)) {
 623         socktype = SOCK_DGRAM;
 624      }
 625  
 626      hintsp = &hints;
 627      MEMZERO(&hints, struct addrinfo, 1);
 628      hints.ai_family = PF_UNSPEC;
 629      hints.ai_protocol = 0;
 630      hints.ai_socktype = socktype;
 631      hints.ai_flags = flags;
 632      error = getaddrinfo(hostp, portp, hintsp, &res);
 633      if (error) {
 634          if (hostp && hostp[strlen(hostp)-1] == '\n') {
 635              rb_raise(rb_eSocket, "newline at the end of hostname");
 636          }
 637          rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
 638      }
 639  
 640      return res;
 641  }
 642  
 643  static void
 644  setipaddr(name, addr)
 645      VALUE name;
 646      struct sockaddr_storage *addr;
 647  {
 648      struct addrinfo *res = sock_addrinfo(name, Qnil, SOCK_STREAM, 0);
 649  
 650      /* just take the first one */
 651      memcpy(addr, res->ai_addr, res->ai_addrlen);
 652      freeaddrinfo(res);
 653  }
 654  
 655  static VALUE
 656  ipaddr(sockaddr)
 657      struct sockaddr *sockaddr;
 658  {
 659      VALUE family, port, addr1, addr2;
 660      VALUE ary;
 661      int error;
 662      char hbuf[1024], pbuf[1024];
 663  
 664      switch (sockaddr->sa_family) {
 665      case AF_UNSPEC:
 666          family = rb_str_new2("AF_UNSPEC");
 667          break;
 668      case AF_INET:
 669          family = rb_str_new2("AF_INET");
 670          break;
 671  #ifdef INET6
 672      case AF_INET6:
 673          family = rb_str_new2("AF_INET6");
 674          break;
 675  #endif
 676  #ifdef AF_LOCAL
 677      case AF_LOCAL:
 678          family = rb_str_new2("AF_LOCAL");
 679          break;
 680  #elif  AF_UNIX
 681      case AF_UNIX:
 682          family = rb_str_new2("AF_UNIX");
 683          break;
 684  #endif
 685      default:
 686          sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
 687          family = rb_str_new2(pbuf);
 688          break;
 689      }
 690      if (!do_not_reverse_lookup) {
 691          error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
 692                              NULL, 0, 0);
 693          if (error) {
 694              rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
 695          }
 696          addr1 = rb_str_new2(hbuf);
 697      }
 698      error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
 699                          pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
 700      if (error) {
 701          rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
 702      }
 703      addr2 = rb_str_new2(hbuf);
 704      if (do_not_reverse_lookup) {
 705          addr1 = addr2;
 706      }
 707      port = INT2FIX(atoi(pbuf));
 708      ary = rb_ary_new3(4, family, port, addr1, addr2);
 709  
 710      return ary;
 711  }
 712  
 713  static int
 714  ruby_socket(domain, type, proto)
 715      int domain, type, proto;
 716  {
 717      int fd;
 718  
 719      fd = socket(domain, type, proto);
 720      if (fd < 0) {
 721          if (errno == EMFILE || errno == ENFILE) {
 722              rb_gc();
 723              fd = socket(domain, type, proto);
 724          }
 725      }
 726      return fd;
 727  }
 728  
 729  static void
 730  thread_read_select(fd)
 731      int fd;
 732  {
 733      fd_set fds;
 734  
 735      FD_ZERO(&fds);
 736      FD_SET(fd, &fds);
 737      rb_thread_select(fd+1, &fds, 0, 0, 0);
 738  }
 739  
 740  static void
 741  thread_write_select(fd)
 742      int fd;
 743  {
 744      fd_set fds;
 745  
 746      FD_ZERO(&fds);
 747      FD_SET(fd, &fds);
 748      rb_thread_select(fd+1, 0, &fds, 0, 0);
 749  }
 750  
 751  static int
 752  ruby_connect(fd, sockaddr, len, socks)
 753      int fd;
 754      struct sockaddr *sockaddr;
 755      int len;
 756      int socks;
 757  {
 758      int status;
 759      int mode;
 760  #if defined __CYGWIN__
 761      int wait_in_progress = -1;
 762  #endif
 763  
 764  #if defined(HAVE_FCNTL)
 765      mode = fcntl(fd, F_GETFL, 0);
 766  
 767  #ifdef O_NDELAY
 768  # define NONBLOCKING O_NDELAY
 769  #else
 770  #ifdef O_NBIO
 771  # define NONBLOCKING O_NBIO
 772  #else
 773  # define NONBLOCKING O_NONBLOCK
 774  #endif
 775  #endif
 776  #ifdef SOCKS5
 777      if (!socks)
 778  #endif
 779      fcntl(fd, F_SETFL, mode|NONBLOCKING);
 780  #endif /* HAVE_FCNTL */
 781  
 782      for (;;) {
 783  #if defined(SOCKS) && !defined(SOCKS5)
 784          if (socks) {
 785              status = Rconnect(fd, sockaddr, len);
 786          }
 787          else
 788  #endif
 789          {
 790              status = connect(fd, sockaddr, len);
 791          }
 792          if (status < 0) {
 793              switch (errno) {
 794                case EAGAIN:
 795  #ifdef EINPROGRESS
 796                case EINPROGRESS:
 797  #ifdef __CYGWIN__
 798                case EALREADY:
 799                  wait_in_progress = 10;
 800  #endif
 801  #endif
 802                  thread_write_select(fd);
 803                  continue;
 804  
 805  #if defined __CYGWIN__
 806                case EINVAL:
 807                  if (wait_in_progress-- > 0) {
 808                      struct timeval tv = {0, 100000};
 809                      rb_thread_wait_for(tv);
 810                      continue;
 811                  }
 812                  break;
 813  #endif
 814  
 815  #ifdef EISCONN
 816                case EISCONN:
 817                  status = 0;
 818                  errno = 0;
 819                  break;
 820  #endif
 821                default:
 822                  break;
 823              }
 824          }
 825  #ifdef HAVE_FCNTL
 826          fcntl(fd, F_SETFL, mode);
 827  #endif
 828          return status;
 829      }
 830  }
 831  
 832  static void
 833  load_addr_info(h, serv, type, res)
 834      VALUE h, serv;
 835      int type;
 836      struct addrinfo **res;
 837  {
 838      char *host;
 839      char pbuf[1024], *portp;
 840      struct addrinfo hints;
 841      int error;
 842  
 843      if (!NIL_P(h)) {
 844          SafeStringValue(h);
 845          host = RSTRING(h)->ptr;
 846      }
 847      else {
 848          host = NULL;
 849      }
 850      if (FIXNUM_P(serv)) {
 851          snprintf(pbuf, sizeof(pbuf), "%ld", FIX2UINT(serv));
 852          portp = pbuf;
 853      }
 854      else {
 855          SafeStringValue(serv);
 856          if (RSTRING(serv)->len >= sizeof(pbuf))
 857              rb_raise(rb_eArgError, "servicename too long (%d)", RSTRING(serv)->len);
 858          strcpy(pbuf, RSTRING(serv)->ptr);
 859          portp = pbuf;
 860      }
 861      MEMZERO(&hints, struct addrinfo, 1);
 862      hints.ai_family = PF_UNSPEC;
 863      if (type == INET_SERVER) {
 864          hints.ai_flags = AI_PASSIVE;
 865      }
 866      error = getaddrinfo(host, portp, &hints, res);
 867      if (error) {
 868          rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
 869      }
 870  }
 871  
 872  struct inetsock_arg
 873  {
 874      VALUE sock;
 875      struct {
 876          VALUE host, serv;
 877          struct addrinfo *res;
 878      } remote, local;
 879      int type;
 880      int fd;
 881  };
 882  
 883  static VALUE
 884  inetsock_cleanup(arg)
 885      struct inetsock_arg *arg;
 886  {
 887      if (arg->remote.res) {
 888          freeaddrinfo(arg->remote.res);
 889          arg->remote.res = 0;
 890      }
 891      if (arg->local.res) {
 892          freeaddrinfo(arg->local.res);
 893          arg->local.res = 0;
 894      }
 895      if (arg->fd >= 0) {
 896          close(arg->fd);
 897      }
 898      return Qnil;
 899  }
 900  
 901  static VALUE
 902  init_inetsock_internal(arg)
 903      struct inetsock_arg *arg;
 904  {
 905      int type = arg->type;
 906      struct addrinfo hints, *res;
 907      int fd, status;
 908      char *syscall;
 909  
 910      arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
 911                                      (type == INET_SERVER) ? AI_PASSIVE : 0);
 912      /*
 913       * Maybe also accept a local address
 914       */
 915  
 916      if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
 917          arg->local.res = sock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
 918      }
 919  
 920      arg->fd = fd = -1;
 921      for (res = arg->remote.res; res; res = res->ai_next) {
 922          status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
 923          syscall = "socket(2)";
 924          fd = status;
 925          if (fd < 0) {
 926              continue;
 927          }
 928          arg->fd = fd;
 929          if (type == INET_SERVER) {
 930  #ifndef NT
 931              status = 1;
 932              setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
 933                         (char*)&status, sizeof(status));
 934  #endif
 935              status = bind(fd, res->ai_addr, res->ai_addrlen);
 936              syscall = "bind(2)";
 937          }
 938          else {
 939              if (arg->local.res) {
 940                  status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
 941                  syscall = "bind(2)";
 942              }
 943  
 944              if (status >= 0) {
 945                  status = ruby_connect(fd, res->ai_addr, res->ai_addrlen,
 946                                        (type == INET_SOCKS));
 947                  syscall = "connect(2)";
 948              }
 949          }
 950  
 951          if (status < 0) {
 952              close(fd);
 953              arg->fd = fd = -1;
 954              continue;
 955          } else
 956              break;
 957      }
 958      if (status < 0) {
 959          rb_sys_fail(syscall);
 960      }
 961  
 962      arg->fd = -1;
 963  
 964      if (type == INET_SERVER)
 965          listen(fd, 5);
 966  
 967      /* create new instance */
 968      return init_sock(arg->sock, fd);
 969  }
 970  
 971  static VALUE
 972  init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type)
 973      VALUE sock, remote_host, remote_serv, local_host, local_serv;
 974      int type;
 975  {
 976      struct inetsock_arg arg;
 977      arg.sock = sock;
 978      arg.remote.host = remote_host;
 979      arg.remote.serv = remote_serv;
 980      arg.remote.res = 0;
 981      arg.local.host = local_host;
 982      arg.local.serv = local_serv;
 983      arg.local.res = 0;
 984      arg.type = type;
 985      arg.fd = -1;
 986      return rb_ensure(init_inetsock_internal, (VALUE)&arg,
 987                       inetsock_cleanup, (VALUE)&arg);
 988  }
 989  
 990  static VALUE
 991  tcp_init(argc, argv, sock)
 992       int argc;
 993       VALUE *argv;
 994       VALUE sock;
 995  {
 996      VALUE remote_host, remote_serv;
 997      VALUE local_host, local_serv;
 998  
 999      int pcount = rb_scan_args(argc, argv, "22",
1000                                &remote_host, &remote_serv,
1001                                &local_host, &local_serv);
1002  
1003      return init_inetsock(sock, remote_host, remote_serv,
1004                           local_host, local_serv, INET_CLIENT);
1005  }
1006  
1007  #ifdef SOCKS
1008  static VALUE
1009  socks_init(sock, host, serv)
1010      VALUE sock, host, serv;
1011  {
1012      static init = 0;
1013  
1014      if (init == 0) {
1015          SOCKSinit("ruby");
1016          init = 1;
1017      }
1018  
1019      return init_inetsock(class, host, serv, Qnil, Qnil, INET_SOCKS);
1020  }
1021  
1022  #ifdef SOCKS5
1023  static VALUE
1024  socks_s_close(sock)
1025      VALUE sock;
1026  {
1027      OpenFile *fptr;
1028  
1029      if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
1030          rb_raise(rb_eSecurityError, "Insecure: can't close socket");
1031      }
1032      GetOpenFile(sock, fptr);
1033      shutdown(fileno(fptr->f), 2);
1034      shutdown(fileno(fptr->f2), 2);
1035      return rb_io_close(sock);
1036  }
1037  #endif
1038  #endif
1039  
1040  /*
1041   * NOTE: using gethostbyname() against AF_INET6 is a bad idea, as it
1042   * does not initialize sin_flowinfo nor sin_scope_id properly.
1043   */
1044  
1045  struct hostent*
1046  sock_hostbyname(host)
1047      VALUE host;
1048  {
1049      struct sockaddr_storage addr;
1050      struct hostent *h;
1051  
1052      rb_secure(3);
1053      setipaddr(host, &addr);
1054      switch (addr.ss_family) {
1055        case AF_INET:
1056        {
1057          struct sockaddr_in *sin;
1058          sin = (struct sockaddr_in*)&addr;
1059          h = gethostbyaddr((char*)&sin->sin_addr,
1060                            sizeof(sin->sin_addr),
1061                            sin->sin_family);
1062          break;
1063        }
1064  #ifdef INET6
1065        case AF_INET6:
1066        {
1067          struct sockaddr_in6 *sin6;
1068          sin6 = (struct sockaddr_in6*)&addr;
1069          h = gethostbyaddr((char*)&sin6->sin6_addr,
1070                            sizeof(sin6->sin6_addr),
1071                            sin6->sin6_family);
1072          break;
1073        }
1074  #endif
1075        default:
1076          h = NULL;
1077          break;
1078      }
1079  
1080      if (h == NULL) {
1081  #ifdef HAVE_HSTERROR
1082          extern int h_errno;
1083          rb_raise(rb_eSocket, "%s", (char*)hsterror(h_errno));
1084  #else
1085          rb_raise(rb_eSocket, "host not found");
1086  #endif
1087      }
1088      return h;
1089  }
1090  
1091  static VALUE
1092  tcp_s_gethostbyname(obj, host)
1093      VALUE obj, host;
1094  {
1095      struct hostent *h = sock_hostbyname(host);
1096      VALUE ary, names;
1097      char **pch;
1098      size_t size;
1099  
1100      ary = rb_ary_new();
1101      rb_ary_push(ary, rb_str_new2(h->h_name));
1102      names = rb_ary_new();
1103      rb_ary_push(ary, names);
1104      for (pch = h->h_aliases; *pch; pch++) {
1105          rb_ary_push(names, rb_str_new2(*pch));
1106      }
1107      rb_ary_push(ary, INT2NUM(h->h_addrtype));
1108  #ifdef h_addr
1109      for (pch = h->h_addr_list; *pch; pch++) {
1110          switch (h->h_length) {
1111            case 4: /* AF_INET */ {
1112              struct sockaddr_in sin;
1113  
1114              MEMZERO(&sin, struct sockaddr_in, 1);
1115              sin.sin_family = AF_INET;
1116              SET_SIN_LEN(&sin, sizeof(sin));
1117              memcpy((char*)&sin.sin_addr, *pch, h->h_length);
1118              rb_ary_push(ary, mkipaddr((struct sockaddr*)&sin));
1119              break;
1120            }
1121  #ifdef INET6
1122            case 8: /* AF_INET6 */ {
1123              struct sockaddr_in6 sin6;
1124  
1125              MEMZERO(&sin6, struct sockaddr_in6, 1);
1126              sin6.sin6_family = AF_INET6;
1127  #ifdef SIN6_LEN
1128              sin6.sin6_len = sizeof(sin6);
1129  #endif
1130              memcpy((char*)&sin6.sin6_addr, *pch, size);
1131              rb_ary_push(ary, mkipaddr((struct sockaddr*)&sin6));
1132              break;
1133            }
1134  #endif
1135            default:
1136              break;
1137          }
1138      }
1139  #else
1140      memcpy((char*)&addr.sin_addr, h->h_addr, h->h_length);
1141      rb_ary_push(ary, mkipaddr((struct sockaddr*)&addr));
1142  #endif
1143  
1144      return ary;
1145  }
1146  
1147  static VALUE
1148  tcp_svr_init(argc, argv, sock)
1149      int argc;
1150      VALUE *argv;
1151      VALUE sock;
1152  {
1153      VALUE arg1, arg2;
1154  
1155      if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2)
1156          return init_inetsock(sock, arg1, arg2, NULL, Qnil, INET_SERVER);
1157      else
1158          return init_inetsock(sock, Qnil, arg1, NULL, Qnil, INET_SERVER);
1159  }
1160  
1161  static VALUE
1162  s_accept(klass, fd, sockaddr, len)
1163      VALUE klass;
1164      int fd;
1165      struct sockaddr *sockaddr;
1166      socklen_t *len;
1167  {
1168      int fd2;
1169      int retry = 0;
1170  
1171      rb_secure(3);
1172    retry:
1173      rb_thread_wait_fd(fd);
1174  #if defined(_nec_ews)
1175      fd2 = accept(fd, sockaddr, len);
1176  #else
1177      TRAP_BEG;
1178      fd2 = accept(fd, sockaddr, len);
1179      TRAP_END;
1180  #endif
1181      if (fd2 < 0) {
1182          switch (errno) {
1183            case EMFILE:
1184            case ENFILE:
1185              if (retry) break;
1186              rb_gc();
1187              retry = 1;
1188              goto retry;
1189            case EINTR:
1190              rb_thread_schedule();
1191              goto retry;
1192          }
1193          rb_sys_fail(0);
1194      }
1195      if (!klass) return INT2NUM(fd2);
1196      return init_sock(rb_obj_alloc(klass), fd2);
1197  }
1198  
1199  static VALUE
1200  tcp_accept(sock)
1201      VALUE sock;
1202  {
1203      OpenFile *fptr;
1204      struct sockaddr_storage from;
1205      socklen_t fromlen;
1206  
1207      GetOpenFile(sock, fptr);
1208      fromlen = sizeof(from);
1209      return s_accept(rb_cTCPSocket, fileno(fptr->f),
1210                      (struct sockaddr*)&from, &fromlen);
1211  }
1212  
1213  static VALUE
1214  tcp_sysaccept(sock)
1215      VALUE sock;
1216  {
1217      OpenFile *fptr;
1218      struct sockaddr_storage from;
1219      socklen_t fromlen;
1220  
1221      GetOpenFile(sock, fptr);
1222      fromlen = sizeof(from);
1223      return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
1224  }
1225  
1226  #ifdef HAVE_SYS_UN_H
1227  struct unixsock_arg {
1228      struct sockaddr_un *sockaddr;
1229      int fd;
1230  };
1231  
1232  static VALUE
1233  unixsock_connect_internal(arg)
1234      struct unixsock_arg *arg;
1235  {
1236      return (VALUE)ruby_connect(arg->fd, arg->sockaddr, sizeof(*arg->sockaddr),
1237                                 0);
1238  }
1239  
1240  static VALUE
1241  init_unixsock(sock, path, server)
1242      VALUE sock;
1243      VALUE path;
1244      int server;
1245  {
1246      struct sockaddr_un sockaddr;
1247      int fd, status;
1248      OpenFile *fptr;
1249  
1250      SafeStringValue(path);
1251      fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
1252      if (fd < 0) {
1253          rb_sys_fail("socket(2)");
1254      }
1255  
1256      MEMZERO(&sockaddr, struct sockaddr_un, 1);
1257      sockaddr.sun_family = AF_UNIX;
1258      strncpy(sockaddr.sun_path, RSTRING(path)->ptr, sizeof(sockaddr.sun_path)-1);
1259      sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0';
1260  
1261      if (server) {
1262          status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
1263      }
1264      else {
1265          int prot;
1266          struct unixsock_arg arg;
1267          arg.sockaddr = &sockaddr;
1268          arg.fd = fd;
1269          status = rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
1270          if (prot) {
1271              close(fd);
1272              rb_jump_tag(prot);
1273          }
1274      }
1275  
1276      if (status < 0) {
1277          close(fd);
1278          rb_sys_fail(sockaddr.sun_path);
1279      }
1280  
1281      if (server) listen(fd, 5);
1282  
1283      init_sock(sock, fd);
1284      GetOpenFile(sock, fptr);
1285      fptr->path = strdup(RSTRING(path)->ptr);
1286  
1287      return sock;
1288  }
1289  #endif
1290  
1291  static VALUE
1292  ip_addr(sock)
1293      VALUE sock;
1294  {
1295      OpenFile *fptr;
1296      struct sockaddr_storage addr;
1297      socklen_t len = sizeof addr;
1298  
1299      GetOpenFile(sock, fptr);
1300  
1301      if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1302          rb_sys_fail("getsockname(2)");
1303      return ipaddr((struct sockaddr*)&addr);
1304  }
1305  
1306  static VALUE
1307  ip_peeraddr(sock)
1308      VALUE sock;
1309  {
1310      OpenFile *fptr;
1311      struct sockaddr_storage addr;
1312      socklen_t len = sizeof addr;
1313  
1314      GetOpenFile(sock, fptr);
1315  
1316      if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1317          rb_sys_fail("getpeername(2)");
1318      return ipaddr((struct sockaddr*)&addr);
1319  }
1320  
1321  static VALUE
1322  ip_recvfrom(argc, argv, sock)
1323      int argc;
1324      VALUE *argv;
1325      VALUE sock;
1326  {
1327      return s_recvfrom(sock, argc, argv, RECV_IP);
1328  }
1329  
1330  static VALUE
1331  ip_s_getaddress(obj, host)
1332      VALUE obj, host;
1333  {
1334      struct sockaddr_storage addr;
1335  
1336      setipaddr(host, &addr);
1337      return mkipaddr((struct sockaddr*)&addr);
1338  }
1339  
1340  static VALUE
1341  udp_init(argc, argv, sock)
1342      int argc;
1343      VALUE *argv;
1344      VALUE sock;
1345  {
1346      VALUE arg;
1347      int socktype = AF_INET;
1348      int fd;
1349  
1350      rb_secure(3);
1351      if (rb_scan_args(argc, argv, "01", &arg) == 1) {
1352          socktype = NUM2INT(arg);
1353      }
1354      fd = ruby_socket(socktype, SOCK_DGRAM, 0);
1355      if (fd < 0) {
1356          rb_sys_fail("socket(2) - udp");
1357      }
1358  
1359      return init_sock(sock, fd);
1360  }
1361  
1362  struct udp_arg
1363  {
1364      struct addrinfo *res;
1365      int fd;
1366  };
1367  
1368  static VALUE
1369  udp_connect_internal(arg)
1370      struct udp_arg *arg;
1371  {
1372      int fd = arg->fd;
1373      struct addrinfo *res;
1374  
1375      for (res = arg->res; res; res = res->ai_next) {
1376          if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
1377              return Qtrue;
1378          }
1379      }
1380      return Qfalse;
1381  }
1382  
1383  static VALUE
1384  udp_connect(sock, host, port)
1385      VALUE sock, host, port;
1386  {
1387      OpenFile *fptr;
1388      int fd;
1389      struct udp_arg arg;
1390      VALUE ret;
1391  
1392      rb_secure(3);
1393      GetOpenFile(sock, fptr);
1394      arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0);
1395      arg.fd = fileno(fptr->f);
1396      ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
1397                      RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res);
1398      if (!ret) rb_sys_fail("connect(2)");
1399      return INT2FIX(0);
1400  }
1401  
1402  static VALUE
1403  udp_bind(sock, host, port)
1404      VALUE sock, host, port;
1405  {
1406      OpenFile *fptr;
1407      struct addrinfo *res0, *res;
1408  
1409      rb_secure(3);
1410      GetOpenFile(sock, fptr);
1411      res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
1412      for (res = res0; res; res = res->ai_next) {
1413          if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
1414              continue;
1415          }
1416          freeaddrinfo(res0);
1417          return INT2FIX(0);
1418      }
1419      freeaddrinfo(res0);
1420      rb_sys_fail("bind(2)");
1421      return INT2FIX(0);
1422  }
1423  
1424  static VALUE
1425  udp_send(argc, argv, sock)
1426      int argc;
1427      VALUE *argv;
1428      VALUE sock;
1429  {
1430      VALUE mesg, flags, host, port;
1431      OpenFile *fptr;
1432      FILE *f;
1433      int n;
1434      struct addrinfo *res0, *res;
1435  
1436      if (argc == 2 || argc == 3) {
1437          return bsock_send(argc, argv, sock);
1438      }
1439      rb_secure(4);
1440      rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
1441  
1442      GetOpenFile(sock, fptr);
1443      res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
1444      f = GetWriteFile(fptr);
1445      StringValue(mesg);
1446      for (res = res0; res; res = res->ai_next) {
1447        retry:
1448          n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
1449                     res->ai_addr, res->ai_addrlen);
1450          if (n >= 0) {
1451              freeaddrinfo(res0);
1452              return INT2FIX(n);
1453          }
1454          switch (errno) {
1455            case EINTR:
1456              rb_thread_schedule();
1457              goto retry;
1458          }
1459      }
1460      freeaddrinfo(res0);
1461      rb_sys_fail("sendto(2)");
1462      return INT2FIX(n);
1463  }
1464  
1465  #ifdef HAVE_SYS_UN_H
1466  static VALUE
1467  unix_init(sock, path)
1468      VALUE sock, path;
1469  {
1470      return init_unixsock(sock, path, 0);
1471  }
1472  
1473  static VALUE
1474  unix_path(sock)
1475      VALUE sock;
1476  {
1477      OpenFile *fptr;
1478  
1479      GetOpenFile(sock, fptr);
1480      if (fptr->path == 0) {
1481          struct sockaddr_un addr;
1482          socklen_t len = sizeof(addr);
1483          if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1484              rb_sys_fail(0);
1485          fptr->path = strdup(addr.sun_path);
1486      }
1487      return rb_str_new2(fptr->path);
1488  }
1489  
1490  static VALUE
1491  unix_svr_s_open(klass, path)
1492      VALUE klass, path;
1493  {
1494      return init_unixsock(rb_obj_alloc(klass), path, 1);
1495  }
1496  
1497  static VALUE
1498  unix_svr_init(sock, path)
1499      VALUE sock, path;
1500  {
1501      return init_unixsock(sock, path, 1);
1502  }
1503  
1504  static VALUE
1505  unix_recvfrom(argc, argv, sock)
1506      int argc;
1507      VALUE *argv;
1508      VALUE sock;
1509  {
1510      return s_recvfrom(sock, argc, argv, RECV_UNIX);
1511  }
1512  
1513  static VALUE
1514  unix_send_io(sock, val)
1515      VALUE sock, val;
1516  {
1517  #if defined(HAVE_ST_MSG_CONTROL) || defined(HAVE_ST_MSG_ACCRIGHTS)
1518      int fd;
1519      OpenFile *fptr;
1520      struct msghdr msg;
1521      struct iovec vec[1];
1522      char buf[1];
1523  
1524  #if defined(HAVE_ST_MSG_CONTROL)
1525      struct {
1526          struct cmsghdr hdr;
1527          int fd;
1528      } cmsg;
1529  #endif
1530  
1531      if (rb_obj_is_kind_of(val, rb_cIO)) {
1532          OpenFile *valfptr;
1533          GetOpenFile(val, valfptr);
1534          fd = fileno(valfptr->f);
1535      }
1536      else if (FIXNUM_P(val)) {
1537          fd = FIX2INT(val);
1538      }
1539      else {
1540          rb_raise(rb_eTypeError, "IO nor file descriptor");
1541      }
1542  
1543      GetOpenFile(sock, fptr);
1544  
1545      msg.msg_name = NULL;
1546      msg.msg_namelen = 0;
1547  
1548      /* Linux and Solaris doesn't work if msg_iov is NULL. */
1549      buf[0] = '\0';
1550      vec[0].iov_base = buf;
1551      vec[0].iov_len = 1;
1552      msg.msg_iov = vec;
1553      msg.msg_iovlen = 1;
1554  
1555  #if defined(HAVE_ST_MSG_CONTROL)
1556      msg.msg_control = (caddr_t)&cmsg;
1557      msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
1558      msg.msg_flags = 0;
1559      cmsg.hdr.cmsg_len = sizeof(struct cmsghdr) + sizeof(int);
1560      cmsg.hdr.cmsg_level = SOL_SOCKET;
1561      cmsg.hdr.cmsg_type = SCM_RIGHTS;
1562      cmsg.fd = fd;
1563  #else
1564      msg.msg_accrights = (caddr_t)&fd;
1565      msg.msg_accrightslen = sizeof(fd);
1566  #endif
1567  
1568      if (sendmsg(fileno(fptr->f), &msg, 0) == -1)
1569          rb_sys_fail("sendmsg(2)");
1570  
1571      return Qnil;
1572  #else
1573      rb_notimplement();
1574  #endif
1575  }
1576  
1577  static VALUE
1578  unix_recv_io(argc, argv, sock)
1579      int argc;
1580      VALUE *argv;
1581      VALUE sock;
1582  {
1583  #if defined(HAVE_ST_MSG_CONTROL) || defined(HAVE_ST_MSG_ACCRIGHTS)
1584      VALUE klass, mode;
1585      OpenFile *fptr;
1586      struct msghdr msg;
1587      struct iovec vec[2];
1588      char buf[1];
1589  
1590      int fd;
1591  #if defined(HAVE_ST_MSG_CONTROL)
1592      struct {
1593          struct cmsghdr hdr;
1594          int fd;
1595      } cmsg;
1596  #endif
1597  
1598      rb_scan_args(argc, argv, "02", &klass, &mode);
1599      if (argc == 0)
1600          klass = rb_cIO;
1601      if (argc <= 1)
1602          mode = Qnil;
1603  
1604      GetOpenFile(sock, fptr);
1605  
1606      thread_read_select(fileno(fptr->f));
1607  
1608      msg.msg_name = NULL;
1609      msg.msg_namelen = 0;
1610  
1611      vec[0].iov_base = buf;
1612      vec[0].iov_len = sizeof(buf);
1613      msg.msg_iov = vec;
1614      msg.msg_iovlen = 1;
1615  
1616  #if defined(HAVE_ST_MSG_CONTROL)
1617      msg.msg_control = (caddr_t)&cmsg;
1618      msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
1619      msg.msg_flags = 0;
1620      cmsg.hdr.cmsg_len = sizeof(struct cmsghdr) + sizeof(int);
1621      cmsg.hdr.cmsg_level = SOL_SOCKET;
1622      cmsg.hdr.cmsg_type = SCM_RIGHTS;
1623      cmsg.fd = -1;
1624  #else
1625      msg.msg_accrights = (caddr_t)&fd;
1626      msg.msg_accrightslen = sizeof(fd);
1627      fd = -1;
1628  #endif
1629  
1630      if (recvmsg(fileno(fptr->f), &msg, 0) == -1)
1631          rb_sys_fail("recvmsg(2)");
1632  
1633      if (
1634  #if defined(HAVE_ST_MSG_CONTROL)
1635          msg.msg_controllen != sizeof(struct cmsghdr) + sizeof(int) ||
1636          cmsg.hdr.cmsg_len != sizeof(struct cmsghdr) + sizeof(int) ||
1637          cmsg.hdr.cmsg_level != SOL_SOCKET ||
1638          cmsg.hdr.cmsg_type != SCM_RIGHTS
1639  #else
1640          msg.msg_accrightslen != sizeof(fd)
1641  #endif
1642          ) {
1643          rb_raise(rb_eSocket, "File descriptor was not passed");
1644      }
1645  
1646  #if defined(HAVE_ST_MSG_CONTROL)
1647      fd = cmsg.fd;
1648  #endif
1649  
1650      if (klass == Qnil)
1651          return INT2FIX(fd);
1652      else {
1653          static ID for_fd = 0;
1654          int ff_argc;
1655          VALUE ff_argv[2];
1656          if (!for_fd)
1657              for_fd = rb_intern("for_fd");
1658          ff_argc = mode == Qnil ? 1 : 2;
1659          ff_argv[0] = INT2FIX(fd);
1660          ff_argv[1] = mode;
1661          return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
1662      }
1663  #else
1664      rb_notimplement();
1665  #endif
1666  }
1667  
1668  static VALUE
1669  unix_accept(sock)
1670      VALUE sock;
1671  {
1672      OpenFile *fptr;
1673      struct sockaddr_un from;
1674      socklen_t fromlen;
1675  
1676      GetOpenFile(sock, fptr);
1677      fromlen = sizeof(struct sockaddr_un);
1678      return s_accept(rb_cUNIXSocket, fileno(fptr->f),
1679                      (struct sockaddr*)&from, &fromlen);
1680  }
1681  
1682  static VALUE
1683  unix_sysaccept(sock)
1684      VALUE sock;
1685  {
1686      OpenFile *fptr;
1687      struct sockaddr_un from;
1688      socklen_t fromlen;
1689  
1690      GetOpenFile(sock, fptr);
1691      fromlen = sizeof(struct sockaddr_un);
1692      return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen);
1693  }
1694  
1695  static VALUE
1696  unixaddr(sockaddr)
1697      struct sockaddr_un *sockaddr;
1698  {
1699      return rb_assoc_new(rb_str_new2("AF_UNIX"),
1700                          rb_str_new2(sockaddr->sun_path));
1701  }
1702  
1703  static VALUE
1704  unix_addr(sock)
1705      VALUE sock;
1706  {
1707      OpenFile *fptr;
1708      struct sockaddr_un addr;
1709      socklen_t len = sizeof addr;
1710  
1711      GetOpenFile(sock, fptr);
1712  
1713      if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1714          rb_sys_fail("getsockname(2)");
1715      if (len == 0)
1716          addr.sun_path[0] = '\0';
1717      return unixaddr(&addr);
1718  }
1719  
1720  static VALUE
1721  unix_peeraddr(sock)
1722      VALUE sock;
1723  {
1724      OpenFile *fptr;
1725      struct sockaddr_un addr;
1726      socklen_t len = sizeof addr;
1727  
1728      GetOpenFile(sock, fptr);
1729  
1730      if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
1731          rb_sys_fail("getsockname(2)");
1732      if (len == 0)
1733          addr.sun_path[0] = '\0';
1734      return unixaddr(&addr);
1735  }
1736  #endif
1737  
1738  static void
1739  setup_domain_and_type(domain, dv, type, tv)
1740      VALUE domain, type;
1741      int *dv, *tv;
1742  {
1743      char *ptr;
1744  
1745      if (TYPE(domain) == T_STRING) {
1746          SafeStringValue(domain);
1747          ptr = RSTRING(domain)->ptr;
1748          if (strcmp(ptr, "AF_INET") == 0)
1749              *dv = AF_INET;
1750  #ifdef AF_UNIX
1751          else if (strcmp(ptr, "AF_UNIX") == 0)
1752              *dv = AF_UNIX;
1753  #endif
1754  #ifdef AF_ISO
1755          else if (strcmp(ptr, "AF_ISO") == 0)
1756              *dv = AF_ISO;
1757  #endif
1758  #ifdef AF_NS
1759          else if (strcmp(ptr, "AF_NS") == 0)
1760              *dv = AF_NS;
1761  #endif
1762  #ifdef AF_IMPLINK
1763          else if (strcmp(ptr, "AF_IMPLINK") == 0)
1764              *dv = AF_IMPLINK;
1765  #endif
1766  #ifdef PF_INET
1767          else if (strcmp(ptr, "PF_INET") == 0)
1768              *dv = PF_INET;
1769  #endif
1770  #ifdef PF_UNIX
1771          else if (strcmp(ptr, "PF_UNIX") == 0)
1772              *dv = PF_UNIX;
1773  #endif
1774  #ifdef PF_IMPLINK
1775          else if (strcmp(ptr, "PF_IMPLINK") == 0)
1776              *dv = PF_IMPLINK;
1777          else if (strcmp(ptr, "AF_IMPLINK") == 0)
1778              *dv = AF_IMPLINK;
1779  #endif
1780  #ifdef PF_AX25
1781          else if (strcmp(ptr, "PF_AX25") == 0)
1782              *dv = PF_AX25;
1783  #endif
1784  #ifdef PF_IPX
1785          else if (strcmp(ptr, "PF_IPX") == 0)
1786              *dv = PF_IPX;
1787  #endif
1788          else
1789              rb_raise(rb_eSocket, "Unknown socket domain %s", ptr);
1790      }
1791      else {
1792          *dv = NUM2INT(domain);
1793      }
1794      if (TYPE(type) == T_STRING) {
1795          SafeStringValue(type);
1796          ptr = RSTRING(type)->ptr;
1797          if (strcmp(ptr, "SOCK_STREAM") == 0)
1798              *tv = SOCK_STREAM;
1799          else if (strcmp(ptr, "SOCK_DGRAM") == 0)
1800              *tv = SOCK_DGRAM;
1801  #ifdef SOCK_RAW
1802          else if (strcmp(ptr, "SOCK_RAW") == 0)
1803              *tv = SOCK_RAW;
1804  #endif
1805  #ifdef SOCK_SEQPACKET
1806          else if (strcmp(ptr, "SOCK_SEQPACKET") == 0)
1807              *tv = SOCK_SEQPACKET;
1808  #endif
1809  #ifdef SOCK_RDM
1810          else if (strcmp(ptr, "SOCK_RDM") == 0)
1811              *tv = SOCK_RDM;
1812  #endif
1813  #ifdef SOCK_PACKET
1814          else if (strcmp(ptr, "SOCK_PACKET") == 0)
1815              *tv = SOCK_PACKET;
1816  #endif
1817          else
1818              rb_raise(rb_eSocket, "Unknown socket type %s", ptr);
1819      }
1820      else {
1821          *tv = NUM2INT(type);
1822      }
1823  }
1824  
1825  static VALUE
1826  sock_init(sock, domain, type, protocol)
1827      VALUE sock, domain, type, protocol;
1828  {
1829      int fd;
1830      int d, t;
1831  
1832      rb_secure(3);
1833      setup_domain_and_type(domain, &d, type, &t);
1834      fd = ruby_socket(d, t, NUM2INT(protocol));
1835      if (fd < 0) rb_sys_fail("socket(2)");
1836  
1837      return init_sock(sock, fd);
1838  }
1839  
1840  static VALUE
1841  sock_s_socketpair(klass, domain, type, protocol)
1842      VALUE klass, domain, type, protocol;
1843  {
1844  #if !defined(NT) && !defined(__BEOS__) && !defined(__EMX__) && !defined(__QNXNTO__)
1845      int d, t, sp[2];
1846  
1847      setup_domain_and_type(domain, &d, type, &t);
1848    again:
1849      if (socketpair(d, t, NUM2INT(protocol), sp) < 0) {
1850          if (errno == EMFILE || errno == ENFILE) {
1851              rb_gc();
1852              goto again;
1853          }
1854          rb_sys_fail("socketpair(2)");
1855      }
1856  
1857      return rb_assoc_new(init_sock(rb_obj_alloc(klass), sp[0]),
1858                          init_sock(rb_obj_alloc(klass), sp[1]));
1859  #else
1860      rb_notimplement();
1861  #endif
1862  }
1863  
1864  #ifdef HAVE_SYS_UN_H
1865  static VALUE
1866  unix_s_socketpair(argc, argv, klass)
1867      int argc;
1868      VALUE *argv;
1869      VALUE klass;
1870  {
1871      VALUE domain, type, protocol;
1872      domain = INT2FIX(PF_UNIX);
1873  
1874      rb_scan_args(argc, argv, "02", &type, &protocol);
1875      if (argc == 0)
1876          type = INT2FIX(SOCK_STREAM);
1877      if (argc <= 1)
1878          protocol = INT2FIX(0);
1879  
1880      return sock_s_socketpair(klass, domain, type, protocol);
1881  }
1882  #endif
1883  
1884  static VALUE
1885  sock_connect(sock, addr)
1886      VALUE sock, addr;
1887  {
1888      OpenFile *fptr;
1889      int fd;
1890  
1891      StringValue(addr);
1892      rb_str_modify(addr);
1893  
1894      GetOpenFile(sock, fptr);
1895      fd = fileno(fptr->f);
1896      if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
1897          rb_sys_fail("connect(2)");
1898      }
1899  
1900      return INT2FIX(0);
1901  }
1902  
1903  static VALUE
1904  sock_bind(sock, addr)
1905      VALUE sock, addr;
1906  {
1907      OpenFile *fptr;
1908  
1909      StringValue(addr);
1910      rb_str_modify(addr);
1911  
1912      GetOpenFile(sock, fptr);
1913      if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
1914          rb_sys_fail("bind(2)");
1915  
1916      return INT2FIX(0);
1917  }
1918  
1919  static VALUE
1920  sock_listen(sock, log)
1921     VALUE sock, log;
1922  {
1923      OpenFile *fptr;
1924  
1925      rb_secure(4);
1926      GetOpenFile(sock, fptr);
1927      if (listen(fileno(fptr->f), NUM2INT(log)) < 0)
1928          rb_sys_fail("listen(2)");
1929  
1930      return INT2FIX(0);
1931  }
1932  
1933  static VALUE
1934  sock_recvfrom(argc, argv, sock)
1935      int argc;
1936      VALUE *argv;
1937      VALUE sock;
1938  {
1939      return s_recvfrom(sock, argc, argv, RECV_SOCKET);
1940  }
1941  
1942  static VALUE
1943  sock_accept(sock)
1944     VALUE sock;
1945  {
1946      OpenFile *fptr;
1947      VALUE sock2;
1948      char buf[1024];
1949      socklen_t len = sizeof buf;
1950  
1951      GetOpenFile(sock, fptr);
1952      sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
1953  
1954      return rb_assoc_new(sock2, rb_str_new(buf, len));
1955  }
1956  
1957  static VALUE
1958  sock_sysaccept(sock)
1959     VALUE sock;
1960  {
1961      OpenFile *fptr;
1962      VALUE sock2;
1963      char buf[1024];
1964      socklen_t len = sizeof buf;
1965  
1966      GetOpenFile(sock, fptr);
1967      sock2 = s_accept(0,fileno(fptr->f),(struct sockaddr*)buf,&len);
1968  
1969      return rb_assoc_new(sock2, rb_str_new(buf, len));
1970  }
1971  
1972  #ifdef HAVE_GETHOSTNAME
1973  static VALUE
1974  sock_gethostname(obj)
1975      VALUE obj;
1976  {
1977      char buf[1024];
1978  
1979      rb_secure(3);
1980      if (gethostname(buf, (int)sizeof buf - 1) < 0)
1981          rb_sys_fail("gethostname");
1982  
1983      buf[sizeof buf - 1] = '\0';
1984      return rb_str_new2(buf);
1985  }
1986  #else
1987  #ifdef HAVE_UNAME
1988  
1989  #include <sys/utsname.h>
1990  
1991  static VALUE
1992  sock_gethostname(obj)
1993      VALUE obj;
1994  {
1995      struct utsname un;
1996  
1997      rb_secure(3);
1998      uname(&un);
1999      return rb_str_new2(un.nodename);
2000  }
2001  #else
2002  static VALUE
2003  sock_gethostname(obj)
2004      VALUE obj;
2005  {
2006      rb_notimplement();
2007  }
2008  #endif
2009  #endif
2010  
2011  static VALUE
2012  sock_mkhostent(h)
2013      struct hostent *h;
2014  {
2015      char **pch;
2016      VALUE ary, names;
2017  
2018      if (h == NULL) {
2019  #ifdef HAVE_HSTRERROR
2020          extern int h_errno;
2021          rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
2022  #else
2023          rb_raise(rb_eSocket, "host not found");
2024  #endif
2025      }
2026      ary = rb_ary_new();
2027      rb_ary_push(ary, rb_str_new2(h->h_name));
2028      names = rb_ary_new();
2029      rb_ary_push(ary, names);
2030      for (pch = h->h_aliases; *pch; pch++) {
2031          rb_ary_push(names, rb_str_new2(*pch));
2032      }
2033      rb_ary_push(ary, INT2NUM(h->h_addrtype));
2034  #ifdef h_addr
2035      for (pch = h->h_addr_list; *pch; pch++) {
2036          rb_ary_push(ary, rb_str_new(*pch, h->h_length));
2037      }
2038  #else
2039      rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
2040  #endif
2041  
2042      return ary;
2043  }
2044  
2045  static VALUE
2046  mkaddrinfo(res0)
2047      struct addrinfo *res0;
2048  {
2049      VALUE base, ary;
2050      struct addrinfo *res;
2051  
2052      if (res0 == NULL) {
2053          rb_raise(rb_eSocket, "host not found");
2054      }
2055      base = rb_ary_new();
2056      for (res = res0; res; res = res->ai_next) {
2057          ary = ipaddr(res->ai_addr);
2058          rb_ary_push(ary, INT2FIX(res->ai_family));
2059          rb_ary_push(ary, INT2FIX(res->ai_socktype));
2060          rb_ary_push(ary, INT2FIX(res->ai_protocol));
2061          rb_ary_push(base, ary);
2062      }
2063      return base;
2064  }
2065  
2066  static VALUE
2067  sock_s_gethostbyname(obj, host)
2068      VALUE obj, host;
2069  {
2070      return sock_mkhostent(sock_hostbyname(host));
2071  }
2072  
2073  static VALUE
2074  sock_s_gethostbyaddr(argc, argv)
2075      int argc;
2076      VALUE *argv;
2077  {
2078      VALUE addr, type;
2079      struct hostent *h;
2080      struct sockaddr *sa;
2081      int t = AF_INET;
2082  
2083      rb_scan_args(argc, argv, "11", &addr, &type);
2084      sa = (struct sockaddr*)StringValuePtr(addr);
2085      if (!NIL_P(type)) {
2086          t = NUM2INT(type);
2087      }
2088  #ifdef INET6
2089      else if (RSTRING(addr)->len == 16) {
2090          t = AF_INET6;
2091      }
2092  #endif
2093      h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, t);
2094  
2095      return sock_mkhostent(h);
2096  }
2097  
2098  static VALUE
2099  sock_s_getservbyaname(argc, argv)
2100      int argc;
2101      VALUE *argv;
2102  {
2103      VALUE service, protocol;
2104      char *proto;
2105      struct servent *sp;
2106      int port;
2107  
2108      rb_scan_args(argc, argv, "11", &service, &protocol);
2109      if (NIL_P(protocol)) proto = "tcp";
2110      else proto = StringValuePtr(protocol);
2111  
2112      StringValue(service);
2113      sp = getservbyname(RSTRING(service)->ptr, proto);
2114      if (sp) {
2115          port = ntohs(sp->s_port);
2116      }
2117      else {
2118          char *s = RSTRING(service)->ptr;
2119          char *end;
2120  
2121          port = strtoul(s, &end, 0);
2122          if (*end != '\0') {
2123              rb_raise(rb_eSocket, "no such service %s/%s", s, proto);
2124          }
2125      }
2126      return INT2FIX(port);
2127  }
2128  
2129  static VALUE
2130  sock_s_getaddrinfo(argc, argv)
2131      int argc;
2132      VALUE *argv;
2133  {
2134      VALUE host, port, family, socktype, protocol, flags, ret;
2135      char hbuf[1024], pbuf[1024];
2136      char *hptr, *pptr, *ap;
2137      struct addrinfo hints, *res;
2138      int error;
2139  
2140      host = port = family = socktype = protocol = flags = Qnil;
2141      rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol, &flags);
2142      if (NIL_P(host)) {
2143          hptr = NULL;
2144      }
2145      else {
2146          strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
2147          hbuf[sizeof(hbuf) - 1] = '\0';
2148          hptr = hbuf;
2149      }
2150      if (NIL_P(port)) {
2151          pptr = NULL;
2152      }
2153      else if (FIXNUM_P(port)) {
2154          snprintf(pbuf, sizeof(pbuf), "%ld", FIX2INT(port));
2155          pptr = pbuf;
2156      }
2157      else {
2158          strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
2159          pbuf[sizeof(pbuf) - 1] = '\0';
2160          pptr = pbuf;
2161      }
2162  
2163      MEMZERO(&hints, struct addrinfo, 1);
2164      if (NIL_P(family)) {
2165          hints.ai_family = PF_UNSPEC;
2166      }
2167      else if (FIXNUM_P(family)) {
2168          hints.ai_family = FIX2INT(family);
2169      }
2170      else if ((ap = StringValuePtr(family)) != 0) {
2171          if (strcmp(ap, "AF_INET") == 0) {
2172              hints.ai_family = PF_INET;
2173          }
2174  #ifdef INET6
2175          else if (strcmp(ap, "AF_INET6") == 0) {
2176              hints.ai_family = PF_INET6;
2177          }
2178  #endif
2179      }
2180  
2181      if (!NIL_P(socktype)) {
2182          hints.ai_socktype = NUM2INT(socktype);
2183      }
2184      if (!NIL_P(protocol)) {
2185          hints.ai_protocol = NUM2INT(protocol);
2186      }
2187      if (!NIL_P(flags)) {
2188          hints.ai_flags = NUM2INT(flags);
2189      }
2190      error = getaddrinfo(hptr, pptr, &hints, &res);
2191      if (error) {
2192          rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
2193      }
2194  
2195      ret = mkaddrinfo(res);
2196      freeaddrinfo(res);
2197      return ret;
2198  }
2199  
2200  static VALUE
2201  sock_s_getnameinfo(argc, argv)
2202      int argc;
2203      VALUE *argv;
2204  {
2205      VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags;
2206      char *hptr, *pptr;
2207      char hbuf[1024], pbuf[1024];
2208      int fl;
2209      struct addrinfo hints, *res = NULL, *r;
2210      int error;
2211      struct sockaddr_storage ss;
2212      struct sockaddr *sap;
2213      char *ep, *ap;
2214  
2215      sa = flags = Qnil;
2216      rb_scan_args(argc, argv, "11", &sa, &flags);
2217  
2218      fl = 0;
2219      if (!NIL_P(flags)) {
2220          fl = NUM2INT(flags);
2221      }
2222      if (TYPE(sa) == T_STRING) {
2223          if (sizeof(ss) < RSTRING(sa)->len) {
2224              rb_raise(rb_eTypeError, "sockaddr length too big");
2225          }
2226          memcpy(&ss, RSTRING(sa)->ptr, RSTRING(sa)->len);
2227          if (RSTRING(sa)->len != SA_LEN((struct sockaddr*)&ss)) {
2228              rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
2229          }
2230          sap = (struct sockaddr*)&ss;
2231      }
2232      else if (TYPE(sa) == T_ARRAY) {
2233          MEMZERO(&hints, struct addrinfo, 1);
2234          if (RARRAY(sa)->len == 3) {
2235              af = RARRAY(sa)->ptr[0];
2236              port = RARRAY(sa)->ptr[1];
2237              host = RARRAY(sa)->ptr[2];
2238          }
2239          else if (RARRAY(sa)->len >= 4) {
2240              af = RARRAY(sa)->ptr[0];
2241              port = RARRAY(sa)->ptr[1];
2242              host = RARRAY(sa)->ptr[3];
2243              if (NIL_P(host)) {
2244                  host = RARRAY(sa)->ptr[2];
2245              }
2246              else {
2247                  /*
2248                   * 4th element holds numeric form, don't resolve.
2249                   * see ipaddr().
2250                   */
2251                  hints.ai_flags |= AI_NUMERICHOST;
2252              }
2253          }
2254          else {
2255              rb_raise(rb_eArgError, "array size should be 3 or 4, %d given",
2256                       RARRAY(sa)->len);
2257          }
2258          /* host */
2259          if (NIL_P(host)) {
2260              hptr = NULL;
2261          }
2262          else {
2263              strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
2264              hbuf[sizeof(hbuf) - 1] = '\0';
2265              hptr = hbuf;
2266          }
2267          /* port */
2268          if (NIL_P(port)) {
2269              strcpy(pbuf, "0");
2270              pptr = NULL;
2271          }
2272          else if (FIXNUM_P(port)) {
2273              snprintf(pbuf, sizeof(pbuf), "%ld", NUM2INT(port));
2274              pptr = pbuf;
2275          }
2276          else {
2277              strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
2278              pbuf[sizeof(pbuf) - 1] = '\0';
2279              pptr = pbuf;
2280          }
2281          hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
2282          /* af */
2283          if (NIL_P(af)) {
2284              hints.ai_family = PF_UNSPEC;
2285          }
2286          else if (FIXNUM_P(af)) {
2287              hints.ai_family = FIX2INT(af);
2288          }
2289          else if ((ap = StringValuePtr(af)) != 0) {
2290              if (strcmp(ap, "AF_INET") == 0) {
2291                  hints.ai_family = PF_INET;
2292              }
2293  #ifdef INET6
2294              else if (strcmp(ap, "AF_INET6") == 0) {
2295                  hints.ai_family = PF_INET6;
2296              }
2297  #endif
2298          }
2299          error = getaddrinfo(hptr, pptr, &hints, &res);
2300          if (error) goto error_exit_addr;
2301          sap = res->ai_addr;
2302      }
2303      else {
2304          rb_raise(rb_eTypeError, "expecting String or Array");
2305      }
2306  
2307      error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
2308                          pbuf, sizeof(pbuf), fl);
2309      if (error) goto error_exit_name;
2310      if (res) {
2311          for (r = res->ai_next; r; r = r->ai_next) {
2312              char hbuf2[1024], pbuf2[1024];
2313  
2314              sap = r->ai_addr;
2315              error = getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
2316                                  pbuf2, sizeof(pbuf2), fl);
2317              if (error) goto error_exit_name;
2318              if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
2319                  freeaddrinfo(res);
2320                  rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
2321              }
2322          }
2323          freeaddrinfo(res);
2324      }
2325      return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
2326  
2327    error_exit_addr:
2328      if (res) freeaddrinfo(res);
2329      rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
2330  
2331    error_exit_name:
2332      if (res) freeaddrinfo(res);
2333      rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
2334  }
2335  
2336  static VALUE
2337  sock_s_pack_sockaddr_in(self, port, host)
2338      VALUE self, port, host;
2339  {
2340      struct addrinfo *res = sock_addrinfo(host, port, 0, 0);
2341      VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
2342  
2343      freeaddrinfo(res);
2344      OBJ_INFECT(addr, port);
2345      OBJ_INFECT(addr, host);
2346  
2347      return addr;
2348  }
2349  
2350  static VALUE
2351  sock_s_unpack_sockaddr_in(self, addr)
2352      VALUE self, addr;
2353  {
2354      struct sockaddr_in * sockaddr;
2355      VALUE host;
2356  
2357      sockaddr = (struct sockaddr_in*)StringValuePtr(addr);
2358      if (RSTRING(addr)->len != sizeof(struct sockaddr_in)) {
2359          rb_raise(rb_eTypeError, "sockaddr_in size differs - %d required; %d given",
2360                   RSTRING(addr)->len, sizeof(struct sockaddr_in));
2361      }
2362      host = mkipaddr(sockaddr);
2363      OBJ_INFECT(host, addr);
2364      return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
2365  }
2366  
2367  #ifdef HAVE_SYS_UN_H
2368  static VALUE
2369  sock_s_pack_sockaddr_un(self, path)
2370      VALUE self, path;
2371  {
2372      struct sockaddr_un sockaddr;
2373      VALUE addr;
2374  
2375      MEMZERO(&sockaddr, struct sockaddr_un, 1);
2376      sockaddr.sun_family = AF_UNIX;
2377      strncpy(sockaddr.sun_path, StringValuePtr(path), sizeof(sockaddr.sun_path)-1);
2378      addr = rb_str_new((char*)&sockaddr, sizeof(sockaddr));
2379      OBJ_INFECT(addr, path);
2380  
2381      return addr;
2382  }
2383  
2384  static VALUE
2385  sock_s_unpack_sockaddr_un(self, addr)
2386      VALUE self, addr;
2387  {
2388      struct sockaddr_un * sockaddr;
2389      VALUE path;
2390  
2391      sockaddr = (struct sockaddr_un*)StringValuePtr(addr);
2392      if (RSTRING(addr)->len != sizeof(struct sockaddr_un)) {
2393          rb_raise(rb_eTypeError, "sockaddr_un size differs - %d required; %d given",
2394                   RSTRING(addr)->len, sizeof(struct sockaddr_un));
2395      }
2396      /* xxx: should I check against sun_path size? */
2397      path = rb_str_new2(sockaddr->sun_path);
2398      OBJ_INFECT(path, addr);
2399      return path;
2400  }
2401  #endif
2402  
2403  static VALUE mConst;
2404  
2405  static void
2406  sock_define_const(name, value)
2407      char *name;
2408      int value;
2409  {
2410      rb_define_const(rb_cSocket, name, INT2FIX(value));
2411      rb_define_const(mConst, name, INT2FIX(value));
2412  }
2413  
2414  void
2415  Init_socket()
2416  {
2417      rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
2418  
2419      rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
2420      rb_undef_method(rb_cBasicSocket, "initialize");
2421  
2422      rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
2423                                 bsock_do_not_rev_lookup, 0);
2424      rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
2425                                 bsock_do_not_rev_lookup_set, 1);
2426      rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
2427  
2428      rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
2429      rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
2430      rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
2431      rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3);
2432      rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
2433      rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
2434      rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
2435      rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
2436      rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
2437  
2438      rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
2439      rb_define_global_const("IPsocket", rb_cIPSocket);
2440      rb_define_method(rb_cIPSocket, "addr", ip_addr, 0);
2441      rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, 0);
2442      rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
2443      rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
2444  
2445      rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
2446      rb_define_global_const("TCPsocket", rb_cTCPSocket);
2447      rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
2448      rb_define_method(rb_cTCPSocket, "initialize", tcp_init, -1);
2449  
2450  #ifdef SOCKS
2451      rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
2452      rb_define_global_const("SOCKSsocket", rb_cSOCKSSocket);
2453      rb_define_method(rb_cSOCKSSocket, "initialize", socks_init, 2);
2454  #ifdef SOCKS5
2455      rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
2456  #endif
2457  #endif
2458  
2459      rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
2460      rb_define_global_const("TCPserver", rb_cTCPServer);
2461      rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
2462      rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
2463      rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
2464      rb_define_method(rb_cTCPServer, "listen", sock_listen, 1);
2465  
2466      rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
2467      rb_define_global_const("UDPsocket", rb_cUDPSocket);
2468      rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
2469      rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
2470      rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
2471      rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
2472  
2473  #ifdef HAVE_SYS_UN_H
2474      rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
2475      rb_define_global_const("UNIXsocket", rb_cUNIXSocket);
2476      rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1);
2477      rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
2478      rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
2479      rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
2480      rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
2481      rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
2482      rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
2483      rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
2484      rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
2485  
2486      rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
2487      rb_define_global_const("UNIXserver", rb_cUNIXServer);
2488      rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
2489      rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
2490      rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
2491      rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1);
2492  #endif
2493  
2494      rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
2495  
2496      rb_define_method(rb_cSocket, "initialize", sock_init, 3);
2497      rb_define_method(rb_cSocket, "connect", sock_connect, 1);
2498      rb_define_method(rb_cSocket, "bind", sock_bind, 1);
2499      rb_define_method(rb_cSocket, "listen", sock_listen, 1);
2500      rb_define_method(rb_cSocket, "accept", sock_accept, 0);
2501      rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
2502  
2503      rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
2504  
2505      rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
2506      rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
2507      rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
2508      rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
2509      rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
2510      rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1);
2511      rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
2512      rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
2513      rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
2514      rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
2515      rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
2516  #ifdef HAVE_SYS_UN_H
2517      rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
2518      rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
2519      rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
2520  #endif
2521  
2522      /* constants */
2523      mConst = rb_define_module_under(rb_cSocket, "Constants");
2524      sock_define_const("SOCK_STREAM", SOCK_STREAM);
2525      sock_define_const("SOCK_DGRAM", SOCK_DGRAM);
2526  #ifdef SOCK_RAW
2527      sock_define_const("SOCK_RAW", SOCK_RAW);
2528  #endif
2529  #ifdef SOCK_RDM
2530      sock_define_const("SOCK_RDM", SOCK_RDM);
2531  #endif
2532  #ifdef SOCK_SEQPACKET
2533      sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
2534  #endif
2535  #ifdef SOCK_PACKET
2536      sock_define_const("SOCK_PACKET", SOCK_PACKET);
2537  #endif
2538  
2539      sock_define_const("AF_INET", AF_INET);
2540  #ifdef PF_INET
2541      sock_define_const("PF_INET", PF_INET);
2542  #endif
2543  #ifdef AF_UNIX
2544      sock_define_const("AF_UNIX", AF_UNIX);
2545      sock_define_const("PF_UNIX", PF_UNIX);
2546  #endif
2547  #ifdef AF_AX25
2548      sock_define_const("AF_AX25", AF_AX25);
2549      sock_define_const("PF_AX25", PF_AX25);
2550  #endif
2551  #ifdef AF_IPX
2552      sock_define_const("AF_IPX", AF_IPX);
2553      sock_define_const("PF_IPX", PF_IPX);
2554  #endif
2555  #ifdef AF_APPLETALK
2556      sock_define_const("AF_APPLETALK", AF_APPLETALK);
2557      sock_define_const("PF_APPLETALK", PF_APPLETALK);
2558  #endif
2559  #ifdef AF_UNSPEC
2560      sock_define_const("AF_UNSPEC", AF_UNSPEC);
2561      sock_define_const("PF_UNSPEC", PF_UNSPEC);
2562  #endif
2563  #ifdef AF_INET6
2564      sock_define_const("AF_INET6", AF_INET6);
2565  #endif
2566  #ifdef PF_INET6
2567      sock_define_const("PF_INET6", PF_INET6);
2568  #endif
2569  
2570      sock_define_const("MSG_OOB", MSG_OOB);
2571  #ifdef MSG_PEEK
2572      sock_define_const("MSG_PEEK", MSG_PEEK);
2573  #endif
2574  #ifdef MSG_DONTROUTE
2575      sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
2576  #endif
2577  
2578      sock_define_const("SOL_SOCKET", SOL_SOCKET);
2579  #ifdef SOL_IP
2580      sock_define_const("SOL_IP", SOL_IP);
2581  #endif
2582  #ifdef SOL_IPX
2583      sock_define_const("SOL_IPX", SOL_IPX);
2584  #endif
2585  #ifdef SOL_AX25
2586      sock_define_const("SOL_AX25", SOL_AX25);
2587  #endif
2588  #ifdef SOL_ATALK
2589      sock_define_const("SOL_ATALK", SOL_ATALK);
2590  #endif
2591  #ifdef SOL_TCP
2592      sock_define_const("SOL_TCP", SOL_TCP);
2593  #endif
2594  #ifdef SOL_UDP
2595      sock_define_const("SOL_UDP", SOL_UDP);
2596  #endif
2597  
2598  #ifdef  IPPROTO_IP
2599      sock_define_const("IPPROTO_IP", IPPROTO_IP);
2600  #else
2601      sock_define_const("IPPROTO_IP", 0);
2602  #endif
2603  #ifdef  IPPROTO_ICMP
2604      sock_define_const("IPPROTO_ICMP", IPPROTO_ICMP);
2605  #else
2606      sock_define_const("IPPROTO_ICMP", 1);
2607  #endif
2608  #ifdef  IPPROTO_IGMP
2609      sock_define_const("IPPROTO_IGMP", IPPROTO_IGMP);
2610  #endif
2611  #ifdef  IPPROTO_GGP
2612      sock_define_const("IPPROTO_GGP", IPPROTO_GGP);
2613  #endif
2614  #ifdef  IPPROTO_TCP
2615      sock_define_const("IPPROTO_TCP", IPPROTO_TCP);
2616  #else
2617      sock_define_const("IPPROTO_TCP", 6);
2618  #endif
2619  #ifdef  IPPROTO_EGP
2620      sock_define_const("IPPROTO_EGP", IPPROTO_EGP);
2621  #endif
2622  #ifdef  IPPROTO_PUP
2623      sock_define_const("IPPROTO_PUP", IPPROTO_PUP);
2624  #endif
2625  #ifdef  IPPROTO_UDP
2626      sock_define_const("IPPROTO_UDP", IPPROTO_UDP);
2627  #else
2628      sock_define_const("IPPROTO_UDP", 17);
2629  #endif
2630  #ifdef  IPPROTO_IDP
2631      sock_define_const("IPPROTO_IDP", IPPROTO_IDP);
2632  #endif
2633  #ifdef  IPPROTO_HELLO
2634      sock_define_const("IPPROTO_HELLO", IPPROTO_HELLO);
2635  #endif
2636  #ifdef  IPPROTO_ND
2637      sock_define_const("IPPROTO_ND", IPPROTO_ND);
2638  #endif
2639  #ifdef  IPPROTO_TP
2640      sock_define_const("IPPROTO_TP", IPPROTO_TP);
2641  #endif
2642  #ifdef  IPPROTO_XTP
2643      sock_define_const("IPPROTO_XTP", IPPROTO_XTP);
2644  #endif
2645  #ifdef  IPPROTO_EON
2646      sock_define_const("IPPROTO_EON", IPPROTO_EON);
2647  #endif
2648  #ifdef  IPPROTO_BIP
2649      sock_define_const("IPPROTO_BIP", IPPROTO_BIP);
2650  #endif
2651  /**/
2652  #ifdef  IPPROTO_RAW
2653      sock_define_const("IPPROTO_RAW", IPPROTO_RAW);
2654  #else
2655      sock_define_const("IPPROTO_RAW", 255);
2656  #endif
2657  #ifdef  IPPROTO_MAX
2658      sock_define_const("IPPROTO_MAX", IPPROTO_MAX);
2659  #endif
2660  
2661          /* Some port configuration */
2662  #ifdef  IPPORT_RESERVED
2663      sock_define_const("IPPORT_RESERVED", IPPORT_RESERVED);
2664  #else
2665      sock_define_const("IPPORT_RESERVED", 1024);
2666  #endif
2667  #ifdef  IPPORT_USERRESERVED
2668      sock_define_const("IPPORT_USERRESERVED", IPPORT_USERRESERVED);
2669  #else
2670      sock_define_const("IPPORT_USERRESERVED", 5000);
2671  #endif
2672          /* Some reserved IP v.4 addresses */
2673  #ifdef  INADDR_ANY
2674      sock_define_const("INADDR_ANY", INADDR_ANY);
2675  #else
2676      sock_define_const("INADDR_ANY", 0x00000000);
2677  #endif
2678  #ifdef  INADDR_BROADCAST
2679      sock_define_const("INADDR_BROADCAST", INADDR_BROADCAST);
2680  #else
2681      sock_define_const("INADDR_BROADCAST", 0xffffffff);
2682  #endif
2683  #ifdef  INADDR_LOOPBACK
2684      sock_define_const("INADDR_LOOPBACK", INADDR_LOOPBACK);
2685  #else
2686      sock_define_const("INADDR_LOOPBACK", 0x7F000001);
2687  #endif
2688  #ifdef  INADDR_UNSPEC_GROUP
2689      sock_define_const("INADDR_UNSPEC_GROUP", INADDR_UNSPEC_GROUP);
2690  #else
2691      sock_define_const("INADDR_UNSPEC_GROUP", 0xe0000000);
2692  #endif
2693  #ifdef  INADDR_ALLHOSTS_GROUP
2694      sock_define_const("INADDR_ALLHOSTS_GROUP", INADDR_ALLHOSTS_GROUP);
2695  #else
2696      sock_define_const("INADDR_ALLHOSTS_GROUP", 0xe0000001);
2697  #endif
2698  #ifdef  INADDR_MAX_LOCAL_GROUP
2699      sock_define_const("INADDR_MAX_LOCAL_GROUP", INADDR_MAX_LOCAL_GROUP);
2700  #else
2701      sock_define_const("INADDR_MAX_LOCAL_GROUP", 0xe00000ff);
2702  #endif
2703  #ifdef  INADDR_NONE
2704      sock_define_const("INADDR_NONE", INADDR_NONE);
2705  #else
2706      sock_define_const("INADDR_NONE", 0xffffffff);
2707  #endif
2708          /* IP [gs]etsockopt options */
2709  #ifdef  IP_OPTIONS
2710      sock_define_const("IP_OPTIONS", IP_OPTIONS);
2711  #endif
2712  #ifdef  IP_HDRINCL
2713      sock_define_const("IP_HDRINCL", IP_HDRINCL);
2714  #endif
2715  #ifdef  IP_TOS
2716      sock_define_const("IP_TOS", IP_TOS);
2717  #endif
2718  #ifdef  IP_TTL
2719      sock_define_const("IP_TTL", IP_TTL);
2720  #endif
2721  #ifdef  IP_RECVOPTS
2722      sock_define_const("IP_RECVOPTS", IP_RECVOPTS);
2723  #endif
2724  #ifdef  IP_RECVRETOPTS
2725      sock_define_const("IP_RECVRETOPTS", IP_RECVRETOPTS);
2726  #endif
2727  #ifdef  IP_RECVDSTADDR
2728      sock_define_const("IP_RECVDSTADDR", IP_RECVDSTADDR);
2729  #endif
2730  #ifdef  IP_RETOPTS
2731      sock_define_const("IP_RETOPTS", IP_RETOPTS);
2732  #endif
2733  #ifdef  IP_MULTICAST_IF
2734      sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
2735  #endif
2736  #ifdef  IP_MULTICAST_TTL
2737      sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
2738  #endif
2739  #ifdef  IP_MULTICAST_LOOP
2740      sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
2741  #endif
2742  #ifdef  IP_ADD_MEMBERSHIP
2743      sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
2744  #endif
2745  #ifdef  IP_DROP_MEMBERSHIP
2746      sock_define_const("IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP);
2747  #endif
2748  #ifdef  IP_DEFAULT_MULTICAST_TTL
2749      sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
2750  #endif
2751  #ifdef  IP_DEFAULT_MULTICAST_LOOP
2752      sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
2753  #endif
2754  #ifdef  IP_MAX_MEMBERSHIPS
2755      sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
2756  #endif
2757  #ifdef SO_DEBUG
2758      sock_define_const("SO_DEBUG", SO_DEBUG);
2759  #endif
2760      sock_define_const("SO_REUSEADDR", SO_REUSEADDR);
2761  #ifdef SO_TYPE
2762      sock_define_const("SO_TYPE", SO_TYPE);
2763  #endif
2764  #ifdef SO_ERROR
2765      sock_define_const("SO_ERROR", SO_ERROR);
2766  #endif
2767  #ifdef SO_DONTROUTE
2768      sock_define_const("SO_DONTROUTE", SO_DONTROUTE);
2769  #endif
2770  #ifdef SO_BROADCAST
2771      sock_define_const("SO_BROADCAST", SO_BROADCAST);
2772  #endif
2773  #ifdef SO_SNDBUF
2774      sock_define_const("SO_SNDBUF", SO_SNDBUF);
2775  #endif
2776  #ifdef SO_RCVBUF
2777      sock_define_const("SO_RCVBUF", SO_RCVBUF);
2778  #endif
2779  #ifdef SO_KEEPALIVE
2780      sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
2781  #endif
2782  #ifdef SO_OOBINLINE
2783      sock_define_const("SO_OOBINLINE", SO_OOBINLINE);
2784  #endif
2785  #ifdef SO_NO_CHECK
2786      sock_define_const("SO_NO_CHECK", SO_NO_CHECK);
2787  #endif
2788  #ifdef SO_PRIORITY
2789      sock_define_const("SO_PRIORITY", SO_PRIORITY);
2790  #endif
2791  #ifdef SO_LINGER
2792      sock_define_const("SO_LINGER", SO_LINGER);
2793  #endif
2794  #ifdef SO_PASSCRED
2795      sock_define_const("SO_PASSCRED", SO_PASSCRED);
2796  #endif
2797  #ifdef SO_PEERCRED
2798      sock_define_const("SO_PEERCRED", SO_PEERCRED);
2799  #endif
2800  #ifdef SO_RCVLOWAT
2801      sock_define_const("SO_RCVLOWAT", SO_RCVLOWAT);
2802  #endif
2803  #ifdef SO_SNDLOWAT
2804      sock_define_const("SO_SNDLOWAT", SO_SNDLOWAT);
2805  #endif
2806  #ifdef SO_RCVTIMEO
2807      sock_define_const("SO_RCVTIMEO", SO_RCVTIMEO);
2808  #endif
2809  #ifdef SO_SNDTIMEO
2810      sock_define_const("SO_SNDTIMEO", SO_SNDTIMEO);
2811  #endif
2812  
2813  #ifdef SO_SECURITY_AUTHENTICATION
2814      sock_define_const("SO_SECURITY_AUTHENTICATION", SO_SECURITY_AUTHENTICATION);
2815  #endif
2816  #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
2817      sock_define_const("SO_SECURITY_ENCRYPTION_TRANSPORT", SO_SECURITY_ENCRYPTION_TRANSPORT);
2818  #endif
2819  #ifdef SO_SECURITY_ENCRYPTION_NETWORK
2820      sock_define_const("SO_SECURITY_ENCRYPTION_NETWORK", SO_SECURITY_ENCRYPTION_NETWORK);
2821  #endif
2822  
2823  #ifdef SO_BINDTODEVICE
2824      sock_define_const("SO_BINDTODEVICE", SO_BINDTODEVICE);
2825  #endif
2826  #ifdef SO_ATTACH_FILTER
2827      sock_define_const("SO_ATTACH_FILTER", SO_ATTACH_FILTER);
2828  #endif
2829  #ifdef SO_DETACH_FILTER
2830      sock_define_const("SO_DETACH_FILTER", SO_DETACH_FILTER);
2831  #endif
2832  #ifdef SO_PEERNAME
2833      sock_define_const("SO_PEERNAME", SO_PEERNAME);
2834  #endif
2835  #ifdef SO_TIMESTAMP
2836      sock_define_const("SO_TIMESTAMP", SO_TIMESTAMP);
2837  #endif
2838  
2839  #ifdef SOPRI_INTERACTIVE
2840      sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
2841  #endif
2842  #ifdef SOPRI_NORMAL
2843      sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
2844  #endif
2845  #ifdef SOPRI_BACKGROUND
2846      sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
2847  #endif
2848  
2849  #ifdef IPX_TYPE
2850      sock_define_const("IPX_TYPE", IPX_TYPE);
2851  #endif
2852  
2853  #ifdef TCP_NODELAY
2854      sock_define_const("TCP_NODELAY", TCP_NODELAY);
2855  #endif
2856  #ifdef TCP_MAXSEG
2857      sock_define_const("TCP_MAXSEG", TCP_MAXSEG);
2858  #endif
2859  
2860  #ifdef EAI_ADDRFAMILY
2861      sock_define_const("EAI_ADDRFAMILY", EAI_ADDRFAMILY);
2862  #endif
2863  #ifdef EAI_AGAIN
2864      sock_define_const("EAI_AGAIN", EAI_AGAIN);
2865  #endif
2866  #ifdef EAI_BADFLAGS
2867      sock_define_const("EAI_BADFLAGS", EAI_BADFLAGS);
2868  #endif
2869  #ifdef EAI_FAIL
2870      sock_define_const("EAI_FAIL", EAI_FAIL);
2871  #endif
2872  #ifdef EAI_FAMILY
2873      sock_define_const("EAI_FAMILY", EAI_FAMILY);
2874  #endif
2875  #ifdef EAI_MEMORY
2876      sock_define_const("EAI_MEMORY", EAI_MEMORY);
2877  #endif
2878  #ifdef EAI_NODATA
2879      sock_define_const("EAI_NODATA", EAI_NODATA);
2880  #endif
2881  #ifdef EAI_NONAME
2882      sock_define_const("EAI_NONAME", EAI_NONAME);
2883  #endif
2884  #ifdef EAI_SERVICE
2885      sock_define_const("EAI_SERVICE", EAI_SERVICE);
2886  #endif
2887  #ifdef EAI_SOCKTYPE
2888      sock_define_const("EAI_SOCKTYPE", EAI_SOCKTYPE);
2889  #endif
2890  #ifdef EAI_SYSTEM
2891      sock_define_const("EAI_SYSTEM", EAI_SYSTEM);
2892  #endif
2893  #ifdef EAI_BADHINTS
2894      sock_define_const("EAI_BADHINTS", EAI_BADHINTS);
2895  #endif
2896  #ifdef EAI_PROTOCOL
2897      sock_define_const("EAI_PROTOCOL", EAI_PROTOCOL);
2898  #endif
2899  #ifdef EAI_MAX
2900      sock_define_const("EAI_MAX", EAI_MAX);
2901  #endif
2902  #ifdef AI_PASSIVE
2903      sock_define_const("AI_PASSIVE", AI_PASSIVE);
2904  #endif
2905  #ifdef AI_CANONNAME
2906      sock_define_const("AI_CANONNAME", AI_CANONNAME);
2907  #endif
2908  #ifdef AI_NUMERICHOST
2909      sock_define_const("AI_NUMERICHOST", AI_NUMERICHOST);
2910  #endif
2911  #ifdef AI_MASK
2912      sock_define_const("AI_MASK", AI_MASK);
2913  #endif
2914  #ifdef AI_ALL
2915      sock_define_const("AI_ALL", AI_ALL);
2916  #endif
2917  #ifdef AI_V4MAPPED_CFG
2918      sock_define_const("AI_V4MAPPED_CFG", AI_V4MAPPED_CFG);
2919  #endif
2920  #ifdef AI_ADDRCONFIG
2921      sock_define_const("AI_ADDRCONFIG", AI_ADDRCONFIG);
2922  #endif
2923  #ifdef AI_V4MAPPED
2924      sock_define_const("AI_V4MAPPED", AI_V4MAPPED);
2925  #endif
2926  #ifdef AI_DEFAULT
2927      sock_define_const("AI_DEFAULT", AI_DEFAULT);
2928  #endif
2929  #ifdef NI_MAXHOST
2930      sock_define_const("NI_MAXHOST", NI_MAXHOST);
2931  #endif
2932  #ifdef NI_MAXSERV
2933      sock_define_const("NI_MAXSERV", NI_MAXSERV);
2934  #endif
2935  #ifdef NI_NOFQDN
2936      sock_define_const("NI_NOFQDN", NI_NOFQDN);
2937  #endif
2938  #ifdef NI_NUMERICHOST
2939      sock_define_const("NI_NUMERICHOST", NI_NUMERICHOST);
2940  #endif
2941  #ifdef NI_NAMEREQD
2942      sock_define_const("NI_NAMEREQD", NI_NAMEREQD);
2943  #endif
2944  #ifdef NI_NUMERICSERV
2945      sock_define_const("NI_NUMERICSERV", NI_NUMERICSERV);
2946  #endif
2947  #ifdef NI_DGRAM
2948      sock_define_const("NI_DGRAM", NI_DGRAM);
2949  #endif
2950  }