ipsdr.c revision 255332
1248613Sdes/*	$FreeBSD: head/contrib/ipfilter/ipsd/ipsdr.c 255332 2013-09-06 23:11:19Z cy $	*/
2204861Sdes
3204861Sdes/*
4204861Sdes * (C)opyright 1995-1998 Darren Reed.
5204861Sdes *
6218767Sdes * See the IPFILTER.LICENCE file for details on licencing.
7218767Sdes *
8218767Sdes */
9218767Sdes#include <stdio.h>
10218767Sdes#include <fcntl.h>
11218767Sdes#include <signal.h>
12204861Sdes#include <malloc.h>
13204861Sdes#include <netdb.h>
14204861Sdes#include <string.h>
15204861Sdes#include <sys/dir.h>
16204861Sdes#include <sys/types.h>
17204861Sdes#include <sys/time.h>
18204861Sdes#include <sys/socket.h>
19204861Sdes#include <netinet/in.h>
20218767Sdes#include <netinet/in_systm.h>
21204861Sdes#include <netinet/ip.h>
22204861Sdes#include <netinet/tcp.h>
23204861Sdes#include <netinet/udp.h>
24204861Sdes#include <netinet/ip_icmp.h>
25248613Sdes#ifndef	linux
26248613Sdes#include <netinet/ip_var.h>
27204861Sdes#include <netinet/tcpip.h>
28218767Sdes#endif
29225825Sdes#include "ip_compat.h"
30214979Sdes#ifdef	linux
31214979Sdes#include <linux/sockios.h>
32214979Sdes#include "tcpip.h"
33214979Sdes#endif
34214979Sdes#include "ipsd.h"
35214979Sdes
36204861Sdes#ifndef	lint
37204861Sdesstatic const char sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
38214979Sdesstatic const char rcsid[] = "@(#)$Id$";
39218767Sdes#endif
40214979Sdes
41214979Sdesextern	char	*optarg;
42214979Sdesextern	int	optind;
43214979Sdes
44214979Sdes#define	NPORTS	21
45214979Sdes
46214979Sdesu_short	defports[NPORTS] = {
47214979Sdes		7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
48214979Sdes		123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
49214979Sdes	};
50214979Sdesu_short	pweights[NPORTS] = {
51214979Sdes		1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
52214979Sdes		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
53214979Sdes	};
54214979Sdes
55214979Sdesipsd_t	*iphits[NPORTS];
56214979Sdesint	pkts;
57214979Sdes
58214979Sdes
59214979Sdesint	ipcmp(sh1, sh2)
60214979Sdes	sdhit_t	*sh1, *sh2;
61214979Sdes{
62214979Sdes	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
63214979Sdes}
64214979Sdes
65214979Sdes
66214979Sdesint	ssipcmp(sh1, sh2)
67214979Sdes	ipss_t	*sh1, *sh2;
68214979Sdes{
69214979Sdes	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
70214979Sdes}
71214979Sdes
72214979Sdes
73214979Sdesint countpbits(num)
74214979Sdes	u_long	num;
75214979Sdes{
76214979Sdes	int	i, j;
77214979Sdes
78214979Sdes	for (i = 1, j = 0; i; i <<= 1)
79214979Sdes		if (num & i)
80214979Sdes			j++;
81214979Sdes	return j;
82214979Sdes}
83214979Sdes
84214979Sdes
85214979Sdes/*
86214979Sdes * Check to see if we've already received a packet from this host for this
87214979Sdes * port.
88214979Sdes */
89214979Sdesint	findhit(ihp, src, dport)
90214979Sdes	ipsd_t	*ihp;
91214979Sdes	struct	in_addr	src;
92214979Sdes	u_short	dport;
93214979Sdes{
94214979Sdes	int	i, j, k;
95214979Sdes	sdhit_t	*sh;
96214979Sdes
97214979Sdes	sh = NULL;
98214979Sdes
99214979Sdes	if (ihp->sd_sz == 4) {
100214979Sdes		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
101214979Sdes			if (src.s_addr == sh->sh_ip.s_addr)
102214979Sdes				return 1;
103214979Sdes	} else {
104214979Sdes		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
105214979Sdes			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
106214979Sdes			if (!k)
107214979Sdes				return 1;
108214979Sdes			else if (k < 0)
109214979Sdes				i -= j;
110214979Sdes			else
111214979Sdes				i += j;
112214979Sdes		}
113214979Sdes	}
114214979Sdes	return 0;
115214979Sdes}
116214979Sdes
117214979Sdes
118214979Sdes/*
119214979Sdes * Search for port number amongst the sorted array of targets we're
120214979Sdes * interested in.
121214979Sdes */
122214979Sdesint	detect(srcip, dport, date)
123214979Sdes	struct	in_addr	srcip;
124214979Sdes	u_short	dport;
125214979Sdes	time_t	date;
126214979Sdes{
127214979Sdes	ipsd_t	*ihp;
128214979Sdes	sdhit_t	*sh;
129214979Sdes	int	i, j, k;
130214979Sdes
131214979Sdes	for (i = 10, j = 4; j >= 0; j--) {
132214979Sdes		k = dport - defports[i];
133214979Sdes		if (!k) {
134214979Sdes			ihp = iphits[i];
135214979Sdes			if (findhit(ihp, srcip, dport))
136214979Sdes				return 0;
137214979Sdes			sh = ihp->sd_hit + ihp->sd_cnt;
138214979Sdes			sh->sh_date = date;
139214979Sdes			sh->sh_ip = srcip;
140214979Sdes			if (++ihp->sd_cnt == ihp->sd_sz)
141214979Sdes			{
142214979Sdes				ihp->sd_sz += 8;
143214979Sdes				sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
144214979Sdes				ihp->sd_hit = sh;
145214979Sdes			}
146214979Sdes			qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
147214979Sdes			return 0;
148214979Sdes		}
149214979Sdes		if (k < 0)
150214979Sdes			i -= j;
151214979Sdes		else
152204861Sdes			i += j;
153204861Sdes	}
154204861Sdes	return -1;
155204861Sdes}
156204861Sdes
157204861Sdes
158204861Sdes/*
159204861Sdes * Allocate initial storage for hosts
160204861Sdes */
161204861Sdessetuphits()
162204861Sdes{
163204861Sdes	int	i;
164204861Sdes
165218767Sdes	for (i = 0; i < NPORTS; i++) {
166204861Sdes		if (iphits[i]) {
167204861Sdes			if (iphits[i]->sd_hit)
168204861Sdes				free(iphits[i]->sd_hit);
169204861Sdes			free(iphits[i]);
170204861Sdes		}
171204861Sdes		iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
172204861Sdes		iphits[i]->sd_port = defports[i];
173204861Sdes		iphits[i]->sd_cnt = 0;
174204861Sdes		iphits[i]->sd_sz = 4;
175204861Sdes		iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
176204861Sdes	}
177204861Sdes}
178204861Sdes
179204861Sdes
180204861Sdes/*
181204861Sdes * Write statistics out to a file
182204861Sdes */
183204861Sdesaddfile(file)
184204861Sdes	char	*file;
185204861Sdes{
186204861Sdes	ipsd_t	ipsd, *ips = &ipsd;
187248613Sdes	sdhit_t	hit, *hp;
188204861Sdes	char	fname[32];
189204861Sdes	int	i, fd, sz;
190248613Sdes
191248613Sdes	if ((fd = open(file, O_RDONLY)) == -1) {
192204861Sdes		perror("open");
193204861Sdes		return;
194204861Sdes	}
195204861Sdes
196204861Sdes	printf("opened %s\n", file);
197248613Sdes	do {
198248613Sdes		if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
199248613Sdes			break;
200248613Sdes		sz = ips->sd_sz * sizeof(*hp);
201248613Sdes		hp = (sdhit_t *)malloc(sz);
202248613Sdes		if (read(fd, hp, sz) != sz)
203248613Sdes			break;
204248613Sdes		for (i = 0; i < ips->sd_cnt; i++)
205248613Sdes			detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
206248613Sdes	} while (1);
207248613Sdes	(void) close(fd);
208248613Sdes}
209248613Sdes
210248613Sdes
211248613Sdesreadfiles(dir)
212248613Sdes	char *dir;
213204861Sdes{
214204861Sdes	struct	direct	**d;
215204861Sdes	int	i, j;
216204861Sdes
217204861Sdes	d = NULL;
218204861Sdes	i = scandir(dir, &d, NULL, NULL);
219204861Sdes
220204861Sdes	for (j = 0; j < i; j++) {
221204861Sdes		if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
222204861Sdes			continue;
223204861Sdes		addfile(d[j]->d_name);
224204861Sdes	}
225204861Sdes}
226204861Sdes
227204861Sdes
228204861Sdesvoid printreport(ss, num)
229204861Sdes	ipss_t	*ss;
230204861Sdes	int	num;
231204861Sdes{
232204861Sdes	struct	in_addr	ip;
233204861Sdes	ipss_t	*sp;
234204861Sdes	int	i, j, mask;
235204861Sdes	u_long	ports;
236204861Sdes
237204861Sdes	printf("Hosts detected: %d\n", num);
238204861Sdes	if (!num)
239204861Sdes		return;
240204861Sdes	for (i = 0; i < num; i++)
241204861Sdes		printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
242204861Sdes			countpbits(ss[i].ss_ports));
243204861Sdes
244204861Sdes	printf("--------------------------\n");
245204861Sdes	for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
246204861Sdes		ip.s_addr = ss[0].ss_ip.s_addr & mask;
247204861Sdes		ports = ss[0].ss_ports;
248204861Sdes		for (i = 1; i < num; i++) {
249204861Sdes			sp = ss + i;
250214979Sdes			if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
251204861Sdes				printf("Netmask: 0x%08x\n", mask);
252204861Sdes				printf("%s %d\n", inet_ntoa(ip),
253204861Sdes					countpbits(ports));
254204861Sdes				ip.s_addr = sp->ss_ip.s_addr & mask;
255204861Sdes				ports = 0;
256204861Sdes			}
257214979Sdes			ports |= sp->ss_ports;
258218767Sdes		}
259218767Sdes		if (ports) {
260218767Sdes			printf("Netmask: 0x%08x\n", mask);
261218767Sdes			printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
262218767Sdes		}
263214979Sdes	}
264214979Sdes}
265214979Sdes
266214979Sdes
267214979Sdescollectips()
268214979Sdes{
269214979Sdes	ipsd_t	*ips;
270214979Sdes	ipss_t	*ss;
271214979Sdes	int	i, num, nip, in, j, k;
272214979Sdes
273214979Sdes	for (i = 0; i < NPORTS; i++)
274214979Sdes		nip += iphits[i]->sd_cnt;
275214979Sdes
276214979Sdes	ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
277214979Sdes
278214979Sdes	for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
279214979Sdes		ips = iphits[i];
280214979Sdes		for (j = 0; j < ips->sd_cnt; j++) {
281214979Sdes			for (k = 0; k < num; k++)
282218767Sdes				if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
283214979Sdes					  sizeof(struct in_addr))) {
284214979Sdes					ss[k].ss_hits += pweights[i];
285204861Sdes					ss[k].ss_ports |= (1 << i);
286214979Sdes					break;
287214979Sdes				}
288214979Sdes			if (k == num) {
289214979Sdes				ss[num].ss_ip = ips->sd_hit[j].sh_ip;
290214979Sdes				ss[num].ss_hits = pweights[i];
291214979Sdes				ss[k].ss_ports |= (1 << i);
292214979Sdes				num++;
293214979Sdes			}
294214979Sdes		}
295214979Sdes	}
296214979Sdes
297204861Sdes	qsort(ss, num, sizeof(*ss), ssipcmp);
298214979Sdes
299204861Sdes	printreport(ss, num);
300204861Sdes}
301204861Sdes
302204861Sdes
303204861Sdesmain(argc, argv)
304204861Sdes	int	argc;
305204861Sdes	char	*argv[];
306204861Sdes{
307204861Sdes	char	c, *name =  argv[0], *dir = NULL;
308204861Sdes	int	fd;
309204861Sdes
310204861Sdes	setuphits();
311204861Sdes	dir = dir ? dir : ".";
312204861Sdes	readfiles(dir);
313204861Sdes	collectips();
314204861Sdes}
315214979Sdes