diff options
Diffstat (limited to 'lib/mpls_ntop.c')
-rw-r--r-- | lib/mpls_ntop.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/lib/mpls_ntop.c b/lib/mpls_ntop.c new file mode 100644 index 0000000..f8d89f4 --- /dev/null +++ b/lib/mpls_ntop.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <linux/mpls.h> + +#include "utils.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); + default: + errno = EAFNOSUPPORT; + } + + return NULL; +} |