41 #include "ruby/config.h"
43 #include RUBY_EXTCONF_H
45 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #if defined(HAVE_ARPA_INET_H)
51 #include <arpa/inet.h>
53 #if defined(HAVE_ARPA_NAMESER_H)
54 #include <arpa/nameser.h>
57 #if defined(HAVE_RESOLV_H)
65 #if defined(_MSC_VER) && _MSC_VER <= 1200
82 #ifndef HAVE_TYPE_SOCKLEN_T
95 static int translate =
NO;
96 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
99 static const char in_addrany[] = { 0, 0, 0, 0 };
100 static const char in6_addrany[] = {
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
103 static const char in_loopback[] = { 127, 0, 0, 1 };
104 static const char in6_loopback[] = {
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
114 static const struct afd {
119 const char *a_addrany;
120 const char *a_loopback;
124 {PF_INET6,
sizeof(
struct in6_addr),
125 sizeof(struct sockaddr_in6),
126 offsetof(struct sockaddr_in6, sin6_addr),
127 in6_addrany, in6_loopback},
132 {
PF_INET,
sizeof(
struct in_addr),
133 sizeof(struct sockaddr_in),
134 offsetof(struct sockaddr_in, sin_addr),
135 in_addrany, in_loopback},
145 static int get_name
__P((
const char *,
const struct afd *,
148 static int get_addr
__P((
const char *,
int,
struct addrinfo **,
150 static int str_isnumber
__P((
const char *));
152 #ifndef HAVE_GAI_STRERROR
153 static const char *
const ai_errlist[] = {
155 "address family for hostname not supported.",
156 "temporary failure in name resolution.",
157 "invalid value for ai_flags.",
158 "non-recoverable failure in name resolution.",
159 "ai_family not supported.",
160 "memory allocation failure.",
161 "no address associated with hostname.",
162 "hostname nor servname provided, or not known.",
163 "servname not supported for ai_socktype.",
164 "ai_socktype not supported.",
165 "system error returned in errno.",
166 "invalid value for hints.",
167 "resolved protocol is unknown.",
172 #define GET_CANONNAME(ai, str) \
173 if (pai->ai_flags & AI_CANONNAME) {\
174 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
175 strcpy((ai)->ai_canonname, (str));\
182 #define GET_AI(ai, afd, addr, port) {\
184 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
185 ((afd)->a_socklen)))\
190 memcpy((ai), pai, sizeof(struct addrinfo));\
191 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
192 (ai)->ai_family = (afd)->a_af;\
193 (ai)->ai_addrlen = (afd)->a_socklen;\
194 INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\
195 ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\
196 p = (char *)((ai)->ai_addr);\
197 memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
200 #define ERR(err) { error = (err); goto bad; }
202 #ifndef HAVE_GAI_STRERROR
203 #ifdef GAI_STRERROR_CONST
209 if (ecode < 0 || ecode >
EAI_MAX)
211 return (
char *)ai_errlist[ecode];
226 }
while ((ai = next) !=
NULL);
230 str_isnumber(
const char *p)
241 #ifndef HAVE_INET_PTON
244 inet_pton(
int af,
const char *hostname,
void *pton)
248 #ifdef HAVE_INET_ATON
249 if (!inet_aton(hostname, &in))
255 if (
sscanf(hostname,
"%d.%d.%d.%d%c", &
d1, &d2, &d3, &d4, &ch) == 4 &&
256 0 <=
d1 &&
d1 <= 255 && 0 <= d2 && d2 <= 255 &&
257 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
259 ((
long)
d1 << 24) | ((
long) d2 << 16) |
260 ((
long) d3 << 8) | ((
long) d4 << 0));
266 memcpy(pton, &in,
sizeof(in));
284 static int firsttime = 1;
290 if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
311 if (hostname ==
NULL && servname ==
NULL)
330 memcpy(pai, hints,
sizeof(*pai));
343 #if defined(SOCK_RAW)
349 #if defined(SOCK_RAW)
375 if (str_isnumber(servname)) {
381 port = htons((
unsigned short)
atoi(servname));
403 if ((sp = getservbyname((
char*)servname,
proto)) ==
NULL)
407 if (
strcmp(sp->s_proto,
"udp") == 0) {
410 }
else if (
strcmp(sp->s_proto,
"tcp") == 0) {
423 if (hostname ==
NULL) {
424 const struct afd *afd;
427 for (afd = &afdl[0]; afd->a_af; afd++) {
437 s = socket(afd->a_af, SOCK_DGRAM, 0);
465 for (
i = 0; afdl[
i].a_af;
i++) {
466 if (inet_pton(afdl[
i].a_af, hostname, pton)) {
472 switch (afdl[
i].a_af) {
474 v4a = ((
struct in_addr *)pton)->s_addr;
483 pfx = ((
struct in6_addr *)pton)->s6_addr[0];
484 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
505 get_name(pton, &afdl[
i], &
top, pton, pai, port);
534 get_name(
const char *addr,
const struct afd *afd,
struct addrinfo **res,
char *numaddr,
struct addrinfo *pai,
int port0)
545 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
547 hp = gethostbyaddr((
char*)addr, afd->a_addrlen, AF_INET);
549 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
550 GET_AI(cur, afd, hp->h_addr_list[0], port);
553 GET_AI(cur, afd, numaddr, port);
574 get_addr(
const char *hostname,
int af,
struct addrinfo **res,
struct addrinfo *pai,
int port0)
580 const struct afd *afd;
581 int i,
error = 0, h_error;
585 sentinel.ai_next =
NULL;
589 hp = getipnodebyname(hostname, AF_INET6,
595 hp = gethostbyname((
char*)hostname);
615 if ((hp->h_name ==
NULL) || (hp->h_name[0] == 0) ||
616 (hp->h_addr_list[0] ==
NULL))
619 for (
i = 0; (ap = hp->h_addr_list[
i]) !=
NULL;
i++) {
623 afd = &afdl[N_INET6];
634 if (IN6_IS_ADDR_V4MAPPED((
struct in6_addr *)ap)) {
635 ap +=
sizeof(
struct in6_addr) -
636 sizeof(struct in_addr);
639 afd = &afdl[N_INET6];
644 if (translate && afd->a_af == AF_INET) {
645 struct in6_addr *in6;
649 memcpy(&in6->s6_addr, &faith_prefix,
650 sizeof(
struct in6_addr) -
sizeof(
struct in_addr));
651 memcpy(&in6->s6_addr +
sizeof(
struct in_addr), ap,
652 sizeof(
struct in_addr));
656 if (cur == &sentinel) {