41 #include "ruby/config.h"
43 #include RUBY_EXTCONF_H
45 #include <sys/types.h>
47 #include <sys/param.h>
48 #if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
49 # include <net/socket.h>
51 # include <sys/socket.h>
53 #include <netinet/in.h>
54 #if defined(HAVE_ARPA_INET_H)
55 #include <arpa/inet.h>
57 #if defined(HAVE_ARPA_NAMESER_H)
58 #include <arpa/nameser.h>
61 #if defined(HAVE_RESOLV_H)
83 #ifndef HAVE_TYPE_SOCKLEN_T
96 static int translate =
NO;
97 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
125 {PF_INET6,
sizeof(
struct in6_addr),
126 sizeof(struct sockaddr_in6),
127 offsetof(struct sockaddr_in6, sin6_addr),
128 in6_addrany, in6_loopback},
133 {
PF_INET,
sizeof(
struct in_addr),
134 sizeof(struct sockaddr_in),
135 offsetof(struct sockaddr_in, sin_addr),
136 in_addrany, in_loopback},
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.",
171 #define GET_CANONNAME(ai, str) \
172 if (pai->ai_flags & AI_CANONNAME) {\
173 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
174 strcpy((ai)->ai_canonname, (str));\
181 #define GET_AI(ai, afd, addr, port) {\
183 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
184 ((afd)->a_socklen)))\
189 memcpy((ai), pai, sizeof(struct addrinfo));\
190 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
191 (ai)->ai_family = (afd)->a_af;\
192 (ai)->ai_addrlen = (afd)->a_socklen;\
193 INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\
194 ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\
195 p = (char *)((ai)->ai_addr);\
196 memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
199 #define ERR(err) { error = (err); goto bad; }
201 #ifndef HAVE_GAI_STRERROR
202 #ifdef GAI_STRERROR_CONST
208 if (ecode < 0 || ecode >
EAI_MAX)
210 return (
char *)ai_errlist[ecode];
225 }
while ((ai = next) !=
NULL);
240 #ifndef HAVE_INET_PTON
247 #ifdef HAVE_INET_ATON
248 if (!inet_aton(hostname, &in))
254 if (sscanf(hostname,
"%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
255 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
256 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
258 ((
long) d1 << 24) | ((
long) d2 << 16) |
259 ((
long) d3 << 8) | ((
long) d4 << 0));
265 memcpy(pton, &in,
sizeof(in));
283 static int firsttime = 1;
289 if (q &&
inet_pton(AF_INET6, q, &faith_prefix) == 1)
310 if (hostname ==
NULL && servname ==
NULL)
329 memcpy(pai, hints,
sizeof(*pai));
342 #if defined(SOCK_RAW)
348 #if defined(SOCK_RAW)
380 port = htons((
unsigned short)atoi(servname));
399 fprintf(stderr,
"panic!\n");
402 if ((sp = getservbyname((
char*)servname, proto)) ==
NULL)
406 if (strcmp(sp->s_proto,
"udp") == 0) {
409 }
else if (strcmp(sp->s_proto,
"tcp") == 0) {
422 if (hostname ==
NULL) {
426 for (afd = &
afdl[0]; afd->
a_af; afd++) {
436 s = socket(afd->
a_af, SOCK_DGRAM, 0);
439 #if defined(__BEOS__)
474 switch (
afdl[i].a_af) {
476 v4a = ((
struct in_addr *)pton)->s_addr;
485 pfx = ((
struct in6_addr *)pton)->s6_addr[0];
486 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
547 hp = getipnodebyaddr(addr, afd->
a_addrlen, afd->
a_af, &h_error);
549 hp = gethostbyaddr((
char*)addr, afd->
a_addrlen, AF_INET);
551 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
552 GET_AI(cur, afd, hp->h_addr_list[0], port);
555 GET_AI(cur, afd, numaddr, port);
583 int i, error = 0, h_error;
591 hp = getipnodebyname(hostname, AF_INET6,
597 hp = gethostbyname((
char*)hostname);
617 if ((hp->h_name ==
NULL) || (hp->h_name[0] == 0) ||
618 (hp->h_addr_list[0] ==
NULL))
621 for (i = 0; (ap = hp->h_addr_list[
i]) !=
NULL; i++) {
625 afd = &
afdl[N_INET6];
636 if (IN6_IS_ADDR_V4MAPPED((
struct in6_addr *)ap)) {
637 ap +=
sizeof(
struct in6_addr) -
638 sizeof(struct in_addr);
641 afd = &
afdl[N_INET6];
646 if (translate && afd->
a_af == AF_INET) {
647 struct in6_addr *in6;
651 memcpy(&in6->s6_addr, &faith_prefix,
652 sizeof(
struct in6_addr) -
sizeof(
struct in_addr));
653 memcpy(&in6->s6_addr +
sizeof(
struct in_addr), ap,
654 sizeof(
struct in_addr));
658 if (cur == &sentinel) {
static const char *const ai_errlist[]
size_t strlen(const char *)
static const char in_addrany[]
#define GET_CANONNAME(ai, str)
static int get_addr(const char *hostname, int af, struct addrinfo **res, struct addrinfo *pai, int port0)
static int get_name(const char *addr, const struct afd *afd, struct addrinfo **res, char *numaddr, struct addrinfo *pai, int port0)
static const char in_loopback[]
#define GET_AI(ai, afd, addr, port)
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
char * gai_strerror(int ecode)
void freeaddrinfo(struct addrinfo *ai)
static int inet_pton(int af, const char *hostname, void *pton)
static const char in6_loopback[]
static int str_isnumber(const char *p)
static const char in6_addrany[]
#define IN_EXPERIMENTAL(i)
struct addrinfo * ai_next
struct sockaddr * ai_addr