xref: /dpdk/drivers/net/softnic/parser.c (revision 6d13ea8e)
131ce8d88SJasvinder Singh /* SPDX-License-Identifier: BSD-3-Clause
231ce8d88SJasvinder Singh  * Copyright(c) 2016 Intel Corporation.
331ce8d88SJasvinder Singh  * Copyright (c) 2009, Olivier MATZ <[email protected]>
431ce8d88SJasvinder Singh  * All rights reserved.
531ce8d88SJasvinder Singh  */
631ce8d88SJasvinder Singh 
731ce8d88SJasvinder Singh /* For inet_pton4() and inet_pton6() functions:
831ce8d88SJasvinder Singh  *
931ce8d88SJasvinder Singh  * Copyright (c) 1996 by Internet Software Consortium.
1031ce8d88SJasvinder Singh  *
1131ce8d88SJasvinder Singh  * Permission to use, copy, modify, and distribute this software for any
1231ce8d88SJasvinder Singh  * purpose with or without fee is hereby granted, provided that the above
1331ce8d88SJasvinder Singh  * copyright notice and this permission notice appear in all copies.
1431ce8d88SJasvinder Singh  *
1531ce8d88SJasvinder Singh  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1631ce8d88SJasvinder Singh  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1731ce8d88SJasvinder Singh  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1831ce8d88SJasvinder Singh  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1931ce8d88SJasvinder Singh  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2031ce8d88SJasvinder Singh  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2131ce8d88SJasvinder Singh  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2231ce8d88SJasvinder Singh  * SOFTWARE.
2331ce8d88SJasvinder Singh  */
2431ce8d88SJasvinder Singh 
2531ce8d88SJasvinder Singh #include <stdint.h>
2631ce8d88SJasvinder Singh #include <stdlib.h>
2731ce8d88SJasvinder Singh #include <stdio.h>
2831ce8d88SJasvinder Singh #include <ctype.h>
2931ce8d88SJasvinder Singh #include <getopt.h>
3031ce8d88SJasvinder Singh #include <errno.h>
3131ce8d88SJasvinder Singh #include <stdarg.h>
3231ce8d88SJasvinder Singh #include <string.h>
3331ce8d88SJasvinder Singh #include <libgen.h>
3431ce8d88SJasvinder Singh #include <unistd.h>
3531ce8d88SJasvinder Singh #include <sys/wait.h>
3631ce8d88SJasvinder Singh 
3731ce8d88SJasvinder Singh #include <rte_errno.h>
3831ce8d88SJasvinder Singh 
3931ce8d88SJasvinder Singh #include "parser.h"
4031ce8d88SJasvinder Singh 
4131ce8d88SJasvinder Singh static uint32_t
4231ce8d88SJasvinder Singh get_hex_val(char c)
4331ce8d88SJasvinder Singh {
4431ce8d88SJasvinder Singh 	switch (c) {
4531ce8d88SJasvinder Singh 	case '0': case '1': case '2': case '3': case '4': case '5':
4631ce8d88SJasvinder Singh 	case '6': case '7': case '8': case '9':
4731ce8d88SJasvinder Singh 		return c - '0';
4831ce8d88SJasvinder Singh 	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
4931ce8d88SJasvinder Singh 		return c - 'A' + 10;
5031ce8d88SJasvinder Singh 	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
5131ce8d88SJasvinder Singh 		return c - 'a' + 10;
5231ce8d88SJasvinder Singh 	default:
5331ce8d88SJasvinder Singh 		return 0;
5431ce8d88SJasvinder Singh 	}
5531ce8d88SJasvinder Singh }
5631ce8d88SJasvinder Singh 
5731ce8d88SJasvinder Singh int
5831ce8d88SJasvinder Singh softnic_parser_read_arg_bool(const char *p)
5931ce8d88SJasvinder Singh {
6031ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
6131ce8d88SJasvinder Singh 	int result = -EINVAL;
6231ce8d88SJasvinder Singh 
6331ce8d88SJasvinder Singh 	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
6431ce8d88SJasvinder Singh 		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
6531ce8d88SJasvinder Singh 		p += 3;
6631ce8d88SJasvinder Singh 		result = 1;
6731ce8d88SJasvinder Singh 	}
6831ce8d88SJasvinder Singh 
6931ce8d88SJasvinder Singh 	if (((p[0] == 'o') && (p[1] == 'n')) ||
7031ce8d88SJasvinder Singh 		((p[0] == 'O') && (p[1] == 'N'))) {
7131ce8d88SJasvinder Singh 		p += 2;
7231ce8d88SJasvinder Singh 		result = 1;
7331ce8d88SJasvinder Singh 	}
7431ce8d88SJasvinder Singh 
7531ce8d88SJasvinder Singh 	if (((p[0] == 'n') && (p[1] == 'o')) ||
7631ce8d88SJasvinder Singh 		((p[0] == 'N') && (p[1] == 'O'))) {
7731ce8d88SJasvinder Singh 		p += 2;
7831ce8d88SJasvinder Singh 		result = 0;
7931ce8d88SJasvinder Singh 	}
8031ce8d88SJasvinder Singh 
8131ce8d88SJasvinder Singh 	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
8231ce8d88SJasvinder Singh 		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
8331ce8d88SJasvinder Singh 		p += 3;
8431ce8d88SJasvinder Singh 		result = 0;
8531ce8d88SJasvinder Singh 	}
8631ce8d88SJasvinder Singh 
8731ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
8831ce8d88SJasvinder Singh 
8931ce8d88SJasvinder Singh 	if (p[0] != '\0')
9031ce8d88SJasvinder Singh 		return -EINVAL;
9131ce8d88SJasvinder Singh 
9231ce8d88SJasvinder Singh 	return result;
9331ce8d88SJasvinder Singh }
9431ce8d88SJasvinder Singh 
9531ce8d88SJasvinder Singh int
96552e3f72SCristian Dumitrescu softnic_parser_read_int32(int32_t *value, const char *p)
97552e3f72SCristian Dumitrescu {
98552e3f72SCristian Dumitrescu 	char *next;
99552e3f72SCristian Dumitrescu 	int32_t val;
100552e3f72SCristian Dumitrescu 
101552e3f72SCristian Dumitrescu 	p = skip_white_spaces(p);
102552e3f72SCristian Dumitrescu 	if (!isdigit(*p))
103552e3f72SCristian Dumitrescu 		return -EINVAL;
104552e3f72SCristian Dumitrescu 
105552e3f72SCristian Dumitrescu 	val = strtol(p, &next, 10);
106552e3f72SCristian Dumitrescu 	if (p == next)
107552e3f72SCristian Dumitrescu 		return -EINVAL;
108552e3f72SCristian Dumitrescu 
109552e3f72SCristian Dumitrescu 	*value = val;
110552e3f72SCristian Dumitrescu 	return 0;
111552e3f72SCristian Dumitrescu }
112552e3f72SCristian Dumitrescu 
113552e3f72SCristian Dumitrescu int
11431ce8d88SJasvinder Singh softnic_parser_read_uint64(uint64_t *value, const char *p)
11531ce8d88SJasvinder Singh {
11631ce8d88SJasvinder Singh 	char *next;
11731ce8d88SJasvinder Singh 	uint64_t val;
11831ce8d88SJasvinder Singh 
11931ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
12031ce8d88SJasvinder Singh 	if (!isdigit(*p))
12131ce8d88SJasvinder Singh 		return -EINVAL;
12231ce8d88SJasvinder Singh 
12331ce8d88SJasvinder Singh 	val = strtoul(p, &next, 10);
12431ce8d88SJasvinder Singh 	if (p == next)
12531ce8d88SJasvinder Singh 		return -EINVAL;
12631ce8d88SJasvinder Singh 
12731ce8d88SJasvinder Singh 	p = next;
12831ce8d88SJasvinder Singh 	switch (*p) {
12931ce8d88SJasvinder Singh 	case 'T':
13031ce8d88SJasvinder Singh 		val *= 1024ULL;
13131ce8d88SJasvinder Singh 		/* fall through */
13231ce8d88SJasvinder Singh 	case 'G':
13331ce8d88SJasvinder Singh 		val *= 1024ULL;
13431ce8d88SJasvinder Singh 		/* fall through */
13531ce8d88SJasvinder Singh 	case 'M':
13631ce8d88SJasvinder Singh 		val *= 1024ULL;
13731ce8d88SJasvinder Singh 		/* fall through */
13831ce8d88SJasvinder Singh 	case 'k':
13931ce8d88SJasvinder Singh 	case 'K':
14031ce8d88SJasvinder Singh 		val *= 1024ULL;
14131ce8d88SJasvinder Singh 		p++;
14231ce8d88SJasvinder Singh 		break;
14331ce8d88SJasvinder Singh 	}
14431ce8d88SJasvinder Singh 
14531ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
14631ce8d88SJasvinder Singh 	if (*p != '\0')
14731ce8d88SJasvinder Singh 		return -EINVAL;
14831ce8d88SJasvinder Singh 
14931ce8d88SJasvinder Singh 	*value = val;
15031ce8d88SJasvinder Singh 	return 0;
15131ce8d88SJasvinder Singh }
15231ce8d88SJasvinder Singh 
15331ce8d88SJasvinder Singh int
15431ce8d88SJasvinder Singh softnic_parser_read_uint64_hex(uint64_t *value, const char *p)
15531ce8d88SJasvinder Singh {
15631ce8d88SJasvinder Singh 	char *next;
15731ce8d88SJasvinder Singh 	uint64_t val;
15831ce8d88SJasvinder Singh 
15931ce8d88SJasvinder Singh 	p = skip_white_spaces(p);
16031ce8d88SJasvinder Singh 
16131ce8d88SJasvinder Singh 	val = strtoul(p, &next, 16);
16231ce8d88SJasvinder Singh 	if (p == next)
16331ce8d88SJasvinder Singh 		return -EINVAL;
16431ce8d88SJasvinder Singh 
16531ce8d88SJasvinder Singh 	p = skip_white_spaces(next);
16631ce8d88SJasvinder Singh 	if (*p != '\0')
16731ce8d88SJasvinder Singh 		return -EINVAL;
16831ce8d88SJasvinder Singh 
16931ce8d88SJasvinder Singh 	*value = val;
17031ce8d88SJasvinder Singh 	return 0;
17131ce8d88SJasvinder Singh }
17231ce8d88SJasvinder Singh 
17331ce8d88SJasvinder Singh int
17431ce8d88SJasvinder Singh softnic_parser_read_uint32(uint32_t *value, const char *p)
17531ce8d88SJasvinder Singh {
17631ce8d88SJasvinder Singh 	uint64_t val = 0;
17731ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64(&val, p);
17831ce8d88SJasvinder Singh 
17931ce8d88SJasvinder Singh 	if (ret < 0)
18031ce8d88SJasvinder Singh 		return ret;
18131ce8d88SJasvinder Singh 
18231ce8d88SJasvinder Singh 	if (val > UINT32_MAX)
18331ce8d88SJasvinder Singh 		return -ERANGE;
18431ce8d88SJasvinder Singh 
18531ce8d88SJasvinder Singh 	*value = val;
18631ce8d88SJasvinder Singh 	return 0;
18731ce8d88SJasvinder Singh }
18831ce8d88SJasvinder Singh 
18931ce8d88SJasvinder Singh int
19031ce8d88SJasvinder Singh softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
19131ce8d88SJasvinder Singh {
19231ce8d88SJasvinder Singh 	uint64_t val = 0;
19331ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64_hex(&val, p);
19431ce8d88SJasvinder Singh 
19531ce8d88SJasvinder Singh 	if (ret < 0)
19631ce8d88SJasvinder Singh 		return ret;
19731ce8d88SJasvinder Singh 
19831ce8d88SJasvinder Singh 	if (val > UINT32_MAX)
19931ce8d88SJasvinder Singh 		return -ERANGE;
20031ce8d88SJasvinder Singh 
20131ce8d88SJasvinder Singh 	*value = val;
20231ce8d88SJasvinder Singh 	return 0;
20331ce8d88SJasvinder Singh }
20431ce8d88SJasvinder Singh 
20531ce8d88SJasvinder Singh int
20631ce8d88SJasvinder Singh softnic_parser_read_uint16(uint16_t *value, const char *p)
20731ce8d88SJasvinder Singh {
20831ce8d88SJasvinder Singh 	uint64_t val = 0;
20931ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64(&val, p);
21031ce8d88SJasvinder Singh 
21131ce8d88SJasvinder Singh 	if (ret < 0)
21231ce8d88SJasvinder Singh 		return ret;
21331ce8d88SJasvinder Singh 
21431ce8d88SJasvinder Singh 	if (val > UINT16_MAX)
21531ce8d88SJasvinder Singh 		return -ERANGE;
21631ce8d88SJasvinder Singh 
21731ce8d88SJasvinder Singh 	*value = val;
21831ce8d88SJasvinder Singh 	return 0;
21931ce8d88SJasvinder Singh }
22031ce8d88SJasvinder Singh 
22131ce8d88SJasvinder Singh int
22231ce8d88SJasvinder Singh softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
22331ce8d88SJasvinder Singh {
22431ce8d88SJasvinder Singh 	uint64_t val = 0;
22531ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64_hex(&val, p);
22631ce8d88SJasvinder Singh 
22731ce8d88SJasvinder Singh 	if (ret < 0)
22831ce8d88SJasvinder Singh 		return ret;
22931ce8d88SJasvinder Singh 
23031ce8d88SJasvinder Singh 	if (val > UINT16_MAX)
23131ce8d88SJasvinder Singh 		return -ERANGE;
23231ce8d88SJasvinder Singh 
23331ce8d88SJasvinder Singh 	*value = val;
23431ce8d88SJasvinder Singh 	return 0;
23531ce8d88SJasvinder Singh }
23631ce8d88SJasvinder Singh 
23731ce8d88SJasvinder Singh int
23831ce8d88SJasvinder Singh softnic_parser_read_uint8(uint8_t *value, const char *p)
23931ce8d88SJasvinder Singh {
24031ce8d88SJasvinder Singh 	uint64_t val = 0;
24131ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64(&val, p);
24231ce8d88SJasvinder Singh 
24331ce8d88SJasvinder Singh 	if (ret < 0)
24431ce8d88SJasvinder Singh 		return ret;
24531ce8d88SJasvinder Singh 
24631ce8d88SJasvinder Singh 	if (val > UINT8_MAX)
24731ce8d88SJasvinder Singh 		return -ERANGE;
24831ce8d88SJasvinder Singh 
24931ce8d88SJasvinder Singh 	*value = val;
25031ce8d88SJasvinder Singh 	return 0;
25131ce8d88SJasvinder Singh }
25231ce8d88SJasvinder Singh 
25331ce8d88SJasvinder Singh int
25431ce8d88SJasvinder Singh softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
25531ce8d88SJasvinder Singh {
25631ce8d88SJasvinder Singh 	uint64_t val = 0;
25731ce8d88SJasvinder Singh 	int ret = softnic_parser_read_uint64_hex(&val, p);
25831ce8d88SJasvinder Singh 
25931ce8d88SJasvinder Singh 	if (ret < 0)
26031ce8d88SJasvinder Singh 		return ret;
26131ce8d88SJasvinder Singh 
26231ce8d88SJasvinder Singh 	if (val > UINT8_MAX)
26331ce8d88SJasvinder Singh 		return -ERANGE;
26431ce8d88SJasvinder Singh 
26531ce8d88SJasvinder Singh 	*value = val;
26631ce8d88SJasvinder Singh 	return 0;
26731ce8d88SJasvinder Singh }
26831ce8d88SJasvinder Singh 
26931ce8d88SJasvinder Singh int
27031ce8d88SJasvinder Singh softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
27131ce8d88SJasvinder Singh {
27231ce8d88SJasvinder Singh 	uint32_t i;
27331ce8d88SJasvinder Singh 
27431ce8d88SJasvinder Singh 	if (string == NULL ||
27531ce8d88SJasvinder Singh 		tokens == NULL ||
27631ce8d88SJasvinder Singh 		(*n_tokens < 1))
27731ce8d88SJasvinder Singh 		return -EINVAL;
27831ce8d88SJasvinder Singh 
27931ce8d88SJasvinder Singh 	for (i = 0; i < *n_tokens; i++) {
28031ce8d88SJasvinder Singh 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
28131ce8d88SJasvinder Singh 		if (tokens[i] == NULL)
28231ce8d88SJasvinder Singh 			break;
28331ce8d88SJasvinder Singh 	}
28431ce8d88SJasvinder Singh 
28531ce8d88SJasvinder Singh 	if (i == *n_tokens &&
28631ce8d88SJasvinder Singh 		strtok_r(string, PARSE_DELIMITER, &string) != NULL)
28731ce8d88SJasvinder Singh 		return -E2BIG;
28831ce8d88SJasvinder Singh 
28931ce8d88SJasvinder Singh 	*n_tokens = i;
29031ce8d88SJasvinder Singh 	return 0;
29131ce8d88SJasvinder Singh }
29231ce8d88SJasvinder Singh 
29331ce8d88SJasvinder Singh int
29431ce8d88SJasvinder Singh softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
29531ce8d88SJasvinder Singh {
29631ce8d88SJasvinder Singh 	char *c;
29731ce8d88SJasvinder Singh 	uint32_t len, i;
29831ce8d88SJasvinder Singh 
29931ce8d88SJasvinder Singh 	/* Check input parameters */
30031ce8d88SJasvinder Singh 	if (src == NULL ||
30131ce8d88SJasvinder Singh 		dst == NULL ||
30231ce8d88SJasvinder Singh 		size == NULL ||
30331ce8d88SJasvinder Singh 		(*size == 0))
30431ce8d88SJasvinder Singh 		return -1;
30531ce8d88SJasvinder Singh 
30631ce8d88SJasvinder Singh 	len = strlen(src);
30731ce8d88SJasvinder Singh 	if (((len & 3) != 0) ||
30831ce8d88SJasvinder Singh 		(len > (*size) * 2))
30931ce8d88SJasvinder Singh 		return -1;
31031ce8d88SJasvinder Singh 	*size = len / 2;
31131ce8d88SJasvinder Singh 
31231ce8d88SJasvinder Singh 	for (c = src; *c != 0; c++) {
31331ce8d88SJasvinder Singh 		if ((((*c) >= '0') && ((*c) <= '9')) ||
31431ce8d88SJasvinder Singh 			(((*c) >= 'A') && ((*c) <= 'F')) ||
31531ce8d88SJasvinder Singh 			(((*c) >= 'a') && ((*c) <= 'f')))
31631ce8d88SJasvinder Singh 			continue;
31731ce8d88SJasvinder Singh 
31831ce8d88SJasvinder Singh 		return -1;
31931ce8d88SJasvinder Singh 	}
32031ce8d88SJasvinder Singh 
32131ce8d88SJasvinder Singh 	/* Convert chars to bytes */
32231ce8d88SJasvinder Singh 	for (i = 0; i < *size; i++)
32331ce8d88SJasvinder Singh 		dst[i] = get_hex_val(src[2 * i]) * 16 +
32431ce8d88SJasvinder Singh 			get_hex_val(src[2 * i + 1]);
32531ce8d88SJasvinder Singh 
32631ce8d88SJasvinder Singh 	return 0;
32731ce8d88SJasvinder Singh }
32831ce8d88SJasvinder Singh 
32931ce8d88SJasvinder Singh int
33031ce8d88SJasvinder Singh softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
33131ce8d88SJasvinder Singh {
33231ce8d88SJasvinder Singh 	uint32_t n_max_labels = *n_labels, count = 0;
33331ce8d88SJasvinder Singh 
33431ce8d88SJasvinder Singh 	/* Check for void list of labels */
33531ce8d88SJasvinder Singh 	if (strcmp(string, "<void>") == 0) {
33631ce8d88SJasvinder Singh 		*n_labels = 0;
33731ce8d88SJasvinder Singh 		return 0;
33831ce8d88SJasvinder Singh 	}
33931ce8d88SJasvinder Singh 
34031ce8d88SJasvinder Singh 	/* At least one label should be present */
34131ce8d88SJasvinder Singh 	for ( ; (*string != '\0'); ) {
34231ce8d88SJasvinder Singh 		char *next;
34331ce8d88SJasvinder Singh 		int value;
34431ce8d88SJasvinder Singh 
34531ce8d88SJasvinder Singh 		if (count >= n_max_labels)
34631ce8d88SJasvinder Singh 			return -1;
34731ce8d88SJasvinder Singh 
34831ce8d88SJasvinder Singh 		if (count > 0) {
34931ce8d88SJasvinder Singh 			if (string[0] != ':')
35031ce8d88SJasvinder Singh 				return -1;
35131ce8d88SJasvinder Singh 
35231ce8d88SJasvinder Singh 			string++;
35331ce8d88SJasvinder Singh 		}
35431ce8d88SJasvinder Singh 
35531ce8d88SJasvinder Singh 		value = strtol(string, &next, 10);
35631ce8d88SJasvinder Singh 		if (next == string)
35731ce8d88SJasvinder Singh 			return -1;
35831ce8d88SJasvinder Singh 		string = next;
35931ce8d88SJasvinder Singh 
36031ce8d88SJasvinder Singh 		labels[count++] = (uint32_t)value;
36131ce8d88SJasvinder Singh 	}
36231ce8d88SJasvinder Singh 
36331ce8d88SJasvinder Singh 	*n_labels = count;
36431ce8d88SJasvinder Singh 	return 0;
36531ce8d88SJasvinder Singh }
36631ce8d88SJasvinder Singh 
36731ce8d88SJasvinder Singh #define INADDRSZ 4
36831ce8d88SJasvinder Singh #define IN6ADDRSZ 16
36931ce8d88SJasvinder Singh 
37031ce8d88SJasvinder Singh /* int
37131ce8d88SJasvinder Singh  * inet_pton4(src, dst)
37231ce8d88SJasvinder Singh  *      like inet_aton() but without all the hexadecimal and shorthand.
37331ce8d88SJasvinder Singh  * return:
37431ce8d88SJasvinder Singh  *      1 if `src' is a valid dotted quad, else 0.
37531ce8d88SJasvinder Singh  * notice:
37631ce8d88SJasvinder Singh  *      does not touch `dst' unless it's returning 1.
37731ce8d88SJasvinder Singh  * author:
37831ce8d88SJasvinder Singh  *      Paul Vixie, 1996.
37931ce8d88SJasvinder Singh  */
38031ce8d88SJasvinder Singh static int
38131ce8d88SJasvinder Singh inet_pton4(const char *src, unsigned char *dst)
38231ce8d88SJasvinder Singh {
38331ce8d88SJasvinder Singh 	static const char digits[] = "0123456789";
38431ce8d88SJasvinder Singh 	int saw_digit, octets, ch;
38531ce8d88SJasvinder Singh 	unsigned char tmp[INADDRSZ], *tp;
38631ce8d88SJasvinder Singh 
38731ce8d88SJasvinder Singh 	saw_digit = 0;
38831ce8d88SJasvinder Singh 	octets = 0;
38931ce8d88SJasvinder Singh 	*(tp = tmp) = 0;
39031ce8d88SJasvinder Singh 	while ((ch = *src++) != '\0') {
39131ce8d88SJasvinder Singh 		const char *pch;
39231ce8d88SJasvinder Singh 
39331ce8d88SJasvinder Singh 		pch = strchr(digits, ch);
39431ce8d88SJasvinder Singh 		if (pch != NULL) {
39531ce8d88SJasvinder Singh 			unsigned int new = *tp * 10 + (pch - digits);
39631ce8d88SJasvinder Singh 
39731ce8d88SJasvinder Singh 			if (new > 255)
39831ce8d88SJasvinder Singh 				return 0;
39931ce8d88SJasvinder Singh 			if (!saw_digit) {
40031ce8d88SJasvinder Singh 				if (++octets > 4)
40131ce8d88SJasvinder Singh 					return 0;
40231ce8d88SJasvinder Singh 				saw_digit = 1;
40331ce8d88SJasvinder Singh 			}
40431ce8d88SJasvinder Singh 			*tp = (unsigned char)new;
40531ce8d88SJasvinder Singh 		} else if (ch == '.' && saw_digit) {
40631ce8d88SJasvinder Singh 			if (octets == 4)
40731ce8d88SJasvinder Singh 				return 0;
40831ce8d88SJasvinder Singh 			*++tp = 0;
40931ce8d88SJasvinder Singh 			saw_digit = 0;
41031ce8d88SJasvinder Singh 		} else
41131ce8d88SJasvinder Singh 			return 0;
41231ce8d88SJasvinder Singh 	}
41331ce8d88SJasvinder Singh 	if (octets < 4)
41431ce8d88SJasvinder Singh 		return 0;
41531ce8d88SJasvinder Singh 
41631ce8d88SJasvinder Singh 	memcpy(dst, tmp, INADDRSZ);
41731ce8d88SJasvinder Singh 	return 1;
41831ce8d88SJasvinder Singh }
41931ce8d88SJasvinder Singh 
42031ce8d88SJasvinder Singh /* int
42131ce8d88SJasvinder Singh  * inet_pton6(src, dst)
42231ce8d88SJasvinder Singh  *      convert presentation level address to network order binary form.
42331ce8d88SJasvinder Singh  * return:
42431ce8d88SJasvinder Singh  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
42531ce8d88SJasvinder Singh  * notice:
42631ce8d88SJasvinder Singh  *      (1) does not touch `dst' unless it's returning 1.
42731ce8d88SJasvinder Singh  *      (2) :: in a full address is silently ignored.
42831ce8d88SJasvinder Singh  * credit:
42931ce8d88SJasvinder Singh  *      inspired by Mark Andrews.
43031ce8d88SJasvinder Singh  * author:
43131ce8d88SJasvinder Singh  *      Paul Vixie, 1996.
43231ce8d88SJasvinder Singh  */
43331ce8d88SJasvinder Singh static int
43431ce8d88SJasvinder Singh inet_pton6(const char *src, unsigned char *dst)
43531ce8d88SJasvinder Singh {
43631ce8d88SJasvinder Singh 	static const char xdigits_l[] = "0123456789abcdef",
43731ce8d88SJasvinder Singh 		xdigits_u[] = "0123456789ABCDEF";
43831ce8d88SJasvinder Singh 	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
43931ce8d88SJasvinder Singh 	const char *xdigits = 0, *curtok = 0;
44031ce8d88SJasvinder Singh 	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
44131ce8d88SJasvinder Singh 	unsigned int val = 0;
44231ce8d88SJasvinder Singh 	unsigned int dbloct_count = 0;
44331ce8d88SJasvinder Singh 
44431ce8d88SJasvinder Singh 	memset((tp = tmp), '\0', IN6ADDRSZ);
44531ce8d88SJasvinder Singh 	endp = tp + IN6ADDRSZ;
44631ce8d88SJasvinder Singh 	colonp = NULL;
44731ce8d88SJasvinder Singh 	/* Leading :: requires some special handling. */
44831ce8d88SJasvinder Singh 	if (*src == ':')
44931ce8d88SJasvinder Singh 		if (*++src != ':')
45031ce8d88SJasvinder Singh 			return 0;
45131ce8d88SJasvinder Singh 	curtok = src;
45231ce8d88SJasvinder Singh 	saw_xdigit = count_xdigit = 0;
45331ce8d88SJasvinder Singh 	val = 0;
45431ce8d88SJasvinder Singh 
45531ce8d88SJasvinder Singh 	while ((ch = *src++) != '\0') {
45631ce8d88SJasvinder Singh 		const char *pch;
45731ce8d88SJasvinder Singh 
45831ce8d88SJasvinder Singh 		pch = strchr((xdigits = xdigits_l), ch);
45931ce8d88SJasvinder Singh 		if (pch == NULL)
46031ce8d88SJasvinder Singh 			pch = strchr((xdigits = xdigits_u), ch);
46131ce8d88SJasvinder Singh 		if (pch != NULL) {
46231ce8d88SJasvinder Singh 			if (count_xdigit >= 4)
46331ce8d88SJasvinder Singh 				return 0;
46431ce8d88SJasvinder Singh 			val <<= 4;
46531ce8d88SJasvinder Singh 			val |= (pch - xdigits);
46631ce8d88SJasvinder Singh 			if (val > 0xffff)
46731ce8d88SJasvinder Singh 				return 0;
46831ce8d88SJasvinder Singh 			saw_xdigit = 1;
46931ce8d88SJasvinder Singh 			count_xdigit++;
47031ce8d88SJasvinder Singh 			continue;
47131ce8d88SJasvinder Singh 		}
47231ce8d88SJasvinder Singh 		if (ch == ':') {
47331ce8d88SJasvinder Singh 			curtok = src;
47431ce8d88SJasvinder Singh 			if (!saw_xdigit) {
47531ce8d88SJasvinder Singh 				if (colonp)
47631ce8d88SJasvinder Singh 					return 0;
47731ce8d88SJasvinder Singh 				colonp = tp;
47831ce8d88SJasvinder Singh 				continue;
47931ce8d88SJasvinder Singh 			} else if (*src == '\0') {
48031ce8d88SJasvinder Singh 				return 0;
48131ce8d88SJasvinder Singh 			}
48231ce8d88SJasvinder Singh 			if (tp + sizeof(int16_t) > endp)
48331ce8d88SJasvinder Singh 				return 0;
48431ce8d88SJasvinder Singh 			*tp++ = (unsigned char)((val >> 8) & 0xff);
48531ce8d88SJasvinder Singh 			*tp++ = (unsigned char)(val & 0xff);
48631ce8d88SJasvinder Singh 			saw_xdigit = 0;
48731ce8d88SJasvinder Singh 			count_xdigit = 0;
48831ce8d88SJasvinder Singh 			val = 0;
48931ce8d88SJasvinder Singh 			dbloct_count++;
49031ce8d88SJasvinder Singh 			continue;
49131ce8d88SJasvinder Singh 		}
49231ce8d88SJasvinder Singh 		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
49331ce8d88SJasvinder Singh 		    inet_pton4(curtok, tp) > 0) {
49431ce8d88SJasvinder Singh 			tp += INADDRSZ;
49531ce8d88SJasvinder Singh 			saw_xdigit = 0;
49631ce8d88SJasvinder Singh 			dbloct_count += 2;
49731ce8d88SJasvinder Singh 			break;  /* '\0' was seen by inet_pton4(). */
49831ce8d88SJasvinder Singh 		}
49931ce8d88SJasvinder Singh 		return 0;
50031ce8d88SJasvinder Singh 	}
50131ce8d88SJasvinder Singh 	if (saw_xdigit) {
50231ce8d88SJasvinder Singh 		if (tp + sizeof(int16_t) > endp)
50331ce8d88SJasvinder Singh 			return 0;
50431ce8d88SJasvinder Singh 		*tp++ = (unsigned char)((val >> 8) & 0xff);
50531ce8d88SJasvinder Singh 		*tp++ = (unsigned char)(val & 0xff);
50631ce8d88SJasvinder Singh 		dbloct_count++;
50731ce8d88SJasvinder Singh 	}
50831ce8d88SJasvinder Singh 	if (colonp != NULL) {
50931ce8d88SJasvinder Singh 		/* if we already have 8 double octets, having a colon means error */
51031ce8d88SJasvinder Singh 		if (dbloct_count == 8)
51131ce8d88SJasvinder Singh 			return 0;
51231ce8d88SJasvinder Singh 
51331ce8d88SJasvinder Singh 		/* Since some memmove()'s erroneously fail to handle
51431ce8d88SJasvinder Singh 		 * overlapping regions, we'll do the shift by hand.
51531ce8d88SJasvinder Singh 		 */
51631ce8d88SJasvinder Singh 		const int n = tp - colonp;
51731ce8d88SJasvinder Singh 		int i;
51831ce8d88SJasvinder Singh 
51931ce8d88SJasvinder Singh 		for (i = 1; i <= n; i++) {
52031ce8d88SJasvinder Singh 			endp[-i] = colonp[n - i];
52131ce8d88SJasvinder Singh 			colonp[n - i] = 0;
52231ce8d88SJasvinder Singh 		}
52331ce8d88SJasvinder Singh 		tp = endp;
52431ce8d88SJasvinder Singh 	}
52531ce8d88SJasvinder Singh 	if (tp != endp)
52631ce8d88SJasvinder Singh 		return 0;
52731ce8d88SJasvinder Singh 	memcpy(dst, tmp, IN6ADDRSZ);
52831ce8d88SJasvinder Singh 	return 1;
52931ce8d88SJasvinder Singh }
53031ce8d88SJasvinder Singh 
531*6d13ea8eSOlivier Matz static struct rte_ether_addr *
53231ce8d88SJasvinder Singh my_ether_aton(const char *a)
53331ce8d88SJasvinder Singh {
53431ce8d88SJasvinder Singh 	int i;
53531ce8d88SJasvinder Singh 	char *end;
53631ce8d88SJasvinder Singh 	unsigned long o[ETHER_ADDR_LEN];
537*6d13ea8eSOlivier Matz 	static struct rte_ether_addr ether_addr;
53831ce8d88SJasvinder Singh 
53931ce8d88SJasvinder Singh 	i = 0;
54031ce8d88SJasvinder Singh 	do {
54131ce8d88SJasvinder Singh 		errno = 0;
54231ce8d88SJasvinder Singh 		o[i] = strtoul(a, &end, 16);
54331ce8d88SJasvinder Singh 		if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
54431ce8d88SJasvinder Singh 			return NULL;
54531ce8d88SJasvinder Singh 		a = end + 1;
54631ce8d88SJasvinder Singh 	} while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
54731ce8d88SJasvinder Singh 
54831ce8d88SJasvinder Singh 	/* Junk at the end of line */
54931ce8d88SJasvinder Singh 	if (end[0] != 0)
55031ce8d88SJasvinder Singh 		return NULL;
55131ce8d88SJasvinder Singh 
55231ce8d88SJasvinder Singh 	/* Support the format XX:XX:XX:XX:XX:XX */
55331ce8d88SJasvinder Singh 	if (i == ETHER_ADDR_LEN) {
55431ce8d88SJasvinder Singh 		while (i-- != 0) {
55531ce8d88SJasvinder Singh 			if (o[i] > UINT8_MAX)
55631ce8d88SJasvinder Singh 				return NULL;
55731ce8d88SJasvinder Singh 			ether_addr.addr_bytes[i] = (uint8_t)o[i];
55831ce8d88SJasvinder Singh 		}
55931ce8d88SJasvinder Singh 	/* Support the format XXXX:XXXX:XXXX */
56031ce8d88SJasvinder Singh 	} else if (i == ETHER_ADDR_LEN / 2) {
56131ce8d88SJasvinder Singh 		while (i-- != 0) {
56231ce8d88SJasvinder Singh 			if (o[i] > UINT16_MAX)
56331ce8d88SJasvinder Singh 				return NULL;
56431ce8d88SJasvinder Singh 			ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
56531ce8d88SJasvinder Singh 			ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
56631ce8d88SJasvinder Singh 		}
56731ce8d88SJasvinder Singh 	/* unknown format */
56831ce8d88SJasvinder Singh 	} else
56931ce8d88SJasvinder Singh 		return NULL;
57031ce8d88SJasvinder Singh 
571*6d13ea8eSOlivier Matz 	return (struct rte_ether_addr *)&ether_addr;
57231ce8d88SJasvinder Singh }
57331ce8d88SJasvinder Singh 
57431ce8d88SJasvinder Singh int
57531ce8d88SJasvinder Singh softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
57631ce8d88SJasvinder Singh {
57731ce8d88SJasvinder Singh 	if (strlen(token) >= INET_ADDRSTRLEN)
57831ce8d88SJasvinder Singh 		return -EINVAL;
57931ce8d88SJasvinder Singh 
58031ce8d88SJasvinder Singh 	if (inet_pton4(token, (unsigned char *)ipv4) != 1)
58131ce8d88SJasvinder Singh 		return -EINVAL;
58231ce8d88SJasvinder Singh 
58331ce8d88SJasvinder Singh 	return 0;
58431ce8d88SJasvinder Singh }
58531ce8d88SJasvinder Singh 
58631ce8d88SJasvinder Singh int
58731ce8d88SJasvinder Singh softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
58831ce8d88SJasvinder Singh {
58931ce8d88SJasvinder Singh 	if (strlen(token) >= INET6_ADDRSTRLEN)
59031ce8d88SJasvinder Singh 		return -EINVAL;
59131ce8d88SJasvinder Singh 
59231ce8d88SJasvinder Singh 	if (inet_pton6(token, (unsigned char *)ipv6) != 1)
59331ce8d88SJasvinder Singh 		return -EINVAL;
59431ce8d88SJasvinder Singh 
59531ce8d88SJasvinder Singh 	return 0;
59631ce8d88SJasvinder Singh }
59731ce8d88SJasvinder Singh 
59831ce8d88SJasvinder Singh int
599*6d13ea8eSOlivier Matz softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr)
60031ce8d88SJasvinder Singh {
601*6d13ea8eSOlivier Matz 	struct rte_ether_addr *tmp;
60231ce8d88SJasvinder Singh 
60331ce8d88SJasvinder Singh 	tmp = my_ether_aton(token);
60431ce8d88SJasvinder Singh 	if (tmp == NULL)
60531ce8d88SJasvinder Singh 		return -1;
60631ce8d88SJasvinder Singh 
607*6d13ea8eSOlivier Matz 	memcpy(addr, tmp, sizeof(struct rte_ether_addr));
60831ce8d88SJasvinder Singh 	return 0;
60931ce8d88SJasvinder Singh }
61031ce8d88SJasvinder Singh 
61131ce8d88SJasvinder Singh int
61231ce8d88SJasvinder Singh softnic_parse_cpu_core(const char *entry,
61331ce8d88SJasvinder Singh 	struct softnic_cpu_core_params *p)
61431ce8d88SJasvinder Singh {
61531ce8d88SJasvinder Singh 	size_t num_len;
61631ce8d88SJasvinder Singh 	char num[8];
61731ce8d88SJasvinder Singh 
61831ce8d88SJasvinder Singh 	uint32_t s = 0, c = 0, h = 0, val;
61931ce8d88SJasvinder Singh 	uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
62031ce8d88SJasvinder Singh 	const char *next = skip_white_spaces(entry);
62131ce8d88SJasvinder Singh 	char type;
62231ce8d88SJasvinder Singh 
62331ce8d88SJasvinder Singh 	if (p == NULL)
62431ce8d88SJasvinder Singh 		return -EINVAL;
62531ce8d88SJasvinder Singh 
62631ce8d88SJasvinder Singh 	/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
62731ce8d88SJasvinder Singh 	while (*next != '\0') {
62831ce8d88SJasvinder Singh 		/* If everything parsed nothing should left */
62931ce8d88SJasvinder Singh 		if (s_parsed && c_parsed && h_parsed)
63031ce8d88SJasvinder Singh 			return -EINVAL;
63131ce8d88SJasvinder Singh 
63231ce8d88SJasvinder Singh 		type = *next;
63331ce8d88SJasvinder Singh 		switch (type) {
63431ce8d88SJasvinder Singh 		case 's':
63531ce8d88SJasvinder Singh 		case 'S':
63631ce8d88SJasvinder Singh 			if (s_parsed || c_parsed || h_parsed)
63731ce8d88SJasvinder Singh 				return -EINVAL;
63831ce8d88SJasvinder Singh 			s_parsed = 1;
63931ce8d88SJasvinder Singh 			next++;
64031ce8d88SJasvinder Singh 			break;
64131ce8d88SJasvinder Singh 		case 'c':
64231ce8d88SJasvinder Singh 		case 'C':
64331ce8d88SJasvinder Singh 			if (c_parsed || h_parsed)
64431ce8d88SJasvinder Singh 				return -EINVAL;
64531ce8d88SJasvinder Singh 			c_parsed = 1;
64631ce8d88SJasvinder Singh 			next++;
64731ce8d88SJasvinder Singh 			break;
64831ce8d88SJasvinder Singh 		case 'h':
64931ce8d88SJasvinder Singh 		case 'H':
65031ce8d88SJasvinder Singh 			if (h_parsed)
65131ce8d88SJasvinder Singh 				return -EINVAL;
65231ce8d88SJasvinder Singh 			h_parsed = 1;
65331ce8d88SJasvinder Singh 			next++;
65431ce8d88SJasvinder Singh 			break;
65531ce8d88SJasvinder Singh 		default:
65631ce8d88SJasvinder Singh 			/* If it start from digit it must be only core id. */
65731ce8d88SJasvinder Singh 			if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
65831ce8d88SJasvinder Singh 				return -EINVAL;
65931ce8d88SJasvinder Singh 
66031ce8d88SJasvinder Singh 			type = 'C';
66131ce8d88SJasvinder Singh 		}
66231ce8d88SJasvinder Singh 
66331ce8d88SJasvinder Singh 		for (num_len = 0; *next != '\0'; next++, num_len++) {
66431ce8d88SJasvinder Singh 			if (num_len == RTE_DIM(num))
66531ce8d88SJasvinder Singh 				return -EINVAL;
66631ce8d88SJasvinder Singh 
66731ce8d88SJasvinder Singh 			if (!isdigit(*next))
66831ce8d88SJasvinder Singh 				break;
66931ce8d88SJasvinder Singh 
67031ce8d88SJasvinder Singh 			num[num_len] = *next;
67131ce8d88SJasvinder Singh 		}
67231ce8d88SJasvinder Singh 
67331ce8d88SJasvinder Singh 		if (num_len == 0 && type != 'h' && type != 'H')
67431ce8d88SJasvinder Singh 			return -EINVAL;
67531ce8d88SJasvinder Singh 
67631ce8d88SJasvinder Singh 		if (num_len != 0 && (type == 'h' || type == 'H'))
67731ce8d88SJasvinder Singh 			return -EINVAL;
67831ce8d88SJasvinder Singh 
67931ce8d88SJasvinder Singh 		num[num_len] = '\0';
68031ce8d88SJasvinder Singh 		val = strtol(num, NULL, 10);
68131ce8d88SJasvinder Singh 
68231ce8d88SJasvinder Singh 		h = 0;
68331ce8d88SJasvinder Singh 		switch (type) {
68431ce8d88SJasvinder Singh 		case 's':
68531ce8d88SJasvinder Singh 		case 'S':
68631ce8d88SJasvinder Singh 			s = val;
68731ce8d88SJasvinder Singh 			break;
68831ce8d88SJasvinder Singh 		case 'c':
68931ce8d88SJasvinder Singh 		case 'C':
69031ce8d88SJasvinder Singh 			c = val;
69131ce8d88SJasvinder Singh 			break;
69231ce8d88SJasvinder Singh 		case 'h':
69331ce8d88SJasvinder Singh 		case 'H':
69431ce8d88SJasvinder Singh 			h = 1;
69531ce8d88SJasvinder Singh 			break;
69631ce8d88SJasvinder Singh 		}
69731ce8d88SJasvinder Singh 	}
69831ce8d88SJasvinder Singh 
69931ce8d88SJasvinder Singh 	p->socket_id = s;
70031ce8d88SJasvinder Singh 	p->core_id = c;
70131ce8d88SJasvinder Singh 	p->thread_id = h;
70231ce8d88SJasvinder Singh 	return 0;
70331ce8d88SJasvinder Singh }
704