ipsd.c revision 259065
161151Sdcs/* $FreeBSD: releng/10.0/contrib/ipfilter/ipsd/ipsd.c 255332 2013-09-06 23:11:19Z cy $ */ 261151Sdcs 361151Sdcs/* 461151Sdcs * (C)opyright 1995-1998 Darren Reed. 561151Sdcs * 6221909Suqs * See the IPFILTER.LICENCE file for details on licencing. 795677Sdougb * 895677Sdougb */ 995677Sdougb#include <stdio.h> 1061151Sdcs#include <fcntl.h> 1161151Sdcs#include <signal.h> 1261151Sdcs#include <stdlib.h> 1361151Sdcs#include <netdb.h> 1461151Sdcs#include <string.h> 1561151Sdcs#include <sys/types.h> 1661151Sdcs#include <sys/time.h> 1761151Sdcs#include <sys/socket.h> 1861151Sdcs#include <netinet/in.h> 1961151Sdcs#include <netinet/in_systm.h> 2061151Sdcs#include <netinet/ip.h> 2161151Sdcs#include <netinet/tcp.h> 2261151Sdcs#include <netinet/udp.h> 2395677Sdougb#include <netinet/ip_icmp.h> 2461151Sdcs#ifndef linux 2561151Sdcs#include <netinet/ip_var.h> 2661151Sdcs#include <netinet/tcpip.h> 2761151Sdcs#endif 2861151Sdcs#include "ip_compat.h" 2961151Sdcs#ifdef linux 3061151Sdcs#include <linux/sockios.h> 3195677Sdougb#include "tcpip.h" 3261151Sdcs#endif 3361151Sdcs#include "ipsd.h" 3495677Sdougb 3561151Sdcs#ifndef lint 3661151Sdcsstatic const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; 3761151Sdcsstatic const char rcsid[] = "@(#)$Id$"; 3861151Sdcs#endif 3995677Sdougb 4061151Sdcsextern char *optarg; 4195677Sdougbextern int optind; 42175017Sdougb 4361151Sdcs#ifdef linux 4461151Sdcschar default_device[] = "eth0"; 4561151Sdcs#else 4661151Sdcs# ifdef sun 47106711Sdcschar default_device[] = "le0"; 48106711Sdcs# else 49106711Sdcs# ifdef ultrix 50106711Sdcschar default_device[] = "ln0"; 51106711Sdcs# else 52106711Sdcschar default_device[] = "lan0"; 53106711Sdcs# endif 54106711Sdcs# endif 55106711Sdcs#endif 56106711Sdcs 57106711Sdcs#define NPORTS 21 58106711Sdcs 59106711Sdcsu_short defports[NPORTS] = { 60106711Sdcs 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 61106711Sdcs 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0 62106711Sdcs }; 63106711Sdcs 64106711Sdcsipsd_t *iphits[NPORTS]; 65106711Sdcsint writes = 0; 66106711Sdcs 67106711Sdcs 68106711Sdcsint ipcmp(sh1, sh2) 69106711Sdcs sdhit_t *sh1, *sh2; 70106746Sdcs{ 71106711Sdcs return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 72106711Sdcs} 73106711Sdcs 74106711Sdcs 75106711Sdcs/* 76106711Sdcs * Check to see if we've already received a packet from this host for this 77106711Sdcs * port. 78106711Sdcs */ 79106711Sdcsint findhit(ihp, src, dport) 80106711Sdcs ipsd_t *ihp; 81106711Sdcs struct in_addr src; 82106711Sdcs u_short dport; 83106711Sdcs{ 84106711Sdcs int i, j, k; 85106711Sdcs sdhit_t *sh; 86106711Sdcs 87106711Sdcs sh = NULL; 88106711Sdcs 89106711Sdcs if (ihp->sd_sz == 4) { 90106711Sdcs for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 91106711Sdcs if (src.s_addr == sh->sh_ip.s_addr) 92106711Sdcs return 1; 93106711Sdcs } else { 94106711Sdcs for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 95106711Sdcs k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 96106711Sdcs if (!k) 97106711Sdcs return 1; 98106711Sdcs else if (k < 0) 99106711Sdcs i -= j; 100106711Sdcs else 101106711Sdcs i += j; 102106711Sdcs } 103106711Sdcs } 104106711Sdcs return 0; 105106711Sdcs} 106106711Sdcs 107106711Sdcs 108106711Sdcs/* 109106711Sdcs * Search for port number amongst the sorted array of targets we're 110106711Sdcs * interested in. 111106711Sdcs */ 112106711Sdcsint detect(ip, tcp) 113106711Sdcs ip_t *ip; 114106711Sdcs tcphdr_t *tcp; 115106711Sdcs{ 116106711Sdcs ipsd_t *ihp; 117106711Sdcs sdhit_t *sh; 118106711Sdcs int i, j, k; 119106746Sdcs 120106746Sdcs for (i = 10, j = 4; j >= 0; j--) { 121106746Sdcs k = tcp->th_dport - defports[i]; 122106746Sdcs if (!k) { 123106746Sdcs ihp = iphits[i]; 124106746Sdcs if (findhit(ihp, ip->ip_src, tcp->th_dport)) 125106746Sdcs return 0; 126106746Sdcs sh = ihp->sd_hit + ihp->sd_cnt; 127106746Sdcs sh->sh_date = time(NULL); 128106746Sdcs sh->sh_ip.s_addr = ip->ip_src.s_addr; 129106746Sdcs if (++ihp->sd_cnt == ihp->sd_sz) 130106746Sdcs { 131106746Sdcs ihp->sd_sz += 8; 132106746Sdcs sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 133106746Sdcs ihp->sd_hit = sh; 134106746Sdcs } 135106746Sdcs qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 136106746Sdcs return 0; 137106746Sdcs } 138106746Sdcs if (k < 0) 139106746Sdcs i -= j; 140106746Sdcs else 141106746Sdcs i += j; 142106746Sdcs } 143106746Sdcs return -1; 144106746Sdcs} 145106746Sdcs 146106746Sdcs 147106746Sdcs/* 148106746Sdcs * Allocate initial storage for hosts 149106746Sdcs */ 150106746Sdcssetuphits() 151106746Sdcs{ 152106746Sdcs int i; 153106746Sdcs 154106746Sdcs for (i = 0; i < NPORTS; i++) { 155106746Sdcs if (iphits[i]) { 156106746Sdcs if (iphits[i]->sd_hit) 157106746Sdcs free(iphits[i]->sd_hit); 158106746Sdcs free(iphits[i]); 159106746Sdcs } 160106746Sdcs iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 161106746Sdcs iphits[i]->sd_port = defports[i]; 162106746Sdcs iphits[i]->sd_cnt = 0; 163106746Sdcs iphits[i]->sd_sz = 4; 164106746Sdcs iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 165106746Sdcs } 166106746Sdcs} 167106746Sdcs 168106746Sdcs 169106746Sdcs/* 170106746Sdcs * cleanup exits 171106746Sdcs */ 172106746Sdcswaiter() 173106746Sdcs{ 174106746Sdcs wait(0); 175106746Sdcs} 176106746Sdcs 177106746Sdcs 178106746Sdcs/* 179106746Sdcs * Write statistics out to a file 180106746Sdcs */ 181106746Sdcswritestats(nwrites) 182106746Sdcs int nwrites; 183106746Sdcs{ 184106746Sdcs ipsd_t **ipsd, *ips; 185106746Sdcs char fname[32]; 186106746Sdcs int i, fd; 187106746Sdcs 188106746Sdcs (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites); 189106746Sdcs fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 190106746Sdcs for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) { 191106746Sdcs ips = *ipsd; 192106746Sdcs if (ips->sd_cnt) { 193106746Sdcs write(fd, ips, sizeof(ipsd_t)); 194106746Sdcs write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz); 195106746Sdcs } 196106746Sdcs } 197106746Sdcs (void) close(fd); 198106746Sdcs exit(0); 199106746Sdcs} 200106746Sdcs 201106746Sdcs 202106746Sdcsvoid writenow() 203106746Sdcs{ 204106746Sdcs signal(SIGCHLD, waiter); 205106746Sdcs switch (fork()) 206106746Sdcs { 207106746Sdcs case 0 : 208106746Sdcs writestats(writes); 209106746Sdcs exit(0); 210106746Sdcs case -1 : 211106746Sdcs perror("vfork"); 212106746Sdcs break; 213106746Sdcs default : 214106746Sdcs writes++; 215106746Sdcs setuphits(); 216106746Sdcs break; 217106746Sdcs } 218175017Sdougb} 219106746Sdcs 220106746Sdcs 221106746Sdcsvoid usage(prog) 222106746Sdcs char *prog; 223106746Sdcs{ 224106746Sdcs fprintf(stderr, "Usage: %s [-d device]\n", prog); 225106746Sdcs exit(1); 226106746Sdcs} 227106746Sdcs 228106746Sdcs 229106746Sdcsvoid detecthits(fd, writecount) 230106746Sdcs int fd, writecount; 231106746Sdcs{ 232106746Sdcs struct in_addr ip; 233106746Sdcs int hits = 0; 234106746Sdcs 235106746Sdcs while (1) { 236106746Sdcs hits += readloop(fd, ip); 237106746Sdcs if (hits > writecount) { 238106746Sdcs writenow(); 239106746Sdcs hits = 0; 240106746Sdcs } 241106746Sdcs } 242106746Sdcs} 243106746Sdcs 244106746Sdcs 245106746Sdcsmain(argc, argv) 246106746Sdcs int argc; 247106746Sdcs char *argv[]; 248106746Sdcs{ 249106746Sdcs char *name = argv[0], *dev = NULL; 250106746Sdcs int fd, writeafter = 10000, angelic = 0, c; 251106746Sdcs 252106746Sdcs while ((c = getopt(argc, argv, "ad:n:")) != -1) 253106746Sdcs switch (c) 254106746Sdcs { 255106746Sdcs case 'a' : 256106746Sdcs angelic = 1; 257106746Sdcs break; 258106746Sdcs case 'd' : 259106746Sdcs dev = optarg; 260106746Sdcs break; 261106746Sdcs case 'n' : 262106746Sdcs writeafter = atoi(optarg); 263106746Sdcs break; 264106746Sdcs default : 265106746Sdcs fprintf(stderr, "Unknown option \"%c\"\n", c); 266106746Sdcs usage(name); 267106746Sdcs } 268106746Sdcs 269106746Sdcs bzero(iphits, sizeof(iphits)); 270106746Sdcs setuphits(); 271106746Sdcs 272106746Sdcs if (!dev) 273106746Sdcs dev = default_device; 274106746Sdcs printf("Device: %s\n", dev); 275106746Sdcs fd = initdevice(dev, 60); 276106746Sdcs 277106746Sdcs if (!angelic) { 278106746Sdcs switch (fork()) 279106746Sdcs { 280106746Sdcs case 0 : 281106746Sdcs (void) close(0); 282106746Sdcs (void) close(1); 283106746Sdcs (void) close(2); 284106746Sdcs (void) setpgrp(0, getpgrp()); 285106746Sdcs (void) setsid(); 286106746Sdcs break; 287106746Sdcs case -1: 288106746Sdcs perror("fork"); 289106746Sdcs exit(-1); 290106746Sdcs default: 291106746Sdcs exit(0); 292106746Sdcs } 293106746Sdcs } 294106746Sdcs signal(SIGUSR1, writenow); 295106746Sdcs detecthits(fd, writeafter); 296106746Sdcs} 297106746Sdcs