|
Ruby
1.9.3p537(2014-02-19revision0)
|
00001 /************************************************ 00002 00003 ainfo.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 VALUE 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 (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)BLOCKING_REGION(nogvl_getaddrinfo, &arg); 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 VALUE 00207 nogvl_getnameinfo(void *arg) 00208 { 00209 struct getnameinfo_arg *ptr = arg; 00210 return 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)BLOCKING_REGION(nogvl_getnameinfo, &arg); 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 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 00699 int ret; 00700 ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 00701 sizeof(hbuf), pbuf, sizeof(pbuf), 00702 NI_NUMERICHOST|NI_NUMERICSERV); 00703 if (ret == 0) { 00704 if (TYPE(node) == T_STRING && strcmp(hbuf, RSTRING_PTR(node)) == 0) 00705 node = Qnil; 00706 if (TYPE(service) == T_STRING && strcmp(pbuf, RSTRING_PTR(service)) == 0) 00707 service = Qnil; 00708 else if (TYPE(service) == T_FIXNUM && atoi(pbuf) == FIX2INT(service)) 00709 service = Qnil; 00710 } 00711 } 00712 00713 if (TYPE(node) == T_STRING) { 00714 inspectname = rb_str_dup(node); 00715 } 00716 if (TYPE(service) == T_STRING) { 00717 if (NIL_P(inspectname)) 00718 inspectname = rb_sprintf(":%s", StringValueCStr(service)); 00719 else 00720 rb_str_catf(inspectname, ":%s", StringValueCStr(service)); 00721 } 00722 else if (TYPE(service) == T_FIXNUM && FIX2INT(service) != 0) 00723 { 00724 if (NIL_P(inspectname)) 00725 inspectname = rb_sprintf(":%d", FIX2INT(service)); 00726 else 00727 rb_str_catf(inspectname, ":%d", FIX2INT(service)); 00728 } 00729 if (!NIL_P(inspectname)) { 00730 OBJ_INFECT(inspectname, node); 00731 OBJ_INFECT(inspectname, service); 00732 OBJ_FREEZE(inspectname); 00733 } 00734 return inspectname; 00735 } 00736 00737 static VALUE 00738 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00739 { 00740 VALUE ret; 00741 VALUE canonname; 00742 VALUE inspectname; 00743 00744 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00745 00746 inspectname = make_inspectname(node, service, res); 00747 00748 canonname = Qnil; 00749 if (res->ai_canonname) { 00750 canonname = rb_tainted_str_new_cstr(res->ai_canonname); 00751 OBJ_FREEZE(canonname); 00752 } 00753 00754 ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen, 00755 res->ai_family, res->ai_socktype, res->ai_protocol, 00756 canonname, inspectname); 00757 00758 freeaddrinfo(res); 00759 return ret; 00760 } 00761 00762 static VALUE 00763 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00764 { 00765 VALUE ret; 00766 struct addrinfo *r; 00767 VALUE inspectname; 00768 00769 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00770 00771 inspectname = make_inspectname(node, service, res); 00772 00773 ret = rb_ary_new(); 00774 for (r = res; r; r = r->ai_next) { 00775 VALUE addr; 00776 VALUE canonname = Qnil; 00777 00778 if (r->ai_canonname) { 00779 canonname = rb_tainted_str_new_cstr(r->ai_canonname); 00780 OBJ_FREEZE(canonname); 00781 } 00782 00783 addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen, 00784 r->ai_family, r->ai_socktype, r->ai_protocol, 00785 canonname, inspectname); 00786 00787 rb_ary_push(ret, addr); 00788 } 00789 00790 freeaddrinfo(res); 00791 return ret; 00792 } 00793 00794 00795 #ifdef HAVE_SYS_UN_H 00796 static void 00797 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) 00798 { 00799 struct sockaddr_un un; 00800 socklen_t len; 00801 00802 StringValue(path); 00803 00804 if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path)) 00805 rb_raise(rb_eArgError, 00806 "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 00807 (size_t)RSTRING_LEN(path), sizeof(un.sun_path)); 00808 00809 MEMZERO(&un, struct sockaddr_un, 1); 00810 00811 un.sun_family = AF_UNIX; 00812 memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); 00813 00814 len = rsock_unix_sockaddr_len(path); 00815 init_addrinfo(rai, (struct sockaddr *)&un, len, 00816 PF_UNIX, socktype, 0, Qnil, Qnil); 00817 } 00818 #endif 00819 00820 /* 00821 * call-seq: 00822 * Addrinfo.new(sockaddr) => addrinfo 00823 * Addrinfo.new(sockaddr, family) => addrinfo 00824 * Addrinfo.new(sockaddr, family, socktype) => addrinfo 00825 * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo 00826 * 00827 * returns a new instance of Addrinfo. 00828 * The instance contains sockaddr, family, socktype, protocol. 00829 * sockaddr means struct sockaddr which can be used for connect(2), etc. 00830 * family, socktype and protocol are integers which is used for arguments of socket(2). 00831 * 00832 * sockaddr is specified as an array or a string. 00833 * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr. 00834 * The string should be struct sockaddr as generated by 00835 * Socket.sockaddr_in or Socket.unpack_sockaddr_un. 00836 * 00837 * sockaddr examples: 00838 * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] 00839 * - ["AF_INET6", 42304, "ip6-localhost", "::1"] 00840 * - ["AF_UNIX", "/tmp/sock"] 00841 * - Socket.sockaddr_in("smtp", "2001:DB8::1") 00842 * - Socket.sockaddr_in(80, "172.18.22.42") 00843 * - Socket.sockaddr_in(80, "www.ruby-lang.org") 00844 * - Socket.sockaddr_un("/tmp/sock") 00845 * 00846 * In an AF_INET/AF_INET6 sockaddr array, the 4th element, 00847 * numeric IP address, is used to construct socket address in the Addrinfo instance. 00848 * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect. 00849 * 00850 * family is specified as an integer to specify the protocol family such as Socket::PF_INET. 00851 * It can be a symbol or a string which is the constant name 00852 * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc. 00853 * If omitted, PF_UNSPEC is assumed. 00854 * 00855 * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM. 00856 * It can be a symbol or a string which is the constant name 00857 * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc. 00858 * If omitted, 0 is assumed. 00859 * 00860 * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP. 00861 * It must be an integer, unlike family and socktype. 00862 * If omitted, 0 is assumed. 00863 * Note that 0 is reasonable value for most protocols, except raw socket. 00864 * 00865 */ 00866 static VALUE 00867 addrinfo_initialize(int argc, VALUE *argv, VALUE self) 00868 { 00869 rb_addrinfo_t *rai; 00870 VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol; 00871 int i_pfamily, i_socktype, i_protocol; 00872 struct sockaddr *sockaddr_ptr; 00873 socklen_t sockaddr_len; 00874 VALUE canonname = Qnil, inspectname = Qnil; 00875 00876 if (check_addrinfo(self)) 00877 rb_raise(rb_eTypeError, "already initialized socket address"); 00878 DATA_PTR(self) = rai = alloc_addrinfo(); 00879 00880 rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol); 00881 00882 i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily); 00883 i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype); 00884 i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol); 00885 00886 sockaddr_ary = rb_check_array_type(sockaddr_arg); 00887 if (!NIL_P(sockaddr_ary)) { 00888 VALUE afamily = rb_ary_entry(sockaddr_ary, 0); 00889 int af; 00890 StringValue(afamily); 00891 if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1) 00892 rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily)); 00893 switch (af) { 00894 case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */ 00895 #ifdef INET6 00896 case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */ 00897 #endif 00898 { 00899 VALUE service = rb_ary_entry(sockaddr_ary, 1); 00900 VALUE nodename = rb_ary_entry(sockaddr_ary, 2); 00901 VALUE numericnode = rb_ary_entry(sockaddr_ary, 3); 00902 int flags; 00903 00904 service = INT2NUM(NUM2INT(service)); 00905 if (!NIL_P(nodename)) 00906 StringValue(nodename); 00907 StringValue(numericnode); 00908 flags = AI_NUMERICHOST; 00909 #ifdef AI_NUMERICSERV 00910 flags |= AI_NUMERICSERV; 00911 #endif 00912 00913 init_addrinfo_getaddrinfo(rai, numericnode, service, 00914 INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol), 00915 INT2NUM(flags), 00916 nodename, service); 00917 break; 00918 } 00919 00920 #ifdef HAVE_SYS_UN_H 00921 case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */ 00922 { 00923 VALUE path = rb_ary_entry(sockaddr_ary, 1); 00924 StringValue(path); 00925 init_unix_addrinfo(rai, path, SOCK_STREAM); 00926 break; 00927 } 00928 #endif 00929 00930 default: 00931 rb_raise(rb_eSocket, "unexpected address family"); 00932 } 00933 } 00934 else { 00935 StringValue(sockaddr_arg); 00936 sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg); 00937 sockaddr_len = RSTRING_LENINT(sockaddr_arg); 00938 init_addrinfo(rai, sockaddr_ptr, sockaddr_len, 00939 i_pfamily, i_socktype, i_protocol, 00940 canonname, inspectname); 00941 } 00942 00943 return self; 00944 } 00945 00946 static int 00947 get_afamily(struct sockaddr *addr, socklen_t len) 00948 { 00949 if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len) 00950 return addr->sa_family; 00951 else 00952 return AF_UNSPEC; 00953 } 00954 00955 static int 00956 ai_get_afamily(rb_addrinfo_t *rai) 00957 { 00958 return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len); 00959 } 00960 00961 static VALUE 00962 inspect_sockaddr(VALUE addrinfo, VALUE ret) 00963 { 00964 rb_addrinfo_t *rai = get_addrinfo(addrinfo); 00965 00966 if (rai->sockaddr_len == 0) { 00967 rb_str_cat2(ret, "empty-sockaddr"); 00968 } 00969 else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr) 00970 rb_str_cat2(ret, "too-short-sockaddr"); 00971 else { 00972 switch (rai->addr.ss_family) { 00973 case AF_INET: 00974 { 00975 struct sockaddr_in *addr; 00976 int port; 00977 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) { 00978 rb_str_cat2(ret, "too-short-AF_INET-sockaddr"); 00979 } 00980 else { 00981 addr = (struct sockaddr_in *)&rai->addr; 00982 rb_str_catf(ret, "%d.%d.%d.%d", 00983 ((unsigned char*)&addr->sin_addr)[0], 00984 ((unsigned char*)&addr->sin_addr)[1], 00985 ((unsigned char*)&addr->sin_addr)[2], 00986 ((unsigned char*)&addr->sin_addr)[3]); 00987 port = ntohs(addr->sin_port); 00988 if (port) 00989 rb_str_catf(ret, ":%d", port); 00990 if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len) 00991 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in))); 00992 } 00993 break; 00994 } 00995 00996 #ifdef AF_INET6 00997 case AF_INET6: 00998 { 00999 struct sockaddr_in6 *addr; 01000 char hbuf[1024]; 01001 int port; 01002 int error; 01003 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) { 01004 rb_str_cat2(ret, "too-short-AF_INET6-sockaddr"); 01005 } 01006 else { 01007 addr = (struct sockaddr_in6 *)&rai->addr; 01008 /* use getnameinfo for scope_id. 01009 * RFC 4007: IPv6 Scoped Address Architecture 01010 * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API 01011 */ 01012 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01013 hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 01014 NI_NUMERICHOST|NI_NUMERICSERV); 01015 if (error) { 01016 rsock_raise_socket_error("getnameinfo", error); 01017 } 01018 if (addr->sin6_port == 0) { 01019 rb_str_cat2(ret, hbuf); 01020 } 01021 else { 01022 port = ntohs(addr->sin6_port); 01023 rb_str_catf(ret, "[%s]:%d", hbuf, port); 01024 } 01025 if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len) 01026 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6))); 01027 } 01028 break; 01029 } 01030 #endif 01031 01032 #ifdef HAVE_SYS_UN_H 01033 case AF_UNIX: 01034 { 01035 struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr; 01036 char *p, *s, *e; 01037 s = addr->sun_path; 01038 e = (char*)addr + rai->sockaddr_len; 01039 while (s < e && *(e-1) == '\0') 01040 e--; 01041 if (e < s) 01042 rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr"); 01043 else if (s == e) 01044 rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr"); 01045 else { 01046 int printable_only = 1; 01047 p = s; 01048 while (p < e) { 01049 printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p); 01050 p++; 01051 } 01052 if (printable_only) { /* only printable, no space */ 01053 if (s[0] != '/') /* relative path */ 01054 rb_str_cat2(ret, "AF_UNIX "); 01055 rb_str_cat(ret, s, p - s); 01056 } 01057 else { 01058 rb_str_cat2(ret, "AF_UNIX"); 01059 while (s < e) 01060 rb_str_catf(ret, ":%02x", (unsigned char)*s++); 01061 } 01062 if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len) 01063 rb_str_catf(ret, "(sockaddr %d bytes too long)", 01064 (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr))); 01065 } 01066 break; 01067 } 01068 #endif 01069 01070 default: 01071 { 01072 ID id = rsock_intern_family(rai->addr.ss_family); 01073 if (id == 0) 01074 rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family); 01075 else 01076 rb_str_catf(ret, "%s address format unknown", rb_id2name(id)); 01077 break; 01078 } 01079 } 01080 } 01081 01082 return ret; 01083 } 01084 01085 /* 01086 * call-seq: 01087 * addrinfo.inspect => string 01088 * 01089 * returns a string which shows addrinfo in human-readable form. 01090 * 01091 * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost:80)>" 01092 * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>" 01093 * 01094 */ 01095 static VALUE 01096 addrinfo_inspect(VALUE self) 01097 { 01098 rb_addrinfo_t *rai = get_addrinfo(self); 01099 int internet_p; 01100 VALUE ret; 01101 01102 ret = rb_sprintf("#<%s: ", rb_obj_classname(self)); 01103 01104 inspect_sockaddr(self, ret); 01105 01106 if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) { 01107 ID id = rsock_intern_protocol_family(rai->pfamily); 01108 if (id) 01109 rb_str_catf(ret, " %s", rb_id2name(id)); 01110 else 01111 rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily); 01112 } 01113 01114 internet_p = rai->pfamily == PF_INET; 01115 #ifdef INET6 01116 internet_p = internet_p || rai->pfamily == PF_INET6; 01117 #endif 01118 if (internet_p && rai->socktype == SOCK_STREAM && 01119 (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) { 01120 rb_str_cat2(ret, " TCP"); 01121 } 01122 else if (internet_p && rai->socktype == SOCK_DGRAM && 01123 (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) { 01124 rb_str_cat2(ret, " UDP"); 01125 } 01126 else { 01127 if (rai->socktype) { 01128 ID id = rsock_intern_socktype(rai->socktype); 01129 if (id) 01130 rb_str_catf(ret, " %s", rb_id2name(id)); 01131 else 01132 rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype); 01133 } 01134 01135 if (rai->protocol) { 01136 if (internet_p) { 01137 ID id = rsock_intern_ipproto(rai->protocol); 01138 if (id) 01139 rb_str_catf(ret, " %s", rb_id2name(id)); 01140 else 01141 goto unknown_protocol; 01142 } 01143 else { 01144 unknown_protocol: 01145 rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol); 01146 } 01147 } 01148 } 01149 01150 if (!NIL_P(rai->canonname)) { 01151 VALUE name = rai->canonname; 01152 rb_str_catf(ret, " %s", StringValueCStr(name)); 01153 } 01154 01155 if (!NIL_P(rai->inspectname)) { 01156 VALUE name = rai->inspectname; 01157 rb_str_catf(ret, " (%s)", StringValueCStr(name)); 01158 } 01159 01160 rb_str_buf_cat2(ret, ">"); 01161 return ret; 01162 } 01163 01164 /* 01165 * call-seq: 01166 * addrinfo.inspect_sockaddr => string 01167 * 01168 * returns a string which shows the sockaddr in _addrinfo_ with human-readable form. 01169 * 01170 * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80" 01171 * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80" 01172 * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock" 01173 * 01174 */ 01175 static VALUE 01176 addrinfo_inspect_sockaddr(VALUE self) 01177 { 01178 return inspect_sockaddr(self, rb_str_new("", 0)); 01179 } 01180 01181 /* :nodoc: */ 01182 static VALUE 01183 addrinfo_mdump(VALUE self) 01184 { 01185 rb_addrinfo_t *rai = get_addrinfo(self); 01186 VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname; 01187 int afamily_int = ai_get_afamily(rai); 01188 ID id; 01189 01190 id = rsock_intern_protocol_family(rai->pfamily); 01191 if (id == 0) 01192 rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily); 01193 pfamily = rb_id2str(id); 01194 01195 if (rai->socktype == 0) 01196 socktype = INT2FIX(0); 01197 else { 01198 id = rsock_intern_socktype(rai->socktype); 01199 if (id == 0) 01200 rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype); 01201 socktype = rb_id2str(id); 01202 } 01203 01204 if (rai->protocol == 0) 01205 protocol = INT2FIX(0); 01206 else if (IS_IP_FAMILY(afamily_int)) { 01207 id = rsock_intern_ipproto(rai->protocol); 01208 if (id == 0) 01209 rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol); 01210 protocol = rb_id2str(id); 01211 } 01212 else { 01213 rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol); 01214 } 01215 01216 canonname = rai->canonname; 01217 01218 inspectname = rai->inspectname; 01219 01220 id = rsock_intern_family(afamily_int); 01221 if (id == 0) 01222 rb_raise(rb_eSocket, "unknown address family: %d", afamily_int); 01223 afamily = rb_id2str(id); 01224 01225 switch(afamily_int) { 01226 #ifdef HAVE_SYS_UN_H 01227 case AF_UNIX: 01228 { 01229 struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr; 01230 char *s, *e; 01231 s = su->sun_path; 01232 e = (char*)su + rai->sockaddr_len; 01233 while (s < e && *(e-1) == '\0') 01234 e--; 01235 sockaddr = rb_str_new(s, e-s); 01236 break; 01237 } 01238 #endif 01239 01240 default: 01241 { 01242 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 01243 int error; 01244 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01245 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01246 NI_NUMERICHOST|NI_NUMERICSERV); 01247 if (error) { 01248 rsock_raise_socket_error("getnameinfo", error); 01249 } 01250 sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf)); 01251 break; 01252 } 01253 } 01254 01255 return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname); 01256 } 01257 01258 /* :nodoc: */ 01259 static VALUE 01260 addrinfo_mload(VALUE self, VALUE ary) 01261 { 01262 VALUE v; 01263 VALUE canonname, inspectname; 01264 int afamily, pfamily, socktype, protocol; 01265 struct sockaddr_storage ss; 01266 socklen_t len; 01267 rb_addrinfo_t *rai; 01268 01269 if (check_addrinfo(self)) 01270 rb_raise(rb_eTypeError, "already initialized socket address"); 01271 01272 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary"); 01273 01274 v = rb_ary_entry(ary, 0); 01275 StringValue(v); 01276 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1) 01277 rb_raise(rb_eTypeError, "unexpected address family"); 01278 01279 v = rb_ary_entry(ary, 2); 01280 StringValue(v); 01281 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1) 01282 rb_raise(rb_eTypeError, "unexpected protocol family"); 01283 01284 v = rb_ary_entry(ary, 3); 01285 if (v == INT2FIX(0)) 01286 socktype = 0; 01287 else { 01288 StringValue(v); 01289 if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1) 01290 rb_raise(rb_eTypeError, "unexpected socktype"); 01291 } 01292 01293 v = rb_ary_entry(ary, 4); 01294 if (v == INT2FIX(0)) 01295 protocol = 0; 01296 else { 01297 StringValue(v); 01298 if (IS_IP_FAMILY(afamily)) { 01299 if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1) 01300 rb_raise(rb_eTypeError, "unexpected protocol"); 01301 } 01302 else { 01303 rb_raise(rb_eTypeError, "unexpected protocol"); 01304 } 01305 } 01306 01307 v = rb_ary_entry(ary, 5); 01308 if (NIL_P(v)) 01309 canonname = Qnil; 01310 else { 01311 StringValue(v); 01312 canonname = v; 01313 } 01314 01315 v = rb_ary_entry(ary, 6); 01316 if (NIL_P(v)) 01317 inspectname = Qnil; 01318 else { 01319 StringValue(v); 01320 inspectname = v; 01321 } 01322 01323 v = rb_ary_entry(ary, 1); 01324 switch(afamily) { 01325 #ifdef HAVE_SYS_UN_H 01326 case AF_UNIX: 01327 { 01328 struct sockaddr_un uaddr; 01329 MEMZERO(&uaddr, struct sockaddr_un, 1); 01330 uaddr.sun_family = AF_UNIX; 01331 01332 StringValue(v); 01333 if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v)) 01334 rb_raise(rb_eSocket, 01335 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 01336 (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path)); 01337 memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v)); 01338 len = (socklen_t)sizeof(uaddr); 01339 memcpy(&ss, &uaddr, len); 01340 break; 01341 } 01342 #endif 01343 01344 default: 01345 { 01346 VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary"); 01347 struct addrinfo *res; 01348 int flags = AI_NUMERICHOST; 01349 #ifdef AI_NUMERICSERV 01350 flags |= AI_NUMERICSERV; 01351 #endif 01352 res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1), 01353 INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol), 01354 INT2NUM(flags), 1); 01355 01356 len = res->ai_addrlen; 01357 memcpy(&ss, res->ai_addr, res->ai_addrlen); 01358 break; 01359 } 01360 } 01361 01362 DATA_PTR(self) = rai = alloc_addrinfo(); 01363 init_addrinfo(rai, (struct sockaddr *)&ss, len, 01364 pfamily, socktype, protocol, 01365 canonname, inspectname); 01366 return self; 01367 } 01368 01369 /* 01370 * call-seq: 01371 * addrinfo.afamily => integer 01372 * 01373 * returns the address family as an integer. 01374 * 01375 * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true 01376 * 01377 */ 01378 static VALUE 01379 addrinfo_afamily(VALUE self) 01380 { 01381 rb_addrinfo_t *rai = get_addrinfo(self); 01382 return INT2NUM(ai_get_afamily(rai)); 01383 } 01384 01385 /* 01386 * call-seq: 01387 * addrinfo.pfamily => integer 01388 * 01389 * returns the protocol family as an integer. 01390 * 01391 * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true 01392 * 01393 */ 01394 static VALUE 01395 addrinfo_pfamily(VALUE self) 01396 { 01397 rb_addrinfo_t *rai = get_addrinfo(self); 01398 return INT2NUM(rai->pfamily); 01399 } 01400 01401 /* 01402 * call-seq: 01403 * addrinfo.socktype => integer 01404 * 01405 * returns the socket type as an integer. 01406 * 01407 * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true 01408 * 01409 */ 01410 static VALUE 01411 addrinfo_socktype(VALUE self) 01412 { 01413 rb_addrinfo_t *rai = get_addrinfo(self); 01414 return INT2NUM(rai->socktype); 01415 } 01416 01417 /* 01418 * call-seq: 01419 * addrinfo.protocol => integer 01420 * 01421 * returns the socket type as an integer. 01422 * 01423 * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true 01424 * 01425 */ 01426 static VALUE 01427 addrinfo_protocol(VALUE self) 01428 { 01429 rb_addrinfo_t *rai = get_addrinfo(self); 01430 return INT2NUM(rai->protocol); 01431 } 01432 01433 /* 01434 * call-seq: 01435 * addrinfo.to_sockaddr => string 01436 * addrinfo.to_s => string 01437 * 01438 * returns the socket address as packed struct sockaddr string. 01439 * 01440 * Addrinfo.tcp("localhost", 80).to_sockaddr 01441 * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" 01442 * 01443 */ 01444 static VALUE 01445 addrinfo_to_sockaddr(VALUE self) 01446 { 01447 rb_addrinfo_t *rai = get_addrinfo(self); 01448 VALUE ret; 01449 ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len); 01450 OBJ_INFECT(ret, self); 01451 return ret; 01452 } 01453 01454 /* 01455 * call-seq: 01456 * addrinfo.canonname => string or nil 01457 * 01458 * returns the canonical name as an string. 01459 * 01460 * nil is returned if no canonical name. 01461 * 01462 * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified. 01463 * 01464 * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME) 01465 * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org:80)> 01466 * p list[0].canonname #=> "carbon.ruby-lang.org" 01467 * 01468 */ 01469 static VALUE 01470 addrinfo_canonname(VALUE self) 01471 { 01472 rb_addrinfo_t *rai = get_addrinfo(self); 01473 return rai->canonname; 01474 } 01475 01476 /* 01477 * call-seq: 01478 * addrinfo.ip? => true or false 01479 * 01480 * returns true if addrinfo is internet (IPv4/IPv6) address. 01481 * returns false otherwise. 01482 * 01483 * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true 01484 * Addrinfo.tcp("::1", 80).ip? #=> true 01485 * Addrinfo.unix("/tmp/sock").ip? #=> false 01486 * 01487 */ 01488 static VALUE 01489 addrinfo_ip_p(VALUE self) 01490 { 01491 rb_addrinfo_t *rai = get_addrinfo(self); 01492 int family = ai_get_afamily(rai); 01493 return IS_IP_FAMILY(family) ? Qtrue : Qfalse; 01494 } 01495 01496 /* 01497 * call-seq: 01498 * addrinfo.ipv4? => true or false 01499 * 01500 * returns true if addrinfo is IPv4 address. 01501 * returns false otherwise. 01502 * 01503 * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true 01504 * Addrinfo.tcp("::1", 80).ipv4? #=> false 01505 * Addrinfo.unix("/tmp/sock").ipv4? #=> false 01506 * 01507 */ 01508 static VALUE 01509 addrinfo_ipv4_p(VALUE self) 01510 { 01511 rb_addrinfo_t *rai = get_addrinfo(self); 01512 return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse; 01513 } 01514 01515 /* 01516 * call-seq: 01517 * addrinfo.ipv6? => true or false 01518 * 01519 * returns true if addrinfo is IPv6 address. 01520 * returns false otherwise. 01521 * 01522 * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false 01523 * Addrinfo.tcp("::1", 80).ipv6? #=> true 01524 * Addrinfo.unix("/tmp/sock").ipv6? #=> false 01525 * 01526 */ 01527 static VALUE 01528 addrinfo_ipv6_p(VALUE self) 01529 { 01530 #ifdef AF_INET6 01531 rb_addrinfo_t *rai = get_addrinfo(self); 01532 return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse; 01533 #else 01534 return Qfalse; 01535 #endif 01536 } 01537 01538 /* 01539 * call-seq: 01540 * addrinfo.unix? => true or false 01541 * 01542 * returns true if addrinfo is UNIX address. 01543 * returns false otherwise. 01544 * 01545 * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false 01546 * Addrinfo.tcp("::1", 80).unix? #=> false 01547 * Addrinfo.unix("/tmp/sock").unix? #=> true 01548 * 01549 */ 01550 static VALUE 01551 addrinfo_unix_p(VALUE self) 01552 { 01553 rb_addrinfo_t *rai = get_addrinfo(self); 01554 #ifdef AF_UNIX 01555 return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse; 01556 #else 01557 return Qfalse; 01558 #endif 01559 } 01560 01561 /* 01562 * call-seq: 01563 * addrinfo.getnameinfo => [nodename, service] 01564 * addrinfo.getnameinfo(flags) => [nodename, service] 01565 * 01566 * returns nodename and service as a pair of strings. 01567 * This converts struct sockaddr in addrinfo to textual representation. 01568 * 01569 * flags should be bitwise OR of Socket::NI_??? constants. 01570 * 01571 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"] 01572 * 01573 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV) 01574 * #=> ["localhost", "80"] 01575 */ 01576 static VALUE 01577 addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self) 01578 { 01579 rb_addrinfo_t *rai = get_addrinfo(self); 01580 VALUE vflags; 01581 char hbuf[1024], pbuf[1024]; 01582 int flags, error; 01583 01584 rb_scan_args(argc, argv, "01", &vflags); 01585 01586 flags = NIL_P(vflags) ? 0 : NUM2INT(vflags); 01587 01588 if (rai->socktype == SOCK_DGRAM) 01589 flags |= NI_DGRAM; 01590 01591 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01592 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01593 flags); 01594 if (error) { 01595 rsock_raise_socket_error("getnameinfo", error); 01596 } 01597 01598 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); 01599 } 01600 01601 /* 01602 * call-seq: 01603 * addrinfo.ip_unpack => [addr, port] 01604 * 01605 * Returns the IP address and port number as 2-element array. 01606 * 01607 * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80] 01608 * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80] 01609 */ 01610 static VALUE 01611 addrinfo_ip_unpack(VALUE self) 01612 { 01613 rb_addrinfo_t *rai = get_addrinfo(self); 01614 int family = ai_get_afamily(rai); 01615 VALUE vflags; 01616 VALUE ret, portstr; 01617 01618 if (!IS_IP_FAMILY(family)) 01619 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01620 01621 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01622 ret = addrinfo_getnameinfo(1, &vflags, self); 01623 portstr = rb_ary_entry(ret, 1); 01624 rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr)))); 01625 return ret; 01626 } 01627 01628 /* 01629 * call-seq: 01630 * addrinfo.ip_address => string 01631 * 01632 * Returns the IP address as a string. 01633 * 01634 * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1" 01635 * Addrinfo.tcp("::1", 80).ip_address #=> "::1" 01636 */ 01637 static VALUE 01638 addrinfo_ip_address(VALUE self) 01639 { 01640 rb_addrinfo_t *rai = get_addrinfo(self); 01641 int family = ai_get_afamily(rai); 01642 VALUE vflags; 01643 VALUE ret; 01644 01645 if (!IS_IP_FAMILY(family)) 01646 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01647 01648 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01649 ret = addrinfo_getnameinfo(1, &vflags, self); 01650 return rb_ary_entry(ret, 0); 01651 } 01652 01653 /* 01654 * call-seq: 01655 * addrinfo.ip_port => port 01656 * 01657 * Returns the port number as an integer. 01658 * 01659 * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80 01660 * Addrinfo.tcp("::1", 80).ip_port #=> 80 01661 */ 01662 static VALUE 01663 addrinfo_ip_port(VALUE self) 01664 { 01665 rb_addrinfo_t *rai = get_addrinfo(self); 01666 int family = ai_get_afamily(rai); 01667 int port; 01668 01669 if (!IS_IP_FAMILY(family)) { 01670 bad_family: 01671 #ifdef AF_INET6 01672 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01673 #else 01674 rb_raise(rb_eSocket, "need IPv4 address"); 01675 #endif 01676 } 01677 01678 switch (family) { 01679 case AF_INET: 01680 if (rai->sockaddr_len != sizeof(struct sockaddr_in)) 01681 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4"); 01682 port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port); 01683 break; 01684 01685 #ifdef AF_INET6 01686 case AF_INET6: 01687 if (rai->sockaddr_len != sizeof(struct sockaddr_in6)) 01688 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6"); 01689 port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port); 01690 break; 01691 #endif 01692 01693 default: 01694 goto bad_family; 01695 } 01696 01697 return INT2NUM(port); 01698 } 01699 01700 static int 01701 extract_in_addr(VALUE self, uint32_t *addrp) 01702 { 01703 rb_addrinfo_t *rai = get_addrinfo(self); 01704 int family = ai_get_afamily(rai); 01705 if (family != AF_INET) return 0; 01706 *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr); 01707 return 1; 01708 } 01709 01710 /* 01711 * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). 01712 * It returns false otherwise. 01713 */ 01714 static VALUE 01715 addrinfo_ipv4_private_p(VALUE self) 01716 { 01717 uint32_t a; 01718 if (!extract_in_addr(self, &a)) return Qfalse; 01719 if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */ 01720 (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */ 01721 (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */ 01722 return Qtrue; 01723 return Qfalse; 01724 } 01725 01726 /* 01727 * Returns true for IPv4 loopback address (127.0.0.0/8). 01728 * It returns false otherwise. 01729 */ 01730 static VALUE 01731 addrinfo_ipv4_loopback_p(VALUE self) 01732 { 01733 uint32_t a; 01734 if (!extract_in_addr(self, &a)) return Qfalse; 01735 if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */ 01736 return Qtrue; 01737 return Qfalse; 01738 } 01739 01740 /* 01741 * Returns true for IPv4 multicast address (224.0.0.0/4). 01742 * It returns false otherwise. 01743 */ 01744 static VALUE 01745 addrinfo_ipv4_multicast_p(VALUE self) 01746 { 01747 uint32_t a; 01748 if (!extract_in_addr(self, &a)) return Qfalse; 01749 if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */ 01750 return Qtrue; 01751 return Qfalse; 01752 } 01753 01754 #ifdef INET6 01755 01756 static struct in6_addr * 01757 extract_in6_addr(VALUE self) 01758 { 01759 rb_addrinfo_t *rai = get_addrinfo(self); 01760 int family = ai_get_afamily(rai); 01761 if (family != AF_INET6) return NULL; 01762 return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01763 } 01764 01765 /* 01766 * Returns true for IPv6 unspecified address (::). 01767 * It returns false otherwise. 01768 */ 01769 static VALUE 01770 addrinfo_ipv6_unspecified_p(VALUE self) 01771 { 01772 struct in6_addr *addr = extract_in6_addr(self); 01773 if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue; 01774 return Qfalse; 01775 } 01776 01777 /* 01778 * Returns true for IPv6 loopback address (::1). 01779 * It returns false otherwise. 01780 */ 01781 static VALUE 01782 addrinfo_ipv6_loopback_p(VALUE self) 01783 { 01784 struct in6_addr *addr = extract_in6_addr(self); 01785 if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue; 01786 return Qfalse; 01787 } 01788 01789 /* 01790 * Returns true for IPv6 multicast address (ff00::/8). 01791 * It returns false otherwise. 01792 */ 01793 static VALUE 01794 addrinfo_ipv6_multicast_p(VALUE self) 01795 { 01796 struct in6_addr *addr = extract_in6_addr(self); 01797 if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue; 01798 return Qfalse; 01799 } 01800 01801 /* 01802 * Returns true for IPv6 link local address (ff80::/10). 01803 * It returns false otherwise. 01804 */ 01805 static VALUE 01806 addrinfo_ipv6_linklocal_p(VALUE self) 01807 { 01808 struct in6_addr *addr = extract_in6_addr(self); 01809 if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue; 01810 return Qfalse; 01811 } 01812 01813 /* 01814 * Returns true for IPv6 site local address (ffc0::/10). 01815 * It returns false otherwise. 01816 */ 01817 static VALUE 01818 addrinfo_ipv6_sitelocal_p(VALUE self) 01819 { 01820 struct in6_addr *addr = extract_in6_addr(self); 01821 if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue; 01822 return Qfalse; 01823 } 01824 01825 /* 01826 * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80). 01827 * It returns false otherwise. 01828 */ 01829 static VALUE 01830 addrinfo_ipv6_v4mapped_p(VALUE self) 01831 { 01832 struct in6_addr *addr = extract_in6_addr(self); 01833 if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue; 01834 return Qfalse; 01835 } 01836 01837 /* 01838 * Returns true for IPv4-compatible IPv6 address (::/80). 01839 * It returns false otherwise. 01840 */ 01841 static VALUE 01842 addrinfo_ipv6_v4compat_p(VALUE self) 01843 { 01844 struct in6_addr *addr = extract_in6_addr(self); 01845 if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue; 01846 return Qfalse; 01847 } 01848 01849 /* 01850 * Returns true for IPv6 multicast node-local scope address. 01851 * It returns false otherwise. 01852 */ 01853 static VALUE 01854 addrinfo_ipv6_mc_nodelocal_p(VALUE self) 01855 { 01856 struct in6_addr *addr = extract_in6_addr(self); 01857 if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue; 01858 return Qfalse; 01859 } 01860 01861 /* 01862 * Returns true for IPv6 multicast link-local scope address. 01863 * It returns false otherwise. 01864 */ 01865 static VALUE 01866 addrinfo_ipv6_mc_linklocal_p(VALUE self) 01867 { 01868 struct in6_addr *addr = extract_in6_addr(self); 01869 if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue; 01870 return Qfalse; 01871 } 01872 01873 /* 01874 * Returns true for IPv6 multicast site-local scope address. 01875 * It returns false otherwise. 01876 */ 01877 static VALUE 01878 addrinfo_ipv6_mc_sitelocal_p(VALUE self) 01879 { 01880 struct in6_addr *addr = extract_in6_addr(self); 01881 if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue; 01882 return Qfalse; 01883 } 01884 01885 /* 01886 * Returns true for IPv6 multicast organization-local scope address. 01887 * It returns false otherwise. 01888 */ 01889 static VALUE 01890 addrinfo_ipv6_mc_orglocal_p(VALUE self) 01891 { 01892 struct in6_addr *addr = extract_in6_addr(self); 01893 if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue; 01894 return Qfalse; 01895 } 01896 01897 /* 01898 * Returns true for IPv6 multicast global scope address. 01899 * It returns false otherwise. 01900 */ 01901 static VALUE 01902 addrinfo_ipv6_mc_global_p(VALUE self) 01903 { 01904 struct in6_addr *addr = extract_in6_addr(self); 01905 if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue; 01906 return Qfalse; 01907 } 01908 01909 /* 01910 * Returns IPv4 address of IPv4 mapped/compatible IPv6 address. 01911 * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address. 01912 * 01913 * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01914 * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01915 * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil 01916 * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil 01917 * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil 01918 */ 01919 static VALUE 01920 addrinfo_ipv6_to_ipv4(VALUE self) 01921 { 01922 rb_addrinfo_t *rai = get_addrinfo(self); 01923 struct in6_addr *addr; 01924 int family = ai_get_afamily(rai); 01925 if (family != AF_INET6) return Qnil; 01926 addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01927 if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) { 01928 struct sockaddr_in sin4; 01929 MEMZERO(&sin4, struct sockaddr_in, 1); 01930 sin4.sin_family = AF_INET; 01931 SET_SIN_LEN(&sin4, sizeof(sin4)); 01932 memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr)); 01933 return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4), 01934 PF_INET, rai->socktype, rai->protocol, 01935 rai->canonname, rai->inspectname); 01936 } 01937 else { 01938 return Qnil; 01939 } 01940 } 01941 01942 #endif 01943 01944 #ifdef HAVE_SYS_UN_H 01945 /* 01946 * call-seq: 01947 * addrinfo.unix_path => path 01948 * 01949 * Returns the socket path as a string. 01950 * 01951 * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock" 01952 */ 01953 static VALUE 01954 addrinfo_unix_path(VALUE self) 01955 { 01956 rb_addrinfo_t *rai = get_addrinfo(self); 01957 int family = ai_get_afamily(rai); 01958 struct sockaddr_un *addr; 01959 char *s, *e; 01960 01961 if (family != AF_UNIX) 01962 rb_raise(rb_eSocket, "need AF_UNIX address"); 01963 01964 addr = (struct sockaddr_un *)&rai->addr; 01965 01966 s = addr->sun_path; 01967 e = (char*)addr + rai->sockaddr_len; 01968 if (e < s) 01969 rb_raise(rb_eSocket, "too short AF_UNIX address"); 01970 if (addr->sun_path + sizeof(addr->sun_path) < e) 01971 rb_raise(rb_eSocket, "too long AF_UNIX address"); 01972 while (s < e && *(e-1) == '\0') 01973 e--; 01974 return rb_str_new(s, e-s); 01975 } 01976 #endif 01977 01978 /* 01979 * call-seq: 01980 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...] 01981 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...] 01982 * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...] 01983 * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...] 01984 * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...] 01985 * 01986 * returns a list of addrinfo objects as an array. 01987 * 01988 * This method converts nodename (hostname) and service (port) to addrinfo. 01989 * Since the conversion is not unique, the result is a list of addrinfo objects. 01990 * 01991 * nodename or service can be nil if no conversion intended. 01992 * 01993 * family, socktype and protocol are hint for preferred protocol. 01994 * If the result will be used for a socket with SOCK_STREAM, 01995 * SOCK_STREAM should be specified as socktype. 01996 * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM. 01997 * If they are omitted or nil is given, the result is not restricted. 01998 * 01999 * Similarly, PF_INET6 as family restricts for IPv6. 02000 * 02001 * flags should be bitwise OR of Socket::AI_??? constants. 02002 * 02003 * Note that socktype should be specified whenever application knows the usage of the address. 02004 * Some platform causes an error when socktype is omitted and servname is specified as an integer 02005 * because some port numbers, 512 for example, are ambiguous without socktype. 02006 * 02007 * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM) 02008 * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net:80)>, 02009 * # #<Addrinfo: [2001:200:0:8002:203:47ff:fea5:3085]:80 TCP (www.kame.net:80)>] 02010 * 02011 */ 02012 static VALUE 02013 addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self) 02014 { 02015 VALUE node, service, family, socktype, protocol, flags; 02016 02017 rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags); 02018 return addrinfo_list_new(node, service, family, socktype, protocol, flags); 02019 } 02020 02021 /* 02022 * call-seq: 02023 * Addrinfo.ip(host) => addrinfo 02024 * 02025 * returns an addrinfo object for IP address. 02026 * 02027 * The port, socktype, protocol of the result is filled by zero. 02028 * So, it is not appropriate to create a socket. 02029 * 02030 * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)> 02031 */ 02032 static VALUE 02033 addrinfo_s_ip(VALUE self, VALUE host) 02034 { 02035 VALUE ret; 02036 rb_addrinfo_t *rai; 02037 ret = addrinfo_firstonly_new(host, Qnil, 02038 INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0)); 02039 rai = get_addrinfo(ret); 02040 rai->socktype = 0; 02041 rai->protocol = 0; 02042 return ret; 02043 } 02044 02045 /* 02046 * call-seq: 02047 * Addrinfo.tcp(host, port) => addrinfo 02048 * 02049 * returns an addrinfo object for TCP address. 02050 * 02051 * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)> 02052 */ 02053 static VALUE 02054 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port) 02055 { 02056 return addrinfo_firstonly_new(host, port, 02057 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0)); 02058 } 02059 02060 /* 02061 * call-seq: 02062 * Addrinfo.udp(host, port) => addrinfo 02063 * 02064 * returns an addrinfo object for UDP address. 02065 * 02066 * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)> 02067 */ 02068 static VALUE 02069 addrinfo_s_udp(VALUE self, VALUE host, VALUE port) 02070 { 02071 return addrinfo_firstonly_new(host, port, 02072 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0)); 02073 } 02074 02075 #ifdef HAVE_SYS_UN_H 02076 02077 /* 02078 * call-seq: 02079 * Addrinfo.unix(path [, socktype]) => addrinfo 02080 * 02081 * returns an addrinfo object for UNIX socket address. 02082 * 02083 * _socktype_ specifies the socket type. 02084 * If it is omitted, :STREAM is used. 02085 * 02086 * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM> 02087 * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM> 02088 */ 02089 static VALUE 02090 addrinfo_s_unix(int argc, VALUE *argv, VALUE self) 02091 { 02092 VALUE path, vsocktype, addr; 02093 int socktype; 02094 rb_addrinfo_t *rai; 02095 02096 rb_scan_args(argc, argv, "11", &path, &vsocktype); 02097 02098 if (NIL_P(vsocktype)) 02099 socktype = SOCK_STREAM; 02100 else 02101 socktype = rsock_socktype_arg(vsocktype); 02102 02103 addr = addrinfo_s_allocate(rb_cAddrinfo); 02104 DATA_PTR(addr) = rai = alloc_addrinfo(); 02105 init_unix_addrinfo(rai, path, socktype); 02106 OBJ_INFECT(addr, path); 02107 return addr; 02108 } 02109 02110 #endif 02111 02112 VALUE 02113 rsock_sockaddr_string_value(volatile VALUE *v) 02114 { 02115 VALUE val = *v; 02116 if (IS_ADDRINFO(val)) { 02117 *v = addrinfo_to_sockaddr(val); 02118 } 02119 StringValue(*v); 02120 return *v; 02121 } 02122 02123 char * 02124 rsock_sockaddr_string_value_ptr(volatile VALUE *v) 02125 { 02126 rsock_sockaddr_string_value(v); 02127 return RSTRING_PTR(*v); 02128 } 02129 02130 VALUE 02131 rb_check_sockaddr_string_type(VALUE val) 02132 { 02133 if (IS_ADDRINFO(val)) 02134 return addrinfo_to_sockaddr(val); 02135 return rb_check_string_type(val); 02136 } 02137 02138 VALUE 02139 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len) 02140 { 02141 int family; 02142 int socktype; 02143 int ret; 02144 socklen_t optlen = (socklen_t)sizeof(socktype); 02145 02146 /* assumes protocol family and address family are identical */ 02147 family = get_afamily(addr, len); 02148 02149 ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen); 02150 if (ret == -1) { 02151 rb_sys_fail("getsockopt(SO_TYPE)"); 02152 } 02153 02154 return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil); 02155 } 02156 02157 VALUE 02158 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) 02159 { 02160 rb_io_t *fptr; 02161 02162 switch (TYPE(io)) { 02163 case T_FIXNUM: 02164 return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len); 02165 02166 case T_BIGNUM: 02167 return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len); 02168 02169 case T_FILE: 02170 GetOpenFile(io, fptr); 02171 return rsock_fd_socket_addrinfo(fptr->fd, addr, len); 02172 02173 default: 02174 rb_raise(rb_eTypeError, "neither IO nor file descriptor"); 02175 } 02176 } 02177 02178 /* 02179 * Addrinfo class 02180 */ 02181 void 02182 rsock_init_addrinfo(void) 02183 { 02184 /* 02185 * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This 02186 * structure identifies an Internet host and a service. 02187 */ 02188 rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData); 02189 rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); 02190 rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); 02191 rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0); 02192 rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0); 02193 rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1); 02194 rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1); 02195 rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2); 02196 rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2); 02197 #ifdef HAVE_SYS_UN_H 02198 rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1); 02199 #endif 02200 02201 rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0); 02202 rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0); 02203 rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0); 02204 rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0); 02205 rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0); 02206 02207 rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0); 02208 rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0); 02209 rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0); 02210 02211 rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0); 02212 rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0); 02213 rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0); 02214 rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0); 02215 02216 rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0); 02217 rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0); 02218 rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0); 02219 02220 #ifdef INET6 02221 rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0); 02222 rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0); 02223 rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0); 02224 rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0); 02225 rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0); 02226 rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0); 02227 rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0); 02228 rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0); 02229 rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0); 02230 rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0); 02231 rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0); 02232 rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0); 02233 02234 rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0); 02235 #endif 02236 02237 #ifdef HAVE_SYS_UN_H 02238 rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0); 02239 #endif 02240 02241 rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0); 02242 rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */ 02243 02244 rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1); 02245 02246 rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0); 02247 rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1); 02248 } 02249
1.7.6.1