155682Smarkm/*	$FreeBSD$	*/
2120945Snectar
355682Smarkm/*
455682Smarkm * (C)opyright 1995-1998 Darren Reed.
555682Smarkm *
655682Smarkm * See the IPFILTER.LICENCE file for details on licencing.
755682Smarkm *
855682Smarkm */
955682Smarkm#include <stdio.h>
1055682Smarkm#include <fcntl.h>
1155682Smarkm#include <signal.h>
1255682Smarkm#include <malloc.h>
1355682Smarkm#include <netdb.h>
1455682Smarkm#include <string.h>
1555682Smarkm#include <sys/dir.h>
1655682Smarkm#include <sys/types.h>
1755682Smarkm#include <sys/time.h>
1855682Smarkm#include <sys/socket.h>
1955682Smarkm#include <netinet/in.h>
2055682Smarkm#include <netinet/in_systm.h>
2155682Smarkm#include <netinet/ip.h>
2255682Smarkm#include <netinet/tcp.h>
2355682Smarkm#include <netinet/udp.h>
2455682Smarkm#include <netinet/ip_icmp.h>
2555682Smarkm#ifndef	linux
2655682Smarkm#include <netinet/ip_var.h>
2755682Smarkm#include <netinet/tcpip.h>
2855682Smarkm#endif
2955682Smarkm#include "ip_compat.h"
3055682Smarkm#ifdef	linux
3155682Smarkm#include <linux/sockios.h>
3255682Smarkm#include "tcpip.h"
3355682Smarkm#endif
3455682Smarkm#include "ipsd.h"
3555682Smarkm
3655682Smarkm#ifndef	lint
3755682Smarkmstatic const char sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
3855682Smarkmstatic const char rcsid[] = "@(#)$Id$";
3955682Smarkm#endif
40127808Snectar
4155682Smarkmextern	char	*optarg;
4255682Smarkmextern	int	optind;
4355682Smarkm
4455682Smarkm#define	NPORTS	21
4555682Smarkm
4655682Smarkmu_short	defports[NPORTS] = {
4772445Sassar		7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
4855682Smarkm		123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
4955682Smarkm	};
5055682Smarkmu_short	pweights[NPORTS] = {
5155682Smarkm		1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5255682Smarkm		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
5355682Smarkm	};
5455682Smarkm
5555682Smarkmipsd_t	*iphits[NPORTS];
5655682Smarkmint	pkts;
5755682Smarkm
5855682Smarkm
5955682Smarkmint	ipcmp(sh1, sh2)
6055682Smarkm	sdhit_t	*sh1, *sh2;
6155682Smarkm{
6255682Smarkm	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
6355682Smarkm}
6455682Smarkm
6555682Smarkm
6655682Smarkmint	ssipcmp(sh1, sh2)
6755682Smarkm	ipss_t	*sh1, *sh2;
6855682Smarkm{
6955682Smarkm	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
7055682Smarkm}
7155682Smarkm
7255682Smarkm
7355682Smarkmint countpbits(num)
7455682Smarkm	u_long	num;
75127808Snectar{
76127808Snectar	int	i, j;
7755682Smarkm
78127808Snectar	for (i = 1, j = 0; i; i <<= 1)
79127808Snectar		if (num & i)
80127808Snectar			j++;
81127808Snectar	return j;
82127808Snectar}
83127808Snectar
84127808Snectar
85127808Snectar/*
8655682Smarkm * Check to see if we've already received a packet from this host for this
8755682Smarkm * port.
8855682Smarkm */
8955682Smarkmint	findhit(ihp, src, dport)
9055682Smarkm	ipsd_t	*ihp;
9155682Smarkm	struct	in_addr	src;
92127808Snectar	u_short	dport;
93127808Snectar{
94127808Snectar	int	i, j, k;
9555682Smarkm	sdhit_t	*sh;
96127808Snectar
9755682Smarkm	sh = NULL;
9855682Smarkm
9955682Smarkm	if (ihp->sd_sz == 4) {
10055682Smarkm		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
101127808Snectar			if (src.s_addr == sh->sh_ip.s_addr)
10255682Smarkm				return 1;
103127808Snectar	} else {
104127808Snectar		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
105127808Snectar			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
10655682Smarkm			if (!k)
10755682Smarkm				return 1;
10855682Smarkm			else if (k < 0)
10955682Smarkm				i -= j;
11055682Smarkm			else
11155682Smarkm				i += j;
11255682Smarkm		}
11355682Smarkm	}
11455682Smarkm	return 0;
11555682Smarkm}
11655682Smarkm
11755682Smarkm
11855682Smarkm/*
11955682Smarkm * Search for port number amongst the sorted array of targets we're
12055682Smarkm * interested in.
12155682Smarkm */
12255682Smarkmint	detect(srcip, dport, date)
12355682Smarkm	struct	in_addr	srcip;
12455682Smarkm	u_short	dport;
12555682Smarkm	time_t	date;
12655682Smarkm{
12755682Smarkm	ipsd_t	*ihp;
12855682Smarkm	sdhit_t	*sh;
12955682Smarkm	int	i, j, k;
13055682Smarkm
13155682Smarkm	for (i = 10, j = 4; j >= 0; j--) {
13255682Smarkm		k = dport - defports[i];
13355682Smarkm		if (!k) {
13455682Smarkm			ihp = iphits[i];
13555682Smarkm			if (findhit(ihp, srcip, dport))
13655682Smarkm				return 0;
13755682Smarkm			sh = ihp->sd_hit + ihp->sd_cnt;
13855682Smarkm			sh->sh_date = date;
13955682Smarkm			sh->sh_ip = srcip;
14055682Smarkm			if (++ihp->sd_cnt == ihp->sd_sz)
14155682Smarkm			{
14255682Smarkm				ihp->sd_sz += 8;
14355682Smarkm				sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
14455682Smarkm				ihp->sd_hit = sh;
14555682Smarkm			}
14655682Smarkm			qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
14755682Smarkm			return 0;
14855682Smarkm		}
14955682Smarkm		if (k < 0)
15055682Smarkm			i -= j;
15155682Smarkm		else
15255682Smarkm			i += j;
15355682Smarkm	}
15455682Smarkm	return -1;
15555682Smarkm}
15655682Smarkm
15755682Smarkm
15855682Smarkm/*
15955682Smarkm * Allocate initial storage for hosts
16055682Smarkm */
16190926Snectarsetuphits()
16290926Snectar{
16390926Snectar	int	i;
16490926Snectar
16590926Snectar	for (i = 0; i < NPORTS; i++) {
16690926Snectar		if (iphits[i]) {
16790926Snectar			if (iphits[i]->sd_hit)
16857416Smarkm				free(iphits[i]->sd_hit);
16957416Smarkm			free(iphits[i]);
17057416Smarkm		}
17155682Smarkm		iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
17255682Smarkm		iphits[i]->sd_port = defports[i];
17355682Smarkm		iphits[i]->sd_cnt = 0;
17455682Smarkm		iphits[i]->sd_sz = 4;
17555682Smarkm		iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
17655682Smarkm	}
17755682Smarkm}
17855682Smarkm
17955682Smarkm
18055682Smarkm/*
18155682Smarkm * Write statistics out to a file
18255682Smarkm */
18355682Smarkmaddfile(file)
18455682Smarkm	char	*file;
18555682Smarkm{
18655682Smarkm	ipsd_t	ipsd, *ips = &ipsd;
18755682Smarkm	sdhit_t	hit, *hp;
18855682Smarkm	char	fname[32];
18955682Smarkm	int	i, fd, sz;
19055682Smarkm
19155682Smarkm	if ((fd = open(file, O_RDONLY)) == -1) {
19255682Smarkm		perror("open");
19355682Smarkm		return;
19455682Smarkm	}
19555682Smarkm
19655682Smarkm	printf("opened %s\n", file);
19755682Smarkm	do {
19855682Smarkm		if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
19955682Smarkm			break;
20055682Smarkm		sz = ips->sd_sz * sizeof(*hp);
20155682Smarkm		hp = (sdhit_t *)malloc(sz);
20255682Smarkm		if (read(fd, hp, sz) != sz)
20355682Smarkm			break;
20455682Smarkm		for (i = 0; i < ips->sd_cnt; i++)
20555682Smarkm			detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
20655682Smarkm	} while (1);
20755682Smarkm	(void) close(fd);
20855682Smarkm}
20955682Smarkm
21055682Smarkm
21155682Smarkmreadfiles(dir)
21255682Smarkm	char *dir;
21355682Smarkm{
21455682Smarkm	struct	direct	**d;
21555682Smarkm	int	i, j;
21655682Smarkm
21755682Smarkm	d = NULL;
21855682Smarkm	i = scandir(dir, &d, NULL, NULL);
21955682Smarkm
22055682Smarkm	for (j = 0; j < i; j++) {
22155682Smarkm		if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
22255682Smarkm			continue;
22355682Smarkm		addfile(d[j]->d_name);
22455682Smarkm	}
22555682Smarkm}
22655682Smarkm
22755682Smarkm
22855682Smarkmvoid printreport(ss, num)
22955682Smarkm	ipss_t	*ss;
23055682Smarkm	int	num;
23155682Smarkm{
23255682Smarkm	struct	in_addr	ip;
23355682Smarkm	ipss_t	*sp;
23455682Smarkm	int	i, j, mask;
23555682Smarkm	u_long	ports;
23655682Smarkm
23755682Smarkm	printf("Hosts detected: %d\n", num);
23855682Smarkm	if (!num)
23955682Smarkm		return;
24055682Smarkm	for (i = 0; i < num; i++)
24155682Smarkm		printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
24255682Smarkm			countpbits(ss[i].ss_ports));
24355682Smarkm
24455682Smarkm	printf("--------------------------\n");
24555682Smarkm	for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
24655682Smarkm		ip.s_addr = ss[0].ss_ip.s_addr & mask;
24755682Smarkm		ports = ss[0].ss_ports;
24855682Smarkm		for (i = 1; i < num; i++) {
24955682Smarkm			sp = ss + i;
25055682Smarkm			if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
25155682Smarkm				printf("Netmask: 0x%08x\n", mask);
25255682Smarkm				printf("%s %d\n", inet_ntoa(ip),
25355682Smarkm					countpbits(ports));
25455682Smarkm				ip.s_addr = sp->ss_ip.s_addr & mask;
25555682Smarkm				ports = 0;
256102644Snectar			}
257102644Snectar			ports |= sp->ss_ports;
258102644Snectar		}
259102644Snectar		if (ports) {
260102644Snectar			printf("Netmask: 0x%08x\n", mask);
261102644Snectar			printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
262102644Snectar		}
263102644Snectar	}
264102644Snectar}
265102644Snectar
266102644Snectar
267102644Snectarcollectips()
268102644Snectar{
269102644Snectar	ipsd_t	*ips;
270102644Snectar	ipss_t	*ss;
271102644Snectar	int	i, num, nip, in, j, k;
272102644Snectar
273102644Snectar	for (i = 0; i < NPORTS; i++)
274102644Snectar		nip += iphits[i]->sd_cnt;
275102644Snectar
27655682Smarkm	ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
27755682Smarkm
278102644Snectar	for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
279102644Snectar		ips = iphits[i];
280102644Snectar		for (j = 0; j < ips->sd_cnt; j++) {
281102644Snectar			for (k = 0; k < num; k++)
282102644Snectar				if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
283102644Snectar					  sizeof(struct in_addr))) {
284102644Snectar					ss[k].ss_hits += pweights[i];
285102644Snectar					ss[k].ss_ports |= (1 << i);
286102644Snectar					break;
287102644Snectar				}
288102644Snectar			if (k == num) {
289102644Snectar				ss[num].ss_ip = ips->sd_hit[j].sh_ip;
29055682Smarkm				ss[num].ss_hits = pweights[i];
291102644Snectar				ss[k].ss_ports |= (1 << i);
292102644Snectar				num++;
293102644Snectar			}
294102644Snectar		}
29555682Smarkm	}
29655682Smarkm
29755682Smarkm	qsort(ss, num, sizeof(*ss), ssipcmp);
29855682Smarkm
29955682Smarkm	printreport(ss, num);
30055682Smarkm}
30155682Smarkm
30255682Smarkm
30355682Smarkmmain(argc, argv)
30455682Smarkm	int	argc;
30555682Smarkm	char	*argv[];
30655682Smarkm{
30755682Smarkm	char	c, *name =  argv[0], *dir = NULL;
30855682Smarkm	int	fd;
30955682Smarkm
31055682Smarkm	setuphits();
31155682Smarkm	dir = dir ? dir : ".";
31255682Smarkm	readfiles(dir);
31355682Smarkm	collectips();
31455682Smarkm}
31555682Smarkm