Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation.
3 : : * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include <string.h>
10 : : #include <errno.h>
11 : :
12 : : #include <eal_export.h>
13 : : #include <rte_string_fns.h>
14 : :
15 : : #include "cmdline_parse.h"
16 : : #include "cmdline_parse_ipaddr.h"
17 : :
18 : : RTE_EXPORT_SYMBOL(cmdline_token_ipaddr_ops)
19 : : struct cmdline_token_ops cmdline_token_ipaddr_ops = {
20 : : .parse = cmdline_parse_ipaddr,
21 : : .complete_get_nb = NULL,
22 : : .complete_get_elt = NULL,
23 : : .get_help = cmdline_get_help_ipaddr,
24 : : };
25 : :
26 : : #define PREFIXMAX 128
27 : : #define V4PREFIXMAX 32
28 : :
29 : : RTE_EXPORT_SYMBOL(cmdline_parse_ipaddr)
30 : : int
31 : 670 : cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
32 : : unsigned ressize)
33 : : {
34 : : struct cmdline_token_ipaddr *tk2;
35 : : unsigned int token_len = 0;
36 : : char ip_str[INET6_ADDRSTRLEN+4+1]; /* '+4' is for prefixlen (if any) */
37 : : cmdline_ipaddr_t ipaddr;
38 : : char *prefix, *prefix_end;
39 : : long prefixlen = 0;
40 : :
41 [ + - ]: 670 : if (res && ressize < sizeof(cmdline_ipaddr_t))
42 : : return -1;
43 : :
44 [ + + + + ]: 670 : if (!buf || !tk || ! *buf)
45 : : return -1;
46 : :
47 : : tk2 = (struct cmdline_token_ipaddr *)tk;
48 : :
49 [ + + ]: 9554 : while (!cmdline_isendoftoken(buf[token_len]))
50 : 8899 : token_len++;
51 : :
52 : : /* if token is too big... */
53 [ + + ]: 655 : if (token_len >= INET6_ADDRSTRLEN+4)
54 : : return -1;
55 : :
56 [ + + ]: 649 : strlcpy(ip_str, buf, token_len + 1);
57 : :
58 : : /* convert the network prefix */
59 [ + + ]: 649 : if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) {
60 : 324 : prefix = strrchr(ip_str, '/');
61 [ + + ]: 324 : if (prefix == NULL)
62 : : return -1;
63 : 150 : *prefix = '\0';
64 : 150 : prefix ++;
65 : 150 : errno = 0;
66 : 150 : prefixlen = strtol(prefix, &prefix_end, 10);
67 [ + - + + ]: 150 : if (errno || (*prefix_end != '\0')
68 [ + + ]: 144 : || prefixlen < 0 || prefixlen > PREFIXMAX)
69 : : return -1;
70 : 129 : ipaddr.prefixlen = prefixlen;
71 : : }
72 : : else {
73 : 325 : ipaddr.prefixlen = 0;
74 : : }
75 : :
76 : : /* convert the IP addr */
77 [ + + + + ]: 757 : if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V4) &&
78 [ + + ]: 340 : inet_pton(AF_INET, ip_str, &ipaddr.addr.ipv4) == 1 &&
79 : : prefixlen <= V4PREFIXMAX) {
80 : 35 : ipaddr.family = AF_INET;
81 [ + + ]: 35 : if (res)
82 : : memcpy(res, &ipaddr, sizeof(ipaddr));
83 : 35 : return token_len;
84 : : }
85 [ + + + + ]: 704 : if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V6) &&
86 : 285 : inet_pton(AF_INET6, ip_str, &ipaddr.addr.ipv6) == 1) {
87 : 46 : ipaddr.family = AF_INET6;
88 [ + - ]: 46 : if (res)
89 : : memcpy(res, &ipaddr, sizeof(ipaddr));
90 : 46 : return token_len;
91 : : }
92 : : return -1;
93 : :
94 : : }
95 : :
96 : : RTE_EXPORT_SYMBOL(cmdline_get_help_ipaddr)
97 : 675 : int cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf,
98 : : unsigned int size)
99 : : {
100 : : struct cmdline_token_ipaddr *tk2;
101 : :
102 [ + + ]: 675 : if (!tk || !dstbuf)
103 : : return -1;
104 : :
105 : : tk2 = (struct cmdline_token_ipaddr *)tk;
106 : :
107 [ + + + + : 673 : switch (tk2->ipaddr_data.flags) {
+ + + ]
108 : 112 : case CMDLINE_IPADDR_V4:
109 : 112 : snprintf(dstbuf, size, "IPv4");
110 : : break;
111 : 112 : case CMDLINE_IPADDR_V6:
112 : 112 : snprintf(dstbuf, size, "IPv6");
113 : : break;
114 : 112 : case CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
115 : 112 : snprintf(dstbuf, size, "IPv4/IPv6");
116 : : break;
117 : 112 : case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4:
118 : 112 : snprintf(dstbuf, size, "IPv4 network");
119 : : break;
120 : 112 : case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V6:
121 : 112 : snprintf(dstbuf, size, "IPv6 network");
122 : : break;
123 : 112 : case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
124 : 112 : snprintf(dstbuf, size, "IPv4/IPv6 network");
125 : : break;
126 : 1 : default:
127 : 1 : snprintf(dstbuf, size, "IPaddr (bad flags)");
128 : : break;
129 : : }
130 : : return 0;
131 : : }
|