ipsd.c revision 22514
1/* 2 * (C)opyright December 1995 Darren Reed. 3 * 4 * This software may be freely distributed as long as it is not altered 5 * in any way and that this messagge always accompanies it. 6 * 7 * The author of this software makes no garuntee about the 8 * performance of this package or its suitability to fulfill any purpose. 9 * 10 */ 11#include <stdio.h> 12#include <fcntl.h> 13#include <signal.h> 14#include <stdlib.h> 15#include <netdb.h> 16#include <string.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 38static char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; 39#endif 40 41extern char *optarg; 42extern int optind; 43 44#ifdef linux 45char default_device[] = "eth0"; 46#else 47# ifdef sun 48char default_device[] = "le0"; 49# else 50# ifdef ultrix 51char default_device[] = "ln0"; 52# else 53char default_device[] = "lan0"; 54# endif 55# endif 56#endif 57 58#define NPORTS 21 59 60u_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 63 }; 64 65ipsd_t *iphits[NPORTS]; 66int writes = 0; 67 68 69int ipcmp(sh1, sh2) 70sdhit_t *sh1, *sh2; 71{ 72 return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 73} 74 75 76/* 77 * Check to see if we've already received a packet from this host for this 78 * port. 79 */ 80int findhit(ihp, src, dport) 81ipsd_t *ihp; 82struct in_addr src; 83u_short dport; 84{ 85 int i, j, k; 86 sdhit_t *sh; 87 88 sh = NULL; 89 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; 103 } 104 } 105 return 0; 106} 107 108 109/* 110 * Search for port number amongst the sorted array of targets we're 111 * interested in. 112 */ 113int detect(ip, tcp) 114ip_t *ip; 115tcphdr_t *tcp; 116{ 117 ipsd_t *ihp; 118 sdhit_t *sh; 119 int i, j, k; 120 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) 131 { 132 ihp->sd_sz += 8; 133 sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 134 ihp->sd_hit = sh; 135 } 136 qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 137 return 0; 138 } 139 if (k < 0) 140 i -= j; 141 else 142 i += j; 143 } 144 return -1; 145} 146 147 148/* 149 * Allocate initial storage for hosts 150 */ 151setuphits() 152{ 153 int i; 154 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]); 160 } 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); 166 } 167} 168 169 170/* 171 * cleanup exits 172 */ 173waiter() 174{ 175 wait(0); 176} 177 178 179/* 180 * Write statistics out to a file 181 */ 182writestats(nwrites) 183int nwrites; 184{ 185 ipsd_t **ipsd, *ips; 186 char fname[32]; 187 int i, fd; 188 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); 196 } 197 } 198 (void) close(fd); 199 exit(0); 200} 201 202 203void writenow() 204{ 205 signal(SIGCHLD, waiter); 206 switch (fork()) 207 { 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; 218 } 219} 220 221 222void usage(prog) 223char *prog; 224{ 225 fprintf(stderr, "Usage: %s [-d device]\n", prog); 226 exit(1); 227} 228 229 230void detecthits(fd, writecount) 231int fd, writecount; 232{ 233 struct in_addr ip; 234 int hits = 0; 235 236 while (1) { 237 hits += readloop(fd, ip); 238 if (hits > writecount) { 239 writenow(); 240 hits = 0; 241 } 242 } 243} 244 245 246main(argc, argv) 247int argc; 248char *argv[]; 249{ 250 char c, *name = argv[0], *dev = NULL; 251 int fd, writeafter = 10000, angelic = 0; 252 253 while ((c = getopt(argc, argv, "ad:n:")) != -1) 254 switch (c) 255 { 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); 268 } 269 270 bzero(iphits, sizeof(iphits)); 271 setuphits(); 272 273 if (!dev) 274 dev = default_device; 275 printf("Device: %s\n", dev); 276 fd = initdevice(dev, 60); 277 278 if (!angelic) { 279 switch (fork()) 280 { 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); 293 } 294 } 295 signal(SIGUSR1, writenow); 296 detecthits(fd, writeafter); 297} 298