ipsd.c revision 53024
122514Sdarrenr/* 253024Sguido * (C)opyright 1995-1998 Darren Reed. 322514Sdarrenr * 431183Speter * Redistribution and use in source and binary forms are permitted 531183Speter * provided that this notice is preserved and due credit is given 631183Speter * to the original author and the contributors. 722514Sdarrenr * 822514Sdarrenr * The author of this software makes no garuntee about the 922514Sdarrenr * performance of this package or its suitability to fulfill any purpose. 1022514Sdarrenr * 1122514Sdarrenr */ 1222514Sdarrenr#include <stdio.h> 1322514Sdarrenr#include <fcntl.h> 1422514Sdarrenr#include <signal.h> 1522514Sdarrenr#include <stdlib.h> 1622514Sdarrenr#include <netdb.h> 1722514Sdarrenr#include <string.h> 1822514Sdarrenr#include <sys/types.h> 1922514Sdarrenr#include <sys/time.h> 2022514Sdarrenr#include <sys/socket.h> 2122514Sdarrenr#include <netinet/in.h> 2222514Sdarrenr#include <netinet/in_systm.h> 2322514Sdarrenr#include <netinet/ip.h> 2422514Sdarrenr#include <netinet/tcp.h> 2522514Sdarrenr#include <netinet/udp.h> 2622514Sdarrenr#include <netinet/ip_icmp.h> 2722514Sdarrenr#ifndef linux 2822514Sdarrenr#include <netinet/ip_var.h> 2922514Sdarrenr#include <netinet/tcpip.h> 3022514Sdarrenr#endif 3122514Sdarrenr#include "ip_compat.h" 3222514Sdarrenr#ifdef linux 3322514Sdarrenr#include <linux/sockios.h> 3422514Sdarrenr#include "tcpip.h" 3522514Sdarrenr#endif 3622514Sdarrenr#include "ipsd.h" 3722514Sdarrenr 3822514Sdarrenr#ifndef lint 3931183Speterstatic const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; 4053024Sguidostatic const char rcsid[] = "@(#)$Id: ipsd.c,v 2.1 1999/08/04 17:30:56 darrenr Exp $"; 4122514Sdarrenr#endif 4222514Sdarrenr 4322514Sdarrenrextern char *optarg; 4422514Sdarrenrextern int optind; 4522514Sdarrenr 4622514Sdarrenr#ifdef linux 4722514Sdarrenrchar default_device[] = "eth0"; 4822514Sdarrenr#else 4922514Sdarrenr# ifdef sun 5022514Sdarrenrchar default_device[] = "le0"; 5122514Sdarrenr# else 5222514Sdarrenr# ifdef ultrix 5322514Sdarrenrchar default_device[] = "ln0"; 5422514Sdarrenr# else 5522514Sdarrenrchar default_device[] = "lan0"; 5622514Sdarrenr# endif 5722514Sdarrenr# endif 5822514Sdarrenr#endif 5922514Sdarrenr 6022514Sdarrenr#define NPORTS 21 6122514Sdarrenr 6222514Sdarrenru_short defports[NPORTS] = { 6322514Sdarrenr 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 6422514Sdarrenr 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0 6522514Sdarrenr }; 6622514Sdarrenr 6722514Sdarrenripsd_t *iphits[NPORTS]; 6822514Sdarrenrint writes = 0; 6922514Sdarrenr 7022514Sdarrenr 7122514Sdarrenrint ipcmp(sh1, sh2) 7222514Sdarrenrsdhit_t *sh1, *sh2; 7322514Sdarrenr{ 7422514Sdarrenr return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 7522514Sdarrenr} 7622514Sdarrenr 7722514Sdarrenr 7822514Sdarrenr/* 7922514Sdarrenr * Check to see if we've already received a packet from this host for this 8022514Sdarrenr * port. 8122514Sdarrenr */ 8222514Sdarrenrint findhit(ihp, src, dport) 8322514Sdarrenripsd_t *ihp; 8422514Sdarrenrstruct in_addr src; 8522514Sdarrenru_short dport; 8622514Sdarrenr{ 8722514Sdarrenr int i, j, k; 8822514Sdarrenr sdhit_t *sh; 8922514Sdarrenr 9022514Sdarrenr sh = NULL; 9122514Sdarrenr 9222514Sdarrenr if (ihp->sd_sz == 4) { 9322514Sdarrenr for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 9422514Sdarrenr if (src.s_addr == sh->sh_ip.s_addr) 9522514Sdarrenr return 1; 9622514Sdarrenr } else { 9722514Sdarrenr for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 9822514Sdarrenr k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 9922514Sdarrenr if (!k) 10022514Sdarrenr return 1; 10122514Sdarrenr else if (k < 0) 10222514Sdarrenr i -= j; 10322514Sdarrenr else 10422514Sdarrenr i += j; 10522514Sdarrenr } 10622514Sdarrenr } 10722514Sdarrenr return 0; 10822514Sdarrenr} 10922514Sdarrenr 11022514Sdarrenr 11122514Sdarrenr/* 11222514Sdarrenr * Search for port number amongst the sorted array of targets we're 11322514Sdarrenr * interested in. 11422514Sdarrenr */ 11522514Sdarrenrint detect(ip, tcp) 11622514Sdarrenrip_t *ip; 11722514Sdarrenrtcphdr_t *tcp; 11822514Sdarrenr{ 11922514Sdarrenr ipsd_t *ihp; 12022514Sdarrenr sdhit_t *sh; 12122514Sdarrenr int i, j, k; 12222514Sdarrenr 12322514Sdarrenr for (i = 10, j = 4; j >= 0; j--) { 12422514Sdarrenr k = tcp->th_dport - defports[i]; 12522514Sdarrenr if (!k) { 12622514Sdarrenr ihp = iphits[i]; 12722514Sdarrenr if (findhit(ihp, ip->ip_src, tcp->th_dport)) 12822514Sdarrenr return 0; 12922514Sdarrenr sh = ihp->sd_hit + ihp->sd_cnt; 13022514Sdarrenr sh->sh_date = time(NULL); 13122514Sdarrenr sh->sh_ip.s_addr = ip->ip_src.s_addr; 13222514Sdarrenr if (++ihp->sd_cnt == ihp->sd_sz) 13322514Sdarrenr { 13422514Sdarrenr ihp->sd_sz += 8; 13522514Sdarrenr sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 13622514Sdarrenr ihp->sd_hit = sh; 13722514Sdarrenr } 13822514Sdarrenr qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 13922514Sdarrenr return 0; 14022514Sdarrenr } 14122514Sdarrenr if (k < 0) 14222514Sdarrenr i -= j; 14322514Sdarrenr else 14422514Sdarrenr i += j; 14522514Sdarrenr } 14622514Sdarrenr return -1; 14722514Sdarrenr} 14822514Sdarrenr 14922514Sdarrenr 15022514Sdarrenr/* 15122514Sdarrenr * Allocate initial storage for hosts 15222514Sdarrenr */ 15322514Sdarrenrsetuphits() 15422514Sdarrenr{ 15522514Sdarrenr int i; 15622514Sdarrenr 15722514Sdarrenr for (i = 0; i < NPORTS; i++) { 15822514Sdarrenr if (iphits[i]) { 15922514Sdarrenr if (iphits[i]->sd_hit) 16022514Sdarrenr free(iphits[i]->sd_hit); 16122514Sdarrenr free(iphits[i]); 16222514Sdarrenr } 16322514Sdarrenr iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 16422514Sdarrenr iphits[i]->sd_port = defports[i]; 16522514Sdarrenr iphits[i]->sd_cnt = 0; 16622514Sdarrenr iphits[i]->sd_sz = 4; 16722514Sdarrenr iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 16822514Sdarrenr } 16922514Sdarrenr} 17022514Sdarrenr 17122514Sdarrenr 17222514Sdarrenr/* 17322514Sdarrenr * cleanup exits 17422514Sdarrenr */ 17522514Sdarrenrwaiter() 17622514Sdarrenr{ 17722514Sdarrenr wait(0); 17822514Sdarrenr} 17922514Sdarrenr 18022514Sdarrenr 18122514Sdarrenr/* 18222514Sdarrenr * Write statistics out to a file 18322514Sdarrenr */ 18422514Sdarrenrwritestats(nwrites) 18522514Sdarrenrint nwrites; 18622514Sdarrenr{ 18722514Sdarrenr ipsd_t **ipsd, *ips; 18822514Sdarrenr char fname[32]; 18922514Sdarrenr int i, fd; 19022514Sdarrenr 19122514Sdarrenr (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites); 19222514Sdarrenr fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 19322514Sdarrenr for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) { 19422514Sdarrenr ips = *ipsd; 19522514Sdarrenr if (ips->sd_cnt) { 19622514Sdarrenr write(fd, ips, sizeof(ipsd_t)); 19722514Sdarrenr write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz); 19822514Sdarrenr } 19922514Sdarrenr } 20022514Sdarrenr (void) close(fd); 20122514Sdarrenr exit(0); 20222514Sdarrenr} 20322514Sdarrenr 20422514Sdarrenr 20522514Sdarrenrvoid writenow() 20622514Sdarrenr{ 20722514Sdarrenr signal(SIGCHLD, waiter); 20822514Sdarrenr switch (fork()) 20922514Sdarrenr { 21022514Sdarrenr case 0 : 21122514Sdarrenr writestats(writes); 21222514Sdarrenr exit(0); 21322514Sdarrenr case -1 : 21422514Sdarrenr perror("vfork"); 21522514Sdarrenr break; 21622514Sdarrenr default : 21722514Sdarrenr writes++; 21822514Sdarrenr setuphits(); 21922514Sdarrenr break; 22022514Sdarrenr } 22122514Sdarrenr} 22222514Sdarrenr 22322514Sdarrenr 22422514Sdarrenrvoid usage(prog) 22522514Sdarrenrchar *prog; 22622514Sdarrenr{ 22722514Sdarrenr fprintf(stderr, "Usage: %s [-d device]\n", prog); 22822514Sdarrenr exit(1); 22922514Sdarrenr} 23022514Sdarrenr 23122514Sdarrenr 23222514Sdarrenrvoid detecthits(fd, writecount) 23322514Sdarrenrint fd, writecount; 23422514Sdarrenr{ 23522514Sdarrenr struct in_addr ip; 23622514Sdarrenr int hits = 0; 23722514Sdarrenr 23822514Sdarrenr while (1) { 23922514Sdarrenr hits += readloop(fd, ip); 24022514Sdarrenr if (hits > writecount) { 24122514Sdarrenr writenow(); 24222514Sdarrenr hits = 0; 24322514Sdarrenr } 24422514Sdarrenr } 24522514Sdarrenr} 24622514Sdarrenr 24722514Sdarrenr 24822514Sdarrenrmain(argc, argv) 24922514Sdarrenrint argc; 25022514Sdarrenrchar *argv[]; 25122514Sdarrenr{ 25231183Speter char *name = argv[0], *dev = NULL; 25331183Speter int fd, writeafter = 10000, angelic = 0, c; 25422514Sdarrenr 25522514Sdarrenr while ((c = getopt(argc, argv, "ad:n:")) != -1) 25622514Sdarrenr switch (c) 25722514Sdarrenr { 25822514Sdarrenr case 'a' : 25922514Sdarrenr angelic = 1; 26022514Sdarrenr break; 26122514Sdarrenr case 'd' : 26222514Sdarrenr dev = optarg; 26322514Sdarrenr break; 26422514Sdarrenr case 'n' : 26522514Sdarrenr writeafter = atoi(optarg); 26622514Sdarrenr break; 26722514Sdarrenr default : 26822514Sdarrenr fprintf(stderr, "Unknown option \"%c\"\n", c); 26922514Sdarrenr usage(name); 27022514Sdarrenr } 27122514Sdarrenr 27222514Sdarrenr bzero(iphits, sizeof(iphits)); 27322514Sdarrenr setuphits(); 27422514Sdarrenr 27522514Sdarrenr if (!dev) 27622514Sdarrenr dev = default_device; 27722514Sdarrenr printf("Device: %s\n", dev); 27822514Sdarrenr fd = initdevice(dev, 60); 27922514Sdarrenr 28022514Sdarrenr if (!angelic) { 28122514Sdarrenr switch (fork()) 28222514Sdarrenr { 28322514Sdarrenr case 0 : 28422514Sdarrenr (void) close(0); 28522514Sdarrenr (void) close(1); 28622514Sdarrenr (void) close(2); 28722514Sdarrenr (void) setpgrp(0, getpgrp()); 28822514Sdarrenr (void) setsid(); 28922514Sdarrenr break; 29022514Sdarrenr case -1: 29122514Sdarrenr perror("fork"); 29222514Sdarrenr exit(-1); 29322514Sdarrenr default: 29422514Sdarrenr exit(0); 29522514Sdarrenr } 29622514Sdarrenr } 29722514Sdarrenr signal(SIGUSR1, writenow); 29822514Sdarrenr detecthits(fd, writeafter); 29922514Sdarrenr} 300