lib, zebra: unify link layer type and hardware address handling

This removes the BSD specific usage of struct sockaddr_dl
hardware address. This unifies to use explict hw_addr member for
the address, and zebra specific enumeration for the link layer
type.

Additionally the zapi is updated to never send platform specific
structures over the wire, but the ll_type along with hw_addr_len
and hw_addr are now sent for all platforms.

Based on initial work by Paul Jakma.

Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
diff --git a/lib/if.c b/lib/if.c
index 4d4b656..3426212 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1065,3 +1065,63 @@
   if (vrf_id == VRF_DEFAULT)
     iflist = NULL;
 }
+
+const char *
+if_link_type_str (enum zebra_link_type llt)
+{
+  switch (llt)
+    {
+#define llts(T,S) case (T): return (S)
+      llts(ZEBRA_LLT_UNKNOWN,               "Unknown");
+      llts(ZEBRA_LLT_ETHER,                 "Ethernet");
+      llts(ZEBRA_LLT_EETHER,                "Experimental Ethernet");
+      llts(ZEBRA_LLT_AX25,                  "AX.25 Level 2");
+      llts(ZEBRA_LLT_PRONET,                "PROnet token ring");
+      llts(ZEBRA_LLT_IEEE802,               "IEEE 802.2 Ethernet/TR/TB");
+      llts(ZEBRA_LLT_ARCNET,                "ARCnet");
+      llts(ZEBRA_LLT_APPLETLK,              "AppleTalk");
+      llts(ZEBRA_LLT_DLCI,                  "Frame Relay DLCI");
+      llts(ZEBRA_LLT_ATM,                   "ATM");
+      llts(ZEBRA_LLT_METRICOM,              "Metricom STRIP");
+      llts(ZEBRA_LLT_IEEE1394,              "IEEE 1394 IPv4");
+      llts(ZEBRA_LLT_EUI64,                 "EUI-64");
+      llts(ZEBRA_LLT_INFINIBAND,            "InfiniBand");
+      llts(ZEBRA_LLT_SLIP,                  "SLIP");
+      llts(ZEBRA_LLT_CSLIP,                 "Compressed SLIP");
+      llts(ZEBRA_LLT_SLIP6,                 "SLIPv6");
+      llts(ZEBRA_LLT_CSLIP6,                "Compressed SLIPv6");
+      llts(ZEBRA_LLT_ROSE,                  "ROSE packet radio");
+      llts(ZEBRA_LLT_X25,                   "CCITT X.25");
+      llts(ZEBRA_LLT_PPP,                   "PPP");
+      llts(ZEBRA_LLT_CHDLC,                 "Cisco HDLC");
+      llts(ZEBRA_LLT_RAWHDLC,               "Raw HDLC");
+      llts(ZEBRA_LLT_LAPB,                  "LAPB");
+      llts(ZEBRA_LLT_IPIP,                  "IPIP Tunnel");
+      llts(ZEBRA_LLT_IPIP6,                 "IPIP6 Tunnel");
+      llts(ZEBRA_LLT_FRAD,                  "FRAD");
+      llts(ZEBRA_LLT_SKIP,                  "SKIP vif");
+      llts(ZEBRA_LLT_LOOPBACK,              "Loopback");
+      llts(ZEBRA_LLT_LOCALTLK,              "Localtalk");
+      llts(ZEBRA_LLT_FDDI,                  "FDDI");
+      llts(ZEBRA_LLT_SIT,                   "IPv6-in-IPv4 SIT");
+      llts(ZEBRA_LLT_IPDDP,                 "IP-in-DDP tunnel");
+      llts(ZEBRA_LLT_IPGRE,                 "GRE over IP");
+      llts(ZEBRA_LLT_PIMREG,                "PIMSM registration");
+      llts(ZEBRA_LLT_HIPPI,                 "HiPPI");
+      llts(ZEBRA_LLT_IRDA,                  "IrDA");
+      llts(ZEBRA_LLT_FCPP,                  "Fibre-Channel PtP");
+      llts(ZEBRA_LLT_FCAL,                  "Fibre-Channel Arbitrated Loop");
+      llts(ZEBRA_LLT_FCPL,                  "Fibre-Channel Public Loop");
+      llts(ZEBRA_LLT_FCFABRIC,              "Fibre-Channel Fabric");
+      llts(ZEBRA_LLT_IEEE802_TR,            "IEEE 802.2 Token Ring");
+      llts(ZEBRA_LLT_IEEE80211,             "IEEE 802.11");
+      llts(ZEBRA_LLT_IEEE80211_RADIOTAP,    "IEEE 802.11 Radiotap");
+      llts(ZEBRA_LLT_IEEE802154,            "IEEE 802.15.4");
+      llts(ZEBRA_LLT_IEEE802154_PHY,        "IEEE 802.15.4 Phy");
+      default:
+        zlog_warn ("Unknown value %d", llt);
+        return "Unknown type!";
+#undef llts
+    }
+  return NULL;
+}
diff --git a/lib/if.h b/lib/if.h
index ad85dca..0cb2202 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -23,6 +23,66 @@
 
 #include "linklist.h"
 
