lib: add AF_ETHERNET/AFI_ETHER
diff --git a/lib/plist.c b/lib/plist.c
index abce633..2176c03 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -734,6 +734,11 @@
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. */
diff --git a/lib/prefix.c b/lib/prefix.c
index aeb627b..43fc317 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -194,8 +194,9 @@
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 @@
else if (afi == AFI_IP6)
return AF_INET6;
#endif /* HAVE_IPV6 */
+ else if (afi == AFI_ETHER)
+ return AF_ETHERNET;
return 0;
}
@@ -220,10 +223,26 @@
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";
+ }
+ return NULL;
+}
+
+const char *
safi2str(safi_t safi)
{
switch (safi) {
@@ -286,6 +305,10 @@
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",
@@ -315,6 +338,10 @@
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;
}
@@ -406,6 +433,8 @@
if (p->family == AF_INET6)
return "inet6";
#endif /* HAVE_IPV6 */
+ if (p->family == AF_ETHERNET)
+ return "ether";
return "unspec";
}
@@ -476,6 +505,60 @@
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)
@@ -762,6 +845,8 @@
return IPV6_MAX_BYTELEN;
break;
#endif /* HAVE_IPV6 */
+ case AF_ETHERNET:
+ return ETHER_ADDR_LEN;
}
return 0;
}
@@ -784,6 +869,11 @@
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;
}
@@ -793,6 +883,24 @@
const struct prefix *p = pu.p;
char buf[BUFSIZ];
+ 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;
+ }
+
inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
snprintf (str, size, "%s/%d", buf, p->prefixlen);
return str;
diff --git a/lib/prefix.h b/lib/prefix.h
index 4a31750..2cf0b20 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -23,8 +23,30 @@
#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
@@ -34,6 +56,15 @@
* 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 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 @@
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 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);
@@ -197,6 +238,8 @@
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 *);
diff --git a/lib/zebra.h b/lib/zebra.h
index cb83a11..70d498a 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -493,7 +493,8 @@
typedef enum {
AFI_IP = 1,
AFI_IP6 = 2,
-#define AFI_MAX 3
+ AFI_ETHER = 3, /* RFC 1700 has "6" for 802.* */
+#define AFI_MAX 4
} afi_t;
/* Subsequent Address Family Identifier. */