1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016 Intel Corporation
5 #include <sys/socket.h>
7 #include <rte_common.h>
8 #include <rte_crypto.h>
9 #include <rte_string_fns.h>
11 #include <cmdline_parse_string.h>
12 #include <cmdline_parse_num.h>
13 #include <cmdline_parse_ipaddr.h>
14 #include <cmdline_socket.h>
21 #define PARSE_DELIMITER " \f\n\r\t\v"
23 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
27 if ((string == NULL) ||
32 for (i = 0; i < *n_tokens; i++) {
33 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
34 if (tokens[i] == NULL)
38 if ((i == *n_tokens) &&
39 (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
47 parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
49 char ip_str[INET_ADDRSTRLEN] = {0};
52 pch = strchr(token, '/');
54 strlcpy(ip_str, token,
55 RTE_MIN((unsigned int long)(pch - token + 1),
58 if (is_str_num(pch) != 0)
63 strlcpy(ip_str, token, sizeof(ip_str));
67 if (strlen(ip_str) >= INET_ADDRSTRLEN)
70 if (inet_pton(AF_INET, ip_str, ipv4) != 1)
77 parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
79 char ip_str[256] = {0};
82 pch = strchr(token, '/');
84 strlcpy(ip_str, token,
85 RTE_MIN((unsigned int long)(pch - token + 1),
88 if (is_str_num(pch) != 0)
93 strlcpy(ip_str, token, sizeof(ip_str));
98 if (strlen(ip_str) >= INET6_ADDRSTRLEN)
101 if (inet_pton(AF_INET6, ip_str, ipv6) != 1)
108 parse_range(const char *token, uint16_t *low, uint16_t *high)
119 memset(num_str, 0, 20);
122 while ((ch = *token++) != '\0') {
127 } else if (ch == ':') {
130 range_low = atoi(num_str);
131 memset(num_str, 0, 20);
136 if (strlen(num_str) == 0)
139 range_high = atoi(num_str);
141 *low = (uint16_t)range_low;
142 *high = (uint16_t)range_high;
148 * helper function for parse_mac, parse one section of the ether addr.
151 parse_uint8x16(const char *s, uint8_t *v, uint8_t ls)
157 t = strtoul(s, &end, 16);
158 if (errno != 0 || end[0] != ls || t > UINT8_MAX)
165 parse_mac(const char *str, struct rte_ether_addr *addr)
169 static const uint8_t stop_sym[RTE_DIM(addr->addr_bytes)] = {
178 for (i = 0; i != RTE_DIM(addr->addr_bytes); i++) {
179 str = parse_uint8x16(str, addr->addr_bytes + i, stop_sym[i]);
188 struct cfg_sp_add_cfg_item {
189 cmdline_fixed_string_t sp_keyword;
190 cmdline_multi_string_t multi_string;
194 cfg_sp_add_cfg_item_parsed(void *parsed_result,
195 __rte_unused struct cmdline *cl, void *data)
197 struct cfg_sp_add_cfg_item *params = parsed_result;
199 uint32_t n_tokens = RTE_DIM(tokens);
200 struct parse_status *status = (struct parse_status *)data;
202 APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
203 &n_tokens) == 0), status, "too many arguments");
205 if (status->status < 0)
208 if (strcmp(tokens[0], "ipv4") == 0) {
209 parse_sp4_tokens(tokens, n_tokens, status);
210 if (status->status < 0)
212 } else if (strcmp(tokens[0], "ipv6") == 0) {
213 parse_sp6_tokens(tokens, n_tokens, status);
214 if (status->status < 0)
217 APP_CHECK(0, status, "unrecognizable input %s\n",
223 static cmdline_parse_token_string_t cfg_sp_add_sp_str =
224 TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
227 static cmdline_parse_token_string_t cfg_sp_add_multi_str =
228 TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
231 cmdline_parse_inst_t cfg_sp_add_rule = {
232 .f = cfg_sp_add_cfg_item_parsed,
236 (void *) &cfg_sp_add_sp_str,
237 (void *) &cfg_sp_add_multi_str,
243 struct cfg_sa_add_cfg_item {
244 cmdline_fixed_string_t sa_keyword;
245 cmdline_multi_string_t multi_string;
249 cfg_sa_add_cfg_item_parsed(void *parsed_result,
250 __rte_unused struct cmdline *cl, void *data)
252 struct cfg_sa_add_cfg_item *params = parsed_result;
254 uint32_t n_tokens = RTE_DIM(tokens);
255 struct parse_status *status = (struct parse_status *)data;
257 APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
258 &n_tokens) == 0, status, "too many arguments\n");
260 parse_sa_tokens(tokens, n_tokens, status);
263 static cmdline_parse_token_string_t cfg_sa_add_sa_str =
264 TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
267 static cmdline_parse_token_string_t cfg_sa_add_multi_str =
268 TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
271 cmdline_parse_inst_t cfg_sa_add_rule = {
272 .f = cfg_sa_add_cfg_item_parsed,
276 (void *) &cfg_sa_add_sa_str,
277 (void *) &cfg_sa_add_multi_str,
283 struct cfg_rt_add_cfg_item {
284 cmdline_fixed_string_t rt_keyword;
285 cmdline_multi_string_t multi_string;
289 cfg_rt_add_cfg_item_parsed(void *parsed_result,
290 __rte_unused struct cmdline *cl, void *data)
292 struct cfg_rt_add_cfg_item *params = parsed_result;
294 uint32_t n_tokens = RTE_DIM(tokens);
295 struct parse_status *status = (struct parse_status *)data;
297 APP_CHECK(parse_tokenize_string(
298 params->multi_string, tokens, &n_tokens) == 0,
299 status, "too many arguments\n");
300 if (status->status < 0)
303 parse_rt_tokens(tokens, n_tokens, status);
306 static cmdline_parse_token_string_t cfg_rt_add_rt_str =
307 TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
310 static cmdline_parse_token_string_t cfg_rt_add_multi_str =
311 TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
314 cmdline_parse_inst_t cfg_rt_add_rule = {
315 .f = cfg_rt_add_cfg_item_parsed,
319 (void *) &cfg_rt_add_rt_str,
320 (void *) &cfg_rt_add_multi_str,
326 struct cfg_flow_add_cfg_item {
327 cmdline_fixed_string_t flow_keyword;
328 cmdline_multi_string_t multi_string;
332 cfg_flow_add_cfg_item_parsed(void *parsed_result,
333 __rte_unused struct cmdline *cl, void *data)
335 struct cfg_flow_add_cfg_item *params = parsed_result;
337 uint32_t n_tokens = RTE_DIM(tokens);
338 struct parse_status *status = (struct parse_status *)data;
340 APP_CHECK(parse_tokenize_string(
341 params->multi_string, tokens, &n_tokens) == 0,
342 status, "too many arguments\n");
343 if (status->status < 0)
346 parse_flow_tokens(tokens, n_tokens, status);
349 static cmdline_parse_token_string_t cfg_flow_add_flow_str =
350 TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
351 flow_keyword, "flow");
353 static cmdline_parse_token_string_t cfg_flow_add_multi_str =
354 TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item, multi_string,
357 cmdline_parse_inst_t cfg_flow_add_rule = {
358 .f = cfg_flow_add_cfg_item_parsed,
362 (void *) &cfg_flow_add_flow_str,
363 (void *) &cfg_flow_add_multi_str,
368 /* neigh add parse */
369 struct cfg_neigh_add_item {
370 cmdline_fixed_string_t neigh;
371 cmdline_fixed_string_t pstr;
373 cmdline_fixed_string_t mac;
377 cfg_parse_neigh(void *parsed_result, __rte_unused struct cmdline *cl,
381 struct cfg_neigh_add_item *res;
382 struct parse_status *st;
383 struct rte_ether_addr mac;
387 rc = parse_mac(res->mac, &mac);
388 APP_CHECK(rc == 0, st, "invalid ether addr:%s", res->mac);
389 rc = add_dst_ethaddr(res->port, &mac);
390 APP_CHECK(rc == 0, st, "invalid port numer:%hu", res->port);
395 cmdline_parse_token_string_t cfg_add_neigh_start =
396 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, neigh, "neigh");
397 cmdline_parse_token_string_t cfg_add_neigh_pstr =
398 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, pstr, "port");
399 cmdline_parse_token_num_t cfg_add_neigh_port =
400 TOKEN_NUM_INITIALIZER(struct cfg_neigh_add_item, port, RTE_UINT16);
401 cmdline_parse_token_string_t cfg_add_neigh_mac =
402 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, mac, NULL);
404 cmdline_parse_inst_t cfg_neigh_add_rule = {
405 .f = cfg_parse_neigh,
409 (void *)&cfg_add_neigh_start,
410 (void *)&cfg_add_neigh_pstr,
411 (void *)&cfg_add_neigh_port,
412 (void *)&cfg_add_neigh_mac,
417 /** set of cfg items */
418 cmdline_parse_ctx_t ipsec_ctx[] = {
419 (cmdline_parse_inst_t *)&cfg_sp_add_rule,
420 (cmdline_parse_inst_t *)&cfg_sa_add_rule,
421 (cmdline_parse_inst_t *)&cfg_rt_add_rule,
422 (cmdline_parse_inst_t *)&cfg_flow_add_rule,
423 (cmdline_parse_inst_t *)&cfg_neigh_add_rule,
428 parse_cfg_file(const char *cfg_filename)
430 struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, "");
431 FILE *f = fopen(cfg_filename, "r");
432 char str[1024] = {0}, *get_s = NULL;
433 uint32_t line_num = 0;
434 struct parse_status status = {0};
437 rte_panic("Error: invalid file descriptor %s\n", cfg_filename);
442 rte_panic("Error: cannot create cmdline instance\n");
446 cfg_sp_add_rule.data = &status;
447 cfg_sa_add_rule.data = &status;
448 cfg_rt_add_rule.data = &status;
449 cfg_flow_add_rule.data = &status;
450 cfg_neigh_add_rule.data = &status;
455 get_s = fgets(oneline, 1024, f);
462 if (strlen(oneline) > 1022) {
463 rte_panic("%s:%u: error: "
464 "the line contains more characters the parser can handle\n",
465 cfg_filename, line_num);
469 /* process comment char '#' */
470 if (oneline[0] == '#')
473 pos = strchr(oneline, '#');
477 /* process line concatenator '\' */
478 pos = strchr(oneline, 92);
480 if (pos != oneline+strlen(oneline) - 2) {
481 rte_panic("%s:%u: error: "
482 "no character should exist after '\\'\n",
483 cfg_filename, line_num);
489 if (strlen(oneline) + strlen(str) > 1022) {
490 rte_panic("%s:%u: error: "
491 "the concatenated line contains more characters the parser can handle\n",
492 cfg_filename, line_num);
496 strcpy(str + strlen(str), oneline);
500 /* copy the line to str and process */
501 if (strlen(oneline) + strlen(str) > 1022) {
502 rte_panic("%s:%u: error: "
503 "the line contains more characters the parser can handle\n",
504 cfg_filename, line_num);
507 strcpy(str + strlen(str), oneline);
509 str[strlen(str)] = '\n';
510 if (cmdline_parse(cl, str) < 0) {
511 rte_panic("%s:%u: error: parsing \"%s\" failed\n",
512 cfg_filename, line_num, str);
516 if (status.status < 0) {
517 rte_panic("%s:%u: error: %s", cfg_filename,
518 line_num, status.parse_msg);
522 memset(str, 0, 1024);
525 cmdline_stdin_exit(cl);
536 cmdline_stdin_exit(cl);