ipsd.c revision 31183
1/* 2 * (C)opyright 1995-1997 Darren Reed. 3 * 4 * Redistribution and use in source and binary forms are permitted 5 * provided that this notice is preserved and due credit is given 6 * to the original author and the contributors. 7 * 8 * The author of this software makes no garuntee about the 9 * performance of this package or its suitability to fulfill any purpose. 10 * 11 */ 12#include <stdio.h> 13#include <fcntl.h> 14#include <signal.h> 15#include <stdlib.h> 16#include <netdb.h> 17#include <string.h> 18#include <sys/types.h> 19#include <sys/time.h> 20#include <sys/socket.h> 21#include <netinet/in.h> 22#include <netinet/in_systm.h> 23#include <netinet/ip.h> 24#include <netinet/tcp.h> 25#include <netinet/udp.h> 26#include <netinet/ip_icmp.h> 27#ifndef linux 28#include <netinet/ip_var.h> 29#include <netinet/tcpip.h> 30#endif 31#include "ip_compat.h" 32#ifdef linux 33#include <linux/sockios.h> 34#include "tcpip.h" 35#endif 36#include "ipsd.h" 37 38#ifndef lint 39static const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed"; 40static const char rcsid[] = "@(#)$Id: ipsd.c,v 2.0.2.4 1997/09/28 07:13:17 darrenr Exp $"; 41#endif 42 43extern char *optarg; 44extern int optind; 45 46#ifdef linux 47char default_device[] = "eth0"; 48#else 49# ifdef sun 50char default_device[] = "le0"; 51# else 52# ifdef ultrix 53char default_device[] = "ln0"; 54# else 55char default_device[] = "lan0"; 56# endif 57# endif 58#endif 59 60#define NPORTS 21 61 62u_short defports[NPORTS] = { 63 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 64 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0 65 }; 66 67ipsd_t *iphits[NPORTS]; 68int writes = 0; 69 70 71int ipcmp(sh1, sh2) 72sdhit_t *sh1, *sh2; 73{ 74 return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 75} 76 77 78/* 79 * Check to see if we've already received a packet from this host for this 80 * port. 81 */ 82int findhit(ihp, src, dport) 83ipsd_t *ihp; 84struct in_addr src; 85u_short dport; 86{ 87 int i, j, k; 88 sdhit_t *sh; 89 90 sh = NULL; 91 92 if (ihp->sd_sz == 4) { 93 for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 94 if (src.s_addr == sh->sh_ip.s_addr) 95 return 1; 96 } else { 97 for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 98 k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 99 if (!k) 100 return 1; 101 else if (k < 0) 102 i -= j; 103 else 104 i += j; 105 } 106 } 107 return 0; 108} 109 110 111/* 112 * Search for port number amongst the sorted array of targets we're 113 * interested in. 114 */ 115int detect(ip, tcp) 116ip_t *ip; 117tcphdr_t *tcp; 118{ 119 ipsd_t *ihp; 120 sdhit_t *sh; 121 int i, j, k; 122 123 for (i = 10, j = 4; j >= 0; j--) { 124 k = tcp->th_dport - defports[i]; 125 if (!k) { 126 ihp = iphits[i]; 127 if (findhit(ihp, ip->ip_src, tcp->th_dport)) 128 return 0; 129 sh = ihp->sd_hit + ihp->sd_cnt; 130 sh->sh_date = time(NULL); 131 sh->sh_ip.s_addr = ip->ip_src.s_addr; 132 if (++ihp->sd_cnt == ihp->sd_sz) 133 { 134 ihp->sd_sz += 8; 135 sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 136 ihp->sd_hit = sh; 137 } 138 qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 139 return 0; 140 } 141 if (k < 0) 142 i -= j; 143 else 144 i += j; 145 } 146 return -1; 147} 148 149 150/* 151 * Allocate initial storage for hosts 152 */ 153setuphits() 154{ 155 int i; 156 157 for (i = 0; i < NPORTS; i++) { 158 if (iphits[i]) { 159 if (iphits[i]->sd_hit) 160 free(iphits[i]->sd_hit); 161 free(iphits[i]); 162 } 163 iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 164 iphits[i]->sd_port = defports[i]; 165 iphits[i]->sd_cnt = 0; 166 iphits[i]->sd_sz = 4; 167 iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 168 } 169} 170 171 172/* 173 * cleanup exits 174 */ 175waiter() 176{ 177 wait(0); 178} 179 180 181/* 182 * Write statistics out to a file 183 */ 184writestats(nwrites) 185int nwrites; 186{ 187 ipsd_t **ipsd, *ips; 188 char fname[32]; 189 int i, fd; 190 191 (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites); 192 fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 193 for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) { 194 ips = *ipsd; 195 if (ips->sd_cnt) { 196 write(fd, ips, sizeof(ipsd_t)); 197 write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz); 198 } 199 } 200 (void) close(fd); 201 exit(0); 202} 203 204 205void writenow() 206{ 207 signal(SIGCHLD, waiter); 208 switch (fork()) 209 { 210 case 0 : 211 writestats(writes); 212 exit(0); 213 case -1 : 214 perror("vfork"); 215 break; 216 default : 217 writes++; 218 setuphits(); 219 break; 220 } 221} 222 223 224void usage(prog) 225char *prog; 226{ 227 fprintf(stderr, "Usage: %s [-d device]\n", prog); 228 exit(1); 229} 230 231 232void detecthits(fd, writecount) 233int fd, writecount; 234{ 235 struct in_addr ip; 236 int hits = 0; 237 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