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