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