From 8eb6953a650f28b21016f63de8639ba104655a21 Mon Sep 17 00:00:00 2001
From: Joel Cunningham <joel.cunningham@me.com>
Date: Thu, 19 Jan 2017 21:38:46 -0600
Subject: [PATCH] Task #14314: Add interface name/index APIs

This commit adds the following sets of interface name/index APIs:

Interface Identification APIs from RFC 3493:
  * lwip_if_nametoindex (COMPAT macro if_nametoindex)
  * lwip_if_indextoname (COMPAT macro if_indextoname)

netifapi:
  * netifapi_netif_name_to_index
  * netifapi_netif_index_to_name

netif:
  * netif_name_to_index
  * netif_index_to_name
  * netif_num_to_index
  * netif_index_to_num
---
 src/api/if.c                | 73 ++++++++++++++++++++++++++++++++++
 src/api/netifapi.c          | 95 +++++++++++++++++++++++++++++++++++++++++++++
 src/core/netif.c            | 50 ++++++++++++++++++++++++
 src/include/lwip/if.h       | 54 ++++++++++++++++++++++++++
 src/include/lwip/netif.h    |  8 ++++
 src/include/lwip/netifapi.h | 14 +++++++
 src/include/posix/net/if.h  | 33 ++++++++++++++++
 7 files changed, 327 insertions(+)
 create mode 100644 src/api/if.c
 create mode 100644 src/include/lwip/if.h
 create mode 100644 src/include/posix/net/if.h

diff --git a/src/api/if.c b/src/api/if.c
new file mode 100644
index 0000000..e511bf5
--- /dev/null
+++ b/src/api/if.c
@@ -0,0 +1,73 @@
+/**
+ * @file
+ * Interface Identification APIs from:
+ *              RFC 3493: Basic Socket Interface Extensions for IPv6
+ *                  Section 4: Interface Identification
+ */
+
+/*
+ * Copyright (c) 2017 Joel Cunningham <joel.cunningham@me.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Joel Cunningham <joel.cunningham@me.com>
+ *
+ */
+#include "lwip/opt.h"
+
+#if LWIP_SOCKET
+
+#include "lwip/netifapi.h"
+
+char *
+lwip_if_indextoname(unsigned ifindex, char *ifname)
+{
+  err_t err;
+  if (ifindex > 0xff) {
+    return NULL;
+  }
+  
+  err = netifapi_netif_index_to_name((u8_t)ifindex, ifname);
+  if (!err && ifname[0] != '\0') {
+    return ifname;
+  }
+  return NULL;
+}
+
+unsigned int
+lwip_if_nametoindex(const char *ifname)
+{
+  err_t err;
+  u8_t index;
+  
+  err = netifapi_netif_name_to_index(ifname, &index);
+  if (!err) {
+    return index;
+  }
+  return 0; /* invalid index */
+}
+
+#endif /* LWIP_SOCKET */
diff --git a/src/api/netifapi.c b/src/api/netifapi.c
index fef05a3..364889d 100644
--- a/src/api/netifapi.c
+++ b/src/api/netifapi.c
@@ -46,6 +46,8 @@
 #include "lwip/memp.h"
 #include "lwip/priv/tcpip_priv.h"
 
+#include <string.h> /* strncpy */
+
 #define NETIFAPI_VAR_REF(name)      API_VAR_REF(name)
 #define NETIFAPI_VAR_DECLARE(name)  API_VAR_DECLARE(struct netifapi_msg, name)
 #define NETIFAPI_VAR_ALLOC(name)    API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM)
@@ -96,6 +98,37 @@ netifapi_do_netif_set_addr(struct tcpip_api_call_data *m)
 #endif /* LWIP_IPV4 */
 
 /**
+* Call netif_name_to_index() inside the tcpip_thread context.
+*/
+static err_t
+netifapi_do_name_to_index(struct tcpip_api_call_data *m)
+{
+  /* cast through void* to silence alignment warnings.
+   * We know it works because the structs have been instantiated as struct netifapi_msg */
+  struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
+
+  msg->msg.ifs.index = netif_name_to_index(msg->msg.ifs.name);
+  return ERR_OK;
+}
+
+/**
+* Call netif_index_to_name() inside the tcpip_thread context.
+*/
+static err_t
+netifapi_do_index_to_name(struct tcpip_api_call_data *m)
+{
+  /* cast through void* to silence alignment warnings.
+   * We know it works because the structs have been instantiated as struct netifapi_msg */
+  struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
+
+  if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name)) {
+    /* return failure via empty name */
+    msg->msg.ifs.name[0] = '\0';
+  }
+  return ERR_OK;
+}
+
+/**
  * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
  * tcpip_thread context.
  */
