⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.c

📁 Linux系统下著名的个人防火墙
💻 C
字号:
/*---[ util.c ]------------------------------------------------------- * Copyright (C) 2000-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. * * Functions that don't logically belong to any other module but still * need to be widely accessible *--------------------------------------------------------------------*/#include <sys/stat.h>#include <stdio.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <net/if.h>#include <sys/ioctl.h>#include "globals.h"#include "firestarter.h"#include "util.h"#include "hitview.h"#include "preferences.h"extern int h_errno;static voiderror_dialog_response (GtkDialog *dialog,                       gint response_id,                       gpointer data){	gtk_widget_destroy (GTK_WIDGET (dialog));}/* [ error_dialog ] * Run a dialog with an specified error message */voiderror_dialog (const gchar *title, const gchar *header, const gchar *message, GtkWidget *parent){	GtkWidget *dialog;	GtkWidget *hbox;	GtkWidget *label;	GdkPixbuf *pixbuf;	GtkWidget *icon;	GtkWindow *window = NULL;	const gchar *text;		if (Firestarter.window != NULL)		window = GTK_WINDOW (Firestarter.window);	dialog = gtk_dialog_new_with_buttons (		title,		GTK_WINDOW (parent),		GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,		GTK_STOCK_OK,		GTK_RESPONSE_ACCEPT,		NULL	);	gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);	/* If the main window is displayed we don't block and need a destroyer cb */	if (window != NULL)		g_signal_connect (G_OBJECT (dialog), "response",		                  G_CALLBACK (error_dialog_response), NULL);	hbox = gtk_hbox_new (FALSE, 12);	gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);	pixbuf = gtk_widget_render_icon (dialog, GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG, NULL);	icon = gtk_image_new_from_pixbuf (pixbuf);	g_object_unref (G_OBJECT(pixbuf));		gtk_misc_set_alignment (GTK_MISC (icon), 0.0, 0.0);	gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);	if (header != NULL)		text = g_strconcat ("<span weight=\"bold\" size=\"larger\">",		                    header,		                    "</span>\n\n",		                    message, "\n", NULL);	else		text = message;	label = gtk_label_new (text);	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);	gtk_widget_show_all (dialog);	/* If the main window is not displayed we need an new event loop */	if (window == NULL)		gtk_dialog_run (GTK_DIALOG (dialog));}/* [ show_error ] * Report that a error has occured to the user, either in GUI or on stderr */voidshow_error (gchar *message){	if (CONSOLE)		fprintf (stderr, "%s\n", message);	else		error_dialog (_("Firestarter error"), NULL, message, Firestarter.window);}/* [ get_system_log_path ] * Get the correct path to the system log, which may vary with distributions */const gchar *get_system_log_path (void){	static gchar *path = NULL;	if (path == NULL) {		/* User has specified the log file location */		path = preferences_get_string (PREFS_SYSLOG_FILE);		if (path && g_file_test (path, G_FILE_TEST_EXISTS)) {			return path;		} else { /* Try to guess some default syslog location */			if (g_file_test ("/var/log/messages", G_FILE_TEST_EXISTS))				path = g_strdup ("/var/log/messages");			else if (g_file_test ("/var/log/kernel", G_FILE_TEST_EXISTS))				path = g_strdup ("/var/log/kernel");			else				path = NULL;		}				if (path == NULL) {			show_error (g_strconcat (				"<span weight=\"bold\" size=\"larger\">",				_("Failed to open the system log\n\n"),				"</span>",				_("No event information will be available."),				NULL));		}	}	return path;}voidprint_hit (Hit *h){	printf ("HIT: %s from %s to %s:%s, protocol %s, service %s\n",		h->time,		h->source,		h->destination,		h->port,		h->protocol,		h->service);}Hit *copy_hit (Hit *h){	Hit *new = g_new (Hit, 1);		new->time = g_strdup (h->time);	new->direction = g_strdup (h->direction);	new->in =  g_strdup (h->in);	new->out = g_strdup (h->out);	new->port = g_strdup (h->port);	new->source = g_strdup (h->source);	new->destination = g_strdup (h->destination);	new->length = g_strdup (h->length);	new->tos = g_strdup (h->tos);	new->protocol = g_strdup (h->protocol);	new->service = g_strdup (h->service);	return new;}/* [ get_ip_of_interface ] * Get the IP address in use by an interface */gchar*get_ip_of_interface (gchar *itf) {	int fd;		struct ifreq ifreq;	struct sockaddr_in *sin;	gchar *ip;	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);	strcpy(ifreq.ifr_name, itf);	ioctl(fd, SIOCGIFADDR, &ifreq);	sin = (struct sockaddr_in *)&ifreq.ifr_broadaddr;	ip = g_strdup(inet_ntoa(sin->sin_addr));	close (fd);	return ip;}/* [ get_subnet_of_interface ] * Get the subnet-mask used by an interface */gchar*get_subnet_of_interface (gchar *itf) {	int fd;		struct ifreq ifreq;	struct sockaddr_in *sin;	gchar *subnet;	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);	strcpy(ifreq.ifr_name, itf);	ioctl(fd, SIOCGIFNETMASK, &ifreq);	sin = (struct sockaddr_in *)&ifreq.ifr_broadaddr;	subnet = g_strdup(inet_ntoa(sin->sin_addr));		return subnet;}GtkTreeModel*get_devices_model (void){	static GtkTreeModel *model = NULL;	GIOChannel *in;	GError *error = NULL;	if (model != NULL)		return model;	model = (GtkTreeModel *)gtk_list_store_new (2,		G_TYPE_STRING, G_TYPE_STRING);	in = g_io_channel_new_file ("/proc/net/dev", "r", &error);	if (in == NULL) {		gchar *error_message = g_strconcat (			_("Failed to open /proc/net/dev for reading: "),			error->message, NULL);		show_error (error_message);		g_free (error_message);		return NULL;	} else {		gchar *line, *interface;			while (g_io_channel_read_line (in, &line, NULL, NULL, &error) == G_IO_STATUS_NORMAL) {			if (index (line, ':')) {				GtkTreeIter iter;				interface = g_strndup (line, index (line, ':')-line);				interface = g_strstrip (interface);				if (g_str_equal (interface, "lo")) { /* Skip local loopback interface */					g_free (interface);					continue;				}				gtk_list_store_append (GTK_LIST_STORE (model), &iter);				gtk_list_store_set (GTK_LIST_STORE (model), &iter,				                    0, get_pretty_device_name (interface, TRUE),			                            1, interface,				                    -1);				g_free (interface);			}				g_free (line);		}		g_io_channel_shutdown (in, TRUE, NULL);	}	return model;}gchar *get_pretty_device_name (gchar *interface, gboolean long_form){	gchar *name;	if (g_str_has_prefix (interface, "eth"))		if (long_form)			name = g_strdup (_("Ethernet device"));		else			name = g_strdup (_("Ethernet"));	else if (g_str_has_prefix (interface, "ppp"))		if (long_form)			name = g_strdup (_("Dialup device"));		else			name = g_strdup (_("Dialup"));	else if (g_str_has_prefix (interface, "wlan"))		if (long_form)			name = g_strdup (_("Wireless device"));		else			name = g_strdup (_("Wireless"));	else if (g_str_has_prefix (interface, "sit"))		name = g_strdup (_("IPv6 Tunnel"));	else if (g_str_has_prefix (interface, "tap"))		name = g_strdup (_("VPN Tunnel"));	else if (g_str_has_prefix (interface, "tun"))		name = g_strdup (_("Routed IP Tunnel"));	else		if (long_form)			name = g_strdup (_("Unknown device"));		else			name = g_strdup (_("Unknown"));		if (long_form) {		gchar *long_name;				long_name = g_strconcat (name, " (", interface, ")", NULL);		g_free (name);		return long_name;	} else		return name;	}/* [ is_capable_of_nat ] * Return true if we can do nat, port forwarding etc. */gbooleanis_capable_of_nat (void){	GtkTreeModel *model;	model = get_devices_model ();	return gtk_tree_model_iter_n_children (model, NULL) > 1;}/* [ get_text_between ] * Give a string and two subtext markers in the string and the function  * returns the text between the markers. Note: Return empty string if fail. */gchar *get_text_between (const gchar *string, gchar *marker1, gchar *marker2){	gint i = strlen (marker1);	gchar *text = NULL;	marker1 = strstr (string, marker1);	if (marker1 != NULL) {		marker1 += i;		marker2 = strstr (marker1, marker2);		if (marker2 != NULL)			text = g_strndup (marker1, marker2-marker1);	}	if (text == NULL)		text = g_strdup ("");	return text;}/* [ lookup_ip ] * Resolve an IP address given in dotted-decimal notation into * an hostname or vice versa. */gchar *lookup_ip (gchar *ip){	struct hostent *hostentry = NULL;	struct in_addr address;	if (inet_aton (ip, &address)) {		hostentry = gethostbyaddr ((char *)&address,					   sizeof (address), AF_INET);		if (hostentry != NULL)			return hostentry->h_name;		else			return ip;	} else {		hostentry = gethostbyname (ip);		if (hostentry != NULL) {			memcpy (&address.s_addr, hostentry ->h_addr, hostentry->h_length);			return inet_ntoa(address);		}		else			return ip;	}}/* [ is_a_valid_port ] * Test that port is a valid number or range */gbooleanis_a_valid_port (const gchar *port){	static GPatternSpec *pattern = NULL;	gint length, i;	length = strlen (port);	/* Only numbers, a dash (range) or a space (delimiter) is allowed */	for (i = 0; i < length; i++) {		if (!g_ascii_isdigit (port[i]) &&		    port[i] != '-' &&		    port[i] != ' ') {			return FALSE;		}	}	if (pattern == NULL)		pattern = g_pattern_spec_new ("*-*");	if (g_pattern_match_string (pattern, port)) {		gchar *separator, *start, *end;		int range_start, range_end;				separator = strstr (port, "-");		start = g_strndup (port, separator-port);		end = g_strdup (separator+1);		range_start = atoi (start);		range_end = atoi (end);		g_free (start);		g_free (end);		return (range_start >= 1 && range_start <= 65535 &&			range_end >= 1 && range_end <= 65535);	} else {		int port_num;		port_num = atoi (port);		return (port_num >= 1 && port_num <= 65535);	}}/* [ is_a_valid_host ] * _Very_ loose host string checking */gbooleanis_a_valid_host (const gchar *host){	gint length, i;	length = strlen (host);		/* Check that the host only contains alphanumerics, dots or slashes */	for (i = 0; i < length; i++) {		if (!g_ascii_isalnum (host[i]) &&		    host[i] != '.' &&		    host[i] != '/' &&		    host[i] != '-') {			return FALSE;		}	}	/* Host name must contain a dot and be over 3 but less than 255 chars long */	if (length < 3 || length > 255) {		return FALSE;	}	return TRUE;}voidfree_hit (Hit *h){	if (h == NULL)		return;	g_free (h->time);	g_free (h->direction);	g_free (h->in);	g_free (h->out);	g_free (h->port);	g_free (h->source);	g_free (h->destination);	g_free (h->length);	g_free (h->tos);	g_free (h->protocol);	g_free (h->service);	g_free (h);}/* [ append_to_file ] * Append a string to a file */gbooleanappend_to_file (gchar *path, gchar *data, gboolean newline){	GIOChannel* out;	GError *error = NULL;	out = g_io_channel_new_file (path, "a", &error);	if (out == NULL) {		g_printerr ("Error reading file %s: %s\n", path, error->message);		return FALSE;	}	if (g_io_channel_write_chars (out, data, -1, NULL, &error) == G_IO_STATUS_NORMAL) {		g_io_channel_write_chars (out, "\n", -1, NULL, NULL);		g_io_channel_shutdown (out, TRUE, &error);		return TRUE;	} else {		g_io_channel_shutdown (out, FALSE, &error);		return FALSE;	}}/* [ remove_line_from_file ] * Remove a single rule from a file */voidremove_line_from_file (gchar *path, gint position){	GIOChannel* io;	GError *error = NULL;	gint i;	gchar *contents = "";	gchar *tail;	io = g_io_channel_new_file (path, "r", &error);	if (io == NULL) {		g_printerr ("Error reading file %s: %s\n", path, error->message);		return;	}	/* Read contents up until the line to be excised */	for (i = 0; i < position; i++) {		gchar *line;				g_io_channel_read_line (io, &line, NULL, NULL, &error);		contents = g_strconcat (contents, line, NULL);		g_free (line);	}	g_io_channel_read_line (io, &tail, NULL, NULL, &error); /* Skip one line */	g_free (tail);	g_io_channel_read_to_end (io, &tail, NULL, &error); /* Read in the rest */	contents = g_strconcat (contents, tail, NULL);	g_io_channel_shutdown (io, FALSE, &error);	io = g_io_channel_new_file (path, "w", &error); /* Write it back out */	g_io_channel_write_chars (io, contents, -1, NULL, &error);	g_io_channel_shutdown (io, TRUE, &error);	g_free (contents);	g_free (tail);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -