diff options
Diffstat (limited to 'lib/prefix.c')
| -rw-r--r-- | lib/prefix.c | 116 |
1 files changed, 113 insertions, 3 deletions
diff --git a/lib/prefix.c b/lib/prefix.c index 256cd3a49a..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,10 +223,28 @@ 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) { switch (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) @@ -572,7 +657,7 @@ str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p) { int plen; - cp = XMALLOC (0, (pnt - str) + 1); + cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); strncpy (cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; ret = inet_pton (AF_INET6, cp, &p->prefix); @@ -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); |
