[COMMIT osv master] libc/getifaddrs: Extract and use allocate_and_add_ifaddrs

2016-10-26 Thread Commit Bot

From: Benoît Canet 
Committer: Nadav Har'El 
Branch: master

libc/getifaddrs: Extract and use allocate_and_add_ifaddrs

The code will need to allocate twice as much
ifaddr_storage structure to be able to return mac
addresses in their own ifaddrs structure.

Signed-off-by: Benoît Canet 
Message-Id: <1477485154-13682-3-git-send-email-ben...@scylladb.com>

---
diff --git a/libc/network/getifaddrs.c b/libc/network/getifaddrs.c
--- a/libc/network/getifaddrs.c
+++ b/libc/network/getifaddrs.c
@@ -112,18 +112,27 @@ static void dealwithipv6(stor **list, stor** head)
fclose(f);
 }

+int allocate_and_add_ifaddrs(stor **list, stor **head, struct if_nameindex  
*ii)

+{
+   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) {
+   return 0;
+   }
+   }
+   return i;
+}
+
 int getifaddrs(struct ifaddrs **ifap)
 {
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(, , ii[i].if_name);
-   if(!curr) {
-   if_freenameindex(ii);
-   goto err2;
-   }
+   if (!allocate_and_add_ifaddrs(, , ii)) {
+   if_freenameindex(ii);
+   goto err2;
}
if_freenameindex(ii);

--
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[COMMIT osv master] libc/getifaddrs: Also return ifaddrs with ether hw addresses

2016-10-26 Thread Commit Bot

From: Benoît Canet 
Committer: Nadav Har'El 
Branch: master

libc/getifaddrs: Also return ifaddrs with ether hw addresses

Before this patch, OSv's getifaddrs() returns for each network interface
a single entry, with the AF_INET address family and sockaddr_in address
type.

Linux's getifaddrs() returns an additional entry for each interface,
with the AF_PACKET address family and sockaddr_ll address type. This
sockaddr_ll structure ("ll" = link level) contains the MAC address of this
interface, and some code expects to find these interfaces (see issue #787).
So this patch adds them, after the list of AF_INET interfaces.

Fixes #787.

Signed-off-by: Benoît Canet 
Signed-off-by: Nadav Har'El 
Message-Id: <1477485154-13682-4-git-send-email-ben...@scylladb.com>

---
diff --git a/libc/network/getifaddrs.c b/libc/network/getifaddrs.c
--- a/libc/network/getifaddrs.c
+++ b/libc/network/getifaddrs.c
@@ -11,10 +11,13 @@
 #include  /* inet_pton */
 #include 
 #include 
+#include 
+#include 

 typedef union {
struct sockaddr_in6 v6;
struct sockaddr_in v4;
+   struct sockaddr_ll hw;
 } soa;

 typedef struct ifaddrs_storage {
@@ -124,15 +127,70 @@ int allocate_and_add_ifaddrs(stor **list, stor  
**head, struct if_nameindex *ii)

return i;
 }

+int fill_mac_addrs(int sock, stor *list, struct if_nameindex *ii)
+{
+   stor *head;
+   size_t i;
+
+   for(head = list, i = 0;
+   head; head = (stor*)(head->next)) {
+   struct sockaddr_ll *hw_addr = (struct sockaddr_ll *) 
>addr;
+   head->ifa.ifa_addr = (struct sockaddr*) >addr;
+   struct ifreq req;
+   int ret;
+
+   if (!ii[i].if_name) {
+   continue;
+   }
+
+   /* zero the ifreq structure */
+   memset(, 0, sizeof(req));
+
+   /* fill in the interface name */
+   strlcpy(req.ifr_name, ii[i].if_name, IFNAMSIZ);
+
+   /* Get the hardware address */
+   ret = ioctl(sock, SIOCGIFHWADDR, );
+   if (ret == -1) {
+   return ret;
+   }
+
+   /* Fill address, index, type, length, familly */
+   memcpy(hw_addr->sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+   hw_addr->sll_ifindex  = ii[i].if_index;
+   hw_addr->sll_hatype = ARPHRD_ETHER;
+   hw_addr->sll_halen  = IFHWADDRLEN;
+   hw_addr->sll_family = AF_PACKET;
+
+   /* Get and fill the address flags */
+   ret = ioctl(sock, SIOCGIFFLAGS, );
+   if (ret == - 1) {
+   return ret;
+   }
+   head->ifa.ifa_flags = req.ifr_flags;
+   i++;
+   }
+
+   return 0;
+}
+
 int getifaddrs(struct ifaddrs **ifap)
 {
stor *list = 0, *head = 0;
struct if_nameindex* ii = if_nameindex();
if(!ii) return -1;
+   int addr_count;
size_t i;
-   if (!allocate_and_add_ifaddrs(, , ii)) {
-   if_freenameindex(ii);
-   goto err2;
+   // allocate and add to the list twice the number of
+   // interface of ifaddr storage in order to have enough
+   // for MAC HW addresses that require their own location.
+   for (i = 0; i < 2; i++) {
+   addr_count =
+   allocate_and_add_ifaddrs(, , ii);
+   if (!addr_count) {
+   if_freenameindex(ii);
+   goto err2;
+   }
}
if_freenameindex(ii);

@@ -142,7 +200,9 @@ int getifaddrs(struct ifaddrs **ifap)
struct ifconf conf = {.ifc_len = sizeof reqs, .ifc_req = reqs};
if(-1 == ioctl(sock, SIOCGIFCONF, )) goto err;
size_t reqitems = conf.ifc_len / sizeof(struct ifreq);
-   for(head = list; head; head = (stor*)head->next) {
+   int j;
+   // loop and fill the INET addrs
+	for(head = list, j = 0; head && j < addr_count; head = (stor*)head->next,  
j++) {

for(i = 0; i < reqitems; i++) {
// get SIOCGIFADDR of active interfaces.
if(!strcmp(reqs[i].ifr_name, head->name)) {
@@ -173,6 +233,9 @@ int getifaddrs(struct ifaddrs **ifap)
head->ifa.ifa_ifu.ifu_dstaddr = (struct sockaddr*) 
>dst;
}
}
+   if (-1 == fill_mac_addrs(sock, head, ii)) {
+   goto err;
+   }
close(sock);
void* last = 0;
for(head = list; head; head=(stor*)head->next) last=head;

--
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[COMMIT osv master] uipc_socket.cc: prevent use after free bug in soisdisconnected

2016-10-26 Thread Commit Bot

From: Timmons C. Player 
Committer: Nadav Har'El 
Branch: master

uipc_socket.cc: prevent use after free bug in soisdisconnected

Simultaneously closing a socket from both the network and user
space sides can trigger a use after free bug in soisdisconnected.
This change uses the existing socket reference counting mechanism
to prevent the socket from being freed until after this function
has completed.

Signed-off-by: Timmons C. Player 
Message-Id: <1473445171-17551-1-git-send-email-timmons.pla...@spirent.com>

---
diff --git a/bsd/sys/kern/uipc_socket.cc b/bsd/sys/kern/uipc_socket.cc
--- a/bsd/sys/kern/uipc_socket.cc
+++ b/bsd/sys/kern/uipc_socket.cc
@@ -3469,20 +3469,45 @@ void
 soisdisconnected(struct socket *so)
 {

+   bool do_release = false;
/*
 * Note: This code assumes that SOCK_LOCK(so) and
 * SOCKBUF_LOCK(>so_rcv) are the same.
 */
SOCK_LOCK(so);
+   /*
+* If user space has already closed the socket, then it's possible
+* for some of these wakeups to trigger soclose.  We need to prevent
+* the socket from getting freed in the middle of this function, so
+* bump the reference count.
+*/
+   soref(so);
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
so->so_state |= SS_ISDISCONNECTED;
so->so_rcv.sb_state |= SBS_CANTRCVMORE;
sorwakeup_locked(so);
so->so_snd.sb_state |= SBS_CANTSENDMORE;
sbdrop_locked(so, >so_snd, so->so_snd.sb_cc);
sowwakeup_locked(so);
+   /*
+* If we have the only reference, then we need to call sorele to
+* free the socket.  If not, then we just quietly drop the ref
+* count ourselves to avoid taking the accept lock and possibly
+* deadlocking.
+*/
+   if (so->so_count == 1) {
+   do_release = true;
+   } else {
+   so->so_count--;
+   }
SOCK_UNLOCK(so);
wakeup(>so_timeo);
+
+   if (do_release) {
+   ACCEPT_LOCK();
+   SOCK_LOCK(so);
+   sorele(so);
+   }
 }

 /*

--
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[PATCH v3 3/3] libc/getifaddrs: Also return ifaddrs with ether hw addresses

2016-10-26 Thread Benoît Canet
Add these structure add the end of the list after the
INET and INET6 addresses are filled.

Signed-off-by: Benoît Canet 
---
 libc/network/getifaddrs.c | 71 ---
 1 file changed, 67 insertions(+), 4 deletions(-)

diff --git a/libc/network/getifaddrs.c b/libc/network/getifaddrs.c
index 7bab121..4cdf4d6 100644
--- a/libc/network/getifaddrs.c
+++ b/libc/network/getifaddrs.c
@@ -11,10 +11,13 @@
 #include  /* inet_pton */
 #include 
 #include 
+#include 
+#include 
 
 typedef union {
struct sockaddr_in6 v6;
struct sockaddr_in v4;
+   struct sockaddr_ll hw;
 } soa;
 
 typedef struct ifaddrs_storage {
@@ -124,15 +127,70 @@ int allocate_and_add_ifaddrs(stor **list, stor **head, 
struct if_nameindex *ii)
return i;
 }
 
+int fill_mac_addrs(int sock, stor *list, struct if_nameindex *ii)
+{
+   stor *head;
+   size_t i;
+
+   for(head = list, i = 0;
+   head; head = (stor*)(head->next)) {
+   struct sockaddr_ll *hw_addr = (struct sockaddr_ll *) 
>addr;
+   head->ifa.ifa_addr = (struct sockaddr*) >addr;
+   struct ifreq req;
+   int ret;
+
+   if (!ii[i].if_name) {
+   continue;
+   }
+
+   /* zero the ifreq structure */
+   memset(, 0, sizeof(req));
+
+   /* fill in the interface name */
+   strlcpy(req.ifr_name, ii[i].if_name, IFNAMSIZ);
+
+   /* Get the hardware address */
+   ret = ioctl(sock, SIOCGIFHWADDR, );
+   if (ret == -1) {
+   return ret;
+   }
+
+   /* Fill address, index, type, length, familly */
+   memcpy(hw_addr->sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+   hw_addr->sll_ifindex  = ii[i].if_index;
+   hw_addr->sll_hatype = ARPHRD_ETHER;
+   hw_addr->sll_halen  = IFHWADDRLEN;
+   hw_addr->sll_family = AF_PACKET;
+
+   /* Get and fill the address flags */
+   ret = ioctl(sock, SIOCGIFFLAGS, );
+   if (ret == - 1) {
+   return ret;
+   }
+   head->ifa.ifa_flags = req.ifr_flags;
+   i++;
+   }
+
+   return 0;
+}
+
 int getifaddrs(struct ifaddrs **ifap)
 {
stor *list = 0, *head = 0;
struct if_nameindex* ii = if_nameindex();
if(!ii) return -1;
+   int addr_count;
size_t i;
-   if (!allocate_and_add_ifaddrs(, , ii)) {
-   if_freenameindex(ii);
-   goto err2;
+   // allocate and add to the list twice the number of
+   // interface of ifaddr storage in order to have enough
+   // for MAC HW addresses that require their own location.
+   for (i = 0; i < 2; i++) {
+   addr_count =
+   allocate_and_add_ifaddrs(, , ii);
+   if (!addr_count) {
+   if_freenameindex(ii);
+   goto err2;
+   }
}
if_freenameindex(ii);
 
@@ -142,7 +200,9 @@ int getifaddrs(struct ifaddrs **ifap)
struct ifconf conf = {.ifc_len = sizeof reqs, .ifc_req = reqs};
if(-1 == ioctl(sock, SIOCGIFCONF, )) goto err;
size_t reqitems = conf.ifc_len / sizeof(struct ifreq);
-   for(head = list; head; head = (stor*)head->next) {
+   int j;
+   // loop and fill the INET addrs
+   for(head = list, j = 0; head && j < addr_count; head = 
(stor*)head->next, j++) {
for(i = 0; i < reqitems; i++) {
// get SIOCGIFADDR of active interfaces.
if(!strcmp(reqs[i].ifr_name, head->name)) {
@@ -173,6 +233,9 @@ int getifaddrs(struct ifaddrs **ifap)
head->ifa.ifa_ifu.ifu_dstaddr = (struct sockaddr*) 
>dst;
}
}
+   if (-1 == fill_mac_addrs(sock, head, ii)) {
+   goto err;
+   }
close(sock);
void* last = 0;
for(head = list; head; head=(stor*)head->next) last=head;
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [PATCH v2 3/3] libc/getifaddrs: Also return ifaddrs with ether hw addresses

2016-10-26 Thread Benoît Canet
On Wed, Oct 26, 2016 at 2:03 PM, Nadav Har'El  wrote:

> Please add "Fixes #787" to the commit message.
>
> Thanks, the patch looks mostly correct, but one question below.
>
> On Wed, Oct 26, 2016 at 2:33 PM, Benoît Canet  com> wrote:
>
>> Add these structure add the end of the list after the
>> INET and INET6 addresses are filled.
>>
>> Signed-off-by: Benoît Canet 
>> ---
>>  libc/network/getifaddrs.c | 70 ++
>> ++---
>>  1 file changed, 66 insertions(+), 4 deletions(-)
>>
>> diff --git a/libc/network/getifaddrs.c b/libc/network/getifaddrs.c
>> index 7bab121..bfce1e9 100644
>> --- a/libc/network/getifaddrs.c
>> +++ b/libc/network/getifaddrs.c
>> @@ -11,6 +11,8 @@
>>  #include  /* inet_pton */
>>  #include 
>>  #include 
>> +#include 
>> +#include 
>>
>>  typedef union {
>> struct sockaddr_in6 v6;
>> @@ -124,15 +126,70 @@ int allocate_and_add_ifaddrs(stor **list, stor
>> **head, struct if_nameindex *ii)
>> return i;
>>  }
>>
>> +int fill_mac_addrs(int sock, stor *list, struct if_nameindex *ii)
>> +{
>> +   stor *head;
>> +   size_t i;
>> +
>> +   for(head = list, i = 0;
>> +   head; head = (stor*)(head->next)) {
>> +   struct sockaddr_ll *hw_addr = (struct sockaddr_ll *)
>> >addr;
>> +   head->ifa.ifa_addr = (struct sockaddr*) >addr;
>> +   struct ifreq req;
>> +   int ret;
>> +
>> +   if (!ii[i].if_name) {
>> +   continue;
>> +   }
>>
>
> Shouldn't we also skip non-AF_INET interfaces, like loopback?
>

127.0.0.1 look totally like an IPV4 address so it's AF_INET.

See http://man7.org/linux/man-pages/man3/getifaddrs.3.html or man
getifaddrs .

So lo seems to have an AF_PACKET entry in the getifaddrs list.


>
> I think your code makes two copies of the loopback interface, and then
> tries to find the hw address for that interface (I don't know what it
> finds). Would have been nicer to have just one copy.
>
> Is it really necessary for you to call allocate_and_add_ifaddrs() twice?
> Couldn't you fill the normal interfaces just once (as in the original
> code), and then loop over them adding *additional* AF_PACKET interface for
> each AF_INET interface?
>

It make the code manipulating the linked list simple. I think that having
simple code for this is a strong selling point.


>
> (Another possible problem with the way you did it which I don't fully
> understand how it worked for you: sockaddr_ll has a different length than
> sockaddr_in. So how could you allocate the structure with the normal code
> which allocated sockaddr_in, and then put a sockaddr_ll in there?)
>

Well spotted.

I just have to put sockaddr_ll in the soa union at the begining of the file.

Thanks


>
>
>> +
>> +   /* zero the ifreq structure */
>> +   memset(, 0, sizeof(req));
>> +
>> +   /* fill in the interface name */
>> +   strlcpy(req.ifr_name, ii[i].if_name, IFNAMSIZ);
>> +
>> +   /* Get the hardware address */
>> +   ret = ioctl(sock, SIOCGIFHWADDR, );
>> +   if (ret == -1) {
>> +   return ret;
>> +   }
>> +
>> +   /* Fill address, index, type, length, familly */
>> +   memcpy(hw_addr->sll_addr, req.ifr_hwaddr.sa_data,
>> IFHWADDRLEN);
>> +   hw_addr->sll_ifindex  = ii[i].if_index;
>> +   hw_addr->sll_hatype = ARPHRD_ETHER;
>> +   hw_addr->sll_halen  = IFHWADDRLEN;
>> +   hw_addr->sll_family = AF_PACKET;
>> +
>> +   /* Get and fill the address flags */
>> +   ret = ioctl(sock, SIOCGIFFLAGS, );
>> +   if (ret == - 1) {
>> +   return ret;
>> +   }
>> +   head->ifa.ifa_flags = req.ifr_flags;
>> +   i++;
>> +   }
>> +
>> +   return 0;
>> +}
>> +
>>  int getifaddrs(struct ifaddrs **ifap)
>>  {
>> stor *list = 0, *head = 0;
>> struct if_nameindex* ii = if_nameindex();
>> if(!ii) return -1;
>> +   int addr_count;
>> size_t i;
>> -   if (!allocate_and_add_ifaddrs(, , ii)) {
>> -   if_freenameindex(ii);
>> -   goto err2;
>> +   // allocate and add to the list twice the number of
>> +   // interface of ifaddr storage in order to have enough
>> +   // for MAC HW addresses that require their own location.
>> +   for (i = 0; i < 2; i++) {
>> +   addr_count =
>> +   allocate_and_add_ifaddrs(, , ii);
>> +   if (!addr_count) {
>> +   if_freenameindex(ii);
>> +   goto err2;
>> +   }
>> }
>> if_freenameindex(ii);
>>
>> @@ -142,7 +199,9 @@ int getifaddrs(struct ifaddrs **ifap)
>> struct ifconf conf = {.ifc_len = sizeof reqs, .ifc_req = 

[PATCH v2 1/3] libc: Move getifaddrs.c from musl to libc.

2016-10-26 Thread Benoît Canet
Signed-off-by: Benoît Canet 
---
 Makefile  |   2 +-
 libc/network/getifaddrs.c | 180 ++
 2 files changed, 181 insertions(+), 1 deletion(-)
 create mode 100644 libc/network/getifaddrs.c

diff --git a/Makefile b/Makefile
index e294a03..03b06e2 100644
--- a/Makefile
+++ b/Makefile
@@ -1354,7 +1354,7 @@ musl += network/getservbyname_r.o
 musl += network/getservbyname.o
 musl += network/getservbyport_r.o
 musl += network/getservbyport.o
-musl += network/getifaddrs.o
+libc += network/getifaddrs.o
 libc += network/if_nameindex.o
 musl += network/if_freenameindex.o
 
diff --git a/libc/network/getifaddrs.c b/libc/network/getifaddrs.c
new file mode 100644
index 000..a14ac1b
--- /dev/null
+++ b/libc/network/getifaddrs.c
@@ -0,0 +1,180 @@
+/* (C) 2013 John Spencer. released under musl's standard MIT license. */
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+#include 
+#include 
+#include  /* IFNAMSIZ, ifreq, ifconf */
+#include 
+#include 
+#include 
+#include 
+#include  /* inet_pton */
+#include 
+#include 
+
+typedef union {
+   struct sockaddr_in6 v6;
+   struct sockaddr_in v4;
+} soa;
+
+typedef struct ifaddrs_storage {
+   struct ifaddrs ifa;
+   soa addr;
+   soa netmask;
+   soa dst;
+   char name[IFNAMSIZ+1];
+} stor;
+#define next ifa.ifa_next
+
+static stor* list_add(stor** list, stor** head, char* ifname)
+{
+   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;
+   }
+   return curr;
+}
+
+void freeifaddrs(struct ifaddrs *ifp)
+{
+   stor *head = (stor *) ifp;
+   while(head) {
+   void *p = head;
+   head = (stor *) head->next;
+   free(p);
+   }
+}
+
+static void ipv6netmask(unsigned prefix_length, struct sockaddr_in6 *sa)
+{
+   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;
+   }
+}
+
+static void dealwithipv6(stor **list, stor** head)
+{
+   FILE* f = fopen("/proc/net/if_inet6", "r");
+   /* 0001 01 80 10 80 lo
+  AB  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", , , , , name)) {
+   struct sockaddr_in6 sa = {0};
+   if(1 == inet_pton(AF_INET6, v6conv, _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*) 
>addr;
+   ipv6netmask(c, );
+   curr->netmask.v6 = sa;
+   curr->ifa.ifa_netmask = (struct sockaddr*) 
>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;
+   }
+   }
+   out:
+   fclose(f);
+}
+
+int getifaddrs(struct ifaddrs **ifap)
+{
+   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(, , ii[i].if_name);
+   if(!curr) {
+   if_freenameindex(ii);
+