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