aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2014-04-09 13:25:31 +0300
committerTimo Teräs <timo.teras@iki.fi>2014-04-09 13:27:19 +0300
commita488eea97d8d9d53f9a361465b341221246377f5 (patch)
tree6fb83b9029119d329ea1ecdf4f1cbfbbb56280f0
parent195f616f91ed4bd9733ef60e9945fdb292904162 (diff)
downloadaports-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.
-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.patch726
-rw-r--r--main/musl/APKBUILD14
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