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-apps.git

commit 43a8e862e0d55b4cc0b5bd71535016a9fd6b76a1
Author: Zhe Weng <[email protected]>
AuthorDate: Thu Mar 21 21:11:52 2024 +0800

    apps/system: Add conntrack command
    
    A simple tool like Linux's 'conntrack', only supports printing NAT 
connections now.
    
    nuttx> conntrack -E
        [NEW] icmp  src=192.168.21.66 dst=1.2.3.4 type=8 code=0 id=26739 
src=1.2.3.4 dst=192.168.11.1 type=0 code=0 id=26739
        [NEW] tcp   src=192.168.21.66 dst=1.2.3.4 sport=38446 dport=80 
src=1.2.3.4 dst=192.168.11.1 sport=80 dport=38446
    [DESTROY] icmp  src=192.168.21.66 dst=1.2.3.4 type=8 code=0 id=26739 
src=1.2.3.4 dst=192.168.11.1 type=0 code=0 id=26739
    
    nuttx> conntrack -L
    tcp   src=192.168.21.66 dst=1.2.3.4 sport=38446 dport=80 src=1.2.3.4 
dst=192.168.11.1 sport=80 dport=38446
    icmp  src=192.168.21.66 dst=1.2.3.4 type=8 code=0 id=26739 src=1.2.3.4 
dst=192.168.11.1 type=0 code=0 id=26739
    conntrack: 2 flow entries have been shown.
    
    Signed-off-by: Zhe Weng <[email protected]>
---
 system/conntrack/Kconfig     |  32 +++++
 system/conntrack/Make.defs   |  23 ++++
 system/conntrack/Makefile    |  30 +++++
 system/conntrack/conntrack.c | 289 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 374 insertions(+)

