xref: /f-stack/dpdk/examples/ipsec-secgw/parser.c (revision 2d9fd380)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2016 Intel Corporation
32bfe3f2eSlogwang  */
40c6bd470Sfengbojiang #include <arpa/inet.h>
50c6bd470Sfengbojiang #include <sys/socket.h>
60c6bd470Sfengbojiang 
72bfe3f2eSlogwang #include <rte_common.h>
82bfe3f2eSlogwang #include <rte_crypto.h>
9d30ea906Sjfb8856606 #include <rte_string_fns.h>
102bfe3f2eSlogwang 
112bfe3f2eSlogwang #include <cmdline_parse_string.h>
122bfe3f2eSlogwang #include <cmdline_parse_num.h>
132bfe3f2eSlogwang #include <cmdline_parse_ipaddr.h>
142bfe3f2eSlogwang #include <cmdline_socket.h>
152bfe3f2eSlogwang #include <cmdline.h>
162bfe3f2eSlogwang 
17*2d9fd380Sjfb8856606 #include "flow.h"
182bfe3f2eSlogwang #include "ipsec.h"
192bfe3f2eSlogwang #include "parser.h"
202bfe3f2eSlogwang 
212bfe3f2eSlogwang #define PARSE_DELIMITER		" \f\n\r\t\v"
222bfe3f2eSlogwang static int
parse_tokenize_string(char * string,char * tokens[],uint32_t * n_tokens)232bfe3f2eSlogwang parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
242bfe3f2eSlogwang {
252bfe3f2eSlogwang 	uint32_t i;
262bfe3f2eSlogwang 
272bfe3f2eSlogwang 	if ((string == NULL) ||
282bfe3f2eSlogwang 		(tokens == NULL) ||
292bfe3f2eSlogwang 		(*n_tokens < 1))
302bfe3f2eSlogwang 		return -EINVAL;
312bfe3f2eSlogwang 
322bfe3f2eSlogwang 	for (i = 0; i < *n_tokens; i++) {
332bfe3f2eSlogwang 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
342bfe3f2eSlogwang 		if (tokens[i] == NULL)
352bfe3f2eSlogwang 			break;
362bfe3f2eSlogwang 	}
372bfe3f2eSlogwang 
382bfe3f2eSlogwang 	if ((i == *n_tokens) &&
392bfe3f2eSlogwang 		(NULL != strtok_r(string, PARSE_DELIMITER, &string)))
402bfe3f2eSlogwang 		return -E2BIG;
412bfe3f2eSlogwang 
422bfe3f2eSlogwang 	*n_tokens = i;
432bfe3f2eSlogwang 	return 0;
442bfe3f2eSlogwang }
452bfe3f2eSlogwang 
462bfe3f2eSlogwang int
parse_ipv4_addr(const char * token,struct in_addr * ipv4,uint32_t * mask)472bfe3f2eSlogwang parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
482bfe3f2eSlogwang {
49d30ea906Sjfb8856606 	char ip_str[INET_ADDRSTRLEN] = {0};
502bfe3f2eSlogwang 	char *pch;
512bfe3f2eSlogwang 
522bfe3f2eSlogwang 	pch = strchr(token, '/');
532bfe3f2eSlogwang 	if (pch != NULL) {
54d30ea906Sjfb8856606 		strlcpy(ip_str, token,
55d30ea906Sjfb8856606 			RTE_MIN((unsigned int long)(pch - token + 1),
56d30ea906Sjfb8856606 			sizeof(ip_str)));
572bfe3f2eSlogwang 		pch += 1;
582bfe3f2eSlogwang 		if (is_str_num(pch) != 0)
592bfe3f2eSlogwang 			return -EINVAL;
602bfe3f2eSlogwang 		if (mask)
612bfe3f2eSlogwang 			*mask = atoi(pch);
622bfe3f2eSlogwang 	} else {
63d30ea906Sjfb8856606 		strlcpy(ip_str, token, sizeof(ip_str));
642bfe3f2eSlogwang 		if (mask)
652bfe3f2eSlogwang 			*mask = 0;
662bfe3f2eSlogwang 	}
672bfe3f2eSlogwang 	if (strlen(ip_str) >= INET_ADDRSTRLEN)
682bfe3f2eSlogwang 		return -EINVAL;
692bfe3f2eSlogwang 
700c6bd470Sfengbojiang 	if (inet_pton(AF_INET, ip_str, ipv4) != 1)
712bfe3f2eSlogwang 		return -EINVAL;
722bfe3f2eSlogwang 
732bfe3f2eSlogwang 	return 0;
742bfe3f2eSlogwang }
752bfe3f2eSlogwang 
762bfe3f2eSlogwang int
parse_ipv6_addr(const char * token,struct in6_addr * ipv6,uint32_t * mask)772bfe3f2eSlogwang parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
782bfe3f2eSlogwang {
792bfe3f2eSlogwang 	char ip_str[256] = {0};
802bfe3f2eSlogwang 	char *pch;
812bfe3f2eSlogwang 
822bfe3f2eSlogwang 	pch = strchr(token, '/');
832bfe3f2eSlogwang 	if (pch != NULL) {
84d30ea906Sjfb8856606 		strlcpy(ip_str, token,
85d30ea906Sjfb8856606 			RTE_MIN((unsigned int long)(pch - token + 1),
86d30ea906Sjfb8856606 					sizeof(ip_str)));
872bfe3f2eSlogwang 		pch += 1;
882bfe3f2eSlogwang 		if (is_str_num(pch) != 0)
892bfe3f2eSlogwang 			return -EINVAL;
902bfe3f2eSlogwang 		if (mask)
912bfe3f2eSlogwang 			*mask = atoi(pch);
922bfe3f2eSlogwang 	} else {
93d30ea906Sjfb8856606 		strlcpy(ip_str, token, sizeof(ip_str));
942bfe3f2eSlogwang 		if (mask)
952bfe3f2eSlogwang 			*mask = 0;
962bfe3f2eSlogwang 	}
972bfe3f2eSlogwang 
982bfe3f2eSlogwang 	if (strlen(ip_str) >= INET6_ADDRSTRLEN)
992bfe3f2eSlogwang 		return -EINVAL;
1002bfe3f2eSlogwang 
1010c6bd470Sfengbojiang 	if (inet_pton(AF_INET6, ip_str, ipv6) != 1)
1022bfe3f2eSlogwang 		return -EINVAL;
1032bfe3f2eSlogwang 
1042bfe3f2eSlogwang 	return 0;
1052bfe3f2eSlogwang }
1062bfe3f2eSlogwang 
1072bfe3f2eSlogwang int
parse_range(const char * token,uint16_t * low,uint16_t * high)1082bfe3f2eSlogwang parse_range(const char *token, uint16_t *low, uint16_t *high)
1092bfe3f2eSlogwang {
1102bfe3f2eSlogwang 	char ch;
1112bfe3f2eSlogwang 	char num_str[20];
1122bfe3f2eSlogwang 	uint32_t pos;
1132bfe3f2eSlogwang 	int range_low = -1;
1142bfe3f2eSlogwang 	int range_high = -1;
1152bfe3f2eSlogwang 
1162bfe3f2eSlogwang 	if (!low || !high)
1172bfe3f2eSlogwang 		return -1;
1182bfe3f2eSlogwang 
1192bfe3f2eSlogwang 	memset(num_str, 0, 20);
1202bfe3f2eSlogwang 	pos = 0;
1212bfe3f2eSlogwang 
1222bfe3f2eSlogwang 	while ((ch = *token++) != '\0') {
1232bfe3f2eSlogwang 		if (isdigit(ch)) {
1242bfe3f2eSlogwang 			if (pos >= 19)
1252bfe3f2eSlogwang 				return -1;
1262bfe3f2eSlogwang 			num_str[pos++] = ch;
1272bfe3f2eSlogwang 		} else if (ch == ':') {
1282bfe3f2eSlogwang 			if (range_low != -1)
1292bfe3f2eSlogwang 				return -1;
1302bfe3f2eSlogwang 			range_low = atoi(num_str);
1312bfe3f2eSlogwang 			memset(num_str, 0, 20);
1322bfe3f2eSlogwang 			pos = 0;
1332bfe3f2eSlogwang 		}
1342bfe3f2eSlogwang 	}
1352bfe3f2eSlogwang 
1362bfe3f2eSlogwang 	if (strlen(num_str) == 0)
1372bfe3f2eSlogwang 		return -1;
1382bfe3f2eSlogwang 
1392bfe3f2eSlogwang 	range_high = atoi(num_str);
1402bfe3f2eSlogwang 
1412bfe3f2eSlogwang 	*low = (uint16_t)range_low;
1422bfe3f2eSlogwang 	*high = (uint16_t)range_high;
1432bfe3f2eSlogwang 
1442bfe3f2eSlogwang 	return 0;
1452bfe3f2eSlogwang }
1462bfe3f2eSlogwang 
1474418919fSjohnjiang /*
1484418919fSjohnjiang  * helper function for parse_mac, parse one section of the ether addr.
1494418919fSjohnjiang  */
1504418919fSjohnjiang static const char *
parse_uint8x16(const char * s,uint8_t * v,uint8_t ls)1514418919fSjohnjiang parse_uint8x16(const char *s, uint8_t *v, uint8_t ls)
1524418919fSjohnjiang {
1534418919fSjohnjiang 	char *end;
1544418919fSjohnjiang 	unsigned long t;
1554418919fSjohnjiang 
1564418919fSjohnjiang 	errno = 0;
1574418919fSjohnjiang 	t = strtoul(s, &end, 16);
1584418919fSjohnjiang 	if (errno != 0 || end[0] != ls || t > UINT8_MAX)
1594418919fSjohnjiang 		return NULL;
1604418919fSjohnjiang 	v[0] = t;
1614418919fSjohnjiang 	return end + 1;
1624418919fSjohnjiang }
1634418919fSjohnjiang 
1644418919fSjohnjiang static int
parse_mac(const char * str,struct rte_ether_addr * addr)1654418919fSjohnjiang parse_mac(const char *str, struct rte_ether_addr *addr)
1664418919fSjohnjiang {
1674418919fSjohnjiang 	uint32_t i;
1684418919fSjohnjiang 
1694418919fSjohnjiang 	static const uint8_t stop_sym[RTE_DIM(addr->addr_bytes)] = {
1704418919fSjohnjiang 		[0] = ':',
1714418919fSjohnjiang 		[1] = ':',
1724418919fSjohnjiang 		[2] = ':',
1734418919fSjohnjiang 		[3] = ':',
1744418919fSjohnjiang 		[4] = ':',
1754418919fSjohnjiang 		[5] = 0,
1764418919fSjohnjiang 	};
1774418919fSjohnjiang 
1784418919fSjohnjiang 	for (i = 0; i != RTE_DIM(addr->addr_bytes); i++) {
1794418919fSjohnjiang 		str = parse_uint8x16(str, addr->addr_bytes + i, stop_sym[i]);
1804418919fSjohnjiang 		if (str == NULL)
1814418919fSjohnjiang 			return -EINVAL;
1824418919fSjohnjiang 	}
1834418919fSjohnjiang 
1844418919fSjohnjiang 	return 0;
1854418919fSjohnjiang }
1864418919fSjohnjiang 
1872bfe3f2eSlogwang /** sp add parse */
1882bfe3f2eSlogwang struct cfg_sp_add_cfg_item {
1892bfe3f2eSlogwang 	cmdline_fixed_string_t sp_keyword;
1902bfe3f2eSlogwang 	cmdline_multi_string_t multi_string;
1912bfe3f2eSlogwang };
1922bfe3f2eSlogwang 
1932bfe3f2eSlogwang static void
cfg_sp_add_cfg_item_parsed(void * parsed_result,__rte_unused struct cmdline * cl,void * data)1942bfe3f2eSlogwang cfg_sp_add_cfg_item_parsed(void *parsed_result,
1952bfe3f2eSlogwang 	__rte_unused struct cmdline *cl, void *data)
1962bfe3f2eSlogwang {
1972bfe3f2eSlogwang 	struct cfg_sp_add_cfg_item *params = parsed_result;
1982bfe3f2eSlogwang 	char *tokens[32];
1992bfe3f2eSlogwang 	uint32_t n_tokens = RTE_DIM(tokens);
2002bfe3f2eSlogwang 	struct parse_status *status = (struct parse_status *)data;
2012bfe3f2eSlogwang 
2022bfe3f2eSlogwang 	APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
2032bfe3f2eSlogwang 		&n_tokens) == 0), status, "too many arguments");
2042bfe3f2eSlogwang 
2052bfe3f2eSlogwang 	if (status->status < 0)
2062bfe3f2eSlogwang 		return;
2072bfe3f2eSlogwang 
2082bfe3f2eSlogwang 	if (strcmp(tokens[0], "ipv4") == 0) {
2092bfe3f2eSlogwang 		parse_sp4_tokens(tokens, n_tokens, status);
2102bfe3f2eSlogwang 		if (status->status < 0)
2112bfe3f2eSlogwang 			return;
2122bfe3f2eSlogwang 	} else if (strcmp(tokens[0], "ipv6") == 0) {
2132bfe3f2eSlogwang 		parse_sp6_tokens(tokens, n_tokens, status);
2142bfe3f2eSlogwang 		if (status->status < 0)
2152bfe3f2eSlogwang 			return;
2162bfe3f2eSlogwang 	} else {
2172bfe3f2eSlogwang 		APP_CHECK(0, status, "unrecognizable input %s\n",
2182bfe3f2eSlogwang 			tokens[0]);
2192bfe3f2eSlogwang 		return;
2202bfe3f2eSlogwang 	}
2212bfe3f2eSlogwang }
2222bfe3f2eSlogwang 
2232bfe3f2eSlogwang static cmdline_parse_token_string_t cfg_sp_add_sp_str =
2242bfe3f2eSlogwang 	TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
2252bfe3f2eSlogwang 		sp_keyword, "sp");
2262bfe3f2eSlogwang 
2272bfe3f2eSlogwang static cmdline_parse_token_string_t cfg_sp_add_multi_str =
2282bfe3f2eSlogwang 	TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
2292bfe3f2eSlogwang 		TOKEN_STRING_MULTI);
2302bfe3f2eSlogwang 
2312bfe3f2eSlogwang cmdline_parse_inst_t cfg_sp_add_rule = {
2322bfe3f2eSlogwang 	.f = cfg_sp_add_cfg_item_parsed,
2332bfe3f2eSlogwang 	.data = NULL,
2342bfe3f2eSlogwang 	.help_str = "",
2352bfe3f2eSlogwang 	.tokens = {
2362bfe3f2eSlogwang 		(void *) &cfg_sp_add_sp_str,
2372bfe3f2eSlogwang 		(void *) &cfg_sp_add_multi_str,
2382bfe3f2eSlogwang 		NULL,
2392bfe3f2eSlogwang 	},
2402bfe3f2eSlogwang };
2412bfe3f2eSlogwang 
2422bfe3f2eSlogwang /* sa add parse */
2432bfe3f2eSlogwang struct cfg_sa_add_cfg_item {
2442bfe3f2eSlogwang 	cmdline_fixed_string_t sa_keyword;
2452bfe3f2eSlogwang 	cmdline_multi_string_t multi_string;
2462bfe3f2eSlogwang };
2472bfe3f2eSlogwang 
2482bfe3f2eSlogwang static void
cfg_sa_add_cfg_item_parsed(void * parsed_result,__rte_unused struct cmdline * cl,void * data)2492bfe3f2eSlogwang cfg_sa_add_cfg_item_parsed(void *parsed_result,
2502bfe3f2eSlogwang 	__rte_unused struct cmdline *cl, void *data)
2512bfe3f2eSlogwang {
2522bfe3f2eSlogwang 	struct cfg_sa_add_cfg_item *params = parsed_result;
2532bfe3f2eSlogwang 	char *tokens[32];
2542bfe3f2eSlogwang 	uint32_t n_tokens = RTE_DIM(tokens);
2552bfe3f2eSlogwang 	struct parse_status *status = (struct parse_status *)data;
2562bfe3f2eSlogwang 
2572bfe3f2eSlogwang 	APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
2582bfe3f2eSlogwang 		&n_tokens) == 0, status, "too many arguments\n");
2592bfe3f2eSlogwang 
2602bfe3f2eSlogwang 	parse_sa_tokens(tokens, n_tokens, status);
2612bfe3f2eSlogwang }
2622bfe3f2eSlogwang 
2632bfe3f2eSlogwang static cmdline_parse_token_string_t cfg_sa_add_sa_str =
2642bfe3f2eSlogwang 	TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
2652bfe3f2eSlogwang 		sa_keyword, "sa");
2662bfe3f2eSlogwang 
2672bfe3f2eSlogwang static cmdline_parse_token_string_t cfg_sa_add_multi_str =
2682bfe3f2eSlogwang 	TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
2692bfe3f2eSlogwang 		TOKEN_STRING_MULTI);
2702bfe3f2eSlogwang 
2712bfe3f2eSlogwang cmdline_parse_inst_t cfg_sa_add_rule = {
2722bfe3f2eSlogwang 	.f = cfg_sa_add_cfg_item_parsed,
2732bfe3f2eSlogwang 	.data = NULL,
2742bfe3f2eSlogwang 	.help_str = "",
2752bfe3f2eSlogwang 	.tokens = {
2762bfe3f2eSlogwang 		(void *) &cfg_sa_add_sa_str,
2772bfe3f2eSlogwang 		(void *) &cfg_sa_add_multi_str,
2782bfe3f2eSlogwang 		NULL,
2792bfe3f2eSlogwang 	},
2802bfe3f2eSlogwang };
2812bfe3f2eSlogwang 
2822bfe3f2eSlogwang /* rt add parse */
2832bfe3f2eSlogwang struct cfg_rt_add_cfg_item {
2842bfe3f2eSlogwang 	cmdline_fixed_string_t rt_keyword;
2852bfe3f2eSlogwang 	cmdline_multi_string_t multi_string;
2862bfe3f2eSlogwang };
2872bfe3f2eSlogwang 
2882bfe3f2eSlogwang static void
cfg_rt_add_cfg_item_parsed(void * parsed_result,__rte_unused struct cmdline * cl,void * data)2892bfe3f2eSlogwang cfg_rt_add_cfg_item_parsed(void *parsed_result,
2902bfe3f2eSlogwang 	__rte_unused struct cmdline *cl, void *data)
2912bfe3f2eSlogwang {
2922bfe3f2eSlogwang 	struct cfg_rt_add_cfg_item *params = parsed_result;
2932bfe3f2eSlogwang 	char *tokens[32];
2942bfe3f2eSlogwang 	uint32_t n_tokens = RTE_DIM(tokens);
2952bfe3f2eSlogwang 	struct parse_status *status = (struct parse_status *)data;
2962bfe3f2eSlogwang 
2972bfe3f2eSlogwang 	APP_CHECK(parse_tokenize_string(
2982bfe3f2eSlogwang 		params->multi_string, tokens, &n_tokens) == 0,
2992bfe3f2eSlogwang 		status, "too many arguments\n");
3002bfe3f2eSlogwang 	if (status->status < 0)
3012bfe3f2eSlogwang 		return;
3022bfe3f2eSlogwang 
3032bfe3f2eSlogwang 	parse_rt_tokens(tokens, n_tokens, status);
3042bfe3f2eSlogwang }
3052bfe3f2eSlogwang 
3062bfe3f2eSlogwang static cmdline_parse_token_string_t cfg_rt_add_rt_str =
3072bfe3f2eSlogwang 	TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
3082bfe3f2eSlogwang 		rt_keyword, "rt");
3092bfe3f2eSlogwang 
3102bfe3f2eSlogwang static cmdline_parse_token_string_t cfg_rt_add_multi_str =
3112bfe3f2eSlogwang 	TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
3122bfe3f2eSlogwang 		TOKEN_STRING_MULTI);
3132bfe3f2eSlogwang 
3142bfe3f2eSlogwang cmdline_parse_inst_t cfg_rt_add_rule = {
3152bfe3f2eSlogwang 	.f = cfg_rt_add_cfg_item_parsed,
3162bfe3f2eSlogwang 	.data = NULL,
3172bfe3f2eSlogwang 	.help_str = "",
3182bfe3f2eSlogwang 	.tokens = {
3192bfe3f2eSlogwang 		(void *) &cfg_rt_add_rt_str,
3202bfe3f2eSlogwang 		(void *) &cfg_rt_add_multi_str,
3212bfe3f2eSlogwang 		NULL,
3222bfe3f2eSlogwang 	},
3232bfe3f2eSlogwang };
3242bfe3f2eSlogwang 
325*2d9fd380Sjfb8856606 /* flow add parse */
326*2d9fd380Sjfb8856606 struct cfg_flow_add_cfg_item {
327*2d9fd380Sjfb8856606 	cmdline_fixed_string_t flow_keyword;
328*2d9fd380Sjfb8856606 	cmdline_multi_string_t multi_string;
329*2d9fd380Sjfb8856606 };
330*2d9fd380Sjfb8856606 
331*2d9fd380Sjfb8856606 static void
cfg_flow_add_cfg_item_parsed(void * parsed_result,__rte_unused struct cmdline * cl,void * data)332*2d9fd380Sjfb8856606 cfg_flow_add_cfg_item_parsed(void *parsed_result,
333*2d9fd380Sjfb8856606 	__rte_unused struct cmdline *cl, void *data)
334*2d9fd380Sjfb8856606 {
335*2d9fd380Sjfb8856606 	struct cfg_flow_add_cfg_item *params = parsed_result;
336*2d9fd380Sjfb8856606 	char *tokens[32];
337*2d9fd380Sjfb8856606 	uint32_t n_tokens = RTE_DIM(tokens);
338*2d9fd380Sjfb8856606 	struct parse_status *status = (struct parse_status *)data;
339*2d9fd380Sjfb8856606 
340*2d9fd380Sjfb8856606 	APP_CHECK(parse_tokenize_string(
341*2d9fd380Sjfb8856606 		params->multi_string, tokens, &n_tokens) == 0,
342*2d9fd380Sjfb8856606 		status, "too many arguments\n");
343*2d9fd380Sjfb8856606 	if (status->status < 0)
344*2d9fd380Sjfb8856606 		return;
345*2d9fd380Sjfb8856606 
346*2d9fd380Sjfb8856606 	parse_flow_tokens(tokens, n_tokens, status);
347*2d9fd380Sjfb8856606 }
348*2d9fd380Sjfb8856606 
349*2d9fd380Sjfb8856606 static cmdline_parse_token_string_t cfg_flow_add_flow_str =
350*2d9fd380Sjfb8856606 	TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
351*2d9fd380Sjfb8856606 		flow_keyword, "flow");
352*2d9fd380Sjfb8856606 
353*2d9fd380Sjfb8856606 static cmdline_parse_token_string_t cfg_flow_add_multi_str =
354*2d9fd380Sjfb8856606 	TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item, multi_string,
355*2d9fd380Sjfb8856606 		TOKEN_STRING_MULTI);
356*2d9fd380Sjfb8856606 
357*2d9fd380Sjfb8856606 cmdline_parse_inst_t cfg_flow_add_rule = {
358*2d9fd380Sjfb8856606 	.f = cfg_flow_add_cfg_item_parsed,
359*2d9fd380Sjfb8856606 	.data = NULL,
360*2d9fd380Sjfb8856606 	.help_str = "",
361*2d9fd380Sjfb8856606 	.tokens = {
362*2d9fd380Sjfb8856606 		(void *) &cfg_flow_add_flow_str,
363*2d9fd380Sjfb8856606 		(void *) &cfg_flow_add_multi_str,
364*2d9fd380Sjfb8856606 		NULL,
365*2d9fd380Sjfb8856606 	},
366*2d9fd380Sjfb8856606 };
367*2d9fd380Sjfb8856606 
3684418919fSjohnjiang /* neigh add parse */
3694418919fSjohnjiang struct cfg_neigh_add_item {
3704418919fSjohnjiang 	cmdline_fixed_string_t neigh;
3714418919fSjohnjiang 	cmdline_fixed_string_t pstr;
3724418919fSjohnjiang 	uint16_t port;
3734418919fSjohnjiang 	cmdline_fixed_string_t mac;
3744418919fSjohnjiang };
3754418919fSjohnjiang 
3764418919fSjohnjiang static void
cfg_parse_neigh(void * parsed_result,__rte_unused struct cmdline * cl,void * data)3774418919fSjohnjiang cfg_parse_neigh(void *parsed_result, __rte_unused struct cmdline *cl,
3784418919fSjohnjiang 	void *data)
3794418919fSjohnjiang {
3804418919fSjohnjiang 	int32_t rc;
3814418919fSjohnjiang 	struct cfg_neigh_add_item *res;
3824418919fSjohnjiang 	struct parse_status *st;
3834418919fSjohnjiang 	struct rte_ether_addr mac;
3844418919fSjohnjiang 
3854418919fSjohnjiang 	st = data;
3864418919fSjohnjiang 	res = parsed_result;
3874418919fSjohnjiang 	rc = parse_mac(res->mac, &mac);
3884418919fSjohnjiang 	APP_CHECK(rc == 0, st, "invalid ether addr:%s", res->mac);
3894418919fSjohnjiang 	rc = add_dst_ethaddr(res->port, &mac);
3904418919fSjohnjiang 	APP_CHECK(rc == 0, st, "invalid port numer:%hu", res->port);
3914418919fSjohnjiang 	if (st->status < 0)
3924418919fSjohnjiang 		return;
3934418919fSjohnjiang }
3944418919fSjohnjiang 
3954418919fSjohnjiang cmdline_parse_token_string_t cfg_add_neigh_start =
3964418919fSjohnjiang 	TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, neigh, "neigh");
3974418919fSjohnjiang cmdline_parse_token_string_t cfg_add_neigh_pstr =
3984418919fSjohnjiang 	TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, pstr, "port");
3994418919fSjohnjiang cmdline_parse_token_num_t cfg_add_neigh_port =
400*2d9fd380Sjfb8856606 	TOKEN_NUM_INITIALIZER(struct cfg_neigh_add_item, port, RTE_UINT16);
4014418919fSjohnjiang cmdline_parse_token_string_t cfg_add_neigh_mac =
4024418919fSjohnjiang 	TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, mac, NULL);
4034418919fSjohnjiang 
4044418919fSjohnjiang cmdline_parse_inst_t cfg_neigh_add_rule = {
4054418919fSjohnjiang 	.f = cfg_parse_neigh,
4064418919fSjohnjiang 	.data = NULL,
4074418919fSjohnjiang 	.help_str = "",
4084418919fSjohnjiang 	.tokens = {
4094418919fSjohnjiang 		(void *)&cfg_add_neigh_start,
4104418919fSjohnjiang 		(void *)&cfg_add_neigh_pstr,
4114418919fSjohnjiang 		(void *)&cfg_add_neigh_port,
4124418919fSjohnjiang 		(void *)&cfg_add_neigh_mac,
4134418919fSjohnjiang 		NULL,
4144418919fSjohnjiang 	},
4154418919fSjohnjiang };
4164418919fSjohnjiang 
4172bfe3f2eSlogwang /** set of cfg items */
4182bfe3f2eSlogwang cmdline_parse_ctx_t ipsec_ctx[] = {
4192bfe3f2eSlogwang 	(cmdline_parse_inst_t *)&cfg_sp_add_rule,
4202bfe3f2eSlogwang 	(cmdline_parse_inst_t *)&cfg_sa_add_rule,
4212bfe3f2eSlogwang 	(cmdline_parse_inst_t *)&cfg_rt_add_rule,
422*2d9fd380Sjfb8856606 	(cmdline_parse_inst_t *)&cfg_flow_add_rule,
4234418919fSjohnjiang 	(cmdline_parse_inst_t *)&cfg_neigh_add_rule,
4242bfe3f2eSlogwang 	NULL,
4252bfe3f2eSlogwang };
4262bfe3f2eSlogwang 
4272bfe3f2eSlogwang int
parse_cfg_file(const char * cfg_filename)4282bfe3f2eSlogwang parse_cfg_file(const char *cfg_filename)
4292bfe3f2eSlogwang {
4302bfe3f2eSlogwang 	struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, "");
4312bfe3f2eSlogwang 	FILE *f = fopen(cfg_filename, "r");
4322bfe3f2eSlogwang 	char str[1024] = {0}, *get_s = NULL;
4332bfe3f2eSlogwang 	uint32_t line_num = 0;
4342bfe3f2eSlogwang 	struct parse_status status = {0};
4352bfe3f2eSlogwang 
4362bfe3f2eSlogwang 	if (f == NULL) {
4372bfe3f2eSlogwang 		rte_panic("Error: invalid file descriptor %s\n", cfg_filename);
4382bfe3f2eSlogwang 		goto error_exit;
4392bfe3f2eSlogwang 	}
4402bfe3f2eSlogwang 
4412bfe3f2eSlogwang 	if (cl == NULL) {
4422bfe3f2eSlogwang 		rte_panic("Error: cannot create cmdline instance\n");
4432bfe3f2eSlogwang 		goto error_exit;
4442bfe3f2eSlogwang 	}
4452bfe3f2eSlogwang 
4462bfe3f2eSlogwang 	cfg_sp_add_rule.data = &status;
4472bfe3f2eSlogwang 	cfg_sa_add_rule.data = &status;
4482bfe3f2eSlogwang 	cfg_rt_add_rule.data = &status;
449*2d9fd380Sjfb8856606 	cfg_flow_add_rule.data = &status;
4504418919fSjohnjiang 	cfg_neigh_add_rule.data = &status;
4512bfe3f2eSlogwang 
4522bfe3f2eSlogwang 	do {
4532bfe3f2eSlogwang 		char oneline[1024];
4542bfe3f2eSlogwang 		char *pos;
4552bfe3f2eSlogwang 		get_s = fgets(oneline, 1024, f);
4562bfe3f2eSlogwang 
4572bfe3f2eSlogwang 		if (!get_s)
4582bfe3f2eSlogwang 			break;
4592bfe3f2eSlogwang 
4602bfe3f2eSlogwang 		line_num++;
4612bfe3f2eSlogwang 
4622bfe3f2eSlogwang 		if (strlen(oneline) > 1022) {
4632bfe3f2eSlogwang 			rte_panic("%s:%u: error: "
4642bfe3f2eSlogwang 				"the line contains more characters the parser can handle\n",
4652bfe3f2eSlogwang 				cfg_filename, line_num);
4662bfe3f2eSlogwang 			goto error_exit;
4672bfe3f2eSlogwang 		}
4682bfe3f2eSlogwang 
4692bfe3f2eSlogwang 		/* process comment char '#' */
4702bfe3f2eSlogwang 		if (oneline[0] == '#')
4712bfe3f2eSlogwang 			continue;
4722bfe3f2eSlogwang 
4732bfe3f2eSlogwang 		pos = strchr(oneline, '#');
4742bfe3f2eSlogwang 		if (pos != NULL)
4752bfe3f2eSlogwang 			*pos = '\0';
4762bfe3f2eSlogwang 
4772bfe3f2eSlogwang 		/* process line concatenator '\' */
4782bfe3f2eSlogwang 		pos = strchr(oneline, 92);
4792bfe3f2eSlogwang 		if (pos != NULL) {
4802bfe3f2eSlogwang 			if (pos != oneline+strlen(oneline) - 2) {
4812bfe3f2eSlogwang 				rte_panic("%s:%u: error: "
4822bfe3f2eSlogwang 					"no character should exist after '\\'\n",
4832bfe3f2eSlogwang 					cfg_filename, line_num);
4842bfe3f2eSlogwang 				goto error_exit;
4852bfe3f2eSlogwang 			}
4862bfe3f2eSlogwang 
4872bfe3f2eSlogwang 			*pos = '\0';
4882bfe3f2eSlogwang 
4892bfe3f2eSlogwang 			if (strlen(oneline) + strlen(str) > 1022) {
4902bfe3f2eSlogwang 				rte_panic("%s:%u: error: "
4912bfe3f2eSlogwang 					"the concatenated line contains more characters the parser can handle\n",
4922bfe3f2eSlogwang 					cfg_filename, line_num);
4932bfe3f2eSlogwang 				goto error_exit;
4942bfe3f2eSlogwang 			}
4952bfe3f2eSlogwang 
496d30ea906Sjfb8856606 			strcpy(str + strlen(str), oneline);
4972bfe3f2eSlogwang 			continue;
4982bfe3f2eSlogwang 		}
4992bfe3f2eSlogwang 
5002bfe3f2eSlogwang 		/* copy the line to str and process */
5012bfe3f2eSlogwang 		if (strlen(oneline) + strlen(str) > 1022) {
5022bfe3f2eSlogwang 			rte_panic("%s:%u: error: "
5032bfe3f2eSlogwang 				"the line contains more characters the parser can handle\n",
5042bfe3f2eSlogwang 				cfg_filename, line_num);
5052bfe3f2eSlogwang 			goto error_exit;
5062bfe3f2eSlogwang 		}
507d30ea906Sjfb8856606 		strcpy(str + strlen(str), oneline);
5082bfe3f2eSlogwang 
5092bfe3f2eSlogwang 		str[strlen(str)] = '\n';
5102bfe3f2eSlogwang 		if (cmdline_parse(cl, str) < 0) {
5112bfe3f2eSlogwang 			rte_panic("%s:%u: error: parsing \"%s\" failed\n",
5122bfe3f2eSlogwang 				cfg_filename, line_num, str);
5132bfe3f2eSlogwang 			goto error_exit;
5142bfe3f2eSlogwang 		}
5152bfe3f2eSlogwang 
5162bfe3f2eSlogwang 		if (status.status < 0) {
5172bfe3f2eSlogwang 			rte_panic("%s:%u: error: %s", cfg_filename,
5182bfe3f2eSlogwang 				line_num, status.parse_msg);
5192bfe3f2eSlogwang 			goto error_exit;
5202bfe3f2eSlogwang 		}
5212bfe3f2eSlogwang 
5222bfe3f2eSlogwang 		memset(str, 0, 1024);
5232bfe3f2eSlogwang 	} while (1);
5242bfe3f2eSlogwang 
5252bfe3f2eSlogwang 	cmdline_stdin_exit(cl);
5262bfe3f2eSlogwang 	fclose(f);
5272bfe3f2eSlogwang 
528*2d9fd380Sjfb8856606 	sa_sort_arr();
529*2d9fd380Sjfb8856606 	sp4_sort_arr();
530*2d9fd380Sjfb8856606 	sp6_sort_arr();
531*2d9fd380Sjfb8856606 
5322bfe3f2eSlogwang 	return 0;
5332bfe3f2eSlogwang 
5342bfe3f2eSlogwang error_exit:
5352bfe3f2eSlogwang 	if (cl)
5362bfe3f2eSlogwang 		cmdline_stdin_exit(cl);
5372bfe3f2eSlogwang 	if (f)
5382bfe3f2eSlogwang 		fclose(f);
5392bfe3f2eSlogwang 
5402bfe3f2eSlogwang 	return -1;
5412bfe3f2eSlogwang }
542