/* Extra slots needed for storing canonical name */
#define EXTRA ((256+sizeof(struct aibuf)-1)/sizeof(struct aibuf))
-int getaddrinfo(const char *host, const char *serv, const struct addrinfo *hint, struct addrinfo **res)
+int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res)
{
int flags = hint ? hint->ai_flags : 0;
int family = hint ? hint->ai_family : AF_UNSPEC;
if (serv) {
if (!*serv) return EAI_SERVICE;
port = strtoul(serv, &z, 10);
- if (!*z && port > 65535) return EAI_SERVICE;
- if (!port) {
+ if (*z) {
size_t servlen = strlen(serv);
- char protname[4];
+ char *end = line;
if (flags & AI_NUMERICSERV) return EAI_SERVICE;
f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf);
if (!f) return EAI_SERVICE;
while (fgets(line, sizeof line, f)) {
- if (strncmp(line, serv, servlen))
+ if (strncmp(line, serv, servlen) || !isspace(line[servlen]))
continue;
- if (sscanf(line+servlen, "%lu/%3s", &port, protname) < 2)
- continue;
- if (strcmp(protname, proto==IPPROTO_UDP ? "udp" : "tcp"))
+ port = strtoul(line+servlen, &end, 10);
+ if (strncmp(end, proto==IPPROTO_UDP ? "/udp" : "/tcp", 4))
continue;
break;
}
__fclose_ca(f);
if (feof(f)) return EAI_SERVICE;
}
+ if (port > 65535) return EAI_SERVICE;
port = htons(port);
}
if (!host) {
- if (family == AF_UNSPEC) family = AF_INET;
- buf = calloc(sizeof *buf, 1+EXTRA);
+ if (family == AF_UNSPEC) {
+ cnt = 2; family = AF_INET;
+ } else {
+ cnt = 1;
+ }
+ buf = calloc(sizeof *buf, cnt);
if (!buf) return EAI_MEMORY;
- buf->ai.ai_protocol = proto;
- buf->ai.ai_socktype = type;
- buf->ai.ai_addr = (void *)&buf->sa;
- buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
- buf->ai.ai_family = family;
- buf->sa.sin.sin_family = family;
- buf->sa.sin.sin_port = port;
- if (!(flags & AI_PASSIVE)) {
- if (family == AF_INET) {
- 0[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=127;
- 3[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=1;
- } else buf[0].sa.sin6.sin6_addr.s6_addr[15] = 1;
+ for (i=0; i<cnt; i++) {
+ if (i) family = AF_INET6;
+ buf[i].ai.ai_protocol = proto;
+ buf[i].ai.ai_socktype = type;
+ buf[i].ai.ai_addr = (void *)&buf[i].sa;
+ buf[i].ai.ai_addrlen = family==AF_INET6
+ ? sizeof sa.sin6 : sizeof sa.sin;
+ buf[i].ai.ai_family = family;
+ buf[i].sa.sin.sin_family = family;
+ buf[i].sa.sin.sin_port = port;
+ if (i+1<cnt) buf[i].ai.ai_next = &buf[i+1].ai;
+ if (!(flags & AI_PASSIVE)) {
+ if (family == AF_INET) {
+ 0[(uint8_t*)&buf[i].sa.sin.sin_addr.s_addr]=127;
+ 3[(uint8_t*)&buf[i].sa.sin.sin_addr.s_addr]=1;
+ } else buf[i].sa.sin6.sin6_addr.s6_addr[15] = 1;
+ }
}
*res = &buf->ai;
return 0;
while (j--) buf[i++].sa.sin.sin_family = AF_INET6;
}
- if (__dns_get_rr((void *)&buf[cnt], 0, 256, 1, reply, RR_CNAME, 1) < 0)
+ if (__dns_get_rr((void *)&buf[cnt], 0, 256, 1, reply, RR_CNAME, 1) <= 0)
strcpy((void *)&buf[cnt], host);
for (i=0; i<cnt; i++) {