bandwidthd-2.0.1+cvs20090917/0000755000175000017500000000000011254363050013346 5ustar gemgembandwidthd-2.0.1+cvs20090917/conf.y0000644000175000017500000000730010337130110014453 0ustar gemgem %{ #include #include #include #include #include #include #include #include #include #include #include "bandwidthd.h" extern unsigned int SubnetCount; extern struct SubnetData SubnetTable[]; extern struct config config; int bdconfig_lex(void); int LineNo = 1; void bdconfig_error(const char *str) { fprintf(stderr, "Syntax Error \"%s\" on line %d\n", str, LineNo); syslog(LOG_ERR, "Syntax Error \"%s\" on line %d", str, LineNo); exit(1); } int bdconfig_wrap() { return(1); } %} %token TOKJUNK TOKSUBNET TOKDEV TOKSLASH TOKSKIPINTERVALS TOKGRAPHCUTOFF TOKDESCRIPTION %token TOKPROMISC TOKOUTPUTCDF TOKRECOVERCDF TOKGRAPH TOKNEWLINE TOKFILTER TOKMANAGEMENTURL %token TOKMETAREFRESH TOKPGSQLCONNECTSTRING TOKSENSORID TOKHTDOCSDIR TOKLOGDIR TOKEXTENSIONS %union { int number; char *string; } %token IPADDR %token NUMBER %token STRING %token STATE %type string %% commands: /* EMPTY */ | commands command ; command: subnet | device | skip_intervals | graph_cutoff | promisc | extensions | output_cdf | recover_cdf | graph | newline | filter | meta_refresh | pgsql_connect_string | sensor_name | htdocs_dir | log_dir | description | management_url; ; subnet: subneta | subnetb ; newline: TOKNEWLINE { LineNo++; } ; subneta: TOKSUBNET IPADDR IPADDR { //struct in_addr addr, addr2; MonitorSubnet(inet_network($2), inet_network($3)); /* SubnetTable[SubnetCount].ip = inet_network($2) & inet_network($3); SubnetTable[SubnetCount].mask = inet_network($3); addr.s_addr = ntohl(SubnetTable[SubnetCount].ip); addr2.s_addr = ntohl(SubnetTable[SubnetCount++].mask); syslog(LOG_INFO, "Monitoring subnet %s with netmask %s", inet_ntoa(addr), inet_ntoa(addr2)); */ } ; subnetb: TOKSUBNET IPADDR TOKSLASH NUMBER { unsigned int Subnet, Counter, Mask; //struct in_addr addr, addr2; Mask = 1; Mask <<= 31; for (Counter = 0, Subnet = 0; Counter < $4; Counter++) { Subnet >>= 1; Subnet |= Mask; } MonitorSubnet(inet_network($2), Subnet); /* SubnetTable[SubnetCount].mask = Subnet; SubnetTable[SubnetCount].ip = inet_network($2) & Subnet; addr.s_addr = ntohl(SubnetTable[SubnetCount].ip); addr2.s_addr = ntohl(SubnetTable[SubnetCount++].mask); syslog(LOG_INFO, "Monitoring subnet %s with netmask %s", inet_ntoa(addr), inet_ntoa(addr2)); */ } ; string: STRING { $1[strlen($1)-1] = '\0'; $$ = $1+1; } ; device: TOKDEV string { config.dev = $2; } ; management_url: TOKMANAGEMENTURL string { config.management_url = $2; } ; description: TOKDESCRIPTION string { config.description = $2; } ; htdocs_dir: TOKHTDOCSDIR string { config.htdocs_dir = $2; } ; log_dir: TOKLOGDIR string { config.log_dir = $2; } ; filter: TOKFILTER string { config.filter = $2; } ; meta_refresh: TOKMETAREFRESH NUMBER { config.meta_refresh = $2; } ; skip_intervals: TOKSKIPINTERVALS NUMBER { config.skip_intervals = $2+1; } ; graph_cutoff: TOKGRAPHCUTOFF NUMBER { config.graph_cutoff = $2*1024; } ; promisc: TOKPROMISC STATE { config.promisc = $2; } ; extensions: TOKEXTENSIONS STATE { config.extensions = $2; } ; output_cdf: TOKOUTPUTCDF STATE { config.output_cdf = $2; } ; recover_cdf: TOKRECOVERCDF STATE { config.recover_cdf = $2; } ; graph: TOKGRAPH STATE { config.graph = $2; } ; pgsql_connect_string: TOKPGSQLCONNECTSTRING string { config.db_connect_string = $2; config.output_database = DB_PGSQL; } ; sensor_name: TOKSENSORID string { config.sensor_name = $2; } ; bandwidthd-2.0.1+cvs20090917/extensions/0000755000175000017500000000000011254363050015545 5ustar gemgembandwidthd-2.0.1+cvs20090917/extensions/errors0000755000175000017500000000006410667337010017013 0ustar gemgem#!/bin/bash ifconfig $1 | egrep "RX|TX|collisions" bandwidthd-2.0.1+cvs20090917/extensions/wireless0000755000175000017500000000003110667337010017326 0ustar gemgem#!/bin/bash iwconfig $1 bandwidthd-2.0.1+cvs20090917/extensions/loadavg0000755000175000017500000000006310667337010017113 0ustar gemgem#!/bin/bash cat /proc/loadavg | awk '{print($2)}'; bandwidthd-2.0.1+cvs20090917/extensions/uptime0000755000175000017500000000006210667337010017000 0ustar gemgem#!/bin/bash cat /proc/uptime | awk '{print($1)}' bandwidthd-2.0.1+cvs20090917/extensions/signal0000755000175000017500000000013410667337010016752 0ustar gemgem#!/bin/bash iwconfig ath0 | grep "Signal level" | awk '{print($4)}' | awk -F: '{print($2)}' bandwidthd-2.0.1+cvs20090917/configure.in0000644000175000017500000001124210337130110015645 0ustar gemgem# Process this file with autoconf to produce a configure script. AC_INIT AC_CANONICAL_HOST AC_CONFIG_SRCDIR([bandwidthd.c]) AC_CONFIG_HEADER([config.h]) MAJOR_VERSION=2 MINOR_VERSION=0 RELEASE_VERSION=0 EXTRA_VERSION="" VERSION="$MAJOR_VERSION.$MINOR_VERSION.$RELEASE_VERSION$EXTRA_VERSION" # Checks for programs. AC_PROG_YACC AC_PROG_CC AC_PROG_INSTALL AC_PROG_LEX # May be required for libgd on bsd AC_PATH_X if test -n "$x_libraries" && test "x$x_libraries" != xNONE ; then LDFLAGS="$LDFLAGS -L$x_libraries" fi # May be equired for BSD LDFLAGS="$LDFLAGS -L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" #Check for Darwin sw directory AC_CHECK_FILE(/sw/lib, LDFLAGS="$LDFLAGS -L/sw/lib") AC_CHECK_FILE(/sw/include, CPPFLAGS="$CPPFLAGS -I/sw/include") #Check for NetBSD usr/pkg directory AC_CHECK_FILE(/usr/pkg/lib, LDFLAGS="$LDFLAGS -L/usr/pkg/lib") AC_CHECK_FILE(/usr/pkg/include, CPPFLAGS="$CPPFLAGS -I/usr/pkg/include") # Required for solaris AC_CHECK_LIB(socket, connect) AC_CHECK_LIB(nsl, gethostbyname) AC_CHECK_LIB(resolv, inet_aton) # Required for openbsd png library AC_CHECK_LIB(m, pow) # Required for gd under netbsd AC_CHECK_LIB(iconv, libiconv_open) # Required Libraries AC_CHECK_LIB(png, png_read_info, ,[AC_MSG_ERROR([Bandwidthd requires but cannot libpng])]) AC_CHECK_LIB(gd, gdImageCreate, ,[AC_MSG_ERROR([Bandwidthd requires but cannot find libgd])]) AC_CHECK_LIB(pcap, pcap_open_live, , [AC_CHECK_LIB(wpcap, pcap_open_live, ,[AC_MSG_ERROR([Bandwidthd requires but cannot find libpcap])])]) # Optional Library AC_CHECK_FILE(/usr/local/pgsql/lib, LDFLAGS="$LDFLAGS -L/usr/local/pgsql/lib") AC_CHECK_FILE(/usr/local/pgsql/include, CPPFLAGS="$CPPFLAGS -I/usr/local/pgsql/include") AC_CHECK_LIB(pq, PQconnectdb, [AC_CHECK_LIB(pq,PQexecParams, ,AC_MSG_WARN([libpq exists but is too old... bandwidthd requires support for PQexecParams]))]) # Checks for header files. AC_HEADER_DIRENT AC_CHECK_HEADERS([gd.h],, [AC_CHECK_HEADERS([gd/gd.h],, AC_MSG_ERROR([Bandwidthd cannot find gd.h]))]) AC_CHECK_HEADERS(gdfonts.h,, [AC_CHECK_HEADERS(gd/gdfonts.h,, AC_MSG_ERROR([Bandwidthd cannot find gdfonts.h]))]) AC_CHECK_HEADERS([pcap.h],, [AC_MSG_ERROR([Bandwidthd cannot find pcap.h])]) AC_CHECK_HEADERS([arpa/inet.h errno.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/socket.h sys/time.h sys/wait.h syslog.h unistd.h],, [AC_MSG_ERROR([Bandwidthd cannot find some header files])]) #Headers missing on cygwin AC_CHECK_HEADERS([arpa/nameser.h]) AC_CHECK_HEADERS([resolv.h],,, [#include #include ]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_PID_T AC_TYPE_SIZE_T AC_STRUCT_TM TCPHDR_SPORT="undefined" AC_CHECK_MEMBER(struct tcphdr.source,TCPHDR_SPORT="source",,[#include "bandwidthd.h"]) AC_CHECK_MEMBER(struct tcphdr.th_sport,TCPHDR_SPORT="th_sport",,[#include "bandwidthd.h"]) if test "$TCPHDR_SPORT" = "undefined" ; then AC_MSG_ERROR([Could not determine souce port field name for tcphdr structure]) fi AC_DEFINE_UNQUOTED(TCPHDR_SPORT,$TCPHDR_SPORT,[source port field name in tcphdr]) TCPHDR_DPORT="undefined" AC_CHECK_MEMBER(struct tcphdr.dest,TCPHDR_DPORT="dest",,[#include "bandwidthd.h"]) AC_CHECK_MEMBER(struct tcphdr.th_dport,TCPHDR_DPORT="th_dport",,[#include "bandwidthd.h"]) if test "$TCPHDR_DPORT" = "undefined" ; then AC_MSG_ERROR([Could not determine dest port field name for tcphdr structure]) fi AC_DEFINE_UNQUOTED(TCPHDR_DPORT,$TCPHDR_DPORT,[dest port field name in tcphdr]) # Checks for library functions. AC_FUNC_MALLOC AC_HEADER_STDC AC_FUNC_MKTIME AC_TYPE_SIGNAL AC_FUNC_STAT AC_CHECK_FUNCS([alarm gethostbyaddr inet_ntoa memset strdup strftime pcap_findalldevs]) # Set directory names AC_ARG_WITH([htdocs-dir], AC_HELP_STRING([--with-htdocs-dir=DIR], [Sets default htdocs directory. Default is LOCALSTATEDIR/bandwidthd/htdocs]), htdocs_dir=${with_htdocs_dir}, htdocs_dir="${localstatedir}/bandwidthd/htdocs") AC_ARG_WITH([log-dir], AC_HELP_STRING([--with-log-dir=DIR], [Sets default cdf log directory. Default is LOCALSTATEDIR/bandwidthd]), log_dir=${with_log_dir}, log_dir="${localstatedir}/bandwidthd") AC_ARG_WITH([extension-dir], AC_HELP_STRING([--with-extension-dir=DIR], [Sets default extension directory. Default is LOCALSTATEDIR/bandwidthd/extensions]), extension_dir=${with_extension_dir}, extension_dir="${localstatedir}/bandwidthd/extensions") config_file="${sysconfdir}/bandwidthd.conf" AC_DEFINE_DIR(CONFIG_FILE, config_file, [Name of bandwidthd.conf]) AC_DEFINE_DIR(LOG_DIR, log_dir, [Name of log directory]) AC_DEFINE_DIR(HTDOCS_DIR, htdocs_dir, [Name of htdocs directory]) AC_DEFINE_DIR(EXTENSION_DIR, extension_dir, [Name of the extensions directory]) AC_OUTPUT(Makefile) bandwidthd-2.0.1+cvs20090917/TODO0000644000175000017500000000122210167515532014041 0ustar gemgemMove output modules to forked section Config switches for sample intervals and graphing ranges # Features requested by people, I make a note of them here in case myself # or someone else wants to come along and implement them. Stoilis: List of IP's to exclude from the page Switch to hide all ip addresses Me: Switch to only graph traffic not to and from the local network (internet traffic only) Change ram datastore: Linked lists with identifiers that store only non-zero traffic, use longs for traffic storage instead of long longs and implement a multiplyer field. will allow implementation of custom ports to graph and reduce ram usage by 70%ish bandwidthd-2.0.1+cvs20090917/Makefile.in0000644000175000017500000000375310337130110015411 0ustar gemgemexec_prefix = @exec_prefix@ prefix = @prefix@ bindir = @bindir@ sysconfdir = @sysconfdir@ localstatedir = @localstatedir@ extensiondir = @extensiondir@ CC = @CC@ LDFLAGS = @LDFLAGS@ @LIBS@ OBS= bandwidthd.o graph.o conf.tab.o conf.l.o pgsql.o extensions.o CFLAGS= -Wall @CFLAGS@ @CPPFLAGS@ @DEFS@ NONWALLCFLAGS= @CFLAGS@ @CPPFLAGS@ @DEFS@ # Profiling #CFLAGS += -Wall -pg -DPROFILE #LDFLAGS += -pg # Debugging #CFLAGS += -Wall -g -DDEBUG all: bandwidthd bandwidthd: $(OBS) bandwidthd.h $(CC) $(CFLAGS) $(OBS) -o bandwidthd $(LDFLAGS) conf.tab.c: conf.y @YACC@ -pbdconfig_ -d conf.y mv y.tab.c conf.tab.c mv y.tab.h conf.tab.h conf.l.c: conf.l @LEX@ -Pbdconfig_ -s -i -t -I conf.l > conf.l.c clean: -rm -f *.o bandwidthd *~ DEADJOE core # Resets us to distributable code distclean: conf.tab.c conf.l.c clean @echo "Deleting all files that don't come with the distribution" -rm -f config.h config.log config.status Makefile # Deletes all derived files # You must have flex, bison, and autoconf to build the source if you run this # Before you can do anything after running this you must run "autoheader; autoconf" real-clean: distclean @echo 'Deleting all derived files, you will need to run' @echo 'autoconf && autoheader && ./configure && make' @echo 'to build the package' -rm -f conf.tab.c conf.tab.h conf.l.c config.h.in configure install: all @INSTALL@ -d $(DESTDIR)$(bindir) @INSTALL@ -d $(DESTDIR)$(sysconfdir) @INSTALL@ -d $(DESTDIR)$(localstatedir)/bandwidthd/htdocs @INSTALL@ -m755 -s bandwidthd $(DESTDIR)$(bindir) if [ ! -f $(DESTDIR)$(sysconfdir)/bandwidthd.conf ] ; then @INSTALL@ -m644 etc/bandwidthd.conf $(DESTDIR)$(sysconfdir); fi @INSTALL@ -m644 htdocs/legend.gif $(DESTDIR)$(localstatedir)/bandwidthd/htdocs @INSTALL@ -m644 htdocs/logo.gif $(DESTDIR)$(localstatedir)/bandwidthd/htdocs #**** Stuff where -WALL is turned off to reduce the noise in a compile so I can see my own errors ******************* conf.l.o: conf.l.c $(CC) $(NONWALLCFLAGS) -c -o conf.l.o conf.l.c bandwidthd-2.0.1+cvs20090917/aclocal.m40000644000175000017500000000046110172352024015204 0ustar gemgemAC_DEFUN([AC_DEFINE_DIR], [ test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' eval ac_define_dir="\"[$]$2\"" eval ac_define_dir="\"[$]ac_define_dir\"" AC_SUBST($1, "$ac_define_dir") AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3]) ]) bandwidthd-2.0.1+cvs20090917/pgsql.c0000644000175000017500000005766611145324327014667 0ustar gemgem#include "bandwidthd.h" #include extern struct config config; extern unsigned int IpCount; extern struct Broadcast *Broadcasts; extern time_t ProgramStart; jmp_buf pgsqljmp; #ifdef HAVE_LIBPQ #include "postgresql/libpq-fe.h" #define MAX_PARAM_SIZE 200 // Check that tables exist and create them if not PGconn *pgsqlCheckTables(PGconn *conn) { PGresult *res; res = PQexec(conn, "select tablename from pg_tables where tablename='sensors';"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql Select failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } if (PQntuples(res) != 1) { PQclear(res); res = PQexec(conn, "CREATE TABLE bd_rx_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, packet_count int, total int, icmp int, udp int, tcp int, ftp int, http int, mail int, p2p int); create index bd_rx_log_sensor_id_ip_timestamp_idx on bd_rx_log (sensor_id, ip, timestamp); create index bd_rx_log_sensor_id_timestamp_idx on bd_rx_log(sensor_id, timestamp);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table bd_rx_log failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "CREATE TABLE bd_tx_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, packet_count int, total int, icmp int, udp int, tcp int, ftp int, http int, mail int, p2p int); create index bd_tx_log_sensor_id_ip_timestamp_idx on bd_tx_log (sensor_id, ip, timestamp); create index bd_tx_log_sensor_id_timestamp_idx on bd_tx_log(sensor_id, timestamp);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table bd_tx_log failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "CREATE TABLE bd_rx_total_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, packet_count int, total int, icmp int, udp int, tcp int, ftp int, http int, mail int, p2p int); create index bd_rx_total_log_sensor_id_timestamp_ip_idx on bd_rx_total_log (sensor_id, timestamp);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table bd_rx_total_log failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "CREATE TABLE bd_tx_total_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, packet_count int, total int, icmp int, udp int, tcp int, ftp int, http int, mail int, p2p int); create index bd_tx_total_log_sensor_id_timestamp_ip_idx on bd_tx_total_log (sensor_id, timestamp);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table bd_tx_total_log failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "CREATE TABLE sensors ( sensor_id serial PRIMARY KEY, sensor_name varchar, location int, build int default 0, uptime interval, reboots int default 0, interface varchar, description varchar, management_url varchar, last_connection timestamp with time zone );"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table sensors failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "CREATE TABLE links (id1 int, id2 int, plot boolean default TRUE, last_update timestamp with time zone);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table links failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); return(conn); } else { PQclear(res); // Patch database to include mail column if it doesn't alread exist res = PQexec(conn, "SELECT table_name, column_name from information_schema.columns where table_name = 'bd_rx_log' and column_name = 'mail';"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql Select failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } if (PQntuples(res) != 1) { PQclear(res); res = PQexec(conn, "alter table bd_rx_log add column mail int;"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Add column failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "alter table bd_tx_log add column mail int;"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Add column failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "alter table bd_rx_total_log add column mail int;"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Add column failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); res = PQexec(conn, "alter table bd_tx_total_log add column mail int;"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Add column failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); } else { PQclear(res); } return(conn); } } PGconn *pgsqlInit(void) { PGconn *conn = NULL; conn = PQconnectdb(config.db_connect_string); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { syslog(LOG_ERR, "Connection to database '%s' failed: %s", config.db_connect_string, PQerrorMessage(conn)); PQfinish(conn); return(NULL); } return(conn); } PGconn *pgsqlDetermineSensorID(PGconn *conn, char *sensor_id, char *sensor_name, char *interface) { const char *paramValues[3]; char Values[2][MAX_PARAM_SIZE]; PGresult *res; paramValues[0] = Values[0]; paramValues[1] = Values[1]; strncpy(Values[0], sensor_name, MAX_PARAM_SIZE); strncpy(Values[1], interface, MAX_PARAM_SIZE); res = PQexecParams(conn, "select sensor_id from sensors where sensor_name = $1 and interface = $2;", 2, /* number of params */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } if (PQntuples(res)) { strncpy(sensor_id, PQgetvalue(res, 0, 0), MAX_PARAM_SIZE); PQclear(res); return(conn); } else { sensor_id[0] = '\0'; return(conn); } } PGconn *pgsqlCreateSensorID(PGconn *conn, char *sensor_id) { const char *paramValues[3]; char Values[3][MAX_PARAM_SIZE]; PGresult *res; paramValues[0] = Values[0]; paramValues[1] = Values[1]; paramValues[2] = Values[2]; res = PQexec(conn, "select nextval('sensors_sensor_id_seq'::Text);"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql select failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } strncpy(sensor_id, PQgetvalue(res, 0, 0), MAX_PARAM_SIZE); PQclear(res); strncpy(Values[0], config.sensor_name, MAX_PARAM_SIZE); strncpy(Values[1], config.dev, MAX_PARAM_SIZE); strncpy(Values[2], sensor_id, MAX_PARAM_SIZE); // Insert new sensor id res = PQexecParams(conn, "insert into sensors (sensor_name, interface, sensor_id) VALUES ($1, $2, $3);", 3, /* number of parameters */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } else { PQclear(res); return(conn); } } PGconn *pgsqlUpdateLinkStatus(PGconn *conn, char *sensor_id) { struct Broadcast *bc; unsigned long diff; const char *paramValues[3]; char Values[3][MAX_PARAM_SIZE]; PGresult *res; paramValues[0] = Values[0]; paramValues[1] = Values[1]; paramValues[2] = Values[2]; for (bc = Broadcasts; bc; bc = bc->next) { strncpy(Values[0], sensor_id, MAX_PARAM_SIZE); // Determine numeric sensor ID of other sensor if (!(conn = pgsqlDetermineSensorID(conn, Values[1], bc->sensor_name, bc->interface))) return(NULL); if (!Values[1][0]) { syslog(LOG_ERR, "Sensor '%s - %s' does not exist in database, skiping link update", bc->sensor_name, bc->interface); continue; } diff = time(NULL) - bc->received; snprintf(Values[2], MAX_PARAM_SIZE, "%lu", diff); res = PQexecParams(conn, "update links set last_update = now()-($3*interval '1 second') where (id1 = $1 and id2 = $2) or (id1 = $2 and id2 = $1);", 3, /* number of parameters */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql Update of links table failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } // There may be duplicate rows if (atol(PQcmdTuples(res)) > 0) { PQclear(res); // Sucess, allow loop to fall through } else { PQclear(res); // Link doesn't exist so we must add it diff = time(NULL) - bc->received; snprintf(Values[2], MAX_PARAM_SIZE, "%lu", diff); res = PQexecParams(conn, "insert into links (id1, id2, last_update) values ($1, $2, now()-($3*interval '1 second'));", 3, /* number of parameters */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql Insert into links table failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } PQclear(res); } } return(conn); } PGconn *pgsqlUpdateSensorStatus(PGconn *conn, char *sensor_id) { const char *paramValues[5]; char Values[5][MAX_PARAM_SIZE]; PGresult *res; paramValues[0] = Values[0]; paramValues[1] = Values[1]; paramValues[2] = Values[2]; paramValues[3] = Values[3]; paramValues[4] = Values[4]; strncpy(Values[0], sensor_id, MAX_PARAM_SIZE); strncpy(Values[1], config.description, MAX_PARAM_SIZE); strncpy(Values[2], config.management_url, MAX_PARAM_SIZE); snprintf(Values[3], MAX_PARAM_SIZE, "%u", BUILD); snprintf(Values[4], MAX_PARAM_SIZE, "%lu", time(NULL)-ProgramStart); res = PQexecParams(conn, "update sensors set description = $2, management_url = $3, last_connection = now(), build = $4, uptime = $5*interval '1 second' where sensor_id = $1;", 5, /* number of parameters */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql UPDATE description and management_url failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } else { PQclear(res); return(conn); } } PGconn *pgsqlIncReboots(PGconn *conn, char *sensor_id) { const char *paramValues[1]; char Values[1][MAX_PARAM_SIZE]; PGresult *res; paramValues[0] = Values[0]; strncpy(Values[0], sensor_id, MAX_PARAM_SIZE); res = PQexecParams(conn, "update sensors set reboots = reboots+1 where sensor_id = $1;", 1, /* number of parameters */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql UPDATE reboots failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return(NULL); } else { PQclear(res); return(conn); } } #endif static void pgsqllngjmp(int signal) { longjmp(pgsqljmp, 1); } void pgsqlStoreIPData(struct IPData IncData[], struct extensions *extension_data) { #ifdef HAVE_LIBPQ static char sensor_id[MAX_PARAM_SIZE] = { '\0' }; static pid_t child = 0; struct IPData *IPData; unsigned int Counter; struct Statistics *Stats; PGresult *res; PGconn *conn = NULL; char now[MAX_PARAM_SIZE]; // This is higher than Values below for the extensions code const char *paramValues[22]; char *sql1; char *sql2; char Values[13][MAX_PARAM_SIZE]; if (!config.output_database == DB_PGSQL) return; // Start of actual work paramValues[0] = Values[0]; paramValues[1] = Values[1]; paramValues[2] = Values[2]; paramValues[3] = Values[3]; paramValues[4] = Values[4]; paramValues[5] = Values[5]; paramValues[6] = Values[6]; paramValues[7] = Values[7]; paramValues[8] = Values[8]; paramValues[9] = Values[9]; paramValues[10] = Values[10]; paramValues[11] = Values[11]; paramValues[12] = Values[12]; // ************ Inititialize the db if it's not already // Do initialization in main thread in order to prevent doing sensor_id work repeatedly if (!sensor_id[0]) // Determine numeric sensor ID { /* I don't know how safe interupting pgsql's calls to the database are, and since we're working in the main process here I picked a higher interval soas to interupt less frequently. If I don't do this, the whole process gets locked up when the database is unreachable so it can only help. */ alarm(config.interval*5); signal(SIGALRM, pgsqllngjmp); if (setjmp(pgsqljmp)) { syslog(LOG_ERR, "Timeout when working with database"); return; } syslog(LOG_INFO, "Initializing database info"); conn = pgsqlInit(); if (!conn) { syslog(LOG_ERR, "Could not connect to database"); alarm(0); return; } if (!(conn = pgsqlCheckTables(conn))) // Create tables if neccisary { syslog(LOG_ERR, "Failed to check or create database tables"); alarm(0); return; } if (!(conn = pgsqlDetermineSensorID(conn, sensor_id, config.sensor_name, config.dev))) { syslog(LOG_ERR, "Failed to determine sensor_id"); alarm(0); return; } if (!sensor_id[0]) // Create a new sensor ID if (!(conn = pgsqlCreateSensorID(conn, sensor_id))) { syslog(LOG_ERR, "Failed to create new sensor_id"); alarm(0); return; } pgsqlIncReboots(conn, sensor_id); PQfinish(conn); conn = NULL; syslog(LOG_INFO, "Sensor ID: %s", sensor_id); alarm(0); } // If we have a valid child see if he has exited if (child > 0) { if (waitpid(child, NULL, WNOHANG) == 0) { syslog(LOG_ERR, "Logging child still active: No response or slow database? Killing child."); kill(child, SIGKILL); waitpid(child, NULL, 0); } } // Fork to allow bandwidthd to operate un-interupted if ((child = fork())) return; conn = pgsqlInit(); if (!conn) { syslog(LOG_ERR, "Could not connect to database"); _exit(2); } // Update sensor state if (!(conn = pgsqlUpdateSensorStatus(conn, sensor_id))) { syslog(LOG_ERR, "Could not update sensor status"); _exit(2); } // Update link state if (!(conn = pgsqlUpdateLinkStatus(conn, sensor_id))) { syslog(LOG_ERR, "Count not update link status"); _exit(2); } // Determine Now res = PQexecParams(conn, "select now();", 0, /* number of params */ NULL, /* let the backend deduce param type */ NULL, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 0); /* ask for binary results */ if (PQresultStatus(res) != PGRES_TUPLES_OK) { syslog(LOG_ERR, "Postresql SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); _exit(2); } strncpy(now, PQgetvalue(res, 0, 0), MAX_PARAM_SIZE); PQclear(res); // Begin transaction // **** Perform inserts strncpy(Values[0], sensor_id, MAX_PARAM_SIZE); strncpy(Values[1], now, MAX_PARAM_SIZE); snprintf(Values[2], MAX_PARAM_SIZE, "%llu", config.interval); for (Counter=0; Counter < IpCount; Counter++) { IPData = &IncData[Counter]; if (IPData->ip == 0) { // This optimization allows us to quickly draw totals graphs for a sensor sql1 = "INSERT INTO bd_tx_total_log (sensor_id, timestamp, sample_duration, ip, packet_count,total, icmp, udp, tcp, ftp, http, mail, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);"; sql2 = "INSERT INTO bd_rx_total_log (sensor_id, timestamp, sample_duration, ip, packet_count,total, icmp, udp, tcp, ftp, http, mail, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);"; } else { sql1 = "INSERT INTO bd_tx_log (sensor_id, timestamp, sample_duration, ip, packet_count, total, icmp, udp, tcp, ftp, http, mail, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);"; sql2 = "INSERT INTO bd_rx_log (sensor_id, timestamp, sample_duration, ip, packet_count, total, icmp, udp, tcp, ftp, http, mail, p2p) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);"; } HostIp2CharIp(IPData->ip, Values[3]); Stats = &(IPData->Send); if (Stats->total > 512) // Don't log empty sets { // Log data in kilobytes snprintf(Values[4], MAX_PARAM_SIZE, "%llu", Stats->packet_count); snprintf(Values[5], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->total)/1024.0) + 0.5)); snprintf(Values[6], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->icmp)/1024.0) + 0.5)); snprintf(Values[7], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->udp)/1024.0) + 0.5)); snprintf(Values[8], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->tcp)/1024.0) + 0.5)); snprintf(Values[9], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->ftp)/1024.0) + 0.5)); snprintf(Values[10], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->http)/1024.0) + 0.5)); snprintf(Values[11], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->mail)/1024.0) + 0.5)); snprintf(Values[12], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->p2p)/1024.0) + 0.5)); res = PQexecParams(conn, sql1, 13, NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 1); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; _exit(2); } PQclear(res); } Stats = &(IPData->Receive); if (Stats->total > 512) // Don't log empty sets { snprintf(Values[4], MAX_PARAM_SIZE, "%llu", Stats->packet_count); snprintf(Values[5], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->total)/1024.0) + 0.5)); snprintf(Values[6], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->icmp)/1024.0) + 0.5)); snprintf(Values[7], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->udp)/1024.0) + 0.5)); snprintf(Values[8], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->tcp)/1024.0) + 0.5)); snprintf(Values[9], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->ftp)/1024.0) + 0.5)); snprintf(Values[10], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->http)/1024.0) + 0.5)); snprintf(Values[11], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->mail)/1024.0) + 0.5)); snprintf(Values[12], MAX_PARAM_SIZE, "%llu", (long long unsigned int)((((double)Stats->p2p)/1024.0) + 0.5)); res = PQexecParams(conn, sql2, 13, NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 1); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; _exit(2); } PQclear(res); } } // Insert extension data if (extension_data) { char *sql; char *ptr; int len, Counter; int fields; struct extensions *extptr; // Allocate SQL buffer; for(extptr = extension_data, len=200, fields=0; extptr; extptr = extptr->next) { len += strlen(extptr->name)+6; fields++; } if (fields > 20) { fields = 20; syslog(LOG_ERR, "pgsql: This module limited to 20 extension fields"); } sql = malloc(len); if (!sql) { syslog(LOG_ERR, "Could not allocate RAM for extension SQL statement. Size: %d", len); PQfinish(conn); conn = NULL; _exit(2); } // Write SQL statement ptr = sql; ptr += sprintf(ptr, "INSERT INTO extension_log (sensor_id, timestamp, "); for(extptr = extension_data, Counter=0; Counter < fields; extptr = extptr->next, Counter++) { ptr += sprintf(ptr, "%s, ", extptr->name); paramValues[Counter+2] = extptr->value; } ptr -= 2; ptr += sprintf(ptr, ") VALUES ($1, $2, "); for(extptr = extension_data, Counter=0; Counter < fields; extptr = extptr->next, Counter++) ptr += sprintf(ptr, "$%d, ", Counter+3); ptr -= 2; ptr += sprintf(ptr, ");"); res = PQexecParams(conn, sql, fields+2, NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 1); /* ask for binary results */ if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql INSERT failed: %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); conn = NULL; _exit(2); } PQclear(res); free(sql); } PQfinish(conn); _exit(0); #else syslog(LOG_ERR, "Postgresql logging selected but postgresql support is not compiled into binary. Please check the documentation in README, distributed with this software."); #endif } bandwidthd-2.0.1+cvs20090917/extensions.c0000644000175000017500000000661310667336733015736 0ustar gemgem#include "bandwidthd.h" #include #include #include #include extern struct config config; static char *execute_extension(char * filename); struct extensions *execute_extensions(void) { struct dirent **namelist; int Counter, n; struct stat statbuffer; char *filename; struct extensions *results = NULL; struct extensions **resptr; char *ptr; resptr = &results; n = scandir(EXTENSION_DIR, &namelist, 0, alphasort); if (n < 0) syslog(LOG_ERR, "Failed to open %s for executing extensions", EXTENSION_DIR); else { for(Counter = 0; Counter < n; Counter++) { filename = malloc(strlen(EXTENSION_DIR)+strlen(namelist[Counter]->d_name)+2); sprintf(filename, "%s/%s", EXTENSION_DIR, namelist[Counter]->d_name); stat(filename, &statbuffer); if (S_ISREG(statbuffer.st_mode)) { ptr = execute_extension(filename); if (ptr) { *resptr = malloc(sizeof(struct extensions)); (*resptr)->name = strdup(namelist[Counter]->d_name); (*resptr)->value = ptr; (*resptr)->next = NULL; resptr = &((*resptr)->next); } } free(filename); free(namelist[Counter]); } free(namelist); } return(results); } static char *execute_extension(char *filename) { int ExtPipe[2]; pid_t extpid; char buffer[1500]; char *res = NULL; char *ptr; ssize_t len; int child; int Counter; fd_set rset; fd_set eset; if (pipe(ExtPipe)) { syslog(LOG_ERR, "Failed to open pipe for extension processing"); return(NULL); } if (!(extpid = fork())) { close(ExtPipe[0]); dup2(ExtPipe[1], 1); execl(filename, filename, config.dev, NULL); syslog(LOG_ERR, "Failed to launch extension %s", filename); _exit(1); } close(ExtPipe[1]); child = 1; while (child) { child = !waitpid(extpid, NULL, WNOHANG); // If child is running drop into a select and wait for data if (child) { FD_ZERO(&rset); FD_SET(ExtPipe[0], &rset); FD_ZERO(&eset); FD_SET(ExtPipe[0], &eset); select(ExtPipe[0]+1, &rset, NULL, &eset, NULL); } len = 1; while (len) { len = read(ExtPipe[0], buffer, 1499); buffer[len] = '\0'; if (res) { ptr = malloc(strlen(res)+len+1); sprintf(ptr, "%s%s", res, buffer); free(res); } else { ptr = malloc(len+1); sprintf(ptr, "%s", buffer); } res = ptr; } } close(ExtPipe[0]); // Trim whitespace from end for(Counter = strlen(res)-1; Counter >= 0; Counter--) { if (res[Counter] == ' ' || res[Counter] == '\t' || res[Counter] == '\r' || res[Counter] == '\n') res[Counter] = '\0'; else break; } // Filter empty responses (Also filters all whitespace responses because of previouse trim) if (strlen(res) < 1) { free(res); return(NULL); } else return(res); } void destroy_extension_data(struct extensions *ext) { struct extensions *ptr; struct extensions *ptr2; ptr = ext; while(ptr) { if (ptr->name) free(ptr->name); if (ptr->value) free(ptr->value); ptr2 = ptr->next; free(ptr); ptr = ptr2; } } /* int main(void) { struct extensions *res; struct extensions *resptr; res = execute_extensions(); resptr = res; while(resptr) { printf("%s\n", resptr->name); printf("%s\n", resptr->value); resptr = resptr->next; } destroy_extensions(res); return(0); } */bandwidthd-2.0.1+cvs20090917/htdocs/0000755000175000017500000000000011254363050014632 5ustar gemgembandwidthd-2.0.1+cvs20090917/htdocs/logo.gif0000755000175000017500000001662507762670022016307 0ustar gemgemGIF87a  3fLyL(u@@}NN ppfAAA쟟7j3pp=lﹿ33Y|33%%%``̙DlY0p SZZަ3怀4`33q))V"a@@PPVVV v:ﯯ@p &ZəCP`Y([!!鏏#IPPBGy{{̳-y)|ffrʙ SwwSw r,+wHTw<rrjwtt+w6wCwaFw@BANDrH Vw`w6w\WCraFw@ ~L˚~#~$h bandwidthd-logo.8l qwLL4+w6wDswaFwDDxl|l|H8lDxlsD8l!, @H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sܹĀPIѣH*MSd~,JիX6}u@֯`¤ت[:=6!ٟfqjp[E׈l9{W^ (^ވ}W2PO^sǾBOF|fbƨS(8Zri^H}F̑%Wư|ECw# {"+.iqk]C"U|sHu mW{xQ! 5({ ݄NfTAj]衇M t|{`BH@ruA"aH8.CiQ (TN@v1(vq]Y Q0!e\"e%r&@ B tfWd t5>ŇyКWB}>%&Bd*J@B9lFv ~:abGjFZjri꫞~I%vŅH5kd} BլR+rD_xI.!0k $wQNu %Є&?k!LAH @Z0A x8~IOp4apPĒDS3FlDxP U } $Pn(1@avx~Cm|O8 +O Gu)re 4~7H 0AxH3U4uD)-Ppa5b[AMD|dVGNЊek~yA~Ӣn騧ꨓǾeO.u/XN+F[P ]|0 Wogw/o觯VA) HLXBL̠IV z0A5P3".ka r7I&A0H O$gwHF /”:4hQS@AE  ĊIt eA>rƚEI-df3uJ[\!F VfoVrҵ(4GKԃ%_YUe%T| > urj(IL*`,) \2 &= ^~…# b SA0j A : @ b@0;eb' 贌:I~h Q 40"g2eS2/ZH泌N'fz`6d#<"B<+dH^AgaHHф4ecuh,fMqI247!B8x+r~TC`OBt V=Nv|60{@GK!Q@ L:!.2atf ְ$L;ڔ!}=lE(Ȑ)~A@z!J(z)f"˼dЩEN*;-l2W%W%] ]\} wӹX:E2/Pf٫b绕.FrRO۩:%{+K$7)7zN4F;ѐ'MJ[Ҙδ7NGxԨNMcAU*QT`MZε+]v5 pA㰍]ϰّVDD a<-h(eih`wÅ([U@z*^;m`%RKTؑ%5UM{!IlppecN.f5i3Oz0olB0ڕO dI1 pc%}:-d;Pԟ_LtS]SVz}uN%xA2ˎz !8čakdT )X#} *\-\X([/1 :,D/:<)aW-~@hrsO|W:ނ^2Wu0tG l %B 2 |M <~{'zA/PeϢ+F Jon3~Txqjv€ ~\"nFhSj1U2q''BVC E)WMĥttU*_`_)20! P*%@!)_ |])=?*A8!u) !ф%ܲKc8!bH]B3EvJRv> z%xzk{3}HMҁ!OUq!;E>MywxwXC$JR a h-$?@xgrAS~"_lvQ&yw4Nq#x}NA2;狆kȇ*7}Qo2#X$0}7/erexGu( sbŎXax5s''RC\SzzQ ~ ]Dxk~mR)]@Iya9%I_37"%9"D%B8 9nWWG)a\f0i)EUMS)^uEv"_YN[ɃBX*RXa!0v$c)Pue$]Y-B!dpUtNW]^+/pQ/)rX$t1(!UU nq<(d7 EHD_%N@!bx42I6G_u6Q0u0CU"8!2AwDxB_PrqS0BxUÚS8#B@4S@B;D[F{HJL۴NPR;fHX{@MqY۵b?c{AlKqpmlA0p+v47wS|:᷀;5!{0a+Ajij;3ij$nTh;j[m@VCќֺf3ؖ@纍vW@炙UmDb15ĻhnҁgNڤX)ޤNRF Ba;-{O؁q>9 ^+[o3ENG.$PP)m!NNQ.@K>#ax5քC#5|*x.oSKz>#[tl~b>|>} GgW3{TǡމE~LΈna`'es I3\!(Ic e>t͈$?D m}"= l˪m9#x@V-}xSa^H>žOB&.E鬘K㽼bXVFXJmS^5jaU2'V>  j .p阝lмWVmnPj{.A?ќ6mj.5[i\z_h~_&5p7ű#d&("5\;lc[d̤#~Պh)EjO:Bx8=9J ,aw|5(o2_&OEѥȇï#a3( YBz*73Wm͎)얱9"P-#!y~eb5M4IdCorSGNX@1@@.&Dxp@ I HH"C=~, MRJ-U*@.Y.XLrV40Od~$0"NURLz3FhA $*Pq <O[P09&d = \FujRaH!-_Ɯyw HCbp"^IA). r0l&Kc.[zś۰c3H4Ict^vݽc9Ա{zB;l;5z/Y nҝ=؊ X R .*BhB6C/b# Q QC.?B4kLjV HH0rqҸPQ" rcý(=K&"D]c '⽆k*HؚǰJ1#}#p(# Z#JH' OJ(x3< t /WeU%D8Z ~:D ;[t˄Js`TJhJ3PdT7X֢h+k ˝ 80#I}GgU<)hʜEY/VWbaM H(XPuc =͖Pt*y\<2Ee+dvXakg]>r6wQ RXulߔZFVevYb 4nDYƈlIfO.~D yfS:qgqߙgdkS%;\mW#9kMߛU پcfcN(l 7_.rjgow柇y<;DܷEŖ@*0?7.u7orF2 M`,8JPR^~)3x-k~1 @X«mzS?b8D"шG" D&PH" RV,"E.vыRb8F2reDc(-z G*Z x&8^ib!z'Z偽*= +1:fY+Ynjj)'%YQCꍨ d.Z>fċJt*q*Oo:(i6,47_JK1&,#_J53803]\0wE9Egyt͂YCP2ܢ#qm'^[nո\3NW]Iygw砇.褗n騧ꬷ.nD;;;bandwidthd-2.0.1+cvs20090917/CHANGELOG0000644000175000017500000001563610172567667014615 0ustar gemgemMake file tweaks Adhere more strictly to GNU coding standards for directories Optional htdocs and log file locations specified at configure time Optional bandwidthd.conf entries to specify htdocs and log file locations Command line option help Command line option for specifying a bandwidthd.conf file Changed signal handling to avoid the parent thread dying from a hup during CDF recovery Fixed bug that could cause segfault if no devices exist that can be captured from and no device is specified in the bandwidthd.conf Fixed bug in CDF recovery that may have been affecting recovery on FreeBSD systems. 2.0.1 Big Feature - Added optional postgresql database logging mode and php for dynamic graph creation from databases. Great for big sites, multiple sensors with very low overhead collect traffic statistics and log them to database. Graphs are created when a user visits the page instead of burning CPU cycles night and day. Logging/Multiple sensor support is completed. Big Feature - Implemented auto conf Ported to and compiles on: ix86 Fedora Core 2 ix86 Solaris 9 ix86 OpenBSD 3.4 ix86 Debian 2.2 ix86 FreeBSD 4.8 AMD64 Fedora Core 3 PPC MaxOsX 10.2 ix86 Microsoft Windows Changed default interval to 200 seconds to save ram and cpu power Huge performance gain in graphing engine due to bug fix (Peak Send and Total Sent strings font operations were being done to each graphic almost 1000 times instead of just 1) Removed need of Sys V IPC shared memeory log rotation on all logs implemented - secondary logs rotate every RANGE?/RANGE1 HUP's Added syslog support, removed all printf's except a few early errors, closed stdin, stdout, and stderr before beginning capture loop Bandwidthd collects the pids of it's children and distributes HUP and TERM signals when issued to the first process Changed yy parser name to bdconfig_ to avoid a bug in BSD Added some semi-colons to conf.y to fix BSD flex/bison compatability bug Fixed bug that caused memory corruption when ram datastore had data on more than IP_NUM ips. Fixed some longs that missed being converted to unsigned long long. Fixed bug in CDF recovery that would cause bandwidthd to ignore some CDF logs during recovery Bandwidthd now checks for ./etc/bandwidthd.conf, and if it doesn't exist it checks for /usr/local/bandwidthd/etc/bandwidthd.conf, if that exists it will chdir("/usr/local/bandwidthd") Fixed problem that caused bandwidthd to sit and never create graphs if graph is set to false do not store data in ram, do not fork unless output_cdf is true log names changed to be consistent so all logs could be rotated with same function 1.2.1b Reduced Loading spam Added filter option to bandwidhtd.conf to specify libpcap filter Fixed problems with YAxis labeling and scaling on high volume networks Skips starting a new graphing run if the last run is still going to prevent fork bomb style box crashes Exits on a configuration error Print out line number of errors in bandwidthd.conf Caused graph_cutoff to be scaled with time range to reduce load induced by weekly/monthly/yearly graphs Fixed bad documentation 1.2.0 10,000 downloads edition! :) Added Weekly, Monthly, and yearly graphs! Bandwidthd will now do a graph run immediatly after loading it's data New 10 Minute (log2.cdf), 1 hour (log3.cdf), and 12 hour (log4.cdf) interval log files Graphing code now scales better with different custom intervals and periods 1.1.8b Fixed bug in support for linux cooked socket DLT_LINUX_SLL (PPPOE, T1, etc) - Christian Laubscher 1.1.8 Wrapped DLT_EN10MB in an ifdef for platforms that don't supply it Fixed bandwidthd crashing when brought up on an ip addressless interface Fixed segfault in DropOldData discovered by Hannes Reich Fixed some errors in Makefile, preserved bandwidthd.conf - Bob Toxen Detected https as http - Bob Toxen Fixed bug that would cause "killall -HUP bandwidthd" to kill the graphing process Initial support for datalink type 12 DLT_RAW Initial support for datalink type 6 token ring DLT_IEEE802 1.1.7 Compiles clean on BSD - Colin Harford - Sheepkiller 1.1.6 Updated Documentation Fixed Segmentation fault in DropOldData, also pointed out by Hannes Reich Modified RecoverCdf to load files from the rotation Added log rotation Modifed RecoverCdf to load large log files much faster Added code by Hannes Reich which loads the contents of the log file back into bandwidthd on restart, so data is persistant between restarts. Alan Evens replaced my bugged sort algorithm with one of his own, fixing the long standing sort issue. 1.1.5 Fixed DLT_LINUX_SLL undefined compile bug by wrapping it in an #ifdef Added date/time to top of html output Added ftp track based on "ftp-data" port numbers Added alternating light blue background to stats table and centered column headers Modified stat table so everything lines up and it's easy to read at low res - Alan Evens 1.1.4 added totals graph Added support for linux cooked sockets, allowing the monitoring of many ppp interfaces and T1's. csv logging made much more usefull, now actually logs the throughput for each interval, not the total acumulated so far. check for ./htdocs and ./etc/bandwidthd.conf so new people don't get confused when they don't run bandwidthd from it's directory. reap zombies every interval, just not when we don't skip. updated documentation 1.1.3 Makefile was broken, bandwidthd could only compile under solaris 1.1.2 Added new logo Increased sample size to 100 bytes in order to avoid future bugs resulting from trying to categorise by information in the tcp header when ip options are present. Source now compiles and works under Solaris with gcc :) 1.1.1 Fixed a bug that caused web and p2p counters not to increment when ip options are present in the packets. Was only capturing 34 bytes of packets instead of 54, http and p2p weren't being incremented because the tcp header was not captured. Older versions of libpcap must have returned full headers regardless of pcap size. 1.1.0 Added a logo.gif to the package Added "skip_intervals" option to the config file Added "graph_cutoff" option to the config file Added "promiscuous" option to the config file (Allows graphing of traffic not routed through the host) Changed default to promiscuous Added "output_cdf" option to the config file (Logs bandwidthd data to comma deliminated file) Added "graph" option to the config file (Set to false to suppress drawing of the graphs) When IpCount (Number of ip's being tracked) exceed IP_NUM (Max number of IP's) stop tracking new ip's instead of exiting Added legend to graphs Added CHANGELOG Updated Documentation Added credits to bottom of top20 web page 1.0.0 Changed all statistics storage to type "long long" to avoid roll over Updated documentation Added "make dist-clean" to force rebuild of flex and bison output Modifed make file to allow building without flex and bison Removed some debugging macros that wouldn't compile under old versions of gcc Modifed RDNS code to complain less and use longjump less 0.46 Initial public release bandwidthd-2.0.1+cvs20090917/graph.c0000644000175000017500000010447411145324327014630 0ustar gemgem#include #include #include #include #include #include #include #include #include #include "bandwidthd.h" #ifdef HAVE_ARPA_NAMESER_H #include #endif #ifdef HAVE_RESOLV_H #include #endif extern unsigned int SubnetCount; extern struct config config; jmp_buf dnsjump; static void rdnslngjmp(int signal); void rdns(char *Buffer, unsigned long IP) // This takes over sigalarm! { #ifdef HAVE_RESOLV_H char DNSError[] = "DNS Timeout: Correct to speed up graphing"; char None[] = "Configure DNS to reverse this IP"; char TooManyDNSTimeouts[] = "Too many dns timeouts, reverse lookups suspended"; struct hostent *hostent; char chrIP[50]; static int Init = TRUE; static int DNSTimeouts = 0; // This is reset for each run because we're forked unsigned long addr = htonl(IP); _res.retrans = 1; _res.retry = 2; if (Init) { signal(SIGALRM, rdnslngjmp); Init = FALSE; } if (DNSTimeouts > 100) { syslog(LOG_ERR, "Too many dns timeouts, reverse lookups suspended"); strncpy(Buffer, TooManyDNSTimeouts, 253); Buffer[254] = '\0'; return; } if (setjmp(dnsjump) == 0) { alarm(10); // Don't let gethostbyaddr hold us up too long hostent = gethostbyaddr((char *) &addr, 4, AF_INET); // (char *)&Data->IP alarm(0); if (hostent) sprintf(Buffer, "%s", hostent->h_name); else { strncpy(Buffer, None, 253); Buffer[254] = '\0'; } } else // Our alarm timed out { HostIp2CharIp(IP, chrIP); syslog(LOG_ERR, "DNS timeout for %s: This problem reduces graphing performance", chrIP); DNSTimeouts++; strncpy(Buffer, DNSError, 253); Buffer[254] = '\0'; } #else Buffer[0] = '\0'; #endif } static void rdnslngjmp(int signal) { longjmp(dnsjump, 1); } void swap(struct SummaryData **a, struct SummaryData **b) { struct SummaryData *temp; temp = *a; *a = *b; *b = temp; } void QuickSortSummaryData(struct SummaryData *SummaryData[], int left, int right) { int i,j,center; unsigned long long pivot; if (left==right) return; if (left+1==right) { if (SummaryData[left]->Total < SummaryData[right]->Total) swap(&SummaryData[left],&SummaryData[right]); return; } /* use the median-of-three method for picking pivot */ center = (left+right)/2; if (SummaryData[left]->Total < SummaryData[center]->Total) swap(&SummaryData[left],&SummaryData[center]); if (SummaryData[left]->Total < SummaryData[right]->Total) swap(&SummaryData[left],&SummaryData[right]); if (SummaryData[center]->Total < SummaryData[right]->Total) swap(&SummaryData[center],&SummaryData[right]); pivot = SummaryData[center]->Total; swap(&SummaryData[center],&SummaryData[right-1]); /* hide the pivot */ i = left; j = right - 1; do { do { ++i; } while (SummaryData[i]->Total > pivot); do { --j; } while (SummaryData[j]->Total < pivot); swap(&SummaryData[i],&SummaryData[j]); } while (j > i); swap(&SummaryData[i],&SummaryData[j]); /* undo last swap */ swap(&SummaryData[i],&SummaryData[right-1]); /* restore pivot */ QuickSortSummaryData(SummaryData,left,i-1); QuickSortSummaryData(SummaryData,i+1,right); } #define NumFactor 1024 static void FormatNum(unsigned long long n, char *buf, int len) { double f; if (n%i ",(int)n); return; } f = n; f /= NumFactor; if (f%.1fK",f); return; } f /= NumFactor; if (f%.1fM",f); return; } f /= NumFactor; if (f%.1fG",f); return; } f /= NumFactor; snprintf(buf,len,"%.1fT\n",f); } void PrintTableLine(FILE *stream, struct SummaryData *Data, int Counter) { char Buffer1[50]; char Buffer2[50]; char Buffer3[50]; char Buffer4[50]; char Buffer4b[50]; char Buffer5[50]; char Buffer5b[50]; char Buffer5c[50]; char Buffer6[50]; char Buffer7[50]; char Buffer8[50]; // First convert the info to nice, human readable stuff if (Data->IP == 0) strcpy(Buffer1, "Total"); else HostIp2CharIp(Data->IP, Buffer1); FormatNum(Data->Total, Buffer2, 50); FormatNum(Data->TotalSent, Buffer3, 50); FormatNum(Data->TotalReceived, Buffer4, 50); FormatNum(Data->FTP, Buffer4b, 50); FormatNum(Data->HTTP, Buffer5, 50); FormatNum(Data->MAIL, Buffer5c, 50); FormatNum(Data->P2P, Buffer5b, 50); FormatNum(Data->TCP, Buffer6, 50); FormatNum(Data->UDP, Buffer7, 50); FormatNum(Data->ICMP, Buffer8, 50); if (Counter%4 == 0 || (Counter-1)%4 == 0) fprintf(stream, ""); else fprintf(stream, ""); if (Data->Graph) fprintf(stream, "%s%s%s%s%s%s%s%s%s%s%s\n", Buffer1, // Ip config.tag, Buffer1, // Ip Buffer2, // Total Buffer3, // TotalSent Buffer4, // TotalReceived Buffer4b, // FTP Buffer5, // HTTP Buffer5c, // Mail Buffer5b, // P2P Buffer6, // TCP Buffer7, // UDP Buffer8); // ICMP else fprintf(stream, "%s%s%s%s%s%s%s%s%s%s%s\n", Buffer1, // Ip Buffer2, // Total Buffer3, // TotalSent Buffer4, // TotalReceived Buffer4b, // FTP Buffer5, // HTTP Buffer5c, // Mail Buffer5b, // P2P Buffer6, // TCP Buffer7, // UDP Buffer8); // ICMP } void MakeIndexPages(int NumIps, struct SummaryData *SummaryData[]) { int SubnetCounter; int Counter, tCounter; time_t WriteTime; char filename[MAX_FILENAME]; char *PeriodDesc; FILE *file; char Buffer1[50]; char Buffer2[50]; char HostName[255]; WriteTime = time(NULL); QuickSortSummaryData(SummaryData, 0, NumIps-1); //////////////////////////////////////////////// // Print main index page if (config.tag == '1') { snprintf(filename, MAX_FILENAME, "%s/index.html", config.htdocs_dir); if ((file = fopen(filename, "wt")) == NULL) { syslog(LOG_ERR, "Failed to open %s", filename); exit(1); } } else { snprintf(filename, MAX_FILENAME, "%s/index%c.html", config.htdocs_dir, config.tag); if ((file = fopen(filename, "wt")) == NULL) { syslog(LOG_ERR, "Failed to open %s", filename); exit(1); } } switch (config.tag) { case '1': PeriodDesc = "Daily"; break; case '2': PeriodDesc = "Weekly"; break; case '3': PeriodDesc = "Monthly"; break; case '4': PeriodDesc = "Yearly"; break; default: PeriodDesc = ""; break; } fprintf(file, "\n"); fprintf(file, "\n\nBandwidthd\n"); if (config.meta_refresh) fprintf(file, "\n", config.meta_refresh); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n\n%s
\n
\"Logo\"
\n", ctime(&WriteTime)); fprintf(file, "Programmed by David Hinkle, Commissioned by DerbyTech wireless networking.
"); fprintf(file, "
\n - Daily -- Weekly -- "); fprintf(file, "Monthly -- Yearly -
\n"); fprintf(file, "
\nPick a Subnet:
\n"); if (config.tag == '1') fprintf(file, "- Top20 -"); else fprintf(file, "- Top20 -", config.tag); for (Counter = 0; Counter < SubnetCount; Counter++) { HostIp2CharIp(SubnetTable[Counter].ip, Buffer1); fprintf(file, "- %s -", config.tag, Buffer1, Buffer1); } ///// TOP 20 fprintf(file, "

Top 20 IPs by Traffic - %s

", PeriodDesc); fprintf(file, "
\n\n"); // PASS 1: Write out the table fprintf(file, "
Ip and NameTotalTotal SentTotal ReceivedFTPHTTPP2PTCPUDPICMP\n"); for (Counter=0; Counter < 21 && Counter < NumIps; Counter++) PrintTableLine(file, SummaryData[Counter], Counter); fprintf(file, "
\n"); // PASS 2: The graphs for (Counter=0; Counter < 21 && Counter < NumIps; Counter++) if (SummaryData[Counter]->Graph) { if (SummaryData[Counter]->IP == 0) { strcpy(Buffer1, "Total"); strcpy(HostName, "Total of all subnets"); } else { HostIp2CharIp(SummaryData[Counter]->IP, Buffer1); rdns(HostName, SummaryData[Counter]->IP); } fprintf(file, "

(Top) %s - %s


\nSend:
\n\"Sent
\n\"Legend\"
\nReceived:
\n\"Sent
\n\"Legend\"
\n
\n", Buffer1, config.tag, Buffer1, HostName, Buffer1, config.tag, Buffer1, Buffer1, config.tag, Buffer1); } fprintf(file, "\n"); fclose(file); //////////////////////////////////////////////// // Print each subnet page for (SubnetCounter = 0; SubnetCounter < SubnetCount; SubnetCounter++) { HostIp2CharIp(SubnetTable[SubnetCounter].ip, Buffer1); snprintf(filename, MAX_FILENAME, "%s/Subnet-%c-%s.html", config.htdocs_dir, config.tag, Buffer1); if ((file = fopen(filename, "wt")) == NULL) { syslog(LOG_ERR, "Failed to open %s", filename); exit(1); } fprintf(file, "\n"); fprintf(file, "\nBandwidthd - Subnet %s\n", Buffer1); if (config.meta_refresh) fprintf(file, "\n", config.meta_refresh); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n\n%s
\n
", ctime(&WriteTime)); fprintf(file, "\"Logo\"
"); fprintf(file, "Programmed by David Hinkle, Commissioned by DerbyTech wireless networking.
\n"); fprintf(file, "
\n - Daily -- Weekly -- "); fprintf(file, "Monthly -- Yearly -
\n"); fprintf(file, "
\nPick a Subnet:
\n"); if (config.tag == '1') fprintf(file, "- Top20 -"); else fprintf(file, "- Top20 -", config.tag); for (Counter = 0; Counter < SubnetCount; Counter++) { HostIp2CharIp(SubnetTable[Counter].ip, Buffer2); fprintf(file, "- %s -", config.tag, Buffer2, Buffer2); } fprintf(file, "

%s - %s

", Buffer1, PeriodDesc); fprintf(file, "\n"); // PASS 1: Write out the table fprintf(file, "
Ip and NameTotalTotal SentTotal ReceivedFTPHTTPP2PTCPUDPICMP\n"); for (tCounter=0, Counter=0; Counter < NumIps; Counter++) { if (SubnetTable[SubnetCounter].ip == (SummaryData[Counter]->IP & SubnetTable[SubnetCounter].mask)) { // The ip belongs to this subnet PrintTableLine(file, SummaryData[Counter], tCounter++); } } fprintf(file, "
\n"); // PASS 2: The graphs for (Counter=0; Counter < NumIps; Counter++) { if (SubnetTable[SubnetCounter].ip == (SummaryData[Counter]->IP & SubnetTable[SubnetCounter].mask)) { // The ip belongs to this subnet if (SummaryData[Counter]->Graph) { HostIp2CharIp(SummaryData[Counter]->IP, Buffer1); rdns(HostName, SummaryData[Counter]->IP); fprintf(file, "

(Top) %s - %s


\nSend:
\n\"Sent
\n\"Legend\"
\nReceived:
\n\"Received
\n\"Legend\"
\n
\n", Buffer1, config.tag, Buffer1, HostName, Buffer1, config.tag, Buffer1, Buffer1, config.tag, Buffer1); } } } fprintf(file, "\n"); fclose(file); } free(SummaryData); } void GraphIp(struct IPDataStore *DataStore, struct SummaryData *SummaryData, time_t timestamp) { FILE *OutputFile; char filename[MAX_FILENAME]; gdImagePtr im, im2; int white; unsigned long long int YMax; char CharIp[20]; time_t GraphBeginTime; // TODO: First determine if graph will be printed before creating image and drawing backround, etc if (DataStore->ip == 0) strcpy(CharIp, "Total"); else HostIp2CharIp(DataStore->ip, CharIp); GraphBeginTime = timestamp - config.range; im = gdImageCreate(XWIDTH, YHEIGHT); white = gdImageColorAllocate(im, 255, 255, 255); //gdImageFill(im, 10, 10, white); im2 = gdImageCreate(XWIDTH, YHEIGHT); white = gdImageColorAllocate(im2, 255, 255, 255); //gdImageFill(im2, 10, 10, white); YMax = GraphData(im, im2, DataStore, GraphBeginTime, SummaryData); if (YMax != 0) { // Finish the graph PrepareXAxis(im, timestamp); PrepareYAxis(im, YMax); PrepareXAxis(im2, timestamp); PrepareYAxis(im2, YMax); snprintf(filename, MAX_FILENAME, "%s/%s-%c-S.png", config.htdocs_dir, CharIp, config.tag); if ((OutputFile = fopen(filename, "wb")) == NULL) { syslog(LOG_ERR, "Failed to open %s", filename); exit(1); } gdImagePng(im, OutputFile); fclose(OutputFile); snprintf(filename, MAX_FILENAME, "%s/%s-%c-R.png", config.htdocs_dir, CharIp, config.tag); if ((OutputFile = fopen(filename, "wb")) == NULL) { syslog(LOG_ERR, "Failed to open %s", filename); exit(1); } gdImagePng(im2, OutputFile); fclose(OutputFile); } else { // The graph isn't worth clutering up the web pages with sprintf(filename, "%s/htdocs/%s-%c-R.png", config.htdocs_dir, CharIp, config.tag); unlink(filename); sprintf(filename, "%s/htdocs/%s-%c-S.png", config.htdocs_dir, CharIp, config.tag); unlink(filename); } gdImageDestroy(im); gdImageDestroy(im2); } // Returns YMax unsigned long long int GraphData(gdImagePtr im, gdImagePtr im2, struct IPDataStore *DataStore, time_t timestamp, struct SummaryData *SummaryData) { unsigned long long int YMax=0; struct DataStoreBlock *CurrentBlock; struct IPData *Data; // TODO: These should be a structure!!!! // TODO: This is an awfull lot of data to be allocated on the stack unsigned long long total[XWIDTH]; unsigned long long icmp[XWIDTH]; unsigned long long udp[XWIDTH]; unsigned long long tcp[XWIDTH]; unsigned long long ftp[XWIDTH]; unsigned long long http[XWIDTH]; unsigned long long mail[XWIDTH]; unsigned long long p2p[XWIDTH]; int Count[XWIDTH]; unsigned long long total2[XWIDTH]; unsigned long long icmp2[XWIDTH]; unsigned long long udp2[XWIDTH]; unsigned long long tcp2[XWIDTH]; unsigned long long ftp2[XWIDTH]; unsigned long long mail2[XWIDTH]; unsigned long long http2[XWIDTH]; unsigned long long p2p2[XWIDTH]; size_t DataPoints; double x; int xint; int Counter; char Buffer[30]; char Buffer2[50]; int blue, lblue, orange, red, yellow, purple, green, brown, black; int blue2, lblue2, orange2, red2, yellow2, purple2, green2, brown2, black2; unsigned long long int SentPeak = 0; unsigned long long int ReceivedPeak = 0; yellow = gdImageColorAllocate(im, 255, 255, 0); purple = gdImageColorAllocate(im, 255, 0, 255); green = gdImageColorAllocate(im, 0, 255, 0); blue = gdImageColorAllocate(im, 0, 0, 255); lblue = gdImageColorAllocate(im, 128, 128, 255); orange = gdImageColorAllocate(im, 255, 128, 0); brown = gdImageColorAllocate(im, 128, 0, 0); red = gdImageColorAllocate(im, 255, 0, 0); black = gdImageColorAllocate(im, 0, 0, 0); yellow2 = gdImageColorAllocate(im2, 255, 255, 0); purple2 = gdImageColorAllocate(im2, 255, 0, 255); green2 = gdImageColorAllocate(im2, 0, 255, 0); blue2 = gdImageColorAllocate(im2, 0, 0, 255); lblue2 = gdImageColorAllocate(im2, 128, 128, 255); orange2 = gdImageColorAllocate(im2, 255, 128, 0); brown2 = gdImageColorAllocate(im2, 128, 0, 0); red2 = gdImageColorAllocate(im2, 255, 0, 0); black2 = gdImageColorAllocate(im2, 0, 0, 0); CurrentBlock = DataStore->FirstBlock; Data = CurrentBlock->Data; DataPoints = CurrentBlock->NumEntries; memset(SummaryData, 0, sizeof(struct SummaryData)); SummaryData->IP = Data[0].ip; memset(Count, 0, sizeof(Count[0])*XWIDTH); memset(total, 0, sizeof(total[0])*XWIDTH); memset(icmp, 0, sizeof(total[0])*XWIDTH); memset(udp, 0, sizeof(total[0])*XWIDTH); memset(tcp, 0, sizeof(total[0])*XWIDTH); memset(ftp, 0, sizeof(total[0])*XWIDTH); memset(http, 0, sizeof(total[0])*XWIDTH); memset(mail, 0, sizeof(total[0])*XWIDTH); memset(p2p, 0, sizeof(total[0])*XWIDTH); memset(total2, 0, sizeof(total[0])*XWIDTH); memset(icmp2, 0, sizeof(total[0])*XWIDTH); memset(udp2, 0, sizeof(total[0])*XWIDTH); memset(tcp2, 0, sizeof(total[0])*XWIDTH); memset(ftp2, 0, sizeof(total[0])*XWIDTH); memset(http2, 0, sizeof(total[0])*XWIDTH); memset(mail2, 0, sizeof(total[0])*XWIDTH); memset(p2p2, 0, sizeof(total[0])*XWIDTH); // Change this to just run through all the datapoints we have stored in ram // Sum up the bytes/second while(DataPoints > 0) // We have data to graph { for (Counter = 0; Counter < DataPoints; Counter++) // Graph it all { x = (Data[Counter].timestamp-timestamp)*((XWIDTH-XOFFSET)/config.range)+XOFFSET; xint = x; if (xint >= 0 && xint < XWIDTH) { Count[xint]++; if (Data[Counter].Send.total > SentPeak) SentPeak = Data[Counter].Send.total; total[xint] += Data[Counter].Send.total; icmp[xint] += Data[Counter].Send.icmp; udp[xint] += Data[Counter].Send.udp; tcp[xint] += Data[Counter].Send.tcp; ftp[xint] += Data[Counter].Send.ftp; http[xint] += Data[Counter].Send.http; mail[xint] += Data[Counter].Send.mail; p2p[xint] += Data[Counter].Send.p2p; if (Data[Counter].Receive.total > ReceivedPeak) ReceivedPeak = Data[Counter].Receive.total; total2[xint] += Data[Counter].Receive.total; icmp2[xint] += Data[Counter].Receive.icmp; udp2[xint] += Data[Counter].Receive.udp; tcp2[xint] += Data[Counter].Receive.tcp; ftp2[xint] += Data[Counter].Receive.ftp; http2[xint] += Data[Counter].Receive.http; mail2[xint] += Data[Counter].Receive.mail; p2p2[xint] += Data[Counter].Receive.p2p; } } CurrentBlock = CurrentBlock->Next; if (CurrentBlock) { Data = CurrentBlock->Data; DataPoints = CurrentBlock->NumEntries; } else DataPoints = 0; } // Convert SentPeak and ReceivedPeak from bytes to bytes/second SentPeak /= config.interval; ReceivedPeak /= config.interval; // Preform the Average for(Counter=XOFFSET+1; Counter < XWIDTH; Counter++) { if (Count[Counter] > 0) { SummaryData->Total += total[Counter] + total2[Counter]; SummaryData->TotalSent += total[Counter]; SummaryData->TotalReceived += total2[Counter]; SummaryData->TCP += tcp[Counter] + tcp2[Counter]; SummaryData->FTP += ftp[Counter] + ftp2[Counter]; SummaryData->HTTP += http[Counter] + http2[Counter]; SummaryData->MAIL += mail[Counter] + mail2[Counter]; SummaryData->P2P += p2p[Counter] + p2p2[Counter]; SummaryData->UDP += udp[Counter] + udp2[Counter]; SummaryData->ICMP += icmp[Counter] + icmp2[Counter]; // Preform the average total[Counter] /= (Count[Counter]*config.interval); tcp[Counter] /= (Count[Counter]*config.interval); ftp[Counter] /= (Count[Counter]*config.interval); http[Counter] /= (Count[Counter]*config.interval); mail[Counter] /= (Count[Counter]*config.interval); p2p[Counter] /= (Count[Counter]*config.interval); udp[Counter] /= (Count[Counter]*config.interval); icmp[Counter] /= (Count[Counter]*config.interval); total2[Counter] /= (Count[Counter]*config.interval); tcp2[Counter] /= (Count[Counter]*config.interval); ftp2[Counter] /= (Count[Counter]*config.interval); http2[Counter] /= (Count[Counter]*config.interval); mail2[Counter] /= (Count[Counter]*config.interval); p2p2[Counter] /= (Count[Counter]*config.interval); udp2[Counter] /= (Count[Counter]*config.interval); icmp2[Counter] /= (Count[Counter]*config.interval); if (total[Counter] > YMax) YMax = total[Counter]; if (total2[Counter] > YMax) YMax = total2[Counter]; } } YMax += YMax*0.05; // Add an extra 5% if ((SummaryData->IP != 0 && SummaryData->Total < config.graph_cutoff)) { SummaryData->Graph = FALSE; return(0); } else SummaryData->Graph = TRUE; // Plot the points for(Counter=XOFFSET+1; Counter < XWIDTH; Counter++) { if (Count[Counter] > 0) { // Convert the bytes/sec to y coords total[Counter] = (total[Counter]*(YHEIGHT-YOFFSET))/YMax; tcp[Counter] = (tcp[Counter]*(YHEIGHT-YOFFSET))/YMax; ftp[Counter] = (ftp[Counter]*(YHEIGHT-YOFFSET))/YMax; http[Counter] = (http[Counter]*(YHEIGHT-YOFFSET))/YMax; mail[Counter] = (mail[Counter]*(YHEIGHT-YOFFSET))/YMax; p2p[Counter] = (p2p[Counter]*(YHEIGHT-YOFFSET))/YMax; udp[Counter] = (udp[Counter]*(YHEIGHT-YOFFSET))/YMax; icmp[Counter] = (icmp[Counter]*(YHEIGHT-YOFFSET))/YMax; total2[Counter] = (total2[Counter]*(YHEIGHT-YOFFSET))/YMax; tcp2[Counter] = (tcp2[Counter]*(YHEIGHT-YOFFSET))/YMax; ftp2[Counter] = (ftp2[Counter]*(YHEIGHT-YOFFSET))/YMax; http2[Counter] = (http2[Counter]*(YHEIGHT-YOFFSET))/YMax; mail2[Counter] = (mail2[Counter]*(YHEIGHT-YOFFSET))/YMax; p2p2[Counter] = (p2p2[Counter]*(YHEIGHT-YOFFSET))/YMax; udp2[Counter] = (udp2[Counter]*(YHEIGHT-YOFFSET))/YMax; icmp2[Counter] = (icmp2[Counter]*(YHEIGHT-YOFFSET))/YMax; // Stack 'em up! // Total is stacked from the bottom // Icmp is on the bottom too // Udp is stacked on top of icmp udp[Counter] += icmp[Counter]; udp2[Counter] += icmp2[Counter]; // TCP and p2p are stacked on top of Udp tcp[Counter] += udp[Counter]; tcp2[Counter] += udp2[Counter]; p2p[Counter] += udp[Counter]; p2p2[Counter] += udp2[Counter]; // Http is stacked on top of p2p http[Counter] += p2p[Counter]; http2[Counter] += p2p2[Counter]; // Mail is stacked on top of http mail[Counter] += http[Counter]; mail2[Counter] += http2[Counter]; // Ftp is stacked on top of mail ftp[Counter] += mail[Counter]; ftp2[Counter] += mail2[Counter]; // Plot them! // Sent gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - total[Counter], Counter, YHEIGHT-YOFFSET-1, yellow); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - icmp[Counter], Counter, YHEIGHT-YOFFSET-1, red); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - udp[Counter], Counter, (YHEIGHT-YOFFSET) - icmp[Counter] - 1, brown); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - tcp[Counter], Counter, (YHEIGHT-YOFFSET) - udp[Counter] - 1, green); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - p2p[Counter], Counter, (YHEIGHT-YOFFSET) - udp[Counter] - 1, purple); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - http[Counter], Counter, (YHEIGHT-YOFFSET) - p2p[Counter] - 1, blue); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - mail[Counter], Counter, (YHEIGHT-YOFFSET) - http[Counter] - 1, orange); gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - ftp[Counter], Counter, (YHEIGHT-YOFFSET) - mail[Counter] - 1, lblue); // Receive gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - total2[Counter], Counter, YHEIGHT-YOFFSET-1, yellow2); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - icmp2[Counter], Counter, YHEIGHT-YOFFSET-1, red2); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - udp2[Counter], Counter, (YHEIGHT-YOFFSET) - icmp2[Counter] - 1, brown2); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - tcp2[Counter], Counter, (YHEIGHT-YOFFSET) - udp2[Counter] - 1, green2); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - p2p2[Counter], Counter, (YHEIGHT-YOFFSET) - udp2[Counter] - 1, purple2); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - http2[Counter], Counter, (YHEIGHT-YOFFSET) - p2p2[Counter] - 1, blue2); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - mail2[Counter], Counter, (YHEIGHT-YOFFSET) - http2[Counter] - 1, orange); gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - ftp2[Counter], Counter, (YHEIGHT-YOFFSET) - mail2[Counter] - 1, lblue2); } } if (SentPeak < 1024/8) snprintf(Buffer2, 50, "Peak Send Rate: %.1f Bits/sec", (double)SentPeak*8); else if (SentPeak < (1024*1024)/8) snprintf(Buffer2, 50, "Peak Send Rate: %.1f KBits/sec", ((double)SentPeak*8.0)/1024.0); else snprintf(Buffer2, 50, "Peak Send Rate: %.1f MBits/sec", ((double)SentPeak*8.0)/(1024.0*1024.0)); if (SummaryData->TotalSent < 1024) snprintf(Buffer, 30, "Sent %.1f Bytes", (double)SummaryData->TotalSent); else if (SummaryData->TotalSent < 1024*1024) snprintf(Buffer, 30, "Sent %.1f KBytes", (double)SummaryData->TotalSent/1024.0); else snprintf(Buffer, 30, "Sent %.1f MBytes", (double)SummaryData->TotalSent/(1024.0*1024.0)); gdImageString(im, gdFontSmall, XOFFSET+5, YHEIGHT-20, Buffer, black); gdImageString(im, gdFontSmall, XWIDTH/2+XOFFSET/2, YHEIGHT-20, Buffer2, black); if (ReceivedPeak < 1024/8) snprintf(Buffer2, 50, "Peak Receive Rate: %.1f Bits/sec", (double)ReceivedPeak*8); else if (ReceivedPeak < (1024*1024)/8) snprintf(Buffer2, 50, "Peak Receive Rate: %.1f KBits/sec", ((double)ReceivedPeak*8.0)/1024.0); else snprintf(Buffer2, 50, "Peak Receive Rate: %.1f MBits/sec", ((double)ReceivedPeak*8.0)/(1024.0*1024.0)); if (SummaryData->TotalReceived < 1024) snprintf(Buffer, 30, "Received %.1f Bytes", (double)SummaryData->TotalReceived); else if (SummaryData->TotalReceived < 1024*1024) snprintf(Buffer, 30, "Received %.1f KBytes", (double)SummaryData->TotalReceived/1024.0); else snprintf(Buffer, 30, "Received %.1f MBytes", (double)SummaryData->TotalReceived/(1024.0*1024.0)); gdImageString(im2, gdFontSmall, XOFFSET+5, YHEIGHT-20, Buffer, black2); gdImageString(im2, gdFontSmall, XWIDTH/2+XOFFSET/2, YHEIGHT-20, Buffer2, black2); return(YMax); } void PrepareYAxis(gdImagePtr im, unsigned long long int YMax) { char buffer[20]; char YLegend; long long int Divisor; int black; float YTic = 0; double y; long int YStep; black = gdImageColorAllocate(im, 0, 0, 0); gdImageLine(im, XOFFSET, 0, XOFFSET, YHEIGHT, black); YLegend = ' '; Divisor = 1; if (YMax*8 > 1024*2) { Divisor = 1024; // Display in K YLegend = 'k'; } if (YMax*8 > 1024*1024*2) { Divisor = 1024*1024; // Display in M YLegend = 'm'; } if (YMax*8 > (long long)1024*1024*1024*2) { Divisor = 1024*1024*1024; // Display in G YLegend = 'g'; } YStep = YMax/10; if (YStep < 1) YStep=1; YTic=YStep; while (YTic < (YMax - YMax/10)) { y = (YHEIGHT-YOFFSET)-((YTic*(YHEIGHT-YOFFSET))/YMax); gdImageLine(im, XOFFSET, y, XWIDTH, y, black); snprintf(buffer, 20, "%4.1f %cbits/s", (float)(8.0*YTic)/Divisor, YLegend); gdImageString(im, gdFontSmall, 3, y-7, buffer, black); YTic += YStep; } } void PrepareXAxis(gdImagePtr im, time_t timestamp) { char buffer[100]; int black, red; time_t sample_begin, sample_end; struct tm *timestruct; long int MarkTime; long int MarkTimeStep; double x; sample_begin=timestamp-config.range; sample_end=sample_begin+config.interval; black = gdImageColorAllocate(im, 0, 0, 0); red = gdImageColorAllocate(im, 255, 0, 0); gdImageLine(im, 0, YHEIGHT-YOFFSET, XWIDTH, YHEIGHT-YOFFSET, black); // ******************************************************************** // **** Write the red day/month seperator bars // ******************************************************************** if ((24*60*60*(XWIDTH-XOFFSET))/config.range > (XWIDTH-XOFFSET)/10) { // Day bars timestruct = localtime((time_t *)&sample_begin); timestruct->tm_sec = 0; timestruct->tm_min = 0; timestruct->tm_hour = 0; MarkTime = mktime(timestruct); x = (MarkTime-sample_begin)*( ((double)(XWIDTH-XOFFSET)) / config.range) + XOFFSET; while (x < XOFFSET) { MarkTime += (24*60*60); x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } while (x < (XWIDTH-10)) { // Day Lines gdImageLine(im, x, 0, x, YHEIGHT-YOFFSET, red); gdImageLine(im, x+1, 0, x+1, YHEIGHT-YOFFSET, red); timestruct = localtime((time_t *)&MarkTime); strftime(buffer, 100, "%a, %b %d", timestruct); gdImageString(im, gdFontSmall, x-30, YHEIGHT-YOFFSET+10, buffer, black); // Calculate Next x MarkTime += (24*60*60); x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } } else { // Month Bars timestruct = localtime((time_t *)&sample_begin); timestruct->tm_sec = 0; timestruct->tm_min = 0; timestruct->tm_hour = 0; timestruct->tm_mday = 1; timestruct->tm_mon--; // Start the month before the sample MarkTime = mktime(timestruct); x = (MarkTime-sample_begin)*( ((double)(XWIDTH-XOFFSET)) / config.range) + XOFFSET; while (x < XOFFSET) { timestruct->tm_mon++; MarkTime = mktime(timestruct); x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } while (x < (XWIDTH-10)) { // Month Lines gdImageLine(im, x, 0, x, YHEIGHT-YOFFSET, red); gdImageLine(im, x+1, 0, x+1, YHEIGHT-YOFFSET, red); timestruct = localtime((time_t *)&MarkTime); strftime(buffer, 100, "%b", timestruct); gdImageString(im, gdFontSmall, x-6, YHEIGHT-YOFFSET+10, buffer, black); // Calculate Next x timestruct->tm_mon++; MarkTime = mktime(timestruct); x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } } // ******************************************************************** // **** Write the tic marks // ******************************************************************** timestruct = localtime((time_t *)&sample_begin); timestruct->tm_sec = 0; timestruct->tm_min = 0; timestruct->tm_hour = 0; MarkTime = mktime(timestruct); if ((6*60*60*(XWIDTH-XOFFSET))/config.range > 10) // pixels per 6 hours is more than 2 MarkTimeStep = 6*60*60; // Major ticks are 6 hours else if ((24*60*60*(XWIDTH-XOFFSET))/config.range > 10) MarkTimeStep = 24*60*60; // Major ticks are 24 hours; else return; // Done x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; while (x < XOFFSET) { MarkTime += MarkTimeStep; x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } while (x < (XWIDTH-10)) { if (x > XOFFSET) { gdImageLine(im, x, YHEIGHT-YOFFSET-5, x, YHEIGHT-YOFFSET+5, black); gdImageLine(im, x+1, YHEIGHT-YOFFSET-5, x+1, YHEIGHT-YOFFSET+5, black); } MarkTime += MarkTimeStep; x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } timestruct = localtime((time_t *)&sample_begin); timestruct->tm_sec = 0; timestruct->tm_min = 0; timestruct->tm_hour = 0; MarkTime = mktime(timestruct); if ((60*60*(XWIDTH-XOFFSET))/config.range > 2) // pixels per hour is more than 2 MarkTimeStep = 60*60; // Minor ticks are 1 hour else if ((6*60*60*(XWIDTH-XOFFSET))/config.range > 2) MarkTimeStep = 6*60*60; // Minor ticks are 6 hours else if ((24*60*60*(XWIDTH-XOFFSET))/config.range > 2) MarkTimeStep = 24*60*60; else return; // Done // Draw Minor Tic Marks x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; while (x < XOFFSET) { MarkTime += MarkTimeStep; x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } while (x < (XWIDTH-10)) { if (x > XOFFSET) { gdImageLine(im, x, YHEIGHT-YOFFSET, x, YHEIGHT-YOFFSET+5, black); gdImageLine(im, x+1, YHEIGHT-YOFFSET, x+1, YHEIGHT-YOFFSET+5, black); } MarkTime+=MarkTimeStep; x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET; } } bandwidthd-2.0.1+cvs20090917/INSTALL.Unix0000644000175000017500000000114410171037615015323 0ustar gemgem#### INSTALLATION # You need 3 dependencies to make Bandwidthd work: libpcap from http://www.tcpdump.org/ libpng from http://www.libpng.org/ libgd from http://www.boutell.com/gd/ Chances are you already have all three, if in doubt just run configure and see what it complains about. If you are missing libpng, make sure you re-install libgd after you install it. Configure and install the Bandwidthd source: ./configure && make install Edit /usr/local/bandwidthd/etc/bandwidthd.conf to suit your network. Start Bandwidthd. See README for details and information on stand alone vs database driven mode. bandwidthd-2.0.1+cvs20090917/INSTALL.Windows0000644000175000017500000000140410171037615016031 0ustar gemgem#### INSTALLATION # You must download and install Winpcap from: http://winpcap.polito.it I recommend version 3.0 at this time. Then, unzip Bandwidthd to the folder of your choice. Edit etc/bandwidthd.conf to suit your environment. Double click "Install Service" to install the service. You can now start Bandwidthd from the services control panel. Stopping the service from the services panel not supported. You will need to kill it with task manager if you want it stopped. If you have more than one network interface card, and you want to listen on a specific device, you can run "List Device Names" to produce a list of devices that can be used on the "dev" line in bandwidthd.conf. By default, Bandwidthd listens on the first interface it detects. bandwidthd-2.0.1+cvs20090917/config.guess0000755000175000017500000011416310170330773015676 0ustar gemgem#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. timestamp='2001-06-05' # This file 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. # # 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Written by Per Bothner . # Please send patches to . # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi dummy=dummy-$$ trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int dummy(){}" > $dummy.c for c in cc gcc c89 ; do ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 if test $? = 0 ; then CC_FOR_BUILD="$c"; break fi done rm -f $dummy.c $dummy.o $dummy.rel if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 8/24/94.) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # Netbsd (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # Determine the machine/vendor (is the vendor relevant). case "${UNAME_MACHINE}" in amiga) machine=m68k-unknown ;; arm32) machine=arm-unknown ;; atari*) machine=m68k-atari ;; sun3*) machine=m68k-sun ;; mac68k) machine=m68k-apple ;; macppc) machine=powerpc-apple ;; hp3[0-9][05]) machine=m68k-hp ;; ibmrt|romp-ibm) machine=romp-ibm ;; *) machine=${UNAME_MACHINE}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE}" in i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. cat <$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then case `./$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; esac fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; arc64:OpenBSD:*:*) echo mips64el-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hkmips:OpenBSD:*:*) echo mips-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mips-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; atari*:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; sun3*:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy \ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) case "${HPUX_REV}" in 11.[0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; esac ;; esac fi ;; esac if [ "${HP_ARCH}" = "" ]; then sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; hppa*:OpenBSD:*:*) echo hppa-unknown-openbsd exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*X-MP:*:*:*) echo xmp-cray-unicos exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY-2:*:*:*) echo cray2-cray-unicos exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) cat >$dummy.c < /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #ifdef __MIPSEB__ printf ("%s-unknown-linux-gnu\n", argv[1]); #endif #ifdef __MIPSEL__ printf ("%sel-unknown-linux-gnu\n", argv[1]); #endif return 0; } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy ;; ppc:Linux:*:*) # Determine Lib Version cat >$dummy.c < #if defined(__GLIBC__) extern char __libc_version[]; extern char __libc_release[]; #endif main(argc, argv) int argc; char *argv[]; { #if defined(__GLIBC__) printf("%s %s\n", __libc_version, __libc_release); #else printf("unknown\n"); #endif return 0; } EOF LIBC="" $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null if test "$?" = 0 ; then ./$dummy | grep 1\.99 > /dev/null if test "$?" = 0 ; then LIBC="libc1" ; fi fi rm -f $dummy.c $dummy echo powerpc-unknown-linux-gnu${LIBC} exit 0 ;; alpha:Linux:*:*) cat <$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF LIBC="" $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then case `./$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; esac objdump --private-headers $dummy | \ grep ld.so.1 > /dev/null if test "$?" = 0 ; then LIBC="libc1" fi fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. ld_supported_targets=`cd /; ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf cat >$dummy.c < #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 printf ("%s-pc-linux-gnu\n", argv[1]); # else printf ("%s-pc-linux-gnulibc1\n", argv[1]); # endif # else printf ("%s-pc-linux-gnulibc1\n", argv[1]); # endif #else printf ("%s-pc-linux-gnuaout\n", argv[1]); #endif return 0; } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions # are messed up and put the nodename in both sysname and nodename. i*86:DYNIX/ptx:4*:*) echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:7*) # Fixed at (any) Pentium or better UNAME_MACHINE=i586 if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} fi exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) if test "${UNAME_MACHINE}" = "x86pc"; then UNAME_MACHINE=pc fi echo `uname -p`-${UNAME_MACHINE}-nto-qnx exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[KW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: bandwidthd-2.0.1+cvs20090917/conf.l0000644000175000017500000000231510337130110014437 0ustar gemgem%{ #include #include #include #include "conf.tab.h" %} %% [ \t]+ /* Ignore */; \n { return TOKNEWLINE; } #.*\n { return TOKNEWLINE; } ([0-9]{1,3}"."){3,3}([0-9]{1,3}) { bdconfig_lval.string=strdup(yytext); return IPADDR; } [-0-9]+ { bdconfig_lval.number=atoi(yytext); return NUMBER; } \".*\" { bdconfig_lval.string=strdup(yytext); return STRING; } \/ { return TOKSLASH; } true|false { bdconfig_lval.number=!strcmp(yytext,"true"); return STATE; } subnet { return TOKSUBNET; } dev { return TOKDEV; } skip_intervals { return TOKSKIPINTERVALS; } graph_cutoff { return TOKGRAPHCUTOFF; } promiscuous { return TOKPROMISC; } output_cdf { return TOKOUTPUTCDF; } recover_cdf { return TOKRECOVERCDF; } graph { return TOKGRAPH; } filter { return TOKFILTER; } meta_refresh { return TOKMETAREFRESH; } pgsql_connect_string { return TOKPGSQLCONNECTSTRING; } sensor_id { return TOKSENSORID; } htdocs_dir { return TOKHTDOCSDIR; } log_dir { return TOKLOGDIR; } description { return TOKDESCRIPTION; } management_url { return TOKMANAGEMENTURL; } extensions { return TOKEXTENSIONS; } . { return TOKJUNK; } %% bandwidthd-2.0.1+cvs20090917/config.sub0000755000175000017500000006630610170330773015346 0ustar gemgem#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. timestamp='2001-06-08' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file 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. # # 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., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ | pyramid | mn10200 | mn10300 | tron | a29k \ | 580 | i960 | h8300 \ | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ | hppa64 \ | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ | alphaev6[78] \ | we32k | ns16k | clipper | i370 | sh | sh[34] \ | powerpc | powerpcle \ | 1750a | dsp16xx | pdp10 | pdp11 \ | mips16 | mips64 | mipsel | mips64el \ | mips64orion | mips64orionel | mipstx39 | mipstx39el \ | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ | mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \ | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ | v850 | c4x \ | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ | pj | pjl | h8500 | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. # FIXME: clean up the formatting here. vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ | xmp-* | ymp-* \ | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ | hppa2.0n-* | hppa64-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ | alphaev6[78]-* \ | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ | clipper-* | orion-* \ | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \ | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ | mips16-* | mips64-* | mipsel-* \ | mips64el-* | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ | mipstx39-* | mipstx39el-* | mcore-* \ | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ | [cjt]90-* \ | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | ymp) basic_machine=ymp-cray os=-unicos ;; cray2) basic_machine=cray2-cray os=-unicos ;; [cjt]90) basic_machine=${basic_machine}-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mipsel*-linux*) basic_machine=mipsel-unknown os=-linux-gnu ;; mips*-linux*) basic_machine=mips-unknown os=-linux-gnu ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=t3e-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xmp) basic_machine=xmp-cray os=-unicos ;; xps | xps100) basic_machine=xps100-honeywell ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; mips) if [ x$os = x-linux-gnu ]; then basic_machine=mips-unknown else basic_machine=mips-mips fi ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4) basic_machine=sh-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; c4x*) basic_machine=c4x-none os=-coff ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: bandwidthd-2.0.1+cvs20090917/bandwidthd.h0000644000175000017500000001375611145324327015646 0ustar gemgem#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_INTTYPES_H #include #endif #ifdef TYPEDEF_UINT32 typedef u_int32_t uint32_t; #endif #ifdef TYPEDEF_UINT16 typedef u_int16_t uint16_t; #endif #ifdef HAVE_GD_H #include #else #ifdef HAVE_GD_GD_H #include #endif #endif #ifdef HAVE_GDFONTS_H #include #else #ifdef HAVE_GD_GDFONTS_H #include #endif #endif #include #include #include #define BUILD 17 #define IP_NUM 10000 // TODO: Do this dynamicly to save ram and/or scale bigger #define SUBNET_NUM 100 #define XWIDTH 900 #define YHEIGHT 256L #define XOFFSET 90L #define YOFFSET 45L #define NR_WORKER_CHILDS 3 #define RANGE1 172800.0 // 2 days #define RANGE2 604800.0 // 7 days #define RANGE3 3024000.0 // 35 days #define RANGE4 35640000.0 // 412.5ish days #define INTERVAL1 200L // 150 -60 (213 is the perfect interval?) #define INTERVAL2 600L // 10 minutes #define INTERVAL3 3600L // 1 hour #define INTERVAL4 43200L // 12 hours #define CONFIG_GRAPHINTERVALS 1 // 2 -5 Number of Intervals to wait before redrawing the graphs #define CONFIG_GRAPHCUTOFF 1024*1024 // If total data transfered doesn't reach at least this number we don't graph the ip #define LEAD .05 // % Of time to lead the graph #define TRUE 1 #define FALSE 0 #define CONFIG_METAREFRESH 150 #define PERMIS 1 #define MAX_FILENAME 1024 #define DB_PGSQL 1 // No mysql support yet #define DB_MYSQL 2 struct config { char *dev; char *filter; unsigned int skip_intervals; unsigned long long graph_cutoff; int promisc; int extensions; int output_cdf; int recover_cdf; int graph; double range; unsigned long long interval; char tag; unsigned int meta_refresh; int output_database; char *db_connect_string; char *sensor_name; char *log_dir; char *htdocs_dir; char *description; char *management_url; }; struct SubnetData { uint32_t ip; uint32_t mask; } SubnetTable[SUBNET_NUM]; struct Statistics { unsigned long long packet_count; unsigned long long total; unsigned long long icmp; unsigned long long udp; unsigned long long tcp; unsigned long long ftp; unsigned long long http; unsigned long long mail; unsigned long long p2p; }; struct IPData { time_t timestamp; uint32_t ip; // Host byte order struct Statistics Send; struct Statistics Receive; } IpTable[IP_NUM]; struct SummaryData { uint32_t IP; int Graph; // TRUE or FALSE, Did we write out a graph for this ip unsigned long long Total; unsigned long long TotalSent; unsigned long long TotalReceived; unsigned long long ICMP; unsigned long long UDP; unsigned long long TCP; unsigned long long FTP; unsigned long long HTTP; unsigned long long MAIL; unsigned long long P2P; }; struct IPDataStore { uint32_t ip; struct DataStoreBlock *FirstBlock; // This is structure is allocated at the same time, so it always exists. struct IPDataStore *Next; }; #define IPDATAALLOCCHUNKS 100 struct DataStoreBlock { time_t LatestTimestamp; int NumEntries; // Is the index of the first unused entry in IPData struct IPData *Data; // These are allocated at creation, and thus always exist struct DataStoreBlock *Next; }; struct Broadcast { char *sensor_name; char *interface; time_t received; struct Broadcast *next; }; struct extensions { char *name; char *value; struct extensions *next; }; // **************************************************************************************** // ** Function Prototypes // **************************************************************************************** // ************ A fork that orphans the child int fork2(); // ************ The function that gets called with each packet void PacketCallback(u_char *user, const struct pcap_pkthdr *h, const u_char *p); // ************ Reads a CDF file from a previous run void RecoverDataFromCDF(void); // ************ Adds subnets to the list of subnets that are monitored void MonitorSubnet(unsigned int ip, unsigned int mask); // ************ This function converts and IP to a char string char inline *HostIp2CharIp(unsigned long ipaddr, char *buffer); // ************ This function converts the numbers for each quad into an IP inline uint32_t IpAddr(unsigned char q1, unsigned char q2, unsigned char q3, unsigned char q4); // ************ This function adds the packet's size to the proper entries in the data structure inline void Credit(struct Statistics *Stats, const struct ip *ip); // ************ Finds an IP in our IPTable inline struct IPData *FindIp(uint32_t ipaddr); // ************ Writes our IPTable to Disk or to the Ram cache void CommitData(time_t timestamp); // ************ Creates our Graphs void GraphIp(struct IPDataStore *DataStore, struct SummaryData *SummaryData, time_t timestamp); void PrepareXAxis(gdImagePtr im, time_t timestamp); void PrepareYAxis(gdImagePtr im, unsigned long long int YMax); unsigned long long GraphData(gdImagePtr im, gdImagePtr im2, struct IPDataStore *DataStore, time_t timestamp, struct SummaryData *SummaryData); // ************ Misc inline void DstCredit(uint32_t ipaddr, unsigned int psize); void MakeIndexPages(int NumGraphs, struct SummaryData *SummaryData[]); // ************ Pgsql void pgsqlStoreIPData(struct IPData IncData[], struct extensions *); // ************ Extensions struct extensions *execute_extensions(void); void destroy_extension_data(struct extensions *ext); bandwidthd-2.0.1+cvs20090917/phphtdocs/0000755000175000017500000000000011254363050015342 5ustar gemgembandwidthd-2.0.1+cvs20090917/phphtdocs/geographic-management.sql0000755000175000017500000000054010337130110022275 0ustar gemgemcreate table groups ( group_id serial, name varchar, color varchar); CREATE TABLE locations ( id serial PRIMARY KEY, name varchar, group_id int default 0, latitude varchar, longitude varchar ); CREATE TABLE links_ignorelist ( sensor_id int ); CREATE TABLE slices ( id serial, sensor_id int, direction float, angle float, radius float);bandwidthd-2.0.1+cvs20090917/phphtdocs/details.php0000644000175000017500000001023410337130110017466 0ustar gemgemPlease provide a sensor_id"; exit(1); } if (isset($_GET['ip'])) $ip = $_GET['ip']; else { echo "
Please provide an ip address"; exit(1); } echo "