@@ -218,4 +251,66 @@ netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
   return err;
 }
 
+/**
+* @ingroup netifapi_netif
+* Call netif_name_to_index() in a thread-safe way by running that function inside the
+* tcpip_thread context.
+*
+* @param name the interface name of the netif
+* @param index output index of the found netif
+*/
+err_t
+netifapi_netif_name_to_index(const char *name, u8_t *index)
+{
+  err_t err;
+  NETIFAPI_VAR_DECLARE(msg);
+  NETIFAPI_VAR_ALLOC(msg);
+
+  *index = 0;
+
+#if LWIP_MPU_COMPATIBLE
+  strncpy(NETIFAPI_VAR_REF(msg).msg.ifs.name, name, IF_NAMESIZE - 1);
+  NETIFAPI_VAR_REF(msg).msg.ifs.name[IF_NAMESIZE - 1] = '\0';
+#else
+  NETIFAPI_VAR_REF(msg).msg.ifs.name = (char *)name;
+#endif /* LWIP_MPU_COMPATIBLE */
+  err = tcpip_api_call(netifapi_do_name_to_index, &API_VAR_REF(msg).call);
+  if (!err) {
+    *index = NETIFAPI_VAR_REF(msg).msg.ifs.index;
+  }
+  NETIFAPI_VAR_FREE(msg);
+  return err;
+}
+
+/**
+* @ingroup netifapi_netif
+* Call netif_index_to_name() in a thread-safe way by running that function inside the
+* tcpip_thread context.
+*
+* @param index the interface index of the netif
+* @param name output name of the found netif, empty '\0' string if netif not found.
+*             name should be of at least IF_NAMESIZE bytes
+*/
+err_t
+netifapi_netif_index_to_name(u8_t index, char *name)
+{
+  err_t err;
+  NETIFAPI_VAR_DECLARE(msg);
+  NETIFAPI_VAR_ALLOC(msg);
+
+  NETIFAPI_VAR_REF(msg).msg.ifs.index = index;
+#if !LWIP_MPU_COMPATIBLE
+  NETIFAPI_VAR_REF(msg).msg.ifs.name = name;
+#endif /* LWIP_MPU_COMPATIBLE */
+  err = tcpip_api_call(netifapi_do_index_to_name, &API_VAR_REF(msg).call);
+#if LWIP_MPU_COMPATIBLE
+  if (!err) {
+    strncpy(name, NETIFAPI_VAR_REF(msg).msg.ifs.name, IF_NAMESIZE - 1);
+    name[IF_NAMESIZE - 1] = '\0';
+  }
+#endif /* LWIP_MPU_COMPATIBLE */
+  NETIFAPI_VAR_FREE(msg);
+  return err;
+}
+
 #endif /* LWIP_NETIF_API */
diff --git a/src/core/netif.c b/src/core/netif.c
index c5bd3c5..ded899c 100644
--- a/src/core/netif.c
+++ b/src/core/netif.c
@@ -65,6 +65,7 @@
 #include "lwip/stats.h"
 #include "lwip/sys.h"
 #include "lwip/ip.h"
+#include "lwip/if.h"
 #if ENABLE_LOOPBACK
 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
 #include "lwip/tcpip.h"
@@ -1268,3 +1269,52 @@ netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipa
   return ERR_IF;
 }
 #endif /* LWIP_IPV6 */
