1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2016 Intel Corporation. All rights reserved. 5 * Copyright(c) 2017 Cavium, Inc. All rights reserved. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <stdint.h> 36 #include <stdlib.h> 37 #include <stdio.h> 38 #include <ctype.h> 39 #include <getopt.h> 40 #include <errno.h> 41 #include <stdarg.h> 42 #include <string.h> 43 #include <libgen.h> 44 #include <unistd.h> 45 #include <sys/wait.h> 46 #include <stdbool.h> 47 48 #include <rte_errno.h> 49 #include <rte_string_fns.h> 50 51 #include "parser.h" 52 53 static uint32_t 54 get_hex_val(char c) 55 { 56 switch (c) { 57 case '0': case '1': case '2': case '3': case '4': case '5': 58 case '6': case '7': case '8': case '9': 59 return c - '0'; 60 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 61 return c - 'A' + 10; 62 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 63 return c - 'a' + 10; 64 default: 65 return 0; 66 } 67 } 68 69 int 70 parser_read_arg_bool(const char *p) 71 { 72 p = skip_white_spaces(p); 73 int result = -EINVAL; 74 75 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || 76 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { 77 p += 3; 78 result = 1; 79 } 80 81 if (((p[0] == 'o') && (p[1] == 'n')) || 82 ((p[0] == 'O') && (p[1] == 'N'))) { 83 p += 2; 84 result = 1; 85 } 86 87 if (((p[0] == 'n') && (p[1] == 'o')) || 88 ((p[0] == 'N') && (p[1] == 'O'))) { 89 p += 2; 90 result = 0; 91 } 92 93 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || 94 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { 95 p += 3; 96 result = 0; 97 } 98 99 p = skip_white_spaces(p); 100 101 if (p[0] != '\0') 102 return -EINVAL; 103 104 return result; 105 } 106 107 int 108 parser_read_uint64(uint64_t *value, const char *p) 109 { 110 char *next; 111 uint64_t val; 112 113 p = skip_white_spaces(p); 114 if (!isdigit(*p)) 115 return -EINVAL; 116 117 val = strtoul(p, &next, 10); 118 if (p == next) 119 return -EINVAL; 120 121 p = next; 122 switch (*p) { 123 case 'T': 124 val *= 1024ULL; 125 /* fall through */ 126 case 'G': 127 val *= 1024ULL; 128 /* fall through */ 129 case 'M': 130 val *= 1024ULL; 131 /* fall through */ 132 case 'k': 133 case 'K': 134 val *= 1024ULL; 135 p++; 136 break; 137 } 138 139 p = skip_white_spaces(p); 140 if (*p != '\0') 141 return -EINVAL; 142 143 *value = val; 144 return 0; 145 } 146 147 int 148 parser_read_int32(int32_t *value, const char *p) 149 { 150 char *next; 151 int32_t val; 152 153 p = skip_white_spaces(p); 154 if (!isdigit(*p)) 155 return -EINVAL; 156 157 val = strtol(p, &next, 10); 158 if (p == next) 159 return -EINVAL; 160 161 *value = val; 162 return 0; 163 } 164 165 int 166 parser_read_uint64_hex(uint64_t *value, const char *p) 167 { 168 char *next; 169 uint64_t val; 170 171 p = skip_white_spaces(p); 172 173 val = strtoul(p, &next, 16); 174 if (p == next) 175 return -EINVAL; 176 177 p = skip_white_spaces(next); 178 if (*p != '\0') 179 return -EINVAL; 180 181 *value = val; 182 return 0; 183 } 184 185 int 186 parser_read_uint32(uint32_t *value, const char *p) 187 { 188 uint64_t val = 0; 189 int ret = parser_read_uint64(&val, p); 190 191 if (ret < 0) 192 return ret; 193 194 if (val > UINT32_MAX) 195 return -ERANGE; 196 197 *value = val; 198 return 0; 199 } 200 201 int 202 parser_read_uint32_hex(uint32_t *value, const char *p) 203 { 204 uint64_t val = 0; 205 int ret = parser_read_uint64_hex(&val, p); 206 207 if (ret < 0) 208 return ret; 209 210 if (val > UINT32_MAX) 211 return -ERANGE; 212 213 *value = val; 214 return 0; 215 } 216 217 int 218 parser_read_uint16(uint16_t *value, const char *p) 219 { 220 uint64_t val = 0; 221 int ret = parser_read_uint64(&val, p); 222 223 if (ret < 0) 224 return ret; 225 226 if (val > UINT16_MAX) 227 return -ERANGE; 228 229 *value = val; 230 return 0; 231 } 232 233 int 234 parser_read_uint16_hex(uint16_t *value, const char *p) 235 { 236 uint64_t val = 0; 237 int ret = parser_read_uint64_hex(&val, p); 238 239 if (ret < 0) 240 return ret; 241 242 if (val > UINT16_MAX) 243 return -ERANGE; 244 245 *value = val; 246 return 0; 247 } 248 249 int 250 parser_read_uint8(uint8_t *value, const char *p) 251 { 252 uint64_t val = 0; 253 int ret = parser_read_uint64(&val, p); 254 255 if (ret < 0) 256 return ret; 257 258 if (val > UINT8_MAX) 259 return -ERANGE; 260 261 *value = val; 262 return 0; 263 } 264 265 int 266 parser_read_uint8_hex(uint8_t *value, const char *p) 267 { 268 uint64_t val = 0; 269 int ret = parser_read_uint64_hex(&val, p); 270 271 if (ret < 0) 272 return ret; 273 274 if (val > UINT8_MAX) 275 return -ERANGE; 276 277 *value = val; 278 return 0; 279 } 280 281 int 282 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 283 { 284 uint32_t i; 285 286 if ((string == NULL) || 287 (tokens == NULL) || 288 (*n_tokens < 1)) 289 return -EINVAL; 290 291 for (i = 0; i < *n_tokens; i++) { 292 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 293 if (tokens[i] == NULL) 294 break; 295 } 296 297 if ((i == *n_tokens) && 298 (strtok_r(string, PARSE_DELIMITER, &string) != NULL)) 299 return -E2BIG; 300 301 *n_tokens = i; 302 return 0; 303 } 304 305 int 306 parse_hex_string(char *src, uint8_t *dst, uint32_t *size) 307 { 308 char *c; 309 uint32_t len, i; 310 311 /* Check input parameters */ 312 if ((src == NULL) || 313 (dst == NULL) || 314 (size == NULL) || 315 (*size == 0)) 316 return -1; 317 318 len = strlen(src); 319 if (((len & 3) != 0) || 320 (len > (*size) * 2)) 321 return -1; 322 *size = len / 2; 323 324 for (c = src; *c != 0; c++) { 325 if ((((*c) >= '0') && ((*c) <= '9')) || 326 (((*c) >= 'A') && ((*c) <= 'F')) || 327 (((*c) >= 'a') && ((*c) <= 'f'))) 328 continue; 329 330 return -1; 331 } 332 333 /* Convert chars to bytes */ 334 for (i = 0; i < *size; i++) 335 dst[i] = get_hex_val(src[2 * i]) * 16 + 336 get_hex_val(src[2 * i + 1]); 337 338 return 0; 339 } 340 341 int 342 parse_lcores_list(bool lcores[], const char *corelist) 343 { 344 int i, idx = 0; 345 int min, max; 346 char *end = NULL; 347 348 if (corelist == NULL) 349 return -1; 350 while (isblank(*corelist)) 351 corelist++; 352 i = strlen(corelist); 353 while ((i > 0) && isblank(corelist[i - 1])) 354 i--; 355 356 /* Get list of lcores */ 357 min = RTE_MAX_LCORE; 358 do { 359 while (isblank(*corelist)) 360 corelist++; 361 if (*corelist == '\0') 362 return -1; 363 idx = strtoul(corelist, &end, 10); 364 365 if (end == NULL) 366 return -1; 367 while (isblank(*end)) 368 end++; 369 if (*end == '-') { 370 min = idx; 371 } else if ((*end == ',') || (*end == '\0')) { 372 max = idx; 373 if (min == RTE_MAX_LCORE) 374 min = idx; 375 for (idx = min; idx <= max; idx++) { 376 if (lcores[idx] == 1) 377 return -E2BIG; 378 lcores[idx] = 1; 379 } 380 381 min = RTE_MAX_LCORE; 382 } else 383 return -1; 384 corelist = end + 1; 385 } while (*end != '\0'); 386 387 return 0; 388 } 389