"; if (strpos($ip, "/") === FALSE) echo "$ip - ".gethostbyaddr($ip)."

"; else echo "Total - $ip"; $db = ConnectDb(); if ($ip == "0.0.0.0/0") { $rxtable = "bd_rx_total_log"; $txtable = "bd_tx_total_log"; } else { $rxtable = "bd_rx_log"; $txtable = "bd_tx_log"; } $sql = "select rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp, tx.icmp+rx.icmp as icmp, tx.http+rx.http as http, tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp from (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp from sensors, $txtable where sensors.sensor_id = '$sensor_id' and sensors.sensor_id = ".$txtable.".sensor_id and ip <<= '$ip' group by ip) as tx, (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp from sensors, $rxtable where sensors.sensor_id = '$sensor_id' and sensors.sensor_id = ".$rxtable.".sensor_id and ip <<= '$ip' group by ip) as rx where tx.ip = rx.ip;"; //echo "
$sql
";exit(0); $result = pg_query($sql); echo "
IpNameTotalSentReceivedtcpudpicmphttpp2pftp"; $r = pg_fetch_array($result); echo "
"; if (strpos($ip, "/") === FALSE) echo "$ip".gethostbyaddr($ip); else echo "Total$ip"; echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']). fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']). fmtb($r['p2p']).fmtb($r['ftp']); echo "
"; echo "

