1 /** @file
2  * @brief Network context API
3  *
4  * An API for applications to define a network connection.
5  */
6 
7 /*
8  * Copyright (c) 2016 Intel Corporation
9  * Copyright (c) 2021 Nordic Semiconductor
10  * Copyright (c) 2025 Aerlync Labs Inc.
11  * Copyright 2025 NXP
12  *
13  * SPDX-License-Identifier: Apache-2.0
14  */
15 
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(net_ctx, CONFIG_NET_CONTEXT_LOG_LEVEL);
18 
19 #include <zephyr/kernel.h>
20 #include <zephyr/random/random.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <stdbool.h>
24 
25 #include <zephyr/net/net_pkt.h>
26 #include <zephyr/net/net_ip.h>
27 #include <zephyr/net/socket.h>
28 #include <zephyr/net/net_context.h>
29 #include <zephyr/net/net_offload.h>
30 #include <zephyr/net/ethernet.h>
31 #include <zephyr/net/socketcan.h>
32 #include <zephyr/net/ieee802154.h>
33 
34 #include "connection.h"
35 #include "net_private.h"
36 
37 #include "ipv6.h"
38 #include "ipv4.h"
39 #include "udp_internal.h"
40 #include "tcp_internal.h"
41 #include "net_stats.h"
42 #include "pmtu.h"
43 
44 #ifdef CONFIG_NET_INITIAL_MCAST_TTL
45 #define INITIAL_MCAST_TTL CONFIG_NET_INITIAL_MCAST_TTL
46 #else
47 #define INITIAL_MCAST_TTL 1
48 #endif
49 
50 #ifdef CONFIG_NET_INITIAL_TTL
51 #define INITIAL_TTL CONFIG_NET_INITIAL_TTL
52 #else
53 #define INITIAL_TTL 1
54 #endif
55 
56 #ifdef CONFIG_NET_INITIAL_MCAST_HOP_LIMIT
57 #define INITIAL_MCAST_HOP_LIMIT CONFIG_NET_INITIAL_MCAST_HOP_LIMIT
58 #else
59 #define INITIAL_MCAST_HOP_LIMIT 1
60 #endif
61 
62 #ifdef CONFIG_NET_INITIAL_HOP_LIMIT
63 #define INITIAL_HOP_LIMIT CONFIG_NET_INITIAL_HOP_LIMIT
64 #else
65 #define INITIAL_HOP_LIMIT 1
66 #endif
67 
68 #ifndef EPFNOSUPPORT
69 /* Some old versions of newlib haven't got this defined in errno.h,
70  * Just use EPROTONOSUPPORT in this case
71  */
72 #define EPFNOSUPPORT EPROTONOSUPPORT
73 #endif
74 
75 #define PKT_WAIT_TIME K_SECONDS(1)
76 
77 #define NET_MAX_CONTEXT CONFIG_NET_MAX_CONTEXTS
78 
79 static struct net_context contexts[NET_MAX_CONTEXT];
80 
81 /* We need to lock the contexts array as these APIs are typically called
82  * from applications which are usually run in task context.
83  */
84 static struct k_sem contexts_lock;
85 
net_context_is_reuseaddr_set(struct net_context * context)86 bool net_context_is_reuseaddr_set(struct net_context *context)
87 {
88 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
89 	return context->options.reuseaddr;
90 #else
91 	return false;
92 #endif
93 }
94 
net_context_is_reuseport_set(struct net_context * context)95 bool net_context_is_reuseport_set(struct net_context *context)
96 {
97 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
98 	return context->options.reuseport;
99 #else
100 	return false;
101 #endif
102 }
103 
net_context_is_v6only_set(struct net_context * context)104 bool net_context_is_v6only_set(struct net_context *context)
105 {
106 #if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
107 	if (context == NULL) {
108 		return false;
109 	}
110 
111 	return context->options.ipv6_v6only;
112 #else
113 	ARG_UNUSED(context);
114 
115 	return true;
116 #endif
117 }
118 
net_context_is_recv_pktinfo_set(struct net_context * context)119 bool net_context_is_recv_pktinfo_set(struct net_context *context)
120 {
121 #if defined(CONFIG_NET_CONTEXT_RECV_PKTINFO)
122 	return context->options.recv_pktinfo;
123 #else
124 	ARG_UNUSED(context);
125 
126 	return false;
127 #endif
128 }
129 
net_context_is_recv_hoplimit_set(struct net_context * context)130 bool net_context_is_recv_hoplimit_set(struct net_context *context)
131 {
132 #if defined(CONFIG_NET_CONTEXT_RECV_HOPLIMIT)
133 	return context->options.recv_hoplimit;
134 #else
135 	ARG_UNUSED(context);
136 
137 	return false;
138 #endif
139 }
140 
net_context_is_timestamping_set(struct net_context * context)141 bool net_context_is_timestamping_set(struct net_context *context)
142 {
143 #if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
144 	return (bool)(context->options.timestamping > 0);
145 #else
146 	ARG_UNUSED(context);
147 
148 	return false;
149 #endif
150 }
151 
152 #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
is_in_tcp_listen_state(struct net_context * context)153 static inline bool is_in_tcp_listen_state(struct net_context *context)
154 {
155 #if defined(CONFIG_NET_TCP)
156 	if (net_context_get_type(context) == NET_SOCK_STREAM &&
157 	    net_context_get_state(context) == NET_CONTEXT_LISTENING) {
158 		return true;
159 	}
160 
161 	return false;
162 #else
163 	return false;
164 #endif
165 }
166 
is_in_tcp_time_wait_state(struct net_context * context)167 static inline bool is_in_tcp_time_wait_state(struct net_context *context)
168 {
169 #if defined(CONFIG_NET_TCP)
170 	if (net_context_get_type(context) == NET_SOCK_STREAM) {
171 		const struct tcp *tcp_conn = context->tcp;
172 
173 		if (net_tcp_get_state(tcp_conn) == TCP_TIME_WAIT) {
174 			return true;
175 		}
176 	}
177 
178 	return false;
179 #else
180 	return false;
181 #endif
182 }
183 
check_used_port(struct net_context * context,struct net_if * iface,enum net_ip_protocol proto,uint16_t local_port,const struct net_sockaddr * local_addr,bool reuseaddr_set,bool reuseport_set,bool check_port_range)184 static int check_used_port(struct net_context *context,
185 			   struct net_if *iface,
186 			   enum net_ip_protocol proto,
187 			   uint16_t local_port,
188 			   const struct net_sockaddr *local_addr,
189 			   bool reuseaddr_set,
190 			   bool reuseport_set,
191 			   bool check_port_range)
192 {
193 	int i;
194 
195 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
196 		if (!net_context_is_used(&contexts[i])) {
197 			continue;
198 		}
199 
200 		if (context != NULL && context == &contexts[i]) {
201 			continue;
202 		}
203 
204 		if (!(net_context_get_proto(&contexts[i]) == proto &&
205 		      net_sin((struct net_sockaddr *)&
206 			      contexts[i].local)->sin_port == local_port)) {
207 			continue;
208 		}
209 
210 		if (net_context_is_bound_to_iface(&contexts[i])) {
211 			if (iface != NULL && iface != net_context_get_iface(&contexts[i])) {
212 				continue;
213 			}
214 		}
215 
216 		if (IS_ENABLED(CONFIG_NET_IPV6) &&
217 		    local_addr->sa_family == NET_AF_INET6) {
218 			if (net_sin6_ptr(&contexts[i].local)->sin6_addr == NULL ||
219 			    net_sin6_ptr(&contexts[i].local)->sin6_family != NET_AF_INET6) {
220 				continue;
221 			}
222 
223 			if ((net_ipv6_is_addr_unspecified(
224 					net_sin6_ptr(&contexts[i].local)->sin6_addr) ||
225 			     net_ipv6_is_addr_unspecified(
226 					&net_sin6(local_addr)->sin6_addr))) {
227 				if (reuseport_set &&
228 				    net_context_is_reuseport_set(&contexts[i])) {
229 					/* When both context have the REUSEPORT set, both
230 					 * may be unspecified.
231 					 */
232 					continue;
233 				} else if (reuseaddr_set &&
234 					   !is_in_tcp_listen_state(&contexts[i]) &&
235 					   !(net_ipv6_is_addr_unspecified(
236 						net_sin6_ptr(&contexts[i].local)->sin6_addr) &&
237 					     net_ipv6_is_addr_unspecified(
238 						&net_sin6(local_addr)->sin6_addr))) {
239 					/* In case of REUSEADDR, only one context may be
240 					 * bound to the unspecified address, but not both.
241 					 * Furthermore, in case the existing context is in
242 					 * TCP LISTEN state, we ignore the REUSEADDR option
243 					 * (Linux behavior).
244 					 */
245 					continue;
246 				} else {
247 					return -EEXIST;
248 				}
249 			}
250 
251 			if (net_ipv6_addr_cmp(
252 				    net_sin6_ptr(&contexts[i].local)->
253 							     sin6_addr,
254 				    &((struct net_sockaddr_in6 *)
255 				      local_addr)->sin6_addr)) {
256 				if (reuseport_set &&
257 				    net_context_is_reuseport_set(&contexts[i])) {
258 					/* When both context have the REUSEPORT set, both
259 					 * may be bound to exactly the same address.
260 					 */
261 					continue;
262 				} else if (reuseaddr_set &&
263 					   is_in_tcp_time_wait_state(&contexts[i])) {
264 					/* With REUSEADDR, the existing context must be
265 					 * in the TCP TIME_WAIT state.
266 					 */
267 					continue;
268 				} else {
269 					return -EEXIST;
270 				}
271 			}
272 		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
273 			   local_addr->sa_family == NET_AF_INET) {
274 			/* If there is an IPv6 socket already bound and
275 			 * if v6only option is enabled, then it is possible to
276 			 * bind IPv4 address to it.
277 			 */
278 			if (net_sin_ptr(&contexts[i].local)->sin_addr == NULL ||
279 			    ((IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) ?
280 			      net_context_is_v6only_set(&contexts[i]) : true) &&
281 			     net_sin_ptr(&contexts[i].local)->sin_family != NET_AF_INET)) {
282 				continue;
283 			}
284 
285 			if ((net_ipv4_is_addr_unspecified(
286 					net_sin_ptr(&contexts[i].local)->sin_addr) ||
287 			     net_ipv4_is_addr_unspecified(
288 					&net_sin(local_addr)->sin_addr))) {
289 				if (reuseport_set &&
290 				    net_context_is_reuseport_set(&contexts[i])) {
291 					/* When both context have the REUSEPORT set, both
292 					 * may be unspecified.
293 					 */
294 					continue;
295 				} else if (reuseaddr_set &&
296 					   !is_in_tcp_listen_state(&contexts[i]) &&
297 					   !(net_ipv4_is_addr_unspecified(
298 						net_sin_ptr(&contexts[i].local)->sin_addr) &&
299 					     net_ipv4_is_addr_unspecified(
300 						&net_sin(local_addr)->sin_addr))) {
301 					/* In case of REUSEADDR, only one context may be
302 					 * bound to the unspecified address, but not both.
303 					 * Furthermore, in case the existing context is in
304 					 * TCP LISTEN state, we ignore the REUSEADDR option
305 					 * (Linux behavior).
306 					 */
307 					continue;
308 				} else {
309 					return -EEXIST;
310 				}
311 			}
312 
313 			if (net_ipv4_addr_cmp(
314 				    net_sin_ptr(&contexts[i].local)->
315 							      sin_addr,
316 				    &((struct net_sockaddr_in *)
317 				      local_addr)->sin_addr)) {
318 				if (reuseport_set &&
319 				    net_context_is_reuseport_set(&contexts[i])) {
320 					/* When both context have the REUSEPORT set, both
321 					 * may be bound to exactly the same address.
322 					 */
323 					continue;
324 				} else if (reuseaddr_set &&
325 					   is_in_tcp_time_wait_state(&contexts[i])) {
326 					/* With REUSEADDR, the existing context must be
327 					 * in the TCP TIME_WAIT state.
328 					 */
329 					continue;
330 				} else {
331 					return -EEXIST;
332 				}
333 			}
334 		}
335 	}
336 
337 	/* Make sure that if the port range is active, the port is
338 	 * within the range.
339 	 */
340 	if (IS_ENABLED(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE) && check_port_range) {
341 		uint16_t upper, lower;
342 
343 		upper = COND_CODE_1(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE,
344 				    (context->options.port_range >> 16),
345 				    (0));
346 		lower = COND_CODE_1(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE,
347 				    (context->options.port_range & 0xffff),
348 				    (0));
349 
350 		if (upper != 0 && lower != 0 && lower < upper) {
351 			if (net_ntohs(local_port) < lower || net_ntohs(local_port) > upper) {
352 				return -ERANGE;
353 			}
354 		}
355 	}
356 
357 	return 0;
358 }
359 
360 /* How many times we try to find a free port */
361 #define MAX_PORT_RETRIES 5
362 
find_available_port(struct net_context * context,const struct net_sockaddr * addr)363 static uint16_t find_available_port(struct net_context *context,
364 				    const struct net_sockaddr *addr)
365 {
366 	uint16_t local_port;
367 	int count = MAX_PORT_RETRIES;
368 
369 	do {
370 		if (IS_ENABLED(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)) {
371 			uint16_t upper, lower;
372 
373 			upper = COND_CODE_1(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE,
374 					    (context->options.port_range >> 16),
375 					    (0));
376 			lower = COND_CODE_1(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE,
377 					    (context->options.port_range & 0xffff),
378 					    (0));
379 
380 			/* This works the same way as in Linux. If either port
381 			 * range is 0, then we use random port. If both are set,
382 			 * then we use the range. Also make sure that upper is
383 			 * greater than lower.
384 			 */
385 			if (upper == 0 || lower == 0 || upper <= lower) {
386 				local_port = sys_rand16_get() | 0x8000;
387 			} else {
388 				local_port = lower + sys_rand16_get() % (upper - lower);
389 
390 				NET_DBG("Port range %d - %d, proposing port %d",
391 					lower, upper, local_port);
392 			}
393 		} else {
394 			local_port = sys_rand16_get() | 0x8000;
395 		}
396 
397 		count--;
398 	} while (count > 0 && check_used_port(context,
399 					      NULL,
400 					      net_context_get_proto(context),
401 					      net_htons(local_port),
402 					      addr,
403 					      false,
404 					      false,
405 					      false) == -EEXIST);
406 
407 	if (count == 0) {
408 		return 0;
409 	}
410 
411 	return net_htons(local_port);
412 }
413 #else
414 #define check_used_port(...) 0
415 #define find_available_port(...) 0
416 #endif
417 
net_context_port_in_use(enum net_ip_protocol proto,uint16_t local_port,const struct net_sockaddr * local_addr)418 bool net_context_port_in_use(enum net_ip_protocol proto,
419 			   uint16_t local_port,
420 			   const struct net_sockaddr *local_addr)
421 {
422 	return check_used_port(NULL, NULL, proto, net_htons(local_port),
423 			       local_addr, false, false, false) != 0;
424 }
425 
426 #if defined(CONFIG_NET_CONTEXT_CHECK)
net_context_check(net_sa_family_t family,enum net_sock_type type,uint16_t proto,struct net_context ** context)427 static int net_context_check(net_sa_family_t family, enum net_sock_type type,
428 			     uint16_t proto, struct net_context **context)
429 {
430 	switch (family) {
431 	case NET_AF_INET:
432 	case NET_AF_INET6:
433 		if (family == NET_AF_INET && !IS_ENABLED(CONFIG_NET_IPV4)) {
434 			NET_DBG("IPv4 disabled");
435 			return -EPFNOSUPPORT;
436 		}
437 		if (family == NET_AF_INET6 && !IS_ENABLED(CONFIG_NET_IPV6)) {
438 			NET_DBG("IPv6 disabled");
439 			return -EPFNOSUPPORT;
440 		}
441 		if (!IS_ENABLED(CONFIG_NET_UDP)) {
442 			if (type == NET_SOCK_DGRAM) {
443 				NET_DBG("DGRAM socket type disabled.");
444 				return -EPROTOTYPE;
445 			}
446 			if (proto == NET_IPPROTO_UDP) {
447 				NET_DBG("UDP disabled");
448 				return -EPROTONOSUPPORT;
449 			}
450 		}
451 		if (!IS_ENABLED(CONFIG_NET_TCP)) {
452 			if (type == NET_SOCK_STREAM) {
453 				NET_DBG("STREAM socket type disabled.");
454 				return -EPROTOTYPE;
455 			}
456 			if (proto == NET_IPPROTO_TCP) {
457 				NET_DBG("TCP disabled");
458 				return -EPROTONOSUPPORT;
459 			}
460 		}
461 		switch (type) {
462 		case NET_SOCK_DGRAM:
463 			if (proto != NET_IPPROTO_UDP) {
464 				NET_DBG("Context type and protocol mismatch,"
465 					" type %d proto %d", type, proto);
466 				return -EPROTONOSUPPORT;
467 			}
468 			break;
469 		case NET_SOCK_STREAM:
470 			if (proto != NET_IPPROTO_TCP) {
471 				NET_DBG("Context type and protocol mismatch,"
472 					" type %d proto %d", type, proto);
473 				return -EPROTONOSUPPORT;
474 			}
475 			break;
476 		case NET_SOCK_RAW:
477 			if (!IS_ENABLED(CONFIG_NET_SOCKETS_INET_RAW)) {
478 				NET_DBG("RAW IP sockets disabled.");
479 				return -EPROTONOSUPPORT;
480 			}
481 			break;
482 		default:
483 			NET_DBG("Unknown context type.");
484 			return -EPROTOTYPE;
485 		}
486 		break;
487 
488 	case NET_AF_PACKET:
489 		if (!IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
490 			NET_DBG("AF_PACKET disabled");
491 			return -EPFNOSUPPORT;
492 		}
493 		if (!IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) &&
494 		    type == NET_SOCK_DGRAM) {
495 			NET_DBG("DGRAM socket type disabled.");
496 			return -EPROTOTYPE;
497 		}
498 		if (type != NET_SOCK_RAW && type != NET_SOCK_DGRAM) {
499 			NET_DBG("AF_PACKET only supports RAW and DGRAM socket "
500 				"types.");
501 			return -EPROTOTYPE;
502 		}
503 		break;
504 
505 	case NET_AF_CAN:
506 		if (!IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
507 			NET_DBG("AF_CAN disabled");
508 			return -EPFNOSUPPORT;
509 		}
510 		if (type != NET_SOCK_RAW) {
511 			NET_DBG("AF_CAN only supports RAW socket type.");
512 			return -EPROTOTYPE;
513 		}
514 		if (proto != NET_CAN_RAW) {
515 			NET_DBG("AF_CAN only supports RAW_CAN protocol.");
516 			return -EPROTOTYPE;
517 		}
518 		break;
519 
520 	default:
521 		NET_DBG("Unknown address family %d", family);
522 		return -EAFNOSUPPORT;
523 	}
524 
525 	if (!context) {
526 		NET_DBG("Invalid context");
527 		return -EINVAL;
528 	}
529 
530 	return 0;
531 }
532 #endif /* CONFIG_NET_CONTEXT_CHECK */
533 
net_context_get(net_sa_family_t family,enum net_sock_type type,uint16_t proto,struct net_context ** context)534 int net_context_get(net_sa_family_t family, enum net_sock_type type, uint16_t proto,
535 		    struct net_context **context)
536 {
537 	int i, ret;
538 
539 	if (IS_ENABLED(CONFIG_NET_CONTEXT_CHECK)) {
540 		ret = net_context_check(family, type, proto, context);
541 		if (ret < 0) {
542 			return ret;
543 		}
544 	}
545 
546 	k_sem_take(&contexts_lock, K_FOREVER);
547 
548 	ret = -ENOENT;
549 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
550 		if (net_context_is_used(&contexts[i])) {
551 			continue;
552 		}
553 
554 		memset(&contexts[i], 0, sizeof(contexts[i]));
555 		/* FIXME - Figure out a way to get the correct network interface
556 		 * as it is not known at this point yet.
557 		 */
558 		if (!net_if_is_ip_offloaded(net_if_get_default())
559 			&& proto == NET_IPPROTO_TCP) {
560 			if (net_tcp_get(&contexts[i]) < 0) {
561 				break;
562 			}
563 		}
564 
565 		contexts[i].iface = -1;
566 		contexts[i].flags = 0U;
567 		atomic_set(&contexts[i].refcount, 1);
568 
569 		net_context_set_family(&contexts[i], family);
570 		net_context_set_type(&contexts[i], type);
571 		net_context_set_proto(&contexts[i], proto);
572 
573 #if defined(CONFIG_NET_IPV6)
574 		contexts[i].options.addr_preferences = ZSOCK_IPV6_PREFER_SRC_PUBTMP_DEFAULT;
575 #endif
576 
577 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
578 		contexts[i].options.rcvtimeo = K_FOREVER;
579 #endif
580 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
581 		contexts[i].options.sndtimeo = K_FOREVER;
582 #endif
583 #if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
584 		/* By default IPv4 and IPv6 are in different port spaces */
585 		contexts[i].options.ipv6_v6only = true;
586 #endif
587 #if defined(CONFIG_NET_IPV4)
588 		contexts[i].options.ipv4_mcast_loop =
589 			IS_ENABLED(CONFIG_NET_INITIAL_IPV4_MCAST_LOOP);
590 #endif
591 		if (IS_ENABLED(CONFIG_NET_IP)) {
592 			(void)memset(&contexts[i].remote, 0, sizeof(struct net_sockaddr));
593 			(void)memset(&contexts[i].local, 0, sizeof(struct net_sockaddr_ptr));
594 
595 			if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
596 				struct net_sockaddr_in6 *addr6 =
597 					(struct net_sockaddr_in6 *)&contexts[i].local;
598 				addr6->sin6_port =
599 					find_available_port(&contexts[i],
600 							    (struct net_sockaddr *)addr6);
601 
602 				if (!addr6->sin6_port) {
603 					ret = -EADDRINUSE;
604 					break;
605 				}
606 
607 				contexts[i].ipv6_hop_limit = INITIAL_HOP_LIMIT;
608 				contexts[i].ipv6_mcast_hop_limit = INITIAL_MCAST_HOP_LIMIT;
609 #if defined(CONFIG_NET_IPV6)
610 				contexts[i].options.ipv6_mcast_loop =
611 					IS_ENABLED(CONFIG_NET_INITIAL_IPV6_MCAST_LOOP);
612 #endif
613 			}
614 			if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
615 				struct net_sockaddr_in *addr =
616 					(struct net_sockaddr_in *)&contexts[i].local;
617 
618 				addr->sin_port =
619 					find_available_port(&contexts[i],
620 							    (struct net_sockaddr *)addr);
621 
622 				if (!addr->sin_port) {
623 					ret = -EADDRINUSE;
624 					break;
625 				}
626 
627 				contexts[i].ipv4_ttl = INITIAL_TTL;
628 				contexts[i].ipv4_mcast_ttl = INITIAL_MCAST_TTL;
629 			}
630 		}
631 
632 		if (IS_ENABLED(CONFIG_NET_CONTEXT_SYNC_RECV)) {
633 			k_sem_init(&contexts[i].recv_data_wait, 1, K_SEM_MAX_LIMIT);
634 		}
635 
636 		k_mutex_init(&contexts[i].lock);
637 
638 		contexts[i].flags |= NET_CONTEXT_IN_USE;
639 		*context = &contexts[i];
640 
641 		ret = 0;
642 		break;
643 	}
644 
645 	k_sem_give(&contexts_lock);
646 
647 	if (ret < 0) {
648 		if (ret == -EADDRINUSE &&
649 		    !net_if_is_ip_offloaded(net_if_get_default()) &&
650 		    proto == NET_IPPROTO_TCP) {
651 			/* Free the TCP context that we allocated earlier */
652 			net_tcp_put(&contexts[i], false);
653 		}
654 
655 		return ret;
656 	}
657 
658 	/* FIXME - Figure out a way to get the correct network interface
659 	 * as it is not known at this point yet.
660 	 */
661 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(net_if_get_default())) {
662 		ret = net_offload_get(net_if_get_default(), family, type, proto, context);
663 		if (ret < 0) {
664 			(*context)->flags &= ~NET_CONTEXT_IN_USE;
665 			*context = NULL;
666 			return ret;
667 		}
668 
669 		net_context_set_iface(*context, net_if_get_default());
670 	}
671 
672 	return 0;
673 }
674 
net_context_ref(struct net_context * context)675 int net_context_ref(struct net_context *context)
676 {
677 	int old_rc = atomic_inc(&context->refcount);
678 
679 	return old_rc + 1;
680 }
681 
net_context_unref(struct net_context * context)682 int net_context_unref(struct net_context *context)
683 {
684 	int old_rc = atomic_dec(&context->refcount);
685 
686 	if (old_rc != 1) {
687 		return old_rc - 1;
688 	}
689 
690 	k_mutex_lock(&context->lock, K_FOREVER);
691 
692 	if (context->conn_handler) {
693 		if (IS_ENABLED(CONFIG_NET_TCP) || IS_ENABLED(CONFIG_NET_UDP) ||
694 		    IS_ENABLED(CONFIG_NET_SOCKETS_CAN) ||
695 		    IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
696 			net_conn_unregister(context->conn_handler);
697 		}
698 
699 		context->conn_handler = NULL;
700 	}
701 
702 	net_context_set_state(context, NET_CONTEXT_UNCONNECTED);
703 
704 	k_mutex_unlock(&context->lock);
705 
706 	context->flags &= ~NET_CONTEXT_IN_USE;
707 
708 	NET_DBG("Context %p released", context);
709 
710 	return 0;
711 }
712 
net_context_put(struct net_context * context)713 int net_context_put(struct net_context *context)
714 {
715 	int ret = 0;
716 
717 	NET_ASSERT(context);
718 
719 	if (!PART_OF_ARRAY(contexts, context)) {
720 		return -EINVAL;
721 	}
722 
723 	k_mutex_lock(&context->lock, K_FOREVER);
724 
725 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
726 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
727 		ret = net_offload_put(net_context_get_iface(context), context);
728 		k_mutex_unlock(&context->lock);
729 		context->flags &= ~NET_CONTEXT_IN_USE;
730 		return ret;
731 	}
732 
733 	context->connect_cb = NULL;
734 	context->recv_cb = NULL;
735 	context->send_cb = NULL;
736 
737 	/* net_tcp_put() will handle decrementing refcount on stack's behalf */
738 	net_tcp_put(context, false);
739 
740 	k_mutex_unlock(&context->lock);
741 
742 	/* Decrement refcount on user app's behalf */
743 	net_context_unref(context);
744 
745 	return ret;
746 }
747 
748 /* If local address is not bound, bind it to NET_INADDR_ANY and random port. */
bind_default(struct net_context * context)749 static int bind_default(struct net_context *context)
750 {
751 	net_sa_family_t family = net_context_get_family(context);
752 
753 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
754 		struct net_sockaddr_in6 addr6;
755 
756 		if (net_sin6_ptr(&context->local)->sin6_addr) {
757 			return 0;
758 		}
759 
760 		addr6.sin6_family = NET_AF_INET6;
761 		memcpy(&addr6.sin6_addr, net_ipv6_unspecified_address(),
762 		       sizeof(addr6.sin6_addr));
763 		addr6.sin6_port = net_context_get_type(context) == NET_SOCK_RAW ?
764 			0 : find_available_port(context,
765 						(struct net_sockaddr *)&addr6);
766 
767 		return net_context_bind(context, (struct net_sockaddr *)&addr6,
768 					sizeof(addr6));
769 	}
770 
771 	if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
772 		struct net_sockaddr_in addr4;
773 
774 		if (net_sin_ptr(&context->local)->sin_addr) {
775 			return 0;
776 		}
777 
778 		addr4.sin_family = NET_AF_INET;
779 		addr4.sin_addr.s_addr = NET_INADDR_ANY;
780 		addr4.sin_port = net_context_get_type(context) == NET_SOCK_RAW ?
781 			0 : find_available_port(context,
782 						(struct net_sockaddr *)&addr4);
783 
784 		return net_context_bind(context, (struct net_sockaddr *)&addr4,
785 					sizeof(addr4));
786 	}
787 
788 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && family == NET_AF_PACKET) {
789 		struct net_sockaddr_ll ll_addr;
790 		struct net_if *iface = net_context_get_iface(context);
791 
792 		if (net_sll_ptr(&context->local)->sll_addr) {
793 			return 0;
794 		}
795 
796 		ll_addr.sll_family = NET_AF_PACKET;
797 		ll_addr.sll_protocol = net_htons(net_context_get_proto(context));
798 		ll_addr.sll_ifindex = (iface == NULL) ? 0 : net_if_get_by_iface(iface);
799 
800 		return net_context_bind(context, (struct net_sockaddr *)&ll_addr,
801 					sizeof(ll_addr));
802 	}
803 
804 	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == NET_AF_CAN) {
805 		struct net_sockaddr_can can_addr;
806 
807 		if (context->iface >= 0) {
808 			return 0;
809 		} else {
810 #if defined(CONFIG_NET_L2_CANBUS_RAW)
811 			struct net_if *iface;
812 
813 			iface = net_if_get_first_by_type(
814 						&NET_L2_GET_NAME(CANBUS_RAW));
815 			if (!iface) {
816 				return -ENOENT;
817 			}
818 
819 			can_addr.can_ifindex = net_if_get_by_iface(iface);
820 			context->iface = can_addr.can_ifindex;
821 #else
822 			return -ENOENT;
823 #endif
824 		}
825 
826 		can_addr.can_family = NET_AF_CAN;
827 
828 		return net_context_bind(context, (struct net_sockaddr *)&can_addr,
829 					sizeof(can_addr));
830 	}
831 
832 	return -EINVAL;
833 }
834 
recheck_port(struct net_context * context,struct net_if * iface,int proto,uint16_t port,const struct net_sockaddr * addr)835 static int recheck_port(struct net_context *context,
836 			struct net_if *iface,
837 			int proto,
838 			uint16_t port,
839 			const struct net_sockaddr *addr)
840 {
841 	int ret;
842 
843 	ret = check_used_port(context, iface,
844 			      proto,
845 			      net_sin(addr)->sin_port,
846 			      addr,
847 			      net_context_is_reuseaddr_set(context),
848 			      net_context_is_reuseport_set(context),
849 			      true);
850 	if (ret != 0) {
851 		if (IS_ENABLED(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE) && ret == -ERANGE) {
852 			uint16_t re_port;
853 
854 			NET_DBG("Port %d is out of range, re-selecting!",
855 				net_ntohs(net_sin(addr)->sin_port));
856 			re_port = find_available_port(context, addr);
857 			if (re_port == 0U) {
858 				NET_ERR("No available port found (iface %d)",
859 					iface ? net_if_get_by_iface(iface) : 0);
860 				return -EADDRINUSE;
861 			}
862 
863 			net_sin_ptr(&context->local)->sin_port = re_port;
864 			net_sin(addr)->sin_port = re_port;
865 		} else {
866 			NET_ERR("Port %d is in use!", net_ntohs(net_sin(addr)->sin_port));
867 			NET_DBG("Interface %d (%p)",
868 				iface ? net_if_get_by_iface(iface) : 0, iface);
869 			return -EADDRINUSE;
870 		}
871 	} else {
872 		net_sin_ptr(&context->local)->sin_port = net_sin(addr)->sin_port;
873 	}
874 
875 	return 0;
876 }
877 
net_context_bind(struct net_context * context,const struct net_sockaddr * addr,net_socklen_t addrlen)878 int net_context_bind(struct net_context *context, const struct net_sockaddr *addr,
879 		     net_socklen_t addrlen)
880 {
881 	int ret;
882 
883 	NET_ASSERT(addr);
884 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
885 
886 	/* If we already have connection handler, then it effectively
887 	 * means that it's already bound to an interface/port, and we
888 	 * don't support rebinding connection to new address/port in
889 	 * the code below. Only applies for stream sockets.
890 	 * TODO: Support rebinding.
891 	 */
892 	if (net_context_get_type(context) == NET_SOCK_STREAM) {
893 		if (context->conn_handler != NULL) {
894 			return -EISCONN;
895 		}
896 	}
897 
898 	if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == NET_AF_INET6) {
899 		struct net_if *iface = NULL;
900 		struct net_in6_addr *ptr;
901 		struct net_sockaddr_in6 *addr6 = (struct net_sockaddr_in6 *)addr;
902 
903 		if (addrlen < sizeof(struct net_sockaddr_in6)) {
904 			return -EINVAL;
905 		}
906 
907 		if (net_context_is_bound_to_iface(context)) {
908 			iface = net_context_get_iface(context);
909 		}
910 
911 		if (net_ipv6_is_addr_mcast(&addr6->sin6_addr)) {
912 			struct net_if_mcast_addr *maddr;
913 
914 			if (IS_ENABLED(CONFIG_NET_UDP) &&
915 			    net_context_get_type(context) == NET_SOCK_DGRAM) {
916 				if (COND_CODE_1(CONFIG_NET_IPV6,
917 						(context->options.ipv6_mcast_ifindex > 0),
918 						(false))) {
919 					IF_ENABLED(CONFIG_NET_IPV6,
920 						   (iface = net_if_get_by_index(
921 							   context->options.ipv6_mcast_ifindex)));
922 				}
923 			}
924 
925 			maddr = net_if_ipv6_maddr_lookup(&addr6->sin6_addr,
926 							 &iface);
927 			if (!maddr) {
928 				return -ENOENT;
929 			}
930 
931 			ptr = &maddr->address.in6_addr;
932 
933 		} else if (net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
934 			if (iface == NULL) {
935 				iface = net_if_ipv6_select_src_iface(
936 					&net_sin6(&context->remote)->sin6_addr);
937 			}
938 
939 			ptr = (struct net_in6_addr *)net_ipv6_unspecified_address();
940 		} else {
941 			struct net_if_addr *ifaddr;
942 
943 			if (net_ipv6_is_ll_addr(&addr6->sin6_addr)) {
944 				if (iface == NULL) {
945 					iface = net_if_get_by_index(addr6->sin6_scope_id);
946 				}
947 			}
948 
949 			ifaddr = net_if_ipv6_addr_lookup(
950 					&addr6->sin6_addr,
951 					iface == NULL ? &iface : NULL);
952 			if (!ifaddr) {
953 				return -ENOENT;
954 			}
955 
956 			ptr = &ifaddr->address.in6_addr;
957 		}
958 
959 		if (!iface) {
960 			NET_ERR("Cannot bind to %s",
961 				net_sprint_ipv6_addr(&addr6->sin6_addr));
962 
963 			return -EADDRNOTAVAIL;
964 		}
965 
966 		k_mutex_lock(&context->lock, K_FOREVER);
967 
968 		net_context_set_iface(context, iface);
969 
970 		net_sin6_ptr(&context->local)->sin6_family = NET_AF_INET6;
971 		net_sin6_ptr(&context->local)->sin6_addr = ptr;
972 
973 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) {
974 			k_mutex_unlock(&context->lock);
975 			return net_offload_bind(iface, context, addr, addrlen);
976 		}
977 
978 		ret = 0;
979 		if (addr6->sin6_port) {
980 			ret = recheck_port(context, iface, context->proto,
981 					   addr6->sin6_port, addr);
982 			if (ret != 0) {
983 				goto unlock_ipv6;
984 			}
985 		} else {
986 			addr6->sin6_port =
987 				net_sin6_ptr(&context->local)->sin6_port;
988 
989 			if (IS_ENABLED(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)) {
990 				ret = recheck_port(context, iface, context->proto,
991 						   addr6->sin6_port, addr);
992 				if (ret != 0) {
993 					goto unlock_ipv6;
994 				}
995 			}
996 		}
997 
998 		NET_DBG("Context %p binding to %s [%s]:%d iface %d (%p)",
999 			context,
1000 			net_proto2str(NET_AF_INET6,
1001 				      net_context_get_proto(context)),
1002 			net_sprint_ipv6_addr(ptr),
1003 			net_ntohs(addr6->sin6_port),
1004 			net_if_get_by_iface(iface), iface);
1005 
1006 	unlock_ipv6:
1007 		k_mutex_unlock(&context->lock);
1008 
1009 		return ret;
1010 	}
1011 
1012 	if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == NET_AF_INET) {
1013 		struct net_sockaddr_in *addr4 = (struct net_sockaddr_in *)addr;
1014 		struct net_if *iface = NULL;
1015 		struct net_if_addr *ifaddr;
1016 		struct net_in_addr *ptr;
1017 
1018 		if (addrlen < sizeof(struct net_sockaddr_in)) {
1019 			return -EINVAL;
1020 		}
1021 
1022 		if (net_context_is_bound_to_iface(context)) {
1023 			iface = net_context_get_iface(context);
1024 		}
1025 
1026 		if (net_ipv4_is_addr_mcast(&addr4->sin_addr)) {
1027 			struct net_if_mcast_addr *maddr;
1028 
1029 			if (IS_ENABLED(CONFIG_NET_UDP) &&
1030 			    net_context_get_type(context) == NET_SOCK_DGRAM) {
1031 				if (COND_CODE_1(CONFIG_NET_IPV4,
1032 						(context->options.ipv4_mcast_ifindex > 0),
1033 						(false))) {
1034 					IF_ENABLED(CONFIG_NET_IPV4,
1035 						   (iface = net_if_get_by_index(
1036 							   context->options.ipv4_mcast_ifindex)));
1037 				}
1038 			}
1039 
1040 			maddr = net_if_ipv4_maddr_lookup(&addr4->sin_addr,
1041 							 &iface);
1042 			if (!maddr) {
1043 				return -ENOENT;
1044 			}
1045 
1046 			ptr = &maddr->address.in_addr;
1047 
1048 		} else if (UNALIGNED_GET(&addr4->sin_addr.s_addr) == NET_INADDR_ANY) {
1049 			if (iface == NULL) {
1050 				iface = net_if_ipv4_select_src_iface(
1051 					&net_sin(&context->remote)->sin_addr);
1052 			}
1053 
1054 			ptr = (struct net_in_addr *)net_ipv4_unspecified_address();
1055 		} else {
1056 			ifaddr = net_if_ipv4_addr_lookup(
1057 					&addr4->sin_addr,
1058 					iface == NULL ? &iface : NULL);
1059 			if (!ifaddr) {
1060 				return -ENOENT;
1061 			}
1062 
1063 			ptr = &ifaddr->address.in_addr;
1064 		}
1065 
1066 		if (!iface) {
1067 			NET_ERR("Cannot bind to %s",
1068 				net_sprint_ipv4_addr(&addr4->sin_addr));
1069 
1070 			return -EADDRNOTAVAIL;
1071 		}
1072 
1073 		k_mutex_lock(&context->lock, K_FOREVER);
1074 
1075 		net_context_set_iface(context, iface);
1076 
1077 		net_sin_ptr(&context->local)->sin_family = NET_AF_INET;
1078 		net_sin_ptr(&context->local)->sin_addr = ptr;
1079 
1080 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) {
1081 			k_mutex_unlock(&context->lock);
1082 			return net_offload_bind(iface, context, addr, addrlen);
1083 		}
1084 
1085 		ret = 0;
1086 		if (addr4->sin_port) {
1087 			ret = recheck_port(context, iface, context->proto,
1088 					   addr4->sin_port, addr);
1089 			if (ret != 0) {
1090 				goto unlock_ipv4;
1091 			}
1092 		} else {
1093 			addr4->sin_port =
1094 				net_sin_ptr(&context->local)->sin_port;
1095 
1096 			if (IS_ENABLED(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)) {
1097 				ret = recheck_port(context, iface, context->proto,
1098 						   addr4->sin_port, addr);
1099 				if (ret != 0) {
1100 					goto unlock_ipv4;
1101 				}
1102 			}
1103 		}
1104 
1105 		NET_DBG("Context %p binding to %s %s:%d iface %d (%p)",
1106 			context,
1107 			net_proto2str(NET_AF_INET,
1108 				      net_context_get_proto(context)),
1109 			net_sprint_ipv4_addr(ptr),
1110 			net_ntohs(addr4->sin_port),
1111 			net_if_get_by_iface(iface), iface);
1112 
1113 	unlock_ipv4:
1114 		k_mutex_unlock(&context->lock);
1115 
1116 		return ret;
1117 	}
1118 
1119 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
1120 	    addr->sa_family == NET_AF_PACKET) {
1121 		struct net_sockaddr_ll *ll_addr = (struct net_sockaddr_ll *)addr;
1122 		struct net_if *iface = NULL;
1123 
1124 		if (addrlen < sizeof(struct net_sockaddr_ll)) {
1125 			return -EINVAL;
1126 		}
1127 
1128 		if (ll_addr->sll_ifindex < 0) {
1129 			return -EINVAL;
1130 		}
1131 
1132 		iface = net_if_get_by_index(ll_addr->sll_ifindex);
1133 
1134 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) && iface != NULL &&
1135 		    net_if_is_ip_offloaded(iface)) {
1136 			net_context_set_iface(context, iface);
1137 
1138 			return net_offload_bind(iface,
1139 						context,
1140 						addr,
1141 						addrlen);
1142 		}
1143 
1144 		k_mutex_lock(&context->lock, K_FOREVER);
1145 
1146 		net_sll_ptr(&context->local)->sll_family = NET_AF_PACKET;
1147 		net_sll_ptr(&context->local)->sll_ifindex =
1148 			ll_addr->sll_ifindex;
1149 		net_sll_ptr(&context->local)->sll_protocol =
1150 			ll_addr->sll_protocol;
1151 
1152 		if (iface != NULL) {
1153 			net_context_set_iface(context, iface);
1154 
1155 			net_if_lock(iface);
1156 			net_sll_ptr(&context->local)->sll_addr =
1157 				net_if_get_link_addr(iface)->addr;
1158 			net_sll_ptr(&context->local)->sll_halen =
1159 				net_if_get_link_addr(iface)->len;
1160 			net_if_unlock(iface);
1161 		}
1162 
1163 		NET_DBG("Context %p bind to type 0x%04x iface[%d] %p addr %s",
1164 			context, net_htons(net_context_get_proto(context)),
1165 			ll_addr->sll_ifindex, iface,
1166 			net_sprint_ll_addr(
1167 				net_sll_ptr(&context->local)->sll_addr,
1168 				net_sll_ptr(&context->local)->sll_halen));
1169 
1170 		k_mutex_unlock(&context->lock);
1171 
1172 		return 0;
1173 	}
1174 
1175 	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && addr->sa_family == NET_AF_CAN) {
1176 		struct net_sockaddr_can *can_addr = (struct net_sockaddr_can *)addr;
1177 		struct net_if *iface = NULL;
1178 
1179 		if (addrlen < sizeof(struct net_sockaddr_can)) {
1180 			return -EINVAL;
1181 		}
1182 
1183 		if (can_addr->can_ifindex < 0) {
1184 			return -EINVAL;
1185 		}
1186 
1187 		iface = net_if_get_by_index(can_addr->can_ifindex);
1188 		if (!iface) {
1189 			NET_ERR("Cannot bind to interface index %d",
1190 				can_addr->can_ifindex);
1191 			return -EADDRNOTAVAIL;
1192 		}
1193 
1194 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1195 		    net_if_is_ip_offloaded(iface)) {
1196 			net_context_set_iface(context, iface);
1197 
1198 			return net_offload_bind(iface,
1199 						context,
1200 						addr,
1201 						addrlen);
1202 		}
1203 
1204 		k_mutex_lock(&context->lock, K_FOREVER);
1205 
1206 		net_context_set_iface(context, iface);
1207 		net_context_set_family(context, NET_AF_CAN);
1208 
1209 		net_can_ptr(&context->local)->can_family = NET_AF_CAN;
1210 		net_can_ptr(&context->local)->can_ifindex =
1211 			can_addr->can_ifindex;
1212 
1213 		NET_DBG("Context %p binding to %d iface[%d] %p",
1214 			context, net_context_get_proto(context),
1215 			can_addr->can_ifindex, iface);
1216 
1217 		k_mutex_unlock(&context->lock);
1218 
1219 		return 0;
1220 	}
1221 
1222 	return -EINVAL;
1223 }
1224 
find_context(void * conn_handler)1225 static inline struct net_context *find_context(void *conn_handler)
1226 {
1227 	int i;
1228 
1229 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
1230 		if (!net_context_is_used(&contexts[i])) {
1231 			continue;
1232 		}
1233 
1234 		if (contexts[i].conn_handler == conn_handler) {
1235 			return &contexts[i];
1236 		}
1237 	}
1238 
1239 	return NULL;
1240 }
1241 
net_context_listen(struct net_context * context,int backlog)1242 int net_context_listen(struct net_context *context, int backlog)
1243 {
1244 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
1245 
1246 	if (!net_context_is_used(context)) {
1247 		return -EBADF;
1248 	}
1249 
1250 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1251 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
1252 		return net_offload_listen(net_context_get_iface(context),
1253 					  context, backlog);
1254 	}
1255 
1256 	k_mutex_lock(&context->lock, K_FOREVER);
1257 
1258 	if (net_tcp_listen(context, backlog) >= 0) {
1259 		k_mutex_unlock(&context->lock);
1260 		return 0;
1261 	}
1262 
1263 	k_mutex_unlock(&context->lock);
1264 
1265 	return -EOPNOTSUPP;
1266 }
1267 
1268 #if defined(CONFIG_NET_IPV4)
net_context_create_ipv4_new(struct net_context * context,struct net_pkt * pkt,const struct net_in_addr * src,const struct net_in_addr * dst)1269 int net_context_create_ipv4_new(struct net_context *context,
1270 				struct net_pkt *pkt,
1271 				const struct net_in_addr *src,
1272 				const struct net_in_addr *dst)
1273 {
1274 	if (!src) {
1275 		NET_ASSERT(((
1276 			struct net_sockaddr_in_ptr *)&context->local)->sin_addr);
1277 
1278 		src = ((struct net_sockaddr_in_ptr *)&context->local)->sin_addr;
1279 	}
1280 
1281 	if (net_ipv4_is_addr_unspecified(src)
1282 	    || net_ipv4_is_addr_mcast(src)) {
1283 		src = net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
1284 						  (struct net_in_addr *)dst);
1285 		/* If src address is still unspecified, do not create pkt */
1286 		if (net_ipv4_is_addr_unspecified(src)) {
1287 			NET_WARN("DROP: src addr is unspecified");
1288 			return -EINVAL;
1289 		}
1290 	}
1291 
1292 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
1293 	net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(context->options.dscp_ecn));
1294 	net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(context->options.dscp_ecn));
1295 	/* Direct priority takes precedence over DSCP */
1296 	if (!IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
1297 		net_pkt_set_priority(pkt, net_ipv4_dscp_to_priority(
1298 			net_ipv4_get_dscp(context->options.dscp_ecn)));
1299 	}
1300 #endif
1301 
1302 	if (IS_ENABLED(CONFIG_NET_IPV4_PMTU)) {
1303 		struct net_pmtu_entry *entry;
1304 		struct net_sockaddr_in dst_addr = {
1305 			.sin_family = NET_AF_INET,
1306 			.sin_addr = *dst,
1307 		};
1308 
1309 		entry = net_pmtu_get_entry((struct net_sockaddr *)&dst_addr);
1310 		if (entry == NULL) {
1311 			/* Try to figure out the MTU of the path */
1312 			net_pkt_set_ipv4_pmtu(pkt, true);
1313 		} else {
1314 			net_pkt_set_ipv4_pmtu(pkt, false);
1315 		}
1316 	}
1317 
1318 	return net_ipv4_create(pkt, src, dst);
1319 }
1320 #endif /* CONFIG_NET_IPV4 */
1321 
1322 #if defined(CONFIG_NET_IPV6)
net_context_create_ipv6_new(struct net_context * context,struct net_pkt * pkt,const struct net_in6_addr * src,const struct net_in6_addr * dst)1323 int net_context_create_ipv6_new(struct net_context *context,
1324 				struct net_pkt *pkt,
1325 				const struct net_in6_addr *src,
1326 				const struct net_in6_addr *dst)
1327 {
1328 	if (!src) {
1329 		NET_ASSERT(((
1330 			struct net_sockaddr_in6_ptr *)&context->local)->sin6_addr);
1331 
1332 		src = ((struct net_sockaddr_in6_ptr *)&context->local)->sin6_addr;
1333 	}
1334 
1335 	if (net_ipv6_is_addr_unspecified(src) || net_ipv6_is_addr_mcast(src)) {
1336 		src = net_if_ipv6_select_src_addr_hint(net_pkt_iface(pkt),
1337 						       (struct net_in6_addr *)dst,
1338 						       context->options.addr_preferences);
1339 	}
1340 
1341 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
1342 	net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(context->options.dscp_ecn));
1343 	net_pkt_set_ip_ecn(pkt, net_ipv6_get_ecn(context->options.dscp_ecn));
1344 	/* Direct priority takes precedence over DSCP */
1345 	if (!IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
1346 		net_pkt_set_priority(pkt, net_ipv6_dscp_to_priority(
1347 			net_ipv6_get_dscp(context->options.dscp_ecn)));
1348 	}
1349 #endif
1350 
1351 	return net_ipv6_create(pkt, src, dst);
1352 }
1353 #endif /* CONFIG_NET_IPV6 */
1354 
net_context_connect(struct net_context * context,const struct net_sockaddr * addr,net_socklen_t addrlen,net_context_connect_cb_t cb,k_timeout_t timeout,void * user_data)1355 int net_context_connect(struct net_context *context,
1356 			const struct net_sockaddr *addr,
1357 			net_socklen_t addrlen,
1358 			net_context_connect_cb_t cb,
1359 			k_timeout_t timeout,
1360 			void *user_data)
1361 {
1362 	struct net_sockaddr *laddr = NULL;
1363 	struct net_sockaddr local_addr __unused;
1364 	uint16_t lport, rport;
1365 	int ret;
1366 
1367 	NET_ASSERT(addr);
1368 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
1369 
1370 	k_mutex_lock(&context->lock, K_FOREVER);
1371 
1372 	if (net_context_get_state(context) == NET_CONTEXT_CONNECTING) {
1373 		ret = -EALREADY;
1374 		goto unlock;
1375 	}
1376 
1377 	if (!net_context_is_used(context)) {
1378 		ret = -EBADF;
1379 		goto unlock;
1380 	}
1381 
1382 	/* As per POSIX, for non-connection-mode sockets:
1383 	 * "If the sa_family member of address is NET_AF_UNSPEC, the socket's peer
1384 	 *  address shall be reset.""
1385 	 */
1386 	if (IS_ENABLED(CONFIG_NET_UDP) && addr->sa_family == NET_AF_UNSPEC &&
1387 	    net_context_get_type(context) == NET_SOCK_DGRAM) {
1388 		context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
1389 		memset(&context->remote, 0, sizeof(context->remote));
1390 		ret = 0;
1391 		goto unlock;
1392 	}
1393 
1394 	if (addr->sa_family != net_context_get_family(context)) {
1395 		NET_ERR("Address family %d does not match network context family %d",
1396 			addr->sa_family, net_context_get_family(context));
1397 		ret = -EINVAL;
1398 		goto unlock;
1399 	}
1400 
1401 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
1402 	    addr->sa_family == NET_AF_PACKET) {
1403 		ret = -EOPNOTSUPP;
1404 		goto unlock;
1405 	}
1406 
1407 	if (net_context_get_state(context) == NET_CONTEXT_LISTENING) {
1408 		ret = -EOPNOTSUPP;
1409 		goto unlock;
1410 	}
1411 
1412 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
1413 	    net_context_get_family(context) == NET_AF_INET6) {
1414 		struct net_sockaddr_in6 *addr6 = (struct net_sockaddr_in6 *)
1415 							&context->remote;
1416 
1417 		if (addrlen < sizeof(struct net_sockaddr_in6)) {
1418 			ret = -EINVAL;
1419 			goto unlock;
1420 		}
1421 
1422 		if (net_context_get_proto(context) == NET_IPPROTO_TCP &&
1423 		    net_ipv6_is_addr_mcast(&addr6->sin6_addr)) {
1424 			ret = -EADDRNOTAVAIL;
1425 			goto unlock;
1426 		}
1427 
1428 		memcpy(&addr6->sin6_addr, &net_sin6(addr)->sin6_addr,
1429 		       sizeof(struct net_in6_addr));
1430 
1431 		addr6->sin6_port = net_sin6(addr)->sin6_port;
1432 		addr6->sin6_family = NET_AF_INET6;
1433 
1434 		if (!net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
1435 			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
1436 		} else {
1437 			context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
1438 		}
1439 
1440 		rport = addr6->sin6_port;
1441 
1442 		/* The binding must be done after we have set the remote
1443 		 * address but before checking the local address. Otherwise
1444 		 * the laddr might not be set properly which would then cause
1445 		 * issues when doing net_tcp_connect(). This issue was seen
1446 		 * with socket tests and when connecting to loopback interface.
1447 		 */
1448 		ret = bind_default(context);
1449 		if (ret) {
1450 			goto unlock;
1451 		}
1452 
1453 		net_sin6_ptr(&context->local)->sin6_family = NET_AF_INET6;
1454 		net_sin6(&local_addr)->sin6_family = NET_AF_INET6;
1455 		net_sin6(&local_addr)->sin6_port = lport =
1456 			net_sin6((struct net_sockaddr *)&context->local)->sin6_port;
1457 
1458 		if (net_sin6_ptr(&context->local)->sin6_addr) {
1459 			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
1460 				     net_sin6_ptr(&context->local)->sin6_addr);
1461 
1462 			laddr = &local_addr;
1463 		}
1464 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
1465 		   net_context_get_family(context) == NET_AF_INET) {
1466 		struct net_sockaddr_in *addr4 = (struct net_sockaddr_in *)
1467 							&context->remote;
1468 
1469 		if (addrlen < sizeof(struct net_sockaddr_in)) {
1470 			ret = -EINVAL;
1471 			goto unlock;
1472 		}
1473 
1474 		if (net_context_get_proto(context) == NET_IPPROTO_TCP &&
1475 		    (net_ipv4_is_addr_mcast(&addr4->sin_addr) ||
1476 		     net_ipv4_is_addr_bcast(net_context_get_iface(context),
1477 					    &addr4->sin_addr))) {
1478 			ret = -EADDRNOTAVAIL;
1479 			goto unlock;
1480 		}
1481 
1482 		memcpy(&addr4->sin_addr, &net_sin(addr)->sin_addr,
1483 		       sizeof(struct net_in_addr));
1484 
1485 		addr4->sin_port = net_sin(addr)->sin_port;
1486 		addr4->sin_family = NET_AF_INET;
1487 
1488 		if (addr4->sin_addr.s_addr) {
1489 			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
1490 		} else {
1491 			context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
1492 		}
1493 
1494 		rport = addr4->sin_port;
1495 
1496 		ret = bind_default(context);
1497 		if (ret) {
1498 			goto unlock;
1499 		}
1500 
1501 		net_sin_ptr(&context->local)->sin_family = NET_AF_INET;
1502 		net_sin(&local_addr)->sin_family = NET_AF_INET;
1503 		net_sin(&local_addr)->sin_port = lport =
1504 			net_sin((struct net_sockaddr *)&context->local)->sin_port;
1505 
1506 		if (net_sin_ptr(&context->local)->sin_addr) {
1507 			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
1508 				       net_sin_ptr(&context->local)->sin_addr);
1509 
1510 			laddr = &local_addr;
1511 		}
1512 	} else {
1513 		ret = -EINVAL; /* Not IPv4 or IPv6 */
1514 		goto unlock;
1515 	}
1516 
1517 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1518 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
1519 		ret = net_offload_connect(
1520 			net_context_get_iface(context),
1521 			context,
1522 			addr,
1523 			addrlen,
1524 			cb,
1525 			timeout,
1526 			user_data);
1527 		goto unlock;
1528 	}
1529 
1530 	if (IS_ENABLED(CONFIG_NET_UDP) &&
1531 	    net_context_get_type(context) == NET_SOCK_DGRAM) {
1532 		if (cb) {
1533 			cb(context, 0, user_data);
1534 		}
1535 
1536 		ret = 0;
1537 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
1538 		   net_context_get_type(context) == NET_SOCK_STREAM) {
1539 		NET_ASSERT(laddr != NULL);
1540 
1541 		ret = net_tcp_connect(context, addr, laddr, rport, lport,
1542 				      timeout, cb, user_data);
1543 	} else {
1544 		ret = -ENOTSUP;
1545 	}
1546 
1547 unlock:
1548 	k_mutex_unlock(&context->lock);
1549 
1550 	return ret;
1551 }
1552 
net_context_accept(struct net_context * context,net_tcp_accept_cb_t cb,k_timeout_t timeout,void * user_data)1553 int net_context_accept(struct net_context *context,
1554 		       net_tcp_accept_cb_t cb,
1555 		       k_timeout_t timeout,
1556 		       void *user_data)
1557 {
1558 	int ret = 0;
1559 
1560 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
1561 
1562 	if (!net_context_is_used(context)) {
1563 		return -EBADF;
1564 	}
1565 
1566 	k_mutex_lock(&context->lock, K_FOREVER);
1567 
1568 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1569 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
1570 		ret = net_offload_accept(
1571 			net_context_get_iface(context),
1572 			context,
1573 			cb,
1574 			timeout,
1575 			user_data);
1576 		goto unlock;
1577 	}
1578 
1579 	if ((net_context_get_state(context) != NET_CONTEXT_LISTENING) &&
1580 	    (net_context_get_type(context) != NET_SOCK_STREAM)) {
1581 		NET_DBG("Invalid socket, state %d type %d",
1582 			net_context_get_state(context),
1583 			net_context_get_type(context));
1584 		ret = -EINVAL;
1585 		goto unlock;
1586 	}
1587 
1588 	if (net_context_get_proto(context) == NET_IPPROTO_TCP) {
1589 		ret = net_tcp_accept(context, cb, user_data);
1590 		goto unlock;
1591 	}
1592 
1593 unlock:
1594 	k_mutex_unlock(&context->lock);
1595 
1596 	return ret;
1597 }
1598 
get_bool_option(bool option,int * value,uint32_t * len)1599 __maybe_unused static int get_bool_option(bool option, int *value, uint32_t *len)
1600 {
1601 	if (value == NULL) {
1602 		return -EINVAL;
1603 	}
1604 
1605 	if (len != NULL) {
1606 		if (*len != sizeof(int)) {
1607 			return -EINVAL;
1608 		}
1609 
1610 		*len = sizeof(int);
1611 	}
1612 
1613 	*((int *)value) = (int)option;
1614 
1615 	return 0;
1616 }
1617 
get_uint8_option(uint8_t option,uint8_t * value,uint32_t * len)1618 __maybe_unused static int get_uint8_option(uint8_t option, uint8_t *value, uint32_t *len)
1619 {
1620 	if (value == NULL) {
1621 		return -EINVAL;
1622 	}
1623 
1624 	*value = option;
1625 
1626 	if (len != NULL) {
1627 		*len = sizeof(uint8_t);
1628 	}
1629 
1630 	return 0;
1631 }
1632 
get_uint16_option(uint16_t option,int * value,uint32_t * len)1633 __maybe_unused static int get_uint16_option(uint16_t option, int *value, uint32_t *len)
1634 {
1635 	if (value == NULL) {
1636 		return -EINVAL;
1637 	}
1638 
1639 	*value = option;
1640 
1641 	if (len != NULL) {
1642 		*len = sizeof(int);
1643 	}
1644 
1645 	return 0;
1646 }
1647 
get_context_priority(struct net_context * context,void * value,uint32_t * len)1648 static int get_context_priority(struct net_context *context,
1649 				void *value, uint32_t *len)
1650 {
1651 #if defined(CONFIG_NET_CONTEXT_PRIORITY)
1652 	return get_uint8_option(context->options.priority,
1653 				value, len);
1654 #else
1655 	ARG_UNUSED(context);
1656 	ARG_UNUSED(value);
1657 	ARG_UNUSED(len);
1658 
1659 	return -ENOTSUP;
1660 #endif
1661 }
1662 
get_context_proxy(struct net_context * context,void * value,uint32_t * len)1663 static int get_context_proxy(struct net_context *context,
1664 			     void *value, uint32_t *len)
1665 {
1666 #if defined(CONFIG_SOCKS)
1667 	struct net_sockaddr *addr = (struct net_sockaddr *)value;
1668 
1669 	if (!value || !len) {
1670 		return -EINVAL;
1671 	}
1672 
1673 	if (*len < context->options.proxy.addrlen) {
1674 		return -EINVAL;
1675 	}
1676 
1677 	*len = MIN(context->options.proxy.addrlen, *len);
1678 
1679 	memcpy(addr, &context->options.proxy.addr, *len);
1680 
1681 	return 0;
1682 #else
1683 	ARG_UNUSED(context);
1684 	ARG_UNUSED(value);
1685 	ARG_UNUSED(len);
1686 
1687 	return -ENOTSUP;
1688 #endif
1689 }
1690 
get_context_txtime(struct net_context * context,void * value,uint32_t * len)1691 static int get_context_txtime(struct net_context *context,
1692 			      void *value, uint32_t *len)
1693 {
1694 #if defined(CONFIG_NET_CONTEXT_TXTIME)
1695 	return get_bool_option(context->options.txtime,
1696 			       value, len);
1697 #else
1698 	ARG_UNUSED(context);
1699 	ARG_UNUSED(value);
1700 	ARG_UNUSED(len);
1701 
1702 	return -ENOTSUP;
1703 #endif
1704 }
1705 
get_context_rcvtimeo(struct net_context * context,void * value,uint32_t * len)1706 static int get_context_rcvtimeo(struct net_context *context,
1707 				void *value, uint32_t *len)
1708 {
1709 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
1710 	*((k_timeout_t *)value) = context->options.rcvtimeo;
1711 
1712 	if (len) {
1713 		*len = sizeof(k_timeout_t);
1714 	}
1715 
1716 	return 0;
1717 #else
1718 	ARG_UNUSED(context);
1719 	ARG_UNUSED(value);
1720 	ARG_UNUSED(len);
1721 
1722 	return -ENOTSUP;
1723 #endif
1724 }
1725 
get_context_sndtimeo(struct net_context * context,void * value,uint32_t * len)1726 static int get_context_sndtimeo(struct net_context *context,
1727 				void *value, uint32_t *len)
1728 {
1729 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
1730 	*((k_timeout_t *)value) = context->options.sndtimeo;
1731 
1732 	if (len) {
1733 		*len = sizeof(k_timeout_t);
1734 	}
1735 
1736 	return 0;
1737 #else
1738 	ARG_UNUSED(context);
1739 	ARG_UNUSED(value);
1740 	ARG_UNUSED(len);
1741 
1742 	return -ENOTSUP;
1743 #endif
1744 }
1745 
get_context_rcvbuf(struct net_context * context,void * value,uint32_t * len)1746 static int get_context_rcvbuf(struct net_context *context,
1747 			      void *value, uint32_t *len)
1748 {
1749 #if defined(CONFIG_NET_CONTEXT_RCVBUF)
1750 	return get_uint16_option(context->options.rcvbuf,
1751 				 value, len);
1752 #else
1753 	ARG_UNUSED(context);
1754 	ARG_UNUSED(value);
1755 	ARG_UNUSED(len);
1756 
1757 	return -ENOTSUP;
1758 #endif
1759 }
1760 
get_context_sndbuf(struct net_context * context,void * value,uint32_t * len)1761 static int get_context_sndbuf(struct net_context *context,
1762 				void *value, uint32_t *len)
1763 {
1764 #if defined(CONFIG_NET_CONTEXT_SNDBUF)
1765 	return get_uint16_option(context->options.sndbuf,
1766 				 value, len);
1767 #else
1768 	ARG_UNUSED(context);
1769 	ARG_UNUSED(value);
1770 	ARG_UNUSED(len);
1771 
1772 	return -ENOTSUP;
1773 #endif
1774 }
1775 
get_context_dscp_ecn(struct net_context * context,void * value,uint32_t * len)1776 static int get_context_dscp_ecn(struct net_context *context,
1777 				void *value, uint32_t *len)
1778 {
1779 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
1780 	return get_uint8_option(context->options.dscp_ecn,
1781 				value, len);
1782 #else
1783 	ARG_UNUSED(context);
1784 	ARG_UNUSED(value);
1785 	ARG_UNUSED(len);
1786 
1787 	return -ENOTSUP;
1788 #endif
1789 }
1790 
get_context_ttl(struct net_context * context,void * value,uint32_t * len)1791 static int get_context_ttl(struct net_context *context,
1792 				 void *value, uint32_t *len)
1793 {
1794 #if defined(CONFIG_NET_IPV4)
1795 	*((int *)value) = context->ipv4_ttl;
1796 
1797 	if (len) {
1798 		*len = sizeof(int);
1799 	}
1800 
1801 	return 0;
1802 #else
1803 	ARG_UNUSED(context);
1804 	ARG_UNUSED(value);
1805 	ARG_UNUSED(len);
1806 
1807 	return -ENOTSUP;
1808 #endif
1809 }
1810 
get_context_mcast_ttl(struct net_context * context,void * value,uint32_t * len)1811 static int get_context_mcast_ttl(struct net_context *context,
1812 				 void *value, uint32_t *len)
1813 {
1814 #if defined(CONFIG_NET_IPV4)
1815 	*((int *)value) = context->ipv4_mcast_ttl;
1816 
1817 	if (len) {
1818 		*len = sizeof(int);
1819 	}
1820 
1821 	return 0;
1822 #else
1823 	ARG_UNUSED(context);
1824 	ARG_UNUSED(value);
1825 	ARG_UNUSED(len);
1826 
1827 	return -ENOTSUP;
1828 #endif
1829 }
1830 
get_context_ipv4_mcast_loop(struct net_context * context,void * value,uint32_t * len)1831 static int get_context_ipv4_mcast_loop(struct net_context *context,
1832 				  void *value, uint32_t *len)
1833 {
1834 #if defined(CONFIG_NET_IPV4)
1835 	return get_bool_option(context->options.ipv4_mcast_loop, value, len);
1836 #else
1837 	ARG_UNUSED(context);
1838 	ARG_UNUSED(value);
1839 	ARG_UNUSED(len);
1840 	return -ENOTSUP;
1841 #endif
1842 }
1843 
get_context_mcast_hop_limit(struct net_context * context,void * value,uint32_t * len)1844 static int get_context_mcast_hop_limit(struct net_context *context,
1845 				       void *value, uint32_t *len)
1846 {
1847 #if defined(CONFIG_NET_IPV6)
1848 	*((int *)value) = context->ipv6_mcast_hop_limit;
1849 
1850 	if (len) {
1851 		*len = sizeof(int);
1852 	}
1853 
1854 	return 0;
1855 #else
1856 	ARG_UNUSED(context);
1857 	ARG_UNUSED(value);
1858 	ARG_UNUSED(len);
1859 
1860 	return -ENOTSUP;
1861 #endif
1862 }
1863 
get_context_unicast_hop_limit(struct net_context * context,void * value,uint32_t * len)1864 static int get_context_unicast_hop_limit(struct net_context *context,
1865 					 void *value, uint32_t *len)
1866 {
1867 #if defined(CONFIG_NET_IPV6)
1868 	*((int *)value) = context->ipv6_hop_limit;
1869 
1870 	if (len) {
1871 		*len = sizeof(int);
1872 	}
1873 
1874 	return 0;
1875 #else
1876 	ARG_UNUSED(context);
1877 	ARG_UNUSED(value);
1878 	ARG_UNUSED(len);
1879 
1880 	return -ENOTSUP;
1881 #endif
1882 }
1883 
get_context_reuseaddr(struct net_context * context,void * value,uint32_t * len)1884 static int get_context_reuseaddr(struct net_context *context,
1885 				 void *value, uint32_t *len)
1886 {
1887 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
1888 	return get_bool_option(context->options.reuseaddr,
1889 			       value, len);
1890 #else
1891 	ARG_UNUSED(context);
1892 	ARG_UNUSED(value);
1893 	ARG_UNUSED(len);
1894 
1895 	return -ENOTSUP;
1896 #endif
1897 }
1898 
get_context_reuseport(struct net_context * context,void * value,uint32_t * len)1899 static int get_context_reuseport(struct net_context *context,
1900 				void *value, uint32_t *len)
1901 {
1902 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
1903 	return get_bool_option(context->options.reuseport,
1904 			       value, len);
1905 #else
1906 	ARG_UNUSED(context);
1907 	ARG_UNUSED(value);
1908 	ARG_UNUSED(len);
1909 
1910 	return -ENOTSUP;
1911 #endif
1912 }
1913 
get_context_ipv6_v6only(struct net_context * context,void * value,uint32_t * len)1914 static int get_context_ipv6_v6only(struct net_context *context,
1915 				   void *value, uint32_t *len)
1916 {
1917 #if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
1918 	return get_bool_option(context->options.ipv6_v6only,
1919 			       value, len);
1920 #else
1921 	ARG_UNUSED(context);
1922 	ARG_UNUSED(value);
1923 	ARG_UNUSED(len);
1924 
1925 	return -ENOTSUP;
1926 #endif
1927 }
1928 
get_context_recv_pktinfo(struct net_context * context,void * value,uint32_t * len)1929 static int get_context_recv_pktinfo(struct net_context *context,
1930 				    void *value, uint32_t *len)
1931 {
1932 #if defined(CONFIG_NET_CONTEXT_RECV_PKTINFO)
1933 	return get_bool_option(context->options.recv_pktinfo,
1934 			       value, len);
1935 #else
1936 	ARG_UNUSED(context);
1937 	ARG_UNUSED(value);
1938 	ARG_UNUSED(len);
1939 
1940 	return -ENOTSUP;
1941 #endif
1942 }
1943 
get_context_recv_hoplimit(struct net_context * context,void * value,uint32_t * len)1944 static int get_context_recv_hoplimit(struct net_context *context,
1945 				    void *value, uint32_t *len)
1946 {
1947 #if defined(CONFIG_NET_CONTEXT_RECV_HOPLIMIT)
1948 	return get_bool_option(context->options.recv_hoplimit,
1949 			       value, len);
1950 #else
1951 	ARG_UNUSED(context);
1952 	ARG_UNUSED(value);
1953 	ARG_UNUSED(len);
1954 
1955 	return -ENOTSUP;
1956 #endif
1957 }
1958 
get_context_addr_preferences(struct net_context * context,void * value,uint32_t * len)1959 static int get_context_addr_preferences(struct net_context *context,
1960 					void *value, uint32_t *len)
1961 {
1962 #if defined(CONFIG_NET_IPV6)
1963 	return get_uint16_option(context->options.addr_preferences,
1964 				 value, len);
1965 #else
1966 	ARG_UNUSED(context);
1967 	ARG_UNUSED(value);
1968 	ARG_UNUSED(len);
1969 
1970 	return -ENOTSUP;
1971 #endif
1972 }
1973 
get_context_timestamping(struct net_context * context,void * value,uint32_t * len)1974 static int get_context_timestamping(struct net_context *context,
1975 				    void *value, uint32_t *len)
1976 {
1977 #if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
1978 	*((uint8_t *)value) = context->options.timestamping;
1979 
1980 	if (len) {
1981 		*len = sizeof(uint8_t);
1982 	}
1983 
1984 	return 0;
1985 #else
1986 	ARG_UNUSED(context);
1987 	ARG_UNUSED(value);
1988 	ARG_UNUSED(len);
1989 
1990 	return -ENOTSUP;
1991 #endif
1992 }
1993 
get_context_mtu(struct net_context * context,void * value,uint32_t * len)1994 static int get_context_mtu(struct net_context *context,
1995 			   void *value, uint32_t *len)
1996 {
1997 	net_sa_family_t family = net_context_get_family(context);
1998 	struct net_if *iface = NULL;
1999 	int mtu;
2000 
2001 	if (IS_ENABLED(CONFIG_NET_PMTU)) {
2002 		mtu = net_pmtu_get_mtu(&context->remote);
2003 		if (mtu > 0) {
2004 			goto out;
2005 		}
2006 	}
2007 
2008 	if (net_context_is_bound_to_iface(context)) {
2009 		iface = net_context_get_iface(context);
2010 
2011 		mtu = net_if_get_mtu(iface);
2012 	} else {
2013 		if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
2014 			iface = net_if_ipv6_select_src_iface(
2015 				&net_sin6(&context->remote)->sin6_addr);
2016 		} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
2017 			iface = net_if_ipv4_select_src_iface(
2018 				&net_sin(&context->remote)->sin_addr);
2019 		} else {
2020 			return -EAFNOSUPPORT;
2021 		}
2022 
2023 		mtu = net_if_get_mtu(iface);
2024 	}
2025 
2026 out:
2027 	*((int *)value) = mtu;
2028 
2029 	if (len) {
2030 		*len = sizeof(int);
2031 	}
2032 
2033 	return 0;
2034 }
2035 
get_context_mcast_ifindex(struct net_context * context,void * value,uint32_t * len)2036 static int get_context_mcast_ifindex(struct net_context *context,
2037 				     void *value, uint32_t *len)
2038 {
2039 #if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
2040 	net_sa_family_t family = net_context_get_family(context);
2041 
2042 	if ((IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) ||
2043 	    (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET)) {
2044 		/* If user has not set the ifindex, then get the interface
2045 		 * that this socket is bound to.
2046 		 */
2047 		if (context->options.ipv6_mcast_ifindex == 0) {
2048 			struct net_if *iface;
2049 			int ifindex;
2050 
2051 			if (net_context_is_bound_to_iface(context)) {
2052 				iface = net_context_get_iface(context);
2053 			} else {
2054 				iface = net_if_get_default();
2055 			}
2056 
2057 			if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
2058 				if (!net_if_flag_is_set(iface, NET_IF_IPV6)) {
2059 					return -EPROTOTYPE;
2060 				}
2061 			} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
2062 				if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
2063 					return -EPROTOTYPE;
2064 				}
2065 			}
2066 
2067 			ifindex = net_if_get_by_iface(iface);
2068 			if (ifindex < 1) {
2069 				return -ENOENT;
2070 			}
2071 
2072 			*((int *)value) = ifindex;
2073 		} else {
2074 			*((int *)value) = context->options.ipv6_mcast_ifindex;
2075 		}
2076 
2077 		if (len) {
2078 			*len = sizeof(int);
2079 		}
2080 
2081 		return 0;
2082 	}
2083 
2084 	return -EAFNOSUPPORT;
2085 #else
2086 	ARG_UNUSED(context);
2087 	ARG_UNUSED(value);
2088 	ARG_UNUSED(len);
2089 
2090 	return -ENOTSUP;
2091 #endif
2092 }
2093 
get_context_local_port_range(struct net_context * context,void * value,uint32_t * len)2094 static int get_context_local_port_range(struct net_context *context,
2095 					void *value, uint32_t *len)
2096 {
2097 #if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)
2098 	if (len == NULL || *len != sizeof(uint32_t)) {
2099 		return -EINVAL;
2100 	}
2101 
2102 	*((uint32_t *)value) = context->options.port_range;
2103 
2104 	return 0;
2105 #else
2106 	ARG_UNUSED(context);
2107 	ARG_UNUSED(value);
2108 	ARG_UNUSED(len);
2109 
2110 	return -ENOTSUP;
2111 #endif
2112 }
2113 
get_context_ipv6_mcast_loop(struct net_context * context,void * value,uint32_t * len)2114 static int get_context_ipv6_mcast_loop(struct net_context *context,
2115 				       void *value, uint32_t *len)
2116 {
2117 #if defined(CONFIG_NET_IPV6)
2118 	return get_bool_option(context->options.ipv6_mcast_loop, value, len);
2119 #else
2120 	ARG_UNUSED(context);
2121 	ARG_UNUSED(value);
2122 	ARG_UNUSED(len);
2123 
2124 	return -ENOTSUP;
2125 #endif
2126 }
2127 
2128 /* If buf is not NULL, then use it. Otherwise read the data to be written
2129  * to net_pkt from msghdr.
2130  */
context_write_data(struct net_pkt * pkt,const void * buf,int buf_len,const struct net_msghdr * msghdr)2131 static int context_write_data(struct net_pkt *pkt, const void *buf,
2132 			      int buf_len, const struct net_msghdr *msghdr)
2133 {
2134 	int ret = 0;
2135 
2136 	if (msghdr) {
2137 		int i;
2138 
2139 		for (i = 0; i < msghdr->msg_iovlen; i++) {
2140 			int len = MIN(msghdr->msg_iov[i].iov_len, buf_len);
2141 
2142 			ret = net_pkt_write(pkt, msghdr->msg_iov[i].iov_base,
2143 					    len);
2144 			if (ret < 0) {
2145 				break;
2146 			}
2147 
2148 			buf_len -= len;
2149 			if (buf_len == 0) {
2150 				break;
2151 			}
2152 		}
2153 	} else {
2154 		ret = net_pkt_write(pkt, buf, buf_len);
2155 	}
2156 
2157 	return ret;
2158 }
2159 
context_setup_udp_packet(struct net_context * context,net_sa_family_t family,struct net_pkt * pkt,const void * buf,size_t len,const struct net_msghdr * msg,const struct net_sockaddr * dst_addr,net_socklen_t addrlen)2160 static int context_setup_udp_packet(struct net_context *context,
2161 				    net_sa_family_t family,
2162 				    struct net_pkt *pkt,
2163 				    const void *buf,
2164 				    size_t len,
2165 				    const struct net_msghdr *msg,
2166 				    const struct net_sockaddr *dst_addr,
2167 				    net_socklen_t addrlen)
2168 {
2169 	int ret = -EINVAL;
2170 	uint16_t dst_port = 0U;
2171 
2172 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
2173 		struct net_sockaddr_in6 *addr6 = (struct net_sockaddr_in6 *)dst_addr;
2174 
2175 		dst_port = addr6->sin6_port;
2176 
2177 		ret = net_context_create_ipv6_new(context, pkt,
2178 						  NULL, &addr6->sin6_addr);
2179 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
2180 		struct net_sockaddr_in *addr4 = (struct net_sockaddr_in *)dst_addr;
2181 
2182 		dst_port = addr4->sin_port;
2183 
2184 		ret = net_context_create_ipv4_new(context, pkt,
2185 						  NULL, &addr4->sin_addr);
2186 	}
2187 
2188 	if (ret < 0) {
2189 		return ret;
2190 	}
2191 
2192 	ret = bind_default(context);
2193 	if (ret) {
2194 		return ret;
2195 	}
2196 
2197 	ret = net_udp_create(pkt,
2198 			     net_sin((struct net_sockaddr *)
2199 				     &context->local)->sin_port,
2200 			     dst_port);
2201 	if (ret) {
2202 		return ret;
2203 	}
2204 
2205 	ret = context_write_data(pkt, buf, len, msg);
2206 	if (ret) {
2207 		return ret;
2208 	}
2209 
2210 #if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
2211 	if (context->options.timestamping & ZSOCK_SOF_TIMESTAMPING_TX_HARDWARE) {
2212 		net_pkt_set_tx_timestamping(pkt, true);
2213 	}
2214 
2215 	if (context->options.timestamping & ZSOCK_SOF_TIMESTAMPING_RX_HARDWARE) {
2216 		net_pkt_set_rx_timestamping(pkt, true);
2217 	}
2218 #endif
2219 
2220 	return 0;
2221 }
2222 
context_setup_raw_ip_packet(net_sa_family_t family,struct net_pkt * pkt,const void * buf,size_t len,const struct net_msghdr * msg)2223 static int context_setup_raw_ip_packet(net_sa_family_t family,
2224 				       struct net_pkt *pkt,
2225 				       const void *buf,
2226 				       size_t len,
2227 				       const struct net_msghdr *msg)
2228 {
2229 	int ret;
2230 
2231 	ret = context_write_data(pkt, buf, len, msg);
2232 	if (ret < 0) {
2233 		return ret;
2234 	}
2235 
2236 	if (family == NET_AF_INET) {
2237 		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access,
2238 						      struct net_ipv4_hdr);
2239 		struct net_ipv4_hdr *ipv4_hdr;
2240 		uint8_t hdr_len;
2241 
2242 		net_pkt_cursor_init(pkt);
2243 		net_pkt_set_overwrite(pkt, true);
2244 
2245 		ipv4_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &ipv4_access);
2246 		if (ipv4_hdr == NULL) {
2247 			return -ENOBUFS;
2248 		}
2249 
2250 		net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
2251 
2252 		hdr_len = (ipv4_hdr->vhl & 0x0F) * 4;
2253 		if (hdr_len > sizeof(struct net_ipv4_hdr)) {
2254 			net_pkt_set_ipv4_opts_len(
2255 				pkt, hdr_len - sizeof(struct net_ipv4_hdr));
2256 		}
2257 
2258 		if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt),
2259 						 NET_IF_CHECKSUM_IPV4_HEADER)) {
2260 			ipv4_hdr->chksum = 0;
2261 			ipv4_hdr->chksum = net_calc_chksum_ipv4(pkt);
2262 			net_pkt_set_data(pkt, &ipv4_access);
2263 		}
2264 
2265 		net_pkt_set_ll_proto_type(pkt, NET_ETH_PTYPE_IP);
2266 	} else {
2267 		net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
2268 		net_pkt_set_ll_proto_type(pkt, NET_ETH_PTYPE_IPV6);
2269 	}
2270 
2271 	return 0;
2272 }
2273 
context_finalize_packet(struct net_context * context,net_sa_family_t family,struct net_pkt * pkt)2274 static void context_finalize_packet(struct net_context *context,
2275 				    net_sa_family_t family,
2276 				    struct net_pkt *pkt)
2277 {
2278 	/* This function is meant to be temporary: once all moved to new
2279 	 * API, it will be up to net_send_data() to finalize the packet.
2280 	 */
2281 
2282 	net_pkt_cursor_init(pkt);
2283 
2284 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
2285 		net_ipv6_finalize(pkt, net_context_get_proto(context));
2286 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
2287 		net_ipv4_finalize(pkt, net_context_get_proto(context));
2288 	}
2289 }
2290 
context_alloc_pkt(struct net_context * context,net_sa_family_t family,size_t len,k_timeout_t timeout)2291 static struct net_pkt *context_alloc_pkt(struct net_context *context,
2292 					 net_sa_family_t family,
2293 					 size_t len, k_timeout_t timeout)
2294 {
2295 	struct net_pkt *pkt;
2296 
2297 #if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
2298 	if (context->tx_slab) {
2299 		pkt = net_pkt_alloc_from_slab(context->tx_slab(), timeout);
2300 		if (!pkt) {
2301 			return NULL;
2302 		}
2303 
2304 		net_pkt_set_iface(pkt, net_context_get_iface(context));
2305 		net_pkt_set_family(pkt, family);
2306 		net_pkt_set_context(pkt, context);
2307 
2308 		if (net_pkt_alloc_buffer(pkt, len,
2309 					 net_context_get_proto(context),
2310 					 timeout)) {
2311 			net_pkt_unref(pkt);
2312 
2313 			return NULL;
2314 		}
2315 
2316 		return pkt;
2317 	}
2318 #endif
2319 	pkt = net_pkt_alloc_with_buffer(net_context_get_iface(context), len,
2320 					family,
2321 					net_context_get_proto(context),
2322 					timeout);
2323 	if (pkt) {
2324 		net_pkt_set_context(pkt, context);
2325 	}
2326 
2327 	return pkt;
2328 }
2329 
set_pkt_txtime(struct net_pkt * pkt,const struct net_msghdr * msghdr)2330 static void set_pkt_txtime(struct net_pkt *pkt, const struct net_msghdr *msghdr)
2331 {
2332 	struct net_cmsghdr *cmsg;
2333 
2334 	for (cmsg = NET_CMSG_FIRSTHDR(msghdr); cmsg != NULL;
2335 	     cmsg = NET_CMSG_NXTHDR(msghdr, cmsg)) {
2336 		if (cmsg->cmsg_len == NET_CMSG_LEN(sizeof(uint64_t)) &&
2337 		    cmsg->cmsg_level == ZSOCK_SOL_SOCKET &&
2338 		    cmsg->cmsg_type == ZSOCK_SCM_TXTIME) {
2339 			net_pkt_set_timestamp_ns(pkt, *(net_time_t *)NET_CMSG_DATA(cmsg));
2340 			break;
2341 		}
2342 	}
2343 }
2344 
set_pkt_hoplimit(struct net_pkt * pkt,const struct net_msghdr * msg_hdr)2345 static void set_pkt_hoplimit(struct net_pkt *pkt, const struct net_msghdr *msg_hdr)
2346 {
2347 	struct net_cmsghdr *cmsg;
2348 	const struct net_sockaddr_in6 *addr6 = NULL;
2349 
2350 	if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) && IS_ENABLED(CONFIG_NET_IPV6)) {
2351 		addr6 = msg_hdr->msg_name;
2352 	}
2353 
2354 	for (cmsg = NET_CMSG_FIRSTHDR(msg_hdr); cmsg != NULL;
2355 	     cmsg = NET_CMSG_NXTHDR(msg_hdr, cmsg)) {
2356 		if (net_pkt_family(pkt) == NET_AF_INET6) {
2357 			if (cmsg->cmsg_len == NET_CMSG_LEN(sizeof(int)) &&
2358 			    cmsg->cmsg_level == NET_IPPROTO_IPV6 &&
2359 			    cmsg->cmsg_type == ZSOCK_IPV6_HOPLIMIT) {
2360 				net_pkt_set_ipv6_hop_limit(pkt, *(uint8_t *)NET_CMSG_DATA(cmsg));
2361 				break;
2362 			}
2363 		} else if (net_pkt_family(pkt) == NET_AF_INET) {
2364 			if (addr6  == NULL ||
2365 			    (addr6 != NULL && !net_ipv6_addr_is_v4_mapped(&addr6->sin6_addr))) {
2366 				if (cmsg->cmsg_len == NET_CMSG_LEN(sizeof(int)) &&
2367 				    cmsg->cmsg_level == NET_IPPROTO_IP &&
2368 				    cmsg->cmsg_type == ZSOCK_IP_TTL) {
2369 					net_pkt_set_ipv4_ttl(pkt, *(uint8_t *)NET_CMSG_DATA(cmsg));
2370 					break;
2371 				}
2372 			} else if (addr6 != NULL &&
2373 				   net_ipv6_addr_is_v4_mapped(&addr6->sin6_addr)) {
2374 				if (cmsg->cmsg_len == NET_CMSG_LEN(sizeof(int)) &&
2375 				    cmsg->cmsg_level == NET_IPPROTO_IPV6 &&
2376 				    cmsg->cmsg_type == ZSOCK_IPV6_HOPLIMIT) {
2377 					net_pkt_set_ipv4_ttl(pkt, *(uint8_t *)NET_CMSG_DATA(cmsg));
2378 					break;
2379 				}
2380 			}
2381 		}
2382 	}
2383 }
2384 
context_sendto(struct net_context * context,const void * buf,size_t len,const struct net_sockaddr * dst_addr,net_socklen_t addrlen,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data,bool sendto)2385 static int context_sendto(struct net_context *context,
2386 			  const void *buf,
2387 			  size_t len,
2388 			  const struct net_sockaddr *dst_addr,
2389 			  net_socklen_t addrlen,
2390 			  net_context_send_cb_t cb,
2391 			  k_timeout_t timeout,
2392 			  void *user_data,
2393 			  bool sendto)
2394 {
2395 	const struct net_msghdr *msghdr = NULL;
2396 	struct net_if *iface = NULL;
2397 	struct net_pkt *pkt = NULL;
2398 	net_sa_family_t family;
2399 	size_t tmp_len;
2400 	int ret;
2401 
2402 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
2403 
2404 	if (!net_context_is_used(context)) {
2405 		return -EBADF;
2406 	}
2407 
2408 	if (sendto && addrlen == 0 && dst_addr == NULL && buf != NULL) {
2409 		/* User wants to call sendmsg */
2410 		msghdr = buf;
2411 	}
2412 
2413 	if (!msghdr && !dst_addr) {
2414 		return -EDESTADDRREQ;
2415 	}
2416 
2417 	/* Are we trying to send IPv4 packet to mapped V6 address, in that case
2418 	 * we need to set the family to NET_AF_INET so that various checks below
2419 	 * are done to the packet correctly and we actually send an IPv4 pkt.
2420 	 */
2421 	if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) &&
2422 	    IS_ENABLED(CONFIG_NET_IPV6) &&
2423 	    net_context_get_family(context) == NET_AF_INET6) {
2424 		const struct net_sockaddr_in6 *addr6 = NULL;
2425 
2426 		if (dst_addr != NULL) {
2427 			addr6 = (const struct net_sockaddr_in6 *)dst_addr;
2428 		} else if (msghdr != NULL) {
2429 			addr6 = msghdr->msg_name;
2430 		}
2431 
2432 		if (addr6 != NULL && net_ipv6_addr_is_v4_mapped(&addr6->sin6_addr)) {
2433 			family = NET_AF_INET;
2434 		} else {
2435 			family = net_context_get_family(context);
2436 		}
2437 	} else {
2438 		family = net_context_get_family(context);
2439 	}
2440 
2441 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
2442 		const struct net_sockaddr_in6 *addr6 =
2443 			(const struct net_sockaddr_in6 *)dst_addr;
2444 
2445 		if (msghdr) {
2446 			addr6 = msghdr->msg_name;
2447 			addrlen = msghdr->msg_namelen;
2448 
2449 			if (!addr6) {
2450 				addr6 = net_sin6(&context->remote);
2451 				addrlen = sizeof(struct net_sockaddr_in6);
2452 			}
2453 
2454 			/* For sendmsg(), the dst_addr is NULL so set it here.
2455 			 */
2456 			dst_addr = (const struct net_sockaddr *)addr6;
2457 		}
2458 
2459 		if (addrlen < sizeof(struct net_sockaddr_in6)) {
2460 			return -EINVAL;
2461 		}
2462 
2463 		if (net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
2464 			return -EDESTADDRREQ;
2465 		}
2466 
2467 		if (IS_ENABLED(CONFIG_NET_UDP) &&
2468 		    net_context_get_type(context) == NET_SOCK_DGRAM) {
2469 			if (net_ipv6_is_addr_mcast(&addr6->sin6_addr) &&
2470 			    COND_CODE_1(CONFIG_NET_IPV6,
2471 					(context->options.ipv6_mcast_ifindex > 0), (false))) {
2472 				IF_ENABLED(CONFIG_NET_IPV6,
2473 					   (iface = net_if_get_by_index(
2474 						   context->options.ipv6_mcast_ifindex)));
2475 			}
2476 
2477 			if (net_ipv6_is_ll_addr(&addr6->sin6_addr) &&
2478 			    !net_context_is_bound_to_iface(context) &&
2479 			    COND_CODE_1(CONFIG_NET_IPV6,
2480 					(addr6->sin6_scope_id > 0), (false))) {
2481 				IF_ENABLED(CONFIG_NET_IPV6, (
2482 					   iface = net_if_get_by_index(addr6->sin6_scope_id)));
2483 				if (iface != NULL) {
2484 					net_context_set_iface(context, iface);
2485 				}
2486 			}
2487 		}
2488 
2489 		/* If application has not yet set the destination address
2490 		 * i.e., by not calling connect(), then set the interface
2491 		 * here so that the packet gets sent to the correct network
2492 		 * interface. This issue can be seen if there are multiple
2493 		 * network interfaces and we are trying to send data to
2494 		 * second or later network interface.
2495 		 */
2496 		if (iface == NULL) {
2497 			if (net_ipv6_is_addr_unspecified(
2498 				    &net_sin6(&context->remote)->sin6_addr) &&
2499 			    !net_context_is_bound_to_iface(context)) {
2500 				iface = net_if_ipv6_select_src_iface(&addr6->sin6_addr);
2501 				net_context_set_iface(context, iface);
2502 			}
2503 		}
2504 
2505 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
2506 		const struct net_sockaddr_in *addr4 = (const struct net_sockaddr_in *)dst_addr;
2507 		struct net_sockaddr_in mapped;
2508 
2509 		if (msghdr) {
2510 			addr4 = msghdr->msg_name;
2511 			addrlen = msghdr->msg_namelen;
2512 
2513 			if (!addr4) {
2514 				addr4 = net_sin(&context->remote);
2515 				addrlen = sizeof(struct net_sockaddr_in);
2516 			}
2517 
2518 			/* For sendmsg(), the dst_addr is NULL so set it here.
2519 			 */
2520 			dst_addr = (const struct net_sockaddr *)addr4;
2521 		}
2522 
2523 		/* Get the destination address from the mapped IPv6 address */
2524 		if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) &&
2525 		    addr4->sin_family == NET_AF_INET6 &&
2526 		    net_ipv6_addr_is_v4_mapped(&net_sin6(dst_addr)->sin6_addr)) {
2527 			struct net_sockaddr_in6 *addr6 = (struct net_sockaddr_in6 *)dst_addr;
2528 
2529 			mapped.sin_port = addr6->sin6_port;
2530 			mapped.sin_family = NET_AF_INET;
2531 			net_ipaddr_copy(&mapped.sin_addr,
2532 					(struct net_in_addr *)(&addr6->sin6_addr.s6_addr32[3]));
2533 			addr4 = &mapped;
2534 
2535 			/* For sendmsg(), the dst_addr is NULL so set it here.
2536 			 */
2537 			dst_addr = (const struct net_sockaddr *)addr4;
2538 		}
2539 
2540 		if (addrlen < sizeof(struct net_sockaddr_in)) {
2541 			return -EINVAL;
2542 		}
2543 
2544 		if (!addr4->sin_addr.s_addr) {
2545 			return -EDESTADDRREQ;
2546 		}
2547 
2548 		if (IS_ENABLED(CONFIG_NET_UDP) &&
2549 		    net_context_get_type(context) == NET_SOCK_DGRAM) {
2550 			if (net_ipv4_is_addr_mcast(&addr4->sin_addr) &&
2551 			    COND_CODE_1(CONFIG_NET_IPV4,
2552 					(context->options.ipv4_mcast_ifindex > 0), (false))) {
2553 				IF_ENABLED(CONFIG_NET_IPV4,
2554 					   (iface = net_if_get_by_index(
2555 						   context->options.ipv4_mcast_ifindex)));
2556 			}
2557 		}
2558 
2559 		/* If application has not yet set the destination address
2560 		 * i.e., by not calling connect(), then set the interface
2561 		 * here so that the packet gets sent to the correct network
2562 		 * interface. This issue can be seen if there are multiple
2563 		 * network interfaces and we are trying to send data to
2564 		 * second or later network interface.
2565 		 */
2566 		if (iface == NULL) {
2567 			if (net_sin(&context->remote)->sin_addr.s_addr == 0U &&
2568 			    !net_context_is_bound_to_iface(context)) {
2569 				iface = net_if_ipv4_select_src_iface(&addr4->sin_addr);
2570 				net_context_set_iface(context, iface);
2571 			}
2572 		}
2573 
2574 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && family == NET_AF_PACKET) {
2575 		struct net_sockaddr_ll *ll_addr = (struct net_sockaddr_ll *)dst_addr;
2576 
2577 		if (msghdr) {
2578 			ll_addr = msghdr->msg_name;
2579 			addrlen = msghdr->msg_namelen;
2580 
2581 			if (!ll_addr) {
2582 				ll_addr = (struct net_sockaddr_ll *)
2583 							(&context->remote);
2584 				addrlen = sizeof(struct net_sockaddr_ll);
2585 			}
2586 
2587 			/* For sendmsg(), the dst_addr is NULL so set it here.
2588 			 */
2589 			dst_addr = (const struct net_sockaddr *)ll_addr;
2590 		}
2591 
2592 		if (addrlen < sizeof(struct net_sockaddr_ll)) {
2593 			return -EINVAL;
2594 		}
2595 
2596 		iface = net_context_get_iface(context);
2597 		if (iface == NULL) {
2598 			if (ll_addr->sll_ifindex < 0) {
2599 				return -EDESTADDRREQ;
2600 			}
2601 
2602 			iface = net_if_get_by_index(ll_addr->sll_ifindex);
2603 			if (iface == NULL) {
2604 				NET_ERR("Cannot bind to interface index %d",
2605 					ll_addr->sll_ifindex);
2606 				return -EDESTADDRREQ;
2607 			}
2608 
2609 			net_context_set_iface(context, iface);
2610 		}
2611 
2612 		if (net_context_get_type(context) == NET_SOCK_DGRAM) {
2613 			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
2614 
2615 			/* The user must set the protocol in send call */
2616 
2617 			/* For sendmsg() call, we might have set ll_addr to
2618 			 * point to remote addr.
2619 			 */
2620 			if ((void *)&context->remote != (void *)ll_addr) {
2621 				memcpy((struct net_sockaddr_ll *)&context->remote,
2622 				       ll_addr, sizeof(struct net_sockaddr_ll));
2623 			}
2624 		}
2625 
2626 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == NET_AF_CAN) {
2627 		struct net_sockaddr_can *can_addr = (struct net_sockaddr_can *)dst_addr;
2628 
2629 		if (msghdr) {
2630 			can_addr = msghdr->msg_name;
2631 			addrlen = msghdr->msg_namelen;
2632 
2633 			if (!can_addr) {
2634 				can_addr = (struct net_sockaddr_can *)
2635 							(&context->remote);
2636 				addrlen = sizeof(struct net_sockaddr_can);
2637 			}
2638 
2639 			/* For sendmsg(), the dst_addr is NULL so set it here.
2640 			 */
2641 			dst_addr = (const struct net_sockaddr *)can_addr;
2642 		}
2643 
2644 		if (addrlen < sizeof(struct net_sockaddr_can)) {
2645 			return -EINVAL;
2646 		}
2647 
2648 		if (can_addr->can_ifindex < 0) {
2649 			/* The index should have been set in bind */
2650 			can_addr->can_ifindex =
2651 				net_can_ptr(&context->local)->can_ifindex;
2652 		}
2653 
2654 		if (can_addr->can_ifindex < 0) {
2655 			return -EDESTADDRREQ;
2656 		}
2657 
2658 		iface = net_if_get_by_index(can_addr->can_ifindex);
2659 		if (!iface) {
2660 			NET_ERR("Cannot bind to interface index %d",
2661 				can_addr->can_ifindex);
2662 			return -EDESTADDRREQ;
2663 		}
2664 	} else {
2665 		NET_DBG("Invalid protocol family %d", family);
2666 		return -EINVAL;
2667 	}
2668 
2669 	if (msghdr && len == 0) {
2670 		int i;
2671 
2672 		for (i = 0; i < msghdr->msg_iovlen; i++) {
2673 			len += msghdr->msg_iov[i].iov_len;
2674 		}
2675 	}
2676 
2677 	iface = net_context_get_iface(context);
2678 	if (iface && !net_if_is_up(iface)) {
2679 		return -ENETDOWN;
2680 	}
2681 
2682 	context->send_cb = cb;
2683 	context->user_data = user_data;
2684 
2685 	if (IS_ENABLED(CONFIG_NET_TCP) &&
2686 	    net_context_get_proto(context) == NET_IPPROTO_TCP &&
2687 	    !net_if_is_ip_offloaded(net_context_get_iface(context))) {
2688 		goto skip_alloc;
2689 	}
2690 
2691 	pkt = context_alloc_pkt(context, family, len, PKT_WAIT_TIME);
2692 	if (!pkt) {
2693 		NET_ERR("Failed to allocate net_pkt");
2694 		return -ENOBUFS;
2695 	}
2696 
2697 	tmp_len = net_pkt_available_payload_buffer(
2698 				pkt, net_context_get_proto(context));
2699 	if (tmp_len < len) {
2700 		if (net_context_get_type(context) == NET_SOCK_DGRAM ||
2701 		    net_context_get_type(context) == NET_SOCK_RAW) {
2702 			NET_ERR("Available payload buffer (%zu) is not enough for requested DGRAM (%zu)",
2703 				tmp_len, len);
2704 			ret = -ENOMEM;
2705 			goto fail;
2706 		}
2707 		len = tmp_len;
2708 	}
2709 
2710 	if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
2711 		uint8_t priority;
2712 
2713 		get_context_priority(context, &priority, NULL);
2714 		net_pkt_set_priority(pkt, priority);
2715 	}
2716 
2717 	/* If there is ancillary data in msghdr, then we need to add that
2718 	 * to net_pkt as there is no other way to store it.
2719 	 */
2720 	if (msghdr && msghdr->msg_control && msghdr->msg_controllen) {
2721 		if (IS_ENABLED(CONFIG_NET_CONTEXT_TXTIME)) {
2722 			int is_txtime;
2723 
2724 			get_context_txtime(context, &is_txtime, NULL);
2725 			if (is_txtime) {
2726 				set_pkt_txtime(pkt, msghdr);
2727 			}
2728 		}
2729 
2730 		set_pkt_hoplimit(pkt, msghdr);
2731 
2732 	}
2733 
2734 skip_alloc:
2735 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
2736 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
2737 		ret = context_write_data(pkt, buf, len, msghdr);
2738 		if (ret < 0) {
2739 			goto fail;
2740 		}
2741 
2742 		net_pkt_cursor_init(pkt);
2743 
2744 		if (sendto) {
2745 			ret = net_offload_sendto(net_context_get_iface(context),
2746 						 pkt, dst_addr, addrlen, cb,
2747 						 timeout, user_data);
2748 		} else {
2749 			ret = net_offload_send(net_context_get_iface(context),
2750 					       pkt, cb, timeout, user_data);
2751 		}
2752 	} else if (((IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) ||
2753 		    (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6)) &&
2754 		   IS_ENABLED(CONFIG_NET_SOCKETS_INET_RAW) &&
2755 		   net_context_get_type(context) == NET_SOCK_RAW) {
2756 		ret = context_setup_raw_ip_packet(family, pkt, buf, len, msghdr);
2757 		if (ret < 0) {
2758 			goto fail;
2759 		}
2760 
2761 		ret = net_try_send_data(pkt, timeout);
2762 	} else if (IS_ENABLED(CONFIG_NET_UDP) &&
2763 	    net_context_get_proto(context) == NET_IPPROTO_UDP) {
2764 		ret = context_setup_udp_packet(context, family, pkt, buf, len, msghdr,
2765 					       dst_addr, addrlen);
2766 		if (ret < 0) {
2767 			goto fail;
2768 		}
2769 
2770 		context_finalize_packet(context, family, pkt);
2771 
2772 		ret = net_try_send_data(pkt, timeout);
2773 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
2774 		   net_context_get_proto(context) == NET_IPPROTO_TCP) {
2775 
2776 		ret = net_tcp_queue(context, buf, len, msghdr);
2777 		if (ret < 0) {
2778 			goto fail;
2779 		}
2780 
2781 		len = ret;
2782 
2783 		ret = net_tcp_send_data(context, cb, user_data);
2784 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && family == NET_AF_PACKET) {
2785 		ret = context_write_data(pkt, buf, len, msghdr);
2786 		if (ret < 0) {
2787 			goto fail;
2788 		}
2789 
2790 		net_pkt_cursor_init(pkt);
2791 
2792 		struct net_sockaddr_ll_ptr *ll_src_addr;
2793 		struct net_sockaddr_ll *ll_dst_addr;
2794 
2795 		/* The destination address is set in remote for this
2796 		 * socket type.
2797 		 */
2798 		ll_dst_addr = (struct net_sockaddr_ll *)&context->remote;
2799 		ll_src_addr = (struct net_sockaddr_ll_ptr *)&context->local;
2800 
2801 		(void)net_linkaddr_set(net_pkt_lladdr_dst(pkt),
2802 				       ll_dst_addr->sll_addr,
2803 				       sizeof(struct net_eth_addr));
2804 		(void)net_linkaddr_set(net_pkt_lladdr_src(pkt),
2805 				       ll_src_addr->sll_addr,
2806 				       sizeof(struct net_eth_addr));
2807 
2808 		net_pkt_set_ll_proto_type(pkt, net_ntohs(ll_dst_addr->sll_protocol));
2809 
2810 		net_if_try_queue_tx(net_pkt_iface(pkt), pkt, timeout);
2811 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == NET_AF_CAN &&
2812 		   net_context_get_proto(context) == NET_CAN_RAW) {
2813 		ret = context_write_data(pkt, buf, len, msghdr);
2814 		if (ret < 0) {
2815 			goto fail;
2816 		}
2817 
2818 		net_pkt_cursor_init(pkt);
2819 
2820 		ret = net_try_send_data(pkt, timeout);
2821 	} else {
2822 		NET_DBG("Unknown protocol while sending packet: %d",
2823 		net_context_get_proto(context));
2824 		ret = -EPROTONOSUPPORT;
2825 	}
2826 
2827 	if (ret < 0) {
2828 		goto fail;
2829 	}
2830 
2831 	return len;
2832 fail:
2833 	if (pkt != NULL) {
2834 		net_pkt_unref(pkt);
2835 	}
2836 
2837 	return ret;
2838 }
2839 
raw_inet_set_remote(struct net_context * context,const void * buf,size_t len)2840 static void raw_inet_set_remote(struct net_context *context, const void *buf,
2841 				size_t len)
2842 {
2843 	struct net_if *iface;
2844 
2845 	if (net_context_get_family(context) == NET_AF_INET) {
2846 		struct net_sockaddr_in *remote =
2847 			(struct net_sockaddr_in *)&context->remote;
2848 		const struct net_ipv4_hdr *iphdr = buf;
2849 
2850 		if (len < sizeof(struct net_ipv4_hdr)) {
2851 			return;
2852 		}
2853 
2854 		if (!net_ipv4_is_addr_unspecified(
2855 				&net_sin(&context->remote)->sin_addr)) {
2856 			goto out;
2857 		}
2858 
2859 		remote->sin_family = NET_AF_INET;
2860 		remote->sin_port = 0;
2861 		memcpy(&remote->sin_addr, iphdr->dst, sizeof(remote->sin_addr));
2862 
2863 		if (net_context_is_bound_to_iface(context)) {
2864 			goto out;
2865 		}
2866 
2867 		iface = net_if_ipv4_select_src_iface(&remote->sin_addr);
2868 		if (iface == NULL) {
2869 			goto out;
2870 		}
2871 
2872 		net_context_set_iface(context, iface);
2873 	} else if (net_context_get_family(context) == NET_AF_INET6) {
2874 		struct net_sockaddr_in6 *remote =
2875 			(struct net_sockaddr_in6 *)&context->remote;
2876 		const struct net_ipv6_hdr *iphdr = buf;
2877 
2878 		if (len < sizeof(struct net_ipv6_hdr)) {
2879 			return;
2880 		}
2881 
2882 		if (!net_ipv6_is_addr_unspecified(
2883 				&net_sin6(&context->remote)->sin6_addr)) {
2884 			goto out;
2885 		}
2886 
2887 		remote->sin6_family = NET_AF_INET6;
2888 		remote->sin6_port = 0;
2889 		memcpy(&remote->sin6_addr, iphdr->dst, sizeof(remote->sin6_addr));
2890 
2891 		if (net_context_is_bound_to_iface(context)) {
2892 			goto out;
2893 		}
2894 
2895 		iface = net_if_ipv6_select_src_iface(&remote->sin6_addr);
2896 		if (iface == NULL) {
2897 			goto out;
2898 		}
2899 
2900 		net_context_set_iface(context, iface);
2901 	} else {
2902 		return;
2903 	}
2904 
2905 out:
2906 	context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
2907 }
2908 
net_context_send(struct net_context * context,const void * buf,size_t len,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)2909 int net_context_send(struct net_context *context,
2910 		     const void *buf,
2911 		     size_t len,
2912 		     net_context_send_cb_t cb,
2913 		     k_timeout_t timeout,
2914 		     void *user_data)
2915 {
2916 	bool dst_check = true;
2917 	net_socklen_t addrlen;
2918 	int ret = 0;
2919 
2920 	k_mutex_lock(&context->lock, K_FOREVER);
2921 
2922 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
2923 	    net_context_get_family(context) == NET_AF_INET6) {
2924 		addrlen = sizeof(struct net_sockaddr_in6);
2925 		if (IS_ENABLED(CONFIG_NET_SOCKETS_INET_RAW) &&
2926 		    net_context_get_type(context) == NET_SOCK_RAW) {
2927 			raw_inet_set_remote(context, buf, len);
2928 			dst_check = false;
2929 		}
2930 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2931 		   net_context_get_family(context) == NET_AF_INET) {
2932 		addrlen = sizeof(struct net_sockaddr_in);
2933 		if (IS_ENABLED(CONFIG_NET_SOCKETS_INET_RAW) &&
2934 		    net_context_get_type(context) == NET_SOCK_RAW) {
2935 			raw_inet_set_remote(context, buf, len);
2936 			dst_check = false;
2937 		}
2938 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2939 		   net_context_get_family(context) == NET_AF_PACKET) {
2940 		ret = -EOPNOTSUPP;
2941 		goto unlock;
2942 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2943 		   net_context_get_family(context) == NET_AF_CAN) {
2944 		addrlen = sizeof(struct net_sockaddr_can);
2945 	} else {
2946 		addrlen = 0;
2947 	}
2948 
2949 	if (dst_check) {
2950 		if (!(context->flags & NET_CONTEXT_REMOTE_ADDR_SET) ||
2951 		    net_sin(&context->remote)->sin_port == 0) {
2952 			ret = -EDESTADDRREQ;
2953 			goto unlock;
2954 		}
2955 	}
2956 
2957 	ret = context_sendto(context, buf, len, &context->remote,
2958 			     addrlen, cb, timeout, user_data, false);
2959 unlock:
2960 	k_mutex_unlock(&context->lock);
2961 
2962 	return ret;
2963 }
2964 
net_context_sendmsg(struct net_context * context,const struct net_msghdr * msghdr,int flags,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)2965 int net_context_sendmsg(struct net_context *context,
2966 			const struct net_msghdr *msghdr,
2967 			int flags,
2968 			net_context_send_cb_t cb,
2969 			k_timeout_t timeout,
2970 			void *user_data)
2971 {
2972 	int ret;
2973 
2974 	k_mutex_lock(&context->lock, K_FOREVER);
2975 
2976 	ret = context_sendto(context, msghdr, 0, NULL, 0,
2977 			     cb, timeout, user_data, true);
2978 
2979 	k_mutex_unlock(&context->lock);
2980 
2981 	return ret;
2982 }
2983 
net_context_sendto(struct net_context * context,const void * buf,size_t len,const struct net_sockaddr * dst_addr,net_socklen_t addrlen,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)2984 int net_context_sendto(struct net_context *context,
2985 		       const void *buf,
2986 		       size_t len,
2987 		       const struct net_sockaddr *dst_addr,
2988 		       net_socklen_t addrlen,
2989 		       net_context_send_cb_t cb,
2990 		       k_timeout_t timeout,
2991 		       void *user_data)
2992 {
2993 	int ret;
2994 
2995 	k_mutex_lock(&context->lock, K_FOREVER);
2996 
2997 	ret = context_sendto(context, buf, len, dst_addr, addrlen,
2998 			     cb, timeout, user_data, true);
2999 
3000 	k_mutex_unlock(&context->lock);
3001 
3002 	return ret;
3003 }
3004 
net_context_packet_received(struct net_conn * conn,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,void * user_data)3005 enum net_verdict net_context_packet_received(struct net_conn *conn,
3006 					     struct net_pkt *pkt,
3007 					     union net_ip_header *ip_hdr,
3008 					     union net_proto_header *proto_hdr,
3009 					     void *user_data)
3010 {
3011 	struct net_context *context = find_context(conn);
3012 	enum net_verdict verdict = NET_DROP;
3013 
3014 	NET_ASSERT(context);
3015 	NET_ASSERT(net_pkt_iface(pkt));
3016 
3017 	k_mutex_lock(&context->lock, K_FOREVER);
3018 
3019 	net_context_set_iface(context, net_pkt_iface(pkt));
3020 	net_pkt_set_context(pkt, context);
3021 
3022 	/* If there is no callback registered, then we can only drop
3023 	 * the packet.
3024 	 */
3025 	if (!context->recv_cb) {
3026 		goto unlock;
3027 	}
3028 
3029 	if (net_context_get_proto(context) == NET_IPPROTO_TCP) {
3030 		net_stats_update_tcp_recv(net_pkt_iface(pkt),
3031 					  net_pkt_remaining_data(pkt));
3032 	}
3033 
3034 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
3035 	k_sem_give(&context->recv_data_wait);
3036 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
3037 
3038 	k_mutex_unlock(&context->lock);
3039 
3040 	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
3041 
3042 	verdict = NET_OK;
3043 
3044 	return verdict;
3045 
3046 unlock:
3047 	k_mutex_unlock(&context->lock);
3048 
3049 	return verdict;
3050 }
3051 
3052 #if defined(CONFIG_NET_NATIVE_IP)
recv_dgram(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)3053 static int recv_dgram(struct net_context *context,
3054 		      net_context_recv_cb_t cb,
3055 		      k_timeout_t timeout,
3056 		      void *user_data)
3057 {
3058 	struct net_sockaddr local_addr = {
3059 		.sa_family = net_context_get_family(context),
3060 	};
3061 	struct net_sockaddr *laddr = NULL;
3062 	uint16_t lport = 0U;
3063 	int ret;
3064 
3065 	ARG_UNUSED(timeout);
3066 
3067 	ret = bind_default(context);
3068 	if (ret) {
3069 		return ret;
3070 	}
3071 
3072 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
3073 	    net_context_get_family(context) == NET_AF_INET6) {
3074 		if (net_sin6_ptr(&context->local)->sin6_addr) {
3075 			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
3076 				     net_sin6_ptr(&context->local)->sin6_addr);
3077 
3078 			laddr = &local_addr;
3079 		}
3080 
3081 		net_sin6(&local_addr)->sin6_port =
3082 			net_sin6((struct net_sockaddr *)&context->local)->sin6_port;
3083 		lport = net_sin6((struct net_sockaddr *)&context->local)->sin6_port;
3084 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
3085 		   net_context_get_family(context) == NET_AF_INET) {
3086 		if (net_sin_ptr(&context->local)->sin_addr) {
3087 			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
3088 				      net_sin_ptr(&context->local)->sin_addr);
3089 
3090 			laddr = &local_addr;
3091 		}
3092 
3093 		lport = net_sin((struct net_sockaddr *)&context->local)->sin_port;
3094 	}
3095 
3096 	context->recv_cb = cb;
3097 
3098 	/* If the context already has a connection handler, it means it's
3099 	 * already registered. In that case, all we have to do is 1) update
3100 	 * the callback registered in the net_context and 2) update the
3101 	 * user_data and local/remote address and port using net_conn_update().
3102 	 *
3103 	 * The callback function passed to net_conn_update() must be the same
3104 	 * function as the one passed to net_conn_register(), not the callback
3105 	 * set for the net context passed by recv_udp().
3106 	 */
3107 	if (context->conn_handler != NULL) {
3108 		ret = net_conn_update(context->conn_handler,
3109 				      net_context_packet_received,
3110 				      user_data,
3111 				      context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
3112 						&context->remote : NULL,
3113 				      net_ntohs(net_sin(&context->remote)->sin_port),
3114 				      laddr, net_ntohs(lport));
3115 		return ret;
3116 	}
3117 
3118 	ret = net_conn_register(net_context_get_proto(context),
3119 				net_context_get_type(context),
3120 				net_context_get_family(context),
3121 				context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
3122 							&context->remote : NULL,
3123 				laddr,
3124 				net_ntohs(net_sin(&context->remote)->sin_port),
3125 				net_ntohs(lport),
3126 				context,
3127 				net_context_packet_received,
3128 				user_data,
3129 				&context->conn_handler);
3130 
3131 	return ret;
3132 }
3133 #else
3134 #define recv_dgram(...) 0
3135 #endif /* CONFIG_NET_NATIVE_UDP */
3136 
net_context_raw_packet_received(struct net_conn * conn,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,void * user_data)3137 static enum net_verdict net_context_raw_packet_received(
3138 					struct net_conn *conn,
3139 					struct net_pkt *pkt,
3140 					union net_ip_header *ip_hdr,
3141 					union net_proto_header *proto_hdr,
3142 					void *user_data)
3143 {
3144 	struct net_context *context = find_context(conn);
3145 
3146 	NET_ASSERT(context);
3147 	NET_ASSERT(net_pkt_iface(pkt));
3148 
3149 	/* If there is no callback registered, then we can only drop
3150 	 * the packet.
3151 	 */
3152 
3153 	if (!context->recv_cb) {
3154 		return NET_DROP;
3155 	}
3156 
3157 	net_context_set_iface(context, net_pkt_iface(pkt));
3158 	net_pkt_set_context(pkt, context);
3159 
3160 	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
3161 
3162 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
3163 	k_sem_give(&context->recv_data_wait);
3164 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
3165 
3166 	return NET_OK;
3167 }
3168 
recv_raw(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,struct net_sockaddr * local_addr,void * user_data)3169 static int recv_raw(struct net_context *context,
3170 		    net_context_recv_cb_t cb,
3171 		    k_timeout_t timeout,
3172 		    struct net_sockaddr *local_addr,
3173 		    void *user_data)
3174 {
3175 	int ret;
3176 
3177 	ARG_UNUSED(timeout);
3178 
3179 	context->recv_cb = cb;
3180 
3181 	/* If the context already has a connection handler, it means it's
3182 	 * already registered. In that case, all we have to do is 1) update
3183 	 * the callback registered in the net_context and 2) update the
3184 	 * user_data and local address using net_conn_update().
3185 	 *
3186 	 * The callback function passed to net_conn_update() must be the same
3187 	 * function as the one passed to net_conn_register(), not the callback
3188 	 * set for the net context passed by recv_raw().
3189 	 */
3190 	if (context->conn_handler) {
3191 		context->recv_cb = cb;
3192 		ret = net_conn_update(context->conn_handler,
3193 				      net_context_raw_packet_received,
3194 				      user_data,
3195 				      NULL, 0, local_addr, 0);
3196 		return ret;
3197 	}
3198 
3199 	ret = net_conn_register(net_context_get_proto(context),
3200 				net_context_get_type(context),
3201 				net_context_get_family(context),
3202 				NULL, local_addr, 0, 0,
3203 				context,
3204 				net_context_raw_packet_received,
3205 				user_data,
3206 				&context->conn_handler);
3207 
3208 	return ret;
3209 }
3210 
net_context_recv(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)3211 int net_context_recv(struct net_context *context,
3212 		     net_context_recv_cb_t cb,
3213 		     k_timeout_t timeout,
3214 		     void *user_data)
3215 {
3216 	int family;
3217 	int ret;
3218 
3219 	NET_ASSERT(context);
3220 
3221 	if (!net_context_is_used(context)) {
3222 		return -EBADF;
3223 	}
3224 
3225 	k_mutex_lock(&context->lock, K_FOREVER);
3226 
3227 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
3228 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
3229 		ret = net_offload_recv(
3230 			net_context_get_iface(context),
3231 			context, cb, timeout, user_data);
3232 		goto unlock;
3233 	}
3234 
3235 	family = net_context_get_family(context);
3236 
3237 	if (((IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) ||
3238 	     (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6)) &&
3239 	    IS_ENABLED(CONFIG_NET_SOCKETS_INET_RAW) &&
3240 	    net_context_get_type(context) == NET_SOCK_RAW) {
3241 		ret = recv_dgram(context, cb, timeout, user_data);
3242 	} else if (IS_ENABLED(CONFIG_NET_UDP) &&
3243 		   net_context_get_proto(context) == NET_IPPROTO_UDP) {
3244 		ret = recv_dgram(context, cb, timeout, user_data);
3245 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
3246 		   net_context_get_proto(context) == NET_IPPROTO_TCP) {
3247 		ret = net_tcp_recv(context, cb, user_data);
3248 	} else {
3249 		if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
3250 		    family == NET_AF_PACKET) {
3251 			struct net_sockaddr_ll addr = { 0 };
3252 
3253 			ret = bind_default(context);
3254 			if (ret < 0) {
3255 				goto unlock;
3256 			}
3257 
3258 			addr.sll_family = NET_AF_PACKET;
3259 			addr.sll_ifindex =
3260 				net_sll_ptr(&context->local)->sll_ifindex;
3261 			addr.sll_protocol =
3262 				net_sll_ptr(&context->local)->sll_protocol;
3263 			addr.sll_halen =
3264 				net_sll_ptr(&context->local)->sll_halen;
3265 
3266 			if (net_sll_ptr(&context->local)->sll_addr != NULL) {
3267 				/* NET_AF_PACKET socket is bound to an iface as
3268 				 * context->local->sll_addr is valid.  Although the sll_addr
3269 				 * pointer correctly links to the iface net_linkaddr, the
3270 				 * sll_halen is a copy and doesn't track properly the iface
3271 				 * linkaddr len. For example, the linkaddr len can change
3272 				 * depending on the link address format with 802.15.4, between
3273 				 * extended (8 bytes) or short (2 bytes).
3274 				 *
3275 				 * Instead, use the iface link_addr directly. The socket is
3276 				 * bound to an interface as context->local->sll_addr is valid.
3277 				 */
3278 				struct net_linkaddr *link_addr = CONTAINER_OF(
3279 						(uint8_t(*)[NET_LINK_ADDR_MAX_LENGTH])
3280 						net_sll_ptr(&context->local)->sll_addr,
3281 						struct net_linkaddr, addr);
3282 
3283 				addr.sll_halen = link_addr->len;
3284 				memcpy(addr.sll_addr,
3285 				       net_sll_ptr(&context->local)->sll_addr,
3286 				       MIN(addr.sll_halen, sizeof(addr.sll_addr)));
3287 			}
3288 
3289 			ret = recv_raw(context, cb, timeout,
3290 				       (struct net_sockaddr *)&addr, user_data);
3291 		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
3292 			   family == NET_AF_CAN) {
3293 			struct net_sockaddr_can local_addr = {
3294 				.can_family = NET_AF_CAN,
3295 			};
3296 
3297 			ret = bind_default(context);
3298 			if (ret < 0) {
3299 				goto unlock;
3300 			}
3301 
3302 			ret = recv_raw(context, cb, timeout,
3303 				       (struct net_sockaddr *)&local_addr,
3304 				       user_data);
3305 			if (ret == -EALREADY) {
3306 				/* This is perfectly normal for CAN sockets.
3307 				 * The SocketCAN will dispatch the packet to
3308 				 * correct net_context listener.
3309 				 */
3310 				ret = 0;
3311 			}
3312 		} else {
3313 			ret = -EPROTOTYPE;
3314 		}
3315 	}
3316 
3317 	if (ret < 0) {
3318 		goto unlock;
3319 	}
3320 
3321 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
3322 	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
3323 		/* Make sure we have the lock, then the
3324 		 * net_context_packet_received() callback will release the
3325 		 * semaphore when data has been received.
3326 		 */
3327 		k_sem_reset(&context->recv_data_wait);
3328 
3329 		k_mutex_unlock(&context->lock);
3330 
3331 		if (k_sem_take(&context->recv_data_wait, timeout) == -EAGAIN) {
3332 			ret = -ETIMEDOUT;
3333 		}
3334 
3335 		k_mutex_lock(&context->lock, K_FOREVER);
3336 	}
3337 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
3338 
3339 unlock:
3340 	k_mutex_unlock(&context->lock);
3341 
3342 	return ret;
3343 }
3344 
net_context_update_recv_wnd(struct net_context * context,int32_t delta)3345 int net_context_update_recv_wnd(struct net_context *context,
3346 				int32_t delta)
3347 {
3348 	int ret;
3349 
3350 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
3351 		net_if_is_ip_offloaded(net_context_get_iface(context))) {
3352 		return 0;
3353 	}
3354 
3355 	k_mutex_lock(&context->lock, K_FOREVER);
3356 
3357 	ret = net_tcp_update_recv_wnd(context, delta);
3358 
3359 	k_mutex_unlock(&context->lock);
3360 
3361 	return ret;
3362 }
3363 
set_bool_option(bool * option,const void * value,uint32_t len)3364 __maybe_unused static int set_bool_option(bool *option, const void *value, uint32_t len)
3365 {
3366 	if (value == NULL) {
3367 		return -EINVAL;
3368 	}
3369 
3370 	if (len != sizeof(int)) {
3371 		return -EINVAL;
3372 	}
3373 
3374 	*option = !!*((int *)value);
3375 
3376 	return 0;
3377 }
3378 
set_uint8_option(uint8_t * option,const void * value,uint32_t len)3379 __maybe_unused static int set_uint8_option(uint8_t *option, const void *value, uint32_t len)
3380 {
3381 	if (value == NULL) {
3382 		return -EINVAL;
3383 	}
3384 
3385 	if (len > sizeof(uint8_t)) {
3386 		return -EINVAL;
3387 	}
3388 
3389 	*option = *((uint8_t *)value);
3390 
3391 	return 0;
3392 }
3393 
set_uint16_option(uint16_t * option,const void * value,uint32_t len)3394 __maybe_unused static int set_uint16_option(uint16_t *option, const void *value, uint32_t len)
3395 {
3396 	int v;
3397 
3398 	if (value == NULL) {
3399 		return -EINVAL;
3400 	}
3401 
3402 	if (len != sizeof(int)) {
3403 		return -EINVAL;
3404 	}
3405 
3406 	v = *((int *)value);
3407 
3408 	if (v < 0 || v > UINT16_MAX) {
3409 		return -EINVAL;
3410 	}
3411 
3412 	*option = (uint16_t)v;
3413 
3414 	return 0;
3415 
3416 }
3417 
set_context_priority(struct net_context * context,const void * value,uint32_t len)3418 static int set_context_priority(struct net_context *context,
3419 				const void *value, uint32_t len)
3420 {
3421 #if defined(CONFIG_NET_CONTEXT_PRIORITY)
3422 	return set_uint8_option(&context->options.priority, value, len);
3423 #else
3424 	ARG_UNUSED(context);
3425 	ARG_UNUSED(value);
3426 	ARG_UNUSED(len);
3427 
3428 	return -ENOTSUP;
3429 #endif
3430 }
3431 
set_context_txtime(struct net_context * context,const void * value,uint32_t len)3432 static int set_context_txtime(struct net_context *context,
3433 			      const void *value, uint32_t len)
3434 {
3435 #if defined(CONFIG_NET_CONTEXT_TXTIME)
3436 	return set_bool_option(&context->options.txtime, value, len);
3437 #else
3438 	ARG_UNUSED(context);
3439 	ARG_UNUSED(value);
3440 	ARG_UNUSED(len);
3441 
3442 	return -ENOTSUP;
3443 #endif
3444 }
3445 
set_context_proxy(struct net_context * context,const void * value,uint32_t len)3446 static int set_context_proxy(struct net_context *context,
3447 			     const void *value, uint32_t len)
3448 {
3449 #if defined(CONFIG_SOCKS)
3450 	struct net_sockaddr *addr = (struct net_sockaddr *)value;
3451 
3452 	if (len > NET_SOCKADDR_MAX_SIZE) {
3453 		return -EINVAL;
3454 	}
3455 
3456 	if (addr->sa_family != net_context_get_family(context)) {
3457 		return -EINVAL;
3458 	}
3459 
3460 	context->options.proxy.addrlen = len;
3461 	memcpy(&context->options.proxy.addr, addr, len);
3462 
3463 	return 0;
3464 #else
3465 	ARG_UNUSED(context);
3466 	ARG_UNUSED(value);
3467 	ARG_UNUSED(len);
3468 
3469 	return -ENOTSUP;
3470 #endif
3471 }
3472 
set_context_rcvtimeo(struct net_context * context,const void * value,uint32_t len)3473 static int set_context_rcvtimeo(struct net_context *context,
3474 				const void *value, uint32_t len)
3475 {
3476 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
3477 	if (len != sizeof(k_timeout_t)) {
3478 		return -EINVAL;
3479 	}
3480 
3481 	context->options.rcvtimeo = *((k_timeout_t *)value);
3482 
3483 	return 0;
3484 #else
3485 	ARG_UNUSED(context);
3486 	ARG_UNUSED(value);
3487 	ARG_UNUSED(len);
3488 
3489 	return -ENOTSUP;
3490 #endif
3491 }
3492 
set_context_sndtimeo(struct net_context * context,const void * value,uint32_t len)3493 static int set_context_sndtimeo(struct net_context *context,
3494 				const void *value, uint32_t len)
3495 {
3496 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
3497 	if (len != sizeof(k_timeout_t)) {
3498 		return -EINVAL;
3499 	}
3500 
3501 	context->options.sndtimeo = *((k_timeout_t *)value);
3502 
3503 	return 0;
3504 #else
3505 	ARG_UNUSED(context);
3506 	ARG_UNUSED(value);
3507 	ARG_UNUSED(len);
3508 
3509 	return -ENOTSUP;
3510 #endif
3511 }
3512 
set_context_rcvbuf(struct net_context * context,const void * value,uint32_t len)3513 static int set_context_rcvbuf(struct net_context *context,
3514 				const void *value, uint32_t len)
3515 {
3516 #if defined(CONFIG_NET_CONTEXT_RCVBUF)
3517 	return set_uint16_option(&context->options.rcvbuf, value, len);
3518 #else
3519 	ARG_UNUSED(context);
3520 	ARG_UNUSED(value);
3521 	ARG_UNUSED(len);
3522 
3523 	return -ENOTSUP;
3524 #endif
3525 }
3526 
set_context_sndbuf(struct net_context * context,const void * value,uint32_t len)3527 static int set_context_sndbuf(struct net_context *context,
3528 				const void *value, uint32_t len)
3529 {
3530 #if defined(CONFIG_NET_CONTEXT_SNDBUF)
3531 	return set_uint16_option(&context->options.sndbuf, value, len);
3532 #else
3533 	ARG_UNUSED(context);
3534 	ARG_UNUSED(value);
3535 	ARG_UNUSED(len);
3536 
3537 	return -ENOTSUP;
3538 #endif
3539 }
3540 
set_context_dscp_ecn(struct net_context * context,const void * value,uint32_t len)3541 static int set_context_dscp_ecn(struct net_context *context,
3542 				const void *value, uint32_t len)
3543 {
3544 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
3545 	return set_uint8_option(&context->options.dscp_ecn, value, len);
3546 #else
3547 	ARG_UNUSED(context);
3548 	ARG_UNUSED(value);
3549 	ARG_UNUSED(len);
3550 
3551 	return -ENOTSUP;
3552 #endif
3553 }
3554 
set_context_ttl(struct net_context * context,const void * value,uint32_t len)3555 static int set_context_ttl(struct net_context *context,
3556 			   const void *value, uint32_t len)
3557 {
3558 #if defined(CONFIG_NET_IPV4)
3559 	uint8_t ttl = *((int *)value);
3560 
3561 	len = sizeof(context->ipv4_ttl);
3562 
3563 	return set_uint8_option(&context->ipv4_ttl, &ttl, len);
3564 #else
3565 	ARG_UNUSED(context);
3566 	ARG_UNUSED(value);
3567 	ARG_UNUSED(len);
3568 
3569 	return -ENOTSUP;
3570 #endif
3571 }
3572 
set_context_mcast_ttl(struct net_context * context,const void * value,uint32_t len)3573 static int set_context_mcast_ttl(struct net_context *context,
3574 				 const void *value, uint32_t len)
3575 {
3576 #if defined(CONFIG_NET_IPV4)
3577 	uint8_t mcast_ttl = *((int *)value);
3578 
3579 	len = sizeof(context->ipv4_mcast_ttl);
3580 
3581 	return set_uint8_option(&context->ipv4_mcast_ttl, &mcast_ttl, len);
3582 #else
3583 	ARG_UNUSED(context);
3584 	ARG_UNUSED(value);
3585 	ARG_UNUSED(len);
3586 
3587 	return -ENOTSUP;
3588 #endif
3589 }
3590 
set_context_ipv4_mcast_loop(struct net_context * context,const void * value,uint32_t len)3591 static int set_context_ipv4_mcast_loop(struct net_context *context,
3592 				       const void *value, uint32_t len)
3593 {
3594 #if defined(CONFIG_NET_IPV4)
3595 	return set_bool_option(&context->options.ipv4_mcast_loop, value, len);
3596 #else
3597 	ARG_UNUSED(context);
3598 	ARG_UNUSED(value);
3599 	ARG_UNUSED(len);
3600 
3601 	return -ENOTSUP;
3602 #endif
3603 }
3604 
set_context_mcast_hop_limit(struct net_context * context,const void * value,uint32_t len)3605 static int set_context_mcast_hop_limit(struct net_context *context,
3606 				       const void *value, uint32_t len)
3607 {
3608 #if defined(CONFIG_NET_IPV6)
3609 	int mcast_hop_limit = *((int *)value);
3610 
3611 	if (len != sizeof(int)) {
3612 		return -EINVAL;
3613 	}
3614 
3615 	if (mcast_hop_limit == -1) {
3616 		/* If value is -1 then use the system default.
3617 		 * This is done same way as in Linux.
3618 		 */
3619 		if (net_if_get_by_index(context->iface) == NULL) {
3620 			mcast_hop_limit = INITIAL_MCAST_HOP_LIMIT;
3621 		} else {
3622 			mcast_hop_limit = net_if_ipv6_get_mcast_hop_limit(
3623 				net_if_get_by_index(context->iface));
3624 		}
3625 	} else if (mcast_hop_limit < 0 || mcast_hop_limit > 255) {
3626 		return -EINVAL;
3627 	}
3628 
3629 	context->ipv6_mcast_hop_limit = mcast_hop_limit;
3630 
3631 	return 0;
3632 #else
3633 	ARG_UNUSED(context);
3634 	ARG_UNUSED(value);
3635 	ARG_UNUSED(len);
3636 
3637 	return -ENOTSUP;
3638 #endif
3639 }
3640 
set_context_unicast_hop_limit(struct net_context * context,const void * value,uint32_t len)3641 static int set_context_unicast_hop_limit(struct net_context *context,
3642 					 const void *value, uint32_t len)
3643 {
3644 #if defined(CONFIG_NET_IPV6)
3645 	uint8_t unicast_hop_limit = *((int *)value);
3646 
3647 	len = sizeof(context->ipv6_hop_limit);
3648 
3649 	return set_uint8_option(&context->ipv6_hop_limit,
3650 				&unicast_hop_limit, len);
3651 #else
3652 	ARG_UNUSED(context);
3653 	ARG_UNUSED(value);
3654 	ARG_UNUSED(len);
3655 
3656 	return -ENOTSUP;
3657 #endif
3658 }
3659 
set_context_ipv6_mcast_loop(struct net_context * context,const void * value,uint32_t len)3660 static int set_context_ipv6_mcast_loop(struct net_context *context,
3661 				       const void *value, uint32_t len)
3662 {
3663 #if defined(CONFIG_NET_IPV6)
3664 	return set_bool_option(&context->options.ipv6_mcast_loop, value, len);
3665 #else
3666 	ARG_UNUSED(context);
3667 	ARG_UNUSED(value);
3668 	ARG_UNUSED(len);
3669 
3670 	return -ENOTSUP;
3671 #endif
3672 }
3673 
set_context_reuseaddr(struct net_context * context,const void * value,uint32_t len)3674 static int set_context_reuseaddr(struct net_context *context,
3675 				 const void *value, uint32_t len)
3676 {
3677 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
3678 	return set_bool_option(&context->options.reuseaddr, value, len);
3679 #else
3680 	ARG_UNUSED(context);
3681 	ARG_UNUSED(value);
3682 	ARG_UNUSED(len);
3683 
3684 	return -ENOTSUP;
3685 #endif
3686 }
3687 
set_context_reuseport(struct net_context * context,const void * value,uint32_t len)3688 static int set_context_reuseport(struct net_context *context,
3689 				 const void *value, uint32_t len)
3690 {
3691 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
3692 	return set_bool_option(&context->options.reuseport, value, len);
3693 #else
3694 	ARG_UNUSED(context);
3695 	ARG_UNUSED(value);
3696 	ARG_UNUSED(len);
3697 
3698 	return -ENOTSUP;
3699 #endif
3700 }
3701 
set_context_ipv6_mtu(struct net_context * context,const void * value,uint32_t len)3702 static int set_context_ipv6_mtu(struct net_context *context,
3703 				const void *value, uint32_t len)
3704 {
3705 #if defined(CONFIG_NET_IPV6)
3706 	struct net_if *iface;
3707 	uint16_t mtu;
3708 
3709 	if (len != sizeof(int)) {
3710 		return -EINVAL;
3711 	}
3712 
3713 	mtu = *((int *)value);
3714 
3715 	if (IS_ENABLED(CONFIG_NET_IPV6_PMTU)) {
3716 		int ret;
3717 
3718 		ret = net_pmtu_update_mtu(&context->remote, mtu);
3719 		if (ret < 0) {
3720 			return ret;
3721 		}
3722 
3723 		return 0;
3724 	}
3725 
3726 	if (net_context_is_bound_to_iface(context)) {
3727 		iface = net_context_get_iface(context);
3728 	} else {
3729 		net_sa_family_t family = net_context_get_family(context);
3730 
3731 		if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
3732 			iface = net_if_ipv6_select_src_iface(
3733 				&net_sin6(&context->remote)->sin6_addr);
3734 		} else {
3735 			return -EAFNOSUPPORT;
3736 		}
3737 	}
3738 
3739 	net_if_set_mtu(iface, (uint16_t)mtu);
3740 
3741 	return 0;
3742 #else
3743 	ARG_UNUSED(context);
3744 	ARG_UNUSED(value);
3745 	ARG_UNUSED(len);
3746 
3747 	return -ENOTSUP;
3748 #endif
3749 }
3750 
set_context_ipv6_v6only(struct net_context * context,const void * value,uint32_t len)3751 static int set_context_ipv6_v6only(struct net_context *context,
3752 				   const void *value, uint32_t len)
3753 {
3754 #if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
3755 	return set_bool_option(&context->options.ipv6_v6only, value, len);
3756 #else
3757 	ARG_UNUSED(context);
3758 	ARG_UNUSED(value);
3759 	ARG_UNUSED(len);
3760 
3761 	return -ENOTSUP;
3762 #endif
3763 }
3764 
set_context_recv_pktinfo(struct net_context * context,const void * value,uint32_t len)3765 static int set_context_recv_pktinfo(struct net_context *context,
3766 				    const void *value, uint32_t len)
3767 {
3768 #if defined(CONFIG_NET_CONTEXT_RECV_PKTINFO)
3769 	return set_bool_option(&context->options.recv_pktinfo, value, len);
3770 #else
3771 	ARG_UNUSED(context);
3772 	ARG_UNUSED(value);
3773 	ARG_UNUSED(len);
3774 
3775 	return -ENOTSUP;
3776 #endif
3777 }
3778 
set_context_recv_hoplimit(struct net_context * context,const void * value,uint32_t len)3779 static int set_context_recv_hoplimit(struct net_context *context,
3780 				    const void *value, uint32_t len)
3781 {
3782 #if defined(CONFIG_NET_CONTEXT_RECV_HOPLIMIT)
3783 	if (net_context_get_type(context) == NET_SOCK_DGRAM) {
3784 		return set_bool_option(&context->options.recv_hoplimit, value, len);
3785 	}
3786 
3787 	return -ENOTSUP;
3788 #else
3789 	ARG_UNUSED(context);
3790 	ARG_UNUSED(value);
3791 	ARG_UNUSED(len);
3792 
3793 	return -ENOTSUP;
3794 #endif
3795 }
3796 
set_context_addr_preferences(struct net_context * context,const void * value,uint32_t len)3797 static int set_context_addr_preferences(struct net_context *context,
3798 					const void *value, uint32_t len)
3799 {
3800 #if defined(CONFIG_NET_IPV6)
3801 	return set_uint16_option(&context->options.addr_preferences,
3802 				 value, len);
3803 #else
3804 	ARG_UNUSED(context);
3805 	ARG_UNUSED(value);
3806 	ARG_UNUSED(len);
3807 
3808 	return -ENOTSUP;
3809 #endif
3810 }
3811 
set_context_timestamping(struct net_context * context,const void * value,uint32_t len)3812 static int set_context_timestamping(struct net_context *context,
3813 				    const void *value, uint32_t len)
3814 {
3815 #if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
3816 	uint8_t timestamping_flags = *((uint8_t *)value);
3817 
3818 	return set_uint8_option(&context->options.timestamping,
3819 				&timestamping_flags, len);
3820 #else
3821 	ARG_UNUSED(context);
3822 	ARG_UNUSED(value);
3823 	ARG_UNUSED(len);
3824 
3825 	return -ENOTSUP;
3826 #endif
3827 }
3828 
set_context_mcast_ifindex(struct net_context * context,const void * value,uint32_t len)3829 static int set_context_mcast_ifindex(struct net_context *context,
3830 				     const void *value, uint32_t len)
3831 {
3832 #if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
3833 	net_sa_family_t family = net_context_get_family(context);
3834 	int mcast_ifindex = *((int *)value);
3835 	enum net_sock_type type;
3836 	struct net_if *iface;
3837 
3838 	if ((IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) ||
3839 	    (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET)) {
3840 
3841 		if (len != sizeof(int)) {
3842 			return -EINVAL;
3843 		}
3844 
3845 		type = net_context_get_type(context);
3846 		if (type != NET_SOCK_DGRAM) {
3847 			return -EINVAL;
3848 		}
3849 
3850 		/* optlen equal to 0 then remove the binding */
3851 		if (mcast_ifindex == 0) {
3852 			context->options.ipv6_mcast_ifindex = 0;
3853 			return 0;
3854 		}
3855 
3856 		if (mcast_ifindex < 1 || mcast_ifindex > 255) {
3857 			return -EINVAL;
3858 		}
3859 
3860 		iface = net_if_get_by_index(mcast_ifindex);
3861 		if (iface == NULL) {
3862 			return -ENOENT;
3863 		}
3864 
3865 		if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
3866 			if (!net_if_flag_is_set(iface, NET_IF_IPV6)) {
3867 				return -EPROTOTYPE;
3868 			}
3869 		} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
3870 			if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
3871 				return -EPROTOTYPE;
3872 			}
3873 		}
3874 
3875 		context->options.ipv6_mcast_ifindex = mcast_ifindex;
3876 
3877 		return 0;
3878 	}
3879 
3880 	return -EAFNOSUPPORT;
3881 #else
3882 	ARG_UNUSED(context);
3883 	ARG_UNUSED(value);
3884 	ARG_UNUSED(len);
3885 
3886 	return -ENOTSUP;
3887 #endif
3888 }
3889 
set_context_local_port_range(struct net_context * context,const void * value,uint32_t len)3890 static int set_context_local_port_range(struct net_context *context,
3891 					const void *value, uint32_t len)
3892 {
3893 #if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)
3894 	uint16_t lower_range, upper_range;
3895 	uint32_t port_range;
3896 
3897 	if (len != sizeof(uint32_t)) {
3898 		return -EINVAL;
3899 	}
3900 
3901 	port_range = *((uint32_t *)value);
3902 	lower_range = port_range & 0xffff;
3903 	upper_range = port_range >> 16;
3904 
3905 	/* If the range is 0, then it means that the port range clamping
3906 	 * is disabled. If the range is not 0, then the lower range must
3907 	 * be smaller than the upper range.
3908 	 */
3909 	if (lower_range != 0U && upper_range != 0U &&
3910 	    lower_range >= upper_range) {
3911 		return -EINVAL;
3912 	}
3913 
3914 	/* If either of the range is 0, then that bound has no effect.
3915 	 * This is checked when the emphemeral port is selected.
3916 	 */
3917 	context->options.port_range = port_range;
3918 
3919 	return 0;
3920 #else
3921 	ARG_UNUSED(context);
3922 	ARG_UNUSED(value);
3923 	ARG_UNUSED(len);
3924 
3925 	return -ENOTSUP;
3926 #endif
3927 }
3928 
net_context_set_option(struct net_context * context,enum net_context_option option,const void * value,uint32_t len)3929 int net_context_set_option(struct net_context *context,
3930 			   enum net_context_option option,
3931 			   const void *value, uint32_t len)
3932 {
3933 	int ret = 0;
3934 
3935 	NET_ASSERT(context);
3936 
3937 	if (!PART_OF_ARRAY(contexts, context)) {
3938 		return -EINVAL;
3939 	}
3940 
3941 	k_mutex_lock(&context->lock, K_FOREVER);
3942 
3943 	switch (option) {
3944 	case NET_OPT_PRIORITY:
3945 		ret = set_context_priority(context, value, len);
3946 		break;
3947 	case NET_OPT_TXTIME:
3948 		ret = set_context_txtime(context, value, len);
3949 		break;
3950 	case NET_OPT_SOCKS5:
3951 		ret = set_context_proxy(context, value, len);
3952 		break;
3953 	case NET_OPT_RCVTIMEO:
3954 		ret = set_context_rcvtimeo(context, value, len);
3955 		break;
3956 	case NET_OPT_SNDTIMEO:
3957 		ret = set_context_sndtimeo(context, value, len);
3958 		break;
3959 	case NET_OPT_RCVBUF:
3960 		ret = set_context_rcvbuf(context, value, len);
3961 		break;
3962 	case NET_OPT_SNDBUF:
3963 		ret = set_context_sndbuf(context, value, len);
3964 		break;
3965 	case NET_OPT_DSCP_ECN:
3966 		ret = set_context_dscp_ecn(context, value, len);
3967 		break;
3968 	case NET_OPT_TTL:
3969 		ret = set_context_ttl(context, value, len);
3970 		break;
3971 	case NET_OPT_MCAST_TTL:
3972 		ret = set_context_mcast_ttl(context, value, len);
3973 		break;
3974 	case NET_OPT_MCAST_HOP_LIMIT:
3975 		ret = set_context_mcast_hop_limit(context, value, len);
3976 		break;
3977 	case NET_OPT_UNICAST_HOP_LIMIT:
3978 		ret = set_context_unicast_hop_limit(context, value, len);
3979 		break;
3980 	case NET_OPT_REUSEADDR:
3981 		ret = set_context_reuseaddr(context, value, len);
3982 		break;
3983 	case NET_OPT_REUSEPORT:
3984 		ret = set_context_reuseport(context, value, len);
3985 		break;
3986 	case NET_OPT_IPV6_V6ONLY:
3987 		ret = set_context_ipv6_v6only(context, value, len);
3988 		break;
3989 	case NET_OPT_RECV_PKTINFO:
3990 		ret = set_context_recv_pktinfo(context, value, len);
3991 		break;
3992 	case NET_OPT_ADDR_PREFERENCES:
3993 		ret = set_context_addr_preferences(context, value, len);
3994 		break;
3995 	case NET_OPT_TIMESTAMPING:
3996 		ret = set_context_timestamping(context, value, len);
3997 		break;
3998 	case NET_OPT_MTU:
3999 		/* IPv4 only supports getting the MTU */
4000 		if (IS_ENABLED(CONFIG_NET_IPV4) &&
4001 		    net_context_get_family(context) == NET_AF_INET) {
4002 			ret = -EOPNOTSUPP;
4003 		} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
4004 			   net_context_get_family(context) == NET_AF_INET6) {
4005 			ret = set_context_ipv6_mtu(context, value, len);
4006 		}
4007 
4008 		break;
4009 	case NET_OPT_MCAST_IFINDEX:
4010 		ret = set_context_mcast_ifindex(context, value, len);
4011 		break;
4012 	case NET_OPT_LOCAL_PORT_RANGE:
4013 		ret = set_context_local_port_range(context, value, len);
4014 		break;
4015 	case NET_OPT_IPV6_MCAST_LOOP:
4016 		ret = set_context_ipv6_mcast_loop(context, value, len);
4017 		break;
4018 	case NET_OPT_IPV4_MCAST_LOOP:
4019 		ret = set_context_ipv4_mcast_loop(context, value, len);
4020 		break;
4021 	case NET_OPT_RECV_HOPLIMIT:
4022 		ret = set_context_recv_hoplimit(context, value, len);
4023 		break;
4024 	}
4025 
4026 	k_mutex_unlock(&context->lock);
4027 
4028 	return ret;
4029 }
4030 
net_context_get_option(struct net_context * context,enum net_context_option option,void * value,uint32_t * len)4031 int net_context_get_option(struct net_context *context,
4032 			    enum net_context_option option,
4033 			    void *value, uint32_t *len)
4034 {
4035 	int ret = 0;
4036 
4037 	NET_ASSERT(context);
4038 
4039 	if (!PART_OF_ARRAY(contexts, context)) {
4040 		return -EINVAL;
4041 	}
4042 
4043 	k_mutex_lock(&context->lock, K_FOREVER);
4044 
4045 	switch (option) {
4046 	case NET_OPT_PRIORITY:
4047 		ret = get_context_priority(context, value, len);
4048 		break;
4049 	case NET_OPT_TXTIME:
4050 		ret = get_context_txtime(context, value, len);
4051 		break;
4052 	case NET_OPT_SOCKS5:
4053 		ret = get_context_proxy(context, value, len);
4054 		break;
4055 	case NET_OPT_RCVTIMEO:
4056 		ret = get_context_rcvtimeo(context, value, len);
4057 		break;
4058 	case NET_OPT_SNDTIMEO:
4059 		ret = get_context_sndtimeo(context, value, len);
4060 		break;
4061 	case NET_OPT_RCVBUF:
4062 		ret = get_context_rcvbuf(context, value, len);
4063 		break;
4064 	case NET_OPT_SNDBUF:
4065 		ret = get_context_sndbuf(context, value, len);
4066 		break;
4067 	case NET_OPT_DSCP_ECN:
4068 		ret = get_context_dscp_ecn(context, value, len);
4069 		break;
4070 	case NET_OPT_TTL:
4071 		ret = get_context_ttl(context, value, len);
4072 		break;
4073 	case NET_OPT_MCAST_TTL:
4074 		ret = get_context_mcast_ttl(context, value, len);
4075 		break;
4076 	case NET_OPT_MCAST_HOP_LIMIT:
4077 		ret = get_context_mcast_hop_limit(context, value, len);
4078 		break;
4079 	case NET_OPT_UNICAST_HOP_LIMIT:
4080 		ret = get_context_unicast_hop_limit(context, value, len);
4081 		break;
4082 	case NET_OPT_REUSEADDR:
4083 		ret = get_context_reuseaddr(context, value, len);
4084 		break;
4085 	case NET_OPT_REUSEPORT:
4086 		ret = get_context_reuseport(context, value, len);
4087 		break;
4088 	case NET_OPT_IPV6_V6ONLY:
4089 		ret = get_context_ipv6_v6only(context, value, len);
4090 		break;
4091 	case NET_OPT_RECV_PKTINFO:
4092 		ret = get_context_recv_pktinfo(context, value, len);
4093 		break;
4094 	case NET_OPT_ADDR_PREFERENCES:
4095 		ret = get_context_addr_preferences(context, value, len);
4096 		break;
4097 	case NET_OPT_TIMESTAMPING:
4098 		ret = get_context_timestamping(context, value, len);
4099 		break;
4100 	case NET_OPT_MTU:
4101 		ret = get_context_mtu(context, value, len);
4102 		break;
4103 	case NET_OPT_MCAST_IFINDEX:
4104 		ret = get_context_mcast_ifindex(context, value, len);
4105 		break;
4106 	case NET_OPT_LOCAL_PORT_RANGE:
4107 		ret = get_context_local_port_range(context, value, len);
4108 		break;
4109 	case NET_OPT_IPV6_MCAST_LOOP:
4110 		ret = get_context_ipv6_mcast_loop(context, value, len);
4111 		break;
4112 	case NET_OPT_IPV4_MCAST_LOOP:
4113 		ret = get_context_ipv4_mcast_loop(context, value, len);
4114 		break;
4115 	case NET_OPT_RECV_HOPLIMIT:
4116 		ret = get_context_recv_hoplimit(context, value, len);
4117 		break;
4118 	}
4119 
4120 	k_mutex_unlock(&context->lock);
4121 
4122 	return ret;
4123 }
4124 
net_context_get_local_addr(struct net_context * ctx,struct net_sockaddr * addr,net_socklen_t * addrlen)4125 int net_context_get_local_addr(struct net_context *ctx,
4126 			       struct net_sockaddr *addr,
4127 			       net_socklen_t *addrlen)
4128 {
4129 	if (ctx == NULL || addr == NULL || addrlen == NULL) {
4130 		return -EINVAL;
4131 	}
4132 
4133 	if (IS_ENABLED(CONFIG_NET_TCP) &&
4134 	    net_context_get_type(ctx) == NET_SOCK_STREAM) {
4135 		return net_tcp_endpoint_copy(ctx, addr, NULL, addrlen);
4136 	}
4137 
4138 	if (IS_ENABLED(CONFIG_NET_UDP) && net_context_get_type(ctx) == NET_SOCK_DGRAM) {
4139 		net_socklen_t newlen;
4140 
4141 		if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == NET_AF_INET) {
4142 			newlen = MIN(*addrlen, sizeof(struct net_sockaddr_in));
4143 
4144 			net_sin(addr)->sin_family = NET_AF_INET;
4145 			net_sin(addr)->sin_port = net_sin_ptr(&ctx->local)->sin_port;
4146 			memcpy(&net_sin(addr)->sin_addr,
4147 			       net_sin_ptr(&ctx->local)->sin_addr,
4148 			       sizeof(struct net_in_addr));
4149 
4150 		} else if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->local.family == NET_AF_INET6) {
4151 			newlen = MIN(*addrlen, sizeof(struct net_sockaddr_in6));
4152 
4153 			net_sin6(addr)->sin6_family = NET_AF_INET6;
4154 			net_sin6(addr)->sin6_port = net_sin6_ptr(&ctx->local)->sin6_port;
4155 			memcpy(&net_sin6(addr)->sin6_addr,
4156 			       net_sin6_ptr(&ctx->local)->sin6_addr,
4157 			       sizeof(struct net_in6_addr));
4158 		} else {
4159 			return -EAFNOSUPPORT;
4160 		}
4161 
4162 		*addrlen = newlen;
4163 
4164 		return 0;
4165 	}
4166 
4167 	return -ENOPROTOOPT;
4168 }
4169 
net_context_foreach(net_context_cb_t cb,void * user_data)4170 void net_context_foreach(net_context_cb_t cb, void *user_data)
4171 {
4172 	int i;
4173 
4174 	k_sem_take(&contexts_lock, K_FOREVER);
4175 
4176 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
4177 		if (!net_context_is_used(&contexts[i])) {
4178 			continue;
4179 		}
4180 
4181 		k_mutex_lock(&contexts[i].lock, K_FOREVER);
4182 
4183 		cb(&contexts[i], user_data);
4184 
4185 		k_mutex_unlock(&contexts[i].lock);
4186 	}
4187 
4188 	k_sem_give(&contexts_lock);
4189 }
4190 
net_context_state(struct net_context * context)4191 const char *net_context_state(struct net_context *context)
4192 {
4193 	switch (net_context_get_state(context)) {
4194 	case NET_CONTEXT_IDLE:
4195 		return "IDLE";
4196 	case NET_CONTEXT_CONNECTING:
4197 		return "CONNECTING";
4198 	case NET_CONTEXT_CONNECTED:
4199 		return "CONNECTED";
4200 	case NET_CONTEXT_LISTENING:
4201 		return "LISTENING";
4202 	}
4203 
4204 	return NULL;
4205 }
4206 
net_context_init(void)4207 void net_context_init(void)
4208 {
4209 	k_sem_init(&contexts_lock, 1, K_SEM_MAX_LIMIT);
4210 }
4211