]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/dpdk/examples/ipsec-secgw/parser.c
bump version to 19.2.0-pve1
[ceph.git] / ceph / src / seastar / dpdk / examples / ipsec-secgw / parser.c
CommitLineData
9f95a23c
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016 Intel Corporation
7c673cae 3 */
f51cf556
TL
4#include <stdlib.h>
5#include <arpa/inet.h>
6#include <sys/socket.h>
7
7c673cae
FG
8#include <rte_common.h>
9#include <rte_crypto.h>
9f95a23c 10#include <rte_string_fns.h>
7c673cae
FG
11
12#include <cmdline_parse_string.h>
13#include <cmdline_parse_num.h>
14#include <cmdline_parse_ipaddr.h>
15#include <cmdline_socket.h>
16#include <cmdline.h>
17
f51cf556 18#include "flow.h"
7c673cae
FG
19#include "ipsec.h"
20#include "parser.h"
21
22#define PARSE_DELIMITER " \f\n\r\t\v"
23static int
24parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
25{
26 uint32_t i;
27
28 if ((string == NULL) ||
29 (tokens == NULL) ||
30 (*n_tokens < 1))
31 return -EINVAL;
32
33 for (i = 0; i < *n_tokens; i++) {
34 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
35 if (tokens[i] == NULL)
36 break;
37 }
38
39 if ((i == *n_tokens) &&
40 (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
41 return -E2BIG;
42
43 *n_tokens = i;
44 return 0;
45}
46
7c673cae
FG
47int
48parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
49{
9f95a23c 50 char ip_str[INET_ADDRSTRLEN] = {0};
7c673cae
FG
51 char *pch;
52
53 pch = strchr(token, '/');
54 if (pch != NULL) {
9f95a23c
TL
55 strlcpy(ip_str, token,
56 RTE_MIN((unsigned int long)(pch - token + 1),
57 sizeof(ip_str)));
7c673cae
FG
58 pch += 1;
59 if (is_str_num(pch) != 0)
60 return -EINVAL;
61 if (mask)
62 *mask = atoi(pch);
63 } else {
9f95a23c 64 strlcpy(ip_str, token, sizeof(ip_str));
7c673cae
FG
65 if (mask)
66 *mask = 0;
67 }
7c673cae
FG
68 if (strlen(ip_str) >= INET_ADDRSTRLEN)
69 return -EINVAL;
70
f51cf556 71 if (inet_pton(AF_INET, ip_str, ipv4) != 1)
7c673cae
FG
72 return -EINVAL;
73
74 return 0;
75}
76
77int
78parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
79{
80 char ip_str[256] = {0};
81 char *pch;
82
83 pch = strchr(token, '/');
84 if (pch != NULL) {
9f95a23c
TL
85 strlcpy(ip_str, token,
86 RTE_MIN((unsigned int long)(pch - token + 1),
87 sizeof(ip_str)));
7c673cae
FG
88 pch += 1;
89 if (is_str_num(pch) != 0)
90 return -EINVAL;
91 if (mask)
92 *mask = atoi(pch);
93 } else {
9f95a23c 94 strlcpy(ip_str, token, sizeof(ip_str));
7c673cae
FG
95 if (mask)
96 *mask = 0;
97 }
98
99 if (strlen(ip_str) >= INET6_ADDRSTRLEN)
100 return -EINVAL;
101
f51cf556 102 if (inet_pton(AF_INET6, ip_str, ipv6) != 1)
7c673cae
FG
103 return -EINVAL;
104
105 return 0;
106}
107
108int
109parse_range(const char *token, uint16_t *low, uint16_t *high)
110{
111 char ch;
112 char num_str[20];
113 uint32_t pos;
114 int range_low = -1;
115 int range_high = -1;
116
117 if (!low || !high)
118 return -1;
119
120 memset(num_str, 0, 20);
121 pos = 0;
122
123 while ((ch = *token++) != '\0') {
124 if (isdigit(ch)) {
125 if (pos >= 19)
126 return -1;
127 num_str[pos++] = ch;
128 } else if (ch == ':') {
129 if (range_low != -1)
130 return -1;
131 range_low = atoi(num_str);
132 memset(num_str, 0, 20);
133 pos = 0;
134 }
135 }
136
137 if (strlen(num_str) == 0)
138 return -1;
139
140 range_high = atoi(num_str);
141
142 *low = (uint16_t)range_low;
143 *high = (uint16_t)range_high;
144
145 return 0;
146}
147
9f95a23c
TL
148/*
149 * helper function for parse_mac, parse one section of the ether addr.
150 */
151static const char *
152parse_uint8x16(const char *s, uint8_t *v, uint8_t ls)
153{
154 char *end;
155 unsigned long t;
156
157 errno = 0;
158 t = strtoul(s, &end, 16);
159 if (errno != 0 || end[0] != ls || t > UINT8_MAX)
160 return NULL;
161 v[0] = t;
162 return end + 1;
163}
164
165static int
f51cf556 166parse_mac(const char *str, struct rte_ether_addr *addr)
9f95a23c
TL
167{
168 uint32_t i;
169
170 static const uint8_t stop_sym[RTE_DIM(addr->addr_bytes)] = {
171 [0] = ':',
172 [1] = ':',
173 [2] = ':',
174 [3] = ':',
175 [4] = ':',
176 [5] = 0,
177 };
178
179 for (i = 0; i != RTE_DIM(addr->addr_bytes); i++) {
180 str = parse_uint8x16(str, addr->addr_bytes + i, stop_sym[i]);
181 if (str == NULL)
182 return -EINVAL;
183 }
184
185 return 0;
186}
187
7c673cae
FG
188/** sp add parse */
189struct cfg_sp_add_cfg_item {
190 cmdline_fixed_string_t sp_keyword;
191 cmdline_multi_string_t multi_string;
192};
193
194static void
195cfg_sp_add_cfg_item_parsed(void *parsed_result,
196 __rte_unused struct cmdline *cl, void *data)
197{
198 struct cfg_sp_add_cfg_item *params = parsed_result;
199 char *tokens[32];
200 uint32_t n_tokens = RTE_DIM(tokens);
201 struct parse_status *status = (struct parse_status *)data;
202
203 APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
204 &n_tokens) == 0), status, "too many arguments");
205
206 if (status->status < 0)
207 return;
208
209 if (strcmp(tokens[0], "ipv4") == 0) {
210 parse_sp4_tokens(tokens, n_tokens, status);
211 if (status->status < 0)
212 return;
213 } else if (strcmp(tokens[0], "ipv6") == 0) {
214 parse_sp6_tokens(tokens, n_tokens, status);
215 if (status->status < 0)
216 return;
217 } else {
218 APP_CHECK(0, status, "unrecognizable input %s\n",
219 tokens[0]);
220 return;
221 }
222}
223
224static cmdline_parse_token_string_t cfg_sp_add_sp_str =
225 TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
226 sp_keyword, "sp");
227
228static cmdline_parse_token_string_t cfg_sp_add_multi_str =
229 TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
230 TOKEN_STRING_MULTI);
231
232cmdline_parse_inst_t cfg_sp_add_rule = {
233 .f = cfg_sp_add_cfg_item_parsed,
234 .data = NULL,
235 .help_str = "",
236 .tokens = {
237 (void *) &cfg_sp_add_sp_str,
238 (void *) &cfg_sp_add_multi_str,
239 NULL,
240 },
241};
242
243/* sa add parse */
244struct cfg_sa_add_cfg_item {
245 cmdline_fixed_string_t sa_keyword;
246 cmdline_multi_string_t multi_string;
247};
248
249static void
250cfg_sa_add_cfg_item_parsed(void *parsed_result,
251 __rte_unused struct cmdline *cl, void *data)
252{
253 struct cfg_sa_add_cfg_item *params = parsed_result;
254 char *tokens[32];
255 uint32_t n_tokens = RTE_DIM(tokens);
256 struct parse_status *status = (struct parse_status *)data;
257
258 APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
259 &n_tokens) == 0, status, "too many arguments\n");
260
261 parse_sa_tokens(tokens, n_tokens, status);
262}
263
264static cmdline_parse_token_string_t cfg_sa_add_sa_str =
265 TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
266 sa_keyword, "sa");
267
268static cmdline_parse_token_string_t cfg_sa_add_multi_str =
269 TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
270 TOKEN_STRING_MULTI);
271
272cmdline_parse_inst_t cfg_sa_add_rule = {
273 .f = cfg_sa_add_cfg_item_parsed,
274 .data = NULL,
275 .help_str = "",
276 .tokens = {
277 (void *) &cfg_sa_add_sa_str,
278 (void *) &cfg_sa_add_multi_str,
279 NULL,
280 },
281};
282
283/* rt add parse */
284struct cfg_rt_add_cfg_item {
285 cmdline_fixed_string_t rt_keyword;
286 cmdline_multi_string_t multi_string;
287};
288
289static void
290cfg_rt_add_cfg_item_parsed(void *parsed_result,
291 __rte_unused struct cmdline *cl, void *data)
292{
293 struct cfg_rt_add_cfg_item *params = parsed_result;
294 char *tokens[32];
295 uint32_t n_tokens = RTE_DIM(tokens);
296 struct parse_status *status = (struct parse_status *)data;
297
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)
302 return;
303
304 parse_rt_tokens(tokens, n_tokens, status);
305}
306
307static cmdline_parse_token_string_t cfg_rt_add_rt_str =
308 TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
309 rt_keyword, "rt");
310
311static cmdline_parse_token_string_t cfg_rt_add_multi_str =
312 TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
313 TOKEN_STRING_MULTI);
314
315cmdline_parse_inst_t cfg_rt_add_rule = {
316 .f = cfg_rt_add_cfg_item_parsed,
317 .data = NULL,
318 .help_str = "",
319 .tokens = {
320 (void *) &cfg_rt_add_rt_str,
321 (void *) &cfg_rt_add_multi_str,
322 NULL,
323 },
324};
325
f51cf556
TL
326/* flow add parse */
327struct cfg_flow_add_cfg_item {
328 cmdline_fixed_string_t flow_keyword;
329 cmdline_multi_string_t multi_string;
330};
331
332static void
333cfg_flow_add_cfg_item_parsed(void *parsed_result,
334 __rte_unused struct cmdline *cl, void *data)
335{
336 struct cfg_flow_add_cfg_item *params = parsed_result;
337 char *tokens[32];
338 uint32_t n_tokens = RTE_DIM(tokens);
339 struct parse_status *status = (struct parse_status *)data;
340
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)
345 return;
346
347 parse_flow_tokens(tokens, n_tokens, status);
348}
349
350static cmdline_parse_token_string_t cfg_flow_add_flow_str =
351 TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
352 flow_keyword, "flow");
353
354static cmdline_parse_token_string_t cfg_flow_add_multi_str =
355 TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item, multi_string,
356 TOKEN_STRING_MULTI);
357
358cmdline_parse_inst_t cfg_flow_add_rule = {
359 .f = cfg_flow_add_cfg_item_parsed,
360 .data = NULL,
361 .help_str = "",
362 .tokens = {
363 (void *) &cfg_flow_add_flow_str,
364 (void *) &cfg_flow_add_multi_str,
365 NULL,
366 },
367};
368
9f95a23c
TL
369/* neigh add parse */
370struct cfg_neigh_add_item {
371 cmdline_fixed_string_t neigh;
372 cmdline_fixed_string_t pstr;
373 uint16_t port;
374 cmdline_fixed_string_t mac;
375};
376
377static void
378cfg_parse_neigh(void *parsed_result, __rte_unused struct cmdline *cl,
379 void *data)
380{
381 int32_t rc;
382 struct cfg_neigh_add_item *res;
383 struct parse_status *st;
f51cf556 384 struct rte_ether_addr mac;
9f95a23c
TL
385
386 st = data;
387 res = parsed_result;
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);
392 if (st->status < 0)
393 return;
394}
395
396cmdline_parse_token_string_t cfg_add_neigh_start =
397 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, neigh, "neigh");
398cmdline_parse_token_string_t cfg_add_neigh_pstr =
399 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, pstr, "port");
400cmdline_parse_token_num_t cfg_add_neigh_port =
f51cf556 401 TOKEN_NUM_INITIALIZER(struct cfg_neigh_add_item, port, RTE_UINT16);
9f95a23c
TL
402cmdline_parse_token_string_t cfg_add_neigh_mac =
403 TOKEN_STRING_INITIALIZER(struct cfg_neigh_add_item, mac, NULL);
404
405cmdline_parse_inst_t cfg_neigh_add_rule = {
406 .f = cfg_parse_neigh,
407 .data = NULL,
408 .help_str = "",
409 .tokens = {
410 (void *)&cfg_add_neigh_start,
411 (void *)&cfg_add_neigh_pstr,
412 (void *)&cfg_add_neigh_port,
413 (void *)&cfg_add_neigh_mac,
414 NULL,
415 },
416};
417
7c673cae
FG
418/** set of cfg items */
419cmdline_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,
f51cf556 423 (cmdline_parse_inst_t *)&cfg_flow_add_rule,
9f95a23c 424 (cmdline_parse_inst_t *)&cfg_neigh_add_rule,
7c673cae
FG
425 NULL,
426};
427
428int
429parse_cfg_file(const char *cfg_filename)
430{
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};
436
437 if (f == NULL) {
438 rte_panic("Error: invalid file descriptor %s\n", cfg_filename);
439 goto error_exit;
440 }
441
442 if (cl == NULL) {
443 rte_panic("Error: cannot create cmdline instance\n");
444 goto error_exit;
445 }
446
447 cfg_sp_add_rule.data = &status;
448 cfg_sa_add_rule.data = &status;
449 cfg_rt_add_rule.data = &status;
f51cf556 450 cfg_flow_add_rule.data = &status;
9f95a23c 451 cfg_neigh_add_rule.data = &status;
7c673cae
FG
452
453 do {
454 char oneline[1024];
455 char *pos;
456 get_s = fgets(oneline, 1024, f);
457
458 if (!get_s)
459 break;
460
461 line_num++;
462
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);
467 goto error_exit;
468 }
469
470 /* process comment char '#' */
471 if (oneline[0] == '#')
472 continue;
473
474 pos = strchr(oneline, '#');
475 if (pos != NULL)
476 *pos = '\0';
477
478 /* process line concatenator '\' */
479 pos = strchr(oneline, 92);
480 if (pos != NULL) {
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);
485 goto error_exit;
486 }
487
488 *pos = '\0';
489
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);
494 goto error_exit;
495 }
496
9f95a23c 497 strcpy(str + strlen(str), oneline);
7c673cae
FG
498 continue;
499 }
500
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);
506 goto error_exit;
507 }
9f95a23c 508 strcpy(str + strlen(str), oneline);
7c673cae
FG
509
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);
514 goto error_exit;
515 }
516
517 if (status.status < 0) {
518 rte_panic("%s:%u: error: %s", cfg_filename,
519 line_num, status.parse_msg);
520 goto error_exit;
521 }
522
523 memset(str, 0, 1024);
524 } while (1);
525
526 cmdline_stdin_exit(cl);
527 fclose(f);
528
f51cf556
TL
529 sa_sort_arr();
530 sp4_sort_arr();
531 sp6_sort_arr();
532
7c673cae
FG
533 return 0;
534
535error_exit:
536 if (cl)
537 cmdline_stdin_exit(cl);
538 if (f)
539 fclose(f);
540
541 return -1;
542}