1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include <linux/if_infiniband.h>
5 #include <net/ethernet.h>
6 #include <stdbool.h>
7 
8 #include "hash-funcs.h"
9 #include "in-addr-util.h"
10 #include "macro.h"
11 #include "memory-util.h"
12 
13 /* This is MAX_ADDR_LEN as defined in linux/netdevice.h, but net/if_arp.h
14  * defines a macro of the same name with a much lower size. */
15 #define HW_ADDR_MAX_SIZE 32
16 
17 struct hw_addr_data {
18         size_t length;
19         union {
20                 struct ether_addr ether;
21                 uint8_t infiniband[INFINIBAND_ALEN];
22                 struct in_addr in;
23                 struct in6_addr in6;
24                 uint8_t bytes[HW_ADDR_MAX_SIZE];
25         };
26 };
27 
28 int parse_hw_addr_full(const char *s, size_t expected_len, struct hw_addr_data *ret);
parse_hw_addr(const char * s,struct hw_addr_data * ret)29 static inline int parse_hw_addr(const char *s, struct hw_addr_data *ret) {
30         return parse_hw_addr_full(s, 0, ret);
31 }
32 int parse_ether_addr(const char *s, struct ether_addr *ret);
33 
34 typedef enum HardwareAddressToStringFlags {
35         HW_ADDR_TO_STRING_NO_COLON = 1 << 0,
36 } HardwareAddressToStringFlags;
37 
38 #define HW_ADDR_TO_STRING_MAX (3*HW_ADDR_MAX_SIZE)
39 char *hw_addr_to_string_full(
40                 const struct hw_addr_data *addr,
41                 HardwareAddressToStringFlags flags,
42                 char buffer[static HW_ADDR_TO_STRING_MAX]);
hw_addr_to_string(const struct hw_addr_data * addr,char buffer[static HW_ADDR_TO_STRING_MAX])43 static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buffer[static HW_ADDR_TO_STRING_MAX]) {
44         return hw_addr_to_string_full(addr, 0, buffer);
45 }
46 
47 /* Note: the lifetime of the compound literal is the immediately surrounding block,
48  * see C11 §6.5.2.5, and
49  * https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
50 #define HW_ADDR_TO_STR_FULL(hw_addr, flags) hw_addr_to_string_full((hw_addr), flags, (char[HW_ADDR_TO_STRING_MAX]){})
51 #define HW_ADDR_TO_STR(hw_addr) HW_ADDR_TO_STR_FULL(hw_addr, 0)
52 
53 #define HW_ADDR_NULL ((const struct hw_addr_data){})
54 
55 void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
56 int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
hw_addr_equal(const struct hw_addr_data * a,const struct hw_addr_data * b)57 static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {
58         return hw_addr_compare(a, b) == 0;
59 }
hw_addr_is_null(const struct hw_addr_data * addr)60 static inline bool hw_addr_is_null(const struct hw_addr_data *addr) {
61         assert(addr);
62         return addr->length == 0 || memeqzero(addr->bytes, addr->length);
63 }
64 
65 extern const struct hash_ops hw_addr_hash_ops;
66 extern const struct hash_ops hw_addr_hash_ops_free;
67 
68 #define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
69 #define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
70 
71 #define ETHER_ADDR_TO_STRING_MAX (3*6)
72 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
73 int ether_addr_to_string_alloc(const struct ether_addr *addr, char **ret);
74 /* Use only as function argument, never stand-alone! */
75 #define ETHER_ADDR_TO_STR(addr) ether_addr_to_string((addr), (char[ETHER_ADDR_TO_STRING_MAX]){})
76 
77 int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b);
ether_addr_equal(const struct ether_addr * a,const struct ether_addr * b)78 static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
79         return ether_addr_compare(a, b) == 0;
80 }
81 
82 #define ETHER_ADDR_NULL ((const struct ether_addr){})
83 
ether_addr_is_null(const struct ether_addr * addr)84 static inline bool ether_addr_is_null(const struct ether_addr *addr) {
85         return ether_addr_equal(addr, &ETHER_ADDR_NULL);
86 }
87 
ether_addr_is_broadcast(const struct ether_addr * addr)88 static inline bool ether_addr_is_broadcast(const struct ether_addr *addr) {
89         assert(addr);
90         return memeqbyte(0xff, addr->ether_addr_octet, ETH_ALEN);
91 }
92 
ether_addr_is_multicast(const struct ether_addr * addr)93 static inline bool ether_addr_is_multicast(const struct ether_addr *addr) {
94         assert(addr);
95         return FLAGS_SET(addr->ether_addr_octet[0], 0x01);
96 }
97 
ether_addr_is_unicast(const struct ether_addr * addr)98 static inline bool ether_addr_is_unicast(const struct ether_addr *addr) {
99         return !ether_addr_is_multicast(addr);
100 }
101 
ether_addr_is_local(const struct ether_addr * addr)102 static inline bool ether_addr_is_local(const struct ether_addr *addr) {
103         /* Determine if the Ethernet address is locally-assigned one (IEEE 802) */
104         assert(addr);
105         return FLAGS_SET(addr->ether_addr_octet[0], 0x02);
106 }
107 
ether_addr_is_global(const struct ether_addr * addr)108 static inline bool ether_addr_is_global(const struct ether_addr *addr) {
109         return !ether_addr_is_local(addr);
110 }
111 
112 extern const struct hash_ops ether_addr_hash_ops;
113 extern const struct hash_ops ether_addr_hash_ops_free;
114