+/* Interface link-layer type, if known. Derived from:
+ *
+ * net/if_arp.h on various platforms - Linux especially.
+ * http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
+ *
+ * Some of the more obviously defunct technologies left out.
+ */
+enum zebra_link_type {
+  ZEBRA_LLT_UNKNOWN = 0,
+  ZEBRA_LLT_ETHER,
+  ZEBRA_LLT_EETHER,
+  ZEBRA_LLT_AX25,
+  ZEBRA_LLT_PRONET,
+  ZEBRA_LLT_IEEE802,
+  ZEBRA_LLT_ARCNET,
+  ZEBRA_LLT_APPLETLK,
+  ZEBRA_LLT_DLCI,
+  ZEBRA_LLT_ATM,
+  ZEBRA_LLT_METRICOM,
+  ZEBRA_LLT_IEEE1394,
+  ZEBRA_LLT_EUI64,
+  ZEBRA_LLT_INFINIBAND,
+  ZEBRA_LLT_SLIP,
+  ZEBRA_LLT_CSLIP,
+  ZEBRA_LLT_SLIP6,
+  ZEBRA_LLT_CSLIP6,
+  ZEBRA_LLT_RSRVD,
+  ZEBRA_LLT_ADAPT,
+  ZEBRA_LLT_ROSE,
+  ZEBRA_LLT_X25,
+  ZEBRA_LLT_PPP,
+  ZEBRA_LLT_CHDLC,
+  ZEBRA_LLT_LAPB,
+  ZEBRA_LLT_RAWHDLC,
+  ZEBRA_LLT_IPIP,
+  ZEBRA_LLT_IPIP6,
+  ZEBRA_LLT_FRAD,
+  ZEBRA_LLT_SKIP,
+  ZEBRA_LLT_LOOPBACK,
+  ZEBRA_LLT_LOCALTLK,
+  ZEBRA_LLT_FDDI,
+  ZEBRA_LLT_SIT,
+  ZEBRA_LLT_IPDDP,
+  ZEBRA_LLT_IPGRE,
+  ZEBRA_LLT_IP6GRE,
+  ZEBRA_LLT_PIMREG,
+  ZEBRA_LLT_HIPPI,
+  ZEBRA_LLT_ECONET,
+  ZEBRA_LLT_IRDA,
+  ZEBRA_LLT_FCPP,
+  ZEBRA_LLT_FCAL,
+  ZEBRA_LLT_FCPL,
+  ZEBRA_LLT_FCFABRIC,
+  ZEBRA_LLT_IEEE802_TR,
+  ZEBRA_LLT_IEEE80211,
+  ZEBRA_LLT_IEEE80211_RADIOTAP,
+  ZEBRA_LLT_IEEE802154,
+  ZEBRA_LLT_IEEE802154_PHY,
+};
+
 /*
   Interface name length.
 
@@ -101,20 +161,10 @@
   unsigned int mtu;    /* IPv4 MTU */
   unsigned int mtu6;   /* IPv6 MTU - probably, but not neccessarily same as mtu */
 
-  /* Hardware address. */
-#ifdef HAVE_STRUCT_SOCKADDR_DL
-  union {
-    /* note that sdl_storage is never accessed, it only exists to make space.
-     * all actual uses refer to sdl - but use sizeof(sdl_storage)!  this fits
-     * best with C aliasing rules. */
-    struct sockaddr_dl sdl;
-    struct sockaddr_storage sdl_storage;
-  };
-#else
-  unsigned short hw_type;
+  /* Link-layer information and hardware address */
+  enum zebra_link_type ll_type;
   u_char hw_addr[INTERFACE_HWADDR_MAX];
   int hw_addr_len;
-#endif /* HAVE_STRUCT_SOCKADDR_DL */
 
   /* interface bandwidth, kbits */
   unsigned int bandwidth;
@@ -304,6 +354,7 @@
 extern void if_terminate (vrf_id_t, struct list **);
 extern void if_dump_all (void);
 extern const char *if_flag_dump(unsigned long);
+extern const char *if_link_type_str (enum zebra_link_type);
 
 /* Please use ifindex2ifname instead of if_indextoname where possible;
    ifindex2ifname uses internal interface info, whereas if_indextoname must
diff --git a/lib/zclient.c b/lib/zclient.c
index ca6a4c7..bd93d06 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -791,13 +791,10 @@
   ifp->mtu = stream_getl (s);
   ifp->mtu6 = stream_getl (s);
   ifp->bandwidth = stream_getl (s);
-#ifdef HAVE_STRUCT_SOCKADDR_DL
-  stream_get (&ifp->sdl, s, sizeof (ifp->sdl_storage));
-#else
+  ifp->ll_type = stream_getl (s);
   ifp->hw_addr_len = stream_getl (s);
   if (ifp->hw_addr_len)
     stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
-#endif /* HAVE_STRUCT_SOCKADDR_DL */
 }
 
 static int