1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public API for network link address
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_
13 #define ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_
14 
15 #include <zephyr/types.h>
16 #include <stdbool.h>
17 #include <errno.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * @brief Network link address library
25  * @defgroup net_linkaddr Network Link Address Library
26  * @since 1.0
27  * @version 1.0.0
28  * @ingroup networking
29  * @{
30  */
31 
32 /** Maximum length of the link address */
33 #ifdef CONFIG_NET_L2_IEEE802154
34 #define NET_LINK_ADDR_MAX_LENGTH 8
35 #else
36 #ifdef CONFIG_NET_L2_PPP
37 #define NET_LINK_ADDR_MAX_LENGTH 8
38 #else
39 #define NET_LINK_ADDR_MAX_LENGTH 6
40 #endif
41 #endif
42 
43 /**
44  * Type of the link address. This indicates the network technology that this
45  * address is used in. Note that in order to save space we store the value
46  * into a uint8_t variable, so please do not introduce any values > 255 in
47  * this enum.
48  */
49 enum net_link_type {
50 	/** Unknown link address type. */
51 	NET_LINK_UNKNOWN = 0,
52 	/** IEEE 802.15.4 link address. */
53 	NET_LINK_IEEE802154,
54 	/** Bluetooth IPSP link address. */
55 	NET_LINK_BLUETOOTH,
56 	/** Ethernet link address. */
57 	NET_LINK_ETHERNET,
58 	/** Dummy link address. Used in testing apps and loopback support. */
59 	NET_LINK_DUMMY,
60 	/** CANBUS link address. */
61 	NET_LINK_CANBUS_RAW,
62 } __packed;
63 
64 /**
65  *  @brief Hardware link address structure
66  *
67  *  Used to hold the link address information. This variant is needed
68  *  when we have to store the link layer address.
69  *
70  *  Note that you cannot cast this to net_linkaddr as uint8_t * is
71  *  handled differently than uint8_t addr[] and the fields are purposely
72  *  in different order.
73  */
74 struct net_linkaddr {
75 	/** What kind of address is this for */
76 	uint8_t type;
77 
78 	/** The real length of the ll address. */
79 	uint8_t len;
80 
81 	/** The array of bytes representing the address */
82 	uint8_t addr[NET_LINK_ADDR_MAX_LENGTH]; /* in big endian */
83 };
84 
85 /**
86  * @brief Compare two link layer addresses.
87  *
88  * @param lladdr1 Pointer to a link layer address
89  * @param lladdr2 Pointer to a link layer address
90  *
91  * @return True if the addresses are the same, false otherwise.
92  */
net_linkaddr_cmp(struct net_linkaddr * lladdr1,struct net_linkaddr * lladdr2)93 static inline bool net_linkaddr_cmp(struct net_linkaddr *lladdr1,
94 				    struct net_linkaddr *lladdr2)
95 {
96 	if (!lladdr1 || !lladdr2) {
97 		return false;
98 	}
99 
100 	if (lladdr1->len != lladdr2->len) {
101 		return false;
102 	}
103 
104 	return !memcmp(lladdr1->addr, lladdr2->addr, lladdr1->len);
105 }
106 
107 /**
108  *
109  * @brief Set the member data of a link layer address storage structure.
110  *
111  * @param lladdr The link address storage structure to change.
112  * @param new_addr Array of bytes containing the link address.
113  * @param new_len Length of the link address array.
114  * This value should always be <= NET_LINK_ADDR_MAX_LENGTH.
115  * @return 0 if ok, <0 if error
116  */
net_linkaddr_set(struct net_linkaddr * lladdr,const uint8_t * new_addr,uint8_t new_len)117 static inline int net_linkaddr_set(struct net_linkaddr *lladdr,
118 				   const uint8_t *new_addr,
119 				   uint8_t new_len)
120 {
121 	if (lladdr == NULL || new_addr == NULL) {
122 		return -EINVAL;
123 	}
124 
125 	if (new_len > NET_LINK_ADDR_MAX_LENGTH) {
126 		return -EMSGSIZE;
127 	}
128 
129 	lladdr->len = new_len;
130 	memcpy(lladdr->addr, new_addr, new_len);
131 
132 	return 0;
133 }
134 
135 /**
136  * @brief Copy link address from one variable to another.
137  *
138  * @param dst The link address structure destination.
139  * @param src The link address structure to source.
140  * @return 0 if ok, <0 if error
141  */
net_linkaddr_copy(struct net_linkaddr * dst,const struct net_linkaddr * src)142 static inline int net_linkaddr_copy(struct net_linkaddr *dst,
143 				    const struct net_linkaddr *src)
144 {
145 	if (dst == NULL || src == NULL) {
146 		return -EINVAL;
147 	}
148 
149 	if (src->len > NET_LINK_ADDR_MAX_LENGTH) {
150 		return -EMSGSIZE;
151 	}
152 
153 	dst->type = src->type;
154 	dst->len = src->len;
155 	memcpy(dst->addr, src->addr, src->len);
156 
157 	return 0;
158 }
159 
160 /**
161  * @brief Create a link address structure.
162  *
163  * @param lladdr The link address structure to change.
164  * @param addr Array of bytes containing the link address. If set to NULL,
165  * the address will be cleared.
166  * @param len Length of the link address array.
167  * @param type Type of the link address.
168  * @return 0 if ok, <0 if error
169  */
net_linkaddr_create(struct net_linkaddr * lladdr,const uint8_t * addr,uint8_t len,enum net_link_type type)170 static inline int net_linkaddr_create(struct net_linkaddr *lladdr,
171 				      const uint8_t *addr, uint8_t len,
172 				      enum net_link_type type)
173 {
174 	if (lladdr == NULL) {
175 		return -EINVAL;
176 	}
177 
178 	if (len > NET_LINK_ADDR_MAX_LENGTH) {
179 		return -EMSGSIZE;
180 	}
181 
182 	if (addr == NULL) {
183 		memset(lladdr->addr, 0, NET_LINK_ADDR_MAX_LENGTH);
184 	} else {
185 		memcpy(lladdr->addr, addr, len);
186 	}
187 
188 	lladdr->type = type;
189 	lladdr->len = len;
190 
191 	return 0;
192 }
193 
194 /**
195  * @brief Clear link address.
196  *
197  * @param lladdr The link address structure.
198  * @return 0 if ok, <0 if error
199  */
net_linkaddr_clear(struct net_linkaddr * lladdr)200 static inline int net_linkaddr_clear(struct net_linkaddr *lladdr)
201 {
202 	return net_linkaddr_create(lladdr, NULL, 0, NET_LINK_UNKNOWN);
203 }
204 
205 /**
206  * @}
207  */
208 
209 #ifdef __cplusplus
210 }
211 #endif
212 
213 #endif /* ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_ */
214