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