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