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