Fix exec from setuid/setgid binaries
[dragonfly.git] / contrib / ipfilter / ipsd / ipsd.c
blob261ad89985c1461ffebf778cb6432f1809fa55ae
1 /*
2 * (C)opyright 1995-1998 Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * The author of this software makes no garuntee about the
7 * performance of this package or its suitability to fulfill any purpose.
9 */
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <signal.h>
13 #include <stdlib.h>
14 #include <netdb.h>
15 #include <string.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"
36 #ifndef lint
37 static const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed";
38 static const char rcsid[] = "@(#)$Id: ipsd.c,v 2.1.4.1 2001/06/26 10:43:21 darrenr Exp $";
39 #endif
41 extern char *optarg;
42 extern int optind;
44 #ifdef linux
45 char default_device[] = "eth0";
46 #else
47 # ifdef sun
48 char default_device[] = "le0";
49 # else
50 # ifdef ultrix
51 char default_device[] = "ln0";
52 # else
53 char default_device[] = "lan0";
54 # endif
55 # endif
56 #endif
58 #define NPORTS 21
60 u_short defports[NPORTS] = {
61 7, 9, 20, 21, 23, 25, 53, 69, 79, 111,
62 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0
65 ipsd_t *iphits[NPORTS];
66 int writes = 0;
69 int ipcmp(sh1, sh2)
70 sdhit_t *sh1, *sh2;
72 return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
77 * Check to see if we've already received a packet from this host for this
78 * port.
80 int findhit(ihp, src, dport)
81 ipsd_t *ihp;
82 struct in_addr src;
83 u_short dport;
85 int i, j, k;
86 sdhit_t *sh;
88 sh = NULL;
90 if (ihp->sd_sz == 4) {
91 for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
92 if (src.s_addr == sh->sh_ip.s_addr)
93 return 1;
94 } else {
95 for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
96 k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
97 if (!k)
98 return 1;
99 else if (k < 0)
100 i -= j;
101 else
102 i += j;
105 return 0;
110 * Search for port number amongst the sorted array of targets we're
111 * interested in.
113 int detect(ip, tcp)
114 ip_t *ip;
115 tcphdr_t *tcp;
117 ipsd_t *ihp;
118 sdhit_t *sh;
119 int i, j, k;
121 for (i = 10, j = 4; j >= 0; j--) {
122 k = tcp->th_dport - defports[i];
123 if (!k) {
124 ihp = iphits[i];
125 if (findhit(ihp, ip->ip_src, tcp->th_dport))
126 return 0;
127 sh = ihp->sd_hit + ihp->sd_cnt;
128 sh->sh_date = time(NULL);
129 sh->sh_ip.s_addr = ip->ip_src.s_addr;
130 if (++ihp->sd_cnt == ihp->sd_sz)
132 ihp->sd_sz += 8;
133 sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
134 ihp->sd_hit = sh;
136 qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
137 return 0;
139 if (k < 0)
140 i -= j;
141 else
142 i += j;
144 return -1;
149 * Allocate initial storage for hosts
151 setuphits()
153 int i;
155 for (i = 0; i < NPORTS; i++) {
156 if (iphits[i]) {
157 if (iphits[i]->sd_hit)
158 free(iphits[i]->sd_hit);
159 free(iphits[i]);
161 iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
162 iphits[i]->sd_port = defports[i];
163 iphits[i]->sd_cnt = 0;
164 iphits[i]->sd_sz = 4;
165 iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
171 * cleanup exits
173 waiter()
175 wait(0);
180 * Write statistics out to a file
182 writestats(nwrites)
183 int nwrites;
185 ipsd_t **ipsd, *ips;
186 char fname[32];
187 int i, fd;
189 (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites);
190 fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644);
191 for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) {
192 ips = *ipsd;
193 if (ips->sd_cnt) {
194 write(fd, ips, sizeof(ipsd_t));
195 write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz);
198 (void) close(fd);
199 exit(0);
203 void writenow()
205 signal(SIGCHLD, waiter);
206 switch (fork())
208 case 0 :
209 writestats(writes);
210 exit(0);
211 case -1 :
212 perror("vfork");
213 break;
214 default :
215 writes++;
216 setuphits();
217 break;
222 void usage(prog)
223 char *prog;
225 fprintf(stderr, "Usage: %s [-d device]\n", prog);
226 exit(1);
230 void detecthits(fd, writecount)
231 int fd, writecount;
233 struct in_addr ip;
234 int hits = 0;
236 while (1) {
237 hits += readloop(fd, ip);
238 if (hits > writecount) {
239 writenow();
240 hits = 0;
246 main(argc, argv)
247 int argc;
248 char *argv[];
250 char *name = argv[0], *dev = NULL;
251 int fd, writeafter = 10000, angelic = 0, c;
253 while ((c = getopt(argc, argv, "ad:n:")) != -1)
254 switch (c)
256 case 'a' :
257 angelic = 1;
258 break;
259 case 'd' :
260 dev = optarg;
261 break;
262 case 'n' :
263 writeafter = atoi(optarg);
264 break;
265 default :
266 fprintf(stderr, "Unknown option \"%c\"\n", c);
267 usage(name);
270 bzero(iphits, sizeof(iphits));
271 setuphits();
273 if (!dev)
274 dev = default_device;
275 printf("Device: %s\n", dev);
276 fd = initdevice(dev, 60);
278 if (!angelic) {
279 switch (fork())
281 case 0 :
282 (void) close(0);
283 (void) close(1);
284 (void) close(2);
285 (void) setpgrp(0, getpgrp());
286 (void) setsid();
287 break;
288 case -1:
289 perror("fork");
290 exit(-1);
291 default:
292 exit(0);
295 signal(SIGUSR1, writenow);
296 detecthits(fd, writeafter);