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