1*3998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2*3998e2a0SBruce Richardson * Copyright(c) 2016 Intel Corporation 30d547ed0SFan Zhang */ 40d547ed0SFan Zhang #include <rte_common.h> 50d547ed0SFan Zhang #include <rte_crypto.h> 60d547ed0SFan Zhang 70d547ed0SFan Zhang #include <cmdline_parse_string.h> 80d547ed0SFan Zhang #include <cmdline_parse_num.h> 90d547ed0SFan Zhang #include <cmdline_parse_ipaddr.h> 100d547ed0SFan Zhang #include <cmdline_socket.h> 110d547ed0SFan Zhang #include <cmdline.h> 120d547ed0SFan Zhang 130d547ed0SFan Zhang #include "ipsec.h" 140d547ed0SFan Zhang #include "parser.h" 150d547ed0SFan Zhang 160d547ed0SFan Zhang #define PARSE_DELIMITER " \f\n\r\t\v" 170d547ed0SFan Zhang static int 180d547ed0SFan Zhang parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 190d547ed0SFan Zhang { 200d547ed0SFan Zhang uint32_t i; 210d547ed0SFan Zhang 220d547ed0SFan Zhang if ((string == NULL) || 230d547ed0SFan Zhang (tokens == NULL) || 240d547ed0SFan Zhang (*n_tokens < 1)) 250d547ed0SFan Zhang return -EINVAL; 260d547ed0SFan Zhang 270d547ed0SFan Zhang for (i = 0; i < *n_tokens; i++) { 280d547ed0SFan Zhang tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 290d547ed0SFan Zhang if (tokens[i] == NULL) 300d547ed0SFan Zhang break; 310d547ed0SFan Zhang } 320d547ed0SFan Zhang 330d547ed0SFan Zhang if ((i == *n_tokens) && 340d547ed0SFan Zhang (NULL != strtok_r(string, PARSE_DELIMITER, &string))) 350d547ed0SFan Zhang return -E2BIG; 360d547ed0SFan Zhang 370d547ed0SFan Zhang *n_tokens = i; 380d547ed0SFan Zhang return 0; 390d547ed0SFan Zhang } 400d547ed0SFan Zhang 410d547ed0SFan Zhang #define INADDRSZ 4 420d547ed0SFan Zhang #define IN6ADDRSZ 16 430d547ed0SFan Zhang 440d547ed0SFan Zhang /* int 450d547ed0SFan Zhang * inet_pton4(src, dst) 460d547ed0SFan Zhang * like inet_aton() but without all the hexadecimal and shorthand. 470d547ed0SFan Zhang * return: 480d547ed0SFan Zhang * 1 if `src' is a valid dotted quad, else 0. 490d547ed0SFan Zhang * notice: 500d547ed0SFan Zhang * does not touch `dst' unless it's returning 1. 510d547ed0SFan Zhang * author: 520d547ed0SFan Zhang * Paul Vixie, 1996. 530d547ed0SFan Zhang */ 540d547ed0SFan Zhang static int 550d547ed0SFan Zhang inet_pton4(const char *src, unsigned char *dst) 560d547ed0SFan Zhang { 570d547ed0SFan Zhang static const char digits[] = "0123456789"; 580d547ed0SFan Zhang int saw_digit, octets, ch; 590d547ed0SFan Zhang unsigned char tmp[INADDRSZ], *tp; 600d547ed0SFan Zhang 610d547ed0SFan Zhang saw_digit = 0; 620d547ed0SFan Zhang octets = 0; 630d547ed0SFan Zhang *(tp = tmp) = 0; 640d547ed0SFan Zhang while ((ch = *src++) != '\0') { 650d547ed0SFan Zhang const char *pch; 660d547ed0SFan Zhang 670d547ed0SFan Zhang pch = strchr(digits, ch); 680d547ed0SFan Zhang if (pch != NULL) { 690d547ed0SFan Zhang unsigned int new = *tp * 10 + (pch - digits); 700d547ed0SFan Zhang 710d547ed0SFan Zhang if (new > 255) 720d547ed0SFan Zhang return 0; 730d547ed0SFan Zhang if (!saw_digit) { 740d547ed0SFan Zhang if (++octets > 4) 750d547ed0SFan Zhang return 0; 760d547ed0SFan Zhang saw_digit = 1; 770d547ed0SFan Zhang } 780d547ed0SFan Zhang *tp = (unsigned char)new; 790d547ed0SFan Zhang } else if (ch == '.' && saw_digit) { 800d547ed0SFan Zhang if (octets == 4) 810d547ed0SFan Zhang return 0; 820d547ed0SFan Zhang *++tp = 0; 830d547ed0SFan Zhang saw_digit = 0; 840d547ed0SFan Zhang } else 850d547ed0SFan Zhang return 0; 860d547ed0SFan Zhang } 870d547ed0SFan Zhang if (octets < 4) 880d547ed0SFan Zhang return 0; 890d547ed0SFan Zhang 900d547ed0SFan Zhang memcpy(dst, tmp, INADDRSZ); 910d547ed0SFan Zhang return 1; 920d547ed0SFan Zhang } 930d547ed0SFan Zhang 940d547ed0SFan Zhang /* int 950d547ed0SFan Zhang * inet_pton6(src, dst) 960d547ed0SFan Zhang * convert presentation level address to network order binary form. 970d547ed0SFan Zhang * return: 980d547ed0SFan Zhang * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 990d547ed0SFan Zhang * notice: 1000d547ed0SFan Zhang * (1) does not touch `dst' unless it's returning 1. 1010d547ed0SFan Zhang * (2) :: in a full address is silently ignored. 1020d547ed0SFan Zhang * credit: 1030d547ed0SFan Zhang * inspired by Mark Andrews. 1040d547ed0SFan Zhang * author: 1050d547ed0SFan Zhang * Paul Vixie, 1996. 1060d547ed0SFan Zhang */ 1070d547ed0SFan Zhang static int 1080d547ed0SFan Zhang inet_pton6(const char *src, unsigned char *dst) 1090d547ed0SFan Zhang { 1100d547ed0SFan Zhang static const char xdigits_l[] = "0123456789abcdef", 1110d547ed0SFan Zhang xdigits_u[] = "0123456789ABCDEF"; 1120d547ed0SFan Zhang unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; 1130d547ed0SFan Zhang const char *xdigits = 0, *curtok = 0; 1140d547ed0SFan Zhang int ch = 0, saw_xdigit = 0, count_xdigit = 0; 1150d547ed0SFan Zhang unsigned int val = 0; 1160d547ed0SFan Zhang unsigned dbloct_count = 0; 1170d547ed0SFan Zhang 1180d547ed0SFan Zhang memset((tp = tmp), '\0', IN6ADDRSZ); 1190d547ed0SFan Zhang endp = tp + IN6ADDRSZ; 1200d547ed0SFan Zhang colonp = NULL; 1210d547ed0SFan Zhang /* Leading :: requires some special handling. */ 1220d547ed0SFan Zhang if (*src == ':') 1230d547ed0SFan Zhang if (*++src != ':') 1240d547ed0SFan Zhang return 0; 1250d547ed0SFan Zhang curtok = src; 1260d547ed0SFan Zhang saw_xdigit = count_xdigit = 0; 1270d547ed0SFan Zhang val = 0; 1280d547ed0SFan Zhang 1290d547ed0SFan Zhang while ((ch = *src++) != '\0') { 1300d547ed0SFan Zhang const char *pch; 1310d547ed0SFan Zhang 1320d547ed0SFan Zhang pch = strchr((xdigits = xdigits_l), ch); 1330d547ed0SFan Zhang if (pch == NULL) 1340d547ed0SFan Zhang pch = strchr((xdigits = xdigits_u), ch); 1350d547ed0SFan Zhang if (pch != NULL) { 1360d547ed0SFan Zhang if (count_xdigit >= 4) 1370d547ed0SFan Zhang return 0; 1380d547ed0SFan Zhang val <<= 4; 1390d547ed0SFan Zhang val |= (pch - xdigits); 1400d547ed0SFan Zhang if (val > 0xffff) 1410d547ed0SFan Zhang return 0; 1420d547ed0SFan Zhang saw_xdigit = 1; 1430d547ed0SFan Zhang count_xdigit++; 1440d547ed0SFan Zhang continue; 1450d547ed0SFan Zhang } 1460d547ed0SFan Zhang if (ch == ':') { 1470d547ed0SFan Zhang curtok = src; 1480d547ed0SFan Zhang if (!saw_xdigit) { 1490d547ed0SFan Zhang if (colonp) 1500d547ed0SFan Zhang return 0; 1510d547ed0SFan Zhang colonp = tp; 1520d547ed0SFan Zhang continue; 1530d547ed0SFan Zhang } else if (*src == '\0') { 1540d547ed0SFan Zhang return 0; 1550d547ed0SFan Zhang } 1560d547ed0SFan Zhang if (tp + sizeof(int16_t) > endp) 1570d547ed0SFan Zhang return 0; 1580d547ed0SFan Zhang *tp++ = (unsigned char) ((val >> 8) & 0xff); 1590d547ed0SFan Zhang *tp++ = (unsigned char) (val & 0xff); 1600d547ed0SFan Zhang saw_xdigit = 0; 1610d547ed0SFan Zhang count_xdigit = 0; 1620d547ed0SFan Zhang val = 0; 1630d547ed0SFan Zhang dbloct_count++; 1640d547ed0SFan Zhang continue; 1650d547ed0SFan Zhang } 1660d547ed0SFan Zhang if (ch == '.' && ((tp + INADDRSZ) <= endp) && 1670d547ed0SFan Zhang inet_pton4(curtok, tp) > 0) { 1680d547ed0SFan Zhang tp += INADDRSZ; 1690d547ed0SFan Zhang saw_xdigit = 0; 1700d547ed0SFan Zhang dbloct_count += 2; 1710d547ed0SFan Zhang break; /* '\0' was seen by inet_pton4(). */ 1720d547ed0SFan Zhang } 1730d547ed0SFan Zhang return 0; 1740d547ed0SFan Zhang } 1750d547ed0SFan Zhang if (saw_xdigit) { 1760d547ed0SFan Zhang if (tp + sizeof(int16_t) > endp) 1770d547ed0SFan Zhang return 0; 1780d547ed0SFan Zhang *tp++ = (unsigned char) ((val >> 8) & 0xff); 1790d547ed0SFan Zhang *tp++ = (unsigned char) (val & 0xff); 1800d547ed0SFan Zhang dbloct_count++; 1810d547ed0SFan Zhang } 1820d547ed0SFan Zhang if (colonp != NULL) { 1830d547ed0SFan Zhang /* if we already have 8 double octets, having a colon 1840d547ed0SFan Zhang * means error */ 1850d547ed0SFan Zhang if (dbloct_count == 8) 1860d547ed0SFan Zhang return 0; 1870d547ed0SFan Zhang 1880d547ed0SFan Zhang /* 1890d547ed0SFan Zhang * Since some memmove()'s erroneously fail to handle 1900d547ed0SFan Zhang * overlapping regions, we'll do the shift by hand. 1910d547ed0SFan Zhang */ 1920d547ed0SFan Zhang const int n = tp - colonp; 1930d547ed0SFan Zhang int i; 1940d547ed0SFan Zhang 1950d547ed0SFan Zhang for (i = 1; i <= n; i++) { 1960d547ed0SFan Zhang endp[-i] = colonp[n - i]; 1970d547ed0SFan Zhang colonp[n - i] = 0; 1980d547ed0SFan Zhang } 1990d547ed0SFan Zhang tp = endp; 2000d547ed0SFan Zhang } 2010d547ed0SFan Zhang if (tp != endp) 2020d547ed0SFan Zhang return 0; 2030d547ed0SFan Zhang memcpy(dst, tmp, IN6ADDRSZ); 2040d547ed0SFan Zhang return 1; 2050d547ed0SFan Zhang } 2060d547ed0SFan Zhang 2070d547ed0SFan Zhang int 2080d547ed0SFan Zhang parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask) 2090d547ed0SFan Zhang { 2100d547ed0SFan Zhang char ip_str[256] = {0}; 2110d547ed0SFan Zhang char *pch; 2120d547ed0SFan Zhang 2130d547ed0SFan Zhang pch = strchr(token, '/'); 2140d547ed0SFan Zhang if (pch != NULL) { 2150d547ed0SFan Zhang strncpy(ip_str, token, pch - token); 2160d547ed0SFan Zhang pch += 1; 2170d547ed0SFan Zhang if (is_str_num(pch) != 0) 2180d547ed0SFan Zhang return -EINVAL; 2190d547ed0SFan Zhang if (mask) 2200d547ed0SFan Zhang *mask = atoi(pch); 2210d547ed0SFan Zhang } else { 22207b15619SFan Zhang strncpy(ip_str, token, sizeof(ip_str) - 1); 2230d547ed0SFan Zhang if (mask) 2240d547ed0SFan Zhang *mask = 0; 2250d547ed0SFan Zhang } 2260d547ed0SFan Zhang 2270d547ed0SFan Zhang if (strlen(ip_str) >= INET_ADDRSTRLEN) 2280d547ed0SFan Zhang return -EINVAL; 2290d547ed0SFan Zhang 2300d547ed0SFan Zhang if (inet_pton4(ip_str, (unsigned char *)ipv4) != 1) 2310d547ed0SFan Zhang return -EINVAL; 2320d547ed0SFan Zhang 2330d547ed0SFan Zhang return 0; 2340d547ed0SFan Zhang } 2350d547ed0SFan Zhang 2360d547ed0SFan Zhang int 2370d547ed0SFan Zhang parse_ipv6_addr(const char *token, struct in6_addr *ipv6, 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 { 25107b15619SFan 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) >= INET6_ADDRSTRLEN) 2570d547ed0SFan Zhang return -EINVAL; 2580d547ed0SFan Zhang 2590d547ed0SFan Zhang if (inet_pton6(ip_str, (unsigned char *)ipv6) != 1) 2600d547ed0SFan Zhang return -EINVAL; 2610d547ed0SFan Zhang 2620d547ed0SFan Zhang return 0; 2630d547ed0SFan Zhang } 2640d547ed0SFan Zhang 2650d547ed0SFan Zhang int 2660d547ed0SFan Zhang parse_range(const char *token, uint16_t *low, uint16_t *high) 2670d547ed0SFan Zhang { 2680d547ed0SFan Zhang char ch; 2690d547ed0SFan Zhang char num_str[20]; 2700d547ed0SFan Zhang uint32_t pos; 2710d547ed0SFan Zhang int range_low = -1; 2720d547ed0SFan Zhang int range_high = -1; 2730d547ed0SFan Zhang 2740d547ed0SFan Zhang if (!low || !high) 2750d547ed0SFan Zhang return -1; 2760d547ed0SFan Zhang 2770d547ed0SFan Zhang memset(num_str, 0, 20); 2780d547ed0SFan Zhang pos = 0; 2790d547ed0SFan Zhang 2800d547ed0SFan Zhang while ((ch = *token++) != '\0') { 2810d547ed0SFan Zhang if (isdigit(ch)) { 2820d547ed0SFan Zhang if (pos >= 19) 2830d547ed0SFan Zhang return -1; 2840d547ed0SFan Zhang num_str[pos++] = ch; 2850d547ed0SFan Zhang } else if (ch == ':') { 2860d547ed0SFan Zhang if (range_low != -1) 2870d547ed0SFan Zhang return -1; 2880d547ed0SFan Zhang range_low = atoi(num_str); 2890d547ed0SFan Zhang memset(num_str, 0, 20); 2900d547ed0SFan Zhang pos = 0; 2910d547ed0SFan Zhang } 2920d547ed0SFan Zhang } 2930d547ed0SFan Zhang 2940d547ed0SFan Zhang if (strlen(num_str) == 0) 2950d547ed0SFan Zhang return -1; 2960d547ed0SFan Zhang 2970d547ed0SFan Zhang range_high = atoi(num_str); 2980d547ed0SFan Zhang 2990d547ed0SFan Zhang *low = (uint16_t)range_low; 3000d547ed0SFan Zhang *high = (uint16_t)range_high; 3010d547ed0SFan Zhang 3020d547ed0SFan Zhang return 0; 3030d547ed0SFan Zhang } 3040d547ed0SFan Zhang 3050d547ed0SFan Zhang /** sp add parse */ 3060d547ed0SFan Zhang struct cfg_sp_add_cfg_item { 3070d547ed0SFan Zhang cmdline_fixed_string_t sp_keyword; 3080d547ed0SFan Zhang cmdline_multi_string_t multi_string; 3090d547ed0SFan Zhang }; 3100d547ed0SFan Zhang 3110d547ed0SFan Zhang static void 3120d547ed0SFan Zhang cfg_sp_add_cfg_item_parsed(void *parsed_result, 3130d547ed0SFan Zhang __rte_unused struct cmdline *cl, void *data) 3140d547ed0SFan Zhang { 3150d547ed0SFan Zhang struct cfg_sp_add_cfg_item *params = parsed_result; 3160d547ed0SFan Zhang char *tokens[32]; 3170d547ed0SFan Zhang uint32_t n_tokens = RTE_DIM(tokens); 3180d547ed0SFan Zhang struct parse_status *status = (struct parse_status *)data; 3190d547ed0SFan Zhang 3200d547ed0SFan Zhang APP_CHECK((parse_tokenize_string(params->multi_string, tokens, 3210d547ed0SFan Zhang &n_tokens) == 0), status, "too many arguments"); 3220d547ed0SFan Zhang 3230d547ed0SFan Zhang if (status->status < 0) 3240d547ed0SFan Zhang return; 3250d547ed0SFan Zhang 3260d547ed0SFan Zhang if (strcmp(tokens[0], "ipv4") == 0) { 3270d547ed0SFan Zhang parse_sp4_tokens(tokens, n_tokens, status); 3280d547ed0SFan Zhang if (status->status < 0) 3290d547ed0SFan Zhang return; 3300d547ed0SFan Zhang } else if (strcmp(tokens[0], "ipv6") == 0) { 3310d547ed0SFan Zhang parse_sp6_tokens(tokens, n_tokens, status); 3320d547ed0SFan Zhang if (status->status < 0) 3330d547ed0SFan Zhang return; 3340d547ed0SFan Zhang } else { 3350d547ed0SFan Zhang APP_CHECK(0, status, "unrecognizable input %s\n", 3360d547ed0SFan Zhang tokens[0]); 3370d547ed0SFan Zhang return; 3380d547ed0SFan Zhang } 3390d547ed0SFan Zhang } 3400d547ed0SFan Zhang 3410d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sp_add_sp_str = 3420d547ed0SFan Zhang TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, 3430d547ed0SFan Zhang sp_keyword, "sp"); 3440d547ed0SFan Zhang 3450d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sp_add_multi_str = 3460d547ed0SFan Zhang TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string, 3470d547ed0SFan Zhang TOKEN_STRING_MULTI); 3480d547ed0SFan Zhang 3490d547ed0SFan Zhang cmdline_parse_inst_t cfg_sp_add_rule = { 3500d547ed0SFan Zhang .f = cfg_sp_add_cfg_item_parsed, 3510d547ed0SFan Zhang .data = NULL, 3520d547ed0SFan Zhang .help_str = "", 3530d547ed0SFan Zhang .tokens = { 3540d547ed0SFan Zhang (void *) &cfg_sp_add_sp_str, 3550d547ed0SFan Zhang (void *) &cfg_sp_add_multi_str, 3560d547ed0SFan Zhang NULL, 3570d547ed0SFan Zhang }, 3580d547ed0SFan Zhang }; 3590d547ed0SFan Zhang 3600d547ed0SFan Zhang /* sa add parse */ 3610d547ed0SFan Zhang struct cfg_sa_add_cfg_item { 3620d547ed0SFan Zhang cmdline_fixed_string_t sa_keyword; 3630d547ed0SFan Zhang cmdline_multi_string_t multi_string; 3640d547ed0SFan Zhang }; 3650d547ed0SFan Zhang 3660d547ed0SFan Zhang static void 3670d547ed0SFan Zhang cfg_sa_add_cfg_item_parsed(void *parsed_result, 3680d547ed0SFan Zhang __rte_unused struct cmdline *cl, void *data) 3690d547ed0SFan Zhang { 3700d547ed0SFan Zhang struct cfg_sa_add_cfg_item *params = parsed_result; 3710d547ed0SFan Zhang char *tokens[32]; 3720d547ed0SFan Zhang uint32_t n_tokens = RTE_DIM(tokens); 3730d547ed0SFan Zhang struct parse_status *status = (struct parse_status *)data; 3740d547ed0SFan Zhang 3750d547ed0SFan Zhang APP_CHECK(parse_tokenize_string(params->multi_string, tokens, 3760d547ed0SFan Zhang &n_tokens) == 0, status, "too many arguments\n"); 3770d547ed0SFan Zhang 3780d547ed0SFan Zhang parse_sa_tokens(tokens, n_tokens, status); 3790d547ed0SFan Zhang } 3800d547ed0SFan Zhang 3810d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sa_add_sa_str = 3820d547ed0SFan Zhang TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, 3830d547ed0SFan Zhang sa_keyword, "sa"); 3840d547ed0SFan Zhang 3850d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_sa_add_multi_str = 3860d547ed0SFan Zhang TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string, 3870d547ed0SFan Zhang TOKEN_STRING_MULTI); 3880d547ed0SFan Zhang 3890d547ed0SFan Zhang cmdline_parse_inst_t cfg_sa_add_rule = { 3900d547ed0SFan Zhang .f = cfg_sa_add_cfg_item_parsed, 3910d547ed0SFan Zhang .data = NULL, 3920d547ed0SFan Zhang .help_str = "", 3930d547ed0SFan Zhang .tokens = { 3940d547ed0SFan Zhang (void *) &cfg_sa_add_sa_str, 3950d547ed0SFan Zhang (void *) &cfg_sa_add_multi_str, 3960d547ed0SFan Zhang NULL, 3970d547ed0SFan Zhang }, 3980d547ed0SFan Zhang }; 3990d547ed0SFan Zhang 4000d547ed0SFan Zhang /* rt add parse */ 4010d547ed0SFan Zhang struct cfg_rt_add_cfg_item { 4020d547ed0SFan Zhang cmdline_fixed_string_t rt_keyword; 4030d547ed0SFan Zhang cmdline_multi_string_t multi_string; 4040d547ed0SFan Zhang }; 4050d547ed0SFan Zhang 4060d547ed0SFan Zhang static void 4070d547ed0SFan Zhang cfg_rt_add_cfg_item_parsed(void *parsed_result, 4080d547ed0SFan Zhang __rte_unused struct cmdline *cl, void *data) 4090d547ed0SFan Zhang { 4100d547ed0SFan Zhang struct cfg_rt_add_cfg_item *params = parsed_result; 4110d547ed0SFan Zhang char *tokens[32]; 4120d547ed0SFan Zhang uint32_t n_tokens = RTE_DIM(tokens); 4130d547ed0SFan Zhang struct parse_status *status = (struct parse_status *)data; 4140d547ed0SFan Zhang 4150d547ed0SFan Zhang APP_CHECK(parse_tokenize_string( 4160d547ed0SFan Zhang params->multi_string, tokens, &n_tokens) == 0, 4170d547ed0SFan Zhang status, "too many arguments\n"); 4180d547ed0SFan Zhang if (status->status < 0) 4190d547ed0SFan Zhang return; 4200d547ed0SFan Zhang 4210d547ed0SFan Zhang parse_rt_tokens(tokens, n_tokens, status); 4220d547ed0SFan Zhang } 4230d547ed0SFan Zhang 4240d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_rt_add_rt_str = 4250d547ed0SFan Zhang TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, 4260d547ed0SFan Zhang rt_keyword, "rt"); 4270d547ed0SFan Zhang 4280d547ed0SFan Zhang static cmdline_parse_token_string_t cfg_rt_add_multi_str = 4290d547ed0SFan Zhang TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string, 4300d547ed0SFan Zhang TOKEN_STRING_MULTI); 4310d547ed0SFan Zhang 4320d547ed0SFan Zhang cmdline_parse_inst_t cfg_rt_add_rule = { 4330d547ed0SFan Zhang .f = cfg_rt_add_cfg_item_parsed, 4340d547ed0SFan Zhang .data = NULL, 4350d547ed0SFan Zhang .help_str = "", 4360d547ed0SFan Zhang .tokens = { 4370d547ed0SFan Zhang (void *) &cfg_rt_add_rt_str, 4380d547ed0SFan Zhang (void *) &cfg_rt_add_multi_str, 4390d547ed0SFan Zhang NULL, 4400d547ed0SFan Zhang }, 4410d547ed0SFan Zhang }; 4420d547ed0SFan Zhang 4430d547ed0SFan Zhang /** set of cfg items */ 4440d547ed0SFan Zhang cmdline_parse_ctx_t ipsec_ctx[] = { 4450d547ed0SFan Zhang (cmdline_parse_inst_t *)&cfg_sp_add_rule, 4460d547ed0SFan Zhang (cmdline_parse_inst_t *)&cfg_sa_add_rule, 4470d547ed0SFan Zhang (cmdline_parse_inst_t *)&cfg_rt_add_rule, 4480d547ed0SFan Zhang NULL, 4490d547ed0SFan Zhang }; 4500d547ed0SFan Zhang 4510d547ed0SFan Zhang int 4520d547ed0SFan Zhang parse_cfg_file(const char *cfg_filename) 4530d547ed0SFan Zhang { 4540d547ed0SFan Zhang struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, ""); 4550d547ed0SFan Zhang FILE *f = fopen(cfg_filename, "r"); 4560d547ed0SFan Zhang char str[1024] = {0}, *get_s = NULL; 4570d547ed0SFan Zhang uint32_t line_num = 0; 4580d547ed0SFan Zhang struct parse_status status = {0}; 4590d547ed0SFan Zhang 4600d547ed0SFan Zhang if (f == NULL) { 461a1469c31SFan Zhang rte_panic("Error: invalid file descriptor %s\n", cfg_filename); 4620d547ed0SFan Zhang goto error_exit; 4630d547ed0SFan Zhang } 4640d547ed0SFan Zhang 4650d547ed0SFan Zhang if (cl == NULL) { 4660d547ed0SFan Zhang rte_panic("Error: cannot create cmdline instance\n"); 4670d547ed0SFan Zhang goto error_exit; 4680d547ed0SFan Zhang } 4690d547ed0SFan Zhang 4700d547ed0SFan Zhang cfg_sp_add_rule.data = &status; 4710d547ed0SFan Zhang cfg_sa_add_rule.data = &status; 4720d547ed0SFan Zhang cfg_rt_add_rule.data = &status; 4730d547ed0SFan Zhang 4740d547ed0SFan Zhang do { 4750d547ed0SFan Zhang char oneline[1024]; 4760d547ed0SFan Zhang char *pos; 477a1469c31SFan Zhang get_s = fgets(oneline, 1024, f); 478a1469c31SFan Zhang 479a1469c31SFan Zhang if (!get_s) 480a1469c31SFan Zhang break; 4810d547ed0SFan Zhang 4820d547ed0SFan Zhang line_num++; 4830d547ed0SFan Zhang 4840d547ed0SFan Zhang if (strlen(oneline) > 1022) { 485a1469c31SFan Zhang rte_panic("%s:%u: error: " 486a1469c31SFan Zhang "the line contains more characters the parser can handle\n", 4870d547ed0SFan Zhang cfg_filename, line_num); 4880d547ed0SFan Zhang goto error_exit; 4890d547ed0SFan Zhang } 4900d547ed0SFan Zhang 4910d547ed0SFan Zhang /* process comment char '#' */ 4920d547ed0SFan Zhang if (oneline[0] == '#') 4930d547ed0SFan Zhang continue; 4940d547ed0SFan Zhang 4950d547ed0SFan Zhang pos = strchr(oneline, '#'); 4960d547ed0SFan Zhang if (pos != NULL) 4970d547ed0SFan Zhang *pos = '\0'; 4980d547ed0SFan Zhang 4990d547ed0SFan Zhang /* process line concatenator '\' */ 5000d547ed0SFan Zhang pos = strchr(oneline, 92); 5010d547ed0SFan Zhang if (pos != NULL) { 5020d547ed0SFan Zhang if (pos != oneline+strlen(oneline) - 2) { 503a1469c31SFan Zhang rte_panic("%s:%u: error: " 504a1469c31SFan Zhang "no character should exist after '\\'\n", 5050d547ed0SFan Zhang cfg_filename, line_num); 5060d547ed0SFan Zhang goto error_exit; 5070d547ed0SFan Zhang } 5080d547ed0SFan Zhang 5090d547ed0SFan Zhang *pos = '\0'; 5100d547ed0SFan Zhang 5110d547ed0SFan Zhang if (strlen(oneline) + strlen(str) > 1022) { 512a1469c31SFan Zhang rte_panic("%s:%u: error: " 513a1469c31SFan Zhang "the concatenated line contains more characters the parser can handle\n", 5140d547ed0SFan Zhang cfg_filename, line_num); 5150d547ed0SFan Zhang goto error_exit; 5160d547ed0SFan Zhang } 5170d547ed0SFan Zhang 5180d547ed0SFan Zhang strncpy(str + strlen(str), oneline, 5190d547ed0SFan Zhang strlen(oneline)); 5200d547ed0SFan Zhang 5210d547ed0SFan Zhang continue; 5220d547ed0SFan Zhang } 5230d547ed0SFan Zhang 5240d547ed0SFan Zhang /* copy the line to str and process */ 5250d547ed0SFan Zhang if (strlen(oneline) + strlen(str) > 1022) { 526a1469c31SFan Zhang rte_panic("%s:%u: error: " 527a1469c31SFan Zhang "the line contains more characters the parser can handle\n", 5280d547ed0SFan Zhang cfg_filename, line_num); 5290d547ed0SFan Zhang goto error_exit; 5300d547ed0SFan Zhang } 5310d547ed0SFan Zhang strncpy(str + strlen(str), oneline, 5320d547ed0SFan Zhang strlen(oneline)); 5330d547ed0SFan Zhang 5340d547ed0SFan Zhang str[strlen(str)] = '\n'; 5350d547ed0SFan Zhang if (cmdline_parse(cl, str) < 0) { 536a1469c31SFan Zhang rte_panic("%s:%u: error: parsing \"%s\" failed\n", 537a1469c31SFan Zhang cfg_filename, line_num, str); 5380d547ed0SFan Zhang goto error_exit; 5390d547ed0SFan Zhang } 5400d547ed0SFan Zhang 5410d547ed0SFan Zhang if (status.status < 0) { 542a1469c31SFan Zhang rte_panic("%s:%u: error: %s", cfg_filename, 543a1469c31SFan Zhang line_num, status.parse_msg); 5440d547ed0SFan Zhang goto error_exit; 5450d547ed0SFan Zhang } 5460d547ed0SFan Zhang 5470d547ed0SFan Zhang memset(str, 0, 1024); 548a1469c31SFan Zhang } while (1); 5490d547ed0SFan Zhang 5500d547ed0SFan Zhang cmdline_stdin_exit(cl); 5510d547ed0SFan Zhang fclose(f); 5520d547ed0SFan Zhang 5530d547ed0SFan Zhang return 0; 5540d547ed0SFan Zhang 5550d547ed0SFan Zhang error_exit: 5560d547ed0SFan Zhang if (cl) 5570d547ed0SFan Zhang cmdline_stdin_exit(cl); 5580d547ed0SFan Zhang if (f) 5590d547ed0SFan Zhang fclose(f); 5600d547ed0SFan Zhang 5610d547ed0SFan Zhang return -1; 5620d547ed0SFan Zhang } 563