1 /** @file
2 * @brief Generic connection related functions
3 */
4
5 /*
6 * Copyright (c) 2016 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 /* TODO: Make core part of networking subsystem less dependent on
12 * UDP, TCP, IPv4 or IPv6. So that we can add new features with
13 * less cross-module changes.
14 */
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(net_conn, CONFIG_NET_CONN_LOG_LEVEL);
18
19 #include <errno.h>
20 #include <zephyr/sys/util.h>
21
22 #include <zephyr/net/net_core.h>
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/net/udp.h>
25 #include <zephyr/net/ethernet.h>
26 #include <zephyr/net/socketcan.h>
27
28 #include "net_private.h"
29 #include "icmpv6.h"
30 #include "icmpv4.h"
31 #include "udp_internal.h"
32 #include "tcp_internal.h"
33 #include "connection.h"
34 #include "net_stats.h"
35
36 /** How long to wait for when cloning multicast packet */
37 #define CLONE_TIMEOUT K_MSEC(100)
38
39 /** Is this connection used or not */
40 #define NET_CONN_IN_USE BIT(0)
41
42 /** Remote address set */
43 #define NET_CONN_REMOTE_ADDR_SET BIT(1)
44
45 /** Local address set */
46 #define NET_CONN_LOCAL_ADDR_SET BIT(2)
47
48 /** Local port set */
49 #define NET_CONN_REMOTE_PORT_SPEC BIT(3)
50
51 /** Remote port set */
52 #define NET_CONN_LOCAL_PORT_SPEC BIT(4)
53
54 /** Local address specified */
55 #define NET_CONN_REMOTE_ADDR_SPEC BIT(5)
56
57 /** Remote address specified */
58 #define NET_CONN_LOCAL_ADDR_SPEC BIT(6)
59
60 #define NET_CONN_RANK(_flags) (_flags & 0x78)
61
62 static struct net_conn conns[CONFIG_NET_MAX_CONN];
63
64 static sys_slist_t conn_unused;
65 static sys_slist_t conn_used;
66
67 #if (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG)
68 static inline
conn_register_debug(struct net_conn * conn,uint16_t remote_port,uint16_t local_port)69 void conn_register_debug(struct net_conn *conn,
70 uint16_t remote_port, uint16_t local_port)
71 {
72 char dst[NET_IPV6_ADDR_LEN];
73 char src[NET_IPV6_ADDR_LEN];
74
75 if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
76 if (IS_ENABLED(CONFIG_NET_IPV6) &&
77 conn->family == AF_INET6) {
78 snprintk(dst, sizeof(dst), "%s",
79 net_sprint_ipv6_addr(&net_sin6(&conn->remote_addr)->sin6_addr));
80 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
81 conn->family == AF_INET) {
82 snprintk(dst, sizeof(dst), "%s",
83 net_sprint_ipv4_addr(&net_sin(&conn->remote_addr)->sin_addr));
84 } else {
85 snprintk(dst, sizeof(dst), "%s", "?");
86 }
87 } else {
88 snprintk(dst, sizeof(dst), "%s", "-");
89 }
90
91 if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
92 if (IS_ENABLED(CONFIG_NET_IPV6) &&
93 conn->family == AF_INET6) {
94 snprintk(src, sizeof(src), "%s",
95 net_sprint_ipv6_addr(&net_sin6(&conn->local_addr)->sin6_addr));
96 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
97 conn->family == AF_INET) {
98 snprintk(src, sizeof(src), "%s",
99 net_sprint_ipv4_addr(&net_sin(&conn->local_addr)->sin_addr));
100 } else {
101 snprintk(src, sizeof(src), "%s", "?");
102 }
103 } else {
104 snprintk(src, sizeof(src), "%s", "-");
105 }
106
107 NET_DBG("[%p/%d/%u/0x%02x] remote %s/%u ",
108 conn, conn->proto, conn->family, conn->flags,
109 dst, remote_port);
110 NET_DBG(" local %s/%u cb %p ud %p",
111 src, local_port, conn->cb, conn->user_data);
112 }
113 #else
114 #define conn_register_debug(...)
115 #endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
116
117 static K_MUTEX_DEFINE(conn_lock);
118
conn_get_unused(void)119 static struct net_conn *conn_get_unused(void)
120 {
121 sys_snode_t *node;
122
123 k_mutex_lock(&conn_lock, K_FOREVER);
124
125 node = sys_slist_peek_head(&conn_unused);
126 if (!node) {
127 k_mutex_unlock(&conn_lock);
128 return NULL;
129 }
130
131 sys_slist_remove(&conn_unused, NULL, node);
132
133 k_mutex_unlock(&conn_lock);
134
135 return CONTAINER_OF(node, struct net_conn, node);
136 }
137
conn_set_used(struct net_conn * conn)138 static void conn_set_used(struct net_conn *conn)
139 {
140 conn->flags |= NET_CONN_IN_USE;
141
142 k_mutex_lock(&conn_lock, K_FOREVER);
143 sys_slist_prepend(&conn_used, &conn->node);
144 k_mutex_unlock(&conn_lock);
145 }
146
conn_set_unused(struct net_conn * conn)147 static void conn_set_unused(struct net_conn *conn)
148 {
149 (void)memset(conn, 0, sizeof(*conn));
150
151 k_mutex_lock(&conn_lock, K_FOREVER);
152 sys_slist_prepend(&conn_unused, &conn->node);
153 k_mutex_unlock(&conn_lock);
154 }
155
156 /* Check if we already have identical connection handler installed. */
conn_find_handler(struct net_if * iface,uint16_t proto,uint8_t family,const struct sockaddr * remote_addr,const struct sockaddr * local_addr,uint16_t remote_port,uint16_t local_port,bool reuseport_set)157 static struct net_conn *conn_find_handler(struct net_if *iface,
158 uint16_t proto, uint8_t family,
159 const struct sockaddr *remote_addr,
160 const struct sockaddr *local_addr,
161 uint16_t remote_port,
162 uint16_t local_port,
163 bool reuseport_set)
164 {
165 struct net_conn *conn;
166 struct net_conn *tmp;
167
168 k_mutex_lock(&conn_lock, K_FOREVER);
169
170 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
171 if (conn->proto != proto) {
172 continue;
173 }
174
175 if (conn->family != family) {
176 continue;
177 }
178
179 if (local_addr) {
180 if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) {
181 continue;
182 }
183
184 if (IS_ENABLED(CONFIG_NET_IPV6) &&
185 local_addr->sa_family == AF_INET6 &&
186 local_addr->sa_family ==
187 conn->local_addr.sa_family) {
188 if (!net_ipv6_addr_cmp(
189 &net_sin6(local_addr)->sin6_addr,
190 &net_sin6(&conn->local_addr)->
191 sin6_addr)) {
192 continue;
193 }
194 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
195 local_addr->sa_family == AF_INET &&
196 local_addr->sa_family ==
197 conn->local_addr.sa_family) {
198 if (!net_ipv4_addr_cmp(
199 &net_sin(local_addr)->sin_addr,
200 &net_sin(&conn->local_addr)->
201 sin_addr)) {
202 continue;
203 }
204 } else {
205 continue;
206 }
207 } else if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
208 continue;
209 }
210
211 if (net_sin(&conn->local_addr)->sin_port !=
212 htons(local_port)) {
213 continue;
214 }
215
216 if (remote_addr) {
217 if (!(conn->flags & NET_CONN_REMOTE_ADDR_SET)) {
218 continue;
219 }
220
221 if (IS_ENABLED(CONFIG_NET_IPV6) &&
222 remote_addr->sa_family == AF_INET6 &&
223 remote_addr->sa_family ==
224 conn->remote_addr.sa_family) {
225 if (!net_ipv6_addr_cmp(
226 &net_sin6(remote_addr)->sin6_addr,
227 &net_sin6(&conn->remote_addr)->
228 sin6_addr)) {
229 continue;
230 }
231 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
232 remote_addr->sa_family == AF_INET &&
233 remote_addr->sa_family ==
234 conn->remote_addr.sa_family) {
235 if (!net_ipv4_addr_cmp(
236 &net_sin(remote_addr)->sin_addr,
237 &net_sin(&conn->remote_addr)->
238 sin_addr)) {
239 continue;
240 }
241 } else {
242 continue;
243 }
244 } else if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
245 continue;
246 } else if (reuseport_set && conn->context != NULL &&
247 net_context_is_reuseport_set(conn->context)) {
248 continue;
249 }
250
251 if (net_sin(&conn->remote_addr)->sin_port !=
252 htons(remote_port)) {
253 continue;
254 }
255
256 if (conn->context != NULL && iface != NULL &&
257 net_context_is_bound_to_iface(conn->context)) {
258 if (iface != net_context_get_iface(conn->context)) {
259 continue;
260 }
261 }
262
263 k_mutex_unlock(&conn_lock);
264 return conn;
265 }
266
267 k_mutex_unlock(&conn_lock);
268 return NULL;
269 }
270
net_conn_register(uint16_t proto,uint8_t family,const struct sockaddr * remote_addr,const struct sockaddr * local_addr,uint16_t remote_port,uint16_t local_port,struct net_context * context,net_conn_cb_t cb,void * user_data,struct net_conn_handle ** handle)271 int net_conn_register(uint16_t proto, uint8_t family,
272 const struct sockaddr *remote_addr,
273 const struct sockaddr *local_addr,
274 uint16_t remote_port,
275 uint16_t local_port,
276 struct net_context *context,
277 net_conn_cb_t cb,
278 void *user_data,
279 struct net_conn_handle **handle)
280 {
281 struct net_conn *conn;
282 uint8_t flags = 0U;
283
284 conn = conn_find_handler(context != NULL ? net_context_get_iface(context) : NULL,
285 proto, family, remote_addr, local_addr,
286 remote_port, local_port,
287 context != NULL ?
288 net_context_is_reuseport_set(context) :
289 false);
290 if (conn) {
291 NET_ERR("Identical connection handler %p already found.", conn);
292 return -EADDRINUSE;
293 }
294
295 conn = conn_get_unused();
296 if (!conn) {
297 return -ENOENT;
298 }
299
300 if (remote_addr) {
301 if (IS_ENABLED(CONFIG_NET_IPV6) &&
302 remote_addr->sa_family == AF_INET6) {
303 memcpy(&conn->remote_addr, remote_addr,
304 sizeof(struct sockaddr_in6));
305
306 if (!net_ipv6_is_addr_unspecified(
307 &net_sin6(remote_addr)->
308 sin6_addr)) {
309 flags |= NET_CONN_REMOTE_ADDR_SPEC;
310 }
311 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
312 remote_addr->sa_family == AF_INET) {
313 memcpy(&conn->remote_addr, remote_addr,
314 sizeof(struct sockaddr_in));
315
316 if (net_sin(remote_addr)->sin_addr.s_addr) {
317 flags |= NET_CONN_REMOTE_ADDR_SPEC;
318 }
319 } else {
320 NET_ERR("Remote address family not set");
321 goto error;
322 }
323
324 flags |= NET_CONN_REMOTE_ADDR_SET;
325 }
326
327 if (local_addr) {
328 if (IS_ENABLED(CONFIG_NET_IPV6) &&
329 local_addr->sa_family == AF_INET6) {
330 memcpy(&conn->local_addr, local_addr,
331 sizeof(struct sockaddr_in6));
332
333 if (!net_ipv6_is_addr_unspecified(
334 &net_sin6(local_addr)->
335 sin6_addr)) {
336 flags |= NET_CONN_LOCAL_ADDR_SPEC;
337 }
338 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
339 local_addr->sa_family == AF_INET) {
340 memcpy(&conn->local_addr, local_addr,
341 sizeof(struct sockaddr_in));
342
343 if (net_sin(local_addr)->sin_addr.s_addr) {
344 flags |= NET_CONN_LOCAL_ADDR_SPEC;
345 }
346 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
347 local_addr->sa_family == AF_CAN) {
348 memcpy(&conn->local_addr, local_addr,
349 sizeof(struct sockaddr_can));
350 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
351 local_addr->sa_family == AF_PACKET) {
352 memcpy(&conn->local_addr, local_addr,
353 sizeof(struct sockaddr_ll));
354 } else {
355 NET_ERR("Local address family not set");
356 goto error;
357 }
358
359 flags |= NET_CONN_LOCAL_ADDR_SET;
360 }
361
362 if (remote_addr && local_addr) {
363 if (remote_addr->sa_family != local_addr->sa_family) {
364 NET_ERR("Address families different");
365 goto error;
366 }
367 }
368
369 if (remote_port) {
370 flags |= NET_CONN_REMOTE_PORT_SPEC;
371 net_sin(&conn->remote_addr)->sin_port = htons(remote_port);
372 }
373
374 if (local_port) {
375 flags |= NET_CONN_LOCAL_PORT_SPEC;
376 net_sin(&conn->local_addr)->sin_port = htons(local_port);
377 }
378
379 conn->cb = cb;
380 conn->user_data = user_data;
381 conn->flags = flags;
382 conn->proto = proto;
383 conn->family = family;
384 conn->context = context;
385
386 if (handle) {
387 *handle = (struct net_conn_handle *)conn;
388 }
389
390 conn_set_used(conn);
391
392 conn->v6only = net_context_is_v6only_set(context);
393
394 conn_register_debug(conn, remote_port, local_port);
395
396 return 0;
397 error:
398 conn_set_unused(conn);
399 return -EINVAL;
400 }
401
net_conn_unregister(struct net_conn_handle * handle)402 int net_conn_unregister(struct net_conn_handle *handle)
403 {
404 struct net_conn *conn = (struct net_conn *)handle;
405
406 if (conn < &conns[0] || conn > &conns[CONFIG_NET_MAX_CONN]) {
407 return -EINVAL;
408 }
409
410 if (!(conn->flags & NET_CONN_IN_USE)) {
411 return -ENOENT;
412 }
413
414 NET_DBG("Connection handler %p removed", conn);
415
416 k_mutex_lock(&conn_lock, K_FOREVER);
417 sys_slist_find_and_remove(&conn_used, &conn->node);
418 k_mutex_unlock(&conn_lock);
419
420 conn_set_unused(conn);
421
422 return 0;
423 }
424
net_conn_change_callback(struct net_conn_handle * handle,net_conn_cb_t cb,void * user_data)425 int net_conn_change_callback(struct net_conn_handle *handle,
426 net_conn_cb_t cb, void *user_data)
427 {
428 struct net_conn *conn = (struct net_conn *)handle;
429
430 if (conn < &conns[0] || conn > &conns[CONFIG_NET_MAX_CONN]) {
431 return -EINVAL;
432 }
433
434 if (!(conn->flags & NET_CONN_IN_USE)) {
435 return -ENOENT;
436 }
437
438 NET_DBG("[%zu] connection handler %p changed callback",
439 conn - conns, conn);
440
441 conn->cb = cb;
442 conn->user_data = user_data;
443
444 return 0;
445 }
446
conn_addr_cmp(struct net_pkt * pkt,union net_ip_header * ip_hdr,struct sockaddr * addr,bool is_remote)447 static bool conn_addr_cmp(struct net_pkt *pkt,
448 union net_ip_header *ip_hdr,
449 struct sockaddr *addr,
450 bool is_remote)
451 {
452 if (addr->sa_family != net_pkt_family(pkt)) {
453 return false;
454 }
455
456 if (IS_ENABLED(CONFIG_NET_IPV6) &&
457 net_pkt_family(pkt) == AF_INET6 &&
458 addr->sa_family == AF_INET6) {
459 uint8_t *addr6;
460
461 if (is_remote) {
462 addr6 = ip_hdr->ipv6->src;
463 } else {
464 addr6 = ip_hdr->ipv6->dst;
465 }
466
467 if (!net_ipv6_is_addr_unspecified(
468 &net_sin6(addr)->sin6_addr)) {
469 if (!net_ipv6_addr_cmp_raw((uint8_t *)&net_sin6(addr)->sin6_addr,
470 addr6)) {
471 return false;
472 }
473 }
474
475 return true;
476 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
477 net_pkt_family(pkt) == AF_INET &&
478 addr->sa_family == AF_INET) {
479 uint8_t *addr4;
480
481 if (is_remote) {
482 addr4 = ip_hdr->ipv4->src;
483 } else {
484 addr4 = ip_hdr->ipv4->dst;
485 }
486
487 if (net_sin(addr)->sin_addr.s_addr) {
488 if (!net_ipv4_addr_cmp_raw((uint8_t *)&net_sin(addr)->sin_addr,
489 addr4)) {
490 return false;
491 }
492 }
493 }
494
495 return true;
496 }
497
conn_send_icmp_error(struct net_pkt * pkt)498 static inline void conn_send_icmp_error(struct net_pkt *pkt)
499 {
500 if (IS_ENABLED(CONFIG_NET_DISABLE_ICMP_DESTINATION_UNREACHABLE)) {
501 return;
502 }
503
504 if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
505 net_icmpv6_send_error(pkt, NET_ICMPV6_DST_UNREACH,
506 NET_ICMPV6_DST_UNREACH_NO_PORT, 0);
507
508 } else if (IS_ENABLED(CONFIG_NET_IPV4)) {
509 net_icmpv4_send_error(pkt, NET_ICMPV4_DST_UNREACH,
510 NET_ICMPV4_DST_UNREACH_NO_PORT);
511 }
512 }
513
conn_are_endpoints_valid(struct net_pkt * pkt,uint8_t family,union net_ip_header * ip_hdr,uint16_t src_port,uint16_t dst_port)514 static bool conn_are_endpoints_valid(struct net_pkt *pkt, uint8_t family,
515 union net_ip_header *ip_hdr,
516 uint16_t src_port, uint16_t dst_port)
517 {
518 bool is_my_src_addr;
519 bool is_same_src_and_dst_addr;
520
521 if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
522 is_my_src_addr = net_ipv4_is_my_addr(
523 (struct in_addr *)ip_hdr->ipv4->src);
524 is_same_src_and_dst_addr = net_ipv4_addr_cmp_raw(
525 ip_hdr->ipv4->src, ip_hdr->ipv4->dst);
526 } else if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
527 is_my_src_addr = net_ipv6_is_my_addr(
528 (struct in6_addr *)ip_hdr->ipv6->src);
529 is_same_src_and_dst_addr = net_ipv6_addr_cmp_raw(
530 ip_hdr->ipv6->src, ip_hdr->ipv6->dst);
531 } else {
532 return true;
533 }
534
535 bool is_same_src_and_dst_port = src_port == dst_port;
536 bool are_invalid_endpoints =
537 (is_same_src_and_dst_addr || is_my_src_addr) && is_same_src_and_dst_port;
538
539 return !are_invalid_endpoints;
540 }
541
conn_raw_socket(struct net_pkt * pkt,struct net_conn * conn,uint8_t proto)542 static enum net_verdict conn_raw_socket(struct net_pkt *pkt,
543 struct net_conn *conn, uint8_t proto)
544 {
545 if (proto == ETH_P_ALL) {
546 enum net_sock_type type = net_context_get_type(conn->context);
547
548 if ((type == SOCK_DGRAM && !net_pkt_is_l2_processed(pkt)) ||
549 (type == SOCK_RAW && net_pkt_is_l2_processed(pkt))) {
550 return NET_CONTINUE;
551 }
552 }
553
554 if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) {
555 return NET_CONTINUE;
556 }
557
558 struct net_if *pkt_iface = net_pkt_iface(pkt);
559 struct sockaddr_ll *local;
560 struct net_pkt *raw_pkt;
561
562 local = (struct sockaddr_ll *)&conn->local_addr;
563
564 if (local->sll_ifindex != net_if_get_by_iface(pkt_iface)) {
565 return NET_CONTINUE;
566 }
567
568 NET_DBG("[%p] raw match found cb %p ud %p", conn, conn->cb,
569 conn->user_data);
570
571 raw_pkt = net_pkt_clone(pkt, CLONE_TIMEOUT);
572 if (!raw_pkt) {
573 net_stats_update_per_proto_drop(pkt_iface, proto);
574 NET_WARN("pkt cloning failed, pkt %p dropped", pkt);
575 return NET_DROP;
576 }
577
578 if (conn->cb(conn, raw_pkt, NULL, NULL, conn->user_data) == NET_DROP) {
579 net_stats_update_per_proto_drop(pkt_iface, proto);
580 net_pkt_unref(raw_pkt);
581 } else {
582 net_stats_update_per_proto_recv(pkt_iface, proto);
583 }
584
585 return NET_OK;
586 }
587
net_conn_input(struct net_pkt * pkt,union net_ip_header * ip_hdr,uint8_t proto,union net_proto_header * proto_hdr)588 enum net_verdict net_conn_input(struct net_pkt *pkt,
589 union net_ip_header *ip_hdr,
590 uint8_t proto,
591 union net_proto_header *proto_hdr)
592 {
593 struct net_if *pkt_iface = net_pkt_iface(pkt);
594 uint8_t pkt_family = net_pkt_family(pkt);
595 uint16_t src_port = 0U, dst_port = 0U;
596
597 if (!net_pkt_filter_local_in_recv_ok(pkt)) {
598 /* drop the packet */
599 return NET_DROP;
600 }
601
602 if (IS_ENABLED(CONFIG_NET_IP) && (pkt_family == AF_INET || pkt_family == AF_INET6)) {
603 if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
604 src_port = proto_hdr->udp->src_port;
605 dst_port = proto_hdr->udp->dst_port;
606 } else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
607 if (proto_hdr->tcp == NULL) {
608 return NET_DROP;
609 }
610 src_port = proto_hdr->tcp->src_port;
611 dst_port = proto_hdr->tcp->dst_port;
612 }
613 if (!conn_are_endpoints_valid(pkt, pkt_family, ip_hdr, src_port, dst_port)) {
614 NET_DBG("Dropping invalid src/dst end-points packet");
615 return NET_DROP;
616 }
617 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && pkt_family == AF_PACKET) {
618 if (proto != ETH_P_ALL && proto != IPPROTO_RAW) {
619 return NET_DROP;
620 }
621 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && pkt_family == AF_CAN) {
622 if (proto != CAN_RAW) {
623 return NET_DROP;
624 }
625 } else {
626 NET_DBG("No suitable protocol handler configured");
627 return NET_DROP;
628 }
629
630 NET_DBG("Check %s listener for pkt %p src port %u dst port %u"
631 " family %d", net_proto2str(net_pkt_family(pkt), proto), pkt,
632 ntohs(src_port), ntohs(dst_port), net_pkt_family(pkt));
633
634
635 struct net_conn *best_match = NULL;
636 int16_t best_rank = -1;
637 bool is_mcast_pkt = false;
638 bool mcast_pkt_delivered = false;
639 bool is_bcast_pkt = false;
640 bool raw_pkt_delivered = false;
641 bool raw_pkt_continue = false;
642 struct net_conn *conn;
643 net_conn_cb_t cb = NULL;
644 void *user_data = NULL;
645
646 if (IS_ENABLED(CONFIG_NET_IP)) {
647 /* If we receive a packet with multicast destination address, we might
648 * need to deliver the packet to multiple recipients.
649 */
650 if (IS_ENABLED(CONFIG_NET_IPV4) && pkt_family == AF_INET) {
651 if (net_ipv4_is_addr_mcast((struct in_addr *)ip_hdr->ipv4->dst)) {
652 is_mcast_pkt = true;
653 } else if (net_if_ipv4_is_addr_bcast(pkt_iface,
654 (struct in_addr *)ip_hdr->ipv4->dst)) {
655 is_bcast_pkt = true;
656 }
657 } else if (IS_ENABLED(CONFIG_NET_IPV6) && pkt_family == AF_INET6) {
658 is_mcast_pkt = net_ipv6_is_addr_mcast((struct in6_addr *)ip_hdr->ipv6->dst);
659 }
660 }
661
662 k_mutex_lock(&conn_lock, K_FOREVER);
663
664 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
665 /* Is the candidate connection matching the packet's interface? */
666 if (conn->context != NULL &&
667 net_context_is_bound_to_iface(conn->context) &&
668 net_pkt_iface(pkt) != net_context_get_iface(conn->context)) {
669 continue; /* wrong interface */
670 }
671
672 /* Is the candidate connection matching the packet's protocol family? */
673 if (conn->family != AF_UNSPEC &&
674 conn->family != pkt_family) {
675 if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
676 /* If there are other listening connections than
677 * AF_PACKET, the packet shall be also passed back to
678 * net_conn_input() in upper layer processing in order to
679 * re-check if there is any listening socket interested
680 * in this packet.
681 */
682 if (conn->family != AF_PACKET) {
683 raw_pkt_continue = true;
684 }
685 }
686
687 if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
688 if (!(conn->family == AF_INET6 && pkt_family == AF_INET &&
689 !conn->v6only)) {
690 continue;
691 }
692 } else {
693 continue; /* wrong protocol family */
694 }
695
696 /* We might have a match for v4-to-v6 mapping, check more */
697 }
698
699 /* Is the candidate connection matching the packet's protocol wihin the family? */
700 if (conn->proto != proto) {
701 /* For packet socket data, the proto is set to ETH_P_ALL
702 * or IPPROTO_RAW but the listener might have a specific
703 * protocol set. This is ok and let the packet pass this
704 * check in this case.
705 */
706 if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && pkt_family == AF_PACKET) {
707 if (proto != ETH_P_ALL && proto != IPPROTO_RAW) {
708 continue; /* wrong protocol */
709 }
710 } else {
711 continue; /* wrong protocol */
712 }
713 }
714
715 /* Apply protocol-specific matching criteria... */
716 uint8_t conn_family = conn->family;
717
718 if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && conn_family == AF_PACKET) {
719 /* This code shall be only executed when one enters
720 * the net_conn_input() from net_packet_socket() which
721 * targets AF_PACKET sockets.
722 *
723 * All AF_PACKET connections will receive the packet if
724 * their socket type and - in case of IPPROTO - protocol
725 * also matches.
726 */
727 if (proto == ETH_P_ALL) {
728 /* We shall continue with ETH_P_ALL to IPPROTO_RAW: */
729 raw_pkt_continue = true;
730 }
731
732 /* With IPPROTO_RAW deliver only if protocol match: */
733 if ((proto == ETH_P_ALL && conn->proto != IPPROTO_RAW) ||
734 conn->proto == proto) {
735 enum net_verdict ret = conn_raw_socket(pkt, conn, proto);
736
737 if (ret == NET_DROP) {
738 k_mutex_unlock(&conn_lock);
739 goto drop;
740 } else if (ret == NET_OK) {
741 raw_pkt_delivered = true;
742 }
743
744 continue; /* packet was consumed */
745 }
746 } else if ((IS_ENABLED(CONFIG_NET_UDP) || IS_ENABLED(CONFIG_NET_TCP)) &&
747 (conn_family == AF_INET || conn_family == AF_INET6 ||
748 conn_family == AF_UNSPEC)) {
749 /* Is the candidate connection matching the packet's TCP/UDP
750 * address and port?
751 */
752 if (net_sin(&conn->remote_addr)->sin_port &&
753 net_sin(&conn->remote_addr)->sin_port != src_port) {
754 continue; /* wrong remote port */
755 }
756
757 if (net_sin(&conn->local_addr)->sin_port &&
758 net_sin(&conn->local_addr)->sin_port != dst_port) {
759 continue; /* wrong local port */
760 }
761
762 if ((conn->flags & NET_CONN_REMOTE_ADDR_SET) &&
763 !conn_addr_cmp(pkt, ip_hdr, &conn->remote_addr, true)) {
764 continue; /* wrong remote address */
765 }
766
767 if ((conn->flags & NET_CONN_LOCAL_ADDR_SET) &&
768 !conn_addr_cmp(pkt, ip_hdr, &conn->local_addr, false)) {
769
770 /* Check if we could do a v4-mapping-to-v6 and the IPv6 socket
771 * has no IPV6_V6ONLY option set and if the local IPV6 address
772 * is unspecified, then we could accept a connection from IPv4
773 * address by mapping it to IPv6 address.
774 */
775 if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
776 if (!(conn->family == AF_INET6 && pkt_family == AF_INET &&
777 !conn->v6only &&
778 net_ipv6_is_addr_unspecified(
779 &net_sin6(&conn->local_addr)->sin6_addr))) {
780 continue; /* wrong local address */
781 }
782 } else {
783 continue; /* wrong local address */
784 }
785
786 /* We might have a match for v4-to-v6 mapping,
787 * continue with rank checking.
788 */
789 }
790
791 if (best_rank < NET_CONN_RANK(conn->flags)) {
792 struct net_pkt *mcast_pkt;
793
794 if (!is_mcast_pkt) {
795 best_rank = NET_CONN_RANK(conn->flags);
796 best_match = conn;
797
798 continue; /* found a match - but maybe not yet the best */
799 }
800
801 /* If we have a multicast packet, and we found
802 * a match, then deliver the packet immediately
803 * to the handler. As there might be several
804 * sockets interested about these, we need to
805 * clone the received pkt.
806 */
807
808 NET_DBG("[%p] mcast match found cb %p ud %p", conn, conn->cb,
809 conn->user_data);
810
811 mcast_pkt = net_pkt_clone(pkt, CLONE_TIMEOUT);
812 if (!mcast_pkt) {
813 k_mutex_unlock(&conn_lock);
814 goto drop;
815 }
816
817 if (conn->cb(conn, mcast_pkt, ip_hdr, proto_hdr, conn->user_data) ==
818 NET_DROP) {
819 net_stats_update_per_proto_drop(pkt_iface, proto);
820 net_pkt_unref(mcast_pkt);
821 } else {
822 net_stats_update_per_proto_recv(pkt_iface, proto);
823 }
824
825 mcast_pkt_delivered = true;
826 }
827 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && conn_family == AF_CAN) {
828 best_match = conn;
829 }
830 } /* loop end */
831
832 if (best_match) {
833 cb = best_match->cb;
834 user_data = best_match->user_data;
835 }
836
837 k_mutex_unlock(&conn_lock);
838
839 if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && pkt_family == AF_PACKET) {
840 if (raw_pkt_continue) {
841 /* When there is open connection different than
842 * AF_PACKET this packet shall be also handled in
843 * the upper net stack layers.
844 */
845 return NET_CONTINUE;
846 }
847 if (raw_pkt_delivered) {
848 /* As one or more raw socket packets
849 * have already been delivered in the loop above,
850 * we shall not call the callback again here.
851 */
852 net_pkt_unref(pkt);
853 return NET_OK;
854 }
855 }
856
857 if (IS_ENABLED(CONFIG_NET_IP) && is_mcast_pkt && mcast_pkt_delivered) {
858 /* As one or more multicast packets
859 * have already been delivered in the loop above,
860 * we shall not call the callback again here.
861 */
862 net_pkt_unref(pkt);
863 return NET_OK;
864 }
865
866 if (cb) {
867 NET_DBG("[%p] match found cb %p ud %p rank 0x%02x", best_match, cb,
868 user_data, NET_CONN_RANK(best_match->flags));
869
870 if (cb(best_match, pkt, ip_hdr, proto_hdr, user_data)
871 == NET_DROP) {
872 goto drop;
873 }
874
875 net_stats_update_per_proto_recv(pkt_iface, proto);
876
877 return NET_OK;
878 }
879
880 NET_DBG("No match found.");
881
882 if (IS_ENABLED(CONFIG_NET_IP) && (pkt_family == AF_INET || pkt_family == AF_INET6) &&
883 !(is_mcast_pkt || is_bcast_pkt)) {
884 if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP &&
885 IS_ENABLED(CONFIG_NET_TCP_REJECT_CONN_WITH_RST)) {
886 net_tcp_reply_rst(pkt);
887 net_stats_update_tcp_seg_connrst(pkt_iface);
888 } else {
889 conn_send_icmp_error(pkt);
890 }
891 }
892
893 drop:
894 net_stats_update_per_proto_drop(pkt_iface, proto);
895
896 return NET_DROP;
897 }
898
net_conn_foreach(net_conn_foreach_cb_t cb,void * user_data)899 void net_conn_foreach(net_conn_foreach_cb_t cb, void *user_data)
900 {
901 struct net_conn *conn;
902
903 k_mutex_lock(&conn_lock, K_FOREVER);
904
905 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
906 cb(conn, user_data);
907 }
908
909 k_mutex_unlock(&conn_lock);
910 }
911
net_conn_init(void)912 void net_conn_init(void)
913 {
914 int i;
915
916 sys_slist_init(&conn_unused);
917 sys_slist_init(&conn_used);
918
919 for (i = 0; i < CONFIG_NET_MAX_CONN; i++) {
920 sys_slist_prepend(&conn_unused, &conns[i].node);
921 }
922 }
923