1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016 Intel Corporation
6 #include <sys/socket.h>
8 #include <rte_common.h>
9 #include <rte_crypto.h>
10 #include <rte_string_fns.h>
12 #include <cmdline_parse_string.h>
13 #include <cmdline_parse_num.h>
14 #include <cmdline_parse_ipaddr.h>
15 #include <cmdline_socket.h>
22 #define PARSE_DELIMITER " \f\n\r\t\v"
24 parse_tokenize_string(char *string
, char *tokens
[], uint32_t *n_tokens
)
28 if ((string
== NULL
) ||
33 for (i
= 0; i
< *n_tokens
; i
++) {
34 tokens
[i
] = strtok_r(string
, PARSE_DELIMITER
, &string
);
35 if (tokens
[i
] == NULL
)
39 if ((i
== *n_tokens
) &&
40 (NULL
!= strtok_r(string
, PARSE_DELIMITER
, &string
)))
48 parse_ipv4_addr(const char *token
, struct in_addr
*ipv4
, uint32_t *mask
)
50 char ip_str
[INET_ADDRSTRLEN
] = {0};
53 pch
= strchr(token
, '/');
55 strlcpy(ip_str
, token
,
56 RTE_MIN((unsigned int long)(pch
- token
+ 1),
59 if (is_str_num(pch
) != 0)
64 strlcpy(ip_str
, token
, sizeof(ip_str
));
68 if (strlen(ip_str
) >= INET_ADDRSTRLEN
)
71 if (inet_pton(AF_INET
, ip_str
, ipv4
) != 1)
78 parse_ipv6_addr(const char *token
, struct in6_addr
*ipv6
, uint32_t *mask
)
80 char ip_str
[256] = {0};
83 pch
= strchr(token
, '/');
85 strlcpy(ip_str
, token
,
86 RTE_MIN((unsigned int long)(pch
- token
+ 1),
89 if (is_str_num(pch
) != 0)
94 strlcpy(ip_str
, token
, sizeof(ip_str
));
99 if (strlen(ip_str
) >= INET6_ADDRSTRLEN
)
102 if (inet_pton(AF_INET6
, ip_str
, ipv6
) != 1)
109 parse_range(const char *token
, uint16_t *low
, uint16_t *high
)
120 memset(num_str
, 0, 20);
123 while ((ch
= *token
++) != '\0') {
128 } else if (ch
== ':') {
131 range_low
= atoi(num_str
);
132 memset(num_str
, 0, 20);
137 if (strlen(num_str
) == 0)
140 range_high
= atoi(num_str
);
142 *low
= (uint16_t)range_low
;
143 *high
= (uint16_t)range_high
;
149 * helper function for parse_mac, parse one section of the ether addr.
152 parse_uint8x16(const char *s
, uint8_t *v
, uint8_t ls
)
158 t
= strtoul(s
, &end
, 16);
159 if (errno
!= 0 || end
[0] != ls
|| t
> UINT8_MAX
)
166 parse_mac(const char *str
, struct rte_ether_addr
*addr
)
170 static const uint8_t stop_sym
[RTE_DIM(addr
->addr_bytes
)] = {
179 for (i
= 0; i
!= RTE_DIM(addr
->addr_bytes
); i
++) {
180 str
= parse_uint8x16(str
, addr
->addr_bytes
+ i
, stop_sym
[i
]);
189 struct cfg_sp_add_cfg_item
{
190 cmdline_fixed_string_t sp_keyword
;
191 cmdline_multi_string_t multi_string
;
195 cfg_sp_add_cfg_item_parsed(void *parsed_result
,
196 __rte_unused
struct cmdline
*cl
, void *data
)
198 struct cfg_sp_add_cfg_item
*params
= parsed_result
;
200 uint32_t n_tokens
= RTE_DIM(tokens
);
201 struct parse_status
*status
= (struct parse_status
*)data
;
203 APP_CHECK((parse_tokenize_string(params
->multi_string
, tokens
,
204 &n_tokens
) == 0), status
, "too many arguments");
206 if (status
->status
< 0)
209 if (strcmp(tokens
[0], "ipv4") == 0) {
210 parse_sp4_tokens(tokens
, n_tokens
, status
);
211 if (status
->status
< 0)
213 } else if (strcmp(tokens
[0], "ipv6") == 0) {
214 parse_sp6_tokens(tokens
, n_tokens
, status
);
215 if (status
->status
< 0)
218 APP_CHECK(0, status
, "unrecognizable input %s\n",
224 static cmdline_parse_token_string_t cfg_sp_add_sp_str
=
225 TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item
,
228 static cmdline_parse_token_string_t cfg_sp_add_multi_str
=
229 TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item
, multi_string
,
232 cmdline_parse_inst_t cfg_sp_add_rule
= {
233 .f
= cfg_sp_add_cfg_item_parsed
,
237 (void *) &cfg_sp_add_sp_str
,
238 (void *) &cfg_sp_add_multi_str
,
244 struct cfg_sa_add_cfg_item
{
245 cmdline_fixed_string_t sa_keyword
;
246 cmdline_multi_string_t multi_string
;
250 cfg_sa_add_cfg_item_parsed(void *parsed_result
,
251 __rte_unused
struct cmdline
*cl
, void *data
)
253 struct cfg_sa_add_cfg_item
*params
= parsed_result
;
255 uint32_t n_tokens
= RTE_DIM(tokens
);
256 struct parse_status
*status
= (struct parse_status
*)data
;
258 APP_CHECK(parse_tokenize_string(params
->multi_string
, tokens
,
259 &n_tokens
) == 0, status
, "too many arguments\n");
261 parse_sa_tokens(tokens
, n_tokens
, status
);
264 static cmdline_parse_token_string_t cfg_sa_add_sa_str
=
265 TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item
,
268 static cmdline_parse_token_string_t cfg_sa_add_multi_str
=
269 TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item
, multi_string
,
272 cmdline_parse_inst_t cfg_sa_add_rule
= {
273 .f
= cfg_sa_add_cfg_item_parsed
,
277 (void *) &cfg_sa_add_sa_str
,
278 (void *) &cfg_sa_add_multi_str
,
284 struct cfg_rt_add_cfg_item
{
285 cmdline_fixed_string_t rt_keyword
;
286 cmdline_multi_string_t multi_string
;
290 cfg_rt_add_cfg_item_parsed(void *parsed_result
,
291 __rte_unused
struct cmdline
*cl
, void *data
)
293 struct cfg_rt_add_cfg_item
*params
= parsed_result
;
295 uint32_t n_tokens
= RTE_DIM(tokens
);
296 struct parse_status
*status
= (struct parse_status
*)data
;
298 APP_CHECK(parse_tokenize_string(
299 params
->multi_string
, tokens
, &n_tokens
) == 0,
300 status
, "too many arguments\n");
301 if (status
->status
< 0)
304 parse_rt_tokens(tokens
, n_tokens
, status
);
307 static cmdline_parse_token_string_t cfg_rt_add_rt_str
=
308 TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item
,
311 static cmdline_parse_token_string_t cfg_rt_add_multi_str
=
312 TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item
, multi_string
,
315 cmdline_parse_inst_t cfg_rt_add_rule
= {
316 .f
= cfg_rt_add_cfg_item_parsed
,
320 (void *) &cfg_rt_add_rt_str
,
321 (void *) &cfg_rt_add_multi_str
,
327 struct cfg_flow_add_cfg_item
{
328 cmdline_fixed_string_t flow_keyword
;
329 cmdline_multi_string_t multi_string
;
333 cfg_flow_add_cfg_item_parsed(void *parsed_result
,
334 __rte_unused
struct cmdline
*cl
, void *data
)
336 struct cfg_flow_add_cfg_item
*params
= parsed_result
;
338 uint32_t n_tokens
= RTE_DIM(tokens
);
339 struct parse_status
*status
= (struct parse_status
*)data
;
341 APP_CHECK(parse_tokenize_string(
342 params
->multi_string
, tokens
, &n_tokens
) == 0,
343 status
, "too many arguments\n");
344 if (status
->status
< 0)
347 parse_flow_tokens(tokens
, n_tokens
, status
);
350 static cmdline_parse_token_string_t cfg_flow_add_flow_str
=
351 TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item
,
352 flow_keyword
, "flow");
354 static cmdline_parse_token_string_t cfg_flow_add_multi_str
=
355 TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item
, multi_string
,
358 cmdline_parse_inst_t cfg_flow_add_rule
= {
359 .f
= cfg_flow_add_cfg_item_parsed
,
363 (void *) &cfg_flow_add_flow_str
,
364 (void *) &cfg_flow_add_multi_str
,
369 /* neigh add parse */
370 struct cfg_neigh_add_item
{
371 cmdline_fixed_string_t neigh
;
372 cmdline_fixed_string_t pstr
;
374 cmdline_fixed_string_t mac
;
378 cfg_parse_neigh(void *parsed_result
, __rte_unused
struct cmdline
*cl
,
382 struct cfg_neigh_add_item
*res
;
383 struct parse_status
*st
;
384 struct rte_ether_addr mac
;
388 rc
= parse_mac(res
->mac
, &mac
);
389 APP_CHECK(rc
== 0, st
, "invalid ether addr:%s", res
->mac
);
390 rc
= add_dst_ethaddr(res
->port
, &mac
);
391 APP_CHECK(rc
== 0, st
, "invalid port numer:%hu", res
->port
);
396 cmdline_parse_token_string_t cfg_add_neigh_start
=
397 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item
, neigh
, "neigh");
398 cmdline_parse_token_string_t cfg_add_neigh_pstr
=
399 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item
, pstr
, "port");
400 cmdline_parse_token_num_t cfg_add_neigh_port
=
401 TOKEN_NUM_INITIALIZER(struct cfg_neigh_add_item
, port
, RTE_UINT16
);
402 cmdline_parse_token_string_t cfg_add_neigh_mac
=
403 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item
, mac
, NULL
);
405 cmdline_parse_inst_t cfg_neigh_add_rule
= {
406 .f
= cfg_parse_neigh
,
410 (void *)&cfg_add_neigh_start
,
411 (void *)&cfg_add_neigh_pstr
,
412 (void *)&cfg_add_neigh_port
,
413 (void *)&cfg_add_neigh_mac
,
418 /** set of cfg items */
419 cmdline_parse_ctx_t ipsec_ctx
[] = {
420 (cmdline_parse_inst_t
*)&cfg_sp_add_rule
,
421 (cmdline_parse_inst_t
*)&cfg_sa_add_rule
,
422 (cmdline_parse_inst_t
*)&cfg_rt_add_rule
,
423 (cmdline_parse_inst_t
*)&cfg_flow_add_rule
,
424 (cmdline_parse_inst_t
*)&cfg_neigh_add_rule
,
429 parse_cfg_file(const char *cfg_filename
)
431 struct cmdline
*cl
= cmdline_stdin_new(ipsec_ctx
, "");
432 FILE *f
= fopen(cfg_filename
, "r");
433 char str
[1024] = {0}, *get_s
= NULL
;
434 uint32_t line_num
= 0;
435 struct parse_status status
= {0};
438 rte_panic("Error: invalid file descriptor %s\n", cfg_filename
);
443 rte_panic("Error: cannot create cmdline instance\n");
447 cfg_sp_add_rule
.data
= &status
;
448 cfg_sa_add_rule
.data
= &status
;
449 cfg_rt_add_rule
.data
= &status
;
450 cfg_flow_add_rule
.data
= &status
;
451 cfg_neigh_add_rule
.data
= &status
;
456 get_s
= fgets(oneline
, 1024, f
);
463 if (strlen(oneline
) > 1022) {
464 rte_panic("%s:%u: error: "
465 "the line contains more characters the parser can handle\n",
466 cfg_filename
, line_num
);
470 /* process comment char '#' */
471 if (oneline
[0] == '#')
474 pos
= strchr(oneline
, '#');
478 /* process line concatenator '\' */
479 pos
= strchr(oneline
, 92);
481 if (pos
!= oneline
+strlen(oneline
) - 2) {
482 rte_panic("%s:%u: error: "
483 "no character should exist after '\\'\n",
484 cfg_filename
, line_num
);
490 if (strlen(oneline
) + strlen(str
) > 1022) {
491 rte_panic("%s:%u: error: "
492 "the concatenated line contains more characters the parser can handle\n",
493 cfg_filename
, line_num
);
497 strcpy(str
+ strlen(str
), oneline
);
501 /* copy the line to str and process */
502 if (strlen(oneline
) + strlen(str
) > 1022) {
503 rte_panic("%s:%u: error: "
504 "the line contains more characters the parser can handle\n",
505 cfg_filename
, line_num
);
508 strcpy(str
+ strlen(str
), oneline
);
510 str
[strlen(str
)] = '\n';
511 if (cmdline_parse(cl
, str
) < 0) {
512 rte_panic("%s:%u: error: parsing \"%s\" failed\n",
513 cfg_filename
, line_num
, str
);
517 if (status
.status
< 0) {
518 rte_panic("%s:%u: error: %s", cfg_filename
,
519 line_num
, status
.parse_msg
);
523 memset(str
, 0, 1024);
526 cmdline_stdin_exit(cl
);
537 cmdline_stdin_exit(cl
);