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(¶ms.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(¶ms.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, ¶ms, 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, ¶ms, 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