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