Daily

"; echo "Send:

"; echo "
"; echo "Receive:

"; echo "
"; echo "

Weekly

"; echo "Send:

"; echo "
"; echo "Receive:

"; echo "
"; echo "

Monthly

"; echo "Send:

"; echo "
"; echo "Receive:

"; echo "
"; echo "

Yearly

"; echo "Send:

"; echo "
"; echo "Receive:

"; echo "
";bandwidthd-2.0.1+cvs20090917/phphtdocs/bandwidthd.css0000755000175000017500000000353410337130110020162 0ustar gemgem.body { font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: #333333; } h3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-weight: bold; color: #2A337E; border: solid 1px #666666; padding: 2px; background-color: #c0c0c0; } th { font-family: verdana; font-size: 10px; background-color: #c0c0c0; color: #333333; align: center; cell-spacing: 0px; } .row-header-left { border-left: solid 1px #666666; border-top: solid 1px #666666; border-bottom: solid 1px #666666; line-height: 9px; padding: 2px; } .row-header-middle { border-top: solid 1px #666666; border-bottom: solid 1px #666666; line-height: 9px; padding: 2px; } .row-header-right { border-right: solid 1px #666666; border-top: solid 1px #666666; border-bottom: solid 1px #666666; line-height: 9px; padding: 2px; } a.text-button:link, a.text-button:visited { font-family: verdana; font-size: 10px; font-weight: bold; color: #2A337E; text-decoration: none; background-color: #F6F6F6; border: solid 1px #666666; padding-top: 1px; padding-bottom: 1px; padding-left: 5px; padding-right: 5px; margin-top: 10px; } a.text-button:hover { font-family: verdana; font-size: 10px; font-weight: bold; color: #ffffff; text-decoration: none; background-color: #828DBA; border: solid 1px #666666; padding-top: 1px; padding-bottom: 1px; padding-left: 5px; padding-right: 5px; } bandwidthd-2.0.1+cvs20090917/phphtdocs/xml.php0000755000175000017500000000523410667336241016673 0ustar gemgem\n"); // Display links $sql = " SELECT distinct on (a_long, a_lat, b_long, b_lat) loc_a.longitude as a_long, loc_a.latitude as a_lat, loc_b.longitude as b_long, loc_b.latitude as b_lat, id1, sens_a.sensor_name, sens_b.sensor_name, extract (epoch from (now() - last_update))/60 as age from links, sensors as sens_a, sensors as sens_b, locations as loc_a, locations as loc_b WHERE id1 not in (select * from links_ignorelist ) and id2 not in (select * from links_ignorelist ) and sens_a.location != sens_b.location and id1 = sens_a.sensor_id and id2 = sens_b.sensor_id and sens_a.location = loc_a.id and sens_b.location = loc_b.id"; if (isset($group_id)) $sql .= " and (loc_a.group_id = $group_id or loc_b.group_id = $group_id)"; $links = pg_query($sql); $lnk_colors[0] = "0000FF"; // Bright Blue $lnk_colors[1] = "7700FF"; // Violet $lnk_colors[2] = "CC00CC"; // Purple $lnk_colors[3] = "FF6600"; // Orange $lnk_colors[4] = "FF0000"; // Red while ($link = @pg_fetch_array($links)) { $rate = 0; if ($link['age'] < 10) { $res = pg_query("SELECT total, sample_duration from bd_rx_total_log where sensor_id = ".$link['id1']." and timestamp > now()-interval '20 minutes' order by timestamp desc limit 1;"); if ($res && pg_num_rows($res) == 1) { $r = @pg_fetch_array($res); $rate += ($r['total']*8)/$r['sample_duration']; } $res = pg_query("SELECT total, sample_duration from bd_tx_total_log where sensor_id = ".$link['id1']." and timestamp > now()-interval '20 minutes' order by timestamp desc limit 1;"); if ($res && pg_num_rows($res) == 1) { $r = @pg_fetch_array($res); $rate += ($r['total']*8)/$r['sample_duration']; } if ($rate < 256) $color = $lnk_colors[0]; elseif ($rate < 1500) $color = $lnk_colors[1]; elseif ($rate < 3000) $color = $lnk_colors[2]; elseif ($rate < 4500) $color = $lnk_colors[3]; else $color = $lnk_colors[4]; //$color = str_pad(dechex($red), 2, '0', STR_PAD_LEFT).str_pad(dechex($green), 2, '0', STR_PAD_LEFT)."00"; } else $color = "000000"; echo("\n"); } echo("\n"); ?> bandwidthd-2.0.1+cvs20090917/phphtdocs/maint.hourly0000755000175000017500000000025510667336241017734 0ustar gemgemecho "vacuum ANALYZE sensors;" echo "vacuum analyze links;" echo "delete from extension_log where timestamp < now()-interval '1 hour';" echo "vacuum analyze extension_log;" bandwidthd-2.0.1+cvs20090917/phphtdocs/logo.gif0000755000175000017500000001662510165355101017004 0ustar gemgemGIF87a  3fLyL(u@@}NN ppfAAA쟟7j3pp=lﹿ33Y|33%%%``̙DlY0p SZZަ3怀4`33q))V"a@@PPVVV v:ﯯ@p &ZəCP`Y([!!鏏#IPPBGy{{̳-y)|ffrʙ SwwSw r,+wHTw<rrjwtt+w6wCwaFw@BANDrH Vw`w6w\WCraFw@ ~L˚~#~$h bandwidthd-logo.8l qwLL4+w6wDswaFwDDxl|l|H8lDxlsD8l!, @H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sܹĀPIѣH*MSd~,JիX6}u@֯`¤ت[:=6!ٟfqjp[E׈l9{W^ (^ވ}W2PO^sǾBOF|fbƨS(8Zri^H}F̑%Wư|ECw# {"+.iqk]C"U|sHu mW{xQ! 5({ ݄NfTAj]衇M t|{`BH@ruA"aH8.CiQ (TN@v1(vq]Y Q0!e\"e%r&@ B tfWd t5>ŇyКWB}>%&Bd*J@B9lFv ~:abGjFZjri꫞~I%vŅH5kd} BլR+rD_xI.!0k $wQNu %Є&?k!LAH @Z0A x8~IOp4apPĒDS3FlDxP U } $Pn(1@avx~Cm|O8 +O Gu)re 4~7H 0AxH3U4uD)-Ppa5b[AMD|dVGNЊek~yA~Ӣn騧ꨓǾeO.u/XN+F[P ]|0 Wogw/o觯VA) HLXBL̠IV z0A5P3".ka r7I&A0H O$gwHF /”:4hQS@AE  ĊIt eA>rƚEI-df3uJ[\!F VfoVrҵ(4GKԃ%_YUe%T| > urj(IL*`,) \2 &= ^~…# b SA0j A : @ b@0;eb' 贌:I~h Q 40"g2eS2/ZH泌N'fz`6d#<"B<+dH^AgaHHф4ecuh,fMqI247!B8x+r~TC`OBt V=Nv|60{@GK!Q@ L:!.2atf ְ$L;ڔ!}=lE(Ȑ)~A@z!J(z)f"˼dЩEN*;-l2W%W%] ]\} wӹX:E2/Pf٫b绕.FrRO۩:%{+K$7)7zN4F;ѐ'MJ[Ҙδ7NGxԨNMcAU*QT`MZε+]v5 pA㰍]ϰّVDD a<-h(eih`wÅ([U@z*^;m`%RKTؑ%5UM{!IlppecN.f5i3Oz0olB0ڕO dI1 pc%}:-d;Pԟ_LtS]SVz}uN%xA2ˎz !8čakdT )X#} *\-\X([/1 :,D/:<)aW-~@hrsO|W:ނ^2Wu0tG l %B 2 |M <~{'zA/PeϢ+F Jon3~Txqjv€ ~\"nFhSj1U2q''BVC E)WMĥttU*_`_)20! P*%@!)_ |])=?*A8!u) !ф%ܲKc8!bH]B3EvJRv> z%xzk{3}HMҁ!OUq!;E>MywxwXC$JR a h-$?@xgrAS~"_lvQ&yw4Nq#x}NA2;狆kȇ*7}Qo2#X$0}7/erexGu( sbŎXax5s''RC\SzzQ ~ ]Dxk~mR)]@Iya9%I_37"%9"D%B8 9nWWG)a\f0i)EUMS)^uEv"_YN[ɃBX*RXa!0v$c)Pue$]Y-B!dpUtNW]^+/pQ/)rX$t1(!UU nq<(d7 EHD_%N@!bx42I6G_u6Q0u0CU"8!2AwDxB_PrqS0BxUÚS8#B@4S@B;D[F{HJL۴NPR;fHX{@MqY۵b?c{AlKqpmlA0p+v47wS|:᷀;5!{0a+Ajij;3ij$nTh;j[m@VCќֺf3ؖ@纍vW@炙UmDb15ĻhnҁgNڤX)ޤNRF Ba;-{O؁q>9 ^+[o3ENG.$PP)m!NNQ.@K>#ax5քC#5|*x.oSKz>#[tl~b>|>} GgW3{TǡމE~LΈna`'es I3\!(Ic e>t͈$?D m}"= l˪m9#x@V-}xSa^H>žOB&.E鬘K㽼bXVFXJmS^5jaU2'V>  j .p阝lмWVmnPj{.A?ќ6mj.5[i\z_h~_&5p7ű#d&("5\;lc[d̤#~Պh)EjO:Bx8=9J ,aw|5(o2_&OEѥȇï#a3( YBz*73Wm͎)얱9"P-#!y~eb5M4IdCorSGNX@1@@.&Dxp@ I HH"C=~, MRJ-U*@.Y.XLrV40Od~$0"NURLz3FhA $*Pq <O[P09&d = \FujRaH!-_Ɯyw HCbp"^IA). r0l&Kc.[zś۰c3H4Ict^vݽc9Ա{zB;l;5z/Y nҝ=؊ X R .*BhB6C/b# Q QC.?B4kLjV HH0rqҸPQ" rcý(=K&"D]c '⽆k*HؚǰJ1#}#p(# Z#JH' OJ(x3< t /WeU%D8Z ~:D ;[t˄Js`TJhJ3PdT7X֢h+k ˝ 80#I}GgU<)hʜEY/VWbaM H(XPuc =͖Pt*y\<2Ee+dvXakg]>r6wQ RXulߔZFVevYb 4nDYƈlIfO.~D yfS:qgqߙgdkS%;\mW#9kMߛU پcfcN(l 7_.rjgow柇y<;DܷEŖ@*0?7.u7orF2 M`,8JPR^~)3x-k~1 @X«mzS?b8D"шG" D&PH" RV,"E.vыRb8F2reDc(-z G Location Statistics
No matching locations in database..."; $r = @pg_fetch_array($locations); $sensors = pg_query("select distinct sensor_name from sensors where location = ".$r['id']." order by sensor_name;"); while ($sensor = @pg_fetch_array($sensors)) { echo("

