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