1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation. 3 * Copyright (c) 2009, Olivier MATZ <[email protected]> 4 * All rights reserved. 5 */ 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <stdarg.h> 10 #include <errno.h> 11 #include <inttypes.h> 12 #include <ctype.h> 13 #include <string.h> 14 #include <sys/types.h> 15 #include <net/ethernet.h> 16 17 #include <rte_string_fns.h> 18 19 #include "cmdline_parse.h" 20 #include "cmdline_parse_etheraddr.h" 21 22 struct cmdline_token_ops cmdline_token_etheraddr_ops = { 23 .parse = cmdline_parse_etheraddr, 24 .complete_get_nb = NULL, 25 .complete_get_elt = NULL, 26 .get_help = cmdline_get_help_etheraddr, 27 }; 28 29 /* the format can be either XX:XX:XX:XX:XX:XX or XXXX:XXXX:XXXX */ 30 #define ETHER_ADDRSTRLENLONG 18 31 #define ETHER_ADDRSTRLENSHORT 15 32 33 #ifdef __linux__ 34 #define ea_oct ether_addr_octet 35 #else 36 #define ea_oct octet 37 #endif 38 39 40 static struct ether_addr * 41 my_ether_aton(const char *a) 42 { 43 int i; 44 char *end; 45 unsigned long o[ETHER_ADDR_LEN]; 46 static struct ether_addr ether_addr; 47 48 i = 0; 49 do { 50 errno = 0; 51 o[i] = strtoul(a, &end, 16); 52 if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 53 return NULL; 54 a = end + 1; 55 } while (++i != sizeof (o) / sizeof (o[0]) && end[0] != 0); 56 57 /* Junk at the end of line */ 58 if (end[0] != 0) 59 return NULL; 60 61 /* Support the format XX:XX:XX:XX:XX:XX */ 62 if (i == ETHER_ADDR_LEN) { 63 while (i-- != 0) { 64 if (o[i] > UINT8_MAX) 65 return NULL; 66 ether_addr.ea_oct[i] = (uint8_t)o[i]; 67 } 68 /* Support the format XXXX:XXXX:XXXX */ 69 } else if (i == ETHER_ADDR_LEN / 2) { 70 while (i-- != 0) { 71 if (o[i] > UINT16_MAX) 72 return NULL; 73 ether_addr.ea_oct[i * 2] = (uint8_t)(o[i] >> 8); 74 ether_addr.ea_oct[i * 2 + 1] = (uint8_t)(o[i] & 0xff); 75 } 76 /* unknown format */ 77 } else 78 return NULL; 79 80 return (struct ether_addr *)ðer_addr; 81 } 82 83 int 84 cmdline_parse_etheraddr(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, 85 const char *buf, void *res, unsigned ressize) 86 { 87 unsigned int token_len = 0; 88 char ether_str[ETHER_ADDRSTRLENLONG+1]; 89 struct ether_addr *tmp; 90 91 if (res && ressize < sizeof(struct ether_addr)) 92 return -1; 93 94 if (!buf || ! *buf) 95 return -1; 96 97 while (!cmdline_isendoftoken(buf[token_len])) 98 token_len++; 99 100 /* if token doesn't match possible string lengths... */ 101 if ((token_len != ETHER_ADDRSTRLENLONG - 1) && 102 (token_len != ETHER_ADDRSTRLENSHORT - 1)) 103 return -1; 104 105 strlcpy(ether_str, buf, token_len + 1); 106 107 tmp = my_ether_aton(ether_str); 108 if (tmp == NULL) 109 return -1; 110 if (res) 111 memcpy(res, tmp, sizeof(struct ether_addr)); 112 return token_len; 113 } 114 115 int 116 cmdline_get_help_etheraddr(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, 117 char *dstbuf, unsigned int size) 118 { 119 int ret; 120 121 ret = snprintf(dstbuf, size, "Ethernet address"); 122 if (ret < 0) 123 return -1; 124 return 0; 125 } 126