You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/ksysguard/ksysguardd/Linux/netstat.c

498 lines
12 KiB

/*
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 <sys/types.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");
}