1f819588bSLee Daly /* SPDX-License-Identifier: BSD-3-Clause 2f819588bSLee Daly * Copyright(c) 2016 Intel Corporation. 3ed7a0490SPiotr Azarewicz * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> 4ed7a0490SPiotr Azarewicz * All rights reserved. 5ed7a0490SPiotr Azarewicz */ 6ed7a0490SPiotr Azarewicz 7ed7a0490SPiotr Azarewicz /* 8ed7a0490SPiotr Azarewicz * For inet_pton4() and inet_pton6() functions: 9ed7a0490SPiotr Azarewicz * 10ed7a0490SPiotr Azarewicz * Copyright (c) 1996 by Internet Software Consortium. 11ed7a0490SPiotr Azarewicz * 12ed7a0490SPiotr Azarewicz * Permission to use, copy, modify, and distribute this software for any 13ed7a0490SPiotr Azarewicz * purpose with or without fee is hereby granted, provided that the above 14ed7a0490SPiotr Azarewicz * copyright notice and this permission notice appear in all copies. 15ed7a0490SPiotr Azarewicz * 16ed7a0490SPiotr Azarewicz * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 17ed7a0490SPiotr Azarewicz * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 18ed7a0490SPiotr Azarewicz * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 19ed7a0490SPiotr Azarewicz * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 20ed7a0490SPiotr Azarewicz * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 21ed7a0490SPiotr Azarewicz * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 22ed7a0490SPiotr Azarewicz * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23ed7a0490SPiotr Azarewicz * SOFTWARE. 24ed7a0490SPiotr Azarewicz */ 25ed7a0490SPiotr Azarewicz 26ed7a0490SPiotr Azarewicz #include <stdint.h> 27ed7a0490SPiotr Azarewicz #include <stdlib.h> 28ed7a0490SPiotr Azarewicz #include <stdio.h> 29ed7a0490SPiotr Azarewicz #include <ctype.h> 30ed7a0490SPiotr Azarewicz #include <getopt.h> 31ed7a0490SPiotr Azarewicz #include <errno.h> 32ed7a0490SPiotr Azarewicz #include <stdarg.h> 33ed7a0490SPiotr Azarewicz #include <string.h> 34ed7a0490SPiotr Azarewicz #include <libgen.h> 35ed7a0490SPiotr Azarewicz #include <unistd.h> 36ed7a0490SPiotr Azarewicz #include <sys/wait.h> 37ed7a0490SPiotr Azarewicz 38ed7a0490SPiotr Azarewicz #include <rte_errno.h> 39ed7a0490SPiotr Azarewicz #include <rte_string_fns.h> 40ed7a0490SPiotr Azarewicz 41ed7a0490SPiotr Azarewicz #include "parser.h" 42ed7a0490SPiotr Azarewicz 43ed7a0490SPiotr Azarewicz static uint32_t 44ed7a0490SPiotr Azarewicz get_hex_val(char c) 45ed7a0490SPiotr Azarewicz { 46ed7a0490SPiotr Azarewicz switch (c) { 47ed7a0490SPiotr Azarewicz case '0': case '1': case '2': case '3': case '4': case '5': 48ed7a0490SPiotr Azarewicz case '6': case '7': case '8': case '9': 49ed7a0490SPiotr Azarewicz return c - '0'; 50ed7a0490SPiotr Azarewicz case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 51ed7a0490SPiotr Azarewicz return c - 'A' + 10; 52ed7a0490SPiotr Azarewicz case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 53ed7a0490SPiotr Azarewicz return c - 'a' + 10; 54ed7a0490SPiotr Azarewicz default: 55ed7a0490SPiotr Azarewicz return 0; 56ed7a0490SPiotr Azarewicz } 57ed7a0490SPiotr Azarewicz } 58ed7a0490SPiotr Azarewicz 59ed7a0490SPiotr Azarewicz int 60ed7a0490SPiotr Azarewicz parser_read_arg_bool(const char *p) 61ed7a0490SPiotr Azarewicz { 62ed7a0490SPiotr Azarewicz p = skip_white_spaces(p); 63ed7a0490SPiotr Azarewicz int result = -EINVAL; 64ed7a0490SPiotr Azarewicz 65ed7a0490SPiotr Azarewicz if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || 66ed7a0490SPiotr Azarewicz ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { 67ed7a0490SPiotr Azarewicz p += 3; 68ed7a0490SPiotr Azarewicz result = 1; 69ed7a0490SPiotr Azarewicz } 70ed7a0490SPiotr Azarewicz 71ed7a0490SPiotr Azarewicz if (((p[0] == 'o') && (p[1] == 'n')) || 72ed7a0490SPiotr Azarewicz ((p[0] == 'O') && (p[1] == 'N'))) { 73ed7a0490SPiotr Azarewicz p += 2; 74ed7a0490SPiotr Azarewicz result = 1; 75ed7a0490SPiotr Azarewicz } 76ed7a0490SPiotr Azarewicz 77ed7a0490SPiotr Azarewicz if (((p[0] == 'n') && (p[1] == 'o')) || 78ed7a0490SPiotr Azarewicz ((p[0] == 'N') && (p[1] == 'O'))) { 79ed7a0490SPiotr Azarewicz p += 2; 80ed7a0490SPiotr Azarewicz result = 0; 81ed7a0490SPiotr Azarewicz } 82ed7a0490SPiotr Azarewicz 83ed7a0490SPiotr Azarewicz if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || 84ed7a0490SPiotr Azarewicz ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { 85ed7a0490SPiotr Azarewicz p += 3; 86ed7a0490SPiotr Azarewicz result = 0; 87ed7a0490SPiotr Azarewicz } 88ed7a0490SPiotr Azarewicz 89ed7a0490SPiotr Azarewicz p = skip_white_spaces(p); 90ed7a0490SPiotr Azarewicz 91ed7a0490SPiotr Azarewicz if (p[0] != '\0') 92ed7a0490SPiotr Azarewicz return -EINVAL; 93ed7a0490SPiotr Azarewicz 94ed7a0490SPiotr Azarewicz return result; 95ed7a0490SPiotr Azarewicz } 96ed7a0490SPiotr Azarewicz 97ed7a0490SPiotr Azarewicz int 98ed7a0490SPiotr Azarewicz parser_read_uint64(uint64_t *value, const char *p) 99ed7a0490SPiotr Azarewicz { 100ed7a0490SPiotr Azarewicz char *next; 101ed7a0490SPiotr Azarewicz uint64_t val; 102ed7a0490SPiotr Azarewicz 103ed7a0490SPiotr Azarewicz p = skip_white_spaces(p); 104ed7a0490SPiotr Azarewicz if (!isdigit(*p)) 105ed7a0490SPiotr Azarewicz return -EINVAL; 106ed7a0490SPiotr Azarewicz 107ed7a0490SPiotr Azarewicz val = strtoul(p, &next, 10); 108ed7a0490SPiotr Azarewicz if (p == next) 109ed7a0490SPiotr Azarewicz return -EINVAL; 110ed7a0490SPiotr Azarewicz 111ed7a0490SPiotr Azarewicz p = next; 112ed7a0490SPiotr Azarewicz switch (*p) { 113ed7a0490SPiotr Azarewicz case 'T': 114ed7a0490SPiotr Azarewicz val *= 1024ULL; 115ed7a0490SPiotr Azarewicz /* fall through */ 116ed7a0490SPiotr Azarewicz case 'G': 117ed7a0490SPiotr Azarewicz val *= 1024ULL; 118ed7a0490SPiotr Azarewicz /* fall through */ 119ed7a0490SPiotr Azarewicz case 'M': 120ed7a0490SPiotr Azarewicz val *= 1024ULL; 121ed7a0490SPiotr Azarewicz /* fall through */ 122ed7a0490SPiotr Azarewicz case 'k': 123ed7a0490SPiotr Azarewicz case 'K': 124ed7a0490SPiotr Azarewicz val *= 1024ULL; 125ed7a0490SPiotr Azarewicz p++; 126ed7a0490SPiotr Azarewicz break; 127ed7a0490SPiotr Azarewicz } 128ed7a0490SPiotr Azarewicz 129ed7a0490SPiotr Azarewicz p = skip_white_spaces(p); 130ed7a0490SPiotr Azarewicz if (*p != '\0') 131ed7a0490SPiotr Azarewicz return -EINVAL; 132ed7a0490SPiotr Azarewicz 133ed7a0490SPiotr Azarewicz *value = val; 134ed7a0490SPiotr Azarewicz return 0; 135ed7a0490SPiotr Azarewicz } 136ed7a0490SPiotr Azarewicz 137ed7a0490SPiotr Azarewicz int 138ed7a0490SPiotr Azarewicz parser_read_uint64_hex(uint64_t *value, const char *p) 139ed7a0490SPiotr Azarewicz { 140ed7a0490SPiotr Azarewicz char *next; 141ed7a0490SPiotr Azarewicz uint64_t val; 142ed7a0490SPiotr Azarewicz 143ed7a0490SPiotr Azarewicz p = skip_white_spaces(p); 144ed7a0490SPiotr Azarewicz 145ed7a0490SPiotr Azarewicz val = strtoul(p, &next, 16); 146ed7a0490SPiotr Azarewicz if (p == next) 147ed7a0490SPiotr Azarewicz return -EINVAL; 148ed7a0490SPiotr Azarewicz 149ed7a0490SPiotr Azarewicz p = skip_white_spaces(next); 150ed7a0490SPiotr Azarewicz if (*p != '\0') 151ed7a0490SPiotr Azarewicz return -EINVAL; 152ed7a0490SPiotr Azarewicz 153ed7a0490SPiotr Azarewicz *value = val; 154ed7a0490SPiotr Azarewicz return 0; 155ed7a0490SPiotr Azarewicz } 156ed7a0490SPiotr Azarewicz 157ed7a0490SPiotr Azarewicz int 158ed7a0490SPiotr Azarewicz parser_read_uint32(uint32_t *value, const char *p) 159ed7a0490SPiotr Azarewicz { 160ed7a0490SPiotr Azarewicz uint64_t val = 0; 161ed7a0490SPiotr Azarewicz int ret = parser_read_uint64(&val, p); 162ed7a0490SPiotr Azarewicz 163ed7a0490SPiotr Azarewicz if (ret < 0) 164ed7a0490SPiotr Azarewicz return ret; 165ed7a0490SPiotr Azarewicz 166ed7a0490SPiotr Azarewicz if (val > UINT32_MAX) 167ed7a0490SPiotr Azarewicz return -ERANGE; 168ed7a0490SPiotr Azarewicz 169ed7a0490SPiotr Azarewicz *value = val; 170ed7a0490SPiotr Azarewicz return 0; 171ed7a0490SPiotr Azarewicz } 172ed7a0490SPiotr Azarewicz 173ed7a0490SPiotr Azarewicz int 174ed7a0490SPiotr Azarewicz parser_read_uint32_hex(uint32_t *value, const char *p) 175ed7a0490SPiotr Azarewicz { 176ed7a0490SPiotr Azarewicz uint64_t val = 0; 177ed7a0490SPiotr Azarewicz int ret = parser_read_uint64_hex(&val, p); 178ed7a0490SPiotr Azarewicz 179ed7a0490SPiotr Azarewicz if (ret < 0) 180ed7a0490SPiotr Azarewicz return ret; 181ed7a0490SPiotr Azarewicz 182ed7a0490SPiotr Azarewicz if (val > UINT32_MAX) 183ed7a0490SPiotr Azarewicz return -ERANGE; 184ed7a0490SPiotr Azarewicz 185ed7a0490SPiotr Azarewicz *value = val; 186ed7a0490SPiotr Azarewicz return 0; 187ed7a0490SPiotr Azarewicz } 188ed7a0490SPiotr Azarewicz 189ed7a0490SPiotr Azarewicz int 190ed7a0490SPiotr Azarewicz parser_read_uint16(uint16_t *value, const char *p) 191ed7a0490SPiotr Azarewicz { 192ed7a0490SPiotr Azarewicz uint64_t val = 0; 193ed7a0490SPiotr Azarewicz int ret = parser_read_uint64(&val, p); 194ed7a0490SPiotr Azarewicz 195ed7a0490SPiotr Azarewicz if (ret < 0) 196ed7a0490SPiotr Azarewicz return ret; 197ed7a0490SPiotr Azarewicz 198ed7a0490SPiotr Azarewicz if (val > UINT16_MAX) 199ed7a0490SPiotr Azarewicz return -ERANGE; 200ed7a0490SPiotr Azarewicz 201ed7a0490SPiotr Azarewicz *value = val; 202ed7a0490SPiotr Azarewicz return 0; 203ed7a0490SPiotr Azarewicz } 204ed7a0490SPiotr Azarewicz 205ed7a0490SPiotr Azarewicz int 206ed7a0490SPiotr Azarewicz parser_read_uint16_hex(uint16_t *value, const char *p) 207ed7a0490SPiotr Azarewicz { 208ed7a0490SPiotr Azarewicz uint64_t val = 0; 209ed7a0490SPiotr Azarewicz int ret = parser_read_uint64_hex(&val, p); 210ed7a0490SPiotr Azarewicz 211ed7a0490SPiotr Azarewicz if (ret < 0) 212ed7a0490SPiotr Azarewicz return ret; 213ed7a0490SPiotr Azarewicz 214ed7a0490SPiotr Azarewicz if (val > UINT16_MAX) 215ed7a0490SPiotr Azarewicz return -ERANGE; 216ed7a0490SPiotr Azarewicz 217ed7a0490SPiotr Azarewicz *value = val; 218ed7a0490SPiotr Azarewicz return 0; 219ed7a0490SPiotr Azarewicz } 220ed7a0490SPiotr Azarewicz 221ed7a0490SPiotr Azarewicz int 222ed7a0490SPiotr Azarewicz parser_read_uint8(uint8_t *value, const char *p) 223ed7a0490SPiotr Azarewicz { 224ed7a0490SPiotr Azarewicz uint64_t val = 0; 225ed7a0490SPiotr Azarewicz int ret = parser_read_uint64(&val, p); 226ed7a0490SPiotr Azarewicz 227ed7a0490SPiotr Azarewicz if (ret < 0) 228ed7a0490SPiotr Azarewicz return ret; 229ed7a0490SPiotr Azarewicz 230ed7a0490SPiotr Azarewicz if (val > UINT8_MAX) 231ed7a0490SPiotr Azarewicz return -ERANGE; 232ed7a0490SPiotr Azarewicz 233ed7a0490SPiotr Azarewicz *value = val; 234ed7a0490SPiotr Azarewicz return 0; 235ed7a0490SPiotr Azarewicz } 236ed7a0490SPiotr Azarewicz 237ed7a0490SPiotr Azarewicz int 238ed7a0490SPiotr Azarewicz parser_read_uint8_hex(uint8_t *value, const char *p) 239ed7a0490SPiotr Azarewicz { 240ed7a0490SPiotr Azarewicz uint64_t val = 0; 241ed7a0490SPiotr Azarewicz int ret = parser_read_uint64_hex(&val, p); 242ed7a0490SPiotr Azarewicz 243ed7a0490SPiotr Azarewicz if (ret < 0) 244ed7a0490SPiotr Azarewicz return ret; 245ed7a0490SPiotr Azarewicz 246ed7a0490SPiotr Azarewicz if (val > UINT8_MAX) 247ed7a0490SPiotr Azarewicz return -ERANGE; 248ed7a0490SPiotr Azarewicz 249ed7a0490SPiotr Azarewicz *value = val; 250ed7a0490SPiotr Azarewicz return 0; 251ed7a0490SPiotr Azarewicz } 252ed7a0490SPiotr Azarewicz 253ed7a0490SPiotr Azarewicz int 254ed7a0490SPiotr Azarewicz parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 255ed7a0490SPiotr Azarewicz { 256ed7a0490SPiotr Azarewicz uint32_t i; 257ed7a0490SPiotr Azarewicz 258ed7a0490SPiotr Azarewicz if ((string == NULL) || 259ed7a0490SPiotr Azarewicz (tokens == NULL) || 260ed7a0490SPiotr Azarewicz (*n_tokens < 1)) 261ed7a0490SPiotr Azarewicz return -EINVAL; 262ed7a0490SPiotr Azarewicz 263ed7a0490SPiotr Azarewicz for (i = 0; i < *n_tokens; i++) { 264ed7a0490SPiotr Azarewicz tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 265ed7a0490SPiotr Azarewicz if (tokens[i] == NULL) 266ed7a0490SPiotr Azarewicz break; 267ed7a0490SPiotr Azarewicz } 268ed7a0490SPiotr Azarewicz 269ed7a0490SPiotr Azarewicz if ((i == *n_tokens) && 270ed7a0490SPiotr Azarewicz (NULL != strtok_r(string, PARSE_DELIMITER, &string))) 271ed7a0490SPiotr Azarewicz return -E2BIG; 272ed7a0490SPiotr Azarewicz 273ed7a0490SPiotr Azarewicz *n_tokens = i; 274ed7a0490SPiotr Azarewicz return 0; 275ed7a0490SPiotr Azarewicz } 276ed7a0490SPiotr Azarewicz 277ed7a0490SPiotr Azarewicz int 278ed7a0490SPiotr Azarewicz parse_hex_string(char *src, uint8_t *dst, uint32_t *size) 279ed7a0490SPiotr Azarewicz { 280ed7a0490SPiotr Azarewicz char *c; 281ed7a0490SPiotr Azarewicz uint32_t len, i; 282ed7a0490SPiotr Azarewicz 283ed7a0490SPiotr Azarewicz /* Check input parameters */ 284ed7a0490SPiotr Azarewicz if ((src == NULL) || 285ed7a0490SPiotr Azarewicz (dst == NULL) || 286ed7a0490SPiotr Azarewicz (size == NULL) || 287ed7a0490SPiotr Azarewicz (*size == 0)) 288ed7a0490SPiotr Azarewicz return -1; 289ed7a0490SPiotr Azarewicz 290ed7a0490SPiotr Azarewicz len = strlen(src); 291ed7a0490SPiotr Azarewicz if (((len & 3) != 0) || 292ed7a0490SPiotr Azarewicz (len > (*size) * 2)) 293ed7a0490SPiotr Azarewicz return -1; 294ed7a0490SPiotr Azarewicz *size = len / 2; 295ed7a0490SPiotr Azarewicz 296ed7a0490SPiotr Azarewicz for (c = src; *c != 0; c++) { 297ed7a0490SPiotr Azarewicz if ((((*c) >= '0') && ((*c) <= '9')) || 298ed7a0490SPiotr Azarewicz (((*c) >= 'A') && ((*c) <= 'F')) || 299ed7a0490SPiotr Azarewicz (((*c) >= 'a') && ((*c) <= 'f'))) 300ed7a0490SPiotr Azarewicz continue; 301ed7a0490SPiotr Azarewicz 302ed7a0490SPiotr Azarewicz return -1; 303ed7a0490SPiotr Azarewicz } 304ed7a0490SPiotr Azarewicz 305ed7a0490SPiotr Azarewicz /* Convert chars to bytes */ 306ed7a0490SPiotr Azarewicz for (i = 0; i < *size; i++) 307ed7a0490SPiotr Azarewicz dst[i] = get_hex_val(src[2 * i]) * 16 + 308ed7a0490SPiotr Azarewicz get_hex_val(src[2 * i + 1]); 309ed7a0490SPiotr Azarewicz 310ed7a0490SPiotr Azarewicz return 0; 311ed7a0490SPiotr Azarewicz } 312ed7a0490SPiotr Azarewicz 313ed7a0490SPiotr Azarewicz int 314ed7a0490SPiotr Azarewicz parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels) 315ed7a0490SPiotr Azarewicz { 316ed7a0490SPiotr Azarewicz uint32_t n_max_labels = *n_labels, count = 0; 317ed7a0490SPiotr Azarewicz 318ed7a0490SPiotr Azarewicz /* Check for void list of labels */ 319ed7a0490SPiotr Azarewicz if (strcmp(string, "<void>") == 0) { 320ed7a0490SPiotr Azarewicz *n_labels = 0; 321ed7a0490SPiotr Azarewicz return 0; 322ed7a0490SPiotr Azarewicz } 323ed7a0490SPiotr Azarewicz 324ed7a0490SPiotr Azarewicz /* At least one label should be present */ 325ed7a0490SPiotr Azarewicz for ( ; (*string != '\0'); ) { 326ed7a0490SPiotr Azarewicz char *next; 327ed7a0490SPiotr Azarewicz int value; 328ed7a0490SPiotr Azarewicz 329ed7a0490SPiotr Azarewicz if (count >= n_max_labels) 330ed7a0490SPiotr Azarewicz return -1; 331ed7a0490SPiotr Azarewicz 332ed7a0490SPiotr Azarewicz if (count > 0) { 333ed7a0490SPiotr Azarewicz if (string[0] != ':') 334ed7a0490SPiotr Azarewicz return -1; 335ed7a0490SPiotr Azarewicz 336ed7a0490SPiotr Azarewicz string++; 337ed7a0490SPiotr Azarewicz } 338ed7a0490SPiotr Azarewicz 339ed7a0490SPiotr Azarewicz value = strtol(string, &next, 10); 340ed7a0490SPiotr Azarewicz if (next == string) 341ed7a0490SPiotr Azarewicz return -1; 342ed7a0490SPiotr Azarewicz string = next; 343ed7a0490SPiotr Azarewicz 344ed7a0490SPiotr Azarewicz labels[count++] = (uint32_t) value; 345ed7a0490SPiotr Azarewicz } 346ed7a0490SPiotr Azarewicz 347ed7a0490SPiotr Azarewicz *n_labels = count; 348ed7a0490SPiotr Azarewicz return 0; 349ed7a0490SPiotr Azarewicz } 350ed7a0490SPiotr Azarewicz 351ed7a0490SPiotr Azarewicz #define INADDRSZ 4 352ed7a0490SPiotr Azarewicz #define IN6ADDRSZ 16 353ed7a0490SPiotr Azarewicz 354ed7a0490SPiotr Azarewicz /* int 355ed7a0490SPiotr Azarewicz * inet_pton4(src, dst) 356ed7a0490SPiotr Azarewicz * like inet_aton() but without all the hexadecimal and shorthand. 357ed7a0490SPiotr Azarewicz * return: 358ed7a0490SPiotr Azarewicz * 1 if `src' is a valid dotted quad, else 0. 359ed7a0490SPiotr Azarewicz * notice: 360ed7a0490SPiotr Azarewicz * does not touch `dst' unless it's returning 1. 361ed7a0490SPiotr Azarewicz * author: 362ed7a0490SPiotr Azarewicz * Paul Vixie, 1996. 363ed7a0490SPiotr Azarewicz */ 364ed7a0490SPiotr Azarewicz static int 365ed7a0490SPiotr Azarewicz inet_pton4(const char *src, unsigned char *dst) 366ed7a0490SPiotr Azarewicz { 367ed7a0490SPiotr Azarewicz static const char digits[] = "0123456789"; 368ed7a0490SPiotr Azarewicz int saw_digit, octets, ch; 369ed7a0490SPiotr Azarewicz unsigned char tmp[INADDRSZ], *tp; 370ed7a0490SPiotr Azarewicz 371ed7a0490SPiotr Azarewicz saw_digit = 0; 372ed7a0490SPiotr Azarewicz octets = 0; 373ed7a0490SPiotr Azarewicz *(tp = tmp) = 0; 374ed7a0490SPiotr Azarewicz while ((ch = *src++) != '\0') { 375ed7a0490SPiotr Azarewicz const char *pch; 376ed7a0490SPiotr Azarewicz 377ed7a0490SPiotr Azarewicz pch = strchr(digits, ch); 378ed7a0490SPiotr Azarewicz if (pch != NULL) { 379ed7a0490SPiotr Azarewicz unsigned int new = *tp * 10 + (pch - digits); 380ed7a0490SPiotr Azarewicz 381ed7a0490SPiotr Azarewicz if (new > 255) 382ed7a0490SPiotr Azarewicz return 0; 383ed7a0490SPiotr Azarewicz if (!saw_digit) { 384ed7a0490SPiotr Azarewicz if (++octets > 4) 385ed7a0490SPiotr Azarewicz return 0; 386ed7a0490SPiotr Azarewicz saw_digit = 1; 387ed7a0490SPiotr Azarewicz } 388ed7a0490SPiotr Azarewicz *tp = (unsigned char)new; 389ed7a0490SPiotr Azarewicz } else if (ch == '.' && saw_digit) { 390ed7a0490SPiotr Azarewicz if (octets == 4) 391ed7a0490SPiotr Azarewicz return 0; 392ed7a0490SPiotr Azarewicz *++tp = 0; 393ed7a0490SPiotr Azarewicz saw_digit = 0; 394ed7a0490SPiotr Azarewicz } else 395ed7a0490SPiotr Azarewicz return 0; 396ed7a0490SPiotr Azarewicz } 397ed7a0490SPiotr Azarewicz if (octets < 4) 398ed7a0490SPiotr Azarewicz return 0; 399ed7a0490SPiotr Azarewicz 400ed7a0490SPiotr Azarewicz memcpy(dst, tmp, INADDRSZ); 401ed7a0490SPiotr Azarewicz return 1; 402ed7a0490SPiotr Azarewicz } 403ed7a0490SPiotr Azarewicz 404ed7a0490SPiotr Azarewicz /* int 405ed7a0490SPiotr Azarewicz * inet_pton6(src, dst) 406ed7a0490SPiotr Azarewicz * convert presentation level address to network order binary form. 407ed7a0490SPiotr Azarewicz * return: 408ed7a0490SPiotr Azarewicz * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 409ed7a0490SPiotr Azarewicz * notice: 410ed7a0490SPiotr Azarewicz * (1) does not touch `dst' unless it's returning 1. 411ed7a0490SPiotr Azarewicz * (2) :: in a full address is silently ignored. 412ed7a0490SPiotr Azarewicz * credit: 413ed7a0490SPiotr Azarewicz * inspired by Mark Andrews. 414ed7a0490SPiotr Azarewicz * author: 415ed7a0490SPiotr Azarewicz * Paul Vixie, 1996. 416ed7a0490SPiotr Azarewicz */ 417ed7a0490SPiotr Azarewicz static int 418ed7a0490SPiotr Azarewicz inet_pton6(const char *src, unsigned char *dst) 419ed7a0490SPiotr Azarewicz { 420ed7a0490SPiotr Azarewicz static const char xdigits_l[] = "0123456789abcdef", 421ed7a0490SPiotr Azarewicz xdigits_u[] = "0123456789ABCDEF"; 422ed7a0490SPiotr Azarewicz unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; 423ed7a0490SPiotr Azarewicz const char *xdigits = 0, *curtok = 0; 424ed7a0490SPiotr Azarewicz int ch = 0, saw_xdigit = 0, count_xdigit = 0; 425ed7a0490SPiotr Azarewicz unsigned int val = 0; 426ed7a0490SPiotr Azarewicz unsigned dbloct_count = 0; 427ed7a0490SPiotr Azarewicz 428ed7a0490SPiotr Azarewicz memset((tp = tmp), '\0', IN6ADDRSZ); 429ed7a0490SPiotr Azarewicz endp = tp + IN6ADDRSZ; 430ed7a0490SPiotr Azarewicz colonp = NULL; 431ed7a0490SPiotr Azarewicz /* Leading :: requires some special handling. */ 432ed7a0490SPiotr Azarewicz if (*src == ':') 433ed7a0490SPiotr Azarewicz if (*++src != ':') 434ed7a0490SPiotr Azarewicz return 0; 435ed7a0490SPiotr Azarewicz curtok = src; 436ed7a0490SPiotr Azarewicz saw_xdigit = count_xdigit = 0; 437ed7a0490SPiotr Azarewicz val = 0; 438ed7a0490SPiotr Azarewicz 439ed7a0490SPiotr Azarewicz while ((ch = *src++) != '\0') { 440ed7a0490SPiotr Azarewicz const char *pch; 441ed7a0490SPiotr Azarewicz 442ed7a0490SPiotr Azarewicz pch = strchr((xdigits = xdigits_l), ch); 443ed7a0490SPiotr Azarewicz if (pch == NULL) 444ed7a0490SPiotr Azarewicz pch = strchr((xdigits = xdigits_u), ch); 445ed7a0490SPiotr Azarewicz if (pch != NULL) { 446ed7a0490SPiotr Azarewicz if (count_xdigit >= 4) 447ed7a0490SPiotr Azarewicz return 0; 448ed7a0490SPiotr Azarewicz val <<= 4; 449ed7a0490SPiotr Azarewicz val |= (pch - xdigits); 450ed7a0490SPiotr Azarewicz if (val > 0xffff) 451ed7a0490SPiotr Azarewicz return 0; 452ed7a0490SPiotr Azarewicz saw_xdigit = 1; 453ed7a0490SPiotr Azarewicz count_xdigit++; 454ed7a0490SPiotr Azarewicz continue; 455ed7a0490SPiotr Azarewicz } 456ed7a0490SPiotr Azarewicz if (ch == ':') { 457ed7a0490SPiotr Azarewicz curtok = src; 458ed7a0490SPiotr Azarewicz if (!saw_xdigit) { 459ed7a0490SPiotr Azarewicz if (colonp) 460ed7a0490SPiotr Azarewicz return 0; 461ed7a0490SPiotr Azarewicz colonp = tp; 462ed7a0490SPiotr Azarewicz continue; 463ed7a0490SPiotr Azarewicz } else if (*src == '\0') { 464ed7a0490SPiotr Azarewicz return 0; 465ed7a0490SPiotr Azarewicz } 466ed7a0490SPiotr Azarewicz if (tp + sizeof(int16_t) > endp) 467ed7a0490SPiotr Azarewicz return 0; 468ed7a0490SPiotr Azarewicz *tp++ = (unsigned char) ((val >> 8) & 0xff); 469ed7a0490SPiotr Azarewicz *tp++ = (unsigned char) (val & 0xff); 470ed7a0490SPiotr Azarewicz saw_xdigit = 0; 471ed7a0490SPiotr Azarewicz count_xdigit = 0; 472ed7a0490SPiotr Azarewicz val = 0; 473ed7a0490SPiotr Azarewicz dbloct_count++; 474ed7a0490SPiotr Azarewicz continue; 475ed7a0490SPiotr Azarewicz } 476ed7a0490SPiotr Azarewicz if (ch == '.' && ((tp + INADDRSZ) <= endp) && 477ed7a0490SPiotr Azarewicz inet_pton4(curtok, tp) > 0) { 478ed7a0490SPiotr Azarewicz tp += INADDRSZ; 479ed7a0490SPiotr Azarewicz saw_xdigit = 0; 480ed7a0490SPiotr Azarewicz dbloct_count += 2; 481ed7a0490SPiotr Azarewicz break; /* '\0' was seen by inet_pton4(). */ 482ed7a0490SPiotr Azarewicz } 483ed7a0490SPiotr Azarewicz return 0; 484ed7a0490SPiotr Azarewicz } 485ed7a0490SPiotr Azarewicz if (saw_xdigit) { 486ed7a0490SPiotr Azarewicz if (tp + sizeof(int16_t) > endp) 487ed7a0490SPiotr Azarewicz return 0; 488ed7a0490SPiotr Azarewicz *tp++ = (unsigned char) ((val >> 8) & 0xff); 489ed7a0490SPiotr Azarewicz *tp++ = (unsigned char) (val & 0xff); 490ed7a0490SPiotr Azarewicz dbloct_count++; 491ed7a0490SPiotr Azarewicz } 492ed7a0490SPiotr Azarewicz if (colonp != NULL) { 493ed7a0490SPiotr Azarewicz /* if we already have 8 double octets, having a colon means error */ 494ed7a0490SPiotr Azarewicz if (dbloct_count == 8) 495ed7a0490SPiotr Azarewicz return 0; 496ed7a0490SPiotr Azarewicz 497ed7a0490SPiotr Azarewicz /* 498ed7a0490SPiotr Azarewicz * Since some memmove()'s erroneously fail to handle 499ed7a0490SPiotr Azarewicz * overlapping regions, we'll do the shift by hand. 500ed7a0490SPiotr Azarewicz */ 501ed7a0490SPiotr Azarewicz const int n = tp - colonp; 502ed7a0490SPiotr Azarewicz int i; 503ed7a0490SPiotr Azarewicz 504ed7a0490SPiotr Azarewicz for (i = 1; i <= n; i++) { 505ed7a0490SPiotr Azarewicz endp[-i] = colonp[n - i]; 506ed7a0490SPiotr Azarewicz colonp[n - i] = 0; 507ed7a0490SPiotr Azarewicz } 508ed7a0490SPiotr Azarewicz tp = endp; 509ed7a0490SPiotr Azarewicz } 510ed7a0490SPiotr Azarewicz if (tp != endp) 511ed7a0490SPiotr Azarewicz return 0; 512ed7a0490SPiotr Azarewicz memcpy(dst, tmp, IN6ADDRSZ); 513ed7a0490SPiotr Azarewicz return 1; 514ed7a0490SPiotr Azarewicz } 515ed7a0490SPiotr Azarewicz 516*6d13ea8eSOlivier Matz static struct rte_ether_addr * 517ed7a0490SPiotr Azarewicz my_ether_aton(const char *a) 518ed7a0490SPiotr Azarewicz { 519ed7a0490SPiotr Azarewicz int i; 520ed7a0490SPiotr Azarewicz char *end; 521ed7a0490SPiotr Azarewicz unsigned long o[ETHER_ADDR_LEN]; 522*6d13ea8eSOlivier Matz static struct rte_ether_addr ether_addr; 523ed7a0490SPiotr Azarewicz 524ed7a0490SPiotr Azarewicz i = 0; 525ed7a0490SPiotr Azarewicz do { 526ed7a0490SPiotr Azarewicz errno = 0; 527ed7a0490SPiotr Azarewicz o[i] = strtoul(a, &end, 16); 528ed7a0490SPiotr Azarewicz if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 529ed7a0490SPiotr Azarewicz return NULL; 530ed7a0490SPiotr Azarewicz a = end + 1; 531ed7a0490SPiotr Azarewicz } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0); 532ed7a0490SPiotr Azarewicz 533ed7a0490SPiotr Azarewicz /* Junk at the end of line */ 534ed7a0490SPiotr Azarewicz if (end[0] != 0) 535ed7a0490SPiotr Azarewicz return NULL; 536ed7a0490SPiotr Azarewicz 537ed7a0490SPiotr Azarewicz /* Support the format XX:XX:XX:XX:XX:XX */ 538ed7a0490SPiotr Azarewicz if (i == ETHER_ADDR_LEN) { 539ed7a0490SPiotr Azarewicz while (i-- != 0) { 540ed7a0490SPiotr Azarewicz if (o[i] > UINT8_MAX) 541ed7a0490SPiotr Azarewicz return NULL; 542ed7a0490SPiotr Azarewicz ether_addr.addr_bytes[i] = (uint8_t)o[i]; 543ed7a0490SPiotr Azarewicz } 544ed7a0490SPiotr Azarewicz /* Support the format XXXX:XXXX:XXXX */ 545ed7a0490SPiotr Azarewicz } else if (i == ETHER_ADDR_LEN / 2) { 546ed7a0490SPiotr Azarewicz while (i-- != 0) { 547ed7a0490SPiotr Azarewicz if (o[i] > UINT16_MAX) 548ed7a0490SPiotr Azarewicz return NULL; 549ed7a0490SPiotr Azarewicz ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8); 550ed7a0490SPiotr Azarewicz ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff); 551ed7a0490SPiotr Azarewicz } 552ed7a0490SPiotr Azarewicz /* unknown format */ 553ed7a0490SPiotr Azarewicz } else 554ed7a0490SPiotr Azarewicz return NULL; 555ed7a0490SPiotr Azarewicz 556*6d13ea8eSOlivier Matz return (struct rte_ether_addr *)ðer_addr; 557ed7a0490SPiotr Azarewicz } 558ed7a0490SPiotr Azarewicz 559ed7a0490SPiotr Azarewicz int 560ed7a0490SPiotr Azarewicz parse_ipv4_addr(const char *token, struct in_addr *ipv4) 561ed7a0490SPiotr Azarewicz { 562ed7a0490SPiotr Azarewicz if (strlen(token) >= INET_ADDRSTRLEN) 563ed7a0490SPiotr Azarewicz return -EINVAL; 564ed7a0490SPiotr Azarewicz 565ed7a0490SPiotr Azarewicz if (inet_pton4(token, (unsigned char *)ipv4) != 1) 566ed7a0490SPiotr Azarewicz return -EINVAL; 567ed7a0490SPiotr Azarewicz 568ed7a0490SPiotr Azarewicz return 0; 569ed7a0490SPiotr Azarewicz } 570ed7a0490SPiotr Azarewicz 571ed7a0490SPiotr Azarewicz int 572ed7a0490SPiotr Azarewicz parse_ipv6_addr(const char *token, struct in6_addr *ipv6) 573ed7a0490SPiotr Azarewicz { 574ed7a0490SPiotr Azarewicz if (strlen(token) >= INET6_ADDRSTRLEN) 575ed7a0490SPiotr Azarewicz return -EINVAL; 576ed7a0490SPiotr Azarewicz 577ed7a0490SPiotr Azarewicz if (inet_pton6(token, (unsigned char *)ipv6) != 1) 578ed7a0490SPiotr Azarewicz return -EINVAL; 579ed7a0490SPiotr Azarewicz 580ed7a0490SPiotr Azarewicz return 0; 581ed7a0490SPiotr Azarewicz } 582ed7a0490SPiotr Azarewicz 583ed7a0490SPiotr Azarewicz int 584*6d13ea8eSOlivier Matz parse_mac_addr(const char *token, struct rte_ether_addr *addr) 585ed7a0490SPiotr Azarewicz { 586*6d13ea8eSOlivier Matz struct rte_ether_addr *tmp; 587ed7a0490SPiotr Azarewicz 588ed7a0490SPiotr Azarewicz tmp = my_ether_aton(token); 589ed7a0490SPiotr Azarewicz if (tmp == NULL) 590ed7a0490SPiotr Azarewicz return -1; 591ed7a0490SPiotr Azarewicz 592*6d13ea8eSOlivier Matz memcpy(addr, tmp, sizeof(struct rte_ether_addr)); 593ed7a0490SPiotr Azarewicz return 0; 594ed7a0490SPiotr Azarewicz } 595ed7a0490SPiotr Azarewicz 596ed7a0490SPiotr Azarewicz int 597fbc74e66SJasvinder Singh parse_cpu_core(const char *entry, 598fbc74e66SJasvinder Singh struct cpu_core_params *p) 599ed7a0490SPiotr Azarewicz { 600ed7a0490SPiotr Azarewicz size_t num_len; 601ed7a0490SPiotr Azarewicz char num[8]; 602ed7a0490SPiotr Azarewicz 603ed7a0490SPiotr Azarewicz uint32_t s = 0, c = 0, h = 0, val; 604ed7a0490SPiotr Azarewicz uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; 605ed7a0490SPiotr Azarewicz const char *next = skip_white_spaces(entry); 606ed7a0490SPiotr Azarewicz char type; 607ed7a0490SPiotr Azarewicz 608fbc74e66SJasvinder Singh if (p == NULL) 609fbc74e66SJasvinder Singh return -EINVAL; 610fbc74e66SJasvinder Singh 611ed7a0490SPiotr Azarewicz /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */ 612ed7a0490SPiotr Azarewicz while (*next != '\0') { 613ed7a0490SPiotr Azarewicz /* If everything parsed nothing should left */ 614ed7a0490SPiotr Azarewicz if (s_parsed && c_parsed && h_parsed) 615ed7a0490SPiotr Azarewicz return -EINVAL; 616ed7a0490SPiotr Azarewicz 617ed7a0490SPiotr Azarewicz type = *next; 618ed7a0490SPiotr Azarewicz switch (type) { 619ed7a0490SPiotr Azarewicz case 's': 620ed7a0490SPiotr Azarewicz case 'S': 621ed7a0490SPiotr Azarewicz if (s_parsed || c_parsed || h_parsed) 622ed7a0490SPiotr Azarewicz return -EINVAL; 623ed7a0490SPiotr Azarewicz s_parsed = 1; 624ed7a0490SPiotr Azarewicz next++; 625ed7a0490SPiotr Azarewicz break; 626ed7a0490SPiotr Azarewicz case 'c': 627ed7a0490SPiotr Azarewicz case 'C': 628ed7a0490SPiotr Azarewicz if (c_parsed || h_parsed) 629ed7a0490SPiotr Azarewicz return -EINVAL; 630ed7a0490SPiotr Azarewicz c_parsed = 1; 631ed7a0490SPiotr Azarewicz next++; 632ed7a0490SPiotr Azarewicz break; 633ed7a0490SPiotr Azarewicz case 'h': 634ed7a0490SPiotr Azarewicz case 'H': 635ed7a0490SPiotr Azarewicz if (h_parsed) 636ed7a0490SPiotr Azarewicz return -EINVAL; 637ed7a0490SPiotr Azarewicz h_parsed = 1; 638ed7a0490SPiotr Azarewicz next++; 639ed7a0490SPiotr Azarewicz break; 640ed7a0490SPiotr Azarewicz default: 641ed7a0490SPiotr Azarewicz /* If it start from digit it must be only core id. */ 642ed7a0490SPiotr Azarewicz if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) 643ed7a0490SPiotr Azarewicz return -EINVAL; 644ed7a0490SPiotr Azarewicz 645ed7a0490SPiotr Azarewicz type = 'C'; 646ed7a0490SPiotr Azarewicz } 647ed7a0490SPiotr Azarewicz 648ed7a0490SPiotr Azarewicz for (num_len = 0; *next != '\0'; next++, num_len++) { 649ed7a0490SPiotr Azarewicz if (num_len == RTE_DIM(num)) 650ed7a0490SPiotr Azarewicz return -EINVAL; 651ed7a0490SPiotr Azarewicz 652ed7a0490SPiotr Azarewicz if (!isdigit(*next)) 653ed7a0490SPiotr Azarewicz break; 654ed7a0490SPiotr Azarewicz 655ed7a0490SPiotr Azarewicz num[num_len] = *next; 656ed7a0490SPiotr Azarewicz } 657ed7a0490SPiotr Azarewicz 658ed7a0490SPiotr Azarewicz if (num_len == 0 && type != 'h' && type != 'H') 659ed7a0490SPiotr Azarewicz return -EINVAL; 660ed7a0490SPiotr Azarewicz 661ed7a0490SPiotr Azarewicz if (num_len != 0 && (type == 'h' || type == 'H')) 662ed7a0490SPiotr Azarewicz return -EINVAL; 663ed7a0490SPiotr Azarewicz 664ed7a0490SPiotr Azarewicz num[num_len] = '\0'; 665ed7a0490SPiotr Azarewicz val = strtol(num, NULL, 10); 666ed7a0490SPiotr Azarewicz 667ed7a0490SPiotr Azarewicz h = 0; 668ed7a0490SPiotr Azarewicz switch (type) { 669ed7a0490SPiotr Azarewicz case 's': 670ed7a0490SPiotr Azarewicz case 'S': 671ed7a0490SPiotr Azarewicz s = val; 672ed7a0490SPiotr Azarewicz break; 673ed7a0490SPiotr Azarewicz case 'c': 674ed7a0490SPiotr Azarewicz case 'C': 675ed7a0490SPiotr Azarewicz c = val; 676ed7a0490SPiotr Azarewicz break; 677ed7a0490SPiotr Azarewicz case 'h': 678ed7a0490SPiotr Azarewicz case 'H': 679ed7a0490SPiotr Azarewicz h = 1; 680ed7a0490SPiotr Azarewicz break; 681ed7a0490SPiotr Azarewicz } 682ed7a0490SPiotr Azarewicz } 683ed7a0490SPiotr Azarewicz 684fbc74e66SJasvinder Singh p->socket_id = s; 685fbc74e66SJasvinder Singh p->core_id = c; 686fbc74e66SJasvinder Singh p->thread_id = h; 687ed7a0490SPiotr Azarewicz return 0; 688ed7a0490SPiotr Azarewicz } 689