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