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_try_send_data(pkt, timeout);
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 struct sockaddr_ll *ll_addr;
2570
2571 /* Set the family to pkt if detected */
2572 switch (type) {
2573 case 0x60:
2574 net_pkt_set_family(pkt, AF_INET6);
2575 net_pkt_set_ll_proto_type(pkt, NET_ETH_PTYPE_IPV6);
2576 break;
2577 case 0x40:
2578 net_pkt_set_family(pkt, AF_INET);
2579 net_pkt_set_ll_proto_type(pkt, NET_ETH_PTYPE_IP);
2580 break;
2581 default:
2582 /* Not IP traffic, let it go forward as it is */
2583 ll_addr = (struct sockaddr_ll *)dst_addr;
2584
2585 net_pkt_set_ll_proto_type(pkt,
2586 ntohs(ll_addr->sll_protocol));
2587 break;
2588 }
2589
2590 /* Pass to L2: */
2591 ret = net_try_send_data(pkt, timeout);
2592 } else {
2593 struct sockaddr_ll_ptr *ll_src_addr;
2594 struct sockaddr_ll *ll_dst_addr;
2595
2596 /* The destination address is set in remote for this
2597 * socket type.
2598 */
2599 ll_dst_addr = (struct sockaddr_ll *)&context->remote;
2600 ll_src_addr = (struct sockaddr_ll_ptr *)&context->local;
2601
2602 (void)net_linkaddr_set(net_pkt_lladdr_dst(pkt),
2603 ll_dst_addr->sll_addr,
2604 sizeof(struct net_eth_addr));
2605 (void)net_linkaddr_set(net_pkt_lladdr_src(pkt),
2606 ll_src_addr->sll_addr,
2607 sizeof(struct net_eth_addr));
2608
2609 net_pkt_set_ll_proto_type(pkt,
2610 ntohs(ll_dst_addr->sll_protocol));
2611
2612 net_if_try_queue_tx(net_pkt_iface(pkt), pkt, timeout);
2613 }
2614 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN &&
2615 net_context_get_proto(context) == CAN_RAW) {
2616 ret = context_write_data(pkt, buf, len, msghdr);
2617 if (ret < 0) {
2618 goto fail;
2619 }
2620
2621 net_pkt_cursor_init(pkt);
2622
2623 ret = net_try_send_data(pkt, timeout);
2624 } else {
2625 NET_DBG("Unknown protocol while sending packet: %d",
2626 net_context_get_proto(context));
2627 ret = -EPROTONOSUPPORT;
2628 }
2629
2630 if (ret < 0) {
2631 goto fail;
2632 }
2633
2634 return len;
2635 fail:
2636 if (pkt != NULL) {
2637 net_pkt_unref(pkt);
2638 }
2639
2640 return ret;
2641 }
2642
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)2643 int net_context_send(struct net_context *context,
2644 const void *buf,
2645 size_t len,
2646 net_context_send_cb_t cb,
2647 k_timeout_t timeout,
2648 void *user_data)
2649 {
2650 socklen_t addrlen;
2651 int ret = 0;
2652
2653 k_mutex_lock(&context->lock, K_FOREVER);
2654
2655 if (!(context->flags & NET_CONTEXT_REMOTE_ADDR_SET) ||
2656 !net_sin(&context->remote)->sin_port) {
2657 ret = -EDESTADDRREQ;
2658 goto unlock;
2659 }
2660
2661 if (IS_ENABLED(CONFIG_NET_IPV6) &&
2662 net_context_get_family(context) == AF_INET6) {
2663 addrlen = sizeof(struct sockaddr_in6);
2664 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2665 net_context_get_family(context) == AF_INET) {
2666 addrlen = sizeof(struct sockaddr_in);
2667 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2668 net_context_get_family(context) == AF_PACKET) {
2669 ret = -EOPNOTSUPP;
2670 goto unlock;
2671 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2672 net_context_get_family(context) == AF_CAN) {
2673 addrlen = sizeof(struct sockaddr_can);
2674 } else {
2675 addrlen = 0;
2676 }
2677
2678 ret = context_sendto(context, buf, len, &context->remote,
2679 addrlen, cb, timeout, user_data, false);
2680 unlock:
2681 k_mutex_unlock(&context->lock);
2682
2683 return ret;
2684 }
2685
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)2686 int net_context_sendmsg(struct net_context *context,
2687 const struct msghdr *msghdr,
2688 int flags,
2689 net_context_send_cb_t cb,
2690 k_timeout_t timeout,
2691 void *user_data)
2692 {
2693 int ret;
2694
2695 k_mutex_lock(&context->lock, K_FOREVER);
2696
2697 ret = context_sendto(context, msghdr, 0, NULL, 0,
2698 cb, timeout, user_data, true);
2699
2700 k_mutex_unlock(&context->lock);
2701
2702 return ret;
2703 }
2704
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)2705 int net_context_sendto(struct net_context *context,
2706 const void *buf,
2707 size_t len,
2708 const struct sockaddr *dst_addr,
2709 socklen_t addrlen,
2710 net_context_send_cb_t cb,
2711 k_timeout_t timeout,
2712 void *user_data)
2713 {
2714 int ret;
2715
2716 k_mutex_lock(&context->lock, K_FOREVER);
2717
2718 ret = context_sendto(context, buf, len, dst_addr, addrlen,
2719 cb, timeout, user_data, true);
2720
2721 k_mutex_unlock(&context->lock);
2722
2723 return ret;
2724 }
2725
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)2726 enum net_verdict net_context_packet_received(struct net_conn *conn,
2727 struct net_pkt *pkt,
2728 union net_ip_header *ip_hdr,
2729 union net_proto_header *proto_hdr,
2730 void *user_data)
2731 {
2732 struct net_context *context = find_context(conn);
2733 enum net_verdict verdict = NET_DROP;
2734
2735 NET_ASSERT(context);
2736 NET_ASSERT(net_pkt_iface(pkt));
2737
2738 k_mutex_lock(&context->lock, K_FOREVER);
2739
2740 net_context_set_iface(context, net_pkt_iface(pkt));
2741 net_pkt_set_context(pkt, context);
2742
2743 /* If there is no callback registered, then we can only drop
2744 * the packet.
2745 */
2746 if (!context->recv_cb) {
2747 goto unlock;
2748 }
2749
2750 if (net_context_get_proto(context) == IPPROTO_TCP) {
2751 net_stats_update_tcp_recv(net_pkt_iface(pkt),
2752 net_pkt_remaining_data(pkt));
2753 }
2754
2755 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2756 k_sem_give(&context->recv_data_wait);
2757 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2758
2759 k_mutex_unlock(&context->lock);
2760
2761 context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
2762
2763 verdict = NET_OK;
2764
2765 return verdict;
2766
2767 unlock:
2768 k_mutex_unlock(&context->lock);
2769
2770 return verdict;
2771 }
2772
2773 #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)2774 static int recv_udp(struct net_context *context,
2775 net_context_recv_cb_t cb,
2776 k_timeout_t timeout,
2777 void *user_data)
2778 {
2779 struct sockaddr local_addr = {
2780 .sa_family = net_context_get_family(context),
2781 };
2782 struct sockaddr *laddr = NULL;
2783 uint16_t lport = 0U;
2784 int ret;
2785
2786 ARG_UNUSED(timeout);
2787
2788 /* If the context already has a connection handler, it means it's
2789 * already registered. In that case, all we have to do is 1) update
2790 * the callback registered in the net_context and 2) update the
2791 * user_data and remote address and port using net_conn_update().
2792 *
2793 * The callback function passed to net_conn_update() must be the same
2794 * function as the one passed to net_conn_register(), not the callback
2795 * set for the net context passed by recv_udp().
2796 */
2797 if (context->conn_handler) {
2798 context->recv_cb = cb;
2799 ret = net_conn_update(context->conn_handler,
2800 net_context_packet_received,
2801 user_data,
2802 context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
2803 &context->remote : NULL,
2804 ntohs(net_sin(&context->remote)->sin_port));
2805 return ret;
2806 }
2807
2808 ret = bind_default(context);
2809 if (ret) {
2810 return ret;
2811 }
2812
2813 if (IS_ENABLED(CONFIG_NET_IPV6) &&
2814 net_context_get_family(context) == AF_INET6) {
2815 if (net_sin6_ptr(&context->local)->sin6_addr) {
2816 net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
2817 net_sin6_ptr(&context->local)->sin6_addr);
2818
2819 laddr = &local_addr;
2820 }
2821
2822 net_sin6(&local_addr)->sin6_port =
2823 net_sin6((struct sockaddr *)&context->local)->sin6_port;
2824 lport = net_sin6((struct sockaddr *)&context->local)->sin6_port;
2825 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
2826 net_context_get_family(context) == AF_INET) {
2827 if (net_sin_ptr(&context->local)->sin_addr) {
2828 net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
2829 net_sin_ptr(&context->local)->sin_addr);
2830
2831 laddr = &local_addr;
2832 }
2833
2834 lport = net_sin((struct sockaddr *)&context->local)->sin_port;
2835 }
2836
2837 context->recv_cb = cb;
2838
2839 ret = net_conn_register(net_context_get_proto(context),
2840 net_context_get_family(context),
2841 context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
2842 &context->remote : NULL,
2843 laddr,
2844 ntohs(net_sin(&context->remote)->sin_port),
2845 ntohs(lport),
2846 context,
2847 net_context_packet_received,
2848 user_data,
2849 &context->conn_handler);
2850
2851 return ret;
2852 }
2853 #else
2854 #define recv_udp(...) 0
2855 #endif /* CONFIG_NET_NATIVE_UDP */
2856
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)2857 static enum net_verdict net_context_raw_packet_received(
2858 struct net_conn *conn,
2859 struct net_pkt *pkt,
2860 union net_ip_header *ip_hdr,
2861 union net_proto_header *proto_hdr,
2862 void *user_data)
2863 {
2864 struct net_context *context = find_context(conn);
2865
2866 NET_ASSERT(context);
2867 NET_ASSERT(net_pkt_iface(pkt));
2868
2869 /* If there is no callback registered, then we can only drop
2870 * the packet.
2871 */
2872
2873 if (!context->recv_cb) {
2874 return NET_DROP;
2875 }
2876
2877 net_context_set_iface(context, net_pkt_iface(pkt));
2878 net_pkt_set_context(pkt, context);
2879
2880 context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
2881
2882 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
2883 k_sem_give(&context->recv_data_wait);
2884 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
2885
2886 return NET_OK;
2887 }
2888
recv_raw(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,struct sockaddr * local_addr,void * user_data)2889 static int recv_raw(struct net_context *context,
2890 net_context_recv_cb_t cb,
2891 k_timeout_t timeout,
2892 struct sockaddr *local_addr,
2893 void *user_data)
2894 {
2895 int ret;
2896
2897 ARG_UNUSED(timeout);
2898
2899 /* If the context already has a connection handler, it means it's
2900 * already registered. In that case, all we have to do is 1) update
2901 * the callback registered in the net_context and 2) update the
2902 * user_data using net_conn_update().
2903 *
2904 * The callback function passed to net_conn_update() must be the same
2905 * function as the one passed to net_conn_register(), not the callback
2906 * set for the net context passed by recv_raw().
2907 */
2908 if (context->conn_handler) {
2909 context->recv_cb = cb;
2910 ret = net_conn_update(context->conn_handler,
2911 net_context_raw_packet_received,
2912 user_data,
2913 NULL, 0);
2914 return ret;
2915 }
2916
2917 ret = bind_default(context);
2918 if (ret) {
2919 return ret;
2920 }
2921
2922 context->recv_cb = cb;
2923
2924 ret = net_conn_register(net_context_get_proto(context),
2925 net_context_get_family(context),
2926 NULL, local_addr, 0, 0,
2927 context,
2928 net_context_raw_packet_received,
2929 user_data,
2930 &context->conn_handler);
2931
2932 return ret;
2933 }
2934
net_context_recv(struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)2935 int net_context_recv(struct net_context *context,
2936 net_context_recv_cb_t cb,
2937 k_timeout_t timeout,
2938 void *user_data)
2939 {
2940 int ret;
2941 NET_ASSERT(context);
2942
2943 if (!net_context_is_used(context)) {
2944 return -EBADF;
2945 }
2946
2947 k_mutex_lock(&context->lock, K_FOREVER);
2948
2949 if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
2950 net_if_is_ip_offloaded(net_context_get_iface(context))) {
2951 ret = net_offload_recv(
2952 net_context_get_iface(context),
2953 context, cb, timeout, user_data);
2954 goto unlock;
2955 }
2956
2957 if (IS_ENABLED(CONFIG_NET_UDP) &&
2958 net_context_get_proto(context) == IPPROTO_UDP) {
2959 ret = recv_udp(context, cb, timeout, user_data);
2960 } else if (IS_ENABLED(CONFIG_NET_TCP) &&
2961 net_context_get_proto(context) == IPPROTO_TCP) {
2962 ret = net_tcp_recv(context, cb, user_data);
2963 } else {
2964 if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
2965 net_context_get_family(context) == AF_PACKET) {
2966 struct sockaddr_ll addr;
2967
2968 addr.sll_family = AF_PACKET;
2969 addr.sll_ifindex =
2970 net_sll_ptr(&context->local)->sll_ifindex;
2971 addr.sll_protocol =
2972 net_sll_ptr(&context->local)->sll_protocol;
2973 addr.sll_halen =
2974 net_sll_ptr(&context->local)->sll_halen;
2975
2976 memcpy(addr.sll_addr,
2977 net_sll_ptr(&context->local)->sll_addr,
2978 MIN(addr.sll_halen, sizeof(addr.sll_addr)));
2979
2980 ret = recv_raw(context, cb, timeout,
2981 (struct sockaddr *)&addr, user_data);
2982 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
2983 net_context_get_family(context) == AF_CAN) {
2984 struct sockaddr_can local_addr = {
2985 .can_family = AF_CAN,
2986 };
2987
2988 ret = recv_raw(context, cb, timeout,
2989 (struct sockaddr *)&local_addr,
2990 user_data);
2991 if (ret == -EALREADY) {
2992 /* This is perfectly normal for CAN sockets.
2993 * The SocketCAN will dispatch the packet to
2994 * correct net_context listener.
2995 */
2996 ret = 0;
2997 }
2998 } else {
2999 ret = -EPROTOTYPE;
3000 }
3001 }
3002
3003 if (ret < 0) {
3004 goto unlock;
3005 }
3006
3007 #if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
3008 if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
3009 /* Make sure we have the lock, then the
3010 * net_context_packet_received() callback will release the
3011 * semaphore when data has been received.
3012 */
3013 k_sem_reset(&context->recv_data_wait);
3014
3015 k_mutex_unlock(&context->lock);
3016
3017 if (k_sem_take(&context->recv_data_wait, timeout) == -EAGAIN) {
3018 ret = -ETIMEDOUT;
3019 }
3020
3021 k_mutex_lock(&context->lock, K_FOREVER);
3022 }
3023 #endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
3024
3025 unlock:
3026 k_mutex_unlock(&context->lock);
3027
3028 return ret;
3029 }
3030
net_context_update_recv_wnd(struct net_context * context,int32_t delta)3031 int net_context_update_recv_wnd(struct net_context *context,
3032 int32_t delta)
3033 {
3034 int ret;
3035
3036 if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
3037 net_if_is_ip_offloaded(net_context_get_iface(context))) {
3038 return 0;
3039 }
3040
3041 k_mutex_lock(&context->lock, K_FOREVER);
3042
3043 ret = net_tcp_update_recv_wnd(context, delta);
3044
3045 k_mutex_unlock(&context->lock);
3046
3047 return ret;
3048 }
3049
set_bool_option(bool * option,const void * value,size_t len)3050 __maybe_unused static int set_bool_option(bool *option, const void *value, size_t len)
3051 {
3052 if (value == NULL) {
3053 return -EINVAL;
3054 }
3055
3056 if (len != sizeof(int)) {
3057 return -EINVAL;
3058 }
3059
3060 *option = !!*((int *)value);
3061
3062 return 0;
3063 }
3064
set_uint8_option(uint8_t * option,const void * value,size_t len)3065 __maybe_unused static int set_uint8_option(uint8_t *option, const void *value, size_t len)
3066 {
3067 if (value == NULL) {
3068 return -EINVAL;
3069 }
3070
3071 if (len > sizeof(uint8_t)) {
3072 return -EINVAL;
3073 }
3074
3075 *option = *((uint8_t *)value);
3076
3077 return 0;
3078 }
3079
set_uint16_option(uint16_t * option,const void * value,size_t len)3080 __maybe_unused static int set_uint16_option(uint16_t *option, const void *value, size_t len)
3081 {
3082 int v;
3083
3084 if (value == NULL) {
3085 return -EINVAL;
3086 }
3087
3088 if (len != sizeof(int)) {
3089 return -EINVAL;
3090 }
3091
3092 v = *((int *)value);
3093
3094 if (v < 0 || v > UINT16_MAX) {
3095 return -EINVAL;
3096 }
3097
3098 *option = (uint16_t)v;
3099
3100 return 0;
3101
3102 }
3103
set_context_priority(struct net_context * context,const void * value,size_t len)3104 static int set_context_priority(struct net_context *context,
3105 const void *value, size_t len)
3106 {
3107 #if defined(CONFIG_NET_CONTEXT_PRIORITY)
3108 return set_uint8_option(&context->options.priority, value, len);
3109 #else
3110 ARG_UNUSED(context);
3111 ARG_UNUSED(value);
3112 ARG_UNUSED(len);
3113
3114 return -ENOTSUP;
3115 #endif
3116 }
3117
set_context_txtime(struct net_context * context,const void * value,size_t len)3118 static int set_context_txtime(struct net_context *context,
3119 const void *value, size_t len)
3120 {
3121 #if defined(CONFIG_NET_CONTEXT_TXTIME)
3122 return set_bool_option(&context->options.txtime, value, len);
3123 #else
3124 ARG_UNUSED(context);
3125 ARG_UNUSED(value);
3126 ARG_UNUSED(len);
3127
3128 return -ENOTSUP;
3129 #endif
3130 }
3131
set_context_proxy(struct net_context * context,const void * value,size_t len)3132 static int set_context_proxy(struct net_context *context,
3133 const void *value, size_t len)
3134 {
3135 #if defined(CONFIG_SOCKS)
3136 struct sockaddr *addr = (struct sockaddr *)value;
3137
3138 if (len > NET_SOCKADDR_MAX_SIZE) {
3139 return -EINVAL;
3140 }
3141
3142 if (addr->sa_family != net_context_get_family(context)) {
3143 return -EINVAL;
3144 }
3145
3146 context->options.proxy.addrlen = len;
3147 memcpy(&context->options.proxy.addr, addr, len);
3148
3149 return 0;
3150 #else
3151 ARG_UNUSED(context);
3152 ARG_UNUSED(value);
3153 ARG_UNUSED(len);
3154
3155 return -ENOTSUP;
3156 #endif
3157 }
3158
set_context_rcvtimeo(struct net_context * context,const void * value,size_t len)3159 static int set_context_rcvtimeo(struct net_context *context,
3160 const void *value, size_t len)
3161 {
3162 #if defined(CONFIG_NET_CONTEXT_RCVTIMEO)
3163 if (len != sizeof(k_timeout_t)) {
3164 return -EINVAL;
3165 }
3166
3167 context->options.rcvtimeo = *((k_timeout_t *)value);
3168
3169 return 0;
3170 #else
3171 ARG_UNUSED(context);
3172 ARG_UNUSED(value);
3173 ARG_UNUSED(len);
3174
3175 return -ENOTSUP;
3176 #endif
3177 }
3178
set_context_sndtimeo(struct net_context * context,const void * value,size_t len)3179 static int set_context_sndtimeo(struct net_context *context,
3180 const void *value, size_t len)
3181 {
3182 #if defined(CONFIG_NET_CONTEXT_SNDTIMEO)
3183 if (len != sizeof(k_timeout_t)) {
3184 return -EINVAL;
3185 }
3186
3187 context->options.sndtimeo = *((k_timeout_t *)value);
3188
3189 return 0;
3190 #else
3191 ARG_UNUSED(context);
3192 ARG_UNUSED(value);
3193 ARG_UNUSED(len);
3194
3195 return -ENOTSUP;
3196 #endif
3197 }
3198
set_context_rcvbuf(struct net_context * context,const void * value,size_t len)3199 static int set_context_rcvbuf(struct net_context *context,
3200 const void *value, size_t len)
3201 {
3202 #if defined(CONFIG_NET_CONTEXT_RCVBUF)
3203 return set_uint16_option(&context->options.rcvbuf, value, len);
3204 #else
3205 ARG_UNUSED(context);
3206 ARG_UNUSED(value);
3207 ARG_UNUSED(len);
3208
3209 return -ENOTSUP;
3210 #endif
3211 }
3212
set_context_sndbuf(struct net_context * context,const void * value,size_t len)3213 static int set_context_sndbuf(struct net_context *context,
3214 const void *value, size_t len)
3215 {
3216 #if defined(CONFIG_NET_CONTEXT_SNDBUF)
3217 return set_uint16_option(&context->options.sndbuf, value, len);
3218 #else
3219 ARG_UNUSED(context);
3220 ARG_UNUSED(value);
3221 ARG_UNUSED(len);
3222
3223 return -ENOTSUP;
3224 #endif
3225 }
3226
set_context_dscp_ecn(struct net_context * context,const void * value,size_t len)3227 static int set_context_dscp_ecn(struct net_context *context,
3228 const void *value, size_t len)
3229 {
3230 #if defined(CONFIG_NET_CONTEXT_DSCP_ECN)
3231 return set_uint8_option(&context->options.dscp_ecn, value, len);
3232 #else
3233 ARG_UNUSED(context);
3234 ARG_UNUSED(value);
3235 ARG_UNUSED(len);
3236
3237 return -ENOTSUP;
3238 #endif
3239 }
3240
set_context_ttl(struct net_context * context,const void * value,size_t len)3241 static int set_context_ttl(struct net_context *context,
3242 const void *value, size_t len)
3243 {
3244 #if defined(CONFIG_NET_IPV4)
3245 uint8_t ttl = *((int *)value);
3246
3247 len = sizeof(context->ipv4_ttl);
3248
3249 return set_uint8_option(&context->ipv4_ttl, &ttl, len);
3250 #else
3251 ARG_UNUSED(context);
3252 ARG_UNUSED(value);
3253 ARG_UNUSED(len);
3254
3255 return -ENOTSUP;
3256 #endif
3257 }
3258
set_context_mcast_ttl(struct net_context * context,const void * value,size_t len)3259 static int set_context_mcast_ttl(struct net_context *context,
3260 const void *value, size_t len)
3261 {
3262 #if defined(CONFIG_NET_IPV4)
3263 uint8_t mcast_ttl = *((int *)value);
3264
3265 len = sizeof(context->ipv4_mcast_ttl);
3266
3267 return set_uint8_option(&context->ipv4_mcast_ttl, &mcast_ttl, len);
3268 #else
3269 ARG_UNUSED(context);
3270 ARG_UNUSED(value);
3271 ARG_UNUSED(len);
3272
3273 return -ENOTSUP;
3274 #endif
3275 }
3276
set_context_mcast_hop_limit(struct net_context * context,const void * value,size_t len)3277 static int set_context_mcast_hop_limit(struct net_context *context,
3278 const void *value, size_t len)
3279 {
3280 #if defined(CONFIG_NET_IPV6)
3281 int mcast_hop_limit = *((int *)value);
3282
3283 if (len != sizeof(int)) {
3284 return -EINVAL;
3285 }
3286
3287 if (mcast_hop_limit == -1) {
3288 /* If value is -1 then use the system default.
3289 * This is done same way as in Linux.
3290 */
3291 if (net_if_get_by_index(context->iface) == NULL) {
3292 mcast_hop_limit = INITIAL_MCAST_HOP_LIMIT;
3293 } else {
3294 mcast_hop_limit = net_if_ipv6_get_mcast_hop_limit(
3295 net_if_get_by_index(context->iface));
3296 }
3297 } else if (mcast_hop_limit < 0 || mcast_hop_limit > 255) {
3298 return -EINVAL;
3299 }
3300
3301 context->ipv6_mcast_hop_limit = mcast_hop_limit;
3302
3303 return 0;
3304 #else
3305 ARG_UNUSED(context);
3306 ARG_UNUSED(value);
3307 ARG_UNUSED(len);
3308
3309 return -ENOTSUP;
3310 #endif
3311 }
3312
set_context_unicast_hop_limit(struct net_context * context,const void * value,size_t len)3313 static int set_context_unicast_hop_limit(struct net_context *context,
3314 const void *value, size_t len)
3315 {
3316 #if defined(CONFIG_NET_IPV6)
3317 uint8_t unicast_hop_limit = *((int *)value);
3318
3319 len = sizeof(context->ipv6_hop_limit);
3320
3321 return set_uint8_option(&context->ipv6_hop_limit,
3322 &unicast_hop_limit, len);
3323 #else
3324 ARG_UNUSED(context);
3325 ARG_UNUSED(value);
3326 ARG_UNUSED(len);
3327
3328 return -ENOTSUP;
3329 #endif
3330 }
3331
set_context_reuseaddr(struct net_context * context,const void * value,size_t len)3332 static int set_context_reuseaddr(struct net_context *context,
3333 const void *value, size_t len)
3334 {
3335 #if defined(CONFIG_NET_CONTEXT_REUSEADDR)
3336 return set_bool_option(&context->options.reuseaddr, value, len);
3337 #else
3338 ARG_UNUSED(context);
3339 ARG_UNUSED(value);
3340 ARG_UNUSED(len);
3341
3342 return -ENOTSUP;
3343 #endif
3344 }
3345
set_context_reuseport(struct net_context * context,const void * value,size_t len)3346 static int set_context_reuseport(struct net_context *context,
3347 const void *value, size_t len)
3348 {
3349 #if defined(CONFIG_NET_CONTEXT_REUSEPORT)
3350 return set_bool_option(&context->options.reuseport, value, len);
3351 #else
3352 ARG_UNUSED(context);
3353 ARG_UNUSED(value);
3354 ARG_UNUSED(len);
3355
3356 return -ENOTSUP;
3357 #endif
3358 }
3359
set_context_ipv6_mtu(struct net_context * context,const void * value,size_t len)3360 static int set_context_ipv6_mtu(struct net_context *context,
3361 const void *value, size_t len)
3362 {
3363 #if defined(CONFIG_NET_IPV6)
3364 struct net_if *iface;
3365 uint16_t mtu;
3366
3367 if (len != sizeof(int)) {
3368 return -EINVAL;
3369 }
3370
3371 mtu = *((int *)value);
3372
3373 if (IS_ENABLED(CONFIG_NET_IPV6_PMTU)) {
3374 int ret;
3375
3376 ret = net_pmtu_update_mtu(&context->remote, mtu);
3377 if (ret < 0) {
3378 return ret;
3379 }
3380
3381 return 0;
3382 }
3383
3384 if (net_context_is_bound_to_iface(context)) {
3385 iface = net_context_get_iface(context);
3386 } else {
3387 sa_family_t family = net_context_get_family(context);
3388
3389 if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
3390 iface = net_if_ipv6_select_src_iface(
3391 &net_sin6(&context->remote)->sin6_addr);
3392 } else {
3393 return -EAFNOSUPPORT;
3394 }
3395 }
3396
3397 net_if_set_mtu(iface, (uint16_t)mtu);
3398
3399 return 0;
3400 #else
3401 ARG_UNUSED(context);
3402 ARG_UNUSED(value);
3403 ARG_UNUSED(len);
3404
3405 return -ENOTSUP;
3406 #endif
3407 }
3408
set_context_ipv6_v6only(struct net_context * context,const void * value,size_t len)3409 static int set_context_ipv6_v6only(struct net_context *context,
3410 const void *value, size_t len)
3411 {
3412 #if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
3413 return set_bool_option(&context->options.ipv6_v6only, value, len);
3414 #else
3415 ARG_UNUSED(context);
3416 ARG_UNUSED(value);
3417 ARG_UNUSED(len);
3418
3419 return -ENOTSUP;
3420 #endif
3421 }
3422
set_context_recv_pktinfo(struct net_context * context,const void * value,size_t len)3423 static int set_context_recv_pktinfo(struct net_context *context,
3424 const void *value, size_t len)
3425 {
3426 #if defined(CONFIG_NET_CONTEXT_RECV_PKTINFO)
3427 return set_bool_option(&context->options.recv_pktinfo, value, len);
3428 #else
3429 ARG_UNUSED(context);
3430 ARG_UNUSED(value);
3431 ARG_UNUSED(len);
3432
3433 return -ENOTSUP;
3434 #endif
3435 }
3436
set_context_addr_preferences(struct net_context * context,const void * value,size_t len)3437 static int set_context_addr_preferences(struct net_context *context,
3438 const void *value, size_t len)
3439 {
3440 #if defined(CONFIG_NET_IPV6)
3441 return set_uint16_option(&context->options.addr_preferences,
3442 value, len);
3443 #else
3444 ARG_UNUSED(context);
3445 ARG_UNUSED(value);
3446 ARG_UNUSED(len);
3447
3448 return -ENOTSUP;
3449 #endif
3450 }
3451
set_context_timestamping(struct net_context * context,const void * value,size_t len)3452 static int set_context_timestamping(struct net_context *context,
3453 const void *value, size_t len)
3454 {
3455 #if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
3456 uint8_t timestamping_flags = *((uint8_t *)value);
3457
3458 return set_uint8_option(&context->options.timestamping,
3459 ×tamping_flags, len);
3460 #else
3461 ARG_UNUSED(context);
3462 ARG_UNUSED(value);
3463 ARG_UNUSED(len);
3464
3465 return -ENOTSUP;
3466 #endif
3467 }
3468
set_context_mcast_ifindex(struct net_context * context,const void * value,size_t len)3469 static int set_context_mcast_ifindex(struct net_context *context,
3470 const void *value, size_t len)
3471 {
3472 #if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
3473 sa_family_t family = net_context_get_family(context);
3474 int mcast_ifindex = *((int *)value);
3475 enum net_sock_type type;
3476 struct net_if *iface;
3477
3478 if ((IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) ||
3479 (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET)) {
3480
3481 if (len != sizeof(int)) {
3482 return -EINVAL;
3483 }
3484
3485 type = net_context_get_type(context);
3486 if (type != SOCK_DGRAM) {
3487 return -EINVAL;
3488 }
3489
3490 /* optlen equal to 0 then remove the binding */
3491 if (mcast_ifindex == 0) {
3492 context->options.ipv6_mcast_ifindex = 0;
3493 return 0;
3494 }
3495
3496 if (mcast_ifindex < 1 || mcast_ifindex > 255) {
3497 return -EINVAL;
3498 }
3499
3500 iface = net_if_get_by_index(mcast_ifindex);
3501 if (iface == NULL) {
3502 return -ENOENT;
3503 }
3504
3505 if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
3506 if (!net_if_flag_is_set(iface, NET_IF_IPV6)) {
3507 return -EPROTOTYPE;
3508 }
3509 } else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
3510 if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
3511 return -EPROTOTYPE;
3512 }
3513 }
3514
3515 context->options.ipv6_mcast_ifindex = mcast_ifindex;
3516
3517 return 0;
3518 }
3519
3520 return -EAFNOSUPPORT;
3521 #else
3522 ARG_UNUSED(context);
3523 ARG_UNUSED(value);
3524 ARG_UNUSED(len);
3525
3526 return -ENOTSUP;
3527 #endif
3528 }
3529
set_context_local_port_range(struct net_context * context,const void * value,size_t len)3530 static int set_context_local_port_range(struct net_context *context,
3531 const void *value, size_t len)
3532 {
3533 #if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE)
3534 uint16_t lower_range, upper_range;
3535 uint32_t port_range;
3536
3537 if (len != sizeof(uint32_t)) {
3538 return -EINVAL;
3539 }
3540
3541 port_range = *((uint32_t *)value);
3542 lower_range = port_range & 0xffff;
3543 upper_range = port_range >> 16;
3544
3545 /* If the range is 0, then it means that the port range clamping
3546 * is disabled. If the range is not 0, then the lower range must
3547 * be smaller than the upper range.
3548 */
3549 if (lower_range != 0U && upper_range != 0U &&
3550 lower_range >= upper_range) {
3551 return -EINVAL;
3552 }
3553
3554 /* If either of the range is 0, then that bound has no effect.
3555 * This is checked when the emphemeral port is selected.
3556 */
3557 context->options.port_range = port_range;
3558
3559 return 0;
3560 #else
3561 ARG_UNUSED(context);
3562 ARG_UNUSED(value);
3563 ARG_UNUSED(len);
3564
3565 return -ENOTSUP;
3566 #endif
3567 }
3568
net_context_set_option(struct net_context * context,enum net_context_option option,const void * value,size_t len)3569 int net_context_set_option(struct net_context *context,
3570 enum net_context_option option,
3571 const void *value, size_t len)
3572 {
3573 int ret = 0;
3574
3575 NET_ASSERT(context);
3576
3577 if (!PART_OF_ARRAY(contexts, context)) {
3578 return -EINVAL;
3579 }
3580
3581 k_mutex_lock(&context->lock, K_FOREVER);
3582
3583 switch (option) {
3584 case NET_OPT_PRIORITY:
3585 ret = set_context_priority(context, value, len);
3586 break;
3587 case NET_OPT_TXTIME:
3588 ret = set_context_txtime(context, value, len);
3589 break;
3590 case NET_OPT_SOCKS5:
3591 ret = set_context_proxy(context, value, len);
3592 break;
3593 case NET_OPT_RCVTIMEO:
3594 ret = set_context_rcvtimeo(context, value, len);
3595 break;
3596 case NET_OPT_SNDTIMEO:
3597 ret = set_context_sndtimeo(context, value, len);
3598 break;
3599 case NET_OPT_RCVBUF:
3600 ret = set_context_rcvbuf(context, value, len);
3601 break;
3602 case NET_OPT_SNDBUF:
3603 ret = set_context_sndbuf(context, value, len);
3604 break;
3605 case NET_OPT_DSCP_ECN:
3606 ret = set_context_dscp_ecn(context, value, len);
3607 break;
3608 case NET_OPT_TTL:
3609 ret = set_context_ttl(context, value, len);
3610 break;
3611 case NET_OPT_MCAST_TTL:
3612 ret = set_context_mcast_ttl(context, value, len);
3613 break;
3614 case NET_OPT_MCAST_HOP_LIMIT:
3615 ret = set_context_mcast_hop_limit(context, value, len);
3616 break;
3617 case NET_OPT_UNICAST_HOP_LIMIT:
3618 ret = set_context_unicast_hop_limit(context, value, len);
3619 break;
3620 case NET_OPT_REUSEADDR:
3621 ret = set_context_reuseaddr(context, value, len);
3622 break;
3623 case NET_OPT_REUSEPORT:
3624 ret = set_context_reuseport(context, value, len);
3625 break;
3626 case NET_OPT_IPV6_V6ONLY:
3627 ret = set_context_ipv6_v6only(context, value, len);
3628 break;
3629 case NET_OPT_RECV_PKTINFO:
3630 ret = set_context_recv_pktinfo(context, value, len);
3631 break;
3632 case NET_OPT_ADDR_PREFERENCES:
3633 ret = set_context_addr_preferences(context, value, len);
3634 break;
3635 case NET_OPT_TIMESTAMPING:
3636 ret = set_context_timestamping(context, value, len);
3637 break;
3638 case NET_OPT_MTU:
3639 /* IPv4 only supports getting the MTU */
3640 if (IS_ENABLED(CONFIG_NET_IPV4) &&
3641 net_context_get_family(context) == AF_INET) {
3642 ret = -EOPNOTSUPP;
3643 } else if (IS_ENABLED(CONFIG_NET_IPV6) &&
3644 net_context_get_family(context) == AF_INET6) {
3645 ret = set_context_ipv6_mtu(context, value, len);
3646 }
3647
3648 break;
3649 case NET_OPT_MCAST_IFINDEX:
3650 ret = set_context_mcast_ifindex(context, value, len);
3651 break;
3652 case NET_OPT_LOCAL_PORT_RANGE:
3653 ret = set_context_local_port_range(context, value, len);
3654 break;
3655 }
3656
3657 k_mutex_unlock(&context->lock);
3658
3659 return ret;
3660 }
3661
net_context_get_option(struct net_context * context,enum net_context_option option,void * value,size_t * len)3662 int net_context_get_option(struct net_context *context,
3663 enum net_context_option option,
3664 void *value, size_t *len)
3665 {
3666 int ret = 0;
3667
3668 NET_ASSERT(context);
3669
3670 if (!PART_OF_ARRAY(contexts, context)) {
3671 return -EINVAL;
3672 }
3673
3674 k_mutex_lock(&context->lock, K_FOREVER);
3675
3676 switch (option) {
3677 case NET_OPT_PRIORITY:
3678 ret = get_context_priority(context, value, len);
3679 break;
3680 case NET_OPT_TXTIME:
3681 ret = get_context_txtime(context, value, len);
3682 break;
3683 case NET_OPT_SOCKS5:
3684 ret = get_context_proxy(context, value, len);
3685 break;
3686 case NET_OPT_RCVTIMEO:
3687 ret = get_context_rcvtimeo(context, value, len);
3688 break;
3689 case NET_OPT_SNDTIMEO:
3690 ret = get_context_sndtimeo(context, value, len);
3691 break;
3692 case NET_OPT_RCVBUF:
3693 ret = get_context_rcvbuf(context, value, len);
3694 break;
3695 case NET_OPT_SNDBUF:
3696 ret = get_context_sndbuf(context, value, len);
3697 break;
3698 case NET_OPT_DSCP_ECN:
3699 ret = get_context_dscp_ecn(context, value, len);
3700 break;
3701 case NET_OPT_TTL:
3702 ret = get_context_ttl(context, value, len);
3703 break;
3704 case NET_OPT_MCAST_TTL:
3705 ret = get_context_mcast_ttl(context, value, len);
3706 break;
3707 case NET_OPT_MCAST_HOP_LIMIT:
3708 ret = get_context_mcast_hop_limit(context, value, len);
3709 break;
3710 case NET_OPT_UNICAST_HOP_LIMIT:
3711 ret = get_context_unicast_hop_limit(context, value, len);
3712 break;
3713 case NET_OPT_REUSEADDR:
3714 ret = get_context_reuseaddr(context, value, len);
3715 break;
3716 case NET_OPT_REUSEPORT:
3717 ret = get_context_reuseport(context, value, len);
3718 break;
3719 case NET_OPT_IPV6_V6ONLY:
3720 ret = get_context_ipv6_v6only(context, value, len);
3721 break;
3722 case NET_OPT_RECV_PKTINFO:
3723 ret = get_context_recv_pktinfo(context, value, len);
3724 break;
3725 case NET_OPT_ADDR_PREFERENCES:
3726 ret = get_context_addr_preferences(context, value, len);
3727 break;
3728 case NET_OPT_TIMESTAMPING:
3729 ret = get_context_timestamping(context, value, len);
3730 break;
3731 case NET_OPT_MTU:
3732 ret = get_context_mtu(context, value, len);
3733 break;
3734 case NET_OPT_MCAST_IFINDEX:
3735 ret = get_context_mcast_ifindex(context, value, len);
3736 break;
3737 case NET_OPT_LOCAL_PORT_RANGE:
3738 ret = get_context_local_port_range(context, value, len);
3739 break;
3740 }
3741
3742 k_mutex_unlock(&context->lock);
3743
3744 return ret;
3745 }
3746
net_context_get_local_addr(struct net_context * ctx,struct sockaddr * addr,socklen_t * addrlen)3747 int net_context_get_local_addr(struct net_context *ctx,
3748 struct sockaddr *addr,
3749 socklen_t *addrlen)
3750 {
3751 if (ctx == NULL || addr == NULL || addrlen == NULL) {
3752 return -EINVAL;
3753 }
3754
3755 if (IS_ENABLED(CONFIG_NET_TCP) &&
3756 net_context_get_type(ctx) == SOCK_STREAM) {
3757 return net_tcp_endpoint_copy(ctx, addr, NULL, addrlen);
3758 }
3759
3760 if (IS_ENABLED(CONFIG_NET_UDP) && net_context_get_type(ctx) == SOCK_DGRAM) {
3761 socklen_t newlen;
3762
3763 if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET) {
3764 newlen = MIN(*addrlen, sizeof(struct sockaddr_in));
3765
3766 net_sin(addr)->sin_family = AF_INET;
3767 net_sin(addr)->sin_port = net_sin_ptr(&ctx->local)->sin_port;
3768 memcpy(&net_sin(addr)->sin_addr,
3769 net_sin_ptr(&ctx->local)->sin_addr,
3770 sizeof(struct in_addr));
3771
3772 } else if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->local.family == AF_INET6) {
3773 newlen = MIN(*addrlen, sizeof(struct sockaddr_in6));
3774
3775 net_sin6(addr)->sin6_family = AF_INET6;
3776 net_sin6(addr)->sin6_port = net_sin6_ptr(&ctx->local)->sin6_port;
3777 memcpy(&net_sin6(addr)->sin6_addr,
3778 net_sin6_ptr(&ctx->local)->sin6_addr,
3779 sizeof(struct in6_addr));
3780 } else {
3781 return -EAFNOSUPPORT;
3782 }
3783
3784 *addrlen = newlen;
3785
3786 return 0;
3787 }
3788
3789 return -ENOPROTOOPT;
3790 }
3791
net_context_foreach(net_context_cb_t cb,void * user_data)3792 void net_context_foreach(net_context_cb_t cb, void *user_data)
3793 {
3794 int i;
3795
3796 k_sem_take(&contexts_lock, K_FOREVER);
3797
3798 for (i = 0; i < NET_MAX_CONTEXT; i++) {
3799 if (!net_context_is_used(&contexts[i])) {
3800 continue;
3801 }
3802
3803 k_mutex_lock(&contexts[i].lock, K_FOREVER);
3804
3805 cb(&contexts[i], user_data);
3806
3807 k_mutex_unlock(&contexts[i].lock);
3808 }
3809
3810 k_sem_give(&contexts_lock);
3811 }
3812
net_context_state(struct net_context * context)3813 const char *net_context_state(struct net_context *context)
3814 {
3815 switch (net_context_get_state(context)) {
3816 case NET_CONTEXT_IDLE:
3817 return "IDLE";
3818 case NET_CONTEXT_CONNECTING:
3819 return "CONNECTING";
3820 case NET_CONTEXT_CONNECTED:
3821 return "CONNECTED";
3822 case NET_CONTEXT_LISTENING:
3823 return "LISTENING";
3824 }
3825
3826 return NULL;
3827 }
3828
net_context_init(void)3829 void net_context_init(void)
3830 {
3831 k_sem_init(&contexts_lock, 1, K_SEM_MAX_LIMIT);
3832 }
3833