]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add AF_ETHERNET/AFI_ETHER
authorLou Berger <lberger@labn.net>
Tue, 19 Apr 2016 20:08:59 +0000 (16:08 -0400)
committerDonald Sharp <sharpd@cumulusnetwroks.com>
Sat, 3 Sep 2016 15:05:51 +0000 (11:05 -0400)
bgpd/bgp_open.c
lib/plist.c
lib/prefix.c
lib/prefix.h
lib/zebra.h

index 915757e622f55dc15b52972d742adb4fe4bfa144..6001092ce2cd1b320653508e32451aea0b3ec566 100644 (file)
@@ -196,6 +196,9 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
          return 1;
        }
       break;
+    case AFI_ETHER:
+    default:
+      break;
     }
 
   zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
index a1289801c462fa0903b26319378a85849bfff3f3..7bb80fa2a4608e66aeab98b0f2a11da5825c44a5 100644 (file)
@@ -958,6 +958,11 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name,
          return CMD_WARNING;
        }
       break;
+    case AFI_ETHER:
+    default:
+      vty_out (vty, "%% Unrecognized AFI (%d)%s", afi, VTY_NEWLINE);
+      return CMD_WARNING;
+      break;
     }
 
   /* ge and le check. */
index c311b94eef698592080d69388f26f10782c249d0..d2bb0283159815b7a2c82cd0942698f093084b05 100644 (file)
@@ -194,8 +194,9 @@ str2family(const char *string)
     return AF_INET;
   else if (!strcmp("ipv6", string))
     return AF_INET6;
-  else
-    return -1;
+  else if (!strcmp("ethernet", string))
+    return AF_ETHERNET;
+  return -1;
 }
 
 /* Address Famiy Identifier to Address Family converter. */
@@ -208,6 +209,8 @@ afi2family (afi_t afi)
   else if (afi == AFI_IP6)
     return AF_INET6;
 #endif /* HAVE_IPV6 */
+  else if (afi == AFI_ETHER)
+    return AF_ETHERNET;
   return 0;
 }
 
@@ -220,9 +223,27 @@ family2afi (int family)
   else if (family == AF_INET6)
     return AFI_IP6;
 #endif /* HAVE_IPV6 */
+  else if (family == AF_ETHERNET)
+    return AFI_ETHER;
   return 0;
 }
 
+const char *
+afi2str(afi_t afi)
+{
+  switch (afi) {
+    case AFI_IP:
+       return "IPv4";
+    case AFI_IP6:
+       return "IPv6";
+    case AFI_ETHER:
+       return "ethernet";
+    default:
+       break;
+  }
+  return NULL;
+}
+
 const char *
 safi2str(safi_t safi)
 {
@@ -286,6 +307,10 @@ prefix_copy (struct prefix *dest, const struct prefix *src)
       dest->u.lp.id = src->u.lp.id;
       dest->u.lp.adv_router = src->u.lp.adv_router;
     }
+  else if (src->family == AF_ETHERNET)
+    {
+      dest->u.prefix_eth = src->u.prefix_eth;
+    }
   else
     {
       zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
@@ -321,6 +346,10 @@ prefix_same (const struct prefix *p1, const struct prefix *p2)
        if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr))
          return 1;
 #endif /* HAVE_IPV6 */
+      if (p1->family == AF_ETHERNET) {
+       if (!memcmp(p1->u.prefix_eth.octet, p2->u.prefix_eth.octet, ETHER_ADDR_LEN))
+           return 1;
+      }
     }
   return 0;
 }
@@ -412,6 +441,8 @@ prefix_family_str (const struct prefix *p)
   if (p->family == AF_INET6)
     return "inet6";
 #endif /* HAVE_IPV6 */
+  if (p->family == AF_ETHERNET)
+    return "ether";
   return "unspec";
 }
 
@@ -482,6 +513,60 @@ str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
   return ret;
 }
 
+/* When string format is invalid return 0. */
+int
+str2prefix_eth (const char *str, struct prefix_eth *p)
+{
+  int          ret = 0;
+  int          plen = 48;
+  char         *pnt;
+  char         *cp = NULL;
+  const char   *str_addr = str;
+  unsigned int a[6];
+  int          i;
+
+  /* Find slash inside string. */
+  pnt = strchr (str, '/');
+
+  if (pnt)
+    {
+      /* Get prefix length. */
+      plen = (u_char) atoi (++pnt);
+      if (plen > 48)
+       {
+         ret = 0;
+         goto done;
+       }
+
+      cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
+      strncpy (cp, str, pnt - str);
+      *(cp + (pnt - str)) = '\0';
+
+      str_addr = cp;
+    }
+
+  /* Convert string to prefix. */
+  if (sscanf(str_addr, "%2x:%2x:%2x:%2x:%2x:%2x",
+    a+0, a+1, a+2, a+3, a+4, a+5) != 6)
+    {
+      ret = 0;
+      goto done;
+    }
+  for (i = 0; i < 6; ++i)
+    {
+      p->eth_addr.octet[i] = a[i] & 0xff;
+    }
+  p->prefixlen = plen;
+  p->family = AF_ETHERNET;
+  ret = 1;
+
+done:
+  if (cp)
+    XFREE (MTYPE_TMP, cp);
+
+  return ret;
+}
+
 /* Convert masklen into IP address's netmask (network byte order). */
 void
 masklen2ip (const int masklen, struct in_addr *netmask)
