diff options
author | Timo Teräs <timo.teras@iki.fi> | 2014-04-09 13:25:31 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2014-04-09 13:27:19 +0300 |
commit | a488eea97d8d9d53f9a361465b341221246377f5 (patch) | |
tree | 6fb83b9029119d329ea1ecdf4f1cbfbbb56280f0 /main/musl | |
parent | 195f616f91ed4bd9733ef60e9945fdb292904162 (diff) | |
download | aports-a488eea97d8d9d53f9a361465b341221246377f5.tar.bz2 aports-a488eea97d8d9d53f9a361465b341221246377f5.tar.xz |
main/musl: reimplement getifaddrs() and if_nameindex() with netlink
this fixes issues with dhcpcd. cherry-pick also one more printf
formatting fix from musl git.
Diffstat (limited to 'main/musl')
-rw-r--r-- | main/musl/0003-b9b2db2f-to-e94d0692.patch (renamed from main/musl/0003-b9b2db2f-to-efe07b0f.patch) | 12 | ||||
-rw-r--r-- | main/musl/1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch | 726 | ||||
-rw-r--r-- | main/musl/APKBUILD | 14 |
3 files changed, 746 insertions, 6 deletions
diff --git a/main/musl/0003-b9b2db2f-to-efe07b0f.patch b/main/musl/0003-b9b2db2f-to-e94d0692.patch index 5c4291378b..c13a5ffc8e 100644 --- a/main/musl/0003-b9b2db2f-to-efe07b0f.patch +++ b/main/musl/0003-b9b2db2f-to-e94d0692.patch @@ -133,9 +133,19 @@ index 0000000..5ac8b3d + return 0; +} diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c -index 31c3d5d..0be7549 100644 +index 31c3d5d..f6e7f38 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c +@@ -308,8 +308,8 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) + *d = x % 1000000000; + carry = x / 1000000000; + } +- if (!z[-1] && z>a) z--; + if (carry) *--a = carry; ++ while (z>a && !z[-1]) z--; + e2-=sh; + } + while (e2<0) { @@ -356,15 +356,15 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) *d = *d + i; while (*d > 999999999) { diff --git a/main/musl/1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch b/main/musl/1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch new file mode 100644 index 0000000000..f740e20672 --- /dev/null +++ b/main/musl/1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch @@ -0,0 +1,726 @@ +From 274b49ab1c7296fc13076b3ed8ca30050487a343 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Tue, 8 Apr 2014 14:03:16 +0000 +Subject: [PATCH] reimplement if_nameindex and getifaddrs using netlink + +--- + src/network/__netlink.c | 68 ++++++++++ + src/network/__netlink.h | 143 ++++++++++++++++++++ + src/network/getifaddrs.c | 322 ++++++++++++++++++++++++--------------------- + src/network/if_nameindex.c | 105 +++++++++------ + 4 files changed, 451 insertions(+), 187 deletions(-) + create mode 100644 src/network/__netlink.c + create mode 100644 src/network/__netlink.h + +diff --git a/src/network/__netlink.c b/src/network/__netlink.c +new file mode 100644 +index 0000000..d0c9fab +--- /dev/null ++++ b/src/network/__netlink.c +@@ -0,0 +1,68 @@ ++#define _GNU_SOURCE ++#include <errno.h> ++#include <string.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <sys/socket.h> ++#include <sys/param.h> ++#include "__netlink.h" ++ ++struct __netlink_handle { ++ int fd; ++ unsigned int seq; ++ size_t bufsize; ++}; ++ ++struct __netlink_handle *__netlink_open(int type) ++{ ++ struct __netlink_handle *nh; ++ int bufsize = getpagesize(); ++ /* required buffer size is MIN(8192,pagesize)-sizeof(struct skb_shared_info) ++ * the estimate for skb_shared_info size is conservative, but gives enough ++ * space to fit struct __netlink_handle including malloc overhead in one page . */ ++ if (bufsize > 8192) bufsize = 8192; ++ bufsize -= 128; ++ nh = malloc(sizeof(struct __netlink_handle) + bufsize); ++ if (!nh) return 0; ++ nh->fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, type); ++ if (nh->fd < 0) { free(nh); return 0; } ++ nh->seq = 1; ++ nh->bufsize = bufsize; ++ return nh; ++} ++ ++void __netlink_close(struct __netlink_handle *nh) ++{ ++ close(nh->fd); ++ free(nh); ++} ++ ++int __netlink_enumerate(struct __netlink_handle *nh, int type, int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx) ++{ ++ struct nlmsghdr *h; ++ void *buf = (void*)(nh+1); ++ struct { ++ struct nlmsghdr nlh; ++ struct rtgenmsg g; ++ } *req = buf; ++ int r, ret = 0; ++ ++ memset(req, 0, NETLINK_ALIGN(sizeof(*req))); ++ req->nlh.nlmsg_len = sizeof(*req); ++ req->nlh.nlmsg_type = type; ++ req->nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; ++ req->nlh.nlmsg_seq = nh->seq++; ++ req->g.rtgen_family = AF_UNSPEC; ++ r = send(nh->fd, req, sizeof(*req), 0); ++ if (r < 0) return r; ++ ++ while (1) { ++ r = recv(nh->fd, buf, nh->bufsize, MSG_DONTWAIT); ++ if (r <= 0) return -1; ++ for (h = (struct nlmsghdr*) buf; NLMSG_OK(h, (void*)((uint8_t*)buf+r)); h = NLMSG_NEXT(h)) { ++ if (h->nlmsg_type == NLMSG_DONE) return ret; ++ if (h->nlmsg_type == NLMSG_ERROR) return -1; ++ if (!ret) ret = cb(ctx, h); ++ } ++ } ++} +diff --git a/src/network/__netlink.h b/src/network/__netlink.h +new file mode 100644 +index 0000000..94728f3 +--- /dev/null ++++ b/src/network/__netlink.h +@@ -0,0 +1,143 @@ ++#include <stdint.h> ++ ++/* linux/netlink.h */ ++ ++#define NETLINK_ROUTE 0 ++ ++struct nlmsghdr { ++ uint32_t nlmsg_len; ++ uint16_t nlmsg_type; ++ uint16_t nlmsg_flags; ++ uint32_t nlmsg_seq; ++ uint32_t nlmsg_pid; ++}; ++ ++#define NLM_F_REQUEST 1 ++#define NLM_F_MULTI 2 ++#define NLM_F_ACK 4 ++#define NLM_F_ECHO 8 ++#define NLM_F_DUMP_INTR 16 ++ ++#define NLM_F_ROOT 0x100 ++#define NLM_F_MATCH 0x200 ++#define NLM_F_ATOMIC 0x400 ++#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) ++ ++#define NLMSG_NOOP 0x1 ++#define NLMSG_ERROR 0x2 ++#define NLMSG_DONE 0x3 ++#define NLMSG_OVERRUN 0x4 ++ ++/* linux/rtnetlink.h */ ++ ++#define RTM_GETLINK 18 ++#define RTM_GETADDR 22 ++ ++struct rtattr { ++ unsigned short rta_len; ++ unsigned short rta_type; ++}; ++ ++struct rtgenmsg { ++ unsigned char rtgen_family; ++}; ++ ++struct ifinfomsg { ++ unsigned char ifi_family; ++ unsigned char __ifi_pad; ++ unsigned short ifi_type; ++ int ifi_index; ++ unsigned ifi_flags; ++ unsigned ifi_change; ++}; ++ ++/* linux/if_link.h */ ++ ++enum { ++ IFLA_UNSPEC, ++ IFLA_ADDRESS, ++ IFLA_BROADCAST, ++ IFLA_IFNAME, ++ IFLA_MTU, ++ IFLA_LINK, ++ IFLA_QDISC, ++ IFLA_STATS, ++ IFLA_COST, ++ IFLA_PRIORITY, ++ IFLA_MASTER, ++ IFLA_WIRELESS, ++ IFLA_PROTINFO, ++ IFLA_TXQLEN, ++ IFLA_MAP, ++ IFLA_WEIGHT, ++ IFLA_OPERSTATE, ++ IFLA_LINKMODE, ++ IFLA_LINKINFO, ++ IFLA_NET_NS_PID, ++ IFLA_IFALIAS, ++ IFLA_NUM_VF, ++ IFLA_VFINFO_LIST, ++ IFLA_STATS64, ++ IFLA_VF_PORTS, ++ IFLA_PORT_SELF, ++ IFLA_AF_SPEC, ++ IFLA_GROUP, ++ IFLA_NET_NS_FD, ++ IFLA_EXT_MASK, ++ IFLA_PROMISCUITY, ++ IFLA_NUM_TX_QUEUES, ++ IFLA_NUM_RX_QUEUES, ++ IFLA_CARRIER, ++ IFLA_PHYS_PORT_ID, ++ __IFLA_MAX ++}; ++ ++/* linux/if_addr.h */ ++ ++struct ifaddrmsg { ++ uint8_t ifa_family; ++ uint8_t ifa_prefixlen; ++ uint8_t ifa_flags; ++ uint8_t ifa_scope; ++ uint32_t ifa_index; ++}; ++ ++enum { ++ IFA_UNSPEC, ++ IFA_ADDRESS, ++ IFA_LOCAL, ++ IFA_LABEL, ++ IFA_BROADCAST, ++ IFA_ANYCAST, ++ IFA_CACHEINFO, ++ IFA_MULTICAST, ++ __IFA_MAX ++}; ++ ++/* musl */ ++ ++#define NETLINK_ALIGN(len) (((len)+3) & ~3) ++#define NLMSG_DATA(nlh) ((void*)((char*)(nlh)+NETLINK_ALIGN(sizeof(struct nlmsghdr)))) ++#define NLMSG_DATALEN(nlh) ((nlh)->nlmsg_len-NETLINK_ALIGN(sizeof(struct nlmsghdr))) ++#define NLMSG_DATAEND(nlh) ((char*)(nlh)+(nlh)->nlmsg_len) ++#define NLMSG_NEXT(nlh) (struct nlmsghdr*)((char*)(nlh)+NETLINK_ALIGN((nlh)->nlmsg_len)) ++#define NLMSG_OK(nlh,end) (NLMSG_DATA(nlh) <= (end) && \ ++ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ ++ (void*)NLMSG_NEXT(nlh) <= (end)) ++ ++#define RTA_DATA(rta) ((void*)((char*)(rta)+NETLINK_ALIGN(sizeof(struct rtattr)))) ++#define RTA_DATALEN(rta) ((rta)->rta_len-NETLINK_ALIGN(sizeof(struct rtattr))) ++#define RTA_DATAEND(rta) ((char*)(rta)+(rta)->rta_len) ++#define RTA_NEXT(rta) (struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len)) ++#define RTA_OK(rta,end) (RTA_DATA(rta) <= (void*)(end) && \ ++ (rta)->rta_len >= sizeof(struct rtattr) && \ ++ (void*)RTA_NEXT(rta) <= (void*)(end)) ++ ++#define NLMSG_RTA(nlh,len) ((void*)((char*)(nlh)+NETLINK_ALIGN(sizeof(struct nlmsghdr))+NETLINK_ALIGN(len))) ++#define NLMSG_RTAOK(rta,nlh) RTA_OK(rta,NLMSG_DATAEND(nlh)) ++ ++struct __netlink_handle; ++ ++struct __netlink_handle *__netlink_open(int type); ++void __netlink_close(struct __netlink_handle *h); ++int __netlink_enumerate(struct __netlink_handle *h, int type, int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx); +diff --git a/src/network/getifaddrs.c b/src/network/getifaddrs.c +index 5a94cc7..5b1ebe7 100644 +--- a/src/network/getifaddrs.c ++++ b/src/network/getifaddrs.c +@@ -1,181 +1,209 @@ +-/* (C) 2013 John Spencer. released under musl's standard MIT license. */ +-#undef _GNU_SOURCE + #define _GNU_SOURCE +-#include <ifaddrs.h> +-#include <stdlib.h> +-#include <net/if.h> /* IFNAMSIZ, ifreq, ifconf */ +-#include <stdio.h> +-#include <ctype.h> +-#include <string.h> + #include <errno.h> +-#include <arpa/inet.h> /* inet_pton */ ++#include <string.h> ++#include <stdlib.h> + #include <unistd.h> +-#include <sys/ioctl.h> +-#include <sys/socket.h> ++#include <ifaddrs.h> ++#include <net/if.h> ++#include "__netlink.h" + +-typedef union { +- struct sockaddr_in6 v6; ++/* getifaddrs() uses PF_PACKET to relay hardware addresses. ++ * But Infiniband socket address length is longer, so use this hack ++ * (like glibc) to return it anyway. */ ++struct sockaddr_ll_hack { ++ unsigned short sll_family, sll_protocol; ++ int sll_ifindex; ++ unsigned short sll_hatype; ++ unsigned char sll_pkttype, sll_halen; ++ unsigned char sll_addr[24]; ++}; ++ ++union sockany { ++ struct sockaddr sa; ++ struct sockaddr_ll_hack ll; + struct sockaddr_in v4; +-} soa; ++ struct sockaddr_in6 v6; ++}; + +-typedef struct ifaddrs_storage { ++struct ifaddrs_storage { + struct ifaddrs ifa; +- soa addr; +- soa netmask; +- soa dst; ++ struct ifaddrs_storage *hash_next; ++ union sockany addr, netmask, ifu; ++ unsigned int index; + char name[IFNAMSIZ+1]; +-} stor; +-#define next ifa.ifa_next ++}; + +-static stor* list_add(stor** list, stor** head, char* ifname) ++#define IFADDRS_HASH_SIZE 64 ++struct ifaddrs_ctx { ++ struct ifaddrs_storage *first; ++ struct ifaddrs_storage *last; ++ struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE]; ++}; ++ ++void freeifaddrs(struct ifaddrs *ifp) + { +- stor* curr = calloc(1, sizeof(stor)); +- if(curr) { +- strcpy(curr->name, ifname); +- curr->ifa.ifa_name = curr->name; +- if(*head) (*head)->next = (struct ifaddrs*) curr; +- *head = curr; +- if(!*list) *list = curr; ++ struct ifaddrs *n; ++ while (ifp) { ++ n = ifp->ifa_next; ++ free(ifp); ++ ifp = n; + } +- return curr; + } + +-void freeifaddrs(struct ifaddrs *ifp) ++static void addifaddrs(struct ifaddrs_ctx *ctx, struct ifaddrs_storage *add) + { +- stor *head = (stor *) ifp; +- while(head) { +- void *p = head; +- head = (stor *) head->next; +- free(p); ++ if (!add->ifa.ifa_name) { ++ free(add); ++ return; + } ++ if (!ctx->first) ctx->first = add; ++ if (ctx->last) ctx->last->ifa.ifa_next = &add->ifa; ++ ctx->last = add; + } + +-static void ipv6netmask(unsigned prefix_length, struct sockaddr_in6 *sa) ++static struct sockaddr* copy_lladdr(union sockany *sa, struct rtattr *rta, struct ifinfomsg *ifi) + { +- unsigned char* hb = sa->sin6_addr.s6_addr; +- unsigned onebytes = prefix_length / 8; +- unsigned bits = prefix_length % 8; +- unsigned nullbytes = 16 - onebytes; +- memset(hb, -1, onebytes); +- memset(hb+onebytes, 0, nullbytes); +- if(bits) { +- unsigned char x = -1; +- x <<= 8 - bits; +- hb[onebytes] = x; ++ if (RTA_DATALEN(rta) > sizeof(sa->ll.sll_addr)) return 0; ++ sa->ll.sll_family = AF_PACKET; ++ sa->ll.sll_ifindex = ifi->ifi_index; ++ sa->ll.sll_hatype = ifi->ifi_type; ++ sa->ll.sll_halen = RTA_DATALEN(rta); ++ memcpy(sa->ll.sll_addr, RTA_DATA(rta), RTA_DATALEN(rta)); ++ return &sa->sa; ++} ++ ++static uint8_t *sockany_addr(int af, union sockany *sa, int *len) ++{ ++ switch (af) { ++ case AF_INET: *len = 4; return (uint8_t*) &sa->v4.sin_addr; ++ case AF_INET6: *len = 16; return (uint8_t*) &sa->v6.sin6_addr; + } ++ return 0; + } + +-static void dealwithipv6(stor **list, stor** head) ++static struct sockaddr* copy_addr(int af, union sockany *sa, struct rtattr *rta) + { +- FILE* f = fopen("/proc/net/if_inet6", "rbe"); +- /* 00000000000000000000000000000001 01 80 10 80 lo +- A B C D E F +- all numbers in hex +- A = addr B=netlink device#, C=prefix length, +- D = scope value (ipv6.h) E = interface flags (rnetlink.h, addrconf.c) +- F = if name */ +- char v6conv[32 + 7 + 1], *v6; +- char *line, linebuf[512]; +- if(!f) return; +- while((line = fgets(linebuf, sizeof linebuf, f))) { +- v6 = v6conv; +- size_t i = 0; +- for(; i < 8; i++) { +- memcpy(v6, line, 4); +- v6+=4; +- *v6++=':'; +- line+=4; +- } +- --v6; *v6 = 0; +- line++; +- unsigned b, c, d, e; +- char name[IFNAMSIZ+1]; +- if(5 == sscanf(line, "%x %x %x %x %s", &b, &c, &d, &e, name)) { +- struct sockaddr_in6 sa = {0}; +- if(1 == inet_pton(AF_INET6, v6conv, &sa.sin6_addr)) { +- sa.sin6_family = AF_INET6; +- stor* curr = list_add(list, head, name); +- if(!curr) goto out; +- curr->addr.v6 = sa; +- curr->ifa.ifa_addr = (struct sockaddr*) &curr->addr; +- ipv6netmask(c, &sa); +- curr->netmask.v6 = sa; +- curr->ifa.ifa_netmask = (struct sockaddr*) &curr->netmask; +- /* find ipv4 struct with the same interface name to copy flags */ +- stor* scan = *list; +- for(;scan && strcmp(name, scan->name);scan=(stor*)scan->next); +- if(scan) curr->ifa.ifa_flags = scan->ifa.ifa_flags; +- else curr->ifa.ifa_flags = 0; +- } else errno = 0; +- } ++ int len; ++ uint8_t *dst = sockany_addr(af, sa, &len); ++ if (!dst || RTA_DATALEN(rta) != len) return 0; ++ sa->sa.sa_family = af; ++ memcpy(dst, RTA_DATA(rta), len); ++ return &sa->sa; ++} ++ ++static struct sockaddr *gen_netmask(int af, union sockany *sa, int prefixlen) ++{ ++ int maxlen, i; ++ uint8_t *dst = sockany_addr(af, sa, &maxlen); ++ if (!dst) return 0; ++ sa->sa.sa_family = af; ++ if (prefixlen > 8*maxlen) prefixlen = 8*maxlen; ++ i = prefixlen / 8; ++ memset(dst, 0xff, i); ++ if (i<maxlen) { ++ dst[i++] = 0xff << (8 - (prefixlen % 8)); ++ if (i<maxlen) memset(&dst[i+1], 0x00, maxlen-i); + } +- out: +- fclose(f); ++ return &sa->sa; + } + +-int getifaddrs(struct ifaddrs **ifap) ++static int __handle_link(void *pctx, struct nlmsghdr *h) + { +- stor *list = 0, *head = 0; +- struct if_nameindex* ii = if_nameindex(); +- if(!ii) return -1; +- size_t i; +- for(i = 0; ii[i].if_index || ii[i].if_name; i++) { +- stor* curr = list_add(&list, &head, ii[i].if_name); +- if(!curr) { +- if_freenameindex(ii); +- goto err2; +- } ++ struct ifaddrs_ctx *ctx = pctx; ++ struct ifaddrs_storage *ifs; ++ struct ifinfomsg *ifi = NLMSG_DATA(h); ++ struct rtattr *rta; ++ int stats_len = 0; ++ ++ for (rta = NLMSG_RTA(h, sizeof(*ifi)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) { ++ if (rta->rta_type != IFLA_STATS) continue; ++ stats_len = RTA_DATALEN(rta); ++ break; + } +- if_freenameindex(ii); +- +- int sock = socket(PF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP); +- if(sock == -1) goto err2; +- struct ifreq reqs[32]; /* arbitrary chosen boundary */ +- struct ifconf conf = {.ifc_len = sizeof reqs, .ifc_req = reqs}; +- if(-1 == ioctl(sock, SIOCGIFCONF, &conf)) goto err; +- size_t reqitems = conf.ifc_len / sizeof(struct ifreq); +- for(head = list; head; head = (stor*)head->next) { +- for(i = 0; i < reqitems; i++) { +- // get SIOCGIFADDR of active interfaces. +- if(!strcmp(reqs[i].ifr_name, head->name)) { +- head->addr.v4 = *(struct sockaddr_in*)&reqs[i].ifr_addr; +- head->ifa.ifa_addr = (struct sockaddr*) &head->addr; +- break; ++ ++ ifs = calloc(1, sizeof(struct ifaddrs_storage) + stats_len); ++ if (ifs == 0) return -1; ++ ++ ifs->index = ifi->ifi_index; ++ ifs->ifa.ifa_flags = ifi->ifi_flags; ++ ++ for (rta = NLMSG_RTA(h, sizeof(*ifi)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) { ++ switch (rta->rta_type) { ++ case IFLA_IFNAME: ++ if (RTA_DATALEN(rta) <= IFNAMSIZ) { ++ strncpy(ifs->name, RTA_DATA(rta), RTA_DATALEN(rta)); ++ ifs->ifa.ifa_name = ifs->name; + } ++ break; ++ case IFLA_ADDRESS: ++ ifs->ifa.ifa_addr = copy_lladdr(&ifs->addr, rta, ifi); ++ break; ++ case IFLA_BROADCAST: ++ ifs->ifa.ifa_broadaddr = copy_lladdr(&ifs->ifu, rta, ifi); ++ break; ++ case IFLA_STATS: ++ ifs->ifa.ifa_data = (void*)(ifs+1); ++ memcpy(ifs->ifa.ifa_data, RTA_DATA(rta), RTA_DATALEN(rta)); ++ break; + } +- struct ifreq req; +- snprintf(req.ifr_name, sizeof req.ifr_name, "%s", head->name); +- if(-1 == ioctl(sock, SIOCGIFFLAGS, &req)) goto err; +- +- head->ifa.ifa_flags = req.ifr_flags; +- if(head->ifa.ifa_addr) { +- /* or'ing flags with IFF_LOWER_UP on active interfaces to mimic glibc */ +- head->ifa.ifa_flags |= IFF_LOWER_UP; +- if(-1 == ioctl(sock, SIOCGIFNETMASK, &req)) goto err; +- head->netmask.v4 = *(struct sockaddr_in*)&req.ifr_netmask; +- head->ifa.ifa_netmask = (struct sockaddr*) &head->netmask; +- +- if(head->ifa.ifa_flags & IFF_POINTOPOINT) { +- if(-1 == ioctl(sock, SIOCGIFDSTADDR, &req)) goto err; +- head->dst.v4 = *(struct sockaddr_in*)&req.ifr_dstaddr; +- } else { +- if(-1 == ioctl(sock, SIOCGIFBRDADDR, &req)) goto err; +- head->dst.v4 = *(struct sockaddr_in*)&req.ifr_broadaddr; +- } +- head->ifa.ifa_ifu.ifu_dstaddr = (struct sockaddr*) &head->dst; ++ } ++ if (ifs->ifa.ifa_name) { ++ ifs->hash_next = ctx->hash[ifs->index%IFADDRS_HASH_SIZE]; ++ ctx->hash[ifs->index%IFADDRS_HASH_SIZE] = ifs; ++ } ++ addifaddrs(ctx, ifs); ++ return 0; ++} ++ ++static int __handle_addr(void *pctx, struct nlmsghdr *h) ++{ ++ struct ifaddrs_ctx *ctx = pctx; ++ struct ifaddrs_storage *ifs, *ifs0; ++ struct ifaddrmsg *ifa = NLMSG_DATA(h); ++ struct rtattr *rta; ++ ++ ifs = calloc(1, sizeof(struct ifaddrs_storage)); ++ if (ifs == 0) return -1; ++ ++ for (ifs0 = ctx->hash[ifa->ifa_index%IFADDRS_HASH_SIZE]; ifs0; ifs0 = ifs0->hash_next) ++ if (ifs0->index == ifa->ifa_index) ++ break; ++ if (!ifs0) return 0; ++ ++ ifs->ifa.ifa_name = ifs0->ifa.ifa_name; ++ ifs->ifa.ifa_flags = ifs0->ifa.ifa_flags; ++ for (rta = NLMSG_RTA(h, sizeof(*ifa)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) { ++ switch (rta->rta_type) { ++ case IFA_ADDRESS: ++ ifs->ifa.ifa_addr = copy_addr(ifa->ifa_family, &ifs->addr, rta); ++ if (ifs->ifa.ifa_addr) ++ ifs->ifa.ifa_netmask = gen_netmask(ifa->ifa_family, &ifs->netmask, ifa->ifa_prefixlen); ++ break; ++ case IFA_BROADCAST: ++ /* For point-to-point links this is peer, but ifa_broadaddr ++ * and ifa_dstaddr are union, so this works for both. */ ++ ifs->ifa.ifa_broadaddr = copy_addr(ifa->ifa_family, &ifs->ifu, rta); ++ break; + } + } +- close(sock); +- void* last = 0; +- for(head = list; head; head=(stor*)head->next) last=head; +- head = last; +- dealwithipv6(&list, &head); +- *ifap = (struct ifaddrs*) list; ++ ++ addifaddrs(ctx, ifs); + return 0; +- err: +- close(sock); +- err2: +- freeifaddrs((struct ifaddrs*) list); +- return -1; + } + ++int getifaddrs(struct ifaddrs **ifap) ++{ ++ struct ifaddrs_ctx _ctx, *ctx = &_ctx; ++ struct __netlink_handle *nh; ++ int r = 0; ++ ++ nh = __netlink_open(NETLINK_ROUTE); ++ if (!nh) return -1; ++ memset(ctx, 0, sizeof(*ctx)); ++ if (__netlink_enumerate(nh, RTM_GETLINK, __handle_link, ctx)) r = -1; ++ if (__netlink_enumerate(nh, RTM_GETADDR, __handle_addr, ctx)) r = -1; ++ __netlink_close(nh); ++ if (r == 0) *ifap = &ctx->first->ifa; ++ else freeifaddrs(&ctx->first->ifa); ++ return r; ++} +diff --git a/src/network/if_nameindex.c b/src/network/if_nameindex.c +index 53b80b2..d4e8b2d 100644 +--- a/src/network/if_nameindex.c ++++ b/src/network/if_nameindex.c +@@ -1,55 +1,80 @@ + #define _GNU_SOURCE + #include <net/if.h> +-#include <stdlib.h> + #include <sys/socket.h> +-#include <sys/ioctl.h> + #include <errno.h> +-#include "syscall.h" ++#include <unistd.h> ++#include <stdlib.h> ++#include <string.h> ++#include "__netlink.h" ++ ++struct ifnamemap { ++ unsigned int index; ++ unsigned char namelen; ++ char name[IFNAMSIZ]; ++}; + +-static void *do_nameindex(int s, size_t n) ++struct ifnameindexctx { ++ unsigned int num; ++ unsigned int str_bytes; ++ struct ifnamemap *list; ++}; ++ ++static int __handle_link(void *pctx, struct nlmsghdr *h) + { +- size_t i, len, k; +- struct ifconf conf; +- struct if_nameindex *idx; +- +- idx = malloc(n * (sizeof(struct if_nameindex)+sizeof(struct ifreq))); +- if (!idx) return 0; +- +- conf.ifc_buf = (void *)&idx[n]; +- conf.ifc_len = len = n * sizeof(struct ifreq); +- if (ioctl(s, SIOCGIFCONF, &conf) < 0) { +- free(idx); +- return 0; +- } +- if (conf.ifc_len == len) { +- free(idx); +- return (void *)-1; +- } ++ struct ifnameindexctx *ctx = pctx; ++ struct ifinfomsg *ifim = NLMSG_DATA(h); ++ struct rtattr *rta; ++ struct ifnamemap *e; + +- n = conf.ifc_len / sizeof(struct ifreq); +- for (i=k=0; i<n; i++) { +- if (ioctl(s, SIOCGIFINDEX, &conf.ifc_req[i]) < 0) { +- k++; +- continue; +- } +- idx[i-k].if_index = conf.ifc_req[i].ifr_ifindex; +- idx[i-k].if_name = conf.ifc_req[i].ifr_name; ++ for (rta = NLMSG_RTA(h, sizeof(*ifim)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) { ++ if (rta->rta_type != IFLA_IFNAME) continue; ++ if (RTA_DATALEN(rta) > IFNAMSIZ) return -ENOBUFS; ++ ++ ctx->num++; ++ ctx->str_bytes += RTA_DATALEN(rta) + 1; ++ e = realloc(ctx->list, sizeof(struct ifnamemap[ctx->num])); ++ if (e == 0) return -ENOMEM; ++ ctx->list = e; ++ ++ e = &ctx->list[ctx->num-1]; ++ e->index = ifim->ifi_index; ++ e->namelen = RTA_DATALEN(rta); ++ memcpy(e->name, RTA_DATA(rta), IFNAMSIZ); + } +- idx[i-k].if_name = 0; +- idx[i-k].if_index = 0; + +- return idx; ++ return 0; + } + + struct if_nameindex *if_nameindex() + { +- size_t n; +- void *p = 0; +- int s = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); +- if (s>=0) { +- for (n=0; (p=do_nameindex(s, n)) == (void *)-1; n++); +- __syscall(SYS_close, s); ++ struct ifnameindexctx _ctx, *ctx = &_ctx; ++ struct if_nameindex *ifs = NULL; ++ struct __netlink_handle *nh; ++ int r, i; ++ char *p; ++ ++ nh = __netlink_open(NETLINK_ROUTE); ++ if (!nh) goto err; ++ memset(ctx, 0, sizeof(*ctx)); ++ r = __netlink_enumerate(nh, RTM_GETLINK, __handle_link, ctx); ++ __netlink_close(nh); ++ if (r < 0) goto err; ++ ++ ifs = malloc(sizeof(struct if_nameindex[ctx->num+1]) + ctx->str_bytes); ++ if (ifs == 0) goto err; ++ ++ p = (char*)ifs + sizeof(struct if_nameindex[ctx->num+1]); ++ for (i = 0; i < ctx->num; i++) { ++ ifs[i].if_index = ctx->list[i].index; ++ ifs[i].if_name = p; ++ memcpy(p, ctx->list[i].name, ctx->list[i].namelen); ++ p += ctx->list[i].namelen; ++ *p++ = 0; + } +- errno = ENOBUFS; +- return p; ++ ifs[i].if_index = 0; ++ ifs[i].if_name = 0; ++err: ++ free(ctx->list); ++ if (ifs == NULL) errno = ENOBUFS; ++ return ifs; + } +-- +1.9.1 + diff --git a/main/musl/APKBUILD b/main/musl/APKBUILD index 8cc3879ea0..9ec126bdd1 100644 --- a/main/musl/APKBUILD +++ b/main/musl/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Timo Teräs <timo.teras@iki.fi> pkgname=musl pkgver=1.0.0 -pkgrel=7 +pkgrel=8 pkgdesc="the musl c library (libc) implementation" url="http://www.musl-libc.org/" arch="all" @@ -16,8 +16,9 @@ subpackages="$pkgname-dev $pkgname-utils" source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz 0001-v1.0.0-to-2b74315d.patch 0002-2b74315d-to-b9b2db2f.patch - 0003-b9b2db2f-to-efe07b0f.patch + 0003-b9b2db2f-to-e94d0692.patch 1001-add-basic-dns-record-parsing-functions.patch + 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch getopt_long.c __stack_chk_fail_local.c @@ -117,8 +118,9 @@ crosstool() { md5sums="e54664fdf211d27737e328c4462b545e musl-1.0.0.tar.gz d081fc3424229c639e636be2dd00d221 0001-v1.0.0-to-2b74315d.patch 48fa02a48a33bbcb8149edf6540d02f9 0002-2b74315d-to-b9b2db2f.patch -b461fa6b4921ddd296795f431a74b8ce 0003-b9b2db2f-to-efe07b0f.patch +d0a6498cede60e70c468d9a44b968abe 0003-b9b2db2f-to-e94d0692.patch a3810683ef61ac27e2f6ec9801280c81 1001-add-basic-dns-record-parsing-functions.patch +d7775d12bb7903094a384626e8b060be 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch 61c6c1e84ed1df82abbe6d75e90cf21c getopt_long.c 0df687757221bbb0fc1aa67f1bd646f9 __stack_chk_fail_local.c 7b391300396e58fe9073866b5a80cfe8 getconf.c @@ -127,8 +129,9 @@ ef81489a6258501cf45db58dfc6d5211 getent sha256sums="1ad7f45d2972daff19c9e6a92714e6d70f4aad003cd8c3d1e6113432114c1a32 musl-1.0.0.tar.gz aa632b635d472d5a6a49800899ce34cddc89a63a489690faa683d08622b9cd60 0001-v1.0.0-to-2b74315d.patch edc0cebaabd16f894d91c1860bfb70d3f2d9a70cf558c5455689610374447f7d 0002-2b74315d-to-b9b2db2f.patch -d524109b51f0c24de58ff32c9b9e64a7f69885c96e52ec71638ebe373959a1e5 0003-b9b2db2f-to-efe07b0f.patch +8ee26d42062a4bc91a7fc95fe3f257b9ffcbef600a6344257f7681f358a4a012 0003-b9b2db2f-to-e94d0692.patch 758390768b1bc4159d56908ca332b9640cd0552ed3b4b2b8d4a6d499c54c11a1 1001-add-basic-dns-record-parsing-functions.patch +3809a7758c0c138a03fae7ad8e27a1c34090c44260a93fcbbb8966994755f450 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch d9b644ec20bc33e81a7c52b9fcf7973d835923a69faf50f03db45534b811bd96 getopt_long.c 299a7d75a09de3e2e11e7fb4acc3182e4a14e868093d2f30938fce9bfcff13da __stack_chk_fail_local.c 530ea449f93d53fafcb377fa0a23a7564f2961e49c07a8fdef6c960110317301 getconf.c @@ -137,8 +140,9 @@ d6996273f5aaaed429058257e4646b243d9e3a4d8609522f802762453f5be4cb getent sha512sums="c76cbfe60cbe9b1ceb1faedddf2dcce0f11c942c8f74e4f217efe63e8e1d7be70fcb6cf1182eeaee90441152c4493d678682cb247a0dbc7537d24f943a7bbdf8 musl-1.0.0.tar.gz e04f0f9de2859d18cb13aa8bfd839cc757aa9d835f133e46b48a760c7e689a92c641abe1e84dcaab6134c22500603e66d9a880f9b80b77e36a063348f5879878 0001-v1.0.0-to-2b74315d.patch 19c09e09d61ba31caeece27ea4241be4f14f73ab958da7f37fc4f0c8391fcaa912a750a2b79c29b3fec24ad22995244c91d1f0372d9b8481c99411e2442c2d4e 0002-2b74315d-to-b9b2db2f.patch -d61f309d10621f7ac330c30c72369697c149de67f264f67fbb666bf748350033bbbe4eceeafd9dca27b277c39707575084a0f2d553682147d35e394494eeae96 0003-b9b2db2f-to-efe07b0f.patch +352b7c0693ebe6093e71d4e9cb704ff569e0e0ae2dcc576d3dc4883e7dddd1ffbc09d8365cceabbeec6b974496dddb9ed7bfacaa244c92c2735caf08c843593a 0003-b9b2db2f-to-e94d0692.patch dad965258daf69371b844f76bfe5a914b0eca0ca76f3fc340b8fd7acf598b5f87bbe6d68b1f43ed0293ee0ed3bfd85d5173ccc169aa6265646248d5b8a906708 1001-add-basic-dns-record-parsing-functions.patch +d2477eca267dae1da25c5612e519a95048a7d651ed2f98b247c735bfd940aa2042624821e03c1f3ed6bc832ffcd0c1342f04bece80fd4aa37729ada222889e9c 1002-reimplement-if_nameindex-and-getifaddrs-using-netlin.patch 140f3f20d30bd95ebce8c41b8cc7f616c6cbedf4ea06c729c21014e74f6043796825cc40ebc5180620ea38173afdba23f09ebf6d8b11fa05440b14d23764fca9 getopt_long.c 062bb49fa54839010acd4af113e20f7263dde1c8a2ca359b5fb2661ef9ed9d84a0f7c3bc10c25dcfa10bb3c5a4874588dff636ac43d5dbb3d748d75400756d0b __stack_chk_fail_local.c d638cdd02371351190fd0545fb83f44b822fa8c930e9fb47ef93d32a1aaee27641f875e10fa2e9833f1a56dfc2055fb89932a89c88da3e2eb17529bca58f5182 getconf.c |