".$sensor['sensor_name']."

"); $interfaces = pg_query("select * from sensors where sensor_name = '".$sensor['sensor_name']."' order by interface;"); $First = true; while ($interface = @pg_fetch_array($interfaces)) { $extension_log = pg_query("select * from extension_log where sensor_id = ".$interface['sensor_id']." order by timestamp desc limit 1;"); $extension = @pg_fetch_array($extension_log); if ($First) { $First = false; echo(""); if ($extension['version'] != "") echo("
Version: ".$extension['version']); if ($extension['uptime'] != "") { $uptime_seconds = $extension['uptime']; $uptime_text = ""; if ($uptime_seconds > 60*60*24) { $value = floor($uptime_seconds/(60*60*24)); $uptime_text .= $value." Days "; $uptime_seconds -= $value*60*60*24; } if ($uptime_seconds > 60*60) { $value = floor($uptime_seconds/(60*60)); $uptime_text .= $value." Hours "; $uptime_seconds -= $value*60*60; } $value = floor($uptime_seconds/60); $uptime_text .= $value." Minutes "; $uptime_seconds -= $value*60*60; echo("Uptime: ".$uptime_text); } if ($extension['loadavg'] != "") echo("
5 Min load Avg: ".$extension['loadavg']); echo("
"); } echo "

