ipsdr.c revision 22514
190075Sobrien/*
2169689Skan * (C)opyright December 1995 Darren Reed.
3132718Skan *
490075Sobrien *   This software may be freely distributed as long as it is not altered
5132718Skan * in any way and that this messagge always accompanies it.
690075Sobrien *
7132718Skan *   The author of this software makes no garuntee about the
890075Sobrien * performance of this package or its suitability to fulfill any purpose.
990075Sobrien *
1090075Sobrien */
1190075Sobrien#include <stdio.h>
12132718Skan#include <fcntl.h>
1390075Sobrien#include <signal.h>
1490075Sobrien#include <malloc.h>
1590075Sobrien#include <netdb.h>
1690075Sobrien#include <string.h>
1790075Sobrien#include <sys/dir.h>
18132718Skan#include <sys/types.h>
19169689Skan#include <sys/time.h>
20169689Skan#include <sys/socket.h>
2190075Sobrien#include <netinet/in.h>
2290075Sobrien#include <netinet/in_systm.h>
2390075Sobrien#include <netinet/ip.h>
2490075Sobrien#include <netinet/tcp.h>
25117395Skan#include <netinet/udp.h>
26117395Skan#include <netinet/ip_icmp.h>
2790075Sobrien#ifndef	linux
2890075Sobrien#include <netinet/ip_var.h>
2990075Sobrien#include <netinet/tcpip.h>
3090075Sobrien#endif
31132718Skan#include "ip_compat.h"
3290075Sobrien#ifdef	linux
33132718Skan#include <linux/sockios.h>
34132718Skan#include "tcpip.h"
35132718Skan#endif
3690075Sobrien#include "ipsd.h"
37169689Skan
38169689Skan#ifndef	lint
39169689Skanstatic	char	sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
40169689Skan#endif
41169689Skan
42132718Skanextern	char	*optarg;
43132718Skanextern	int	optind;
44169689Skan
45132718Skan#define	NPORTS	21
46132718Skan
47132718Skanu_short	defports[NPORTS] = {
48132718Skan		7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
49169689Skan		123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
50132718Skan	};
51169689Skanu_short	pweights[NPORTS] = {
52169689Skan		1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
53169689Skan		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
54169689Skan	};
55132718Skan
56132718Skanipsd_t	*iphits[NPORTS];
57132718Skanint	pkts;
58169689Skan
5990075Sobrien
60132718Skanint	ipcmp(sh1, sh2)
61132718Skansdhit_t	*sh1, *sh2;
62132718Skan{
6390075Sobrien	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
64132718Skan}
65169689Skan
66132718Skan
6790075Sobrienint	ssipcmp(sh1, sh2)
68132718Skanipss_t	*sh1, *sh2;
69132718Skan{
70132718Skan	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
71169689Skan}
72132718Skan
73132718Skan
74132718Skanint countpbits(num)
75132718Skanu_long	num;
7690075Sobrien{
7790075Sobrien	int	i, j;
7890075Sobrien
7990075Sobrien	for (i = 1, j = 0; i; i <<= 1)
80132718Skan		if (num & i)
81132718Skan			j++;
82132718Skan	return j;
83132718Skan}
84132718Skan
8590075Sobrien
8690075Sobrien/*
87132718Skan * Check to see if we've already received a packet from this host for this
88132718Skan * port.
89169689Skan */
90132718Skanint	findhit(ihp, src, dport)
9190075Sobrienipsd_t	*ihp;
9290075Sobrienstruct	in_addr	src;
93132718Skanu_short	dport;
94132718Skan{
95132718Skan	int	i, j, k;
96132718Skan	sdhit_t	*sh;
97132718Skan
98132718Skan	sh = NULL;
99132718Skan
100132718Skan	if (ihp->sd_sz == 4) {
10190075Sobrien		for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
102132718Skan			if (src.s_addr == sh->sh_ip.s_addr)
103132718Skan				return 1;
104122180Skan	} else {
10590075Sobrien		for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
10690075Sobrien			k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
107132718Skan			if (!k)
10890075Sobrien				return 1;
109117395Skan			else if (k < 0)
110132718Skan				i -= j;
111169689Skan			else
112169689Skan				i += j;
113169689Skan		}
114169689Skan	}
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