xref: /dpdk/drivers/net/softnic/parser.c (revision 31ce8d88)
1*31ce8d88SJasvinder Singh /* SPDX-License-Identifier: BSD-3-Clause
2*31ce8d88SJasvinder Singh  * Copyright(c) 2016 Intel Corporation.
3*31ce8d88SJasvinder Singh  * Copyright (c) 2009, Olivier MATZ <[email protected]>
4*31ce8d88SJasvinder Singh  * All rights reserved.
5*31ce8d88SJasvinder Singh  */
6*31ce8d88SJasvinder Singh 
7*31ce8d88SJasvinder Singh /* For inet_pton4() and inet_pton6() functions:
8*31ce8d88SJasvinder Singh  *
9*31ce8d88SJasvinder Singh  * Copyright (c) 1996 by Internet Software Consortium.
10*31ce8d88SJasvinder Singh  *
11*31ce8d88SJasvinder Singh  * Permission to use, copy, modify, and distribute this software for any
12*31ce8d88SJasvinder Singh  * purpose with or without fee is hereby granted, provided that the above
13*31ce8d88SJasvinder Singh  * copyright notice and this permission notice appear in all copies.
14*31ce8d88SJasvinder Singh  *
15*31ce8d88SJasvinder Singh  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
16*31ce8d88SJasvinder Singh  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
17*31ce8d88SJasvinder Singh  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
18*31ce8d88SJasvinder Singh  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
19*31ce8d88SJasvinder Singh  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
20*31ce8d88SJasvinder Singh  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
21*31ce8d88SJasvinder Singh  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22*31ce8d88SJasvinder Singh  * SOFTWARE.
23*31ce8d88SJasvinder Singh  */
24*31ce8d88SJasvinder Singh 
25*31ce8d88SJasvinder Singh #include <stdint.h>
26*31ce8d88SJasvinder Singh #include <stdlib.h>
27*31ce8d88SJasvinder Singh #include <stdio.h>
28*31ce8d88SJasvinder Singh #include <ctype.h>
29*31ce8d88SJasvinder Singh #include <getopt.h>
30*31ce8d88SJasvinder Singh #include <errno.h>
31*31ce8d88SJasvinder Singh #include <stdarg.h>
32*31ce8d88SJasvinder Singh #include <string.h>
33*31ce8d88SJasvinder Singh #include <libgen.h>
34*31ce8d88SJasvinder Singh #include <unistd.h>
35*31ce8d88SJasvinder Singh #include <sys/wait.h>
36*31ce8d88SJasvinder Singh 
37*31ce8d88SJasvinder Singh #include <rte_errno.h>
38*31ce8d88SJasvinder Singh 
39*31ce8d88SJasvinder Singh #include "parser.h"
40*31ce8d88SJasvinder Singh 
41*31ce8d88SJasvinder Singh static uint32_t
42*31ce8d88SJasvinder Singh get_hex_val(char c)
43*31ce8d88SJasvinder Singh {
44*31ce8d88SJasvinder Singh 	switch (c) {
45*31ce8d88SJasvinder Singh 	case '0': case '1': case '2': case '3': case '4': case '5':
46*31ce8d88SJasvinder Singh 	case '6': case '7': case '8': case '9':
47*31ce8d88SJasvinder Singh 		return c - '0';
48*31ce8d88SJasvinder Singh 	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
49*31ce8d88SJasvinder Singh 		return c - 'A' + 10;
50*31ce8d88SJasvinder Singh 	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
51*31ce8d88SJasvinder Singh 		return c - 'a' + 10;
52*31ce8d88SJasvinder Singh 	default:
53*31ce8d88SJasvinder Singh 		return 0;
54*31ce8d88SJasvinder Singh 	}
55*31ce8d88SJasvinder Singh }
56*31ce8d88SJasvinder Singh 
57*31ce8d88SJasvinder Singh int
58*31ce8d88SJasvinder Singh softnic_parser_read_arg_bool(const char *p)
59*31ce8d88SJasvinder Singh {
60*31ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
61*31ce8d88SJasvinder Singh 	int result = -EINVAL;
62*31ce8d88SJasvinder Singh 
63*31ce8d88SJasvinder Singh 	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
64*31ce8d88SJasvinder Singh 		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
65*31ce8d88SJasvinder Singh 		p += 3;
66*31ce8d88SJasvinder Singh 		result = 1;
67*31ce8d88SJasvinder Singh 	}
68*31ce8d88SJasvinder Singh 
69*31ce8d88SJasvinder Singh 	if (((p[0] == 'o') && (p[1] == 'n')) ||
70*31ce8d88SJasvinder Singh 		((p[0] == 'O') && (p[1] == 'N'))) {
71*31ce8d88SJasvinder Singh 		p += 2;
72*31ce8d88SJasvinder Singh 		result = 1;
73*31ce8d88SJasvinder Singh 	}
74*31ce8d88SJasvinder Singh 
75*31ce8d88SJasvinder Singh 	if (((p[0] == 'n') && (p[1] == 'o')) ||
76*31ce8d88SJasvinder Singh 		((p[0] == 'N') && (p[1] == 'O'))) {
77*31ce8d88SJasvinder Singh 		p += 2;
78*31ce8d88SJasvinder Singh 		result = 0;
79*31ce8d88SJasvinder Singh 	}
80*31ce8d88SJasvinder Singh 
81*31ce8d88SJasvinder Singh 	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
82*31ce8d88SJasvinder Singh 		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
83*31ce8d88SJasvinder Singh 		p += 3;
84*31ce8d88SJasvinder Singh 		result = 0;
85*31ce8d88SJasvinder Singh 	}
86*31ce8d88SJasvinder Singh 
87*31ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
88*31ce8d88SJasvinder Singh 
89*31ce8d88SJasvinder Singh 	if (p[0] != '\0')
90*31ce8d88SJasvinder Singh 		return -EINVAL;
91*31ce8d88SJasvinder Singh 
92*31ce8d88SJasvinder Singh 	return result;
93*31ce8d88SJasvinder Singh }
94*31ce8d88SJasvinder Singh 
95*31ce8d88SJasvinder Singh int
96*31ce8d88SJasvinder Singh softnic_parser_read_uint64(uint64_t *value, const char *p)
97*31ce8d88SJasvinder Singh {
98*31ce8d88SJasvinder Singh 	char *next;
99*31ce8d88SJasvinder Singh 	uint64_t val;
100*31ce8d88SJasvinder Singh 
101*31ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
102*31ce8d88SJasvinder Singh 	if (!isdigit(*p))
103*31ce8d88SJasvinder Singh 		return -EINVAL;
104*31ce8d88SJasvinder Singh 
105*31ce8d88SJasvinder Singh 	val = strtoul(p, &next, 10);
106*31ce8d88SJasvinder Singh 	if (p == next)
107*31ce8d88SJasvinder Singh 		return -EINVAL;
108*31ce8d88SJasvinder Singh 
109*31ce8d88SJasvinder Singh 	p = next;
110*31ce8d88SJasvinder Singh 	switch (*p) {
111*31ce8d88SJasvinder Singh 	case 'T':
112*31ce8d88SJasvinder Singh 		val *= 1024ULL;
113*31ce8d88SJasvinder Singh 		/* fall through */
114*31ce8d88SJasvinder Singh 	case 'G':
115*31ce8d88SJasvinder Singh 		val *= 1024ULL;
116*31ce8d88SJasvinder Singh 		/* fall through */
117*31ce8d88SJasvinder Singh 	case 'M':
118*31ce8d88SJasvinder Singh 		val *= 1024ULL;
119*31ce8d88SJasvinder Singh 		/* fall through */
120*31ce8d88SJasvinder Singh 	case 'k':
121*31ce8d88SJasvinder Singh 	case 'K':
122*31ce8d88SJasvinder Singh 		val *= 1024ULL;
123*31ce8d88SJasvinder Singh 		p++;
124*31ce8d88SJasvinder Singh 		break;
125*31ce8d88SJasvinder Singh 	}
126*31ce8d88SJasvinder Singh 
127*31ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
128*31ce8d88SJasvinder Singh 	if (*p != '\0')
129*31ce8d88SJasvinder Singh 		return -EINVAL;
130*31ce8d88SJasvinder Singh 
131*31ce8d88SJasvinder Singh 	*value = val;
132*31ce8d88SJasvinder Singh 	return 0;
133*31ce8d88SJasvinder Singh }
134*31ce8d88SJasvinder Singh 
135*31ce8d88SJasvinder Singh int
136*31ce8d88SJasvinder Singh softnic_parser_read_uint64_hex(uint64_t *value, const char *p)
137*31ce8d88SJasvinder Singh {
138*31ce8d88SJasvinder Singh 	char *next;
139*31ce8d88SJasvinder Singh 	uint64_t val;
140*31ce8d88SJasvinder Singh 
141*31ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
142*31ce8d88SJasvinder Singh 
143*31ce8d88SJasvinder Singh 	val = strtoul(p, &next, 16);
144*31ce8d88SJasvinder Singh 	if (p == next)
145*31ce8d88SJasvinder Singh 		return -EINVAL;
146*31ce8d88SJasvinder Singh 
147*31ce8d88SJasvinder Singh 	p = skip_white_spaces(next);
148*31ce8d88SJasvinder Singh 	if (*p != '\0')
149*31ce8d88SJasvinder Singh 		return -EINVAL;
150*31ce8d88SJasvinder Singh 
151*31ce8d88SJasvinder Singh 	*value = val;
152*31ce8d88SJasvinder Singh 	return 0;
153*31ce8d88SJasvinder Singh }
154*31ce8d88SJasvinder Singh 
155*31ce8d88SJasvinder Singh int
156*31ce8d88SJasvinder Singh softnic_parser_read_uint32(uint32_t *value, const char *p)
157*31ce8d88SJasvinder Singh {
158*31ce8d88SJasvinder Singh 	uint64_t val = 0;
159*31ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64(&val, p);
160*31ce8d88SJasvinder Singh 
161*31ce8d88SJasvinder Singh 	if (ret < 0)
162*31ce8d88SJasvinder Singh 		return ret;
163*31ce8d88SJasvinder Singh 
164*31ce8d88SJasvinder Singh 	if (val > UINT32_MAX)
165*31ce8d88SJasvinder Singh 		return -ERANGE;
166*31ce8d88SJasvinder Singh 
167*31ce8d88SJasvinder Singh 	*value = val;
168*31ce8d88SJasvinder Singh 	return 0;
169*31ce8d88SJasvinder Singh }
170*31ce8d88SJasvinder Singh 
171*31ce8d88SJasvinder Singh int
172*31ce8d88SJasvinder Singh softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
173*31ce8d88SJasvinder Singh {
174*31ce8d88SJasvinder Singh 	uint64_t val = 0;
175*31ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64_hex(&val, p);
176*31ce8d88SJasvinder Singh 
177*31ce8d88SJasvinder Singh 	if (ret < 0)
178*31ce8d88SJasvinder Singh 		return ret;
179*31ce8d88SJasvinder Singh 
180*31ce8d88SJasvinder Singh 	if (val > UINT32_MAX)
181*31ce8d88SJasvinder Singh 		return -ERANGE;
182*31ce8d88SJasvinder Singh 
183*31ce8d88SJasvinder Singh 	*value = val;
184*31ce8d88SJasvinder Singh 	return 0;
185*31ce8d88SJasvinder Singh }
186*31ce8d88SJasvinder Singh 
187*31ce8d88SJasvinder Singh int
188*31ce8d88SJasvinder Singh softnic_parser_read_uint16(uint16_t *value, const char *p)
189*31ce8d88SJasvinder Singh {
190*31ce8d88SJasvinder Singh 	uint64_t val = 0;
191*31ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64(&val, p);
192*31ce8d88SJasvinder Singh 
193*31ce8d88SJasvinder Singh 	if (ret < 0)
194*31ce8d88SJasvinder Singh 		return ret;
195*31ce8d88SJasvinder Singh 
196*31ce8d88SJasvinder Singh 	if (val > UINT16_MAX)
197*31ce8d88SJasvinder Singh 		return -ERANGE;
198*31ce8d88SJasvinder Singh 
199*31ce8d88SJasvinder Singh 	*value = val;
200*31ce8d88SJasvinder Singh 	return 0;
201*31ce8d88SJasvinder Singh }
202*31ce8d88SJasvinder Singh 
203*31ce8d88SJasvinder Singh int
204*31ce8d88SJasvinder Singh softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
205*31ce8d88SJasvinder Singh {
206*31ce8d88SJasvinder Singh 	uint64_t val = 0;
207*31ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64_hex(&val, p);
208*31ce8d88SJasvinder Singh 
209*31ce8d88SJasvinder Singh 	if (ret < 0)
210*31ce8d88SJasvinder Singh 		return ret;
211*31ce8d88SJasvinder Singh 
212*31ce8d88SJasvinder Singh 	if (val > UINT16_MAX)
213*31ce8d88SJasvinder Singh 		return -ERANGE;
214*31ce8d88SJasvinder Singh 
215*31ce8d88SJasvinder Singh 	*value = val;
216*31ce8d88SJasvinder Singh 	return 0;
217*31ce8d88SJasvinder Singh }
218*31ce8d88SJasvinder Singh 
219*31ce8d88SJasvinder Singh int
220*31ce8d88SJasvinder Singh softnic_parser_read_uint8(uint8_t *value, const char *p)
221*31ce8d88SJasvinder Singh {
222*31ce8d88SJasvinder Singh 	uint64_t val = 0;
223*31ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64(&val, p);
224*31ce8d88SJasvinder Singh 
225*31ce8d88SJasvinder Singh 	if (ret < 0)
226*31ce8d88SJasvinder Singh 		return ret;
227*31ce8d88SJasvinder Singh 
228*31ce8d88SJasvinder Singh 	if (val > UINT8_MAX)
229*31ce8d88SJasvinder Singh 		return -ERANGE;
230*31ce8d88SJasvinder Singh 
231*31ce8d88SJasvinder Singh 	*value = val;
232*31ce8d88SJasvinder Singh 	return 0;
233*31ce8d88SJasvinder Singh }
234*31ce8d88SJasvinder Singh 
235*31ce8d88SJasvinder Singh int
236*31ce8d88SJasvinder Singh softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
237*31ce8d88SJasvinder Singh {
238*31ce8d88SJasvinder Singh 	uint64_t val = 0;
239*31ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64_hex(&val, p);
240*31ce8d88SJasvinder Singh 
241*31ce8d88SJasvinder Singh 	if (ret < 0)
242*31ce8d88SJasvinder Singh 		return ret;
243*31ce8d88SJasvinder Singh 
244*31ce8d88SJasvinder Singh 	if (val > UINT8_MAX)
245*31ce8d88SJasvinder Singh 		return -ERANGE;
246*31ce8d88SJasvinder Singh 
247*31ce8d88SJasvinder Singh 	*value = val;
248*31ce8d88SJasvinder Singh 	return 0;
249*31ce8d88SJasvinder Singh }
250*31ce8d88SJasvinder Singh 
251*31ce8d88SJasvinder Singh int
252*31ce8d88SJasvinder Singh softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
253*31ce8d88SJasvinder Singh {
254*31ce8d88SJasvinder Singh 	uint32_t i;
255*31ce8d88SJasvinder Singh 
256*31ce8d88SJasvinder Singh 	if (string == NULL ||
257*31ce8d88SJasvinder Singh 		tokens == NULL ||
258*31ce8d88SJasvinder Singh 		(*n_tokens < 1))
259*31ce8d88SJasvinder Singh 		return -EINVAL;
260*31ce8d88SJasvinder Singh 
261*31ce8d88SJasvinder Singh 	for (i = 0; i < *n_tokens; i++) {
262*31ce8d88SJasvinder Singh 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
263*31ce8d88SJasvinder Singh 		if (tokens[i] == NULL)
264*31ce8d88SJasvinder Singh 			break;
265*31ce8d88SJasvinder Singh 	}
266*31ce8d88SJasvinder Singh 
267*31ce8d88SJasvinder Singh 	if (i == *n_tokens &&
268*31ce8d88SJasvinder Singh 		strtok_r(string, PARSE_DELIMITER, &string) != NULL)
269*31ce8d88SJasvinder Singh 		return -E2BIG;
270*31ce8d88SJasvinder Singh 
271*31ce8d88SJasvinder Singh 	*n_tokens = i;
272*31ce8d88SJasvinder Singh 	return 0;
273*31ce8d88SJasvinder Singh }
274*31ce8d88SJasvinder Singh 
275*31ce8d88SJasvinder Singh int
276*31ce8d88SJasvinder Singh softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
277*31ce8d88SJasvinder Singh {
278*31ce8d88SJasvinder Singh 	char *c;
279*31ce8d88SJasvinder Singh 	uint32_t len, i;
280*31ce8d88SJasvinder Singh 
281*31ce8d88SJasvinder Singh 	/* Check input parameters */
282*31ce8d88SJasvinder Singh 	if (src == NULL ||
283*31ce8d88SJasvinder Singh 		dst == NULL ||
284*31ce8d88SJasvinder Singh 		size == NULL ||
285*31ce8d88SJasvinder Singh 		(*size == 0))
286*31ce8d88SJasvinder Singh 		return -1;
287*31ce8d88SJasvinder Singh 
288*31ce8d88SJasvinder Singh 	len = strlen(src);
289*31ce8d88SJasvinder Singh 	if (((len & 3) != 0) ||
290*31ce8d88SJasvinder Singh 		(len > (*size) * 2))
291*31ce8d88SJasvinder Singh 		return -1;
292*31ce8d88SJasvinder Singh 	*size = len / 2;
293*31ce8d88SJasvinder Singh 
294*31ce8d88SJasvinder Singh 	for (c = src; *c != 0; c++) {
295*31ce8d88SJasvinder Singh 		if ((((*c) >= '0') && ((*c) <= '9')) ||
296*31ce8d88SJasvinder Singh 			(((*c) >= 'A') && ((*c) <= 'F')) ||
297*31ce8d88SJasvinder Singh 			(((*c) >= 'a') && ((*c) <= 'f')))
298*31ce8d88SJasvinder Singh 			continue;
299*31ce8d88SJasvinder Singh 
300*31ce8d88SJasvinder Singh 		return -1;
301*31ce8d88SJasvinder Singh 	}
302*31ce8d88SJasvinder Singh 
303*31ce8d88SJasvinder Singh 	/* Convert chars to bytes */
304*31ce8d88SJasvinder Singh 	for (i = 0; i < *size; i++)
305*31ce8d88SJasvinder Singh 		dst[i] = get_hex_val(src[2 * i]) * 16 +
306*31ce8d88SJasvinder Singh 			get_hex_val(src[2 * i + 1]);
307*31ce8d88SJasvinder Singh 
308*31ce8d88SJasvinder Singh 	return 0;
309*31ce8d88SJasvinder Singh }
310*31ce8d88SJasvinder Singh 
311*31ce8d88SJasvinder Singh int
312*31ce8d88SJasvinder Singh softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
313*31ce8d88SJasvinder Singh {
314*31ce8d88SJasvinder Singh 	uint32_t n_max_labels = *n_labels, count = 0;
315*31ce8d88SJasvinder Singh 
316*31ce8d88SJasvinder Singh 	/* Check for void list of labels */
317*31ce8d88SJasvinder Singh 	if (strcmp(string, "<void>") == 0) {
318*31ce8d88SJasvinder Singh 		*n_labels = 0;
319*31ce8d88SJasvinder Singh 		return 0;
320*31ce8d88SJasvinder Singh 	}
321*31ce8d88SJasvinder Singh 
322*31ce8d88SJasvinder Singh 	/* At least one label should be present */
323*31ce8d88SJasvinder Singh 	for ( ; (*string != '\0'); ) {
324*31ce8d88SJasvinder Singh 		char *next;
325*31ce8d88SJasvinder Singh 		int value;
326*31ce8d88SJasvinder Singh 
327*31ce8d88SJasvinder Singh 		if (count >= n_max_labels)
328*31ce8d88SJasvinder Singh 			return -1;
329*31ce8d88SJasvinder Singh 
330*31ce8d88SJasvinder Singh 		if (count > 0) {
331*31ce8d88SJasvinder Singh 			if (string[0] != ':')
332*31ce8d88SJasvinder Singh 				return -1;
333*31ce8d88SJasvinder Singh 
334*31ce8d88SJasvinder Singh 			string++;
335*31ce8d88SJasvinder Singh 		}
336*31ce8d88SJasvinder Singh 
337*31ce8d88SJasvinder Singh 		value = strtol(string, &next, 10);
338*31ce8d88SJasvinder Singh 		if (next == string)
339*31ce8d88SJasvinder Singh 			return -1;
340*31ce8d88SJasvinder Singh 		string = next;
341*31ce8d88SJasvinder Singh 
342*31ce8d88SJasvinder Singh 		labels[count++] = (uint32_t)value;
343*31ce8d88SJasvinder Singh 	}
344*31ce8d88SJasvinder Singh 
345*31ce8d88SJasvinder Singh 	*n_labels = count;
346*31ce8d88SJasvinder Singh 	return 0;
347*31ce8d88SJasvinder Singh }
348*31ce8d88SJasvinder Singh 
349*31ce8d88SJasvinder Singh #define INADDRSZ 4
350*31ce8d88SJasvinder Singh #define IN6ADDRSZ 16
351*31ce8d88SJasvinder Singh 
352*31ce8d88SJasvinder Singh /* int
353*31ce8d88SJasvinder Singh  * inet_pton4(src, dst)
354*31ce8d88SJasvinder Singh  *      like inet_aton() but without all the hexadecimal and shorthand.
355*31ce8d88SJasvinder Singh  * return:
356*31ce8d88SJasvinder Singh  *      1 if `src' is a valid dotted quad, else 0.
357*31ce8d88SJasvinder Singh  * notice:
358*31ce8d88SJasvinder Singh  *      does not touch `dst' unless it's returning 1.
359*31ce8d88SJasvinder Singh  * author:
360*31ce8d88SJasvinder Singh  *      Paul Vixie, 1996.
361*31ce8d88SJasvinder Singh  */
362*31ce8d88SJasvinder Singh static int
363*31ce8d88SJasvinder Singh inet_pton4(const char *src, unsigned char *dst)
364*31ce8d88SJasvinder Singh {
365*31ce8d88SJasvinder Singh 	static const char digits[] = "0123456789";
366*31ce8d88SJasvinder Singh 	int saw_digit, octets, ch;
367*31ce8d88SJasvinder Singh 	unsigned char tmp[INADDRSZ], *tp;
368*31ce8d88SJasvinder Singh 
369*31ce8d88SJasvinder Singh 	saw_digit = 0;
370*31ce8d88SJasvinder Singh 	octets = 0;
371*31ce8d88SJasvinder Singh 	*(tp = tmp) = 0;
372*31ce8d88SJasvinder Singh 	while ((ch = *src++) != '\0') {
373*31ce8d88SJasvinder Singh 		const char *pch;
374*31ce8d88SJasvinder Singh 
375*31ce8d88SJasvinder Singh 		pch = strchr(digits, ch);
376*31ce8d88SJasvinder Singh 		if (pch != NULL) {
377*31ce8d88SJasvinder Singh 			unsigned int new = *tp * 10 + (pch - digits);
378*31ce8d88SJasvinder Singh 
379*31ce8d88SJasvinder Singh 			if (new > 255)
380*31ce8d88SJasvinder Singh 				return 0;
381*31ce8d88SJasvinder Singh 			if (!saw_digit) {
382*31ce8d88SJasvinder Singh 				if (++octets > 4)
383*31ce8d88SJasvinder Singh 					return 0;
384*31ce8d88SJasvinder Singh 				saw_digit = 1;
385*31ce8d88SJasvinder Singh 			}
386*31ce8d88SJasvinder Singh 			*tp = (unsigned char)new;
387*31ce8d88SJasvinder Singh 		} else if (ch == '.' && saw_digit) {
388*31ce8d88SJasvinder Singh 			if (octets == 4)
389*31ce8d88SJasvinder Singh 				return 0;
390*31ce8d88SJasvinder Singh 			*++tp = 0;
391*31ce8d88SJasvinder Singh 			saw_digit = 0;
392*31ce8d88SJasvinder Singh 		} else
393*31ce8d88SJasvinder Singh 			return 0;
394*31ce8d88SJasvinder Singh 	}
395*31ce8d88SJasvinder Singh 	if (octets < 4)
396*31ce8d88SJasvinder Singh 		return 0;
397*31ce8d88SJasvinder Singh 
398*31ce8d88SJasvinder Singh 	memcpy(dst, tmp, INADDRSZ);
399*31ce8d88SJasvinder Singh 	return 1;
400*31ce8d88SJasvinder Singh }
401*31ce8d88SJasvinder Singh 
402*31ce8d88SJasvinder Singh /* int
403*31ce8d88SJasvinder Singh  * inet_pton6(src, dst)
404*31ce8d88SJasvinder Singh  *      convert presentation level address to network order binary form.
405*31ce8d88SJasvinder Singh  * return:
406*31ce8d88SJasvinder Singh  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
407*31ce8d88SJasvinder Singh  * notice:
408*31ce8d88SJasvinder Singh  *      (1) does not touch `dst' unless it's returning 1.
409*31ce8d88SJasvinder Singh  *      (2) :: in a full address is silently ignored.
410*31ce8d88SJasvinder Singh  * credit:
411*31ce8d88SJasvinder Singh  *      inspired by Mark Andrews.
412*31ce8d88SJasvinder Singh  * author:
413*31ce8d88SJasvinder Singh  *      Paul Vixie, 1996.
414*31ce8d88SJasvinder Singh  */
415*31ce8d88SJasvinder Singh static int
416*31ce8d88SJasvinder Singh inet_pton6(const char *src, unsigned char *dst)
417*31ce8d88SJasvinder Singh {
418*31ce8d88SJasvinder Singh 	static const char xdigits_l[] = "0123456789abcdef",
419*31ce8d88SJasvinder Singh 		xdigits_u[] = "0123456789ABCDEF";
420*31ce8d88SJasvinder Singh 	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
421*31ce8d88SJasvinder Singh 	const char *xdigits = 0, *curtok = 0;
422*31ce8d88SJasvinder Singh 	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
423*31ce8d88SJasvinder Singh 	unsigned int val = 0;
424*31ce8d88SJasvinder Singh 	unsigned int dbloct_count = 0;
425*31ce8d88SJasvinder Singh 
426*31ce8d88SJasvinder Singh 	memset((tp = tmp), '\0', IN6ADDRSZ);
427*31ce8d88SJasvinder Singh 	endp = tp + IN6ADDRSZ;
428*31ce8d88SJasvinder Singh 	colonp = NULL;
429*31ce8d88SJasvinder Singh 	/* Leading :: requires some special handling. */
430*31ce8d88SJasvinder Singh 	if (*src == ':')
431*31ce8d88SJasvinder Singh 		if (*++src != ':')
432*31ce8d88SJasvinder Singh 			return 0;
433*31ce8d88SJasvinder Singh 	curtok = src;
434*31ce8d88SJasvinder Singh 	saw_xdigit = count_xdigit = 0;
435*31ce8d88SJasvinder Singh 	val = 0;
436*31ce8d88SJasvinder Singh 
437*31ce8d88SJasvinder Singh 	while ((ch = *src++) != '\0') {
438*31ce8d88SJasvinder Singh 		const char *pch;
439*31ce8d88SJasvinder Singh 
440*31ce8d88SJasvinder Singh 		pch = strchr((xdigits = xdigits_l), ch);
441*31ce8d88SJasvinder Singh 		if (pch == NULL)
442*31ce8d88SJasvinder Singh 			pch = strchr((xdigits = xdigits_u), ch);
443*31ce8d88SJasvinder Singh 		if (pch != NULL) {
444*31ce8d88SJasvinder Singh 			if (count_xdigit >= 4)
445*31ce8d88SJasvinder Singh 				return 0;
446*31ce8d88SJasvinder Singh 			val <<= 4;
447*31ce8d88SJasvinder Singh 			val |= (pch - xdigits);
448*31ce8d88SJasvinder Singh 			if (val > 0xffff)
449*31ce8d88SJasvinder Singh 				return 0;
450*31ce8d88SJasvinder Singh 			saw_xdigit = 1;
451*31ce8d88SJasvinder Singh 			count_xdigit++;
452*31ce8d88SJasvinder Singh 			continue;
453*31ce8d88SJasvinder Singh 		}
454*31ce8d88SJasvinder Singh 		if (ch == ':') {
455*31ce8d88SJasvinder Singh 			curtok = src;
456*31ce8d88SJasvinder Singh 			if (!saw_xdigit) {
457*31ce8d88SJasvinder Singh 				if (colonp)
458*31ce8d88SJasvinder Singh 					return 0;
459*31ce8d88SJasvinder Singh 				colonp = tp;
460*31ce8d88SJasvinder Singh 				continue;
461*31ce8d88SJasvinder Singh 			} else if (*src == '\0') {
462*31ce8d88SJasvinder Singh 				return 0;
463*31ce8d88SJasvinder Singh 			}
464*31ce8d88SJasvinder Singh 			if (tp + sizeof(int16_t) > endp)
465*31ce8d88SJasvinder Singh 				return 0;
466*31ce8d88SJasvinder Singh 			*tp++ = (unsigned char)((val >> 8) & 0xff);
467*31ce8d88SJasvinder Singh 			*tp++ = (unsigned char)(val & 0xff);
468*31ce8d88SJasvinder Singh 			saw_xdigit = 0;
469*31ce8d88SJasvinder Singh 			count_xdigit = 0;
470*31ce8d88SJasvinder Singh 			val = 0;
471*31ce8d88SJasvinder Singh 			dbloct_count++;
472*31ce8d88SJasvinder Singh 			continue;
473*31ce8d88SJasvinder Singh 		}
474*31ce8d88SJasvinder Singh 		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
475*31ce8d88SJasvinder Singh 		    inet_pton4(curtok, tp) > 0) {
476*31ce8d88SJasvinder Singh 			tp += INADDRSZ;
477*31ce8d88SJasvinder Singh 			saw_xdigit = 0;
478*31ce8d88SJasvinder Singh 			dbloct_count += 2;
479*31ce8d88SJasvinder Singh 			break;  /* '\0' was seen by inet_pton4(). */
480*31ce8d88SJasvinder Singh 		}
481*31ce8d88SJasvinder Singh 		return 0;
482*31ce8d88SJasvinder Singh 	}
483*31ce8d88SJasvinder Singh 	if (saw_xdigit) {
484*31ce8d88SJasvinder Singh 		if (tp + sizeof(int16_t) > endp)
485*31ce8d88SJasvinder Singh 			return 0;
486*31ce8d88SJasvinder Singh 		*tp++ = (unsigned char)((val >> 8) & 0xff);
487*31ce8d88SJasvinder Singh 		*tp++ = (unsigned char)(val & 0xff);
488*31ce8d88SJasvinder Singh 		dbloct_count++;
489*31ce8d88SJasvinder Singh 	}
490*31ce8d88SJasvinder Singh 	if (colonp != NULL) {
491*31ce8d88SJasvinder Singh 		/* if we already have 8 double octets, having a colon means error */
492*31ce8d88SJasvinder Singh 		if (dbloct_count == 8)
493*31ce8d88SJasvinder Singh 			return 0;
494*31ce8d88SJasvinder Singh 
495*31ce8d88SJasvinder Singh 		/* Since some memmove()'s erroneously fail to handle
496*31ce8d88SJasvinder Singh 		 * overlapping regions, we'll do the shift by hand.
497*31ce8d88SJasvinder Singh 		 */
498*31ce8d88SJasvinder Singh 		const int n = tp - colonp;
499*31ce8d88SJasvinder Singh 		int i;
500*31ce8d88SJasvinder Singh 
501*31ce8d88SJasvinder Singh 		for (i = 1; i <= n; i++) {
502*31ce8d88SJasvinder Singh 			endp[-i] = colonp[n - i];
503*31ce8d88SJasvinder Singh 			colonp[n - i] = 0;
504*31ce8d88SJasvinder Singh 		}
505*31ce8d88SJasvinder Singh 		tp = endp;
506*31ce8d88SJasvinder Singh 	}
507*31ce8d88SJasvinder Singh 	if (tp != endp)
508*31ce8d88SJasvinder Singh 		return 0;
509*31ce8d88SJasvinder Singh 	memcpy(dst, tmp, IN6ADDRSZ);
510*31ce8d88SJasvinder Singh 	return 1;
511*31ce8d88SJasvinder Singh }
512*31ce8d88SJasvinder Singh 
513*31ce8d88SJasvinder Singh static struct ether_addr *
514*31ce8d88SJasvinder Singh my_ether_aton(const char *a)
515*31ce8d88SJasvinder Singh {
516*31ce8d88SJasvinder Singh 	int i;
517*31ce8d88SJasvinder Singh 	char *end;
518*31ce8d88SJasvinder Singh 	unsigned long o[ETHER_ADDR_LEN];
519*31ce8d88SJasvinder Singh 	static struct ether_addr ether_addr;
520*31ce8d88SJasvinder Singh 
521*31ce8d88SJasvinder Singh 	i = 0;
522*31ce8d88SJasvinder Singh 	do {
523*31ce8d88SJasvinder Singh 		errno = 0;
524*31ce8d88SJasvinder Singh 		o[i] = strtoul(a, &end, 16);
525*31ce8d88SJasvinder Singh 		if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
526*31ce8d88SJasvinder Singh 			return NULL;
527*31ce8d88SJasvinder Singh 		a = end + 1;
528*31ce8d88SJasvinder Singh 	} while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
529*31ce8d88SJasvinder Singh 
530*31ce8d88SJasvinder Singh 	/* Junk at the end of line */
531*31ce8d88SJasvinder Singh 	if (end[0] != 0)
532*31ce8d88SJasvinder Singh 		return NULL;
533*31ce8d88SJasvinder Singh 
534*31ce8d88SJasvinder Singh 	/* Support the format XX:XX:XX:XX:XX:XX */
535*31ce8d88SJasvinder Singh 	if (i == ETHER_ADDR_LEN) {
536*31ce8d88SJasvinder Singh 		while (i-- != 0) {
537*31ce8d88SJasvinder Singh 			if (o[i] > UINT8_MAX)
538*31ce8d88SJasvinder Singh 				return NULL;
539*31ce8d88SJasvinder Singh 			ether_addr.addr_bytes[i] = (uint8_t)o[i];
540*31ce8d88SJasvinder Singh 		}
541*31ce8d88SJasvinder Singh 	/* Support the format XXXX:XXXX:XXXX */
542*31ce8d88SJasvinder Singh 	} else if (i == ETHER_ADDR_LEN / 2) {
543*31ce8d88SJasvinder Singh 		while (i-- != 0) {
544*31ce8d88SJasvinder Singh 			if (o[i] > UINT16_MAX)
545*31ce8d88SJasvinder Singh 				return NULL;
546*31ce8d88SJasvinder Singh 			ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
547*31ce8d88SJasvinder Singh 			ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
548*31ce8d88SJasvinder Singh 		}
549*31ce8d88SJasvinder Singh 	/* unknown format */
550*31ce8d88SJasvinder Singh 	} else
551*31ce8d88SJasvinder Singh 		return NULL;
552*31ce8d88SJasvinder Singh 
553*31ce8d88SJasvinder Singh 	return (struct ether_addr *)&ether_addr;
554*31ce8d88SJasvinder Singh }
555*31ce8d88SJasvinder Singh 
556*31ce8d88SJasvinder Singh int
557*31ce8d88SJasvinder Singh softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
558*31ce8d88SJasvinder Singh {
559*31ce8d88SJasvinder Singh 	if (strlen(token) >= INET_ADDRSTRLEN)
560*31ce8d88SJasvinder Singh 		return -EINVAL;
561*31ce8d88SJasvinder Singh 
562*31ce8d88SJasvinder Singh 	if (inet_pton4(token, (unsigned char *)ipv4) != 1)
563*31ce8d88SJasvinder Singh 		return -EINVAL;
564*31ce8d88SJasvinder Singh 
565*31ce8d88SJasvinder Singh 	return 0;
566*31ce8d88SJasvinder Singh }
567*31ce8d88SJasvinder Singh 
568*31ce8d88SJasvinder Singh int
569*31ce8d88SJasvinder Singh softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
570*31ce8d88SJasvinder Singh {
571*31ce8d88SJasvinder Singh 	if (strlen(token) >= INET6_ADDRSTRLEN)
572*31ce8d88SJasvinder Singh 		return -EINVAL;
573*31ce8d88SJasvinder Singh 
574*31ce8d88SJasvinder Singh 	if (inet_pton6(token, (unsigned char *)ipv6) != 1)
575*31ce8d88SJasvinder Singh 		return -EINVAL;
576*31ce8d88SJasvinder Singh 
577*31ce8d88SJasvinder Singh 	return 0;
578*31ce8d88SJasvinder Singh }
579*31ce8d88SJasvinder Singh 
580*31ce8d88SJasvinder Singh int
581*31ce8d88SJasvinder Singh softnic_parse_mac_addr(const char *token, struct ether_addr *addr)
582*31ce8d88SJasvinder Singh {
583*31ce8d88SJasvinder Singh 	struct ether_addr *tmp;
584*31ce8d88SJasvinder Singh 
585*31ce8d88SJasvinder Singh 	tmp = my_ether_aton(token);
586*31ce8d88SJasvinder Singh 	if (tmp == NULL)
587*31ce8d88SJasvinder Singh 		return -1;
588*31ce8d88SJasvinder Singh 
589*31ce8d88SJasvinder Singh 	memcpy(addr, tmp, sizeof(struct ether_addr));
590*31ce8d88SJasvinder Singh 	return 0;
591*31ce8d88SJasvinder Singh }
592*31ce8d88SJasvinder Singh 
593*31ce8d88SJasvinder Singh int
594*31ce8d88SJasvinder Singh softnic_parse_cpu_core(const char *entry,
595*31ce8d88SJasvinder Singh 	struct softnic_cpu_core_params *p)
596*31ce8d88SJasvinder Singh {
597*31ce8d88SJasvinder Singh 	size_t num_len;
598*31ce8d88SJasvinder Singh 	char num[8];
599*31ce8d88SJasvinder Singh 
600*31ce8d88SJasvinder Singh 	uint32_t s = 0, c = 0, h = 0, val;
601*31ce8d88SJasvinder Singh 	uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
602*31ce8d88SJasvinder Singh 	const char *next = skip_white_spaces(entry);
603*31ce8d88SJasvinder Singh 	char type;
604*31ce8d88SJasvinder Singh 
605*31ce8d88SJasvinder Singh 	if (p == NULL)
606*31ce8d88SJasvinder Singh 		return -EINVAL;
607*31ce8d88SJasvinder Singh 
608*31ce8d88SJasvinder Singh 	/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
609*31ce8d88SJasvinder Singh 	while (*next != '\0') {
610*31ce8d88SJasvinder Singh 		/* If everything parsed nothing should left */
611*31ce8d88SJasvinder Singh 		if (s_parsed && c_parsed && h_parsed)
612*31ce8d88SJasvinder Singh 			return -EINVAL;
613*31ce8d88SJasvinder Singh 
614*31ce8d88SJasvinder Singh 		type = *next;
615*31ce8d88SJasvinder Singh 		switch (type) {
616*31ce8d88SJasvinder Singh 		case 's':
617*31ce8d88SJasvinder Singh 		case 'S':
618*31ce8d88SJasvinder Singh 			if (s_parsed || c_parsed || h_parsed)
619*31ce8d88SJasvinder Singh 				return -EINVAL;
620*31ce8d88SJasvinder Singh 			s_parsed = 1;
621*31ce8d88SJasvinder Singh 			next++;
622*31ce8d88SJasvinder Singh 			break;
623*31ce8d88SJasvinder Singh 		case 'c':
624*31ce8d88SJasvinder Singh 		case 'C':
625*31ce8d88SJasvinder Singh 			if (c_parsed || h_parsed)
626*31ce8d88SJasvinder Singh 				return -EINVAL;
627*31ce8d88SJasvinder Singh 			c_parsed = 1;
628*31ce8d88SJasvinder Singh 			next++;
629*31ce8d88SJasvinder Singh 			break;
630*31ce8d88SJasvinder Singh 		case 'h':
631*31ce8d88SJasvinder Singh 		case 'H':
632*31ce8d88SJasvinder Singh 			if (h_parsed)
633*31ce8d88SJasvinder Singh 				return -EINVAL;
634*31ce8d88SJasvinder Singh 			h_parsed = 1;
635*31ce8d88SJasvinder Singh 			next++;
636*31ce8d88SJasvinder Singh 			break;
637*31ce8d88SJasvinder Singh 		default:
638*31ce8d88SJasvinder Singh 			/* If it start from digit it must be only core id. */
639*31ce8d88SJasvinder Singh 			if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
640*31ce8d88SJasvinder Singh 				return -EINVAL;
641*31ce8d88SJasvinder Singh 
642*31ce8d88SJasvinder Singh 			type = 'C';
643*31ce8d88SJasvinder Singh 		}
644*31ce8d88SJasvinder Singh 
645*31ce8d88SJasvinder Singh 		for (num_len = 0; *next != '\0'; next++, num_len++) {
646*31ce8d88SJasvinder Singh 			if (num_len == RTE_DIM(num))
647*31ce8d88SJasvinder Singh 				return -EINVAL;
648*31ce8d88SJasvinder Singh 
649*31ce8d88SJasvinder Singh 			if (!isdigit(*next))
650*31ce8d88SJasvinder Singh 				break;
651*31ce8d88SJasvinder Singh 
652*31ce8d88SJasvinder Singh 			num[num_len] = *next;
653*31ce8d88SJasvinder Singh 		}
654*31ce8d88SJasvinder Singh 
655*31ce8d88SJasvinder Singh 		if (num_len == 0 && type != 'h' && type != 'H')
656*31ce8d88SJasvinder Singh 			return -EINVAL;
657*31ce8d88SJasvinder Singh 
658*31ce8d88SJasvinder Singh 		if (num_len != 0 && (type == 'h' || type == 'H'))
659*31ce8d88SJasvinder Singh 			return -EINVAL;
660*31ce8d88SJasvinder Singh 
661*31ce8d88SJasvinder Singh 		num[num_len] = '\0';
662*31ce8d88SJasvinder Singh 		val = strtol(num, NULL, 10);
663*31ce8d88SJasvinder Singh 
664*31ce8d88SJasvinder Singh 		h = 0;
665*31ce8d88SJasvinder Singh 		switch (type) {
666*31ce8d88SJasvinder Singh 		case 's':
667*31ce8d88SJasvinder Singh 		case 'S':
668*31ce8d88SJasvinder Singh 			s = val;
669*31ce8d88SJasvinder Singh 			break;
670*31ce8d88SJasvinder Singh 		case 'c':
671*31ce8d88SJasvinder Singh 		case 'C':
672*31ce8d88SJasvinder Singh 			c = val;
673*31ce8d88SJasvinder Singh 			break;
674*31ce8d88SJasvinder Singh 		case 'h':
675*31ce8d88SJasvinder Singh 		case 'H':
676*31ce8d88SJasvinder Singh 			h = 1;
677*31ce8d88SJasvinder Singh 			break;
678*31ce8d88SJasvinder Singh 		}
679*31ce8d88SJasvinder Singh 	}
680*31ce8d88SJasvinder Singh 
681*31ce8d88SJasvinder Singh 	p->socket_id = s;
682*31ce8d88SJasvinder Singh 	p->core_id = c;
683*31ce8d88SJasvinder Singh 	p->thread_id = h;
684*31ce8d88SJasvinder Singh 	return 0;
685*31ce8d88SJasvinder Singh }
686