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