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