1/*	$FreeBSD$	*/
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 <malloc.h>
13#include <netdb.h>
14#include <string.h>
15#include <sys/dir.h>
16#include <sys/types.h>
17#include <sys/time.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20#include <netinet/in_systm.h>
21#include <netinet/ip.h>
22#include <netinet/tcp.h>
23#include <netinet/udp.h>
24#include <netinet/ip_icmp.h>
25#ifndef	linux
26#include <netinet/ip_var.h>
27#include <netinet/tcpip.h>
28#endif
29#include "ip_compat.h"
30#ifdef	linux
31#include <linux/sockios.h>
32#include "tcpip.h"
33#endif
34#include "ipsd.h"
35
36#ifndef	lint
37static const char sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
38static const char rcsid[] = "@(#)$Id$";
39#endif
40
41extern	char	*optarg;
42extern	int	optind;
43
44#define	NPORTS	21
45
46u_short	defports[NPORTS] = {
47		7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
48		123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
49	};
50u_short	pweights[NPORTS] = {
51		1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
52		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
53	};
54
55ipsd_t	*iphits[NPORTS];
56int	pkts;
57
58
59int	ipcmp(sh1, sh2)
60	sdhit_t	*sh1, *sh2;
61{
62	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
63}
64
65
66int	ssipcmp(sh1, sh2)
67	ipss_t	*sh1, *sh2;
68{
69	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
70}
71
72
73int countpbits(num)
74	u_long	num;
75{
76	int	i, j;
77
78	for (i = 1, j = 0; i; i <<= 1)
79		if (num & i)
80			j++;
81	return j;
82}
83
84
85/*
86 * Check to see if we've already received a packet from this host for this
87 * port.
88 */
89int	findhit(ihp, src, dport)
90	ipsd_t	*ihp;
91	struct	in_addr	src;
92	u_short	dport;
93{
94	int	i, j, k;
95	sdhit_t	*sh;
96
97	sh = NULL;
98
99	if (ihp->sd_sz == 4) {
100		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
101			if (src.s_addr == sh->sh_ip.s_addr)
102				return 1;
103	} else {
104		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
105			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
106			if (!k)
107				return 1;
108			else if (k < 0)
109				i -= j;
110			else
111				i += j;
112		}
113	}
114	return 0;
115}
116
117
118/*
119 * Search for port number amongst the sorted array of targets we're
120 * interested in.
121 */
122int	detect(srcip, dport, date)
123	struct	in_addr	srcip;
124	u_short	dport;
125	time_t	date;
126{
127	ipsd_t	*ihp;
128	sdhit_t	*sh;
129	int	i, j, k;
130
131	for (i = 10, j = 4; j >= 0; j--) {
132		k = dport - defports[i];
133		if (!k) {
134			ihp = iphits[i];
135			if (findhit(ihp, srcip, dport))
136				return 0;
137			sh = ihp->sd_hit + ihp->sd_cnt;
138			sh->sh_date = date;
139			sh->sh_ip = srcip;
140			if (++ihp->sd_cnt == ihp->sd_sz)
141			{
142				ihp->sd_sz += 8;
143				sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
144				ihp->sd_hit = sh;
145			}
146			qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
147			return 0;
148		}
149		if (k < 0)
150			i -= j;
151		else
152			i += j;
153	}
154	return -1;
155}
156
157
158/*
159 * Allocate initial storage for hosts
160 */
161setuphits()
162{
163	int	i;
164
165	for (i = 0; i < NPORTS; i++) {
166		if (iphits[i]) {
167			if (iphits[i]->sd_hit)
168				free(iphits[i]->sd_hit);
169			free(iphits[i]);
170		}
171		iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
172		iphits[i]->sd_port = defports[i];
173		iphits[i]->sd_cnt = 0;
174		iphits[i]->sd_sz = 4;
175		iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
176	}
177}
178
179
180/*
181 * Write statistics out to a file
182 */
183addfile(file)
184	char	*file;
185{
186	ipsd_t	ipsd, *ips = &ipsd;
187	sdhit_t	hit, *hp;
188	char	fname[32];
189	int	i, fd, sz;
190
191	if ((fd = open(file, O_RDONLY)) == -1) {
192		perror("open");
193		return;
194	}
195
196	printf("opened %s\n", file);
197	do {
198		if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
199			break;
200		sz = ips->sd_sz * sizeof(*hp);
201		hp = (sdhit_t *)malloc(sz);
202		if (read(fd, hp, sz) != sz)
203			break;
204		for (i = 0; i < ips->sd_cnt; i++)
205			detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
206	} while (1);
207	(void) close(fd);
208}
209
210
211readfiles(dir)
212	char *dir;
213{
214	struct	direct	**d;
215	int	i, j;
216
217	d = NULL;
218	i = scandir(dir, &d, NULL, NULL);
219
220	for (j = 0; j < i; j++) {
221		if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
222			continue;
223		addfile(d[j]->d_name);
224	}
225}
226
227
228void printreport(ss, num)
229	ipss_t	*ss;
230	int	num;
231{
232	struct	in_addr	ip;
233	ipss_t	*sp;
234	int	i, j, mask;
235	u_long	ports;
236
237	printf("Hosts detected: %d\n", num);
238	if (!num)
239		return;
240	for (i = 0; i < num; i++)
241		printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
242			countpbits(ss[i].ss_ports));
243
244	printf("--------------------------\n");
245	for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
246		ip.s_addr = ss[0].ss_ip.s_addr & mask;
247		ports = ss[0].ss_ports;
248		for (i = 1; i < num; i++) {
249			sp = ss + i;
250			if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
251				printf("Netmask: 0x%08x\n", mask);
252				printf("%s %d\n", inet_ntoa(ip),
253					countpbits(ports));
254				ip.s_addr = sp->ss_ip.s_addr & mask;
255				ports = 0;
256			}
257			ports |= sp->ss_ports;
258		}
259		if (ports) {
260			printf("Netmask: 0x%08x\n", mask);
261			printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
262		}
263	}
264}
265
266
267collectips()
268{
269	ipsd_t	*ips;
270	ipss_t	*ss;
271	int	i, num, nip, in, j, k;
272
273	for (i = 0; i < NPORTS; i++)
274		nip += iphits[i]->sd_cnt;
275
276	ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
277
278	for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
279		ips = iphits[i];
280		for (j = 0; j < ips->sd_cnt; j++) {
281			for (k = 0; k < num; k++)
282				if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
283					  sizeof(struct in_addr))) {
284					ss[k].ss_hits += pweights[i];
285					ss[k].ss_ports |= (1 << i);
286					break;
287				}
288			if (k == num) {
289				ss[num].ss_ip = ips->sd_hit[j].sh_ip;
290				ss[num].ss_hits = pweights[i];
291				ss[k].ss_ports |= (1 << i);
292				num++;
293			}
294		}
295	}
296
297	qsort(ss, num, sizeof(*ss), ssipcmp);
298
299	printreport(ss, num);
300}
301
302
303main(argc, argv)
304	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