1 /* udp.c - UDP specific code for echo client */
2 
3 /*
4  * Copyright (c) 2017 Intel Corporation.
5  * Copyright (c) 2018 Nordic Semiconductor ASA.
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG);
12 
13 #include <zephyr/kernel.h>
14 #include <errno.h>
15 #include <stdio.h>
16 
17 #include <zephyr/net/socket.h>
18 #include <zephyr/net/tls_credentials.h>
19 #include <zephyr/random/random.h>
20 
21 #include "common.h"
22 #include "ca_certificate.h"
23 
24 #define RECV_BUF_SIZE 1280
25 #define UDP_SLEEP K_MSEC(150)
26 #define UDP_WAIT K_SECONDS(10)
27 
28 static APP_BMEM char recv_buf[RECV_BUF_SIZE];
29 
30 static K_THREAD_STACK_DEFINE(udp_tx_thread_stack, UDP_STACK_SIZE);
31 static struct k_thread udp_tx_thread;
32 
33 /* Kernel objects should not be placed in a memory area accessible from user
34  * threads.
35  */
36 static struct udp_control udp4_ctrl, udp6_ctrl;
37 static struct k_poll_signal udp_kill;
38 
39 static int send_udp_data(struct sample_data *data);
40 static void wait_reply(struct k_timer *timer);
41 static void wait_transmit(struct k_timer *timer);
42 
process_udp_tx(void * p1,void * p2,void * p3)43 static void process_udp_tx(void *p1, void *p2, void *p3)
44 {
45 	ARG_UNUSED(p1);
46 	ARG_UNUSED(p2);
47 	ARG_UNUSED(p3);
48 
49 	struct k_poll_event events[] = {
50 		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
51 					 K_POLL_MODE_NOTIFY_ONLY,
52 					 &udp_kill),
53 #if defined(CONFIG_NET_IPV4)
54 		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
55 					 K_POLL_MODE_NOTIFY_ONLY,
56 					 &udp4_ctrl.tx_signal),
57 #endif
58 #if defined(CONFIG_NET_IPV6)
59 		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
60 					 K_POLL_MODE_NOTIFY_ONLY,
61 					 &udp6_ctrl.tx_signal),
62 #endif
63 	};
64 
65 	while (true) {
66 		k_poll(events, ARRAY_SIZE(events), K_FOREVER);
67 
68 		for (int i = 0; i < ARRAY_SIZE(events); i++) {
69 			unsigned int signaled;
70 			int result;
71 
72 			k_poll_signal_check(events[i].signal, &signaled, &result);
73 			if (signaled == 0) {
74 				continue;
75 			}
76 
77 			k_poll_signal_reset(events[i].signal);
78 			events[i].state = K_POLL_STATE_NOT_READY;
79 
80 			if (events[i].signal == &udp_kill) {
81 				return;
82 			} else if (events[i].signal == &udp4_ctrl.tx_signal) {
83 				send_udp_data(&conf.ipv4);
84 			} else if (events[i].signal == &udp6_ctrl.tx_signal) {
85 				send_udp_data(&conf.ipv6);
86 			}
87 		}
88 	}
89 }
90 
udp_control_init(struct udp_control * ctrl)91 static void udp_control_init(struct udp_control *ctrl)
92 {
93 	k_timer_init(&ctrl->rx_timer, wait_reply, NULL);
94 	k_timer_init(&ctrl->tx_timer, wait_transmit, NULL);
95 	k_poll_signal_init(&ctrl->tx_signal);
96 }
97 
udp_control_access_grant(struct udp_control * ctrl)98 static void udp_control_access_grant(struct udp_control *ctrl)
99 {
100 	k_thread_access_grant(k_current_get(),
101 			      &ctrl->rx_timer,
102 			      &ctrl->tx_timer,
103 			      &ctrl->tx_signal);
104 }
105 
init_udp(void)106 void init_udp(void)
107 {
108 	/* k_timer_init() is not a system call, therefore initialize kernel
109 	 * objects here.
110 	 */
111 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
112 		udp_control_init(&udp4_ctrl);
113 		conf.ipv4.udp.ctrl = &udp4_ctrl;
114 	}
115 
116 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
117 		udp_control_init(&udp6_ctrl);
118 		conf.ipv6.udp.ctrl = &udp6_ctrl;
119 	}
120 
121 	k_poll_signal_init(&udp_kill);
122 
123 	if (IS_ENABLED(CONFIG_USERSPACE)) {
124 		k_thread_access_grant(k_current_get(),
125 				      &udp_tx_thread,
126 				      &udp_tx_thread_stack,
127 				      &udp_kill);
128 
129 		if (IS_ENABLED(CONFIG_NET_IPV4)) {
130 			udp_control_access_grant(&udp4_ctrl);
131 		}
132 
133 		if (IS_ENABLED(CONFIG_NET_IPV6)) {
134 			udp_control_access_grant(&udp6_ctrl);
135 		}
136 	}
137 }
138 
send_udp_data(struct sample_data * data)139 static int send_udp_data(struct sample_data *data)
140 {
141 	int ret;
142 
143 	do {
144 		data->udp.expecting = sys_rand32_get() % ipsum_len;
145 	} while (data->udp.expecting == 0U ||
146 		 data->udp.expecting > data->udp.mtu);
147 
148 	ret = send(data->udp.sock, lorem_ipsum, data->udp.expecting, 0);
149 
150 	if (PRINT_PROGRESS) {
151 		LOG_DBG("%s UDP: Sent %d bytes", data->proto, data->udp.expecting);
152 	}
153 
154 	k_timer_start(&data->udp.ctrl->rx_timer, UDP_WAIT, K_NO_WAIT);
155 
156 	return ret < 0 ? -EIO : 0;
157 }
158 
compare_udp_data(struct sample_data * data,const char * buf,uint32_t received)159 static int compare_udp_data(struct sample_data *data, const char *buf, uint32_t received)
160 {
161 	if (received != data->udp.expecting) {
162 		LOG_ERR("Invalid amount of data received: UDP %s", data->proto);
163 		return -EIO;
164 	}
165 
166 	if (memcmp(buf, lorem_ipsum, received) != 0) {
167 		LOG_ERR("Invalid data received: UDP %s", data->proto);
168 		return -EIO;
169 	}
170 
171 	return 0;
172 }
173 
wait_reply(struct k_timer * timer)174 static void wait_reply(struct k_timer *timer)
175 {
176 	/* This means that we did not receive response in time. */
177 	struct udp_control *ctrl = CONTAINER_OF(timer, struct udp_control, rx_timer);
178 	struct sample_data *data = (ctrl == conf.ipv4.udp.ctrl) ? &conf.ipv4 : &conf.ipv6;
179 
180 	LOG_ERR("UDP %s: Data packet not received", data->proto);
181 
182 	/* Send a new packet at this point */
183 	k_poll_signal_raise(&ctrl->tx_signal, 0);
184 }
185 
wait_transmit(struct k_timer * timer)186 static void wait_transmit(struct k_timer *timer)
187 {
188 	struct udp_control *ctrl = CONTAINER_OF(timer, struct udp_control, tx_timer);
189 
190 	k_poll_signal_raise(&ctrl->tx_signal, 0);
191 }
192 
start_udp_proto(struct sample_data * data,sa_family_t family,struct sockaddr * addr,socklen_t addrlen)193 static int start_udp_proto(struct sample_data *data, sa_family_t family,
194 			   struct sockaddr *addr, socklen_t addrlen)
195 {
196 	int optval;
197 	int ret;
198 
199 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
200 	data->udp.sock = socket(family, SOCK_DGRAM, IPPROTO_DTLS_1_2);
201 #else
202 	data->udp.sock = socket(family, SOCK_DGRAM, IPPROTO_UDP);
203 #endif
204 	if (data->udp.sock < 0) {
205 		LOG_ERR("Failed to create UDP socket (%s): %d", data->proto,
206 			errno);
207 		return -errno;
208 	}
209 
210 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
211 	sec_tag_t sec_tag_list[] = {
212 		CA_CERTIFICATE_TAG,
213 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
214 		PSK_TAG,
215 #endif
216 	};
217 
218 	ret = setsockopt(data->udp.sock, SOL_TLS, TLS_SEC_TAG_LIST,
219 			 sec_tag_list, sizeof(sec_tag_list));
220 	if (ret < 0) {
221 		LOG_ERR("Failed to set TLS_SEC_TAG_LIST option (%s): %d",
222 			data->proto, errno);
223 		ret = -errno;
224 	}
225 
226 	ret = setsockopt(data->udp.sock, SOL_TLS, TLS_HOSTNAME,
227 			 TLS_PEER_HOSTNAME, sizeof(TLS_PEER_HOSTNAME));
228 	if (ret < 0) {
229 		LOG_ERR("Failed to set TLS_HOSTNAME option (%s): %d",
230 			data->proto, errno);
231 		ret = -errno;
232 	}
233 #endif
234 
235 	/* Prefer IPv6 temporary addresses */
236 	if (family == AF_INET6) {
237 		optval = IPV6_PREFER_SRC_TMP;
238 		(void)setsockopt(data->udp.sock, IPPROTO_IPV6,
239 				 IPV6_ADDR_PREFERENCES,
240 				 &optval, sizeof(optval));
241 	}
242 
243 	/* Call connect so we can use send and recv. */
244 	ret = connect(data->udp.sock, addr, addrlen);
245 	if (ret < 0) {
246 		LOG_ERR("Cannot connect to UDP remote (%s): %d", data->proto,
247 			errno);
248 		ret = -errno;
249 	}
250 
251 	return ret;
252 }
253 
process_udp_proto(struct sample_data * data)254 static int process_udp_proto(struct sample_data *data)
255 {
256 	int ret, received;
257 
258 	received = recv(data->udp.sock, recv_buf, sizeof(recv_buf),
259 			MSG_DONTWAIT);
260 
261 	if (received == 0) {
262 		return -EIO;
263 	}
264 	if (received < 0) {
265 		if (errno == EAGAIN || errno == EWOULDBLOCK) {
266 			ret = 0;
267 		} else {
268 			ret = -errno;
269 		}
270 		return ret;
271 	}
272 
273 	ret = compare_udp_data(data, recv_buf, received);
274 	if (ret != 0) {
275 		LOG_WRN("%s UDP: Received and compared %d bytes, data "
276 			"mismatch", data->proto, received);
277 		return 0;
278 	}
279 
280 	if (PRINT_PROGRESS) {
281 		/* Correct response received */
282 		LOG_DBG("%s UDP: Received and compared %d bytes, all ok",
283 			data->proto, received);
284 	}
285 
286 	if (++data->udp.counter % 1000 == 0U) {
287 		LOG_INF("%s UDP: Exchanged %u packets", data->proto,
288 			data->udp.counter);
289 	}
290 
291 	k_timer_stop(&data->udp.ctrl->rx_timer);
292 
293 	/* Do not flood the link if we have also TCP configured */
294 	if (IS_ENABLED(CONFIG_NET_TCP)) {
295 		k_timer_start(&data->udp.ctrl->tx_timer, UDP_SLEEP, K_NO_WAIT);
296 	} else {
297 		k_poll_signal_raise(&data->udp.ctrl->tx_signal, 0);
298 	}
299 
300 	return ret;
301 }
302 
start_udp(void)303 int start_udp(void)
304 {
305 	int ret = 0;
306 	struct sockaddr_in addr4;
307 	struct sockaddr_in6 addr6;
308 
309 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
310 		addr6.sin6_family = AF_INET6;
311 		addr6.sin6_port = htons(PEER_PORT);
312 		inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR,
313 			  &addr6.sin6_addr);
314 
315 		ret = start_udp_proto(&conf.ipv6, AF_INET6,
316 				      (struct sockaddr *)&addr6,
317 				      sizeof(addr6));
318 		if (ret < 0) {
319 			return ret;
320 		}
321 	}
322 
323 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
324 		addr4.sin_family = AF_INET;
325 		addr4.sin_port = htons(PEER_PORT);
326 		inet_pton(AF_INET, CONFIG_NET_CONFIG_PEER_IPV4_ADDR,
327 			  &addr4.sin_addr);
328 
329 		ret = start_udp_proto(&conf.ipv4, AF_INET,
330 				      (struct sockaddr *)&addr4,
331 				      sizeof(addr4));
332 		if (ret < 0) {
333 			return ret;
334 		}
335 	}
336 
337 	k_thread_create(&udp_tx_thread, udp_tx_thread_stack,
338 			K_THREAD_STACK_SIZEOF(udp_tx_thread_stack),
339 			process_udp_tx,
340 			NULL, NULL, NULL, THREAD_PRIORITY,
341 			IS_ENABLED(CONFIG_USERSPACE) ?
342 						K_USER | K_INHERIT_PERMS : 0,
343 			K_NO_WAIT);
344 
345 	k_thread_name_set(&udp_tx_thread, "udp_tx");
346 
347 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
348 		k_poll_signal_raise(&conf.ipv6.udp.ctrl->tx_signal, 0);
349 	}
350 
351 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
352 		k_poll_signal_raise(&conf.ipv4.udp.ctrl->tx_signal, 0);
353 	}
354 
355 	return ret;
356 }
357 
process_udp(void)358 int process_udp(void)
359 {
360 	int ret = 0;
361 
362 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
363 		ret = process_udp_proto(&conf.ipv6);
364 		if (ret < 0) {
365 			return ret;
366 		}
367 	}
368 
369 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
370 		ret = process_udp_proto(&conf.ipv4);
371 		if (ret < 0) {
372 			return ret;
373 		}
374 	}
375 
376 	return ret;
377 }
378 
stop_udp(void)379 void stop_udp(void)
380 {
381 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
382 		k_timer_stop(&udp6_ctrl.tx_timer);
383 		k_timer_stop(&udp6_ctrl.rx_timer);
384 
385 		if (conf.ipv6.udp.sock >= 0) {
386 			(void)close(conf.ipv6.udp.sock);
387 		}
388 	}
389 
390 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
391 		k_timer_stop(&udp4_ctrl.tx_timer);
392 		k_timer_stop(&udp4_ctrl.rx_timer);
393 
394 		if (conf.ipv4.udp.sock >= 0) {
395 			(void)close(conf.ipv4.udp.sock);
396 		}
397 	}
398 
399 	k_poll_signal_raise(&udp_kill, 0);
400 }
401