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