[PATCH v2 03/11] addr: Add implementations for mpls_ntop and mpls_pton
David Ahern
dsahern at gmail.com
Thu Aug 17 15:59:30 PDT 2017
Implementations of mpls_ntop and mpls_pton taken from iproute2.
Signed-off-by: David Ahern <dsahern at gmail.com>
---
Makefile.am | 3 +-
include/netlink-private/route/mpls.h | 15 +++++
lib/mpls.c | 108 +++++++++++++++++++++++++++++++++++
3 files changed, 125 insertions(+), 1 deletion(-)
create mode 100644 include/netlink-private/route/mpls.h
create mode 100644 lib/mpls.c
diff --git a/Makefile.am b/Makefile.am
index 2b817f4a185b..3fd6ba83ad6c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -323,7 +323,8 @@ lib_libnl_3_la_SOURCES = \
lib/utils.c \
lib/version.c \
lib/hash.c \
- lib/hashtable.c
+ lib/hashtable.c \
+ lib/mpls.c
EXTRA_lib_libnl_3_la_DEPENDENCIES = \
libnl-3.sym
lib_libnl_3_la_CPPFLAGS = \
diff --git a/include/netlink-private/route/mpls.h b/include/netlink-private/route/mpls.h
new file mode 100644
index 000000000000..502fd34ad4fb
--- /dev/null
+++ b/include/netlink-private/route/mpls.h
@@ -0,0 +1,15 @@
+#ifndef MPLS_H_
+#define MPLS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char *mpls_ntop(int af, const void *addr, char *buf, size_t buflen);
+extern int mpls_pton(int af, const char *src, void *addr, size_t alen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/mpls.c b/lib/mpls.c
new file mode 100644
index 000000000000..cf79ad20ff6a
--- /dev/null
+++ b/lib/mpls.c
@@ -0,0 +1,108 @@
+/*
+ * Adapted from mpls_ntop and mpls_pton copied from iproute2,
+ * lib/mpls_ntop.c and lib/mpls_pton.c
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <netlink/netlink-compat.h>
+#include <netlink-private/route/mpls.h>
+#include <linux-private/linux/mpls.h>
+
+static const char *mpls_ntop1(const struct mpls_label *addr,
+ char *buf, size_t buflen)
+{
+ size_t destlen = buflen;
+ char *dest = buf;
+ int count = 0;
+
+ while (1) {
+ uint32_t entry = ntohl(addr[count++].entry);
+ uint32_t label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
+ int len = snprintf(dest, destlen, "%u", label);
+
+ if (len >= destlen)
+ break;
+
+ /* Is this the end? */
+ if (entry & MPLS_LS_S_MASK)
+ return buf;
+
+ dest += len;
+ destlen -= len;
+ if (destlen) {
+ *dest = '/';
+ dest++;
+ destlen--;
+ }
+ }
+ errno = E2BIG;
+
+ return NULL;
+}
+
+const char *mpls_ntop(int af, const void *addr, char *buf, size_t buflen)
+{
+ switch(af) {
+ case AF_MPLS:
+ errno = 0;
+ return mpls_ntop1((struct mpls_label *)addr, buf, buflen);
+ }
+
+ errno = EINVAL;
+ return NULL;
+}
+
+static int mpls_pton1(const char *name, struct mpls_label *addr,
+ unsigned int maxlabels)
+{
+ char *endp;
+ unsigned count;
+
+ for (count = 0; count < maxlabels; count++) {
+ unsigned long label;
+
+ label = strtoul(name, &endp, 0);
+ /* Fail when the label value is out or range */
+ if (label >= (1 << 20))
+ return 0;
+
+ if (endp == name) /* no digits */
+ return 0;
+
+ addr->entry = htonl(label << MPLS_LS_LABEL_SHIFT);
+ if (*endp == '\0') {
+ addr->entry |= htonl(1 << MPLS_LS_S_SHIFT);
+ return (count + 1) * sizeof(struct mpls_label);
+ }
+
+ /* Bad character in the address */
+ if (*endp != '/')
+ return 0;
+
+ name = endp + 1;
+ addr += 1;
+ }
+
+ /* The address was too long */
+ return 0;
+}
+
+int mpls_pton(int af, const char *src, void *addr, size_t alen)
+{
+ unsigned int maxlabels = alen / sizeof(struct mpls_label);
+ int err;
+
+ switch(af) {
+ case AF_MPLS:
+ errno = 0;
+ err = mpls_pton1(src, (struct mpls_label *)addr, maxlabels);
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ err = -1;
+ }
+
+ return err;
+}
--
2.1.4
More information about the libnl
mailing list