Home | History | Annotate | Line # | Download | only in ipsd
      1  1.2   darrenr /*	$NetBSD: ipsd.c,v 1.2 2012/07/22 14:27:35 darrenr Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * (C)opyright 1995-1998 Darren Reed.
      5  1.1  christos  *
      6  1.1  christos  * See the IPFILTER.LICENCE file for details on licencing.
      7  1.1  christos  *
      8  1.1  christos  */
      9  1.1  christos #include <stdio.h>
     10  1.1  christos #include <fcntl.h>
     11  1.1  christos #include <signal.h>
     12  1.1  christos #include <stdlib.h>
     13  1.1  christos #include <netdb.h>
     14  1.1  christos #include <string.h>
     15  1.1  christos #include <sys/types.h>
     16  1.1  christos #include <sys/time.h>
     17  1.1  christos #include <sys/socket.h>
     18  1.1  christos #include <netinet/in.h>
     19  1.1  christos #include <netinet/in_systm.h>
     20  1.1  christos #include <netinet/ip.h>
     21  1.1  christos #include <netinet/tcp.h>
     22  1.1  christos #include <netinet/udp.h>
     23  1.1  christos #include <netinet/ip_icmp.h>
     24  1.1  christos #ifndef	linux
     25  1.1  christos #include <netinet/ip_var.h>
     26  1.1  christos #include <netinet/tcpip.h>
     27  1.1  christos #endif
     28  1.1  christos #include "ip_compat.h"
     29  1.1  christos #ifdef	linux
     30  1.1  christos #include <linux/sockios.h>
     31  1.1  christos #include "tcpip.h"
     32  1.1  christos #endif
     33  1.1  christos #include "ipsd.h"
     34  1.1  christos 
     35  1.1  christos #ifndef	lint
     36  1.1  christos static const char sccsid[] = "@(#)ipsd.c	1.3 12/3/95 (C)1995 Darren Reed";
     37  1.2   darrenr static const char rcsid[] = "@(#)Id: ipsd.c,v 1.1.1.2 2012/07/22 13:44:34 darrenr Exp $";
     38  1.1  christos #endif
     39  1.1  christos 
     40  1.1  christos extern	char	*optarg;
     41  1.1  christos extern	int	optind;
     42  1.1  christos 
     43  1.1  christos #ifdef	linux
     44  1.1  christos char	default_device[] = "eth0";
     45  1.1  christos #else
     46  1.1  christos # ifdef	sun
     47  1.1  christos char	default_device[] = "le0";
     48  1.1  christos # else
     49  1.1  christos #  ifdef	ultrix
     50  1.1  christos char	default_device[] = "ln0";
     51  1.1  christos #  else
     52  1.1  christos char	default_device[] = "lan0";
     53  1.1  christos #  endif
     54  1.1  christos # endif
     55  1.1  christos #endif
     56  1.1  christos 
     57  1.1  christos #define	NPORTS	21
     58  1.1  christos 
     59  1.1  christos u_short	defports[NPORTS] = {
     60  1.1  christos 		  7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
     61  1.1  christos 		123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0
     62  1.1  christos 	};
     63  1.1  christos 
     64  1.1  christos ipsd_t	*iphits[NPORTS];
     65  1.1  christos int	writes = 0;
     66  1.1  christos 
     67  1.1  christos 
     68  1.1  christos int	ipcmp(sh1, sh2)
     69  1.1  christos 	sdhit_t	*sh1, *sh2;
     70  1.1  christos {
     71  1.1  christos 	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
     72  1.1  christos }
     73  1.1  christos 
     74  1.1  christos 
     75  1.1  christos /*
     76  1.1  christos  * Check to see if we've already received a packet from this host for this
     77  1.1  christos  * port.
     78  1.1  christos  */
     79  1.1  christos int	findhit(ihp, src, dport)
     80  1.1  christos 	ipsd_t	*ihp;
     81  1.1  christos 	struct	in_addr	src;
     82  1.1  christos 	u_short	dport;
     83  1.1  christos {
     84  1.1  christos 	int	i, j, k;
     85  1.1  christos 	sdhit_t	*sh;
     86  1.1  christos 
     87  1.1  christos 	sh = NULL;
     88  1.1  christos 
     89  1.1  christos 	if (ihp->sd_sz == 4) {
     90  1.1  christos 		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
     91  1.1  christos 			if (src.s_addr == sh->sh_ip.s_addr)
     92  1.1  christos 				return 1;
     93  1.1  christos 	} else {
     94  1.1  christos 		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
     95  1.1  christos 			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
     96  1.1  christos 			if (!k)
     97  1.1  christos 				return 1;
     98  1.1  christos 			else if (k < 0)
     99  1.1  christos 				i -= j;
    100  1.1  christos 			else
    101  1.1  christos 				i += j;
    102  1.1  christos 		}
    103  1.1  christos 	}
    104  1.1  christos 	return 0;
    105  1.1  christos }
    106  1.1  christos 
    107  1.1  christos 
    108  1.1  christos /*
    109  1.1  christos  * Search for port number amongst the sorted array of targets we're
    110  1.1  christos  * interested in.
    111  1.1  christos  */
    112  1.1  christos int	detect(ip, tcp)
    113  1.1  christos 	ip_t	*ip;
    114  1.1  christos 	tcphdr_t	*tcp;
    115  1.1  christos {
    116  1.1  christos 	ipsd_t	*ihp;
    117  1.1  christos 	sdhit_t	*sh;
    118  1.1  christos 	int	i, j, k;
    119  1.1  christos 
    120  1.1  christos 	for (i = 10, j = 4; j >= 0; j--) {
    121  1.1  christos 		k = tcp->th_dport - defports[i];
    122  1.1  christos 		if (!k) {
    123  1.1  christos 			ihp = iphits[i];
    124  1.1  christos 			if (findhit(ihp, ip->ip_src, tcp->th_dport))
    125  1.1  christos 				return 0;
    126  1.1  christos 			sh = ihp->sd_hit + ihp->sd_cnt;
    127  1.1  christos 			sh->sh_date = time(NULL);
    128  1.1  christos 			sh->sh_ip.s_addr = ip->ip_src.s_addr;
    129  1.1  christos 			if (++ihp->sd_cnt == ihp->sd_sz)
    130  1.1  christos 			{
    131  1.1  christos 				ihp->sd_sz += 8;
    132  1.1  christos 				sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
    133  1.1  christos 				ihp->sd_hit = sh;
    134  1.1  christos 			}
    135  1.1  christos 			qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
    136  1.1  christos 			return 0;
    137  1.1  christos 		}
    138  1.1  christos 		if (k < 0)
    139  1.1  christos 			i -= j;
    140  1.1  christos 		else
    141  1.1  christos 			i += j;
    142  1.1  christos 	}
    143  1.1  christos 	return -1;
    144  1.1  christos }
    145  1.1  christos 
    146  1.1  christos 
    147  1.1  christos /*
    148  1.1  christos  * Allocate initial storage for hosts
    149  1.1  christos  */
    150  1.1  christos setuphits()
    151  1.1  christos {
    152  1.1  christos 	int	i;
    153  1.1  christos 
    154  1.1  christos 	for (i = 0; i < NPORTS; i++) {
    155  1.1  christos 		if (iphits[i]) {
    156  1.1  christos 			if (iphits[i]->sd_hit)
    157  1.1  christos 				free(iphits[i]->sd_hit);
    158  1.1  christos 			free(iphits[i]);
    159  1.1  christos 		}
    160  1.1  christos 		iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
    161  1.1  christos 		iphits[i]->sd_port = defports[i];
    162  1.1  christos 		iphits[i]->sd_cnt = 0;
    163  1.1  christos 		iphits[i]->sd_sz = 4;
    164  1.1  christos 		iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
    165  1.1  christos 	}
    166  1.1  christos }
    167  1.1  christos 
    168  1.1  christos 
    169  1.1  christos /*
    170  1.1  christos  * cleanup exits
    171  1.1  christos  */
    172  1.1  christos waiter()
    173  1.1  christos {
    174  1.1  christos 	wait(0);
    175  1.1  christos }
    176  1.1  christos 
    177  1.1  christos 
    178  1.1  christos /*
    179  1.1  christos  * Write statistics out to a file
    180  1.1  christos  */
    181  1.1  christos writestats(nwrites)
    182  1.1  christos 	int	nwrites;
    183  1.1  christos {
    184  1.1  christos 	ipsd_t	**ipsd, *ips;
    185  1.1  christos 	char	fname[32];
    186  1.1  christos 	int	i, fd;
    187  1.1  christos 
    188  1.1  christos 	(void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites);
    189  1.1  christos 	fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644);
    190  1.1  christos 	for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) {
    191  1.1  christos 		ips = *ipsd;
    192  1.1  christos 		if (ips->sd_cnt) {
    193  1.1  christos 			write(fd, ips, sizeof(ipsd_t));
    194  1.1  christos 			write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz);
    195  1.1  christos 		}
    196  1.1  christos 	}
    197  1.1  christos 	(void) close(fd);
    198  1.1  christos 	exit(0);
    199  1.1  christos }
    200  1.1  christos 
    201  1.1  christos 
    202  1.1  christos void writenow()
    203  1.1  christos {
    204  1.1  christos 	signal(SIGCHLD, waiter);
    205  1.1  christos 	switch (fork())
    206  1.1  christos 	{
    207  1.1  christos 	case 0 :
    208  1.1  christos 		writestats(writes);
    209  1.1  christos 		exit(0);
    210  1.1  christos 	case -1 :
    211  1.1  christos 		perror("vfork");
    212  1.1  christos 		break;
    213  1.1  christos 	default :
    214  1.1  christos 		writes++;
    215  1.1  christos 		setuphits();
    216  1.1  christos 		break;
    217  1.1  christos 	}
    218  1.1  christos }
    219  1.1  christos 
    220  1.1  christos 
    221  1.1  christos void	usage(prog)
    222  1.1  christos 	char	*prog;
    223  1.1  christos {
    224  1.1  christos 	fprintf(stderr, "Usage: %s [-d device]\n", prog);
    225  1.1  christos 	exit(1);
    226  1.1  christos }
    227  1.1  christos 
    228  1.1  christos 
    229  1.1  christos void detecthits(fd, writecount)
    230  1.1  christos 	int fd, writecount;
    231  1.1  christos {
    232  1.1  christos 	struct	in_addr	ip;
    233  1.1  christos 	int	hits = 0;
    234  1.1  christos 
    235  1.1  christos 	while (1) {
    236  1.1  christos 		hits += readloop(fd, ip);
    237  1.1  christos 		if (hits > writecount) {
    238  1.1  christos 			writenow();
    239  1.1  christos 			hits = 0;
    240  1.1  christos 		}
    241  1.1  christos 	}
    242  1.1  christos }
    243  1.1  christos 
    244  1.1  christos 
    245  1.1  christos main(argc, argv)
    246  1.1  christos 	int	argc;
    247  1.1  christos 	char	*argv[];
    248  1.1  christos {
    249  1.1  christos 	char	*name =  argv[0], *dev = NULL;
    250  1.1  christos 	int	fd, writeafter = 10000, angelic = 0, c;
    251  1.1  christos 
    252  1.1  christos 	while ((c = getopt(argc, argv, "ad:n:")) != -1)
    253  1.1  christos 		switch (c)
    254  1.1  christos 		{
    255  1.1  christos 		case 'a' :
    256  1.1  christos 			angelic = 1;
    257  1.1  christos 			break;
    258  1.1  christos 		case 'd' :
    259  1.1  christos 			dev = optarg;
    260  1.1  christos 			break;
    261  1.1  christos 		case 'n' :
    262  1.1  christos 			writeafter = atoi(optarg);
    263  1.1  christos 			break;
    264  1.1  christos 		default :
    265  1.1  christos 			fprintf(stderr, "Unknown option \"%c\"\n", c);
    266  1.1  christos 			usage(name);
    267  1.1  christos 		}
    268  1.1  christos 
    269  1.1  christos 	bzero(iphits, sizeof(iphits));
    270  1.1  christos 	setuphits();
    271  1.1  christos 
    272  1.1  christos 	if (!dev)
    273  1.1  christos 		dev = default_device;
    274  1.1  christos 	printf("Device:  %s\n", dev);
    275  1.1  christos 	fd = initdevice(dev, 60);
    276  1.1  christos 
    277  1.1  christos 	if (!angelic) {
    278  1.1  christos 		switch (fork())
    279  1.1  christos 		{
    280  1.1  christos 		case 0 :
    281  1.1  christos 			(void) close(0);
    282  1.1  christos 			(void) close(1);
    283  1.1  christos 			(void) close(2);
    284  1.1  christos 			(void) setpgrp(0, getpgrp());
    285  1.1  christos 			(void) setsid();
    286  1.1  christos 			break;
    287  1.1  christos 		case -1:
    288  1.1  christos 			perror("fork");
    289  1.1  christos 			exit(-1);
    290  1.1  christos 		default:
    291  1.1  christos 			exit(0);
    292  1.1  christos 		}
    293  1.1  christos 	}
    294  1.1  christos 	signal(SIGUSR1, writenow);
    295  1.1  christos 	detecthits(fd, writeafter);
    296  1.1  christos }
    297