xref: /dpdk/examples/ipsec-secgw/parser.c (revision 9ac91e2f7339e66658ef55b756a06b328e336fde)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2016 Intel Corporation
30d547ed0SFan Zhang  */
472b452c5SDmitry Kozlyuk #include <stdlib.h>
54054466bSIbtisam Tariq #include <arpa/inet.h>
64054466bSIbtisam Tariq #include <sys/socket.h>
74054466bSIbtisam Tariq 
80d547ed0SFan Zhang #include <rte_common.h>
90d547ed0SFan Zhang #include <rte_crypto.h>
10ae943ebeSReshma Pattan #include <rte_string_fns.h>
110d547ed0SFan Zhang 
120d547ed0SFan Zhang #include <cmdline_parse_string.h>
130d547ed0SFan Zhang #include <cmdline_parse_num.h>
140d547ed0SFan Zhang #include <cmdline_parse_ipaddr.h>
150d547ed0SFan Zhang #include <cmdline_socket.h>
160d547ed0SFan Zhang #include <cmdline.h>
170d547ed0SFan Zhang 
188e693616SAnoob Joseph #include "flow.h"
190d547ed0SFan Zhang #include "ipsec.h"
200d547ed0SFan Zhang #include "parser.h"
210d547ed0SFan Zhang 
220d547ed0SFan Zhang #define PARSE_DELIMITER		" \f\n\r\t\v"
230d547ed0SFan Zhang static int
240d547ed0SFan Zhang parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
250d547ed0SFan Zhang {
260d547ed0SFan Zhang 	uint32_t i;
270d547ed0SFan Zhang 
280d547ed0SFan Zhang 	if ((string == NULL) ||
290d547ed0SFan Zhang 		(tokens == NULL) ||
300d547ed0SFan Zhang 		(*n_tokens < 1))
310d547ed0SFan Zhang 		return -EINVAL;
320d547ed0SFan Zhang 
330d547ed0SFan Zhang 	for (i = 0; i < *n_tokens; i++) {
340d547ed0SFan Zhang 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
350d547ed0SFan Zhang 		if (tokens[i] == NULL)
360d547ed0SFan Zhang 			break;
370d547ed0SFan Zhang 	}
380d547ed0SFan Zhang 
390d547ed0SFan Zhang 	if ((i == *n_tokens) &&
400d547ed0SFan Zhang 		(NULL != strtok_r(string, PARSE_DELIMITER, &string)))
410d547ed0SFan Zhang 		return -E2BIG;
420d547ed0SFan Zhang 
430d547ed0SFan Zhang 	*n_tokens = i;
440d547ed0SFan Zhang 	return 0;
450d547ed0SFan Zhang }
460d547ed0SFan Zhang 
470d547ed0SFan Zhang int
480d547ed0SFan Zhang parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
490d547ed0SFan Zhang {
50ae943ebeSReshma Pattan 	char ip_str[INET_ADDRSTRLEN] = {0};
510d547ed0SFan Zhang 	char *pch;
520d547ed0SFan Zhang 
530d547ed0SFan Zhang 	pch = strchr(token, '/');
540d547ed0SFan Zhang 	if (pch != NULL) {
551bdea611SKirill Rybalchenko 		strlcpy(ip_str, token,
561bdea611SKirill Rybalchenko 			RTE_MIN((unsigned int long)(pch - token + 1),
57ae943ebeSReshma Pattan 			sizeof(ip_str)));
580d547ed0SFan Zhang 		pch += 1;
590d547ed0SFan Zhang 		if (is_str_num(pch) != 0)
600d547ed0SFan Zhang 			return -EINVAL;
610d547ed0SFan Zhang 		if (mask)
620d547ed0SFan Zhang 			*mask = atoi(pch);
630d547ed0SFan Zhang 	} else {
64ae943ebeSReshma Pattan 		strlcpy(ip_str, token, sizeof(ip_str));
650d547ed0SFan Zhang 		if (mask)
660d547ed0SFan Zhang 			*mask = 0;
670d547ed0SFan Zhang 	}
680d547ed0SFan Zhang 	if (strlen(ip_str) >= INET_ADDRSTRLEN)
690d547ed0SFan Zhang 		return -EINVAL;
700d547ed0SFan Zhang 
714054466bSIbtisam Tariq 	if (inet_pton(AF_INET, ip_str, ipv4) != 1)
720d547ed0SFan Zhang 		return -EINVAL;
730d547ed0SFan Zhang 
740d547ed0SFan Zhang 	return 0;
750d547ed0SFan Zhang }
760d547ed0SFan Zhang 
770d547ed0SFan Zhang int
78*9ac91e2fSRobin Jarry parse_ipv6_addr(const char *token, struct rte_ipv6_addr *ipv6, uint32_t *mask)
790d547ed0SFan Zhang {
800d547ed0SFan Zhang 	char ip_str[256] = {0};
810d547ed0SFan Zhang 	char *pch;
820d547ed0SFan Zhang 
830d547ed0SFan Zhang 	pch = strchr(token, '/');
840d547ed0SFan Zhang 	if (pch != NULL) {
851bdea611SKirill Rybalchenko 		strlcpy(ip_str, token,
861bdea611SKirill Rybalchenko 			RTE_MIN((unsigned int long)(pch - token + 1),
87ae943ebeSReshma Pattan 					sizeof(ip_str)));
880d547ed0SFan Zhang 		pch += 1;
890d547ed0SFan Zhang 		if (is_str_num(pch) != 0)
900d547ed0SFan Zhang 			return -EINVAL;
910d547ed0SFan Zhang 		if (mask)
920d547ed0SFan Zhang 			*mask = atoi(pch);
930d547ed0SFan Zhang 	} else {
94ae943ebeSReshma Pattan 		strlcpy(ip_str, token, sizeof(ip_str));
950d547ed0SFan Zhang 		if (mask)
960d547ed0SFan Zhang 			*mask = 0;
970d547ed0SFan Zhang 	}
980d547ed0SFan Zhang 
990d547ed0SFan Zhang 	if (strlen(ip_str) >= INET6_ADDRSTRLEN)
1000d547ed0SFan Zhang 		return -EINVAL;
1010d547ed0SFan Zhang 
1024054466bSIbtisam Tariq 	if (inet_pton(AF_INET6, ip_str, ipv6) != 1)
1030d547ed0SFan Zhang 		return -EINVAL;
1040d547ed0SFan Zhang 
1050d547ed0SFan Zhang 	return 0;
1060d547ed0SFan Zhang }
1070d547ed0SFan Zhang 
1080d547ed0SFan Zhang int
1090d547ed0SFan Zhang parse_range(const char *token, uint16_t *low, uint16_t *high)
1100d547ed0SFan Zhang {
1110d547ed0SFan Zhang 	char ch;
1120d547ed0SFan Zhang 	char num_str[20];
1130d547ed0SFan Zhang 	uint32_t pos;
1140d547ed0SFan Zhang 	int range_low = -1;
1150d547ed0SFan Zhang 	int range_high = -1;
1160d547ed0SFan Zhang 
1170d547ed0SFan Zhang 	if (!low || !high)
1180d547ed0SFan Zhang 		return -1;
1190d547ed0SFan Zhang 
1200d547ed0SFan Zhang 	memset(num_str, 0, 20);
1210d547ed0SFan Zhang 	pos = 0;
1220d547ed0SFan Zhang 
1230d547ed0SFan Zhang 	while ((ch = *token++) != '\0') {
1240d547ed0SFan Zhang 		if (isdigit(ch)) {
1250d547ed0SFan Zhang 			if (pos >= 19)
1260d547ed0SFan Zhang 				return -1;
1270d547ed0SFan Zhang 			num_str[pos++] = ch;
1280d547ed0SFan Zhang 		} else if (ch == ':') {
1290d547ed0SFan Zhang 			if (range_low != -1)
1300d547ed0SFan Zhang 				return -1;
1310d547ed0SFan Zhang 			range_low = atoi(num_str);
1320d547ed0SFan Zhang 			memset(num_str, 0, 20);
1330d547ed0SFan Zhang 			pos = 0;
1340d547ed0SFan Zhang 		}
1350d547ed0SFan Zhang 	}
1360d547ed0SFan Zhang 
1370d547ed0SFan Zhang 	if (strlen(num_str) == 0)
1380d547ed0SFan Zhang 		return -1;
1390d547ed0SFan Zhang 
1400d547ed0SFan Zhang 	range_high = atoi(num_str);
1410d547ed0SFan Zhang 
1420d547ed0SFan Zhang 	*low = (uint16_t)range_low;
1430d547ed0SFan Zhang 	*high = (uint16_t)range_high;
1440d547ed0SFan Zhang 
1450d547ed0SFan Zhang 	return 0;
1460d547ed0SFan Zhang }
1470d547ed0SFan Zhang 
1487622291bSKonstantin Ananyev /*
1497622291bSKonstantin Ananyev  * helper function for parse_mac, parse one section of the ether addr.
1507622291bSKonstantin Ananyev  */
1517622291bSKonstantin Ananyev static const char *
1527622291bSKonstantin Ananyev parse_uint8x16(const char *s, uint8_t *v, uint8_t ls)
1537622291bSKonstantin Ananyev {
1547622291bSKonstantin Ananyev 	char *end;
1557622291bSKonstantin Ananyev 	unsigned long t;
1567622291bSKonstantin Ananyev 
1577622291bSKonstantin Ananyev 	errno = 0;
1587622291bSKonstantin Ananyev 	t = strtoul(s, &end, 16);
1597622291bSKonstantin Ananyev 	if (errno != 0 || end[0] != ls || t > UINT8_MAX)
1607622291bSKonstantin Ananyev 		return NULL;
1617622291bSKonstantin Ananyev 	v[0] = t;
1627622291bSKonstantin Ananyev 	return end + 1;
1637622291bSKonstantin Ananyev }
1647622291bSKonstantin Ananyev 
1657622291bSKonstantin Ananyev static int
1666d13ea8eSOlivier Matz parse_mac(const char *str, struct rte_ether_addr *addr)
1677622291bSKonstantin Ananyev {
1687622291bSKonstantin Ananyev 	uint32_t i;
1697622291bSKonstantin Ananyev 
1707622291bSKonstantin Ananyev 	static const uint8_t stop_sym[RTE_DIM(addr->addr_bytes)] = {
1717622291bSKonstantin Ananyev 		[0] = ':',
1727622291bSKonstantin Ananyev 		[1] = ':',
1737622291bSKonstantin Ananyev 		[2] = ':',
1747622291bSKonstantin Ananyev 		[3] = ':',
1757622291bSKonstantin Ananyev 		[4] = ':',
1767622291bSKonstantin Ananyev 		[5] = 0,
1777622291bSKonstantin Ananyev 	};
1787622291bSKonstantin Ananyev 
1797622291bSKonstantin Ananyev 	for (i = 0; i != RTE_DIM(addr->addr_bytes); i++) {
1807622291bSKonstantin Ananyev 		str = parse_uint8x16(str, addr->addr_bytes + i, stop_sym[i]);
1817622291bSKonstantin Ananyev 		if (str == NULL)
1827622291bSKonstantin Ananyev 			return -EINVAL;
1837622291bSKonstantin Ananyev 	}
1847622291bSKonstantin Ananyev 
1857622291bSKonstantin Ananyev 	return 0;
1867622291bSKonstantin Ananyev }
1877622291bSKonstantin Ananyev 
1880d547ed0SFan Zhang /** sp add parse */
1890d547ed0SFan Zhang struct cfg_sp_add_cfg_item {
1900d547ed0SFan Zhang 	cmdline_fixed_string_t sp_keyword;
1910d547ed0SFan Zhang 	cmdline_multi_string_t multi_string;
1920d547ed0SFan Zhang };
1930d547ed0SFan Zhang 
1940d547ed0SFan Zhang static void
1950d547ed0SFan Zhang cfg_sp_add_cfg_item_parsed(void *parsed_result,
1960d547ed0SFan Zhang 	__rte_unused struct cmdline *cl, void *data)
1970d547ed0SFan Zhang {
1980d547ed0SFan Zhang 	struct cfg_sp_add_cfg_item *params = parsed_result;
1990d547ed0SFan Zhang 	char *tokens[32];
2000d547ed0SFan Zhang 	uint32_t n_tokens = RTE_DIM(tokens);
2010d547ed0SFan Zhang 	struct parse_status *status = (struct parse_status *)data;
2020d547ed0SFan Zhang 
2030d547ed0SFan Zhang 	APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
2040d547ed0SFan Zhang 		&n_tokens) == 0), status, "too many arguments");
2050d547ed0SFan Zhang 
2060d547ed0SFan Zhang 	if (status->status < 0)
2070d547ed0SFan Zhang 		return;
2080d547ed0SFan Zhang 
2090d547ed0SFan Zhang 	if (strcmp(tokens[0], "ipv4") == 0) {
2100d547ed0SFan Zhang 		parse_sp4_tokens(tokens, n_tokens, status);
2110d547ed0SFan Zhang 		if (status->status < 0)
2120d547ed0SFan Zhang 			return;
2130d547ed0SFan Zhang 	} else if (strcmp(tokens[0], "ipv6") == 0) {
2140d547ed0SFan Zhang 		parse_sp6_tokens(tokens, n_tokens, status);
2150d547ed0SFan Zhang 		if (status->status < 0)
2160d547ed0SFan Zhang 			return;
2170d547ed0SFan Zhang 	} else {
2180d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognizable input %s\n",
2190d547ed0SFan Zhang 			tokens[0]);
2200d547ed0SFan Zhang 		return;
2210d547ed0SFan Zhang 	}
2220d547ed0SFan Zhang }
2230d547ed0SFan Zhang 
2240d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sp_add_sp_str =
2250d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
2260d547ed0SFan Zhang 		sp_keyword, "sp");
2270d547ed0SFan Zhang 
2280d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sp_add_multi_str =
2290d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
2300d547ed0SFan Zhang 		TOKEN_STRING_MULTI);
2310d547ed0SFan Zhang 
2320d547ed0SFan Zhang cmdline_parse_inst_t cfg_sp_add_rule = {
2330d547ed0SFan Zhang 	.f = cfg_sp_add_cfg_item_parsed,
2340d547ed0SFan Zhang 	.data = NULL,
2350d547ed0SFan Zhang 	.help_str = "",
2360d547ed0SFan Zhang 	.tokens = {
2370d547ed0SFan Zhang 		(void *) &cfg_sp_add_sp_str,
2380d547ed0SFan Zhang 		(void *) &cfg_sp_add_multi_str,
2390d547ed0SFan Zhang 		NULL,
2400d547ed0SFan Zhang 	},
2410d547ed0SFan Zhang };
2420d547ed0SFan Zhang 
2430d547ed0SFan Zhang /* sa add parse */
2440d547ed0SFan Zhang struct cfg_sa_add_cfg_item {
2450d547ed0SFan Zhang 	cmdline_fixed_string_t sa_keyword;
2460d547ed0SFan Zhang 	cmdline_multi_string_t multi_string;
2470d547ed0SFan Zhang };
2480d547ed0SFan Zhang 
2490d547ed0SFan Zhang static void
2500d547ed0SFan Zhang cfg_sa_add_cfg_item_parsed(void *parsed_result,
2510d547ed0SFan Zhang 	__rte_unused struct cmdline *cl, void *data)
2520d547ed0SFan Zhang {
2530d547ed0SFan Zhang 	struct cfg_sa_add_cfg_item *params = parsed_result;
2540d547ed0SFan Zhang 	char *tokens[32];
2550d547ed0SFan Zhang 	uint32_t n_tokens = RTE_DIM(tokens);
2560d547ed0SFan Zhang 	struct parse_status *status = (struct parse_status *)data;
2570d547ed0SFan Zhang 
2580d547ed0SFan Zhang 	APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
2590d547ed0SFan Zhang 		&n_tokens) == 0, status, "too many arguments\n");
2600d547ed0SFan Zhang 
2610d547ed0SFan Zhang 	parse_sa_tokens(tokens, n_tokens, status);
2620d547ed0SFan Zhang }
2630d547ed0SFan Zhang 
2640d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sa_add_sa_str =
2650d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
2660d547ed0SFan Zhang 		sa_keyword, "sa");
2670d547ed0SFan Zhang 
2680d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sa_add_multi_str =
2690d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
2700d547ed0SFan Zhang 		TOKEN_STRING_MULTI);
2710d547ed0SFan Zhang 
2720d547ed0SFan Zhang cmdline_parse_inst_t cfg_sa_add_rule = {
2730d547ed0SFan Zhang 	.f = cfg_sa_add_cfg_item_parsed,
2740d547ed0SFan Zhang 	.data = NULL,
2750d547ed0SFan Zhang 	.help_str = "",
2760d547ed0SFan Zhang 	.tokens = {
2770d547ed0SFan Zhang 		(void *) &cfg_sa_add_sa_str,
2780d547ed0SFan Zhang 		(void *) &cfg_sa_add_multi_str,
2790d547ed0SFan Zhang 		NULL,
2800d547ed0SFan Zhang 	},
2810d547ed0SFan Zhang };
2820d547ed0SFan Zhang 
2830d547ed0SFan Zhang /* rt add parse */
2840d547ed0SFan Zhang struct cfg_rt_add_cfg_item {
2850d547ed0SFan Zhang 	cmdline_fixed_string_t rt_keyword;
2860d547ed0SFan Zhang 	cmdline_multi_string_t multi_string;
2870d547ed0SFan Zhang };
2880d547ed0SFan Zhang 
2890d547ed0SFan Zhang static void
2900d547ed0SFan Zhang cfg_rt_add_cfg_item_parsed(void *parsed_result,
2910d547ed0SFan Zhang 	__rte_unused struct cmdline *cl, void *data)
2920d547ed0SFan Zhang {
2930d547ed0SFan Zhang 	struct cfg_rt_add_cfg_item *params = parsed_result;
2940d547ed0SFan Zhang 	char *tokens[32];
2950d547ed0SFan Zhang 	uint32_t n_tokens = RTE_DIM(tokens);
2960d547ed0SFan Zhang 	struct parse_status *status = (struct parse_status *)data;
2970d547ed0SFan Zhang 
2980d547ed0SFan Zhang 	APP_CHECK(parse_tokenize_string(
2990d547ed0SFan Zhang 		params->multi_string, tokens, &n_tokens) == 0,
3000d547ed0SFan Zhang 		status, "too many arguments\n");
3010d547ed0SFan Zhang 	if (status->status < 0)
3020d547ed0SFan Zhang 		return;
3030d547ed0SFan Zhang 
3040d547ed0SFan Zhang 	parse_rt_tokens(tokens, n_tokens, status);
3050d547ed0SFan Zhang }
3060d547ed0SFan Zhang 
3070d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_rt_add_rt_str =
3080d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
3090d547ed0SFan Zhang 		rt_keyword, "rt");
3100d547ed0SFan Zhang 
3110d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_rt_add_multi_str =
3120d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
3130d547ed0SFan Zhang 		TOKEN_STRING_MULTI);
3140d547ed0SFan Zhang 
3150d547ed0SFan Zhang cmdline_parse_inst_t cfg_rt_add_rule = {
3160d547ed0SFan Zhang 	.f = cfg_rt_add_cfg_item_parsed,
3170d547ed0SFan Zhang 	.data = NULL,
3180d547ed0SFan Zhang 	.help_str = "",
3190d547ed0SFan Zhang 	.tokens = {
3200d547ed0SFan Zhang 		(void *) &cfg_rt_add_rt_str,
3210d547ed0SFan Zhang 		(void *) &cfg_rt_add_multi_str,
3220d547ed0SFan Zhang 		NULL,
3230d547ed0SFan Zhang 	},
3240d547ed0SFan Zhang };
3250d547ed0SFan Zhang 
3268e693616SAnoob Joseph /* flow add parse */
3278e693616SAnoob Joseph struct cfg_flow_add_cfg_item {
3288e693616SAnoob Joseph 	cmdline_fixed_string_t flow_keyword;
3298e693616SAnoob Joseph 	cmdline_multi_string_t multi_string;
3308e693616SAnoob Joseph };
3318e693616SAnoob Joseph 
3328e693616SAnoob Joseph static void
3338e693616SAnoob Joseph cfg_flow_add_cfg_item_parsed(void *parsed_result,
3348e693616SAnoob Joseph 	__rte_unused struct cmdline *cl, void *data)
3358e693616SAnoob Joseph {
3368e693616SAnoob Joseph 	struct cfg_flow_add_cfg_item *params = parsed_result;
3378e693616SAnoob Joseph 	char *tokens[32];
3388e693616SAnoob Joseph 	uint32_t n_tokens = RTE_DIM(tokens);
3398e693616SAnoob Joseph 	struct parse_status *status = (struct parse_status *)data;
3408e693616SAnoob Joseph 
3418e693616SAnoob Joseph 	APP_CHECK(parse_tokenize_string(
3428e693616SAnoob Joseph 		params->multi_string, tokens, &n_tokens) == 0,
3438e693616SAnoob Joseph 		status, "too many arguments\n");
3448e693616SAnoob Joseph 	if (status->status < 0)
3458e693616SAnoob Joseph 		return;
3468e693616SAnoob Joseph 
3478e693616SAnoob Joseph 	parse_flow_tokens(tokens, n_tokens, status);
3488e693616SAnoob Joseph }
3498e693616SAnoob Joseph 
3508e693616SAnoob Joseph static cmdline_parse_token_string_t cfg_flow_add_flow_str =
3518e693616SAnoob Joseph 	TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
3528e693616SAnoob Joseph 		flow_keyword, "flow");
3538e693616SAnoob Joseph 
3548e693616SAnoob Joseph static cmdline_parse_token_string_t cfg_flow_add_multi_str =
3558e693616SAnoob Joseph 	TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item, multi_string,
3568e693616SAnoob Joseph 		TOKEN_STRING_MULTI);
3578e693616SAnoob Joseph 
3588e693616SAnoob Joseph cmdline_parse_inst_t cfg_flow_add_rule = {
3598e693616SAnoob Joseph 	.f = cfg_flow_add_cfg_item_parsed,
3608e693616SAnoob Joseph 	.data = NULL,
3618e693616SAnoob Joseph 	.help_str = "",
3628e693616SAnoob Joseph 	.tokens = {
3638e693616SAnoob Joseph 		(void *) &cfg_flow_add_flow_str,
3648e693616SAnoob Joseph 		(void *) &cfg_flow_add_multi_str,
3658e693616SAnoob Joseph 		NULL,
3668e693616SAnoob Joseph 	},
3678e693616SAnoob Joseph };
3688e693616SAnoob Joseph 
3697622291bSKonstantin Ananyev /* neigh add parse */
3707622291bSKonstantin Ananyev struct cfg_neigh_add_item {
3717622291bSKonstantin Ananyev 	cmdline_fixed_string_t neigh;
3727622291bSKonstantin Ananyev 	cmdline_fixed_string_t pstr;
3737622291bSKonstantin Ananyev 	uint16_t port;
3747622291bSKonstantin Ananyev 	cmdline_fixed_string_t mac;
3757622291bSKonstantin Ananyev };
3767622291bSKonstantin Ananyev 
3777622291bSKonstantin Ananyev static void
3787622291bSKonstantin Ananyev cfg_parse_neigh(void *parsed_result, __rte_unused struct cmdline *cl,
3797622291bSKonstantin Ananyev 	void *data)
3807622291bSKonstantin Ananyev {
3817622291bSKonstantin Ananyev 	int32_t rc;
3827622291bSKonstantin Ananyev 	struct cfg_neigh_add_item *res;
3837622291bSKonstantin Ananyev 	struct parse_status *st;
3846d13ea8eSOlivier Matz 	struct rte_ether_addr mac;
3857622291bSKonstantin Ananyev 
3867622291bSKonstantin Ananyev 	st = data;
3877622291bSKonstantin Ananyev 	res = parsed_result;
3887622291bSKonstantin Ananyev 	rc = parse_mac(res->mac, &mac);
3897622291bSKonstantin Ananyev 	APP_CHECK(rc == 0, st, "invalid ether addr:%s", res->mac);
3907622291bSKonstantin Ananyev 	rc = add_dst_ethaddr(res->port, &mac);
3910dc91038SMasoumeh Farhadi Nia 	APP_CHECK(rc == 0, st, "invalid port number:%hu", res->port);
3927622291bSKonstantin Ananyev 	if (st->status < 0)
3937622291bSKonstantin Ananyev 		return;
3947622291bSKonstantin Ananyev }
3957622291bSKonstantin Ananyev 
3967622291bSKonstantin Ananyev cmdline_parse_token_string_t cfg_add_neigh_start =
3977622291bSKonstantin Ananyev 	TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, neigh, "neigh");
3987622291bSKonstantin Ananyev cmdline_parse_token_string_t cfg_add_neigh_pstr =
3997622291bSKonstantin Ananyev 	TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, pstr, "port");
4007622291bSKonstantin Ananyev cmdline_parse_token_num_t cfg_add_neigh_port =
401c2341bb6SDmitry Kozlyuk 	TOKEN_NUM_INITIALIZER(struct cfg_neigh_add_item, port, RTE_UINT16);
4027622291bSKonstantin Ananyev cmdline_parse_token_string_t cfg_add_neigh_mac =
4037622291bSKonstantin Ananyev 	TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, mac, NULL);
4047622291bSKonstantin Ananyev 
4057622291bSKonstantin Ananyev cmdline_parse_inst_t cfg_neigh_add_rule = {
4067622291bSKonstantin Ananyev 	.f = cfg_parse_neigh,
4077622291bSKonstantin Ananyev 	.data = NULL,
4087622291bSKonstantin Ananyev 	.help_str = "",
4097622291bSKonstantin Ananyev 	.tokens = {
4107622291bSKonstantin Ananyev 		(void *)&cfg_add_neigh_start,
4117622291bSKonstantin Ananyev 		(void *)&cfg_add_neigh_pstr,
4127622291bSKonstantin Ananyev 		(void *)&cfg_add_neigh_port,
4137622291bSKonstantin Ananyev 		(void *)&cfg_add_neigh_mac,
4147622291bSKonstantin Ananyev 		NULL,
4157622291bSKonstantin Ananyev 	},
4167622291bSKonstantin Ananyev };
4177622291bSKonstantin Ananyev 
4180d547ed0SFan Zhang /** set of cfg items */
4190d547ed0SFan Zhang cmdline_parse_ctx_t ipsec_ctx[] = {
4200d547ed0SFan Zhang 	(cmdline_parse_inst_t *)&cfg_sp_add_rule,
4210d547ed0SFan Zhang 	(cmdline_parse_inst_t *)&cfg_sa_add_rule,
4220d547ed0SFan Zhang 	(cmdline_parse_inst_t *)&cfg_rt_add_rule,
4238e693616SAnoob Joseph 	(cmdline_parse_inst_t *)&cfg_flow_add_rule,
4247622291bSKonstantin Ananyev 	(cmdline_parse_inst_t *)&cfg_neigh_add_rule,
4250d547ed0SFan Zhang 	NULL,
4260d547ed0SFan Zhang };
4270d547ed0SFan Zhang 
4280d547ed0SFan Zhang int
4290d547ed0SFan Zhang parse_cfg_file(const char *cfg_filename)
4300d547ed0SFan Zhang {
4310d547ed0SFan Zhang 	struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, "");
4320d547ed0SFan Zhang 	FILE *f = fopen(cfg_filename, "r");
4330d547ed0SFan Zhang 	char str[1024] = {0}, *get_s = NULL;
4340d547ed0SFan Zhang 	uint32_t line_num = 0;
4350d547ed0SFan Zhang 	struct parse_status status = {0};
4360d547ed0SFan Zhang 
4370d547ed0SFan Zhang 	if (f == NULL) {
438a1469c31SFan Zhang 		rte_panic("Error: invalid file descriptor %s\n", cfg_filename);
4390d547ed0SFan Zhang 		goto error_exit;
4400d547ed0SFan Zhang 	}
4410d547ed0SFan Zhang 
4420d547ed0SFan Zhang 	if (cl == NULL) {
4430d547ed0SFan Zhang 		rte_panic("Error: cannot create cmdline instance\n");
4440d547ed0SFan Zhang 		goto error_exit;
4450d547ed0SFan Zhang 	}
4460d547ed0SFan Zhang 
4470d547ed0SFan Zhang 	cfg_sp_add_rule.data = &status;
4480d547ed0SFan Zhang 	cfg_sa_add_rule.data = &status;
4490d547ed0SFan Zhang 	cfg_rt_add_rule.data = &status;
4508e693616SAnoob Joseph 	cfg_flow_add_rule.data = &status;
4517622291bSKonstantin Ananyev 	cfg_neigh_add_rule.data = &status;
4520d547ed0SFan Zhang 
4530d547ed0SFan Zhang 	do {
4540d547ed0SFan Zhang 		char oneline[1024];
4550d547ed0SFan Zhang 		char *pos;
456a1469c31SFan Zhang 		get_s = fgets(oneline, 1024, f);
457a1469c31SFan Zhang 
458a1469c31SFan Zhang 		if (!get_s)
459a1469c31SFan Zhang 			break;
4600d547ed0SFan Zhang 
4610d547ed0SFan Zhang 		line_num++;
4620d547ed0SFan Zhang 
4630d547ed0SFan Zhang 		if (strlen(oneline) > 1022) {
464a1469c31SFan Zhang 			rte_panic("%s:%u: error: "
465a1469c31SFan Zhang 				"the line contains more characters the parser can handle\n",
4660d547ed0SFan Zhang 				cfg_filename, line_num);
4670d547ed0SFan Zhang 			goto error_exit;
4680d547ed0SFan Zhang 		}
4690d547ed0SFan Zhang 
4700d547ed0SFan Zhang 		/* process comment char '#' */
4710d547ed0SFan Zhang 		if (oneline[0] == '#')
4720d547ed0SFan Zhang 			continue;
4730d547ed0SFan Zhang 
4740d547ed0SFan Zhang 		pos = strchr(oneline, '#');
4750d547ed0SFan Zhang 		if (pos != NULL)
4760d547ed0SFan Zhang 			*pos = '\0';
4770d547ed0SFan Zhang 
4780d547ed0SFan Zhang 		/* process line concatenator '\' */
4790d547ed0SFan Zhang 		pos = strchr(oneline, 92);
4800d547ed0SFan Zhang 		if (pos != NULL) {
4810d547ed0SFan Zhang 			if (pos != oneline+strlen(oneline) - 2) {
482a1469c31SFan Zhang 				rte_panic("%s:%u: error: "
483a1469c31SFan Zhang 					"no character should exist after '\\'\n",
4840d547ed0SFan Zhang 					cfg_filename, line_num);
4850d547ed0SFan Zhang 				goto error_exit;
4860d547ed0SFan Zhang 			}
4870d547ed0SFan Zhang 
4880d547ed0SFan Zhang 			*pos = '\0';
4890d547ed0SFan Zhang 
4900d547ed0SFan Zhang 			if (strlen(oneline) + strlen(str) > 1022) {
491a1469c31SFan Zhang 				rte_panic("%s:%u: error: "
492a1469c31SFan Zhang 					"the concatenated line contains more characters the parser can handle\n",
4930d547ed0SFan Zhang 					cfg_filename, line_num);
4940d547ed0SFan Zhang 				goto error_exit;
4950d547ed0SFan Zhang 			}
4960d547ed0SFan Zhang 
497ae943ebeSReshma Pattan 			strcpy(str + strlen(str), oneline);
4980d547ed0SFan Zhang 			continue;
4990d547ed0SFan Zhang 		}
5000d547ed0SFan Zhang 
5010d547ed0SFan Zhang 		/* copy the line to str and process */
5020d547ed0SFan Zhang 		if (strlen(oneline) + strlen(str) > 1022) {
503a1469c31SFan Zhang 			rte_panic("%s:%u: error: "
504a1469c31SFan Zhang 				"the line contains more characters the parser can handle\n",
5050d547ed0SFan Zhang 				cfg_filename, line_num);
5060d547ed0SFan Zhang 			goto error_exit;
5070d547ed0SFan Zhang 		}
508ae943ebeSReshma Pattan 		strcpy(str + strlen(str), oneline);
5090d547ed0SFan Zhang 
5100d547ed0SFan Zhang 		str[strlen(str)] = '\n';
5110d547ed0SFan Zhang 		if (cmdline_parse(cl, str) < 0) {
512a1469c31SFan Zhang 			rte_panic("%s:%u: error: parsing \"%s\" failed\n",
513a1469c31SFan Zhang 				cfg_filename, line_num, str);
5140d547ed0SFan Zhang 			goto error_exit;
5150d547ed0SFan Zhang 		}
5160d547ed0SFan Zhang 
5170d547ed0SFan Zhang 		if (status.status < 0) {
518a1469c31SFan Zhang 			rte_panic("%s:%u: error: %s", cfg_filename,
519a1469c31SFan Zhang 				line_num, status.parse_msg);
5200d547ed0SFan Zhang 			goto error_exit;
5210d547ed0SFan Zhang 		}
5220d547ed0SFan Zhang 
5230d547ed0SFan Zhang 		memset(str, 0, 1024);
524a1469c31SFan Zhang 	} while (1);
5250d547ed0SFan Zhang 
5260d547ed0SFan Zhang 	cmdline_stdin_exit(cl);
5270d547ed0SFan Zhang 	fclose(f);
5280d547ed0SFan Zhang 
529e1143d7dSVladimir Medvedkin 	sa_sort_arr();
530b0806375SVladimir Medvedkin 	sp4_sort_arr();
531b0806375SVladimir Medvedkin 	sp6_sort_arr();
532e1143d7dSVladimir Medvedkin 
5330d547ed0SFan Zhang 	return 0;
5340d547ed0SFan Zhang 
5350d547ed0SFan Zhang error_exit:
5360d547ed0SFan Zhang 	if (cl)
5370d547ed0SFan Zhang 		cmdline_stdin_exit(cl);
5380d547ed0SFan Zhang 	if (f)
5390d547ed0SFan Zhang 		fclose(f);
5400d547ed0SFan Zhang 
5410d547ed0SFan Zhang 	return -1;
5420d547ed0SFan Zhang }
543