]>
git.proxmox.com Git - wasi-libc.git/blob - libc-top-half/musl/src/network/getaddrinfo.c
2 #include <sys/socket.h>
3 #include <netinet/in.h>
12 int getaddrinfo(const char *restrict host
, const char *restrict serv
, const struct addrinfo
*restrict hint
, struct addrinfo
**restrict res
)
14 struct service ports
[MAXSERVS
];
15 struct address addrs
[MAXADDRS
];
16 char canon
[256], *outcanon
;
17 int nservs
, naddrs
, nais
, canon_len
, i
, j
, k
;
18 int family
= AF_UNSPEC
, flags
= 0, proto
= 0, socktype
= 0;
21 if (!host
&& !serv
) return EAI_NONAME
;
24 family
= hint
->ai_family
;
25 flags
= hint
->ai_flags
;
26 proto
= hint
->ai_protocol
;
27 socktype
= hint
->ai_socktype
;
29 const int mask
= AI_PASSIVE
| AI_CANONNAME
| AI_NUMERICHOST
|
30 AI_V4MAPPED
| AI_ALL
| AI_ADDRCONFIG
| AI_NUMERICSERV
;
31 if ((flags
& mask
) != flags
)
44 if (flags
& AI_ADDRCONFIG
) {
45 /* Define the "an address is configured" condition for address
46 * families via ability to create a socket for the family plus
47 * routability of the loopback address for the family. */
48 static const struct sockaddr_in lo4
= {
49 .sin_family
= AF_INET
, .sin_port
= 65535,
50 .sin_addr
.s_addr
= __BYTE_ORDER
== __BIG_ENDIAN
51 ? 0x7f000001 : 0x0100007f
53 static const struct sockaddr_in6 lo6
= {
54 .sin6_family
= AF_INET6
, .sin6_port
= 65535,
55 .sin6_addr
= IN6ADDR_LOOPBACK_INIT
57 int tf
[2] = { AF_INET
, AF_INET6
};
58 const void *ta
[2] = { &lo4
, &lo6
};
59 socklen_t tl
[2] = { sizeof lo4
, sizeof lo6
};
61 if (family
==tf
[1-i
]) continue;
62 int s
= socket(tf
[i
], SOCK_CLOEXEC
|SOCK_DGRAM
,
66 pthread_setcancelstate(
67 PTHREAD_CANCEL_DISABLE
, &cs
);
68 int r
= connect(s
, ta
[i
], tl
[i
]);
69 pthread_setcancelstate(cs
, 0);
83 if (family
== tf
[i
]) return EAI_NONAME
;
88 nservs
= __lookup_serv(ports
, serv
, proto
, socktype
, flags
);
89 if (nservs
< 0) return nservs
;
91 naddrs
= __lookup_name(addrs
, canon
, host
, family
, flags
);
92 if (naddrs
< 0) return naddrs
;
94 nais
= nservs
* naddrs
;
95 canon_len
= strlen(canon
);
96 out
= calloc(1, nais
* sizeof(*out
) + canon_len
+ 1);
97 if (!out
) return EAI_MEMORY
;
100 outcanon
= (void *)&out
[nais
];
101 memcpy(outcanon
, canon
, canon_len
+1);
106 for (k
=i
=0; i
<naddrs
; i
++) for (j
=0; j
<nservs
; j
++, k
++) {
108 out
[k
].ai
= (struct addrinfo
){
109 .ai_family
= addrs
[i
].family
,
110 .ai_socktype
= ports
[j
].socktype
,
111 .ai_protocol
= ports
[j
].proto
,
112 .ai_addrlen
= addrs
[i
].family
== AF_INET
113 ? sizeof(struct sockaddr_in
)
114 : sizeof(struct sockaddr_in6
),
115 .ai_addr
= (void *)&out
[k
].sa
,
116 .ai_canonname
= outcanon
,
117 .ai_next
= &out
[k
+1].ai
};
118 switch (addrs
[i
].family
) {
120 out
[k
].sa
.sin
.sin_family
= AF_INET
;
121 out
[k
].sa
.sin
.sin_port
= htons(ports
[j
].port
);
122 memcpy(&out
[k
].sa
.sin
.sin_addr
, &addrs
[i
].addr
, 4);
125 out
[k
].sa
.sin6
.sin6_family
= AF_INET6
;
126 out
[k
].sa
.sin6
.sin6_port
= htons(ports
[j
].port
);
127 out
[k
].sa
.sin6
.sin6_scope_id
= addrs
[i
].scopeid
;
128 memcpy(&out
[k
].sa
.sin6
.sin6_addr
, &addrs
[i
].addr
, 16);
133 out
[nais
-1].ai
.ai_next
= 0;