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