mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
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 <wengzhe@xiaomi.com>
This commit is contained in:
parent
7e7b108ef9
commit
43a8e862e0
4 changed files with 374 additions and 0 deletions
32
system/conntrack/Kconfig
Normal file
32
system/conntrack/Kconfig
Normal file
|
|
@ -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
|
||||
23
system/conntrack/Make.defs
Normal file
23
system/conntrack/Make.defs
Normal file
|
|
@ -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
|
||||
30
system/conntrack/Makefile
Normal file
30
system/conntrack/Makefile
Normal file
|
|
@ -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
|
||||
289
system/conntrack/conntrack.c
Normal file
289
system/conntrack/conntrack.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue