[PATCH v2 04/11] addr: Add support for AF_MPLS
David Ahern
dsahern at gmail.com
Thu Aug 17 15:59:31 PDT 2017
MPLS 'addresses' are 4-byte labels with a prefix length of 20.
Signed-off-by: David Ahern <dsahern at gmail.com>
---
lib/addr.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/lib/addr.c b/lib/addr.c
index fe4b2deaa21a..c299b402a12b 100644
--- a/lib/addr.c
+++ b/lib/addr.c
@@ -31,6 +31,7 @@
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/addr.h>
+#include <netlink-private/route/mpls.h>
#include <linux/socket.h>
/* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote
@@ -223,7 +224,13 @@ struct nl_addr *nl_addr_build(int family, const void *buf, size_t size)
addr->a_family = family;
addr->a_len = size;
- addr->a_prefixlen = size*8;
+ switch(family) {
+ case AF_MPLS:
+ addr->a_prefixlen = 20; /* MPLS address is a 20-bit label */
+ break;
+ default:
+ addr->a_prefixlen = size*8;
+ }
if (size)
memcpy(addr->a_addr, buf, size);
@@ -290,8 +297,8 @@ struct nl_addr *nl_addr_alloc_attr(const struct nlattr *nla, int family)
*/
int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
{
- int err, copy = 0, len = 0, family = AF_UNSPEC;
- char *str, *prefix, buf[32];
+ int err, copy = 0, len = 0, family = AF_UNSPEC, plen = 0;
+ char *str, *prefix = NULL, buf[256];
struct nl_addr *addr = NULL; /* gcc ain't that smart */
str = strdup(addrstr);
@@ -300,9 +307,11 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
goto errout;
}
- prefix = strchr(str, '/');
- if (prefix)
- *prefix = '\0';
+ if (hint != AF_MPLS) {
+ prefix = strchr(str, '/');
+ if (prefix)
+ *prefix = '\0';
+ }
if (!strcasecmp(str, "none")) {
family = hint;
@@ -399,6 +408,17 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
}
}
+ if (hint == AF_MPLS) {
+ len = mpls_pton(AF_MPLS, str, buf, sizeof(buf));
+ if (len <= 0) {
+ err = -NLE_INVAL;
+ goto errout;
+ }
+ family = AF_MPLS;
+ plen = 20;
+ goto prefix;
+ }
+
if (hint == AF_UNSPEC && strchr(str, ':')) {
size_t i = 0;
char *s = str, *p;
@@ -445,9 +465,11 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
goto errout;
}
nl_addr_set_prefixlen(addr, pl);
- } else
- nl_addr_set_prefixlen(addr, len * 8);
-
+ } else {
+ if (!plen)
+ plen = len * 8;
+ nl_addr_set_prefixlen(addr, plen);
+ }
*result = addr;
err = 0;
errout:
@@ -639,7 +661,7 @@ int nl_addr_iszero(const struct nl_addr *addr)
int nl_addr_valid(const char *addr, int family)
{
int ret;
- char buf[32];
+ char buf[256]; /* MPLS has N-labels at 4-bytes / label */
switch (family) {
case AF_INET:
@@ -649,6 +671,12 @@ int nl_addr_valid(const char *addr, int family)
return 0;
break;
+ case AF_MPLS:
+ ret = mpls_pton(family, addr, buf, sizeof(buf));
+ if (ret <= 0)
+ return 0;
+ break;
+
case AF_DECnet:
ret = dnet_pton(addr, buf);
if (ret <= 0)
@@ -982,6 +1010,10 @@ char *nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
inet_ntop(AF_INET6, addr->a_addr, buf, size);
break;
+ case AF_MPLS:
+ mpls_ntop(AF_MPLS, addr->a_addr, buf, size);
+ break;
+
case AF_DECnet:
dnet_ntop(addr->a_addr, addr->a_len, buf, size);
break;
@@ -999,7 +1031,8 @@ char *nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
}
prefix:
- if (addr->a_prefixlen != (8 * addr->a_len)) {
+ if (addr->a_family != AF_MPLS &&
+ addr->a_prefixlen != (8 * addr->a_len)) {
snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen);
strncat(buf, tmp, size - strlen(buf) - 1);
}
@@ -1078,6 +1111,7 @@ static const struct trans_tbl afs[] = {
#ifdef AF_VSOCK
__ADD(AF_VSOCK,vsock),
#endif
+ __ADD(AF_MPLS,mpls),
};
char *nl_af2str(int family, char *buf, size_t size)
--
2.1.4
More information about the libnl
mailing list