ipsdr.c revision 285830
1263936Sbr/*	$FreeBSD: releng/10.2/contrib/ipfilter/ipsd/ipsdr.c 255332 2013-09-06 23:11:19Z cy $	*/
2263936Sbr
3263936Sbr/*
4263936Sbr * (C)opyright 1995-1998 Darren Reed.
5263936Sbr *
6263936Sbr * See the IPFILTER.LICENCE file for details on licencing.
7263936Sbr *
8263936Sbr */
9263936Sbr#include <stdio.h>
10263936Sbr#include <fcntl.h>
11263936Sbr#include <signal.h>
12263936Sbr#include <malloc.h>
13263936Sbr#include <netdb.h>
14263936Sbr#include <string.h>
15263936Sbr#include <sys/dir.h>
16263936Sbr#include <sys/types.h>
17263936Sbr#include <sys/time.h>
18263936Sbr#include <sys/socket.h>
19263936Sbr#include <netinet/in.h>
20263936Sbr#include <netinet/in_systm.h>
21263936Sbr#include <netinet/ip.h>
22263936Sbr#include <netinet/tcp.h>
23263936Sbr#include <netinet/udp.h>
24263936Sbr#include <netinet/ip_icmp.h>
25263936Sbr#ifndef	linux
26263936Sbr#include <netinet/ip_var.h>
27263936Sbr#include <netinet/tcpip.h>
28263936Sbr#endif
29263936Sbr#include "ip_compat.h"
30263936Sbr#ifdef	linux
31263936Sbr#include <linux/sockios.h>
32263936Sbr#include "tcpip.h"
33263936Sbr#endif
34263936Sbr#include "ipsd.h"
35263936Sbr
36263936Sbr#ifndef	lint
37263936Sbrstatic const char sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
38263936Sbrstatic const char rcsid[] = "@(#)$Id$";
39263936Sbr#endif
40263936Sbr
41263936Sbrextern	char	*optarg;
42263936Sbrextern	int	optind;
43263936Sbr
44263936Sbr#define	NPORTS	21
45263936Sbr
46263936Sbru_short	defports[NPORTS] = {
47263936Sbr		7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
48263936Sbr		123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
49263936Sbr	};
50263936Sbru_short	pweights[NPORTS] = {
51263936Sbr		1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
52263936Sbr		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
53263936Sbr	};
54263936Sbr
55263936Sbripsd_t	*iphits[NPORTS];
56263936Sbrint	pkts;
57263936Sbr
58263936Sbr
59263936Sbrint	ipcmp(sh1, sh2)
60263936Sbr	sdhit_t	*sh1, *sh2;
61263936Sbr{
62263936Sbr	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
63263936Sbr}
64263936Sbr
65263936Sbr
66263936Sbrint	ssipcmp(sh1, sh2)
67263936Sbr	ipss_t	*sh1, *sh2;
68263936Sbr{
69263936Sbr	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
70263936Sbr}
71263936Sbr
72263936Sbr
73263936Sbrint countpbits(num)
74263936Sbr	u_long	num;
75263936Sbr{
76263936Sbr	int	i, j;
77263936Sbr
78263936Sbr	for (i = 1, j = 0; i; i <<= 1)
79263936Sbr		if (num & i)
80263936Sbr			j++;
81263936Sbr	return j;
82263936Sbr}
83263936Sbr
84263936Sbr
85263936Sbr/*
86263936Sbr * Check to see if we've already received a packet from this host for this
87263936Sbr * port.
88263936Sbr */
89263936Sbrint	findhit(ihp, src, dport)
90263936Sbr	ipsd_t	*ihp;
91263936Sbr	struct	in_addr	src;
92263936Sbr	u_short	dport;
93263936Sbr{
94263936Sbr	int	i, j, k;
95263936Sbr	sdhit_t	*sh;
96263936Sbr
97263936Sbr	sh = NULL;
98263936Sbr
99263936Sbr	if (ihp->sd_sz == 4) {
100263936Sbr		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
101263936Sbr			if (src.s_addr == sh->sh_ip.s_addr)
102263936Sbr				return 1;
103263936Sbr	} else {
104263936Sbr		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
105263936Sbr			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
106263936Sbr			if (!k)
107263936Sbr				return 1;
108263936Sbr			else if (k < 0)
109263936Sbr				i -= j;
110263936Sbr			else
111263936Sbr				i += j;
112263936Sbr		}
113263936Sbr	}
114263936Sbr	return 0;
115263936Sbr}
116263936Sbr
117263936Sbr
118263936Sbr/*
119263936Sbr * Search for port number amongst the sorted array of targets we're
120263936Sbr * interested in.
121263936Sbr */
122263936Sbrint	detect(srcip, dport, date)
123263936Sbr	struct	in_addr	srcip;
124263936Sbr	u_short	dport;
125263936Sbr	time_t	date;
126263936Sbr{
127263936Sbr	ipsd_t	*ihp;
128263936Sbr	sdhit_t	*sh;
129263936Sbr	int	i, j, k;
130263936Sbr
131263936Sbr	for (i = 10, j = 4; j >= 0; j--) {
132263936Sbr		k = dport - defports[i];
133263936Sbr		if (!k) {
134263936Sbr			ihp = iphits[i];
135263936Sbr			if (findhit(ihp, srcip, dport))
136263936Sbr				return 0;
137263936Sbr			sh = ihp->sd_hit + ihp->sd_cnt;
138263936Sbr			sh->sh_date = date;
139263936Sbr			sh->sh_ip = srcip;
140263936Sbr			if (++ihp->sd_cnt == ihp->sd_sz)
141263936Sbr			{
142263936Sbr				ihp->sd_sz += 8;
143263936Sbr				sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
144263936Sbr				ihp->sd_hit = sh;
145263936Sbr			}
146263936Sbr			qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
147263936Sbr			return 0;
148263936Sbr		}
149263936Sbr		if (k < 0)
150263936Sbr			i -= j;
151263936Sbr		else
152263936Sbr			i += j;
153263936Sbr	}
154263936Sbr	return -1;
155263936Sbr}
156263936Sbr
157263936Sbr
158263936Sbr/*
159263936Sbr * Allocate initial storage for hosts
160263936Sbr */
161263936Sbrsetuphits()
162263936Sbr{
163263936Sbr	int	i;
164263936Sbr
165263936Sbr	for (i = 0; i < NPORTS; i++) {
166263936Sbr		if (iphits[i]) {
167263936Sbr			if (iphits[i]->sd_hit)
168263936Sbr				free(iphits[i]->sd_hit);
169263936Sbr			free(iphits[i]);
170263936Sbr		}
171263936Sbr		iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
172263936Sbr		iphits[i]->sd_port = defports[i];
173263936Sbr		iphits[i]->sd_cnt = 0;
174263936Sbr		iphits[i]->sd_sz = 4;
175263936Sbr		iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
176263936Sbr	}
177263936Sbr}
178263936Sbr
179263936Sbr
180263936Sbr/*
181263936Sbr * Write statistics out to a file
182263936Sbr */
183263936Sbraddfile(file)
184263936Sbr	char	*file;
185263936Sbr{
186263936Sbr	ipsd_t	ipsd, *ips = &ipsd;
187263936Sbr	sdhit_t	hit, *hp;
188263936Sbr	char	fname[32];
189263936Sbr	int	i, fd, sz;
190263936Sbr
191263936Sbr	if ((fd = open(file, O_RDONLY)) == -1) {
192263936Sbr		perror("open");
193263936Sbr		return;
194263936Sbr	}
195263936Sbr
196263936Sbr	printf("opened %s\n", file);
197263936Sbr	do {
198263936Sbr		if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
199263936Sbr			break;
200263936Sbr		sz = ips->sd_sz * sizeof(*hp);
201263936Sbr		hp = (sdhit_t *)malloc(sz);
202263936Sbr		if (read(fd, hp, sz) != sz)
203263936Sbr			break;
204263936Sbr		for (i = 0; i < ips->sd_cnt; i++)
205263936Sbr			detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
206263936Sbr	} while (1);
207263936Sbr	(void) close(fd);
208263936Sbr}
209263936Sbr
210263936Sbr
211263936Sbrreadfiles(dir)
212263936Sbr	char *dir;
213263936Sbr{
214263936Sbr	struct	direct	**d;
215263936Sbr	int	i, j;
216263936Sbr
217263936Sbr	d = NULL;
218263936Sbr	i = scandir(dir, &d, NULL, NULL);
219263936Sbr
220263936Sbr	for (j = 0; j < i; j++) {
221263936Sbr		if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
222263936Sbr			continue;
223263936Sbr		addfile(d[j]->d_name);
224263936Sbr	}
225263936Sbr}
226263936Sbr
227263936Sbr
228263936Sbrvoid printreport(ss, num)
229263936Sbr	ipss_t	*ss;
230263936Sbr	int	num;
231263936Sbr{
232263936Sbr	struct	in_addr	ip;
233263936Sbr	ipss_t	*sp;
234263936Sbr	int	i, j, mask;
235263936Sbr	u_long	ports;
236263936Sbr
237263936Sbr	printf("Hosts detected: %d\n", num);
238263936Sbr	if (!num)
239263936Sbr		return;
240263936Sbr	for (i = 0; i < num; i++)
241263936Sbr		printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
242263936Sbr			countpbits(ss[i].ss_ports));
243263936Sbr
244263936Sbr	printf("--------------------------\n");
245263936Sbr	for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
246263936Sbr		ip.s_addr = ss[0].ss_ip.s_addr & mask;
247263936Sbr		ports = ss[0].ss_ports;
248263936Sbr		for (i = 1; i < num; i++) {
249263936Sbr			sp = ss + i;
250263936Sbr			if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
251263936Sbr				printf("Netmask: 0x%08x\n", mask);
252263936Sbr				printf("%s %d\n", inet_ntoa(ip),
253263936Sbr					countpbits(ports));
254263936Sbr				ip.s_addr = sp->ss_ip.s_addr & mask;
255263936Sbr				ports = 0;
256263936Sbr			}
257263936Sbr			ports |= sp->ss_ports;
258263936Sbr		}
259263936Sbr		if (ports) {
260263936Sbr			printf("Netmask: 0x%08x\n", mask);
261263936Sbr			printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
262263936Sbr		}
263263936Sbr	}
264263936Sbr}
265263936Sbr
266263936Sbr
267263936Sbrcollectips()
268263936Sbr{
269263936Sbr	ipsd_t	*ips;
270263936Sbr	ipss_t	*ss;
271263936Sbr	int	i, num, nip, in, j, k;
272263936Sbr
273263936Sbr	for (i = 0; i < NPORTS; i++)
274263936Sbr		nip += iphits[i]->sd_cnt;
275263936Sbr
276263936Sbr	ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
277263936Sbr
278263936Sbr	for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
279263936Sbr		ips = iphits[i];
280263936Sbr		for (j = 0; j < ips->sd_cnt; j++) {
281263936Sbr			for (k = 0; k < num; k++)
282263936Sbr				if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
283263936Sbr					  sizeof(struct in_addr))) {
284263936Sbr					ss[k].ss_hits += pweights[i];
285263936Sbr					ss[k].ss_ports |= (1 << i);
286263936Sbr					break;
287263936Sbr				}
288263936Sbr			if (k == num) {
289263936Sbr				ss[num].ss_ip = ips->sd_hit[j].sh_ip;
290263936Sbr				ss[num].ss_hits = pweights[i];
291263936Sbr				ss[k].ss_ports |= (1 << i);
292263936Sbr				num++;
293263936Sbr			}
294263936Sbr		}
295263936Sbr	}
296263936Sbr
297263936Sbr	qsort(ss, num, sizeof(*ss), ssipcmp);
298263936Sbr
299263936Sbr	printreport(ss, num);
300263936Sbr}
301263936Sbr
302263936Sbr
303263936Sbrmain(argc, argv)
304263936Sbr	int	argc;
305	char	*argv[];
306{
307	char	c, *name =  argv[0], *dir = NULL;
308	int	fd;
309
310	setuphits();
311	dir = dir ? dir : ".";
312	readfiles(dir);
313	collectips();
314}
315