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