diff --git a/subsys/net/ip/connection.c b/subsys/net/ip/connection.c index 89e20592a6a..8f234bf2184 100644 --- a/subsys/net/ip/connection.c +++ b/subsys/net/ip/connection.c @@ -506,11 +506,10 @@ static bool conn_are_end_points_valid(struct net_pkt *pkt, } static enum net_verdict conn_raw_socket(struct net_pkt *pkt, - struct net_conn *conn) + struct net_conn *conn, uint8_t proto) { if (conn->flags & NET_CONN_LOCAL_ADDR_SET) { struct net_if *pkt_iface = net_pkt_iface(pkt); - uint8_t proto = ETH_P_ALL; struct sockaddr_ll *local; struct net_pkt *raw_pkt; @@ -527,6 +526,7 @@ static enum net_verdict conn_raw_socket(struct net_pkt *pkt, raw_pkt = net_pkt_clone(pkt, CLONE_TIMEOUT); if (!raw_pkt) { net_stats_update_per_proto_drop(pkt_iface, proto); + NET_WARN("pkt cloning failed, pkt %p dropped", pkt); return NET_DROP; } @@ -574,7 +574,7 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) { if (net_pkt_family(pkt) != AF_PACKET || (!IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) && - proto != ETH_P_ALL)) { + proto != ETH_P_ALL && proto != IPPROTO_RAW)) { return NET_DROP; } @@ -622,13 +622,14 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, } SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) { - /* For packet socket data, the proto is set to ETH_P_ALL but - * the listener might have a specific protocol set. This is ok + /* For packet socket data, the proto is set to ETH_P_ALL or IPPROTO_RAW + * but the listener might have a specific protocol set. This is ok * and let the packet pass this check in this case. */ if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) || IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) { - if ((conn->proto != proto) && (proto != ETH_P_ALL)) { + if ((conn->proto != proto) && (proto != ETH_P_ALL) && + (proto != IPPROTO_RAW)) { continue; } } else { @@ -662,14 +663,23 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, */ if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && conn->family == AF_PACKET) { - ret = conn_raw_socket(pkt, conn); - if (ret == NET_DROP) { - goto drop; - } else if (ret == NET_OK) { - raw_pkt_delivered = true; + if (proto == ETH_P_ALL) { + /* We shall continue with ETH_P_ALL to IPPROTO_RAW: */ + raw_pkt_continue = true; } - continue; + /* With IPPROTO_RAW deliver only if protocol match: */ + if ((proto == ETH_P_ALL && conn->proto != IPPROTO_RAW) || + conn->proto == proto) { + ret = conn_raw_socket(pkt, conn, proto); + if (ret == NET_DROP) { + goto drop; + } else if (ret == NET_OK) { + raw_pkt_delivered = true; + } + + continue; + } } if (IS_ENABLED(CONFIG_NET_UDP) || @@ -757,7 +767,8 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, } } - if ((is_mcast_pkt && mcast_pkt_delivered) || raw_pkt_delivered) { + if ((is_mcast_pkt && mcast_pkt_delivered) || raw_pkt_delivered || + raw_pkt_continue) { if (raw_pkt_continue) { /* When there is open connection different than * AF_PACKET this packet shall be also handled in diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 414e3cd4ef3..c90f923dbe2 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -1740,7 +1740,12 @@ static int context_sendto(struct net_context *context, net_pkt_cursor_init(pkt); - net_if_queue_tx(net_pkt_iface(pkt), pkt); + if (net_context_get_ip_proto(context) == IPPROTO_RAW) { + /* Pass to L2: */ + ret = net_send_data(pkt); + } else { + net_if_queue_tx(net_pkt_iface(pkt), pkt); + } } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && net_context_get_family(context) == AF_CAN && net_context_get_ip_proto(context) == CAN_RAW) { diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c index ccfb2d4fddd..1836b60d7fc 100644 --- a/subsys/net/ip/net_core.c +++ b/subsys/net/ip/net_core.c @@ -28,6 +28,7 @@ LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL); #include #include #include +#include #if defined(CONFIG_NET_LLDP) #include @@ -61,7 +62,7 @@ static inline enum net_verdict process_data(struct net_pkt *pkt, int ret; bool locally_routed = false; - ret = net_packet_socket_input(pkt); + ret = net_packet_socket_input(pkt, ETH_P_ALL); if (ret != NET_CONTINUE) { return ret; } @@ -97,6 +98,12 @@ static inline enum net_verdict process_data(struct net_pkt *pkt, } } + /* L2 processed, now we can pass IPPROTO_RAW to packet socket: */ + ret = net_packet_socket_input(pkt, IPPROTO_RAW); + if (ret != NET_CONTINUE) { + return ret; + } + ret = net_canbus_socket_input(pkt); if (ret != NET_CONTINUE) { return ret; diff --git a/subsys/net/ip/packet_socket.c b/subsys/net/ip/packet_socket.c index 4ae3ede3bb7..d537791b4a3 100644 --- a/subsys/net/ip/packet_socket.c +++ b/subsys/net/ip/packet_socket.c @@ -20,7 +20,7 @@ LOG_MODULE_REGISTER(net_sockets_raw, CONFIG_NET_SOCKETS_LOG_LEVEL); #include "connection.h" #include "packet_socket.h" -enum net_verdict net_packet_socket_input(struct net_pkt *pkt) +enum net_verdict net_packet_socket_input(struct net_pkt *pkt, uint8_t proto) { #if IS_ENABLED(CONFIG_NET_DSA) /* @@ -48,5 +48,5 @@ enum net_verdict net_packet_socket_input(struct net_pkt *pkt) net_pkt_set_family(pkt, AF_PACKET); - return net_conn_input(pkt, NULL, ETH_P_ALL, NULL); + return net_conn_input(pkt, NULL, proto, NULL); } diff --git a/subsys/net/ip/packet_socket.h b/subsys/net/ip/packet_socket.h index 60ca86d4997..1d853e157ff 100644 --- a/subsys/net/ip/packet_socket.h +++ b/subsys/net/ip/packet_socket.h @@ -26,9 +26,10 @@ * disabled, the function will always return NET_DROP. */ #if defined(CONFIG_NET_SOCKETS_PACKET) -enum net_verdict net_packet_socket_input(struct net_pkt *pkt); +enum net_verdict net_packet_socket_input(struct net_pkt *pkt, uint8_t proto); #else -static inline enum net_verdict net_packet_socket_input(struct net_pkt *pkt) +static inline enum net_verdict net_packet_socket_input(struct net_pkt *pkt, + uint8_t proto) { return NET_CONTINUE; } diff --git a/subsys/net/lib/sockets/CMakeLists.txt b/subsys/net/lib/sockets/CMakeLists.txt index 076b3f56209..0403212c1e0 100644 --- a/subsys/net/lib/sockets/CMakeLists.txt +++ b/subsys/net/lib/sockets/CMakeLists.txt @@ -13,9 +13,10 @@ zephyr_sources( getnameinfo.c sockets_misc.c ) -zephyr_sources_ifdef(CONFIG_NET_SOCKETS_PACKET sockets_packet.c) + zephyr_sources_ifdef(CONFIG_NET_SOCKETS_CAN sockets_can.c) endif() +zephyr_sources_ifdef(CONFIG_NET_SOCKETS_PACKET sockets_packet.c) zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD socket_offload.c) if (CONFIG_NET_SOCKETS_SOCKOPT_TLS AND NOT CONFIG_NET_SOCKETS_OFFLOAD_TLS) diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 10f1f6e5f96..59d5d00ba5c 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -149,7 +149,6 @@ config NET_SOCKETS_OFFLOAD_TLS config NET_SOCKETS_PACKET bool "Enable packet socket support" - depends on NET_L2_ETHERNET help This is an initial version of packet socket support (special type raw socket). Packets are passed to and from the device driver diff --git a/subsys/net/lib/sockets/sockets_packet.c b/subsys/net/lib/sockets/sockets_packet.c index 044db85ae60..3e2099085a4 100644 --- a/subsys/net/lib/sockets/sockets_packet.c +++ b/subsys/net/lib/sockets/sockets_packet.c @@ -386,6 +386,7 @@ static const struct socket_op_vtable packet_sock_fd_op_vtable = { static bool packet_is_supported(int family, int type, int proto) { if (((type == SOCK_RAW) && (proto == ETH_P_ALL)) || + ((type == SOCK_RAW) && (proto == IPPROTO_RAW)) || ((type == SOCK_DGRAM) && (proto > 0))) { return true; }