ipsd.c revision 31183
1114402Sru/* 2114402Sru * (C)opyright 1995-1997 Darren Reed. 3114402Sru * 4114402Sru * Redistribution and use in source and binary forms are permitted 5114402Sru * provided that this notice is preserved and due credit is given 6114402Sru * to the original author and the contributors. 7114402Sru * 8114402Sru * The author of this software makes no garuntee about the 9114402Sru * performance of this package or its suitability to fulfill any purpose. 10114402Sru * 11114402Sru */ 12114402Sru#include <stdio.h> 13114402Sru#include <fcntl.h> 14114402Sru#include <signal.h> 15114402Sru#include <stdlib.h> 16114402Sru#include <netdb.h> 17114402Sru#include <string.h> 18114402Sru#include <sys/types.h> 19151497Sru#include <sys/time.h> 20114402Sru#include <sys/socket.h> 21114402Sru#include <netinet/in.h> 22114402Sru#include <netinet/in_systm.h> 23114402Sru#include <netinet/ip.h> 24114402Sru#include <netinet/tcp.h> 25114402Sru#include <netinet/udp.h> 26114402Sru#include <netinet/ip_icmp.h> 27114402Sru#ifndef linux 28114402Sru#include <netinet/ip_var.h> 29114402Sru#include <netinet/tcpip.h> 30114402Sru#endif 31114402Sru#include "ip_compat.h" 32114402Sru#ifdef linux 33114402Sru#include <linux/sockios.h> 34114402Sru#include "tcpip.h" 35114402Sru#endif 36114402Sru#include "ipsd.h" 37114402Sru 38114402Sru#ifndef lint 39114402Srustatic const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; 40114402Srustatic const char rcsid[] = "@(#)$Id: ipsd.c,v 2.0.2.4 1997/09/28 07:13:17 darrenr Exp $"; 41114402Sru#endif 42114402Sru 43114402Sruextern char *optarg; 44114402Sruextern int optind; 45114402Sru 46114402Sru#ifdef linux 47114402Sruchar default_device[] = "eth0"; 48114402Sru#else 49114402Sru# ifdef sun 50114402Sruchar default_device[] = "le0"; 51114402Sru# else 52114402Sru# ifdef ultrix 53114402Sruchar default_device[] = "ln0"; 54114402Sru# else 55114402Sruchar default_device[] = "lan0"; 56114402Sru# endif 57114402Sru# endif 58114402Sru#endif 59114402Sru 60114402Sru#define NPORTS 21 61114402Sru 62114402Sruu_short defports[NPORTS] = { 63114402Sru 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 64114402Sru 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0 65114402Sru }; 66114402Sru 67114402Sruipsd_t *iphits[NPORTS]; 68114402Sruint writes = 0; 69114402Sru 70114402Sru 71114402Sruint ipcmp(sh1, sh2) 72114402Srusdhit_t *sh1, *sh2; 73114402Sru{ 74114402Sru return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 75114402Sru} 76114402Sru 77114402Sru 78114402Sru/* 79114402Sru * Check to see if we've already received a packet from this host for this 80114402Sru * port. 81114402Sru */ 82114402Sruint findhit(ihp, src, dport) 83114402Sruipsd_t *ihp; 84114402Srustruct in_addr src; 85114402Sruu_short dport; 86114402Sru{ 87114402Sru int i, j, k; 88114402Sru sdhit_t *sh; 89114402Sru 90114402Sru sh = NULL; 91114402Sru 92114402Sru if (ihp->sd_sz == 4) { 93114402Sru for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 94114402Sru if (src.s_addr == sh->sh_ip.s_addr) 95114402Sru return 1; 96114402Sru } else { 97114402Sru for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 98114402Sru k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 99114402Sru if (!k) 100114402Sru return 1; 101114402Sru else if (k < 0) 102114402Sru i -= j; 103114402Sru else 104114402Sru i += j; 105114402Sru } 106114402Sru } 107114402Sru return 0; 108114402Sru} 109114402Sru 110114402Sru 111114402Sru/* 112114402Sru * Search for port number amongst the sorted array of targets we're 113114402Sru * interested in. 114114402Sru */ 115114402Sruint detect(ip, tcp) 116114402Sruip_t *ip; 117114402Srutcphdr_t *tcp; 118114402Sru{ 119114402Sru ipsd_t *ihp; 120114402Sru sdhit_t *sh; 121114402Sru int i, j, k; 122114402Sru 123114402Sru for (i = 10, j = 4; j >= 0; j--) { 124114402Sru k = tcp->th_dport - defports[i]; 125114402Sru if (!k) { 126114402Sru ihp = iphits[i]; 127114402Sru if (findhit(ihp, ip->ip_src, tcp->th_dport)) 128114402Sru return 0; 129114402Sru sh = ihp->sd_hit + ihp->sd_cnt; 130114402Sru sh->sh_date = time(NULL); 131114402Sru sh->sh_ip.s_addr = ip->ip_src.s_addr; 132114402Sru if (++ihp->sd_cnt == ihp->sd_sz) 133114402Sru { 134114402Sru ihp->sd_sz += 8; 135114402Sru sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 136114402Sru ihp->sd_hit = sh; 137114402Sru } 138114402Sru qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 139114402Sru return 0; 140114402Sru } 141114402Sru if (k < 0) 142114402Sru i -= j; 143114402Sru else 144114402Sru i += j; 145114402Sru } 146114402Sru return -1; 147114402Sru} 148114402Sru 149114402Sru 150114402Sru/* 151114402Sru * Allocate initial storage for hosts 152114402Sru */ 153114402Srusetuphits() 154114402Sru{ 155114402Sru int i; 156114402Sru 157114402Sru for (i = 0; i < NPORTS; i++) { 158114402Sru if (iphits[i]) { 159114402Sru if (iphits[i]->sd_hit) 160114402Sru free(iphits[i]->sd_hit); 161114402Sru free(iphits[i]); 162114402Sru } 163114402Sru iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 164114402Sru iphits[i]->sd_port = defports[i]; 165114402Sru iphits[i]->sd_cnt = 0; 166114402Sru iphits[i]->sd_sz = 4; 167114402Sru iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 168114402Sru } 169114402Sru} 170114402Sru 171114402Sru 172114402Sru/* 173114402Sru * cleanup exits 174114402Sru */ 175114402Sruwaiter() 176114402Sru{ 177114402Sru wait(0); 178114402Sru} 179114402Sru 180114402Sru 181114402Sru/* 182114402Sru * Write statistics out to a file 183114402Sru */ 184114402Sruwritestats(nwrites) 185114402Sruint nwrites; 186114402Sru{ 187114402Sru ipsd_t **ipsd, *ips; 188114402Sru char fname[32]; 189114402Sru int i, fd; 190114402Sru 191114402Sru (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites); 192114402Sru fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 193114402Sru for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) { 194114402Sru ips = *ipsd; 195114402Sru if (ips->sd_cnt) { 196114402Sru write(fd, ips, sizeof(ipsd_t)); 197114402Sru write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz); 198114402Sru } 199114402Sru } 200114402Sru (void) close(fd); 201114402Sru exit(0); 202114402Sru} 203114402Sru 204114402Sru 205114402Sruvoid writenow() 206114402Sru{ 207114402Sru signal(SIGCHLD, waiter); 208114402Sru switch (fork()) 209114402Sru { 210114402Sru case 0 : 211114402Sru writestats(writes); 212114402Sru exit(0); 213114402Sru case -1 : 214114402Sru perror("vfork"); 215114402Sru break; 216114402Sru default : 217114402Sru writes++; 218114402Sru setuphits(); 219114402Sru break; 220114402Sru } 221114402Sru} 222114402Sru 223114402Sru 224114402Sruvoid usage(prog) 225114402Sruchar *prog; 226114402Sru{ 227114402Sru fprintf(stderr, "Usage: %s [-d device]\n", prog); 228114402Sru exit(1); 229114402Sru} 230114402Sru 231114402Sru 232114402Sruvoid detecthits(fd, writecount) 233114402Sruint fd, writecount; 234114402Sru{ 235114402Sru struct in_addr ip; 236114402Sru int hits = 0; 237114402Sru 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} 300