1
2
3
4
5
6
7#include <stdint.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <ctype.h>
11#include <getopt.h>
12#include <errno.h>
13#include <stdarg.h>
14#include <string.h>
15#include <libgen.h>
16#include <unistd.h>
17#include <sys/wait.h>
18#include <arpa/inet.h>
19#include <sys/socket.h>
20
21#include <rte_errno.h>
22#include <rte_string_fns.h>
23
24#include "parser.h"
25
26static uint32_t
27get_hex_val(char c)
28{
29 switch (c) {
30 case '0': case '1': case '2': case '3': case '4': case '5':
31 case '6': case '7': case '8': case '9':
32 return c - '0';
33 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
34 return c - 'A' + 10;
35 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
36 return c - 'a' + 10;
37 default:
38 return 0;
39 }
40}
41
42int
43parser_read_arg_bool(const char *p)
44{
45 p = skip_white_spaces(p);
46 int result = -EINVAL;
47
48 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
49 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
50 p += 3;
51 result = 1;
52 }
53
54 if (((p[0] == 'o') && (p[1] == 'n')) ||
55 ((p[0] == 'O') && (p[1] == 'N'))) {
56 p += 2;
57 result = 1;
58 }
59
60 if (((p[0] == 'n') && (p[1] == 'o')) ||
61 ((p[0] == 'N') && (p[1] == 'O'))) {
62 p += 2;
63 result = 0;
64 }
65
66 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
67 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
68 p += 3;
69 result = 0;
70 }
71
72 p = skip_white_spaces(p);
73
74 if (p[0] != '\0')
75 return -EINVAL;
76
77 return result;
78}
79
80int
81parser_read_uint64(uint64_t *value, const char *p)
82{
83 char *next;
84 uint64_t val;
85
86 p = skip_white_spaces(p);
87 if (!isdigit(*p))
88 return -EINVAL;
89
90 val = strtoul(p, &next, 10);
91 if (p == next)
92 return -EINVAL;
93
94 p = next;
95 switch (*p) {
96 case 'T':
97 val *= 1024ULL;
98
99 case 'G':
100 val *= 1024ULL;
101
102 case 'M':
103 val *= 1024ULL;
104
105 case 'k':
106 case 'K':
107 val *= 1024ULL;
108 p++;
109 break;
110 }
111
112 p = skip_white_spaces(p);
113 if (*p != '\0')
114 return -EINVAL;
115
116 *value = val;
117 return 0;
118}
119
120int
121parser_read_uint64_hex(uint64_t *value, const char *p)
122{
123 char *next;
124 uint64_t val;
125
126 p = skip_white_spaces(p);
127
128 val = strtoul(p, &next, 16);
129 if (p == next)
130 return -EINVAL;
131
132 p = skip_white_spaces(next);
133 if (*p != '\0')
134 return -EINVAL;
135
136 *value = val;
137 return 0;
138}
139
140int
141parser_read_uint32(uint32_t *value, const char *p)
142{
143 uint64_t val = 0;
144 int ret = parser_read_uint64(&val, p);
145
146 if (ret < 0)
147 return ret;
148
149 if (val > UINT32_MAX)
150 return -ERANGE;
151
152 *value = val;
153 return 0;
154}
155
156int
157parser_read_uint32_hex(uint32_t *value, const char *p)
158{
159 uint64_t val = 0;
160 int ret = parser_read_uint64_hex(&val, p);
161
162 if (ret < 0)
163 return ret;
164
165 if (val > UINT32_MAX)
166 return -ERANGE;
167
168 *value = val;
169 return 0;
170}
171
172int
173parser_read_uint16(uint16_t *value, const char *p)
174{
175 uint64_t val = 0;
176 int ret = parser_read_uint64(&val, p);
177
178 if (ret < 0)
179 return ret;
180
181 if (val > UINT16_MAX)
182 return -ERANGE;
183
184 *value = val;
185 return 0;
186}
187
188int
189parser_read_uint16_hex(uint16_t *value, const char *p)
190{
191 uint64_t val = 0;
192 int ret = parser_read_uint64_hex(&val, p);
193
194 if (ret < 0)
195 return ret;
196
197 if (val > UINT16_MAX)
198 return -ERANGE;
199
200 *value = val;
201 return 0;
202}
203
204int
205parser_read_uint8(uint8_t *value, const char *p)
206{
207 uint64_t val = 0;
208 int ret = parser_read_uint64(&val, p);
209
210 if (ret < 0)
211 return ret;
212
213 if (val > UINT8_MAX)
214 return -ERANGE;
215
216 *value = val;
217 return 0;
218}
219
220int
221parser_read_uint8_hex(uint8_t *value, const char *p)
222{
223 uint64_t val = 0;
224 int ret = parser_read_uint64_hex(&val, p);
225
226 if (ret < 0)
227 return ret;
228
229 if (val > UINT8_MAX)
230 return -ERANGE;
231
232 *value = val;
233 return 0;
234}
235
236int
237parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
238{
239 uint32_t i;
240
241 if ((string == NULL) ||
242 (tokens == NULL) ||
243 (*n_tokens < 1))
244 return -EINVAL;
245
246 for (i = 0; i < *n_tokens; i++) {
247 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
248 if (tokens[i] == NULL)
249 break;
250 }
251
252 if ((i == *n_tokens) &&
253 (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
254 return -E2BIG;
255
256 *n_tokens = i;
257 return 0;
258}
259
260int
261parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
262{
263 char *c;
264 uint32_t len, i;
265
266
267 if ((src == NULL) ||
268 (dst == NULL) ||
269 (size == NULL) ||
270 (*size == 0))
271 return -1;
272
273 len = strlen(src);
274 if (((len & 3) != 0) ||
275 (len > (*size) * 2))
276 return -1;
277 *size = len / 2;
278
279 for (c = src; *c != 0; c++) {
280 if ((((*c) >= '0') && ((*c) <= '9')) ||
281 (((*c) >= 'A') && ((*c) <= 'F')) ||
282 (((*c) >= 'a') && ((*c) <= 'f')))
283 continue;
284
285 return -1;
286 }
287
288
289 for (i = 0; i < *size; i++)
290 dst[i] = get_hex_val(src[2 * i]) * 16 +
291 get_hex_val(src[2 * i + 1]);
292
293 return 0;
294}
295
296int
297parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
298{
299 uint32_t n_max_labels = *n_labels, count = 0;
300
301
302 if (strcmp(string, "<void>") == 0) {
303 *n_labels = 0;
304 return 0;
305 }
306
307
308 for ( ; (*string != '\0'); ) {
309 char *next;
310 int value;
311
312 if (count >= n_max_labels)
313 return -1;
314
315 if (count > 0) {
316 if (string[0] != ':')
317 return -1;
318
319 string++;
320 }
321
322 value = strtol(string, &next, 10);
323 if (next == string)
324 return -1;
325 string = next;
326
327 labels[count++] = (uint32_t) value;
328 }
329
330 *n_labels = count;
331 return 0;
332}
333
334static struct rte_ether_addr *
335my_ether_aton(const char *a)
336{
337 int i;
338 char *end;
339 unsigned long o[RTE_ETHER_ADDR_LEN];
340 static struct rte_ether_addr ether_addr;
341
342 i = 0;
343 do {
344 errno = 0;
345 o[i] = strtoul(a, &end, 16);
346 if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
347 return NULL;
348 a = end + 1;
349 } while (++i != RTE_DIM(o) && end[0] != 0);
350
351
352 if (end[0] != 0)
353 return NULL;
354
355
356 if (i == RTE_ETHER_ADDR_LEN) {
357 while (i-- != 0) {
358 if (o[i] > UINT8_MAX)
359 return NULL;
360 ether_addr.addr_bytes[i] = (uint8_t)o[i];
361 }
362
363 } else if (i == RTE_ETHER_ADDR_LEN / 2) {
364 while (i-- != 0) {
365 if (o[i] > UINT16_MAX)
366 return NULL;
367 ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
368 ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
369 }
370
371 } else
372 return NULL;
373
374 return (struct rte_ether_addr *)ðer_addr;
375}
376
377int
378parse_ipv4_addr(const char *token, struct in_addr *ipv4)
379{
380 if (strlen(token) >= INET_ADDRSTRLEN)
381 return -EINVAL;
382
383 if (inet_pton(AF_INET, token, ipv4) != 1)
384 return -EINVAL;
385
386 return 0;
387}
388
389int
390parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
391{
392 if (strlen(token) >= INET6_ADDRSTRLEN)
393 return -EINVAL;
394
395 if (inet_pton(AF_INET6, token, ipv6) != 1)
396 return -EINVAL;
397
398 return 0;
399}
400
401int
402parse_mac_addr(const char *token, struct rte_ether_addr *addr)
403{
404 struct rte_ether_addr *tmp;
405
406 tmp = my_ether_aton(token);
407 if (tmp == NULL)
408 return -1;
409
410 memcpy(addr, tmp, sizeof(struct rte_ether_addr));
411 return 0;
412}
413
414int
415parse_cpu_core(const char *entry,
416 struct cpu_core_params *p)
417{
418 size_t num_len;
419 char num[8];
420
421 uint32_t s = 0, c = 0, h = 0, val;
422 uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
423 const char *next = skip_white_spaces(entry);
424 char type;
425
426 if (p == NULL)
427 return -EINVAL;
428
429
430 while (*next != '\0') {
431
432 if (s_parsed && c_parsed && h_parsed)
433 return -EINVAL;
434
435 type = *next;
436 switch (type) {
437 case 's':
438 case 'S':
439 if (s_parsed || c_parsed || h_parsed)
440 return -EINVAL;
441 s_parsed = 1;
442 next++;
443 break;
444 case 'c':
445 case 'C':
446 if (c_parsed || h_parsed)
447 return -EINVAL;
448 c_parsed = 1;
449 next++;
450 break;
451 case 'h':
452 case 'H':
453 if (h_parsed)
454 return -EINVAL;
455 h_parsed = 1;
456 next++;
457 break;
458 default:
459
460 if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
461 return -EINVAL;
462
463 type = 'C';
464 }
465
466 for (num_len = 0; *next != '\0'; next++, num_len++) {
467 if (num_len == RTE_DIM(num))
468 return -EINVAL;
469
470 if (!isdigit(*next))
471 break;
472
473 num[num_len] = *next;
474 }
475
476 if (num_len == 0 && type != 'h' && type != 'H')
477 return -EINVAL;
478
479 if (num_len != 0 && (type == 'h' || type == 'H'))
480 return -EINVAL;
481
482 num[num_len] = '\0';
483 val = strtol(num, NULL, 10);
484
485 h = 0;
486 switch (type) {
487 case 's':
488 case 'S':
489 s = val;
490 break;
491 case 'c':
492 case 'C':
493 c = val;
494 break;
495 case 'h':
496 case 'H':
497 h = 1;
498 break;
499 }
500 }
501
502 p->socket_id = s;
503 p->core_id = c;
504 p->thread_id = h;
505 return 0;
506}
507