Sync usage with man page.
[netbsd-mini2440.git] / dist / ipf / ipsd / ipsd.c
blob3d9ea4cdf568c602cbe796a90a80d1ca06586d08
1 /* $NetBSD$ */
3 /*
4 * (C)opyright 1995-1998 Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
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"
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: ipsd.c,v 2.2 2001/06/09 17:09:25 darrenr Exp";
38 #endif
40 extern char *optarg;
41 extern int optind;
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
57 #define NPORTS 21
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
64 ipsd_t *iphits[NPORTS];
65 int writes = 0;
68 int ipcmp(sh1, sh2)
69 sdhit_t *sh1, *sh2;
71 return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
76 * Check to see if we've already received a packet from this host for this
77 * port.
79 int findhit(ihp, src, dport)
80 ipsd_t *ihp;
81 struct in_addr src;
82 u_short dport;
84 int i, j, k;
85 sdhit_t *sh;
87 sh = NULL;
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;
104 return 0;
109 * Search for port number amongst the sorted array of targets we're
110 * interested in.
112 int detect(ip, tcp)
113 ip_t *ip;
114 tcphdr_t *tcp;
116 ipsd_t *ihp;
117 sdhit_t *sh;
118 int i, j, k;
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)
131 ihp->sd_sz += 8;
132 sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
133 ihp->sd_hit = sh;
135 qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
136 return 0;
138 if (k < 0)
139 i -= j;
140 else
141 i += j;
143 return -1;
148 * Allocate initial storage for hosts
150 setuphits()
152 int i;
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]);
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);
170 * cleanup exits
172 waiter()
174 wait(0);
179 * Write statistics out to a file
181 writestats(nwrites)
182 int nwrites;
184 ipsd_t **ipsd, *ips;
185 char fname[32];
186 int i, fd;
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);
197 (void) close(fd);
198 exit(0);
202 void writenow()
204 signal(SIGCHLD, waiter);
205 switch (fork())
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;
221 void usage(prog)
222 char *prog;
224 fprintf(stderr, "Usage: %s [-d device]\n", prog);
225 exit(1);
229 void detecthits(fd, writecount)
230 int fd, writecount;
232 struct in_addr ip;
233 int hits = 0;
235 while (1) {
236 hits += readloop(fd, ip);
237 if (hits > writecount) {
238 writenow();
239 hits = 0;
245 main(argc, argv)
246 int argc;
247 char *argv[];
249 char *name = argv[0], *dev = NULL;
250 int fd, writeafter = 10000, angelic = 0, c;
252 while ((c = getopt(argc, argv, "ad:n:")) != -1)
253 switch (c)
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);
269 bzero(iphits, sizeof(iphits));
270 setuphits();
272 if (!dev)
273 dev = default_device;
274 printf("Device: %s\n", dev);
275 fd = initdevice(dev, 60);
277 if (!angelic) {
278 switch (fork())
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);
294 signal(SIGUSR1, writenow);
295 detecthits(fd, writeafter);