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_send_data(pkt);
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 
2570 			/* Set the family to pkt if detected */
2571 			switch (type) {
2572 			case 0x60:
2573 				net_pkt_set_family(pkt, AF_INET6);
2574 				break;
2575 			case 0x40:
2576 				net_pkt_set_family(pkt, AF_INET);
2577 				break;
2578 			default:
2579 				/* Not IP traffic, let it go forward as it is */
2580 				break;
2581 			}
2582 
2583 			/* Pass to L2: */
2584 			ret = net_send_data(pkt);
2585 		} else {
2586 			net_if_queue_tx(net_pkt_iface(pkt), pkt);
2587 		}
2588 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN &&
2589 		   net_context_get_proto(context) == CAN_RAW) {
2590 		ret = context_write_data(pkt, buf, len, msghdr);
2591 		if (ret < 0) {
2592 			goto fail;
2593 		}
2594 
2595 		net_pkt_cursor_init(pkt);
2596 
2597 		ret = net_send_data(pkt);
2598 	} else {
2599 		NET_DBG("Unknown protocol while sending packet: %d",
2600 		net_context_get_proto(context));
2601 		ret = -EPROTONOSUPPORT;
2602 	}
2603 
2604 	if (ret < 0) {
2605 		goto fail;
2606 	}
2607 
2608 	return len;
2609 fail:
2610 	if (pkt != NULL) {
2611 		net_pkt_unref(pkt);
2612 	}
2613 
2614 	return ret;
2615 }
2616 
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)2617 int net_context_send(struct net_context *context,
2618 		     const void *buf,
2619 		     size_t len,
2620 		     net_context_send_cb_t cb,
2621 		     k_timeout_t timeout,
2622 		     void *user_data)
2623 {
2624 	socklen_t addrlen;
2625 	int ret = 0;
2626 
2627 	k_mutex_lock(&context->lock, K_FOREVER);
2628 
2629 	if (!(context->flags & NET_CONTEXT_REMOTE_ADDR_SET) ||
2630 	    !net_sin(&context->remote)->sin_port) {
2631 		ret = -EDESTADDRREQ;
2632 		goto unlock;
2633 	}
2634 
2635 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
2636 	    net_context_get_family(context) == AF_INET6) {
2637 		addrlen = sizeof(struct sockaddr_in6);
2638 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2639 		   net_context_get_family(context) == AF_INET) {
2640 		addrlen = sizeof(struct sockaddr_in);
2641 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2642 		   net_context_get_family(context) == AF_PACKET) {
2643 		ret = -EOPNOTSUPP;
2644 		goto unlock;
2645 	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2646 		   net_context_get_family(context) == AF_CAN) {
2647 		addrlen = sizeof(struct sockaddr_can);
2648 	} else {
2649 		addrlen = 0;
2650 	}
2651 
2652 	ret = context_sendto(context, buf, len, &context->remote,
2653 			     addrlen, cb, timeout, user_data, false);
2654 unlock:
2655 	k_mutex_unlock(&context->lock);
2656 
2657 	return ret;
2658 }
2659 
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)2660 int net_context_sendmsg(struct net_context *context,
2661 			const struct msghdr *msghdr,
2662 			int flags,
2663 			net_context_send_cb_t cb,
2664 			k_timeout_t timeout,
2665 			void *user_data)
2666 {
2667 	int ret;
2668 
2669 	k_mutex_lock(&context->lock, K_FOREVER);
2670 
2671 	ret = context_sendto(context, msghdr, 0, NULL, 0,
2672 			     cb, timeout, user_data, true);
2673 
2674 	k_mutex_unlock(&context->lock);
2675 
2676 	return ret;
2677 }
2678 
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)2679 int net_context_sendto(struct net_context *context,
2680 		       const void *buf,
2681 		       size_t len,
2682 		       const struct sockaddr *dst_addr,
2683 		       socklen_t addrlen,
2684 		       net_context_send_cb_t cb,
2685 		       k_timeout_t timeout,
2686 		       void *user_data)
2687 {
2688 	int ret;
2689 
2690 	k_mutex_lock(&context->lock, K_FOREVER);
2691 
2692 	ret = context_sendto(context, buf, len, dst_addr, addrlen,
2693 			     cb, timeout, user_data, true);
2694 
2695 	k_mutex_unlock(&context->lock);
2696 
2697 	return ret;
2698 }
2699 
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)2700 enum net_verdict net_context_packet_received(struct net_conn *conn,
2701 					     struct net_pkt *pkt,
2702 					     union net_ip_header *ip_hdr,
2703 					     union net_proto_header *proto_hdr,
2704 					     void *user_data)
2705 {
2706 	struct net_context *context = find_context(conn);
2707 	enum net_verdict verdict = NET_DROP;
2708 
2709 	NET_ASSERT(context);
2710 	NET_ASSERT(net_pkt_iface(pkt));
2711 
2712 	k_mutex_lock(&context->lock, K_FOREVER);
2713 
2714 	net_context_set_iface(context, net_pkt_iface(pkt));
2715 	net_pkt_set_context(pkt, context);
2716 
2717 	/* If there is no callback registered, then we can only drop
2718 	 * the packet.
2719 	 */
2720 	if (!context->recv_cb) {
2721 		goto unlock;
2722 	}
2723 
2724 	if (net_context_get_proto(context) == IPPROTO_TCP) {
2725 		net_stats_update_tcp_recv(net_pkt_iface(pkt),
2726 					  net_pkt_remaining_data(pkt));
2727 	}
2728 
2729 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2730 	k_sem_give(&context->recv_data_wait);
2731 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2732 
2733 	k_mutex_unlock(&context->lock);
2734 
2735 	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
2736 
2737 	verdict = NET_OK;
2738 
2739 	return verdict;
2740 
2741 unlock:
2742 	k_mutex_unlock(&context->lock);
2743 
2744 	return verdict;
2745 }
2746 
2747 #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)2748 static int recv_udp(struct net_context *context,
2749 		    net_context_recv_cb_t cb,
2750 		    k_timeout_t timeout,
2751 		    void *user_data)
2752 {
2753 	struct sockaddr local_addr = {
2754 		.sa_family = net_context_get_family(context),
2755 	};
2756 	struct sockaddr *laddr = NULL;
2757 	uint16_t lport = 0U;
2758 	int ret;
2759 
2760 	ARG_UNUSED(timeout);
2761 
2762 	/* If the context already has a connection handler, it means it's
2763 	 * already registered. In that case, all we have to do is 1) update
2764 	 * the callback registered in the net_context and 2) update the
2765 	 * user_data and remote address and port using net_conn_update().
2766 	 *
2767 	 * The callback function passed to net_conn_update() must be the same
2768 	 * function as the one passed to net_conn_register(), not the callback
2769 	 * set for the net context passed by recv_udp().
2770 	 */
2771 	if (context->conn_handler) {
2772 		context->recv_cb = cb;
2773 		ret = net_conn_update(context->conn_handler,
2774 				      net_context_packet_received,
2775 				      user_data,
2776 				      context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
2777 						&context->remote : NULL,
2778 				      ntohs(net_sin(&context->remote)->sin_port));
2779 		return ret;
2780 	}
2781 
2782 	ret = bind_default(context);
2783 	if (ret) {
2784 		return ret;
2785 	}
2786 
2787 	if (IS_ENABLED(CONFIG_NET_IPV6) &&
2788 	    net_context_get_family(context) == AF_INET6) {
2789 		if (net_sin6_ptr(&context->local)->sin6_addr) {
2790 			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
2791 				     net_sin6_ptr(&context->local)->sin6_addr);
2792 
2793 			laddr = &local_addr;
2794 		}
2795 
2796 		net_sin6(&local_addr)->sin6_port =
2797 			net_sin6((struct sockaddr *)&context->local)->sin6_port;
2798 		lport = net_sin6((struct sockaddr *)&context->local)->sin6_port;
2799 	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2800 		   net_context_get_family(context) == AF_INET) {
2801 		if (net_sin_ptr(&context->local)->sin_addr) {
2802 			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
2803 				      net_sin_ptr(&context->local)->sin_addr);
2804 
2805 			laddr = &local_addr;
2806 		}
2807 
2808 		lport = net_sin((struct sockaddr *)&context->local)->sin_port;
2809 	}
2810 
2811 	context->recv_cb = cb;
2812 
2813 	ret = net_conn_register(net_context_get_proto(context),
2814 				net_context_get_family(context),
2815 				context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
2816 							&context->remote : NULL,
2817 				laddr,
2818 				ntohs(net_sin(&context->remote)->sin_port),
2819 				ntohs(lport),
2820 				context,
2821 				net_context_packet_received,
2822 				user_data,
2823 				&context->conn_handler);
2824 
2825 	return ret;
2826 }
2827 #else
2828 #define recv_udp(...) 0
2829 #endif /* CONFIG_NET_NATIVE_UDP */
2830 
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)2831 static enum net_verdict net_context_raw_packet_received(
2832 					struct net_conn *conn,
2833 					struct net_pkt *pkt,
2834 					union net_ip_header *ip_hdr,
2835 					union net_proto_header *proto_hdr,
2836 					void *user_data)
2837 {
2838 	struct net_context *context = find_context(conn);
2839 
2840 	NET_ASSERT(context);
2841 	NET_ASSERT(net_pkt_iface(pkt));
2842 
2843 	/* If there is no callback registered, then we can only drop
2844 	 * the packet.
2845 	 */
2846 
2847 	if (!context->recv_cb) {
2848 		return NET_DROP;
2849 	}
2850 
2851 	net_context_set_iface(context, net_pkt_iface(pkt));
2852 	net_pkt_set_context(pkt, context);
2853 
2854 	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
2855 
2856 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2857 	k_sem_give(&context->recv_data_wait);
2858 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2859 
2860 	return NET_OK;
2861 }
2862 
recv_raw(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,struct sockaddr * local_addr,void * user_data)2863 static int recv_raw(struct net_context *context,
2864 		    net_context_recv_cb_t cb,
2865 		    k_timeout_t timeout,
2866 		    struct sockaddr *local_addr,
2867 		    void *user_data)
2868 {
2869 	int ret;
2870 
2871 	ARG_UNUSED(timeout);
2872 
2873 	/* If the context already has a connection handler, it means it's
2874 	 * already registered. In that case, all we have to do is 1) update
2875 	 * the callback registered in the net_context and 2) update the
2876 	 * user_data using net_conn_update().
2877 	 *
2878 	 * The callback function passed to net_conn_update() must be the same
2879 	 * function as the one passed to net_conn_register(), not the callback
2880 	 * set for the net context passed by recv_raw().
2881 	 */
2882 	if (context->conn_handler) {
2883 		context->recv_cb = cb;
2884 		ret = net_conn_update(context->conn_handler,
2885 				      net_context_raw_packet_received,
2886 				      user_data,
2887 				      NULL, 0);
2888 		return ret;
2889 	}
2890 
2891 	ret = bind_default(context);
2892 	if (ret) {
2893 		return ret;
2894 	}
2895 
2896 	context->recv_cb = cb;
2897 
2898 	ret = net_conn_register(net_context_get_proto(context),
2899 				net_context_get_family(context),
2900 				NULL, local_addr, 0, 0,
2901 				context,
2902 				net_context_raw_packet_received,
2903 				user_data,
2904 				&context->conn_handler);
2905 
2906 	return ret;
2907 }
2908 
net_context_recv(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)2909 int net_context_recv(struct net_context *context,
2910 		     net_context_recv_cb_t cb,
2911 		     k_timeout_t timeout,
2912 		     void *user_data)
2913 {
2914 	int ret;
2915 	NET_ASSERT(context);
2916 
2917 	if (!net_context_is_used(context)) {
2918 		return -EBADF;
2919 	}
2920 
2921 	k_mutex_lock(&context->lock, K_FOREVER);
2922 
2923 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
2924 	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
2925 		ret = net_offload_recv(
2926 			net_context_get_iface(context),
2927 			context, cb, timeout, user_data);
2928 		goto unlock;
2929 	}
2930 
2931 	if (IS_ENABLED(CONFIG_NET_UDP) &&
2932 	    net_context_get_proto(context) == IPPROTO_UDP) {
2933 		ret = recv_udp(context, cb, timeout, user_data);
2934 	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
2935 		   net_context_get_proto(context) == IPPROTO_TCP) {
2936 		ret = net_tcp_recv(context, cb, user_data);
2937 	} else {
2938 		if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2939 		    net_context_get_family(context) == AF_PACKET) {
2940 			struct sockaddr_ll addr;
2941 
2942 			addr.sll_family = AF_PACKET;
2943 			addr.sll_ifindex =
2944 				net_sll_ptr(&context->local)->sll_ifindex;
2945 			addr.sll_protocol =
2946 				net_sll_ptr(&context->local)->sll_protocol;
2947 			addr.sll_halen =
2948 				net_sll_ptr(&context->local)->sll_halen;
2949 
2950 			memcpy(addr.sll_addr,
2951 			       net_sll_ptr(&context->local)->sll_addr,
2952 			       MIN(addr.sll_halen, sizeof(addr.sll_addr)));
2953 
2954 			ret = recv_raw(context, cb, timeout,
2955 				       (struct sockaddr *)&addr, user_data);
2956 		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2957 			   net_context_get_family(context) == AF_CAN) {
2958 			struct sockaddr_can local_addr = {
2959 				.can_family = AF_CAN,
2960 			};
2961 
2962 			ret = recv_raw(context, cb, timeout,
2963 				       (struct sockaddr *)&local_addr,
2964 				       user_data);
2965 			if (ret == -EALREADY) {
2966 				/* This is perfectly normal for CAN sockets.
2967 				 * The SocketCAN will dispatch the packet to
2968 				 * correct net_context listener.
2969 				 */
2970 				ret = 0;
2971 			}
2972 		} else {
2973 			ret = -EPROTOTYPE;
2974 		}
2975 	}
2976 
2977 	if (ret < 0) {
2978 		goto unlock;
2979 	}
2980 
2981 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2982 	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
2983 		/* Make sure we have the lock, then the
2984 		 * net_context_packet_received() callback will release the
2985 		 * semaphore when data has been received.
2986 		 */
2987 		k_sem_reset(&context->recv_data_wait);
2988 
2989 		k_mutex_unlock(&context->lock);
2990 
2991 		if (k_sem_take(&context->recv_data_wait, timeout) == -EAGAIN) {
2992 			ret = -ETIMEDOUT;
2993 		}
2994 
2995 		k_mutex_lock(&context->lock, K_FOREVER);
2996 	}
2997 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2998 
2999 unlock:
3000 	k_mutex_unlock(&context->lock);
3001 
3002 	return ret;
3003 }
3004 
net_context_update_recv_wnd(struct net_context * context,int32_t delta)3005 int net_context_update_recv_wnd(struct net_context *context,
3006 				int32_t delta)
3007 {
3008 	int ret;
3009 
3010 	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
3011 		net_if_is_ip_offloaded(net_context_get_iface(context))) {
3012 		return 0;
3013 	}
3014 
3015 	k_mutex_lock(&context->lock, K_FOREVER);
3016 
3017 	ret = net_tcp_update_recv_wnd(context, delta);
3018 
3019 	k_mutex_unlock(&context->lock);
3020 
3021 	return ret;
3022 }
3023 
set_bool_option(bool * option,const void * value,size_t len)3024 __maybe_unused static int set_bool_option(bool *option, const void *value, size_t len)
3025 {
3026 	if (value == NULL) {
3027 		return -EINVAL;
3028 	}
3029 
3030 	if (len != sizeof(int)) {
3031 		return -EINVAL;
3032 	}
3033 
3034 	*option = !!*((int *)value);
3035 
3036 	return 0;
3037 }
3038 
set_uint8_option(uint8_t * option,const void * value,size_t len)3039 __maybe_unused static int set_uint8_option(uint8_t *option, const void *value, size_t len)
3040 {
3041 	if (value == NULL) {
3042 		return -EINVAL;
3043 	}
3044 
3045 	if (len > sizeof(uint8_t)) {
3046 		return -EINVAL;
3047 	}
3048 
3049 	*option = *((uint8_t *)value);
3050 
3051 	return 0;
3052 }
3053 
set_uint16_option(uint16_t * option,const void * value,size_t len)3054 __maybe_unused static int set_uint16_option(uint16_t *option, const void *value, size_t len)
3055 {
3056 	int v;
3057 
3058 	if (value == NULL) {
3059 		return -EINVAL;
3060 	}
3061 
3062 	if (len != sizeof(int)) {
3063 		return -EINVAL;
3064 	}
3065 
3066 	v = *((int *)value);
3067 
3068 	if (v < 0 || v > UINT16_MAX) {
3069 		return -EINVAL;
3070 	}
3071 
3072 	*option = (uint16_t)v;
3073 
3074 	return 0;
3075 
3076 }
3077 
set_context_priority(struct net_context * context,const void * value,size_t len)3078 static int set_context_priority(struct net_context *context,
3079 				const void *value, size_t len)
3080 {
3081 #if defined(CONFIG_NET_CONTEXT_PRIORITY)
3082 	return set_uint8_option(&context->options.priority, value, len);
3083 #else
3084 	ARG_UNUSED(context);
3085 	ARG_UNUSED(value);
3086 	ARG_UNUSED(len);
3087 
3088 	return -ENOTSUP;
3089 #endif
3090 }
3091 
set_context_txtime(struct net_context * context,const void * value,size_t len)3092 static int set_context_txtime(struct net_context *context,
3093 			      const void *value, size_t len)
3094 {
3095 #if defined(CONFIG_NET_CONTEXT_TXTIME)
3096 	return set_bool_option(&context->options.txtime, value, len);
3097 #else
3098 	ARG_UNUSED(context);
3099 	ARG_UNUSED(value);
3100 	ARG_UNUSED(len);
3101 
3102 	return -ENOTSUP;
3103 #endif
3104 }
3105 
set_context_proxy(struct net_context * context,const void * value,size_t len)3106 static int set_context_proxy(struct net_context *context,
3107 			     const void *value, size_t len)
3108 {
3109 #if defined(CONFIG_SOCKS)
3110 	struct sockaddr *addr = (struct sockaddr *)value;
3111 
3112 	if (len > NET_SOCKADDR_MAX_SIZE) {
3113 		return -EINVAL;
3114 	}
3115 
3116 	if (addr->sa_family != net_context_get_family(context)) {
3117 		return -EINVAL;
3118 	}
3119 
3120 	context->options.proxy.addrlen = len;
3121 	memcpy(&context->options.proxy.addr, addr, len);
3122 
3123 	return 0;
3124 #else
3125 	ARG_UNUSED(context);
3126 	ARG_UNUSED(value);
3127 	ARG_UNUSED(len);
3128 
3129 	return -ENOTSUP;
3130 #endif
3131 }
3132 
set_context_rcvtimeo(struct net_context * context,const void * value,size_t len)3133 static int set_context_rcvtimeo(struct net_context *context,
3134 				const void *value, size_t len)
3135 {
3136 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
3137 	if (len != sizeof(k_timeout_t)) {
3138 		return -EINVAL;
3139 	}
3140 
3141 	context->options.rcvtimeo = *((k_timeout_t *)value);
3142 
3143 	return 0;
3144 #else
3145 	ARG_UNUSED(context);
3146 	ARG_UNUSED(value);
3147 	ARG_UNUSED(len);
3148 
3149 	return -ENOTSUP;
3150 #endif
3151 }
3152 
set_context_sndtimeo(struct net_context * context,const void * value,size_t len)3153 static int set_context_sndtimeo(struct net_context *context,
3154 				const void *value, size_t len)
3155 {
3156 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
3157 	if (len != sizeof(k_timeout_t)) {
3158 		return -EINVAL;
3159 	}
3160 
3161 	context->options.sndtimeo = *((k_timeout_t *)value);
3162 
3163 	return 0;
3164 #else
3165 	ARG_UNUSED(context);
3166 	ARG_UNUSED(value);
3167 	ARG_UNUSED(len);
3168 
3169 	return -ENOTSUP;
3170 #endif
3171 }
3172 
set_context_rcvbuf(struct net_context * context,const void * value,size_t len)3173 static int set_context_rcvbuf(struct net_context *context,
3174 				const void *value, size_t len)
3175 {
3176 #if defined(CONFIG_NET_CONTEXT_RCVBUF)
3177 	return set_uint16_option(&context->options.rcvbuf, value, len);
3178 #else
3179 	ARG_UNUSED(context);
3180 	ARG_UNUSED(value);
3181 	ARG_UNUSED(len);
3182 
3183 	return -ENOTSUP;
3184 #endif
3185 }
3186 
set_context_sndbuf(struct net_context * context,const void * value,size_t len)3187 static int set_context_sndbuf(struct net_context *context,
3188 				const void *value, size_t len)
3189 {
3190 #if defined(CONFIG_NET_CONTEXT_SNDBUF)
3191 	return set_uint16_option(&context->options.sndbuf, value, len);
3192 #else
3193 	ARG_UNUSED(context);
3194 	ARG_UNUSED(value);
3195 	ARG_UNUSED(len);
3196 
3197 	return -ENOTSUP;
3198 #endif
3199 }
3200 
set_context_dscp_ecn(struct net_context * context,const void * value,size_t len)3201 static int set_context_dscp_ecn(struct net_context *context,
3202 				const void *value, size_t len)
3203 {
3204 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
3205 	return set_uint8_option(&context->options.dscp_ecn, value, len);
3206 #else
3207 	ARG_UNUSED(context);
3208 	ARG_UNUSED(value);
3209 	ARG_UNUSED(len);
3210 
3211 	return -ENOTSUP;
3212 #endif
3213 }
3214 
set_context_ttl(struct net_context * context,const void * value,size_t len)3215 static int set_context_ttl(struct net_context *context,
3216 			   const void *value, size_t len)
3217 {
3218 #if defined(CONFIG_NET_IPV4)
3219 	uint8_t ttl = *((int *)value);
3220 
3221 	len = sizeof(context->ipv4_ttl);
3222 
3223 	return set_uint8_option(&context->ipv4_ttl, &ttl, len);
3224 #else
3225 	ARG_UNUSED(context);
3226 	ARG_UNUSED(value);
3227 	ARG_UNUSED(len);
3228 
3229 	return -ENOTSUP;
3230 #endif
3231 }
3232 
set_context_mcast_ttl(struct net_context * context,const void * value,size_t len)3233 static int set_context_mcast_ttl(struct net_context *context,
3234 				 const void *value, size_t len)
3235 {
3236 #if defined(CONFIG_NET_IPV4)
3237 	uint8_t mcast_ttl = *((int *)value);
3238 
3239 	len = sizeof(context->ipv4_mcast_ttl);
3240 
3241 	return set_uint8_option(&context->ipv4_mcast_ttl, &mcast_ttl, len);
3242 #else
3243 	ARG_UNUSED(context);
3244 	ARG_UNUSED(value);
3245 	ARG_UNUSED(len);
3246 
3247 	return -ENOTSUP;
3248 #endif
3249 }
3250 
set_context_mcast_hop_limit(struct net_context * context,const void * value,size_t len)3251 static int set_context_mcast_hop_limit(struct net_context *context,
3252 				       const void *value, size_t len)
3253 {
3254 #if defined(CONFIG_NET_IPV6)
3255 	int mcast_hop_limit = *((int *)value);
3256 
3257 	if (len != sizeof(int)) {
3258 		return -EINVAL;
3259 	}
3260 
3261 	if (mcast_hop_limit == -1) {
3262 		/* If value is -1 then use the system default.
3263 		 * This is done same way as in Linux.
3264 		 */
3265 		if (net_if_get_by_index(context->iface) == NULL) {
3266 			mcast_hop_limit = INITIAL_MCAST_HOP_LIMIT;
3267 		} else {
3268 			mcast_hop_limit = net_if_ipv6_get_mcast_hop_limit(
3269 				net_if_get_by_index(context->iface));
3270 		}
3271 	} else if (mcast_hop_limit < 0 || mcast_hop_limit > 255) {
3272 		return -EINVAL;
3273 	}
3274 
3275 	context->ipv6_mcast_hop_limit = mcast_hop_limit;
3276 
3277 	return 0;
3278 #else
3279 	ARG_UNUSED(context);
3280 	ARG_UNUSED(value);
3281 	ARG_UNUSED(len);
3282 
3283 	return -ENOTSUP;
3284 #endif
3285 }
3286 
set_context_unicast_hop_limit(struct net_context * context,const void * value,size_t len)3287 static int set_context_unicast_hop_limit(struct net_context *context,
3288 					 const void *value, size_t len)
3289 {
3290 #if defined(CONFIG_NET_IPV6)
3291 	uint8_t unicast_hop_limit = *((int *)value);
3292 
3293 	len = sizeof(context->ipv6_hop_limit);
3294 
3295 	return set_uint8_option(&context->ipv6_hop_limit,
3296 				&unicast_hop_limit, len);
3297 #else
3298 	ARG_UNUSED(context);
3299 	ARG_UNUSED(value);
3300 	ARG_UNUSED(len);
3301 
3302 	return -ENOTSUP;
3303 #endif
3304 }
3305 
set_context_reuseaddr(struct net_context * context,const void * value,size_t len)3306 static int set_context_reuseaddr(struct net_context *context,
3307 				 const void *value, size_t len)
3308 {
3309 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
3310 	return set_bool_option(&context->options.reuseaddr, value, len);
3311 #else
3312 	ARG_UNUSED(context);
3313 	ARG_UNUSED(value);
3314 	ARG_UNUSED(len);
3315 
3316 	return -ENOTSUP;
3317 #endif
3318 }
3319 
set_context_reuseport(struct net_context * context,const void * value,size_t len)3320 static int set_context_reuseport(struct net_context *context,
3321 				 const void *value, size_t len)
3322 {
3323 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
3324 	return set_bool_option(&context->options.reuseport, value, len);
3325 #else
3326 	ARG_UNUSED(context);
3327 	ARG_UNUSED(value);
3328 	ARG_UNUSED(len);
3329 
3330 	return -ENOTSUP;
3331 #endif
3332 }
3333 
set_context_ipv6_mtu(struct net_context * context,const void * value,size_t len)3334 static int set_context_ipv6_mtu(struct net_context *context,
3335 				const void *value, size_t len)
3336 {
3337 #if defined(CONFIG_NET_IPV6)
3338 	struct net_if *iface;
3339 	uint16_t mtu;
3340 
3341 	if (len != sizeof(int)) {
3342 		return -EINVAL;
3343 	}
3344 
3345 	mtu = *((int *)value);
3346 
3347 	if (IS_ENABLED(CONFIG_NET_IPV6_PMTU)) {
3348 		int ret;
3349 
3350 		ret = net_pmtu_update_mtu(&context->remote, mtu);
3351 		if (ret < 0) {
3352 			return ret;
3353 		}
3354 
3355 		return 0;
3356 	}
3357 
3358 	if (net_context_is_bound_to_iface(context)) {
3359 		iface = net_context_get_iface(context);
3360 	} else {
3361 		sa_family_t family = net_context_get_family(context);
3362 
3363 		if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
3364 			iface = net_if_ipv6_select_src_iface(
3365 				&net_sin6(&context->remote)->sin6_addr);
3366 		} else {
3367 			return -EAFNOSUPPORT;
3368 		}
3369 	}
3370 
3371 	net_if_set_mtu(iface, (uint16_t)mtu);
3372 
3373 	return 0;
3374 #else
3375 	ARG_UNUSED(context);
3376 	ARG_UNUSED(value);
3377 	ARG_UNUSED(len);
3378 
3379 	return -ENOTSUP;
3380 #endif
3381 }
3382 
set_context_ipv6_v6only(struct net_context * context,const void * value,size_t len)3383 static int set_context_ipv6_v6only(struct net_context *context,
3384 				   const void *value, size_t len)
3385 {
3386 #if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
3387 	return set_bool_option(&context->options.ipv6_v6only, value, len);
3388 #else
3389 	ARG_UNUSED(context);
3390 	ARG_UNUSED(value);
3391 	ARG_UNUSED(len);
3392 
3393 	return -ENOTSUP;
3394 #endif
3395 }
3396 
set_context_recv_pktinfo(struct net_context * context,const void * value,size_t len)3397 static int set_context_recv_pktinfo(struct net_context *context,
3398 				    const void *value, size_t len)
3399 {
3400 #if defined(CONFIG_NET_CONTEXT_RECV_PKTINFO)
3401 	return set_bool_option(&context->options.recv_pktinfo, value, len);
3402 #else
3403 	ARG_UNUSED(context);
3404 	ARG_UNUSED(value);
3405 	ARG_UNUSED(len);
3406 
3407 	return -ENOTSUP;
3408 #endif
3409 }
3410 
set_context_addr_preferences(struct net_context * context,const void * value,size_t len)3411 static int set_context_addr_preferences(struct net_context *context,
3412 					const void *value, size_t len)
3413 {
3414 #if defined(CONFIG_NET_IPV6)
3415 	return set_uint16_option(&context->options.addr_preferences,
3416 				 value, len);
3417 #else
3418 	ARG_UNUSED(context);
3419 	ARG_UNUSED(value);
3420 	ARG_UNUSED(len);
3421 
3422 	return -ENOTSUP;
3423 #endif
3424 }
3425 
set_context_timestamping(struct net_context * context,const void * value,size_t len)3426 static int set_context_timestamping(struct net_context *context,
3427 				    const void *value, size_t len)
3428 {
3429 #if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
3430 	uint8_t timestamping_flags = *((uint8_t *)value);
3431 
3432 	return set_uint8_option(&context->options.timestamping,
3433 				&timestamping_flags, len);
3434 #else
3435 	ARG_UNUSED(context);
3436 	ARG_UNUSED(value);
3437 	ARG_UNUSED(len);
3438 
3439 	return -ENOTSUP;
3440 #endif
3441 }
3442 
set_context_mcast_ifindex(struct net_context * context,const void * value,size_t len)3443 static int set_context_mcast_ifindex(struct net_context *context,
3444 				     const void *value, size_t len)
3445 {
3446 #if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
3447 	sa_family_t family = net_context_get_family(context);
3448 	int mcast_ifindex = *((int *)value);
3449 	enum net_sock_type type;
3450 	struct net_if *iface;
3451 
3452 	if ((IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) ||
3453 	    (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET)) {
3454 
3455 		if (len != sizeof(int)) {
3456 			return -EINVAL;
3457 		}
3458 
3459 		type = net_context_get_type(context);
3460 		if (type != SOCK_DGRAM) {
3461 			return -EINVAL;
3462 		}
3463 
3464 		/* optlen equal to 0 then remove the binding */
3465 		if (mcast_ifindex == 0) {
3466 			context->options.ipv6_mcast_ifindex = 0;
3467 			return 0;
3468 		}
3469 
3470 		if (mcast_ifindex < 1 || mcast_ifindex > 255) {
3471 			return -EINVAL;
3472 		}
3473 
3474 		iface = net_if_get_by_index(mcast_ifindex);
3475 		if (iface == NULL) {
3476 			return -ENOENT;
3477 		}
3478 
3479 		if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
3480 			if (!net_if_flag_is_set(iface, NET_IF_IPV6)) {
3481 				return -EPROTOTYPE;
3482 			}
3483 		} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
3484 			if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
3485 				return -EPROTOTYPE;
3486 			}
3487 		}
3488 
3489 		context->options.ipv6_mcast_ifindex = mcast_ifindex;
3490 
3491 		return 0;
3492 	}
3493 
3494 	return -EAFNOSUPPORT;
3495 #else
3496 	ARG_UNUSED(context);
3497 	ARG_UNUSED(value);
3498 	ARG_UNUSED(len);
3499 
3500 	return -ENOTSUP;
3501 #endif
3502 }
3503 
set_context_local_port_range(struct net_context * context,const void * value,size_t len)3504 static int set_context_local_port_range(struct net_context *context,
3505 					const void *value, size_t len)
3506 {
3507 #if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)
3508 	uint16_t lower_range, upper_range;
3509 	uint32_t port_range;
3510 
3511 	if (len != sizeof(uint32_t)) {
3512 		return -EINVAL;
3513 	}
3514 
3515 	port_range = *((uint32_t *)value);
3516 	lower_range = port_range & 0xffff;
3517 	upper_range = port_range >> 16;
3518 
3519 	/* If the range is 0, then it means that the port range clamping
3520 	 * is disabled. If the range is not 0, then the lower range must
3521 	 * be smaller than the upper range.
3522 	 */
3523 	if (lower_range != 0U && upper_range != 0U &&
3524 	    lower_range >= upper_range) {
3525 		return -EINVAL;
3526 	}
3527 
3528 	/* If either of the range is 0, then that bound has no effect.
3529 	 * This is checked when the emphemeral port is selected.
3530 	 */
3531 	context->options.port_range = port_range;
3532 
3533 	return 0;
3534 #else
3535 	ARG_UNUSED(context);
3536 	ARG_UNUSED(value);
3537 	ARG_UNUSED(len);
3538 
3539 	return -ENOTSUP;
3540 #endif
3541 }
3542 
net_context_set_option(struct net_context * context,enum net_context_option option,const void * value,size_t len)3543 int net_context_set_option(struct net_context *context,
3544 			   enum net_context_option option,
3545 			   const void *value, size_t len)
3546 {
3547 	int ret = 0;
3548 
3549 	NET_ASSERT(context);
3550 
3551 	if (!PART_OF_ARRAY(contexts, context)) {
3552 		return -EINVAL;
3553 	}
3554 
3555 	k_mutex_lock(&context->lock, K_FOREVER);
3556 
3557 	switch (option) {
3558 	case NET_OPT_PRIORITY:
3559 		ret = set_context_priority(context, value, len);
3560 		break;
3561 	case NET_OPT_TXTIME:
3562 		ret = set_context_txtime(context, value, len);
3563 		break;
3564 	case NET_OPT_SOCKS5:
3565 		ret = set_context_proxy(context, value, len);
3566 		break;
3567 	case NET_OPT_RCVTIMEO:
3568 		ret = set_context_rcvtimeo(context, value, len);
3569 		break;
3570 	case NET_OPT_SNDTIMEO:
3571 		ret = set_context_sndtimeo(context, value, len);
3572 		break;
3573 	case NET_OPT_RCVBUF:
3574 		ret = set_context_rcvbuf(context, value, len);
3575 		break;
3576 	case NET_OPT_SNDBUF:
3577 		ret = set_context_sndbuf(context, value, len);
3578 		break;
3579 	case NET_OPT_DSCP_ECN:
3580 		ret = set_context_dscp_ecn(context, value, len);
3581 		break;
3582 	case NET_OPT_TTL:
3583 		ret = set_context_ttl(context, value, len);
3584 		break;
3585 	case NET_OPT_MCAST_TTL:
3586 		ret = set_context_mcast_ttl(context, value, len);
3587 		break;
3588 	case NET_OPT_MCAST_HOP_LIMIT:
3589 		ret = set_context_mcast_hop_limit(context, value, len);
3590 		break;
3591 	case NET_OPT_UNICAST_HOP_LIMIT:
3592 		ret = set_context_unicast_hop_limit(context, value, len);
3593 		break;
3594 	case NET_OPT_REUSEADDR:
3595 		ret = set_context_reuseaddr(context, value, len);
3596 		break;
3597 	case NET_OPT_REUSEPORT:
3598 		ret = set_context_reuseport(context, value, len);
3599 		break;
3600 	case NET_OPT_IPV6_V6ONLY:
3601 		ret = set_context_ipv6_v6only(context, value, len);
3602 		break;
3603 	case NET_OPT_RECV_PKTINFO:
3604 		ret = set_context_recv_pktinfo(context, value, len);
3605 		break;
3606 	case NET_OPT_ADDR_PREFERENCES:
3607 		ret = set_context_addr_preferences(context, value, len);
3608 		break;
3609 	case NET_OPT_TIMESTAMPING:
3610 		ret = set_context_timestamping(context, value, len);
3611 		break;
3612 	case NET_OPT_MTU:
3613 		/* IPv4 only supports getting the MTU */
3614 		if (IS_ENABLED(CONFIG_NET_IPV4) &&
3615 		    net_context_get_family(context) == AF_INET) {
3616 			ret = -EOPNOTSUPP;
3617 		} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
3618 			   net_context_get_family(context) == AF_INET6) {
3619 			ret = set_context_ipv6_mtu(context, value, len);
3620 		}
3621 
3622 		break;
3623 	case NET_OPT_MCAST_IFINDEX:
3624 		ret = set_context_mcast_ifindex(context, value, len);
3625 		break;
3626 	case NET_OPT_LOCAL_PORT_RANGE:
3627 		ret = set_context_local_port_range(context, value, len);
3628 		break;
3629 	}
3630 
3631 	k_mutex_unlock(&context->lock);
3632 
3633 	return ret;
3634 }
3635 
net_context_get_option(struct net_context * context,enum net_context_option option,void * value,size_t * len)3636 int net_context_get_option(struct net_context *context,
3637 			    enum net_context_option option,
3638 			    void *value, size_t *len)
3639 {
3640 	int ret = 0;
3641 
3642 	NET_ASSERT(context);
3643 
3644 	if (!PART_OF_ARRAY(contexts, context)) {
3645 		return -EINVAL;
3646 	}
3647 
3648 	k_mutex_lock(&context->lock, K_FOREVER);
3649 
3650 	switch (option) {
3651 	case NET_OPT_PRIORITY:
3652 		ret = get_context_priority(context, value, len);
3653 		break;
3654 	case NET_OPT_TXTIME:
3655 		ret = get_context_txtime(context, value, len);
3656 		break;
3657 	case NET_OPT_SOCKS5:
3658 		ret = get_context_proxy(context, value, len);
3659 		break;
3660 	case NET_OPT_RCVTIMEO:
3661 		ret = get_context_rcvtimeo(context, value, len);
3662 		break;
3663 	case NET_OPT_SNDTIMEO:
3664 		ret = get_context_sndtimeo(context, value, len);
3665 		break;
3666 	case NET_OPT_RCVBUF:
3667 		ret = get_context_rcvbuf(context, value, len);
3668 		break;
3669 	case NET_OPT_SNDBUF:
3670 		ret = get_context_sndbuf(context, value, len);
3671 		break;
3672 	case NET_OPT_DSCP_ECN:
3673 		ret = get_context_dscp_ecn(context, value, len);
3674 		break;
3675 	case NET_OPT_TTL:
3676 		ret = get_context_ttl(context, value, len);
3677 		break;
3678 	case NET_OPT_MCAST_TTL:
3679 		ret = get_context_mcast_ttl(context, value, len);
3680 		break;
3681 	case NET_OPT_MCAST_HOP_LIMIT:
3682 		ret = get_context_mcast_hop_limit(context, value, len);
3683 		break;
3684 	case NET_OPT_UNICAST_HOP_LIMIT:
3685 		ret = get_context_unicast_hop_limit(context, value, len);
3686 		break;
3687 	case NET_OPT_REUSEADDR:
3688 		ret = get_context_reuseaddr(context, value, len);
3689 		break;
3690 	case NET_OPT_REUSEPORT:
3691 		ret = get_context_reuseport(context, value, len);
3692 		break;
3693 	case NET_OPT_IPV6_V6ONLY:
3694 		ret = get_context_ipv6_v6only(context, value, len);
3695 		break;
3696 	case NET_OPT_RECV_PKTINFO:
3697 		ret = get_context_recv_pktinfo(context, value, len);
3698 		break;
3699 	case NET_OPT_ADDR_PREFERENCES:
3700 		ret = get_context_addr_preferences(context, value, len);
3701 		break;
3702 	case NET_OPT_TIMESTAMPING:
3703 		ret = get_context_timestamping(context, value, len);
3704 		break;
3705 	case NET_OPT_MTU:
3706 		ret = get_context_mtu(context, value, len);
3707 		break;
3708 	case NET_OPT_MCAST_IFINDEX:
3709 		ret = get_context_mcast_ifindex(context, value, len);
3710 		break;
3711 	case NET_OPT_LOCAL_PORT_RANGE:
3712 		ret = get_context_local_port_range(context, value, len);
3713 		break;
3714 	}
3715 
3716 	k_mutex_unlock(&context->lock);
3717 
3718 	return ret;
3719 }
3720 
net_context_get_local_addr(struct net_context * ctx,struct sockaddr * addr,socklen_t * addrlen)3721 int net_context_get_local_addr(struct net_context *ctx,
3722 			       struct sockaddr *addr,
3723 			       socklen_t *addrlen)
3724 {
3725 	if (ctx == NULL || addr == NULL || addrlen == NULL) {
3726 		return -EINVAL;
3727 	}
3728 
3729 	if (IS_ENABLED(CONFIG_NET_TCP) &&
3730 	    net_context_get_type(ctx) == SOCK_STREAM) {
3731 		return net_tcp_endpoint_copy(ctx, addr, NULL, addrlen);
3732 	}
3733 
3734 	if (IS_ENABLED(CONFIG_NET_UDP) && net_context_get_type(ctx) == SOCK_DGRAM) {
3735 		socklen_t newlen;
3736 
3737 		if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET) {
3738 			newlen = MIN(*addrlen, sizeof(struct sockaddr_in));
3739 
3740 			net_sin(addr)->sin_family = AF_INET;
3741 			net_sin(addr)->sin_port = net_sin_ptr(&ctx->local)->sin_port;
3742 			memcpy(&net_sin(addr)->sin_addr,
3743 			       net_sin_ptr(&ctx->local)->sin_addr,
3744 			       sizeof(struct in_addr));
3745 
3746 		} else if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->local.family == AF_INET6) {
3747 			newlen = MIN(*addrlen, sizeof(struct sockaddr_in6));
3748 
3749 			net_sin6(addr)->sin6_family = AF_INET6;
3750 			net_sin6(addr)->sin6_port = net_sin6_ptr(&ctx->local)->sin6_port;
3751 			memcpy(&net_sin6(addr)->sin6_addr,
3752 			       net_sin6_ptr(&ctx->local)->sin6_addr,
3753 			       sizeof(struct in6_addr));
3754 		} else {
3755 			return -EAFNOSUPPORT;
3756 		}
3757 
3758 		*addrlen = newlen;
3759 
3760 		return 0;
3761 	}
3762 
3763 	return -ENOPROTOOPT;
3764 }
3765 
net_context_foreach(net_context_cb_t cb,void * user_data)3766 void net_context_foreach(net_context_cb_t cb, void *user_data)
3767 {
3768 	int i;
3769 
3770 	k_sem_take(&contexts_lock, K_FOREVER);
3771 
3772 	for (i = 0; i < NET_MAX_CONTEXT; i++) {
3773 		if (!net_context_is_used(&contexts[i])) {
3774 			continue;
3775 		}
3776 
3777 		k_mutex_lock(&contexts[i].lock, K_FOREVER);
3778 
3779 		cb(&contexts[i], user_data);
3780 
3781 		k_mutex_unlock(&contexts[i].lock);
3782 	}
3783 
3784 	k_sem_give(&contexts_lock);
3785 }
3786 
net_context_state(struct net_context * context)3787 const char *net_context_state(struct net_context *context)
3788 {
3789 	switch (net_context_get_state(context)) {
3790 	case NET_CONTEXT_IDLE:
3791 		return "IDLE";
3792 	case NET_CONTEXT_CONNECTING:
3793 		return "CONNECTING";
3794 	case NET_CONTEXT_CONNECTED:
3795 		return "CONNECTED";
3796 	case NET_CONTEXT_LISTENING:
3797 		return "LISTENING";
3798 	}
3799 
3800 	return NULL;
3801 }
3802 
net_context_init(void)3803 void net_context_init(void)
3804 {
3805 	k_sem_init(&contexts_lock, 1, K_SEM_MAX_LIMIT);
3806 }
3807