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