You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
4.8 KiB
C
205 lines
4.8 KiB
C
/*
|
|
*
|
|
* IPTraffic monitoring extensions for Tomato
|
|
* Copyright (C) 2011-2012 Augusto Bott
|
|
*
|
|
* Tomato Firmware
|
|
* Copyright (C) 2006-2009 Jonathan Zarate
|
|
*
|
|
* Fixes/updates (C) 2018 - 2023 pedro
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "tomato.h"
|
|
#include "shared.h"
|
|
|
|
#include <arpa/inet.h>
|
|
#include "iptraffic.h"
|
|
|
|
|
|
void asp_iptraffic(int argc, char **argv) {
|
|
char comma;
|
|
char sa[256];
|
|
FILE *a;
|
|
char ip[INET_ADDRSTRLEN];
|
|
|
|
char *exclude;
|
|
|
|
unsigned long tx_bytes, rx_bytes;
|
|
unsigned long tp_tcp, rp_tcp;
|
|
unsigned long tp_udp, rp_udp;
|
|
unsigned long tp_icmp, rp_icmp;
|
|
unsigned int ct_tcp, ct_udp;
|
|
|
|
exclude = nvram_safe_get("cstats_exclude");
|
|
|
|
Node tmp;
|
|
Node *ptr;
|
|
|
|
iptraffic_conntrack_init();
|
|
|
|
char br;
|
|
char name[] = "/proc/net/ipt_account/lanX";
|
|
|
|
web_puts("\n\niptraffic=[");
|
|
comma = ' ';
|
|
|
|
for (br = 0; br < BRIDGE_COUNT; br++) {
|
|
char bridge[2] = "0";
|
|
if (br != 0)
|
|
bridge[0] += br;
|
|
else
|
|
memset(bridge, 0, sizeof(bridge));
|
|
|
|
snprintf(name, sizeof(name), "/proc/net/ipt_account/lan%s", bridge);
|
|
|
|
if (!(a = fopen(name, "r")))
|
|
continue;
|
|
|
|
fgets(sa, sizeof(sa), a); /* network */
|
|
while (fgets(sa, sizeof(sa), a)) {
|
|
if (sscanf(sa, "ip = %s bytes_src = %lu %*u %*u %*u %*u packets_src = %*u %lu %lu %lu %*u bytes_dst = %lu %*u %*u %*u %*u packets_dst = %*u %lu %lu %lu %*u time = %*u",
|
|
ip, &tx_bytes, &tp_tcp, &tp_udp, &tp_icmp, &rx_bytes, &rp_tcp, &rp_udp, &rp_icmp) != 9)
|
|
continue;
|
|
if (find_word(exclude, ip))
|
|
continue;
|
|
|
|
if ((tx_bytes > 0) || (rx_bytes > 0)) {
|
|
strlcpy(tmp.ipaddr, ip, INET_ADDRSTRLEN);
|
|
ptr = TREE_FIND(&tree, _Node, linkage, &tmp);
|
|
if (!ptr) {
|
|
ct_tcp = 0;
|
|
ct_udp = 0;
|
|
}
|
|
else {
|
|
ct_tcp = ptr->tcp_conn;
|
|
ct_udp = ptr->udp_conn;
|
|
}
|
|
web_printf("%c['%s', %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %u, %u]", comma, ip, rx_bytes, tx_bytes, rp_tcp, tp_tcp, rp_udp, tp_udp, rp_icmp, tp_icmp, ct_tcp, ct_udp);
|
|
comma = ',';
|
|
}
|
|
}
|
|
fclose(a);
|
|
}
|
|
web_puts("];\n");
|
|
|
|
TREE_FORWARD_APPLY(&tree, _Node, linkage, Node_housekeeping, NULL);
|
|
TREE_INIT(&tree, Node_compare);
|
|
}
|
|
|
|
void iptraffic_conntrack_init() {
|
|
const char conntrack[] = "/proc/net/ip_conntrack";
|
|
unsigned int a_time, a_proto;
|
|
char a_src[INET_ADDRSTRLEN];
|
|
char a_dst[INET_ADDRSTRLEN];
|
|
char b_src[INET_ADDRSTRLEN];
|
|
char b_dst[INET_ADDRSTRLEN];
|
|
|
|
char sa[256];
|
|
char sb[256];
|
|
FILE *a;
|
|
char *p;
|
|
int x;
|
|
|
|
Node tmp;
|
|
Node *ptr;
|
|
|
|
unsigned long rip[BRIDGE_COUNT];
|
|
unsigned long lan[BRIDGE_COUNT];
|
|
unsigned long mask[BRIDGE_COUNT];
|
|
unsigned short int br;
|
|
|
|
for(br = 0; br < BRIDGE_COUNT; br++) {
|
|
char bridge[2] = "0";
|
|
if (br != 0)
|
|
bridge[0] += br;
|
|
else
|
|
memset(bridge, 0, sizeof(bridge));
|
|
|
|
memset(sa, 0, sizeof(sa));
|
|
snprintf(sa, sizeof(sa), "lan%s_ifname", bridge);
|
|
|
|
if (strcmp(nvram_safe_get(sa), "") != 0) {
|
|
memset(sa, 0, sizeof(sa));
|
|
snprintf(sa, sizeof(sa), "lan%s_ipaddr", bridge);
|
|
rip[br] = inet_addr(nvram_safe_get(sa));
|
|
|
|
memset(sa, 0, sizeof(sa));
|
|
snprintf(sa, sizeof(sa), "lan%s_netmask", bridge);
|
|
mask[br] = inet_addr(nvram_safe_get(sa));
|
|
lan[br] = rip[br] & mask[br];
|
|
}
|
|
else {
|
|
mask[br] = 0;
|
|
rip[br] = 0;
|
|
lan[br] = 0;
|
|
}
|
|
}
|
|
|
|
if (!(a = fopen(conntrack, "r")))
|
|
return;
|
|
|
|
ctvbuf(a); /* if possible, read in one go */
|
|
|
|
while (fgets(sa, sizeof(sa), a)) {
|
|
if (sscanf(sa, "%*s %u %u", &a_proto, &a_time) != 2)
|
|
continue;
|
|
if ((a_proto != 6) && (a_proto != 17))
|
|
continue;
|
|
if ((p = strstr(sa, "src=")) == NULL)
|
|
continue;
|
|
if (sscanf(p, "src=%s dst=%s %n", a_src, a_dst, &x) != 2)
|
|
continue;
|
|
|
|
p += x;
|
|
|
|
if ((p = strstr(p, "src=")) == NULL)
|
|
continue;
|
|
if (sscanf(p, "src=%s dst=%s", b_src, b_dst) != 2)
|
|
continue;
|
|
|
|
snprintf(sb, sizeof(sb), "%s %s %s %s", a_src, a_dst, b_src, b_dst);
|
|
remove_dups(sb, sizeof(sb));
|
|
|
|
char ipaddr[INET_ADDRSTRLEN], *next = NULL;
|
|
char skip;
|
|
|
|
foreach(ipaddr, sb, next) {
|
|
skip = 1;
|
|
for (br = 0; br < BRIDGE_COUNT; br++) {
|
|
if ((mask[br] != 0) && ((inet_addr(ipaddr) & mask[br]) == lan[br])) {
|
|
skip = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (skip == 1)
|
|
continue;
|
|
|
|
strlcpy(tmp.ipaddr, ipaddr, INET_ADDRSTRLEN);
|
|
ptr = TREE_FIND(&tree, _Node, linkage, &tmp);
|
|
|
|
if (!ptr) {
|
|
//_dprintf("%s: new ip: %s\n", __FUNCTION__, ipaddr);
|
|
TREE_INSERT(&tree, _Node, linkage, Node_new(ipaddr));
|
|
ptr = TREE_FIND(&tree, _Node, linkage, &tmp);
|
|
}
|
|
if (a_proto == 6)
|
|
++ptr->tcp_conn;
|
|
if (a_proto == 17)
|
|
++ptr->udp_conn;
|
|
}
|
|
}
|
|
fclose(a);
|
|
}
|