1 /*
2  * Copyright (c) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_virtual_ipip, CONFIG_NET_L2_IPIP_LOG_LEVEL);
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <errno.h>
13 
14 #include <zephyr/net/net_core.h>
15 #include <zephyr/net/net_ip.h>
16 #include <zephyr/net/virtual.h>
17 
18 #include "ipv4.h"
19 #include "ipv6.h"
20 #include "net_private.h"
21 
22 #if defined(CONFIG_NET_L2_IPIP_TXRX_DEBUG)
23 #define DEBUG_TX 1
24 #define DEBUG_RX 1
25 #else
26 #define DEBUG_TX 0
27 #define DEBUG_RX 0
28 #endif
29 
30 #define IPIPV4_MTU NET_IPV4_MTU
31 #define IPIPV6_MTU NET_IPV6_MTU
32 
33 #define PKT_ALLOC_TIME K_MSEC(50)
34 
35 static K_MUTEX_DEFINE(lock);
36 
37 static void init_context_iface(void);
38 
39 struct ipip_context {
40 	struct net_if *iface;
41 	struct net_if *attached_to;
42 	union {
43 		sa_family_t family;
44 		struct net_addr peer;
45 	};
46 
47 	union {
48 		const struct in_addr *my4addr;
49 		const struct in6_addr *my6addr;
50 	};
51 
52 	bool is_used;
53 	bool status;
54 	bool init_done;
55 };
56 
virt_dev_init(const struct device * dev)57 static int virt_dev_init(const struct device *dev)
58 {
59 	ARG_UNUSED(dev);
60 
61 	init_context_iface();
62 
63 	return 0;
64 }
65 
iface_init(struct net_if * iface)66 static void iface_init(struct net_if *iface)
67 {
68 	struct ipip_context *ctx = net_if_get_device(iface)->data;
69 
70 	if (ctx->init_done) {
71 		return;
72 	}
73 
74 	ctx->iface = iface;
75 	net_if_flag_set(iface, NET_IF_NO_AUTO_START);
76 	net_if_flag_set(iface, NET_IF_POINTOPOINT);
77 
78 	(void)net_virtual_set_flags(iface, NET_L2_POINT_TO_POINT);
79 
80 	ctx->init_done = true;
81 }
82 
get_capabilities(struct net_if * iface)83 static enum virtual_interface_caps get_capabilities(struct net_if *iface)
84 {
85 	ARG_UNUSED(iface);
86 
87 	return VIRTUAL_INTERFACE_IPIP;
88 }
89 
interface_start(const struct device * dev)90 static int interface_start(const struct device *dev)
91 {
92 	struct ipip_context *ctx = dev->data;
93 	int ret = 0;
94 
95 	if (ctx->status) {
96 		return -EALREADY;
97 	}
98 
99 	ctx->status = true;
100 
101 	NET_DBG("Starting iface %d", net_if_get_by_iface(ctx->iface));
102 
103 	return ret;
104 }
105 
interface_stop(const struct device * dev)106 static int interface_stop(const struct device *dev)
107 {
108 	struct ipip_context *ctx = dev->data;
109 
110 	if (!ctx->status) {
111 		return -EALREADY;
112 	}
113 
114 	ctx->status = false;
115 
116 	NET_DBG("Stopping iface %d", net_if_get_by_iface(ctx->iface));
117 
118 	return 0;
119 }
120 
ipv4_get_tos(struct net_pkt * pkt)121 static uint8_t ipv4_get_tos(struct net_pkt *pkt)
122 {
123 	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
124 	struct net_ipv4_hdr *ipv4_hdr;
125 
126 	ipv4_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &ipv4_access);
127 	if (!ipv4_hdr) {
128 		return 0;
129 	}
130 
131 	return ipv4_hdr->tos;
132 }
133 
interface_send(struct net_if * iface,struct net_pkt * pkt)134 static int interface_send(struct net_if *iface, struct net_pkt *pkt)
135 {
136 	struct ipip_context *ctx = net_if_get_device(iface)->data;
137 	struct net_pkt *tmp = NULL;
138 	uint8_t nexthdr;
139 	uint8_t tos = 0;
140 	int ret;
141 
142 	if (ctx->attached_to == NULL) {
143 		return -ENOENT;
144 	}
145 
146 	if (net_pkt_family(pkt) == AF_INET) {
147 		nexthdr = IPPROTO_IPIP;
148 		tos = ipv4_get_tos(pkt);
149 	} else if (net_pkt_family(pkt) == AF_INET6) {
150 		nexthdr = IPPROTO_IPV6;
151 	} else {
152 		return -EINVAL;
153 	}
154 
155 	/* Add new IP header */
156 	if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->family == AF_INET6) {
157 		tmp = net_pkt_alloc_with_buffer(iface,
158 						sizeof(struct net_ipv6_hdr),
159 						AF_INET6, IPPROTO_IPV6,
160 						PKT_ALLOC_TIME);
161 		if (tmp == NULL) {
162 			return -ENOMEM;
163 		}
164 
165 		if (ctx->my6addr == NULL) {
166 			ctx->my6addr = net_if_ipv6_select_src_addr(
167 						ctx->attached_to,
168 						&ctx->peer.in6_addr);
169 		}
170 
171 		ret = net_ipv6_create(tmp, ctx->my6addr, &ctx->peer.in6_addr);
172 		if (ret < 0) {
173 			goto out;
174 		}
175 
176 		net_buf_frag_add(tmp->buffer, pkt->buffer);
177 		pkt->buffer = tmp->buffer;
178 		tmp->buffer = NULL;
179 
180 		net_pkt_unref(tmp);
181 		tmp = NULL;
182 
183 		net_pkt_cursor_init(pkt);
184 
185 		net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
186 		net_pkt_set_ipv6_ext_opt_len(pkt, 0);
187 		net_pkt_set_iface(pkt, ctx->attached_to);
188 
189 		ret = net_ipv6_finalize(pkt, nexthdr);
190 		if (ret < 0) {
191 			goto out;
192 		}
193 
194 		net_pkt_set_family(pkt, AF_INET6);
195 
196 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->family == AF_INET) {
197 		tmp = net_pkt_alloc_with_buffer(iface,
198 						sizeof(struct net_ipv4_hdr),
199 						AF_INET, IPPROTO_IP,
200 						PKT_ALLOC_TIME);
201 		if (tmp == NULL) {
202 			return -ENOMEM;
203 		}
204 
205 		if (ctx->my4addr == NULL) {
206 			ctx->my4addr = net_if_ipv4_select_src_addr(
207 						ctx->attached_to,
208 						&ctx->peer.in_addr);
209 		}
210 
211 		if (net_if_ipv4_get_ttl(ctx->attached_to) == 0) {
212 			NET_WARN("Interface %d TTL set to 0",
213 				 net_if_get_by_iface(ctx->attached_to));
214 			return -EINVAL;
215 		}
216 
217 		net_pkt_set_ipv4_ttl(tmp,
218 				     net_if_ipv4_get_ttl(ctx->attached_to));
219 
220 		/* RFC2003 chapter 3.1 */
221 		ret = net_ipv4_create_full(tmp, ctx->my4addr,
222 					   &ctx->peer.in_addr,
223 					   tos, 0U, NET_IPV4_DF,
224 					   0U);
225 		if (ret < 0) {
226 			goto out;
227 		}
228 
229 		net_buf_frag_add(tmp->buffer, pkt->buffer);
230 		pkt->buffer = tmp->buffer;
231 		tmp->buffer = NULL;
232 
233 		net_pkt_unref(tmp);
234 		tmp = NULL;
235 
236 		net_pkt_cursor_init(pkt);
237 
238 		net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
239 		net_pkt_set_ipv4_opts_len(pkt, 0);
240 		net_pkt_set_iface(pkt, ctx->attached_to);
241 
242 		ret = net_ipv4_finalize(pkt, nexthdr);
243 		if (ret < 0) {
244 			goto out;
245 		}
246 
247 		net_pkt_set_family(pkt, AF_INET);
248 	}
249 
250 	if (DEBUG_TX) {
251 		char str[sizeof("TX iface xx")];
252 
253 		snprintk(str, sizeof(str), "TX iface %d",
254 			 net_if_get_by_iface(net_pkt_iface(pkt)));
255 
256 		net_pkt_hexdump(pkt, str);
257 	}
258 
259 	return net_send_data(pkt);
260 
261 out:
262 	if (tmp) {
263 		net_pkt_unref(tmp);
264 	}
265 
266 	return ret;
267 }
268 
verify_remote_addr(struct ipip_context * ctx,struct sockaddr * remote_addr)269 static bool verify_remote_addr(struct ipip_context *ctx,
270 			       struct sockaddr *remote_addr)
271 {
272 	if (ctx->family != remote_addr->sa_family) {
273 		return false;
274 	}
275 
276 	if (ctx->family == AF_INET) {
277 		if (memcmp(&ctx->peer.in_addr, &net_sin(remote_addr)->sin_addr,
278 			   sizeof(struct in_addr)) == 0) {
279 			return true;
280 		}
281 	} else {
282 		if (memcmp(&ctx->peer.in6_addr, &net_sin6(remote_addr)->sin6_addr,
283 			   sizeof(struct in6_addr)) == 0) {
284 			return true;
285 		}
286 	}
287 
288 	return false;
289 }
290 
interface_recv(struct net_if * iface,struct net_pkt * pkt)291 static enum net_verdict interface_recv(struct net_if *iface,
292 				       struct net_pkt *pkt)
293 {
294 	struct ipip_context *ctx = net_if_get_device(iface)->data;
295 	struct net_pkt_cursor hdr_start;
296 	uint8_t iptype;
297 
298 	net_pkt_cursor_backup(pkt, &hdr_start);
299 
300 	if (net_pkt_read_u8(pkt, &iptype)) {
301 		return NET_DROP;
302 	}
303 
304 	net_pkt_cursor_restore(pkt, &hdr_start);
305 
306 	switch (iptype & 0xf0) {
307 	case 0x60:
308 		net_pkt_set_family(pkt, AF_INET6);
309 		break;
310 	case 0x40:
311 		net_pkt_set_family(pkt, AF_INET);
312 		break;
313 	default:
314 		return NET_DROP;
315 	}
316 
317 	/* Make sure we are receiving data from remote end of the
318 	 * tunnel. See RFC4213 chapter 4 for details.
319 	 */
320 	if (!verify_remote_addr(ctx, net_pkt_remote_address(pkt))) {
321 		NET_DBG("DROP: remote address %s unknown",
322 			net_pkt_remote_address(pkt)->sa_family == AF_INET6 ?
323 			net_sprint_ipv6_addr(&net_sin6(net_pkt_remote_address(pkt))->sin6_addr) :
324 			net_sprint_ipv4_addr(&net_sin(net_pkt_remote_address(pkt))->sin_addr));
325 		return NET_DROP;
326 	}
327 
328 	if (DEBUG_RX) {
329 		char str[sizeof("RX iface xx")];
330 
331 		snprintk(str, sizeof(str), "RX iface %d",
332 			 net_if_get_by_iface(iface));
333 
334 		net_pkt_hexdump(pkt, str);
335 	}
336 
337 	/* net_pkt cursor must point to correct place so that we can fetch
338 	 * the network header.
339 	 */
340 	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
341 		NET_PKT_DATA_ACCESS_DEFINE(access, struct net_ipv6_hdr);
342 		struct net_ipv6_hdr *hdr;
343 		struct net_if *iface_test;
344 
345 		net_pkt_cursor_backup(pkt, &hdr_start);
346 
347 		hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &access);
348 		if (!hdr) {
349 			return NET_DROP;
350 		}
351 
352 		/* RFC4213 chapter 3.6 */
353 		iface_test = net_if_ipv6_select_src_iface((struct in6_addr *)hdr->dst);
354 		if (iface_test == NULL) {
355 			NET_DBG("DROP: not for me (dst %s)",
356 				net_sprint_ipv6_addr(&hdr->dst));
357 			return NET_DROP;
358 		}
359 
360 		if (iface != iface_test) {
361 			NET_DBG("DROP: wrong interface %d (%p), expecting %d (%p)",
362 				net_if_get_by_iface(iface_test), iface_test,
363 				net_if_get_by_iface(iface), iface);
364 			return NET_DROP;
365 		}
366 
367 		/* Hop limit fields is decremented, RFC2473 chapter 3.1 and
368 		 * RFC4213 chapter 3.3
369 		 */
370 		hdr->hop_limit--;
371 		(void)net_pkt_set_data(pkt, &access);
372 
373 		net_pkt_set_iface(pkt, iface);
374 
375 		net_pkt_cursor_restore(pkt, &hdr_start);
376 
377 		return net_ipv6_input(pkt, false);
378 	}
379 
380 	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
381 		NET_PKT_DATA_ACCESS_DEFINE(access, struct net_ipv4_hdr);
382 		struct net_ipv4_hdr *hdr;
383 		struct net_if *iface_test;
384 		uint16_t sum;
385 
386 		net_pkt_cursor_backup(pkt, &hdr_start);
387 
388 		hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &access);
389 		if (!hdr) {
390 			return NET_DROP;
391 		}
392 
393 		iface_test = net_if_ipv4_select_src_iface((struct in_addr *)hdr->dst);
394 		if (iface_test == NULL) {
395 			NET_DBG("DROP: not for me (dst %s)",
396 				net_sprint_ipv4_addr(&hdr->dst));
397 			return NET_DROP;
398 		}
399 
400 		if (iface != iface_test) {
401 			NET_DBG("DROP: wrong interface %d (%p), expecting %d (%p)",
402 				net_if_get_by_iface(iface_test), iface_test,
403 				net_if_get_by_iface(iface), iface);
404 			return NET_DROP;
405 		}
406 
407 		/* TTL fields is decremented, RFC2003 chapter 3.1 */
408 		hdr->ttl--;
409 
410 		/* Recalculate the checksum because TTL was changed */
411 		hdr->chksum = 0U;
412 
413 		sum = calc_chksum(0, access.data, access.size);
414 		sum = (sum == 0U) ? 0xffff : htons(sum);
415 
416 		hdr->chksum = ~sum;
417 
418 		(void)net_pkt_set_data(pkt, &access);
419 
420 		net_pkt_set_iface(pkt, iface);
421 
422 		net_pkt_cursor_restore(pkt, &hdr_start);
423 
424 		return net_ipv4_input(pkt, false);
425 	}
426 
427 	return NET_CONTINUE;
428 }
429 
interface_attach(struct net_if * iface,struct net_if * lower_iface)430 static int interface_attach(struct net_if *iface, struct net_if *lower_iface)
431 {
432 	struct ipip_context *ctx;
433 
434 	if (net_if_get_by_iface(iface) < 0) {
435 		return -ENOENT;
436 	}
437 
438 	k_mutex_lock(&lock, K_FOREVER);
439 
440 	ctx = net_if_get_device(iface)->data;
441 	ctx->attached_to = lower_iface;
442 	ctx->iface = iface;
443 
444 	if (lower_iface == NULL) {
445 		ctx->is_used = false;
446 	} else {
447 		ctx->is_used = true;
448 
449 		if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->family == AF_INET6) {
450 			struct net_if_addr *ifaddr;
451 			struct in6_addr iid;
452 			int ret;
453 
454 			/* RFC4213 chapter 3.7 */
455 			ret = net_ipv6_addr_generate_iid(iface, NULL,
456 				 COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
457 					     ((uint8_t *)&iface->config.ip.ipv6->network_counter),
458 					     (NULL)),
459 				 COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
460 					     (sizeof(iface->config.ip.ipv6->network_counter)),
461 					     (0U)),
462 				 0,
463 				 &iid,
464 				 net_if_get_link_addr(iface));
465 			if (ret < 0) {
466 				NET_WARN("IPv6 IID generation issue (%d)", ret);
467 			}
468 
469 			ifaddr = net_if_ipv6_addr_add(iface, &iid, NET_ADDR_AUTOCONF, 0);
470 			if (!ifaddr) {
471 				NET_ERR("Cannot add %s address to interface %p",
472 					net_sprint_ipv6_addr(&iid),
473 					iface);
474 			}
475 		}
476 	}
477 
478 	k_mutex_unlock(&lock);
479 
480 	return 0;
481 }
482 
interface_set_config(struct net_if * iface,enum virtual_interface_config_type type,const struct virtual_interface_config * config)483 static int interface_set_config(struct net_if *iface,
484 				enum virtual_interface_config_type type,
485 				const struct virtual_interface_config *config)
486 {
487 	struct ipip_context *ctx = net_if_get_device(iface)->data;
488 
489 	switch (type) {
490 	case VIRTUAL_INTERFACE_CONFIG_TYPE_PEER_ADDRESS:
491 		if (IS_ENABLED(CONFIG_NET_IPV4) && config->family == AF_INET) {
492 			char peer[INET_ADDRSTRLEN];
493 			char *addr_str;
494 
495 			net_ipaddr_copy(&ctx->peer.in_addr, &config->peer4addr);
496 
497 			addr_str = net_addr_ntop(AF_INET, &ctx->peer.in_addr,
498 						 peer, sizeof(peer));
499 
500 			ctx->family = AF_INET;
501 			net_virtual_set_name(iface, "IPv4 tunnel");
502 
503 			if (ctx->attached_to == NULL) {
504 				(void)net_virtual_interface_attach(iface,
505 					net_if_ipv4_select_src_iface(
506 						&ctx->peer.in_addr));
507 			}
508 
509 			if (ctx->attached_to) {
510 				net_if_ipv4_set_ttl(iface,
511 					net_if_ipv4_get_ttl(ctx->attached_to));
512 			}
513 
514 			NET_DBG("Interface %d peer address %s attached to %d",
515 				net_if_get_by_iface(iface),
516 				addr_str,
517 				net_if_get_by_iface(ctx->attached_to));
518 
519 			ctx->my4addr = NULL;
520 
521 		} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
522 			   config->family == AF_INET6) {
523 			char peer[INET6_ADDRSTRLEN];
524 			char *addr_str;
525 
526 			net_ipaddr_copy(&ctx->peer.in6_addr,
527 					&config->peer6addr);
528 
529 			addr_str = net_addr_ntop(AF_INET6, &ctx->peer.in6_addr,
530 						 peer, sizeof(peer));
531 
532 			ctx->family = AF_INET6;
533 			net_virtual_set_name(iface, "IPv6 tunnel");
534 
535 			net_if_ipv6_set_hop_limit(iface, 64);
536 
537 			if (ctx->attached_to == NULL) {
538 				(void)net_virtual_interface_attach(iface,
539 					net_if_ipv6_select_src_iface(
540 						&ctx->peer.in6_addr));
541 			}
542 
543 			NET_DBG("Interface %d peer address %s attached to %d",
544 				net_if_get_by_iface(iface),
545 				addr_str,
546 				net_if_get_by_iface(ctx->attached_to));
547 
548 			ctx->my6addr = NULL;
549 		} else {
550 			return -EINVAL;
551 		}
552 
553 		return 0;
554 
555 	case VIRTUAL_INTERFACE_CONFIG_TYPE_MTU:
556 		NET_DBG("Interface %d MTU set to %d",
557 			net_if_get_by_iface(iface), config->mtu);
558 		net_if_set_mtu(iface, config->mtu);
559 		return 0;
560 
561 	default:
562 		break;
563 	}
564 
565 	return -ENOTSUP;
566 }
567 
interface_get_config(struct net_if * iface,enum virtual_interface_config_type type,struct virtual_interface_config * config)568 static int interface_get_config(struct net_if *iface,
569 				enum virtual_interface_config_type type,
570 				struct virtual_interface_config *config)
571 {
572 	struct ipip_context *ctx = net_if_get_device(iface)->data;
573 
574 	switch (type) {
575 	case VIRTUAL_INTERFACE_CONFIG_TYPE_PEER_ADDRESS:
576 		if (IS_ENABLED(CONFIG_NET_IPV6) &&
577 		    ctx->family == AF_INET6) {
578 			net_ipaddr_copy(&config->peer6addr,
579 					&ctx->peer.in6_addr);
580 
581 		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
582 			   ctx->family == AF_INET) {
583 			net_ipaddr_copy(&config->peer4addr,
584 					&ctx->peer.in_addr);
585 
586 		} else {
587 			return -EINVAL;
588 		}
589 
590 		config->family = ctx->family;
591 		return 0;
592 
593 	case VIRTUAL_INTERFACE_CONFIG_TYPE_MTU:
594 		config->mtu = net_if_get_mtu(iface);
595 		return 0;
596 
597 	default:
598 		break;
599 	}
600 
601 	return -ENOTSUP;
602 }
603 
604 static const struct virtual_interface_api ipip_iface_api = {
605 	.iface_api.init = iface_init,
606 
607 	.get_capabilities = get_capabilities,
608 	.start = interface_start,
609 	.stop = interface_stop,
610 	.send = interface_send,
611 	.recv = interface_recv,
612 	.attach = interface_attach,
613 	.set_config = interface_set_config,
614 	.get_config = interface_get_config,
615 };
616 
617 #define NET_IPIP_INTERFACE_INIT(x, _)					\
618 	static struct ipip_context ipip_context_data_##x = {		\
619 	};								\
620 	NET_VIRTUAL_INTERFACE_INIT_INSTANCE(ipip_##x,			\
621 					    "IP_TUNNEL" #x,		\
622 					    x,				\
623 					    virt_dev_init,		\
624 					    NULL,			\
625 					    &ipip_context_data_##x,	\
626 					    NULL, /* config */		\
627 					    CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
628 					    &ipip_iface_api,		\
629 					    IPIPV4_MTU)
630 
631 LISTIFY(CONFIG_NET_L2_IPIP_TUNNEL_COUNT, NET_IPIP_INTERFACE_INIT, (;), _);
632 
633 #define INIT_IPIP_CONTEXT_PTR(x, _)					\
634 	[x] = &ipip_context_data_##x
635 
636 static struct ipip_context *ipip_ctx[] = {
637 	LISTIFY(CONFIG_NET_L2_IPIP_TUNNEL_COUNT, INIT_IPIP_CONTEXT_PTR, (,), _)
638 };
639 
640 #define INIT_IPIP_CONTEXT_IFACE(x, _)					\
641 	ipip_context_data_##x.iface = NET_IF_GET(ipip_##x, x)
642 
init_context_iface(void)643 static void init_context_iface(void)
644 {
645 	static bool init_done;
646 
647 	if (init_done) {
648 		return;
649 	}
650 
651 	init_done = true;
652 
653 	LISTIFY(CONFIG_NET_L2_IPIP_TUNNEL_COUNT, INIT_IPIP_CONTEXT_IFACE, (;), _);
654 }
655 
net_ipip_get_virtual_interface(struct net_if * input_iface)656 struct net_if *net_ipip_get_virtual_interface(struct net_if *input_iface)
657 {
658 	struct net_if *iface = NULL;
659 
660 	k_mutex_lock(&lock, K_FOREVER);
661 
662 	ARRAY_FOR_EACH(ipip_ctx, i) {
663 		if (ipip_ctx[i] == NULL || !ipip_ctx[i]->is_used) {
664 			continue;
665 		}
666 
667 		if (input_iface == ipip_ctx[i]->attached_to) {
668 			iface = ipip_ctx[i]->iface;
669 			goto out;
670 		}
671 	}
672 
673 out:
674 	k_mutex_unlock(&lock);
675 
676 	return iface;
677 }
678