diff --git a/system/conntrack/Kconfig b/system/conntrack/Kconfig
new file mode 100644
index 000000000..7c1a8ace3
--- /dev/null
+++ b/system/conntrack/Kconfig
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config SYSTEM_CONNTRACK
+       tristate "conntrack command"
+       default n
+       depends on NETLINK_NETFILTER
+       select SYSTEM_ARGTABLE3
+       ---help---
+               Enable support for the 'conntrack' command, a simple tool like
+               Linux's 'conntrack', only supports printing NAT connections now.
+
+if SYSTEM_CONNTRACK
+
+config SYSTEM_CONNTRACK_PROGNAME
+       string "conntrack program name"
+       default "conntrack"
+       ---help---
+               This is the name of the program that will be used when the NSH 
ELF
+               program is installed.
+
+config SYSTEM_CONNTRACK_PRIORITY
+       int "conntrack task priority"
+       default 100
+
+config SYSTEM_CONNTRACK_STACKSIZE
+       int "conntrack stack size"
+       default DEFAULT_TASK_STACKSIZE
+
+endif
diff --git a/system/conntrack/Make.defs b/system/conntrack/Make.defs
new file mode 100644
index 000000000..9c746c6ad
--- /dev/null
+++ b/system/conntrack/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/system/conntrack/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_SYSTEM_CONNTRACK),)
+CONFIGURED_APPS += $(APPDIR)/system/conntrack
+endif
diff --git a/system/conntrack/Makefile b/system/conntrack/Makefile
new file mode 100644
index 000000000..31efea8e0
--- /dev/null
+++ b/system/conntrack/Makefile
@@ -0,0 +1,30 @@
+############################################################################
+# apps/system/conntrack/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+PROGNAME = $(CONFIG_SYSTEM_CONNTRACK_PROGNAME)
+PRIORITY = $(CONFIG_SYSTEM_CONNTRACK_PRIORITY)
+STACKSIZE = $(CONFIG_SYSTEM_CONNTRACK_STACKSIZE)
+MODULE = $(CONFIG_SYSTEM_CONNTRACK)
+
+MAINSRC = conntrack.c
+
+include $(APPDIR)/Application.mk
diff --git a/system/conntrack/conntrack.c b/system/conntrack/conntrack.c
new file mode 100644
index 000000000..c58784b0d
--- /dev/null
+++ b/system/conntrack/conntrack.c
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * apps/system/conntrack/conntrack.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <netpacket/netlink.h>
+
+#include <nuttx/net/ip.h>
+
+#include "argtable3.h"
+#include "netutils/netlib.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RXBUFFER_SIZE 256
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct conntrack_args_s
+{
+  FAR struct arg_lit *dump;
+  FAR struct arg_lit *event;
+  FAR struct arg_str *family;
+  FAR struct arg_end *end;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static volatile bool g_exiting;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sigexit
+ ****************************************************************************/
+
+static void sigexit(int signo)
+{
+  g_exiting = true;
+}
+
+/****************************************************************************
+ * Name: proto2str
+ ****************************************************************************/
+
+static FAR const char *proto2str(uint8_t proto)
+{
+  switch (proto)
+    {
+      case IPPROTO_TCP:
+        return "tcp";
+      case IPPROTO_UDP:
+        return "udp";
+      case IPPROTO_ICMP:
+        return "icmp";
+      case IPPROTO_ICMP6:
+        return "icmp6";
+      default:
+        return "";
+    }
+}
+
+/****************************************************************************
+ * Name: conntrack_print_tuple
+ ****************************************************************************/
+
+static void conntrack_print_tuple(sa_family_t family,
+                            FAR const struct netlib_conntrack_tuple_s *tuple)
+{
+  char ipstrbuf[INET6_ADDRSTRLEN];
+
+  /* src=10.88.0.88 dst=192.168.66.66 sport=45065 dport=5001 */
+
+  inet_ntop(family, &tuple->src, ipstrbuf, INET6_ADDRSTRLEN);
+  printf("src=%s ", ipstrbuf);
+  inet_ntop(family, &tuple->dst, ipstrbuf, INET6_ADDRSTRLEN);
+  printf("dst=%s ", ipstrbuf);
+
+  switch (tuple->l4proto)
+    {
+      case IPPROTO_TCP:
+      case IPPROTO_UDP:
+        printf("sport=%" PRIu16 " dport=%" PRIu16 " ",
+               tuple->l4.tcp.sport, tuple->l4.tcp.dport);
+        break;
+      case IPPROTO_ICMP:
+      case IPPROTO_ICMP6:
+        printf("type=%" PRIu8 " code=%" PRIu8 " id=%" PRIu16 " ",
+               tuple->l4.icmp.type, tuple->l4.icmp.code, tuple->l4.icmp.id);
+        break;
+    }
+}
+
+/****************************************************************************
+ * Name: conntrack_print
+ ****************************************************************************/
+
+static int conntrack_print(FAR struct netlib_conntrack_s *ct)
+{
+  /* tcp  <orig> <reply> */
+
+  printf("%-5s ", proto2str(ct->orig.l4proto));
+  conntrack_print_tuple(ct->family, &ct->orig);
+  conntrack_print_tuple(ct->family, &ct->reply);
+  printf("\n");
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: conntrack_dump
+ ****************************************************************************/
+
+static void conntrack_dump(sa_family_t family)
+{
+  ssize_t ndumped = netlib_get_conntrack(family, conntrack_print);
+  printf("conntrack: %zd flow entries have been shown.\n", ndumped);
+}
+
+/****************************************************************************
+ * Name: conntrack_monitor_socket
+ ****************************************************************************/
+
+static int conntrack_monitor_socket(uint32_t groups)
+{
+  struct sockaddr_nl addr;
+  int fd;
+
+  /* Create a NetLink socket with NETLINK_NETFILTER protocol */
+
+  fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+  if (fd < 0)
+    {
+      perror("ERROR: failed to create netlink socket");
+      return -errno;
+    }
+
+  addr.nl_family = AF_NETLINK;
+  addr.nl_pad    = 0;
+  addr.nl_pid    = getpid();
+  addr.nl_groups = groups;
+
+  if (bind(fd, (FAR const struct sockaddr *)&addr, sizeof(addr)) < 0)
+    {
+      perror("ERROR: failed to bind netlink socket");
+      close(fd);
+      return -errno;
+    }
+
+  return fd;
+}
+
+/****************************************************************************
+ * Name: conntrack_monitor_event
+ ****************************************************************************/
+
+static void conntrack_monitor_event(void)
+{
+  FAR const struct nlmsghdr *nlh;
+  struct netlib_conntrack_s ct;
+  uint8_t buf[RXBUFFER_SIZE];
+  ssize_t len;
+  int fd;
+
+  /* Setup exit signal handler */
+
+  g_exiting = false;
+  signal(SIGINT, sigexit);
+
+  /* Create a NetLink socket with NETLINK_NETFILTER protocol */
+
+  fd = conntrack_monitor_socket(NF_NETLINK_CONNTRACK_NEW |
+                                NF_NETLINK_CONNTRACK_DESTROY);
+  if (fd < 0)
+    {
+      return;
+    }
+
+  while ((len = read(fd, buf, sizeof(buf))) >= 0 && !g_exiting)
+    {
+      nlh = (FAR struct nlmsghdr *)buf;
+
+      if (netlib_parse_conntrack(nlh, len, &ct) < 0)
+        {
+          fprintf(stderr, "Failed to parse conntrack message\n");
+          continue;
+        }
+
+      /* Only event log needs to print type prefix */
+
+      switch (ct.type)
+        {
+          case IPCTNL_MSG_CT_NEW:
+            printf("    [NEW] ");
+            break;
+
+          case IPCTNL_MSG_CT_DELETE:
+            printf("[DESTROY] ");
+            break;
+
+          default:
+            printf("[UNKNOWN] ");
+            break;
+        }
+
+      /* Print the remaining line */
+
+      conntrack_print(&ct);
+    }
+
+  close(fd);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  struct conntrack_args_s args;
+  sa_family_t family = AF_INET;
+  int nerrors;
+
+  args.dump   = arg_lit0("L", "dump", "List connection tracking");
+  args.event  = arg_lit0("E", "event", "Display a real-time event log");
+  args.family = arg_str0("f", "family", "PROTO", "Specify L3 (ipv4, ipv6) "
+                         "protocol, only for dump option (default ipv4)");
+  args.end    = arg_end(3);
+
+  nerrors = arg_parse(argc, argv, (FAR void **)&args);
+  if (nerrors != 0 || args.dump->count + args.event->count == 0)
+    {
+      arg_print_errors(stdout, args.end, argv[0]);
+      printf("Usage:\n");
+      arg_print_glossary(stdout, (FAR void **)&args, NULL);
+      goto out;
+    }
+
+  if (args.family->count != 0)
+    {
+      if (strncmp(args.family->sval[0], "ipv6", 4) == 0)
+        {
+          family = AF_INET6;
+        }
+    }
+
+  if (args.dump->count != 0)
+    {
+      conntrack_dump(family);
+    }
+
+  if (args.event->count != 0)
+    {
+      conntrack_monitor_event();
+    }
+
+out:
+  arg_freetable((FAR void **)&args, 1);
+  return 0;
+}

Reply via email to