1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Adapted from mpls_ntop and mpls_pton copied from iproute2,
4*4dc78e53SAndroid Build Coastguard Worker * lib/mpls_ntop.c and lib/mpls_pton.c
5*4dc78e53SAndroid Build Coastguard Worker */
6*4dc78e53SAndroid Build Coastguard Worker
7*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
8*4dc78e53SAndroid Build Coastguard Worker
9*4dc78e53SAndroid Build Coastguard Worker #include <stdio.h>
10*4dc78e53SAndroid Build Coastguard Worker
11*4dc78e53SAndroid Build Coastguard Worker #include <linux/mpls.h>
12*4dc78e53SAndroid Build Coastguard Worker
13*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink-compat.h>
14*4dc78e53SAndroid Build Coastguard Worker
15*4dc78e53SAndroid Build Coastguard Worker #include "mpls.h"
16*4dc78e53SAndroid Build Coastguard Worker
mpls_ntop1(const struct mpls_label * addr,char * buf,size_t buflen)17*4dc78e53SAndroid Build Coastguard Worker static const char *mpls_ntop1(const struct mpls_label *addr,
18*4dc78e53SAndroid Build Coastguard Worker char *buf, size_t buflen)
19*4dc78e53SAndroid Build Coastguard Worker {
20*4dc78e53SAndroid Build Coastguard Worker size_t destlen = buflen;
21*4dc78e53SAndroid Build Coastguard Worker char *dest = buf;
22*4dc78e53SAndroid Build Coastguard Worker int count = 0;
23*4dc78e53SAndroid Build Coastguard Worker
24*4dc78e53SAndroid Build Coastguard Worker while (1) {
25*4dc78e53SAndroid Build Coastguard Worker uint32_t entry = ntohl(addr[count++].entry);
26*4dc78e53SAndroid Build Coastguard Worker uint32_t label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
27*4dc78e53SAndroid Build Coastguard Worker int len = snprintf(dest, destlen, "%u", label);
28*4dc78e53SAndroid Build Coastguard Worker
29*4dc78e53SAndroid Build Coastguard Worker if (len < 0 || (unsigned)len >= destlen)
30*4dc78e53SAndroid Build Coastguard Worker break;
31*4dc78e53SAndroid Build Coastguard Worker
32*4dc78e53SAndroid Build Coastguard Worker /* Is this the end? */
33*4dc78e53SAndroid Build Coastguard Worker if (entry & MPLS_LS_S_MASK)
34*4dc78e53SAndroid Build Coastguard Worker return buf;
35*4dc78e53SAndroid Build Coastguard Worker
36*4dc78e53SAndroid Build Coastguard Worker dest += len;
37*4dc78e53SAndroid Build Coastguard Worker destlen -= len;
38*4dc78e53SAndroid Build Coastguard Worker if (destlen) {
39*4dc78e53SAndroid Build Coastguard Worker *dest = '/';
40*4dc78e53SAndroid Build Coastguard Worker dest++;
41*4dc78e53SAndroid Build Coastguard Worker destlen--;
42*4dc78e53SAndroid Build Coastguard Worker }
43*4dc78e53SAndroid Build Coastguard Worker }
44*4dc78e53SAndroid Build Coastguard Worker errno = E2BIG;
45*4dc78e53SAndroid Build Coastguard Worker
46*4dc78e53SAndroid Build Coastguard Worker return NULL;
47*4dc78e53SAndroid Build Coastguard Worker }
48*4dc78e53SAndroid Build Coastguard Worker
mpls_ntop(int af,const void * addr,char * buf,size_t buflen)49*4dc78e53SAndroid Build Coastguard Worker const char *mpls_ntop(int af, const void *addr, char *buf, size_t buflen)
50*4dc78e53SAndroid Build Coastguard Worker {
51*4dc78e53SAndroid Build Coastguard Worker switch(af) {
52*4dc78e53SAndroid Build Coastguard Worker case AF_MPLS:
53*4dc78e53SAndroid Build Coastguard Worker errno = 0;
54*4dc78e53SAndroid Build Coastguard Worker return mpls_ntop1((struct mpls_label *)addr, buf, buflen);
55*4dc78e53SAndroid Build Coastguard Worker }
56*4dc78e53SAndroid Build Coastguard Worker
57*4dc78e53SAndroid Build Coastguard Worker errno = EINVAL;
58*4dc78e53SAndroid Build Coastguard Worker return NULL;
59*4dc78e53SAndroid Build Coastguard Worker }
60*4dc78e53SAndroid Build Coastguard Worker
mpls_pton1(const char * name,struct mpls_label * addr,unsigned int maxlabels)61*4dc78e53SAndroid Build Coastguard Worker static int mpls_pton1(const char *name, struct mpls_label *addr,
62*4dc78e53SAndroid Build Coastguard Worker unsigned int maxlabels)
63*4dc78e53SAndroid Build Coastguard Worker {
64*4dc78e53SAndroid Build Coastguard Worker char *endp;
65*4dc78e53SAndroid Build Coastguard Worker unsigned count;
66*4dc78e53SAndroid Build Coastguard Worker
67*4dc78e53SAndroid Build Coastguard Worker for (count = 0; count < maxlabels; count++) {
68*4dc78e53SAndroid Build Coastguard Worker unsigned long label;
69*4dc78e53SAndroid Build Coastguard Worker
70*4dc78e53SAndroid Build Coastguard Worker label = strtoul(name, &endp, 0);
71*4dc78e53SAndroid Build Coastguard Worker /* Fail when the label value is out or range */
72*4dc78e53SAndroid Build Coastguard Worker if (label >= (1 << 20))
73*4dc78e53SAndroid Build Coastguard Worker return 0;
74*4dc78e53SAndroid Build Coastguard Worker
75*4dc78e53SAndroid Build Coastguard Worker if (endp == name) /* no digits */
76*4dc78e53SAndroid Build Coastguard Worker return 0;
77*4dc78e53SAndroid Build Coastguard Worker
78*4dc78e53SAndroid Build Coastguard Worker addr->entry = htonl(label << MPLS_LS_LABEL_SHIFT);
79*4dc78e53SAndroid Build Coastguard Worker if (*endp == '\0') {
80*4dc78e53SAndroid Build Coastguard Worker addr->entry |= htonl(1 << MPLS_LS_S_SHIFT);
81*4dc78e53SAndroid Build Coastguard Worker return (count + 1) * sizeof(struct mpls_label);
82*4dc78e53SAndroid Build Coastguard Worker }
83*4dc78e53SAndroid Build Coastguard Worker
84*4dc78e53SAndroid Build Coastguard Worker /* Bad character in the address */
85*4dc78e53SAndroid Build Coastguard Worker if (*endp != '/')
86*4dc78e53SAndroid Build Coastguard Worker return 0;
87*4dc78e53SAndroid Build Coastguard Worker
88*4dc78e53SAndroid Build Coastguard Worker name = endp + 1;
89*4dc78e53SAndroid Build Coastguard Worker addr += 1;
90*4dc78e53SAndroid Build Coastguard Worker }
91*4dc78e53SAndroid Build Coastguard Worker
92*4dc78e53SAndroid Build Coastguard Worker /* The address was too long */
93*4dc78e53SAndroid Build Coastguard Worker return 0;
94*4dc78e53SAndroid Build Coastguard Worker }
95*4dc78e53SAndroid Build Coastguard Worker
mpls_pton(int af,const char * src,void * addr,size_t alen)96*4dc78e53SAndroid Build Coastguard Worker int mpls_pton(int af, const char *src, void *addr, size_t alen)
97*4dc78e53SAndroid Build Coastguard Worker {
98*4dc78e53SAndroid Build Coastguard Worker unsigned int maxlabels = alen / sizeof(struct mpls_label);
99*4dc78e53SAndroid Build Coastguard Worker int err;
100*4dc78e53SAndroid Build Coastguard Worker
101*4dc78e53SAndroid Build Coastguard Worker switch(af) {
102*4dc78e53SAndroid Build Coastguard Worker case AF_MPLS:
103*4dc78e53SAndroid Build Coastguard Worker errno = 0;
104*4dc78e53SAndroid Build Coastguard Worker err = mpls_pton1(src, (struct mpls_label *)addr, maxlabels);
105*4dc78e53SAndroid Build Coastguard Worker break;
106*4dc78e53SAndroid Build Coastguard Worker default:
107*4dc78e53SAndroid Build Coastguard Worker errno = EAFNOSUPPORT;
108*4dc78e53SAndroid Build Coastguard Worker err = -1;
109*4dc78e53SAndroid Build Coastguard Worker }
110*4dc78e53SAndroid Build Coastguard Worker
111*4dc78e53SAndroid Build Coastguard Worker return err;
112*4dc78e53SAndroid Build Coastguard Worker }
113