|
Ruby
2.0.0p481(2014-05-08revision45883)
|
00001 /************************************************ 00002 00003 raddrinfo.c - 00004 00005 created at: Thu Mar 31 12:21:29 JST 1994 00006 00007 Copyright (C) 1993-2007 Yukihiro Matsumoto 00008 00009 ************************************************/ 00010 00011 #include "rubysocket.h" 00012 00013 #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6)) 00014 #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0])) 00015 static const int lookup_order_table[] = { 00016 #if defined(LOOKUP_ORDER_HACK_INET) 00017 PF_INET, PF_INET6, PF_UNSPEC, 00018 #elif defined(LOOKUP_ORDER_HACK_INET6) 00019 PF_INET6, PF_INET, PF_UNSPEC, 00020 #else 00021 /* should not happen */ 00022 #endif 00023 }; 00024 00025 static int 00026 ruby_getaddrinfo(const char *nodename, const char *servname, 00027 const struct addrinfo *hints, struct addrinfo **res) 00028 { 00029 struct addrinfo tmp_hints; 00030 int i, af, error; 00031 00032 if (hints->ai_family != PF_UNSPEC) { 00033 return getaddrinfo(nodename, servname, hints, res); 00034 } 00035 00036 for (i = 0; i < LOOKUP_ORDERS; i++) { 00037 af = lookup_order_table[i]; 00038 MEMCPY(&tmp_hints, hints, struct addrinfo, 1); 00039 tmp_hints.ai_family = af; 00040 error = getaddrinfo(nodename, servname, &tmp_hints, res); 00041 if (error) { 00042 if (tmp_hints.ai_family == PF_UNSPEC) { 00043 break; 00044 } 00045 } 00046 else { 00047 break; 00048 } 00049 } 00050 00051 return error; 00052 } 00053 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res)) 00054 #endif 00055 00056 #if defined(_AIX) 00057 static int 00058 ruby_getaddrinfo__aix(const char *nodename, const char *servname, 00059 const struct addrinfo *hints, struct addrinfo **res) 00060 { 00061 int error = getaddrinfo(nodename, servname, hints, res); 00062 struct addrinfo *r; 00063 if (error) 00064 return error; 00065 for (r = *res; r != NULL; r = r->ai_next) { 00066 if (r->ai_addr->sa_family == 0) 00067 r->ai_addr->sa_family = r->ai_family; 00068 if (r->ai_addr->sa_len == 0) 00069 r->ai_addr->sa_len = r->ai_addrlen; 00070 } 00071 return 0; 00072 } 00073 #undef getaddrinfo 00074 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res)) 00075 static int 00076 ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen, 00077 char *host, size_t hostlen, 00078 char *serv, size_t servlen, int flags) 00079 { 00080 struct sockaddr_in6 *sa6; 00081 u_int32_t *a6; 00082 00083 if (sa->sa_family == AF_INET6) { 00084 sa6 = (struct sockaddr_in6 *)sa; 00085 a6 = sa6->sin6_addr.u6_addr.u6_addr32; 00086 00087 if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { 00088 strncpy(host, "::", hostlen); 00089 snprintf(serv, servlen, "%d", sa6->sin6_port); 00090 return 0; 00091 } 00092 } 00093 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); 00094 } 00095 #undef getnameinfo 00096 #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \ 00097 ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags)) 00098 #endif 00099 00100 static int str_is_number(const char *); 00101 00102 #if defined(__APPLE__) 00103 static int 00104 ruby_getaddrinfo__darwin(const char *nodename, const char *servname, 00105 const struct addrinfo *hints, struct addrinfo **res) 00106 { 00107 /* fix [ruby-core:29427] */ 00108 const char *tmp_servname; 00109 struct addrinfo tmp_hints; 00110 int error; 00111 00112 tmp_servname = servname; 00113 MEMCPY(&tmp_hints, hints, struct addrinfo, 1); 00114 if (nodename && servname) { 00115 if (str_is_number(tmp_servname) && atoi(servname) == 0) { 00116 tmp_servname = NULL; 00117 #ifdef AI_NUMERICSERV 00118 if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV; 00119 #endif 00120 } 00121 } 00122 00123 error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res); 00124 if (error == 0) { 00125 /* [ruby-dev:23164] */ 00126 struct addrinfo *r; 00127 r = *res; 00128 while (r) { 00129 if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype; 00130 if (! r->ai_protocol) { 00131 if (r->ai_socktype == SOCK_DGRAM) { 00132 r->ai_protocol = IPPROTO_UDP; 00133 } 00134 else if (r->ai_socktype == SOCK_STREAM) { 00135 r->ai_protocol = IPPROTO_TCP; 00136 } 00137 } 00138 r = r->ai_next; 00139 } 00140 } 00141 00142 return error; 00143 } 00144 #undef getaddrinfo 00145 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res)) 00146 #endif 00147 00148 #ifndef GETADDRINFO_EMU 00149 struct getaddrinfo_arg 00150 { 00151 const char *node; 00152 const char *service; 00153 const struct addrinfo *hints; 00154 struct addrinfo **res; 00155 }; 00156 00157 static void * 00158 nogvl_getaddrinfo(void *arg) 00159 { 00160 int ret; 00161 struct getaddrinfo_arg *ptr = arg; 00162 ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res); 00163 #ifdef __linux__ 00164 /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and 00165 * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] 00166 */ 00167 if (ret == EAI_SYSTEM && errno == ENOENT) 00168 ret = EAI_NONAME; 00169 #endif 00170 return (void *)(VALUE)ret; 00171 } 00172 #endif 00173 00174 int 00175 rb_getaddrinfo(const char *node, const char *service, 00176 const struct addrinfo *hints, 00177 struct addrinfo **res) 00178 { 00179 #ifdef GETADDRINFO_EMU 00180 return getaddrinfo(node, service, hints, res); 00181 #else 00182 struct getaddrinfo_arg arg; 00183 int ret; 00184 MEMZERO(&arg, sizeof arg, 1); 00185 arg.node = node; 00186 arg.service = service; 00187 arg.hints = hints; 00188 arg.res = res; 00189 ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); 00190 return ret; 00191 #endif 00192 } 00193 00194 #ifndef GETADDRINFO_EMU 00195 struct getnameinfo_arg 00196 { 00197 const struct sockaddr *sa; 00198 socklen_t salen; 00199 char *host; 00200 size_t hostlen; 00201 char *serv; 00202 size_t servlen; 00203 int flags; 00204 }; 00205 00206 static void * 00207 nogvl_getnameinfo(void *arg) 00208 { 00209 struct getnameinfo_arg *ptr = arg; 00210 return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen, 00211 ptr->host, (socklen_t)ptr->hostlen, 00212 ptr->serv, (socklen_t)ptr->servlen, 00213 ptr->flags); 00214 } 00215 #endif 00216 00217 int 00218 rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, 00219 char *host, size_t hostlen, 00220 char *serv, size_t servlen, int flags) 00221 { 00222 #ifdef GETADDRINFO_EMU 00223 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); 00224 #else 00225 struct getnameinfo_arg arg; 00226 int ret; 00227 arg.sa = sa; 00228 arg.salen = salen; 00229 arg.host = host; 00230 arg.hostlen = hostlen; 00231 arg.serv = serv; 00232 arg.servlen = servlen; 00233 arg.flags = flags; 00234 ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0); 00235 return ret; 00236 #endif 00237 } 00238 00239 static void 00240 make_ipaddr0(struct sockaddr *addr, char *buf, size_t len) 00241 { 00242 int error; 00243 00244 error = rb_getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST); 00245 if (error) { 00246 rsock_raise_socket_error("getnameinfo", error); 00247 } 00248 } 00249 00250 VALUE 00251 rsock_make_ipaddr(struct sockaddr *addr) 00252 { 00253 char hbuf[1024]; 00254 00255 make_ipaddr0(addr, hbuf, sizeof(hbuf)); 00256 return rb_str_new2(hbuf); 00257 } 00258 00259 static void 00260 make_inetaddr(unsigned int host, char *buf, size_t len) 00261 { 00262 struct sockaddr_in sin; 00263 00264 MEMZERO(&sin, struct sockaddr_in, 1); 00265 sin.sin_family = AF_INET; 00266 SET_SIN_LEN(&sin, sizeof(sin)); 00267 sin.sin_addr.s_addr = host; 00268 make_ipaddr0((struct sockaddr*)&sin, buf, len); 00269 } 00270 00271 static int 00272 str_is_number(const char *p) 00273 { 00274 char *ep; 00275 00276 if (!p || *p == '\0') 00277 return 0; 00278 ep = NULL; 00279 (void)STRTOUL(p, &ep, 10); 00280 if (ep && *ep == '\0') 00281 return 1; 00282 else 00283 return 0; 00284 } 00285 00286 static char* 00287 host_str(VALUE host, char *hbuf, size_t len, int *flags_ptr) 00288 { 00289 if (NIL_P(host)) { 00290 return NULL; 00291 } 00292 else if (rb_obj_is_kind_of(host, rb_cInteger)) { 00293 unsigned int i = NUM2UINT(host); 00294 00295 make_inetaddr(htonl(i), hbuf, len); 00296 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST; 00297 return hbuf; 00298 } 00299 else { 00300 char *name; 00301 00302 SafeStringValue(host); 00303 name = RSTRING_PTR(host); 00304 if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) { 00305 make_inetaddr(INADDR_ANY, hbuf, len); 00306 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST; 00307 } 00308 else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) { 00309 make_inetaddr(INADDR_BROADCAST, hbuf, len); 00310 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST; 00311 } 00312 else if (strlen(name) >= len) { 00313 rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")", 00314 strlen(name)); 00315 } 00316 else { 00317 strcpy(hbuf, name); 00318 } 00319 return hbuf; 00320 } 00321 } 00322 00323 static char* 00324 port_str(VALUE port, char *pbuf, size_t len, int *flags_ptr) 00325 { 00326 if (NIL_P(port)) { 00327 return 0; 00328 } 00329 else if (FIXNUM_P(port)) { 00330 snprintf(pbuf, len, "%ld", FIX2LONG(port)); 00331 #ifdef AI_NUMERICSERV 00332 if (flags_ptr) *flags_ptr |= AI_NUMERICSERV; 00333 #endif 00334 return pbuf; 00335 } 00336 else { 00337 char *serv; 00338 00339 SafeStringValue(port); 00340 serv = RSTRING_PTR(port); 00341 if (strlen(serv) >= len) { 00342 rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")", 00343 strlen(serv)); 00344 } 00345 strcpy(pbuf, serv); 00346 return pbuf; 00347 } 00348 } 00349 00350 struct addrinfo* 00351 rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack) 00352 { 00353 struct addrinfo* res = NULL; 00354 char *hostp, *portp; 00355 int error; 00356 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 00357 int additional_flags = 0; 00358 00359 hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags); 00360 portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags); 00361 00362 if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) { 00363 hints->ai_socktype = SOCK_DGRAM; 00364 } 00365 hints->ai_flags |= additional_flags; 00366 00367 error = rb_getaddrinfo(hostp, portp, hints, &res); 00368 if (error) { 00369 if (hostp && hostp[strlen(hostp)-1] == '\n') { 00370 rb_raise(rb_eSocket, "newline at the end of hostname"); 00371 } 00372 rsock_raise_socket_error("getaddrinfo", error); 00373 } 00374 00375 return res; 00376 } 00377 00378 struct addrinfo* 00379 rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags) 00380 { 00381 struct addrinfo hints; 00382 00383 MEMZERO(&hints, struct addrinfo, 1); 00384 hints.ai_family = AF_UNSPEC; 00385 hints.ai_socktype = socktype; 00386 hints.ai_flags = flags; 00387 return rsock_getaddrinfo(host, port, &hints, 1); 00388 } 00389 00390 VALUE 00391 rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup) 00392 { 00393 VALUE family, port, addr1, addr2; 00394 VALUE ary; 00395 int error; 00396 char hbuf[1024], pbuf[1024]; 00397 ID id; 00398 00399 id = rsock_intern_family(sockaddr->sa_family); 00400 if (id) { 00401 family = rb_str_dup(rb_id2str(id)); 00402 } 00403 else { 00404 sprintf(pbuf, "unknown:%d", sockaddr->sa_family); 00405 family = rb_str_new2(pbuf); 00406 } 00407 00408 addr1 = Qnil; 00409 if (!norevlookup) { 00410 error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf), 00411 NULL, 0, 0); 00412 if (! error) { 00413 addr1 = rb_str_new2(hbuf); 00414 } 00415 } 00416 error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf), 00417 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV); 00418 if (error) { 00419 rsock_raise_socket_error("getnameinfo", error); 00420 } 00421 addr2 = rb_str_new2(hbuf); 00422 if (addr1 == Qnil) { 00423 addr1 = addr2; 00424 } 00425 port = INT2FIX(atoi(pbuf)); 00426 ary = rb_ary_new3(4, family, port, addr1, addr2); 00427 00428 return ary; 00429 } 00430 00431 #ifdef HAVE_SYS_UN_H 00432 VALUE 00433 rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len) 00434 { 00435 char *s, *e; 00436 s = sockaddr->sun_path; 00437 e = (char *)sockaddr + len; 00438 while (s < e && *(e-1) == '\0') 00439 e--; 00440 if (s <= e) 00441 return rb_str_new(s, e-s); 00442 else 00443 return rb_str_new2(""); 00444 } 00445 00446 VALUE 00447 rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len) 00448 { 00449 return rb_assoc_new(rb_str_new2("AF_UNIX"), 00450 rsock_unixpath_str(sockaddr, len)); 00451 } 00452 00453 socklen_t 00454 rsock_unix_sockaddr_len(VALUE path) 00455 { 00456 #ifdef __linux__ 00457 if (RSTRING_LEN(path) == 0) { 00458 /* autobind; see unix(7) for details. */ 00459 return (socklen_t) sizeof(sa_family_t); 00460 } 00461 else if (RSTRING_PTR(path)[0] == '\0') { 00462 /* abstract namespace; see unix(7) for details. */ 00463 return (socklen_t) offsetof(struct sockaddr_un, sun_path) + 00464 RSTRING_LEN(path); 00465 } 00466 else { 00467 #endif 00468 return (socklen_t) sizeof(struct sockaddr_un); 00469 #ifdef __linux__ 00470 } 00471 #endif 00472 } 00473 #endif 00474 00475 struct hostent_arg { 00476 VALUE host; 00477 struct addrinfo* addr; 00478 VALUE (*ipaddr)(struct sockaddr*, size_t); 00479 }; 00480 00481 static VALUE 00482 make_hostent_internal(struct hostent_arg *arg) 00483 { 00484 VALUE host = arg->host; 00485 struct addrinfo* addr = arg->addr; 00486 VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr; 00487 00488 struct addrinfo *ai; 00489 struct hostent *h; 00490 VALUE ary, names; 00491 char **pch; 00492 const char* hostp; 00493 char hbuf[NI_MAXHOST]; 00494 00495 ary = rb_ary_new(); 00496 if (addr->ai_canonname) { 00497 hostp = addr->ai_canonname; 00498 } 00499 else { 00500 hostp = host_str(host, hbuf, sizeof(hbuf), NULL); 00501 } 00502 rb_ary_push(ary, rb_str_new2(hostp)); 00503 00504 if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) { 00505 names = rb_ary_new(); 00506 if (h->h_aliases != NULL) { 00507 for (pch = h->h_aliases; *pch; pch++) { 00508 rb_ary_push(names, rb_str_new2(*pch)); 00509 } 00510 } 00511 } 00512 else { 00513 names = rb_ary_new2(0); 00514 } 00515 rb_ary_push(ary, names); 00516 rb_ary_push(ary, INT2NUM(addr->ai_family)); 00517 for (ai = addr; ai; ai = ai->ai_next) { 00518 rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen)); 00519 } 00520 00521 return ary; 00522 } 00523 00524 VALUE 00525 rsock_freeaddrinfo(struct addrinfo *addr) 00526 { 00527 freeaddrinfo(addr); 00528 return Qnil; 00529 } 00530 00531 VALUE 00532 rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t)) 00533 { 00534 struct hostent_arg arg; 00535 00536 arg.host = host; 00537 arg.addr = addr; 00538 arg.ipaddr = ipaddr; 00539 return rb_ensure(make_hostent_internal, (VALUE)&arg, 00540 rsock_freeaddrinfo, (VALUE)addr); 00541 } 00542 00543 typedef struct { 00544 VALUE inspectname; 00545 VALUE canonname; 00546 int pfamily; 00547 int socktype; 00548 int protocol; 00549 socklen_t sockaddr_len; 00550 struct sockaddr_storage addr; 00551 } rb_addrinfo_t; 00552 00553 static void 00554 addrinfo_mark(void *ptr) 00555 { 00556 rb_addrinfo_t *rai = ptr; 00557 if (rai) { 00558 rb_gc_mark(rai->inspectname); 00559 rb_gc_mark(rai->canonname); 00560 } 00561 } 00562 00563 #define addrinfo_free RUBY_TYPED_DEFAULT_FREE 00564 00565 static size_t 00566 addrinfo_memsize(const void *ptr) 00567 { 00568 return ptr ? sizeof(rb_addrinfo_t) : 0; 00569 } 00570 00571 static const rb_data_type_t addrinfo_type = { 00572 "socket/addrinfo", 00573 {addrinfo_mark, addrinfo_free, addrinfo_memsize,}, 00574 }; 00575 00576 static VALUE 00577 addrinfo_s_allocate(VALUE klass) 00578 { 00579 return TypedData_Wrap_Struct(klass, &addrinfo_type, 0); 00580 } 00581 00582 #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type) 00583 static inline rb_addrinfo_t * 00584 check_addrinfo(VALUE self) 00585 { 00586 return rb_check_typeddata(self, &addrinfo_type); 00587 } 00588 00589 static rb_addrinfo_t * 00590 get_addrinfo(VALUE self) 00591 { 00592 rb_addrinfo_t *rai = check_addrinfo(self); 00593 00594 if (!rai) { 00595 rb_raise(rb_eTypeError, "uninitialized socket address"); 00596 } 00597 return rai; 00598 } 00599 00600 00601 static rb_addrinfo_t * 00602 alloc_addrinfo() 00603 { 00604 rb_addrinfo_t *rai = ALLOC(rb_addrinfo_t); 00605 memset(rai, 0, sizeof(rb_addrinfo_t)); 00606 rai->inspectname = Qnil; 00607 rai->canonname = Qnil; 00608 return rai; 00609 } 00610 00611 static void 00612 init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len, 00613 int pfamily, int socktype, int protocol, 00614 VALUE canonname, VALUE inspectname) 00615 { 00616 if ((socklen_t)sizeof(rai->addr) < len) 00617 rb_raise(rb_eArgError, "sockaddr string too big"); 00618 memcpy((void *)&rai->addr, (void *)sa, len); 00619 rai->sockaddr_len = len; 00620 00621 rai->pfamily = pfamily; 00622 rai->socktype = socktype; 00623 rai->protocol = protocol; 00624 rai->canonname = canonname; 00625 rai->inspectname = inspectname; 00626 } 00627 00628 VALUE 00629 rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, 00630 int family, int socktype, int protocol, 00631 VALUE canonname, VALUE inspectname) 00632 { 00633 VALUE a; 00634 rb_addrinfo_t *rai; 00635 00636 a = addrinfo_s_allocate(rb_cAddrinfo); 00637 DATA_PTR(a) = rai = alloc_addrinfo(); 00638 init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname); 00639 return a; 00640 } 00641 00642 static struct addrinfo * 00643 call_getaddrinfo(VALUE node, VALUE service, 00644 VALUE family, VALUE socktype, VALUE protocol, VALUE flags, 00645 int socktype_hack) 00646 { 00647 struct addrinfo hints, *res; 00648 00649 MEMZERO(&hints, struct addrinfo, 1); 00650 hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family); 00651 00652 if (!NIL_P(socktype)) { 00653 hints.ai_socktype = rsock_socktype_arg(socktype); 00654 } 00655 if (!NIL_P(protocol)) { 00656 hints.ai_protocol = NUM2INT(protocol); 00657 } 00658 if (!NIL_P(flags)) { 00659 hints.ai_flags = NUM2INT(flags); 00660 } 00661 res = rsock_getaddrinfo(node, service, &hints, socktype_hack); 00662 00663 if (res == NULL) 00664 rb_raise(rb_eSocket, "host not found"); 00665 return res; 00666 } 00667 00668 static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res); 00669 00670 static void 00671 init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service, 00672 VALUE family, VALUE socktype, VALUE protocol, VALUE flags, 00673 VALUE inspectnode, VALUE inspectservice) 00674 { 00675 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1); 00676 VALUE canonname; 00677 VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res); 00678 00679 canonname = Qnil; 00680 if (res->ai_canonname) { 00681 canonname = rb_tainted_str_new_cstr(res->ai_canonname); 00682 OBJ_FREEZE(canonname); 00683 } 00684 00685 init_addrinfo(rai, res->ai_addr, res->ai_addrlen, 00686 NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol), 00687 canonname, inspectname); 00688 00689 freeaddrinfo(res); 00690 } 00691 00692 static VALUE 00693 make_inspectname(VALUE node, VALUE service, struct addrinfo *res) 00694 { 00695 VALUE inspectname = Qnil; 00696 00697 if (res) { 00698 /* drop redundant information which also shown in address:port part. */ 00699 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 00700 int ret; 00701 ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 00702 sizeof(hbuf), pbuf, sizeof(pbuf), 00703 NI_NUMERICHOST|NI_NUMERICSERV); 00704 if (ret == 0) { 00705 if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0) 00706 node = Qnil; 00707 if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0) 00708 service = Qnil; 00709 else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service)) 00710 service = Qnil; 00711 } 00712 } 00713 00714 if (RB_TYPE_P(node, T_STRING)) { 00715 inspectname = rb_str_dup(node); 00716 } 00717 if (RB_TYPE_P(service, T_STRING)) { 00718 if (NIL_P(inspectname)) 00719 inspectname = rb_sprintf(":%s", StringValueCStr(service)); 00720 else 00721 rb_str_catf(inspectname, ":%s", StringValueCStr(service)); 00722 } 00723 else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0) 00724 { 00725 if (NIL_P(inspectname)) 00726 inspectname = rb_sprintf(":%d", FIX2INT(service)); 00727 else 00728 rb_str_catf(inspectname, ":%d", FIX2INT(service)); 00729 } 00730 if (!NIL_P(inspectname)) { 00731 OBJ_INFECT(inspectname, node); 00732 OBJ_INFECT(inspectname, service); 00733 OBJ_FREEZE(inspectname); 00734 } 00735 return inspectname; 00736 } 00737 00738 static VALUE 00739 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00740 { 00741 VALUE ret; 00742 VALUE canonname; 00743 VALUE inspectname; 00744 00745 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00746 00747 inspectname = make_inspectname(node, service, res); 00748 00749 canonname = Qnil; 00750 if (res->ai_canonname) { 00751 canonname = rb_tainted_str_new_cstr(res->ai_canonname); 00752 OBJ_FREEZE(canonname); 00753 } 00754 00755 ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen, 00756 res->ai_family, res->ai_socktype, res->ai_protocol, 00757 canonname, inspectname); 00758 00759 freeaddrinfo(res); 00760 return ret; 00761 } 00762 00763 static VALUE 00764 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00765 { 00766 VALUE ret; 00767 struct addrinfo *r; 00768 VALUE inspectname; 00769 00770 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00771 00772 inspectname = make_inspectname(node, service, res); 00773 00774 ret = rb_ary_new(); 00775 for (r = res; r; r = r->ai_next) { 00776 VALUE addr; 00777 VALUE canonname = Qnil; 00778 00779 if (r->ai_canonname) { 00780 canonname = rb_tainted_str_new_cstr(r->ai_canonname); 00781 OBJ_FREEZE(canonname); 00782 } 00783 00784 addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen, 00785 r->ai_family, r->ai_socktype, r->ai_protocol, 00786 canonname, inspectname); 00787 00788 rb_ary_push(ret, addr); 00789 } 00790 00791 freeaddrinfo(res); 00792 return ret; 00793 } 00794 00795 00796 #ifdef HAVE_SYS_UN_H 00797 static void 00798 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) 00799 { 00800 struct sockaddr_un un; 00801 socklen_t len; 00802 00803 StringValue(path); 00804 00805 if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path)) 00806 rb_raise(rb_eArgError, 00807 "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 00808 (size_t)RSTRING_LEN(path), sizeof(un.sun_path)); 00809 00810 MEMZERO(&un, struct sockaddr_un, 1); 00811 00812 un.sun_family = AF_UNIX; 00813 memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); 00814 00815 len = rsock_unix_sockaddr_len(path); 00816 init_addrinfo(rai, (struct sockaddr *)&un, len, 00817 PF_UNIX, socktype, 0, Qnil, Qnil); 00818 } 00819 #endif 00820 00821 /* 00822 * call-seq: 00823 * Addrinfo.new(sockaddr) => addrinfo 00824 * Addrinfo.new(sockaddr, family) => addrinfo 00825 * Addrinfo.new(sockaddr, family, socktype) => addrinfo 00826 * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo 00827 * 00828 * returns a new instance of Addrinfo. 00829 * The instance contains sockaddr, family, socktype, protocol. 00830 * sockaddr means struct sockaddr which can be used for connect(2), etc. 00831 * family, socktype and protocol are integers which is used for arguments of socket(2). 00832 * 00833 * sockaddr is specified as an array or a string. 00834 * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr. 00835 * The string should be struct sockaddr as generated by 00836 * Socket.sockaddr_in or Socket.unpack_sockaddr_un. 00837 * 00838 * sockaddr examples: 00839 * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] 00840 * - ["AF_INET6", 42304, "ip6-localhost", "::1"] 00841 * - ["AF_UNIX", "/tmp/sock"] 00842 * - Socket.sockaddr_in("smtp", "2001:DB8::1") 00843 * - Socket.sockaddr_in(80, "172.18.22.42") 00844 * - Socket.sockaddr_in(80, "www.ruby-lang.org") 00845 * - Socket.sockaddr_un("/tmp/sock") 00846 * 00847 * In an AF_INET/AF_INET6 sockaddr array, the 4th element, 00848 * numeric IP address, is used to construct socket address in the Addrinfo instance. 00849 * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect. 00850 * 00851 * family is specified as an integer to specify the protocol family such as Socket::PF_INET. 00852 * It can be a symbol or a string which is the constant name 00853 * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc. 00854 * If omitted, PF_UNSPEC is assumed. 00855 * 00856 * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM. 00857 * It can be a symbol or a string which is the constant name 00858 * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc. 00859 * If omitted, 0 is assumed. 00860 * 00861 * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP. 00862 * It must be an integer, unlike family and socktype. 00863 * If omitted, 0 is assumed. 00864 * Note that 0 is reasonable value for most protocols, except raw socket. 00865 * 00866 */ 00867 static VALUE 00868 addrinfo_initialize(int argc, VALUE *argv, VALUE self) 00869 { 00870 rb_addrinfo_t *rai; 00871 VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol; 00872 int i_pfamily, i_socktype, i_protocol; 00873 struct sockaddr *sockaddr_ptr; 00874 socklen_t sockaddr_len; 00875 VALUE canonname = Qnil, inspectname = Qnil; 00876 00877 if (check_addrinfo(self)) 00878 rb_raise(rb_eTypeError, "already initialized socket address"); 00879 DATA_PTR(self) = rai = alloc_addrinfo(); 00880 00881 rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol); 00882 00883 i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily); 00884 i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype); 00885 i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol); 00886 00887 sockaddr_ary = rb_check_array_type(sockaddr_arg); 00888 if (!NIL_P(sockaddr_ary)) { 00889 VALUE afamily = rb_ary_entry(sockaddr_ary, 0); 00890 int af; 00891 StringValue(afamily); 00892 if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1) 00893 rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily)); 00894 switch (af) { 00895 case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */ 00896 #ifdef INET6 00897 case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */ 00898 #endif 00899 { 00900 VALUE service = rb_ary_entry(sockaddr_ary, 1); 00901 VALUE nodename = rb_ary_entry(sockaddr_ary, 2); 00902 VALUE numericnode = rb_ary_entry(sockaddr_ary, 3); 00903 int flags; 00904 00905 service = INT2NUM(NUM2INT(service)); 00906 if (!NIL_P(nodename)) 00907 StringValue(nodename); 00908 StringValue(numericnode); 00909 flags = AI_NUMERICHOST; 00910 #ifdef AI_NUMERICSERV 00911 flags |= AI_NUMERICSERV; 00912 #endif 00913 00914 init_addrinfo_getaddrinfo(rai, numericnode, service, 00915 INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol), 00916 INT2NUM(flags), 00917 nodename, service); 00918 break; 00919 } 00920 00921 #ifdef HAVE_SYS_UN_H 00922 case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */ 00923 { 00924 VALUE path = rb_ary_entry(sockaddr_ary, 1); 00925 StringValue(path); 00926 init_unix_addrinfo(rai, path, SOCK_STREAM); 00927 break; 00928 } 00929 #endif 00930 00931 default: 00932 rb_raise(rb_eSocket, "unexpected address family"); 00933 } 00934 } 00935 else { 00936 StringValue(sockaddr_arg); 00937 sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg); 00938 sockaddr_len = RSTRING_LENINT(sockaddr_arg); 00939 init_addrinfo(rai, sockaddr_ptr, sockaddr_len, 00940 i_pfamily, i_socktype, i_protocol, 00941 canonname, inspectname); 00942 } 00943 00944 return self; 00945 } 00946 00947 static int 00948 get_afamily(struct sockaddr *addr, socklen_t len) 00949 { 00950 if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len) 00951 return addr->sa_family; 00952 else 00953 return AF_UNSPEC; 00954 } 00955 00956 static int 00957 ai_get_afamily(rb_addrinfo_t *rai) 00958 { 00959 return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len); 00960 } 00961 00962 static VALUE 00963 inspect_sockaddr(VALUE addrinfo, VALUE ret) 00964 { 00965 rb_addrinfo_t *rai = get_addrinfo(addrinfo); 00966 00967 if (rai->sockaddr_len == 0) { 00968 rb_str_cat2(ret, "empty-sockaddr"); 00969 } 00970 else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr) 00971 rb_str_cat2(ret, "too-short-sockaddr"); 00972 else { 00973 switch (rai->addr.ss_family) { 00974 case AF_INET: 00975 { 00976 struct sockaddr_in *addr; 00977 int port; 00978 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) { 00979 rb_str_cat2(ret, "too-short-AF_INET-sockaddr"); 00980 } 00981 else { 00982 addr = (struct sockaddr_in *)&rai->addr; 00983 rb_str_catf(ret, "%d.%d.%d.%d", 00984 ((unsigned char*)&addr->sin_addr)[0], 00985 ((unsigned char*)&addr->sin_addr)[1], 00986 ((unsigned char*)&addr->sin_addr)[2], 00987 ((unsigned char*)&addr->sin_addr)[3]); 00988 port = ntohs(addr->sin_port); 00989 if (port) 00990 rb_str_catf(ret, ":%d", port); 00991 if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len) 00992 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in))); 00993 } 00994 break; 00995 } 00996 00997 #ifdef AF_INET6 00998 case AF_INET6: 00999 { 01000 struct sockaddr_in6 *addr; 01001 char hbuf[1024]; 01002 int port; 01003 int error; 01004 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) { 01005 rb_str_cat2(ret, "too-short-AF_INET6-sockaddr"); 01006 } 01007 else { 01008 addr = (struct sockaddr_in6 *)&rai->addr; 01009 /* use getnameinfo for scope_id. 01010 * RFC 4007: IPv6 Scoped Address Architecture 01011 * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API 01012 */ 01013 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01014 hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 01015 NI_NUMERICHOST|NI_NUMERICSERV); 01016 if (error) { 01017 rsock_raise_socket_error("getnameinfo", error); 01018 } 01019 if (addr->sin6_port == 0) { 01020 rb_str_cat2(ret, hbuf); 01021 } 01022 else { 01023 port = ntohs(addr->sin6_port); 01024 rb_str_catf(ret, "[%s]:%d", hbuf, port); 01025 } 01026 if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len) 01027 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6))); 01028 } 01029 break; 01030 } 01031 #endif 01032 01033 #ifdef HAVE_SYS_UN_H 01034 case AF_UNIX: 01035 { 01036 struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr; 01037 char *p, *s, *e; 01038 s = addr->sun_path; 01039 e = (char*)addr + rai->sockaddr_len; 01040 while (s < e && *(e-1) == '\0') 01041 e--; 01042 if (e < s) 01043 rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr"); 01044 else if (s == e) 01045 rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr"); 01046 else { 01047 int printable_only = 1; 01048 p = s; 01049 while (p < e) { 01050 printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p); 01051 p++; 01052 } 01053 if (printable_only) { /* only printable, no space */ 01054 if (s[0] != '/') /* relative path */ 01055 rb_str_cat2(ret, "AF_UNIX "); 01056 rb_str_cat(ret, s, p - s); 01057 } 01058 else { 01059 rb_str_cat2(ret, "AF_UNIX"); 01060 while (s < e) 01061 rb_str_catf(ret, ":%02x", (unsigned char)*s++); 01062 } 01063 if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len) 01064 rb_str_catf(ret, "(sockaddr %d bytes too long)", 01065 (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr))); 01066 } 01067 break; 01068 } 01069 #endif 01070 01071 default: 01072 { 01073 ID id = rsock_intern_family(rai->addr.ss_family); 01074 if (id == 0) 01075 rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family); 01076 else 01077 rb_str_catf(ret, "%s address format unknown", rb_id2name(id)); 01078 break; 01079 } 01080 } 01081 } 01082 01083 return ret; 01084 } 01085 01086 /* 01087 * call-seq: 01088 * addrinfo.inspect => string 01089 * 01090 * returns a string which shows addrinfo in human-readable form. 01091 * 01092 * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>" 01093 * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>" 01094 * 01095 */ 01096 static VALUE 01097 addrinfo_inspect(VALUE self) 01098 { 01099 rb_addrinfo_t *rai = get_addrinfo(self); 01100 int internet_p; 01101 VALUE ret; 01102 01103 ret = rb_sprintf("#<%s: ", rb_obj_classname(self)); 01104 01105 inspect_sockaddr(self, ret); 01106 01107 if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) { 01108 ID id = rsock_intern_protocol_family(rai->pfamily); 01109 if (id) 01110 rb_str_catf(ret, " %s", rb_id2name(id)); 01111 else 01112 rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily); 01113 } 01114 01115 internet_p = rai->pfamily == PF_INET; 01116 #ifdef INET6 01117 internet_p = internet_p || rai->pfamily == PF_INET6; 01118 #endif 01119 if (internet_p && rai->socktype == SOCK_STREAM && 01120 (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) { 01121 rb_str_cat2(ret, " TCP"); 01122 } 01123 else if (internet_p && rai->socktype == SOCK_DGRAM && 01124 (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) { 01125 rb_str_cat2(ret, " UDP"); 01126 } 01127 else { 01128 if (rai->socktype) { 01129 ID id = rsock_intern_socktype(rai->socktype); 01130 if (id) 01131 rb_str_catf(ret, " %s", rb_id2name(id)); 01132 else 01133 rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype); 01134 } 01135 01136 if (rai->protocol) { 01137 if (internet_p) { 01138 ID id = rsock_intern_ipproto(rai->protocol); 01139 if (id) 01140 rb_str_catf(ret, " %s", rb_id2name(id)); 01141 else 01142 goto unknown_protocol; 01143 } 01144 else { 01145 unknown_protocol: 01146 rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol); 01147 } 01148 } 01149 } 01150 01151 if (!NIL_P(rai->canonname)) { 01152 VALUE name = rai->canonname; 01153 rb_str_catf(ret, " %s", StringValueCStr(name)); 01154 } 01155 01156 if (!NIL_P(rai->inspectname)) { 01157 VALUE name = rai->inspectname; 01158 rb_str_catf(ret, " (%s)", StringValueCStr(name)); 01159 } 01160 01161 rb_str_buf_cat2(ret, ">"); 01162 return ret; 01163 } 01164 01165 /* 01166 * call-seq: 01167 * addrinfo.inspect_sockaddr => string 01168 * 01169 * returns a string which shows the sockaddr in _addrinfo_ with human-readable form. 01170 * 01171 * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80" 01172 * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80" 01173 * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock" 01174 * 01175 */ 01176 static VALUE 01177 addrinfo_inspect_sockaddr(VALUE self) 01178 { 01179 return inspect_sockaddr(self, rb_str_new("", 0)); 01180 } 01181 01182 /* :nodoc: */ 01183 static VALUE 01184 addrinfo_mdump(VALUE self) 01185 { 01186 rb_addrinfo_t *rai = get_addrinfo(self); 01187 VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname; 01188 int afamily_int = ai_get_afamily(rai); 01189 ID id; 01190 01191 id = rsock_intern_protocol_family(rai->pfamily); 01192 if (id == 0) 01193 rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily); 01194 pfamily = rb_id2str(id); 01195 01196 if (rai->socktype == 0) 01197 socktype = INT2FIX(0); 01198 else { 01199 id = rsock_intern_socktype(rai->socktype); 01200 if (id == 0) 01201 rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype); 01202 socktype = rb_id2str(id); 01203 } 01204 01205 if (rai->protocol == 0) 01206 protocol = INT2FIX(0); 01207 else if (IS_IP_FAMILY(afamily_int)) { 01208 id = rsock_intern_ipproto(rai->protocol); 01209 if (id == 0) 01210 rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol); 01211 protocol = rb_id2str(id); 01212 } 01213 else { 01214 rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol); 01215 } 01216 01217 canonname = rai->canonname; 01218 01219 inspectname = rai->inspectname; 01220 01221 id = rsock_intern_family(afamily_int); 01222 if (id == 0) 01223 rb_raise(rb_eSocket, "unknown address family: %d", afamily_int); 01224 afamily = rb_id2str(id); 01225 01226 switch(afamily_int) { 01227 #ifdef HAVE_SYS_UN_H 01228 case AF_UNIX: 01229 { 01230 struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr; 01231 char *s, *e; 01232 s = su->sun_path; 01233 e = (char*)su + rai->sockaddr_len; 01234 while (s < e && *(e-1) == '\0') 01235 e--; 01236 sockaddr = rb_str_new(s, e-s); 01237 break; 01238 } 01239 #endif 01240 01241 default: 01242 { 01243 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 01244 int error; 01245 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01246 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01247 NI_NUMERICHOST|NI_NUMERICSERV); 01248 if (error) { 01249 rsock_raise_socket_error("getnameinfo", error); 01250 } 01251 sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf)); 01252 break; 01253 } 01254 } 01255 01256 return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname); 01257 } 01258 01259 /* :nodoc: */ 01260 static VALUE 01261 addrinfo_mload(VALUE self, VALUE ary) 01262 { 01263 VALUE v; 01264 VALUE canonname, inspectname; 01265 int afamily, pfamily, socktype, protocol; 01266 struct sockaddr_storage ss; 01267 socklen_t len; 01268 rb_addrinfo_t *rai; 01269 01270 if (check_addrinfo(self)) 01271 rb_raise(rb_eTypeError, "already initialized socket address"); 01272 01273 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary"); 01274 01275 v = rb_ary_entry(ary, 0); 01276 StringValue(v); 01277 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1) 01278 rb_raise(rb_eTypeError, "unexpected address family"); 01279 01280 v = rb_ary_entry(ary, 2); 01281 StringValue(v); 01282 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1) 01283 rb_raise(rb_eTypeError, "unexpected protocol family"); 01284 01285 v = rb_ary_entry(ary, 3); 01286 if (v == INT2FIX(0)) 01287 socktype = 0; 01288 else { 01289 StringValue(v); 01290 if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1) 01291 rb_raise(rb_eTypeError, "unexpected socktype"); 01292 } 01293 01294 v = rb_ary_entry(ary, 4); 01295 if (v == INT2FIX(0)) 01296 protocol = 0; 01297 else { 01298 StringValue(v); 01299 if (IS_IP_FAMILY(afamily)) { 01300 if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1) 01301 rb_raise(rb_eTypeError, "unexpected protocol"); 01302 } 01303 else { 01304 rb_raise(rb_eTypeError, "unexpected protocol"); 01305 } 01306 } 01307 01308 v = rb_ary_entry(ary, 5); 01309 if (NIL_P(v)) 01310 canonname = Qnil; 01311 else { 01312 StringValue(v); 01313 canonname = v; 01314 } 01315 01316 v = rb_ary_entry(ary, 6); 01317 if (NIL_P(v)) 01318 inspectname = Qnil; 01319 else { 01320 StringValue(v); 01321 inspectname = v; 01322 } 01323 01324 v = rb_ary_entry(ary, 1); 01325 switch(afamily) { 01326 #ifdef HAVE_SYS_UN_H 01327 case AF_UNIX: 01328 { 01329 struct sockaddr_un uaddr; 01330 MEMZERO(&uaddr, struct sockaddr_un, 1); 01331 uaddr.sun_family = AF_UNIX; 01332 01333 StringValue(v); 01334 if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v)) 01335 rb_raise(rb_eSocket, 01336 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 01337 (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path)); 01338 memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v)); 01339 len = (socklen_t)sizeof(uaddr); 01340 memcpy(&ss, &uaddr, len); 01341 break; 01342 } 01343 #endif 01344 01345 default: 01346 { 01347 VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary"); 01348 struct addrinfo *res; 01349 int flags = AI_NUMERICHOST; 01350 #ifdef AI_NUMERICSERV 01351 flags |= AI_NUMERICSERV; 01352 #endif 01353 res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1), 01354 INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol), 01355 INT2NUM(flags), 1); 01356 01357 len = res->ai_addrlen; 01358 memcpy(&ss, res->ai_addr, res->ai_addrlen); 01359 break; 01360 } 01361 } 01362 01363 DATA_PTR(self) = rai = alloc_addrinfo(); 01364 init_addrinfo(rai, (struct sockaddr *)&ss, len, 01365 pfamily, socktype, protocol, 01366 canonname, inspectname); 01367 return self; 01368 } 01369 01370 /* 01371 * call-seq: 01372 * addrinfo.afamily => integer 01373 * 01374 * returns the address family as an integer. 01375 * 01376 * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true 01377 * 01378 */ 01379 static VALUE 01380 addrinfo_afamily(VALUE self) 01381 { 01382 rb_addrinfo_t *rai = get_addrinfo(self); 01383 return INT2NUM(ai_get_afamily(rai)); 01384 } 01385 01386 /* 01387 * call-seq: 01388 * addrinfo.pfamily => integer 01389 * 01390 * returns the protocol family as an integer. 01391 * 01392 * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true 01393 * 01394 */ 01395 static VALUE 01396 addrinfo_pfamily(VALUE self) 01397 { 01398 rb_addrinfo_t *rai = get_addrinfo(self); 01399 return INT2NUM(rai->pfamily); 01400 } 01401 01402 /* 01403 * call-seq: 01404 * addrinfo.socktype => integer 01405 * 01406 * returns the socket type as an integer. 01407 * 01408 * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true 01409 * 01410 */ 01411 static VALUE 01412 addrinfo_socktype(VALUE self) 01413 { 01414 rb_addrinfo_t *rai = get_addrinfo(self); 01415 return INT2NUM(rai->socktype); 01416 } 01417 01418 /* 01419 * call-seq: 01420 * addrinfo.protocol => integer 01421 * 01422 * returns the socket type as an integer. 01423 * 01424 * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true 01425 * 01426 */ 01427 static VALUE 01428 addrinfo_protocol(VALUE self) 01429 { 01430 rb_addrinfo_t *rai = get_addrinfo(self); 01431 return INT2NUM(rai->protocol); 01432 } 01433 01434 /* 01435 * call-seq: 01436 * addrinfo.to_sockaddr => string 01437 * addrinfo.to_s => string 01438 * 01439 * returns the socket address as packed struct sockaddr string. 01440 * 01441 * Addrinfo.tcp("localhost", 80).to_sockaddr 01442 * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" 01443 * 01444 */ 01445 static VALUE 01446 addrinfo_to_sockaddr(VALUE self) 01447 { 01448 rb_addrinfo_t *rai = get_addrinfo(self); 01449 VALUE ret; 01450 ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len); 01451 OBJ_INFECT(ret, self); 01452 return ret; 01453 } 01454 01455 /* 01456 * call-seq: 01457 * addrinfo.canonname => string or nil 01458 * 01459 * returns the canonical name as an string. 01460 * 01461 * nil is returned if no canonical name. 01462 * 01463 * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified. 01464 * 01465 * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME) 01466 * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)> 01467 * p list[0].canonname #=> "carbon.ruby-lang.org" 01468 * 01469 */ 01470 static VALUE 01471 addrinfo_canonname(VALUE self) 01472 { 01473 rb_addrinfo_t *rai = get_addrinfo(self); 01474 return rai->canonname; 01475 } 01476 01477 /* 01478 * call-seq: 01479 * addrinfo.ip? => true or false 01480 * 01481 * returns true if addrinfo is internet (IPv4/IPv6) address. 01482 * returns false otherwise. 01483 * 01484 * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true 01485 * Addrinfo.tcp("::1", 80).ip? #=> true 01486 * Addrinfo.unix("/tmp/sock").ip? #=> false 01487 * 01488 */ 01489 static VALUE 01490 addrinfo_ip_p(VALUE self) 01491 { 01492 rb_addrinfo_t *rai = get_addrinfo(self); 01493 int family = ai_get_afamily(rai); 01494 return IS_IP_FAMILY(family) ? Qtrue : Qfalse; 01495 } 01496 01497 /* 01498 * call-seq: 01499 * addrinfo.ipv4? => true or false 01500 * 01501 * returns true if addrinfo is IPv4 address. 01502 * returns false otherwise. 01503 * 01504 * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true 01505 * Addrinfo.tcp("::1", 80).ipv4? #=> false 01506 * Addrinfo.unix("/tmp/sock").ipv4? #=> false 01507 * 01508 */ 01509 static VALUE 01510 addrinfo_ipv4_p(VALUE self) 01511 { 01512 rb_addrinfo_t *rai = get_addrinfo(self); 01513 return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse; 01514 } 01515 01516 /* 01517 * call-seq: 01518 * addrinfo.ipv6? => true or false 01519 * 01520 * returns true if addrinfo is IPv6 address. 01521 * returns false otherwise. 01522 * 01523 * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false 01524 * Addrinfo.tcp("::1", 80).ipv6? #=> true 01525 * Addrinfo.unix("/tmp/sock").ipv6? #=> false 01526 * 01527 */ 01528 static VALUE 01529 addrinfo_ipv6_p(VALUE self) 01530 { 01531 #ifdef AF_INET6 01532 rb_addrinfo_t *rai = get_addrinfo(self); 01533 return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse; 01534 #else 01535 return Qfalse; 01536 #endif 01537 } 01538 01539 /* 01540 * call-seq: 01541 * addrinfo.unix? => true or false 01542 * 01543 * returns true if addrinfo is UNIX address. 01544 * returns false otherwise. 01545 * 01546 * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false 01547 * Addrinfo.tcp("::1", 80).unix? #=> false 01548 * Addrinfo.unix("/tmp/sock").unix? #=> true 01549 * 01550 */ 01551 static VALUE 01552 addrinfo_unix_p(VALUE self) 01553 { 01554 rb_addrinfo_t *rai = get_addrinfo(self); 01555 #ifdef AF_UNIX 01556 return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse; 01557 #else 01558 return Qfalse; 01559 #endif 01560 } 01561 01562 /* 01563 * call-seq: 01564 * addrinfo.getnameinfo => [nodename, service] 01565 * addrinfo.getnameinfo(flags) => [nodename, service] 01566 * 01567 * returns nodename and service as a pair of strings. 01568 * This converts struct sockaddr in addrinfo to textual representation. 01569 * 01570 * flags should be bitwise OR of Socket::NI_??? constants. 01571 * 01572 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"] 01573 * 01574 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV) 01575 * #=> ["localhost", "80"] 01576 */ 01577 static VALUE 01578 addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self) 01579 { 01580 rb_addrinfo_t *rai = get_addrinfo(self); 01581 VALUE vflags; 01582 char hbuf[1024], pbuf[1024]; 01583 int flags, error; 01584 01585 rb_scan_args(argc, argv, "01", &vflags); 01586 01587 flags = NIL_P(vflags) ? 0 : NUM2INT(vflags); 01588 01589 if (rai->socktype == SOCK_DGRAM) 01590 flags |= NI_DGRAM; 01591 01592 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01593 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01594 flags); 01595 if (error) { 01596 rsock_raise_socket_error("getnameinfo", error); 01597 } 01598 01599 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); 01600 } 01601 01602 /* 01603 * call-seq: 01604 * addrinfo.ip_unpack => [addr, port] 01605 * 01606 * Returns the IP address and port number as 2-element array. 01607 * 01608 * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80] 01609 * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80] 01610 */ 01611 static VALUE 01612 addrinfo_ip_unpack(VALUE self) 01613 { 01614 rb_addrinfo_t *rai = get_addrinfo(self); 01615 int family = ai_get_afamily(rai); 01616 VALUE vflags; 01617 VALUE ret, portstr; 01618 01619 if (!IS_IP_FAMILY(family)) 01620 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01621 01622 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01623 ret = addrinfo_getnameinfo(1, &vflags, self); 01624 portstr = rb_ary_entry(ret, 1); 01625 rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr)))); 01626 return ret; 01627 } 01628 01629 /* 01630 * call-seq: 01631 * addrinfo.ip_address => string 01632 * 01633 * Returns the IP address as a string. 01634 * 01635 * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1" 01636 * Addrinfo.tcp("::1", 80).ip_address #=> "::1" 01637 */ 01638 static VALUE 01639 addrinfo_ip_address(VALUE self) 01640 { 01641 rb_addrinfo_t *rai = get_addrinfo(self); 01642 int family = ai_get_afamily(rai); 01643 VALUE vflags; 01644 VALUE ret; 01645 01646 if (!IS_IP_FAMILY(family)) 01647 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01648 01649 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01650 ret = addrinfo_getnameinfo(1, &vflags, self); 01651 return rb_ary_entry(ret, 0); 01652 } 01653 01654 /* 01655 * call-seq: 01656 * addrinfo.ip_port => port 01657 * 01658 * Returns the port number as an integer. 01659 * 01660 * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80 01661 * Addrinfo.tcp("::1", 80).ip_port #=> 80 01662 */ 01663 static VALUE 01664 addrinfo_ip_port(VALUE self) 01665 { 01666 rb_addrinfo_t *rai = get_addrinfo(self); 01667 int family = ai_get_afamily(rai); 01668 int port; 01669 01670 if (!IS_IP_FAMILY(family)) { 01671 bad_family: 01672 #ifdef AF_INET6 01673 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01674 #else 01675 rb_raise(rb_eSocket, "need IPv4 address"); 01676 #endif 01677 } 01678 01679 switch (family) { 01680 case AF_INET: 01681 if (rai->sockaddr_len != sizeof(struct sockaddr_in)) 01682 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4"); 01683 port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port); 01684 break; 01685 01686 #ifdef AF_INET6 01687 case AF_INET6: 01688 if (rai->sockaddr_len != sizeof(struct sockaddr_in6)) 01689 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6"); 01690 port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port); 01691 break; 01692 #endif 01693 01694 default: 01695 goto bad_family; 01696 } 01697 01698 return INT2NUM(port); 01699 } 01700 01701 static int 01702 extract_in_addr(VALUE self, uint32_t *addrp) 01703 { 01704 rb_addrinfo_t *rai = get_addrinfo(self); 01705 int family = ai_get_afamily(rai); 01706 if (family != AF_INET) return 0; 01707 *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr); 01708 return 1; 01709 } 01710 01711 /* 01712 * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). 01713 * It returns false otherwise. 01714 */ 01715 static VALUE 01716 addrinfo_ipv4_private_p(VALUE self) 01717 { 01718 uint32_t a; 01719 if (!extract_in_addr(self, &a)) return Qfalse; 01720 if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */ 01721 (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */ 01722 (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */ 01723 return Qtrue; 01724 return Qfalse; 01725 } 01726 01727 /* 01728 * Returns true for IPv4 loopback address (127.0.0.0/8). 01729 * It returns false otherwise. 01730 */ 01731 static VALUE 01732 addrinfo_ipv4_loopback_p(VALUE self) 01733 { 01734 uint32_t a; 01735 if (!extract_in_addr(self, &a)) return Qfalse; 01736 if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */ 01737 return Qtrue; 01738 return Qfalse; 01739 } 01740 01741 /* 01742 * Returns true for IPv4 multicast address (224.0.0.0/4). 01743 * It returns false otherwise. 01744 */ 01745 static VALUE 01746 addrinfo_ipv4_multicast_p(VALUE self) 01747 { 01748 uint32_t a; 01749 if (!extract_in_addr(self, &a)) return Qfalse; 01750 if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */ 01751 return Qtrue; 01752 return Qfalse; 01753 } 01754 01755 #ifdef INET6 01756 01757 static struct in6_addr * 01758 extract_in6_addr(VALUE self) 01759 { 01760 rb_addrinfo_t *rai = get_addrinfo(self); 01761 int family = ai_get_afamily(rai); 01762 if (family != AF_INET6) return NULL; 01763 return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01764 } 01765 01766 /* 01767 * Returns true for IPv6 unspecified address (::). 01768 * It returns false otherwise. 01769 */ 01770 static VALUE 01771 addrinfo_ipv6_unspecified_p(VALUE self) 01772 { 01773 struct in6_addr *addr = extract_in6_addr(self); 01774 if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue; 01775 return Qfalse; 01776 } 01777 01778 /* 01779 * Returns true for IPv6 loopback address (::1). 01780 * It returns false otherwise. 01781 */ 01782 static VALUE 01783 addrinfo_ipv6_loopback_p(VALUE self) 01784 { 01785 struct in6_addr *addr = extract_in6_addr(self); 01786 if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue; 01787 return Qfalse; 01788 } 01789 01790 /* 01791 * Returns true for IPv6 multicast address (ff00::/8). 01792 * It returns false otherwise. 01793 */ 01794 static VALUE 01795 addrinfo_ipv6_multicast_p(VALUE self) 01796 { 01797 struct in6_addr *addr = extract_in6_addr(self); 01798 if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue; 01799 return Qfalse; 01800 } 01801 01802 /* 01803 * Returns true for IPv6 link local address (ff80::/10). 01804 * It returns false otherwise. 01805 */ 01806 static VALUE 01807 addrinfo_ipv6_linklocal_p(VALUE self) 01808 { 01809 struct in6_addr *addr = extract_in6_addr(self); 01810 if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue; 01811 return Qfalse; 01812 } 01813 01814 /* 01815 * Returns true for IPv6 site local address (ffc0::/10). 01816 * It returns false otherwise. 01817 */ 01818 static VALUE 01819 addrinfo_ipv6_sitelocal_p(VALUE self) 01820 { 01821 struct in6_addr *addr = extract_in6_addr(self); 01822 if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue; 01823 return Qfalse; 01824 } 01825 01826 /* 01827 * Returns true for IPv6 unique local address (fc00::/7, RFC4193). 01828 * It returns false otherwise. 01829 */ 01830 static VALUE 01831 addrinfo_ipv6_unique_local_p(VALUE self) 01832 { 01833 struct in6_addr *addr = extract_in6_addr(self); 01834 if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue; 01835 return Qfalse; 01836 } 01837 01838 /* 01839 * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80). 01840 * It returns false otherwise. 01841 */ 01842 static VALUE 01843 addrinfo_ipv6_v4mapped_p(VALUE self) 01844 { 01845 struct in6_addr *addr = extract_in6_addr(self); 01846 if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue; 01847 return Qfalse; 01848 } 01849 01850 /* 01851 * Returns true for IPv4-compatible IPv6 address (::/80). 01852 * It returns false otherwise. 01853 */ 01854 static VALUE 01855 addrinfo_ipv6_v4compat_p(VALUE self) 01856 { 01857 struct in6_addr *addr = extract_in6_addr(self); 01858 if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue; 01859 return Qfalse; 01860 } 01861 01862 /* 01863 * Returns true for IPv6 multicast node-local scope address. 01864 * It returns false otherwise. 01865 */ 01866 static VALUE 01867 addrinfo_ipv6_mc_nodelocal_p(VALUE self) 01868 { 01869 struct in6_addr *addr = extract_in6_addr(self); 01870 if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue; 01871 return Qfalse; 01872 } 01873 01874 /* 01875 * Returns true for IPv6 multicast link-local scope address. 01876 * It returns false otherwise. 01877 */ 01878 static VALUE 01879 addrinfo_ipv6_mc_linklocal_p(VALUE self) 01880 { 01881 struct in6_addr *addr = extract_in6_addr(self); 01882 if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue; 01883 return Qfalse; 01884 } 01885 01886 /* 01887 * Returns true for IPv6 multicast site-local scope address. 01888 * It returns false otherwise. 01889 */ 01890 static VALUE 01891 addrinfo_ipv6_mc_sitelocal_p(VALUE self) 01892 { 01893 struct in6_addr *addr = extract_in6_addr(self); 01894 if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue; 01895 return Qfalse; 01896 } 01897 01898 /* 01899 * Returns true for IPv6 multicast organization-local scope address. 01900 * It returns false otherwise. 01901 */ 01902 static VALUE 01903 addrinfo_ipv6_mc_orglocal_p(VALUE self) 01904 { 01905 struct in6_addr *addr = extract_in6_addr(self); 01906 if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue; 01907 return Qfalse; 01908 } 01909 01910 /* 01911 * Returns true for IPv6 multicast global scope address. 01912 * It returns false otherwise. 01913 */ 01914 static VALUE 01915 addrinfo_ipv6_mc_global_p(VALUE self) 01916 { 01917 struct in6_addr *addr = extract_in6_addr(self); 01918 if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue; 01919 return Qfalse; 01920 } 01921 01922 /* 01923 * Returns IPv4 address of IPv4 mapped/compatible IPv6 address. 01924 * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address. 01925 * 01926 * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01927 * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01928 * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil 01929 * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil 01930 * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil 01931 */ 01932 static VALUE 01933 addrinfo_ipv6_to_ipv4(VALUE self) 01934 { 01935 rb_addrinfo_t *rai = get_addrinfo(self); 01936 struct in6_addr *addr; 01937 int family = ai_get_afamily(rai); 01938 if (family != AF_INET6) return Qnil; 01939 addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01940 if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) { 01941 struct sockaddr_in sin4; 01942 MEMZERO(&sin4, struct sockaddr_in, 1); 01943 sin4.sin_family = AF_INET; 01944 SET_SIN_LEN(&sin4, sizeof(sin4)); 01945 memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr)); 01946 return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4), 01947 PF_INET, rai->socktype, rai->protocol, 01948 rai->canonname, rai->inspectname); 01949 } 01950 else { 01951 return Qnil; 01952 } 01953 } 01954 01955 #endif 01956 01957 #ifdef HAVE_SYS_UN_H 01958 /* 01959 * call-seq: 01960 * addrinfo.unix_path => path 01961 * 01962 * Returns the socket path as a string. 01963 * 01964 * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock" 01965 */ 01966 static VALUE 01967 addrinfo_unix_path(VALUE self) 01968 { 01969 rb_addrinfo_t *rai = get_addrinfo(self); 01970 int family = ai_get_afamily(rai); 01971 struct sockaddr_un *addr; 01972 char *s, *e; 01973 01974 if (family != AF_UNIX) 01975 rb_raise(rb_eSocket, "need AF_UNIX address"); 01976 01977 addr = (struct sockaddr_un *)&rai->addr; 01978 01979 s = addr->sun_path; 01980 e = (char*)addr + rai->sockaddr_len; 01981 if (e < s) 01982 rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.", 01983 (size_t)rai->sockaddr_len, (size_t)(s - (char *)addr)); 01984 if (addr->sun_path + sizeof(addr->sun_path) < e) 01985 rb_raise(rb_eSocket, 01986 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 01987 (size_t)(e - addr->sun_path), sizeof(addr->sun_path)); 01988 while (s < e && *(e-1) == '\0') 01989 e--; 01990 return rb_str_new(s, e-s); 01991 } 01992 #endif 01993 01994 /* 01995 * call-seq: 01996 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...] 01997 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...] 01998 * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...] 01999 * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...] 02000 * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...] 02001 * 02002 * returns a list of addrinfo objects as an array. 02003 * 02004 * This method converts nodename (hostname) and service (port) to addrinfo. 02005 * Since the conversion is not unique, the result is a list of addrinfo objects. 02006 * 02007 * nodename or service can be nil if no conversion intended. 02008 * 02009 * family, socktype and protocol are hint for preferred protocol. 02010 * If the result will be used for a socket with SOCK_STREAM, 02011 * SOCK_STREAM should be specified as socktype. 02012 * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM. 02013 * If they are omitted or nil is given, the result is not restricted. 02014 * 02015 * Similarly, PF_INET6 as family restricts for IPv6. 02016 * 02017 * flags should be bitwise OR of Socket::AI_??? constants such as follows. 02018 * Note that the exact list of the constants depends on OS. 02019 * 02020 * AI_PASSIVE Get address to use with bind() 02021 * AI_CANONNAME Fill in the canonical name 02022 * AI_NUMERICHOST Prevent host name resolution 02023 * AI_NUMERICSERV Prevent service name resolution 02024 * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses 02025 * AI_ALL Allow all addresses 02026 * AI_ADDRCONFIG Accept only if any address is assigned 02027 * 02028 * Note that socktype should be specified whenever application knows the usage of the address. 02029 * Some platform causes an error when socktype is omitted and servname is specified as an integer 02030 * because some port numbers, 512 for example, are ambiguous without socktype. 02031 * 02032 * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM) 02033 * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>, 02034 * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>] 02035 * 02036 */ 02037 static VALUE 02038 addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self) 02039 { 02040 VALUE node, service, family, socktype, protocol, flags; 02041 02042 rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags); 02043 return addrinfo_list_new(node, service, family, socktype, protocol, flags); 02044 } 02045 02046 /* 02047 * call-seq: 02048 * Addrinfo.ip(host) => addrinfo 02049 * 02050 * returns an addrinfo object for IP address. 02051 * 02052 * The port, socktype, protocol of the result is filled by zero. 02053 * So, it is not appropriate to create a socket. 02054 * 02055 * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)> 02056 */ 02057 static VALUE 02058 addrinfo_s_ip(VALUE self, VALUE host) 02059 { 02060 VALUE ret; 02061 rb_addrinfo_t *rai; 02062 ret = addrinfo_firstonly_new(host, Qnil, 02063 INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0)); 02064 rai = get_addrinfo(ret); 02065 rai->socktype = 0; 02066 rai->protocol = 0; 02067 return ret; 02068 } 02069 02070 /* 02071 * call-seq: 02072 * Addrinfo.tcp(host, port) => addrinfo 02073 * 02074 * returns an addrinfo object for TCP address. 02075 * 02076 * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)> 02077 */ 02078 static VALUE 02079 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port) 02080 { 02081 return addrinfo_firstonly_new(host, port, 02082 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0)); 02083 } 02084 02085 /* 02086 * call-seq: 02087 * Addrinfo.udp(host, port) => addrinfo 02088 * 02089 * returns an addrinfo object for UDP address. 02090 * 02091 * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)> 02092 */ 02093 static VALUE 02094 addrinfo_s_udp(VALUE self, VALUE host, VALUE port) 02095 { 02096 return addrinfo_firstonly_new(host, port, 02097 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0)); 02098 } 02099 02100 #ifdef HAVE_SYS_UN_H 02101 02102 /* 02103 * call-seq: 02104 * Addrinfo.unix(path [, socktype]) => addrinfo 02105 * 02106 * returns an addrinfo object for UNIX socket address. 02107 * 02108 * _socktype_ specifies the socket type. 02109 * If it is omitted, :STREAM is used. 02110 * 02111 * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM> 02112 * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM> 02113 */ 02114 static VALUE 02115 addrinfo_s_unix(int argc, VALUE *argv, VALUE self) 02116 { 02117 VALUE path, vsocktype, addr; 02118 int socktype; 02119 rb_addrinfo_t *rai; 02120 02121 rb_scan_args(argc, argv, "11", &path, &vsocktype); 02122 02123 if (NIL_P(vsocktype)) 02124 socktype = SOCK_STREAM; 02125 else 02126 socktype = rsock_socktype_arg(vsocktype); 02127 02128 addr = addrinfo_s_allocate(rb_cAddrinfo); 02129 DATA_PTR(addr) = rai = alloc_addrinfo(); 02130 init_unix_addrinfo(rai, path, socktype); 02131 OBJ_INFECT(addr, path); 02132 return addr; 02133 } 02134 02135 #endif 02136 02137 VALUE 02138 rsock_sockaddr_string_value(volatile VALUE *v) 02139 { 02140 VALUE val = *v; 02141 if (IS_ADDRINFO(val)) { 02142 *v = addrinfo_to_sockaddr(val); 02143 } 02144 StringValue(*v); 02145 return *v; 02146 } 02147 02148 char * 02149 rsock_sockaddr_string_value_ptr(volatile VALUE *v) 02150 { 02151 rsock_sockaddr_string_value(v); 02152 return RSTRING_PTR(*v); 02153 } 02154 02155 VALUE 02156 rb_check_sockaddr_string_type(VALUE val) 02157 { 02158 if (IS_ADDRINFO(val)) 02159 return addrinfo_to_sockaddr(val); 02160 return rb_check_string_type(val); 02161 } 02162 02163 VALUE 02164 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len) 02165 { 02166 int family; 02167 int socktype; 02168 int ret; 02169 socklen_t optlen = (socklen_t)sizeof(socktype); 02170 02171 /* assumes protocol family and address family are identical */ 02172 family = get_afamily(addr, len); 02173 02174 ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen); 02175 if (ret == -1) { 02176 rb_sys_fail("getsockopt(SO_TYPE)"); 02177 } 02178 02179 return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil); 02180 } 02181 02182 VALUE 02183 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) 02184 { 02185 rb_io_t *fptr; 02186 02187 switch (TYPE(io)) { 02188 case T_FIXNUM: 02189 return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len); 02190 02191 case T_BIGNUM: 02192 return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len); 02193 02194 case T_FILE: 02195 GetOpenFile(io, fptr); 02196 return rsock_fd_socket_addrinfo(fptr->fd, addr, len); 02197 02198 default: 02199 rb_raise(rb_eTypeError, "neither IO nor file descriptor"); 02200 } 02201 02202 UNREACHABLE; 02203 } 02204 02205 /* 02206 * Addrinfo class 02207 */ 02208 void 02209 rsock_init_addrinfo(void) 02210 { 02211 /* 02212 * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This 02213 * structure identifies an Internet host and a service. 02214 */ 02215 rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData); 02216 rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); 02217 rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); 02218 rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0); 02219 rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0); 02220 rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1); 02221 rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1); 02222 rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2); 02223 rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2); 02224 #ifdef HAVE_SYS_UN_H 02225 rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1); 02226 #endif 02227 02228 rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0); 02229 rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0); 02230 rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0); 02231 rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0); 02232 rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0); 02233 02234 rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0); 02235 rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0); 02236 rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0); 02237 02238 rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0); 02239 rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0); 02240 rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0); 02241 rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0); 02242 02243 rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0); 02244 rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0); 02245 rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0); 02246 02247 #ifdef INET6 02248 rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0); 02249 rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0); 02250 rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0); 02251 rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0); 02252 rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0); 02253 rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0); 02254 rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0); 02255 rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0); 02256 rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0); 02257 rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0); 02258 rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0); 02259 rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0); 02260 rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0); 02261 02262 rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0); 02263 #endif 02264 02265 #ifdef HAVE_SYS_UN_H 02266 rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0); 02267 #endif 02268 02269 rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0); 02270 rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */ 02271 02272 rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1); 02273 02274 rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0); 02275 rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1); 02276 } 02277
1.7.6.1