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_DECLARE(net_samples_common, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 
12 #include <zephyr/net/ethernet.h>
13 #include <zephyr/net/virtual_mgmt.h>
14 #include <zephyr/net/conn_mgr_monitor.h>
15 
16 #if defined(CONFIG_NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR)
17 #define NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR CONFIG_NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR
18 #else
19 #define NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR ""
20 #endif
21 
22 #if defined(CONFIG_NET_SAMPLE_COMMON_TUNNEL_MY_ADDR)
23 #define NET_SAMPLE_COMMON_TUNNEL_MY_ADDR CONFIG_NET_SAMPLE_COMMON_TUNNEL_MY_ADDR
24 #else
25 #define NET_SAMPLE_COMMON_TUNNEL_MY_ADDR ""
26 #endif
27 
28 /* User data for the interface callback */
29 struct ud {
30 	struct net_if *tunnel;
31 	struct net_if *peer;
32 };
33 
is_tunnel(struct net_if * iface)34 bool is_tunnel(struct net_if *iface)
35 {
36 	if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL) &&
37 	    strncmp(net_if_get_device(iface)->name, "IP_TUNNEL0",
38 		    strlen(net_if_get_device(iface)->name)) == 0) {
39 		return true;
40 	}
41 
42 	return false;
43 }
44 
iface_cb(struct net_if * iface,void * user_data)45 static void iface_cb(struct net_if *iface, void *user_data)
46 {
47 	struct ud *ud = user_data;
48 
49 	if (!ud->tunnel && is_tunnel(iface)) {
50 		ud->tunnel = iface;
51 		return;
52 	}
53 }
54 
setup_iface(struct net_if * iface,const char * ipaddr)55 static int setup_iface(struct net_if *iface, const char *ipaddr)
56 {
57 	struct net_if_addr *ifaddr;
58 	struct sockaddr addr;
59 
60 	/* Before setting up tunnel, make sure it will be ignored by conn_mgr */
61 	conn_mgr_ignore_iface(iface);
62 
63 	if (!net_ipaddr_parse(ipaddr, strlen(ipaddr), &addr)) {
64 		LOG_ERR("Tunnel peer address \"%s\" invalid.", ipaddr);
65 		return -EINVAL;
66 	}
67 
68 	if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) {
69 		ifaddr = net_if_ipv6_addr_add(iface,
70 					      &net_sin6(&addr)->sin6_addr,
71 					      NET_ADDR_MANUAL, 0);
72 		if (!ifaddr) {
73 			LOG_ERR("Cannot add %s to interface %d",
74 				ipaddr, net_if_get_by_iface(iface));
75 			return -EINVAL;
76 		}
77 	}
78 
79 	if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) {
80 		ifaddr = net_if_ipv4_addr_add(iface,
81 					      &net_sin(&addr)->sin_addr,
82 					      NET_ADDR_MANUAL, 0);
83 		if (!ifaddr) {
84 			LOG_ERR("Cannot add %s to interface %d",
85 				ipaddr, net_if_get_by_iface(iface));
86 			return -EINVAL;
87 		}
88 	}
89 
90 	return 0;
91 }
92 
init_tunnel(void)93 int init_tunnel(void)
94 {
95 	struct virtual_interface_req_params params = { 0 };
96 	struct sockaddr peer = { 0 };
97 	struct ud ud;
98 	int ret;
99 	int mtu;
100 
101 	memset(&ud, 0, sizeof(ud));
102 
103 	if (NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR[0] == '\0') {
104 		LOG_INF("Tunnel peer address not set.");
105 		return 0;
106 	}
107 
108 	if (!net_ipaddr_parse(NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR,
109 			      strlen(NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR),
110 			      &peer)) {
111 		LOG_ERR("Tunnel peer address \"%s\" invalid.",
112 			NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR);
113 		return -EINVAL;
114 	}
115 
116 	if (IS_ENABLED(CONFIG_NET_IPV6) && peer.sa_family == AF_INET6) {
117 		struct net_if *iface;
118 
119 		iface = net_if_ipv6_select_src_iface(
120 					&net_sin6(&peer)->sin6_addr);
121 		ud.peer = iface;
122 		params.family = AF_INET6;
123 		net_ipaddr_copy(&params.peer6addr,
124 				&net_sin6(&peer)->sin6_addr);
125 		mtu = NET_ETH_MTU - sizeof(struct net_ipv6_hdr);
126 
127 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && peer.sa_family == AF_INET) {
128 		struct net_if *iface;
129 
130 		iface = net_if_ipv4_select_src_iface(
131 					&net_sin(&peer)->sin_addr);
132 		ud.peer = iface;
133 		params.family = AF_INET;
134 		net_ipaddr_copy(&params.peer4addr,
135 				&net_sin(&peer)->sin_addr);
136 		mtu = NET_ETH_MTU - sizeof(struct net_ipv4_hdr);
137 
138 	} else {
139 		LOG_ERR("Invalid address family %d", peer.sa_family);
140 		return -EINVAL;
141 	}
142 
143 	if (ud.peer == NULL) {
144 		LOG_ERR("Peer address %s unreachable",
145 			NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR);
146 		return -ENETUNREACH;
147 	}
148 
149 	net_if_foreach(iface_cb, &ud);
150 
151 	if (ud.tunnel == NULL) {
152 		LOG_ERR("Tunnel interface not found.");
153 		return -ENOENT;
154 	}
155 
156 	ret = net_mgmt(NET_REQUEST_VIRTUAL_INTERFACE_SET_PEER_ADDRESS,
157 		       ud.tunnel, &params, sizeof(params));
158 	if (ret < 0 && ret != -ENOTSUP) {
159 		LOG_ERR("Cannot set peer address %s to "
160 			"interface %d (%d)",
161 			NET_SAMPLE_COMMON_TUNNEL_PEER_ADDR,
162 			net_if_get_by_iface(ud.tunnel),
163 			ret);
164 	}
165 
166 	params.mtu = mtu;
167 
168 	ret = net_mgmt(NET_REQUEST_VIRTUAL_INTERFACE_SET_MTU,
169 		       ud.tunnel, &params, sizeof(params));
170 	if (ret < 0 && ret != -ENOTSUP) {
171 		LOG_ERR("Cannot set interface %d MTU to %d (%d)",
172 			net_if_get_by_iface(ud.tunnel), params.mtu, ret);
173 	}
174 
175 	ret = setup_iface(ud.tunnel,
176 			  NET_SAMPLE_COMMON_TUNNEL_MY_ADDR);
177 	if (ret < 0) {
178 		LOG_ERR("Cannot set IP address %s to tunnel interface",
179 			NET_SAMPLE_COMMON_TUNNEL_MY_ADDR);
180 		return -EINVAL;
181 	}
182 
183 	return 0;
184 }
185