ipsdr.c revision 53024
122514Sdarrenr/*
253024Sguido * (C)opyright 1995-1998 Darren Reed.
322514Sdarrenr *
431183Speter * Redistribution and use in source and binary forms are permitted
531183Speter * provided that this notice is preserved and due credit is given
631183Speter * to the original author and the contributors.
722514Sdarrenr *
822514Sdarrenr *   The author of this software makes no garuntee about the
922514Sdarrenr * performance of this package or its suitability to fulfill any purpose.
1022514Sdarrenr *
1122514Sdarrenr */
1222514Sdarrenr#include <stdio.h>
1322514Sdarrenr#include <fcntl.h>
1422514Sdarrenr#include <signal.h>
1522514Sdarrenr#include <malloc.h>
1622514Sdarrenr#include <netdb.h>
1722514Sdarrenr#include <string.h>
1822514Sdarrenr#include <sys/dir.h>
1922514Sdarrenr#include <sys/types.h>
2022514Sdarrenr#include <sys/time.h>
2122514Sdarrenr#include <sys/socket.h>
2222514Sdarrenr#include <netinet/in.h>
2322514Sdarrenr#include <netinet/in_systm.h>
2422514Sdarrenr#include <netinet/ip.h>
2522514Sdarrenr#include <netinet/tcp.h>
2622514Sdarrenr#include <netinet/udp.h>
2722514Sdarrenr#include <netinet/ip_icmp.h>
2822514Sdarrenr#ifndef	linux
2922514Sdarrenr#include <netinet/ip_var.h>
3022514Sdarrenr#include <netinet/tcpip.h>
3122514Sdarrenr#endif
3222514Sdarrenr#include "ip_compat.h"
3322514Sdarrenr#ifdef	linux
3422514Sdarrenr#include <linux/sockios.h>
3522514Sdarrenr#include "tcpip.h"
3622514Sdarrenr#endif
3722514Sdarrenr#include "ipsd.h"
3822514Sdarrenr
3922514Sdarrenr#ifndef	lint
4031183Speterstatic const char sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
4153024Sguidostatic const char rcsid[] = "@(#)$Id: ipsdr.c,v 2.1 1999/08/04 17:30:57 darrenr Exp $";
4222514Sdarrenr#endif
4322514Sdarrenr
4422514Sdarrenrextern	char	*optarg;
4522514Sdarrenrextern	int	optind;
4622514Sdarrenr
4722514Sdarrenr#define	NPORTS	21
4822514Sdarrenr
4922514Sdarrenru_short	defports[NPORTS] = {
5022514Sdarrenr		7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
5122514Sdarrenr		123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
5222514Sdarrenr	};
5322514Sdarrenru_short	pweights[NPORTS] = {
5422514Sdarrenr		1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5522514Sdarrenr		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
5622514Sdarrenr	};
5722514Sdarrenr
5822514Sdarrenripsd_t	*iphits[NPORTS];
5922514Sdarrenrint	pkts;
6022514Sdarrenr
6122514Sdarrenr
6222514Sdarrenrint	ipcmp(sh1, sh2)
6322514Sdarrenrsdhit_t	*sh1, *sh2;
6422514Sdarrenr{
6522514Sdarrenr	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
6622514Sdarrenr}
6722514Sdarrenr
6822514Sdarrenr
6922514Sdarrenrint	ssipcmp(sh1, sh2)
7022514Sdarrenripss_t	*sh1, *sh2;
7122514Sdarrenr{
7222514Sdarrenr	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
7322514Sdarrenr}
7422514Sdarrenr
7522514Sdarrenr
7622514Sdarrenrint countpbits(num)
7722514Sdarrenru_long	num;
7822514Sdarrenr{
7922514Sdarrenr	int	i, j;
8022514Sdarrenr
8122514Sdarrenr	for (i = 1, j = 0; i; i <<= 1)
8222514Sdarrenr		if (num & i)
8322514Sdarrenr			j++;
8422514Sdarrenr	return j;
8522514Sdarrenr}
8622514Sdarrenr
8722514Sdarrenr
8822514Sdarrenr/*
8922514Sdarrenr * Check to see if we've already received a packet from this host for this
9022514Sdarrenr * port.
9122514Sdarrenr */
9222514Sdarrenrint	findhit(ihp, src, dport)
9322514Sdarrenripsd_t	*ihp;
9422514Sdarrenrstruct	in_addr	src;
9522514Sdarrenru_short	dport;
9622514Sdarrenr{
9722514Sdarrenr	int	i, j, k;
9822514Sdarrenr	sdhit_t	*sh;
9922514Sdarrenr
10022514Sdarrenr	sh = NULL;
10122514Sdarrenr
10222514Sdarrenr	if (ihp->sd_sz == 4) {
10322514Sdarrenr		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
10422514Sdarrenr			if (src.s_addr == sh->sh_ip.s_addr)
10522514Sdarrenr				return 1;
10622514Sdarrenr	} else {
10722514Sdarrenr		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
10822514Sdarrenr			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
10922514Sdarrenr			if (!k)
11022514Sdarrenr				return 1;
11122514Sdarrenr			else if (k < 0)
11222514Sdarrenr				i -= j;
11322514Sdarrenr			else
11422514Sdarrenr				i += j;
11522514Sdarrenr		}
11622514Sdarrenr	}
11722514Sdarrenr	return 0;
11822514Sdarrenr}
11922514Sdarrenr
12022514Sdarrenr
12122514Sdarrenr/*
12222514Sdarrenr * Search for port number amongst the sorted array of targets we're
12322514Sdarrenr * interested in.
12422514Sdarrenr */
12522514Sdarrenrint	detect(srcip, dport, date)
12622514Sdarrenrstruct	in_addr	srcip;
12722514Sdarrenru_short	dport;
12822514Sdarrenrtime_t	date;
12922514Sdarrenr{
13022514Sdarrenr	ipsd_t	*ihp;
13122514Sdarrenr	sdhit_t	*sh;
13222514Sdarrenr	int	i, j, k;
13322514Sdarrenr
13422514Sdarrenr	for (i = 10, j = 4; j >= 0; j--) {
13522514Sdarrenr		k = dport - defports[i];
13622514Sdarrenr		if (!k) {
13722514Sdarrenr			ihp = iphits[i];
13822514Sdarrenr			if (findhit(ihp, srcip, dport))
13922514Sdarrenr				return 0;
14022514Sdarrenr			sh = ihp->sd_hit + ihp->sd_cnt;
14122514Sdarrenr			sh->sh_date = date;
14222514Sdarrenr			sh->sh_ip = srcip;
14322514Sdarrenr			if (++ihp->sd_cnt == ihp->sd_sz)
14422514Sdarrenr			{
14522514Sdarrenr				ihp->sd_sz += 8;
14622514Sdarrenr				sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
14722514Sdarrenr				ihp->sd_hit = sh;
14822514Sdarrenr			}
14922514Sdarrenr			qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
15022514Sdarrenr			return 0;
15122514Sdarrenr		}
15222514Sdarrenr		if (k < 0)
15322514Sdarrenr			i -= j;
15422514Sdarrenr		else
15522514Sdarrenr			i += j;
15622514Sdarrenr	}
15722514Sdarrenr	return -1;
15822514Sdarrenr}
15922514Sdarrenr
16022514Sdarrenr
16122514Sdarrenr/*
16222514Sdarrenr * Allocate initial storage for hosts
16322514Sdarrenr */
16422514Sdarrenrsetuphits()
16522514Sdarrenr{
16622514Sdarrenr	int	i;
16722514Sdarrenr
16822514Sdarrenr	for (i = 0; i < NPORTS; i++) {
16922514Sdarrenr		if (iphits[i]) {
17022514Sdarrenr			if (iphits[i]->sd_hit)
17122514Sdarrenr				free(iphits[i]->sd_hit);
17222514Sdarrenr			free(iphits[i]);
17322514Sdarrenr		}
17422514Sdarrenr		iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
17522514Sdarrenr		iphits[i]->sd_port = defports[i];
17622514Sdarrenr		iphits[i]->sd_cnt = 0;
17722514Sdarrenr		iphits[i]->sd_sz = 4;
17822514Sdarrenr		iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
17922514Sdarrenr	}
18022514Sdarrenr}
18122514Sdarrenr
18222514Sdarrenr
18322514Sdarrenr/*
18422514Sdarrenr * Write statistics out to a file
18522514Sdarrenr */
18622514Sdarrenraddfile(file)
18722514Sdarrenrchar	*file;
18822514Sdarrenr{
18922514Sdarrenr	ipsd_t	ipsd, *ips = &ipsd;
19022514Sdarrenr	sdhit_t	hit, *hp;
19122514Sdarrenr	char	fname[32];
19222514Sdarrenr	int	i, fd, sz;
19322514Sdarrenr
19422514Sdarrenr	if ((fd = open(file, O_RDONLY)) == -1) {
19522514Sdarrenr		perror("open");
19622514Sdarrenr		return;
19722514Sdarrenr	}
19822514Sdarrenr
19922514Sdarrenr	printf("opened %s\n", file);
20022514Sdarrenr	do {
20122514Sdarrenr		if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
20222514Sdarrenr			break;
20322514Sdarrenr		sz = ips->sd_sz * sizeof(*hp);
20422514Sdarrenr		hp = (sdhit_t *)malloc(sz);
20522514Sdarrenr		if (read(fd, hp, sz) != sz)
20622514Sdarrenr			break;
20722514Sdarrenr		for (i = 0; i < ips->sd_cnt; i++)
20822514Sdarrenr			detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
20922514Sdarrenr	} while (1);
21022514Sdarrenr	(void) close(fd);
21122514Sdarrenr}
21222514Sdarrenr
21322514Sdarrenr
21422514Sdarrenrreadfiles(dir)
21522514Sdarrenrchar *dir;
21622514Sdarrenr{
21722514Sdarrenr	struct	direct	**d;
21822514Sdarrenr	int	i, j;
21922514Sdarrenr
22022514Sdarrenr	d = NULL;
22122514Sdarrenr	i = scandir(dir, &d, NULL, NULL);
22222514Sdarrenr
22322514Sdarrenr	for (j = 0; j < i; j++) {
22422514Sdarrenr		if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
22522514Sdarrenr			continue;
22622514Sdarrenr		addfile(d[j]->d_name);
22722514Sdarrenr	}
22822514Sdarrenr}
22922514Sdarrenr
23022514Sdarrenr
23122514Sdarrenrvoid printreport(ss, num)
23222514Sdarrenripss_t	*ss;
23322514Sdarrenrint	num;
23422514Sdarrenr{
23522514Sdarrenr	struct	in_addr	ip;
23622514Sdarrenr	ipss_t	*sp;
23722514Sdarrenr	int	i, j, mask;
23822514Sdarrenr	u_long	ports;
23922514Sdarrenr
24022514Sdarrenr	printf("Hosts detected: %d\n", num);
24122514Sdarrenr	if (!num)
24222514Sdarrenr		return;
24322514Sdarrenr	for (i = 0; i < num; i++)
24422514Sdarrenr		printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
24522514Sdarrenr			countpbits(ss[i].ss_ports));
24622514Sdarrenr
24722514Sdarrenr	printf("--------------------------\n");
24822514Sdarrenr	for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
24922514Sdarrenr		ip.s_addr = ss[0].ss_ip.s_addr & mask;
25022514Sdarrenr		ports = ss[0].ss_ports;
25122514Sdarrenr		for (i = 1; i < num; i++) {
25222514Sdarrenr			sp = ss + i;
25322514Sdarrenr			if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
25422514Sdarrenr				printf("Netmask: 0x%08x\n", mask);
25522514Sdarrenr				printf("%s %d\n", inet_ntoa(ip),
25622514Sdarrenr					countpbits(ports));
25722514Sdarrenr				ip.s_addr = sp->ss_ip.s_addr & mask;
25822514Sdarrenr				ports = 0;
25922514Sdarrenr			}
26022514Sdarrenr			ports |= sp->ss_ports;
26122514Sdarrenr		}
26222514Sdarrenr		if (ports) {
26322514Sdarrenr			printf("Netmask: 0x%08x\n", mask);
26422514Sdarrenr			printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
26522514Sdarrenr		}
26622514Sdarrenr	}
26722514Sdarrenr}
26822514Sdarrenr
26922514Sdarrenr
27022514Sdarrenrcollectips()
27122514Sdarrenr{
27222514Sdarrenr	ipsd_t	*ips;
27322514Sdarrenr	ipss_t	*ss;
27422514Sdarrenr	int	i, num, nip, in, j, k;
27522514Sdarrenr
27622514Sdarrenr	for (i = 0; i < NPORTS; i++)
27722514Sdarrenr		nip += iphits[i]->sd_cnt;
27822514Sdarrenr
27922514Sdarrenr	ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
28022514Sdarrenr
28122514Sdarrenr	for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
28222514Sdarrenr		ips = iphits[i];
28322514Sdarrenr		for (j = 0; j < ips->sd_cnt; j++) {
28422514Sdarrenr			for (k = 0; k < num; k++)
28522514Sdarrenr				if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
28622514Sdarrenr					  sizeof(struct in_addr))) {
28722514Sdarrenr					ss[k].ss_hits += pweights[i];
28822514Sdarrenr					ss[k].ss_ports |= (1 << i);
28922514Sdarrenr					break;
29022514Sdarrenr				}
29122514Sdarrenr			if (k == num) {
29222514Sdarrenr				ss[num].ss_ip = ips->sd_hit[j].sh_ip;
29322514Sdarrenr				ss[num].ss_hits = pweights[i];
29422514Sdarrenr				ss[k].ss_ports |= (1 << i);
29522514Sdarrenr				num++;
29622514Sdarrenr			}
29722514Sdarrenr		}
29822514Sdarrenr	}
29922514Sdarrenr
30022514Sdarrenr	qsort(ss, num, sizeof(*ss), ssipcmp);
30122514Sdarrenr
30222514Sdarrenr	printreport(ss, num);
30322514Sdarrenr}
30422514Sdarrenr
30522514Sdarrenr
30622514Sdarrenrmain(argc, argv)
30722514Sdarrenrint	argc;
30822514Sdarrenrchar	*argv[];
30922514Sdarrenr{
31022514Sdarrenr	char	c, *name =  argv[0], *dir = NULL;
31122514Sdarrenr	int	fd;
31222514Sdarrenr
31322514Sdarrenr	setuphits();
31422514Sdarrenr	dir = dir ? dir : ".";
31522514Sdarrenr	readfiles(dir);
31622514Sdarrenr	collectips();
31722514Sdarrenr}
318