diff options
Diffstat (limited to 'main/musl/0003-d85d261e-to-2abb70c3.patch')
-rw-r--r-- | main/musl/0003-d85d261e-to-2abb70c3.patch | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/main/musl/0003-d85d261e-to-2abb70c3.patch b/main/musl/0003-d85d261e-to-2abb70c3.patch new file mode 100644 index 0000000000..0ceecf5eb5 --- /dev/null +++ b/main/musl/0003-d85d261e-to-2abb70c3.patch @@ -0,0 +1,540 @@ +diff --git a/include/netdb.h b/include/netdb.h +index dfc70e2..703a4b2 100644 +--- a/include/netdb.h ++++ b/include/netdb.h +@@ -41,7 +41,7 @@ struct addrinfo + #define NI_NOFQDN 0x04 + #define NI_NAMEREQD 0x08 + #define NI_DGRAM 0x10 +-/*#define NI_NUMERICSCOPE */ ++#define NI_NUMERICSCOPE 0x100 + + #define EAI_BADFLAGS -1 + #define EAI_NONAME -2 +diff --git a/src/network/dn_expand.c b/src/network/dn_expand.c +index 96adf37..849df19 100644 +--- a/src/network/dn_expand.c ++++ b/src/network/dn_expand.c +@@ -4,10 +4,11 @@ + int __dn_expand(const unsigned char *base, const unsigned char *end, const unsigned char *src, char *dest, int space) + { + const unsigned char *p = src; +- int len = -1, j; +- if (space > 256) space = 256; ++ char *dend = dest + (space > 254 ? 254 : space); ++ int len = -1, i, j; + if (p==end || !*p) return -1; +- for (;;) { ++ /* detect reference loop using an iteration counter */ ++ for (i=0; i < end-base; i+=2) { + if (*p & 0xc0) { + if (p+1==end) return -1; + j = ((p[0] & 0x3f) << 8) | p[1]; +@@ -16,7 +17,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig + p = base+j; + } else if (*p) { + j = *p+1; +- if (j>=end-p || j>space) return -1; ++ if (j>=end-p || j>dend-dest) return -1; + while (--j) *dest++ = *++p; + *dest++ = *++p ? '.' : 0; + } else { +@@ -24,6 +25,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig + return len; + } + } ++ return -1; + } + + weak_alias(__dn_expand, dn_expand); +diff --git a/src/network/ent.c b/src/network/ent.c +index 4c2f24b..ececdc4 100644 +--- a/src/network/ent.c ++++ b/src/network/ent.c +@@ -16,11 +16,3 @@ void endhostent(void) + weak_alias(sethostent, setnetent); + weak_alias(gethostent, getnetent); + weak_alias(endhostent, endnetent); +- +-weak_alias(sethostent, setservent); +-weak_alias(gethostent, getservent); +-weak_alias(endhostent, endservent); +- +-weak_alias(sethostent, setprotoent); +-weak_alias(gethostent, getprotoent); +-weak_alias(endhostent, endprotoent); +diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c +index 70b6cfd..d991344 100644 +--- a/src/network/getaddrinfo.c ++++ b/src/network/getaddrinfo.c +@@ -105,6 +105,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru + case AF_INET6: + out[k].sa.sin6.sin6_family = AF_INET6; + out[k].sa.sin6.sin6_port = htons(ports[j].port); ++ out[k].sa.sin6.sin6_scope_id = addrs[i].scopeid; + memcpy(&out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16); + break; + } +diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c +index dfcf6ed..588ed76 100644 +--- a/src/network/getnameinfo.c ++++ b/src/network/getnameinfo.c +@@ -5,6 +5,10 @@ + #include <sys/socket.h> + #include <netinet/in.h> + #include <arpa/inet.h> ++#include <net/if.h> ++#include <ctype.h> ++#include "lookup.h" ++#include "stdio_impl.h" + + int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); + int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); +@@ -14,6 +18,16 @@ int __res_send(const unsigned char *, int, unsigned char *, int); + #define PTR_MAX (64 + sizeof ".in-addr.arpa") + #define RR_PTR 12 + ++static char *itoa(char *p, unsigned x) { ++ p += 3*sizeof(int); ++ *--p = 0; ++ do { ++ *--p = '0' + x % 10; ++ x /= 10; ++ } while (x); ++ return p; ++} ++ + static void mkptr4(char *s, const unsigned char *ip) + { + sprintf(s, "%d.%d.%d.%d.in-addr.arpa", +@@ -31,6 +45,72 @@ static void mkptr6(char *s, const unsigned char *ip) + strcpy(s, "ip6.arpa"); + } + ++static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, int family) ++{ ++ char line[512], *p, *z; ++ unsigned char _buf[1032], atmp[16]; ++ struct address iplit; ++ FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf); ++ if (!f) return; ++ if (family == AF_INET) { ++ memcpy(atmp+12, a, 4); ++ memcpy(atmp, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); ++ a = atmp; ++ } ++ while (fgets(line, sizeof line, f)) { ++ if ((p=strchr(line, '#'))) *p++='\n', *p=0; ++ ++ for (p=line; *p && !isspace(*p); p++); ++ *p++ = 0; ++ if (__lookup_ipliteral(&iplit, line, AF_UNSPEC)<=0) ++ continue; ++ ++ if (iplit.family == AF_INET) { ++ memcpy(iplit.addr+12, iplit.addr, 4); ++ memcpy(iplit.addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); ++ iplit.scopeid = 0; ++ } ++ ++ if (memcmp(a, iplit.addr, 16) || iplit.scopeid != scopeid) ++ continue; ++ ++ for (; *p && isspace(*p); p++); ++ for (z=p; *z && !isspace(*z); z++); ++ *z = 0; ++ if (z-p < 256) { ++ memcpy(buf, p, z-p+1); ++ break; ++ } ++ } ++ __fclose_ca(f); ++} ++ ++static void reverse_services(char *buf, int port, int dgram) ++{ ++ unsigned long svport; ++ char line[128], *p, *z; ++ unsigned char _buf[1032]; ++ FILE _f, *f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf); ++ if (!f) return; ++ while (fgets(line, sizeof line, f)) { ++ if ((p=strchr(line, '#'))) *p++='\n', *p=0; ++ ++ for (p=line; *p && !isspace(*p); p++); ++ if (!p) continue; ++ *p++ = 0; ++ svport = strtoul(p, &z, 10); ++ ++ if (svport != port || z==p) continue; ++ if (dgram && strncmp(z, "/udp", 4)) continue; ++ if (!dgram && strncmp(z, "/tcp", 4)) continue; ++ if (p-line > 32) continue; ++ ++ memcpy(buf, line, p-line); ++ break; ++ } ++ __fclose_ca(f); ++} ++ + static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) + { + char tmp[256]; +@@ -48,15 +128,17 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, + int flags) + { + char ptr[PTR_MAX]; +- char buf[256]; ++ char buf[256], num[3*sizeof(int)+1]; + int af = sa->sa_family; + unsigned char *a; ++ unsigned scopeid; + + switch (af) { + case AF_INET: + a = (void *)&((struct sockaddr_in *)sa)->sin_addr; + if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY; + mkptr4(ptr, a); ++ scopeid = 0; + break; + case AF_INET6: + a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr; +@@ -65,6 +147,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, + mkptr6(ptr, a); + else + mkptr4(ptr, a+12); ++ scopeid = ((struct sockaddr_in6 *)sa)->sin6_scope_id; + break; + default: + return EAI_FAMILY; +@@ -73,6 +156,9 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, + if (node && nodelen) { + buf[0] = 0; + if (!(flags & NI_NUMERICHOST)) { ++ reverse_hosts(buf, a, scopeid, af); ++ } ++ if (!*buf && !(flags & NI_NUMERICHOST)) { + unsigned char query[18+PTR_MAX], reply[512]; + int qlen = __res_mkquery(0, ptr, 1, RR_PTR, + 0, 0, 0, query, sizeof query); +@@ -84,16 +170,33 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, + if (!*buf) { + if (flags & NI_NAMEREQD) return EAI_NONAME; + inet_ntop(af, a, buf, sizeof buf); ++ if (scopeid) { ++ char *p = 0, tmp[IF_NAMESIZE+1]; ++ if (!(flags & NI_NUMERICSCOPE) && ++ (IN6_IS_ADDR_LINKLOCAL(a) || ++ IN6_IS_ADDR_MC_LINKLOCAL(a))) ++ p = if_indextoname(scopeid, tmp+1); ++ if (!p) ++ p = itoa(num, scopeid); ++ *--p = '%'; ++ strcat(buf, p); ++ } + } + if (strlen(buf) >= nodelen) return EAI_OVERFLOW; + strcpy(node, buf); + } + + if (serv && servlen) { +- if (snprintf(buf, sizeof buf, "%d", +- ntohs(((struct sockaddr_in *)sa)->sin_port))>=servlen) ++ char *p = buf; ++ int port = ntohs(((struct sockaddr_in *)sa)->sin_port); ++ buf[0] = 0; ++ if (!(flags & NI_NUMERICSERV)) ++ reverse_services(buf, port, flags & NI_DGRAM); ++ if (!*p) ++ p = itoa(num, port); ++ if (strlen(p) >= servlen) + return EAI_OVERFLOW; +- strcpy(serv, buf); ++ strcpy(serv, p); + } + + return 0; +diff --git a/src/network/if_nametoindex.c b/src/network/if_nametoindex.c +index fb4a147..cb6ec05 100644 +--- a/src/network/if_nametoindex.c ++++ b/src/network/if_nametoindex.c +@@ -14,5 +14,5 @@ unsigned if_nametoindex(const char *name) + strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + r = ioctl(fd, SIOCGIFINDEX, &ifr); + __syscall(SYS_close, fd); +- return r < 0 ? r : ifr.ifr_ifindex; ++ return r < 0 ? 0 : ifr.ifr_ifindex; + } +diff --git a/src/network/lookup.h b/src/network/lookup.h +index 82c969e..19c9e48 100644 +--- a/src/network/lookup.h ++++ b/src/network/lookup.h +@@ -22,5 +22,6 @@ struct service { + + int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int flags); + int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags); ++int __lookup_ipliteral(struct address buf[static 1], const char *name, int family); + + #endif +diff --git a/src/network/lookup_ipliteral.c b/src/network/lookup_ipliteral.c +new file mode 100644 +index 0000000..7bcb85f +--- /dev/null ++++ b/src/network/lookup_ipliteral.c +@@ -0,0 +1,52 @@ ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <netdb.h> ++#include <net/if.h> ++#include <arpa/inet.h> ++#include <limits.h> ++#include <stdlib.h> ++#include <string.h> ++#include <ctype.h> ++#include "lookup.h" ++ ++int __inet_aton(const char *, struct in_addr *); ++ ++int __lookup_ipliteral(struct address buf[static 1], const char *name, int family) ++{ ++ struct in_addr a4; ++ struct in6_addr a6; ++ if (family != AF_INET6 && __inet_aton(name, &a4)>0) { ++ memcpy(&buf[0].addr, &a4, sizeof a4); ++ buf[0].family = AF_INET; ++ buf[0].scopeid = 0; ++ return 1; ++ } ++ if (family != AF_INET) { ++ char tmp[64]; ++ char *p = strchr(name, '%'), *z; ++ unsigned long long scopeid; ++ if (p && p-name < 64) { ++ memcpy(tmp, name, p-name); ++ tmp[p-name] = 0; ++ name = tmp; ++ } ++ if (inet_pton(AF_INET6, name, &a6)<=0) return 0; ++ memcpy(&buf[0].addr, &a6, sizeof a6); ++ buf[0].family = AF_INET6; ++ if (p) { ++ if (isdigit(*++p)) scopeid = strtoull(p, &z, 10); ++ else z = p-1; ++ if (*z) { ++ if (!IN6_IS_ADDR_LINKLOCAL(&a6) && ++ !IN6_IS_ADDR_MC_LINKLOCAL(&a6)) ++ return EAI_NONAME; ++ scopeid = if_nametoindex(p); ++ if (!scopeid) return EAI_NONAME; ++ } ++ if (scopeid > UINT_MAX) return EAI_NONAME; ++ buf[0].scopeid = scopeid; ++ } ++ return 1; ++ } ++ return 0; ++} +diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c +index 0292093..68b172b 100644 +--- a/src/network/lookup_name.c ++++ b/src/network/lookup_name.c +@@ -1,6 +1,7 @@ + #include <sys/socket.h> + #include <netinet/in.h> + #include <netdb.h> ++#include <net/if.h> + #include <arpa/inet.h> + #include <ctype.h> + #include <stdlib.h> +@@ -13,7 +14,7 @@ + static int is_valid_hostname(const char *host) + { + const unsigned char *s; +- if (strnlen(host, 256)-1 > 254 || mbstowcs(0, host, 0) > 255) return 0; ++ if (strnlen(host, 254)-1 >= 253 || mbstowcs(0, host, 0) == -1) return 0; + for (s=(void *)host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++); + return !*s; + } +@@ -36,23 +37,9 @@ static int name_from_null(struct address buf[static 2], const char *name, int fa + return cnt; + } + +-int __inet_aton(const char *, struct in_addr *); +- + static int name_from_numeric(struct address buf[static 1], const char *name, int family) + { +- struct in_addr a4; +- struct in6_addr a6; +- if (family != AF_INET6 && __inet_aton(name, &a4)>0) { +- memcpy(&buf[0].addr, &a4, sizeof a4); +- buf[0].family = AF_INET; +- return 1; +- } +- if (family != AF_INET && inet_pton(AF_INET6, name, &a6)>0) { +- memcpy(&buf[0].addr, &a6, sizeof a6); +- buf[0].family = AF_INET6; +- return 1; +- } +- return 0; ++ return __lookup_ipliteral(buf, name, family); + } + + static int name_from_hosts(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) +@@ -110,11 +97,13 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const + case RR_A: + if (len != 4) return -1; + ctx->addrs[ctx->cnt].family = AF_INET; ++ ctx->addrs[ctx->cnt].scopeid = 0; + memcpy(ctx->addrs[ctx->cnt++].addr, data, 4); + break; + case RR_AAAA: + if (len != 16) return -1; + ctx->addrs[ctx->cnt].family = AF_INET6; ++ ctx->addrs[ctx->cnt].scopeid = 0; + memcpy(ctx->addrs[ctx->cnt++].addr, data, 16); + break; + case RR_CNAME: +@@ -164,7 +153,7 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c + *canon = 0; + if (name) { + size_t l; +- if ((l = strnlen(name, 256))-1 > 254) ++ if ((l = strnlen(name, 254))-1 >= 253) + return EAI_NONAME; + memcpy(canon, name, l+1); + } +@@ -179,10 +168,10 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c + + /* Try each backend until there's at least one result. */ + cnt = name_from_null(buf, name, family, flags); +- if (cnt<=0) cnt = name_from_numeric(buf, name, family); +- if (cnt<=0 && !(flags & AI_NUMERICHOST)) { ++ if (!cnt) cnt = name_from_numeric(buf, name, family); ++ if (!cnt && !(flags & AI_NUMERICHOST)) { + cnt = name_from_hosts(buf, canon, name, family); +- if (cnt<=0) cnt = name_from_dns(buf, canon, name, family); ++ if (!cnt) cnt = name_from_dns(buf, canon, name, family); + } + if (cnt<=0) return cnt ? cnt : EAI_NONAME; + +@@ -204,7 +193,6 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c + if (buf[i].family != AF_INET) continue; + memcpy(buf[i].addr+12, buf[i].addr, 4); + memcpy(buf[i].addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); +- buf[i].scopeid = 0; + buf[i].family = AF_INET6; + } + } +diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c +index f7e4e9c..7c49709 100644 +--- a/src/network/res_mkquery.c ++++ b/src/network/res_mkquery.c +@@ -10,9 +10,9 @@ int __res_mkquery(int op, const char *dname, int class, int type, + int id, i, j; + unsigned char q[280]; + struct timespec ts; +- size_t l = strnlen(dname, 256); ++ size_t l = strnlen(dname, 254); + +- if (l-1>=254 || buflen<18+l || op>15u || class>255u || type>255u) ++ if (l-1>=253 || buflen<18+l || op>15u || class>255u || type>255u) + return -1; + + /* Construct query template - ID will be filled later */ +diff --git a/src/network/res_msend.c b/src/network/res_msend.c +index a5b7793..5192b4d 100644 +--- a/src/network/res_msend.c ++++ b/src/network/res_msend.c +@@ -12,6 +12,7 @@ + #include <pthread.h> + #include "stdio_impl.h" + #include "syscall.h" ++#include "lookup.h" + + static void cleanup(void *p) + { +@@ -47,6 +48,7 @@ int __res_msend(int nqueries, const unsigned char *const *queries, + int cs; + struct pollfd pfd; + unsigned long t0, t1, t2; ++ struct address iplit; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + +@@ -76,13 +78,18 @@ int __res_msend(int nqueries, const unsigned char *const *queries, + for (z=s; *z && !isspace(*z); z++); + *z=0; + +- if (inet_pton(AF_INET, s, &ns[nns].sin.sin_addr)>0) { +- ns[nns].sin.sin_port = htons(53); +- ns[nns++].sin.sin_family = AF_INET; +- } else if (inet_pton(AF_INET6, s, &ns[nns].sin6.sin6_addr)>0) { +- sl = sizeof sa.sin6; +- ns[nns].sin6.sin6_port = htons(53); +- ns[nns++].sin6.sin6_family = family = AF_INET6; ++ if (__lookup_ipliteral(&iplit, s, AF_UNSPEC)>0) { ++ if (iplit.family == AF_INET) { ++ memcpy(&ns[nns].sin.sin_addr, iplit.addr, 4); ++ ns[nns].sin.sin_port = htons(53); ++ ns[nns++].sin.sin_family = AF_INET; ++ } else { ++ sl = sizeof sa.sin6; ++ memcpy(&ns[nns].sin6.sin6_addr, iplit.addr, 16); ++ ns[nns].sin6.sin6_port = htons(53); ++ ns[nns].sin6.sin6_scope_id = iplit.scopeid; ++ ns[nns++].sin6.sin6_family = family = AF_INET6; ++ } + } + } + if (f) __fclose_ca(f); +diff --git a/src/network/res_querydomain.c b/src/network/res_querydomain.c +index c746dbe..8ba31f4 100644 +--- a/src/network/res_querydomain.c ++++ b/src/network/res_querydomain.c +@@ -3,10 +3,10 @@ + + int res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *dest, int len) + { +- char tmp[256]; +- size_t nl = strnlen(name, 256); +- size_t dl = strnlen(domain, 256); +- if (nl+dl+1 > 255) return -1; ++ char tmp[254]; ++ size_t nl = strnlen(name, 254); ++ size_t dl = strnlen(domain, 254); ++ if (nl+dl+1 > 253) return -1; + memcpy(tmp, name, nl); + tmp[nl] = '.'; + memcpy(tmp+nl+1, domain, dl+1); +diff --git a/src/stdio/vasprintf.c b/src/stdio/vasprintf.c +index 68b7246..08251bc 100644 +--- a/src/stdio/vasprintf.c ++++ b/src/stdio/vasprintf.c +@@ -3,26 +3,13 @@ + #include <stdarg.h> + #include <stdlib.h> + +-#define GUESS 240U +- + int vasprintf(char **s, const char *fmt, va_list ap) + { + va_list ap2; +- char *a; +- int l=GUESS; +- +- if (!(a=malloc(GUESS))) return -1; +- + va_copy(ap2, ap); +- l=vsnprintf(a, GUESS, fmt, ap2); ++ int l = vsnprintf(0, 0, fmt, ap2); + va_end(ap2); + +- if (l<GUESS) { +- char *b = realloc(a, l+1U); +- *s = b ? b : a; +- return l; +- } +- free(a); + if (l<0 || !(*s=malloc(l+1U))) return -1; + return vsnprintf(*s, l+1U, fmt, ap); + } |