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 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
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
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:
00858 #ifdef INET6
00859 case AF_INET6:
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:
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
00972
00973
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 &&
01017 t < e &&
01018 p == e) {
01019 if (s == t)
01020 rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
01021 else if (s[0] == '/')
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
01059
01060
01061
01062
01063
01064
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
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147 static VALUE
01148 addrinfo_inspect_sockaddr(VALUE self)
01149 {
01150 return inspect_sockaddr(self, rb_str_new("", 0));
01151 }
01152
01153
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
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
01341
01342
01343
01344
01345
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
01357
01358
01359
01360
01361
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
01373
01374
01375
01376
01377
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
01389
01390
01391
01392
01393
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
01405
01406
01407
01408
01409
01410
01411
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
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
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
01448
01449
01450
01451
01452
01453
01454
01455
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
01468
01469
01470
01471
01472
01473
01474
01475
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
01487
01488
01489
01490
01491
01492
01493
01494
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
01510
01511
01512
01513
01514
01515
01516
01517
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
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
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
01573
01574
01575
01576
01577
01578
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
01600
01601
01602
01603
01604
01605
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
01625
01626
01627
01628
01629
01630
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
01682
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 ||
01690 (a & 0xfff00000) == 0xac100000 ||
01691 (a & 0xffff0000) == 0xc0a80000)
01692 return Qtrue;
01693 return Qfalse;
01694 }
01695
01696
01697
01698
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)
01706 return Qtrue;
01707 return Qfalse;
01708 }
01709
01710
01711
01712
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)
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
01737
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
01749
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
01761
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
01773
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
01785
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
01797
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
01809
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
01821
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
01833
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
01845
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
01857
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
01869
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
01881
01882
01883
01884
01885
01886
01887
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
01917
01918
01919
01920
01921
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
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
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
01993
01994
01995
01996
01997
01998
01999
02000
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
02017
02018
02019
02020
02021
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
02032
02033
02034
02035
02036
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
02049
02050
02051
02052
02053
02054
02055
02056
02057
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
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
02150
02151 void
02152 rsock_init_addrinfo(void)
02153 {
02154
02155
02156
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);
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