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