summaryrefslogtreecommitdiffstats
path: root/ksysguard/ksysguardd/Linux/netstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'ksysguard/ksysguardd/Linux/netstat.c')
-rw-r--r--ksysguard/ksysguardd/Linux/netstat.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/ksysguard/ksysguardd/Linux/netstat.c b/ksysguard/ksysguardd/Linux/netstat.c
new file mode 100644
index 000000000..c8570f617
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/netstat.c
@@ -0,0 +1,495 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "ccont.h"
+#include "netstat.h"
+
+static CONTAINER TcpSocketList = 0;
+static CONTAINER UdpSocketList = 0;
+static CONTAINER UnixSocketList = 0;
+static CONTAINER RawSocketList = 0;
+
+static int num_tcp = 0;
+static int num_udp = 0;
+static int num_unix = 0;
+static int num_raw = 0;
+
+typedef struct {
+ char local_addr[128];
+ char local_port[128];
+ char remote_addr[128];
+ char remote_port[128];
+ char state[128];
+ int uid;
+} SocketInfo;
+
+typedef struct {
+ int refcount;
+ char type[128];
+ char state[128];
+ int inode;
+ char path[256];
+} UnixInfo;
+
+char *get_serv_name(int port, const char *proto);
+char *get_host_name(int addr);
+char *get_proto_name(int number);
+int get_num_sockets(FILE *netstat);
+void printSocketInfo(SocketInfo* socket_info);
+
+static time_t TcpUdpRaw_timeStamp = 0;
+static time_t Unix_timeStamp = 0;
+static time_t NetStat_timeStamp = 0;
+
+static const char *raw_type[] =
+{
+ "",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "packet"
+};
+
+static const char *raw_state[] =
+{
+ "free",
+ "unconnected",
+ "connecting",
+ "connected",
+ "disconnecting"
+};
+
+static const char *conn_state[] =
+{
+ "",
+ "established",
+ "syn_sent",
+ "syn_recv",
+ "fin_wait1",
+ "fin_wait2",
+ "time_wait",
+ "close",
+ "close_wait",
+ "last_ack",
+ "listen",
+ "closing"
+};
+
+char *get_serv_name(int port, const char *proto)
+{
+ static char buffer[1024];
+ struct servent *service;
+
+ if (port == 0) {
+ return (char *)"*";
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((service = getservbyport(ntohs(port), proto)) == NULL) {
+ snprintf(buffer, sizeof(buffer), "%d", port);
+ } else {
+ strlcpy(buffer, service->s_name, sizeof(buffer));
+ }
+
+ return (char *)buffer;
+}
+
+char *get_host_name(int addr)
+{
+ static char buffer[1024];
+ struct hostent *host;
+ struct in_addr a_addr;
+
+ if (addr == 0) {
+ return (char *)"*";
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((host = gethostbyaddr((char *)&addr, 4, AF_INET)) == NULL) {
+ a_addr.s_addr = addr;
+ return inet_ntoa(a_addr);
+ } else {
+ strlcpy(buffer, host->h_name, sizeof(buffer));
+ return (char *)buffer;
+ }
+}
+
+char *get_proto_name(int number)
+{
+ static char buffer[1024];
+ struct protoent *protocol;
+
+ if (number == 0) {
+ return (char *)"*";
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((protocol = getprotobynumber(number)) == NULL) {
+ snprintf(buffer, sizeof(buffer), "%d", number);
+ } else {
+ strlcpy(buffer, protocol->p_name, sizeof(buffer));
+ }
+
+ return (char *)buffer;
+}
+
+int get_num_sockets(FILE *netstat)
+{
+ char line[1024];
+ int line_count = 0;
+
+ while (fgets(line, 1024, netstat) != NULL)
+ line_count++;
+
+ return line_count - 1;
+}
+
+void printSocketInfo(SocketInfo* socket_info)
+{
+ fprintf(CurrentClient, "%s\t%s\t%s\t%s\t%s\t%d\n",
+ socket_info->local_addr,
+ socket_info->local_port,
+ socket_info->remote_addr,
+ socket_info->remote_port,
+ socket_info->state,
+ socket_info->uid);
+}
+
+/*
+================================ public part =================================
+*/
+
+void
+initNetStat(struct SensorModul* sm)
+{
+ FILE *netstat;
+
+ if ((netstat = fopen("/proc/net/tcp", "r")) != NULL) {
+ registerMonitor("network/sockets/tcp/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/tcp/list", "listview", printNetStatTcpUdpRaw, printNetStatTcpUdpRawInfo, sm);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/udp", "r")) != NULL) {
+ registerMonitor("network/sockets/udp/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/udp/list", "listview", printNetStatTcpUdpRaw, printNetStatTcpUdpRawInfo, sm);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/unix", "r")) != NULL) {
+ registerMonitor("network/sockets/unix/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/unix/list", "listview", printNetStatUnix, printNetStatUnixInfo, sm);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/raw", "r")) != NULL) {
+ registerMonitor("network/sockets/raw/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/raw/list", "listview", printNetStatTcpUdpRaw, printNetStatTcpUdpRawInfo, sm);
+ fclose(netstat);
+ }
+
+ TcpSocketList = new_ctnr();
+ UdpSocketList = new_ctnr();
+ RawSocketList = new_ctnr();
+ UnixSocketList = new_ctnr();
+}
+
+void
+exitNetStat(void)
+{
+ destr_ctnr(TcpSocketList, free);
+ destr_ctnr(UdpSocketList, free);
+ destr_ctnr(RawSocketList, free);
+ destr_ctnr(UnixSocketList, free);
+}
+
+int
+updateNetStat(void)
+{
+ FILE *netstat;
+
+ if ((netstat = fopen("/proc/net/tcp", "r")) != NULL) {
+ num_tcp = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+
+ if ((netstat = fopen("/proc/net/udp", "r")) != NULL) {
+ num_udp = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+
+ if ((netstat = fopen("/proc/net/unix", "r")) != NULL) {
+ num_unix = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/raw", "r")) != NULL) {
+ num_raw = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+
+ NetStat_timeStamp = time(0);
+ return 0;
+}
+
+int
+updateNetStatTcpUdpRaw(const char *cmd)
+{
+ FILE *netstat;
+ char buffer[1024];
+ uint local_addr, local_port;
+ uint remote_addr, remote_port;
+ int uid, i;
+ uint state;
+ SocketInfo *socket_info;
+
+ if (strstr(cmd, "tcp")) {
+ snprintf(buffer, sizeof(buffer), "/proc/net/tcp");
+ for (i = level_ctnr(TcpSocketList); i >= 0; --i)
+ free(pop_ctnr(TcpSocketList));
+ }
+
+ if (strstr(cmd, "udp")) {
+ snprintf(buffer, sizeof(buffer), "/proc/net/udp");
+ for (i = level_ctnr(UdpSocketList); i >= 0; --i)
+ free(pop_ctnr(UdpSocketList));
+ }
+
+ if (strstr(cmd, "raw")) {
+ snprintf(buffer, sizeof(buffer), "/proc/net/raw");
+ for (i = level_ctnr(RawSocketList); i >= 0; --i)
+ free(pop_ctnr(RawSocketList));
+ }
+
+ if ((netstat = fopen(buffer, "r")) == NULL) {
+ print_error("Cannot open \'%s\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n", buffer);
+ return -1;
+ }
+
+ fgets(buffer, sizeof(buffer), netstat);
+
+ while (fgets(buffer, sizeof(buffer), netstat) != NULL) {
+ if (strcmp(buffer, "")) {
+ sscanf(buffer, "%*d: %x:%x %x:%x %x %*x:%*x %*x:%*x %d",
+ &local_addr, &local_port,
+ &remote_addr, &remote_port,
+ &state,
+ &uid);
+
+ if ((socket_info = (SocketInfo *)malloc(sizeof(SocketInfo))) == NULL) {
+ continue;
+ }
+ strlcpy(socket_info->local_addr, get_host_name(local_addr), sizeof(socket_info->local_addr));
+ strlcpy(socket_info->remote_addr, get_host_name(remote_addr), sizeof(socket_info->remote_addr));
+
+ if (strstr(cmd, "tcp")) {
+ strlcpy(socket_info->local_port, get_serv_name(local_port, "tcp"), sizeof(socket_info->local_port));
+ strlcpy(socket_info->remote_port, get_serv_name(remote_port, "tcp"), sizeof(socket_info->remote_port));
+ strlcpy(socket_info->state, conn_state[state], sizeof(socket_info->state));
+ socket_info->uid = uid;
+
+ push_ctnr(TcpSocketList, socket_info);
+ }
+
+ if (strstr(cmd, "udp")) {
+ strlcpy(socket_info->local_port, get_serv_name(local_port, "udp"), sizeof(socket_info->local_port));
+ strlcpy(socket_info->remote_port, get_serv_name(remote_port, "udp"), sizeof(socket_info->remote_port));
+ strlcpy(socket_info->state, conn_state[state], sizeof(socket_info->state));
+ socket_info->uid = uid;
+
+ push_ctnr(UdpSocketList, socket_info);
+ }
+
+ if (strstr(cmd, "raw")) {
+ strlcpy(socket_info->local_port, get_proto_name(local_port), sizeof(socket_info->local_port));
+ strlcpy(socket_info->remote_port, get_proto_name(remote_port), sizeof(socket_info->remote_port));
+ snprintf(socket_info->state, sizeof(socket_info->state)-1, "%d", state);
+ socket_info->uid = uid;
+
+ push_ctnr(RawSocketList, socket_info);
+ }
+ }
+ }
+ fclose(netstat);
+ TcpUdpRaw_timeStamp = time(0);
+
+ return 0;
+}
+
+int
+updateNetStatUnix(void)
+{
+ FILE *file;
+ char buffer[1024];
+ char path[256];
+ int ref_count, type, state, inode, i;
+ UnixInfo *unix_info;
+
+ if ((file = fopen("/proc/net/unix", "r")) == NULL) {
+ print_error("Cannot open \'/proc/net/unix\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n");
+ return -1;
+ }
+
+ for (i = level_ctnr(UnixSocketList); i >= 0; --i)
+ free(pop_ctnr(UnixSocketList));
+
+ fgets(buffer, sizeof(buffer), file);
+
+ while (fgets(buffer, sizeof(buffer), file) != NULL) {
+ if (strcmp(buffer, "")) {
+ sscanf(buffer, "%*x: %d %*d %*d %d %d %d %255s",
+ &ref_count, &type, &state, &inode, path);
+
+ if ((unix_info = (UnixInfo *)malloc(sizeof(UnixInfo))) == NULL) {
+ continue;
+ }
+
+ unix_info->refcount = ref_count;
+ strlcpy(unix_info->type, raw_type[type], sizeof(unix_info->type));
+ strlcpy(unix_info->state, raw_state[state], sizeof(unix_info->state));
+ unix_info->inode = inode;
+ strlcpy(unix_info->path, path, sizeof(unix_info->path));
+
+ push_ctnr(UnixSocketList, unix_info);
+ }
+ }
+ fclose(file);
+ Unix_timeStamp = time(0);
+
+ return 0;
+}
+
+void
+printNetStat(const char* cmd)
+{
+ if ((time(0) - NetStat_timeStamp) >= UPDATEINTERVAL)
+ updateNetStat();
+
+ if (strstr(cmd, "tcp") != NULL)
+ fprintf(CurrentClient, "%d\n", num_tcp);
+ if (strstr(cmd, "udp") != NULL)
+ fprintf(CurrentClient, "%d\n", num_udp);
+ if (strstr(cmd, "unix") != NULL)
+ fprintf(CurrentClient, "%d\n", num_unix);
+ if (strstr(cmd, "raw") != NULL)
+ fprintf(CurrentClient, "%d\n", num_raw);
+}
+
+void
+printNetStatInfo(const char* cmd)
+{
+ if (strstr(cmd, "tcp") != NULL)
+ fprintf(CurrentClient, "Number of TCP-Sockets\t0\t0\tSockets\n");
+ if (strstr(cmd, "udp") != NULL)
+ fprintf(CurrentClient, "Number of UDP-Sockets\t0\t0\tSockets\n");
+ if (strstr(cmd, "unix") != NULL)
+ fprintf(CurrentClient, "Number of UnixDomain-Sockets\t0\t0\tSockets\n");
+ if (strstr(cmd, "raw") != NULL)
+ fprintf(CurrentClient, "Number of Raw-Sockets\t0\t0\tSockets\n");
+}
+
+void
+printNetStatTcpUdpRaw(const char *cmd)
+{
+ SocketInfo* socket_info;
+
+ if (strstr(cmd, "tcp")) {
+ if ((time(0) - TcpUdpRaw_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatTcpUdpRaw("tcp");
+
+ for (socket_info = first_ctnr(TcpSocketList); socket_info; socket_info = next_ctnr(TcpSocketList))
+ printSocketInfo(socket_info);
+
+ if (level_ctnr(TcpSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+ }
+
+ if (strstr(cmd, "udp")) {
+ if ((time(0) - TcpUdpRaw_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatTcpUdpRaw("udp");
+
+ for (socket_info = first_ctnr(UdpSocketList); socket_info; socket_info = next_ctnr(UdpSocketList))
+ printSocketInfo(socket_info);
+
+ if (level_ctnr(UdpSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+ }
+
+ if (strstr(cmd, "raw")) {
+ if ((time(0) - TcpUdpRaw_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatTcpUdpRaw("raw");
+
+ for (socket_info = first_ctnr(RawSocketList); socket_info; socket_info = next_ctnr(RawSocketList))
+ printSocketInfo(socket_info);
+
+ if (level_ctnr(RawSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+ }
+}
+
+void
+printNetStatTcpUdpRawInfo(const char *cmd)
+{
+ (void) cmd;
+ fprintf(CurrentClient, "Local Address\tPort\tForeign Address\tPort\tState\tUID\ns\ts\ts\ts\ts\td\n");
+}
+
+void printNetStatUnix(const char *cmd)
+{
+ UnixInfo* unix_info;
+
+ (void) cmd;
+ if ((time(0) - Unix_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatUnix();
+
+ for (unix_info = first_ctnr(UnixSocketList); unix_info; unix_info = next_ctnr(UnixSocketList)) {
+ fprintf(CurrentClient, "%d\t%s\t%s\t%d\t%s\n",
+ unix_info->refcount,
+ unix_info->type,
+ unix_info->state,
+ unix_info->inode,
+ unix_info->path);
+ }
+
+ if (level_ctnr(UnixSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+}
+
+void printNetStatUnixInfo(const char *cmd)
+{
+ (void) cmd;
+ fprintf(CurrentClient, "RefCount\tType\tState\tInode\tPath\nd\ts\ts\td\ts\n");
+}