xref: /netbsd-src/external/bsd/ipf/dist/ipsd/ipsdr.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /*	$NetBSD: ipsdr.c,v 1.2 2012/07/22 14:27:35 darrenr Exp $	*/
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
37 static const char sccsid[] = "@(#)ipsdr.c	1.3 12/3/95 (C)1995 Darren Reed";
38 static const char rcsid[] = "@(#)Id: ipsdr.c,v 1.1.1.2 2012/07/22 13:44:34 darrenr Exp $";
39 #endif
40 
41 extern	char	*optarg;
42 extern	int	optind;
43 
44 #define	NPORTS	21
45 
46 u_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 	};
50 u_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 
55 ipsd_t	*iphits[NPORTS];
56 int	pkts;
57 
58 
59 int	ipcmp(sh1, sh2)
60 	sdhit_t	*sh1, *sh2;
61 {
62 	return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
63 }
64 
65 
66 int	ssipcmp(sh1, sh2)
67 	ipss_t	*sh1, *sh2;
68 {
69 	return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
70 }
71 
72 
73 int 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  */
89 int	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  */
122 int	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  */
161 setuphits()
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  */
183 addfile(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 
211 readfiles(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 
228 void 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 
267 collectips()
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 
303 main(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