This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 6fd74f817db99325e618dfec96240f8c058b5744
Author: Zhe Weng <[email protected]>
AuthorDate: Wed Jan 15 16:59:22 2025 +0800

    net/pkt: Support filtering protocol in AF_PACKET
    
    Ref: https://man7.org/linux/man-pages/man7/packet.7.html
    
    1. For `socket(AF_PACKET, int socket_type, int protocol)`: When `protocol` 
is set to `htons(ETH_P_ALL)`, then all protocols are received. If `protocol` is 
set to zero, no packets are received.
    2. For `bind`: `bind` can optionally be called with a nonzero 
`sll_protocol` to start receiving packets for the protocols specified.
    
    Signed-off-by: Zhe Weng <[email protected]>
---
 Documentation/components/net/pkt.rst |  1 +
 include/netinet/if_ether.h           |  7 ++++---
 include/nuttx/net/net.h              |  2 +-
 net/pkt/pkt.h                        |  1 +
 net/pkt/pkt_conn.c                   | 11 ++++++++++-
 net/pkt/pkt_sockif.c                 | 13 ++++++++++---
 6 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/Documentation/components/net/pkt.rst 
b/Documentation/components/net/pkt.rst
index 28eb044293f..9df38f43c35 100644
--- a/Documentation/components/net/pkt.rst
+++ b/Documentation/components/net/pkt.rst
@@ -29,6 +29,7 @@ Usage
 
   addr.sll_family = AF_PACKET;
   addr.sll_ifindex = if_nametoindex("eth0");
+  addr.sll_protocol = htons(ETH_P_ALL);
   bind(sd, (FAR struct sockaddr *)&addr, sizeof(addr)); /* Bind to device */
 
   recv(sd, buffer, sizeof(buffer), 0); /* read(sd, buffer, sizeof(buffer)); */
diff --git a/include/netinet/if_ether.h b/include/netinet/if_ether.h
index de71b9c7936..01da882ab35 100644
--- a/include/netinet/if_ether.h
+++ b/include/netinet/if_ether.h
@@ -46,9 +46,10 @@
 #define ETH_MIN_MTU 68      /* Min IPv4 MTU per RFC791  */
 #define ETH_MAX_MTU 0xFFFFU /* 65535, same as IP_MAX_MTU  */
 
-#define ETH_P_ALL 0x0003    /* Every packet (be careful!!!) */
-#define ETH_P_IP  ETHERTYPE_IP
-#define ETH_P_ARP ETHERTYPE_ARP
+#define ETH_P_ALL   0x0003  /* Every packet (be careful!!!) */
+#define ETH_P_IP    ETHERTYPE_IP
+#define ETH_P_IPV6  ETHERTYPE_IPV6
+#define ETH_P_ARP   ETHERTYPE_ARP
 
 /****************************************************************************
  * Public Type Definitions
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index 28beb668658..af2af577b3e 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -247,7 +247,7 @@ struct socket
 {
   uint8_t       s_domain;    /* IP domain */
   uint8_t       s_type;      /* Protocol type */
-  uint8_t       s_proto;     /* Socket Protocol */
+  uint16_t      s_proto;     /* Socket Protocol */
   FAR void     *s_conn;      /* Connection inherits from struct socket_conn_s 
*/
 
   /* Socket interface */
diff --git a/net/pkt/pkt.h b/net/pkt/pkt.h
index 83ce4d287b8..ab866c21336 100644
--- a/net/pkt/pkt.h
+++ b/net/pkt/pkt.h
@@ -74,6 +74,7 @@ struct pkt_conn_s
 
   uint8_t    ifindex;
   uint8_t    crefs;    /* Reference counts on this instance */
+  uint16_t   type;     /* The Ethernet type of the packet */
 
   /* Read-ahead buffering.
    *
diff --git a/net/pkt/pkt_conn.c b/net/pkt/pkt_conn.c
index 91ea5bb09e9..9387cd961f5 100644
--- a/net/pkt/pkt_conn.c
+++ b/net/pkt/pkt_conn.c
@@ -32,6 +32,7 @@
 #include <debug.h>
 
 #include <arch/irq.h>
+#include <netinet/if_ether.h>
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
@@ -161,10 +162,18 @@ FAR struct pkt_conn_s *pkt_active(FAR struct net_driver_s 
*dev)
 {
   FAR struct pkt_conn_s *conn =
     (FAR struct pkt_conn_s *)g_active_pkt_connections.head;
+  uint16_t ethertype = 0;
+
+  if (dev->d_lltype == NET_LL_ETHERNET || dev->d_lltype == NET_LL_IEEE80211)
+    {
+      FAR struct eth_hdr_s *ethhdr = NETLLBUF;
+      ethertype = ethhdr->type;
+    }
 
   while (conn)
     {
-      if (dev->d_ifindex == conn->ifindex)
+      if (dev->d_ifindex == conn->ifindex &&
+          (conn->type == HTONS(ETH_P_ALL) || conn->type == ethertype))
         {
           /* Matching connection found.. return a reference to it */
 
diff --git a/net/pkt/pkt_sockif.c b/net/pkt/pkt_sockif.c
index b8fe6b369eb..be401da804f 100644
--- a/net/pkt/pkt_sockif.c
+++ b/net/pkt/pkt_sockif.c
@@ -113,6 +113,10 @@ static int pkt_sockif_alloc(FAR struct socket *psock)
   DEBUGASSERT(conn->crefs == 0);
   conn->crefs = 1;
 
+  /* Save the protocol in the connection structure */
+
+  conn->type = psock->s_proto;
+
   /* Save the pre-allocated connection in the socket structure */
 
   psock->s_conn = conn;
@@ -225,8 +229,6 @@ static void pkt_addref(FAR struct socket *psock)
 static int pkt_bind(FAR struct socket *psock,
                     FAR const struct sockaddr *addr, socklen_t addrlen)
 {
-  int ifindex;
-
   /* Verify that a valid address has been provided */
 
   if (addr->sa_family != AF_PACKET || addrlen < sizeof(struct sockaddr_ll))
@@ -245,7 +247,8 @@ static int pkt_bind(FAR struct socket *psock,
 
       /* Look at the addr and identify the network interface */
 
-      ifindex = ((FAR struct sockaddr_ll *)addr)->sll_ifindex;
+      int ifindex = ((FAR struct sockaddr_ll *)addr)->sll_ifindex;
+      int protocol = ((FAR struct sockaddr_ll *)addr)->sll_protocol;
 
       /* Check if we have that interface */
 
@@ -258,6 +261,10 @@ static int pkt_bind(FAR struct socket *psock,
       /* Put ifindex into connection */
 
       conn->ifindex = ifindex;
+      if (protocol != 0)
+        {
+          conn->type = protocol;
+        }
 
       return OK;
     }

Reply via email to