extern int errno considered harmful.
[dragonfly.git] / contrib / ipfilter / ipsd / ipsdr.c
1 /*
2  * (C)opyright 1995-1998 Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  *   The author of this software makes no garuntee about the
7  * performance of this package or its suitability to fulfill any purpose.
8  *
9  */
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <signal.h>
13 #include <malloc.h>
14 #include <netdb.h>
15 #include <string.h>
16 #include <sys/dir.h>
17 #include <sys/types.h>
18 #include <sys/time.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <netinet/in_systm.h>
22 #include <netinet/ip.h>
23 #include <netinet/tcp.h>
24 #include <netinet/udp.h>
25 #include <netinet/ip_icmp.h>
26 #ifndef linux
27 #include <netinet/ip_var.h>
28 #include <netinet/tcpip.h>
29 #endif
30 #include "ip_compat.h"
31 #ifdef  linux
32 #include <linux/sockios.h>
33 #include "tcpip.h"
34 #endif
35 #include "ipsd.h"
36
37 #ifndef lint
38 static const char sccsid[] = "@(#)ipsdr.c       1.3 12/3/95 (C)1995 Darren Reed";
39 static const char rcsid[] = "@(#)$Id: ipsdr.c,v 2.1.4.1 2001/06/26 10:43:21 darrenr Exp $";
40 #endif
41
42 extern  char    *optarg;
43 extern  int     optind;
44
45 #define NPORTS  21
46
47 u_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         };
51 u_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
56 ipsd_t  *iphits[NPORTS];
57 int     pkts;
58
59
60 int     ipcmp(sh1, sh2)
61 sdhit_t *sh1, *sh2;
62 {
63         return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
64 }
65
66
67 int     ssipcmp(sh1, sh2)
68 ipss_t  *sh1, *sh2;
69 {
70         return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
71 }
72
73
74 int countpbits(num)
75 u_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  */
90 int     findhit(ihp, src, dport)
91 ipsd_t  *ihp;
92 struct  in_addr src;
93 u_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  */
123 int     detect(srcip, dport, date)
124 struct  in_addr srcip;
125 u_short dport;
126 time_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  */
162 setuphits()
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  */
184 addfile(file)
185 char    *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
212 readfiles(dir)
213 char *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
229 void printreport(ss, num)
230 ipss_t  *ss;
231 int     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
268 collectips()
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
304 main(argc, argv)
305 int     argc;
306 char    *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 }