1 /** @file
2  * @brief IPv4 autoconf related functions
3  */
4 
5 /*
6  * Copyright (c) 2017 Matthias Boesl
7  * Copyright (c) 2018 Intel Corporation
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(net_ipv4_autoconf, CONFIG_NET_IPV4_AUTO_LOG_LEVEL);
14 
15 #include "net_private.h"
16 #include <errno.h>
17 #include "../l2/ethernet/arp.h"
18 #include <net/net_pkt.h>
19 #include <net/net_core.h>
20 #include <net/net_if.h>
21 #include <random/rand32.h>
22 
23 #include "ipv4_autoconf_internal.h"
24 
25 /* Have only one timer in order to save memory */
26 static struct k_work_delayable ipv4auto_timer;
27 
28 /* Track currently active timers */
29 static sys_slist_t ipv4auto_ifaces;
30 
31 #define BUF_ALLOC_TIMEOUT K_MSEC(100)
32 
ipv4_autoconf_prepare_arp(struct net_if * iface)33 static struct net_pkt *ipv4_autoconf_prepare_arp(struct net_if *iface)
34 {
35 	struct net_if_config *cfg = net_if_get_config(iface);
36 	struct net_pkt *pkt;
37 
38 	/* We provide AF_UNSPEC to the allocator: this packet does not
39 	 * need space for any IPv4 header.
40 	 */
41 	pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_arp_hdr),
42 					AF_UNSPEC, 0, BUF_ALLOC_TIMEOUT);
43 	if (!pkt) {
44 		return NULL;
45 	}
46 
47 	net_pkt_set_family(pkt, AF_INET);
48 	net_pkt_set_ipv4_auto(pkt, true);
49 
50 	return net_arp_prepare(pkt, &cfg->ipv4auto.requested_ip,
51 			       &cfg->ipv4auto.current_ip);
52 }
53 
ipv4_autoconf_send_probe(struct net_if_ipv4_autoconf * ipv4auto)54 static void ipv4_autoconf_send_probe(struct net_if_ipv4_autoconf *ipv4auto)
55 {
56 	struct net_pkt *pkt;
57 
58 	pkt = ipv4_autoconf_prepare_arp(ipv4auto->iface);
59 	if (!pkt) {
60 		NET_DBG("Failed to prepare probe %p", ipv4auto->iface);
61 		return;
62 	}
63 
64 	NET_DBG("Probing pkt %p", pkt);
65 
66 	if (net_if_send_data(ipv4auto->iface, pkt) == NET_DROP) {
67 		net_pkt_unref(pkt);
68 	} else {
69 		ipv4auto->probe_cnt++;
70 		ipv4auto->state = NET_IPV4_AUTOCONF_PROBE;
71 	}
72 }
73 
ipv4_autoconf_send_announcement(struct net_if_ipv4_autoconf * ipv4auto)74 static void ipv4_autoconf_send_announcement(
75 	struct net_if_ipv4_autoconf *ipv4auto)
76 {
77 	struct net_pkt *pkt;
78 
79 	pkt = ipv4_autoconf_prepare_arp(ipv4auto->iface);
80 	if (!pkt) {
81 		NET_DBG("Failed to prepare announcement %p", ipv4auto->iface);
82 		return;
83 	}
84 
85 	NET_DBG("Announcing pkt %p", pkt);
86 
87 	if (net_if_send_data(ipv4auto->iface, pkt) == NET_DROP) {
88 		net_pkt_unref(pkt);
89 	} else {
90 		ipv4auto->announce_cnt++;
91 		ipv4auto->state = NET_IPV4_AUTOCONF_ANNOUNCE;
92 	}
93 }
94 
net_ipv4_autoconf_input(struct net_if * iface,struct net_pkt * pkt)95 enum net_verdict net_ipv4_autoconf_input(struct net_if *iface,
96 					 struct net_pkt *pkt)
97 {
98 	struct net_if_config *cfg = net_if_get_config(iface);
99 	struct net_arp_hdr *arp_hdr;
100 
101 	cfg = net_if_get_config(iface);
102 	if (!cfg) {
103 		NET_DBG("Interface %p configuration missing!", iface);
104 		return NET_DROP;
105 	}
106 
107 	if (net_pkt_get_len(pkt) < sizeof(struct net_arp_hdr)) {
108 		NET_DBG("Invalid ARP header (len %zu, min %zu bytes)",
109 			net_pkt_get_len(pkt), sizeof(struct net_arp_hdr));
110 		return NET_DROP;
111 	}
112 
113 	arp_hdr = NET_ARP_HDR(pkt);
114 
115 	if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr,
116 			       &cfg->ipv4auto.requested_ip)) {
117 		/* No conflict */
118 		return NET_CONTINUE;
119 	}
120 
121 	if (!net_ipv4_addr_cmp(&arp_hdr->src_ipaddr,
122 			       &cfg->ipv4auto.requested_ip)) {
123 		/* No need to defend */
124 		return NET_CONTINUE;
125 	}
126 
127 	NET_DBG("Conflict detected from %s for %s, state %d",
128 		log_strdup(net_sprint_ll_addr((uint8_t *)&arp_hdr->src_hwaddr,
129 					      arp_hdr->hwlen)),
130 		log_strdup(net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr)),
131 		cfg->ipv4auto.state);
132 
133 	cfg->ipv4auto.conflict_cnt++;
134 
135 	switch (cfg->ipv4auto.state) {
136 	case NET_IPV4_AUTOCONF_PROBE:
137 		/* restart probing with renewed IP */
138 		net_ipv4_autoconf_start(iface);
139 		break;
140 	case NET_IPV4_AUTOCONF_ANNOUNCE:
141 	case NET_IPV4_AUTOCONF_ASSIGNED:
142 		if (cfg->ipv4auto.conflict_cnt == 1U) {
143 			/* defend IP */
144 			ipv4_autoconf_send_announcement(&cfg->ipv4auto);
145 		} else {
146 			/* unset host ip */
147 			if (!net_if_ipv4_addr_rm(iface,
148 						 &cfg->ipv4auto.requested_ip)) {
149 				NET_DBG("Failed to remove addr from iface");
150 			}
151 
152 			/* restart probing after second conflict */
153 			net_ipv4_autoconf_start(iface);
154 		}
155 
156 		break;
157 	default:
158 		break;
159 	}
160 
161 	return NET_DROP;
162 }
163 
ipv4_autoconf_send(struct net_if_ipv4_autoconf * ipv4auto)164 static void ipv4_autoconf_send(struct net_if_ipv4_autoconf *ipv4auto)
165 {
166 	switch (ipv4auto->state) {
167 	case NET_IPV4_AUTOCONF_INIT:
168 		ipv4auto->probe_cnt = 0U;
169 		ipv4auto->announce_cnt = 0U;
170 		ipv4auto->conflict_cnt = 0U;
171 		(void)memset(&ipv4auto->current_ip, 0, sizeof(struct in_addr));
172 		ipv4auto->requested_ip.s4_addr[0] = 169U;
173 		ipv4auto->requested_ip.s4_addr[1] = 254U;
174 		ipv4auto->requested_ip.s4_addr[2] = sys_rand32_get() % 254;
175 		ipv4auto->requested_ip.s4_addr[3] = sys_rand32_get() % 254;
176 
177 		NET_DBG("%s: Starting probe for 169.254.%d.%d", "Init",
178 			ipv4auto->requested_ip.s4_addr[2],
179 			ipv4auto->requested_ip.s4_addr[3]);
180 		ipv4_autoconf_send_probe(ipv4auto);
181 		break;
182 	case NET_IPV4_AUTOCONF_RENEW:
183 		ipv4auto->probe_cnt = 0U;
184 		ipv4auto->announce_cnt = 0U;
185 		ipv4auto->conflict_cnt = 0U;
186 		(void)memset(&ipv4auto->current_ip, 0, sizeof(struct in_addr));
187 		NET_DBG("%s: Starting probe for 169.254.%d.%d", "Renew",
188 			ipv4auto->requested_ip.s4_addr[2],
189 			ipv4auto->requested_ip.s4_addr[3]);
190 		ipv4_autoconf_send_probe(ipv4auto);
191 		break;
192 	case NET_IPV4_AUTOCONF_PROBE:
193 		/* schedule next probe */
194 		if (ipv4auto->probe_cnt <= (IPV4_AUTOCONF_PROBE_NUM - 1)) {
195 			ipv4_autoconf_send_probe(ipv4auto);
196 			break;
197 		}
198 		__fallthrough;
199 	case NET_IPV4_AUTOCONF_ANNOUNCE:
200 		if (ipv4auto->announce_cnt <=
201 		    (IPV4_AUTOCONF_ANNOUNCE_NUM - 1)) {
202 			net_ipaddr_copy(&ipv4auto->current_ip,
203 					&ipv4auto->requested_ip);
204 			ipv4_autoconf_send_announcement(ipv4auto);
205 			break;
206 		}
207 
208 		/* success, add new IPv4 address */
209 		if (!net_if_ipv4_addr_add(ipv4auto->iface,
210 					  &ipv4auto->requested_ip,
211 					  NET_ADDR_AUTOCONF, 0)) {
212 			NET_DBG("Failed to add IPv4 addr to iface %p",
213 				ipv4auto->iface);
214 			return;
215 		}
216 
217 		ipv4auto->state = NET_IPV4_AUTOCONF_ASSIGNED;
218 		break;
219 	default:
220 		break;
221 	}
222 }
223 
ipv4_autoconf_get_timeout(struct net_if_ipv4_autoconf * ipv4auto)224 static uint32_t ipv4_autoconf_get_timeout(struct net_if_ipv4_autoconf *ipv4auto)
225 {
226 	switch (ipv4auto->state) {
227 	case NET_IPV4_AUTOCONF_PROBE:
228 		if (ipv4auto->conflict_cnt >= IPV4_AUTOCONF_MAX_CONFLICTS) {
229 			NET_DBG("Rate limiting");
230 			return MSEC_PER_SEC * IPV4_AUTOCONF_RATE_LIMIT_INTERVAL;
231 
232 		} else if (ipv4auto->probe_cnt == IPV4_AUTOCONF_PROBE_NUM) {
233 			return MSEC_PER_SEC * IPV4_AUTOCONF_ANNOUNCE_INTERVAL;
234 		}
235 
236 		return IPV4_AUTOCONF_PROBE_WAIT * MSEC_PER_SEC +
237 			(sys_rand32_get() % MSEC_PER_SEC);
238 
239 	case NET_IPV4_AUTOCONF_ANNOUNCE:
240 		return MSEC_PER_SEC * IPV4_AUTOCONF_ANNOUNCE_INTERVAL;
241 
242 	default:
243 		break;
244 	}
245 
246 	return 0;
247 }
248 
ipv4_autoconf_submit_work(uint32_t timeout)249 static void ipv4_autoconf_submit_work(uint32_t timeout)
250 {
251 	k_work_cancel_delayable(&ipv4auto_timer);
252 	k_work_reschedule(&ipv4auto_timer, K_MSEC(timeout));
253 
254 	NET_DBG("Next wakeup in %d ms",
255 		k_ticks_to_ms_ceil32(
256 			k_work_delayable_remaining_get(&ipv4auto_timer)));
257 }
258 
ipv4_autoconf_check_timeout(int64_t start,uint32_t time,int64_t timeout)259 static bool ipv4_autoconf_check_timeout(int64_t start, uint32_t time, int64_t timeout)
260 {
261 	start += time;
262 	if (start < 0) {
263 		start = -start;
264 	}
265 
266 	if (start > timeout) {
267 		return false;
268 	}
269 
270 	return true;
271 }
272 
ipv4_autoconf_timedout(struct net_if_ipv4_autoconf * ipv4auto,int64_t timeout)273 static bool ipv4_autoconf_timedout(struct net_if_ipv4_autoconf *ipv4auto,
274 				   int64_t timeout)
275 {
276 	return ipv4_autoconf_check_timeout(ipv4auto->timer_start,
277 					   ipv4auto->timer_timeout,
278 					   timeout);
279 }
280 
ipv4_autoconf_manage_timeouts(struct net_if_ipv4_autoconf * ipv4auto,int64_t timeout)281 static uint32_t ipv4_autoconf_manage_timeouts(
282 	struct net_if_ipv4_autoconf *ipv4auto,
283 	int64_t timeout)
284 {
285 	if (ipv4_autoconf_timedout(ipv4auto, timeout)) {
286 		ipv4_autoconf_send(ipv4auto);
287 	}
288 
289 	ipv4auto->timer_timeout = ipv4_autoconf_get_timeout(ipv4auto);
290 
291 	return ipv4auto->timer_timeout;
292 }
293 
ipv4_autoconf_timeout(struct k_work * work)294 static void ipv4_autoconf_timeout(struct k_work *work)
295 {
296 	uint32_t timeout_update = UINT32_MAX - 1;
297 	int64_t timeout = k_uptime_get();
298 	struct net_if_ipv4_autoconf *current, *next;
299 
300 	ARG_UNUSED(work);
301 
302 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ipv4auto_ifaces, current, next,
303 					  node) {
304 		uint32_t next_timeout;
305 
306 		next_timeout = ipv4_autoconf_manage_timeouts(current, timeout);
307 		if (next_timeout < timeout_update) {
308 			timeout_update = next_timeout;
309 		}
310 	}
311 
312 	if (timeout_update != UINT32_MAX && timeout_update > 0) {
313 		NET_DBG("Waiting for %u ms", timeout_update);
314 
315 		k_work_reschedule(&ipv4auto_timer, K_MSEC(timeout_update));
316 	}
317 }
318 
ipv4_autoconf_start_timer(struct net_if * iface,struct net_if_ipv4_autoconf * ipv4auto)319 static void ipv4_autoconf_start_timer(struct net_if *iface,
320 				      struct net_if_ipv4_autoconf *ipv4auto)
321 {
322 	sys_slist_append(&ipv4auto_ifaces, &ipv4auto->node);
323 
324 	ipv4auto->timer_start = k_uptime_get();
325 	ipv4auto->timer_timeout = MSEC_PER_SEC * IPV4_AUTOCONF_START_DELAY;
326 	ipv4auto->iface = iface;
327 
328 	ipv4_autoconf_submit_work(ipv4auto->timer_timeout);
329 }
330 
net_ipv4_autoconf_start(struct net_if * iface)331 void net_ipv4_autoconf_start(struct net_if *iface)
332 {
333 	/* Initialize interface and start probing */
334 	struct net_if_config *cfg;
335 
336 	cfg = net_if_get_config(iface);
337 	if (!cfg) {
338 		return;
339 	}
340 
341 	/* Remove the existing registration if found */
342 	if (cfg->ipv4auto.iface == iface) {
343 		net_ipv4_autoconf_reset(iface);
344 	}
345 
346 	NET_DBG("Starting IPv4 autoconf for iface %p", iface);
347 
348 	if (cfg->ipv4auto.state == NET_IPV4_AUTOCONF_ASSIGNED) {
349 		cfg->ipv4auto.state = NET_IPV4_AUTOCONF_RENEW;
350 	} else {
351 		cfg->ipv4auto.state = NET_IPV4_AUTOCONF_INIT;
352 	}
353 
354 	ipv4_autoconf_start_timer(iface, &cfg->ipv4auto);
355 }
356 
net_ipv4_autoconf_reset(struct net_if * iface)357 void net_ipv4_autoconf_reset(struct net_if *iface)
358 {
359 	struct net_if_config *cfg;
360 
361 	cfg = net_if_get_config(iface);
362 	if (!cfg) {
363 		return;
364 	}
365 
366 	/* Initialize interface and start probing */
367 	if (cfg->ipv4auto.state == NET_IPV4_AUTOCONF_ASSIGNED) {
368 		net_if_ipv4_addr_rm(iface, &cfg->ipv4auto.current_ip);
369 	}
370 
371 	NET_DBG("Autoconf reset for %p", iface);
372 
373 	/* Cancel any ongoing probing/announcing attempt*/
374 	sys_slist_find_and_remove(&ipv4auto_ifaces, &cfg->ipv4auto.node);
375 
376 	if (sys_slist_is_empty(&ipv4auto_ifaces)) {
377 		k_work_cancel_delayable(&ipv4auto_timer);
378 	}
379 }
380 
net_ipv4_autoconf_init(void)381 void net_ipv4_autoconf_init(void)
382 {
383 	k_work_init_delayable(&ipv4auto_timer, ipv4_autoconf_timeout);
384 }
385