Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
raddrinfo.c
Go to the documentation of this file.
1/************************************************
2
3 raddrinfo.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]))
15static 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
25static int
26ruby_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)
57static int
58ruby_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))
75static int
76ruby_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
100static int str_is_number(const char *);
101
102#if defined(__APPLE__)
103static int
104ruby_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) {
133 }
134 else if (r->ai_socktype == SOCK_STREAM) {
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#ifdef HAVE_INET_PTON
149static int
150parse_numeric_port(const char *service, int *portp)
151{
152 unsigned long u;
153
154 if (!service) {
155 *portp = 0;
156 return 1;
157 }
158
159 if (strspn(service, "0123456789") != strlen(service))
160 return 0;
161
162 errno = 0;
163 u = STRTOUL(service, NULL, 10);
164 if (errno)
165 return 0;
166
167 if (0x10000 <= u)
168 return 0;
169
170 *portp = (int)u;
171
172 return 1;
173}
174#endif
175
176#ifndef GETADDRINFO_EMU
178{
179 const char *node;
180 const char *service;
181 const struct addrinfo *hints;
182 struct addrinfo **res;
183};
184
185static void *
186nogvl_getaddrinfo(void *arg)
187{
188 int ret;
189 struct getaddrinfo_arg *ptr = arg;
190 ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res);
191#ifdef __linux__
192 /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
193 * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
194 */
195 if (ret == EAI_SYSTEM && errno == ENOENT)
196 ret = EAI_NONAME;
197#endif
198 return (void *)(VALUE)ret;
199}
200#endif
201
202static int
203numeric_getaddrinfo(const char *node, const char *service,
204 const struct addrinfo *hints,
205 struct addrinfo **res)
206{
207#ifdef HAVE_INET_PTON
208# if defined __MINGW64__
209# define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d)
210# endif
211
212 int port;
213
214 if (node && parse_numeric_port(service, &port)) {
215 static const struct {
216 int socktype;
217 int protocol;
218 } list[] = {
219 { SOCK_STREAM, IPPROTO_TCP },
220 { SOCK_DGRAM, IPPROTO_UDP },
221 { SOCK_RAW, 0 }
222 };
223 struct addrinfo *ai = NULL;
224 int hint_family = hints ? hints->ai_family : PF_UNSPEC;
225 int hint_socktype = hints ? hints->ai_socktype : 0;
226 int hint_protocol = hints ? hints->ai_protocol : 0;
227 char ipv4addr[4];
228#ifdef AF_INET6
229 char ipv6addr[16];
230 if ((hint_family == PF_UNSPEC || hint_family == PF_INET6) &&
231 strspn(node, "0123456789abcdefABCDEF.:") == strlen(node) &&
232 inet_pton(AF_INET6, node, ipv6addr)) {
233 int i;
234 for (i = numberof(list)-1; 0 <= i; i--) {
235 if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
236 (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
237 struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
238 struct sockaddr_in6 *sa = xmalloc(sizeof(struct sockaddr_in6));
239 INIT_SOCKADDR_IN6(sa, sizeof(struct sockaddr_in6));
240 memcpy(&sa->sin6_addr, ipv6addr, sizeof(ipv6addr));
241 sa->sin6_port = htons(port);
242 ai0->ai_family = PF_INET6;
243 ai0->ai_socktype = list[i].socktype;
244 ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
245 ai0->ai_addrlen = sizeof(struct sockaddr_in6);
246 ai0->ai_addr = (struct sockaddr *)sa;
247 ai0->ai_canonname = NULL;
248 ai0->ai_next = ai;
249 ai = ai0;
250 }
251 }
252 }
253 else
254#endif
255 if ((hint_family == PF_UNSPEC || hint_family == PF_INET) &&
256 strspn(node, "0123456789.") == strlen(node) &&
257 inet_pton(AF_INET, node, ipv4addr)) {
258 int i;
259 for (i = numberof(list)-1; 0 <= i; i--) {
260 if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
261 (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
262 struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
263 struct sockaddr_in *sa = xmalloc(sizeof(struct sockaddr_in));
264 INIT_SOCKADDR_IN(sa, sizeof(struct sockaddr_in));
265 memcpy(&sa->sin_addr, ipv4addr, sizeof(ipv4addr));
266 sa->sin_port = htons(port);
267 ai0->ai_family = PF_INET;
268 ai0->ai_socktype = list[i].socktype;
269 ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
270 ai0->ai_addrlen = sizeof(struct sockaddr_in);
271 ai0->ai_addr = (struct sockaddr *)sa;
272 ai0->ai_canonname = NULL;
273 ai0->ai_next = ai;
274 ai = ai0;
275 }
276 }
277 }
278 if (ai) {
279 *res = ai;
280 return 0;
281 }
282 }
283#endif
284 return EAI_FAIL;
285}
286
287int
288rb_getaddrinfo(const char *node, const char *service,
289 const struct addrinfo *hints,
290 struct rb_addrinfo **res)
291{
292 struct addrinfo *ai;
293 int ret;
294 int allocated_by_malloc = 0;
295
296 ret = numeric_getaddrinfo(node, service, hints, &ai);
297 if (ret == 0)
298 allocated_by_malloc = 1;
299 else {
300#ifdef GETADDRINFO_EMU
301 ret = getaddrinfo(node, service, hints, &ai);
302#else
303 struct getaddrinfo_arg arg;
304 MEMZERO(&arg, struct getaddrinfo_arg, 1);
305 arg.node = node;
306 arg.service = service;
307 arg.hints = hints;
308 arg.res = &ai;
309 ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
310#endif
311 }
312
313 if (ret == 0) {
314 *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
315 (*res)->allocated_by_malloc = allocated_by_malloc;
316 (*res)->ai = ai;
317 }
318 return ret;
319}
320
321void
323{
324 if (!ai->allocated_by_malloc)
325 freeaddrinfo(ai->ai);
326 else {
327 struct addrinfo *ai1, *ai2;
328 ai1 = ai->ai;
329 while (ai1) {
330 ai2 = ai1->ai_next;
331 xfree(ai1->ai_addr);
332 xfree(ai1);
333 ai1 = ai2;
334 }
335 }
336 xfree(ai);
337}
338
339#ifndef GETADDRINFO_EMU
341{
342 const struct sockaddr *sa;
344 int flags;
345 char *host;
346 size_t hostlen;
347 char *serv;
348 size_t servlen;
349};
350
351static void *
352nogvl_getnameinfo(void *arg)
353{
354 struct getnameinfo_arg *ptr = arg;
355 return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen,
356 ptr->host, (socklen_t)ptr->hostlen,
357 ptr->serv, (socklen_t)ptr->servlen,
358 ptr->flags);
359}
360#endif
361
362int
363rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
364 char *host, size_t hostlen,
365 char *serv, size_t servlen, int flags)
366{
367#ifdef GETADDRINFO_EMU
369#else
370 struct getnameinfo_arg arg;
371 int ret;
372 arg.sa = sa;
373 arg.salen = salen;
374 arg.host = host;
375 arg.hostlen = hostlen;
376 arg.serv = serv;
377 arg.servlen = servlen;
378 arg.flags = flags;
379 ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0);
380 return ret;
381#endif
382}
383
384static void
385make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
386{
387 int error;
388
389 error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST);
390 if (error) {
391 rsock_raise_socket_error("getnameinfo", error);
392 }
393}
394
395VALUE
396rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
397{
398 char hbuf[1024];
399
400 make_ipaddr0(addr, addrlen, hbuf, sizeof(hbuf));
401 return rb_str_new2(hbuf);
402}
403
404static void
405make_inetaddr(unsigned int host, char *buf, size_t buflen)
406{
407 struct sockaddr_in sin;
408
409 INIT_SOCKADDR_IN(&sin, sizeof(sin));
410 sin.sin_addr.s_addr = host;
411 make_ipaddr0((struct sockaddr*)&sin, sizeof(sin), buf, buflen);
412}
413
414static int
415str_is_number(const char *p)
416{
417 char *ep;
418
419 if (!p || *p == '\0')
420 return 0;
421 ep = NULL;
422 (void)STRTOUL(p, &ep, 10);
423 if (ep && *ep == '\0')
424 return 1;
425 else
426 return 0;
427}
428
429#define str_equal(ptr, len, name) \
430 ((ptr)[0] == name[0] && \
431 rb_strlen_lit(name) == (len) && memcmp(ptr, name, len) == 0)
432
433static char*
434host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
435{
436 if (NIL_P(host)) {
437 return NULL;
438 }
439 else if (rb_obj_is_kind_of(host, rb_cInteger)) {
440 unsigned int i = NUM2UINT(host);
441
442 make_inetaddr(htonl(i), hbuf, hbuflen);
443 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
444 return hbuf;
445 }
446 else {
447 const char *name;
448 size_t len;
449
450 StringValueCStr(host);
451 RSTRING_GETMEM(host, name, len);
452 if (!len || str_equal(name, len, "<any>")) {
453 make_inetaddr(INADDR_ANY, hbuf, hbuflen);
454 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
455 }
456 else if (str_equal(name, len, "<broadcast>")) {
457 make_inetaddr(INADDR_BROADCAST, hbuf, hbuflen);
458 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
459 }
460 else if (len >= hbuflen) {
461 rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")",
462 len);
463 }
464 else {
465 memcpy(hbuf, name, len);
466 hbuf[len] = '\0';
467 }
468 return hbuf;
469 }
470}
471
472static char*
473port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
474{
475 if (NIL_P(port)) {
476 return 0;
477 }
478 else if (FIXNUM_P(port)) {
479 snprintf(pbuf, pbuflen, "%ld", FIX2LONG(port));
480#ifdef AI_NUMERICSERV
481 if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
482#endif
483 return pbuf;
484 }
485 else {
486 const char *serv;
487 size_t len;
488
489 StringValueCStr(port);
490 RSTRING_GETMEM(port, serv, len);
491 if (len >= pbuflen) {
492 rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")",
493 len);
494 }
495 memcpy(pbuf, serv, len);
496 pbuf[len] = '\0';
497 return pbuf;
498 }
499}
500
501struct rb_addrinfo*
502rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
503{
504 struct rb_addrinfo* res = NULL;
505 char *hostp, *portp;
506 int error;
507 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
508 int additional_flags = 0;
509
510 hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
511 portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
512
513 if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
514 hints->ai_socktype = SOCK_DGRAM;
515 }
516 hints->ai_flags |= additional_flags;
517
518 error = rb_getaddrinfo(hostp, portp, hints, &res);
519 if (error) {
520 if (hostp && hostp[strlen(hostp)-1] == '\n') {
521 rb_raise(rb_eSocket, "newline at the end of hostname");
522 }
523 rsock_raise_socket_error("getaddrinfo", error);
524 }
525
526 return res;
527}
528
529int
531{
532 struct sockaddr sa = { 0 };
533 socklen_t sa_len = sizeof(sa);
534
535 if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0 ||
536 (size_t)sa_len < offsetof(struct sockaddr, sa_family) + sizeof(sa.sa_family)) {
537 return AF_UNSPEC;
538 }
539 return sa.sa_family;
540}
541
542struct rb_addrinfo*
543rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
544{
545 struct addrinfo hints;
546
547 MEMZERO(&hints, struct addrinfo, 1);
548 hints.ai_family = family;
549 hints.ai_socktype = socktype;
550 hints.ai_flags = flags;
551 return rsock_getaddrinfo(host, port, &hints, 1);
552}
553
554VALUE
555rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
556{
557 VALUE family, port, addr1, addr2;
558 VALUE ary;
559 int error;
560 char hbuf[1024], pbuf[1024];
561 ID id;
562
563 id = rsock_intern_family(sockaddr->sa_family);
564 if (id) {
565 family = rb_str_dup(rb_id2str(id));
566 }
567 else {
568 sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
569 family = rb_str_new2(pbuf);
570 }
571
572 addr1 = Qnil;
573 if (!norevlookup) {
574 error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
575 NULL, 0, 0);
576 if (! error) {
577 addr1 = rb_str_new2(hbuf);
578 }
579 }
580 error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
581 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
582 if (error) {
583 rsock_raise_socket_error("getnameinfo", error);
584 }
585 addr2 = rb_str_new2(hbuf);
586 if (addr1 == Qnil) {
587 addr1 = addr2;
588 }
589 port = INT2FIX(atoi(pbuf));
590 ary = rb_ary_new3(4, family, port, addr1, addr2);
591
592 return ary;
593}
594
595#ifdef HAVE_SYS_UN_H
596static long
597unixsocket_len(const struct sockaddr_un *su, socklen_t socklen)
598{
599 const char *s = su->sun_path, *e = (const char*)su + socklen;
600 while (s < e && *(e-1) == '\0')
601 e--;
602 return e - s;
603}
604
605VALUE
606rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len)
607{
608 long n = unixsocket_len(sockaddr, len);
609 if (n >= 0)
610 return rb_str_new(sockaddr->sun_path, n);
611 else
612 return rb_str_new2("");
613}
614
615VALUE
616rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len)
617{
618 return rb_assoc_new(rb_str_new2("AF_UNIX"),
619 rsock_unixpath_str(sockaddr, len));
620}
621
623rsock_unix_sockaddr_len(VALUE path)
624{
625#ifdef __linux__
626 if (RSTRING_LEN(path) == 0) {
627 /* autobind; see unix(7) for details. */
628 return (socklen_t) sizeof(sa_family_t);
629 }
630 else if (RSTRING_PTR(path)[0] == '\0') {
631 /* abstract namespace; see unix(7) for details. */
632 if (SOCKLEN_MAX - offsetof(struct sockaddr_un, sun_path) < (size_t)RSTRING_LEN(path))
633 rb_raise(rb_eArgError, "Linux abstract socket too long");
634 return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
635 RSTRING_SOCKLEN(path);
636 }
637 else {
638#endif
639 return (socklen_t) sizeof(struct sockaddr_un);
640#ifdef __linux__
641 }
642#endif
643}
644#endif
645
649 VALUE (*ipaddr)(struct sockaddr*, socklen_t);
650};
651
652static VALUE
653make_hostent_internal(VALUE v)
654{
655 struct hostent_arg *arg = (void *)v;
656 VALUE host = arg->host;
657 struct addrinfo* addr = arg->addr->ai;
658 VALUE (*ipaddr)(struct sockaddr*, socklen_t) = arg->ipaddr;
659
660 struct addrinfo *ai;
661 struct hostent *h;
662 VALUE ary, names;
663 char **pch;
664 const char* hostp;
665 char hbuf[NI_MAXHOST];
666
667 ary = rb_ary_new();
668 if (addr->ai_canonname) {
669 hostp = addr->ai_canonname;
670 }
671 else {
672 hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
673 }
674 rb_ary_push(ary, rb_str_new2(hostp));
675
676 if (addr->ai_canonname && strlen(addr->ai_canonname) < NI_MAXHOST &&
677 (h = gethostbyname(addr->ai_canonname))) {
678 names = rb_ary_new();
679 if (h->h_aliases != NULL) {
680 for (pch = h->h_aliases; *pch; pch++) {
681 rb_ary_push(names, rb_str_new2(*pch));
682 }
683 }
684 }
685 else {
686 names = rb_ary_new2(0);
687 }
688 rb_ary_push(ary, names);
689 rb_ary_push(ary, INT2NUM(addr->ai_family));
690 for (ai = addr; ai; ai = ai->ai_next) {
691 rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
692 }
693
694 return ary;
695}
696
697VALUE
699{
700 struct rb_addrinfo *addr = (struct rb_addrinfo *)arg;
701 rb_freeaddrinfo(addr);
702 return Qnil;
703}
704
705VALUE
706rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t))
707{
708 struct hostent_arg arg;
709
710 arg.host = host;
711 arg.addr = addr;
712 arg.ipaddr = ipaddr;
713 return rb_ensure(make_hostent_internal, (VALUE)&arg,
715}
716
717typedef struct {
726
727static void
728addrinfo_mark(void *ptr)
729{
730 rb_addrinfo_t *rai = ptr;
732 rb_gc_mark(rai->canonname);
733}
734
735#define addrinfo_free RUBY_TYPED_DEFAULT_FREE
736
737static size_t
738addrinfo_memsize(const void *ptr)
739{
740 return sizeof(rb_addrinfo_t);
741}
742
743static const rb_data_type_t addrinfo_type = {
744 "socket/addrinfo",
745 {addrinfo_mark, addrinfo_free, addrinfo_memsize,},
746};
747
748static VALUE
749addrinfo_s_allocate(VALUE klass)
750{
751 return TypedData_Wrap_Struct(klass, &addrinfo_type, 0);
752}
753
754#define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
755static inline rb_addrinfo_t *
756check_addrinfo(VALUE self)
757{
758 return rb_check_typeddata(self, &addrinfo_type);
759}
760
761static rb_addrinfo_t *
762get_addrinfo(VALUE self)
763{
764 rb_addrinfo_t *rai = check_addrinfo(self);
765
766 if (!rai) {
767 rb_raise(rb_eTypeError, "uninitialized socket address");
768 }
769 return rai;
770}
771
772
773static rb_addrinfo_t *
774alloc_addrinfo(void)
775{
777 rai->inspectname = Qnil;
778 rai->canonname = Qnil;
779 return rai;
780}
781
782static void
783init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
784 int pfamily, int socktype, int protocol,
785 VALUE canonname, VALUE inspectname)
786{
787 if ((socklen_t)sizeof(rai->addr) < len)
788 rb_raise(rb_eArgError, "sockaddr string too big");
789 memcpy((void *)&rai->addr, (void *)sa, len);
790 rai->sockaddr_len = len;
791
792 rai->pfamily = pfamily;
793 rai->socktype = socktype;
794 rai->protocol = protocol;
795 rai->canonname = canonname;
796 rai->inspectname = inspectname;
797}
798
799VALUE
800rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
801 int family, int socktype, int protocol,
802 VALUE canonname, VALUE inspectname)
803{
804 VALUE a;
805 rb_addrinfo_t *rai;
806
807 a = addrinfo_s_allocate(rb_cAddrinfo);
808 DATA_PTR(a) = rai = alloc_addrinfo();
809 init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname);
810 return a;
811}
812
813static struct rb_addrinfo *
814call_getaddrinfo(VALUE node, VALUE service,
815 VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
816 int socktype_hack, VALUE timeout)
817{
818 struct addrinfo hints;
819 struct rb_addrinfo *res;
820
821 MEMZERO(&hints, struct addrinfo, 1);
822 hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
823
824 if (!NIL_P(socktype)) {
825 hints.ai_socktype = rsock_socktype_arg(socktype);
826 }
827 if (!NIL_P(protocol)) {
828 hints.ai_protocol = NUM2INT(protocol);
829 }
830 if (!NIL_P(flags)) {
831 hints.ai_flags = NUM2INT(flags);
832 }
833
834 res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
835
836 if (res == NULL)
837 rb_raise(rb_eSocket, "host not found");
838 return res;
839}
840
841static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
842
843static void
844init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service,
845 VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
846 VALUE inspectnode, VALUE inspectservice)
847{
848 struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1, Qnil);
849 VALUE canonname;
850 VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res->ai);
851
852 canonname = Qnil;
853 if (res->ai->ai_canonname) {
854 canonname = rb_str_new_cstr(res->ai->ai_canonname);
855 OBJ_FREEZE(canonname);
856 }
857
858 init_addrinfo(rai, res->ai->ai_addr, res->ai->ai_addrlen,
859 NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
860 canonname, inspectname);
861
862 rb_freeaddrinfo(res);
863}
864
865static VALUE
866make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
867{
868 VALUE inspectname = Qnil;
869
870 if (res) {
871 /* drop redundant information which also shown in address:port part. */
872 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
873 int ret;
874 ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
875 sizeof(hbuf), pbuf, sizeof(pbuf),
877 if (ret == 0) {
878 if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0)
879 node = Qnil;
880 if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0)
881 service = Qnil;
882 else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service))
883 service = Qnil;
884 }
885 }
886
887 if (RB_TYPE_P(node, T_STRING)) {
888 inspectname = rb_str_dup(node);
889 }
890 if (RB_TYPE_P(service, T_STRING)) {
891 if (NIL_P(inspectname))
892 inspectname = rb_sprintf(":%s", StringValueCStr(service));
893 else
894 rb_str_catf(inspectname, ":%s", StringValueCStr(service));
895 }
896 else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0)
897 {
898 if (NIL_P(inspectname))
899 inspectname = rb_sprintf(":%d", FIX2INT(service));
900 else
901 rb_str_catf(inspectname, ":%d", FIX2INT(service));
902 }
903 if (!NIL_P(inspectname)) {
904 OBJ_FREEZE(inspectname);
905 }
906 return inspectname;
907}
908
909static VALUE
910addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
911{
912 VALUE ret;
913 VALUE canonname;
914 VALUE inspectname;
915
916 struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, Qnil);
917
918 inspectname = make_inspectname(node, service, res->ai);
919
920 canonname = Qnil;
921 if (res->ai->ai_canonname) {
922 canonname = rb_str_new_cstr(res->ai->ai_canonname);
923 OBJ_FREEZE(canonname);
924 }
925
926 ret = rsock_addrinfo_new(res->ai->ai_addr, res->ai->ai_addrlen,
927 res->ai->ai_family, res->ai->ai_socktype,
928 res->ai->ai_protocol,
929 canonname, inspectname);
930
931 rb_freeaddrinfo(res);
932 return ret;
933}
934
935static VALUE
936addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE timeout)
937{
938 VALUE ret;
939 struct addrinfo *r;
940 VALUE inspectname;
941
942 struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, timeout);
943
944 inspectname = make_inspectname(node, service, res->ai);
945
946 ret = rb_ary_new();
947 for (r = res->ai; r; r = r->ai_next) {
948 VALUE addr;
949 VALUE canonname = Qnil;
950
951 if (r->ai_canonname) {
952 canonname = rb_str_new_cstr(r->ai_canonname);
953 OBJ_FREEZE(canonname);
954 }
955
958 canonname, inspectname);
959
960 rb_ary_push(ret, addr);
961 }
962
963 rb_freeaddrinfo(res);
964 return ret;
965}
966
967
968#ifdef HAVE_SYS_UN_H
969static void
970init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
971{
972 struct sockaddr_un un;
974
975 StringValue(path);
976
977 if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
979 "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
980 (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
981
982 INIT_SOCKADDR_UN(&un, sizeof(struct sockaddr_un));
983 memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
984
985 len = rsock_unix_sockaddr_len(path);
986 init_addrinfo(rai, (struct sockaddr *)&un, len,
987 PF_UNIX, socktype, 0, Qnil, Qnil);
988}
989
990static long
991rai_unixsocket_len(const rb_addrinfo_t *rai)
992{
993 return unixsocket_len(&rai->addr.un, rai->sockaddr_len);
994}
995#endif
996
997/*
998 * call-seq:
999 * Addrinfo.new(sockaddr) => addrinfo
1000 * Addrinfo.new(sockaddr, family) => addrinfo
1001 * Addrinfo.new(sockaddr, family, socktype) => addrinfo
1002 * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
1003 *
1004 * returns a new instance of Addrinfo.
1005 * The instance contains sockaddr, family, socktype, protocol.
1006 * sockaddr means struct sockaddr which can be used for connect(2), etc.
1007 * family, socktype and protocol are integers which is used for arguments of socket(2).
1008 *
1009 * sockaddr is specified as an array or a string.
1010 * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
1011 * The string should be struct sockaddr as generated by
1012 * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
1013 *
1014 * sockaddr examples:
1015 * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
1016 * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
1017 * - ["AF_UNIX", "/tmp/sock"]
1018 * - Socket.sockaddr_in("smtp", "2001:DB8::1")
1019 * - Socket.sockaddr_in(80, "172.18.22.42")
1020 * - Socket.sockaddr_in(80, "www.ruby-lang.org")
1021 * - Socket.sockaddr_un("/tmp/sock")
1022 *
1023 * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
1024 * numeric IP address, is used to construct socket address in the Addrinfo instance.
1025 * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
1026 *
1027 * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
1028 * It can be a symbol or a string which is the constant name
1029 * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
1030 * If omitted, PF_UNSPEC is assumed.
1031 *
1032 * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
1033 * It can be a symbol or a string which is the constant name
1034 * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
1035 * If omitted, 0 is assumed.
1036 *
1037 * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
1038 * It must be an integer, unlike family and socktype.
1039 * If omitted, 0 is assumed.
1040 * Note that 0 is reasonable value for most protocols, except raw socket.
1041 *
1042 */
1043static VALUE
1044addrinfo_initialize(int argc, VALUE *argv, VALUE self)
1045{
1046 rb_addrinfo_t *rai;
1047 VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
1048 int i_pfamily, i_socktype, i_protocol;
1049 struct sockaddr *sockaddr_ptr;
1050 socklen_t sockaddr_len;
1051 VALUE canonname = Qnil, inspectname = Qnil;
1052
1053 if (check_addrinfo(self))
1054 rb_raise(rb_eTypeError, "already initialized socket address");
1055 DATA_PTR(self) = rai = alloc_addrinfo();
1056
1057 rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
1058
1059 i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
1060 i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
1061 i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
1062
1063 sockaddr_ary = rb_check_array_type(sockaddr_arg);
1064 if (!NIL_P(sockaddr_ary)) {
1065 VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
1066 int af;
1067 StringValue(afamily);
1068 if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
1069 rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
1070 switch (af) {
1071 case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
1072#ifdef INET6
1073 case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
1074#endif
1075 {
1076 VALUE service = rb_ary_entry(sockaddr_ary, 1);
1077 VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
1078 VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
1079 int flags;
1080
1081 service = INT2NUM(NUM2INT(service));
1082 if (!NIL_P(nodename))
1083 StringValue(nodename);
1084 StringValue(numericnode);
1085 flags = AI_NUMERICHOST;
1086#ifdef AI_NUMERICSERV
1087 flags |= AI_NUMERICSERV;
1088#endif
1089
1090 init_addrinfo_getaddrinfo(rai, numericnode, service,
1091 INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
1092 INT2NUM(flags),
1093 nodename, service);
1094 break;
1095 }
1096
1097#ifdef HAVE_SYS_UN_H
1098 case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
1099 {
1100 VALUE path = rb_ary_entry(sockaddr_ary, 1);
1101 StringValue(path);
1102 init_unix_addrinfo(rai, path, SOCK_STREAM);
1103 break;
1104 }
1105#endif
1106
1107 default:
1108 rb_raise(rb_eSocket, "unexpected address family");
1109 }
1110 }
1111 else {
1112 StringValue(sockaddr_arg);
1113 sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
1114 sockaddr_len = RSTRING_SOCKLEN(sockaddr_arg);
1115 init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
1116 i_pfamily, i_socktype, i_protocol,
1117 canonname, inspectname);
1118 }
1119
1120 return self;
1121}
1122
1123static int
1124get_afamily(const struct sockaddr *addr, socklen_t len)
1125{
1126 if ((socklen_t)((const char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
1127 return addr->sa_family;
1128 else
1129 return AF_UNSPEC;
1130}
1131
1132static int
1133ai_get_afamily(const rb_addrinfo_t *rai)
1134{
1135 return get_afamily(&rai->addr.addr, rai->sockaddr_len);
1136}
1137
1138static VALUE
1139inspect_sockaddr(VALUE addrinfo, VALUE ret)
1140{
1141 rb_addrinfo_t *rai = get_addrinfo(addrinfo);
1142 union_sockaddr *sockaddr = &rai->addr;
1143 socklen_t socklen = rai->sockaddr_len;
1144 return rsock_inspect_sockaddr((struct sockaddr *)sockaddr, socklen, ret);
1145}
1146
1147VALUE
1148rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE ret)
1149{
1150 union_sockaddr *sockaddr = (union_sockaddr *)sockaddr_arg;
1151 if (socklen == 0) {
1152 rb_str_cat2(ret, "empty-sockaddr");
1153 }
1154 else if ((long)socklen < ((char*)&sockaddr->addr.sa_family + sizeof(sockaddr->addr.sa_family)) - (char*)sockaddr)
1155 rb_str_cat2(ret, "too-short-sockaddr");
1156 else {
1157 switch (sockaddr->addr.sa_family) {
1158 case AF_UNSPEC:
1159 {
1160 rb_str_cat2(ret, "UNSPEC");
1161 break;
1162 }
1163
1164 case AF_INET:
1165 {
1166 struct sockaddr_in *addr;
1167 int port;
1168 addr = &sockaddr->in;
1169 if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen)
1170 rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]);
1171 else
1172 rb_str_cat2(ret, "?");
1173 if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen)
1174 rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]);
1175 else
1176 rb_str_cat2(ret, ".?");
1177 if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen)
1178 rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]);
1179 else
1180 rb_str_cat2(ret, ".?");
1181 if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen)
1182 rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]);
1183 else
1184 rb_str_cat2(ret, ".?");
1185
1186 if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) {
1187 port = ntohs(addr->sin_port);
1188 if (port)
1189 rb_str_catf(ret, ":%d", port);
1190 }
1191 else {
1192 rb_str_cat2(ret, ":?");
1193 }
1194 if ((socklen_t)sizeof(struct sockaddr_in) != socklen)
1195 rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)",
1196 (int)socklen,
1197 (int)sizeof(struct sockaddr_in));
1198 break;
1199 }
1200
1201#ifdef AF_INET6
1202 case AF_INET6:
1203 {
1204 struct sockaddr_in6 *addr;
1205 char hbuf[1024];
1206 int port;
1207 int error;
1208 if (socklen < (socklen_t)sizeof(struct sockaddr_in6)) {
1209 rb_str_catf(ret, "too-short-AF_INET6-sockaddr %d bytes", (int)socklen);
1210 }
1211 else {
1212 addr = &sockaddr->in6;
1213 /* use getnameinfo for scope_id.
1214 * RFC 4007: IPv6 Scoped Address Architecture
1215 * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
1216 */
1217 error = getnameinfo(&sockaddr->addr, socklen,
1218 hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
1220 if (error) {
1221 rsock_raise_socket_error("getnameinfo", error);
1222 }
1223 if (addr->sin6_port == 0) {
1224 rb_str_cat2(ret, hbuf);
1225 }
1226 else {
1227 port = ntohs(addr->sin6_port);
1228 rb_str_catf(ret, "[%s]:%d", hbuf, port);
1229 }
1230 if ((socklen_t)sizeof(struct sockaddr_in6) < socklen)
1231 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(socklen - sizeof(struct sockaddr_in6)));
1232 }
1233 break;
1234 }
1235#endif
1236
1237#ifdef HAVE_SYS_UN_H
1238 case AF_UNIX:
1239 {
1240 struct sockaddr_un *addr = &sockaddr->un;
1241 char *p, *s, *e;
1242 long len = unixsocket_len(addr, socklen);
1243 s = addr->sun_path;
1244 if (len < 0)
1245 rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
1246 else if (len == 0)
1247 rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
1248 else {
1249 int printable_only = 1;
1250 e = s + len;
1251 p = s;
1252 while (p < e) {
1253 printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
1254 p++;
1255 }
1256 if (printable_only) { /* only printable, no space */
1257 if (s[0] != '/') /* relative path */
1258 rb_str_cat2(ret, "UNIX ");
1259 rb_str_cat(ret, s, p - s);
1260 }
1261 else {
1262 rb_str_cat2(ret, "UNIX");
1263 while (s < e)
1264 rb_str_catf(ret, ":%02x", (unsigned char)*s++);
1265 }
1266 }
1267 break;
1268 }
1269#endif
1270
1271#if defined(AF_PACKET) && defined(__linux__)
1272 /* GNU/Linux */
1273 case AF_PACKET:
1274 {
1275 struct sockaddr_ll *addr;
1276 const char *sep = "[";
1277#define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
1278
1279 addr = (struct sockaddr_ll *)sockaddr;
1280
1281 rb_str_cat2(ret, "PACKET");
1282
1283 if (offsetof(struct sockaddr_ll, sll_protocol) + sizeof(addr->sll_protocol) <= (size_t)socklen) {
1284 CATSEP;
1285 rb_str_catf(ret, "protocol=%d", ntohs(addr->sll_protocol));
1286 }
1287 if (offsetof(struct sockaddr_ll, sll_ifindex) + sizeof(addr->sll_ifindex) <= (size_t)socklen) {
1288 char buf[IFNAMSIZ];
1289 CATSEP;
1290 if (if_indextoname(addr->sll_ifindex, buf) == NULL)
1291 rb_str_catf(ret, "ifindex=%d", addr->sll_ifindex);
1292 else
1293 rb_str_catf(ret, "%s", buf);
1294 }
1295 if (offsetof(struct sockaddr_ll, sll_hatype) + sizeof(addr->sll_hatype) <= (size_t)socklen) {
1296 CATSEP;
1297 rb_str_catf(ret, "hatype=%d", addr->sll_hatype);
1298 }
1299 if (offsetof(struct sockaddr_ll, sll_pkttype) + sizeof(addr->sll_pkttype) <= (size_t)socklen) {
1300 CATSEP;
1301 if (addr->sll_pkttype == PACKET_HOST)
1302 rb_str_cat2(ret, "HOST");
1303 else if (addr->sll_pkttype == PACKET_BROADCAST)
1304 rb_str_cat2(ret, "BROADCAST");
1305 else if (addr->sll_pkttype == PACKET_MULTICAST)
1306 rb_str_cat2(ret, "MULTICAST");
1307 else if (addr->sll_pkttype == PACKET_OTHERHOST)
1308 rb_str_cat2(ret, "OTHERHOST");
1309 else if (addr->sll_pkttype == PACKET_OUTGOING)
1310 rb_str_cat2(ret, "OUTGOING");
1311 else
1312 rb_str_catf(ret, "pkttype=%d", addr->sll_pkttype);
1313 }
1314 if (socklen != (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen)) {
1315 CATSEP;
1316 if (offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen) <= (size_t)socklen) {
1317 rb_str_catf(ret, "halen=%d", addr->sll_halen);
1318 }
1319 }
1320 if (offsetof(struct sockaddr_ll, sll_addr) < (size_t)socklen) {
1321 socklen_t len, i;
1322 CATSEP;
1323 rb_str_cat2(ret, "hwaddr");
1324 len = addr->sll_halen;
1325 if ((size_t)socklen < offsetof(struct sockaddr_ll, sll_addr) + len)
1326 len = socklen - offsetof(struct sockaddr_ll, sll_addr);
1327 for (i = 0; i < len; i++) {
1328 rb_str_cat2(ret, i == 0 ? "=" : ":");
1329 rb_str_catf(ret, "%02x", addr->sll_addr[i]);
1330 }
1331 }
1332
1333 if (socklen < (socklen_t)(offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen)) ||
1334 (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen) != socklen) {
1335 CATSEP;
1336 rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_ll)",
1337 (int)socklen, (int)sizeof(struct sockaddr_ll));
1338 }
1339
1340 rb_str_cat2(ret, "]");
1341#undef CATSEP
1342
1343 break;
1344 }
1345#endif
1346
1347#if defined(AF_LINK) && defined(HAVE_TYPE_STRUCT_SOCKADDR_DL)
1348 /* AF_LINK is defined in 4.4BSD derivations since Net2.
1349 link_ntoa is also defined at Net2.
1350 However Debian GNU/kFreeBSD defines AF_LINK but
1351 don't have link_ntoa. */
1352 case AF_LINK:
1353 {
1354 /*
1355 * Simple implementation using link_ntoa():
1356 * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze).
1357 * Also, the format is bit different.
1358 *
1359 * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl));
1360 * break;
1361 */
1362 struct sockaddr_dl *addr = &sockaddr->dl;
1363 char *np = NULL, *ap = NULL, *endp;
1364 int nlen = 0, alen = 0;
1365 int i, off;
1366 const char *sep = "[";
1367#define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
1368
1369 rb_str_cat2(ret, "LINK");
1370
1371 endp = ((char *)addr) + socklen;
1372
1373 if (offsetof(struct sockaddr_dl, sdl_data) < socklen) {
1374 np = addr->sdl_data;
1375 nlen = addr->sdl_nlen;
1376 if (endp - np < nlen)
1377 nlen = (int)(endp - np);
1378 }
1379 off = addr->sdl_nlen;
1380
1381 if (offsetof(struct sockaddr_dl, sdl_data) + off < socklen) {
1382 ap = addr->sdl_data + off;
1383 alen = addr->sdl_alen;
1384 if (endp - ap < alen)
1385 alen = (int)(endp - ap);
1386 }
1387
1388 CATSEP;
1389 if (np)
1390 rb_str_catf(ret, "%.*s", nlen, np);
1391 else
1392 rb_str_cat2(ret, "?");
1393
1394 if (ap && 0 < alen) {
1395 CATSEP;
1396 for (i = 0; i < alen; i++)
1397 rb_str_catf(ret, "%s%02x", i == 0 ? "" : ":", (unsigned char)ap[i]);
1398 }
1399
1400 if (socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_nlen) + sizeof(addr->sdl_nlen)) ||
1401 socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_alen) + sizeof(addr->sdl_alen)) ||
1402 socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_slen) + sizeof(addr->sdl_slen)) ||
1403 /* longer length is possible behavior because struct sockaddr_dl has "minimum work area, can be larger" as the last field.
1404 * cf. Net2:/usr/src/sys/net/if_dl.h. */
1405 socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_data) + addr->sdl_nlen + addr->sdl_alen + addr->sdl_slen)) {
1406 CATSEP;
1407 rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_dl)",
1408 (int)socklen, (int)sizeof(struct sockaddr_dl));
1409 }
1410
1411 rb_str_cat2(ret, "]");
1412#undef CATSEP
1413 break;
1414 }
1415#endif
1416
1417 default:
1418 {
1419 ID id = rsock_intern_family(sockaddr->addr.sa_family);
1420 if (id == 0)
1421 rb_str_catf(ret, "unknown address family %d", sockaddr->addr.sa_family);
1422 else
1423 rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
1424 break;
1425 }
1426 }
1427 }
1428
1429 return ret;
1430}
1431
1432/*
1433 * call-seq:
1434 * addrinfo.inspect => string
1435 *
1436 * returns a string which shows addrinfo in human-readable form.
1437 *
1438 * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>"
1439 * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
1440 *
1441 */
1442static VALUE
1443addrinfo_inspect(VALUE self)
1444{
1445 rb_addrinfo_t *rai = get_addrinfo(self);
1446 int internet_p;
1447 VALUE ret;
1448
1449 ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
1450
1451 inspect_sockaddr(self, ret);
1452
1453 if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
1455 if (id)
1456 rb_str_catf(ret, " %s", rb_id2name(id));
1457 else
1458 rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
1459 }
1460
1461 internet_p = rai->pfamily == PF_INET;
1462#ifdef INET6
1463 internet_p = internet_p || rai->pfamily == PF_INET6;
1464#endif
1465 if (internet_p && rai->socktype == SOCK_STREAM &&
1466 (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
1467 rb_str_cat2(ret, " TCP");
1468 }
1469 else if (internet_p && rai->socktype == SOCK_DGRAM &&
1470 (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
1471 rb_str_cat2(ret, " UDP");
1472 }
1473 else {
1474 if (rai->socktype) {
1476 if (id)
1477 rb_str_catf(ret, " %s", rb_id2name(id));
1478 else
1479 rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
1480 }
1481
1482 if (rai->protocol) {
1483 if (internet_p) {
1484 ID id = rsock_intern_ipproto(rai->protocol);
1485 if (id)
1486 rb_str_catf(ret, " %s", rb_id2name(id));
1487 else
1488 goto unknown_protocol;
1489 }
1490 else {
1491 unknown_protocol:
1492 rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
1493 }
1494 }
1495 }
1496
1497 if (!NIL_P(rai->canonname)) {
1498 VALUE name = rai->canonname;
1499 rb_str_catf(ret, " %s", StringValueCStr(name));
1500 }
1501
1502 if (!NIL_P(rai->inspectname)) {
1503 VALUE name = rai->inspectname;
1504 rb_str_catf(ret, " (%s)", StringValueCStr(name));
1505 }
1506
1507 rb_str_buf_cat2(ret, ">");
1508 return ret;
1509}
1510
1511/*
1512 * call-seq:
1513 * addrinfo.inspect_sockaddr => string
1514 *
1515 * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
1516 *
1517 * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
1518 * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
1519 * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
1520 *
1521 */
1522VALUE
1524{
1525 return inspect_sockaddr(self, rb_str_new("", 0));
1526}
1527
1528/* :nodoc: */
1529static VALUE
1530addrinfo_mdump(VALUE self)
1531{
1532 rb_addrinfo_t *rai = get_addrinfo(self);
1533 VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
1534 int afamily_int = ai_get_afamily(rai);
1535 ID id;
1536
1538 if (id == 0)
1539 rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
1540 pfamily = rb_id2str(id);
1541
1542 if (rai->socktype == 0)
1543 socktype = INT2FIX(0);
1544 else {
1546 if (id == 0)
1547 rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
1548 socktype = rb_id2str(id);
1549 }
1550
1551 if (rai->protocol == 0)
1552 protocol = INT2FIX(0);
1553 else if (IS_IP_FAMILY(afamily_int)) {
1554 id = rsock_intern_ipproto(rai->protocol);
1555 if (id == 0)
1556 rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
1557 protocol = rb_id2str(id);
1558 }
1559 else {
1560 rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
1561 }
1562
1563 canonname = rai->canonname;
1564
1565 inspectname = rai->inspectname;
1566
1567 id = rsock_intern_family(afamily_int);
1568 if (id == 0)
1569 rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
1570 afamily = rb_id2str(id);
1571
1572 switch(afamily_int) {
1573#ifdef HAVE_SYS_UN_H
1574 case AF_UNIX:
1575 {
1576 sockaddr = rb_str_new(rai->addr.un.sun_path, rai_unixsocket_len(rai));
1577 break;
1578 }
1579#endif
1580
1581 default:
1582 {
1583 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
1584 int error;
1585 error = getnameinfo(&rai->addr.addr, rai->sockaddr_len,
1586 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1588 if (error) {
1589 rsock_raise_socket_error("getnameinfo", error);
1590 }
1591 sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
1592 break;
1593 }
1594 }
1595
1596 return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
1597}
1598
1599/* :nodoc: */
1600static VALUE
1601addrinfo_mload(VALUE self, VALUE ary)
1602{
1603 VALUE v;
1604 VALUE canonname, inspectname;
1605 int afamily, pfamily, socktype, protocol;
1606 union_sockaddr ss;
1607 socklen_t len;
1608 rb_addrinfo_t *rai;
1609
1610 if (check_addrinfo(self))
1611 rb_raise(rb_eTypeError, "already initialized socket address");
1612
1613 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1614
1615 v = rb_ary_entry(ary, 0);
1616 StringValue(v);
1617 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
1618 rb_raise(rb_eTypeError, "unexpected address family");
1619
1620 v = rb_ary_entry(ary, 2);
1621 StringValue(v);
1622 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
1623 rb_raise(rb_eTypeError, "unexpected protocol family");
1624
1625 v = rb_ary_entry(ary, 3);
1626 if (v == INT2FIX(0))
1627 socktype = 0;
1628 else {
1629 StringValue(v);
1630 if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
1631 rb_raise(rb_eTypeError, "unexpected socktype");
1632 }
1633
1634 v = rb_ary_entry(ary, 4);
1635 if (v == INT2FIX(0))
1636 protocol = 0;
1637 else {
1638 StringValue(v);
1639 if (IS_IP_FAMILY(afamily)) {
1640 if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1)
1641 rb_raise(rb_eTypeError, "unexpected protocol");
1642 }
1643 else {
1644 rb_raise(rb_eTypeError, "unexpected protocol");
1645 }
1646 }
1647
1648 v = rb_ary_entry(ary, 5);
1649 if (NIL_P(v))
1650 canonname = Qnil;
1651 else {
1652 StringValue(v);
1653 canonname = v;
1654 }
1655
1656 v = rb_ary_entry(ary, 6);
1657 if (NIL_P(v))
1658 inspectname = Qnil;
1659 else {
1660 StringValue(v);
1661 inspectname = v;
1662 }
1663
1664 v = rb_ary_entry(ary, 1);
1665 switch(afamily) {
1666#ifdef HAVE_SYS_UN_H
1667 case AF_UNIX:
1668 {
1669 struct sockaddr_un uaddr;
1670 INIT_SOCKADDR_UN(&uaddr, sizeof(struct sockaddr_un));
1671
1672 StringValue(v);
1673 if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
1675 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1676 (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
1677 memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
1678 len = (socklen_t)sizeof(uaddr);
1679 memcpy(&ss, &uaddr, len);
1680 break;
1681 }
1682#endif
1683
1684 default:
1685 {
1686 VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
1687 struct rb_addrinfo *res;
1688 int flags = AI_NUMERICHOST;
1689#ifdef AI_NUMERICSERV
1690 flags |= AI_NUMERICSERV;
1691#endif
1692 res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
1693 INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
1694 INT2NUM(flags), 1, Qnil);
1695
1696 len = res->ai->ai_addrlen;
1697 memcpy(&ss, res->ai->ai_addr, res->ai->ai_addrlen);
1698 rb_freeaddrinfo(res);
1699 break;
1700 }
1701 }
1702
1703 DATA_PTR(self) = rai = alloc_addrinfo();
1704 init_addrinfo(rai, &ss.addr, len,
1705 pfamily, socktype, protocol,
1706 canonname, inspectname);
1707 return self;
1708}
1709
1710/*
1711 * call-seq:
1712 * addrinfo.afamily => integer
1713 *
1714 * returns the address family as an integer.
1715 *
1716 * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
1717 *
1718 */
1719static VALUE
1720addrinfo_afamily(VALUE self)
1721{
1722 rb_addrinfo_t *rai = get_addrinfo(self);
1723 return INT2NUM(ai_get_afamily(rai));
1724}
1725
1726/*
1727 * call-seq:
1728 * addrinfo.pfamily => integer
1729 *
1730 * returns the protocol family as an integer.
1731 *
1732 * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
1733 *
1734 */
1735static VALUE
1736addrinfo_pfamily(VALUE self)
1737{
1738 rb_addrinfo_t *rai = get_addrinfo(self);
1739 return INT2NUM(rai->pfamily);
1740}
1741
1742/*
1743 * call-seq:
1744 * addrinfo.socktype => integer
1745 *
1746 * returns the socket type as an integer.
1747 *
1748 * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
1749 *
1750 */
1751static VALUE
1752addrinfo_socktype(VALUE self)
1753{
1754 rb_addrinfo_t *rai = get_addrinfo(self);
1755 return INT2NUM(rai->socktype);
1756}
1757
1758/*
1759 * call-seq:
1760 * addrinfo.protocol => integer
1761 *
1762 * returns the socket type as an integer.
1763 *
1764 * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
1765 *
1766 */
1767static VALUE
1768addrinfo_protocol(VALUE self)
1769{
1770 rb_addrinfo_t *rai = get_addrinfo(self);
1771 return INT2NUM(rai->protocol);
1772}
1773
1774/*
1775 * call-seq:
1776 * addrinfo.to_sockaddr => string
1777 * addrinfo.to_s => string
1778 *
1779 * returns the socket address as packed struct sockaddr string.
1780 *
1781 * Addrinfo.tcp("localhost", 80).to_sockaddr
1782 * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1783 *
1784 */
1785static VALUE
1786addrinfo_to_sockaddr(VALUE self)
1787{
1788 rb_addrinfo_t *rai = get_addrinfo(self);
1789 VALUE ret;
1790 ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
1791 return ret;
1792}
1793
1794/*
1795 * call-seq:
1796 * addrinfo.canonname => string or nil
1797 *
1798 * returns the canonical name as a string.
1799 *
1800 * nil is returned if no canonical name.
1801 *
1802 * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
1803 *
1804 * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
1805 * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)>
1806 * p list[0].canonname #=> "carbon.ruby-lang.org"
1807 *
1808 */
1809static VALUE
1810addrinfo_canonname(VALUE self)
1811{
1812 rb_addrinfo_t *rai = get_addrinfo(self);
1813 return rai->canonname;
1814}
1815
1816/*
1817 * call-seq:
1818 * addrinfo.ip? => true or false
1819 *
1820 * returns true if addrinfo is internet (IPv4/IPv6) address.
1821 * returns false otherwise.
1822 *
1823 * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
1824 * Addrinfo.tcp("::1", 80).ip? #=> true
1825 * Addrinfo.unix("/tmp/sock").ip? #=> false
1826 *
1827 */
1828static VALUE
1829addrinfo_ip_p(VALUE self)
1830{
1831 rb_addrinfo_t *rai = get_addrinfo(self);
1832 int family = ai_get_afamily(rai);
1833 return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
1834}
1835
1836/*
1837 * call-seq:
1838 * addrinfo.ipv4? => true or false
1839 *
1840 * returns true if addrinfo is IPv4 address.
1841 * returns false otherwise.
1842 *
1843 * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
1844 * Addrinfo.tcp("::1", 80).ipv4? #=> false
1845 * Addrinfo.unix("/tmp/sock").ipv4? #=> false
1846 *
1847 */
1848static VALUE
1849addrinfo_ipv4_p(VALUE self)
1850{
1851 rb_addrinfo_t *rai = get_addrinfo(self);
1852 return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
1853}
1854
1855/*
1856 * call-seq:
1857 * addrinfo.ipv6? => true or false
1858 *
1859 * returns true if addrinfo is IPv6 address.
1860 * returns false otherwise.
1861 *
1862 * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
1863 * Addrinfo.tcp("::1", 80).ipv6? #=> true
1864 * Addrinfo.unix("/tmp/sock").ipv6? #=> false
1865 *
1866 */
1867static VALUE
1868addrinfo_ipv6_p(VALUE self)
1869{
1870#ifdef AF_INET6
1871 rb_addrinfo_t *rai = get_addrinfo(self);
1872 return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
1873#else
1874 return Qfalse;
1875#endif
1876}
1877
1878/*
1879 * call-seq:
1880 * addrinfo.unix? => true or false
1881 *
1882 * returns true if addrinfo is UNIX address.
1883 * returns false otherwise.
1884 *
1885 * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
1886 * Addrinfo.tcp("::1", 80).unix? #=> false
1887 * Addrinfo.unix("/tmp/sock").unix? #=> true
1888 *
1889 */
1890static VALUE
1891addrinfo_unix_p(VALUE self)
1892{
1893 rb_addrinfo_t *rai = get_addrinfo(self);
1894#ifdef AF_UNIX
1895 return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
1896#else
1897 return Qfalse;
1898#endif
1899}
1900
1901/*
1902 * call-seq:
1903 * addrinfo.getnameinfo => [nodename, service]
1904 * addrinfo.getnameinfo(flags) => [nodename, service]
1905 *
1906 * returns nodename and service as a pair of strings.
1907 * This converts struct sockaddr in addrinfo to textual representation.
1908 *
1909 * flags should be bitwise OR of Socket::NI_??? constants.
1910 *
1911 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
1912 *
1913 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
1914 * #=> ["localhost", "80"]
1915 */
1916static VALUE
1917addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
1918{
1919 rb_addrinfo_t *rai = get_addrinfo(self);
1920 VALUE vflags;
1921 char hbuf[1024], pbuf[1024];
1922 int flags, error;
1923
1924 rb_scan_args(argc, argv, "01", &vflags);
1925
1926 flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
1927
1928 if (rai->socktype == SOCK_DGRAM)
1929 flags |= NI_DGRAM;
1930
1931 error = getnameinfo(&rai->addr.addr, rai->sockaddr_len,
1932 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1933 flags);
1934 if (error) {
1935 rsock_raise_socket_error("getnameinfo", error);
1936 }
1937
1938 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1939}
1940
1941/*
1942 * call-seq:
1943 * addrinfo.ip_unpack => [addr, port]
1944 *
1945 * Returns the IP address and port number as 2-element array.
1946 *
1947 * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
1948 * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
1949 */
1950static VALUE
1951addrinfo_ip_unpack(VALUE self)
1952{
1953 rb_addrinfo_t *rai = get_addrinfo(self);
1954 int family = ai_get_afamily(rai);
1955 VALUE vflags;
1956 VALUE ret, portstr;
1957
1958 if (!IS_IP_FAMILY(family))
1959 rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1960
1962 ret = addrinfo_getnameinfo(1, &vflags, self);
1963 portstr = rb_ary_entry(ret, 1);
1964 rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
1965 return ret;
1966}
1967
1968/*
1969 * call-seq:
1970 * addrinfo.ip_address => string
1971 *
1972 * Returns the IP address as a string.
1973 *
1974 * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
1975 * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
1976 */
1977static VALUE
1978addrinfo_ip_address(VALUE self)
1979{
1980 rb_addrinfo_t *rai = get_addrinfo(self);
1981 int family = ai_get_afamily(rai);
1982 VALUE vflags;
1983 VALUE ret;
1984
1985 if (!IS_IP_FAMILY(family))
1986 rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1987
1989 ret = addrinfo_getnameinfo(1, &vflags, self);
1990 return rb_ary_entry(ret, 0);
1991}
1992
1993/*
1994 * call-seq:
1995 * addrinfo.ip_port => port
1996 *
1997 * Returns the port number as an integer.
1998 *
1999 * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
2000 * Addrinfo.tcp("::1", 80).ip_port #=> 80
2001 */
2002static VALUE
2003addrinfo_ip_port(VALUE self)
2004{
2005 rb_addrinfo_t *rai = get_addrinfo(self);
2006 int family = ai_get_afamily(rai);
2007 int port;
2008
2009 if (!IS_IP_FAMILY(family)) {
2010 bad_family:
2011#ifdef AF_INET6
2012 rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
2013#else
2014 rb_raise(rb_eSocket, "need IPv4 address");
2015#endif
2016 }
2017
2018 switch (family) {
2019 case AF_INET:
2020 if (rai->sockaddr_len != sizeof(struct sockaddr_in))
2021 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
2022 port = ntohs(rai->addr.in.sin_port);
2023 break;
2024
2025#ifdef AF_INET6
2026 case AF_INET6:
2027 if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
2028 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
2029 port = ntohs(rai->addr.in6.sin6_port);
2030 break;
2031#endif
2032
2033 default:
2034 goto bad_family;
2035 }
2036
2037 return INT2NUM(port);
2038}
2039
2040static int
2041extract_in_addr(VALUE self, uint32_t *addrp)
2042{
2043 rb_addrinfo_t *rai = get_addrinfo(self);
2044 int family = ai_get_afamily(rai);
2045 if (family != AF_INET) return 0;
2046 *addrp = ntohl(rai->addr.in.sin_addr.s_addr);
2047 return 1;
2048}
2049
2050/*
2051 * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
2052 * It returns false otherwise.
2053 */
2054static VALUE
2055addrinfo_ipv4_private_p(VALUE self)
2056{
2057 uint32_t a;
2058 if (!extract_in_addr(self, &a)) return Qfalse;
2059 if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
2060 (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
2061 (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
2062 return Qtrue;
2063 return Qfalse;
2064}
2065
2066/*
2067 * Returns true for IPv4 loopback address (127.0.0.0/8).
2068 * It returns false otherwise.
2069 */
2070static VALUE
2071addrinfo_ipv4_loopback_p(VALUE self)
2072{
2073 uint32_t a;
2074 if (!extract_in_addr(self, &a)) return Qfalse;
2075 if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
2076 return Qtrue;
2077 return Qfalse;
2078}
2079
2080/*
2081 * Returns true for IPv4 multicast address (224.0.0.0/4).
2082 * It returns false otherwise.
2083 */
2084static VALUE
2085addrinfo_ipv4_multicast_p(VALUE self)
2086{
2087 uint32_t a;
2088 if (!extract_in_addr(self, &a)) return Qfalse;
2089 if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
2090 return Qtrue;
2091 return Qfalse;
2092}
2093
2094#ifdef INET6
2095
2096static struct in6_addr *
2097extract_in6_addr(VALUE self)
2098{
2099 rb_addrinfo_t *rai = get_addrinfo(self);
2100 int family = ai_get_afamily(rai);
2101 if (family != AF_INET6) return NULL;
2102 return &rai->addr.in6.sin6_addr;
2103}
2104
2105/*
2106 * Returns true for IPv6 unspecified address (::).
2107 * It returns false otherwise.
2108 */
2109static VALUE
2110addrinfo_ipv6_unspecified_p(VALUE self)
2111{
2112 struct in6_addr *addr = extract_in6_addr(self);
2113 if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
2114 return Qfalse;
2115}
2116
2117/*
2118 * Returns true for IPv6 loopback address (::1).
2119 * It returns false otherwise.
2120 */
2121static VALUE
2122addrinfo_ipv6_loopback_p(VALUE self)
2123{
2124 struct in6_addr *addr = extract_in6_addr(self);
2125 if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
2126 return Qfalse;
2127}
2128
2129/*
2130 * Returns true for IPv6 multicast address (ff00::/8).
2131 * It returns false otherwise.
2132 */
2133static VALUE
2134addrinfo_ipv6_multicast_p(VALUE self)
2135{
2136 struct in6_addr *addr = extract_in6_addr(self);
2137 if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
2138 return Qfalse;
2139}
2140
2141/*
2142 * Returns true for IPv6 link local address (ff80::/10).
2143 * It returns false otherwise.
2144 */
2145static VALUE
2146addrinfo_ipv6_linklocal_p(VALUE self)
2147{
2148 struct in6_addr *addr = extract_in6_addr(self);
2149 if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
2150 return Qfalse;
2151}
2152
2153/*
2154 * Returns true for IPv6 site local address (ffc0::/10).
2155 * It returns false otherwise.
2156 */
2157static VALUE
2158addrinfo_ipv6_sitelocal_p(VALUE self)
2159{
2160 struct in6_addr *addr = extract_in6_addr(self);
2161 if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
2162 return Qfalse;
2163}
2164
2165/*
2166 * Returns true for IPv6 unique local address (fc00::/7, RFC4193).
2167 * It returns false otherwise.
2168 */
2169static VALUE
2170addrinfo_ipv6_unique_local_p(VALUE self)
2171{
2172 struct in6_addr *addr = extract_in6_addr(self);
2173 if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue;
2174 return Qfalse;
2175}
2176
2177/*
2178 * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
2179 * It returns false otherwise.
2180 */
2181static VALUE
2182addrinfo_ipv6_v4mapped_p(VALUE self)
2183{
2184 struct in6_addr *addr = extract_in6_addr(self);
2185 if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
2186 return Qfalse;
2187}
2188
2189/*
2190 * Returns true for IPv4-compatible IPv6 address (::/80).
2191 * It returns false otherwise.
2192 */
2193static VALUE
2194addrinfo_ipv6_v4compat_p(VALUE self)
2195{
2196 struct in6_addr *addr = extract_in6_addr(self);
2197 if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
2198 return Qfalse;
2199}
2200
2201/*
2202 * Returns true for IPv6 multicast node-local scope address.
2203 * It returns false otherwise.
2204 */
2205static VALUE
2206addrinfo_ipv6_mc_nodelocal_p(VALUE self)
2207{
2208 struct in6_addr *addr = extract_in6_addr(self);
2209 if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
2210 return Qfalse;
2211}
2212
2213/*
2214 * Returns true for IPv6 multicast link-local scope address.
2215 * It returns false otherwise.
2216 */
2217static VALUE
2218addrinfo_ipv6_mc_linklocal_p(VALUE self)
2219{
2220 struct in6_addr *addr = extract_in6_addr(self);
2221 if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
2222 return Qfalse;
2223}
2224
2225/*
2226 * Returns true for IPv6 multicast site-local scope address.
2227 * It returns false otherwise.
2228 */
2229static VALUE
2230addrinfo_ipv6_mc_sitelocal_p(VALUE self)
2231{
2232 struct in6_addr *addr = extract_in6_addr(self);
2233 if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
2234 return Qfalse;
2235}
2236
2237/*
2238 * Returns true for IPv6 multicast organization-local scope address.
2239 * It returns false otherwise.
2240 */
2241static VALUE
2242addrinfo_ipv6_mc_orglocal_p(VALUE self)
2243{
2244 struct in6_addr *addr = extract_in6_addr(self);
2245 if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
2246 return Qfalse;
2247}
2248
2249/*
2250 * Returns true for IPv6 multicast global scope address.
2251 * It returns false otherwise.
2252 */
2253static VALUE
2254addrinfo_ipv6_mc_global_p(VALUE self)
2255{
2256 struct in6_addr *addr = extract_in6_addr(self);
2257 if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
2258 return Qfalse;
2259}
2260
2261/*
2262 * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
2263 * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
2264 *
2265 * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
2266 * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
2267 * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
2268 * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
2269 * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
2270 */
2271static VALUE
2272addrinfo_ipv6_to_ipv4(VALUE self)
2273{
2274 rb_addrinfo_t *rai = get_addrinfo(self);
2275 struct in6_addr *addr;
2276 int family = ai_get_afamily(rai);
2277 if (family != AF_INET6) return Qnil;
2278 addr = &rai->addr.in6.sin6_addr;
2279 if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
2280 struct sockaddr_in sin4;
2281 INIT_SOCKADDR_IN(&sin4, sizeof(sin4));
2282 memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
2283 return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
2284 PF_INET, rai->socktype, rai->protocol,
2285 rai->canonname, rai->inspectname);
2286 }
2287 else {
2288 return Qnil;
2289 }
2290}
2291
2292#endif
2293
2294#ifdef HAVE_SYS_UN_H
2295/*
2296 * call-seq:
2297 * addrinfo.unix_path => path
2298 *
2299 * Returns the socket path as a string.
2300 *
2301 * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
2302 */
2303static VALUE
2304addrinfo_unix_path(VALUE self)
2305{
2306 rb_addrinfo_t *rai = get_addrinfo(self);
2307 int family = ai_get_afamily(rai);
2308 struct sockaddr_un *addr;
2309 long n;
2310
2311 if (family != AF_UNIX)
2312 rb_raise(rb_eSocket, "need AF_UNIX address");
2313
2314 addr = &rai->addr.un;
2315
2316 n = rai_unixsocket_len(rai);
2317 if (n < 0)
2318 rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.",
2319 (size_t)rai->sockaddr_len, offsetof(struct sockaddr_un, sun_path));
2320 if ((long)sizeof(addr->sun_path) < n)
2322 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
2323 (size_t)n, sizeof(addr->sun_path));
2324 return rb_str_new(addr->sun_path, n);
2325}
2326#endif
2327
2328static ID id_timeout;
2329
2330/*
2331 * call-seq:
2332 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
2333 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
2334 * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
2335 * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
2336 * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
2337 *
2338 * returns a list of addrinfo objects as an array.
2339 *
2340 * This method converts nodename (hostname) and service (port) to addrinfo.
2341 * Since the conversion is not unique, the result is a list of addrinfo objects.
2342 *
2343 * nodename or service can be nil if no conversion intended.
2344 *
2345 * family, socktype and protocol are hint for preferred protocol.
2346 * If the result will be used for a socket with SOCK_STREAM,
2347 * SOCK_STREAM should be specified as socktype.
2348 * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
2349 * If they are omitted or nil is given, the result is not restricted.
2350 *
2351 * Similarly, PF_INET6 as family restricts for IPv6.
2352 *
2353 * flags should be bitwise OR of Socket::AI_??? constants such as follows.
2354 * Note that the exact list of the constants depends on OS.
2355 *
2356 * AI_PASSIVE Get address to use with bind()
2357 * AI_CANONNAME Fill in the canonical name
2358 * AI_NUMERICHOST Prevent host name resolution
2359 * AI_NUMERICSERV Prevent service name resolution
2360 * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses
2361 * AI_ALL Allow all addresses
2362 * AI_ADDRCONFIG Accept only if any address is assigned
2363 *
2364 * Note that socktype should be specified whenever application knows the usage of the address.
2365 * Some platform causes an error when socktype is omitted and servname is specified as an integer
2366 * because some port numbers, 512 for example, are ambiguous without socktype.
2367 *
2368 * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
2369 * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>,
2370 * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>]
2371 *
2372 */
2373static VALUE
2374addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
2375{
2376 VALUE node, service, family, socktype, protocol, flags, opts, timeout;
2377
2378 rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype,
2379 &protocol, &flags, &opts);
2380 rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout);
2381 if (timeout == Qundef) {
2382 timeout = Qnil;
2383 }
2384
2385 return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout);
2386}
2387
2388/*
2389 * call-seq:
2390 * Addrinfo.ip(host) => addrinfo
2391 *
2392 * returns an addrinfo object for IP address.
2393 *
2394 * The port, socktype, protocol of the result is filled by zero.
2395 * So, it is not appropriate to create a socket.
2396 *
2397 * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
2398 */
2399static VALUE
2400addrinfo_s_ip(VALUE self, VALUE host)
2401{
2402 VALUE ret;
2403 rb_addrinfo_t *rai;
2404 ret = addrinfo_firstonly_new(host, Qnil,
2405 INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
2406 rai = get_addrinfo(ret);
2407 rai->socktype = 0;
2408 rai->protocol = 0;
2409 return ret;
2410}
2411
2412/*
2413 * call-seq:
2414 * Addrinfo.tcp(host, port) => addrinfo
2415 *
2416 * returns an addrinfo object for TCP address.
2417 *
2418 * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
2419 */
2420static VALUE
2421addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
2422{
2423 return addrinfo_firstonly_new(host, port,
2424 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
2425}
2426
2427/*
2428 * call-seq:
2429 * Addrinfo.udp(host, port) => addrinfo
2430 *
2431 * returns an addrinfo object for UDP address.
2432 *
2433 * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
2434 */
2435static VALUE
2436addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
2437{
2438 return addrinfo_firstonly_new(host, port,
2439 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
2440}
2441
2442#ifdef HAVE_SYS_UN_H
2443
2444/*
2445 * call-seq:
2446 * Addrinfo.unix(path [, socktype]) => addrinfo
2447 *
2448 * returns an addrinfo object for UNIX socket address.
2449 *
2450 * _socktype_ specifies the socket type.
2451 * If it is omitted, :STREAM is used.
2452 *
2453 * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
2454 * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
2455 */
2456static VALUE
2457addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
2458{
2459 VALUE path, vsocktype, addr;
2460 int socktype;
2461 rb_addrinfo_t *rai;
2462
2463 rb_scan_args(argc, argv, "11", &path, &vsocktype);
2464
2465 if (NIL_P(vsocktype))
2466 socktype = SOCK_STREAM;
2467 else
2468 socktype = rsock_socktype_arg(vsocktype);
2469
2470 addr = addrinfo_s_allocate(rb_cAddrinfo);
2471 DATA_PTR(addr) = rai = alloc_addrinfo();
2472 init_unix_addrinfo(rai, path, socktype);
2473 return addr;
2474}
2475
2476#endif
2477
2478VALUE
2480{
2481 VALUE val = *v;
2482 if (IS_ADDRINFO(val)) {
2483 *v = addrinfo_to_sockaddr(val);
2484 }
2485 StringValue(*v);
2486 return *v;
2487}
2488
2489VALUE
2491{
2492 VALUE val = *v;
2493 *rai_ret = Qnil;
2494 if (IS_ADDRINFO(val)) {
2495 *v = addrinfo_to_sockaddr(val);
2496 *rai_ret = val;
2497 }
2498 StringValue(*v);
2499 return *v;
2500}
2501
2502char *
2504{
2506 return RSTRING_PTR(*v);
2507}
2508
2509VALUE
2511{
2512 if (IS_ADDRINFO(val))
2513 return addrinfo_to_sockaddr(val);
2514 return rb_check_string_type(val);
2515}
2516
2517VALUE
2518rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
2519{
2520 int family;
2521 int socktype;
2522 int ret;
2523 socklen_t optlen = (socklen_t)sizeof(socktype);
2524
2525 /* assumes protocol family and address family are identical */
2526 family = get_afamily(addr, len);
2527
2528 ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
2529 if (ret == -1) {
2530 rb_sys_fail("getsockopt(SO_TYPE)");
2531 }
2532
2533 return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
2534}
2535
2536VALUE
2537rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
2538{
2539 rb_io_t *fptr;
2540
2541 switch (TYPE(io)) {
2542 case T_FIXNUM:
2543 return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
2544
2545 case T_BIGNUM:
2546 return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
2547
2548 case T_FILE:
2549 GetOpenFile(io, fptr);
2550 return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
2551
2552 default:
2553 rb_raise(rb_eTypeError, "neither IO nor file descriptor");
2554 }
2555
2557}
2558
2559/*
2560 * Addrinfo class
2561 */
2562void
2564{
2565 /*
2566 * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
2567 * structure identifies an Internet host and a service.
2568 */
2569 id_timeout = rb_intern("timeout");
2570
2572 rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate);
2573 rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1);
2574 rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0);
2576 rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1);
2577 rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1);
2578 rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2);
2579 rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2);
2580#ifdef HAVE_SYS_UN_H
2581 rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
2582#endif
2583
2584 rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0);
2585 rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0);
2586 rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0);
2587 rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0);
2588 rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0);
2589
2590 rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0);
2591 rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0);
2592 rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0);
2593
2594 rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0);
2595 rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0);
2596 rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0);
2597 rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0);
2598
2599 rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0);
2600 rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0);
2601 rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0);
2602
2603#ifdef INET6
2604 rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
2605 rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
2606 rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
2607 rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
2608 rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
2609 rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0);
2610 rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
2611 rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
2612 rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
2613 rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
2614 rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
2615 rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
2616 rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
2617
2618 rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
2619#endif
2620
2621#ifdef HAVE_SYS_UN_H
2622 rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
2623#endif
2624
2625 rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0);
2626 rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
2627
2628 rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
2629
2630 rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
2631 rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
2632}
#define EAI_NONAME
Definition: addrinfo.h:85
#define AI_NUMERICHOST
Definition: addrinfo.h:98
#define offsetof(p_type, field)
Definition: addrinfo.h:186
#define NI_NUMERICHOST
Definition: addrinfo.h:125
#define getaddrinfo
Definition: addrinfo.h:145
#define AI_NUMERICSERV
Definition: addrinfo.h:99
#define EAI_SYSTEM
Definition: addrinfo.h:88
#define getnameinfo
Definition: addrinfo.h:149
#define NI_DGRAM
Definition: addrinfo.h:128
#define EAI_FAIL
Definition: addrinfo.h:81
#define freeaddrinfo
Definition: addrinfo.h:157
#define NI_MAXHOST
Definition: addrinfo.h:117
#define NI_MAXSERV
Definition: addrinfo.h:118
#define NI_NUMERICSERV
Definition: addrinfo.h:127
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1141
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
VALUE rb_ary_new(void)
Definition: array.c:749
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:988
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1672
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:975
#define UNREACHABLE_RETURN
Definition: assume.h:31
int rsock_family_arg(VALUE domain)
Definition: constants.c:42
int rsock_socktype_arg(VALUE type)
Definition: constants.c:49
int rsock_family_to_int(const char *str, long len, int *valp)
Definition: constdefs.c:4468
int rsock_socktype_to_int(const char *str, long len, int *valp)
Definition: constdefs.c:4863
ID rsock_intern_family(int val)
Definition: constdefs.c:6748
ID rsock_intern_socktype(int val)
Definition: constdefs.c:6775
int rsock_ipproto_to_int(const char *str, long len, int *valp)
Definition: constdefs.c:4934
ID rsock_intern_ipproto(int val)
Definition: constdefs.c:6784
ID rsock_intern_protocol_family(int val)
Definition: constdefs.c:6766
#define ISSPACE
Definition: ctype.h:38
#define STRTOUL
Definition: ctype.h:54
#define ISPRINT
Definition: ctype.h:36
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:668
struct RIMemo * ptr
Definition: debug.c:88
uint8_t len
Definition: escape.c:17
#define numberof(array)
Definition: etc.c:649
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
#define memcpy(d, s, n)
Definition: ffi_common.h:55
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
int socklen_t
Definition: getaddrinfo.c:83
VALUE rb_cInteger
Definition: numeric.c:191
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:748
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2296
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:2085
#define OBJ_FREEZE
Definition: fl_type.h:134
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
VALUE rb_eTypeError
Definition: error.c:1057
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:1024
VALUE rb_eArgError
Definition: error.c:1058
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1148
void rb_sys_fail(const char *mesg)
Definition: error.c:3041
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
Definition: object.c:2930
VALUE rb_cObject
Object class.
Definition: object.c:49
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:724
#define rb_ary_new3
Definition: array.h:73
#define rb_ary_new2
Definition: array.h:72
#define rb_str_new2
Definition: string.h:276
#define rb_str_buf_cat2
Definition: string.h:284
#define rb_str_cat2
Definition: string.h:285
#define rb_str_new(str, len)
Definition: string.h:213
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2962
VALUE rb_check_string_type(VALUE)
Definition: string.c:2462
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:3423
VALUE rb_str_dup(VALUE)
Definition: string.c:1631
#define rb_str_new_cstr(str)
Definition: string.h:219
#define RUBY_UBF_IO
Definition: thread.h:64
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
const char * rb_id2name(ID)
Definition: symbol.c:944
ID rb_intern(const char *)
Definition: symbol.c:785
#define GetOpenFile
Definition: io.h:125
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
void rsock_raise_socket_error(const char *reason, int error)
Definition: init.c:39
VALUE rb_eSocket
Definition: init.c:29
VALUE rb_cAddrinfo
Definition: init.c:27
#define FIX2INT
Definition: int.h:41
#define NUM2UINT
Definition: int.h:45
#define NUM2INT
Definition: int.h:44
#define INT2NUM
Definition: int.h:43
#define PRIuSIZE
Definition: inttypes.h:127
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
voidpf void * buf
Definition: ioapi.h:138
#define INT2FIX
Definition: long.h:48
#define FIX2LONG
Definition: long.h:46
#define MEMCPY(p1, p2, type, n)
Definition: memory.h:129
#define MEMZERO(p, type, n)
Definition: memory.h:128
const int id
Definition: nkf.c:209
const char * name
Definition: nkf.c:208
#define IFNAMSIZ
void rb_freeaddrinfo(struct rb_addrinfo *ai)
Definition: raddrinfo.c:322
VALUE rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname)
Definition: raddrinfo.c:800
#define addrinfo_free
Definition: raddrinfo.c:735
VALUE rsock_sockaddr_string_value(volatile VALUE *v)
Definition: raddrinfo.c:2479
VALUE rsock_freeaddrinfo(VALUE arg)
Definition: raddrinfo.c:698
void rsock_init_addrinfo(void)
Definition: raddrinfo.c:2563
char * rsock_sockaddr_string_value_ptr(volatile VALUE *v)
Definition: raddrinfo.c:2503
struct rb_addrinfo * rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
Definition: raddrinfo.c:502
VALUE rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE(*ipaddr)(struct sockaddr *, socklen_t))
Definition: raddrinfo.c:706
VALUE rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
Definition: raddrinfo.c:396
VALUE rsock_addrinfo_inspect_sockaddr(VALUE self)
Definition: raddrinfo.c:1523
#define str_equal(ptr, len, name)
Definition: raddrinfo.c:429
VALUE rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE ret)
Definition: raddrinfo.c:1148
VALUE rb_check_sockaddr_string_type(VALUE val)
Definition: raddrinfo.c:2510
VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *rai_ret)
Definition: raddrinfo.c:2490
int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct rb_addrinfo **res)
Definition: raddrinfo.c:288
struct rb_addrinfo * rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
Definition: raddrinfo.c:543
VALUE rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
Definition: raddrinfo.c:555
int rsock_fd_family(int fd)
Definition: raddrinfo.c:530
int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
Definition: raddrinfo.c:363
VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2518
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2537
#define IS_ADDRINFO(obj)
Definition: raddrinfo.c:754
#define DATA_PTR(obj)
Definition: rdata.h:56
#define NULL
Definition: regenc.h:69
#define StringValue(v)
Definition: rstring.h:50
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: rstring.h:211
#define StringValueCStr(v)
Definition: rstring.h:52
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: rtypeddata.h:101
const char * rb_obj_classname(VALUE)
Definition: variable.c:308
int argc
Definition: ruby.c:240
char ** argv
Definition: ruby.c:241
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:187
#define SOCKLEN_MAX
Definition: rubysocket.h:154
#define IN6_IS_ADDR_UNIQUE_LOCAL(a)
Definition: rubysocket.h:191
#define RSTRING_SOCKLEN
Definition: rubysocket.h:160
unsigned int uint32_t
Definition: sha2.h:101
#define INADDR_BROADCAST
Definition: constdefs.h:747
#define INADDR_ANY
Definition: constdefs.h:740
#define IPPROTO_TCP
Definition: constdefs.h:610
#define IPPROTO_UDP
Definition: constdefs.h:627
#define PF_INET
Definition: sockport.h:109
#define PF_UNSPEC
Definition: sockport.h:105
#define INIT_SOCKADDR_IN(addr, len)
Definition: sockport.h:47
#define INIT_SOCKADDR_IN6(addr, len)
Definition: sockport.h:56
#define AF_UNSPEC
Definition: sockport.h:101
#define Qundef
#define Qtrue
#define Qnil
#define Qfalse
#define NIL_P
#define FIXNUM_P
VALUE rb_str_catf(VALUE, const char *,...)
Definition: sprintf.c:1243
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
size_t strlen(const char *)
VALUE flags
Definition: debug.c:33
size_t ai_addrlen
Definition: addrinfo.h:136
struct sockaddr * ai_addr
Definition: addrinfo.h:138
char * ai_canonname
Definition: addrinfo.h:137
int ai_socktype
Definition: addrinfo.h:134
int ai_protocol
Definition: addrinfo.h:135
struct addrinfo * ai_next
Definition: addrinfo.h:139
int ai_flags
Definition: addrinfo.h:132
int ai_family
Definition: addrinfo.h:133
const struct addrinfo * hints
Definition: raddrinfo.c:181
const char * service
Definition: raddrinfo.c:180
struct addrinfo ** res
Definition: raddrinfo.c:182
const char * node
Definition: raddrinfo.c:179
size_t servlen
Definition: raddrinfo.c:348
socklen_t salen
Definition: raddrinfo.c:343
size_t hostlen
Definition: raddrinfo.c:346
const struct sockaddr * sa
Definition: raddrinfo.c:342
VALUE(* ipaddr)(struct sockaddr *, socklen_t)
Definition: raddrinfo.c:649
struct rb_addrinfo * addr
Definition: raddrinfo.c:648
VALUE host
Definition: raddrinfo.c:647
union_sockaddr addr
Definition: raddrinfo.c:724
socklen_t sockaddr_len
Definition: raddrinfo.c:723
VALUE canonname
Definition: raddrinfo.c:719
VALUE inspectname
Definition: raddrinfo.c:718
struct addrinfo * ai
Definition: rubysocket.h:313
int allocated_by_malloc
Definition: rubysocket.h:314
Definition: io.h:61
int fd
Definition: io.h:65
#define snprintf
Definition: subst.h:14
struct sockaddr_in in
Definition: rubysocket.h:219
struct sockaddr addr
Definition: rubysocket.h:218
void error(const char *msg)
Definition: untgz.c:593
unsigned long VALUE
Definition: value.h:38
unsigned long ID
Definition: value.h:39
#define TYPE(_)
Definition: value_type.h:105
#define T_FILE
Definition: value_type.h:61
#define T_STRING
Definition: value_type.h:77
#define T_BIGNUM
Definition: value_type.h:56
#define T_FIXNUM
Definition: value_type.h:62
#define T_ARRAY
Definition: value_type.h:55
#define rb_id2str(id)
Definition: vm_backtrace.c:30
#define xfree
Definition: xmalloc.h:49
#define xmalloc
Definition: xmalloc.h:44
#define xcalloc
Definition: xmalloc.h:46
#define ZALLOC(strm, items, size)
Definition: zutil.h:266