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