1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <net/ethernet.h>
8 #include "ether-addr-util.h"
10 #include "string-util.h"
12 char* ether_addr_to_string(const struct ether_addr
*addr
, char buffer
[ETHER_ADDR_TO_STRING_MAX
]) {
16 /* Like ether_ntoa() but uses %02x instead of %x to print
17 * ethernet addresses, which makes them look less funny. Also,
18 * doesn't use a static buffer. */
20 sprintf(buffer
, "%02x:%02x:%02x:%02x:%02x:%02x",
21 addr
->ether_addr_octet
[0],
22 addr
->ether_addr_octet
[1],
23 addr
->ether_addr_octet
[2],
24 addr
->ether_addr_octet
[3],
25 addr
->ether_addr_octet
[4],
26 addr
->ether_addr_octet
[5]);
31 int ether_addr_compare(const void *a
, const void *b
) {
35 return memcmp(a
, b
, ETH_ALEN
);
38 static void ether_addr_hash_func(const void *p
, struct siphash
*state
) {
39 siphash24_compress(p
, sizeof(struct ether_addr
), state
);
42 const struct hash_ops ether_addr_hash_ops
= {
43 .hash
= ether_addr_hash_func
,
44 .compare
= ether_addr_compare
47 int ether_addr_from_string(const char *s
, struct ether_addr
*ret
) {
48 size_t pos
= 0, n
, field
;
50 const char *hex
= HEXDIGITS
, *hexoff
;
54 #define parse_fields(v) \
55 for (field = 0; field < ELEMENTSOF(v); field++) { \
57 for (n = 0; n < (2 * sizeof(v[0])); n++) { \
60 hexoff = strchr(hex, s[pos]); \
63 assert(hexoff >= hex); \
75 if (field < (ELEMENTSOF(v)-1)) { \
86 s
+= strspn(s
, WHITESPACE
);
87 sep
= s
[strspn(s
, hex
)];
90 uint16_t shorts
[3] = { 0 };
97 for (n
= 0; n
< ELEMENTSOF(shorts
); n
++) {
98 ret
->ether_addr_octet
[2*n
] = ((shorts
[n
] & (uint16_t)0xff00) >> 8);
99 ret
->ether_addr_octet
[2*n
+ 1] = (shorts
[n
] & (uint16_t)0x00ff);
102 } else if (IN_SET(sep
, ':', '-')) {
103 struct ether_addr out
= ETHER_ADDR_NULL
;
105 parse_fields(out
.ether_addr_octet
);
110 for (n
= 0; n
< ELEMENTSOF(out
.ether_addr_octet
); n
++)
111 ret
->ether_addr_octet
[n
] = out
.ether_addr_octet
[n
];