]>
Commit | Line | Data |
---|---|---|
6054c1eb SH |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | ||
dacc5d41 EB |
3 | #include <errno.h> |
4 | #include <string.h> | |
5 | #include <sys/types.h> | |
6 | #include <netinet/in.h> | |
7 | #include <linux/mpls.h> | |
8 | ||
9 | #include "utils.h" | |
10 | ||
11 | ||
4af44716 DA |
12 | static int mpls_pton1(const char *name, struct mpls_label *addr, |
13 | unsigned int maxlabels) | |
dacc5d41 EB |
14 | { |
15 | char *endp; | |
16 | unsigned count; | |
17 | ||
4af44716 | 18 | for (count = 0; count < maxlabels; count++) { |
dacc5d41 EB |
19 | unsigned long label; |
20 | ||
21 | label = strtoul(name, &endp, 0); | |
22 | /* Fail when the label value is out or range */ | |
23 | if (label >= (1 << 20)) | |
24 | return 0; | |
25 | ||
26 | if (endp == name) /* no digits */ | |
27 | return 0; | |
28 | ||
29 | addr->entry = htonl(label << MPLS_LS_LABEL_SHIFT); | |
30 | if (*endp == '\0') { | |
31 | addr->entry |= htonl(1 << MPLS_LS_S_SHIFT); | |
32 | return 1; | |
33 | } | |
34 | ||
35 | /* Bad character in the address */ | |
36 | if (*endp != '/') | |
37 | return 0; | |
38 | ||
39 | name = endp + 1; | |
40 | addr += 1; | |
41 | } | |
42 | /* The address was too long */ | |
4af44716 | 43 | fprintf(stderr, "Error: too many labels.\n"); |
dacc5d41 EB |
44 | return 0; |
45 | } | |
46 | ||
4af44716 | 47 | int mpls_pton(int af, const char *src, void *addr, size_t alen) |
dacc5d41 | 48 | { |
4af44716 | 49 | unsigned int maxlabels = alen / sizeof(struct mpls_label); |
dacc5d41 EB |
50 | int err; |
51 | ||
52 | switch(af) { | |
53 | case AF_MPLS: | |
54 | errno = 0; | |
4af44716 | 55 | err = mpls_pton1(src, (struct mpls_label *)addr, maxlabels); |
dacc5d41 EB |
56 | break; |
57 | default: | |
58 | errno = EAFNOSUPPORT; | |
59 | err = -1; | |
60 | } | |
61 | ||
62 | return err; | |
63 | } |