#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
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);
*/
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);
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;
}
}
+ 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;
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:
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:
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)
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;
}
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);
}
#ifdef AF_VSOCK
__ADD(AF_VSOCK,vsock),
#endif
+ __ADD(AF_MPLS,mpls),
};
char *nl_af2str(int family, char *buf, size_t size)