ipsd.c revision 22514
1223637Sbz/* 2126258Smlaier * (C)opyright December 1995 Darren Reed. 3126258Smlaier * 4126258Smlaier * This software may be freely distributed as long as it is not altered 5223637Sbz * in any way and that this messagge always accompanies it. 6126258Smlaier * 7126258Smlaier * The author of this software makes no garuntee about the 8126258Smlaier * performance of this package or its suitability to fulfill any purpose. 9126258Smlaier * 10126258Smlaier */ 11126258Smlaier#include <stdio.h> 12126258Smlaier#include <fcntl.h> 13126258Smlaier#include <signal.h> 14126258Smlaier#include <stdlib.h> 15126258Smlaier#include <netdb.h> 16126258Smlaier#include <string.h> 17126258Smlaier#include <sys/types.h> 18126258Smlaier#include <sys/time.h> 19126258Smlaier#include <sys/socket.h> 20126258Smlaier#include <netinet/in.h> 21126258Smlaier#include <netinet/in_systm.h> 22126258Smlaier#include <netinet/ip.h> 23126258Smlaier#include <netinet/tcp.h> 24126258Smlaier#include <netinet/udp.h> 25126258Smlaier#include <netinet/ip_icmp.h> 26126258Smlaier#ifndef linux 27126258Smlaier#include <netinet/ip_var.h> 28126258Smlaier#include <netinet/tcpip.h> 29126258Smlaier#endif 30126258Smlaier#include "ip_compat.h" 31126258Smlaier#ifdef linux 32126258Smlaier#include <linux/sockios.h> 33126258Smlaier#include "tcpip.h" 34126258Smlaier#endif 35126258Smlaier#include "ipsd.h" 36126258Smlaier 37126258Smlaier#ifndef lint 38240233Sglebiusstatic char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; 39171168Smlaier#endif 40171168Smlaier 41126261Smlaierextern char *optarg; 42240233Sglebiusextern int optind; 43240233Sglebius 44126261Smlaier#ifdef linux 45126261Smlaierchar default_device[] = "eth0"; 46153110Sru#else 47126258Smlaier# ifdef sun 48240233Sglebiuschar default_device[] = "le0"; 49240233Sglebius# else 50240233Sglebius# ifdef ultrix 51240233Sglebiuschar default_device[] = "ln0"; 52240233Sglebius# else 53240233Sglebiuschar default_device[] = "lan0"; 54240233Sglebius# endif 55126258Smlaier# endif 56240233Sglebius#endif 57240233Sglebius 58240233Sglebius#define NPORTS 21 59126258Smlaier 60126261Smlaieru_short defports[NPORTS] = { 61240233Sglebius 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 62240233Sglebius 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0 63126258Smlaier }; 64126258Smlaier 65126258Smlaieripsd_t *iphits[NPORTS]; 66126258Smlaierint writes = 0; 67171168Smlaier 68240233Sglebius 69126258Smlaierint ipcmp(sh1, sh2) 70240233Sglebiussdhit_t *sh1, *sh2; 71240233Sglebius{ 72240233Sglebius return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 73240233Sglebius} 74240233Sglebius 75240233Sglebius 76126258Smlaier/* 77126258Smlaier * Check to see if we've already received a packet from this host for this 78240233Sglebius * port. 79240233Sglebius */ 80240233Sglebiusint findhit(ihp, src, dport) 81126258Smlaieripsd_t *ihp; 82126258Smlaierstruct in_addr src; 83240233Sglebiusu_short dport; 84126258Smlaier{ 85126258Smlaier int i, j, k; 86126258Smlaier sdhit_t *sh; 87240233Sglebius 88126258Smlaier sh = NULL; 89126258Smlaier 90240494Sglebius if (ihp->sd_sz == 4) { 91240494Sglebius for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 92126258Smlaier if (src.s_addr == sh->sh_ip.s_addr) 93126258Smlaier return 1; 94126258Smlaier } else { 95126258Smlaier for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 96126261Smlaier k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 97126261Smlaier if (!k) 98126258Smlaier return 1; 99126258Smlaier else if (k < 0) 100126261Smlaier i -= j; 101163606Srwatson else 102126258Smlaier i += j; 103223637Sbz } 104126258Smlaier } 105126258Smlaier return 0; 106126258Smlaier} 107126258Smlaier 108126258Smlaier 109223637Sbz/* 110223637Sbz * Search for port number amongst the sorted array of targets we're 111223637Sbz * interested in. 112223637Sbz */ 113223637Sbzint detect(ip, tcp) 114223637Sbzip_t *ip; 115223637Sbztcphdr_t *tcp; 116223637Sbz{ 117223637Sbz ipsd_t *ihp; 118223637Sbz sdhit_t *sh; 119223637Sbz int i, j, k; 120223637Sbz 121223637Sbz for (i = 10, j = 4; j >= 0; j--) { 122223637Sbz k = tcp->th_dport - defports[i]; 123223637Sbz if (!k) { 124223637Sbz ihp = iphits[i]; 125223637Sbz if (findhit(ihp, ip->ip_src, tcp->th_dport)) 126223637Sbz return 0; 127223637Sbz sh = ihp->sd_hit + ihp->sd_cnt; 128223637Sbz sh->sh_date = time(NULL); 129223637Sbz sh->sh_ip.s_addr = ip->ip_src.s_addr; 130240233Sglebius if (++ihp->sd_cnt == ihp->sd_sz) 131240233Sglebius { 132240233Sglebius ihp->sd_sz += 8; 133240233Sglebius sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 134240233Sglebius ihp->sd_hit = sh; 135240233Sglebius } 136240233Sglebius qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 137240233Sglebius return 0; 138240233Sglebius } 139240233Sglebius if (k < 0) 140240233Sglebius i -= j; 141240233Sglebius else 142240233Sglebius i += j; 143240233Sglebius } 144240233Sglebius return -1; 145240233Sglebius} 146240233Sglebius 147240233Sglebius 148240233Sglebius/* 149240233Sglebius * Allocate initial storage for hosts 150240233Sglebius */ 151240233Sglebiussetuphits() 152240233Sglebius{ 153240233Sglebius int i; 154240233Sglebius 155240233Sglebius for (i = 0; i < NPORTS; i++) { 156223637Sbz if (iphits[i]) { 157240233Sglebius if (iphits[i]->sd_hit) 158240233Sglebius free(iphits[i]->sd_hit); 159240233Sglebius free(iphits[i]); 160126258Smlaier } 161240233Sglebius iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 162240233Sglebius iphits[i]->sd_port = defports[i]; 163240233Sglebius iphits[i]->sd_cnt = 0; 164126258Smlaier iphits[i]->sd_sz = 4; 165240233Sglebius iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 166240811Sglebius } 167240233Sglebius} 168240811Sglebius 169240811Sglebius 170240233Sglebius/* 171240233Sglebius * cleanup exits 172240233Sglebius */ 173240811Sglebiuswaiter() 174240233Sglebius{ 175223637Sbz wait(0); 176240811Sglebius} 177240811Sglebius 178240811Sglebius 179240811Sglebius/* 180240811Sglebius * Write statistics out to a file 181126261Smlaier */ 182240811Sglebiuswritestats(nwrites) 183240811Sglebiusint nwrites; 184240811Sglebius{ 185126258Smlaier ipsd_t **ipsd, *ips; 186240233Sglebius char fname[32]; 187240233Sglebius int i, fd; 188240233Sglebius 189240233Sglebius (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites); 190240233Sglebius fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 191240233Sglebius for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) { 192240233Sglebius ips = *ipsd; 193240233Sglebius if (ips->sd_cnt) { 194240233Sglebius write(fd, ips, sizeof(ipsd_t)); 195240233Sglebius write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz); 196240233Sglebius } 197240233Sglebius } 198240233Sglebius (void) close(fd); 199240233Sglebius exit(0); 200240233Sglebius} 201240233Sglebius 202240233Sglebius 203240233Sglebiusvoid writenow() 204240233Sglebius{ 205145836Smlaier signal(SIGCHLD, waiter); 206240233Sglebius switch (fork()) 207240233Sglebius { 208145836Smlaier case 0 : 209240233Sglebius writestats(writes); 210126258Smlaier exit(0); 211126258Smlaier case -1 : 212240233Sglebius perror("vfork"); 213171168Smlaier break; 214240233Sglebius default : 215126258Smlaier writes++; 216126258Smlaier setuphits(); 217126258Smlaier break; 218240233Sglebius } 219162238Scsjp} 220126258Smlaier 221126258Smlaier 222145836Smlaiervoid usage(prog) 223240233Sglebiuschar *prog; 224223637Sbz{ 225126258Smlaier fprintf(stderr, "Usage: %s [-d device]\n", prog); 226240233Sglebius exit(1); 227240233Sglebius} 228240233Sglebius 229240233Sglebius 230240233Sglebiusvoid detecthits(fd, writecount) 231240233Sglebiusint fd, writecount; 232240233Sglebius{ 233130613Smlaier struct in_addr ip; 234240233Sglebius int hits = 0; 235240233Sglebius 236240233Sglebius while (1) { 237223637Sbz hits += readloop(fd, ip); 238223637Sbz if (hits > writecount) { 239223637Sbz writenow(); 240223637Sbz hits = 0; 241223637Sbz } 242223637Sbz } 243240233Sglebius} 244130613Smlaier 245126258Smlaier 246126258Smlaiermain(argc, argv) 247240233Sglebiusint argc; 248200930Sdelphijchar *argv[]; 249200930Sdelphij{ 250200930Sdelphij char c, *name = argv[0], *dev = NULL; 251240233Sglebius int fd, writeafter = 10000, angelic = 0; 252200930Sdelphij 253200930Sdelphij while ((c = getopt(argc, argv, "ad:n:")) != -1) 254240233Sglebius switch (c) 255130613Smlaier { 256126258Smlaier case 'a' : 257240233Sglebius angelic = 1; 258130613Smlaier break; 259126258Smlaier case 'd' : 260240233Sglebius dev = optarg; 261130613Smlaier break; 262145836Smlaier case 'n' : 263240233Sglebius writeafter = atoi(optarg); 264223637Sbz break; 265240233Sglebius default : 266126258Smlaier fprintf(stderr, "Unknown option \"%c\"\n", c); 267240233Sglebius usage(name); 268126258Smlaier } 269240233Sglebius 270231852Sbz bzero(iphits, sizeof(iphits)); 271240233Sglebius setuphits(); 272126258Smlaier 273240233Sglebius if (!dev) 274126258Smlaier dev = default_device; 275240233Sglebius printf("Device: %s\n", dev); 276223637Sbz fd = initdevice(dev, 60); 277240233Sglebius 278126258Smlaier if (!angelic) { 279240233Sglebius switch (fork()) 280240233Sglebius { 281240233Sglebius case 0 : 282240811Sglebius (void) close(0); 283240233Sglebius (void) close(1); 284240233Sglebius (void) close(2); 285241039Sglebius (void) setpgrp(0, getpgrp()); 286240233Sglebius (void) setsid(); 287240233Sglebius break; 288240233Sglebius case -1: 289240233Sglebius perror("fork"); 290240233Sglebius exit(-1); 291240233Sglebius default: 292240233Sglebius exit(0); 293240233Sglebius } 294240233Sglebius } 295240233Sglebius signal(SIGUSR1, writenow); 296240233Sglebius detecthits(fd, writeafter); 297240233Sglebius} 298240233Sglebius