1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016 Intel Corporation. 3 * Copyright(c) 2017 Cavium, Inc. 4 */ 5 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <ctype.h> 10 #include <getopt.h> 11 #include <errno.h> 12 #include <stdarg.h> 13 #include <string.h> 14 #include <libgen.h> 15 #include <unistd.h> 16 #include <sys/wait.h> 17 #include <stdbool.h> 18 19 #include <rte_errno.h> 20 #include <rte_string_fns.h> 21 22 #include "parser.h" 23 24 static uint32_t 25 get_hex_val(char c) 26 { 27 switch (c) { 28 case '0': case '1': case '2': case '3': case '4': case '5': 29 case '6': case '7': case '8': case '9': 30 return c - '0'; 31 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 32 return c - 'A' + 10; 33 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 34 return c - 'a' + 10; 35 default: 36 return 0; 37 } 38 } 39 40 int 41 parser_read_arg_bool(const char *p) 42 { 43 p = skip_white_spaces(p); 44 int result = -EINVAL; 45 46 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || 47 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { 48 p += 3; 49 result = 1; 50 } 51 52 if (((p[0] == 'o') && (p[1] == 'n')) || 53 ((p[0] == 'O') && (p[1] == 'N'))) { 54 p += 2; 55 result = 1; 56 } 57 58 if (((p[0] == 'n') && (p[1] == 'o')) || 59 ((p[0] == 'N') && (p[1] == 'O'))) { 60 p += 2; 61 result = 0; 62 } 63 64 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || 65 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { 66 p += 3; 67 result = 0; 68 } 69 70 p = skip_white_spaces(p); 71 72 if (p[0] != '\0') 73 return -EINVAL; 74 75 return result; 76 } 77 78 int 79 parser_read_uint64(uint64_t *value, const char *p) 80 { 81 char *next; 82 uint64_t val; 83 84 p = skip_white_spaces(p); 85 if (!isdigit(*p)) 86 return -EINVAL; 87 88 val = strtoul(p, &next, 10); 89 if (p == next) 90 return -EINVAL; 91 92 p = next; 93 switch (*p) { 94 case 'T': 95 val *= 1024ULL; 96 /* fall through */ 97 case 'G': 98 val *= 1024ULL; 99 /* fall through */ 100 case 'M': 101 val *= 1024ULL; 102 /* fall through */ 103 case 'k': 104 case 'K': 105 val *= 1024ULL; 106 p++; 107 break; 108 } 109 110 p = skip_white_spaces(p); 111 if (*p != '\0') 112 return -EINVAL; 113 114 *value = val; 115 return 0; 116 } 117 118 int 119 parser_read_int32(int32_t *value, const char *p) 120 { 121 char *next; 122 int32_t val; 123 124 p = skip_white_spaces(p); 125 if (!isdigit(*p)) 126 return -EINVAL; 127 128 val = strtol(p, &next, 10); 129 if (p == next) 130 return -EINVAL; 131 132 *value = val; 133 return 0; 134 } 135 136 int 137 parser_read_uint64_hex(uint64_t *value, const char *p) 138 { 139 char *next; 140 uint64_t val; 141 142 p = skip_white_spaces(p); 143 144 val = strtoul(p, &next, 16); 145 if (p == next) 146 return -EINVAL; 147 148 p = skip_white_spaces(next); 149 if (*p != '\0') 150 return -EINVAL; 151 152 *value = val; 153 return 0; 154 } 155 156 int 157 parser_read_uint32(uint32_t *value, const char *p) 158 { 159 uint64_t val = 0; 160 int ret = parser_read_uint64(&val, p); 161 162 if (ret < 0) 163 return ret; 164 165 if (val > UINT32_MAX) 166 return -ERANGE; 167 168 *value = val; 169 return 0; 170 } 171 172 int 173 parser_read_uint32_hex(uint32_t *value, const char *p) 174 { 175 uint64_t val = 0; 176 int ret = parser_read_uint64_hex(&val, p); 177 178 if (ret < 0) 179 return ret; 180 181 if (val > UINT32_MAX) 182 return -ERANGE; 183 184 *value = val; 185 return 0; 186 } 187 188 int 189 parser_read_uint16(uint16_t *value, const char *p) 190 { 191 uint64_t val = 0; 192 int ret = parser_read_uint64(&val, p); 193 194 if (ret < 0) 195 return ret; 196 197 if (val > UINT16_MAX) 198 return -ERANGE; 199 200 *value = val; 201 return 0; 202 } 203 204 int 205 parser_read_uint16_hex(uint16_t *value, const char *p) 206 { 207 uint64_t val = 0; 208 int ret = parser_read_uint64_hex(&val, p); 209 210 if (ret < 0) 211 return ret; 212 213 if (val > UINT16_MAX) 214 return -ERANGE; 215 216 *value = val; 217 return 0; 218 } 219 220 int 221 parser_read_uint8(uint8_t *value, const char *p) 222 { 223 uint64_t val = 0; 224 int ret = parser_read_uint64(&val, p); 225 226 if (ret < 0) 227 return ret; 228 229 if (val > UINT8_MAX) 230 return -ERANGE; 231 232 *value = val; 233 return 0; 234 } 235 236 int 237 parser_read_uint8_hex(uint8_t *value, const char *p) 238 { 239 uint64_t val = 0; 240 int ret = parser_read_uint64_hex(&val, p); 241 242 if (ret < 0) 243 return ret; 244 245 if (val > UINT8_MAX) 246 return -ERANGE; 247 248 *value = val; 249 return 0; 250 } 251 252 int 253 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 254 { 255 uint32_t i; 256 257 if ((string == NULL) || 258 (tokens == NULL) || 259 (*n_tokens < 1)) 260 return -EINVAL; 261 262 for (i = 0; i < *n_tokens; i++) { 263 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 264 if (tokens[i] == NULL) 265 break; 266 } 267 268 if ((i == *n_tokens) && 269 (strtok_r(string, PARSE_DELIMITER, &string) != NULL)) 270 return -E2BIG; 271 272 *n_tokens = i; 273 return 0; 274 } 275 276 int 277 parse_hex_string(char *src, uint8_t *dst, uint32_t *size) 278 { 279 char *c; 280 uint32_t len, i; 281 282 /* Check input parameters */ 283 if ((src == NULL) || 284 (dst == NULL) || 285 (size == NULL) || 286 (*size == 0)) 287 return -1; 288 289 len = strlen(src); 290 if (((len & 3) != 0) || 291 (len > (*size) * 2)) 292 return -1; 293 *size = len / 2; 294 295 for (c = src; *c != 0; c++) { 296 if ((((*c) >= '0') && ((*c) <= '9')) || 297 (((*c) >= 'A') && ((*c) <= 'F')) || 298 (((*c) >= 'a') && ((*c) <= 'f'))) 299 continue; 300 301 return -1; 302 } 303 304 /* Convert chars to bytes */ 305 for (i = 0; i < *size; i++) 306 dst[i] = get_hex_val(src[2 * i]) * 16 + 307 get_hex_val(src[2 * i + 1]); 308 309 return 0; 310 } 311 312 int 313 parse_lcores_list(bool lcores[], int lcores_num, const char *corelist) 314 { 315 int i, idx = 0; 316 int min, max; 317 char *end = NULL; 318 319 if (corelist == NULL) 320 return -1; 321 while (isblank(*corelist)) 322 corelist++; 323 i = strlen(corelist); 324 while ((i > 0) && isblank(corelist[i - 1])) 325 i--; 326 327 /* Get list of lcores */ 328 min = RTE_MAX_LCORE; 329 do { 330 while (isblank(*corelist)) 331 corelist++; 332 if (*corelist == '\0') 333 return -1; 334 idx = strtoul(corelist, &end, 10); 335 if (idx < 0 || idx > lcores_num) 336 return -1; 337 338 if (end == NULL) 339 return -1; 340 while (isblank(*end)) 341 end++; 342 if (*end == '-') { 343 min = idx; 344 } else if ((*end == ',') || (*end == '\0')) { 345 max = idx; 346 if (min == RTE_MAX_LCORE) 347 min = idx; 348 for (idx = min; idx <= max; idx++) { 349 if (lcores[idx] == 1) 350 return -E2BIG; 351 lcores[idx] = 1; 352 } 353 354 min = RTE_MAX_LCORE; 355 } else 356 return -1; 357 corelist = end + 1; 358 } while (*end != '\0'); 359 360 return 0; 361 } 362