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