📄 statusview.c
字号:
/*---[ statusview.c ]----------------------------------------------------- * Copyright (C) 2004 Tomas Junnonen (majix@sci.fi) * * 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. * * The Status page and related functions *--------------------------------------------------------------------*/#include <config.h>#include <gnome.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <dirent.h>#include <sys/types.h>#include <fcntl.h>#include "firestarter.h"#include "globals.h"#include "statusview.h"#include "menus.h"#include "preferences.h"#include "util.h"#include "service.h"#include "tray.h"#include "gui.h"#include "xpm/firestarter-pixbufs.h" #define DEV_FILE "/proc/net/dev"#define TCP_FILE "/proc/net/tcp"#define CONNTRACK_FILE "/proc/net/ip_conntrack"#define CONNTRACK_TTL 10 /* Number of refresh cycles a non-established connection is kept in the GUI */#define REFRESH_RATE 1 /* Time in seconds between updates */#define HISTORY_LENGTH 5 /* Number of samples to use when averaging the traffic rate */#define COLOR_RETIRED_CONNECTION "#6d6d6d"static gboolean active_connections_visible = FALSE;static FirewallStatus current_status;static GtkWidget *connectionview;static GtkWidget *device_table;static GtkWidget *fw_state_icon;static GtkWidget *fw_state_label;static gint counter_events_in, counter_events_out, counter_serious_events_in, counter_serious_events_out;static GtkWidget *events_in, *events_out, *events_serious_in, *events_serious_out;static GHashTable *conntrack_programs = NULL;typedef struct _Interface_info Interface_info;struct _Interface_info{ gchar *type; gulong received; gulong sent; gulong previous_total; float average; float *traffic_history; gint history_index;};typedef struct _Interface_widgets Interface_widgets;struct _Interface_widgets{ GtkWidget *device; GtkWidget *type; GtkWidget *received; GtkWidget *sent; GtkWidget *activity;};typedef struct _Connection_entry Connection_entry;struct _Connection_entry{ GtkTreeIter *ref; gint ttl;};enum{ CONNECTIONCOL_SOURCE, CONNECTIONCOL_DESTINATION, CONNECTIONCOL_PORT, CONNECTIONCOL_SERVICE, CONNECTIONCOL_PROGRAM, CONNECTIONCOL_COLOR, NUM_CONNECTIONCOLUMNS};static GtkListStore*get_connectionstore (void){ return GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (connectionview)));}static unsigned longget_inode (gchar *m_source, gchar *m_destination, gchar *m_remote_port){ gint line_num = 0; gchar *line; static GIOChannel *in = NULL; unsigned long inode; GError *error = NULL; if (in == NULL) { in = g_io_channel_new_file (TCP_FILE, "r", &error); if (in == NULL) { printf ("Error reading %s: %s\n", TCP_FILE, error->message); return 0; } } while (TRUE) { int local_port, rem_port; gchar local_addr[128], rem_addr[128], more[512]; struct sockaddr_in localaddr, remaddr; gchar *ip; inode = -1; g_io_channel_read_line (in, &line, NULL, NULL, &error); if (line == NULL) // EOF reached break; line_num++; if (line_num == 1) { // Skip tcp file header g_free (line); continue; } sscanf(line, "%*X: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %512s\n", local_addr, &local_port, rem_addr, &rem_port, &inode, more); sscanf(local_addr, "%X", &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); sscanf(rem_addr, "%X", &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr); ((struct sockaddr *) &localaddr)->sa_family = AF_INET; ((struct sockaddr *) &remaddr)->sa_family = AF_INET; if (rem_port != atoi (m_remote_port)) { g_free (line); continue; } ip = inet_ntoa (localaddr.sin_addr); if (!g_str_equal (ip, m_source)) { g_free (line); continue; } ip = inet_ntoa (remaddr.sin_addr); if (!g_str_equal (ip, m_destination)) { g_free (line); continue; } /* printf ("MATCH %s %s\n", ip, m_destination); */ g_free (line); break; } g_io_channel_seek_position (in, 0, G_SEEK_SET, &error); // Rewind return inode;}static voidextract_socket_inode (gchar *lname, long *inode_p){ if (!g_str_has_suffix (lname, "]")) { *inode_p = -1; } else { gchar *inode_str, *serr; inode_str = get_text_between (lname, "[", "]"); *inode_p = strtol (inode_str, &serr, 0); if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX) *inode_p = -1; g_free (inode_str); }}static voidload_program_cache (void){ char line[40]; int procfdlen, fd, cmdllen; char cmdlbuf[512]; long inode; const char *cs, *cmdlp; DIR *dirproc = NULL, *dirfd = NULL; struct dirent *direproc, *direfd; gchar *lname; if (conntrack_programs == NULL) conntrack_programs = g_hash_table_new_full (g_direct_hash, NULL, NULL, g_free); if (!(dirproc=opendir("/proc"))) { printf ("error opening proc filesystem\n"); return; } while (errno=0, direproc = readdir (dirproc)) { if (direproc->d_type!=DT_DIR) continue; for (cs = direproc->d_name; *cs; cs++) if (!g_ascii_isdigit(*cs) || *cs) break; procfdlen = snprintf (line, sizeof (line), "/proc/%s/fd", direproc->d_name); if (procfdlen <= 0 || procfdlen >= sizeof (line)-5) continue; errno = 0; dirfd = opendir (line); if (!dirfd) continue; line[procfdlen] = '/'; cmdlp = NULL; while ((direfd = readdir (dirfd))) { if (direfd->d_type!=DT_LNK) continue; if (procfdlen+1+strlen(direfd->d_name)+1>sizeof(line)) continue; memcpy(line + procfdlen - 2, "fd/", 2+1); strcpy(line + procfdlen + 1, direfd->d_name); lname = g_file_read_link (line, NULL); extract_socket_inode (lname, &inode); if (inode < 0) { g_free (lname); continue; } if (!cmdlp) { if (procfdlen - 2 + 7 >= sizeof(line) - 5) { g_free (lname); continue; } strcpy (line + procfdlen-2, "cmdline"); fd = open(line, O_RDONLY); if (fd < 0) { g_free (lname); continue; } cmdllen = read (fd, cmdlbuf, sizeof(cmdlbuf) - 1); if (close(fd)) { g_free (lname); continue; } if (cmdllen == -1) { g_free (lname); continue; } if (cmdllen < sizeof (cmdlbuf) - 1) cmdlbuf[cmdllen] = '\0'; if ((cmdlp = strrchr(cmdlbuf, '/'))) cmdlp++; else cmdlp = cmdlbuf; } g_hash_table_replace (conntrack_programs, GINT_TO_POINTER (inode), g_strdup (cmdlp)); g_free (lname); } closedir(dirfd); dirfd = NULL; } if (dirproc) closedir(dirproc); if (dirfd) closedir(dirfd);}static gchar *get_program_name (gint inode){ gchar *name = NULL; name = g_hash_table_lookup (conntrack_programs, GINT_TO_POINTER (inode)); /* printf ("Looking up: %d, got: %s\n", inode, name); */ return name;}/* [ connectionview_append_connection ] * Append a connection to the connectionlist */static GtkTreeIter*connectionview_append_connection (gchar *source, gchar *destination, gchar *port, gchar *service){ GtkListStore *store = get_connectionstore (); GtkTreeIter *iter = g_new (GtkTreeIter, 1); unsigned long inode = -1; gchar *program; static gchar *firewall_ip = NULL; if (firewall_ip == NULL); firewall_ip = get_ip_of_interface (preferences_get_string (PREFS_FW_EXT_IF)); /* Only look up program names for local connections */ if (g_str_equal (firewall_ip, source)) { load_program_cache (); inode = get_inode (source, destination, port); } if (inode != -1) program = get_program_name (inode); else program = g_strdup (""); gtk_list_store_append (store, iter); gtk_list_store_set (store, iter, CONNECTIONCOL_SOURCE, source, CONNECTIONCOL_DESTINATION, destination, CONNECTIONCOL_PORT, port, CONNECTIONCOL_SERVICE, service, CONNECTIONCOL_PROGRAM, program, CONNECTIONCOL_COLOR, NULL, -1); gtk_tree_view_columns_autosize (GTK_TREE_VIEW (connectionview)); return iter;}static voidconnectionview_refresh (GHashTable *entries){ static GPatternSpec *pattern = NULL; static GIOChannel *in = NULL; GError *error = NULL; gchar *line; if (pattern == NULL) pattern = g_pattern_spec_new ("* ESTABLISHED src=* dst=* dport=*"); if (in == NULL) { in = g_io_channel_new_file (CONNTRACK_FILE, "r", &error); if (in == NULL) { printf ("Error reading %s: %s\n", CONNTRACK_FILE, error->message); return; } } while (TRUE) { g_io_channel_read_line (in, &line, NULL, NULL, &error); if (line == NULL) // EOF reached break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -