Ruby  1.9.3p448(2013-06-27revision41675)
raddrinfo.c
Go to the documentation of this file.
1 /************************************************
2 
3  ainfo.c -
4 
5  created at: Thu Mar 31 12:21:29 JST 1994
6 
7  Copyright (C) 1993-2007 Yukihiro Matsumoto
8 
9 ************************************************/
10 
11 #include "rubysocket.h"
12 
13 #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
14 #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0]))
15 static const int lookup_order_table[] = {
16 #if defined(LOOKUP_ORDER_HACK_INET)
17  PF_INET, PF_INET6, PF_UNSPEC,
18 #elif defined(LOOKUP_ORDER_HACK_INET6)
19  PF_INET6, PF_INET, PF_UNSPEC,
20 #else
21  /* should not happen */
22 #endif
23 };
24 
25 static int
26 ruby_getaddrinfo(const char *nodename, const char *servname,
27  const struct addrinfo *hints, struct addrinfo **res)
28 {
29  struct addrinfo tmp_hints;
30  int i, af, error;
31 
32  if (hints->ai_family != PF_UNSPEC) {
33  return getaddrinfo(nodename, servname, hints, res);
34  }
35 
36  for (i = 0; i < LOOKUP_ORDERS; i++) {
37  af = lookup_order_table[i];
38  MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
39  tmp_hints.ai_family = af;
40  error = getaddrinfo(nodename, servname, &tmp_hints, res);
41  if (error) {
42  if (tmp_hints.ai_family == PF_UNSPEC) {
43  break;
44  }
45  }
46  else {
47  break;
48  }
49  }
50 
51  return error;
52 }
53 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
54 #endif
55 
56 #if defined(_AIX)
57 static int
58 ruby_getaddrinfo__aix(const char *nodename, const char *servname,
59  const struct addrinfo *hints, struct addrinfo **res)
60 {
61  int error = getaddrinfo(nodename, servname, hints, res);
62  struct addrinfo *r;
63  if (error)
64  return error;
65  for (r = *res; r != NULL; r = r->ai_next) {
66  if (r->ai_addr->sa_family == 0)
67  r->ai_addr->sa_family = r->ai_family;
68  if (r->ai_addr->sa_len == 0)
69  r->ai_addr->sa_len = r->ai_addrlen;
70  }
71  return 0;
72 }
73 #undef getaddrinfo
74 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
75 static int
76 ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen,
77  char *host, size_t hostlen,
78  char *serv, size_t servlen, int flags)
79 {
80  struct sockaddr_in6 *sa6;
81  u_int32_t *a6;
82 
83  if (sa->sa_family == AF_INET6) {
84  sa6 = (struct sockaddr_in6 *)sa;
85  a6 = sa6->sin6_addr.u6_addr.u6_addr32;
86 
87  if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
88  strncpy(host, "::", hostlen);
89  snprintf(serv, servlen, "%d", sa6->sin6_port);
90  return 0;
91  }
92  }
93  return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
94 }
95 #undef getnameinfo
96 #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
97  ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
98 #endif
99 
100 static int str_is_number(const char *);
101 
102 #if defined(__APPLE__)
103 static int
104 ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
105  const struct addrinfo *hints, struct addrinfo **res)
106 {
107  /* fix [ruby-core:29427] */
108  const char *tmp_servname;
109  struct addrinfo tmp_hints;
110  int error;
111 
112  tmp_servname = servname;
113  MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
114  if (nodename && servname) {
115  if (str_is_number(tmp_servname) && atoi(servname) == 0) {
116  tmp_servname = NULL;
117 #ifdef AI_NUMERICSERV
118  if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
119 #endif
120  }
121  }
122 
123  error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res);
124  if (error == 0) {
125  /* [ruby-dev:23164] */
126  struct addrinfo *r;
127  r = *res;
128  while (r) {
129  if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype;
130  if (! r->ai_protocol) {
131  if (r->ai_socktype == SOCK_DGRAM) {
132  r->ai_protocol = IPPROTO_UDP;
133  }
134  else if (r->ai_socktype == SOCK_STREAM) {
135  r->ai_protocol = IPPROTO_TCP;
136  }
137  }
138  r = r->ai_next;
139  }
140  }
141 
142  return error;
143 }
144 #undef getaddrinfo
145 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res))
146 #endif
147 
148 #ifndef GETADDRINFO_EMU
150 {
151  const char *node;
152  const char *service;
153  const struct addrinfo *hints;
154  struct addrinfo **res;
155 };
156 
157 static VALUE
159 {
160  struct getaddrinfo_arg *ptr = arg;
161  return getaddrinfo(ptr->node, ptr->service,
162  ptr->hints, ptr->res);
163 }
164 #endif
165 
166 int
167 rb_getaddrinfo(const char *node, const char *service,
168  const struct addrinfo *hints,
169  struct addrinfo **res)
170 {
171 #ifdef GETADDRINFO_EMU
172  return getaddrinfo(node, service, hints, res);
173 #else
174  struct getaddrinfo_arg arg;
175  int ret;
176  MEMZERO(&arg, sizeof arg, 1);
177  arg.node = node;
178  arg.service = service;
179  arg.hints = hints;
180  arg.res = res;
181  ret = (int)BLOCKING_REGION(nogvl_getaddrinfo, &arg);
182  return ret;
183 #endif
184 }
185 
186 #ifndef GETADDRINFO_EMU
188 {
189  const struct sockaddr *sa;
190  socklen_t salen;
191  char *host;
192  size_t hostlen;
193  char *serv;
194  size_t servlen;
195  int flags;
196 };
197 
198 static VALUE
200 {
201  struct getnameinfo_arg *ptr = arg;
202  return getnameinfo(ptr->sa, ptr->salen,
203  ptr->host, (socklen_t)ptr->hostlen,
204  ptr->serv, (socklen_t)ptr->servlen,
205  ptr->flags);
206 }
207 #endif
208 
209 int
210 rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
211  char *host, size_t hostlen,
212  char *serv, size_t servlen, int flags)
213 {
214 #ifdef GETADDRINFO_EMU
215  return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
216 #else
217  struct getnameinfo_arg arg;
218  int ret;
219  arg.sa = sa;
220  arg.salen = salen;
221  arg.host = host;
222  arg.hostlen = hostlen;
223  arg.serv = serv;
224  arg.servlen = servlen;
225  arg.flags = flags;
226  ret = (int)BLOCKING_REGION(nogvl_getnameinfo, &arg);
227  return ret;
228 #endif
229 }
230 
231 static void
232 make_ipaddr0(struct sockaddr *addr, char *buf, size_t len)
233 {
234  int error;
235 
236  error = rb_getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
237  if (error) {
238  rsock_raise_socket_error("getnameinfo", error);
239  }
240 }
241 
242 VALUE
243 rsock_make_ipaddr(struct sockaddr *addr)
244 {
245  char hbuf[1024];
246 
247  make_ipaddr0(addr, hbuf, sizeof(hbuf));
248  return rb_str_new2(hbuf);
249 }
250 
251 static void
252 make_inetaddr(unsigned int host, char *buf, size_t len)
253 {
254  struct sockaddr_in sin;
255 
256  MEMZERO(&sin, struct sockaddr_in, 1);
257  sin.sin_family = AF_INET;
258  SET_SIN_LEN(&sin, sizeof(sin));
259  sin.sin_addr.s_addr = host;
260  make_ipaddr0((struct sockaddr*)&sin, buf, len);
261 }
262 
263 static int
264 str_is_number(const char *p)
265 {
266  char *ep;
267 
268  if (!p || *p == '\0')
269  return 0;
270  ep = NULL;
271  (void)STRTOUL(p, &ep, 10);
272  if (ep && *ep == '\0')
273  return 1;
274  else
275  return 0;
276 }
277 
278 static char*
279 host_str(VALUE host, char *hbuf, size_t len, int *flags_ptr)
280 {
281  if (NIL_P(host)) {
282  return NULL;
283  }
284  else if (rb_obj_is_kind_of(host, rb_cInteger)) {
285  unsigned int i = NUM2UINT(host);
286 
287  make_inetaddr(htonl(i), hbuf, len);
288  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
289  return hbuf;
290  }
291  else {
292  char *name;
293 
294  SafeStringValue(host);
295  name = RSTRING_PTR(host);
296  if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) {
297  make_inetaddr(INADDR_ANY, hbuf, len);
298  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
299  }
300  else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
301  make_inetaddr(INADDR_BROADCAST, hbuf, len);
302  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
303  }
304  else if (strlen(name) >= len) {
305  rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")",
306  strlen(name));
307  }
308  else {
309  strcpy(hbuf, name);
310  }
311  return hbuf;
312  }
313 }
314 
315 static char*
316 port_str(VALUE port, char *pbuf, size_t len, int *flags_ptr)
317 {
318  if (NIL_P(port)) {
319  return 0;
320  }
321  else if (FIXNUM_P(port)) {
322  snprintf(pbuf, len, "%ld", FIX2LONG(port));
323 #ifdef AI_NUMERICSERV
324  if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
325 #endif
326  return pbuf;
327  }
328  else {
329  char *serv;
330 
331  SafeStringValue(port);
332  serv = RSTRING_PTR(port);
333  if (strlen(serv) >= len) {
334  rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")",
335  strlen(serv));
336  }
337  strcpy(pbuf, serv);
338  return pbuf;
339  }
340 }
341 
342 struct addrinfo*
343 rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
344 {
345  struct addrinfo* res = NULL;
346  char *hostp, *portp;
347  int error;
348  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
349  int additional_flags = 0;
350 
351  hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
352  portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
353 
354  if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
355  hints->ai_socktype = SOCK_DGRAM;
356  }
357  hints->ai_flags |= additional_flags;
358 
359  error = rb_getaddrinfo(hostp, portp, hints, &res);
360  if (error) {
361  if (hostp && hostp[strlen(hostp)-1] == '\n') {
362  rb_raise(rb_eSocket, "newline at the end of hostname");
363  }
364  rsock_raise_socket_error("getaddrinfo", error);
365  }
366 
367  return res;
368 }
369 
370 struct addrinfo*
371 rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
372 {
373  struct addrinfo hints;
374 
375  MEMZERO(&hints, struct addrinfo, 1);
376  hints.ai_family = AF_UNSPEC;
377  hints.ai_socktype = socktype;
378  hints.ai_flags = flags;
379  return rsock_getaddrinfo(host, port, &hints, 1);
380 }
381 
382 VALUE
383 rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup)
384 {
385  VALUE family, port, addr1, addr2;
386  VALUE ary;
387  int error;
388  char hbuf[1024], pbuf[1024];
389  ID id;
390 
391  id = rsock_intern_family(sockaddr->sa_family);
392  if (id) {
393  family = rb_str_dup(rb_id2str(id));
394  }
395  else {
396  sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
397  family = rb_str_new2(pbuf);
398  }
399 
400  addr1 = Qnil;
401  if (!norevlookup) {
402  error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
403  NULL, 0, 0);
404  if (! error) {
405  addr1 = rb_str_new2(hbuf);
406  }
407  }
408  error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
409  pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
410  if (error) {
411  rsock_raise_socket_error("getnameinfo", error);
412  }
413  addr2 = rb_str_new2(hbuf);
414  if (addr1 == Qnil) {
415  addr1 = addr2;
416  }
417  port = INT2FIX(atoi(pbuf));
418  ary = rb_ary_new3(4, family, port, addr1, addr2);
419 
420  return ary;
421 }
422 
423 #ifdef HAVE_SYS_UN_H
424 VALUE
425 rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len)
426 {
427  char *s, *e;
428  s = sockaddr->sun_path;
429  e = (char *)sockaddr + len;
430  while (s < e && *(e-1) == '\0')
431  e--;
432  if (s <= e)
433  return rb_str_new(s, e-s);
434  else
435  return rb_str_new2("");
436 }
437 
438 VALUE
439 rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len)
440 {
441  return rb_assoc_new(rb_str_new2("AF_UNIX"),
442  rsock_unixpath_str(sockaddr, len));
443 }
444 
445 socklen_t
446 rsock_unix_sockaddr_len(VALUE path)
447 {
448 #ifdef __linux__
449  if (RSTRING_LEN(path) == 0) {
450  /* autobind; see unix(7) for details. */
451  return (socklen_t) sizeof(sa_family_t);
452  }
453  else if (RSTRING_PTR(path)[0] == '\0') {
454  /* abstract namespace; see unix(7) for details. */
455  return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
456  RSTRING_LEN(path);
457  }
458  else {
459 #endif
460  return (socklen_t) sizeof(struct sockaddr_un);
461 #ifdef __linux__
462  }
463 #endif
464 }
465 #endif
466 
467 struct hostent_arg {
469  struct addrinfo* addr;
470  VALUE (*ipaddr)(struct sockaddr*, size_t);
471 };
472 
473 static VALUE
475 {
476  VALUE host = arg->host;
477  struct addrinfo* addr = arg->addr;
478  VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr;
479 
480  struct addrinfo *ai;
481  struct hostent *h;
482  VALUE ary, names;
483  char **pch;
484  const char* hostp;
485  char hbuf[NI_MAXHOST];
486 
487  ary = rb_ary_new();
488  if (addr->ai_canonname) {
489  hostp = addr->ai_canonname;
490  }
491  else {
492  hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
493  }
494  rb_ary_push(ary, rb_str_new2(hostp));
495 
496  if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
497  names = rb_ary_new();
498  if (h->h_aliases != NULL) {
499  for (pch = h->h_aliases; *pch; pch++) {
500  rb_ary_push(names, rb_str_new2(*pch));
501  }
502  }
503  }
504  else {
505  names = rb_ary_new2(0);
506  }
507  rb_ary_push(ary, names);
508  rb_ary_push(ary, INT2NUM(addr->ai_family));
509  for (ai = addr; ai; ai = ai->ai_next) {
510  rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
511  }
512 
513  return ary;
514 }
515 
516 VALUE
518 {
519  freeaddrinfo(addr);
520  return Qnil;
521 }
522 
523 VALUE
524 rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t))
525 {
526  struct hostent_arg arg;
527 
528  arg.host = host;
529  arg.addr = addr;
530  arg.ipaddr = ipaddr;
531  return rb_ensure(make_hostent_internal, (VALUE)&arg,
532  rsock_freeaddrinfo, (VALUE)addr);
533 }
534 
535 typedef struct {
538  int pfamily;
539  int socktype;
540  int protocol;
541  socklen_t sockaddr_len;
542  struct sockaddr_storage addr;
543 } rb_addrinfo_t;
544 
545 static void
546 addrinfo_mark(void *ptr)
547 {
548  rb_addrinfo_t *rai = ptr;
549  if (rai) {
550  rb_gc_mark(rai->inspectname);
551  rb_gc_mark(rai->canonname);
552  }
553 }
554 
555 #define addrinfo_free RUBY_TYPED_DEFAULT_FREE
556 
557 static size_t
558 addrinfo_memsize(const void *ptr)
559 {
560  return ptr ? sizeof(rb_addrinfo_t) : 0;
561 }
562 
564  "socket/addrinfo",
566 };
567 
568 static VALUE
570 {
571  return TypedData_Wrap_Struct(klass, &addrinfo_type, 0);
572 }
573 
574 #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
575 static inline rb_addrinfo_t *
577 {
578  return rb_check_typeddata(self, &addrinfo_type);
579 }
580 
581 static rb_addrinfo_t *
583 {
584  rb_addrinfo_t *rai = check_addrinfo(self);
585 
586  if (!rai) {
587  rb_raise(rb_eTypeError, "uninitialized socket address");
588  }
589  return rai;
590 }
591 
592 
593 static rb_addrinfo_t *
595 {
597  memset(rai, 0, sizeof(rb_addrinfo_t));
598  rai->inspectname = Qnil;
599  rai->canonname = Qnil;
600  return rai;
601 }
602 
603 static void
604 init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
605  int pfamily, int socktype, int protocol,
606  VALUE canonname, VALUE inspectname)
607 {
608  if ((socklen_t)sizeof(rai->addr) < len)
609  rb_raise(rb_eArgError, "sockaddr string too big");
610  memcpy((void *)&rai->addr, (void *)sa, len);
611  rai->sockaddr_len = len;
612 
613  rai->pfamily = pfamily;
614  rai->socktype = socktype;
615  rai->protocol = protocol;
616  rai->canonname = canonname;
617  rai->inspectname = inspectname;
618 }
619 
620 VALUE
621 rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
622  int family, int socktype, int protocol,
623  VALUE canonname, VALUE inspectname)
624 {
625  VALUE a;
626  rb_addrinfo_t *rai;
627 
629  DATA_PTR(a) = rai = alloc_addrinfo();
630  init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname);
631  return a;
632 }
633 
634 static struct addrinfo *
636  VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
637  int socktype_hack)
638 {
639  struct addrinfo hints, *res;
640 
641  MEMZERO(&hints, struct addrinfo, 1);
642  hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
643 
644  if (!NIL_P(socktype)) {
645  hints.ai_socktype = rsock_socktype_arg(socktype);
646  }
647  if (!NIL_P(protocol)) {
648  hints.ai_protocol = NUM2INT(protocol);
649  }
650  if (!NIL_P(flags)) {
651  hints.ai_flags = NUM2INT(flags);
652  }
653  res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
654 
655  if (res == NULL)
656  rb_raise(rb_eSocket, "host not found");
657  return res;
658 }
659 
660 static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
661 
662 static void
664  VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
665  VALUE inspectnode, VALUE inspectservice)
666 {
667  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1);
668  VALUE canonname;
669  VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res);
670 
671  canonname = Qnil;
672  if (res->ai_canonname) {
673  canonname = rb_tainted_str_new_cstr(res->ai_canonname);
674  OBJ_FREEZE(canonname);
675  }
676 
677  init_addrinfo(rai, res->ai_addr, res->ai_addrlen,
678  NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
679  canonname, inspectname);
680 
681  freeaddrinfo(res);
682 }
683 
684 static VALUE
685 make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
686 {
687  VALUE inspectname = Qnil;
688 
689  if (res) {
690  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
691  int ret;
692  ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
693  sizeof(hbuf), pbuf, sizeof(pbuf),
695  if (ret == 0) {
696  if (TYPE(node) == T_STRING && strcmp(hbuf, RSTRING_PTR(node)) == 0)
697  node = Qnil;
698  if (TYPE(service) == T_STRING && strcmp(pbuf, RSTRING_PTR(service)) == 0)
699  service = Qnil;
700  else if (TYPE(service) == T_FIXNUM && atoi(pbuf) == FIX2INT(service))
701  service = Qnil;
702  }
703  }
704 
705  if (TYPE(node) == T_STRING) {
706  inspectname = rb_str_dup(node);
707  }
708  if (TYPE(service) == T_STRING) {
709  if (NIL_P(inspectname))
710  inspectname = rb_sprintf(":%s", StringValueCStr(service));
711  else
712  rb_str_catf(inspectname, ":%s", StringValueCStr(service));
713  }
714  else if (TYPE(service) == T_FIXNUM && FIX2INT(service) != 0)
715  {
716  if (NIL_P(inspectname))
717  inspectname = rb_sprintf(":%d", FIX2INT(service));
718  else
719  rb_str_catf(inspectname, ":%d", FIX2INT(service));
720  }
721  if (!NIL_P(inspectname)) {
722  OBJ_INFECT(inspectname, node);
723  OBJ_INFECT(inspectname, service);
724  OBJ_FREEZE(inspectname);
725  }
726  return inspectname;
727 }
728 
729 static VALUE
730 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
731 {
732  VALUE ret;
733  VALUE canonname;
734  VALUE inspectname;
735 
736  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0);
737 
738  inspectname = make_inspectname(node, service, res);
739 
740  canonname = Qnil;
741  if (res->ai_canonname) {
742  canonname = rb_tainted_str_new_cstr(res->ai_canonname);
743  OBJ_FREEZE(canonname);
744  }
745 
746  ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen,
747  res->ai_family, res->ai_socktype, res->ai_protocol,
748  canonname, inspectname);
749 
750  freeaddrinfo(res);
751  return ret;
752 }
753 
754 static VALUE
755 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
756 {
757  VALUE ret;
758  struct addrinfo *r;
759  VALUE inspectname;
760 
761  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0);
762 
763  inspectname = make_inspectname(node, service, res);
764 
765  ret = rb_ary_new();
766  for (r = res; r; r = r->ai_next) {
767  VALUE addr;
768  VALUE canonname = Qnil;
769 
770  if (r->ai_canonname) {
771  canonname = rb_tainted_str_new_cstr(r->ai_canonname);
772  OBJ_FREEZE(canonname);
773  }
774 
775  addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen,
776  r->ai_family, r->ai_socktype, r->ai_protocol,
777  canonname, inspectname);
778 
779  rb_ary_push(ret, addr);
780  }
781 
782  freeaddrinfo(res);
783  return ret;
784 }
785 
786 
787 #ifdef HAVE_SYS_UN_H
788 static void
789 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
790 {
791  struct sockaddr_un un;
792  socklen_t len;
793 
794  StringValue(path);
795 
796  if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
798  "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
799  (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
800 
801  MEMZERO(&un, struct sockaddr_un, 1);
802 
803  un.sun_family = AF_UNIX;
804  memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
805 
806  len = rsock_unix_sockaddr_len(path);
807  init_addrinfo(rai, (struct sockaddr *)&un, len,
808  PF_UNIX, socktype, 0, Qnil, Qnil);
809 }
810 #endif
811 
812 /*
813  * call-seq:
814  * Addrinfo.new(sockaddr) => addrinfo
815  * Addrinfo.new(sockaddr, family) => addrinfo
816  * Addrinfo.new(sockaddr, family, socktype) => addrinfo
817  * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
818  *
819  * returns a new instance of Addrinfo.
820  * The instance contains sockaddr, family, socktype, protocol.
821  * sockaddr means struct sockaddr which can be used for connect(2), etc.
822  * family, socktype and protocol are integers which is used for arguments of socket(2).
823  *
824  * sockaddr is specified as an array or a string.
825  * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
826  * The string should be struct sockaddr as generated by
827  * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
828  *
829  * sockaddr examples:
830  * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
831  * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
832  * - ["AF_UNIX", "/tmp/sock"]
833  * - Socket.sockaddr_in("smtp", "2001:DB8::1")
834  * - Socket.sockaddr_in(80, "172.18.22.42")
835  * - Socket.sockaddr_in(80, "www.ruby-lang.org")
836  * - Socket.sockaddr_un("/tmp/sock")
837  *
838  * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
839  * numeric IP address, is used to construct socket address in the Addrinfo instance.
840  * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
841  *
842  * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
843  * It can be a symbol or a string which is the constant name
844  * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
845  * If omitted, PF_UNSPEC is assumed.
846  *
847  * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
848  * It can be a symbol or a string which is the constant name
849  * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
850  * If omitted, 0 is assumed.
851  *
852  * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
853  * It must be an integer, unlike family and socktype.
854  * If omitted, 0 is assumed.
855  * Note that 0 is reasonable value for most protocols, except raw socket.
856  *
857  */
858 static VALUE
860 {
861  rb_addrinfo_t *rai;
862  VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
863  int i_pfamily, i_socktype, i_protocol;
864  struct sockaddr *sockaddr_ptr;
865  socklen_t sockaddr_len;
866  VALUE canonname = Qnil, inspectname = Qnil;
867 
868  if (check_addrinfo(self))
869  rb_raise(rb_eTypeError, "already initialized socket address");
870  DATA_PTR(self) = rai = alloc_addrinfo();
871 
872  rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
873 
874  i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
875  i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
876  i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
877 
878  sockaddr_ary = rb_check_array_type(sockaddr_arg);
879  if (!NIL_P(sockaddr_ary)) {
880  VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
881  int af;
882  StringValue(afamily);
883  if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
884  rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
885  switch (af) {
886  case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
887 #ifdef INET6
888  case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
889 #endif
890  {
891  VALUE service = rb_ary_entry(sockaddr_ary, 1);
892  VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
893  VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
894  int flags;
895 
896  service = INT2NUM(NUM2INT(service));
897  if (!NIL_P(nodename))
898  StringValue(nodename);
899  StringValue(numericnode);
900  flags = AI_NUMERICHOST;
901 #ifdef AI_NUMERICSERV
902  flags |= AI_NUMERICSERV;
903 #endif
904 
905  init_addrinfo_getaddrinfo(rai, numericnode, service,
906  INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
907  INT2NUM(flags),
908  nodename, service);
909  break;
910  }
911 
912 #ifdef HAVE_SYS_UN_H
913  case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
914  {
915  VALUE path = rb_ary_entry(sockaddr_ary, 1);
916  StringValue(path);
917  init_unix_addrinfo(rai, path, SOCK_STREAM);
918  break;
919  }
920 #endif
921 
922  default:
923  rb_raise(rb_eSocket, "unexpected address family");
924  }
925  }
926  else {
927  StringValue(sockaddr_arg);
928  sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
929  sockaddr_len = RSTRING_LENINT(sockaddr_arg);
930  init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
931  i_pfamily, i_socktype, i_protocol,
932  canonname, inspectname);
933  }
934 
935  return self;
936 }
937 
938 static int
939 get_afamily(struct sockaddr *addr, socklen_t len)
940 {
941  if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
942  return addr->sa_family;
943  else
944  return AF_UNSPEC;
945 }
946 
947 static int
949 {
950  return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len);
951 }
952 
953 static VALUE
955 {
956  rb_addrinfo_t *rai = get_addrinfo(addrinfo);
957 
958  if (rai->sockaddr_len == 0) {
959  rb_str_cat2(ret, "empty-sockaddr");
960  }
961  else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr)
962  rb_str_cat2(ret, "too-short-sockaddr");
963  else {
964  switch (rai->addr.ss_family) {
965  case AF_INET:
966  {
967  struct sockaddr_in *addr;
968  int port;
969  if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) {
970  rb_str_cat2(ret, "too-short-AF_INET-sockaddr");
971  }
972  else {
973  addr = (struct sockaddr_in *)&rai->addr;
974  rb_str_catf(ret, "%d.%d.%d.%d",
975  ((unsigned char*)&addr->sin_addr)[0],
976  ((unsigned char*)&addr->sin_addr)[1],
977  ((unsigned char*)&addr->sin_addr)[2],
978  ((unsigned char*)&addr->sin_addr)[3]);
979  port = ntohs(addr->sin_port);
980  if (port)
981  rb_str_catf(ret, ":%d", port);
982  if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len)
983  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in)));
984  }
985  break;
986  }
987 
988 #ifdef AF_INET6
989  case AF_INET6:
990  {
991  struct sockaddr_in6 *addr;
992  char hbuf[1024];
993  int port;
994  int error;
995  if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) {
996  rb_str_cat2(ret, "too-short-AF_INET6-sockaddr");
997  }
998  else {
999  addr = (struct sockaddr_in6 *)&rai->addr;
1000  /* use getnameinfo for scope_id.
1001  * RFC 4007: IPv6 Scoped Address Architecture
1002  * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
1003  */
1004  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1005  hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
1007  if (error) {
1008  rsock_raise_socket_error("getnameinfo", error);
1009  }
1010  if (addr->sin6_port == 0) {
1011  rb_str_cat2(ret, hbuf);
1012  }
1013  else {
1014  port = ntohs(addr->sin6_port);
1015  rb_str_catf(ret, "[%s]:%d", hbuf, port);
1016  }
1017  if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len)
1018  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6)));
1019  }
1020  break;
1021  }
1022 #endif
1023 
1024 #ifdef HAVE_SYS_UN_H
1025  case AF_UNIX:
1026  {
1027  struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr;
1028  char *p, *s, *e;
1029  s = addr->sun_path;
1030  e = (char*)addr + rai->sockaddr_len;
1031  while (s < e && *(e-1) == '\0')
1032  e--;
1033  if (e < s)
1034  rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
1035  else if (s == e)
1036  rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
1037  else {
1038  int printable_only = 1;
1039  p = s;
1040  while (p < e) {
1041  printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
1042  p++;
1043  }
1044  if (printable_only) { /* only printable, no space */
1045  if (s[0] != '/') /* relative path */
1046  rb_str_cat2(ret, "AF_UNIX ");
1047  rb_str_cat(ret, s, p - s);
1048  }
1049  else {
1050  rb_str_cat2(ret, "AF_UNIX");
1051  while (s < e)
1052  rb_str_catf(ret, ":%02x", (unsigned char)*s++);
1053  }
1054  if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len)
1055  rb_str_catf(ret, "(sockaddr %d bytes too long)",
1056  (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr)));
1057  }
1058  break;
1059  }
1060 #endif
1061 
1062  default:
1063  {
1064  ID id = rsock_intern_family(rai->addr.ss_family);
1065  if (id == 0)
1066  rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family);
1067  else
1068  rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
1069  break;
1070  }
1071  }
1072  }
1073 
1074  return ret;
1075 }
1076 
1077 /*
1078  * call-seq:
1079  * addrinfo.inspect => string
1080  *
1081  * returns a string which shows addrinfo in human-readable form.
1082  *
1083  * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost:80)>"
1084  * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
1085  *
1086  */
1087 static VALUE
1089 {
1090  rb_addrinfo_t *rai = get_addrinfo(self);
1091  int internet_p;
1092  VALUE ret;
1093 
1094  ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
1095 
1096  inspect_sockaddr(self, ret);
1097 
1098  if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
1099  ID id = rsock_intern_protocol_family(rai->pfamily);
1100  if (id)
1101  rb_str_catf(ret, " %s", rb_id2name(id));
1102  else
1103  rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
1104  }
1105 
1106  internet_p = rai->pfamily == PF_INET;
1107 #ifdef INET6
1108  internet_p = internet_p || rai->pfamily == PF_INET6;
1109 #endif
1110  if (internet_p && rai->socktype == SOCK_STREAM &&
1111  (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
1112  rb_str_cat2(ret, " TCP");
1113  }
1114  else if (internet_p && rai->socktype == SOCK_DGRAM &&
1115  (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
1116  rb_str_cat2(ret, " UDP");
1117  }
1118  else {
1119  if (rai->socktype) {
1120  ID id = rsock_intern_socktype(rai->socktype);
1121  if (id)
1122  rb_str_catf(ret, " %s", rb_id2name(id));
1123  else
1124  rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
1125  }
1126 
1127  if (rai->protocol) {
1128  if (internet_p) {
1129  ID id = rsock_intern_ipproto(rai->protocol);
1130  if (id)
1131  rb_str_catf(ret, " %s", rb_id2name(id));
1132  else
1133  goto unknown_protocol;
1134  }
1135  else {
1136  unknown_protocol:
1137  rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
1138  }
1139  }
1140  }
1141 
1142  if (!NIL_P(rai->canonname)) {
1143  VALUE name = rai->canonname;
1144  rb_str_catf(ret, " %s", StringValueCStr(name));
1145  }
1146 
1147  if (!NIL_P(rai->inspectname)) {
1148  VALUE name = rai->inspectname;
1149  rb_str_catf(ret, " (%s)", StringValueCStr(name));
1150  }
1151 
1152  rb_str_buf_cat2(ret, ">");
1153  return ret;
1154 }
1155 
1156 /*
1157  * call-seq:
1158  * addrinfo.inspect_sockaddr => string
1159  *
1160  * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
1161  *
1162  * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
1163  * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
1164  * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
1165  *
1166  */
1167 static VALUE
1169 {
1170  return inspect_sockaddr(self, rb_str_new("", 0));
1171 }
1172 
1173 /* :nodoc: */
1174 static VALUE
1176 {
1177  rb_addrinfo_t *rai = get_addrinfo(self);
1178  VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
1179  int afamily_int = ai_get_afamily(rai);
1180  ID id;
1181 
1182  id = rsock_intern_protocol_family(rai->pfamily);
1183  if (id == 0)
1184  rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
1185  pfamily = rb_id2str(id);
1186 
1187  if (rai->socktype == 0)
1188  socktype = INT2FIX(0);
1189  else {
1190  id = rsock_intern_socktype(rai->socktype);
1191  if (id == 0)
1192  rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
1193  socktype = rb_id2str(id);
1194  }
1195 
1196  if (rai->protocol == 0)
1197  protocol = INT2FIX(0);
1198  else if (IS_IP_FAMILY(afamily_int)) {
1199  id = rsock_intern_ipproto(rai->protocol);
1200  if (id == 0)
1201  rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
1202  protocol = rb_id2str(id);
1203  }
1204  else {
1205  rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
1206  }
1207 
1208  canonname = rai->canonname;
1209 
1210  inspectname = rai->inspectname;
1211 
1212  id = rsock_intern_family(afamily_int);
1213  if (id == 0)
1214  rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
1215  afamily = rb_id2str(id);
1216 
1217  switch(afamily_int) {
1218 #ifdef HAVE_SYS_UN_H
1219  case AF_UNIX:
1220  {
1221  struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr;
1222  char *s, *e;
1223  s = su->sun_path;
1224  e = (char*)su + rai->sockaddr_len;
1225  while (s < e && *(e-1) == '\0')
1226  e--;
1227  sockaddr = rb_str_new(s, e-s);
1228  break;
1229  }
1230 #endif
1231 
1232  default:
1233  {
1234  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
1235  int error;
1236  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1237  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1239  if (error) {
1240  rsock_raise_socket_error("getnameinfo", error);
1241  }
1242  sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
1243  break;
1244  }
1245  }
1246 
1247  return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
1248 }
1249 
1250 /* :nodoc: */
1251 static VALUE
1253 {
1254  VALUE v;
1255  VALUE canonname, inspectname;
1256  int afamily, pfamily, socktype, protocol;
1257  struct sockaddr_storage ss;
1258  socklen_t len;
1259  rb_addrinfo_t *rai;
1260 
1261  if (check_addrinfo(self))
1262  rb_raise(rb_eTypeError, "already initialized socket address");
1263 
1264  ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1265 
1266  v = rb_ary_entry(ary, 0);
1267  StringValue(v);
1268  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
1269  rb_raise(rb_eTypeError, "unexpected address family");
1270 
1271  v = rb_ary_entry(ary, 2);
1272  StringValue(v);
1273  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
1274  rb_raise(rb_eTypeError, "unexpected protocol family");
1275 
1276  v = rb_ary_entry(ary, 3);
1277  if (v == INT2FIX(0))
1278  socktype = 0;
1279  else {
1280  StringValue(v);
1281  if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
1282  rb_raise(rb_eTypeError, "unexpected socktype");
1283  }
1284 
1285  v = rb_ary_entry(ary, 4);
1286  if (v == INT2FIX(0))
1287  protocol = 0;
1288  else {
1289  StringValue(v);
1290  if (IS_IP_FAMILY(afamily)) {
1291  if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1)
1292  rb_raise(rb_eTypeError, "unexpected protocol");
1293  }
1294  else {
1295  rb_raise(rb_eTypeError, "unexpected protocol");
1296  }
1297  }
1298 
1299  v = rb_ary_entry(ary, 5);
1300  if (NIL_P(v))
1301  canonname = Qnil;
1302  else {
1303  StringValue(v);
1304  canonname = v;
1305  }
1306 
1307  v = rb_ary_entry(ary, 6);
1308  if (NIL_P(v))
1309  inspectname = Qnil;
1310  else {
1311  StringValue(v);
1312  inspectname = v;
1313  }
1314 
1315  v = rb_ary_entry(ary, 1);
1316  switch(afamily) {
1317 #ifdef HAVE_SYS_UN_H
1318  case AF_UNIX:
1319  {
1320  struct sockaddr_un uaddr;
1321  MEMZERO(&uaddr, struct sockaddr_un, 1);
1322  uaddr.sun_family = AF_UNIX;
1323 
1324  StringValue(v);
1325  if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
1327  "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1328  (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
1329  memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
1330  len = (socklen_t)sizeof(uaddr);
1331  memcpy(&ss, &uaddr, len);
1332  break;
1333  }
1334 #endif
1335 
1336  default:
1337  {
1338  VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
1339  struct addrinfo *res;
1340  int flags = AI_NUMERICHOST;
1341 #ifdef AI_NUMERICSERV
1342  flags |= AI_NUMERICSERV;
1343 #endif
1344  res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
1345  INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
1346  INT2NUM(flags), 1);
1347 
1348  len = res->ai_addrlen;
1349  memcpy(&ss, res->ai_addr, res->ai_addrlen);
1350  break;
1351  }
1352  }
1353 
1354  DATA_PTR(self) = rai = alloc_addrinfo();
1355  init_addrinfo(rai, (struct sockaddr *)&ss, len,
1356  pfamily, socktype, protocol,
1357  canonname, inspectname);
1358  return self;
1359 }
1360 
1361 /*
1362  * call-seq:
1363  * addrinfo.afamily => integer
1364  *
1365  * returns the address family as an integer.
1366  *
1367  * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
1368  *
1369  */
1370 static VALUE
1372 {
1373  rb_addrinfo_t *rai = get_addrinfo(self);
1374  return INT2NUM(ai_get_afamily(rai));
1375 }
1376 
1377 /*
1378  * call-seq:
1379  * addrinfo.pfamily => integer
1380  *
1381  * returns the protocol family as an integer.
1382  *
1383  * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
1384  *
1385  */
1386 static VALUE
1388 {
1389  rb_addrinfo_t *rai = get_addrinfo(self);
1390  return INT2NUM(rai->pfamily);
1391 }
1392 
1393 /*
1394  * call-seq:
1395  * addrinfo.socktype => integer
1396  *
1397  * returns the socket type as an integer.
1398  *
1399  * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
1400  *
1401  */
1402 static VALUE
1404 {
1405  rb_addrinfo_t *rai = get_addrinfo(self);
1406  return INT2NUM(rai->socktype);
1407 }
1408 
1409 /*
1410  * call-seq:
1411  * addrinfo.protocol => integer
1412  *
1413  * returns the socket type as an integer.
1414  *
1415  * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
1416  *
1417  */
1418 static VALUE
1420 {
1421  rb_addrinfo_t *rai = get_addrinfo(self);
1422  return INT2NUM(rai->protocol);
1423 }
1424 
1425 /*
1426  * call-seq:
1427  * addrinfo.to_sockaddr => string
1428  * addrinfo.to_s => string
1429  *
1430  * returns the socket address as packed struct sockaddr string.
1431  *
1432  * Addrinfo.tcp("localhost", 80).to_sockaddr
1433  * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1434  *
1435  */
1436 static VALUE
1438 {
1439  rb_addrinfo_t *rai = get_addrinfo(self);
1440  VALUE ret;
1441  ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
1442  OBJ_INFECT(ret, self);
1443  return ret;
1444 }
1445 
1446 /*
1447  * call-seq:
1448  * addrinfo.canonname => string or nil
1449  *
1450  * returns the canonical name as an string.
1451  *
1452  * nil is returned if no canonical name.
1453  *
1454  * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
1455  *
1456  * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
1457  * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org:80)>
1458  * p list[0].canonname #=> "carbon.ruby-lang.org"
1459  *
1460  */
1461 static VALUE
1463 {
1464  rb_addrinfo_t *rai = get_addrinfo(self);
1465  return rai->canonname;
1466 }
1467 
1468 /*
1469  * call-seq:
1470  * addrinfo.ip? => true or false
1471  *
1472  * returns true if addrinfo is internet (IPv4/IPv6) address.
1473  * returns false otherwise.
1474  *
1475  * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
1476  * Addrinfo.tcp("::1", 80).ip? #=> true
1477  * Addrinfo.unix("/tmp/sock").ip? #=> false
1478  *
1479  */
1480 static VALUE
1482 {
1483  rb_addrinfo_t *rai = get_addrinfo(self);
1484  int family = ai_get_afamily(rai);
1485  return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
1486 }
1487 
1488 /*
1489  * call-seq:
1490  * addrinfo.ipv4? => true or false
1491  *
1492  * returns true if addrinfo is IPv4 address.
1493  * returns false otherwise.
1494  *
1495  * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
1496  * Addrinfo.tcp("::1", 80).ipv4? #=> false
1497  * Addrinfo.unix("/tmp/sock").ipv4? #=> false
1498  *
1499  */
1500 static VALUE
1502 {
1503  rb_addrinfo_t *rai = get_addrinfo(self);
1504  return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
1505 }
1506 
1507 /*
1508  * call-seq:
1509  * addrinfo.ipv6? => true or false
1510  *
1511  * returns true if addrinfo is IPv6 address.
1512  * returns false otherwise.
1513  *
1514  * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
1515  * Addrinfo.tcp("::1", 80).ipv6? #=> true
1516  * Addrinfo.unix("/tmp/sock").ipv6? #=> false
1517  *
1518  */
1519 static VALUE
1521 {
1522 #ifdef AF_INET6
1523  rb_addrinfo_t *rai = get_addrinfo(self);
1524  return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
1525 #else
1526  return Qfalse;
1527 #endif
1528 }
1529 
1530 /*
1531  * call-seq:
1532  * addrinfo.unix? => true or false
1533  *
1534  * returns true if addrinfo is UNIX address.
1535  * returns false otherwise.
1536  *
1537  * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
1538  * Addrinfo.tcp("::1", 80).unix? #=> false
1539  * Addrinfo.unix("/tmp/sock").unix? #=> true
1540  *
1541  */
1542 static VALUE
1544 {
1545  rb_addrinfo_t *rai = get_addrinfo(self);
1546 #ifdef AF_UNIX
1547  return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
1548 #else
1549  return Qfalse;
1550 #endif
1551 }
1552 
1553 /*
1554  * call-seq:
1555  * addrinfo.getnameinfo => [nodename, service]
1556  * addrinfo.getnameinfo(flags) => [nodename, service]
1557  *
1558  * returns nodename and service as a pair of strings.
1559  * This converts struct sockaddr in addrinfo to textual representation.
1560  *
1561  * flags should be bitwise OR of Socket::NI_??? constants.
1562  *
1563  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
1564  *
1565  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
1566  * #=> ["localhost", "80"]
1567  */
1568 static VALUE
1570 {
1571  rb_addrinfo_t *rai = get_addrinfo(self);
1572  VALUE vflags;
1573  char hbuf[1024], pbuf[1024];
1574  int flags, error;
1575 
1576  rb_scan_args(argc, argv, "01", &vflags);
1577 
1578  flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
1579 
1580  if (rai->socktype == SOCK_DGRAM)
1581  flags |= NI_DGRAM;
1582 
1583  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1584  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1585  flags);
1586  if (error) {
1587  rsock_raise_socket_error("getnameinfo", error);
1588  }
1589 
1590  return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1591 }
1592 
1593 /*
1594  * call-seq:
1595  * addrinfo.ip_unpack => [addr, port]
1596  *
1597  * Returns the IP address and port number as 2-element array.
1598  *
1599  * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
1600  * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
1601  */
1602 static VALUE
1604 {
1605  rb_addrinfo_t *rai = get_addrinfo(self);
1606  int family = ai_get_afamily(rai);
1607  VALUE vflags;
1608  VALUE ret, portstr;
1609 
1610  if (!IS_IP_FAMILY(family))
1611  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1612 
1614  ret = addrinfo_getnameinfo(1, &vflags, self);
1615  portstr = rb_ary_entry(ret, 1);
1616  rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
1617  return ret;
1618 }
1619 
1620 /*
1621  * call-seq:
1622  * addrinfo.ip_address => string
1623  *
1624  * Returns the IP address as a string.
1625  *
1626  * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
1627  * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
1628  */
1629 static VALUE
1631 {
1632  rb_addrinfo_t *rai = get_addrinfo(self);
1633  int family = ai_get_afamily(rai);
1634  VALUE vflags;
1635  VALUE ret;
1636 
1637  if (!IS_IP_FAMILY(family))
1638  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1639 
1641  ret = addrinfo_getnameinfo(1, &vflags, self);
1642  return rb_ary_entry(ret, 0);
1643 }
1644 
1645 /*
1646  * call-seq:
1647  * addrinfo.ip_port => port
1648  *
1649  * Returns the port number as an integer.
1650  *
1651  * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
1652  * Addrinfo.tcp("::1", 80).ip_port #=> 80
1653  */
1654 static VALUE
1656 {
1657  rb_addrinfo_t *rai = get_addrinfo(self);
1658  int family = ai_get_afamily(rai);
1659  int port;
1660 
1661  if (!IS_IP_FAMILY(family)) {
1662  bad_family:
1663 #ifdef AF_INET6
1664  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1665 #else
1666  rb_raise(rb_eSocket, "need IPv4 address");
1667 #endif
1668  }
1669 
1670  switch (family) {
1671  case AF_INET:
1672  if (rai->sockaddr_len != sizeof(struct sockaddr_in))
1673  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
1674  port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port);
1675  break;
1676 
1677 #ifdef AF_INET6
1678  case AF_INET6:
1679  if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
1680  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
1681  port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port);
1682  break;
1683 #endif
1684 
1685  default:
1686  goto bad_family;
1687  }
1688 
1689  return INT2NUM(port);
1690 }
1691 
1692 static int
1694 {
1695  rb_addrinfo_t *rai = get_addrinfo(self);
1696  int family = ai_get_afamily(rai);
1697  if (family != AF_INET) return 0;
1698  *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr);
1699  return 1;
1700 }
1701 
1702 /*
1703  * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
1704  * It returns false otherwise.
1705  */
1706 static VALUE
1708 {
1709  uint32_t a;
1710  if (!extract_in_addr(self, &a)) return Qfalse;
1711  if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
1712  (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
1713  (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
1714  return Qtrue;
1715  return Qfalse;
1716 }
1717 
1718 /*
1719  * Returns true for IPv4 loopback address (127.0.0.0/8).
1720  * It returns false otherwise.
1721  */
1722 static VALUE
1724 {
1725  uint32_t a;
1726  if (!extract_in_addr(self, &a)) return Qfalse;
1727  if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
1728  return Qtrue;
1729  return Qfalse;
1730 }
1731 
1732 /*
1733  * Returns true for IPv4 multicast address (224.0.0.0/4).
1734  * It returns false otherwise.
1735  */
1736 static VALUE
1738 {
1739  uint32_t a;
1740  if (!extract_in_addr(self, &a)) return Qfalse;
1741  if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
1742  return Qtrue;
1743  return Qfalse;
1744 }
1745 
1746 #ifdef INET6
1747 
1748 static struct in6_addr *
1749 extract_in6_addr(VALUE self)
1750 {
1751  rb_addrinfo_t *rai = get_addrinfo(self);
1752  int family = ai_get_afamily(rai);
1753  if (family != AF_INET6) return NULL;
1754  return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr;
1755 }
1756 
1757 /*
1758  * Returns true for IPv6 unspecified address (::).
1759  * It returns false otherwise.
1760  */
1761 static VALUE
1762 addrinfo_ipv6_unspecified_p(VALUE self)
1763 {
1764  struct in6_addr *addr = extract_in6_addr(self);
1765  if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
1766  return Qfalse;
1767 }
1768 
1769 /*
1770  * Returns true for IPv6 loopback address (::1).
1771  * It returns false otherwise.
1772  */
1773 static VALUE
1774 addrinfo_ipv6_loopback_p(VALUE self)
1775 {
1776  struct in6_addr *addr = extract_in6_addr(self);
1777  if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
1778  return Qfalse;
1779 }
1780 
1781 /*
1782  * Returns true for IPv6 multicast address (ff00::/8).
1783  * It returns false otherwise.
1784  */
1785 static VALUE
1786 addrinfo_ipv6_multicast_p(VALUE self)
1787 {
1788  struct in6_addr *addr = extract_in6_addr(self);
1789  if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
1790  return Qfalse;
1791 }
1792 
1793 /*
1794  * Returns true for IPv6 link local address (ff80::/10).
1795  * It returns false otherwise.
1796  */
1797 static VALUE
1798 addrinfo_ipv6_linklocal_p(VALUE self)
1799 {
1800  struct in6_addr *addr = extract_in6_addr(self);
1801  if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
1802  return Qfalse;
1803 }
1804 
1805 /*
1806  * Returns true for IPv6 site local address (ffc0::/10).
1807  * It returns false otherwise.
1808  */
1809 static VALUE
1810 addrinfo_ipv6_sitelocal_p(VALUE self)
1811 {
1812  struct in6_addr *addr = extract_in6_addr(self);
1813  if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
1814  return Qfalse;
1815 }
1816 
1817 /*
1818  * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
1819  * It returns false otherwise.
1820  */
1821 static VALUE
1822 addrinfo_ipv6_v4mapped_p(VALUE self)
1823 {
1824  struct in6_addr *addr = extract_in6_addr(self);
1825  if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
1826  return Qfalse;
1827 }
1828 
1829 /*
1830  * Returns true for IPv4-compatible IPv6 address (::/80).
1831  * It returns false otherwise.
1832  */
1833 static VALUE
1834 addrinfo_ipv6_v4compat_p(VALUE self)
1835 {
1836  struct in6_addr *addr = extract_in6_addr(self);
1837  if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
1838  return Qfalse;
1839 }
1840 
1841 /*
1842  * Returns true for IPv6 multicast node-local scope address.
1843  * It returns false otherwise.
1844  */
1845 static VALUE
1846 addrinfo_ipv6_mc_nodelocal_p(VALUE self)
1847 {
1848  struct in6_addr *addr = extract_in6_addr(self);
1849  if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
1850  return Qfalse;
1851 }
1852 
1853 /*
1854  * Returns true for IPv6 multicast link-local scope address.
1855  * It returns false otherwise.
1856  */
1857 static VALUE
1858 addrinfo_ipv6_mc_linklocal_p(VALUE self)
1859 {
1860  struct in6_addr *addr = extract_in6_addr(self);
1861  if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
1862  return Qfalse;
1863 }
1864 
1865 /*
1866  * Returns true for IPv6 multicast site-local scope address.
1867  * It returns false otherwise.
1868  */
1869 static VALUE
1870 addrinfo_ipv6_mc_sitelocal_p(VALUE self)
1871 {
1872  struct in6_addr *addr = extract_in6_addr(self);
1873  if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
1874  return Qfalse;
1875 }
1876 
1877 /*
1878  * Returns true for IPv6 multicast organization-local scope address.
1879  * It returns false otherwise.
1880  */
1881 static VALUE
1882 addrinfo_ipv6_mc_orglocal_p(VALUE self)
1883 {
1884  struct in6_addr *addr = extract_in6_addr(self);
1885  if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
1886  return Qfalse;
1887 }
1888 
1889 /*
1890  * Returns true for IPv6 multicast global scope address.
1891  * It returns false otherwise.
1892  */
1893 static VALUE
1894 addrinfo_ipv6_mc_global_p(VALUE self)
1895 {
1896  struct in6_addr *addr = extract_in6_addr(self);
1897  if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
1898  return Qfalse;
1899 }
1900 
1901 /*
1902  * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
1903  * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
1904  *
1905  * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
1906  * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
1907  * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
1908  * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
1909  * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
1910  */
1911 static VALUE
1912 addrinfo_ipv6_to_ipv4(VALUE self)
1913 {
1914  rb_addrinfo_t *rai = get_addrinfo(self);
1915  struct in6_addr *addr;
1916  int family = ai_get_afamily(rai);
1917  if (family != AF_INET6) return Qnil;
1918  addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr;
1919  if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
1920  struct sockaddr_in sin4;
1921  MEMZERO(&sin4, struct sockaddr_in, 1);
1922  sin4.sin_family = AF_INET;
1923  SET_SIN_LEN(&sin4, sizeof(sin4));
1924  memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
1925  return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
1926  PF_INET, rai->socktype, rai->protocol,
1927  rai->canonname, rai->inspectname);
1928  }
1929  else {
1930  return Qnil;
1931  }
1932 }
1933 
1934 #endif
1935 
1936 #ifdef HAVE_SYS_UN_H
1937 /*
1938  * call-seq:
1939  * addrinfo.unix_path => path
1940  *
1941  * Returns the socket path as a string.
1942  *
1943  * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
1944  */
1945 static VALUE
1946 addrinfo_unix_path(VALUE self)
1947 {
1948  rb_addrinfo_t *rai = get_addrinfo(self);
1949  int family = ai_get_afamily(rai);
1950  struct sockaddr_un *addr;
1951  char *s, *e;
1952 
1953  if (family != AF_UNIX)
1954  rb_raise(rb_eSocket, "need AF_UNIX address");
1955 
1956  addr = (struct sockaddr_un *)&rai->addr;
1957 
1958  s = addr->sun_path;
1959  e = (char*)addr + rai->sockaddr_len;
1960  if (e < s)
1961  rb_raise(rb_eSocket, "too short AF_UNIX address");
1962  if (addr->sun_path + sizeof(addr->sun_path) < e)
1963  rb_raise(rb_eSocket, "too long AF_UNIX address");
1964  while (s < e && *(e-1) == '\0')
1965  e--;
1966  return rb_str_new(s, e-s);
1967 }
1968 #endif
1969 
1970 /*
1971  * call-seq:
1972  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
1973  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
1974  * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
1975  * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
1976  * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
1977  *
1978  * returns a list of addrinfo objects as an array.
1979  *
1980  * This method converts nodename (hostname) and service (port) to addrinfo.
1981  * Since the conversion is not unique, the result is a list of addrinfo objects.
1982  *
1983  * nodename or service can be nil if no conversion intended.
1984  *
1985  * family, socktype and protocol are hint for preferred protocol.
1986  * If the result will be used for a socket with SOCK_STREAM,
1987  * SOCK_STREAM should be specified as socktype.
1988  * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
1989  * If they are omitted or nil is given, the result is not restricted.
1990  *
1991  * Similarly, PF_INET6 as family restricts for IPv6.
1992  *
1993  * flags should be bitwise OR of Socket::AI_??? constants.
1994  *
1995  * Note that socktype should be specified whenever application knows the usage of the address.
1996  * Some platform causes an error when socktype is omitted and servname is specified as an integer
1997  * because some port numbers, 512 for example, are ambiguous without socktype.
1998  *
1999  * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
2000  * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net:80)>,
2001  * # #<Addrinfo: [2001:200:0:8002:203:47ff:fea5:3085]:80 TCP (www.kame.net:80)>]
2002  *
2003  */
2004 static VALUE
2006 {
2007  VALUE node, service, family, socktype, protocol, flags;
2008 
2009  rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags);
2010  return addrinfo_list_new(node, service, family, socktype, protocol, flags);
2011 }
2012 
2013 /*
2014  * call-seq:
2015  * Addrinfo.ip(host) => addrinfo
2016  *
2017  * returns an addrinfo object for IP address.
2018  *
2019  * The port, socktype, protocol of the result is filled by zero.
2020  * So, it is not appropriate to create a socket.
2021  *
2022  * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
2023  */
2024 static VALUE
2026 {
2027  VALUE ret;
2028  rb_addrinfo_t *rai;
2029  ret = addrinfo_firstonly_new(host, Qnil,
2030  INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
2031  rai = get_addrinfo(ret);
2032  rai->socktype = 0;
2033  rai->protocol = 0;
2034  return ret;
2035 }
2036 
2037 /*
2038  * call-seq:
2039  * Addrinfo.tcp(host, port) => addrinfo
2040  *
2041  * returns an addrinfo object for TCP address.
2042  *
2043  * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
2044  */
2045 static VALUE
2046 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
2047 {
2048  return addrinfo_firstonly_new(host, port,
2049  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
2050 }
2051 
2052 /*
2053  * call-seq:
2054  * Addrinfo.udp(host, port) => addrinfo
2055  *
2056  * returns an addrinfo object for UDP address.
2057  *
2058  * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
2059  */
2060 static VALUE
2061 addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
2062 {
2063  return addrinfo_firstonly_new(host, port,
2064  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
2065 }
2066 
2067 #ifdef HAVE_SYS_UN_H
2068 
2069 /*
2070  * call-seq:
2071  * Addrinfo.unix(path [, socktype]) => addrinfo
2072  *
2073  * returns an addrinfo object for UNIX socket address.
2074  *
2075  * _socktype_ specifies the socket type.
2076  * If it is omitted, :STREAM is used.
2077  *
2078  * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
2079  * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
2080  */
2081 static VALUE
2082 addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
2083 {
2084  VALUE path, vsocktype, addr;
2085  int socktype;
2086  rb_addrinfo_t *rai;
2087 
2088  rb_scan_args(argc, argv, "11", &path, &vsocktype);
2089 
2090  if (NIL_P(vsocktype))
2091  socktype = SOCK_STREAM;
2092  else
2093  socktype = rsock_socktype_arg(vsocktype);
2094 
2096  DATA_PTR(addr) = rai = alloc_addrinfo();
2097  init_unix_addrinfo(rai, path, socktype);
2098  OBJ_INFECT(addr, path);
2099  return addr;
2100 }
2101 
2102 #endif
2103 
2104 VALUE
2106 {
2107  VALUE val = *v;
2108  if (IS_ADDRINFO(val)) {
2109  *v = addrinfo_to_sockaddr(val);
2110  }
2111  StringValue(*v);
2112  return *v;
2113 }
2114 
2115 char *
2117 {
2119  return RSTRING_PTR(*v);
2120 }
2121 
2122 VALUE
2124 {
2125  if (IS_ADDRINFO(val))
2126  return addrinfo_to_sockaddr(val);
2127  return rb_check_string_type(val);
2128 }
2129 
2130 VALUE
2131 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
2132 {
2133  int family;
2134  int socktype;
2135  int ret;
2136  socklen_t optlen = (socklen_t)sizeof(socktype);
2137 
2138  /* assumes protocol family and address family are identical */
2139  family = get_afamily(addr, len);
2140 
2141  ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
2142  if (ret == -1) {
2143  rb_sys_fail("getsockopt(SO_TYPE)");
2144  }
2145 
2146  return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
2147 }
2148 
2149 VALUE
2150 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
2151 {
2152  rb_io_t *fptr;
2153 
2154  switch (TYPE(io)) {
2155  case T_FIXNUM:
2156  return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
2157 
2158  case T_BIGNUM:
2159  return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
2160 
2161  case T_FILE:
2162  GetOpenFile(io, fptr);
2163  return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
2164 
2165  default:
2166  rb_raise(rb_eTypeError, "neither IO nor file descriptor");
2167  }
2168 }
2169 
2170 /*
2171  * Addrinfo class
2172  */
2173 void
2175 {
2176  /*
2177  * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
2178  * structure identifies an Internet host and a service.
2179  */
2180  rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData);
2184  rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0);
2189 #ifdef HAVE_SYS_UN_H
2190  rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
2191 #endif
2192 
2198 
2202 
2207 
2211 
2212 #ifdef INET6
2213  rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
2214  rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
2215  rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
2216  rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
2217  rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
2218  rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
2219  rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
2220  rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
2221  rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
2222  rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
2223  rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
2224  rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
2225 
2226  rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
2227 #endif
2228 
2229 #ifdef HAVE_SYS_UN_H
2230  rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
2231 #endif
2232 
2234  rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
2235 
2236  rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
2237 
2238  rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
2239  rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
2240 }
2241