".$interface['interface']." - ".$interface['description']."

\n"; if ($extension['minlatency'] != "") { echo("
Latency:Min".$extension['minlatency']."msAvg".$extension['avglatency']."msMax".$extension['maxlatency']."ms
"); } if ($extension['ipaddr'] != "") echo "
".$extension['ipaddr']."
\n"; if ($extension['errors'] != "") echo "
".$extension['errors']."
\n"; if ($extension['wireless'] != "") echo "
".preg_replace("/Encryption key:[0-9A-F-]*/", "Encryption key:HIDDEN", $extension['wireless'])."
\n"; echo "Transmit

"; echo "Receive

"; } } // Add some blank lines to the bottom so we can always scroll all the way down to the bottom graph ?>














bandwidthd-2.0.1+cvs20090917/phphtdocs/graph.php0000644000175000017500000004054711145324327017171 0ustar gemgem $number) { $total[$key] /= $number; $icmp[$key] /= $number; $udp[$key] /= $number; $tcp[$key] /= $number; $ftp[$key] /= $number; $http[$key] /= $number; $mail[$key] /= $number; $p2p[$key] /= $number; } foreach ($Count as $key => $number) { $a_total[$key] += $total[$key]; $a_icmp[$key] += $icmp[$key]; $a_udp[$key] += $udp[$key]; $a_tcp[$key] += $tcp[$key]; $a_ftp[$key] += $ftp[$key]; $a_http[$key] += $http[$key]; $a_mail[$key] += $mail[$key]; $a_p2p[$key] += $p2p[$key]; if ($a_total[$key] > $YMax) $YMax = $a_total[$key]; } unset($GLOBALS['total'], $GLOBALS['icmp'], $GLOBALS['udp'], $GLOBALS['tcp'], $GLOBALS['ftp'], $GLOBALS['http'], $GLOBALS['mail'], $GLOBALS['p2p'], $GLOBALS['Count']); $total = array(); $icmp = array(); $udp = array(); $tcp = array(); $ftp = array(); $http = array(); $mail = array(); $p2p = array(); $Count = array(); } $db = ConnectDb(); // Get parameters if (isset($_GET['width'])) $width = $_GET['width']; else $width = DFLT_WIDTH; if (isset($_GET['height'])) $height = $_GET['height']; else $height = DFLT_HEIGHT; if (isset($_GET['interval'])) $interval = $_GET['interval']; else $interval = DFLT_INTERVAL; if (isset($_GET['ip'])) { $ip = $_GET['ip']; #optionall call using underscore instead of slash to seperate subnet from bits $ip = str_replace("_", "/", $ip); } else exit(1); if (isset($_GET['sensor_id'])) $sensor_id = $_GET['sensor_id']; else exit(1); if (isset($_GET['timestamp'])) $timestamp = $_GET['timestamp']; else $timestamp = time() - $interval + (0.05*$interval); if (isset($_GET['table'])) $table = $_GET['table']; else $table = "bd_rx_log"; if (isset($_GET['yscale'])) $yscale = $_GET['yscale']; $total = array(); $icmp = array(); $udp = array(); $tcp = array(); $ftp = array(); $http = array(); $mail = array(); $p2p = array(); $Count = array(); // Accumulator $a_total = array(); $a_icmp = array(); $a_udp = array(); $a_tcp = array(); $a_ftp = array(); $a_http = array(); $a_http = array(); $a_p2p = array(); $sql = "select *, extract(epoch from timestamp) as ts from $table where ip <<= '$ip' and sensor_id = '$sensor_id' and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime order by ip;"; //echo $sql."
"; exit(1); $result = pg_query($sql); // The SQL statement pulls the data out of the database ordered by IP address, that way we can average each // datapoint for each IP address to provide smoothing and then toss the smoothed value into the accumulator // to provide accurate total traffic rate. while ($row = pg_fetch_array($result)) { if ($row['ip'] != $last_ip) { AverageAndAccumulate(); $last_ip = $row['ip']; } $x = ($row['ts']-$timestamp)*(($width-XOFFSET)/$interval)+XOFFSET; $xint = (int) $x; //echo "xint: ".$xint."
"; $Count[$xint]++; if ($row['total']/$row['sample_duration'] > $SentPeak) $SentPeak = $row['total']/$row['sample_duration']; $TotalSent += $row['total']; $TotalPackets += $row['packet_count']; $total[$xint] += $row['total']/$row['sample_duration']; $icmp[$xint] += $row['icmp']/$row['sample_duration']; $udp[$xint] += $row['udp']/$row['sample_duration']; $tcp[$xint] += $row['tcp']/$row['sample_duration']; $ftp[$xint] += $row['ftp']/$row['sample_duration']; $http[$xint] += $row['http']/$row['sample_duration']; $mail[$xint] += $row['mail']/$row['sample_duration']; $p2p[$xint] += $row['p2p']/$row['sample_duration']; } // One more time for the last IP AverageAndAccumulate(); // Pull the data out of Accumulator $total = $a_total; $icmp = $a_icmp; $udp = $a_udp; $tcp = $a_tcp; $ftp = $a_ftp; $http = $a_http; $mail = $a_mail; $p2p = $a_p2p; $YMax += $YMax*0.05; // Add an extra 5% // if a y scale was specified override YMax if (isset($yscale)) $YMax = $yscale/8; // Plot the data header("Content-type: image/png"); // Not enough data to graph if ($YMax <= 1.1) { $im = imagecreate($width, 20); $white = imagecolorallocate($im, 255, 255, 255); $black = ImageColorAllocate($im, 0, 0, 0); ImageString($im, 2, $width/2, 0, "No Data", $black); imagepng($im); imagedestroy($im); exit(0); } $im = imagecreate($width, $height); $white = imagecolorallocate($im, 255, 255, 255); $yellow = ImageColorAllocate($im, 255, 255, 0); $purple = ImageColorAllocate($im, 255, 0, 255); $green = ImageColorAllocate($im, 0, 255, 0); $blue = ImageColorAllocate($im, 0, 0, 255); $orange = ImageColorAllocate($im, 255, 128, 0); $lblue = ImageColorAllocate($im, 128, 128, 255); $brown = ImageColorAllocate($im, 128, 0, 0); $red = ImageColorAllocate($im, 255, 0, 0); $black = ImageColorAllocate($im, 0, 0, 0); for($Counter=XOFFSET+1; $Counter < $width; $Counter++) { if (isset($total[$Counter])) { // Convert the bytes/sec to y coords $total[$Counter] = ($total[$Counter]*($height-YOFFSET))/$YMax; $tcp[$Counter] = ($tcp[$Counter]*($height-YOFFSET))/$YMax; $ftp[$Counter] = ($ftp[$Counter]*($height-YOFFSET))/$YMax; $http[$Counter] = ($http[$Counter]*($height-YOFFSET))/$YMax; $mail[$Counter] = ($mail[$Counter]*($height-YOFFSET))/$YMax; $p2p[$Counter] = ($p2p[$Counter]*($height-YOFFSET))/$YMax; $udp[$Counter] = ($udp[$Counter]*($height-YOFFSET))/$YMax; $icmp[$Counter] = ($icmp[$Counter]*($height-YOFFSET))/$YMax; // Stack 'em up! // Total is stacked from the bottom // Icmp is on the bottom too // Udp is stacked on top of icmp $udp[$Counter] += $icmp[$Counter]; // TCP and p2p are stacked on top of Udp $tcp[$Counter] += $udp[$Counter]; $p2p[$Counter] += $udp[$Counter]; // Http is stacked on top of p2p $http[$Counter] += $p2p[$Counter]; // Mail is stacked on top of http $mail[$Counter] += $http[$Counter]; // Ftp is stacked on top of http $ftp[$Counter] += $mail[$Counter]; // Plot them! //echo "$Counter:".$Counter." (h-y)-t:".($height-YOFFSET) - $total[$Counter]." h-YO-1:".$height-YOFFSET-1; ImageLine($im, $Counter, ($height-YOFFSET) - $total[$Counter], $Counter, $height-YOFFSET-1, $yellow); ImageLine($im, $Counter, ($height-YOFFSET) - $icmp[$Counter], $Counter, $height-YOFFSET-1, $red); ImageLine($im, $Counter, ($height-YOFFSET) - $udp[$Counter], $Counter, ($height-YOFFSET) - $icmp[$Counter] - 1, $brown); ImageLine($im, $Counter, ($height-YOFFSET) - $tcp[$Counter], $Counter, ($height-YOFFSET) - $udp[$Counter] - 1, $green); ImageLine($im, $Counter, ($height-YOFFSET) - $p2p[$Counter], $Counter, ($height-YOFFSET) - $udp[$Counter] - 1, $purple); ImageLine($im, $Counter, ($height-YOFFSET) - $http[$Counter], $Counter, ($height-YOFFSET) - $p2p[$Counter] - 1, $blue); ImageLine($im, $Counter, ($height-YOFFSET) - $mail[$Counter], $Counter, ($height-YOFFSET) - $http[$Counter] - 1, $orange); ImageLine($im, $Counter, ($height-YOFFSET) - $ftp[$Counter], $Counter, ($height-YOFFSET) - $mail[$Counter] - 1, $lblue); } // else // echo $Counter." not set
"; } // Margin Text if ($SentPeak < 1024/8) $txtPeakSendRate = sprintf("Peak Rate: %.1f KBits/sec", $SentPeak*8); else if ($SentPeak < (1024*1024)/8) $txtPeakSendRate = sprintf("Peak Rate: %.1f MBits/sec", ($SentPeak*8.0)/1024.0); else $txtPeakSendRate = sprintf("Peak Rate: %.1f GBits/sec", ($SentPeak*8.0)/(1024.0*1024.0)); if ($TotalSent < 1024) $txtTotalSent = sprintf("Total %.1f KBytes", $TotalSent); else if ($TotalSent < 1024*1024) $txtTotalSent = sprintf("Total %.1f MBytes", $TotalSent/1024.0); else $txtTotalSent = sprintf("Total %.1f GBytes", $TotalSent/(1024.0*1024.0)); $txtPacketsPerMtu = sprintf("%dk Pkts, Avg Size: %.1f bytes", $TotalPackets/1000, ($TotalSent*1024.0)/$TotalPackets); ImageString($im, 2, XOFFSET+5, $height-20, $txtTotalSent, $black); ImageString($im, 2, ($width-XOFFSET)/3+XOFFSET, $height-20, $txtPeakSendRate, $black); ImageString($im, 2, 2*(($width-XOFFSET)/3)+XOFFSET, $height-20, $txtPacketsPerMtu, $black); // Draw X Axis ImageLine($im, 0, $height-YOFFSET, $width, $height-YOFFSET, $black); // Day/Month Seperator bars if ((24*60*60*($width-XOFFSET))/$interval > ($width-XOFFSET)/10) { $ts = getdate($timestamp); $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']); $x = ts2x($MarkTime); while ($x < XOFFSET) { $MarkTime += (24*60*60); $x = ts2x($MarkTime); } while ($x < ($width-10)) { // Day Lines ImageLine($im, $x, 0, $x, $height-YOFFSET, $black); ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black); $txtDate = strftime("%a, %b %d", $MarkTime); ImageString($im, 2, $x-30, $height-YOFFSET+10, $txtDate, $black); // Calculate Next x $MarkTime += (24*60*60); $x = ts2x($MarkTime); } } else if ((24*60*60*30*($width-XOFFSET))/$interval > ($width-XOFFSET)/10) { // Monthly Bars $ts = getdate($timestamp); $month = $ts['mon']; $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']); $x = ts2x($MarkTime); while ($x < XOFFSET) { $month++; $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']); $x = ts2x($MarkTime); } while ($x < ($width-10)) { // Day Lines ImageLine($im, $x, 0, $x, $height-YOFFSET, $black); ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black); $txtDate = strftime("%b, %Y", $MarkTime); ImageString($im, 2, $x-25, $height-YOFFSET+10, $txtDate, $black); // Calculate Next x $month++; $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']); $x = ts2x($MarkTime); } } else { // Year Bars $ts = getdate($timestamp); $year = $ts['year']; $MarkTime = mktime(0, 0, 0, 1, 1, $year); $x = ts2x($MarkTime); while ($x < XOFFSET) { $year++; $MarkTime = mktime(0, 0, 0, 1, 1, $year); $x = ts2x($MarkTime); } while ($x < ($width-10)) { // Day Lines ImageLine($im, $x, 0, $x, $height-YOFFSET, $black); ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black); $txtDate = strftime("%b, %Y", $MarkTime); ImageString($im, 2, $x-25, $height-YOFFSET+10, $txtDate, $black); // Calculate Next x $year++; $MarkTime = mktime(0, 0, 0, 1, 1, $year); $x = ts2x($MarkTime); } } // Draw Major Tick Marks if ((6*60*60*($width-XOFFSET))/$interval > 10) // pixels per 6 hours is more than 2 $MarkTimeStep = 6*60*60; // Major ticks are 6 hours else if ((24*60*60*($width-XOFFSET))/$interval > 10) $MarkTimeStep = 24*60*60; // Major ticks are 24 hours; else if ((24*60*60*30*($width-XOFFSET))/$interval > 10) { // Major tick marks are months $MarkTimeStep = 0; // Skip the standard way of drawing major tick marks below $ts = getdate($timestamp); $month = $ts['mon']; $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']); $x = ts2x($MarkTime); while ($x < XOFFSET) { $month++; $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']); $x = ts2x($MarkTime); } while ($x < ($width-10)) { // Day Lines $date = getdate($MarkTime); if ($date['mon'] != 1) { ImageLine($im, $x, $height-YOFFSET-5, $x, $height-YOFFSET+5, $black); $txtDate = strftime("%b", $MarkTime); ImageString($im, 2, $x-5, $height-YOFFSET+10, $txtDate, $black); } // Calculate Next x $month++; $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']); $x = ts2x($MarkTime); } } else $MarkTimeStep = 0; // Skip Major Tick Marks if ($MarkTimeStep) { $ts = getdate($timestamp); $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']); $x = ts2x($MarkTime); while ($x < ($width-10)) { if ($x > XOFFSET) { ImageLine($im, $x, $height-YOFFSET-5, $x, $height-YOFFSET+5, $black); } $MarkTime += $MarkTimeStep; $x = ts2x($MarkTime); } } // Draw Minor Tick marks if ((60*60*($width-XOFFSET))/$interval > 4) // pixels per hour is more than 2 $MarkTimeStep = 60*60; // Minor ticks are 1 hour else if ((6*60*60*($width-XOFFSET))/$interval > 4) $MarkTimeStep = 6*60*60; // Minor ticks are 6 hours else if ((24*60*60*($width-XOFFSET))/$interval > 4) $MarkTimeStep = 24*60*60; else $MarkTimeStep = 0; // Skip minor tick marks if ($MarkTimeStep) { $ts = getdate($timestamp); $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']); $x = ts2x($MarkTime); while ($x < ($width-10)) { if ($x > XOFFSET) { ImageLine($im, $x, $height-YOFFSET, $x, $height-YOFFSET+5, $black); } $MarkTime += $MarkTimeStep; $x = ts2x($MarkTime); } } // Draw Y Axis ImageLine($im, XOFFSET, 0, XOFFSET, $height, $black); $YLegend = 'k'; $Divisor = 1; if ($YMax*8 > 1024*2) { $Divisor = 1024; // Display in m $YLegend = 'm'; } if ($YMax*8 > 1024*1024*2) { $Divisor = 1024*1024; // Display in g $YLegend = 'g'; } if ($YMax*8 > 1024*1024*1024*2) { $Divisor = 1024*1024*1024; // Display in t $YLegend = 't'; } if ($height/10 > 15) $YMarks = 10; else $YMarks = 5; $YStep = $YMax/$YMarks; if ($YStep < 1) $YStep=1; $YTic=$YStep; while ($YTic <= ($YMax - $YMax/$YMarks)) { $y = ($height-YOFFSET)-(($YTic*($height-YOFFSET))/$YMax); ImageLine($im, XOFFSET, $y, $width, $y, $black); $txtYLegend = sprintf("%4.1f %sbits/s", (8.0*$YTic)/$Divisor, $YLegend); ImageString($im, 2, 3, $y-7, $txtYLegend, $black); $YTic += $YStep; } imagepng($im); imagedestroy($im);bandwidthd-2.0.1+cvs20090917/phphtdocs/index.php0000644000175000017500000002503510667336241017200 0ustar gemgem DerbyTech Wireless Network
>
Search  
Usage Reports Failure Report Uptime Report Management class=text-button>All Towers ".$r['name']." "); } ?>
bandwidthd-2.0.1+cvs20090917/phphtdocs/config.conf0000644000175000017500000000043210667336241017466 0ustar gemgembandwidthd-2.0.1+cvs20090917/phphtdocs/signal_level.php0000755000175000017500000000403410667336733020542 0ustar gemgem Signal Level Report

Signal Level Report

No routers reporting uptime
"; else { echo ""; echo "
LocationRouterInterface Min LatencyAvg Latency Max LatencyLoad AvgSignal Checkin Overdue"; while ($r = @pg_fetch_array($res)) { echo("
".$r['loc_name']. "".$r['sensor_name']." ".$r['interface']. "".$r['minlatency']. "".round($r['avglatency'], 1). "".$r['maxlatency']. "".round($r['loadavg'], 2). "".round($r['signal'],1). ""); if ($r['checkin'] > 0) echo($r['checkin']); } echo "
"; } ?> bandwidthd-2.0.1+cvs20090917/phphtdocs/footer.php0000644000175000017500000000011210165355101017341 0ustar gemgembandwidthd-2.0.1+cvs20090917/phphtdocs/header.php0000644000175000017500000000004310254360024017275 0ustar gemgem
bandwidthd-2.0.1+cvs20090917/phphtdocs/legend.gif0000644000175000017500000000316110165355101017266 0ustar gemgemGIF89a3f3333f333ff3fffff3f3f̙3f3333f3333333333f3333333f3f33ff3f3f3f3333f3333333f3̙333333f333ff3ffffff3f33f3ff3f3f3ffff3fffffffffff3fffffff3fff̙ffff3fffff3f̙3333f33̙3ff3ffff̙f3f̙3f̙̙3f̙3f3333f333ff3fffff̙̙3̙f̙̙̙3f̙3f3f3333f333ff3fffff3f3f̙3f,H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ(Kl˲hǞMv-[,ߖ+W-ػx ߿8ÅmcƊWP@eʑUC3g8=gӥG]ͺk}V} hw%'_$Ϝ)%\\$4M)cBуz۷cppҟ/-x9\tb7vVh!_}EW^bEف{].wem^}g9a1`-~/xL6ٕv2aTc#F0&9a+6棉WF$܌%_\gp /zfC )]xN*LAawUI 88g YhhVVcV8`h)GuڨYbRJ謴 Myaen>*Z x&8^ib!z'Z偽*= +1:fY+Ynjj)'%YQCꍨ d.Z>fċJt*q*Oo:(i6,47_JK1&,#_J53803]\0wE9Egyt͂YCP2ܢ#qm'^[nո\3NW]Iygw砇.褗n騧ꬷ.nD;;;bandwidthd-2.0.1+cvs20090917/phphtdocs/extensions.sql0000755000175000017500000000040210337130110020247 0ustar gemgemCREATE TABLE extension_log ( sensor_id int, timestamp timestamp with time zone DEFAULT now(), errors varchar, loadavg varchar, signal varchar, uptime varchar, wireless varchar); create index extension_log_sensor_id_idx on extension_log(sensor_id); bandwidthd-2.0.1+cvs20090917/phphtdocs/uptime.php0000755000175000017500000000353010667336241017373 0ustar gemgem Uptime Report

