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