00001
00002
00003
00004
00005
00006
00007
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
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
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
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
00165
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
00459 return (socklen_t) sizeof(sa_family_t);
00460 }
00461 else if (RSTRING_PTR(path)[0] == '\0') {
00462
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
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
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:
00895 #ifdef INET6
00896 case AF_INET6:
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:
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
01009
01010
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) {
01053 if (s[0] != '/')
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
01087
01088
01089
01090
01091
01092
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
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 static VALUE
01176 addrinfo_inspect_sockaddr(VALUE self)
01177 {
01178 return inspect_sockaddr(self, rb_str_new("", 0));
01179 }
01180
01181
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
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
01371
01372
01373
01374
01375
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
01387
01388
01389
01390
01391
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
01403
01404
01405
01406
01407
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
01419
01420
01421
01422
01423
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
01435
01436
01437
01438
01439
01440
01441
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
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
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
01478
01479
01480
01481
01482
01483
01484
01485
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
01498
01499
01500
01501
01502
01503
01504
01505
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
01517
01518
01519
01520
01521
01522
01523
01524
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
01540
01541
01542
01543
01544
01545
01546
01547
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
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
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
01603
01604
01605
01606
01607
01608
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
01630
01631
01632
01633
01634
01635
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
01655
01656
01657
01658
01659
01660
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
01712
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 ||
01720 (a & 0xfff00000) == 0xac100000 ||
01721 (a & 0xffff0000) == 0xc0a80000)
01722 return Qtrue;
01723 return Qfalse;
01724 }
01725
01726
01727
01728
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)
01736 return Qtrue;
01737 return Qfalse;
01738 }
01739
01740
01741
01742
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)
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
01767
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
01779
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
01791
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
01803
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
01815
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
01827
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
01839
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
01851
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
01863
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
01875
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
01887
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
01899
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
01911
01912
01913
01914
01915
01916
01917
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
01947
01948
01949
01950
01951
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
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
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
02023
02024
02025
02026
02027
02028
02029
02030
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
02047
02048
02049
02050
02051
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
02062
02063
02064
02065
02066
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
02079
02080
02081
02082
02083
02084
02085
02086
02087
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
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
02180
02181 void
02182 rsock_init_addrinfo(void)
02183 {
02184
02185
02186
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);
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