Uptime Report

No routers reporting uptime
"; else { echo ""; echo "
RouterLocationVersionLoad AvgRebootsUptimeCheckin Overdue"; while ($r = @pg_fetch_array($res)) { $extension_log = pg_query("select * from extension_log where sensor_id = ".$r['sensor_id']." order by timestamp desc limit 1;"); $extension = @pg_fetch_array($extension_log); echo("
".$r['sensor_name']."".$r['loc_name']."".$extension['version']."".$extension['loadavg']."".$r['reboots']."".$r['uptime'].""); if ($r['checkin'] > 0) echo($r['checkin']); } echo "
"; } ?> bandwidthd-2.0.1+cvs20090917/phphtdocs/gpscoords.php0000755000175000017500000000231710337130110020052 0ustar gemgem
bandwidthd-2.0.1+cvs20090917/phphtdocs/sensors.php0000755000175000017500000001764611145324327017573 0ustar gemgem >
Collecting data..."; exit; } ?> >Display Graphs Subnet Filter:">
Top $limit - $sensor_name - $interface"; else echo "

All Records - $sensor_name - $interface

"; // Sqlize the incomming variables if (isset($subnet)) $sql_subnet = "and ip <<= '$subnet'"; // Sql Statement $sql = "select tx.ip, rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp, tx.icmp+rx.icmp as icmp, tx.http+rx.http as http, tx.mail+rx.mail as mail, tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp from (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(mail) as mail, sum(p2p) as p2p, sum(ftp) as ftp from sensors, bd_tx_log where sensors.sensor_id = '$sensor_id' and sensors.sensor_id = bd_tx_log.sensor_id $sql_subnet and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime group by ip) as tx, (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(mail) as mail, sum(p2p) as p2p, sum(ftp) as ftp from sensors, bd_rx_log where sensors.sensor_id = '$sensor_id' and sensors.sensor_id = bd_rx_log.sensor_id $sql_subnet and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime group by ip) as rx where tx.ip = rx.ip order by total desc;"; //echo "
$sql
"; exit(0); pg_query("SET sort_mem TO 30000;"); pg_send_query($db, $sql); $query_start = time(); Echo "Query In Progress."; flush(); while (pg_connection_busy($db)) { sleep(2); Echo "."; flush(); } echo((time()-$query_start)." seconds "); $result = pg_get_result($db); pg_query("set sort_mem to default;"); if ($limit == "all") $limit = pg_num_rows($result); echo "
IpNameTotalSentReceivedtcpudpicmphttpmailp2pftp"; if (!isset($subnet)) // Set this now for total graphs $subnet = "0.0.0.0/0"; // Output Total Line if ($graphs == "") $url = ""; else $url = ""; echo "\n
".$url."Total$subnet"; foreach (array("total", "sent", "received", "tcp", "udp", "icmp", "http", "mail", "p2p", "ftp") as $key) { for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++) { $r = pg_fetch_array($result, $Counter); $Total += $r[$key]; } echo fmtb($Total); } echo "\n"; // Output Other Lines for($Counter=0; $Counter < pg_num_rows($result) && $Counter < $limit; $Counter++) { $r = pg_fetch_array($result, $Counter); if ($graphs == "") $url = ""; else $url = ""; echo "
".$url; echo $r['ip']."".gethostbyaddr($r['ip']); echo ""; echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']). fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']).fmtb($r['mail']). fmtb($r['p2p']).fmtb($r['ftp'])."\n"; } echo "
"; // Stop here if ($graphs == "") exit(); // Output Total Graph for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++) { $r = pg_fetch_array($result, $Counter); $scale = max($r['txscale'], $scale); $scale = max($r['rxscale'], $scale); } if ($subnet == "0.0.0.0/0") $total_table = "bd_tx_total_log"; else $total_table = "bd_tx_log"; $sn = str_replace("/", "_", $subnet); echo "

"; echo "Total - Total of $subnet

"; echo ""; echo "Send:

"; echo "
\n"; if ($subnet == "0.0.0.0/0") $total_table = "bd_rx_total_log"; else $total_table = "bd_rx_log"; echo "Receive:

"; echo "
\n"; echo "[Return to Top]"; // Output Other Graphs for($Counter=0; $Counter < pg_num_rows($result) && $Counter < $limit; $Counter++) { $r = pg_fetch_array($result, $Counter); echo "

"; if ($r['ip'] == "0.0.0.0") echo "Total - Total of all subnets

"; else echo $r['ip']." - ".gethostbyaddr($r['ip']).""; echo ""; echo "Send:

"; echo "
\n"; echo "Receive:

"; echo "
\n"; echo "[Return to Top]"; } include('footer.php');bandwidthd-2.0.1+cvs20090917/phphtdocs/bd_pgsql_purge.sh0000755000175000017500000000440110167562671020711 0ustar gemgemecho "SET sort_mem TO 45000;" echo -e "bd_rx_log \n bd_tx_log \n bd_rx_total_log \n bd_tx_total_log" | while read TABLE; do cat << EOF BEGIN; insert into $TABLE (sensor_id, ip, timestamp, sample_duration, total, icmp, udp, tcp, ftp, http, p2p) select sensor_id, ip, date_trunc('day', timestamp) + (case when extract(hour from timestamp) >= 12 then interval '12 hours' else interval '0 hours' end) + interval '12 hours', 60*60*12, sum(total), sum(icmp), sum(udp), sum(tcp), sum(ftp), sum(http), sum(p2p) from $TABLE where sample_duration < 60*60*12 and timestamp < now() - interval '35 days' group by sensor_id, ip, date_trunc('day', timestamp) + (case when extract(hour from timestamp) >= 12 then interval '12 hours' else interval '0 hours' end); delete from $TABLE where sample_duration < 60*60*12 and timestamp < now() - interval '35 days'; COMMIT; BEGIN; insert into $TABLE (sensor_id, ip, timestamp, sample_duration, total, icmp, udp, tcp, ftp, http, p2p) select sensor_id, ip, date_trunc('hour', timestamp)+interval '1 hour', 60*60, sum(total), sum(icmp), sum(udp), sum(tcp), sum(ftp), sum(http), sum(p2p) from $TABLE where sample_duration < 60*60 and timestamp < now() - interval '7 days' group by sensor_id, ip, date_trunc('hour', timestamp); delete from $TABLE where sample_duration < 60*60 and timestamp < now() - interval '7 days'; COMMIT; BEGIN; insert into $TABLE (sensor_id, ip, timestamp, sample_duration, total, icmp, udp, tcp, ftp, http, p2p) select sensor_id, ip, date_trunc('hour', timestamp) + (interval '1 minute' * trunc(EXTRACT(MINUTE FROM timestamp)::numeric,-1)) + interval '10 minutes', 10*60, sum(total), sum(icmp), sum(udp), sum(tcp), sum(ftp), sum(http), sum(p2p) from $TABLE where sample_duration < 10*60 and timestamp < now() - interval '2 days' group by sensor_id, ip, date_trunc('hour', timestamp) + (interval '1 minute' * trunc(EXTRACT(MINUTE FROM timestamp)::numeric,-1)); delete from $TABLE where sample_duration < 10*60 and timestamp < now() - interval '2 days'; COMMIT; EOF done echo "VACUUM ANALYZE"bandwidthd-2.0.1+cvs20090917/phphtdocs/include.php0000644000175000017500000000250610254360024017476 0ustar gemgem $value) { unset($GLOBALS[$global]); } } } define("INT_DAILY", 60*60*24*2); define("INT_WEEKLY", 60*60*24*8); define("INT_MONTHLY", 60*60*24*35); define("INT_YEARLY", 60*60*24*400); define("XOFFSET", 90); define("YOFFSET", 45); require("config.conf"); function ConnectDb() { global $db_connect_string; $db = pg_pconnect($db_connect_string); if (!$db) { printf("DB Error, could not connect to database"); exit(1); } return($db); } function fmtb($kbytes) { $Max = 1024; $Output = $kbytes; $Suffix = 'K'; if ($Output > $Max) { $Output /= 1024; $Suffix = 'M'; } if ($Output > $Max) { $Output /= 1024; $Suffix = 'G'; } if ($Output > $Max) { $Output /= 1024; $Suffix = 'T'; } return(sprintf("%.1f%s", $Output, $Suffix)); } $starttime = time(); set_time_limit(300); ?>bandwidthd-2.0.1+cvs20090917/phphtdocs/failures.php0000755000175000017500000001062310667336241017703 0ustar gemgem Failure Report

Failed Routers

All routers have checked in"; else { echo ""; echo "
RouterLocationCheckin Overdue"; while ($r = @pg_fetch_array($res)) { echo("
".$r['sensor_name']."".$r['loc_name']."".$r['missing']); } echo "
"; } ?>

Failed Links

?reset_links=1 class=text-button>Reset Broken Links
First TowerSecond TowerFirst Router Second RouterLast Update No links in database..."; while ($r = @pg_fetch_array($links)) { echo("
".$r['loc_a_name']."".$r['loc_b_name']); echo("".ereg_replace("\..*$", "", $r['sens_a_name'])." - ".$r['sens_a_interface']); echo("".ereg_replace("\..*$", "", $r['sens_b_name'])." - ".$r['sens_b_interface']); echo("".$r['last_update']); } ?>

Low Rates

No low rates on record"; else { echo ""; while ($r = @pg_fetch_array($res)) { echo("
".$r['sensor_name']."".$r['interface']."".$r['signal']); $res2 = pg_query("SELECT timestamp, wireless from extension_log where sensor_id = ".$r['sensor_id']." order by timestamp desc limit 3"); echo("
");
		while($r2 = @pg_fetch_array($res2))
			{
			echo($r2['timestamp']."\n".preg_replace("/Encryption key:[0-9A-F-]+/", "Encryption key:HIDDEN", $r2['wireless']));
			}
    	}
	echo "
"; } ?> bandwidthd-2.0.1+cvs20090917/phphtdocs/x.gif0000755000175000017500000000025310337130110016271 0ustar gemgemGIF89aAAAfffsssSSS\\\!,XI+ 5  di!ྰ{ksJ0/7т6(fRYdTQaNo`,,:pwJ ;bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/0000755000175000017500000000000011254363050016572 5ustar gemgembandwidthd-2.0.1+cvs20090917/phphtdocs/manage/bandwidthd.css0000755000175000017500000000353410337130110021412 0ustar gemgem.body { font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: #333333; } h3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; font-weight: bold; color: #2A337E; border: solid 1px #666666; padding: 2px; background-color: #c0c0c0; } th { font-family: verdana; font-size: 10px; background-color: #c0c0c0; color: #333333; align: center; cell-spacing: 0px; } .row-header-left { border-left: solid 1px #666666; border-top: solid 1px #666666; border-bottom: solid 1px #666666; line-height: 9px; padding: 2px; } .row-header-middle { border-top: solid 1px #666666; border-bottom: solid 1px #666666; line-height: 9px; padding: 2px; } .row-header-right { border-right: solid 1px #666666; border-top: solid 1px #666666; border-bottom: solid 1px #666666; line-height: 9px; padding: 2px; } a.text-button:link, a.text-button:visited { font-family: verdana; font-size: 10px; font-weight: bold; color: #2A337E; text-decoration: none; background-color: #F6F6F6; border: solid 1px #666666; padding-top: 1px; padding-bottom: 1px; padding-left: 5px; padding-right: 5px; margin-top: 10px; } a.text-button:hover { font-family: verdana; font-size: 10px; font-weight: bold; color: #ffffff; text-decoration: none; background-color: #828DBA; border: solid 1px #666666; padding-top: 1px; padding-bottom: 1px; padding-left: 5px; padding-right: 5px; } bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/passwords0000755000175000017500000000002310337130110020526 0ustar gemgemroot:E2Xbv81iVlpDA bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/logo.gif0000755000175000017500000001662510337130110020224 0ustar gemgemGIF87a  3fLyL(u@@}NN ppfAAA쟟7j3pp=lﹿ33Y|33%%%``̙DlY0p SZZަ3怀4`33q))V"a@@PPVVV v:ﯯ@p &ZəCP`Y([!!鏏#IPPBGy{{̳-y)|ffrʙ SwwSw r,+wHTw<rrjwtt+w6wCwaFw@BANDrH Vw`w6w\WCraFw@ ~L˚~#~$h bandwidthd-logo.8l qwLL4+w6wDswaFwDDxl|l|H8lDxlsD8l!, @H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sܹĀPIѣH*MSd~,JիX6}u@֯`¤ت[:=6!ٟfqjp[E׈l9{W^ (^ވ}W2PO^sǾBOF|fbƨS(8Zri^H}F̑%Wư|ECw# {"+.iqk]C"U|sHu mW{xQ! 5({ ݄NfTAj]衇M t|{`BH@ruA"aH8.CiQ (TN@v1(vq]Y Q0!e\"e%r&@ B tfWd t5>ŇyКWB}>%&Bd*J@B9lFv ~:abGjFZjri꫞~I%vŅH5kd} BլR+rD_xI.!0k $wQNu %Є&?k!LAH @Z0A x8~IOp4apPĒDS3FlDxP U } $Pn(1@avx~Cm|O8 +O Gu)re 4~7H 0AxH3U4uD)-Ppa5b[AMD|dVGNЊek~yA~Ӣn騧ꨓǾeO.u/XN+F[P ]|0 Wogw/o觯VA) HLXBL̠IV z0A5P3".ka r7I&A0H O$gwHF /”:4hQS@AE  ĊIt eA>rƚEI-df3uJ[\!F VfoVrҵ(4GKԃ%_YUe%T| > urj(IL*`,) \2 &= ^~…# b SA0j A : @ b@0;eb' 贌:I~h Q 40"g2eS2/ZH泌N'fz`6d#<"B<+dH^AgaHHф4ecuh,fMqI247!B8x+r~TC`OBt V=Nv|60{@GK!Q@ L:!.2atf ְ$L;ڔ!}=lE(Ȑ)~A@z!J(z)f"˼dЩEN*;-l2W%W%] ]\} wӹX:E2/Pf٫b绕.FrRO۩:%{+K$7)7zN4F;ѐ'MJ[Ҙδ7NGxԨNMcAU*QT`MZε+]v5 pA㰍]ϰّVDD a<-h(eih`wÅ([U@z*^;m`%RKTؑ%5UM{!IlppecN.f5i3Oz0olB0ڕO dI1 pc%}:-d;Pԟ_LtS]SVz}uN%xA2ˎz !8čakdT )X#} *\-\X([/1 :,D/:<)aW-~@hrsO|W:ނ^2Wu0tG l %B 2 |M <~{'zA/PeϢ+F Jon3~Txqjv€ ~\"nFhSj1U2q''BVC E)WMĥttU*_`_)20! P*%@!)_ |])=?*A8!u) !ф%ܲKc8!bH]B3EvJRv> z%xzk{3}HMҁ!OUq!;E>MywxwXC$JR a h-$?@xgrAS~"_lvQ&yw4Nq#x}NA2;狆kȇ*7}Qo2#X$0}7/erexGu( sbŎXax5s''RC\SzzQ ~ ]Dxk~mR)]@Iya9%I_37"%9"D%B8 9nWWG)a\f0i)EUMS)^uEv"_YN[ɃBX*RXa!0v$c)Pue$]Y-B!dpUtNW]^+/pQ/)rX$t1(!UU nq<(d7 EHD_%N@!bx42I6G_u6Q0u0CU"8!2AwDxB_PrqS0BxUÚS8#B@4S@B;D[F{HJL۴NPR;fHX{@MqY۵b?c{AlKqpmlA0p+v47wS|:᷀;5!{0a+Ajij;3ij$nTh;j[m@VCќֺf3ؖ@纍vW@炙UmDb15ĻhnҁgNڤX)ޤNRF Ba;-{O؁q>9 ^+[o3ENG.$PP)m!NNQ.@K>#ax5քC#5|*x.oSKz>#[tl~b>|>} GgW3{TǡމE~LΈna`'es I3\!(Ic e>t͈$?D m}"= l˪m9#x@V-}xSa^H>žOB&.E鬘K㽼bXVFXJmS^5jaU2'V>  j .p阝lмWVmnPj{.A?ќ6mj.5[i\z_h~_&5p7ű#d&("5\;lc[d̤#~Պh)EjO:Bx8=9J ,aw|5(o2_&OEѥȇï#a3( YBz*73Wm͎)얱9"P-#!y~eb5M4IdCorSGNX@1@@.&Dxp@ I HH"C=~, MRJ-U*@.Y.XLrV40Od~$0"NURLz3FhA $*Pq <O[P09&d = \FujRaH!-_Ɯyw HCbp"^IA). r0l&Kc.[zś۰c3H4Ict^vݽc9Ա{zB;l;5z/Y nҝ=؊ X R .*BhB6C/b# Q QC.?B4kLjV HH0rqҸPQ" rcý(=K&"D]c '⽆k*HؚǰJ1#}#p(# Z#JH' OJ(x3< t /WeU%D8Z ~:D ;[t˄Js`TJhJ3PdT7X֢h+k ˝ 80#I}GgU<)hʜEY/VWbaM H(XPuc =͖Pt*y\<2Ee+dvXakg]>r6wQ RXulߔZFVevYb 4nDYƈlIfO.~D yfS:qgqߙgdkS%;\mW#9kMߛU پcfcN(l 7_.rjgow柇y<;DܷEŖ@*0?7.u7orF2 M`,8JPR^~)3x-k~1 @X«mzS?b8D"шG" D&PH" RV,"E.vыRb8F2reDc(-z G $value) { if (preg_match ("/(^LocationGroup)([0-9]*)$/i", $key, $match)) { $group[$match[2]] = $value; } elseif (preg_match ("/(^LocationLatitude)([0-9]*)$/i", $key, $match)) { $latitude[$match[2]] = $value; } elseif (preg_match ("/(^LocationLongitude)([0-9]*)$/i", $key, $match)) { $longitude[$match[2]] = $value; } elseif (preg_match ("/(^LocationName)([0-9]*)$/i", $key, $match)) { $name[$match[2]] = $value; } } foreach($name as $key => $value) { pg_query("UPDATE locations set name = '".$name[$key]."', group_id = ".$group[$key].", latitude = '".$latitude[$key]."', longitude = '".$longitude[$key]."' where id = '".$key."';"); } pg_query("vacuum locations;"); header("Location: manage.php"); exit(0); } if ($HTTP_POST_VARS['submit'] == "Add Location") { pg_query("INSERT INTO locations (name, group_id, longitude, latitude) values ('".$HTTP_POST_VARS['name']."', ".$HTTP_POST_VARS['group_id'].", '".$HTTP_POST_VARS['longitude']."', '".$HTTP_POST_VARS['latitude']."');"); header("Location: manage.php"); exit(0); } if ($HTTP_POST_VARS['submit'] == "Add to Ignored Links") { pg_query("INSERT INTO links_ignorelist (sensor_id) SELECT sensor_id from sensors where sensor_name like '".$HTTP_POST_VARS['sensor_name']."%' and interface = '".$HTTP_POST_VARS['interface']."';"); header("Location: manage.php"); exit(0); } include("manage_header.php"); ?>

Locations

>
NameColorLongitudeLatitude No locations in database..."; while ($r = @pg_fetch_array($locations)) { echo("
"); pg_result_seek($groups, 0); echo(""); echo(""); echo(""); } ?>
> "); ?>

Links

>
First TowerSecond TowerFirst Router Second RouterLast Update No links in database..."; while ($r = @pg_fetch_array($links)) { echo("
".$r['loc_a_name']."".$r['loc_b_name']); echo("".ereg_replace("\..*$", "", $r['sens_a_name'])." - ".$r['sens_a_interface']); echo("".ereg_replace("\..*$", "", $r['sens_b_name'])." - ".$r['sens_b_interface']); echo("".$r['last_update']); } ?>
 

Hide Links To

>
Sensor NameInterfaceFar LocationFar Router No links in database..."; while ($r = @pg_fetch_array($res)) { echo("
".$r['sensor_name']."".$r['interface']); $res2 = pg_query("select locations.name as loc_name, sensor_name from links, locations, sensors where id2 = ".$r['sensor_id']." and id1 = sensor_id and location = locations.id;"); while ($r2 = @pg_fetch_array($res2)) { echo("
 ".$r2['loc_name']."".$r2['sensor_name']); } $res2 = pg_query("select locations.name as loc_name, sensor_name from links, locations, sensors where id1 = ".$r['sensor_id']." and id2 = sensor_id and location = locations.id;"); while ($r2 = @pg_fetch_array($res2)) { echo("
 ".$r2['loc_name']."".$r2['sensor_name']); } } ?>
bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/legend.gif0000755000175000017500000000316110337130110020511 0ustar gemgemGIF89a3f3333f333ff3fffff3f3f̙3f3333f3333333333f3333333f3f33ff3f3f3f3333f3333333f3̙333333f333ff3ffffff3f33f3ff3f3f3ffff3fffffffffff3fffffff3fff̙ffff3fffff3f̙3333f33̙3ff3ffff̙f3f̙3f̙̙3f̙3f3333f333ff3fffff̙̙3̙f̙̙̙3f̙3f3f3333f333ff3fffff3f3f̙3f,H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ(Kl˲hǞMv-[,ߖ+W-ػx ߿8ÅmcƊWP@eʑUC3g8=gӥG]ͺk}V} hw%'_$Ϝ)%\\$4M)cBуz۷cppҟ/-x9\tb7vVh!_}EW^bEف{].wem^}g9a1`-~/xL6ٕv2aTc#F0&9a+6棉WF$܌%_\gp /zfC )]xN*LAawUI 88g YhhVVcV8`h)GuڨYbRJ謴 Myaen>*Z x&8^ib!z'Z偽*= +1:fY+Ynjj)'%YQCꍨ d.Z>fċJt*q*Oo:(i6,47_JK1&,#_J53803]\0wE9Egyt͂YCP2ܢ#qm'^[nո\3NW]Iygw砇.褗n騧ꬷ.nD;;;bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/manage_header.php0000755000175000017500000000061110337130110022032 0ustar gemgem Bandwidthd Management Console
Locations and Links Manual Symbols Sensors
bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/manage_symbols.php0000755000175000017500000000345710337130110022305 0ustar gemgem

Pie Slices

>
 Sensor NameInterfaceDirectionAngleRadius No links in database..."; while ($r = @pg_fetch_array($res)) { echo("
