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