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 /** Is this connection used or not */
37 #define NET_CONN_IN_USE BIT(0)
38
39 /** Remote address set */
40 #define NET_CONN_REMOTE_ADDR_SET BIT(1)
41
42 /** Local address set */
43 #define NET_CONN_LOCAL_ADDR_SET BIT(2)
44
45 /** Remote port set */
46 #define NET_CONN_REMOTE_PORT_SPEC BIT(3)
47
48 /** Local port set */
49 #define NET_CONN_LOCAL_PORT_SPEC BIT(4)
50
51 /** Remote address specified */
52 #define NET_CONN_REMOTE_ADDR_SPEC BIT(5)
53
54 /** Local address specified */
55 #define NET_CONN_LOCAL_ADDR_SPEC BIT(6)
56
57 #define NET_CONN_RANK(_flags) (_flags & 0x78)
58
59 static struct net_conn conns[CONFIG_NET_MAX_CONN];
60
61 static sys_slist_t conn_unused;
62 static sys_slist_t conn_used;
63
64 #if (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG)
65 static inline
conn_register_debug(struct net_conn * conn,uint16_t remote_port,uint16_t local_port)66 void conn_register_debug(struct net_conn *conn,
67 uint16_t remote_port, uint16_t local_port)
68 {
69 char dst[NET_IPV6_ADDR_LEN];
70 char src[NET_IPV6_ADDR_LEN];
71
72 if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
73 if (IS_ENABLED(CONFIG_NET_IPV6) &&
74 conn->family == NET_AF_INET6) {
75 snprintk(dst, sizeof(dst), "%s",
76 net_sprint_ipv6_addr(&net_sin6(&conn->remote_addr)->sin6_addr));
77 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
78 conn->family == NET_AF_INET) {
79 snprintk(dst, sizeof(dst), "%s",
80 net_sprint_ipv4_addr(&net_sin(&conn->remote_addr)->sin_addr));
81 } else {
82 snprintk(dst, sizeof(dst), "%s", "?");
83 }
84 } else {
85 snprintk(dst, sizeof(dst), "%s", "-");
86 }
87
88 if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
89 if (IS_ENABLED(CONFIG_NET_IPV6) &&
90 conn->family == NET_AF_INET6) {
91 snprintk(src, sizeof(src), "%s",
92 net_sprint_ipv6_addr(&net_sin6(&conn->local_addr)->sin6_addr));
93 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
94 conn->family == NET_AF_INET) {
95 snprintk(src, sizeof(src), "%s",
96 net_sprint_ipv4_addr(&net_sin(&conn->local_addr)->sin_addr));
97 } else {
98 snprintk(src, sizeof(src), "%s", "?");
99 }
100 } else {
101 snprintk(src, sizeof(src), "%s", "-");
102 }
103
104 NET_DBG("[%p/%d/%u/0x%02x] remote %s/%u ",
105 conn, conn->proto, conn->family, conn->flags,
106 dst, remote_port);
107 NET_DBG(" local %s/%u cb %p ud %p",
108 src, local_port, conn->cb, conn->user_data);
109 }
110 #else
111 #define conn_register_debug(...)
112 #endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
113
114 static K_MUTEX_DEFINE(conn_lock);
115
conn_get_unused(void)116 static struct net_conn *conn_get_unused(void)
117 {
118 sys_snode_t *node;
119
120 k_mutex_lock(&conn_lock, K_FOREVER);
121
122 node = sys_slist_peek_head(&conn_unused);
123 if (!node) {
124 k_mutex_unlock(&conn_lock);
125 return NULL;
126 }
127
128 sys_slist_remove(&conn_unused, NULL, node);
129
130 k_mutex_unlock(&conn_lock);
131
132 return CONTAINER_OF(node, struct net_conn, node);
133 }
134
conn_set_used(struct net_conn * conn)135 static void conn_set_used(struct net_conn *conn)
136 {
137 conn->flags |= NET_CONN_IN_USE;
138
139 k_mutex_lock(&conn_lock, K_FOREVER);
140 sys_slist_prepend(&conn_used, &conn->node);
141 k_mutex_unlock(&conn_lock);
142 }
143
conn_set_unused(struct net_conn * conn)144 static void conn_set_unused(struct net_conn *conn)
145 {
146 (void)memset(conn, 0, sizeof(*conn));
147
148 k_mutex_lock(&conn_lock, K_FOREVER);
149 sys_slist_prepend(&conn_unused, &conn->node);
150 k_mutex_unlock(&conn_lock);
151 }
152
153 /* Check if we already have identical connection handler installed. */
conn_find_handler(struct net_if * iface,uint16_t proto,uint8_t family,const struct net_sockaddr * remote_addr,const struct net_sockaddr * local_addr,uint16_t remote_port,uint16_t local_port,bool reuseport_set)154 static struct net_conn *conn_find_handler(struct net_if *iface,
155 uint16_t proto, uint8_t family,
156 const struct net_sockaddr *remote_addr,
157 const struct net_sockaddr *local_addr,
158 uint16_t remote_port,
159 uint16_t local_port,
160 bool reuseport_set)
161 {
162 struct net_conn *conn;
163 struct net_conn *tmp;
164
165 k_mutex_lock(&conn_lock, K_FOREVER);
166
167 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
168 if (conn->proto != proto) {
169 continue;
170 }
171
172 if (conn->family != family) {
173 continue;
174 }
175
176 if (local_addr) {
177 if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) {
178 continue;
179 }
180
181 if (IS_ENABLED(CONFIG_NET_IPV6) &&
182 local_addr->sa_family == NET_AF_INET6 &&
183 local_addr->sa_family ==
184 conn->local_addr.sa_family) {
185 if (!net_ipv6_addr_cmp(
186 &net_sin6(local_addr)->sin6_addr,
187 &net_sin6(&conn->local_addr)->
188 sin6_addr)) {
189 continue;
190 }
191 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
192 local_addr->sa_family == NET_AF_INET &&
193 local_addr->sa_family ==
194 conn->local_addr.sa_family) {
195 if (!net_ipv4_addr_cmp(
196 &net_sin(local_addr)->sin_addr,
197 &net_sin(&conn->local_addr)->
198 sin_addr)) {
199 continue;
200 }
201 } else {
202 continue;
203 }
204 } else if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
205 continue;
206 }
207
208 if (net_sin(&conn->local_addr)->sin_port !=
209 net_htons(local_port)) {
210 continue;
211 }
212
213 if (remote_addr) {
214 if (!(conn->flags & NET_CONN_REMOTE_ADDR_SET)) {
215 continue;
216 }
217
218 if (IS_ENABLED(CONFIG_NET_IPV6) &&
219 remote_addr->sa_family == NET_AF_INET6 &&
220 remote_addr->sa_family ==
221 conn->remote_addr.sa_family) {
222 if (!net_ipv6_addr_cmp(
223 &net_sin6(remote_addr)->sin6_addr,
224 &net_sin6(&conn->remote_addr)->
225 sin6_addr)) {
226 continue;
227 }
228 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
229 remote_addr->sa_family == NET_AF_INET &&
230 remote_addr->sa_family ==
231 conn->remote_addr.sa_family) {
232 if (!net_ipv4_addr_cmp(
233 &net_sin(remote_addr)->sin_addr,
234 &net_sin(&conn->remote_addr)->
235 sin_addr)) {
236 continue;
237 }
238 } else {
239 continue;
240 }
241 } else if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
242 continue;
243 } else if (reuseport_set && conn->context != NULL &&
244 net_context_is_reuseport_set(conn->context)) {
245 continue;
246 }
247
248 if (net_sin(&conn->remote_addr)->sin_port !=
249 net_htons(remote_port)) {
250 continue;
251 }
252
253 if (conn->context != NULL && iface != NULL &&
254 net_context_is_bound_to_iface(conn->context)) {
255 if (iface != net_context_get_iface(conn->context)) {
256 continue;
257 }
258 }
259
260 k_mutex_unlock(&conn_lock);
261 return conn;
262 }
263
264 k_mutex_unlock(&conn_lock);
265 return NULL;
266 }
267
net_conn_change_callback(struct net_conn * conn,net_conn_cb_t cb,void * user_data)268 static void net_conn_change_callback(struct net_conn *conn,
269 net_conn_cb_t cb, void *user_data)
270 {
271 NET_DBG("[%zu] connection handler %p changed callback",
272 conn - conns, conn);
273
274 conn->cb = cb;
275 conn->user_data = user_data;
276 }
277
net_conn_change_remote(struct net_conn * conn,const struct net_sockaddr * remote_addr,uint16_t remote_port)278 static int net_conn_change_remote(struct net_conn *conn,
279 const struct net_sockaddr *remote_addr,
280 uint16_t remote_port)
281 {
282 NET_DBG("[%zu] connection handler %p changed remote",
283 conn - conns, conn);
284
285 if (remote_addr) {
286 if (IS_ENABLED(CONFIG_NET_IPV6) &&
287 remote_addr->sa_family == NET_AF_INET6) {
288 memcpy(&conn->remote_addr, remote_addr,
289 sizeof(struct net_sockaddr_in6));
290
291 if (!net_ipv6_is_addr_unspecified(
292 &net_sin6(remote_addr)->
293 sin6_addr)) {
294 conn->flags |= NET_CONN_REMOTE_ADDR_SPEC;
295 }
296 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
297 remote_addr->sa_family == NET_AF_INET) {
298 memcpy(&conn->remote_addr, remote_addr,
299 sizeof(struct net_sockaddr_in));
300
301 if (net_sin(remote_addr)->sin_addr.s_addr) {
302 conn->flags |= NET_CONN_REMOTE_ADDR_SPEC;
303 }
304 } else {
305 NET_ERR("Remote address family not set");
306 return -EINVAL;
307 }
308
309 conn->flags |= NET_CONN_REMOTE_ADDR_SET;
310 } else {
311 conn->flags &= ~NET_CONN_REMOTE_ADDR_SPEC;
312 conn->flags &= ~NET_CONN_REMOTE_ADDR_SET;
313 }
314
315 if (remote_port) {
316 conn->flags |= NET_CONN_REMOTE_PORT_SPEC;
317 net_sin(&conn->remote_addr)->sin_port = net_htons(remote_port);
318 } else {
319 conn->flags &= ~NET_CONN_REMOTE_PORT_SPEC;
320 }
321
322 return 0;
323 }
324
net_conn_change_local(struct net_conn * conn,const struct net_sockaddr * local_addr,uint16_t local_port)325 static int net_conn_change_local(struct net_conn *conn,
326 const struct net_sockaddr *local_addr,
327 uint16_t local_port)
328 {
329 NET_DBG("[%zu] connection handler %p changed local",
330 conn - conns, conn);
331
332 if (local_addr != NULL) {
333 if (IS_ENABLED(CONFIG_NET_IPV6) &&
334 local_addr->sa_family == NET_AF_INET6) {
335 memcpy(&conn->local_addr, local_addr,
336 sizeof(struct net_sockaddr_in6));
337
338 if (!net_ipv6_is_addr_unspecified(
339 &net_sin6(local_addr)->sin6_addr)) {
340 conn->flags |= NET_CONN_LOCAL_ADDR_SPEC;
341 }
342 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
343 local_addr->sa_family == NET_AF_INET) {
344 memcpy(&conn->local_addr, local_addr,
345 sizeof(struct net_sockaddr_in));
346
347 if (net_sin(local_addr)->sin_addr.s_addr) {
348 conn->flags |= NET_CONN_LOCAL_ADDR_SPEC;
349 }
350 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
351 local_addr->sa_family == NET_AF_CAN) {
352 memcpy(&conn->local_addr, local_addr,
353 sizeof(struct net_sockaddr_can));
354 } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
355 local_addr->sa_family == NET_AF_PACKET) {
356 memcpy(&conn->local_addr, local_addr,
357 sizeof(struct net_sockaddr_ll));
358 } else {
359 NET_ERR("Local address family not set");
360 return -EINVAL;
361 }
362
363 conn->flags |= NET_CONN_LOCAL_ADDR_SET;
364 } else {
365 conn->flags &= ~NET_CONN_LOCAL_ADDR_SPEC;
366 conn->flags &= ~NET_CONN_LOCAL_ADDR_SET;
367 }
368
369 if (local_port > 0U) {
370 conn->flags |= NET_CONN_LOCAL_PORT_SPEC;
371 net_sin(&conn->local_addr)->sin_port = net_htons(local_port);
372 } else {
373 conn->flags &= ~NET_CONN_LOCAL_PORT_SPEC;
374 }
375
376 return 0;
377 }
378
net_conn_register(uint16_t proto,enum net_sock_type type,uint8_t family,const struct net_sockaddr * remote_addr,const struct net_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)379 int net_conn_register(uint16_t proto, enum net_sock_type type, uint8_t family,
380 const struct net_sockaddr *remote_addr,
381 const struct net_sockaddr *local_addr,
382 uint16_t remote_port,
383 uint16_t local_port,
384 struct net_context *context,
385 net_conn_cb_t cb,
386 void *user_data,
387 struct net_conn_handle **handle)
388 {
389 struct net_conn *conn;
390 int ret;
391
392 conn = conn_find_handler(context != NULL ? net_context_get_iface(context) : NULL,
393 proto, family, remote_addr, local_addr,
394 remote_port, local_port,
395 context != NULL ?
396 net_context_is_reuseport_set(context) :
397 false);
398 if (conn != NULL) {
399 NET_ERR("Identical connection handler %p already found.", conn);
400 return -EADDRINUSE;
401 }
402
403 conn = conn_get_unused();
404 if (conn == NULL) {
405 NET_ERR("Not enough connection contexts. "
406 "Consider increasing CONFIG_NET_MAX_CONN.");
407 return -ENOENT;
408 }
409
410 if (remote_addr && local_addr) {
411 if (remote_addr->sa_family != local_addr->sa_family) {
412 NET_ERR("Address families different");
413 goto error;
414 }
415 }
416
417 net_conn_change_callback(conn, cb, user_data);
418
419 conn->proto = proto;
420 conn->type = type;
421 conn->family = family;
422 conn->context = context;
423
424 ret = net_conn_change_local(conn, local_addr, local_port);
425 if (ret < 0) {
426 goto error;
427 }
428
429 ret = net_conn_change_remote(conn, remote_addr, remote_port);
430 if (ret < 0) {
431 goto error;
432 }
433
434 if (handle) {
435 *handle = (struct net_conn_handle *)conn;
436 }
437
438 conn_set_used(conn);
439
440 conn->v6only = net_context_is_v6only_set(context);
441
442 conn_register_debug(conn, remote_port, local_port);
443
444 return 0;
445 error:
446 conn_set_unused(conn);
447 return -EINVAL;
448 }
449
net_conn_unregister(struct net_conn_handle * handle)450 int net_conn_unregister(struct net_conn_handle *handle)
451 {
452 struct net_conn *conn = (struct net_conn *)handle;
453
454 if (conn < &conns[0] || conn > &conns[CONFIG_NET_MAX_CONN]) {
455 return -EINVAL;
456 }
457
458 if (!(conn->flags & NET_CONN_IN_USE)) {
459 return -ENOENT;
460 }
461
462 NET_DBG("Connection handler %p removed", conn);
463
464 k_mutex_lock(&conn_lock, K_FOREVER);
465 sys_slist_find_and_remove(&conn_used, &conn->node);
466 k_mutex_unlock(&conn_lock);
467
468 conn_set_unused(conn);
469
470 return 0;
471 }
472
net_conn_update(struct net_conn_handle * handle,net_conn_cb_t cb,void * user_data,const struct net_sockaddr * remote_addr,uint16_t remote_port,const struct net_sockaddr * local_addr,uint16_t local_port)473 int net_conn_update(struct net_conn_handle *handle,
474 net_conn_cb_t cb,
475 void *user_data,
476 const struct net_sockaddr *remote_addr,
477 uint16_t remote_port,
478 const struct net_sockaddr *local_addr,
479 uint16_t local_port)
480 {
481 struct net_conn *conn = (struct net_conn *)handle;
482 int ret;
483
484 if (conn < &conns[0] || conn > &conns[CONFIG_NET_MAX_CONN]) {
485 return -EINVAL;
486 }
487
488 if (!(conn->flags & NET_CONN_IN_USE)) {
489 return -ENOENT;
490 }
491
492 net_conn_change_callback(conn, cb, user_data);
493
494 ret = net_conn_change_local(conn, local_addr, local_port);
495 if (ret < 0) {
496 return ret;
497 }
498
499 ret = net_conn_change_remote(conn, remote_addr, remote_port);
500
501 return ret;
502 }
503
conn_addr_cmp(struct net_pkt * pkt,union net_ip_header * ip_hdr,struct net_sockaddr * addr,bool is_remote)504 static bool conn_addr_cmp(struct net_pkt *pkt,
505 union net_ip_header *ip_hdr,
506 struct net_sockaddr *addr,
507 bool is_remote)
508 {
509 if (addr->sa_family != net_pkt_family(pkt)) {
510 return false;
511 }
512
513 if (IS_ENABLED(CONFIG_NET_IPV6) &&
514 net_pkt_family(pkt) == NET_AF_INET6 &&
515 addr->sa_family == NET_AF_INET6) {
516 uint8_t *addr6;
517
518 if (is_remote) {
519 addr6 = ip_hdr->ipv6->src;
520 } else {
521 addr6 = ip_hdr->ipv6->dst;
522 }
523
524 if (!net_ipv6_is_addr_unspecified(
525 &net_sin6(addr)->sin6_addr)) {
526 if (!net_ipv6_addr_cmp_raw((uint8_t *)&net_sin6(addr)->sin6_addr,
527 addr6)) {
528 return false;
529 }
530 }
531
532 return true;
533 } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
534 net_pkt_family(pkt) == NET_AF_INET &&
535 addr->sa_family == NET_AF_INET) {
536 uint8_t *addr4;
537
538 if (is_remote) {
539 addr4 = ip_hdr->ipv4->src;
540 } else {
541 addr4 = ip_hdr->ipv4->dst;
542 }
543
544 if (net_sin(addr)->sin_addr.s_addr) {
545 if (!net_ipv4_addr_cmp_raw((uint8_t *)&net_sin(addr)->sin_addr,
546 addr4)) {
547 return false;
548 }
549 }
550 }
551
552 return true;
553 }
554
conn_send_icmp_error(struct net_pkt * pkt)555 static inline void conn_send_icmp_error(struct net_pkt *pkt)
556 {
557 if (IS_ENABLED(CONFIG_NET_DISABLE_ICMP_DESTINATION_UNREACHABLE)) {
558 return;
559 }
560
561 if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == NET_AF_INET6) {
562 net_icmpv6_send_error(pkt, NET_ICMPV6_DST_UNREACH,
563 NET_ICMPV6_DST_UNREACH_NO_PORT, 0);
564
565 } else if (IS_ENABLED(CONFIG_NET_IPV4)) {
566 net_icmpv4_send_error(pkt, NET_ICMPV4_DST_UNREACH,
567 NET_ICMPV4_DST_UNREACH_NO_PORT);
568 }
569 }
570
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)571 static bool conn_are_endpoints_valid(struct net_pkt *pkt, uint8_t family,
572 union net_ip_header *ip_hdr,
573 uint16_t src_port, uint16_t dst_port)
574 {
575 bool is_my_src_addr;
576 bool is_same_src_and_dst_addr;
577
578 if (IS_ENABLED(CONFIG_NET_IPV4) && family == NET_AF_INET) {
579 is_my_src_addr = net_ipv4_is_my_addr_raw(ip_hdr->ipv4->src);
580 is_same_src_and_dst_addr = net_ipv4_addr_cmp_raw(
581 ip_hdr->ipv4->src, ip_hdr->ipv4->dst);
582 } else if (IS_ENABLED(CONFIG_NET_IPV6) && family == NET_AF_INET6) {
583 is_my_src_addr = net_ipv6_is_my_addr_raw(ip_hdr->ipv6->src);
584 is_same_src_and_dst_addr = net_ipv6_addr_cmp_raw(
585 ip_hdr->ipv6->src, ip_hdr->ipv6->dst);
586 } else {
587 return true;
588 }
589
590 bool is_same_src_and_dst_port = src_port == dst_port;
591 bool are_invalid_endpoints =
592 (is_same_src_and_dst_addr || is_my_src_addr) && is_same_src_and_dst_port;
593
594 return !are_invalid_endpoints;
595 }
596
597 /* Is the candidate connection matching the packet's interface? */
is_iface_matching(struct net_conn * conn,struct net_pkt * pkt)598 static bool is_iface_matching(struct net_conn *conn, struct net_pkt *pkt)
599 {
600 if (conn->context == NULL) {
601 return true;
602 }
603
604 if (!net_context_is_bound_to_iface(conn->context)) {
605 return true;
606 }
607
608 return (net_pkt_iface(pkt) == net_context_get_iface(conn->context));
609 }
610
611 #if defined(CONFIG_NET_SOCKETS_PACKET) || defined(CONFIG_NET_SOCKETS_INET_RAW)
conn_raw_socket_deliver(struct net_pkt * pkt,struct net_conn * conn,bool is_ip)612 static void conn_raw_socket_deliver(struct net_pkt *pkt, struct net_conn *conn,
613 bool is_ip)
614 {
615 struct net_pkt *raw_pkt;
616 struct net_pkt_cursor cur;
617
618 net_pkt_cursor_backup(pkt, &cur);
619 net_pkt_cursor_init(pkt);
620
621 NET_DBG("[%p] raw%s match found cb %p ud %p", conn, is_ip ? " IP" : "",
622 conn->cb, conn->user_data);
623
624 raw_pkt = net_pkt_clone(pkt, K_MSEC(CONFIG_NET_CONN_PACKET_CLONE_TIMEOUT));
625 if (raw_pkt == NULL) {
626 NET_WARN("pkt cloning failed, pkt %p not delivered", pkt);
627 goto out;
628 }
629
630 if (conn->cb(conn, raw_pkt, NULL, NULL, conn->user_data) == NET_DROP) {
631 net_pkt_unref(raw_pkt);
632 }
633
634 out:
635 net_pkt_cursor_restore(pkt, &cur);
636 }
637 #endif /* defined(CONFIG_NET_SOCKETS_PACKET) || defined(CONFIG_NET_SOCKETS_INET_RAW) */
638
639 #if defined(CONFIG_NET_SOCKETS_PACKET)
net_conn_packet_input(struct net_pkt * pkt,uint16_t proto,enum net_sock_type type)640 void net_conn_packet_input(struct net_pkt *pkt, uint16_t proto, enum net_sock_type type)
641 {
642 struct net_sockaddr_ll *local;
643 struct net_conn *conn;
644
645 /* Only accept input with NET_AF_PACKET family. */
646 if (net_pkt_family(pkt) != NET_AF_PACKET) {
647 return;
648 }
649
650 NET_DBG("Check proto 0x%04x listener for pkt %p family %d",
651 proto, pkt, net_pkt_family(pkt));
652
653 k_mutex_lock(&conn_lock, K_FOREVER);
654
655 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
656 if (!is_iface_matching(conn, pkt)) {
657 continue; /* wrong interface */
658 }
659
660 /* If there are other listening connections than
661 * NET_AF_PACKET, the packet shall be also passed back to
662 * net_conn_input() in upper layer processing in order to
663 * re-check if there is any listening socket interested
664 * in this packet.
665 */
666 if (conn->family != NET_AF_PACKET) {
667 continue; /* wrong family */
668 }
669
670 if (conn->type != type) {
671 continue;
672 }
673
674 if (conn->proto == 0) {
675 continue; /* Local proto 0 doesn't forward any packets */
676 }
677
678 /* Allow proto mismatch if socket was created with ETH_P_ALL, or it's raw
679 * packet socket input.
680 */
681 if (conn->proto != proto && conn->proto != ETH_P_ALL && type != NET_SOCK_RAW) {
682 continue; /* wrong protocol */
683 }
684
685 /* Apply protocol-specific matching criteria... */
686
687 /* Unbound sockets should collect packets from all interfaces. */
688 if ((conn->flags & NET_CONN_LOCAL_ADDR_SET) != 0U) {
689 local = (struct net_sockaddr_ll *)&conn->local_addr;
690 if (local->sll_ifindex != 0 &&
691 local->sll_ifindex != net_if_get_by_iface(net_pkt_iface(pkt))) {
692 continue;
693 }
694 }
695
696 conn_raw_socket_deliver(pkt, conn, false);
697
698 }
699
700 k_mutex_unlock(&conn_lock);
701
702 }
703 #else
net_conn_packet_input(struct net_pkt * pkt,uint16_t proto,enum net_sock_type type)704 void net_conn_packet_input(struct net_pkt *pkt, uint16_t proto, enum net_sock_type type)
705 {
706 ARG_UNUSED(pkt);
707 ARG_UNUSED(proto);
708 ARG_UNUSED(type);
709 }
710 #endif /* defined(CONFIG_NET_SOCKETS_PACKET) */
711
712 #if defined(CONFIG_NET_SOCKETS_INET_RAW)
net_conn_raw_ip_input(struct net_pkt * pkt,union net_ip_header * ip_hdr,uint8_t proto)713 enum net_verdict net_conn_raw_ip_input(struct net_pkt *pkt,
714 union net_ip_header *ip_hdr,
715 uint8_t proto)
716 {
717 uint8_t pkt_family = net_pkt_family(pkt);
718 struct net_conn *conn;
719
720 if (pkt_family != NET_AF_INET && pkt_family != NET_AF_INET6) {
721 return NET_CONTINUE;
722 }
723
724 NET_DBG("Check %s listener for pkt %p family %d",
725 net_proto2str(net_pkt_family(pkt), proto), pkt,
726 net_pkt_family(pkt));
727
728 k_mutex_lock(&conn_lock, K_FOREVER);
729
730 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
731 if (!is_iface_matching(conn, pkt)) {
732 continue; /* wrong interface */
733 }
734
735 if (conn->family != pkt_family) {
736 continue; /* wrong family */
737 }
738
739 if (conn->type != NET_SOCK_RAW) {
740 continue; /* wrong type */
741 }
742
743 if (conn->proto != proto && conn->proto != NET_IPPROTO_IP) {
744 continue; /* wrong protocol */
745 }
746
747 /* Apply protocol-specific matching criteria... */
748
749 if (((conn->flags & NET_CONN_LOCAL_ADDR_SET) != 0U) &&
750 !conn_addr_cmp(pkt, ip_hdr, &conn->local_addr, false)) {
751 continue; /* wrong local address */
752 }
753
754 conn_raw_socket_deliver(pkt, conn, true);
755 }
756
757 k_mutex_unlock(&conn_lock);
758
759 /* Raw IP packets are passed further in the stack regardless. */
760 return NET_CONTINUE;
761 }
762 #else
net_conn_raw_ip_input(struct net_pkt * pkt,union net_ip_header * ip_hdr,uint8_t proto)763 enum net_verdict net_conn_raw_ip_input(struct net_pkt *pkt,
764 union net_ip_header *ip_hdr,
765 uint8_t proto)
766 {
767 ARG_UNUSED(pkt);
768 ARG_UNUSED(ip_hdr);
769 ARG_UNUSED(proto);
770
771 return NET_CONTINUE;
772 }
773 #endif /* defined(CONFIG_NET_SOCKETS_INET_RAW) */
774
775 #if defined(CONFIG_NET_SOCKETS_CAN)
net_conn_can_input(struct net_pkt * pkt,uint8_t proto)776 enum net_verdict net_conn_can_input(struct net_pkt *pkt, uint8_t proto)
777 {
778 struct net_conn *best_match = NULL;
779 struct net_conn *conn;
780 net_conn_cb_t cb = NULL;
781 void *user_data = NULL;
782
783 /* Only accept input with NET_AF_CAN family and NET_CAN_RAW protocol. */
784 if (net_pkt_family(pkt) != NET_AF_CAN || proto != NET_CAN_RAW) {
785 return NET_DROP;
786 }
787
788 NET_DBG("Check %s listener for pkt %p family %d",
789 net_proto2str(net_pkt_family(pkt), proto), pkt,
790 net_pkt_family(pkt));
791
792 k_mutex_lock(&conn_lock, K_FOREVER);
793
794 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
795 if (!is_iface_matching(conn, pkt)) {
796 continue; /* wrong interface */
797 }
798
799 if (conn->family != NET_AF_CAN) {
800 continue; /* wrong family */
801 }
802
803 if (conn->proto != NET_CAN_RAW) {
804 continue; /* wrong protocol */
805 }
806
807 best_match = conn;
808 }
809
810 if (best_match != NULL) {
811 cb = best_match->cb;
812 user_data = best_match->user_data;
813 }
814
815 k_mutex_unlock(&conn_lock);
816
817 if (cb != NULL) {
818 NET_DBG("[%p] match found cb %p ud %p rank 0x%02x", best_match, cb,
819 user_data, NET_CONN_RANK(best_match->flags));
820
821 if (cb(best_match, pkt, NULL, NULL, user_data) == NET_DROP) {
822 goto drop;
823 }
824
825 net_stats_update_per_proto_recv(net_pkt_iface(pkt), proto);
826
827 return NET_OK;
828 }
829
830 NET_DBG("No match found.");
831
832 drop:
833 net_stats_update_per_proto_drop(net_pkt_iface(pkt), proto);
834
835 return NET_DROP;
836 }
837 #else
net_conn_can_input(struct net_pkt * pkt,uint8_t proto)838 enum net_verdict net_conn_can_input(struct net_pkt *pkt, uint8_t proto)
839 {
840 ARG_UNUSED(pkt);
841 ARG_UNUSED(proto);
842
843 return NET_DROP;
844 }
845 #endif /* defined(CONFIG_NET_SOCKETS_CAN) */
846
net_conn_input(struct net_pkt * pkt,union net_ip_header * ip_hdr,uint8_t proto,union net_proto_header * proto_hdr)847 enum net_verdict net_conn_input(struct net_pkt *pkt,
848 union net_ip_header *ip_hdr,
849 uint8_t proto,
850 union net_proto_header *proto_hdr)
851 {
852 struct net_if *pkt_iface = net_pkt_iface(pkt);
853 uint8_t pkt_family = net_pkt_family(pkt);
854 uint16_t src_port = 0U, dst_port = 0U;
855
856 if (!net_pkt_filter_local_in_recv_ok(pkt)) {
857 /* drop the packet */
858 net_stats_update_filter_rx_local_drop(net_pkt_iface(pkt));
859 return NET_DROP;
860 }
861
862 if (pkt_family == NET_AF_INET || pkt_family == NET_AF_INET6) {
863 if (IS_ENABLED(CONFIG_NET_UDP) && proto == NET_IPPROTO_UDP) {
864 src_port = proto_hdr->udp->src_port;
865 dst_port = proto_hdr->udp->dst_port;
866 } else if (IS_ENABLED(CONFIG_NET_TCP) && proto == NET_IPPROTO_TCP) {
867 if (proto_hdr->tcp == NULL) {
868 return NET_DROP;
869 }
870 src_port = proto_hdr->tcp->src_port;
871 dst_port = proto_hdr->tcp->dst_port;
872 }
873 if (!conn_are_endpoints_valid(pkt, pkt_family, ip_hdr,
874 src_port, dst_port)) {
875 NET_DBG("Dropping invalid src/dst end-points packet");
876 return NET_DROP;
877 }
878 } else {
879 NET_DBG("No suitable protocol handler configured");
880 return NET_DROP;
881 }
882
883 NET_DBG("Check %s listener for pkt %p src port %u dst port %u"
884 " family %d", net_proto2str(net_pkt_family(pkt), proto), pkt,
885 net_ntohs(src_port), net_ntohs(dst_port), net_pkt_family(pkt));
886
887 struct net_conn *best_match = NULL;
888 int16_t best_rank = -1;
889 bool is_mcast_pkt = false;
890 bool mcast_pkt_delivered = false;
891 bool is_bcast_pkt = false;
892 struct net_conn *conn;
893 net_conn_cb_t cb = NULL;
894 void *user_data = NULL;
895
896 /* If we receive a packet with multicast destination address, we might
897 * need to deliver the packet to multiple recipients.
898 */
899 if (IS_ENABLED(CONFIG_NET_IPV4) && pkt_family == NET_AF_INET) {
900 if (net_ipv4_is_addr_mcast_raw(ip_hdr->ipv4->dst)) {
901 is_mcast_pkt = true;
902 } else if (net_if_ipv4_is_addr_bcast_raw(pkt_iface,
903 ip_hdr->ipv4->dst)) {
904 is_bcast_pkt = true;
905 }
906 } else if (IS_ENABLED(CONFIG_NET_IPV6) && pkt_family == NET_AF_INET6) {
907 is_mcast_pkt = net_ipv6_is_addr_mcast_raw(ip_hdr->ipv6->dst);
908 }
909
910 k_mutex_lock(&conn_lock, K_FOREVER);
911
912 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
913 /* Is the candidate connection matching the packet's interface? */
914 if (!is_iface_matching(conn, pkt)) {
915 continue; /* wrong interface */
916 }
917
918 /* Is the candidate connection matching the packet's protocol family? */
919 if (conn->family != NET_AF_UNSPEC && conn->family != pkt_family) {
920 if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
921 if (!(conn->family == NET_AF_INET6 && pkt_family == NET_AF_INET &&
922 !conn->v6only && conn->type != NET_SOCK_RAW)) {
923 continue;
924 }
925 } else {
926 continue; /* wrong protocol family */
927 }
928
929 /* We might have a match for v4-to-v6 mapping, check more */
930 }
931
932 /* Is the candidate connection matching the packet's protocol within the family? */
933 if (conn->proto != proto) {
934 continue; /* wrong protocol */
935 }
936
937 /* Apply protocol-specific matching criteria... */
938 uint8_t conn_family = conn->family;
939
940 if ((IS_ENABLED(CONFIG_NET_UDP) || IS_ENABLED(CONFIG_NET_TCP)) &&
941 (conn_family == NET_AF_INET || conn_family == NET_AF_INET6 ||
942 conn_family == NET_AF_UNSPEC)) {
943 /* Is the candidate connection matching the packet's TCP/UDP
944 * address and port?
945 */
946 if ((conn->flags & NET_CONN_REMOTE_PORT_SPEC) != 0 &&
947 net_sin(&conn->remote_addr)->sin_port != src_port) {
948 continue; /* wrong remote port */
949 }
950
951 if ((conn->flags & NET_CONN_LOCAL_PORT_SPEC) != 0 &&
952 net_sin(&conn->local_addr)->sin_port != dst_port) {
953 continue; /* wrong local port */
954 }
955
956 if ((conn->flags & NET_CONN_REMOTE_ADDR_SET) != 0 &&
957 !conn_addr_cmp(pkt, ip_hdr, &conn->remote_addr, true)) {
958 continue; /* wrong remote address */
959 }
960
961 if ((conn->flags & NET_CONN_LOCAL_ADDR_SET) != 0 &&
962 !conn_addr_cmp(pkt, ip_hdr, &conn->local_addr, false)) {
963
964 /* Check if we could do a v4-mapping-to-v6 and the IPv6 socket
965 * has no IPV6_V6ONLY option set and if the local IPV6 address
966 * is unspecified, then we could accept a connection from IPv4
967 * address by mapping it to IPv6 address.
968 */
969 if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
970 if (!(conn->family == NET_AF_INET6 &&
971 pkt_family == NET_AF_INET &&
972 !conn->v6only &&
973 net_ipv6_is_addr_unspecified(
974 &net_sin6(&conn->local_addr)->sin6_addr))) {
975 continue; /* wrong local address */
976 }
977 } else {
978 continue; /* wrong local address */
979 }
980
981 /* We might have a match for v4-to-v6 mapping,
982 * continue with rank checking.
983 */
984 }
985
986 if (best_rank < NET_CONN_RANK(conn->flags)) {
987 struct net_pkt *mcast_pkt;
988
989 if (!is_mcast_pkt) {
990 best_rank = NET_CONN_RANK(conn->flags);
991 best_match = conn;
992
993 continue; /* found a match - but maybe not yet the best */
994 }
995
996 /* If we have a multicast packet, and we found
997 * a match, then deliver the packet immediately
998 * to the handler. As there might be several
999 * sockets interested about these, we need to
1000 * clone the received pkt.
1001 */
1002
1003 NET_DBG("[%p] mcast match found cb %p ud %p", conn, conn->cb,
1004 conn->user_data);
1005
1006 mcast_pkt = net_pkt_clone(
1007 pkt, K_MSEC(CONFIG_NET_CONN_PACKET_CLONE_TIMEOUT));
1008 if (!mcast_pkt) {
1009 k_mutex_unlock(&conn_lock);
1010 goto drop;
1011 }
1012
1013 if (conn->cb(conn, mcast_pkt, ip_hdr, proto_hdr, conn->user_data) ==
1014 NET_DROP) {
1015 net_stats_update_per_proto_drop(pkt_iface, proto);
1016 net_pkt_unref(mcast_pkt);
1017 } else {
1018 net_stats_update_per_proto_recv(pkt_iface, proto);
1019 }
1020
1021 mcast_pkt_delivered = true;
1022 }
1023 }
1024 } /* loop end */
1025
1026 if (best_match != NULL) {
1027 cb = best_match->cb;
1028 user_data = best_match->user_data;
1029 }
1030
1031 k_mutex_unlock(&conn_lock);
1032
1033 if (is_mcast_pkt && mcast_pkt_delivered) {
1034 /* As one or more multicast packets
1035 * have already been delivered in the loop above,
1036 * we shall not call the callback again here.
1037 */
1038 net_pkt_unref(pkt);
1039 return NET_OK;
1040 }
1041
1042 if (cb != NULL) {
1043 NET_DBG("[%p] match found cb %p ud %p rank 0x%02x", best_match, cb,
1044 user_data, NET_CONN_RANK(best_match->flags));
1045
1046 if (cb(best_match, pkt, ip_hdr, proto_hdr, user_data)
1047 == NET_DROP) {
1048 goto drop;
1049 }
1050
1051 net_stats_update_per_proto_recv(pkt_iface, proto);
1052
1053 return NET_OK;
1054 }
1055
1056 NET_DBG("No match found.");
1057
1058 if ((pkt_family == NET_AF_INET || pkt_family == NET_AF_INET6) &&
1059 !(is_mcast_pkt || is_bcast_pkt)) {
1060 if (IS_ENABLED(CONFIG_NET_TCP) && proto == NET_IPPROTO_TCP &&
1061 IS_ENABLED(CONFIG_NET_TCP_REJECT_CONN_WITH_RST)) {
1062 net_tcp_reply_rst(pkt);
1063 net_stats_update_tcp_seg_connrst(pkt_iface);
1064 } else {
1065 conn_send_icmp_error(pkt);
1066 }
1067 }
1068
1069 drop:
1070 net_stats_update_per_proto_drop(pkt_iface, proto);
1071
1072 return NET_DROP;
1073 }
1074
net_conn_foreach(net_conn_foreach_cb_t cb,void * user_data)1075 void net_conn_foreach(net_conn_foreach_cb_t cb, void *user_data)
1076 {
1077 struct net_conn *conn;
1078
1079 k_mutex_lock(&conn_lock, K_FOREVER);
1080
1081 SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
1082 cb(conn, user_data);
1083 }
1084
1085 k_mutex_unlock(&conn_lock);
1086 }
1087
net_conn_init(void)1088 void net_conn_init(void)
1089 {
1090 int i;
1091
1092 sys_slist_init(&conn_unused);
1093 sys_slist_init(&conn_used);
1094
1095 for (i = 0; i < CONFIG_NET_MAX_CONN; i++) {
1096 sys_slist_prepend(&conn_unused, &conns[i].node);
1097 }
1098 }
1099