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