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  *
11  * SPDX-License-Identifier: Apache-2.0
12  */
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(net_ctx, CONFIG_NET_CONTEXT_LOG_LEVEL);
16 
17 #include <zephyr/kernel.h>
18 #include <zephyr/random/random.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <stdbool.h>
22 
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/net/net_ip.h>
25 #include <zephyr/net/socket.h>
26 #include <zephyr/net/net_context.h>
27 #include <zephyr/net/net_offload.h>
28 #include <zephyr/net/ethernet.h>
29 #include <zephyr/net/socketcan.h>
30 #include <zephyr/net/ieee802154.h>
31 
32 #include "connection.h"
33 #include "net_private.h"
34 
35 #include "ipv6.h"
36 #include "ipv4.h"
37 #include "udp_internal.h"
38 #include "tcp_internal.h"
39 #include "net_stats.h"
40 
41 #if defined(CONFIG_NET_TCP)
42 #include "tcp.h"
43 #endif
44 
45 #ifndef EPFNOSUPPORT
46 /* Some old versions of newlib haven't got this defined in errno.h,
47  * Just use EPROTONOSUPPORT in this case
48  */
49 #define EPFNOSUPPORT EPROTONOSUPPORT
50 #endif
51 
52 #define PKT_WAIT_TIME K_SECONDS(1)
53 
54 #define NET_MAX_CONTEXT CONFIG_NET_MAX_CONTEXTS
55 
56 static struct net_context contexts[NET_MAX_CONTEXT];
57 
58 /* We need to lock the contexts array as these APIs are typically called
59  * from applications which are usually run in task context.
60  */
61 static struct k_sem contexts_lock;
62 
net_context_is_reuseaddr_set(struct net_context * context)63 bool net_context_is_reuseaddr_set(struct net_context *context)
64 {
65 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
66 	return context->options.reuseaddr;
67 #else
68 	return false;
69 #endif
70 }
71 
net_context_is_reuseport_set(struct net_context * context)72 bool net_context_is_reuseport_set(struct net_context *context)
73 {
74 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
75 	return context->options.reuseport;
76 #else
77 	return false;
78 #endif
79 }
80 
81 #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
is_in_tcp_listen_state(struct net_context * context)82 static inline bool is_in_tcp_listen_state(struct net_context *context)
83 {
84 #if defined(CONFIG_NET_TCP)
85 	if (net_context_get_type(context) == SOCK_STREAM &&
86 	    net_context_get_state(context) == NET_CONTEXT_LISTENING) {
87 		return true;
88 	}
89 
90 	return false;
91 #else
92 	return false;
93 #endif
94 }
95 
is_in_tcp_time_wait_state(struct net_context * context)96 static inline bool is_in_tcp_time_wait_state(struct net_context *context)
97 {
98 #if defined(CONFIG_NET_TCP)
99 	if (net_context_get_type(context) == SOCK_STREAM) {
100 		const struct tcp *tcp_conn = context->tcp;
101 
102 		if (net_tcp_get_state(tcp_conn) == TCP_TIME_WAIT) {
103 			return true;
104 		}
105 	}
106 
107 	return false;
108 #else
109 	return false;
110 #endif
111 }
112 
check_used_port(enum net_ip_protocol proto,uint16_t local_port,const struct sockaddr * local_addr,bool reuseaddr_set,bool reuseport_set)113 static int check_used_port(enum net_ip_protocol proto,
114 			   uint16_t local_port,
115 			   const struct sockaddr *local_addr,
116 			   bool reuseaddr_set,
117 			   bool reuseport_set)
118 
119 {
120 	int i;
121 
122 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
123 		if (!net_context_is_used(&contexts[i])) {
124 			continue;
125 		}
126 
127 		if (!(net_context_get_proto(&contexts[i]) == proto &&
128 		      net_sin((struct sockaddr *)&
129 			      contexts[i].local)->sin_port == local_port)) {
130 			continue;
131 		}
132 
133 		if (IS_ENABLED(CONFIG_NET_IPV6) &&
134 		    local_addr->sa_family == AF_INET6) {
135 			if (net_sin6_ptr(&contexts[i].local)->sin6_addr == NULL ||
136 			    net_sin6_ptr(&contexts[i].local)->sin6_family != AF_INET6) {
137 				continue;
138 			}
139 
140 			if ((net_ipv6_is_addr_unspecified(
141 					net_sin6_ptr(&contexts[i].local)->sin6_addr) ||
142 			     net_ipv6_is_addr_unspecified(
143 					&net_sin6(local_addr)->sin6_addr))) {
144 				if (reuseport_set &&
145 				    net_context_is_reuseport_set(&contexts[i])) {
146 					/* When both context have the REUSEPORT set, both
147 					 * may be unspecified.
148 					 */
149 					continue;
150 				} else if (reuseaddr_set &&
151 					   !is_in_tcp_listen_state(&contexts[i]) &&
152 					   !(net_ipv6_is_addr_unspecified(
153 						net_sin6_ptr(&contexts[i].local)->sin6_addr) &&
154 					     net_ipv6_is_addr_unspecified(
155 						&net_sin6(local_addr)->sin6_addr))) {
156 					/* In case of REUSEADDR, only one context may be
157 					 * bound to the unspecified address, but not both.
158 					 * Furthermore, in case the existing context is in
159 					 * TCP LISTEN state, we ignore the REUSEADDR option
160 					 * (Linux behavior).
161 					 */
162 					continue;
163 				} else {
164 					return -EEXIST;
165 				}
166 			}
167 
168 			if (net_ipv6_addr_cmp(
169 				    net_sin6_ptr(&contexts[i].local)->
170 							     sin6_addr,
171 				    &((struct sockaddr_in6 *)
172 				      local_addr)->sin6_addr)) {
173 				if (reuseport_set &&
174 				    net_context_is_reuseport_set(&contexts[i])) {
175 					/* When both context have the REUSEPORT set, both
176 					 * may be bound to exactly the same address.
177 					 */
178 					continue;
179 				} else if (reuseaddr_set &&
180 					   is_in_tcp_time_wait_state(&contexts[i])) {
181 					/* With REUSEADDR, the existing context must be
182 					 * in the TCP TIME_WAIT state.
183 					 */
184 					continue;
185 				} else {
186 					return -EEXIST;
187 				}
188 			}
189 		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
190 			   local_addr->sa_family == AF_INET) {
191 			if (net_sin_ptr(&contexts[i].local)->sin_addr == NULL ||
192 			    net_sin_ptr(&contexts[i].local)->sin_family != AF_INET) {
193 				continue;
194 			}
195 
196 			if ((net_ipv4_is_addr_unspecified(
197 					net_sin_ptr(&contexts[i].local)->sin_addr) ||
198 			     net_ipv4_is_addr_unspecified(
199 					&net_sin(local_addr)->sin_addr))) {
200 				if (reuseport_set &&
201 				    net_context_is_reuseport_set(&contexts[i])) {
202 					/* When both context have the REUSEPORT set, both
203 					 * may be unspecified.
204 					 */
205 					continue;
206 				} else if (reuseaddr_set &&
207 					   !is_in_tcp_listen_state(&contexts[i]) &&
208 					   !(net_ipv4_is_addr_unspecified(
209 						net_sin_ptr(&contexts[i].local)->sin_addr) &&
210 					     net_ipv4_is_addr_unspecified(
211 						&net_sin(local_addr)->sin_addr))) {
212 					/* In case of REUSEADDR, only one context may be
213 					 * bound to the unspecified address, but not both.
214 					 * Furthermore, in case the existing context is in
215 					 * TCP LISTEN state, we ignore the REUSEADDR option
216 					 * (Linux behavior).
217 					 */
218 					continue;
219 				} else {
220 					return -EEXIST;
221 				}
222 			}
223 
224 			if (net_ipv4_addr_cmp(
225 				    net_sin_ptr(&contexts[i].local)->
226 							      sin_addr,
227 				    &((struct sockaddr_in *)
228 				      local_addr)->sin_addr)) {
229 				if (reuseport_set &&
230 				    net_context_is_reuseport_set(&contexts[i])) {
231 					/* When both context have the REUSEPORT set, both
232 					 * may be bound to exactly the same address.
233 					 */
234 					continue;
235 				} else if (reuseaddr_set &&
236 					   is_in_tcp_time_wait_state(&contexts[i])) {
237 					/* With REUSEADDR, the existing context must be
238 					 * in the TCP TIME_WAIT state.
239 					 */
240 					continue;
241 				} else {
242 					return -EEXIST;
243 				}
244 			}
245 		}
246 	}
247 
248 	return 0;
249 }
250 
find_available_port(struct net_context * context,const struct sockaddr * addr)251 static uint16_t find_available_port(struct net_context *context,
252 				    const struct sockaddr *addr)
253 {
254 	uint16_t local_port;
255 
256 	do {
257 		local_port = sys_rand32_get() | 0x8000;
258 	} while (check_used_port(net_context_get_proto(context),
259 				 htons(local_port), addr, false, false) == -EEXIST);
260 
261 	return htons(local_port);
262 }
263 #else
264 #define check_used_port(...) 0
265 #define find_available_port(...) 0
266 #endif
267 
net_context_port_in_use(enum net_ip_protocol proto,uint16_t local_port,const struct sockaddr * local_addr)268 bool net_context_port_in_use(enum net_ip_protocol proto,
269 			   uint16_t local_port,
270 			   const struct sockaddr *local_addr)
271 {
272 	return check_used_port(proto, htons(local_port), local_addr, false, false) != 0;
273 }
274 
275 #if defined(CONFIG_NET_CONTEXT_CHECK)
net_context_check(sa_family_t family,enum net_sock_type type,uint16_t proto,struct net_context ** context)276 static int net_context_check(sa_family_t family, enum net_sock_type type,
277 			     uint16_t proto, struct net_context **context)
278 {
279 	switch (family) {
280 	case AF_INET:
281 	case AF_INET6:
282 		if (family == AF_INET && !IS_ENABLED(CONFIG_NET_IPV4)) {
283 			NET_DBG("IPv4 disabled");
284 			return -EPFNOSUPPORT;
285 		}
286 		if (family == AF_INET6 && !IS_ENABLED(CONFIG_NET_IPV6)) {
287 			NET_DBG("IPv6 disabled");
288 			return -EPFNOSUPPORT;
289 		}
290 		if (!IS_ENABLED(CONFIG_NET_UDP)) {
291 			if (type == SOCK_DGRAM) {
292 				NET_DBG("DGRAM socket type disabled.");
293 				return -EPROTOTYPE;
294 			}
295 			if (proto == IPPROTO_UDP) {
296 				NET_DBG("UDP disabled");
297 				return -EPROTONOSUPPORT;
298 			}
299 		}
300 		if (!IS_ENABLED(CONFIG_NET_TCP)) {
301 			if (type == SOCK_STREAM) {
302 				NET_DBG("STREAM socket type disabled.");
303 				return -EPROTOTYPE;
304 			}
305 			if (proto == IPPROTO_TCP) {
306 				NET_DBG("TCP disabled");
307 				return -EPROTONOSUPPORT;
308 			}
309 		}
310 		switch (type) {
311 		case SOCK_DGRAM:
312 			if (proto != IPPROTO_UDP) {
313 				NET_DBG("Context type and protocol mismatch,"
314 					" type %d proto %d", type, proto);
315 				return -EPROTONOSUPPORT;
316 			}
317 			break;
318 		case SOCK_STREAM:
319 			if (proto != IPPROTO_TCP) {
320 				NET_DBG("Context type and protocol mismatch,"
321 					" type %d proto %d", type, proto);
322 				return -EPROTONOSUPPORT;
323 			}
324 			break;
325 		case SOCK_RAW:
326 			break;
327 		default:
328 			NET_DBG("Unknown context type.");
329 			return -EPROTOTYPE;
330 		}
331 		break;
332 
333 	case AF_PACKET:
334 		if (!IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
335 			NET_DBG("AF_PACKET disabled");
336 			return -EPFNOSUPPORT;
337 		}
338 		if (type != SOCK_RAW && type != SOCK_DGRAM) {
339 			NET_DBG("AF_PACKET only supports RAW and DGRAM socket "
340 				"types.");
341 			return -EPROTOTYPE;
342 		}
343 		break;
344 
345 	case AF_CAN:
346 		if (!IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
347 			NET_DBG("AF_CAN disabled");
348 			return -EPFNOSUPPORT;
349 		}
350 		if (type != SOCK_RAW) {
351 			NET_DBG("AF_CAN only supports RAW socket type.");
352 			return -EPROTOTYPE;
353 		}
354 		if (proto != CAN_RAW) {
355 			NET_DBG("AF_CAN only supports RAW_CAN protocol.");
356 			return -EPROTOTYPE;
357 		}
358 		break;
359 
360 	default:
361 		NET_DBG("Unknown address family %d", family);
362 		return -EAFNOSUPPORT;
363 	}
364 
365 	if (!context) {
366 		NET_DBG("Invalid context");
367 		return -EINVAL;
368 	}
369 
370 	return 0;
371 }
372 #endif /* CONFIG_NET_CONTEXT_CHECK */
373 
net_context_get(sa_family_t family,enum net_sock_type type,uint16_t proto,struct net_context ** context)374 int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto,
375 		    struct net_context **context)
376 {
377 	int i, ret;
378 
379 	if (IS_ENABLED(CONFIG_NET_CONTEXT_CHECK)) {
380 		ret = net_context_check(family, type, proto, context);
381 		if (ret < 0) {
382 			return ret;
383 		}
384 	}
385 
386 	k_sem_take(&contexts_lock, K_FOREVER);
387 
388 	ret = -ENOENT;
389 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
390 		if (net_context_is_used(&contexts[i])) {
391 			continue;
392 		}
393 
394 		memset(&contexts[i], 0, sizeof(contexts[i]));
395 		/* FIXME - Figure out a way to get the correct network interface
396 		 * as it is not known at this point yet.
397 		 */
398 		if (!net_if_is_ip_offloaded(net_if_get_default())
399 			&& proto == IPPROTO_TCP) {
400 			if (net_tcp_get(&contexts[i]) < 0) {
401 				break;
402 			}
403 		}
404 
405 		contexts[i].iface = -1;
406 		contexts[i].flags = 0U;
407 		atomic_set(&contexts[i].refcount, 1);
408 
409 		net_context_set_family(&contexts[i], family);
410 		net_context_set_type(&contexts[i], type);
411 		net_context_set_proto(&contexts[i], proto);
412 
413 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
414 		contexts[i].options.rcvtimeo = K_FOREVER;
415 #endif
416 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
417 		contexts[i].options.sndtimeo = K_FOREVER;
418 #endif
419 
420 		if (IS_ENABLED(CONFIG_NET_IP)) {
421 			(void)memset(&contexts[i].remote, 0, sizeof(struct sockaddr));
422 			(void)memset(&contexts[i].local, 0, sizeof(struct sockaddr_ptr));
423 
424 			if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
425 				struct sockaddr_in6 *addr6 =
426 					(struct sockaddr_in6 *)&contexts[i].local;
427 				addr6->sin6_port =
428 					find_available_port(&contexts[i], (struct sockaddr *)addr6);
429 
430 				if (!addr6->sin6_port) {
431 					ret = -EADDRINUSE;
432 					break;
433 				}
434 			}
435 			if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
436 				struct sockaddr_in *addr = (struct sockaddr_in *)&contexts[i].local;
437 
438 				addr->sin_port =
439 					find_available_port(&contexts[i], (struct sockaddr *)addr);
440 
441 				if (!addr->sin_port) {
442 					ret = -EADDRINUSE;
443 					break;
444 				}
445 			}
446 		}
447 
448 		if (IS_ENABLED(CONFIG_NET_CONTEXT_SYNC_RECV)) {
449 			k_sem_init(&contexts[i].recv_data_wait, 1, K_SEM_MAX_LIMIT);
450 		}
451 
452 		k_mutex_init(&contexts[i].lock);
453 
454 		contexts[i].flags |= NET_CONTEXT_IN_USE;
455 		*context = &contexts[i];
456 
457 		ret = 0;
458 		break;
459 	}
460 
461 	k_sem_give(&contexts_lock);
462 
463 	if (ret < 0) {
464 		return ret;
465 	}
466 
467 	/* FIXME - Figure out a way to get the correct network interface
468 	 * as it is not known at this point yet.
469 	 */
470 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(net_if_get_default())) {
471 		ret = net_offload_get(net_if_get_default(), family, type, proto, context);
472 		if (ret < 0) {
473 			(*context)->flags &= ~NET_CONTEXT_IN_USE;
474 			*context = NULL;
475 			return ret;
476 		}
477 
478 		net_context_set_iface(*context, net_if_get_default());
479 	}
480 
481 	return 0;
482 }
483 
net_context_ref(struct net_context * context)484 int net_context_ref(struct net_context *context)
485 {
486 	int old_rc = atomic_inc(&context->refcount);
487 
488 	return old_rc + 1;
489 }
490 
net_context_unref(struct net_context * context)491 int net_context_unref(struct net_context *context)
492 {
493 	int old_rc = atomic_dec(&context->refcount);
494 
495 	if (old_rc != 1) {
496 		return old_rc - 1;
497 	}
498 
499 	k_mutex_lock(&context->lock, K_FOREVER);
500 
501 	if (context->conn_handler) {
502 		if (IS_ENABLED(CONFIG_NET_TCP) || IS_ENABLED(CONFIG_NET_UDP) ||
503 		    IS_ENABLED(CONFIG_NET_SOCKETS_CAN) ||
504 		    IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
505 			net_conn_unregister(context->conn_handler);
506 		}
507 
508 		context->conn_handler = NULL;
509 	}
510 
511 	net_context_set_state(context, NET_CONTEXT_UNCONNECTED);
512 
513 	context->flags &= ~NET_CONTEXT_IN_USE;
514 
515 	NET_DBG("Context %p released", context);
516 
517 	k_mutex_unlock(&context->lock);
518 
519 	return 0;
520 }
521 
net_context_put(struct net_context * context)522 int net_context_put(struct net_context *context)
523 {
524 	int ret = 0;
525 
526 	NET_ASSERT(context);
527 
528 	if (!PART_OF_ARRAY(contexts, context)) {
529 		return -EINVAL;
530 	}
531 
532 	k_mutex_lock(&context->lock, K_FOREVER);
533 
534 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
535 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
536 		context->flags &= ~NET_CONTEXT_IN_USE;
537 		ret = net_offload_put(net_context_get_iface(context), context);
538 		goto unlock;
539 	}
540 
541 	context->connect_cb = NULL;
542 	context->recv_cb = NULL;
543 	context->send_cb = NULL;
544 
545 	/* net_tcp_put() will handle decrementing refcount on stack's behalf */
546 	net_tcp_put(context);
547 
548 	/* Decrement refcount on user app's behalf */
549 	net_context_unref(context);
550 
551 unlock:
552 	k_mutex_unlock(&context->lock);
553 
554 	return ret;
555 }
556 
557 /* If local address is not bound, bind it to INADDR_ANY and random port. */
bind_default(struct net_context * context)558 static int bind_default(struct net_context *context)
559 {
560 	sa_family_t family = net_context_get_family(context);
561 
562 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
563 		struct sockaddr_in6 addr6;
564 
565 		if (net_sin6_ptr(&context->local)->sin6_addr) {
566 			return 0;
567 		}
568 
569 		addr6.sin6_family = AF_INET6;
570 		memcpy(&addr6.sin6_addr, net_ipv6_unspecified_address(),
571 		       sizeof(addr6.sin6_addr));
572 		addr6.sin6_port =
573 			find_available_port(context,
574 					    (struct sockaddr *)&addr6);
575 
576 		return net_context_bind(context, (struct sockaddr *)&addr6,
577 					sizeof(addr6));
578 	}
579 
580 	if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
581 		struct sockaddr_in addr4;
582 
583 		if (net_sin_ptr(&context->local)->sin_addr) {
584 			return 0;
585 		}
586 
587 		addr4.sin_family = AF_INET;
588 		addr4.sin_addr.s_addr = INADDR_ANY;
589 		addr4.sin_port =
590 			find_available_port(context,
591 					    (struct sockaddr *)&addr4);
592 
593 		return net_context_bind(context, (struct sockaddr *)&addr4,
594 					sizeof(addr4));
595 	}
596 
597 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && family == AF_PACKET) {
598 		struct sockaddr_ll ll_addr;
599 
600 		if (net_sll_ptr(&context->local)->sll_addr) {
601 			return 0;
602 		}
603 
604 		ll_addr.sll_family = AF_PACKET;
605 		ll_addr.sll_protocol = htons(ETH_P_ALL);
606 		ll_addr.sll_ifindex = net_if_get_by_iface(net_if_get_default());
607 
608 		return net_context_bind(context, (struct sockaddr *)&ll_addr,
609 					sizeof(ll_addr));
610 	}
611 
612 	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN) {
613 		struct sockaddr_can can_addr;
614 
615 		if (context->iface >= 0) {
616 			return 0;
617 		} else {
618 #if defined(CONFIG_NET_L2_CANBUS_RAW)
619 			struct net_if *iface;
620 
621 			iface = net_if_get_first_by_type(
622 						&NET_L2_GET_NAME(CANBUS_RAW));
623 			if (!iface) {
624 				return -ENOENT;
625 			}
626 
627 			can_addr.can_ifindex = net_if_get_by_iface(iface);
628 			context->iface = can_addr.can_ifindex;
629 #else
630 			return -ENOENT;
631 #endif
632 		}
633 
634 		can_addr.can_family = AF_CAN;
635 
636 		return net_context_bind(context, (struct sockaddr *)&can_addr,
637 					sizeof(can_addr));
638 	}
639 
640 	return -EINVAL;
641 }
642 
net_context_bind(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen)643 int net_context_bind(struct net_context *context, const struct sockaddr *addr,
644 		     socklen_t addrlen)
645 {
646 	int ret;
647 
648 	NET_ASSERT(addr);
649 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
650 
651 	/* If we already have connection handler, then it effectively
652 	 * means that it's already bound to an interface/port, and we
653 	 * don't support rebinding connection to new address/port in
654 	 * the code below.
655 	 * TODO: Support rebinding.
656 	 */
657 	if (context->conn_handler) {
658 		return -EISCONN;
659 	}
660 
661 	if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) {
662 		struct net_if *iface = NULL;
663 		struct in6_addr *ptr;
664 		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
665 
666 		if (addrlen < sizeof(struct sockaddr_in6)) {
667 			return -EINVAL;
668 		}
669 
670 		if (net_context_is_bound_to_iface(context)) {
671 			iface = net_context_get_iface(context);
672 		}
673 
674 		if (net_ipv6_is_addr_mcast(&addr6->sin6_addr)) {
675 			struct net_if_mcast_addr *maddr;
676 
677 			maddr = net_if_ipv6_maddr_lookup(&addr6->sin6_addr,
678 							 &iface);
679 			if (!maddr) {
680 				return -ENOENT;
681 			}
682 
683 			ptr = &maddr->address.in6_addr;
684 
685 		} else if (net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
686 			if (iface == NULL) {
687 				iface = net_if_ipv6_select_src_iface(
688 					&net_sin6(&context->remote)->sin6_addr);
689 			}
690 
691 			ptr = (struct in6_addr *)net_ipv6_unspecified_address();
692 		} else {
693 			struct net_if_addr *ifaddr;
694 
695 			ifaddr = net_if_ipv6_addr_lookup(
696 					&addr6->sin6_addr,
697 					iface == NULL ? &iface : NULL);
698 			if (!ifaddr) {
699 				return -ENOENT;
700 			}
701 
702 			ptr = &ifaddr->address.in6_addr;
703 		}
704 
705 		if (!iface) {
706 			NET_ERR("Cannot bind to %s",
707 				net_sprint_ipv6_addr(&addr6->sin6_addr));
708 
709 			return -EADDRNOTAVAIL;
710 		}
711 
712 		k_mutex_lock(&context->lock, K_FOREVER);
713 
714 		net_context_set_iface(context, iface);
715 
716 		net_sin6_ptr(&context->local)->sin6_family = AF_INET6;
717 		net_sin6_ptr(&context->local)->sin6_addr = ptr;
718 
719 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) {
720 			k_mutex_unlock(&context->lock);
721 			return net_offload_bind(iface, context, addr, addrlen);
722 		}
723 
724 		ret = 0;
725 		if (addr6->sin6_port) {
726 			ret = check_used_port(context->proto,
727 					      addr6->sin6_port,
728 					      addr,
729 					      net_context_is_reuseaddr_set(context),
730 					      net_context_is_reuseport_set(context));
731 			if (ret != 0) {
732 				NET_ERR("Port %d is in use!",
733 					ntohs(addr6->sin6_port));
734 				ret = -EADDRINUSE;
735 				goto unlock_ipv6;
736 			} else {
737 				net_sin6_ptr(&context->local)->sin6_port =
738 					addr6->sin6_port;
739 			}
740 		} else {
741 			addr6->sin6_port =
742 				net_sin6_ptr(&context->local)->sin6_port;
743 		}
744 
745 		NET_DBG("Context %p binding to %s [%s]:%d iface %d (%p)",
746 			context,
747 			net_proto2str(AF_INET6,
748 				      net_context_get_proto(context)),
749 			net_sprint_ipv6_addr(ptr),
750 			ntohs(addr6->sin6_port),
751 			net_if_get_by_iface(iface), iface);
752 
753 	unlock_ipv6:
754 		k_mutex_unlock(&context->lock);
755 
756 		return ret;
757 	}
758 
759 	if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
760 		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
761 		struct net_if *iface = NULL;
762 		struct net_if_addr *ifaddr;
763 		struct in_addr *ptr;
764 
765 		if (addrlen < sizeof(struct sockaddr_in)) {
766 			return -EINVAL;
767 		}
768 
769 		if (net_context_is_bound_to_iface(context)) {
770 			iface = net_context_get_iface(context);
771 		}
772 
773 		if (net_ipv4_is_addr_mcast(&addr4->sin_addr)) {
774 			struct net_if_mcast_addr *maddr;
775 
776 			maddr = net_if_ipv4_maddr_lookup(&addr4->sin_addr,
777 							 &iface);
778 			if (!maddr) {
779 				return -ENOENT;
780 			}
781 
782 			ptr = &maddr->address.in_addr;
783 
784 		} else if (addr4->sin_addr.s_addr == INADDR_ANY) {
785 			if (iface == NULL) {
786 				iface = net_if_ipv4_select_src_iface(
787 					&net_sin(&context->remote)->sin_addr);
788 			}
789 
790 			ptr = (struct in_addr *)net_ipv4_unspecified_address();
791 		} else {
792 			ifaddr = net_if_ipv4_addr_lookup(
793 					&addr4->sin_addr,
794 					iface == NULL ? &iface : NULL);
795 			if (!ifaddr) {
796 				return -ENOENT;
797 			}
798 
799 			ptr = &ifaddr->address.in_addr;
800 		}
801 
802 		if (!iface) {
803 			NET_ERR("Cannot bind to %s",
804 				net_sprint_ipv4_addr(&addr4->sin_addr));
805 
806 			return -EADDRNOTAVAIL;
807 		}
808 
809 		k_mutex_lock(&context->lock, K_FOREVER);
810 
811 		net_context_set_iface(context, iface);
812 
813 		net_sin_ptr(&context->local)->sin_family = AF_INET;
814 		net_sin_ptr(&context->local)->sin_addr = ptr;
815 
816 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) {
817 			k_mutex_unlock(&context->lock);
818 			return net_offload_bind(iface, context, addr, addrlen);
819 		}
820 
821 		ret = 0;
822 		if (addr4->sin_port) {
823 			ret = check_used_port(context->proto,
824 					      addr4->sin_port,
825 					      addr,
826 					      net_context_is_reuseaddr_set(context),
827 					      net_context_is_reuseport_set(context));
828 			if (ret != 0) {
829 				NET_ERR("Port %d is in use!",
830 					ntohs(addr4->sin_port));
831 					ret = -EADDRINUSE;
832 				goto unlock_ipv4;
833 			} else {
834 				net_sin_ptr(&context->local)->sin_port =
835 					addr4->sin_port;
836 			}
837 		} else {
838 			addr4->sin_port =
839 				net_sin_ptr(&context->local)->sin_port;
840 		}
841 
842 		NET_DBG("Context %p binding to %s %s:%d iface %d (%p)",
843 			context,
844 			net_proto2str(AF_INET,
845 				      net_context_get_proto(context)),
846 			net_sprint_ipv4_addr(ptr),
847 			ntohs(addr4->sin_port),
848 			net_if_get_by_iface(iface), iface);
849 
850 	unlock_ipv4:
851 		k_mutex_unlock(&context->lock);
852 
853 		return ret;
854 	}
855 
856 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
857 	    addr->sa_family == AF_PACKET) {
858 		struct sockaddr_ll *ll_addr = (struct sockaddr_ll *)addr;
859 		struct net_if *iface = NULL;
860 
861 		if (addrlen < sizeof(struct sockaddr_ll)) {
862 			return -EINVAL;
863 		}
864 
865 		if (ll_addr->sll_ifindex < 0) {
866 			return -EINVAL;
867 		}
868 
869 		iface = net_if_get_by_index(ll_addr->sll_ifindex);
870 		if (!iface) {
871 			NET_ERR("Cannot bind to interface index %d",
872 				ll_addr->sll_ifindex);
873 			return -EADDRNOTAVAIL;
874 		}
875 
876 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
877 		    net_if_is_ip_offloaded(iface)) {
878 			net_context_set_iface(context, iface);
879 
880 			return net_offload_bind(iface,
881 						context,
882 						addr,
883 						addrlen);
884 		}
885 
886 		k_mutex_lock(&context->lock, K_FOREVER);
887 
888 		net_context_set_iface(context, iface);
889 
890 		net_sll_ptr(&context->local)->sll_family = AF_PACKET;
891 		net_sll_ptr(&context->local)->sll_ifindex =
892 			ll_addr->sll_ifindex;
893 		net_sll_ptr(&context->local)->sll_protocol =
894 			ll_addr->sll_protocol;
895 
896 		net_if_lock(iface);
897 		net_sll_ptr(&context->local)->sll_addr =
898 			net_if_get_link_addr(iface)->addr;
899 		net_sll_ptr(&context->local)->sll_halen =
900 			net_if_get_link_addr(iface)->len;
901 		net_if_unlock(iface);
902 
903 		NET_DBG("Context %p bind to type 0x%04x iface[%d] %p addr %s",
904 			context, htons(net_context_get_proto(context)),
905 			ll_addr->sll_ifindex, iface,
906 			net_sprint_ll_addr(
907 				net_sll_ptr(&context->local)->sll_addr,
908 				net_sll_ptr(&context->local)->sll_halen));
909 
910 		k_mutex_unlock(&context->lock);
911 
912 		return 0;
913 	}
914 
915 	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && addr->sa_family == AF_CAN) {
916 		struct sockaddr_can *can_addr = (struct sockaddr_can *)addr;
917 		struct net_if *iface = NULL;
918 
919 		if (addrlen < sizeof(struct sockaddr_can)) {
920 			return -EINVAL;
921 		}
922 
923 		if (can_addr->can_ifindex < 0) {
924 			return -EINVAL;
925 		}
926 
927 		iface = net_if_get_by_index(can_addr->can_ifindex);
928 		if (!iface) {
929 			NET_ERR("Cannot bind to interface index %d",
930 				can_addr->can_ifindex);
931 			return -EADDRNOTAVAIL;
932 		}
933 
934 		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
935 		    net_if_is_ip_offloaded(iface)) {
936 			net_context_set_iface(context, iface);
937 
938 			return net_offload_bind(iface,
939 						context,
940 						addr,
941 						addrlen);
942 		}
943 
944 		k_mutex_lock(&context->lock, K_FOREVER);
945 
946 		net_context_set_iface(context, iface);
947 		net_context_set_family(context, AF_CAN);
948 
949 		net_can_ptr(&context->local)->can_family = AF_CAN;
950 		net_can_ptr(&context->local)->can_ifindex =
951 			can_addr->can_ifindex;
952 
953 		NET_DBG("Context %p binding to %d iface[%d] %p",
954 			context, net_context_get_proto(context),
955 			can_addr->can_ifindex, iface);
956 
957 		k_mutex_unlock(&context->lock);
958 
959 		return 0;
960 	}
961 
962 	return -EINVAL;
963 }
964 
find_context(void * conn_handler)965 static inline struct net_context *find_context(void *conn_handler)
966 {
967 	int i;
968 
969 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
970 		if (!net_context_is_used(&contexts[i])) {
971 			continue;
972 		}
973 
974 		if (contexts[i].conn_handler == conn_handler) {
975 			return &contexts[i];
976 		}
977 	}
978 
979 	return NULL;
980 }
981 
net_context_listen(struct net_context * context,int backlog)982 int net_context_listen(struct net_context *context, int backlog)
983 {
984 	ARG_UNUSED(backlog);
985 
986 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
987 
988 	if (!net_context_is_used(context)) {
989 		return -EBADF;
990 	}
991 
992 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
993 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
994 		return net_offload_listen(net_context_get_iface(context),
995 					  context, backlog);
996 	}
997 
998 	k_mutex_lock(&context->lock, K_FOREVER);
999 
1000 	if (net_tcp_listen(context) >= 0) {
1001 		k_mutex_unlock(&context->lock);
1002 		return 0;
1003 	}
1004 
1005 	k_mutex_unlock(&context->lock);
1006 
1007 	return -EOPNOTSUPP;
1008 }
1009 
1010 #if defined(CONFIG_NET_IPV4)
net_context_create_ipv4_new(struct net_context * context,struct net_pkt * pkt,const struct in_addr * src,const struct in_addr * dst)1011 int net_context_create_ipv4_new(struct net_context *context,
1012 				struct net_pkt *pkt,
1013 				const struct in_addr *src,
1014 				const struct in_addr *dst)
1015 {
1016 	if (!src) {
1017 		NET_ASSERT(((
1018 			struct sockaddr_in_ptr *)&context->local)->sin_addr);
1019 
1020 		src = ((struct sockaddr_in_ptr *)&context->local)->sin_addr;
1021 	}
1022 
1023 	if (net_ipv4_is_addr_unspecified(src)
1024 	    || net_ipv4_is_addr_mcast(src)) {
1025 		src = net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
1026 						  (struct in_addr *)dst);
1027 		/* If src address is still unspecified, do not create pkt */
1028 		if (net_ipv4_is_addr_unspecified(src)) {
1029 			NET_DBG("DROP: src addr is unspecified");
1030 			return -EINVAL;
1031 		}
1032 	}
1033 
1034 	net_pkt_set_ipv4_ttl(pkt, net_context_get_ipv4_ttl(context));
1035 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
1036 	net_pkt_set_ip_dscp(pkt, net_ipv4_get_dscp(context->options.dscp_ecn));
1037 	net_pkt_set_ip_ecn(pkt, net_ipv4_get_ecn(context->options.dscp_ecn));
1038 	/* Direct priority takes precedence over DSCP */
1039 	if (!IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
1040 		net_pkt_set_priority(pkt, net_ipv4_dscp_to_priority(
1041 			net_ipv4_get_dscp(context->options.dscp_ecn)));
1042 	}
1043 #endif
1044 
1045 	return net_ipv4_create(pkt, src, dst);
1046 }
1047 #endif /* CONFIG_NET_IPV4 */
1048 
1049 #if defined(CONFIG_NET_IPV6)
net_context_create_ipv6_new(struct net_context * context,struct net_pkt * pkt,const struct in6_addr * src,const struct in6_addr * dst)1050 int net_context_create_ipv6_new(struct net_context *context,
1051 				struct net_pkt *pkt,
1052 				const struct in6_addr *src,
1053 				const struct in6_addr *dst)
1054 {
1055 	if (!src) {
1056 		NET_ASSERT(((
1057 			struct sockaddr_in6_ptr *)&context->local)->sin6_addr);
1058 
1059 		src = ((struct sockaddr_in6_ptr *)&context->local)->sin6_addr;
1060 	}
1061 
1062 	if (net_ipv6_is_addr_unspecified(src)
1063 	    || net_ipv6_is_addr_mcast(src)) {
1064 		src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
1065 						  (struct in6_addr *)dst);
1066 	}
1067 
1068 	net_pkt_set_ipv6_hop_limit(pkt,
1069 				   net_context_get_ipv6_hop_limit(context));
1070 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
1071 	net_pkt_set_ip_dscp(pkt, net_ipv6_get_dscp(context->options.dscp_ecn));
1072 	net_pkt_set_ip_ecn(pkt, net_ipv6_get_ecn(context->options.dscp_ecn));
1073 	/* Direct priority takes precedence over DSCP */
1074 	if (!IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
1075 		net_pkt_set_priority(pkt, net_ipv6_dscp_to_priority(
1076 			net_ipv6_get_dscp(context->options.dscp_ecn)));
1077 	}
1078 #endif
1079 
1080 	return net_ipv6_create(pkt, src, dst);
1081 }
1082 #endif /* CONFIG_NET_IPV6 */
1083 
net_context_connect(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen,net_context_connect_cb_t cb,k_timeout_t timeout,void * user_data)1084 int net_context_connect(struct net_context *context,
1085 			const struct sockaddr *addr,
1086 			socklen_t addrlen,
1087 			net_context_connect_cb_t cb,
1088 			k_timeout_t timeout,
1089 			void *user_data)
1090 {
1091 	struct sockaddr *laddr = NULL;
1092 	struct sockaddr local_addr __unused;
1093 	uint16_t lport, rport;
1094 	int ret;
1095 
1096 	NET_ASSERT(addr);
1097 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
1098 
1099 	k_mutex_lock(&context->lock, K_FOREVER);
1100 
1101 	if (net_context_get_state(context) == NET_CONTEXT_CONNECTING) {
1102 		ret = -EALREADY;
1103 		goto unlock;
1104 	}
1105 
1106 	if (!net_context_is_used(context)) {
1107 		ret = -EBADF;
1108 		goto unlock;
1109 	}
1110 
1111 	if (addr->sa_family != net_context_get_family(context)) {
1112 		NET_ASSERT(addr->sa_family == net_context_get_family(context),
1113 			   "Family mismatch %d should be %d",
1114 			   addr->sa_family,
1115 			   net_context_get_family(context));
1116 		ret = -EINVAL;
1117 		goto unlock;
1118 	}
1119 
1120 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
1121 	    addr->sa_family == AF_PACKET) {
1122 		ret = -EOPNOTSUPP;
1123 		goto unlock;
1124 	}
1125 
1126 	if (net_context_get_state(context) == NET_CONTEXT_LISTENING) {
1127 		ret = -EOPNOTSUPP;
1128 		goto unlock;
1129 	}
1130 
1131 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
1132 	    net_context_get_family(context) == AF_INET6) {
1133 		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)
1134 							&context->remote;
1135 
1136 		if (addrlen < sizeof(struct sockaddr_in6)) {
1137 			ret = -EINVAL;
1138 			goto unlock;
1139 		}
1140 
1141 		if (net_context_get_proto(context) == IPPROTO_TCP &&
1142 		    net_ipv6_is_addr_mcast(&addr6->sin6_addr)) {
1143 			ret = -EADDRNOTAVAIL;
1144 			goto unlock;
1145 		}
1146 
1147 		memcpy(&addr6->sin6_addr, &net_sin6(addr)->sin6_addr,
1148 		       sizeof(struct in6_addr));
1149 
1150 		addr6->sin6_port = net_sin6(addr)->sin6_port;
1151 		addr6->sin6_family = AF_INET6;
1152 
1153 		if (!net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
1154 			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
1155 		} else {
1156 			context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
1157 		}
1158 
1159 		rport = addr6->sin6_port;
1160 
1161 		/* The binding must be done after we have set the remote
1162 		 * address but before checking the local address. Otherwise
1163 		 * the laddr might not be set properly which would then cause
1164 		 * issues when doing net_tcp_connect(). This issue was seen
1165 		 * with socket tests and when connecting to loopback interface.
1166 		 */
1167 		ret = bind_default(context);
1168 		if (ret) {
1169 			goto unlock;
1170 		}
1171 
1172 		net_sin6_ptr(&context->local)->sin6_family = AF_INET6;
1173 		net_sin6(&local_addr)->sin6_family = AF_INET6;
1174 		net_sin6(&local_addr)->sin6_port = lport =
1175 			net_sin6((struct sockaddr *)&context->local)->sin6_port;
1176 
1177 		if (net_sin6_ptr(&context->local)->sin6_addr) {
1178 			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
1179 				     net_sin6_ptr(&context->local)->sin6_addr);
1180 
1181 			laddr = &local_addr;
1182 		}
1183 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
1184 		   net_context_get_family(context) == AF_INET) {
1185 		struct sockaddr_in *addr4 = (struct sockaddr_in *)
1186 							&context->remote;
1187 
1188 		if (addrlen < sizeof(struct sockaddr_in)) {
1189 			ret = -EINVAL;
1190 			goto unlock;
1191 		}
1192 
1193 		/* FIXME - Add multicast and broadcast address check */
1194 
1195 		memcpy(&addr4->sin_addr, &net_sin(addr)->sin_addr,
1196 		       sizeof(struct in_addr));
1197 
1198 		addr4->sin_port = net_sin(addr)->sin_port;
1199 		addr4->sin_family = AF_INET;
1200 
1201 		if (addr4->sin_addr.s_addr) {
1202 			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
1203 		} else {
1204 			context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
1205 		}
1206 
1207 		rport = addr4->sin_port;
1208 
1209 		ret = bind_default(context);
1210 		if (ret) {
1211 			goto unlock;
1212 		}
1213 
1214 		net_sin_ptr(&context->local)->sin_family = AF_INET;
1215 		net_sin(&local_addr)->sin_family = AF_INET;
1216 		net_sin(&local_addr)->sin_port = lport =
1217 			net_sin((struct sockaddr *)&context->local)->sin_port;
1218 
1219 		if (net_sin_ptr(&context->local)->sin_addr) {
1220 			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
1221 				       net_sin_ptr(&context->local)->sin_addr);
1222 
1223 			laddr = &local_addr;
1224 		}
1225 	} else {
1226 		ret = -EINVAL; /* Not IPv4 or IPv6 */
1227 		goto unlock;
1228 	}
1229 
1230 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1231 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
1232 		ret = net_offload_connect(
1233 			net_context_get_iface(context),
1234 			context,
1235 			addr,
1236 			addrlen,
1237 			cb,
1238 			timeout,
1239 			user_data);
1240 		goto unlock;
1241 	}
1242 
1243 	if (IS_ENABLED(CONFIG_NET_UDP) &&
1244 	    net_context_get_type(context) == SOCK_DGRAM) {
1245 		if (cb) {
1246 			cb(context, 0, user_data);
1247 		}
1248 
1249 		ret = 0;
1250 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
1251 		   net_context_get_type(context) == SOCK_STREAM) {
1252 		NET_ASSERT(laddr != NULL);
1253 
1254 		ret = net_tcp_connect(context, addr, laddr, rport, lport,
1255 				      timeout, cb, user_data);
1256 	} else {
1257 		ret = -ENOTSUP;
1258 	}
1259 
1260 unlock:
1261 	k_mutex_unlock(&context->lock);
1262 
1263 	return ret;
1264 }
1265 
net_context_accept(struct net_context * context,net_tcp_accept_cb_t cb,k_timeout_t timeout,void * user_data)1266 int net_context_accept(struct net_context *context,
1267 		       net_tcp_accept_cb_t cb,
1268 		       k_timeout_t timeout,
1269 		       void *user_data)
1270 {
1271 	int ret = 0;
1272 
1273 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
1274 
1275 	if (!net_context_is_used(context)) {
1276 		return -EBADF;
1277 	}
1278 
1279 	k_mutex_lock(&context->lock, K_FOREVER);
1280 
1281 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1282 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
1283 		ret = net_offload_accept(
1284 			net_context_get_iface(context),
1285 			context,
1286 			cb,
1287 			timeout,
1288 			user_data);
1289 		goto unlock;
1290 	}
1291 
1292 	if ((net_context_get_state(context) != NET_CONTEXT_LISTENING) &&
1293 	    (net_context_get_type(context) != SOCK_STREAM)) {
1294 		NET_DBG("Invalid socket, state %d type %d",
1295 			net_context_get_state(context),
1296 			net_context_get_type(context));
1297 		ret = -EINVAL;
1298 		goto unlock;
1299 	}
1300 
1301 	if (net_context_get_proto(context) == IPPROTO_TCP) {
1302 		ret = net_tcp_accept(context, cb, user_data);
1303 		goto unlock;
1304 	}
1305 
1306 unlock:
1307 	k_mutex_unlock(&context->lock);
1308 
1309 	return ret;
1310 }
1311 
1312 
get_context_priority(struct net_context * context,void * value,size_t * len)1313 static int get_context_priority(struct net_context *context,
1314 				void *value, size_t *len)
1315 {
1316 #if defined(CONFIG_NET_CONTEXT_PRIORITY)
1317 	*((uint8_t *)value) = context->options.priority;
1318 
1319 	if (len) {
1320 		*len = sizeof(uint8_t);
1321 	}
1322 
1323 	return 0;
1324 #else
1325 	return -ENOTSUP;
1326 #endif
1327 }
1328 
get_context_proxy(struct net_context * context,void * value,size_t * len)1329 static int get_context_proxy(struct net_context *context,
1330 			     void *value, size_t *len)
1331 {
1332 #if defined(CONFIG_SOCKS)
1333 	struct sockaddr *addr = (struct sockaddr *)value;
1334 
1335 	if (!value || !len) {
1336 		return -EINVAL;
1337 	}
1338 
1339 	if (*len < context->options.proxy.addrlen) {
1340 		return -EINVAL;
1341 	}
1342 
1343 	*len = MIN(context->options.proxy.addrlen, *len);
1344 
1345 	memcpy(addr, &context->options.proxy.addr, *len);
1346 
1347 	return 0;
1348 #else
1349 	return -ENOTSUP;
1350 #endif
1351 }
1352 
get_context_txtime(struct net_context * context,void * value,size_t * len)1353 static int get_context_txtime(struct net_context *context,
1354 			      void *value, size_t *len)
1355 {
1356 #if defined(CONFIG_NET_CONTEXT_TXTIME)
1357 	*((bool *)value) = context->options.txtime;
1358 
1359 	if (len) {
1360 		*len = sizeof(bool);
1361 	}
1362 
1363 	return 0;
1364 #else
1365 	return -ENOTSUP;
1366 #endif
1367 }
1368 
get_context_rcvtimeo(struct net_context * context,void * value,size_t * len)1369 static int get_context_rcvtimeo(struct net_context *context,
1370 				void *value, size_t *len)
1371 {
1372 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
1373 	*((k_timeout_t *)value) = context->options.rcvtimeo;
1374 
1375 	if (len) {
1376 		*len = sizeof(k_timeout_t);
1377 	}
1378 
1379 	return 0;
1380 #else
1381 	return -ENOTSUP;
1382 #endif
1383 }
1384 
get_context_sndtimeo(struct net_context * context,void * value,size_t * len)1385 static int get_context_sndtimeo(struct net_context *context,
1386 				void *value, size_t *len)
1387 {
1388 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
1389 	*((k_timeout_t *)value) = context->options.sndtimeo;
1390 
1391 	if (len) {
1392 		*len = sizeof(k_timeout_t);
1393 	}
1394 
1395 	return 0;
1396 #else
1397 	return -ENOTSUP;
1398 #endif
1399 }
1400 
get_context_rcvbuf(struct net_context * context,void * value,size_t * len)1401 static int get_context_rcvbuf(struct net_context *context,
1402 			      void *value, size_t *len)
1403 {
1404 #if defined(CONFIG_NET_CONTEXT_RCVBUF)
1405 	*((int *)value) = context->options.rcvbuf;
1406 
1407 	if (len) {
1408 		*len = sizeof(int);
1409 	}
1410 	return 0;
1411 #else
1412 	return -ENOTSUP;
1413 #endif
1414 }
1415 
get_context_sndbuf(struct net_context * context,void * value,size_t * len)1416 static int get_context_sndbuf(struct net_context *context,
1417 				void *value, size_t *len)
1418 {
1419 #if defined(CONFIG_NET_CONTEXT_SNDBUF)
1420 	*((int *)value) = context->options.sndbuf;
1421 
1422 	if (len) {
1423 		*len = sizeof(int);
1424 	}
1425 	return 0;
1426 #else
1427 	return -ENOTSUP;
1428 #endif
1429 }
1430 
get_context_dscp_ecn(struct net_context * context,void * value,size_t * len)1431 static int get_context_dscp_ecn(struct net_context *context,
1432 				void *value, size_t *len)
1433 {
1434 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
1435 	*((int *)value) = context->options.dscp_ecn;
1436 
1437 	if (len) {
1438 		*len = sizeof(int);
1439 	}
1440 
1441 	return 0;
1442 #else
1443 	return -ENOTSUP;
1444 #endif
1445 }
1446 
get_context_reuseaddr(struct net_context * context,void * value,size_t * len)1447 static int get_context_reuseaddr(struct net_context *context,
1448 				 void *value, size_t *len)
1449 {
1450 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
1451 	if (!value || !len) {
1452 		return -EINVAL;
1453 	}
1454 
1455 	if (*len != sizeof(int)) {
1456 		return -EINVAL;
1457 	}
1458 
1459 	if (context->options.reuseaddr == true) {
1460 		*((int *)value) = (int) true;
1461 	} else {
1462 		*((int *)value) = (int) false;
1463 	}
1464 
1465 	*len = sizeof(int);
1466 
1467 	return 0;
1468 #else
1469 	return -ENOTSUP;
1470 #endif
1471 }
1472 
get_context_reuseport(struct net_context * context,void * value,size_t * len)1473 static int get_context_reuseport(struct net_context *context,
1474 				void *value, size_t *len)
1475 {
1476 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
1477 	if (!value || !len) {
1478 		return -EINVAL;
1479 	}
1480 
1481 	if (*len != sizeof(int)) {
1482 		return -EINVAL;
1483 	}
1484 
1485 	if (context->options.reuseport == true) {
1486 		*((int *)value) = (int) true;
1487 	} else {
1488 		*((int *)value) = (int) false;
1489 	}
1490 
1491 	*len = sizeof(int);
1492 
1493 	return 0;
1494 #else
1495 	return -ENOTSUP;
1496 #endif
1497 }
1498 
1499 /* If buf is not NULL, then use it. Otherwise read the data to be written
1500  * to net_pkt from msghdr.
1501  */
context_write_data(struct net_pkt * pkt,const void * buf,int buf_len,const struct msghdr * msghdr)1502 static int context_write_data(struct net_pkt *pkt, const void *buf,
1503 			      int buf_len, const struct msghdr *msghdr)
1504 {
1505 	int ret = 0;
1506 
1507 	if (msghdr) {
1508 		int i;
1509 
1510 		for (i = 0; i < msghdr->msg_iovlen; i++) {
1511 			int len = MIN(msghdr->msg_iov[i].iov_len, buf_len);
1512 
1513 			ret = net_pkt_write(pkt, msghdr->msg_iov[i].iov_base,
1514 					    len);
1515 			if (ret < 0) {
1516 				break;
1517 			}
1518 
1519 			buf_len -= len;
1520 			if (buf_len == 0) {
1521 				break;
1522 			}
1523 		}
1524 	} else {
1525 		ret = net_pkt_write(pkt, buf, buf_len);
1526 	}
1527 
1528 	return ret;
1529 }
1530 
context_setup_udp_packet(struct net_context * context,struct net_pkt * pkt,const void * buf,size_t len,const struct msghdr * msg,const struct sockaddr * dst_addr,socklen_t addrlen)1531 static int context_setup_udp_packet(struct net_context *context,
1532 				    struct net_pkt *pkt,
1533 				    const void *buf,
1534 				    size_t len,
1535 				    const struct msghdr *msg,
1536 				    const struct sockaddr *dst_addr,
1537 				    socklen_t addrlen)
1538 {
1539 	int ret = -EINVAL;
1540 	uint16_t dst_port = 0U;
1541 
1542 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
1543 	    net_context_get_family(context) == AF_INET6) {
1544 		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)dst_addr;
1545 
1546 		dst_port = addr6->sin6_port;
1547 
1548 		ret = net_context_create_ipv6_new(context, pkt,
1549 						  NULL, &addr6->sin6_addr);
1550 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
1551 		   net_context_get_family(context) == AF_INET) {
1552 		struct sockaddr_in *addr4 = (struct sockaddr_in *)dst_addr;
1553 
1554 		dst_port = addr4->sin_port;
1555 
1556 		ret = net_context_create_ipv4_new(context, pkt,
1557 						  NULL, &addr4->sin_addr);
1558 	}
1559 
1560 	if (ret < 0) {
1561 		return ret;
1562 	}
1563 
1564 	ret = bind_default(context);
1565 	if (ret) {
1566 		return ret;
1567 	}
1568 
1569 	ret = net_udp_create(pkt,
1570 			     net_sin((struct sockaddr *)
1571 				     &context->local)->sin_port,
1572 			     dst_port);
1573 	if (ret) {
1574 		return ret;
1575 	}
1576 
1577 	ret = context_write_data(pkt, buf, len, msg);
1578 	if (ret) {
1579 		return ret;
1580 	}
1581 
1582 	return 0;
1583 }
1584 
context_finalize_packet(struct net_context * context,struct net_pkt * pkt)1585 static void context_finalize_packet(struct net_context *context,
1586 				    struct net_pkt *pkt)
1587 {
1588 	/* This function is meant to be temporary: once all moved to new
1589 	 * API, it will be up to net_send_data() to finalize the packet.
1590 	 */
1591 
1592 	net_pkt_cursor_init(pkt);
1593 
1594 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
1595 	    net_context_get_family(context) == AF_INET6) {
1596 		net_ipv6_finalize(pkt, net_context_get_proto(context));
1597 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
1598 		   net_context_get_family(context) == AF_INET) {
1599 		net_ipv4_finalize(pkt, net_context_get_proto(context));
1600 	}
1601 }
1602 
context_alloc_pkt(struct net_context * context,size_t len,k_timeout_t timeout)1603 static struct net_pkt *context_alloc_pkt(struct net_context *context,
1604 					 size_t len, k_timeout_t timeout)
1605 {
1606 	struct net_pkt *pkt;
1607 
1608 #if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
1609 	if (context->tx_slab) {
1610 		pkt = net_pkt_alloc_from_slab(context->tx_slab(), timeout);
1611 		if (!pkt) {
1612 			return NULL;
1613 		}
1614 
1615 		net_pkt_set_iface(pkt, net_context_get_iface(context));
1616 		net_pkt_set_family(pkt, net_context_get_family(context));
1617 		net_pkt_set_context(pkt, context);
1618 
1619 		if (net_pkt_alloc_buffer(pkt, len,
1620 					 net_context_get_proto(context),
1621 					 timeout)) {
1622 			net_pkt_unref(pkt);
1623 			return NULL;
1624 		}
1625 
1626 		return pkt;
1627 	}
1628 #endif
1629 	pkt = net_pkt_alloc_with_buffer(net_context_get_iface(context), len,
1630 					net_context_get_family(context),
1631 					net_context_get_proto(context),
1632 					timeout);
1633 	if (pkt) {
1634 		net_pkt_set_context(pkt, context);
1635 	}
1636 
1637 	return pkt;
1638 }
1639 
set_pkt_txtime(struct net_pkt * pkt,const struct msghdr * msghdr)1640 static void set_pkt_txtime(struct net_pkt *pkt, const struct msghdr *msghdr)
1641 {
1642 	struct cmsghdr *cmsg;
1643 
1644 	for (cmsg = CMSG_FIRSTHDR(msghdr); cmsg != NULL;
1645 	     cmsg = CMSG_NXTHDR(msghdr, cmsg)) {
1646 		if (cmsg->cmsg_len == CMSG_LEN(sizeof(uint64_t)) &&
1647 		    cmsg->cmsg_level == SOL_SOCKET &&
1648 		    cmsg->cmsg_type == SCM_TXTIME) {
1649 			net_pkt_set_timestamp_ns(pkt, *(net_time_t *)CMSG_DATA(cmsg));
1650 			break;
1651 		}
1652 	}
1653 }
1654 
context_sendto(struct net_context * context,const void * buf,size_t len,const struct sockaddr * dst_addr,socklen_t addrlen,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data,bool sendto)1655 static int context_sendto(struct net_context *context,
1656 			  const void *buf,
1657 			  size_t len,
1658 			  const struct sockaddr *dst_addr,
1659 			  socklen_t addrlen,
1660 			  net_context_send_cb_t cb,
1661 			  k_timeout_t timeout,
1662 			  void *user_data,
1663 			  bool sendto)
1664 {
1665 	const struct msghdr *msghdr = NULL;
1666 	struct net_if *iface;
1667 	struct net_pkt *pkt;
1668 	size_t tmp_len;
1669 	int ret;
1670 
1671 	NET_ASSERT(PART_OF_ARRAY(contexts, context));
1672 
1673 	if (!net_context_is_used(context)) {
1674 		return -EBADF;
1675 	}
1676 
1677 	if (sendto && addrlen == 0 && dst_addr == NULL && buf != NULL) {
1678 		/* User wants to call sendmsg */
1679 		msghdr = buf;
1680 	}
1681 
1682 	if (!msghdr && !dst_addr) {
1683 		return -EDESTADDRREQ;
1684 	}
1685 
1686 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
1687 	    net_context_get_family(context) == AF_INET6) {
1688 		const struct sockaddr_in6 *addr6 =
1689 			(const struct sockaddr_in6 *)dst_addr;
1690 
1691 		if (msghdr) {
1692 			addr6 = msghdr->msg_name;
1693 			addrlen = msghdr->msg_namelen;
1694 
1695 			if (!addr6) {
1696 				addr6 = net_sin6(&context->remote);
1697 				addrlen = sizeof(struct sockaddr_in6);
1698 			}
1699 
1700 			/* For sendmsg(), the dst_addr is NULL so set it here.
1701 			 */
1702 			dst_addr = (const struct sockaddr *)addr6;
1703 		}
1704 
1705 		if (addrlen < sizeof(struct sockaddr_in6)) {
1706 			return -EINVAL;
1707 		}
1708 
1709 		if (net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
1710 			return -EDESTADDRREQ;
1711 		}
1712 
1713 		/* If application has not yet set the destination address
1714 		 * i.e., by not calling connect(), then set the interface
1715 		 * here so that the packet gets sent to the correct network
1716 		 * interface. This issue can be seen if there are multiple
1717 		 * network interfaces and we are trying to send data to
1718 		 * second or later network interface.
1719 		 */
1720 		if (net_ipv6_is_addr_unspecified(
1721 				&net_sin6(&context->remote)->sin6_addr) &&
1722 		    !net_context_is_bound_to_iface(context)) {
1723 			iface = net_if_ipv6_select_src_iface(&addr6->sin6_addr);
1724 			net_context_set_iface(context, iface);
1725 		}
1726 
1727 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
1728 		   net_context_get_family(context) == AF_INET) {
1729 		const struct sockaddr_in *addr4 =
1730 			(const struct sockaddr_in *)dst_addr;
1731 
1732 		if (msghdr) {
1733 			addr4 = msghdr->msg_name;
1734 			addrlen = msghdr->msg_namelen;
1735 
1736 			if (!addr4) {
1737 				addr4 = net_sin(&context->remote);
1738 				addrlen = sizeof(struct sockaddr_in);
1739 			}
1740 
1741 			/* For sendmsg(), the dst_addr is NULL so set it here.
1742 			 */
1743 			dst_addr = (const struct sockaddr *)addr4;
1744 		}
1745 
1746 		if (addrlen < sizeof(struct sockaddr_in)) {
1747 			return -EINVAL;
1748 		}
1749 
1750 		if (!addr4->sin_addr.s_addr) {
1751 			return -EDESTADDRREQ;
1752 		}
1753 
1754 		/* If application has not yet set the destination address
1755 		 * i.e., by not calling connect(), then set the interface
1756 		 * here so that the packet gets sent to the correct network
1757 		 * interface. This issue can be seen if there are multiple
1758 		 * network interfaces and we are trying to send data to
1759 		 * second or later network interface.
1760 		 */
1761 		if (net_sin(&context->remote)->sin_addr.s_addr == 0U &&
1762 		    !net_context_is_bound_to_iface(context)) {
1763 			iface = net_if_ipv4_select_src_iface(&addr4->sin_addr);
1764 			net_context_set_iface(context, iface);
1765 		}
1766 
1767 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
1768 		   net_context_get_family(context) == AF_PACKET) {
1769 		struct sockaddr_ll *ll_addr = (struct sockaddr_ll *)dst_addr;
1770 
1771 		if (msghdr) {
1772 			ll_addr = msghdr->msg_name;
1773 			addrlen = msghdr->msg_namelen;
1774 
1775 			if (!ll_addr) {
1776 				ll_addr = (struct sockaddr_ll *)
1777 							(&context->remote);
1778 				addrlen = sizeof(struct sockaddr_ll);
1779 			}
1780 
1781 			/* For sendmsg(), the dst_addr is NULL so set it here.
1782 			 */
1783 			dst_addr = (const struct sockaddr *)ll_addr;
1784 		}
1785 
1786 		if (addrlen < sizeof(struct sockaddr_ll)) {
1787 			return -EINVAL;
1788 		}
1789 
1790 		iface = net_context_get_iface(context);
1791 		if (iface == NULL) {
1792 			if (ll_addr->sll_ifindex < 0) {
1793 				return -EDESTADDRREQ;
1794 			}
1795 
1796 			iface = net_if_get_by_index(ll_addr->sll_ifindex);
1797 			if (iface == NULL) {
1798 				NET_ERR("Cannot bind to interface index %d",
1799 					ll_addr->sll_ifindex);
1800 				return -EDESTADDRREQ;
1801 			}
1802 		}
1803 
1804 		if (net_context_get_type(context) == SOCK_DGRAM) {
1805 			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
1806 
1807 			/* The user must set the protocol in send call */
1808 
1809 			/* For sendmsg() call, we might have set ll_addr to
1810 			 * point to remote addr.
1811 			 */
1812 			if ((void *)&context->remote != (void *)ll_addr) {
1813 				memcpy((struct sockaddr_ll *)&context->remote,
1814 				       ll_addr, sizeof(struct sockaddr_ll));
1815 			}
1816 		}
1817 
1818 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
1819 		   net_context_get_family(context) == AF_CAN) {
1820 		struct sockaddr_can *can_addr = (struct sockaddr_can *)dst_addr;
1821 
1822 		if (msghdr) {
1823 			can_addr = msghdr->msg_name;
1824 			addrlen = msghdr->msg_namelen;
1825 
1826 			if (!can_addr) {
1827 				can_addr = (struct sockaddr_can *)
1828 							(&context->remote);
1829 				addrlen = sizeof(struct sockaddr_can);
1830 			}
1831 
1832 			/* For sendmsg(), the dst_addr is NULL so set it here.
1833 			 */
1834 			dst_addr = (const struct sockaddr *)can_addr;
1835 		}
1836 
1837 		if (addrlen < sizeof(struct sockaddr_can)) {
1838 			return -EINVAL;
1839 		}
1840 
1841 		if (can_addr->can_ifindex < 0) {
1842 			/* The index should have been set in bind */
1843 			can_addr->can_ifindex =
1844 				net_can_ptr(&context->local)->can_ifindex;
1845 		}
1846 
1847 		if (can_addr->can_ifindex < 0) {
1848 			return -EDESTADDRREQ;
1849 		}
1850 
1851 		iface = net_if_get_by_index(can_addr->can_ifindex);
1852 		if (!iface) {
1853 			NET_ERR("Cannot bind to interface index %d",
1854 				can_addr->can_ifindex);
1855 			return -EDESTADDRREQ;
1856 		}
1857 	} else {
1858 		NET_DBG("Invalid protocol family %d",
1859 			net_context_get_family(context));
1860 		return -EINVAL;
1861 	}
1862 
1863 	if (msghdr && len == 0) {
1864 		int i;
1865 
1866 		for (i = 0; i < msghdr->msg_iovlen; i++) {
1867 			len += msghdr->msg_iov[i].iov_len;
1868 		}
1869 	}
1870 
1871 	iface = net_context_get_iface(context);
1872 	if (iface && !net_if_is_up(iface)) {
1873 		return -ENETDOWN;
1874 	}
1875 
1876 	pkt = context_alloc_pkt(context, len, PKT_WAIT_TIME);
1877 	if (!pkt) {
1878 		NET_ERR("Failed to allocate net_pkt");
1879 		return -ENOBUFS;
1880 	}
1881 
1882 	tmp_len = net_pkt_available_payload_buffer(
1883 				pkt, net_context_get_proto(context));
1884 	if (tmp_len < len) {
1885 		if (net_context_get_type(context) == SOCK_DGRAM) {
1886 			NET_ERR("Available payload buffer (%zu) is not enough for requested DGRAM (%zu)",
1887 				tmp_len, len);
1888 			ret = -ENOMEM;
1889 			goto fail;
1890 		}
1891 		len = tmp_len;
1892 	}
1893 
1894 	context->send_cb = cb;
1895 	context->user_data = user_data;
1896 
1897 	if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
1898 		uint8_t priority;
1899 
1900 		get_context_priority(context, &priority, NULL);
1901 		net_pkt_set_priority(pkt, priority);
1902 	}
1903 
1904 	/* If there is ancillary data in msghdr, then we need to add that
1905 	 * to net_pkt as there is no other way to store it.
1906 	 */
1907 	if (msghdr && msghdr->msg_control && msghdr->msg_controllen) {
1908 		if (IS_ENABLED(CONFIG_NET_CONTEXT_TXTIME)) {
1909 			bool is_txtime;
1910 
1911 			get_context_txtime(context, &is_txtime, NULL);
1912 			if (is_txtime) {
1913 				set_pkt_txtime(pkt, msghdr);
1914 			}
1915 		}
1916 	}
1917 
1918 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1919 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
1920 		ret = context_write_data(pkt, buf, len, msghdr);
1921 		if (ret < 0) {
1922 			goto fail;
1923 		}
1924 
1925 		net_pkt_cursor_init(pkt);
1926 
1927 		if (sendto) {
1928 			ret = net_offload_sendto(net_context_get_iface(context),
1929 						 pkt, dst_addr, addrlen, cb,
1930 						 timeout, user_data);
1931 		} else {
1932 			ret = net_offload_send(net_context_get_iface(context),
1933 					       pkt, cb, timeout, user_data);
1934 		}
1935 	} else if (IS_ENABLED(CONFIG_NET_UDP) &&
1936 	    net_context_get_proto(context) == IPPROTO_UDP) {
1937 		ret = context_setup_udp_packet(context, pkt, buf, len, msghdr,
1938 					       dst_addr, addrlen);
1939 		if (ret < 0) {
1940 			goto fail;
1941 		}
1942 
1943 		context_finalize_packet(context, pkt);
1944 
1945 		ret = net_send_data(pkt);
1946 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
1947 		   net_context_get_proto(context) == IPPROTO_TCP) {
1948 
1949 		ret = context_write_data(pkt, buf, len, msghdr);
1950 		if (ret < 0) {
1951 			goto fail;
1952 		}
1953 
1954 		net_pkt_cursor_init(pkt);
1955 		ret = net_tcp_queue_data(context, pkt);
1956 		if (ret < 0) {
1957 			goto fail;
1958 		}
1959 
1960 		ret = net_tcp_send_data(context, cb, user_data);
1961 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
1962 		   net_context_get_family(context) == AF_PACKET) {
1963 		ret = context_write_data(pkt, buf, len, msghdr);
1964 		if (ret < 0) {
1965 			goto fail;
1966 		}
1967 
1968 		net_pkt_cursor_init(pkt);
1969 
1970 		if (net_context_get_proto(context) == IPPROTO_RAW) {
1971 			char type = (NET_IPV6_HDR(pkt)->vtc & 0xf0);
1972 
1973 			/* Set the family to pkt if detected */
1974 			switch (type) {
1975 			case 0x60:
1976 				net_pkt_set_family(pkt, AF_INET6);
1977 				break;
1978 			case 0x40:
1979 				net_pkt_set_family(pkt, AF_INET);
1980 				break;
1981 			default:
1982 				/* Not IP traffic, let it go forward as it is */
1983 				break;
1984 			}
1985 
1986 			/* Pass to L2: */
1987 			ret = net_send_data(pkt);
1988 		} else {
1989 			net_if_queue_tx(net_pkt_iface(pkt), pkt);
1990 		}
1991 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
1992 		   net_context_get_family(context) == AF_CAN &&
1993 		   net_context_get_proto(context) == CAN_RAW) {
1994 		ret = context_write_data(pkt, buf, len, msghdr);
1995 		if (ret < 0) {
1996 			goto fail;
1997 		}
1998 
1999 		net_pkt_cursor_init(pkt);
2000 
2001 		ret = net_send_data(pkt);
2002 	} else {
2003 		NET_DBG("Unknown protocol while sending packet: %d",
2004 		net_context_get_proto(context));
2005 		ret = -EPROTONOSUPPORT;
2006 	}
2007 
2008 	if (ret < 0) {
2009 		goto fail;
2010 	}
2011 
2012 	return len;
2013 fail:
2014 	net_pkt_unref(pkt);
2015 
2016 	return ret;
2017 }
2018 
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)2019 int net_context_send(struct net_context *context,
2020 		     const void *buf,
2021 		     size_t len,
2022 		     net_context_send_cb_t cb,
2023 		     k_timeout_t timeout,
2024 		     void *user_data)
2025 {
2026 	socklen_t addrlen;
2027 	int ret = 0;
2028 
2029 	k_mutex_lock(&context->lock, K_FOREVER);
2030 
2031 	if (!(context->flags & NET_CONTEXT_REMOTE_ADDR_SET) ||
2032 	    !net_sin(&context->remote)->sin_port) {
2033 		ret = -EDESTADDRREQ;
2034 		goto unlock;
2035 	}
2036 
2037 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
2038 	    net_context_get_family(context) == AF_INET6) {
2039 		addrlen = sizeof(struct sockaddr_in6);
2040 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2041 		   net_context_get_family(context) == AF_INET) {
2042 		addrlen = sizeof(struct sockaddr_in);
2043 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2044 		   net_context_get_family(context) == AF_PACKET) {
2045 		ret = -EOPNOTSUPP;
2046 		goto unlock;
2047 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2048 		   net_context_get_family(context) == AF_CAN) {
2049 		addrlen = sizeof(struct sockaddr_can);
2050 	} else {
2051 		addrlen = 0;
2052 	}
2053 
2054 	ret = context_sendto(context, buf, len, &context->remote,
2055 			     addrlen, cb, timeout, user_data, false);
2056 unlock:
2057 	k_mutex_unlock(&context->lock);
2058 
2059 	return ret;
2060 }
2061 
net_context_sendmsg(struct net_context * context,const struct msghdr * msghdr,int flags,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)2062 int net_context_sendmsg(struct net_context *context,
2063 			const struct msghdr *msghdr,
2064 			int flags,
2065 			net_context_send_cb_t cb,
2066 			k_timeout_t timeout,
2067 			void *user_data)
2068 {
2069 	int ret;
2070 
2071 	k_mutex_lock(&context->lock, K_FOREVER);
2072 
2073 	ret = context_sendto(context, msghdr, 0, NULL, 0,
2074 			     cb, timeout, user_data, true);
2075 
2076 	k_mutex_unlock(&context->lock);
2077 
2078 	return ret;
2079 }
2080 
net_context_sendto(struct net_context * context,const void * buf,size_t len,const struct sockaddr * dst_addr,socklen_t addrlen,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)2081 int net_context_sendto(struct net_context *context,
2082 		       const void *buf,
2083 		       size_t len,
2084 		       const struct sockaddr *dst_addr,
2085 		       socklen_t addrlen,
2086 		       net_context_send_cb_t cb,
2087 		       k_timeout_t timeout,
2088 		       void *user_data)
2089 {
2090 	int ret;
2091 
2092 	k_mutex_lock(&context->lock, K_FOREVER);
2093 
2094 	ret = context_sendto(context, buf, len, dst_addr, addrlen,
2095 			     cb, timeout, user_data, true);
2096 
2097 	k_mutex_unlock(&context->lock);
2098 
2099 	return ret;
2100 }
2101 
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)2102 enum net_verdict net_context_packet_received(struct net_conn *conn,
2103 					     struct net_pkt *pkt,
2104 					     union net_ip_header *ip_hdr,
2105 					     union net_proto_header *proto_hdr,
2106 					     void *user_data)
2107 {
2108 	struct net_context *context = find_context(conn);
2109 	enum net_verdict verdict = NET_DROP;
2110 
2111 	NET_ASSERT(context);
2112 	NET_ASSERT(net_pkt_iface(pkt));
2113 
2114 	k_mutex_lock(&context->lock, K_FOREVER);
2115 
2116 	net_context_set_iface(context, net_pkt_iface(pkt));
2117 	net_pkt_set_context(pkt, context);
2118 
2119 	/* If there is no callback registered, then we can only drop
2120 	 * the packet.
2121 	 */
2122 	if (!context->recv_cb) {
2123 		goto unlock;
2124 	}
2125 
2126 	if (net_context_get_proto(context) == IPPROTO_TCP) {
2127 		net_stats_update_tcp_recv(net_pkt_iface(pkt),
2128 					  net_pkt_remaining_data(pkt));
2129 	}
2130 
2131 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2132 	k_sem_give(&context->recv_data_wait);
2133 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2134 
2135 	k_mutex_unlock(&context->lock);
2136 
2137 	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
2138 
2139 	verdict = NET_OK;
2140 
2141 	return verdict;
2142 
2143 unlock:
2144 	k_mutex_unlock(&context->lock);
2145 
2146 	return verdict;
2147 }
2148 
2149 #if defined(CONFIG_NET_UDP)
recv_udp(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)2150 static int recv_udp(struct net_context *context,
2151 		    net_context_recv_cb_t cb,
2152 		    k_timeout_t timeout,
2153 		    void *user_data)
2154 {
2155 	struct sockaddr local_addr = {
2156 		.sa_family = net_context_get_family(context),
2157 	};
2158 	struct sockaddr *laddr = NULL;
2159 	uint16_t lport = 0U;
2160 	int ret;
2161 
2162 	ARG_UNUSED(timeout);
2163 
2164 	if (context->conn_handler) {
2165 		net_conn_unregister(context->conn_handler);
2166 		context->conn_handler = NULL;
2167 	}
2168 
2169 	ret = bind_default(context);
2170 	if (ret) {
2171 		return ret;
2172 	}
2173 
2174 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
2175 	    net_context_get_family(context) == AF_INET6) {
2176 		if (net_sin6_ptr(&context->local)->sin6_addr) {
2177 			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
2178 				     net_sin6_ptr(&context->local)->sin6_addr);
2179 
2180 			laddr = &local_addr;
2181 		}
2182 
2183 		net_sin6(&local_addr)->sin6_port =
2184 			net_sin6((struct sockaddr *)&context->local)->sin6_port;
2185 		lport = net_sin6((struct sockaddr *)&context->local)->sin6_port;
2186 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2187 		   net_context_get_family(context) == AF_INET) {
2188 		if (net_sin_ptr(&context->local)->sin_addr) {
2189 			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
2190 				      net_sin_ptr(&context->local)->sin_addr);
2191 
2192 			laddr = &local_addr;
2193 		}
2194 
2195 		lport = net_sin((struct sockaddr *)&context->local)->sin_port;
2196 	}
2197 
2198 	context->recv_cb = cb;
2199 
2200 	ret = net_conn_register(net_context_get_proto(context),
2201 				net_context_get_family(context),
2202 				context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
2203 							&context->remote : NULL,
2204 				laddr,
2205 				ntohs(net_sin(&context->remote)->sin_port),
2206 				ntohs(lport),
2207 				context,
2208 				net_context_packet_received,
2209 				user_data,
2210 				&context->conn_handler);
2211 
2212 	return ret;
2213 }
2214 #else
2215 #define recv_udp(...) 0
2216 #endif /* CONFIG_NET_UDP */
2217 
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)2218 static enum net_verdict net_context_raw_packet_received(
2219 					struct net_conn *conn,
2220 					struct net_pkt *pkt,
2221 					union net_ip_header *ip_hdr,
2222 					union net_proto_header *proto_hdr,
2223 					void *user_data)
2224 {
2225 	struct net_context *context = find_context(conn);
2226 
2227 	NET_ASSERT(context);
2228 	NET_ASSERT(net_pkt_iface(pkt));
2229 
2230 	/* If there is no callback registered, then we can only drop
2231 	 * the packet.
2232 	 */
2233 
2234 	if (!context->recv_cb) {
2235 		return NET_DROP;
2236 	}
2237 
2238 	net_context_set_iface(context, net_pkt_iface(pkt));
2239 	net_pkt_set_context(pkt, context);
2240 
2241 	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
2242 
2243 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2244 	k_sem_give(&context->recv_data_wait);
2245 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2246 
2247 	return NET_OK;
2248 }
2249 
recv_raw(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,struct sockaddr * local_addr,void * user_data)2250 static int recv_raw(struct net_context *context,
2251 		    net_context_recv_cb_t cb,
2252 		    k_timeout_t timeout,
2253 		    struct sockaddr *local_addr,
2254 		    void *user_data)
2255 {
2256 	int ret;
2257 
2258 	ARG_UNUSED(timeout);
2259 
2260 	context->recv_cb = cb;
2261 
2262 	if (context->conn_handler) {
2263 		net_conn_unregister(context->conn_handler);
2264 		context->conn_handler = NULL;
2265 	}
2266 
2267 	ret = bind_default(context);
2268 	if (ret) {
2269 		return ret;
2270 	}
2271 
2272 	ret = net_conn_register(net_context_get_proto(context),
2273 				net_context_get_family(context),
2274 				NULL, local_addr, 0, 0,
2275 				context,
2276 				net_context_raw_packet_received,
2277 				user_data,
2278 				&context->conn_handler);
2279 
2280 	return ret;
2281 }
2282 
net_context_recv(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)2283 int net_context_recv(struct net_context *context,
2284 		     net_context_recv_cb_t cb,
2285 		     k_timeout_t timeout,
2286 		     void *user_data)
2287 {
2288 	int ret;
2289 	NET_ASSERT(context);
2290 
2291 	if (!net_context_is_used(context)) {
2292 		return -EBADF;
2293 	}
2294 
2295 	k_mutex_lock(&context->lock, K_FOREVER);
2296 
2297 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
2298 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
2299 		ret = net_offload_recv(
2300 			net_context_get_iface(context),
2301 			context, cb, timeout, user_data);
2302 		goto unlock;
2303 	}
2304 
2305 	if (IS_ENABLED(CONFIG_NET_UDP) &&
2306 	    net_context_get_proto(context) == IPPROTO_UDP) {
2307 		ret = recv_udp(context, cb, timeout, user_data);
2308 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
2309 		   net_context_get_proto(context) == IPPROTO_TCP) {
2310 		ret = net_tcp_recv(context, cb, user_data);
2311 	} else {
2312 		if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2313 		    net_context_get_family(context) == AF_PACKET) {
2314 			struct sockaddr_ll addr;
2315 
2316 			addr.sll_family = AF_PACKET;
2317 			addr.sll_ifindex =
2318 				net_sll_ptr(&context->local)->sll_ifindex;
2319 			addr.sll_protocol =
2320 				net_sll_ptr(&context->local)->sll_protocol;
2321 			addr.sll_halen =
2322 				net_sll_ptr(&context->local)->sll_halen;
2323 
2324 			memcpy(addr.sll_addr,
2325 			       net_sll_ptr(&context->local)->sll_addr,
2326 			       MIN(addr.sll_halen, sizeof(addr.sll_addr)));
2327 
2328 			ret = recv_raw(context, cb, timeout,
2329 				       (struct sockaddr *)&addr, user_data);
2330 		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2331 			   net_context_get_family(context) == AF_CAN) {
2332 			struct sockaddr_can local_addr = {
2333 				.can_family = AF_CAN,
2334 			};
2335 
2336 			ret = recv_raw(context, cb, timeout,
2337 				       (struct sockaddr *)&local_addr,
2338 				       user_data);
2339 			if (ret == -EALREADY) {
2340 				/* This is perfectly normal for CAN sockets.
2341 				 * The SocketCAN will dispatch the packet to
2342 				 * correct net_context listener.
2343 				 */
2344 				ret = 0;
2345 			}
2346 		} else {
2347 			ret = -EPROTOTYPE;
2348 		}
2349 	}
2350 
2351 	if (ret < 0) {
2352 		goto unlock;
2353 	}
2354 
2355 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2356 	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
2357 		/* Make sure we have the lock, then the
2358 		 * net_context_packet_received() callback will release the
2359 		 * semaphore when data has been received.
2360 		 */
2361 		k_sem_reset(&context->recv_data_wait);
2362 
2363 		k_mutex_unlock(&context->lock);
2364 
2365 		if (k_sem_take(&context->recv_data_wait, timeout) == -EAGAIN) {
2366 			ret = -ETIMEDOUT;
2367 		}
2368 
2369 		k_mutex_lock(&context->lock, K_FOREVER);
2370 	}
2371 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2372 
2373 unlock:
2374 	k_mutex_unlock(&context->lock);
2375 
2376 	return ret;
2377 }
2378 
net_context_update_recv_wnd(struct net_context * context,int32_t delta)2379 int net_context_update_recv_wnd(struct net_context *context,
2380 				int32_t delta)
2381 {
2382 	int ret;
2383 
2384 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
2385 		net_if_is_ip_offloaded(net_context_get_iface(context))) {
2386 		return 0;
2387 	}
2388 
2389 	k_mutex_lock(&context->lock, K_FOREVER);
2390 
2391 	ret = net_tcp_update_recv_wnd(context, delta);
2392 
2393 	k_mutex_unlock(&context->lock);
2394 
2395 	return ret;
2396 }
2397 
set_context_priority(struct net_context * context,const void * value,size_t len)2398 static int set_context_priority(struct net_context *context,
2399 				const void *value, size_t len)
2400 {
2401 #if defined(CONFIG_NET_CONTEXT_PRIORITY)
2402 	if (len > sizeof(uint8_t)) {
2403 		return -EINVAL;
2404 	}
2405 
2406 	context->options.priority = *((uint8_t *)value);
2407 
2408 	return 0;
2409 #else
2410 	return -ENOTSUP;
2411 #endif
2412 }
2413 
set_context_txtime(struct net_context * context,const void * value,size_t len)2414 static int set_context_txtime(struct net_context *context,
2415 			      const void *value, size_t len)
2416 {
2417 #if defined(CONFIG_NET_CONTEXT_TXTIME)
2418 	if (len > sizeof(bool)) {
2419 		return -EINVAL;
2420 	}
2421 
2422 	context->options.txtime = *((bool *)value);
2423 
2424 	return 0;
2425 #else
2426 	return -ENOTSUP;
2427 #endif
2428 }
2429 
set_context_proxy(struct net_context * context,const void * value,size_t len)2430 static int set_context_proxy(struct net_context *context,
2431 			     const void *value, size_t len)
2432 {
2433 #if defined(CONFIG_SOCKS)
2434 	struct sockaddr *addr = (struct sockaddr *)value;
2435 
2436 	if (len > NET_SOCKADDR_MAX_SIZE) {
2437 		return -EINVAL;
2438 	}
2439 
2440 	if (addr->sa_family != net_context_get_family(context)) {
2441 		return -EINVAL;
2442 	}
2443 
2444 	context->options.proxy.addrlen = len;
2445 	memcpy(&context->options.proxy.addr, addr, len);
2446 
2447 	return 0;
2448 #else
2449 	return -ENOTSUP;
2450 #endif
2451 }
2452 
set_context_rcvtimeo(struct net_context * context,const void * value,size_t len)2453 static int set_context_rcvtimeo(struct net_context *context,
2454 				const void *value, size_t len)
2455 {
2456 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
2457 	if (len != sizeof(k_timeout_t)) {
2458 		return -EINVAL;
2459 	}
2460 
2461 	context->options.rcvtimeo = *((k_timeout_t *)value);
2462 
2463 	return 0;
2464 #else
2465 	return -ENOTSUP;
2466 #endif
2467 }
2468 
set_context_sndtimeo(struct net_context * context,const void * value,size_t len)2469 static int set_context_sndtimeo(struct net_context *context,
2470 				const void *value, size_t len)
2471 {
2472 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
2473 	if (len != sizeof(k_timeout_t)) {
2474 		return -EINVAL;
2475 	}
2476 
2477 	context->options.sndtimeo = *((k_timeout_t *)value);
2478 
2479 	return 0;
2480 #else
2481 	return -ENOTSUP;
2482 #endif
2483 }
2484 
set_context_rcvbuf(struct net_context * context,const void * value,size_t len)2485 static int set_context_rcvbuf(struct net_context *context,
2486 				const void *value, size_t len)
2487 {
2488 #if defined(CONFIG_NET_CONTEXT_RCVBUF)
2489 	int rcvbuf_value = *((int *)value);
2490 
2491 	if (len != sizeof(int)) {
2492 		return -EINVAL;
2493 	}
2494 
2495 	if ((rcvbuf_value < 0) || (rcvbuf_value > UINT16_MAX)) {
2496 		return -EINVAL;
2497 	}
2498 
2499 	context->options.rcvbuf = (uint16_t) rcvbuf_value;
2500 
2501 	return 0;
2502 #else
2503 	return -ENOTSUP;
2504 #endif
2505 }
2506 
set_context_sndbuf(struct net_context * context,const void * value,size_t len)2507 static int set_context_sndbuf(struct net_context *context,
2508 				const void *value, size_t len)
2509 {
2510 #if defined(CONFIG_NET_CONTEXT_SNDBUF)
2511 	int sndbuf_value = *((int *)value);
2512 
2513 	if (len != sizeof(int)) {
2514 		return -EINVAL;
2515 	}
2516 
2517 	if ((sndbuf_value < 0) || (sndbuf_value > UINT16_MAX)) {
2518 		return -EINVAL;
2519 	}
2520 
2521 	context->options.sndbuf = (uint16_t) sndbuf_value;
2522 	return 0;
2523 #else
2524 	return -ENOTSUP;
2525 #endif
2526 }
2527 
set_context_dscp_ecn(struct net_context * context,const void * value,size_t len)2528 static int set_context_dscp_ecn(struct net_context *context,
2529 				const void *value, size_t len)
2530 {
2531 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
2532 	int dscp_ecn = *((int *)value);
2533 
2534 	if (len != sizeof(int)) {
2535 		return -EINVAL;
2536 	}
2537 
2538 	if ((dscp_ecn < 0) || (dscp_ecn > UINT8_MAX)) {
2539 		return -EINVAL;
2540 	}
2541 
2542 	context->options.dscp_ecn = (uint8_t)dscp_ecn;
2543 
2544 	return 0;
2545 #else
2546 	return -ENOTSUP;
2547 #endif
2548 }
2549 
set_context_reuseaddr(struct net_context * context,const void * value,size_t len)2550 static int set_context_reuseaddr(struct net_context *context,
2551 				 const void *value, size_t len)
2552 {
2553 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
2554 	bool reuseaddr = false;
2555 
2556 	if (len != sizeof(int)) {
2557 		return -EINVAL;
2558 	}
2559 
2560 	if (*((int *) value) != 0) {
2561 		reuseaddr = true;
2562 	}
2563 
2564 	context->options.reuseaddr = reuseaddr;
2565 
2566 	return 0;
2567 #else
2568 	return -ENOTSUP;
2569 #endif
2570 }
2571 
set_context_reuseport(struct net_context * context,const void * value,size_t len)2572 static int set_context_reuseport(struct net_context *context,
2573 				 const void *value, size_t len)
2574 {
2575 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
2576 	bool reuseport = false;
2577 
2578 	if (len != sizeof(int)) {
2579 		return -EINVAL;
2580 	}
2581 
2582 	if (*((int *) value) != 0) {
2583 		reuseport = true;
2584 	}
2585 
2586 	context->options.reuseport = reuseport;
2587 
2588 	return 0;
2589 #else
2590 	return -ENOTSUP;
2591 #endif
2592 }
2593 
net_context_set_option(struct net_context * context,enum net_context_option option,const void * value,size_t len)2594 int net_context_set_option(struct net_context *context,
2595 			   enum net_context_option option,
2596 			   const void *value, size_t len)
2597 {
2598 	int ret = 0;
2599 
2600 	NET_ASSERT(context);
2601 
2602 	if (!PART_OF_ARRAY(contexts, context)) {
2603 		return -EINVAL;
2604 	}
2605 
2606 	k_mutex_lock(&context->lock, K_FOREVER);
2607 
2608 	switch (option) {
2609 	case NET_OPT_PRIORITY:
2610 		ret = set_context_priority(context, value, len);
2611 		break;
2612 	case NET_OPT_TXTIME:
2613 		ret = set_context_txtime(context, value, len);
2614 		break;
2615 	case NET_OPT_SOCKS5:
2616 		ret = set_context_proxy(context, value, len);
2617 		break;
2618 	case NET_OPT_RCVTIMEO:
2619 		ret = set_context_rcvtimeo(context, value, len);
2620 		break;
2621 	case NET_OPT_SNDTIMEO:
2622 		ret = set_context_sndtimeo(context, value, len);
2623 		break;
2624 	case NET_OPT_RCVBUF:
2625 		ret = set_context_rcvbuf(context, value, len);
2626 		break;
2627 	case NET_OPT_SNDBUF:
2628 		ret = set_context_sndbuf(context, value, len);
2629 		break;
2630 	case NET_OPT_DSCP_ECN:
2631 		ret = set_context_dscp_ecn(context, value, len);
2632 		break;
2633 	case NET_OPT_REUSEADDR:
2634 		ret = set_context_reuseaddr(context, value, len);
2635 		break;
2636 	case NET_OPT_REUSEPORT:
2637 		ret = set_context_reuseport(context, value, len);
2638 		break;
2639 	}
2640 
2641 	k_mutex_unlock(&context->lock);
2642 
2643 	return ret;
2644 }
2645 
net_context_get_option(struct net_context * context,enum net_context_option option,void * value,size_t * len)2646 int net_context_get_option(struct net_context *context,
2647 			    enum net_context_option option,
2648 			    void *value, size_t *len)
2649 {
2650 	int ret = 0;
2651 
2652 	NET_ASSERT(context);
2653 
2654 	if (!PART_OF_ARRAY(contexts, context)) {
2655 		return -EINVAL;
2656 	}
2657 
2658 	k_mutex_lock(&context->lock, K_FOREVER);
2659 
2660 	switch (option) {
2661 	case NET_OPT_PRIORITY:
2662 		ret = get_context_priority(context, value, len);
2663 		break;
2664 	case NET_OPT_TXTIME:
2665 		ret = get_context_txtime(context, value, len);
2666 		break;
2667 	case NET_OPT_SOCKS5:
2668 		ret = get_context_proxy(context, value, len);
2669 		break;
2670 	case NET_OPT_RCVTIMEO:
2671 		ret = get_context_rcvtimeo(context, value, len);
2672 		break;
2673 	case NET_OPT_SNDTIMEO:
2674 		ret = get_context_sndtimeo(context, value, len);
2675 		break;
2676 	case NET_OPT_RCVBUF:
2677 		ret = get_context_rcvbuf(context, value, len);
2678 		break;
2679 	case NET_OPT_SNDBUF:
2680 		ret = get_context_sndbuf(context, value, len);
2681 		break;
2682 	case NET_OPT_DSCP_ECN:
2683 		ret = get_context_dscp_ecn(context, value, len);
2684 		break;
2685 	case NET_OPT_REUSEADDR:
2686 		ret = get_context_reuseaddr(context, value, len);
2687 		break;
2688 	case NET_OPT_REUSEPORT:
2689 		ret = get_context_reuseport(context, value, len);
2690 		break;
2691 	}
2692 
2693 	k_mutex_unlock(&context->lock);
2694 
2695 	return ret;
2696 }
2697 
net_context_foreach(net_context_cb_t cb,void * user_data)2698 void net_context_foreach(net_context_cb_t cb, void *user_data)
2699 {
2700 	int i;
2701 
2702 	k_sem_take(&contexts_lock, K_FOREVER);
2703 
2704 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
2705 		if (!net_context_is_used(&contexts[i])) {
2706 			continue;
2707 		}
2708 
2709 		k_mutex_lock(&contexts[i].lock, K_FOREVER);
2710 
2711 		cb(&contexts[i], user_data);
2712 
2713 		k_mutex_unlock(&contexts[i].lock);
2714 	}
2715 
2716 	k_sem_give(&contexts_lock);
2717 }
2718 
net_context_state(struct net_context * context)2719 const char *net_context_state(struct net_context *context)
2720 {
2721 	switch (net_context_get_state(context)) {
2722 	case NET_CONTEXT_IDLE:
2723 		return "IDLE";
2724 	case NET_CONTEXT_CONNECTING:
2725 		return "CONNECTING";
2726 	case NET_CONTEXT_CONNECTED:
2727 		return "CONNECTED";
2728 	case NET_CONTEXT_LISTENING:
2729 		return "LISTENING";
2730 	}
2731 
2732 	return NULL;
2733 }
2734 
net_context_init(void)2735 void net_context_init(void)
2736 {
2737 	k_sem_init(&contexts_lock, 1, K_SEM_MAX_LIMIT);
2738 }
2739