1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2014 Tom Gundersen
7 #include <net/ethernet.h>
11 #include "ether-addr-util.h"
13 #include "string-util.h"
15 char* ether_addr_to_string(const struct ether_addr
*addr
, char buffer
[ETHER_ADDR_TO_STRING_MAX
]) {
19 /* Like ether_ntoa() but uses %02x instead of %x to print
20 * ethernet addresses, which makes them look less funny. Also,
21 * doesn't use a static buffer. */
23 sprintf(buffer
, "%02x:%02x:%02x:%02x:%02x:%02x",
24 addr
->ether_addr_octet
[0],
25 addr
->ether_addr_octet
[1],
26 addr
->ether_addr_octet
[2],
27 addr
->ether_addr_octet
[3],
28 addr
->ether_addr_octet
[4],
29 addr
->ether_addr_octet
[5]);
34 int ether_addr_compare(const void *a
, const void *b
) {
38 return memcmp(a
, b
, ETH_ALEN
);
41 static void ether_addr_hash_func(const void *p
, struct siphash
*state
) {
42 siphash24_compress(p
, sizeof(struct ether_addr
), state
);
45 const struct hash_ops ether_addr_hash_ops
= {
46 .hash
= ether_addr_hash_func
,
47 .compare
= ether_addr_compare
50 int ether_addr_from_string(const char *s
, struct ether_addr
*ret
) {
51 size_t pos
= 0, n
, field
;
53 const char *hex
= HEXDIGITS
, *hexoff
;
57 #define parse_fields(v) \
58 for (field = 0; field < ELEMENTSOF(v); field++) { \
60 for (n = 0; n < (2 * sizeof(v[0])); n++) { \
63 hexoff = strchr(hex, s[pos]); \
66 assert(hexoff >= hex); \
78 if (field < (ELEMENTSOF(v)-1)) { \
89 s
+= strspn(s
, WHITESPACE
);
90 sep
= s
[strspn(s
, hex
)];
93 uint16_t shorts
[3] = { 0 };
100 for (n
= 0; n
< ELEMENTSOF(shorts
); n
++) {
101 ret
->ether_addr_octet
[2*n
] = ((shorts
[n
] & (uint16_t)0xff00) >> 8);
102 ret
->ether_addr_octet
[2*n
+ 1] = (shorts
[n
] & (uint16_t)0x00ff);
105 } else if (IN_SET(sep
, ':', '-')) {
106 struct ether_addr out
= ETHER_ADDR_NULL
;
108 parse_fields(out
.ether_addr_octet
);
113 for (n
= 0; n
< ELEMENTSOF(out
.ether_addr_octet
); n
++)
114 ret
->ether_addr_octet
[n
] = out
.ether_addr_octet
[n
];