".$r['sensor_name']."".$r['interface']."".$r['direction']."".$r['angle']."".$r['radius']); } ?>
 
 
bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/x.gif0000755000175000017500000000025310337130110017521 0ustar gemgemGIF89aAAAfffsssSSS\\\!,XI+ 5  di!ྰ{ksJ0/7т6(fRYdTQaNo`,,:pwJ ;bandwidthd-2.0.1+cvs20090917/phphtdocs/manage/manage_sensors.php0000755000175000017500000001044210337130110022301 0ustar gemgem $value) { if (preg_match ("/(^SensorLocation)([0-9]*)$/i", $key, $match)) { $result = pg_query("Select sensor_name from sensors where sensor_id = '$match[2]';"); $row = pg_fetch_array($result); pg_query("UPDATE sensors set location = $value where sensor_name = '".$row['sensor_name']."';"); } } header("Location: $PHP_SELF"); exit(0); } include("manage_header.php"); if ($HTTP_GET_VARS['del_sensor'] != "") { $result = pg_query("select * from sensors where sensor_name = '".$HTTP_GET_VARS['del_sensor']."';"); while ($r = @pg_fetch_array($result)) { echo("Please wait while deleting records from tables...
\n"); $sql = "delete from bd_rx_log where sensor_id = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); $sql = "delete from bd_tx_log where sensor_id = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); $sql = "delete from bd_tx_total_log where sensor_id = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); $sql = "delete from bd_rx_total_log where sensor_id = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); $sql = "delete from links where id1 = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); $sql = "delete from links where id2 = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); $sql = "delete from sensors where sensor_id = ".$r['sensor_id']; echo($sql."
\n"); flush(); pg_query($sql); } echo("Done
\n"); exit(0); } ?>
>

Un-assigned sensors

No un-assigned sensors in database..."; ?>
 Sensor NameAssign LocationLast Checkin ".$r['sensor_name']."".$r['last_connection']; } ?>
 

>

Assigned sensors

No un-assigned sensors in database..."; ?>
 Sensor NameAssign LocationLast Checkin ".$r['sensor_name']."".$r['last_connection']; } ?>
 
bandwidthd-2.0.1+cvs20090917/phphtdocs/maint.weekly0000755000175000017500000000455710337130110017700 0ustar gemgemecho "SET sort_mem TO 45000;" echo -e "bd_rx_log \n bd_tx_log \n bd_rx_total_log \n bd_tx_total_log" | while read TABLE; do cat << EOF BEGIN; insert into $TABLE (sensor_id, ip, timestamp, sample_duration, packet_count, total, icmp, udp, tcp, ftp, http, p2p) select sensor_id, ip, date_trunc('day', timestamp) + (case when extract(hour from timestamp) >= 12 then interval '12 hours' else interval '0 hours' end) + interval '12 hours', 60*60*12, sum(packet_count), sum(total), sum(icmp), sum(udp), sum(tcp), sum(ftp), sum(http), sum(p2p) from $TABLE where sample_duration < 60*60*12 and timestamp < now() - interval '35 days' group by sensor_id, ip, date_trunc('day', timestamp) + (case when extract(hour from timestamp) >= 12 then interval '12 hours' else interval '0 hours' end); delete from $TABLE where sample_duration < 60*60*12 and timestamp < now() - interval '35 days'; COMMIT; BEGIN; insert into $TABLE (sensor_id, ip, timestamp, sample_duration, packet_count, total, icmp, udp, tcp, ftp, http, p2p) select sensor_id, ip, date_trunc('hour', timestamp)+interval '1 hour', 60*60, sum(packet_count), sum(total), sum(icmp), sum(udp), sum(tcp), sum(ftp), sum(http), sum(p2p) from $TABLE where sample_duration < 60*60 and timestamp < now() - interval '7 days' group by sensor_id, ip, date_trunc('hour', timestamp); delete from $TABLE where sample_duration < 60*60 and timestamp < now() - interval '7 days'; COMMIT; BEGIN; insert into $TABLE (sensor_id, ip, timestamp, sample_duration, packet_count, total, icmp, udp, tcp, ftp, http, p2p) select sensor_id, ip, date_trunc('hour', timestamp) + (interval '1 minute' * trunc(EXTRACT(MINUTE FROM timestamp)::numeric,-1)) + interval '10 minutes', 10*60, sum(packet_count), sum(total), sum(icmp), sum(udp), sum(tcp), sum(ftp), sum(http), sum(p2p) from $TABLE where sample_duration < 10*60 and timestamp < now() - interval '2 days' group by sensor_id, ip, date_trunc('hour', timestamp) + (interval '1 minute' * trunc(EXTRACT(MINUTE FROM timestamp)::numeric,-1)); delete from $TABLE where sample_duration < 10*60 and timestamp < now() - interval '2 days'; COMMIT; CLUSTER $TABLE; ANALYZE $TABLE; EOF done bandwidthd-2.0.1+cvs20090917/bandwidthd.c0000644000175000017500000010640511145324327015633 0ustar gemgem#include "bandwidthd.h" #include // We must call regular exit to write out profile data, but child forks are supposed to usually // call _exit? #ifdef PROFILE #define _exit(x) exit(x) #endif /* #ifdef DEBUG #define fork() (0) #endif */ // **************************************************************************************** // ** Global Variables // **************************************************************************************** #define SNAPLEN 100 static pcap_t *pd; unsigned int GraphIntervalCount = 0; unsigned int IpCount = 0; unsigned int SubnetCount = 0; int IntervalFinished = FALSE; time_t IntervalStart; time_t ProgramStart; int RotateLogs = FALSE; int PacketCallbackLock = 0; pid_t pidGraphingChild = 0; struct SubnetData SubnetTable[SUBNET_NUM]; struct IPData IpTable[IP_NUM]; int DataLink; int IP_Offset; struct IPDataStore *IPDataStore = NULL; extern int bdconfig_parse(void); void BroadcastState(int fd); extern FILE *bdconfig_in; struct config config; struct Broadcast *Broadcasts = NULL; pid_t workerchildpids[NR_WORKER_CHILDS]; void ResetTrafficCounters(void); void CloseInterval(void); void signal_handler(int sig) { switch (sig) { case SIGHUP: signal(SIGHUP, signal_handler); RotateLogs++; if (config.tag == '1') { int i; /* signal children */ for (i=0; i < NR_WORKER_CHILDS; i++) if (workerchildpids[i]) // this is a child kill(workerchildpids[i], SIGHUP); } break; case SIGTERM: if (config.tag == '1') { int i; /* send term signal to children */ for (i=0; i < NR_WORKER_CHILDS; i++) if (workerchildpids[i]) kill(workerchildpids[i], SIGTERM); } // TODO: Might want to make sure we're not in the middle of wrighting out a log file exit(0); break; } } void bd_CollectingData() { char FileName[4][MAX_FILENAME]; FILE *index; int Counter; snprintf(FileName[0], MAX_FILENAME, "%s/index.html", config.htdocs_dir); snprintf(FileName[1], MAX_FILENAME, "%s/index2.html", config.htdocs_dir); snprintf(FileName[2], MAX_FILENAME, "%s/index3.html", config.htdocs_dir); snprintf(FileName[3], MAX_FILENAME, "%s/index4.html", config.htdocs_dir); for(Counter = 0; Counter < 4; Counter++) { index = fopen(FileName[Counter], "wt"); if (index) { fprintf(index, "\n"); fprintf(index, "Bandwidthd\n"); if (config.meta_refresh) fprintf(index, "\n", config.meta_refresh); fprintf(index, "\n"); fprintf(index, "\n"); fprintf(index, "\n
\"Logo\"
\n"); fprintf(index, "
\n -
Daily -- Weekly -- "); fprintf(index, "Monthly -- Yearly
\n"); fprintf(index, "

bandwidthd has nothing to graph. This message should be replaced by graphs in a few minutes. If it's not, please see the section titled \"Known Bugs and Troubleshooting\" in the README"); fprintf(index, "\n"); fclose(index); } else { syslog(LOG_ERR, "Cannot open %s for writing", FileName[Counter]); exit(1); } } } pid_t WriteOutWebpages(long int timestamp) { struct IPDataStore *DataStore = IPDataStore; struct SummaryData **SummaryData; int NumGraphs = 0; pid_t graphpid; int Counter; /* Did we catch any packets since last time? */ if (!DataStore) return -2; // break off from the main line so we don't miss any packets while we graph graphpid = fork(); switch (graphpid) { case 0: /* we're the child, graph. */ { #ifdef PROFILE // Got this incantation from a message board. Don't forget to set // GMON_OUT_PREFIX in the shell extern void _start(void), etext(void); syslog(LOG_INFO, "Calling profiler startup..."); monstartup((u_long) &_start, (u_long) &etext); #endif signal(SIGHUP, SIG_IGN); nice(4); // reduce priority so I don't choke out other tasks // Count Number of IP's in datastore for (DataStore = IPDataStore, Counter = 0; DataStore; Counter++, DataStore = DataStore->Next); // +1 because we don't want to accidently allocate 0 SummaryData = malloc(sizeof(struct SummaryData *)*Counter+1); DataStore = IPDataStore; while (DataStore) // Is not null { if (DataStore->FirstBlock->NumEntries > 0) { SummaryData[NumGraphs] = (struct SummaryData *) malloc(sizeof(struct SummaryData)); GraphIp(DataStore, SummaryData[NumGraphs++], timestamp+LEAD*config.range); } DataStore = DataStore->Next; } MakeIndexPages(NumGraphs, SummaryData); _exit(0); } break; case -1: syslog(LOG_ERR, "Forking grapher child failed!"); return -1; break; default: /* parent + successful fork, assume graph success */ return(graphpid); break; } } void setchildconfig (int level) { static unsigned long long graph_cutoff; switch (level) { case 0: config.range = RANGE1; config.interval = INTERVAL1; config.tag = '1'; graph_cutoff = config.graph_cutoff; break; case 1: // Overide skip_intervals for children config.skip_intervals = CONFIG_GRAPHINTERVALS; config.range = RANGE2; config.interval = INTERVAL2; config.tag = '2'; config.graph_cutoff = graph_cutoff*(RANGE2/RANGE1); break; case 2: // Overide skip_intervals for children config.skip_intervals = CONFIG_GRAPHINTERVALS; config.range = RANGE3; config.interval = INTERVAL3; config.tag = '3'; config.graph_cutoff = graph_cutoff*(RANGE3/RANGE1); break; case 3: // Overide skip_intervals for children config.skip_intervals = CONFIG_GRAPHINTERVALS; config.range = RANGE4; config.interval = INTERVAL4; config.tag = '4'; config.graph_cutoff = graph_cutoff*(RANGE4/RANGE1); break; default: syslog(LOG_ERR, "setchildconfig got an invalid level argument: %d", level); _exit(1); } } void makepidfile(pid_t pid) { FILE *pidfile; pidfile = fopen("/var/run/bandwidthd.pid", "wt"); if (pidfile) { if (fprintf(pidfile, "%d\n", pid) == 0) { syslog(LOG_ERR, "Bandwidthd: failed to write '%d' to /var/run/bandwidthd.pid", pid); fclose(pidfile); unlink("/var/run/bandwidthd.pid"); } else fclose(pidfile); } else syslog(LOG_ERR, "Could not open /var/run/bandwidthd.pid for write"); } void PrintHelp(void) { printf("\nUsage: bandwidthd [OPTION]\n\nOptions:\n"); printf("\t-D\t\tDo not fork to background\n"); printf("\t-l\t\tList detected devices\n"); printf("\t-c filename\tAlternate configuration file\n"); printf("\t--help\t\tShow this help\n"); printf("\n"); exit(0); } static void handle_interval(int signal) { if (!PacketCallbackLock) CloseInterval(); else // Set flag to have main loop close interval IntervalFinished = TRUE; } int main(int argc, char **argv) { struct bpf_program fcode; u_char *pcap_userdata = 0; #ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *Devices; #endif char Error[PCAP_ERRBUF_SIZE]; struct stat StatBuf; int i; int ForkBackground = TRUE; int ListDevices = FALSE; int Counter; char *bd_conf = NULL; struct in_addr addr, addr2; signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); ProgramStart = time(NULL); // Init worker child pids to zero so we don't kill random things when we shut down for (Counter = 0; Counter < NR_WORKER_CHILDS; Counter++) workerchildpids[Counter] = 0; for(Counter = 1; Counter < argc; Counter++) { if (argv[Counter][0] == '-') { switch(argv[Counter][1]) { case 'D': ForkBackground = FALSE; break; case 'l': ListDevices = TRUE; break; case 'c': if (argv[Counter+1]) { bd_conf = argv[Counter+1]; Counter++; } else PrintHelp(); break; default: printf("Improper argument: %s\n", argv[Counter]); case '-': PrintHelp(); } } } config.dev = NULL; config.description = "No Description"; config.management_url = "https://127.0.0.1"; config.filter = "ip or ether proto 1537"; //config.filter = "ip"; config.skip_intervals = CONFIG_GRAPHINTERVALS; config.graph_cutoff = CONFIG_GRAPHCUTOFF; config.promisc = TRUE; config.extensions = FALSE; config.graph = TRUE; config.output_cdf = FALSE; config.recover_cdf = FALSE; config.meta_refresh = CONFIG_METAREFRESH; config.output_database = FALSE; config.db_connect_string = NULL; config.sensor_name = "unset"; config.log_dir = LOG_DIR; config.htdocs_dir = HTDOCS_DIR; openlog("bandwidthd", LOG_CONS, LOG_DAEMON); // Locate configuration file if (!(bd_conf && !stat(bd_conf, &StatBuf))) { if (bd_conf) { printf("Could not find %s\n", bd_conf); exit(1); } else if (!stat("bandwidthd.conf", &StatBuf)) bd_conf = "bandwidthd.conf"; else if (!stat("./etc/bandwidthd.conf", &StatBuf)) bd_conf = "./etc/bandwidthd.conf"; else if (!stat(CONFIG_FILE, &StatBuf)) bd_conf = CONFIG_FILE; else { printf("Cannot find bandwidthd.conf, ./etc/bandwidthd.conf or %s\n", CONFIG_FILE); syslog(LOG_ERR, "Cannot find bandwidthd.conf, ./etc/bandwidthd.conf or %s", CONFIG_FILE); exit(1); } } bdconfig_in = fopen(bd_conf, "rt"); if (!bdconfig_in) { syslog(LOG_ERR, "Cannot open bandwidthd.conf"); printf("Cannot open ./etc/bandwidthd.conf\n"); exit(1); } bdconfig_parse(); // Log list of monitored subnets for (Counter = 0; Counter < SubnetCount; Counter++) { addr.s_addr = ntohl(SubnetTable[Counter].ip); addr2.s_addr = ntohl(SubnetTable[Counter].mask); syslog(LOG_INFO, "Monitoring subnet %s with netmask %s", inet_ntoa(addr), inet_ntoa(addr2)); } #ifdef HAVE_PCAP_FINDALLDEVS pcap_findalldevs(&Devices, Error); if (config.dev == NULL && Devices && Devices->name) config.dev = strdup(Devices->name); if (ListDevices) { while(Devices) { printf("Description: %s\nName: \"%s\"\n\n", Devices->description, Devices->name); Devices = Devices->next; } exit(0); } #else if (ListDevices) { printf("List devices is not supported by you version of libpcap\n"); exit(0); } #endif if (config.graph) bd_CollectingData(); /* detach from console. */ if (ForkBackground) if (fork2()) exit(0); makepidfile(getpid()); setchildconfig(0); /* initialize first (day graphing) process config */ if (config.graph || config.output_cdf) { /* fork processes for week, month and year graphing. */ for (i=0; i possible infinite loop */ continue; } } } signal(SIGHUP, signal_handler); signal(SIGTERM, signal_handler); if(config.recover_cdf) RecoverDataFromCDF(); IntervalStart = time(NULL); syslog(LOG_INFO, "Opening %s", config.dev); pd = pcap_open_live(config.dev, SNAPLEN, config.promisc, 1000, Error); if (pd == NULL) { syslog(LOG_ERR, "%s", Error); exit(0); } if (pcap_compile(pd, &fcode, config.filter, 1, 0) < 0) { pcap_perror(pd, "Error"); printf("Malformed libpcap filter string in bandwidthd.conf\n"); syslog(LOG_ERR, "Malformed libpcap filter string in bandwidthd.conf"); exit(1); } if (pcap_setfilter(pd, &fcode) < 0) pcap_perror(pd, "Error"); switch (DataLink = pcap_datalink(pd)) { default: if (config.dev) printf("Unknown Datalink Type %d, defaulting to ethernet\nPlease forward this error message and a packet sample (captured with \"tcpdump -i %s -s 2000 -n -w capture.cap\") to hinkle@derbyworks.com\n", DataLink, config.dev); else printf("Unknown Datalink Type %d, defaulting to ethernet\nPlease forward this error message and a packet sample (captured with \"tcpdump -s 2000 -n -w capture.cap\") to hinkle@derbyworks.com\n", DataLink); syslog(LOG_INFO, "Unkown datalink type, defaulting to ethernet"); case DLT_EN10MB: syslog(LOG_INFO, "Packet Encoding: Ethernet"); IP_Offset = 14; //IP_Offset = sizeof(struct ether_header); break; #ifdef DLT_LINUX_SLL case DLT_LINUX_SLL: syslog(LOG_INFO, "Packet Encoding: Linux Cooked Socket"); IP_Offset = 16; break; #endif #ifdef DLT_RAW case DLT_RAW: printf("Untested Datalink Type %d\nPlease report to hinkle@derbyworks.net if bandwidthd works for you\non this interface\n", DataLink); printf("Packet Encoding:\n\tRaw\n"); syslog(LOG_INFO, "Untested packet encoding: Raw"); IP_Offset = 0; break; #endif case DLT_IEEE802: printf("Untested Datalink Type %d\nPlease report to hinkle@derbyworks.net if bandwidthd works for you\non this interface\n", DataLink); printf("Packet Encoding:\nToken Ring\n"); syslog(LOG_INFO, "Untested packet encoding: Token Ring"); IP_Offset = 22; break; } if (ForkBackground) { fclose(stdin); fclose(stdout); fclose(stderr); } if (IPDataStore) // If there is data in the datastore draw some initial graphs { syslog(LOG_INFO, "Drawing initial graphs"); pidGraphingChild = WriteOutWebpages(IntervalStart+config.interval); } ResetTrafficCounters(); // This is also set in CloseInterval because it gets overwritten in some commit modules signal(SIGALRM, handle_interval); alarm(config.interval); nice(1); while (1) { // Bookeeping if (IntervalFinished) // Then write out this intervals data and possibly kick off the grapher CloseInterval(); // Process 1 buffer full of data if (pcap_dispatch(pd, -1, PacketCallback, pcap_userdata) == -1) { syslog(LOG_ERR, "Bandwidthd: pcap_dispatch: %s", pcap_geterr(pd)); exit(1); } } pcap_close(pd); exit(0); } void CloseInterval(void) { time_t current_time; #ifdef PROFILE // Exit and write out profiling information before we commit the data exit(0); #endif current_time = time(NULL); // Sanity check for time getting set forward if ((current_time > IntervalStart+(config.interval*100)) || (current_time < IntervalStart-(config.interval*100))) { IntervalStart = current_time-config.interval; ProgramStart = current_time; } GraphIntervalCount++; CommitData(IntervalStart+config.interval); BroadcastState(pcap_fileno(pd)); ResetTrafficCounters(); // Make sure the signal hasn't been overwritten by one of our CommitData modules // pgsql module does overwrite it signal(SIGALRM, handle_interval); alarm(config.interval); } // Write an ethernet packet describing us out the given socket void BroadcastState(int fd) { char buf[SNAPLEN]; char enet_broadcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; struct ether_header *eptr; if (DataLink != DLT_EN10MB) return; if ((14+strlen(config.sensor_name)+strlen(config.dev)) > SNAPLEN) { syslog(LOG_ERR, "Sensor and device name too long for broadcast"); return; } bzero(buf, sizeof(buf)); eptr = (struct ether_header *) buf; /* start of 16-byte Ethernet header */ // Always broadcast memcpy(&buf[0], enet_broadcast, 6); memcpy(&buf[6], enet_broadcast, 6); // Would rather use our own mac address eptr->ether_type = htons(1537); // Random packet type we'll use for bandwidthd memcpy(buf+14, config.sensor_name, strlen(config.sensor_name)+1); memcpy(buf+14+strlen(config.sensor_name)+1, config.dev, strlen(config.dev)+1); if (write(fd, buf, SNAPLEN) != SNAPLEN) syslog(LOG_ERR, "Write error during bandwidthd broadcast"); } void ParseBroadcast(const u_char *in) { char *p = (char *)in+14; // Skip ethernet header struct Broadcast *bc; struct Broadcast *bc2; char *sensor_name; char *interface; sensor_name = p; interface = p+strlen(p)+1; // Sanity check if (strlen(sensor_name) > SNAPLEN || strlen(interface) > SNAPLEN) { syslog(LOG_ERR, "Bandwidthd broadcast packet failed sanity check, discarding"); return; } if ((!strcmp(sensor_name, config.sensor_name)) && (!strcmp(interface, config.dev))) return; // Our own packet for (bc = Broadcasts; bc; bc = bc->next) { if ((!strcmp(sensor_name, bc->sensor_name)) && (!strcmp(interface, bc->interface))) { // Found this link bc->received = time(NULL); return; } } bc2 = malloc(sizeof(struct Broadcast)); bc2->sensor_name = strdup(sensor_name); bc2->interface = strdup(interface); bc2->received = time(NULL); bc2->next = NULL; if (Broadcasts == NULL) { Broadcasts = bc2; return; } else { for (bc = Broadcasts; bc->next; bc = bc->next); bc->next = bc2; return; } } void PacketCallback(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { unsigned int Counter; u_int caplen = h->caplen; struct ether_header *eptr; const struct ip *ip; uint32_t srcip; uint32_t dstip; struct IPData *ptrIPData; int AlreadyTotaled = FALSE; PacketCallbackLock = TRUE; eptr = (struct ether_header *) p; if (eptr->ether_type == htons(1537)) ParseBroadcast(p); caplen -= IP_Offset; // We're only measuring ip size, so pull off the ethernet header p += IP_Offset; // Move the pointer past the datalink header ip = (const struct ip *)p; // Point ip at the ip header if (ip->ip_v != 4) // then not an ip packet so skip it return; srcip = ntohl(*(uint32_t *) (&ip->ip_src)); dstip = ntohl(*(uint32_t *) (&ip->ip_dst)); for (Counter = 0; Counter < SubnetCount; Counter++) { // Packets from a monitored subnet to a monitored subnet will be // credited to both ip's // Totals are checked for first to speed up FindIp in the total case // That way the 0 entry is always first in the FindIp table if (SubnetTable[Counter].ip == (srcip & SubnetTable[Counter].mask)) { if (!AlreadyTotaled) { Credit(&(IpTable[0].Send), ip); AlreadyTotaled = TRUE; } ptrIPData = FindIp(srcip); // Return or create this ip's data structure if (ptrIPData) Credit(&(ptrIPData->Send), ip); } if (SubnetTable[Counter].ip == (dstip & SubnetTable[Counter].mask)) { if (!AlreadyTotaled) { Credit(&(IpTable[0].Receive), ip); AlreadyTotaled = TRUE; } ptrIPData = FindIp(dstip); if (ptrIPData) Credit(&(ptrIPData->Receive), ip); } } PacketCallbackLock = FALSE; } // Eliminates duplicate entries and fully included subnets so packets don't get // counted multiple times void MonitorSubnet(unsigned int ip, unsigned int mask) { unsigned int subnet = ip & mask; int Counter, Counter2; struct in_addr addr, addr2; addr.s_addr = ntohl(subnet); addr2.s_addr = ntohl(mask); for (Counter = 0; Counter < SubnetCount; Counter++) { if ((SubnetTable[Counter].ip == subnet) && (SubnetTable[Counter].mask == mask)) { syslog(LOG_ERR, "Subnet %s/%s already exists, skipping.", inet_ntoa(addr), inet_ntoa(addr2)); return; } } for (Counter = 0; Counter < SubnetCount; Counter++) { if ((SubnetTable[Counter].ip == (ip & SubnetTable[Counter].mask)) && (SubnetTable[Counter].mask < mask)) { syslog(LOG_ERR, "Subnet %s/%s is already included, skipping.", inet_ntoa(addr), inet_ntoa(addr2)); return; } } for (Counter = 0; Counter < SubnetCount; Counter++) { if (((SubnetTable[Counter].ip & mask) == subnet) && (SubnetTable[Counter].mask > mask)) { syslog(LOG_ERR, "Subnet %s/%s includes already listed subnet, removing smaller entry", inet_ntoa(addr), inet_ntoa(addr2)); // Shift everything down for (Counter2 = Counter; Counter2 < SubnetCount-1; Counter2++) { SubnetTable[Counter2].ip = SubnetTable[Counter2+1].ip; SubnetTable[Counter2].mask = SubnetTable[Counter2+1].mask; } SubnetCount--; Counter--; // Retest this entry because we replaced it } } SubnetTable[SubnetCount].mask = mask; SubnetTable[SubnetCount].ip = subnet; SubnetCount++; } inline void Credit(struct Statistics *Stats, const struct ip *ip) { unsigned long size; const struct tcphdr *tcp; uint16_t port; int Counter; size = ntohs(ip->ip_len); Stats->total += size; Stats->packet_count++; switch(ip->ip_p) { case 6: // TCP tcp = (struct tcphdr *)(ip+1); tcp = (struct tcphdr *) ( ((char *)tcp) + ((ip->ip_hl-5)*4) ); // Compensate for IP Options Stats->tcp += size; // This is a wierd way to do this, I know, but the old "if/then" structure burned alot more CPU for (port = ntohs(tcp->TCPHDR_DPORT), Counter=2 ; Counter ; port = ntohs(tcp->TCPHDR_SPORT), Counter--) { switch(port) { case 110: case 25: case 143: case 587: Stats->mail += size; return; case 80: case 443: Stats->http += size; return; case 20: case 21: Stats->ftp += size; return; case 1044: // Direct File Express case 1045: // '' <- Dito Marks case 1214: // Grokster, Kaza, Morpheus case 4661: // EDonkey 2000 case 4662: // '' case 4665: // '' case 5190: // Song Spy case 5500: // Hotline Connect case 5501: // '' case 5502: // '' case 5503: // '' case 6346: // Gnutella Engine case 6347: // '' case 6666: // Yoink case 6667: // '' case 7788: // Budy Share case 8888: // AudioGnome, OpenNap, Swaptor case 8889: // AudioGnome, OpenNap case 28864: // hotComm case 28865: // hotComm Stats->p2p += size; return; } } return; case 17: Stats->udp += size; return; case 1: Stats->icmp += size; return; } } // TODO: Throw away old data! void DropOldData(long int timestamp) // Go through the ram datastore and dump old data { struct IPDataStore *DataStore; struct IPDataStore *PrevDataStore; struct DataStoreBlock *DeletedBlock; PrevDataStore = NULL; DataStore = IPDataStore; // Progress through the linked list until we reach the end while(DataStore) // we have data { // If the First block is out of date, purge it, if it is the only block // purge the node while(DataStore->FirstBlock->LatestTimestamp < timestamp - config.range) { if ((!DataStore->FirstBlock->Next) && PrevDataStore) // There is no valid block of data for this ip, so unlink the whole ip { // Don't bother unlinking the ip if it's the first one, that's to much // Trouble PrevDataStore->Next = DataStore->Next; // Unlink the node free(DataStore->FirstBlock->Data); // Free the memory free(DataStore->FirstBlock); free(DataStore); DataStore = PrevDataStore->Next; // Go to the next node if (!DataStore) return; // We're done } else if (!DataStore->FirstBlock->Next) { // There is no valid block of data for this ip, and we are // the first ip, so do nothing break; // break out of this loop so the outside loop increments us } else // Just unlink this block { DeletedBlock = DataStore->FirstBlock; DataStore->FirstBlock = DataStore->FirstBlock->Next; // Unlink the block free(DeletedBlock->Data); free(DeletedBlock); } } PrevDataStore = DataStore; DataStore = DataStore->Next; } } void StoreIPDataInDatabase(struct IPData IncData[], struct extensions *extension_data) { if (config.output_database == DB_PGSQL) pgsqlStoreIPData(IncData, extension_data); } void StoreIPDataInCDF(struct IPData IncData[]) { struct IPData *IPData; unsigned int Counter; FILE *cdf; struct Statistics *Stats; char IPBuffer[50]; char logfile[MAX_FILENAME]; snprintf(logfile, MAX_FILENAME, "%s/log.%c.0.cdf", config.log_dir, config.tag); cdf = fopen(logfile, "at"); for (Counter=0; Counter < IpCount; Counter++) { IPData = &IncData[Counter]; HostIp2CharIp(IPData->ip, IPBuffer); fprintf(cdf, "%s,%lu,", IPBuffer, IPData->timestamp); Stats = &(IPData->Send); fprintf(cdf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu", Stats->total, Stats->icmp, Stats->udp, Stats->tcp, Stats->ftp, Stats->http, Stats->mail, Stats->p2p); Stats = &(IPData->Receive); fprintf(cdf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", Stats->total, Stats->icmp, Stats->udp, Stats->tcp, Stats->ftp, Stats->http, Stats->mail, Stats->p2p); } fclose(cdf); } void _StoreIPDataInRam(struct IPData *IPData) { struct IPDataStore *DataStore; struct DataStoreBlock *DataStoreBlock; if (!IPDataStore) // we need to create the first entry { // Allocate Datastore for this IP IPDataStore = malloc(sizeof(struct IPDataStore)); IPDataStore->ip = IPData->ip; IPDataStore->Next = NULL; // Allocate it's first block of storage IPDataStore->FirstBlock = malloc(sizeof(struct DataStoreBlock)); IPDataStore->FirstBlock->LatestTimestamp = 0; IPDataStore->FirstBlock->NumEntries = 0; IPDataStore->FirstBlock->Data = calloc(IPDATAALLOCCHUNKS, sizeof(struct IPData)); IPDataStore->FirstBlock->Next = NULL; if (!IPDataStore->FirstBlock || ! IPDataStore->FirstBlock->Data) { syslog(LOG_ERR, "Could not allocate datastore! Exiting!"); exit(1); } } DataStore = IPDataStore; // Take care of first case while (DataStore) // Is not null { if (DataStore->ip == IPData->ip) // then we have the right store { DataStoreBlock = DataStore->FirstBlock; while(DataStoreBlock) // is not null { if (DataStoreBlock->NumEntries < IPDATAALLOCCHUNKS) // We have a free spot { memcpy(&DataStoreBlock->Data[DataStoreBlock->NumEntries++], IPData, sizeof(struct IPData)); DataStoreBlock->LatestTimestamp = IPData->timestamp; return; } else { if (!DataStoreBlock->Next) // there isn't another block, add one { DataStoreBlock->Next = malloc(sizeof(struct DataStoreBlock)); DataStoreBlock->Next->LatestTimestamp = 0; DataStoreBlock->Next->NumEntries = 0; DataStoreBlock->Next->Data = calloc(IPDATAALLOCCHUNKS, sizeof(struct IPData)); DataStoreBlock->Next->Next = NULL; } DataStoreBlock = DataStoreBlock->Next; } } return; } else { if (!DataStore->Next) // there is no entry for this ip, so lets make one. { // Allocate Datastore for this IP DataStore->Next = malloc(sizeof(struct IPDataStore)); DataStore->Next->ip = IPData->ip; DataStore->Next->Next = NULL; // Allocate it's first block of storage DataStore->Next->FirstBlock = malloc(sizeof(struct DataStoreBlock)); DataStore->Next->FirstBlock->LatestTimestamp = 0; DataStore->Next->FirstBlock->NumEntries = 0; DataStore->Next->FirstBlock->Data = calloc(IPDATAALLOCCHUNKS, sizeof(struct IPData)); DataStore->Next->FirstBlock->Next = NULL; } DataStore = DataStore->Next; } } } void StoreIPDataInRam(struct IPData IncData[]) { unsigned int Counter; for (Counter=0; Counter < IpCount; Counter++) _StoreIPDataInRam(&IncData[Counter]); } void CommitData(time_t timestamp) { int MayGraph = FALSE; unsigned int Counter; struct stat StatBuf; char logname1[MAX_FILENAME]; char logname2[MAX_FILENAME]; int offset; struct extensions *extension_data; // Set the timestamps for (Counter=0; Counter < IpCount; Counter++) IpTable[Counter].timestamp = timestamp; // Call extensions if (config.extensions) extension_data = execute_extensions(); else extension_data = NULL; // Output modules // Only call this from first thread if (config.output_database && config.tag == '1') StoreIPDataInDatabase(IpTable, extension_data); if (config.output_cdf) { // TODO: This needs to be moved into the forked section, but I don't want to // deal with that right now (Heavy disk io may make us drop packets) StoreIPDataInCDF(IpTable); if (RotateLogs >= config.range/RANGE1) // We set this++ on HUP { snprintf(logname1, MAX_FILENAME, "%s/log.%c.%n4.cdf", config.log_dir, config.tag, &offset); snprintf(logname2, MAX_FILENAME, "%s/log.%c.5.cdf", config.log_dir, config.tag); if (!stat(logname2, &StatBuf)) // File exists unlink(logname2); if (!stat(logname1, &StatBuf)) // File exists rename(logname1, logname2); logname1[offset] = '3'; logname2[offset] = '4'; if (!stat(logname1, &StatBuf)) // File exists rename(logname1, logname2); logname1[offset] = '2'; logname2[offset] = '3'; if (!stat(logname1, &StatBuf)) // File exists rename(logname1, logname2); logname1[offset] = '1'; logname2[offset] = '2'; if (!stat(logname1, &StatBuf)) // File exists rename(logname1, logname2); logname1[offset] = '0'; logname2[offset] = '1'; if (!stat(logname1, &StatBuf)) // File exists rename(logname1, logname2); fclose(fopen(logname1, "at")); // Touch file RotateLogs = FALSE; } } if (config.graph) { StoreIPDataInRam(IpTable); // If there is no child to wait on or child returned or waitpid produced an error if (pidGraphingChild < 1 || waitpid(pidGraphingChild, NULL, WNOHANG)) MayGraph = TRUE; if (GraphIntervalCount%config.skip_intervals == 0 && MayGraph) pidGraphingChild = WriteOutWebpages(timestamp); else if (GraphIntervalCount%config.skip_intervals == 0) syslog(LOG_INFO, "Previouse graphing run not complete... Skipping current run"); DropOldData(timestamp); } destroy_extension_data(extension_data); } int RCDF_Test(char *filename) { // Determine if the first date in the file is before the cutoff // return FALSE on error FILE *cdf; char ipaddrBuffer[16]; time_t timestamp; if (!(cdf = fopen(filename, "rt"))) return FALSE; fseek(cdf, 10, SEEK_END); // fseek to near end of file while (fgetc(cdf) != '\n') // rewind to last newline { if (fseek(cdf, -2, SEEK_CUR) == -1) break; } if(fscanf(cdf, " %15[0-9.],%lu,", ipaddrBuffer, ×tamp) != 2) { syslog(LOG_ERR, "%s is corrupted, skipping", filename); return FALSE; } fclose(cdf); if (timestamp < time(NULL) - config.range) return FALSE; // There is no data in this file from after the cutoff else return TRUE; // This file has data from after the cutoff } void RCDF_PositionStream(FILE *cdf) { time_t timestamp; time_t current_timestamp; char ipaddrBuffer[16]; current_timestamp = time(NULL); fseek(cdf, 0, SEEK_END); timestamp = current_timestamp; while (timestamp > current_timestamp - config.range) { // What happenes if we seek past the beginning of the file? if (fseek(cdf, -512*1024,SEEK_CUR) == -1 || ferror(cdf)) { // fseek returned error, just seek to beginning clearerr(cdf); fseek(cdf, 0, SEEK_SET); return; } while (fgetc(cdf) != '\n' && !feof(cdf)); // Read to next line ungetc('\n', cdf); // Just so the fscanf mask stays identical if(fscanf(cdf, " %15[0-9.],%lu,", ipaddrBuffer, ×tamp) != 2) { syslog(LOG_ERR, "Unknown error while scanning for beginning of data...\n"); return; } } while (fgetc(cdf) != '\n' && !feof(cdf)); ungetc('\n', cdf); } void ResetTrafficCounters(void) { // Set to 1 because "totals" are the 0 slot IpCount = 1; IntervalStart=time(NULL); IntervalFinished = FALSE; memset(IpTable, 0, sizeof(struct IPData)*IP_NUM); } void RCDF_Load(FILE *cdf) { time_t timestamp; time_t current_timestamp = 0; struct in_addr ipaddr; struct IPData *ip=NULL; char ipaddrBuffer[16]; unsigned long int Counter = 0; unsigned long int IntervalsRead = 0; for(Counter = 0; !feof(cdf) && !ferror(cdf); Counter++) { if(fscanf(cdf, " %15[0-9.],%lu,", ipaddrBuffer, ×tamp) != 2) goto End_RecoverDataFromCdf; if (!timestamp) // First run through loop current_timestamp = timestamp; if (timestamp != current_timestamp) { // Dump to datastore StoreIPDataInRam(IpTable); IpCount = 0; current_timestamp = timestamp; IntervalsRead++; } inet_aton(ipaddrBuffer, &ipaddr); ip = FindIp(ntohl(ipaddr.s_addr)); ip->timestamp = timestamp; if (fscanf(cdf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,", &ip->Send.total, &ip->Send.icmp, &ip->Send.udp, &ip->Send.tcp, &ip->Send.ftp, &ip->Send.http, &ip->Send.mail, &ip->Send.p2p) != 7 || fscanf(cdf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu", &ip->Receive.total, &ip->Receive.icmp, &ip->Receive.udp, &ip->Receive.tcp, &ip->Receive.ftp, &ip->Receive.http, &ip->Receive.mail, &ip->Receive.p2p) != 7) goto End_RecoverDataFromCdf; } End_RecoverDataFromCdf: StoreIPDataInRam(IpTable); syslog(LOG_INFO, "Finished recovering %lu records", Counter); DropOldData(time(NULL)); // Dump the extra data if(!feof(cdf)) syslog(LOG_ERR, "Failed to parse part of log file. Giving up on the file"); IpCount = 0; // Reset traffic Counters fclose(cdf); } void RecoverDataFromCDF(void) { FILE *cdf; char index[] = "012345"; char logname[MAX_FILENAME]; int offset; int Counter; int First = FALSE; snprintf(logname, MAX_FILENAME, "%s/log.%c.%n0.cdf", config.log_dir, config.tag, &offset); for (Counter = 5; Counter >= 0; Counter--) { logname[offset] = index[Counter]; if (RCDF_Test(logname)) break; } First = TRUE; for (; Counter >= 0; Counter--) { logname[offset] = index[Counter]; if ((cdf = fopen(logname, "rt"))) { syslog(LOG_INFO, "Recovering from %s", logname); if (First) { RCDF_PositionStream(cdf); First = FALSE; } RCDF_Load(cdf); } } } // ****** FindIp ********** // ****** Returns or allocates an Ip's data structure inline struct IPData *FindIp(uint32_t ipaddr) { unsigned int Counter; static time_t last_error = 0; for (Counter=0; Counter < IpCount; Counter++) if (IpTable[Counter].ip == ipaddr) return (&IpTable[Counter]); if (IpCount >= IP_NUM) { time_t current_error = time(NULL); if (current_error > last_error + 30) { last_error = current_error; syslog(LOG_ERR, "Maximum tracked IP's (%d) is too low, some ips will be ignored. Possible network scan?", IP_NUM); } return(NULL); } IpTable[IpCount].ip = ipaddr; return (&IpTable[IpCount++]); } size_t ICGrandTotalDataPoints = 0; char inline *HostIp2CharIp(unsigned long ipaddr, char *buffer) { struct in_addr in_addr; char *s; in_addr.s_addr = htonl(ipaddr); s = inet_ntoa(in_addr); strncpy(buffer, s, 16); buffer[15] = '\0'; return(buffer); /* uint32_t ip = *(uint32_t *)ipaddr; sprintf(buffer, "%d.%d.%d.%d", (ip << 24) >> 24, (ip << 16) >> 24, (ip << 8) >> 24, (ip << 0) >> 24); */ } // Add better error checking int fork2() { pid_t pid; if (!(pid = fork())) { if (!fork()) { #ifdef PROFILE // Got this incantation from a message board. Don't forget to set // GMON_OUT_PREFIX in the shell extern void _start(void), etext(void); syslog(LOG_INFO, "Calling profiler startup..."); monstartup((u_long) &_start, (u_long) &etext); #endif return(0); } _exit(0); } waitpid(pid, NULL, 0); return(1); } bandwidthd-2.0.1+cvs20090917/etc/0000755000175000017500000000000011254363050014121 5ustar gemgembandwidthd-2.0.1+cvs20090917/etc/bandwidthd.conf0000644000175000017500000000332110172352024017074 0ustar gemgem#################################################### # Bandwidthd.conf # # Commented out options are here to provide # documentation and represent defaults # Subnets to collect statistics on. Traffic that # matches none of these subnets will be ignored. # Syntax is either IP Subnet Mask or CIDR subnet 10.0.0.0 255.0.0.0 subnet 192.168.0.0/16 subnet 172.16.0.0/12 # Device to listen on # Bandwidthd listens on the first device it detects # by default. Run "bandwidthd -l" for a list of # devices. #dev "eth0" ################################################### # Options that don't usually get changed # An interval is 2.5 minutes, this is how many # intervals to skip before doing a graphing run #skip_intervals 0 # Graph cutoff is how many k must be transfered by an # ip before we bother to graph it #graph_cutoff 1024 #Put interface in promiscuous mode to score to traffic #that may not be routing through the host machine. #promiscuous true #Log data to cdf file htdocs/log.cdf #output_cdf false #Set the cdf log output directory #log_dir "/usr/local/var/bandwidthd" #Read back the cdf file on startup #recover_cdf false #Libpcap format filter string used to control what bandwidthd see's #Please always include "ip" in the string to avoid strange problems #filter "ip" #Draw Graphs - This default to true to graph the traffic bandwidthd is recording #Usually set this to false if you only want cdf output or #you are using the database output option. Bandwidthd will use very little #ram and cpu if this is set to false. #graph true #Set META REFRESH for static pages in seconds(default 150, use 0 to disable). #meta_refresh 150 #Set the static html output directory #htdocs_dir "/usr/local/var/bandwidthd/htdocs" bandwidthd-2.0.1+cvs20090917/install-sh0000755000175000017500000001273610170330773015365 0ustar gemgem#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 bandwidthd-2.0.1+cvs20090917/README0000644000175000017500000003164310254360216014235 0ustar gemgemProgrammed by David Hinkle, Commissioned by DerbyTech of Illinois. Special thanks goes to Brice Beaman at brice@beamans.org for releasing the software, testing and debugging, Blaze at ts@spective.net for his excellent logo, Andreas Henriksson for polishing, testing, fixing, and all the guys at havok for distributing clue. #### LISCENCE # You may use this software under any version of the GPL that is current as of your download. For exact terms and conditions please see www.gnu.org. #### WHAT IT IS # Bandwidthd is a UNIX daemon/Windows service for graphing the traffic generated by each machine on several configurable subnets. It is much easier to configure than MRTG, and provides significantly more useful information. MRTG only tells you how much bandwidth you are using, Bandwidthd tells you that, and who is using it. Each IP address that has moved any significant volume of traffic has its own graph. The graphs are color coded to help you figure out at a glance if your user is surfing the web, or surfing Kazaa. Bandwidthd is targeted to run on my routing platforms. It is very low overhead. Easily graphing small business traffic on a 133Mhz Elan 486 every 2.5 minutes. My entire ISP (2000-3000 IP addresses across 4 states) is graphed on a Celeron 450 every 10 minutes. #### PORTABILITY # Bandwidthd compiles clean on: ix86 Solaris 9 Debian 2.2 Fedora Core 2 OpenBSD 3.4 FreeBSD 4.8 NetBSD 1.6.1 AMD64 Fedora Core 3 PPC G4 MacOSX 10.2 Thanks goes to SourceForge for providing the test platforms. #### CONFIGURATION INSTRUCTIONS # There are now two ways to install Bandwidthd. The fast easy way, which uses the built in Bandwidthd graphing system to generate static HTML pages and graphs, and the much more complicated way that supports multiple sensors, stores it's data in a back end database, and generates reports and graphs with easily customized php scripts. If you are new to Bandwidthd I would recommend just installing it the following the instructions in the bandwidthd.conf file. If you are interested in customizing your output or you need a more scalable solution, you can always come back and jump through the database hoops later. See "DATABASE SUPPORT" for information on Bandwidthd's advanced configuration. #### GRAPHING INTERVAL # Bandwidthd defaults to graph up to 4000 local IPs every 200 seconds. If you need to track more IPs, change IP_NUM in bandwidthd.h. The weekly graph updates every 10 minutes, monthly every hour, and yearly every 12 hours. A graphing run will automatically be "skipped" if that last one isn't finished before the new one would begin. #### CDF LOGGING # Bandwidthd can be made to log to CDF by setting "output_cdf" to true. This will now log out each interval's traffic, so you can import them into a database and use a tool like access to create your own graphs, or implement 95 percentile billing, for example. Sending Bandwidthd a HUP will cause it to rotate it's logs. It will rotate out 5 times before deleting the oldest log file. These logs are log.1.0.cdf-log.1.5.cdf for daily, log.2.0.cdf-log.2.5.cdf for weekly, etc, etc. If you are upgrading from an older version of Bandwidthd from before all 4 logs rotated you must rename your log files for the new Bandwidthd to find them: mv log.cdf log.1.0.cdf mv log.1.cdf log.1.1.cdf mv log.2.cdf log.1.2.cdf mv log.3.cdf log.1.3.cdf mv log.4.cdf log.1.4.cdf mv log.5.cdf log.1.5.cdf mv log2.cdf log.2.1.cdf mv log3.cdf log.3.1.cdf mv log4.cdf log.4.1.cdf The log format is best documented in the "StoreIPDataInCDF" function in bandwidthd.c. As of this writing, it consists of one line for each IP address for each interval. The line contains only data for the previous interval. Fields: IP Address,Timestamp,Total Sent,Icmp Sent,Udp Sent,Tcp Sent,Ftp Sent,Http Sent, P2P Sent,Total Received,Icmp Received,Udp Received,Tcp Received,Ftp Received,Http Received, P2P Received #### HOW TO KEEP YOUR GRAPHS BETWEEN REBOOTS # Following is the easy way to keep your graphs between reboots. You can also opt to build and use bandwidthd with database support, as described in "DATABASE SUPPORT" below. In the bandwidthd.conf file set: output_cdf true recover_cdf true output_cdf will cause Bandwidthd to log all of it's data to the log.cdf file in it's directory. recover_cdf will cause Bandwidthd to load that file when it starts. You will also want to make a crontab entry like so: 0 0 * * * * /bin/kill -HUP `cat /var/run/bandwidthd.pid` This will send Bandwidthd a HUP every night at midnight. When Bandwidthd receives a HUP it schedules a rotation of it's log files during the next graphing run. Daily log files rotate each HUP. Weekly/Monthly/Yearly log files rotate every so many HUPs. Log files get rotated out 5 times before deletion. Fyi, if you use killall instead of kill, each of the children will receive the HUP command twice, causing them to rotate their log files twice as often as they should. #### GRAPHING Also note that Bandwidthd does not bother to graph an IP that has transmitted less than 1Mbit of data. It does however, include that IP in the table of IPs at the top of the page, so it's traffic can still be viewed. This cutoff can be changed by modifying graph_cutoff in bandwidthd.conf. "graph_cutoff" is in kilobytes. Graphing can be disabled by setting "graph" to false. This will still log, but will use almost no ram or CPU cycles. #### COLOR CODES # RED ICMP BROWN UDP YELLOW IP ENCAPSULATED (IP over IP, IPSEC, most VPN's) BLUE HTTP (Port 80 TCP, actually) PURPLE Peer2Peer (Lots of TCP ports generally used by P2P software) GREEN TCP #### SPECIFYING THE LIBPCAP FILTER # if you'd like more control over what traffic is counted, you can specify a Manuel filter to be passed to libpcap. You can use this to remove certain IPs or only graph certain IPs, or limit the graphs to certain kinds of traffic. You should always specify "ip" in the filter. For example: filter "ip and host 64.215.40.1" #### HOW TO IMPROVE PERFORANCE # Bandwidthd's primary bottleneck in static HTML mode is the drawing of graphs for IP addresses. To improve bandwidthd's performance, therefore, the only thing you can really do is reduce the number of graphs it has to draw in any given run. Adjust graph_cutoff in the bandwidthd.conf file in order to tune out the IP addresses that don't use so much bandwidth. These IP addresses will still have their data displayed in the table at the top of the page, so you can still see what's going on with them. Alternatively, you can choose to graph less often. Bandwidthd automatically skips a graphing run if the last one is still going when the new one is scheduled to start. If you'd like to graph less often than your server is capeable of, you can edit skip_intervals in bandwidthd.conf. A value of 1means to skip every other interval, 3 would mean to skip three intervals between each run. This doesn't disable Bandwidthd's automatic skipping. Also, you can choose to deploy Bandwidthd with database support, which provides significant performance gains. #### DATABASE SUPPORT # Since version 2.0, Bandwidthd now has support for external databases. This system consists of 3 major parts: 1. The Bandwidthd binary which acts as a sensor, recording traffic information and storing it in a database across the network or on the local host. In this mode Bandwidthd uses very little ram and CPU. In addition, multiple sensors can record to the same database. 2. The database system. Currently Bandwidthd only supports Postgresql. 3. The webserver and php application. Bundled with Bandwidthd in the "phphtdocs" directory is a php application that reports on and graphs the contents of the database. This has been designed to be easy to customize. Everything is passed around on the urls, just tinker with it a little and you'll see how to generate custom graphs pretty easy. Using Bandwidthd with a database has many advantages, such as much lower overhead, because graphs are only graphed on demand. And much more flexibility, SQL makes building new reports easy, and php+sql greatly improves the interactivity of the reports. My ISP has now switched over to the database driven version of bandwidthd entirely, we have half a dozen sensors sprinkled around the country, writing millions of data points a day on our customers into the system. INSTRUCTIONS As a prerequisite for these instructions, you must have Postgresql installed and working, as well as a web server that supports php. Setup: 1. Create a database for Bandwidthd. You will need to create users that can access the database remotely if you want remote sensors. 2. Add the following lines to your bandwidthd.conf file: # Standard postgres connect string, just like php, see postgres docs for # details pgsql_connect_string "user = someuser dbname = mydb host = databaseserver.com" # Arbitrary sensor name, I recommend the sensors fully qualified domain # name sensor_id "sensor1.mycompany.com" # Tells Bandwidthd to keep no data and preform no graphing locally graph false # If this is set to true Bandwidthd will try to recover the daily log # into the database. If you set this true on purpose only do it once. # Bandwidthd does not track the fact that it has already transferred # certain records into the database. recover_cdf false 3. Start bandwidthd, and after a few minutes data should start appearing in your database. If not, check syslog for error messages. Web Server Setup: 1. Copy the contents of phphtdocs into your web tree some where. 2. Edit config.conf to set your db connect string You should now be able to access the web application and see you graphs. All graphing is done by graph.php, all parameters are passed to it in it's url. You can create custom urls to pull custom graphs from your own index pages, or use the canned reporting system. In addition, you should schedule bd_pgsql_purge.sh to run every so often. I recomend running it weekly. This script outputs sql statements that aggregate the older data points in your database in order to reduce the amount of data that needs to be slogged through in order to generate yearly, monthly, and weekly graphs. Example: bd_pgsql_purge.sh | psql bandwidthd postgres Will connect to the bandwidthd database on local host as the user postgres and summarize the data. # KNOWN BUGS AND TROUBLESHOOTING # If Bandwidthd shows you nothing but a message saying "Bandwidthd has nothing to graph", that means it currently has recorded no data. The cause is most likely one of these: 1. It's first interval hasn't expired yet (2.5 minutes). 2. It is still chewing through large CDF logs. 3. Bandwidthd's host machine is on a switch and therefor isn't seeing any traffic not destined to or from or going through it. 4. You don't have a subnet line. 5. You have a subnet line but it doesn't match any of the packets Bandwidthd is seeing. 6. You have a filter line that is filtering out all the traffic Bandwidthd could be seeing. Bandwidthd doesn't do a very good job of tracking ftp. This is because only some ftp server software follows the rfc standard of sourceing all ftp transfers from port 20. Surprisingly, Microsofts ftp daemon is compliant in this regard, whereas most open source daemons are not. Bandwidthd forks to perform it's graphing functions. After this fork finishes it remains as a zombie until the next interval, at which time it is reaped by the main process. This zombie is nothing to worry about, it's just an entry in the process table waiting to be deleted. With the new weekly, monthly, yearly graphs you'll have up to 4 zombies now. By default, Bandwidthd now runs in promiscuous mode. This means it can be used to monitor traffic not routing through it's host. Just make sure that the host and the actual router are on the same hub (Not switch) and everything will be ok. Under some circumstances, traffic may get counted twice. If traffic routes to the other router, then routes back out along the same wire, it may get counted twice by Bandwidthd. This is much less of a problem than you might think, due to a little known packet called an "icmp redirect" that causes all packets after the first to go directly to it's target. If you find that traffic looks like it's getting counted twice, make sure you're not firewalling off the icmp redirects. If you find that you actually see none of this traffic, it may be because the icmp redirects cause it to ultimately end up going from one port on a switch to another, never touching your hub. If you want Bandwidthd to only see traffic actually going into and out of the host set "promiscuous" to false in bandwidthd.conf. Bandwidthd supports ethernet, Linux cooked sockets, raw, and token ring, and most ppp packet encapsulation. If you get an "Unknown Datalink Type" error, Bandwidthd has not been programed to handle the physical encapsulation of the ip packets on that interface. If you send me a sample capture and a copy paste of the error message I'll see if I can make bandwidthd work for you.