]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ipfilter/ipsd/ipsd.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ipfilter / ipsd / ipsd.c
1 /*      $FreeBSD$       */
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 <stdlib.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <netinet/in_systm.h>
20 #include <netinet/ip.h>
21 #include <netinet/tcp.h>
22 #include <netinet/udp.h>
23 #include <netinet/ip_icmp.h>
24 #ifndef linux
25 #include <netinet/ip_var.h>
26 #include <netinet/tcpip.h>
27 #endif
28 #include "ip_compat.h"
29 #ifdef  linux
30 #include <linux/sockios.h>
31 #include "tcpip.h"
32 #endif
33 #include "ipsd.h"
34
35 #ifndef lint
36 static const char sccsid[] = "@(#)ipsd.c        1.3 12/3/95 (C)1995 Darren Reed";
37 static const char rcsid[] = "@(#)$Id$";
38 #endif
39
40 extern  char    *optarg;
41 extern  int     optind;
42
43 #ifdef  linux
44 char    default_device[] = "eth0";
45 #else
46 # ifdef sun
47 char    default_device[] = "le0";
48 # else
49 #  ifdef        ultrix
50 char    default_device[] = "ln0";
51 #  else
52 char    default_device[] = "lan0";
53 #  endif
54 # endif
55 #endif
56
57 #define NPORTS  21
58
59 u_short defports[NPORTS] = {
60                   7,   9,  20,  21,  23,  25,  53,  69,  79, 111,
61                 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0
62         };
63
64 ipsd_t  *iphits[NPORTS];
65 int     writes = 0;
66
67
68 int     ipcmp(sh1, sh2)
69         sdhit_t *sh1, *sh2;
70 {
71         return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
72 }
73
74
75 /*
76  * Check to see if we've already received a packet from this host for this
77  * port.
78  */
79 int     findhit(ihp, src, dport)
80         ipsd_t  *ihp;
81         struct  in_addr src;
82         u_short dport;
83 {
84         int     i, j, k;
85         sdhit_t *sh;
86
87         sh = NULL;
88
89         if (ihp->sd_sz == 4) {
90                 for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
91                         if (src.s_addr == sh->sh_ip.s_addr)
92                                 return 1;
93         } else {
94                 for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
95                         k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
96                         if (!k)
97                                 return 1;
98                         else if (k < 0)
99                                 i -= j;
100                         else
101                                 i += j;
102                 }
103         }
104         return 0;
105 }
106
107
108 /*
109  * Search for port number amongst the sorted array of targets we're
110  * interested in.
111  */
112 int     detect(ip, tcp)
113         ip_t    *ip;
114         tcphdr_t        *tcp;
115 {
116         ipsd_t  *ihp;
117         sdhit_t *sh;
118         int     i, j, k;
119
120         for (i = 10, j = 4; j >= 0; j--) {
121                 k = tcp->th_dport - defports[i];
122                 if (!k) {
123                         ihp = iphits[i];
124                         if (findhit(ihp, ip->ip_src, tcp->th_dport))
125                                 return 0;
126                         sh = ihp->sd_hit + ihp->sd_cnt;
127                         sh->sh_date = time(NULL);
128                         sh->sh_ip.s_addr = ip->ip_src.s_addr;
129                         if (++ihp->sd_cnt == ihp->sd_sz)
130                         {
131                                 ihp->sd_sz += 8;
132                                 sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
133                                 ihp->sd_hit = sh;
134                         }
135                         qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
136                         return 0;
137                 }
138                 if (k < 0)
139                         i -= j;
140                 else
141                         i += j;
142         }
143         return -1;
144 }
145
146
147 /*
148  * Allocate initial storage for hosts
149  */
150 setuphits()
151 {
152         int     i;
153
154         for (i = 0; i < NPORTS; i++) {
155                 if (iphits[i]) {
156                         if (iphits[i]->sd_hit)
157                                 free(iphits[i]->sd_hit);
158                         free(iphits[i]);
159                 }
160                 iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
161                 iphits[i]->sd_port = defports[i];
162                 iphits[i]->sd_cnt = 0;
163                 iphits[i]->sd_sz = 4;
164                 iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
165         }
166 }
167
168
169 /*
170  * cleanup exits
171  */
172 waiter()
173 {
174         wait(0);
175 }
176
177
178 /*
179  * Write statistics out to a file
180  */
181 writestats(nwrites)
182         int     nwrites;
183 {
184         ipsd_t  **ipsd, *ips;
185         char    fname[32];
186         int     i, fd;
187
188         (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites);
189         fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644);
190         for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) {
191                 ips = *ipsd;
192                 if (ips->sd_cnt) {
193                         write(fd, ips, sizeof(ipsd_t));
194                         write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz);
195                 }
196         }
197         (void) close(fd);
198         exit(0);
199 }
200
201
202 void writenow()
203 {
204         signal(SIGCHLD, waiter);
205         switch (fork())
206         {
207         case 0 :
208                 writestats(writes);
209                 exit(0);
210         case -1 :
211                 perror("vfork");
212                 break;
213         default :
214                 writes++;
215                 setuphits();
216                 break;
217         }
218 }
219
220
221 void    usage(prog)
222         char    *prog;
223 {
224         fprintf(stderr, "Usage: %s [-d device]\n", prog);
225         exit(1);
226 }
227
228
229 void detecthits(fd, writecount)
230         int fd, writecount;
231 {
232         struct  in_addr ip;
233         int     hits = 0;
234
235         while (1) {
236                 hits += readloop(fd, ip);
237                 if (hits > writecount) {
238                         writenow();
239                         hits = 0;
240                 }
241         }
242 }
243
244
245 main(argc, argv)
246         int     argc;
247         char    *argv[];
248 {
249         char    *name =  argv[0], *dev = NULL;
250         int     fd, writeafter = 10000, angelic = 0, c;
251
252         while ((c = getopt(argc, argv, "ad:n:")) != -1)
253                 switch (c)
254                 {
255                 case 'a' :
256                         angelic = 1;
257                         break;
258                 case 'd' :
259                         dev = optarg;
260                         break;
261                 case 'n' :
262                         writeafter = atoi(optarg);
263                         break;
264                 default :
265                         fprintf(stderr, "Unknown option \"%c\"\n", c);
266                         usage(name);
267                 }
268
269         bzero(iphits, sizeof(iphits));
270         setuphits();
271
272         if (!dev)
273                 dev = default_device;
274         printf("Device:  %s\n", dev);
275         fd = initdevice(dev, 60);
276
277         if (!angelic) {
278                 switch (fork())
279                 {
280                 case 0 :
281                         (void) close(0);
282                         (void) close(1);
283                         (void) close(2);
284                         (void) setpgrp(0, getpgrp());
285                         (void) setsid();
286                         break;
287                 case -1:
288                         perror("fork");
289                         exit(-1);
290                 default:
291                         exit(0);
292                 }
293         }
294         signal(SIGUSR1, writenow);
295         detecthits(fd, writeafter);
296 }