@@ -768,6 +853,8 @@ prefix_blen (const struct prefix *p)
       return IPV6_MAX_BYTELEN;
       break;
 #endif /* HAVE_IPV6 */
+    case AF_ETHERNET:
+      return ETHER_ADDR_LEN;
     }
   return 0;
 }
@@ -790,6 +877,11 @@ str2prefix (const char *str, struct prefix *p)
     return ret;
 #endif /* HAVE_IPV6 */
 
+  /* Next we try to convert string to struct prefix_eth. */
+  ret = str2prefix_eth (str, (struct prefix_eth *) p);
+  if (ret)
+    return ret;
+
   return 0;
 }
 
@@ -799,6 +891,24 @@ prefix2str (union prefix46constptr pu, char *str, int size)
   const struct prefix *p = pu.p;
   char buf[PREFIX2STR_BUFFER];
 
+  if (p->family == AF_ETHERNET) {
+    int                i;
+    char       *s = str;
+
+    assert(size > (3*ETHER_ADDR_LEN) + 1 /* slash */ + 3 /* plen */ );
+    for (i = 0; i < ETHER_ADDR_LEN; ++i) {
+       sprintf(s, "%02x", p->u.prefix_eth.octet[i]);
+       if (i < (ETHER_ADDR_LEN - 1)) {
+           *(s+2) = ':';
+           s += 3;
+       } else {
+           s += 2;
+       }
+    }
+    sprintf(s, "/%d", p->prefixlen);
+    return 0;
+  }
+
   snprintf (str, size, "%s/%d",
            inet_ntop (p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER),
                       p->prefixlen);
index 39c2b620196b07646005b2211ee49adb7af5f4f0..85488ccea7bbd5fb2186ac63c26059b0b320a7b4 100644 (file)
 #ifndef _ZEBRA_PREFIX_H
 #define _ZEBRA_PREFIX_H
 
+#ifdef SUNOS_5
+# include <sys/ethernet.h>
+#else
+# ifdef GNU_LINUX
+#  include <net/ethernet.h>
+# else
+#  include <netinet/if_ether.h>
+# endif
+#endif
 #include "sockunion.h"
 
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN  ETHERADDRL
+#endif
+
+/*
+ * there isn't a portable ethernet address type. We define our
+ * own to simplify internal handling
+ */
+struct ethaddr {
+    u_char octet[ETHER_ADDR_LEN];
+} __packed;
+
+
 /*
  * A struct prefix contains an address family, a prefix length, and an
  * address.  This can represent either a 'network prefix' as defined
  * interface.
  */
 
+/* different OSes use different names */
+#if defined(AF_PACKET)
+#define AF_ETHERNET AF_PACKET
+#else
+#if defined(AF_LINK)
+#define AF_ETHERNET AF_LINK
+#endif
+#endif
+
 /* IPv4 and IPv6 unified prefix structure. */
 struct prefix
 {
@@ -51,6 +82,7 @@ struct prefix
       struct in_addr id;
       struct in_addr adv_router;
     } lp;
+    struct ethaddr prefix_eth; /* AF_ETHERNET */
     u_char val[8];
     uintptr_t ptr;
   } u __attribute__ ((aligned (8)));
@@ -90,6 +122,14 @@ struct prefix_rd
   u_char val[8] __attribute__ ((aligned (8)));
 };
 
+/* Prefix for ethernet. */
+struct prefix_eth
+{
+  u_char family;
+  u_char prefixlen;
+  struct ethaddr eth_addr __attribute__ ((aligned (8))); /* AF_ETHERNET */
+};
+
 /* Prefix for a generic pointer */
 struct prefix_ptr
 {
@@ -174,6 +214,7 @@ extern int str2family(const char *);
 extern int afi2family (afi_t);
 extern afi_t family2afi (int);
 extern const char *safi2str(safi_t safi);
+extern const char *afi2str(afi_t afi);
 
 /* Check bit of the prefix. */
 extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen);
@@ -205,6 +246,8 @@ extern struct prefix *sockunion2prefix (const union sockunion *dest,
 extern struct prefix *sockunion2hostprefix (const union sockunion *, struct prefix *p);
 extern void prefix2sockunion (const struct prefix *, union sockunion *);
 
+extern int str2prefix_eth (const char *, struct prefix_eth *);
+
 extern struct prefix_ipv4 *prefix_ipv4_new (void);
 extern void prefix_ipv4_free (struct prefix_ipv4 *);
 extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *);
index 94158013ec32174ad4976c2c52212ccd2a3825ff..fdfd47182530e3085aa0c8f2d1f9582a882524ec 100644 (file)
@@ -502,7 +502,8 @@ extern const char *zserv_command_string (unsigned int command);
 typedef enum {
   AFI_IP  = 1,
   AFI_IP6 = 2,
-#define AFI_MAX 3
+  AFI_ETHER = 3,                /* RFC 1700 has "6" for 802.* */
+  AFI_MAX = 4
 } afi_t;
 
 /* Subsequent Address Family Identifier. */