From 32ac65d9fa2e9565d4a0251f9e39e8e64526322d Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 19 Apr 2016 16:08:59 -0400 Subject: [PATCH] lib: add AF_ETHERNET/AFI_ETHER --- bgpd/bgp_open.c | 3 ++ lib/plist.c | 5 +++ lib/prefix.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++- lib/prefix.h | 43 ++++++++++++++++++ lib/zebra.h | 3 +- 5 files changed, 165 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 915757e622..6001092ce2 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -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); diff --git a/lib/plist.c b/lib/plist.c index a1289801c4..7bb80fa2a4 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -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. */ diff --git a/lib/prefix.c b/lib/prefix.c index c311b94eef..d2bb028315 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -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); diff --git a/lib/prefix.h b/lib/prefix.h index 39c2b62019..85488ccea7 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 +#else +# ifdef GNU_LINUX +# include +# else +# include +# 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 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 *); diff --git a/lib/zebra.h b/lib/zebra.h index 94158013ec..fdfd471825 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -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. */ -- 2.39.5