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