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