+
+/**
+* @ingroup netif_if
+* Return the interface index for the netif with name
+* or 0 (invalid interface) if not found/on error
+*
+* @param name the name of the netif
+*/
+u8_t
+netif_name_to_index(const char *name)
+{
+  struct netif *netif = netif_find(name);
+  if (netif != NULL) {
+    return netif_num_to_index(netif);
+  }
+  /* No name found, return invalid index */
+  return 0;
+}
+
+/**
+* @ingroup netif_if
+* Return the interface name for the netif matching index
+* or NULL if not found/on error
+*
+* @param index the interface index of the netif
+* @param name char buffer of at least IF_NAMESIZE bytes
+*/
+char *
+netif_index_to_name(u8_t index, char *name)
+{
+  struct netif *curif = netif_list;
+  u8_t num;
+  if (index == 0) {
+    return NULL; /* indexes start at 1 */
+  }
+  num = netif_index_to_num(index);
+
+  /* find netif from num */
+  while (curif != NULL) {
+    if (curif->num == num) {
+      name[0] = curif->name[0];
+      name[1] = curif->name[1];
+      lwip_itoa(&name[2], IF_NAMESIZE - 2, num);
+      return name;
+    }
+    curif = curif->next;
+  }
+  return NULL;
+}
diff --git a/src/include/lwip/if.h b/src/include/lwip/if.h
new file mode 100644
index 0000000..bce4a5f
--- /dev/null
+++ b/src/include/lwip/if.h
@@ -0,0 +1,54 @@
+/**
+ * @file
+ * Interface Identification APIs from:
+ *              RFC 3493: Basic Socket Interface Extensions for IPv6
+ *                  Section 4: Interface Identification
+ */
+
+/*
+ * Copyright (c) 2017 Joel Cunningham <joel.cunningham@me.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Joel Cunningham <joel.cunningham@me.com>
+ *
+ */
+#ifndef LWIP_HDR_IF_H
+#define LWIP_HDR_IF_H
+
+#include "lwip/opt.h"
+
+#define IF_NAMESIZE 6 /* 2 chars, 3 nums, 1 \0 */
+
+char * lwip_if_indextoname(unsigned ifindex, char *ifname);
+unsigned int lwip_if_nametoindex(const char *ifname);
+
+#if LWIP_COMPAT_SOCKETS
+#define if_indextoname(ifindex, ifname)  lwip_if_indextoname(ifindex,ifname)
+#define if_nametoindex(ifname)           lwip_if_nametoindex(ifname)
+#endif /* LWIP_COMPAT_SOCKETS */
+
+#endif /* LWIP_HDR_IF_H */
diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h
index 8160488..6fd20a3 100644
--- a/src/include/lwip/netif.h
+++ b/src/include/lwip/netif.h
@@ -490,6 +490,14 @@ err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t
 #define NETIF_SET_HWADDRHINT(netif, hint)
 #endif /* LWIP_NETIF_HWADDRHINT */
 
+/* @ingroup netif */
+u8_t netif_name_to_index(const char *name);
+char * netif_index_to_name(u8_t index, char *name);
+
+/* Interface indexes always start at 1 per RFC 3493, section 4, num starts at 0 */
+#define netif_num_to_index(netif)   ((netif)->num + 1)
+#define netif_index_to_num(index)   ((index) - 1)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/include/lwip/netifapi.h b/src/include/lwip/netifapi.h
index 8bd2b4f..79369c2 100644
--- a/src/include/lwip/netifapi.h
+++ b/src/include/lwip/netifapi.h
@@ -40,6 +40,7 @@
 #include "lwip/netif.h"
 #include "lwip/dhcp.h"
 #include "lwip/autoip.h"
+#include "lwip/if.h"
 #include "lwip/priv/tcpip_priv.h"
 
 #ifdef __cplusplus
@@ -73,6 +74,14 @@ struct netifapi_msg {
       netifapi_void_fn voidfunc;
       netifapi_errt_fn errtfunc;
     } common;
+    struct {
+#if LWIP_MPU_COMPATIBLE
+      char name[IF_NAMESIZE];
+#else /* LWIP_MPU_COMPATIBLE */
+      char *name;
+#endif /* LWIP_MPU_COMPATIBLE */
+      u8_t index;
+    } ifs;
   } msg;
 };
 
@@ -93,6 +102,11 @@ err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
                             netifapi_errt_fn errtfunc);
 
 /** @ingroup netifapi_netif */
+err_t netifapi_netif_name_to_index(const char *name, u8_t *index);
+/** @ingroup netifapi_netif */
+err_t netifapi_netif_index_to_name(u8_t index, char *name);
+
+/** @ingroup netifapi_netif */
 #define netifapi_netif_remove(n)        netifapi_netif_common(n, netif_remove, NULL)
 /** @ingroup netifapi_netif */
 #define netifapi_netif_set_up(n)        netifapi_netif_common(n, netif_set_up, NULL)
diff --git a/src/include/posix/net/if.h b/src/include/posix/net/if.h
new file mode 100644
index 0000000..cf7df7e
--- /dev/null
+++ b/src/include/posix/net/if.h
@@ -0,0 +1,33 @@
+/**
+ * @file
+ * This file is a posix wrapper for lwip/if.h.
+ */
+
+/*
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#include "lwip/if.h"
-- 
1.9.5.msysgit.0

