mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Add support for Device.IP.ActivePort. in libbbfdm
This commit is contained in:
parent
ffbe8792ad
commit
c22f9997aa
6 changed files with 162 additions and 268 deletions
|
|
@ -6,22 +6,3 @@ add_subdirectory(libbbfdm-api)
|
||||||
add_subdirectory(libbbfdm)
|
add_subdirectory(libbbfdm)
|
||||||
add_subdirectory(bbfdmd)
|
add_subdirectory(bbfdmd)
|
||||||
|
|
||||||
# Capture the environment variables
|
|
||||||
set(MY_CC "$ENV{CC}")
|
|
||||||
set(MY_CFLAGS "$ENV{CFLAGS}")
|
|
||||||
set(MY_LDFLAGS "$ENV{LDFLAGS}")
|
|
||||||
|
|
||||||
# Define a custom target to build the utilities using Makefile
|
|
||||||
add_custom_target(
|
|
||||||
build_utilities
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E env
|
|
||||||
CC=${MY_CC}
|
|
||||||
CFLAGS=${MY_CFLAGS}
|
|
||||||
LDFLAGS=${MY_LDFLAGS}
|
|
||||||
make
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/utilities
|
|
||||||
)
|
|
||||||
|
|
||||||
# Make bbfdmd target depend on the build_utilities target
|
|
||||||
add_dependencies(bbfdmd build_utilities)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 iopsys Software Solutions AB
|
* Copyright (C) 2020-2024 iopsys Software Solutions AB
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License version 2.1
|
* it under the terms of the GNU Lesser General Public License version 2.1
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Author: Anis Ellouze <anis.ellouze@pivasoftware.com>
|
* Author: Anis Ellouze <anis.ellouze@pivasoftware.com>
|
||||||
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
|
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
|
||||||
|
* Author: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -23,6 +24,16 @@ struct intf_ip_args
|
||||||
bool is_main_sec;
|
bool is_main_sec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define STATUS_SIZE 16
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char local_ip[INET6_ADDRSTRLEN];
|
||||||
|
uint16_t local_port;
|
||||||
|
char remote_ip[INET6_ADDRSTRLEN];
|
||||||
|
uint16_t remote_port;
|
||||||
|
unsigned int state;
|
||||||
|
} ActivePort;
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* INIT
|
* INIT
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
|
@ -38,6 +49,82 @@ static int init_interface_ip_args(struct intf_ip_args *args, struct uci_section
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* COMMON Functions
|
* COMMON Functions
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
static void format_ipv6_address(const char *hex_str_ip, char *ipv6_addr)
|
||||||
|
{
|
||||||
|
struct in6_addr addr = {};
|
||||||
|
|
||||||
|
sscanf(hex_str_ip, "%08X%08X%08X%08X",
|
||||||
|
&addr.s6_addr32[0], &addr.s6_addr32[1],
|
||||||
|
&addr.s6_addr32[2], &addr.s6_addr32[3]);
|
||||||
|
|
||||||
|
// Convert the address to the standard IPv6 format
|
||||||
|
inet_ntop(AF_INET6, &addr, ipv6_addr, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_tcp_line(const char* line, int is_ipv6, ActivePort* port)
|
||||||
|
{
|
||||||
|
unsigned int local_port, remote_port;
|
||||||
|
unsigned int state;
|
||||||
|
char local_ip[INET6_ADDRSTRLEN] = {0};
|
||||||
|
char remote_ip[INET6_ADDRSTRLEN] = {0};
|
||||||
|
|
||||||
|
if (is_ipv6) {
|
||||||
|
char local_ip6[33] = {0}, remote_ip6[33] = {0};
|
||||||
|
sscanf(line, "%*d: %32s:%4X %32s:%4X %2X", local_ip6, &local_port, remote_ip6, &remote_port, &state);
|
||||||
|
format_ipv6_address(local_ip6, local_ip);
|
||||||
|
format_ipv6_address(remote_ip6, remote_ip);
|
||||||
|
} else {
|
||||||
|
unsigned int local_ip_num, remote_ip_num;
|
||||||
|
sscanf(line, "%*d: %8X:%4X %8X:%4X %2X", &local_ip_num, &local_port, &remote_ip_num, &remote_port, &state);
|
||||||
|
|
||||||
|
struct in_addr local_addr = { local_ip_num };
|
||||||
|
struct in_addr remote_addr = { remote_ip_num };
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &local_addr, local_ip, INET_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET, &remote_addr, remote_ip, INET_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
DM_STRNCPY(port->local_ip, local_ip, INET6_ADDRSTRLEN);
|
||||||
|
port->local_port = local_port;
|
||||||
|
DM_STRNCPY(port->remote_ip, remote_ip, INET6_ADDRSTRLEN);
|
||||||
|
port->remote_port = remote_port;
|
||||||
|
port->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void browse_ip_port(struct dmctx *dmctx, DMNODE *parent_node, bool is_ipv6, const char *proc_path, int *id, char *inst)
|
||||||
|
{
|
||||||
|
if (proc_path == NULL || DM_STRLEN(proc_path) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FILE* fp = fopen(proc_path, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[256] = {0};
|
||||||
|
fgets(line, sizeof(line), fp); // Skip header line
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), fp)) {
|
||||||
|
struct dm_data curr_data = {0};
|
||||||
|
|
||||||
|
ActivePort port;
|
||||||
|
memset(&port, 0, sizeof(port));
|
||||||
|
parse_tcp_line(line, is_ipv6, &port);
|
||||||
|
|
||||||
|
// only display LISTEN or ESTABLISHED
|
||||||
|
if (port.state != 1 && port.state != 10)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
curr_data.additional_data = (void *)(&port);
|
||||||
|
inst = handle_instance_without_section(dmctx, parent_node, ++(*id));
|
||||||
|
|
||||||
|
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_data, inst) == DM_STOP)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
static int get_sysctl_disable_ipv6_per_device(const char *device, char **value)
|
static int get_sysctl_disable_ipv6_per_device(const char *device, char **value)
|
||||||
{
|
{
|
||||||
char file[256];
|
char file[256];
|
||||||
|
|
@ -808,6 +895,17 @@ end:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int browseIPActivePortInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||||
|
{
|
||||||
|
char *inst = NULL;
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
browse_ip_port(dmctx, parent_node, 0, "/proc/net/tcp", &id, inst);
|
||||||
|
browse_ip_port(dmctx, parent_node, 1, "/proc/net/tcp6", &id, inst);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* ADD & DEL OBJ
|
* ADD & DEL OBJ
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
|
@ -1088,6 +1186,13 @@ static int get_IP_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, vo
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_IP_ActivePortNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
int cnt = get_number_of_entries(ctx, data, instance, browseIPActivePortInst);
|
||||||
|
dmasprintf(value, "%d", cnt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*#Device.IP.Interface.{i}.Enable!UCI:network/interface,@i-1/disabled*/
|
/*#Device.IP.Interface.{i}.Enable!UCI:network/interface,@i-1/disabled*/
|
||||||
static int get_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
static int get_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
{
|
{
|
||||||
|
|
@ -2180,6 +2285,48 @@ static int operate_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *da
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_IP_ActivePort_LocalIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
*value = dmstrdup(((ActivePort *)((struct dm_data *)data)->additional_data)->local_ip);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_IP_ActivePort_LocalPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
dmasprintf(value, "%u", ((ActivePort *)((struct dm_data *)data)->additional_data)->local_port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_IP_ActivePort_RemoteIPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
*value = dmstrdup(((ActivePort *)((struct dm_data *)data)->additional_data)->remote_ip);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_IP_ActivePort_RemotePort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
dmasprintf(value, "%u", ((ActivePort *)((struct dm_data *)data)->additional_data)->remote_port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_IP_ActivePort_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
unsigned int state = (((ActivePort *)((struct dm_data *)data)->additional_data)->state);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case 1:
|
||||||
|
*value = "ESTABLISHED";
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
*value = "LISTEN";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*value = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/**********************************************************************************************************************************
|
/**********************************************************************************************************************************
|
||||||
* OBJ & PARAM DEFINITION
|
* OBJ & PARAM DEFINITION
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
|
@ -2187,6 +2334,7 @@ static int operate_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *da
|
||||||
DMOBJ tIPObj[] = {
|
DMOBJ tIPObj[] = {
|
||||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
|
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
|
||||||
{"Interface", &DMWRITE, addObjIPInterface, delObjIPInterface, NULL, browseIPInterfaceInst, NULL, NULL, tIPInterfaceObj, tIPInterfaceParams, NULL, BBFDM_BOTH, NULL},
|
{"Interface", &DMWRITE, addObjIPInterface, delObjIPInterface, NULL, browseIPInterfaceInst, NULL, NULL, tIPInterfaceObj, tIPInterfaceParams, NULL, BBFDM_BOTH, NULL},
|
||||||
|
{"ActivePort", &DMREAD, NULL, NULL, NULL, browseIPActivePortInst, NULL, NULL, NULL, tIPActivePortParams, NULL, BBFDM_BOTH, NULL},
|
||||||
#if defined(BBF_TR143) || defined(BBF_TR471)
|
#if defined(BBF_TR143) || defined(BBF_TR471)
|
||||||
{"Diagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsObj, tIPDiagnosticsParams, NULL, BBFDM_BOTH, NULL},
|
{"Diagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPDiagnosticsObj, tIPDiagnosticsParams, NULL, BBFDM_BOTH, NULL},
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2203,6 +2351,7 @@ DMLEAF tIPParams[] = {
|
||||||
{"IPv6Status", &DMREAD, DMT_STRING, get_IP_IPv6Status, NULL, BBFDM_BOTH},
|
{"IPv6Status", &DMREAD, DMT_STRING, get_IP_IPv6Status, NULL, BBFDM_BOTH},
|
||||||
{"ULAPrefix", &DMWRITE, DMT_STRING, get_IP_ULAPrefix, set_IP_ULAPrefix, BBFDM_BOTH},
|
{"ULAPrefix", &DMWRITE, DMT_STRING, get_IP_ULAPrefix, set_IP_ULAPrefix, BBFDM_BOTH},
|
||||||
{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_IP_InterfaceNumberOfEntries, NULL, BBFDM_BOTH},
|
{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_IP_InterfaceNumberOfEntries, NULL, BBFDM_BOTH},
|
||||||
|
{"ActivePortNumberOfEntries", &DMREAD, DMT_UNINT, get_IP_ActivePortNumberOfEntries, NULL, BBFDM_BOTH},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2307,3 +2456,14 @@ DMLEAF tIPInterfaceStatsParams[] = {
|
||||||
//{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_IPInterfaceStats_UnknownProtoPacketsReceived, NULL, BBFDM_BOTH},
|
//{"UnknownProtoPacketsReceived", &DMREAD, DMT_UNINT, get_IPInterfaceStats_UnknownProtoPacketsReceived, NULL, BBFDM_BOTH},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* *** Device.IP.ActivePort.{i}. *** */
|
||||||
|
DMLEAF tIPActivePortParams[] = {
|
||||||
|
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
|
||||||
|
{"LocalIPAddress", &DMREAD, DMT_STRING, get_IP_ActivePort_LocalIPAddress, NULL, BBFDM_BOTH},
|
||||||
|
{"LocalPort", &DMREAD, DMT_UNINT, get_IP_ActivePort_LocalPort, NULL, BBFDM_BOTH},
|
||||||
|
{"RemoteIPAddress", &DMREAD, DMT_STRING, get_IP_ActivePort_RemoteIPAddress, NULL, BBFDM_BOTH},
|
||||||
|
{"RemotePort", &DMREAD, DMT_UNINT, get_IP_ActivePort_RemotePort, NULL, BBFDM_BOTH},
|
||||||
|
{"Status", &DMREAD, DMT_STRING, get_IP_ActivePort_Status, NULL, BBFDM_BOTH},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ extern DMLEAF tIPInterfaceIPv4AddressParams[];
|
||||||
extern DMLEAF tIPInterfaceIPv6AddressParams[];
|
extern DMLEAF tIPInterfaceIPv6AddressParams[];
|
||||||
extern DMLEAF tIPInterfaceIPv6PrefixParams[];
|
extern DMLEAF tIPInterfaceIPv6PrefixParams[];
|
||||||
extern DMLEAF tIPInterfaceStatsParams[];
|
extern DMLEAF tIPInterfaceStatsParams[];
|
||||||
|
extern DMLEAF tIPActivePortParams[];
|
||||||
|
|
||||||
#endif //__IP_H
|
#endif //__IP_H
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
CC ?= gcc
|
|
||||||
ACTIVE-PORT = active-port
|
|
||||||
ACTIVE-PORT_OBJS = src/ubus/active-port.o
|
|
||||||
|
|
||||||
PROG_CFLAGS = $(CFLAGS) -Wall -Werror
|
|
||||||
PROG_LDFLAGS = $(LDFLAGS)
|
|
||||||
PROG_LIBS += -luci -lubus -lubox -lblobmsg_json
|
|
||||||
|
|
||||||
INSTALL_DIR = /usr/sbin
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
|
|
||||||
|
|
||||||
.PHONY: all clean install
|
|
||||||
|
|
||||||
all: $(ACTIVE-PORT)
|
|
||||||
|
|
||||||
$(ACTIVE-PORT): $(ACTIVE-PORT_OBJS)
|
|
||||||
$(CC) $(PROG_LDFLAGS) -o $@ $^ $(PROG_LIBS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(ACTIVE-PORT)
|
|
||||||
|
|
||||||
install: $(ACTIVE-PORT)
|
|
||||||
install -m 0755 $(ACTIVE-PORT) $(INSTALL_DIR)
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
# Utilities to support datamodel deployments
|
|
||||||
|
|
||||||
## active-port
|
|
||||||
|
|
||||||
This directory has active-port utility which implements active-port ubus object. This object contains one function: dump, which dumps information of all active tcp ports.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
root@sh31b-f04dd44304e0:~# ubus call active-port dump
|
|
||||||
{
|
|
||||||
"connections": [
|
|
||||||
{
|
|
||||||
"local_ip": "127.0.0.1",
|
|
||||||
"local_port": "5038",
|
|
||||||
"remote_ip": "0.0.0.0",
|
|
||||||
"remote_port": "*",
|
|
||||||
"status": "LISTEN"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"local_ip": "0.0.0.0",
|
|
||||||
"local_port": "8080",
|
|
||||||
"remote_ip": "0.0.0.0",
|
|
||||||
"remote_port": "*",
|
|
||||||
"status": "LISTEN"
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
This ubus call is used by Device.IP.ActivePort datamodel object.
|
|
||||||
|
|
@ -1,191 +0,0 @@
|
||||||
/*
|
|
||||||
* active_port.c: active-port daemon that provides active-port ubus object
|
|
||||||
* and a dump method which read from netstat output and
|
|
||||||
* returns local and remote IP and port and connections state.
|
|
||||||
* This is done for Device.IP.ActivePort object, whose json
|
|
||||||
* maps to this ubus call.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2024 IOPSYS Software Solutions AB. All rights reserved.
|
|
||||||
*
|
|
||||||
* Author: Mohd Husaam Mehdi <husaam.mehdi@genexis.eu>
|
|
||||||
*
|
|
||||||
* See LICENSE file for license related information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <libubox/blobmsg.h>
|
|
||||||
#include <libubox/uloop.h>
|
|
||||||
#include <libubus.h>
|
|
||||||
|
|
||||||
#define MAX_LINE_LEN 256
|
|
||||||
|
|
||||||
static int parse_ip_port(char *str, char **ip, char **port)
|
|
||||||
{
|
|
||||||
char *colon = NULL;
|
|
||||||
|
|
||||||
// get the last colon in string
|
|
||||||
colon = strrchr(str, ':');
|
|
||||||
if (!colon) {
|
|
||||||
syslog(LOG_ERR, "active-port(%s,%u): ERROR (ip port not separated by ':')\n", __func__, __LINE__);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*colon = '\0';
|
|
||||||
*ip = str;
|
|
||||||
*port = colon + 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct blobmsg_policy active_port_policy[] = {};
|
|
||||||
|
|
||||||
static int parse_line(char *line, struct blob_buf *b)
|
|
||||||
{
|
|
||||||
char *local_ip = NULL;
|
|
||||||
char *local_port = NULL;
|
|
||||||
char *remote_ip = NULL;
|
|
||||||
char *remote_port = NULL;
|
|
||||||
bool established = false;
|
|
||||||
|
|
||||||
char *token = NULL, *end = NULL;
|
|
||||||
// split the columns
|
|
||||||
token = strtok_r(line, " ", &end);
|
|
||||||
int i = 0;
|
|
||||||
while (token != NULL) {
|
|
||||||
switch (i) {
|
|
||||||
// first column
|
|
||||||
case 0:
|
|
||||||
if (parse_ip_port(token, &local_ip, &local_port) != 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
// second column
|
|
||||||
case 1:
|
|
||||||
|
|
||||||
if (parse_ip_port(token, &remote_ip, &remote_port) != 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// if established is found strncmp would be 0 and established would be 1
|
|
||||||
established = !strncmp(token, "ESTABLISHED", strlen("ESTABLISHED"));
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
syslog(LOG_ERR, "active-port(%s,%u): ERROR (extra column in netstat)\n", __func__, __LINE__);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
token = strtok_r(NULL, " ", &end);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!local_ip || !local_port || !remote_ip || !remote_port) {
|
|
||||||
syslog(LOG_ERR, "active-port(%s,%u): ERROR (missing data in netstat)\n", __func__, __LINE__);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *dd = NULL;
|
|
||||||
|
|
||||||
dd = blobmsg_open_table(b, "");
|
|
||||||
|
|
||||||
blobmsg_add_string(b, "local_ip", local_ip);
|
|
||||||
blobmsg_add_string(b, "local_port", local_port);
|
|
||||||
blobmsg_add_string(b, "remote_ip", remote_ip);
|
|
||||||
blobmsg_add_string(b, "remote_port", remote_port);
|
|
||||||
blobmsg_add_string(b, "status", established ? "ESTABLISHED" : "LISTEN");
|
|
||||||
|
|
||||||
blobmsg_close_table(b, dd);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int active_port_dump_handler(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)),
|
|
||||||
struct ubus_request_data *req, const char *method __attribute__((unused)),
|
|
||||||
struct blob_attr *msg)
|
|
||||||
{
|
|
||||||
struct blob_buf b = {0};
|
|
||||||
|
|
||||||
memset(&b, 0, sizeof(struct blob_buf));
|
|
||||||
blob_buf_init(&b, 0);
|
|
||||||
|
|
||||||
FILE *pp = NULL;
|
|
||||||
char cmd[64] = {0};
|
|
||||||
// get the output of netstat (do not resolve ip addresses, get tcp connections, all kinds of states)
|
|
||||||
// skip the first two rows(headers) and print the 4th, 5th and 6th column separated by single space
|
|
||||||
snprintf(cmd, sizeof(cmd), "netstat -nta 2>/dev/null | awk \'NR>2 {print $4, $5, $6}\'");
|
|
||||||
|
|
||||||
pp = popen(cmd, "r");
|
|
||||||
if (pp != NULL) {
|
|
||||||
void *d = NULL;
|
|
||||||
d = blobmsg_open_array(&b, "connections");
|
|
||||||
|
|
||||||
char line[MAX_LINE_LEN] = {0};
|
|
||||||
|
|
||||||
while (fgets(line, MAX_LINE_LEN, pp) != NULL) {
|
|
||||||
// remove_new_line
|
|
||||||
line[strcspn(line, "\n")] = 0;
|
|
||||||
// stop parsing if there is a problem in one of the lines
|
|
||||||
if (parse_line(line, &b) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pclose(pp);
|
|
||||||
blobmsg_close_array(&b, d);
|
|
||||||
} else {
|
|
||||||
blobmsg_add_string(&b, "error", "Could not run netstat");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
ubus_send_reply(ctx, req, b.head);
|
|
||||||
blob_buf_free(&b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const struct ubus_method active_port_methods[] = {
|
|
||||||
UBUS_METHOD("dump", active_port_dump_handler, active_port_policy),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct ubus_object_type active_port_object_type = UBUS_OBJECT_TYPE("active-port", active_port_methods);
|
|
||||||
|
|
||||||
static struct ubus_object active_port_object = {
|
|
||||||
.name = "active-port",
|
|
||||||
.type = &active_port_object_type,
|
|
||||||
.methods = active_port_methods,
|
|
||||||
.n_methods = ARRAY_SIZE(active_port_methods),
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct ubus_context *uctx;
|
|
||||||
|
|
||||||
openlog("active-port", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
|
||||||
|
|
||||||
uctx = ubus_connect(NULL);
|
|
||||||
if (uctx == NULL) {
|
|
||||||
printf("Can't create UBUS context");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uloop_init();
|
|
||||||
ubus_add_uloop(uctx);
|
|
||||||
|
|
||||||
if (ubus_add_object(uctx, &active_port_object))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
uloop_run();
|
|
||||||
|
|
||||||
exit:
|
|
||||||
uloop_done();
|
|
||||||
ubus_free(uctx);
|
|
||||||
closelog();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue