diff -urN a/Makefile.linux b/Makefile.linux --- a/Makefile.linux 2011-01-29 18:34:34.000000000 +0300 +++ b/Makefile.linux 2011-01-28 17:48:51.000000000 +0300 @@ -140,7 +140,7 @@ OBJS= ${patsubst %.c,%.o,${filter %.c,${SRCS}}} endif -CLEANFILES+= ${PROG} ${_LIB} ${OBJS} +CLEANFILES+= ${PROG} ${_LIB} ${OBJS} ${CLEAN} ifndef DEBUG_FLAGS STRIP?= -s diff -urN a/doc/trafd.8 b/doc/trafd.8 --- a/doc/trafd.8 2004-11-17 12:21:01.000000000 +0300 +++ b/doc/trafd.8 2011-01-28 17:48:51.000000000 +0300 @@ -216,6 +216,8 @@ .Ip "\fB\-i\fR \fIinterface\fR" 5 Listen on \fIinterface\fR. If unspecified, trafd selects first configured up interface (excluding loopback). +.Ip "\fB\-n\fR \fIfile\fR" 5 +Use \fIfile\fR to describe the controlled subnet. .Ip "\fB\-O\fR" 5 Do not run the packet-matching code optimizer while compiling pcap expression. This is useful only if you suspect a bug in the optimizer. @@ -242,6 +244,8 @@ .SH "SIGNALS" .Ip "\fB\s-1SIGINT\s0\fR, \fB\s-1SIGTERM\s0\fR, \fB\s-1SIGQUIT\s0\fR" 5 Dump current statistics for retaining and clearly shutdown. +.Ip "\fB\s-1SIGHUP\s0\fR" 5 +Reload the description file controlled subnet. .Ip "\fB\s-1SIGUSR1\s0\fR" 5 Save current statistics to output file and clear it from memory. .Ip "\fB\s-1SIGUSR2\s0\fR" 5 diff -urN a/doc/trafd.pod b/doc/trafd.pod --- a/doc/trafd.pod 2004-11-17 12:21:01.000000000 +0300 +++ b/doc/trafd.pod 2011-01-28 17:48:51.000000000 +0300 @@ -47,6 +47,10 @@ Listen on I. If unspecified, trafd selects first configured up interface (excluding loopback). +=item B<-n> I + +Use I to describe the controlled subnet. + =item B<-O> Do not run the packet-matching code optimizer while compiling pcap @@ -94,6 +98,10 @@ Dump current statistics for retaining and clearly shutdown. +=item B + +Reload the description file controlled subnet. + =item B Save current statistics to output file and clear it from memory. diff -urN a/include/traffic.h b/include/traffic.h --- a/include/traffic.h 2006-09-27 09:00:32.000000000 +0400 +++ b/include/traffic.h 2011-01-28 17:48:51.000000000 +0300 @@ -4,9 +4,12 @@ * Copyright (c) 1993 The CAD lab of the * Novosibirsk Institute of Broadcasting and Telecommunication * - * BPFT $Id: traffic.h,v 1.3 2006/09/27 05:00:32 frol Exp $ + * BPFT $Id: traffic.h,v 1.4 2011/01/06 00:08:37 Serg79 Exp $ * * $Log: traffic.h,v $ + * Revision 1.4 2011/01/06 00:08:37 Serg79 + * Added support for option '-n' + * * Revision 1.3 2006/09/27 05:00:32 frol * - Fixes for 64bit platforms (still need to fix usage of time_t in trafdb); * - Add trafdb and trafrev into the build; @@ -128,10 +131,17 @@ struct t_entry { struct in_addr in_ip, out_ip; /* src ip addr and dst ip addr */ uint8_t ip_protocol; /* which protocol been used (/etc/protocols) */ - uint8_t who_srv; /* who was server flag */ - uint16_t p_port; /* which port been used (/etc/services) */ - uint32_t n_psize; /* how many bytes in ip datagrams passed */ - uint32_t n_bytes; /* how many data bytes passed */ + /* + * Who was server flag: + * 0 - no server (icmp, ...) + * 1 - server is src + * 2 - server is dst + * 3 - not determined (the SRC and DST ports are equal) + */ + uint8_t who_srv; + uint16_t p_port; /* which port been used (/etc/services) (host byte order) */ + uint32_t n_psize; /* how many bytes in ip datagrams passed (host byte order) */ + uint32_t n_bytes; /* how many data bytes passed (host byte order) */ }; typedef struct t_entry *p_entry; diff -urN a/trafctl/trafctl.conf-sample.in b/trafctl/trafctl.conf-sample.in --- a/trafctl/trafctl.conf-sample.in 2011-01-29 18:34:34.000000000 +0300 +++ b/trafctl/trafctl.conf-sample.in 2011-01-28 17:48:51.000000000 +0300 @@ -16,7 +16,7 @@ #trafslice_program="%%BINDIR%%/trafslice" ### don't put interfaces into promisc mode, restore on start, ### change credentials to those of user "%%TRAFD_USER%%" -#trafd_flags="-p -r -u %%TRAFD_USER%% -g %%TRAFD_GROUP%% -C" +#trafd_flags="-p -r -u %%TRAFD_USER%% -g %%TRAFD_GROUP%%" #trafd_pid_prefix="%%TRAFDDIR%%/run/trafd." #trafd_sock_prefix="%%TRAFDDIR%%/tmp/trafd." ### pcap expression diff -urN a/trafd/Makefile.linux b/trafd/Makefile.linux --- a/trafd/Makefile.linux 2004-11-17 12:06:31.000000000 +0300 +++ b/trafd/Makefile.linux 2011-01-28 17:48:51.000000000 +0300 @@ -1,7 +1,13 @@ PROG= trafd -SRCS= main.c traffic.c hash_tests.c +SRCS= main.c traffic.c hash_tests.c identify_client.c parser_conf.tab.c lex.yy.c +FILES= subnet.conf BINDIR= ${PREFIX}/bin +YYAC := bison +LEX := flex + +CLEAN := lex.yy.h lex.yy.c parser_conf.tab.h parser_conf.tab.c + ifdef WITH_HASH_TESTS CFLAGS+= -DWITH_HASH_TESTS endif @@ -9,6 +15,20 @@ CFLAGS+= -DWITH_OLD_HASH endif - TOPDIR= .. include ${TOPDIR}/Makefile.linux + +install-subnet.conf: subnet.conf + ${INSTALL_DATA} $< ${DESTDIR}${ETCDIR} + +lex.yy.c: parser_scan.l + ${LEX} --header-file=lex.yy.h $< + +parser_conf.tab.c: parser_conf.y + ${YYAC} -d $< + +parser_conf.tab.o: parser_conf.tab.c lex.yy.h +lex.yy.o: lex.yy.c parser_conf.tab.h + +lex.yy.h: lex.yy.c +parser_conf.tab.h: parser_conf.tab.c diff -urN a/trafd/identify_client.c b/trafd/identify_client.c --- a/trafd/identify_client.c 1970-01-01 03:00:00.000000000 +0300 +++ b/trafd/identify_client.c 2011-01-28 17:48:51.000000000 +0300 @@ -0,0 +1,483 @@ +/* + * $Id: identify_client.c,v 1.0 2011/01/06 00:01:09 Serg79 Exp $ + * + * Revison 1.0 2011/01/06 00:01:09 Serg79 + * Initial revision + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * Redistribution in binary form may occur without any restrictions. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. + */ + +#include +#include +#include +#include +#include +#include + +#include "identify_client.h" +#include "parser_conf.h" +#include "traffic.h" +#include "trafd.h" +#include "util.h" + +struct local_net { + struct in_addr net; + struct in_addr mask; +}; + +struct local_server { + struct in_addr ip; + uint16_t port; +}; + +typedef int (*check_ip_server)(const struct local_server *s, + const struct local_server *s_list, int count); + +enum { + SUBNET_NOT_DEFINED, + SUBNET_SOURCE, + SUBNET_DESTINATION, + SUBNET_ALL +}; + +#define SIZE_BUFF 16 + +static int net_size; +static int net_count; +static struct local_net *net; + +static int tcp_srv_size; +static int tcp_srv_count; +static struct local_server *tcp_srv; +static check_ip_server check_tcp_server; + +static int udp_srv_size; +static int udp_srv_count; +static struct local_server *udp_srv; +static check_ip_server check_udp_server; + +static void insert_local_net(const struct local_net *n) +{ + if (net_count == net_size) { + net_size += SIZE_BUFF; + net = realloc(net, sizeof(struct local_net) * net_size); + if (!net) { + syslog(LOG_ERR, "(%s) failed allocate memory", device_name); + errorx("%s: failed allocate memory", device_name); + } + } + + net[net_count++] = *n; +} + +static void insert_tcp_local_server(const struct local_server *s) +{ + if (tcp_srv_count == tcp_srv_size) { + tcp_srv_size += SIZE_BUFF; + tcp_srv = realloc(tcp_srv, sizeof(struct local_server) * tcp_srv_size); + if (!tcp_srv) { + syslog(LOG_ERR, "(%s) failed allocate memory", device_name); + errorx("%s: failed allocate memory", device_name); + } + } + + tcp_srv[tcp_srv_count++] = *s; +} + +static void insert_udp_local_server(const struct local_server *s) +{ + if (udp_srv_count == udp_srv_size) { + udp_srv_size += SIZE_BUFF; + udp_srv = realloc(udp_srv, sizeof(struct local_server) * udp_srv_size); + if (!udp_srv) { + syslog(LOG_ERR, "(%s) failed allocate memory", device_name); + errorx("%s: failed allocate memory", device_name); + } + } + + udp_srv[udp_srv_count++] = *s; +} + +static int check_number(const char *p, int len) +{ + int i; + + for (i = 0; p[i] && i <= len; i++) { + if (!isdigit(p[i])) + return 0; + } + + return (!i || i > len) ? 0 : 1; +} + +/* Network address (*net) has the following format: 192.168.2.0/24 */ +int add_local_net(const char *net) +{ + struct local_net n; + struct in_addr ip; + uint32_t mask; + char buff[32]; + const char *p, *d; + size_t len; + int m, i; + + p = net; + d = strchr(p, '/'); + if (!d) + goto err; + len = d - p; + if (len >= sizeof(buff)) + goto err; + strncpy(buff, p, len); + buff[len] = '\0'; + if (!inet_aton(buff, &ip)) + goto err; + + p = d + 1; + if (!check_number(p, 2)) + goto err; + m = atoi(p); + if (m > 32) + goto err; + + mask = 0; + for (i = 0; i < m; i++) + mask |= 1 << (31 - i); + + n.net = ip; + n.mask.s_addr = htonl(mask); + insert_local_net(&n); + + return 1; + +err: + return 0; +} + +/* Server IP address (*srv) has the following format: tcp:1.2.3.4:22 */ +int add_local_server(const char *srv) +{ + struct local_server s; + struct in_addr ip; + int tf, uf, port; + char buff[32]; + const char *p, *d; + size_t len; + + p = srv; + tf = uf = 0; + d = strchr(p, ':'); + if (!d) + goto err; + len = d - p; + if (len >= sizeof(buff)) + goto err; + strncpy(buff, p, len); + buff[len] = '\0'; + if (!strcmp(buff, "tcp")) + tf = 1; + else if (!strcmp(buff, "udp")) + uf = 1; + else + goto err; + + p = d + 1; + d = strchr(p, ':'); + if (!d) + goto err; + len = d - p; + if (len >= sizeof(buff)) + goto err; + strncpy(buff, p, len); + buff[len] = '\0'; + if (!inet_aton(buff, &ip)) + goto err; + + p = d + 1; + if (!check_number(p, 5)) + goto err; + port = atoi(p); + if (port <= 0 || port > IPPORT_HILASTAUTO) + goto err; + + s.ip = ip; + s.port = htons(port); + if (tf) + insert_tcp_local_server(&s); + else if (uf) + insert_udp_local_server(&s); + else + goto err; + + return 1; + +err: + return 0; +} + +static int check_ip_server_one(const struct local_server *s, + const struct local_server *s_list, int count) +{ + if ((s->ip.s_addr == s_list->ip.s_addr) && (s->port == s_list->port)) + return 1; + return 0; +} + +static int check_ip_server_small(const struct local_server *s, + const struct local_server *s_list, int count) +{ + int i; + + for (i = 0; i < count; i++) { + const struct local_server *t = s_list + i; + if ((s->ip.s_addr == t->ip.s_addr) && (s->port == t->port)) + return 1; + } + + return 0; +} + +static inline int cmpsrv(const struct local_server *a, const struct local_server *b) +{ + if (a->ip.s_addr < b->ip.s_addr) + return -1; + else if (a->ip.s_addr > b->ip.s_addr) + return 1; + else { + if (a->port < b->port) + return -1; + else if (a->port > b->port) + return 1; + } + + return 0; +} + +static int check_ip_server_large(const struct local_server *s, + const struct local_server *s_list, int count) +{ + int low, high; + + low = 0; + high = count - 1; + while (low <= high) { + int mid = (low + high) / 2; + int cmp = cmpsrv(s, s_list + mid); + if (cmp < 0) + high = mid - 1; + else if (cmp > 0) + low = mid + 1; + else + return 1; + } + + return 0; +} + +static int check_ip_subnet(struct in_addr ip) +{ + int i; + + for (i = 0; i < net_count; i++) { + struct local_net *n = net + i; + if ((ip.s_addr & n->mask.s_addr) == n->net.s_addr) + return 1; + } + + return 0; +} + +static int find_ip_subnet(const struct ip *ip) +{ + int sf, df; + + sf = check_ip_subnet(ip->ip_src); + df = check_ip_subnet(ip->ip_dst); + + if (sf && df) + return SUBNET_ALL; + if (sf) + return SUBNET_SOURCE; + if (df) + return SUBNET_DESTINATION; + + return SUBNET_NOT_DEFINED; +} + +static int check_broadcast_address(const struct ip *ip) +{ + int i; + + if ((ip->ip_src.s_addr == INADDR_ANY) || + (ip->ip_dst.s_addr == INADDR_BROADCAST)) + return 1; + + for (i = 0; i < net_count; i++) { + struct local_net *n = net + i; + if ((n->net.s_addr | ~n->mask.s_addr) == ip->ip_dst.s_addr) + return 1; + } + + return 0; +} + +int identify_ip_client(const struct ip *ip) +{ + switch (find_ip_subnet(ip)) { + case SUBNET_SOURCE: + return CLIENT_SOURCE; + case SUBNET_DESTINATION: + return CLIENT_DESTINATION; + } + + if (check_broadcast_address(ip)) + return CLIENT_DROP_PACKET; + + return CLIENT_INDEFINITE; +} + +int identify_tcp_client(const struct ip *ip, const struct tcphdr *tcp) +{ + uint16_t sport, dport; + int who; + + who = find_ip_subnet(ip); + switch (who) { + case SUBNET_SOURCE: + return CLIENT_SOURCE; + case SUBNET_DESTINATION: + return CLIENT_DESTINATION; + } + + if (who == SUBNET_ALL && check_tcp_server) { + struct local_server srv; + + srv.ip = ip->ip_dst; + srv.port = tcp->th_dport; + if ((*check_tcp_server)(&srv, tcp_srv, tcp_srv_count)) + return CLIENT_SOURCE; + + srv.ip = ip->ip_src; + srv.port = tcp->th_sport; + if ((*check_tcp_server)(&srv, tcp_srv, tcp_srv_count)) + return CLIENT_DESTINATION; + } + + sport = ntohs(tcp->th_sport); + dport = ntohs(tcp->th_dport); + if (dport < sport) + return CLIENT_SOURCE; + if (dport > sport) + return CLIENT_DESTINATION; + + if (check_broadcast_address(ip)) + return CLIENT_DROP_PACKET; + + return CLIENT_INDEFINITE; +} + +int identify_udp_client(const struct ip *ip, const struct udphdr *udp) +{ + uint16_t sport, dport; + int who; + + who = find_ip_subnet(ip); + switch (who) { + case SUBNET_SOURCE: + return CLIENT_SOURCE; + case SUBNET_DESTINATION: + return CLIENT_DESTINATION; + } + + if (who == SUBNET_ALL && check_udp_server) { + struct local_server srv; + + srv.ip = ip->ip_dst; + srv.port = udp->uh_dport; + if ((*check_udp_server)(&srv, udp_srv, udp_srv_count)) + return CLIENT_SOURCE; + + srv.ip = ip->ip_src; + srv.port = udp->uh_sport; + if ((*check_udp_server)(&srv, udp_srv, udp_srv_count)) + return CLIENT_DESTINATION; + } + + sport = ntohs(udp->uh_sport); + dport = ntohs(udp->uh_dport); + if (dport < sport) + return CLIENT_SOURCE; + if (dport > sport) + return CLIENT_DESTINATION; + + if (check_broadcast_address(ip)) + return CLIENT_DROP_PACKET; + + return CLIENT_INDEFINITE; +} + +static inline int ltsrv(const struct local_server *a, const struct local_server *b) +{ + if (a->ip.s_addr < b->ip.s_addr) + return 1; + else if (a->ip.s_addr > b->ip.s_addr) + return 0; + else if (a->port < b->port) + return 1; + + return 0; +} + +static void sort_server(struct local_server *s, int count) +{ + struct local_server t; + int a, b; + + for (a = 1; a < count; a++) { + t = s[a]; + for (b = a - 1; (b >= 0) && ltsrv(&t, s + b); b--) + s[b + 1] = s[b]; + s[b + 1] = t; + } +} + +static void clear_counters(void) +{ + net_count = tcp_srv_count = udp_srv_count = 0; +} + +#define CHECK_IP_SERVER_LARGE 6 + +int init_local_net(const char *conf) +{ + clear_counters(); + + if (parser_config(conf)) + return 1; + + if (tcp_srv_count > CHECK_IP_SERVER_LARGE) { + sort_server(tcp_srv, tcp_srv_count); + check_tcp_server = check_ip_server_large; + } else if (tcp_srv_count > 1) + check_tcp_server = check_ip_server_small; + else if (tcp_srv_count == 1) + check_tcp_server = check_ip_server_one; + else + check_tcp_server = NULL; + + if (udp_srv_count > CHECK_IP_SERVER_LARGE) { + sort_server(udp_srv, udp_srv_count); + check_udp_server = check_ip_server_large; + } else if (udp_srv_count > 1) + check_udp_server = check_ip_server_small; + else if (udp_srv_count == 1) + check_udp_server = check_ip_server_one; + else + check_udp_server = NULL; + + return 0; +} diff -urN a/trafd/identify_client.h b/trafd/identify_client.h --- a/trafd/identify_client.h 1970-01-01 03:00:00.000000000 +0300 +++ b/trafd/identify_client.h 2011-01-28 17:48:51.000000000 +0300 @@ -0,0 +1,34 @@ +/* + * $Id: identify_client.h,v 1.0 2011/01/06 00:01:09 Serg79 Exp $ + * + * Revison 1.0 2011/01/06 00:01:09 Serg79 + * Initial revision + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * Redistribution in binary form may occur without any restrictions. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. + */ + +#ifndef _IDENTIFY_CLIENT_H +#define _IDENTIFY_CLIENT_H + +#include +#include +#include + +int add_local_net(const char *net); +int add_local_server(const char *srv); +int init_local_net(const char *conf); + +#define CLIENT_INDEFINITE 0 +#define CLIENT_SOURCE 1 +#define CLIENT_DESTINATION 2 +#define CLIENT_DROP_PACKET 3 + +int identify_ip_client(const struct ip *ip); +int identify_tcp_client(const struct ip *ip, const struct tcphdr *tcp); +int identify_udp_client(const struct ip *ip, const struct udphdr *udp); + +#endif /* _IDENTIFY_CLIENT_H */ diff -urN a/trafd/main.c b/trafd/main.c --- a/trafd/main.c 2011-01-29 18:34:34.000000000 +0300 +++ b/trafd/main.c 2011-01-28 17:48:51.000000000 +0300 @@ -4,7 +4,10 @@ * Copyright (c) 1993 The CAD lab of the * Novosibirsk Institute of Broadcasting and Telecommunication * - * BPFT $Id: main.c,v 1.3 2006/09/27 03:13:37 count Exp $ + * BPFT $Id: main.c,v 1.4 2011/01/06 00:12:48 Serg79 Exp $ + * + * Revision 1.4 2011/01/06 00:12:48 Serg79 + * Added support for option '-n'. * * $Log: main.c,v $ * Revision 1.3 2006/09/27 03:13:37 count @@ -63,6 +66,7 @@ #include "traffic.h" #include "trafd.h" +#include "identify_client.h" struct trafd_stats { struct timeval tv; @@ -87,6 +91,7 @@ int sigflag_save; /* SIGUSR1 - append collected data to savefile */ int sigflag_backup; /* SIGUSR2 - drop collected data to backup file for recovery */ int sigflag_shutdown; /* dump data for recovery and exit */ +int sigflag_read_config; /* SIGHUP - read config file */ #if 0 int sigflag_info; /* log statistics */ #endif @@ -104,6 +109,7 @@ u_int save_min_record_size = MIN_RECORD_SIZE, pipe_min_record_size = MIN_RECORD_SIZE; +static void usage(); static void cleanup_exit(); static int main_loop(pcap_t*, int, int); /* signal handlers */ @@ -111,6 +117,7 @@ static void sighandler_save(); /* save */ static void sighandler_backup(); /* backup */ static void sighandler_child(); /* reap all children */ +static void sighandler_read_config(); /* read config file */ #if 0 static void sighandler_info(); /* request info */ #endif @@ -124,6 +131,7 @@ int snaplen = DEFAULT_SNAPLEN; static pcap_t *pd = NULL; +static char *local_net_conf = NULL; #ifdef WITH_HASH_TESTS void hash_tests(); @@ -134,8 +142,6 @@ int argc; char **argv; { - void usage(); - int op, cnt = -1, i; struct bpf_program fcode; char *infile = 0, *cmdbuf, *DevFileName = 0; @@ -158,7 +164,7 @@ set_program_name(argv[0]); opterr = 0; - while ((op = getopt(argc, argv, "c:Cdf:F:i:Opru:g:Dm:M:")) != EOF) + while ((op = getopt(argc, argv, "c:Cdf:F:i:Opru:g:Dm:M:n:")) != EOF) switch (op) { case 'c': cnt = atoi(optarg); @@ -204,17 +210,20 @@ case 'M': pipe_min_record_size = (u_int)strtoul(optarg, NULL, 0); break; + case 'n': + local_net_conf = optarg; + break; default: usage(); } + openlog(program_name, LOG_PID|LOG_CONS, LOG_LOCAL0); + if (infile) cmdbuf = read_infile(infile); else cmdbuf = copy_argv(&argv[optind]); - openlog(program_name, LOG_PID|LOG_CONS, LOG_LOCAL0); - if (device_name == 0) if ((device_name = getenv("IFF_LISTEN")) == NULL) if ((device_name = pcap_lookupdev(ebuf)) == 0) @@ -225,6 +234,17 @@ if (pd == NULL) errorx("%s: pcap_open_live: %s", device_name, ebuf); + if (local_net_conf) { + if (init_local_net(local_net_conf)) { + syslog(LOG_ERR, "(%s) error processing configuration file: %s", + device_name, local_net_conf); + errorx("%s: error processing configuration file: %s", + device_name, local_net_conf); + } else + syslog(LOG_INFO, "(%s) configuration file is loaded: %s", + device_name, local_net_conf); + } + if (droproot) { struct passwd *pwd; struct group *grp; @@ -354,7 +374,7 @@ /* Initialize trafd stats routine */ init_trafd_stats(); /* Catch signals */ - sigflag_shutdown = sigflag_save = sigflag_backup = 0; + sigflag_shutdown = sigflag_save = sigflag_backup = sigflag_read_config = 0; #if 0 sigflag_info = 0; #endif @@ -364,6 +384,7 @@ (void)signal(SIGCHLD, sighandler_child); (void)signal(SIGUSR1, sighandler_save); (void)signal(SIGUSR2, sighandler_backup); + (void)signal(SIGHUP, sighandler_read_config); #if 0 (void)signal(SIGINFO, sighandler_info); #endif @@ -454,6 +475,18 @@ exit(0); } } + if (sigflag_read_config) { /* reread config file */ + sigflag_read_config = 0; + if (local_net_conf) { + if (init_local_net(local_net_conf)) + syslog(LOG_ERR, "(%s) error processing configuration file: %s", + device_name, local_net_conf); + else + syslog(LOG_INFO, "(%s) configuration file is loaded: %s", + device_name, local_net_conf); + } else + syslog(LOG_WARNING, "(%s) not specified configuration file", device_name); + } return 0; } @@ -558,6 +591,11 @@ (void)syslog(LOG_WARNING, "(%s) waitpid: %m", device_name); } +static void sighandler_read_config(void) +{ + sigflag_read_config++; +} + #if 0 static void sighandler_info() diff -urN a/trafd/parser_conf.h b/trafd/parser_conf.h --- a/trafd/parser_conf.h 1970-01-01 03:00:00.000000000 +0300 +++ b/trafd/parser_conf.h 2011-01-28 17:48:51.000000000 +0300 @@ -0,0 +1,22 @@ +/* + * $Id: parser_conf.h,v 1.0 2011/01/06 00:14:42 Serg79 Exp $ + * + * Revison 1.0 2011/01/06 00:14:42 Serg79 + * Initial revision + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * Redistribution in binary form may occur without any restrictions. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. + */ + +#ifndef _PARSER_CONF_H +#define _PARSER_CONF_H + +extern int yy_new_line_config; + +int parser_config(const char *conf); +void yyerror(const char *fmt, ...); + +#endif /* _PARSER_CONF_H */ diff -urN a/trafd/parser_conf.y b/trafd/parser_conf.y --- a/trafd/parser_conf.y 1970-01-01 03:00:00.000000000 +0300 +++ b/trafd/parser_conf.y 2011-01-28 17:48:51.000000000 +0300 @@ -0,0 +1,170 @@ +/* + * $Id: parser_conf.y,v 1.0 2011/01/06 00:14:42 Serg79 Exp $ + * + * Revison 1.0 2011/01/06 00:14:42 Serg79 + * Initial revision + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * Redistribution in binary form may occur without any restrictions. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. + */ + +%{ +#include +#include +#include +#include + +#include +#include + +#include "util.h" +#include "identify_client.h" +#include "parser_conf.h" +#include "lex.yy.h" +#include "parser_conf.tab.h" +#include "trafd.h" + +int yy_new_line_config; +static const char *conf_name; + +struct buff_save { + char buff[32]; +}; + +#define SIZE_BUFF 16 + +static int netaddr_size; +static int netaddr_count; +static struct buff_save *netaddr; + +static int server_size; +static int server_count; +static struct buff_save *server; + +static void save_netaddr(const char *n) +{ + char *buff; + + if (netaddr_size == netaddr_count) { + netaddr_size += SIZE_BUFF; + netaddr = realloc(netaddr, sizeof(struct buff_save) * netaddr_size); + if (!netaddr) { + syslog(LOG_ERR, "(%s) failed allocate memory", device_name); + errorx("%s: failed allocate memory", device_name); + } + } + + buff = netaddr[netaddr_count].buff; + strcpy(buff, n); + netaddr_count++; +} + +static void save_server(const char *p, const char *s) +{ + char *buff; + + if (server_size == server_count) { + server_size += SIZE_BUFF; + server = realloc(server, sizeof(struct buff_save) * server_size); + if (!server) { + syslog(LOG_ERR, "(%s) failed allocate memory", device_name); + errorx("%s: failed allocate memory", device_name); + } + } + + buff = server[server_count].buff; + strcpy(buff, p); + strcat(buff, ":"); + strcat(buff, s); + server_count++; +} +%} + +%union { +char buff[32]; +} + +%token SUBNET +%token SERVER +%token TCP +%token UDP +%token NETADDR +%token SRVADDR + +%% +input: + | input SUBNET '{' subnet '}' + | input SERVER '{' server '}' +; + +subnet: + | subnet NETADDR ';' {save_netaddr($2);} +; + +server: + | server TCP '{' tcp '}' + | server UDP '{' udp '}' +; + +tcp: + | tcp SRVADDR ';' {save_server("tcp", $2);} + +udp: + | udp SRVADDR ';' {save_server("udp", $2);} +%% + +void yyerror(const char *msg, ...) +{ + va_list arg; + + va_start(arg, msg); + vsyslog(LOG_ERR, msg, arg); + va_end(arg); + + syslog(LOG_ERR, "(%s) error parsing config: %s:%d", + device_name, conf_name, yy_new_line_config); +} + +int parser_config(const char *conf) +{ + int ret, i; + + yy_new_line_config = 1; + netaddr_count = server_count = 0; + + conf_name = conf; + yyin = fopen(conf, "r"); + if (!yyin) { + syslog(LOG_ERR, "(%s) failed open file '%s': %s", + device_name, conf, strerror(errno)); + return 1; + } + ret = yyparse(); + fclose(yyin); + + if (ret) + return 1; + + for (i = 0; i < netaddr_count; i++) { + char *p = netaddr[i].buff; + if (!add_local_net(p)) { + syslog(LOG_ERR, "(%s) not correct address of the network: %s", + device_name, p); + return 1; + } + } + + for (i = 0; i < server_count; i++) { + char *p = server[i].buff; + if (!add_local_server(p)) { + syslog(LOG_ERR, "(%s) not correct address of the server: %s", + device_name, p); + return 1; + } + } + + return 0; +} diff -urN a/trafd/parser_scan.l b/trafd/parser_scan.l --- a/trafd/parser_scan.l 1970-01-01 03:00:00.000000000 +0300 +++ b/trafd/parser_scan.l 2011-01-28 17:48:51.000000000 +0300 @@ -0,0 +1,53 @@ +/* + * $Id: parser_scan.l,v 1.0 2011/01/06 00:14:42 Serg79 Exp $ + * + * Revison 1.0 2011/01/06 00:14:42 Serg79 + * Initial revision + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * Redistribution in binary form may occur without any restrictions. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. + */ + +%option noyywrap nounput + +%{ +#include + +#include "parser_conf.h" +#include "parser_conf.tab.h" +%} + +D [0-9] +IP ({D}{1,3}"."{D}{1,3}"."{D}{1,3}"."{D}{1,3}) +PORT ({D}{1,5}) +MASK ({D}{1,2}) + +%% +"subnet" {return SUBNET;} +"server" {return SERVER;} +"tcp" {return TCP;} +"udp" {return UDP;} +{IP}"/"{MASK} {strcpy(yylval.buff, yytext); return NETADDR;} +{IP}":"{PORT} {strcpy(yylval.buff, yytext); return SRVADDR;} +"{" {return '{';} +"}" {return '}';} +";" {return ';';} +"#".*\n {yy_new_line_config++;} +\n {yy_new_line_config++;} +[ \t]+ { /* ignore spaces and tabs */ } +. { + if (yytext[0] < ' ') { + yyerror("illegal character: ^%c", yytext[0] + '@'); + } else { + if (yytext[0] > '~') + yyerror("illegal character: \\%03o", (int)yytext[0]); + else + yyerror("illegal character: %s", yytext); + } + + return yytext[0]; +} +%% diff -urN a/trafd/subnet.conf b/trafd/subnet.conf --- a/trafd/subnet.conf 1970-01-01 03:00:00.000000000 +0300 +++ b/trafd/subnet.conf 2011-01-28 17:48:51.000000000 +0300 @@ -0,0 +1,17 @@ +# The configuration file describes a controlled subnet. + +# Subnets. +subnet { +# 192.168.1.0/24; +} + +# Server on a subnet with non-standard ports (> 1024). +server { + tcp { +# 192.168.1.1:3128; # Squid proxy + } + udp { +# 192.168.1.1:137; # netbios-ns +# 192.168.1.1:138; # netbios-dgm + } +} diff -urN a/trafd/traffic.c b/trafd/traffic.c --- a/trafd/traffic.c 2006-09-27 09:00:32.000000000 +0400 +++ b/trafd/traffic.c 2011-01-28 17:48:51.000000000 +0300 @@ -4,9 +4,12 @@ * Copyright (c) 1993 The CAD lab of the * Novosibirsk Institute of Broadcasting and Telecommunication * - * BPFT $Id: traffic.c,v 1.2 2006/09/27 05:00:32 frol Exp $ + * BPFT $Id: traffic.c,v 1.3 2011/01/06 00:32:37 Serg79 Exp $ * * $Log: traffic.c,v $ + * Revision 1.3 2011/01/06 00:32:37 Serg79 + * Added support for option '-n' + * * Revision 1.2 2006/09/27 05:00:32 frol * - Fixes for 64bit platforms (still need to fix usage of time_t in trafdb); * - Add trafdb and trafrev into the build; @@ -58,13 +61,13 @@ /*#include */ #include /*#include */ -#include #include #include #include "interface.h" #include "traffic.h" #include "util.h" +#include "identify_client.h" #include "trafd.h" @@ -78,18 +81,6 @@ static int iplen; static int dlen; static struct tv32 begin_time; -static u_char s_port_big[IPPORT_RESERVED]; - -#define CHECK_SRV(p, proto) (s_port_big[(p) & (IPPORT_RESERVED-1)] & (proto)) -#if IPPORT_HILASTAUTO < USHRT_MAX -#define IS_USER_PORT(p) (((p) >= IPPORT_RESERVED && (p) < IPPORT_USERRESERVED) || \ - ((p) >= IPPORT_HIFIRSTAUTO && \ - (p) <= IPPORT_HILASTAUTO)) -#else -/* (p) <= IPPORT_HILASTAUTO is always true because (p) is an unsigned short */ -#define IS_USER_PORT(p) (((p) >= IPPORT_RESERVED && (p) < IPPORT_USERRESERVED) || \ - ((p) >= IPPORT_HIFIRSTAUTO)) -#endif struct t_entry *entries; /* @@ -104,27 +95,13 @@ traf_init(restore) int restore; { - register int i; - struct servent *sv; struct timeval tv; entries = (struct t_entry *) calloc(MAX_T_ENTRIES, sizeof(struct t_entry)); if (entries == NULL) return -1; - (void) memset(s_port_big, 0, sizeof(s_port_big)); - setservent(1); - while ((sv = getservent())) { - NTOHS(sv->s_port); - if (sv->s_port >= IPPORT_RESERVED) { - i = sv->s_port & (IPPORT_RESERVED-1); - if (strcmp(sv->s_proto, "tcp") == 0) - s_port_big[i] |= IPPROTO_TCP; - else if (strcmp(sv->s_proto, "udp") == 0) - s_port_big[i] |= IPPROTO_UDP; - } - } - endservent(); n_entry = 0; + if (restore) traf_restore(); else { @@ -244,42 +221,29 @@ if ((u_char *)(tp + 1) > snapend || dlen < sizeof(struct tcphdr)) return; - NTOHS(tp->th_sport); - NTOHS(tp->th_dport); - t.in_ip.s_addr = ip->ip_src.s_addr; t.out_ip.s_addr = ip->ip_dst.s_addr; t.ip_protocol = IPPROTO_TCP; t.n_psize = (uint32_t)iplen; - t.n_bytes = (uint32_t)(dlen - tp->th_off * 4) & 2047L; + t.n_bytes = (uint32_t)(dlen - tp->th_off * 4) & 0x7ff; - t.p_port = min(tp->th_sport, tp->th_dport); - if (t.p_port < IPPORT_RESERVED || - (IS_USER_PORT(tp->th_sport) && IS_USER_PORT(tp->th_dport))) { - t.who_srv = tp->th_sport < tp->th_dport ? 1 : 2; - } - else if (tp->th_sport == tp->th_dport) { - t.who_srv = 3; - } - /* tp->th_sport > IPPORT_RESERVED && tp->th_dport > IPPORT_RESERVED */ - else { - if (CHECK_SRV(tp->th_sport, IPPROTO_TCP)) { - t.who_srv = 1; - } - else if (CHECK_SRV(tp->th_dport, IPPROTO_TCP)) { + switch (identify_tcp_client(ip, tp)) { + case CLIENT_SOURCE: + t.p_port = ntohs(tp->th_dport); t.who_srv = 2; - } - else { - t.who_srv = !IS_USER_PORT(tp->th_sport) ? 1 : 2 ; - } - t.p_port = (t.who_srv == 2 ? tp->th_dport : tp->th_sport); + break; + case CLIENT_DESTINATION: + t.p_port = ntohs(tp->th_sport); + t.who_srv = 1; + break; + case CLIENT_DROP_PACKET: + return; + default: + t.p_port = ntohs(tp->th_dport); + t.who_srv = 3; } traf_add(&t); - - HTONS(tp->th_sport); - HTONS(tp->th_dport); - return; } /* @@ -290,50 +254,34 @@ struct udphdr *up; struct ip *ip; { - u_char *cp = (u_char *)(up + 1); struct t_entry t; - if (cp > snapend || dlen < sizeof(struct udphdr)) + if ((u_char *)(up + 1) > snapend || dlen < sizeof(struct udphdr)) return; - NTOHS(up->uh_sport); - NTOHS(up->uh_dport); - NTOHS(up->uh_ulen); - t.in_ip.s_addr = ip->ip_src.s_addr; t.out_ip.s_addr = ip->ip_dst.s_addr; t.ip_protocol = IPPROTO_UDP; t.n_psize = (uint32_t)iplen; - t.n_bytes = (uint32_t)(up->uh_ulen - sizeof(*up)) & 2047L; + t.n_bytes = (uint32_t)(ntohs(up->uh_ulen) - sizeof(*up)) & 0x7ff; - t.p_port = min(up->uh_sport, up->uh_dport); - if (t.p_port < IPPORT_RESERVED || - (IS_USER_PORT(up->uh_sport) && IS_USER_PORT(up->uh_dport))) { - t.who_srv = up->uh_sport < up->uh_dport ? 1 : 2; - } - else if (up->uh_sport == up->uh_dport) { - t.who_srv = 3; - } - /* tp->th_sport > IPPORT_RESERVED && tp->th_dport > IPPORT_RESERVED */ - else { - if (CHECK_SRV(up->uh_sport, IPPROTO_TCP)) { - t.who_srv = 1; - } - else if (CHECK_SRV(up->uh_dport, IPPROTO_TCP)) { + switch (identify_udp_client(ip, up)) { + case CLIENT_SOURCE: + t.p_port = ntohs(up->uh_dport); t.who_srv = 2; - } - else { - t.who_srv = !IS_USER_PORT(up->uh_sport) ? 1 : 2 ; - } - t.p_port = (t.who_srv == 2 ? up->uh_dport : up->uh_sport); + break; + case CLIENT_DESTINATION: + t.p_port = ntohs(up->uh_sport); + t.who_srv = 1; + break; + case CLIENT_DROP_PACKET: + return; + default: + t.p_port = ntohs(up->uh_dport); + t.who_srv = 3; } traf_add(&t); - - HTONS(up->uh_sport); - HTONS(up->uh_dport); - HTONS(up->uh_ulen); - return; } /* @@ -350,9 +298,22 @@ t.ip_protocol = ip->ip_p; t.n_psize = (uint32_t)iplen; t.n_bytes = (uint32_t)dlen; - t.p_port = t.who_srv = 0; + t.p_port = 0; + + switch (identify_ip_client(ip)) { + case CLIENT_SOURCE: + t.who_srv = 2; + break; + case CLIENT_DESTINATION: + t.who_srv = 1; + break; + case CLIENT_DROP_PACKET: + return; + default: + t.who_srv = 0; + } + traf_add(&t); - return; } /* diff -urN a/traflog/traflog.c b/traflog/traflog.c --- a/traflog/traflog.c 2008-02-21 10:20:30.000000000 +0300 +++ b/traflog/traflog.c 2011-01-29 18:09:55.000000000 +0300 @@ -4,9 +4,12 @@ * Copyright (c) 1993 The CAD lab of the * Novosibirsk Institute of Broadcasting and Telecommunication * - * BPFT $Id: traflog.c,v 1.6 2008/02/21 07:20:30 lorf Exp $ + * BPFT $Id: traflog.c,v 1.7 2011/01/29 17:48:35 Serg79 Exp $ * * $Log: traflog.c,v $ + * Revision 1.7 2011/01/29 17:48:35 Serg79 + * Added definition client on the basis of 'who_srv'. + * * Revision 1.6 2008/02/21 07:20:30 lorf * - Compile with large file offset support under Linux * - Fix Linux compatibility @@ -637,7 +640,7 @@ { register int i, j; uint64_t abytes = 0, dbytes = 0; - char buf[MAXHOSTNAMELEN + 1], *port, *user, *proto; + char buf[MAXHOSTNAMELEN + 1], *port, *proto; time_t start_clock, stop_clock; for (i = 0; i < sumh.t_size; i++) @@ -661,7 +664,7 @@ From Port To Port Proto Data All\n"); } for (i = 0; i < sumh.t_size; i++) { - port = "undef"; + port = NULL; switch(sum[i].ip_protocol) { case IPPROTO_TCP: if (sum[i].p_port) @@ -688,13 +691,11 @@ default: proto = "unkn"; } - if (sum[i].p_port) user = "client"; - else user = "none"; if (!fvnum) { printf("%-18.18s %-6.6s ", ipaddr_string(&sum[i].in_ip), - (sum[i].who_srv & 1) ? port : user); + (sum[i].who_srv == 2) ? "client" : (port ? port : "none")); printf("%-18.18s %-6.6s ", ipaddr_string(&sum[i].out_ip), - (sum[i].who_srv & 2) ? port : user); + (sum[i].who_srv == 1) ? "client" : (port ? port : "none")); printf("%-4.4s %9u %10u\n", proto, sum[i].n_bytes, sum[i].n_psize); } else @@ -708,11 +709,11 @@ break; case SPORT: printf(fv[j].format, - (sum[i].who_srv & 1) ? port : user); + (sum[i].who_srv == 2) ? "client" : (port ? port : "none")); break; case DPORT: printf(fv[j].format, - (sum[i].who_srv & 2) ? port : user); + (sum[i].who_srv == 1) ? "client" : (port ? port : "none")); break; case PROTO: printf(fv[j].format, proto); diff -urN a/trafstat/trafstat.c b/trafstat/trafstat.c --- a/trafstat/trafstat.c 2006-10-31 11:57:03.000000000 +0300 +++ b/trafstat/trafstat.c 2011-01-29 18:09:27.000000000 +0300 @@ -4,9 +4,12 @@ * Copyright (c) 1993 The CAD lab of the * Novosibirsk Institute of Broadcasting and Telecommunication * - * BPFT $Id: trafstat.c,v 1.3 2006/10/31 08:57:03 frol Exp $ + * BPFT $Id: trafstat.c,v 1.4 2011/01/29 17:26:37 Serg79 Exp $ * * $Log: trafstat.c,v $ + * Revision 1.4 2011/01/29 17:26:37 Serg79 + * Added definition client on the basis of 'who_srv'. + * * Revision 1.3 2006/10/31 08:57:03 frol * o Allow loading large tables in trafstat. * @@ -131,7 +134,7 @@ { register uint32_t i; uint64_t abytes = 0, dbytes = 0; - char buf[MAXHOSTNAMELEN + 1], *port, *user, *proto; + char buf[MAXHOSTNAMELEN + 1], *port, *proto; time_t start_clock, drop_clock; start_clock = (time_t)start_time.tv32_sec; @@ -182,12 +185,10 @@ default: proto = "unkn"; } - if (entries[i].p_port) user = "client"; - else user = "none"; printf("%-18.18s %-6.6s ", ipaddr_string(&entries[i].in_ip), - (entries[i].who_srv & 1) && port ? port : user); + (entries[i].who_srv == 2) ? "client" : (port ? port : "none")); printf("%-18.18s %-6.6s ", ipaddr_string(&entries[i].out_ip), - (entries[i].who_srv & 2) && port ? port : user); + (entries[i].who_srv == 1) ? "client" : (port ? port : "none")); printf("%-4.4s %9u %10u\n", proto, entries[i].n_bytes, entries[i].n_psize); }