Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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