xref: /dpdk/examples/ipsec-secgw/parser.c (revision 07b156199fa2d5de7e40b865c90fa4b6d99e09d0)
10d547ed0SFan Zhang /*-
20d547ed0SFan Zhang  *   BSD LICENSE
30d547ed0SFan Zhang  *
40d547ed0SFan Zhang  *   Copyright(c) 2016 Intel Corporation. All rights reserved.
50d547ed0SFan Zhang  *   All rights reserved.
60d547ed0SFan Zhang  *
70d547ed0SFan Zhang  *   Redistribution and use in source and binary forms, with or without
80d547ed0SFan Zhang  *   modification, are permitted provided that the following conditions
90d547ed0SFan Zhang  *   are met:
100d547ed0SFan Zhang  *
110d547ed0SFan Zhang  *     * Redistributions of source code must retain the above copyright
120d547ed0SFan Zhang  *       notice, this list of conditions and the following disclaimer.
130d547ed0SFan Zhang  *     * Redistributions in binary form must reproduce the above copyright
140d547ed0SFan Zhang  *       notice, this list of conditions and the following disclaimer in
150d547ed0SFan Zhang  *       the documentation and/or other materials provided with the
160d547ed0SFan Zhang  *       distribution.
170d547ed0SFan Zhang  *     * Neither the name of Intel Corporation nor the names of its
180d547ed0SFan Zhang  *       contributors may be used to endorse or promote products derived
190d547ed0SFan Zhang  *       from this software without specific prior written permission.
200d547ed0SFan Zhang  *
210d547ed0SFan Zhang  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
220d547ed0SFan Zhang  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
230d547ed0SFan Zhang  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
240d547ed0SFan Zhang  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
250d547ed0SFan Zhang  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
260d547ed0SFan Zhang  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
270d547ed0SFan Zhang  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
280d547ed0SFan Zhang  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
290d547ed0SFan Zhang  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
300d547ed0SFan Zhang  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
310d547ed0SFan Zhang  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
320d547ed0SFan Zhang  */
330d547ed0SFan Zhang #include <rte_common.h>
340d547ed0SFan Zhang #include <rte_crypto.h>
350d547ed0SFan Zhang 
360d547ed0SFan Zhang #include <cmdline_parse_string.h>
370d547ed0SFan Zhang #include <cmdline_parse_num.h>
380d547ed0SFan Zhang #include <cmdline_parse_ipaddr.h>
390d547ed0SFan Zhang #include <cmdline_socket.h>
400d547ed0SFan Zhang #include <cmdline.h>
410d547ed0SFan Zhang 
420d547ed0SFan Zhang #include "ipsec.h"
430d547ed0SFan Zhang #include "parser.h"
440d547ed0SFan Zhang 
450d547ed0SFan Zhang #define PARSE_DELIMITER		" \f\n\r\t\v"
460d547ed0SFan Zhang static int
470d547ed0SFan Zhang parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
480d547ed0SFan Zhang {
490d547ed0SFan Zhang 	uint32_t i;
500d547ed0SFan Zhang 
510d547ed0SFan Zhang 	if ((string == NULL) ||
520d547ed0SFan Zhang 		(tokens == NULL) ||
530d547ed0SFan Zhang 		(*n_tokens < 1))
540d547ed0SFan Zhang 		return -EINVAL;
550d547ed0SFan Zhang 
560d547ed0SFan Zhang 	for (i = 0; i < *n_tokens; i++) {
570d547ed0SFan Zhang 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
580d547ed0SFan Zhang 		if (tokens[i] == NULL)
590d547ed0SFan Zhang 			break;
600d547ed0SFan Zhang 	}
610d547ed0SFan Zhang 
620d547ed0SFan Zhang 	if ((i == *n_tokens) &&
630d547ed0SFan Zhang 		(NULL != strtok_r(string, PARSE_DELIMITER, &string)))
640d547ed0SFan Zhang 		return -E2BIG;
650d547ed0SFan Zhang 
660d547ed0SFan Zhang 	*n_tokens = i;
670d547ed0SFan Zhang 	return 0;
680d547ed0SFan Zhang }
690d547ed0SFan Zhang 
700d547ed0SFan Zhang #define INADDRSZ 4
710d547ed0SFan Zhang #define IN6ADDRSZ 16
720d547ed0SFan Zhang 
730d547ed0SFan Zhang /* int
740d547ed0SFan Zhang  * inet_pton4(src, dst)
750d547ed0SFan Zhang  *      like inet_aton() but without all the hexadecimal and shorthand.
760d547ed0SFan Zhang  * return:
770d547ed0SFan Zhang  *      1 if `src' is a valid dotted quad, else 0.
780d547ed0SFan Zhang  * notice:
790d547ed0SFan Zhang  *      does not touch `dst' unless it's returning 1.
800d547ed0SFan Zhang  * author:
810d547ed0SFan Zhang  *      Paul Vixie, 1996.
820d547ed0SFan Zhang  */
830d547ed0SFan Zhang static int
840d547ed0SFan Zhang inet_pton4(const char *src, unsigned char *dst)
850d547ed0SFan Zhang {
860d547ed0SFan Zhang 	static const char digits[] = "0123456789";
870d547ed0SFan Zhang 	int saw_digit, octets, ch;
880d547ed0SFan Zhang 	unsigned char tmp[INADDRSZ], *tp;
890d547ed0SFan Zhang 
900d547ed0SFan Zhang 	saw_digit = 0;
910d547ed0SFan Zhang 	octets = 0;
920d547ed0SFan Zhang 	*(tp = tmp) = 0;
930d547ed0SFan Zhang 	while ((ch = *src++) != '\0') {
940d547ed0SFan Zhang 		const char *pch;
950d547ed0SFan Zhang 
960d547ed0SFan Zhang 		pch = strchr(digits, ch);
970d547ed0SFan Zhang 		if (pch != NULL) {
980d547ed0SFan Zhang 			unsigned int new = *tp * 10 + (pch - digits);
990d547ed0SFan Zhang 
1000d547ed0SFan Zhang 			if (new > 255)
1010d547ed0SFan Zhang 				return 0;
1020d547ed0SFan Zhang 			if (!saw_digit) {
1030d547ed0SFan Zhang 				if (++octets > 4)
1040d547ed0SFan Zhang 					return 0;
1050d547ed0SFan Zhang 				saw_digit = 1;
1060d547ed0SFan Zhang 			}
1070d547ed0SFan Zhang 			*tp = (unsigned char)new;
1080d547ed0SFan Zhang 		} else if (ch == '.' && saw_digit) {
1090d547ed0SFan Zhang 			if (octets == 4)
1100d547ed0SFan Zhang 				return 0;
1110d547ed0SFan Zhang 			*++tp = 0;
1120d547ed0SFan Zhang 			saw_digit = 0;
1130d547ed0SFan Zhang 		} else
1140d547ed0SFan Zhang 			return 0;
1150d547ed0SFan Zhang 	}
1160d547ed0SFan Zhang 	if (octets < 4)
1170d547ed0SFan Zhang 		return 0;
1180d547ed0SFan Zhang 
1190d547ed0SFan Zhang 	memcpy(dst, tmp, INADDRSZ);
1200d547ed0SFan Zhang 	return 1;
1210d547ed0SFan Zhang }
1220d547ed0SFan Zhang 
1230d547ed0SFan Zhang /* int
1240d547ed0SFan Zhang  * inet_pton6(src, dst)
1250d547ed0SFan Zhang  *      convert presentation level address to network order binary form.
1260d547ed0SFan Zhang  * return:
1270d547ed0SFan Zhang  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
1280d547ed0SFan Zhang  * notice:
1290d547ed0SFan Zhang  *      (1) does not touch `dst' unless it's returning 1.
1300d547ed0SFan Zhang  *      (2) :: in a full address is silently ignored.
1310d547ed0SFan Zhang  * credit:
1320d547ed0SFan Zhang  *      inspired by Mark Andrews.
1330d547ed0SFan Zhang  * author:
1340d547ed0SFan Zhang  *      Paul Vixie, 1996.
1350d547ed0SFan Zhang  */
1360d547ed0SFan Zhang static int
1370d547ed0SFan Zhang inet_pton6(const char *src, unsigned char *dst)
1380d547ed0SFan Zhang {
1390d547ed0SFan Zhang 	static const char xdigits_l[] = "0123456789abcdef",
1400d547ed0SFan Zhang 		xdigits_u[] = "0123456789ABCDEF";
1410d547ed0SFan Zhang 	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
1420d547ed0SFan Zhang 	const char *xdigits = 0, *curtok = 0;
1430d547ed0SFan Zhang 	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
1440d547ed0SFan Zhang 	unsigned int val = 0;
1450d547ed0SFan Zhang 	unsigned dbloct_count = 0;
1460d547ed0SFan Zhang 
1470d547ed0SFan Zhang 	memset((tp = tmp), '\0', IN6ADDRSZ);
1480d547ed0SFan Zhang 	endp = tp + IN6ADDRSZ;
1490d547ed0SFan Zhang 	colonp = NULL;
1500d547ed0SFan Zhang 	/* Leading :: requires some special handling. */
1510d547ed0SFan Zhang 	if (*src == ':')
1520d547ed0SFan Zhang 		if (*++src != ':')
1530d547ed0SFan Zhang 			return 0;
1540d547ed0SFan Zhang 	curtok = src;
1550d547ed0SFan Zhang 	saw_xdigit = count_xdigit = 0;
1560d547ed0SFan Zhang 	val = 0;
1570d547ed0SFan Zhang 
1580d547ed0SFan Zhang 	while ((ch = *src++) != '\0') {
1590d547ed0SFan Zhang 		const char *pch;
1600d547ed0SFan Zhang 
1610d547ed0SFan Zhang 		pch = strchr((xdigits = xdigits_l), ch);
1620d547ed0SFan Zhang 		if (pch == NULL)
1630d547ed0SFan Zhang 			pch = strchr((xdigits = xdigits_u), ch);
1640d547ed0SFan Zhang 		if (pch != NULL) {
1650d547ed0SFan Zhang 			if (count_xdigit >= 4)
1660d547ed0SFan Zhang 				return 0;
1670d547ed0SFan Zhang 			val <<= 4;
1680d547ed0SFan Zhang 			val |= (pch - xdigits);
1690d547ed0SFan Zhang 			if (val > 0xffff)
1700d547ed0SFan Zhang 				return 0;
1710d547ed0SFan Zhang 			saw_xdigit = 1;
1720d547ed0SFan Zhang 			count_xdigit++;
1730d547ed0SFan Zhang 			continue;
1740d547ed0SFan Zhang 		}
1750d547ed0SFan Zhang 		if (ch == ':') {
1760d547ed0SFan Zhang 			curtok = src;
1770d547ed0SFan Zhang 			if (!saw_xdigit) {
1780d547ed0SFan Zhang 				if (colonp)
1790d547ed0SFan Zhang 					return 0;
1800d547ed0SFan Zhang 				colonp = tp;
1810d547ed0SFan Zhang 				continue;
1820d547ed0SFan Zhang 			} else if (*src == '\0') {
1830d547ed0SFan Zhang 				return 0;
1840d547ed0SFan Zhang 			}
1850d547ed0SFan Zhang 			if (tp + sizeof(int16_t) > endp)
1860d547ed0SFan Zhang 				return 0;
1870d547ed0SFan Zhang 			*tp++ = (unsigned char) ((val >> 8) & 0xff);
1880d547ed0SFan Zhang 			*tp++ = (unsigned char) (val & 0xff);
1890d547ed0SFan Zhang 			saw_xdigit = 0;
1900d547ed0SFan Zhang 			count_xdigit = 0;
1910d547ed0SFan Zhang 			val = 0;
1920d547ed0SFan Zhang 			dbloct_count++;
1930d547ed0SFan Zhang 			continue;
1940d547ed0SFan Zhang 		}
1950d547ed0SFan Zhang 		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
1960d547ed0SFan Zhang 		    inet_pton4(curtok, tp) > 0) {
1970d547ed0SFan Zhang 			tp += INADDRSZ;
1980d547ed0SFan Zhang 			saw_xdigit = 0;
1990d547ed0SFan Zhang 			dbloct_count += 2;
2000d547ed0SFan Zhang 			break;  /* '\0' was seen by inet_pton4(). */
2010d547ed0SFan Zhang 		}
2020d547ed0SFan Zhang 		return 0;
2030d547ed0SFan Zhang 	}
2040d547ed0SFan Zhang 	if (saw_xdigit) {
2050d547ed0SFan Zhang 		if (tp + sizeof(int16_t) > endp)
2060d547ed0SFan Zhang 			return 0;
2070d547ed0SFan Zhang 		*tp++ = (unsigned char) ((val >> 8) & 0xff);
2080d547ed0SFan Zhang 		*tp++ = (unsigned char) (val & 0xff);
2090d547ed0SFan Zhang 		dbloct_count++;
2100d547ed0SFan Zhang 	}
2110d547ed0SFan Zhang 	if (colonp != NULL) {
2120d547ed0SFan Zhang 		/* if we already have 8 double octets, having a colon
2130d547ed0SFan Zhang 		 * means error */
2140d547ed0SFan Zhang 		if (dbloct_count == 8)
2150d547ed0SFan Zhang 			return 0;
2160d547ed0SFan Zhang 
2170d547ed0SFan Zhang 		/*
2180d547ed0SFan Zhang 		 * Since some memmove()'s erroneously fail to handle
2190d547ed0SFan Zhang 		 * overlapping regions, we'll do the shift by hand.
2200d547ed0SFan Zhang 		 */
2210d547ed0SFan Zhang 		const int n = tp - colonp;
2220d547ed0SFan Zhang 		int i;
2230d547ed0SFan Zhang 
2240d547ed0SFan Zhang 		for (i = 1; i <= n; i++) {
2250d547ed0SFan Zhang 			endp[-i] = colonp[n - i];
2260d547ed0SFan Zhang 			colonp[n - i] = 0;
2270d547ed0SFan Zhang 		}
2280d547ed0SFan Zhang 		tp = endp;
2290d547ed0SFan Zhang 	}
2300d547ed0SFan Zhang 	if (tp != endp)
2310d547ed0SFan Zhang 		return 0;
2320d547ed0SFan Zhang 	memcpy(dst, tmp, IN6ADDRSZ);
2330d547ed0SFan Zhang 	return 1;
2340d547ed0SFan Zhang }
2350d547ed0SFan Zhang 
2360d547ed0SFan Zhang int
2370d547ed0SFan Zhang parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
2380d547ed0SFan Zhang {
2390d547ed0SFan Zhang 	char ip_str[256] = {0};
2400d547ed0SFan Zhang 	char *pch;
2410d547ed0SFan Zhang 
2420d547ed0SFan Zhang 	pch = strchr(token, '/');
2430d547ed0SFan Zhang 	if (pch != NULL) {
2440d547ed0SFan Zhang 		strncpy(ip_str, token, pch - token);
2450d547ed0SFan Zhang 		pch += 1;
2460d547ed0SFan Zhang 		if (is_str_num(pch) != 0)
2470d547ed0SFan Zhang 			return -EINVAL;
2480d547ed0SFan Zhang 		if (mask)
2490d547ed0SFan Zhang 			*mask = atoi(pch);
2500d547ed0SFan Zhang 	} else {
251*07b15619SFan Zhang 		strncpy(ip_str, token, sizeof(ip_str) - 1);
2520d547ed0SFan Zhang 		if (mask)
2530d547ed0SFan Zhang 			*mask = 0;
2540d547ed0SFan Zhang 	}
2550d547ed0SFan Zhang 
2560d547ed0SFan Zhang 	if (strlen(ip_str) >= INET_ADDRSTRLEN)
2570d547ed0SFan Zhang 		return -EINVAL;
2580d547ed0SFan Zhang 
2590d547ed0SFan Zhang 	if (inet_pton4(ip_str, (unsigned char *)ipv4) != 1)
2600d547ed0SFan Zhang 		return -EINVAL;
2610d547ed0SFan Zhang 
2620d547ed0SFan Zhang 	return 0;
2630d547ed0SFan Zhang }
2640d547ed0SFan Zhang 
2650d547ed0SFan Zhang int
2660d547ed0SFan Zhang parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
2670d547ed0SFan Zhang {
2680d547ed0SFan Zhang 	char ip_str[256] = {0};
2690d547ed0SFan Zhang 	char *pch;
2700d547ed0SFan Zhang 
2710d547ed0SFan Zhang 	pch = strchr(token, '/');
2720d547ed0SFan Zhang 	if (pch != NULL) {
2730d547ed0SFan Zhang 		strncpy(ip_str, token, pch - token);
2740d547ed0SFan Zhang 		pch += 1;
2750d547ed0SFan Zhang 		if (is_str_num(pch) != 0)
2760d547ed0SFan Zhang 			return -EINVAL;
2770d547ed0SFan Zhang 		if (mask)
2780d547ed0SFan Zhang 			*mask = atoi(pch);
2790d547ed0SFan Zhang 	} else {
280*07b15619SFan Zhang 		strncpy(ip_str, token, sizeof(ip_str) - 1);
2810d547ed0SFan Zhang 		if (mask)
2820d547ed0SFan Zhang 			*mask = 0;
2830d547ed0SFan Zhang 	}
2840d547ed0SFan Zhang 
2850d547ed0SFan Zhang 	if (strlen(ip_str) >= INET6_ADDRSTRLEN)
2860d547ed0SFan Zhang 		return -EINVAL;
2870d547ed0SFan Zhang 
2880d547ed0SFan Zhang 	if (inet_pton6(ip_str, (unsigned char *)ipv6) != 1)
2890d547ed0SFan Zhang 		return -EINVAL;
2900d547ed0SFan Zhang 
2910d547ed0SFan Zhang 	return 0;
2920d547ed0SFan Zhang }
2930d547ed0SFan Zhang 
2940d547ed0SFan Zhang int
2950d547ed0SFan Zhang parse_range(const char *token, uint16_t *low, uint16_t *high)
2960d547ed0SFan Zhang {
2970d547ed0SFan Zhang 	char ch;
2980d547ed0SFan Zhang 	char num_str[20];
2990d547ed0SFan Zhang 	uint32_t pos;
3000d547ed0SFan Zhang 	int range_low = -1;
3010d547ed0SFan Zhang 	int range_high = -1;
3020d547ed0SFan Zhang 
3030d547ed0SFan Zhang 	if (!low || !high)
3040d547ed0SFan Zhang 		return -1;
3050d547ed0SFan Zhang 
3060d547ed0SFan Zhang 	memset(num_str, 0, 20);
3070d547ed0SFan Zhang 	pos = 0;
3080d547ed0SFan Zhang 
3090d547ed0SFan Zhang 	while ((ch = *token++) != '\0') {
3100d547ed0SFan Zhang 		if (isdigit(ch)) {
3110d547ed0SFan Zhang 			if (pos >= 19)
3120d547ed0SFan Zhang 				return -1;
3130d547ed0SFan Zhang 			num_str[pos++] = ch;
3140d547ed0SFan Zhang 		} else if (ch == ':') {
3150d547ed0SFan Zhang 			if (range_low != -1)
3160d547ed0SFan Zhang 				return -1;
3170d547ed0SFan Zhang 			range_low = atoi(num_str);
3180d547ed0SFan Zhang 			memset(num_str, 0, 20);
3190d547ed0SFan Zhang 			pos = 0;
3200d547ed0SFan Zhang 		}
3210d547ed0SFan Zhang 	}
3220d547ed0SFan Zhang 
3230d547ed0SFan Zhang 	if (strlen(num_str) == 0)
3240d547ed0SFan Zhang 		return -1;
3250d547ed0SFan Zhang 
3260d547ed0SFan Zhang 	range_high = atoi(num_str);
3270d547ed0SFan Zhang 
3280d547ed0SFan Zhang 	*low = (uint16_t)range_low;
3290d547ed0SFan Zhang 	*high = (uint16_t)range_high;
3300d547ed0SFan Zhang 
3310d547ed0SFan Zhang 	return 0;
3320d547ed0SFan Zhang }
3330d547ed0SFan Zhang 
3340d547ed0SFan Zhang /** sp add parse */
3350d547ed0SFan Zhang struct cfg_sp_add_cfg_item {
3360d547ed0SFan Zhang 	cmdline_fixed_string_t sp_keyword;
3370d547ed0SFan Zhang 	cmdline_multi_string_t multi_string;
3380d547ed0SFan Zhang };
3390d547ed0SFan Zhang 
3400d547ed0SFan Zhang static void
3410d547ed0SFan Zhang cfg_sp_add_cfg_item_parsed(void *parsed_result,
3420d547ed0SFan Zhang 	__rte_unused struct cmdline *cl, void *data)
3430d547ed0SFan Zhang {
3440d547ed0SFan Zhang 	struct cfg_sp_add_cfg_item *params = parsed_result;
3450d547ed0SFan Zhang 	char *tokens[32];
3460d547ed0SFan Zhang 	uint32_t n_tokens = RTE_DIM(tokens);
3470d547ed0SFan Zhang 	struct parse_status *status = (struct parse_status *)data;
3480d547ed0SFan Zhang 
3490d547ed0SFan Zhang 	APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
3500d547ed0SFan Zhang 		&n_tokens) == 0), status, "too many arguments");
3510d547ed0SFan Zhang 
3520d547ed0SFan Zhang 	if (status->status < 0)
3530d547ed0SFan Zhang 		return;
3540d547ed0SFan Zhang 
3550d547ed0SFan Zhang 	if (strcmp(tokens[0], "ipv4") == 0) {
3560d547ed0SFan Zhang 		parse_sp4_tokens(tokens, n_tokens, status);
3570d547ed0SFan Zhang 		if (status->status < 0)
3580d547ed0SFan Zhang 			return;
3590d547ed0SFan Zhang 	} else if (strcmp(tokens[0], "ipv6") == 0) {
3600d547ed0SFan Zhang 		parse_sp6_tokens(tokens, n_tokens, status);
3610d547ed0SFan Zhang 		if (status->status < 0)
3620d547ed0SFan Zhang 			return;
3630d547ed0SFan Zhang 	} else {
3640d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognizable input %s\n",
3650d547ed0SFan Zhang 			tokens[0]);
3660d547ed0SFan Zhang 		return;
3670d547ed0SFan Zhang 	}
3680d547ed0SFan Zhang }
3690d547ed0SFan Zhang 
3700d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sp_add_sp_str =
3710d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
3720d547ed0SFan Zhang 		sp_keyword, "sp");
3730d547ed0SFan Zhang 
3740d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sp_add_multi_str =
3750d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
3760d547ed0SFan Zhang 		TOKEN_STRING_MULTI);
3770d547ed0SFan Zhang 
3780d547ed0SFan Zhang cmdline_parse_inst_t cfg_sp_add_rule = {
3790d547ed0SFan Zhang 	.f = cfg_sp_add_cfg_item_parsed,
3800d547ed0SFan Zhang 	.data = NULL,
3810d547ed0SFan Zhang 	.help_str = "",
3820d547ed0SFan Zhang 	.tokens = {
3830d547ed0SFan Zhang 		(void *) &cfg_sp_add_sp_str,
3840d547ed0SFan Zhang 		(void *) &cfg_sp_add_multi_str,
3850d547ed0SFan Zhang 		NULL,
3860d547ed0SFan Zhang 	},
3870d547ed0SFan Zhang };
3880d547ed0SFan Zhang 
3890d547ed0SFan Zhang /* sa add parse */
3900d547ed0SFan Zhang struct cfg_sa_add_cfg_item {
3910d547ed0SFan Zhang 	cmdline_fixed_string_t sa_keyword;
3920d547ed0SFan Zhang 	cmdline_multi_string_t multi_string;
3930d547ed0SFan Zhang };
3940d547ed0SFan Zhang 
3950d547ed0SFan Zhang static void
3960d547ed0SFan Zhang cfg_sa_add_cfg_item_parsed(void *parsed_result,
3970d547ed0SFan Zhang 	__rte_unused struct cmdline *cl, void *data)
3980d547ed0SFan Zhang {
3990d547ed0SFan Zhang 	struct cfg_sa_add_cfg_item *params = parsed_result;
4000d547ed0SFan Zhang 	char *tokens[32];
4010d547ed0SFan Zhang 	uint32_t n_tokens = RTE_DIM(tokens);
4020d547ed0SFan Zhang 	struct parse_status *status = (struct parse_status *)data;
4030d547ed0SFan Zhang 
4040d547ed0SFan Zhang 	APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
4050d547ed0SFan Zhang 		&n_tokens) == 0, status, "too many arguments\n");
4060d547ed0SFan Zhang 
4070d547ed0SFan Zhang 	parse_sa_tokens(tokens, n_tokens, status);
4080d547ed0SFan Zhang }
4090d547ed0SFan Zhang 
4100d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sa_add_sa_str =
4110d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
4120d547ed0SFan Zhang 		sa_keyword, "sa");
4130d547ed0SFan Zhang 
4140d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sa_add_multi_str =
4150d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
4160d547ed0SFan Zhang 		TOKEN_STRING_MULTI);
4170d547ed0SFan Zhang 
4180d547ed0SFan Zhang cmdline_parse_inst_t cfg_sa_add_rule = {
4190d547ed0SFan Zhang 	.f = cfg_sa_add_cfg_item_parsed,
4200d547ed0SFan Zhang 	.data = NULL,
4210d547ed0SFan Zhang 	.help_str = "",
4220d547ed0SFan Zhang 	.tokens = {
4230d547ed0SFan Zhang 		(void *) &cfg_sa_add_sa_str,
4240d547ed0SFan Zhang 		(void *) &cfg_sa_add_multi_str,
4250d547ed0SFan Zhang 		NULL,
4260d547ed0SFan Zhang 	},
4270d547ed0SFan Zhang };
4280d547ed0SFan Zhang 
4290d547ed0SFan Zhang /* rt add parse */
4300d547ed0SFan Zhang struct cfg_rt_add_cfg_item {
4310d547ed0SFan Zhang 	cmdline_fixed_string_t rt_keyword;
4320d547ed0SFan Zhang 	cmdline_multi_string_t multi_string;
4330d547ed0SFan Zhang };
4340d547ed0SFan Zhang 
4350d547ed0SFan Zhang static void
4360d547ed0SFan Zhang cfg_rt_add_cfg_item_parsed(void *parsed_result,
4370d547ed0SFan Zhang 	__rte_unused struct cmdline *cl, void *data)
4380d547ed0SFan Zhang {
4390d547ed0SFan Zhang 	struct cfg_rt_add_cfg_item *params = parsed_result;
4400d547ed0SFan Zhang 	char *tokens[32];
4410d547ed0SFan Zhang 	uint32_t n_tokens = RTE_DIM(tokens);
4420d547ed0SFan Zhang 	struct parse_status *status = (struct parse_status *)data;
4430d547ed0SFan Zhang 
4440d547ed0SFan Zhang 	APP_CHECK(parse_tokenize_string(
4450d547ed0SFan Zhang 		params->multi_string, tokens, &n_tokens) == 0,
4460d547ed0SFan Zhang 		status, "too many arguments\n");
4470d547ed0SFan Zhang 	if (status->status < 0)
4480d547ed0SFan Zhang 		return;
4490d547ed0SFan Zhang 
4500d547ed0SFan Zhang 	parse_rt_tokens(tokens, n_tokens, status);
4510d547ed0SFan Zhang }
4520d547ed0SFan Zhang 
4530d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_rt_add_rt_str =
4540d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
4550d547ed0SFan Zhang 		rt_keyword, "rt");
4560d547ed0SFan Zhang 
4570d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_rt_add_multi_str =
4580d547ed0SFan Zhang 	TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
4590d547ed0SFan Zhang 		TOKEN_STRING_MULTI);
4600d547ed0SFan Zhang 
4610d547ed0SFan Zhang cmdline_parse_inst_t cfg_rt_add_rule = {
4620d547ed0SFan Zhang 	.f = cfg_rt_add_cfg_item_parsed,
4630d547ed0SFan Zhang 	.data = NULL,
4640d547ed0SFan Zhang 	.help_str = "",
4650d547ed0SFan Zhang 	.tokens = {
4660d547ed0SFan Zhang 		(void *) &cfg_rt_add_rt_str,
4670d547ed0SFan Zhang 		(void *) &cfg_rt_add_multi_str,
4680d547ed0SFan Zhang 		NULL,
4690d547ed0SFan Zhang 	},
4700d547ed0SFan Zhang };
4710d547ed0SFan Zhang 
4720d547ed0SFan Zhang /** set of cfg items */
4730d547ed0SFan Zhang cmdline_parse_ctx_t ipsec_ctx[] = {
4740d547ed0SFan Zhang 	(cmdline_parse_inst_t *)&cfg_sp_add_rule,
4750d547ed0SFan Zhang 	(cmdline_parse_inst_t *)&cfg_sa_add_rule,
4760d547ed0SFan Zhang 	(cmdline_parse_inst_t *)&cfg_rt_add_rule,
4770d547ed0SFan Zhang 	NULL,
4780d547ed0SFan Zhang };
4790d547ed0SFan Zhang 
4800d547ed0SFan Zhang int
4810d547ed0SFan Zhang parse_cfg_file(const char *cfg_filename)
4820d547ed0SFan Zhang {
4830d547ed0SFan Zhang 	struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, "");
4840d547ed0SFan Zhang 	FILE *f = fopen(cfg_filename, "r");
4850d547ed0SFan Zhang 	char str[1024] = {0}, *get_s = NULL;
4860d547ed0SFan Zhang 	uint32_t line_num = 0;
4870d547ed0SFan Zhang 	struct parse_status status = {0};
4880d547ed0SFan Zhang 
4890d547ed0SFan Zhang 	if (f == NULL) {
4900d547ed0SFan Zhang 		rte_panic("Error: invalid file descriptor %s\n",
4910d547ed0SFan Zhang 			cfg_filename);
4920d547ed0SFan Zhang 		goto error_exit;
4930d547ed0SFan Zhang 	}
4940d547ed0SFan Zhang 
4950d547ed0SFan Zhang 	if (cl == NULL) {
4960d547ed0SFan Zhang 		rte_panic("Error: cannot create cmdline instance\n");
4970d547ed0SFan Zhang 		goto error_exit;
4980d547ed0SFan Zhang 	}
4990d547ed0SFan Zhang 
5000d547ed0SFan Zhang 	cfg_sp_add_rule.data = &status;
5010d547ed0SFan Zhang 	cfg_sa_add_rule.data = &status;
5020d547ed0SFan Zhang 	cfg_rt_add_rule.data = &status;
5030d547ed0SFan Zhang 
5040d547ed0SFan Zhang 	do {
5050d547ed0SFan Zhang 		char oneline[1024];
5060d547ed0SFan Zhang 
5070d547ed0SFan Zhang 		get_s = fgets(oneline, 1024, f);
5080d547ed0SFan Zhang 		if (get_s) {
5090d547ed0SFan Zhang 			char *pos;
5100d547ed0SFan Zhang 
5110d547ed0SFan Zhang 			line_num++;
5120d547ed0SFan Zhang 
5130d547ed0SFan Zhang 			if (strlen(oneline) > 1022) {
5140d547ed0SFan Zhang 				rte_panic("%s:%u: error: the line "
5150d547ed0SFan Zhang 					"contains more characters the "
5160d547ed0SFan Zhang 					"parser can handle\n",
5170d547ed0SFan Zhang 					cfg_filename, line_num);
5180d547ed0SFan Zhang 				goto error_exit;
5190d547ed0SFan Zhang 			}
5200d547ed0SFan Zhang 
5210d547ed0SFan Zhang 			/* process comment char '#' */
5220d547ed0SFan Zhang 			if (oneline[0] == '#')
5230d547ed0SFan Zhang 				continue;
5240d547ed0SFan Zhang 
5250d547ed0SFan Zhang 			pos = strchr(oneline, '#');
5260d547ed0SFan Zhang 			if (pos != NULL)
5270d547ed0SFan Zhang 				*pos = '\0';
5280d547ed0SFan Zhang 
5290d547ed0SFan Zhang 			/* process line concatenator '\' */
5300d547ed0SFan Zhang 			pos = strchr(oneline, 92);
5310d547ed0SFan Zhang 			if (pos != NULL) {
5320d547ed0SFan Zhang 				if (pos != oneline+strlen(oneline) - 2) {
5330d547ed0SFan Zhang 					rte_panic("%s:%u: error: no "
5340d547ed0SFan Zhang 						"character should exist "
5350d547ed0SFan Zhang 						"after '\\' symbol\n",
5360d547ed0SFan Zhang 						cfg_filename, line_num);
5370d547ed0SFan Zhang 					goto error_exit;
5380d547ed0SFan Zhang 				}
5390d547ed0SFan Zhang 
5400d547ed0SFan Zhang 				*pos = '\0';
5410d547ed0SFan Zhang 
5420d547ed0SFan Zhang 				if (strlen(oneline) + strlen(str) > 1022) {
5430d547ed0SFan Zhang 					rte_panic("%s:%u: error: the "
5440d547ed0SFan Zhang 						"concatenated line "
5450d547ed0SFan Zhang 						"contains more characters "
5460d547ed0SFan Zhang 						"the parser can handle\n",
5470d547ed0SFan Zhang 						cfg_filename, line_num);
5480d547ed0SFan Zhang 					goto error_exit;
5490d547ed0SFan Zhang 				}
5500d547ed0SFan Zhang 
5510d547ed0SFan Zhang 				strncpy(str + strlen(str), oneline,
5520d547ed0SFan Zhang 					strlen(oneline));
5530d547ed0SFan Zhang 
5540d547ed0SFan Zhang 				continue;
5550d547ed0SFan Zhang 			}
5560d547ed0SFan Zhang 
5570d547ed0SFan Zhang 			/* copy the line to str and process */
5580d547ed0SFan Zhang 			if (strlen(oneline) + strlen(str) > 1022) {
5590d547ed0SFan Zhang 				rte_panic("%s:%u: error: the line "
5600d547ed0SFan Zhang 					"contains more characters the "
5610d547ed0SFan Zhang 					"parser can handle\n",
5620d547ed0SFan Zhang 					cfg_filename, line_num);
5630d547ed0SFan Zhang 				goto error_exit;
5640d547ed0SFan Zhang 			}
5650d547ed0SFan Zhang 			strncpy(str + strlen(str), oneline,
5660d547ed0SFan Zhang 				strlen(oneline));
5670d547ed0SFan Zhang 
5680d547ed0SFan Zhang 			str[strlen(str)] = '\n';
5690d547ed0SFan Zhang 			if (cmdline_parse(cl, str) < 0) {
5700d547ed0SFan Zhang 				rte_panic("%s:%u: error: parsing \"%s\" "
5710d547ed0SFan Zhang 					"failed\n", cfg_filename,
5720d547ed0SFan Zhang 					line_num, str);
5730d547ed0SFan Zhang 				goto error_exit;
5740d547ed0SFan Zhang 			}
5750d547ed0SFan Zhang 
5760d547ed0SFan Zhang 			if (status.status < 0) {
5770d547ed0SFan Zhang 				rte_panic("%s:%u: error: %s",
5780d547ed0SFan Zhang 					cfg_filename, line_num,
5790d547ed0SFan Zhang 					status.parse_msg);
5800d547ed0SFan Zhang 				goto error_exit;
5810d547ed0SFan Zhang 			}
5820d547ed0SFan Zhang 
5830d547ed0SFan Zhang 			memset(str, 0, 1024);
5840d547ed0SFan Zhang 		}
5850d547ed0SFan Zhang 	} while (get_s != NULL);
5860d547ed0SFan Zhang 
5870d547ed0SFan Zhang 	cmdline_stdin_exit(cl);
5880d547ed0SFan Zhang 	fclose(f);
5890d547ed0SFan Zhang 
5900d547ed0SFan Zhang 	return 0;
5910d547ed0SFan Zhang 
5920d547ed0SFan Zhang error_exit:
5930d547ed0SFan Zhang 	if (cl)
5940d547ed0SFan Zhang 		cmdline_stdin_exit(cl);
5950d547ed0SFan Zhang 	if (f)
5960d547ed0SFan Zhang 		fclose(f);
5970d547ed0SFan Zhang 
5980d547ed0SFan Zhang 	return -1;
5990d547ed0SFan Zhang }
600