131ce8d88SJasvinder Singh /* SPDX-License-Identifier: BSD-3-Clause 231ce8d88SJasvinder Singh * Copyright(c) 2016 Intel Corporation. 331ce8d88SJasvinder Singh * Copyright (c) 2009, Olivier MATZ <[email protected]> 431ce8d88SJasvinder Singh * All rights reserved. 531ce8d88SJasvinder Singh */ 631ce8d88SJasvinder Singh 731ce8d88SJasvinder Singh /* For inet_pton4() and inet_pton6() functions: 831ce8d88SJasvinder Singh * 931ce8d88SJasvinder Singh * Copyright (c) 1996 by Internet Software Consortium. 1031ce8d88SJasvinder Singh * 1131ce8d88SJasvinder Singh * Permission to use, copy, modify, and distribute this software for any 1231ce8d88SJasvinder Singh * purpose with or without fee is hereby granted, provided that the above 1331ce8d88SJasvinder Singh * copyright notice and this permission notice appear in all copies. 1431ce8d88SJasvinder Singh * 1531ce8d88SJasvinder Singh * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 1631ce8d88SJasvinder Singh * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 1731ce8d88SJasvinder Singh * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 1831ce8d88SJasvinder Singh * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 1931ce8d88SJasvinder Singh * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 2031ce8d88SJasvinder Singh * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 2131ce8d88SJasvinder Singh * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2231ce8d88SJasvinder Singh * SOFTWARE. 2331ce8d88SJasvinder Singh */ 2431ce8d88SJasvinder Singh 2531ce8d88SJasvinder Singh #include <stdint.h> 2631ce8d88SJasvinder Singh #include <stdlib.h> 2731ce8d88SJasvinder Singh #include <stdio.h> 2831ce8d88SJasvinder Singh #include <ctype.h> 2931ce8d88SJasvinder Singh #include <getopt.h> 3031ce8d88SJasvinder Singh #include <errno.h> 3131ce8d88SJasvinder Singh #include <stdarg.h> 3231ce8d88SJasvinder Singh #include <string.h> 3331ce8d88SJasvinder Singh #include <libgen.h> 3431ce8d88SJasvinder Singh #include <unistd.h> 3531ce8d88SJasvinder Singh #include <sys/wait.h> 3631ce8d88SJasvinder Singh 3731ce8d88SJasvinder Singh #include <rte_errno.h> 3831ce8d88SJasvinder Singh 3931ce8d88SJasvinder Singh #include "parser.h" 4031ce8d88SJasvinder Singh 4131ce8d88SJasvinder Singh static uint32_t 4231ce8d88SJasvinder Singh get_hex_val(char c) 4331ce8d88SJasvinder Singh { 4431ce8d88SJasvinder Singh switch (c) { 4531ce8d88SJasvinder Singh case '0': case '1': case '2': case '3': case '4': case '5': 4631ce8d88SJasvinder Singh case '6': case '7': case '8': case '9': 4731ce8d88SJasvinder Singh return c - '0'; 4831ce8d88SJasvinder Singh case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 4931ce8d88SJasvinder Singh return c - 'A' + 10; 5031ce8d88SJasvinder Singh case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 5131ce8d88SJasvinder Singh return c - 'a' + 10; 5231ce8d88SJasvinder Singh default: 5331ce8d88SJasvinder Singh return 0; 5431ce8d88SJasvinder Singh } 5531ce8d88SJasvinder Singh } 5631ce8d88SJasvinder Singh 5731ce8d88SJasvinder Singh int 5831ce8d88SJasvinder Singh softnic_parser_read_arg_bool(const char *p) 5931ce8d88SJasvinder Singh { 6031ce8d88SJasvinder Singh p = skip_white_spaces(p); 6131ce8d88SJasvinder Singh int result = -EINVAL; 6231ce8d88SJasvinder Singh 6331ce8d88SJasvinder Singh if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || 6431ce8d88SJasvinder Singh ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { 6531ce8d88SJasvinder Singh p += 3; 6631ce8d88SJasvinder Singh result = 1; 6731ce8d88SJasvinder Singh } 6831ce8d88SJasvinder Singh 6931ce8d88SJasvinder Singh if (((p[0] == 'o') && (p[1] == 'n')) || 7031ce8d88SJasvinder Singh ((p[0] == 'O') && (p[1] == 'N'))) { 7131ce8d88SJasvinder Singh p += 2; 7231ce8d88SJasvinder Singh result = 1; 7331ce8d88SJasvinder Singh } 7431ce8d88SJasvinder Singh 7531ce8d88SJasvinder Singh if (((p[0] == 'n') && (p[1] == 'o')) || 7631ce8d88SJasvinder Singh ((p[0] == 'N') && (p[1] == 'O'))) { 7731ce8d88SJasvinder Singh p += 2; 7831ce8d88SJasvinder Singh result = 0; 7931ce8d88SJasvinder Singh } 8031ce8d88SJasvinder Singh 8131ce8d88SJasvinder Singh if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || 8231ce8d88SJasvinder Singh ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { 8331ce8d88SJasvinder Singh p += 3; 8431ce8d88SJasvinder Singh result = 0; 8531ce8d88SJasvinder Singh } 8631ce8d88SJasvinder Singh 8731ce8d88SJasvinder Singh p = skip_white_spaces(p); 8831ce8d88SJasvinder Singh 8931ce8d88SJasvinder Singh if (p[0] != '\0') 9031ce8d88SJasvinder Singh return -EINVAL; 9131ce8d88SJasvinder Singh 9231ce8d88SJasvinder Singh return result; 9331ce8d88SJasvinder Singh } 9431ce8d88SJasvinder Singh 9531ce8d88SJasvinder Singh int 96552e3f72SCristian Dumitrescu softnic_parser_read_int32(int32_t *value, const char *p) 97552e3f72SCristian Dumitrescu { 98552e3f72SCristian Dumitrescu char *next; 99552e3f72SCristian Dumitrescu int32_t val; 100552e3f72SCristian Dumitrescu 101552e3f72SCristian Dumitrescu p = skip_white_spaces(p); 102552e3f72SCristian Dumitrescu if (!isdigit(*p)) 103552e3f72SCristian Dumitrescu return -EINVAL; 104552e3f72SCristian Dumitrescu 105552e3f72SCristian Dumitrescu val = strtol(p, &next, 10); 106552e3f72SCristian Dumitrescu if (p == next) 107552e3f72SCristian Dumitrescu return -EINVAL; 108552e3f72SCristian Dumitrescu 109552e3f72SCristian Dumitrescu *value = val; 110552e3f72SCristian Dumitrescu return 0; 111552e3f72SCristian Dumitrescu } 112552e3f72SCristian Dumitrescu 113552e3f72SCristian Dumitrescu int 11431ce8d88SJasvinder Singh softnic_parser_read_uint64(uint64_t *value, const char *p) 11531ce8d88SJasvinder Singh { 11631ce8d88SJasvinder Singh char *next; 11731ce8d88SJasvinder Singh uint64_t val; 11831ce8d88SJasvinder Singh 11931ce8d88SJasvinder Singh p = skip_white_spaces(p); 12031ce8d88SJasvinder Singh if (!isdigit(*p)) 12131ce8d88SJasvinder Singh return -EINVAL; 12231ce8d88SJasvinder Singh 12331ce8d88SJasvinder Singh val = strtoul(p, &next, 10); 12431ce8d88SJasvinder Singh if (p == next) 12531ce8d88SJasvinder Singh return -EINVAL; 12631ce8d88SJasvinder Singh 12731ce8d88SJasvinder Singh p = next; 12831ce8d88SJasvinder Singh switch (*p) { 12931ce8d88SJasvinder Singh case 'T': 13031ce8d88SJasvinder Singh val *= 1024ULL; 13131ce8d88SJasvinder Singh /* fall through */ 13231ce8d88SJasvinder Singh case 'G': 13331ce8d88SJasvinder Singh val *= 1024ULL; 13431ce8d88SJasvinder Singh /* fall through */ 13531ce8d88SJasvinder Singh case 'M': 13631ce8d88SJasvinder Singh val *= 1024ULL; 13731ce8d88SJasvinder Singh /* fall through */ 13831ce8d88SJasvinder Singh case 'k': 13931ce8d88SJasvinder Singh case 'K': 14031ce8d88SJasvinder Singh val *= 1024ULL; 14131ce8d88SJasvinder Singh p++; 14231ce8d88SJasvinder Singh break; 14331ce8d88SJasvinder Singh } 14431ce8d88SJasvinder Singh 14531ce8d88SJasvinder Singh p = skip_white_spaces(p); 14631ce8d88SJasvinder Singh if (*p != '\0') 14731ce8d88SJasvinder Singh return -EINVAL; 14831ce8d88SJasvinder Singh 14931ce8d88SJasvinder Singh *value = val; 15031ce8d88SJasvinder Singh return 0; 15131ce8d88SJasvinder Singh } 15231ce8d88SJasvinder Singh 15331ce8d88SJasvinder Singh int 15431ce8d88SJasvinder Singh softnic_parser_read_uint64_hex(uint64_t *value, const char *p) 15531ce8d88SJasvinder Singh { 15631ce8d88SJasvinder Singh char *next; 15731ce8d88SJasvinder Singh uint64_t val; 15831ce8d88SJasvinder Singh 15931ce8d88SJasvinder Singh p = skip_white_spaces(p); 16031ce8d88SJasvinder Singh 16131ce8d88SJasvinder Singh val = strtoul(p, &next, 16); 16231ce8d88SJasvinder Singh if (p == next) 16331ce8d88SJasvinder Singh return -EINVAL; 16431ce8d88SJasvinder Singh 16531ce8d88SJasvinder Singh p = skip_white_spaces(next); 16631ce8d88SJasvinder Singh if (*p != '\0') 16731ce8d88SJasvinder Singh return -EINVAL; 16831ce8d88SJasvinder Singh 16931ce8d88SJasvinder Singh *value = val; 17031ce8d88SJasvinder Singh return 0; 17131ce8d88SJasvinder Singh } 17231ce8d88SJasvinder Singh 17331ce8d88SJasvinder Singh int 17431ce8d88SJasvinder Singh softnic_parser_read_uint32(uint32_t *value, const char *p) 17531ce8d88SJasvinder Singh { 17631ce8d88SJasvinder Singh uint64_t val = 0; 17731ce8d88SJasvinder Singh int ret = softnic_parser_read_uint64(&val, p); 17831ce8d88SJasvinder Singh 17931ce8d88SJasvinder Singh if (ret < 0) 18031ce8d88SJasvinder Singh return ret; 18131ce8d88SJasvinder Singh 18231ce8d88SJasvinder Singh if (val > UINT32_MAX) 18331ce8d88SJasvinder Singh return -ERANGE; 18431ce8d88SJasvinder Singh 18531ce8d88SJasvinder Singh *value = val; 18631ce8d88SJasvinder Singh return 0; 18731ce8d88SJasvinder Singh } 18831ce8d88SJasvinder Singh 18931ce8d88SJasvinder Singh int 19031ce8d88SJasvinder Singh softnic_parser_read_uint32_hex(uint32_t *value, const char *p) 19131ce8d88SJasvinder Singh { 19231ce8d88SJasvinder Singh uint64_t val = 0; 19331ce8d88SJasvinder Singh int ret = softnic_parser_read_uint64_hex(&val, p); 19431ce8d88SJasvinder Singh 19531ce8d88SJasvinder Singh if (ret < 0) 19631ce8d88SJasvinder Singh return ret; 19731ce8d88SJasvinder Singh 19831ce8d88SJasvinder Singh if (val > UINT32_MAX) 19931ce8d88SJasvinder Singh return -ERANGE; 20031ce8d88SJasvinder Singh 20131ce8d88SJasvinder Singh *value = val; 20231ce8d88SJasvinder Singh return 0; 20331ce8d88SJasvinder Singh } 20431ce8d88SJasvinder Singh 20531ce8d88SJasvinder Singh int 20631ce8d88SJasvinder Singh softnic_parser_read_uint16(uint16_t *value, const char *p) 20731ce8d88SJasvinder Singh { 20831ce8d88SJasvinder Singh uint64_t val = 0; 20931ce8d88SJasvinder Singh int ret = softnic_parser_read_uint64(&val, p); 21031ce8d88SJasvinder Singh 21131ce8d88SJasvinder Singh if (ret < 0) 21231ce8d88SJasvinder Singh return ret; 21331ce8d88SJasvinder Singh 21431ce8d88SJasvinder Singh if (val > UINT16_MAX) 21531ce8d88SJasvinder Singh return -ERANGE; 21631ce8d88SJasvinder Singh 21731ce8d88SJasvinder Singh *value = val; 21831ce8d88SJasvinder Singh return 0; 21931ce8d88SJasvinder Singh } 22031ce8d88SJasvinder Singh 22131ce8d88SJasvinder Singh int 22231ce8d88SJasvinder Singh softnic_parser_read_uint16_hex(uint16_t *value, const char *p) 22331ce8d88SJasvinder Singh { 22431ce8d88SJasvinder Singh uint64_t val = 0; 22531ce8d88SJasvinder Singh int ret = softnic_parser_read_uint64_hex(&val, p); 22631ce8d88SJasvinder Singh 22731ce8d88SJasvinder Singh if (ret < 0) 22831ce8d88SJasvinder Singh return ret; 22931ce8d88SJasvinder Singh 23031ce8d88SJasvinder Singh if (val > UINT16_MAX) 23131ce8d88SJasvinder Singh return -ERANGE; 23231ce8d88SJasvinder Singh 23331ce8d88SJasvinder Singh *value = val; 23431ce8d88SJasvinder Singh return 0; 23531ce8d88SJasvinder Singh } 23631ce8d88SJasvinder Singh 23731ce8d88SJasvinder Singh int 23831ce8d88SJasvinder Singh softnic_parser_read_uint8(uint8_t *value, const char *p) 23931ce8d88SJasvinder Singh { 24031ce8d88SJasvinder Singh uint64_t val = 0; 24131ce8d88SJasvinder Singh int ret = softnic_parser_read_uint64(&val, p); 24231ce8d88SJasvinder Singh 24331ce8d88SJasvinder Singh if (ret < 0) 24431ce8d88SJasvinder Singh return ret; 24531ce8d88SJasvinder Singh 24631ce8d88SJasvinder Singh if (val > UINT8_MAX) 24731ce8d88SJasvinder Singh return -ERANGE; 24831ce8d88SJasvinder Singh 24931ce8d88SJasvinder Singh *value = val; 25031ce8d88SJasvinder Singh return 0; 25131ce8d88SJasvinder Singh } 25231ce8d88SJasvinder Singh 25331ce8d88SJasvinder Singh int 25431ce8d88SJasvinder Singh softnic_parser_read_uint8_hex(uint8_t *value, const char *p) 25531ce8d88SJasvinder Singh { 25631ce8d88SJasvinder Singh uint64_t val = 0; 25731ce8d88SJasvinder Singh int ret = softnic_parser_read_uint64_hex(&val, p); 25831ce8d88SJasvinder Singh 25931ce8d88SJasvinder Singh if (ret < 0) 26031ce8d88SJasvinder Singh return ret; 26131ce8d88SJasvinder Singh 26231ce8d88SJasvinder Singh if (val > UINT8_MAX) 26331ce8d88SJasvinder Singh return -ERANGE; 26431ce8d88SJasvinder Singh 26531ce8d88SJasvinder Singh *value = val; 26631ce8d88SJasvinder Singh return 0; 26731ce8d88SJasvinder Singh } 26831ce8d88SJasvinder Singh 26931ce8d88SJasvinder Singh int 27031ce8d88SJasvinder Singh softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 27131ce8d88SJasvinder Singh { 27231ce8d88SJasvinder Singh uint32_t i; 27331ce8d88SJasvinder Singh 27431ce8d88SJasvinder Singh if (string == NULL || 27531ce8d88SJasvinder Singh tokens == NULL || 27631ce8d88SJasvinder Singh (*n_tokens < 1)) 27731ce8d88SJasvinder Singh return -EINVAL; 27831ce8d88SJasvinder Singh 27931ce8d88SJasvinder Singh for (i = 0; i < *n_tokens; i++) { 28031ce8d88SJasvinder Singh tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 28131ce8d88SJasvinder Singh if (tokens[i] == NULL) 28231ce8d88SJasvinder Singh break; 28331ce8d88SJasvinder Singh } 28431ce8d88SJasvinder Singh 28531ce8d88SJasvinder Singh if (i == *n_tokens && 28631ce8d88SJasvinder Singh strtok_r(string, PARSE_DELIMITER, &string) != NULL) 28731ce8d88SJasvinder Singh return -E2BIG; 28831ce8d88SJasvinder Singh 28931ce8d88SJasvinder Singh *n_tokens = i; 29031ce8d88SJasvinder Singh return 0; 29131ce8d88SJasvinder Singh } 29231ce8d88SJasvinder Singh 29331ce8d88SJasvinder Singh int 29431ce8d88SJasvinder Singh softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size) 29531ce8d88SJasvinder Singh { 29631ce8d88SJasvinder Singh char *c; 29731ce8d88SJasvinder Singh uint32_t len, i; 29831ce8d88SJasvinder Singh 29931ce8d88SJasvinder Singh /* Check input parameters */ 30031ce8d88SJasvinder Singh if (src == NULL || 30131ce8d88SJasvinder Singh dst == NULL || 30231ce8d88SJasvinder Singh size == NULL || 30331ce8d88SJasvinder Singh (*size == 0)) 30431ce8d88SJasvinder Singh return -1; 30531ce8d88SJasvinder Singh 30631ce8d88SJasvinder Singh len = strlen(src); 30731ce8d88SJasvinder Singh if (((len & 3) != 0) || 30831ce8d88SJasvinder Singh (len > (*size) * 2)) 30931ce8d88SJasvinder Singh return -1; 31031ce8d88SJasvinder Singh *size = len / 2; 31131ce8d88SJasvinder Singh 31231ce8d88SJasvinder Singh for (c = src; *c != 0; c++) { 31331ce8d88SJasvinder Singh if ((((*c) >= '0') && ((*c) <= '9')) || 31431ce8d88SJasvinder Singh (((*c) >= 'A') && ((*c) <= 'F')) || 31531ce8d88SJasvinder Singh (((*c) >= 'a') && ((*c) <= 'f'))) 31631ce8d88SJasvinder Singh continue; 31731ce8d88SJasvinder Singh 31831ce8d88SJasvinder Singh return -1; 31931ce8d88SJasvinder Singh } 32031ce8d88SJasvinder Singh 32131ce8d88SJasvinder Singh /* Convert chars to bytes */ 32231ce8d88SJasvinder Singh for (i = 0; i < *size; i++) 32331ce8d88SJasvinder Singh dst[i] = get_hex_val(src[2 * i]) * 16 + 32431ce8d88SJasvinder Singh get_hex_val(src[2 * i + 1]); 32531ce8d88SJasvinder Singh 32631ce8d88SJasvinder Singh return 0; 32731ce8d88SJasvinder Singh } 32831ce8d88SJasvinder Singh 32931ce8d88SJasvinder Singh int 33031ce8d88SJasvinder Singh softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels) 33131ce8d88SJasvinder Singh { 33231ce8d88SJasvinder Singh uint32_t n_max_labels = *n_labels, count = 0; 33331ce8d88SJasvinder Singh 33431ce8d88SJasvinder Singh /* Check for void list of labels */ 33531ce8d88SJasvinder Singh if (strcmp(string, "<void>") == 0) { 33631ce8d88SJasvinder Singh *n_labels = 0; 33731ce8d88SJasvinder Singh return 0; 33831ce8d88SJasvinder Singh } 33931ce8d88SJasvinder Singh 34031ce8d88SJasvinder Singh /* At least one label should be present */ 34131ce8d88SJasvinder Singh for ( ; (*string != '\0'); ) { 34231ce8d88SJasvinder Singh char *next; 34331ce8d88SJasvinder Singh int value; 34431ce8d88SJasvinder Singh 34531ce8d88SJasvinder Singh if (count >= n_max_labels) 34631ce8d88SJasvinder Singh return -1; 34731ce8d88SJasvinder Singh 34831ce8d88SJasvinder Singh if (count > 0) { 34931ce8d88SJasvinder Singh if (string[0] != ':') 35031ce8d88SJasvinder Singh return -1; 35131ce8d88SJasvinder Singh 35231ce8d88SJasvinder Singh string++; 35331ce8d88SJasvinder Singh } 35431ce8d88SJasvinder Singh 35531ce8d88SJasvinder Singh value = strtol(string, &next, 10); 35631ce8d88SJasvinder Singh if (next == string) 35731ce8d88SJasvinder Singh return -1; 35831ce8d88SJasvinder Singh string = next; 35931ce8d88SJasvinder Singh 36031ce8d88SJasvinder Singh labels[count++] = (uint32_t)value; 36131ce8d88SJasvinder Singh } 36231ce8d88SJasvinder Singh 36331ce8d88SJasvinder Singh *n_labels = count; 36431ce8d88SJasvinder Singh return 0; 36531ce8d88SJasvinder Singh } 36631ce8d88SJasvinder Singh 36731ce8d88SJasvinder Singh #define INADDRSZ 4 36831ce8d88SJasvinder Singh #define IN6ADDRSZ 16 36931ce8d88SJasvinder Singh 37031ce8d88SJasvinder Singh /* int 37131ce8d88SJasvinder Singh * inet_pton4(src, dst) 37231ce8d88SJasvinder Singh * like inet_aton() but without all the hexadecimal and shorthand. 37331ce8d88SJasvinder Singh * return: 37431ce8d88SJasvinder Singh * 1 if `src' is a valid dotted quad, else 0. 37531ce8d88SJasvinder Singh * notice: 37631ce8d88SJasvinder Singh * does not touch `dst' unless it's returning 1. 37731ce8d88SJasvinder Singh * author: 37831ce8d88SJasvinder Singh * Paul Vixie, 1996. 37931ce8d88SJasvinder Singh */ 38031ce8d88SJasvinder Singh static int 38131ce8d88SJasvinder Singh inet_pton4(const char *src, unsigned char *dst) 38231ce8d88SJasvinder Singh { 38331ce8d88SJasvinder Singh static const char digits[] = "0123456789"; 38431ce8d88SJasvinder Singh int saw_digit, octets, ch; 38531ce8d88SJasvinder Singh unsigned char tmp[INADDRSZ], *tp; 38631ce8d88SJasvinder Singh 38731ce8d88SJasvinder Singh saw_digit = 0; 38831ce8d88SJasvinder Singh octets = 0; 38931ce8d88SJasvinder Singh *(tp = tmp) = 0; 39031ce8d88SJasvinder Singh while ((ch = *src++) != '\0') { 39131ce8d88SJasvinder Singh const char *pch; 39231ce8d88SJasvinder Singh 39331ce8d88SJasvinder Singh pch = strchr(digits, ch); 39431ce8d88SJasvinder Singh if (pch != NULL) { 39531ce8d88SJasvinder Singh unsigned int new = *tp * 10 + (pch - digits); 39631ce8d88SJasvinder Singh 39731ce8d88SJasvinder Singh if (new > 255) 39831ce8d88SJasvinder Singh return 0; 39931ce8d88SJasvinder Singh if (!saw_digit) { 40031ce8d88SJasvinder Singh if (++octets > 4) 40131ce8d88SJasvinder Singh return 0; 40231ce8d88SJasvinder Singh saw_digit = 1; 40331ce8d88SJasvinder Singh } 40431ce8d88SJasvinder Singh *tp = (unsigned char)new; 40531ce8d88SJasvinder Singh } else if (ch == '.' && saw_digit) { 40631ce8d88SJasvinder Singh if (octets == 4) 40731ce8d88SJasvinder Singh return 0; 40831ce8d88SJasvinder Singh *++tp = 0; 40931ce8d88SJasvinder Singh saw_digit = 0; 41031ce8d88SJasvinder Singh } else 41131ce8d88SJasvinder Singh return 0; 41231ce8d88SJasvinder Singh } 41331ce8d88SJasvinder Singh if (octets < 4) 41431ce8d88SJasvinder Singh return 0; 41531ce8d88SJasvinder Singh 41631ce8d88SJasvinder Singh memcpy(dst, tmp, INADDRSZ); 41731ce8d88SJasvinder Singh return 1; 41831ce8d88SJasvinder Singh } 41931ce8d88SJasvinder Singh 42031ce8d88SJasvinder Singh /* int 42131ce8d88SJasvinder Singh * inet_pton6(src, dst) 42231ce8d88SJasvinder Singh * convert presentation level address to network order binary form. 42331ce8d88SJasvinder Singh * return: 42431ce8d88SJasvinder Singh * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 42531ce8d88SJasvinder Singh * notice: 42631ce8d88SJasvinder Singh * (1) does not touch `dst' unless it's returning 1. 42731ce8d88SJasvinder Singh * (2) :: in a full address is silently ignored. 42831ce8d88SJasvinder Singh * credit: 42931ce8d88SJasvinder Singh * inspired by Mark Andrews. 43031ce8d88SJasvinder Singh * author: 43131ce8d88SJasvinder Singh * Paul Vixie, 1996. 43231ce8d88SJasvinder Singh */ 43331ce8d88SJasvinder Singh static int 43431ce8d88SJasvinder Singh inet_pton6(const char *src, unsigned char *dst) 43531ce8d88SJasvinder Singh { 43631ce8d88SJasvinder Singh static const char xdigits_l[] = "0123456789abcdef", 43731ce8d88SJasvinder Singh xdigits_u[] = "0123456789ABCDEF"; 43831ce8d88SJasvinder Singh unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; 43931ce8d88SJasvinder Singh const char *xdigits = 0, *curtok = 0; 44031ce8d88SJasvinder Singh int ch = 0, saw_xdigit = 0, count_xdigit = 0; 44131ce8d88SJasvinder Singh unsigned int val = 0; 44231ce8d88SJasvinder Singh unsigned int dbloct_count = 0; 44331ce8d88SJasvinder Singh 44431ce8d88SJasvinder Singh memset((tp = tmp), '\0', IN6ADDRSZ); 44531ce8d88SJasvinder Singh endp = tp + IN6ADDRSZ; 44631ce8d88SJasvinder Singh colonp = NULL; 44731ce8d88SJasvinder Singh /* Leading :: requires some special handling. */ 44831ce8d88SJasvinder Singh if (*src == ':') 44931ce8d88SJasvinder Singh if (*++src != ':') 45031ce8d88SJasvinder Singh return 0; 45131ce8d88SJasvinder Singh curtok = src; 45231ce8d88SJasvinder Singh saw_xdigit = count_xdigit = 0; 45331ce8d88SJasvinder Singh val = 0; 45431ce8d88SJasvinder Singh 45531ce8d88SJasvinder Singh while ((ch = *src++) != '\0') { 45631ce8d88SJasvinder Singh const char *pch; 45731ce8d88SJasvinder Singh 45831ce8d88SJasvinder Singh pch = strchr((xdigits = xdigits_l), ch); 45931ce8d88SJasvinder Singh if (pch == NULL) 46031ce8d88SJasvinder Singh pch = strchr((xdigits = xdigits_u), ch); 46131ce8d88SJasvinder Singh if (pch != NULL) { 46231ce8d88SJasvinder Singh if (count_xdigit >= 4) 46331ce8d88SJasvinder Singh return 0; 46431ce8d88SJasvinder Singh val <<= 4; 46531ce8d88SJasvinder Singh val |= (pch - xdigits); 46631ce8d88SJasvinder Singh if (val > 0xffff) 46731ce8d88SJasvinder Singh return 0; 46831ce8d88SJasvinder Singh saw_xdigit = 1; 46931ce8d88SJasvinder Singh count_xdigit++; 47031ce8d88SJasvinder Singh continue; 47131ce8d88SJasvinder Singh } 47231ce8d88SJasvinder Singh if (ch == ':') { 47331ce8d88SJasvinder Singh curtok = src; 47431ce8d88SJasvinder Singh if (!saw_xdigit) { 47531ce8d88SJasvinder Singh if (colonp) 47631ce8d88SJasvinder Singh return 0; 47731ce8d88SJasvinder Singh colonp = tp; 47831ce8d88SJasvinder Singh continue; 47931ce8d88SJasvinder Singh } else if (*src == '\0') { 48031ce8d88SJasvinder Singh return 0; 48131ce8d88SJasvinder Singh } 48231ce8d88SJasvinder Singh if (tp + sizeof(int16_t) > endp) 48331ce8d88SJasvinder Singh return 0; 48431ce8d88SJasvinder Singh *tp++ = (unsigned char)((val >> 8) & 0xff); 48531ce8d88SJasvinder Singh *tp++ = (unsigned char)(val & 0xff); 48631ce8d88SJasvinder Singh saw_xdigit = 0; 48731ce8d88SJasvinder Singh count_xdigit = 0; 48831ce8d88SJasvinder Singh val = 0; 48931ce8d88SJasvinder Singh dbloct_count++; 49031ce8d88SJasvinder Singh continue; 49131ce8d88SJasvinder Singh } 49231ce8d88SJasvinder Singh if (ch == '.' && ((tp + INADDRSZ) <= endp) && 49331ce8d88SJasvinder Singh inet_pton4(curtok, tp) > 0) { 49431ce8d88SJasvinder Singh tp += INADDRSZ; 49531ce8d88SJasvinder Singh saw_xdigit = 0; 49631ce8d88SJasvinder Singh dbloct_count += 2; 49731ce8d88SJasvinder Singh break; /* '\0' was seen by inet_pton4(). */ 49831ce8d88SJasvinder Singh } 49931ce8d88SJasvinder Singh return 0; 50031ce8d88SJasvinder Singh } 50131ce8d88SJasvinder Singh if (saw_xdigit) { 50231ce8d88SJasvinder Singh if (tp + sizeof(int16_t) > endp) 50331ce8d88SJasvinder Singh return 0; 50431ce8d88SJasvinder Singh *tp++ = (unsigned char)((val >> 8) & 0xff); 50531ce8d88SJasvinder Singh *tp++ = (unsigned char)(val & 0xff); 50631ce8d88SJasvinder Singh dbloct_count++; 50731ce8d88SJasvinder Singh } 50831ce8d88SJasvinder Singh if (colonp != NULL) { 50931ce8d88SJasvinder Singh /* if we already have 8 double octets, having a colon means error */ 51031ce8d88SJasvinder Singh if (dbloct_count == 8) 51131ce8d88SJasvinder Singh return 0; 51231ce8d88SJasvinder Singh 51331ce8d88SJasvinder Singh /* Since some memmove()'s erroneously fail to handle 51431ce8d88SJasvinder Singh * overlapping regions, we'll do the shift by hand. 51531ce8d88SJasvinder Singh */ 51631ce8d88SJasvinder Singh const int n = tp - colonp; 51731ce8d88SJasvinder Singh int i; 51831ce8d88SJasvinder Singh 51931ce8d88SJasvinder Singh for (i = 1; i <= n; i++) { 52031ce8d88SJasvinder Singh endp[-i] = colonp[n - i]; 52131ce8d88SJasvinder Singh colonp[n - i] = 0; 52231ce8d88SJasvinder Singh } 52331ce8d88SJasvinder Singh tp = endp; 52431ce8d88SJasvinder Singh } 52531ce8d88SJasvinder Singh if (tp != endp) 52631ce8d88SJasvinder Singh return 0; 52731ce8d88SJasvinder Singh memcpy(dst, tmp, IN6ADDRSZ); 52831ce8d88SJasvinder Singh return 1; 52931ce8d88SJasvinder Singh } 53031ce8d88SJasvinder Singh 5316d13ea8eSOlivier Matz static struct rte_ether_addr * 53231ce8d88SJasvinder Singh my_ether_aton(const char *a) 53331ce8d88SJasvinder Singh { 53431ce8d88SJasvinder Singh int i; 53531ce8d88SJasvinder Singh char *end; 536*35b2d13fSOlivier Matz unsigned long o[RTE_ETHER_ADDR_LEN]; 5376d13ea8eSOlivier Matz static struct rte_ether_addr ether_addr; 53831ce8d88SJasvinder Singh 53931ce8d88SJasvinder Singh i = 0; 54031ce8d88SJasvinder Singh do { 54131ce8d88SJasvinder Singh errno = 0; 54231ce8d88SJasvinder Singh o[i] = strtoul(a, &end, 16); 54331ce8d88SJasvinder Singh if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 54431ce8d88SJasvinder Singh return NULL; 54531ce8d88SJasvinder Singh a = end + 1; 54631ce8d88SJasvinder Singh } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0); 54731ce8d88SJasvinder Singh 54831ce8d88SJasvinder Singh /* Junk at the end of line */ 54931ce8d88SJasvinder Singh if (end[0] != 0) 55031ce8d88SJasvinder Singh return NULL; 55131ce8d88SJasvinder Singh 55231ce8d88SJasvinder Singh /* Support the format XX:XX:XX:XX:XX:XX */ 553*35b2d13fSOlivier Matz if (i == RTE_ETHER_ADDR_LEN) { 55431ce8d88SJasvinder Singh while (i-- != 0) { 55531ce8d88SJasvinder Singh if (o[i] > UINT8_MAX) 55631ce8d88SJasvinder Singh return NULL; 55731ce8d88SJasvinder Singh ether_addr.addr_bytes[i] = (uint8_t)o[i]; 55831ce8d88SJasvinder Singh } 55931ce8d88SJasvinder Singh /* Support the format XXXX:XXXX:XXXX */ 560*35b2d13fSOlivier Matz } else if (i == RTE_ETHER_ADDR_LEN / 2) { 56131ce8d88SJasvinder Singh while (i-- != 0) { 56231ce8d88SJasvinder Singh if (o[i] > UINT16_MAX) 56331ce8d88SJasvinder Singh return NULL; 56431ce8d88SJasvinder Singh ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8); 56531ce8d88SJasvinder Singh ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff); 56631ce8d88SJasvinder Singh } 56731ce8d88SJasvinder Singh /* unknown format */ 56831ce8d88SJasvinder Singh } else 56931ce8d88SJasvinder Singh return NULL; 57031ce8d88SJasvinder Singh 5716d13ea8eSOlivier Matz return (struct rte_ether_addr *)ðer_addr; 57231ce8d88SJasvinder Singh } 57331ce8d88SJasvinder Singh 57431ce8d88SJasvinder Singh int 57531ce8d88SJasvinder Singh softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4) 57631ce8d88SJasvinder Singh { 57731ce8d88SJasvinder Singh if (strlen(token) >= INET_ADDRSTRLEN) 57831ce8d88SJasvinder Singh return -EINVAL; 57931ce8d88SJasvinder Singh 58031ce8d88SJasvinder Singh if (inet_pton4(token, (unsigned char *)ipv4) != 1) 58131ce8d88SJasvinder Singh return -EINVAL; 58231ce8d88SJasvinder Singh 58331ce8d88SJasvinder Singh return 0; 58431ce8d88SJasvinder Singh } 58531ce8d88SJasvinder Singh 58631ce8d88SJasvinder Singh int 58731ce8d88SJasvinder Singh softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6) 58831ce8d88SJasvinder Singh { 58931ce8d88SJasvinder Singh if (strlen(token) >= INET6_ADDRSTRLEN) 59031ce8d88SJasvinder Singh return -EINVAL; 59131ce8d88SJasvinder Singh 59231ce8d88SJasvinder Singh if (inet_pton6(token, (unsigned char *)ipv6) != 1) 59331ce8d88SJasvinder Singh return -EINVAL; 59431ce8d88SJasvinder Singh 59531ce8d88SJasvinder Singh return 0; 59631ce8d88SJasvinder Singh } 59731ce8d88SJasvinder Singh 59831ce8d88SJasvinder Singh int 5996d13ea8eSOlivier Matz softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr) 60031ce8d88SJasvinder Singh { 6016d13ea8eSOlivier Matz struct rte_ether_addr *tmp; 60231ce8d88SJasvinder Singh 60331ce8d88SJasvinder Singh tmp = my_ether_aton(token); 60431ce8d88SJasvinder Singh if (tmp == NULL) 60531ce8d88SJasvinder Singh return -1; 60631ce8d88SJasvinder Singh 6076d13ea8eSOlivier Matz memcpy(addr, tmp, sizeof(struct rte_ether_addr)); 60831ce8d88SJasvinder Singh return 0; 60931ce8d88SJasvinder Singh } 61031ce8d88SJasvinder Singh 61131ce8d88SJasvinder Singh int 61231ce8d88SJasvinder Singh softnic_parse_cpu_core(const char *entry, 61331ce8d88SJasvinder Singh struct softnic_cpu_core_params *p) 61431ce8d88SJasvinder Singh { 61531ce8d88SJasvinder Singh size_t num_len; 61631ce8d88SJasvinder Singh char num[8]; 61731ce8d88SJasvinder Singh 61831ce8d88SJasvinder Singh uint32_t s = 0, c = 0, h = 0, val; 61931ce8d88SJasvinder Singh uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; 62031ce8d88SJasvinder Singh const char *next = skip_white_spaces(entry); 62131ce8d88SJasvinder Singh char type; 62231ce8d88SJasvinder Singh 62331ce8d88SJasvinder Singh if (p == NULL) 62431ce8d88SJasvinder Singh return -EINVAL; 62531ce8d88SJasvinder Singh 62631ce8d88SJasvinder Singh /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */ 62731ce8d88SJasvinder Singh while (*next != '\0') { 62831ce8d88SJasvinder Singh /* If everything parsed nothing should left */ 62931ce8d88SJasvinder Singh if (s_parsed && c_parsed && h_parsed) 63031ce8d88SJasvinder Singh return -EINVAL; 63131ce8d88SJasvinder Singh 63231ce8d88SJasvinder Singh type = *next; 63331ce8d88SJasvinder Singh switch (type) { 63431ce8d88SJasvinder Singh case 's': 63531ce8d88SJasvinder Singh case 'S': 63631ce8d88SJasvinder Singh if (s_parsed || c_parsed || h_parsed) 63731ce8d88SJasvinder Singh return -EINVAL; 63831ce8d88SJasvinder Singh s_parsed = 1; 63931ce8d88SJasvinder Singh next++; 64031ce8d88SJasvinder Singh break; 64131ce8d88SJasvinder Singh case 'c': 64231ce8d88SJasvinder Singh case 'C': 64331ce8d88SJasvinder Singh if (c_parsed || h_parsed) 64431ce8d88SJasvinder Singh return -EINVAL; 64531ce8d88SJasvinder Singh c_parsed = 1; 64631ce8d88SJasvinder Singh next++; 64731ce8d88SJasvinder Singh break; 64831ce8d88SJasvinder Singh case 'h': 64931ce8d88SJasvinder Singh case 'H': 65031ce8d88SJasvinder Singh if (h_parsed) 65131ce8d88SJasvinder Singh return -EINVAL; 65231ce8d88SJasvinder Singh h_parsed = 1; 65331ce8d88SJasvinder Singh next++; 65431ce8d88SJasvinder Singh break; 65531ce8d88SJasvinder Singh default: 65631ce8d88SJasvinder Singh /* If it start from digit it must be only core id. */ 65731ce8d88SJasvinder Singh if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) 65831ce8d88SJasvinder Singh return -EINVAL; 65931ce8d88SJasvinder Singh 66031ce8d88SJasvinder Singh type = 'C'; 66131ce8d88SJasvinder Singh } 66231ce8d88SJasvinder Singh 66331ce8d88SJasvinder Singh for (num_len = 0; *next != '\0'; next++, num_len++) { 66431ce8d88SJasvinder Singh if (num_len == RTE_DIM(num)) 66531ce8d88SJasvinder Singh return -EINVAL; 66631ce8d88SJasvinder Singh 66731ce8d88SJasvinder Singh if (!isdigit(*next)) 66831ce8d88SJasvinder Singh break; 66931ce8d88SJasvinder Singh 67031ce8d88SJasvinder Singh num[num_len] = *next; 67131ce8d88SJasvinder Singh } 67231ce8d88SJasvinder Singh 67331ce8d88SJasvinder Singh if (num_len == 0 && type != 'h' && type != 'H') 67431ce8d88SJasvinder Singh return -EINVAL; 67531ce8d88SJasvinder Singh 67631ce8d88SJasvinder Singh if (num_len != 0 && (type == 'h' || type == 'H')) 67731ce8d88SJasvinder Singh return -EINVAL; 67831ce8d88SJasvinder Singh 67931ce8d88SJasvinder Singh num[num_len] = '\0'; 68031ce8d88SJasvinder Singh val = strtol(num, NULL, 10); 68131ce8d88SJasvinder Singh 68231ce8d88SJasvinder Singh h = 0; 68331ce8d88SJasvinder Singh switch (type) { 68431ce8d88SJasvinder Singh case 's': 68531ce8d88SJasvinder Singh case 'S': 68631ce8d88SJasvinder Singh s = val; 68731ce8d88SJasvinder Singh break; 68831ce8d88SJasvinder Singh case 'c': 68931ce8d88SJasvinder Singh case 'C': 69031ce8d88SJasvinder Singh c = val; 69131ce8d88SJasvinder Singh break; 69231ce8d88SJasvinder Singh case 'h': 69331ce8d88SJasvinder Singh case 'H': 69431ce8d88SJasvinder Singh h = 1; 69531ce8d88SJasvinder Singh break; 69631ce8d88SJasvinder Singh } 69731ce8d88SJasvinder Singh } 69831ce8d88SJasvinder Singh 69931ce8d88SJasvinder Singh p->socket_id = s; 70031ce8d88SJasvinder Singh p->core_id = c; 70131ce8d88SJasvinder Singh p->thread_id = h; 70231ce8d88SJasvinder Singh return 0; 70331ce8d88SJasvinder Singh } 704