ipsdr.c revision 80486
122514Sdarrenr/* 253024Sguido * (C)opyright 1995-1998 Darren Reed. 322514Sdarrenr * 480486Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 522514Sdarrenr * 622514Sdarrenr * The author of this software makes no garuntee about the 722514Sdarrenr * performance of this package or its suitability to fulfill any purpose. 822514Sdarrenr * 922514Sdarrenr */ 1022514Sdarrenr#include <stdio.h> 1122514Sdarrenr#include <fcntl.h> 1222514Sdarrenr#include <signal.h> 1322514Sdarrenr#include <malloc.h> 1422514Sdarrenr#include <netdb.h> 1522514Sdarrenr#include <string.h> 1622514Sdarrenr#include <sys/dir.h> 1722514Sdarrenr#include <sys/types.h> 1822514Sdarrenr#include <sys/time.h> 1922514Sdarrenr#include <sys/socket.h> 2022514Sdarrenr#include <netinet/in.h> 2122514Sdarrenr#include <netinet/in_systm.h> 2222514Sdarrenr#include <netinet/ip.h> 2322514Sdarrenr#include <netinet/tcp.h> 2422514Sdarrenr#include <netinet/udp.h> 2522514Sdarrenr#include <netinet/ip_icmp.h> 2622514Sdarrenr#ifndef linux 2722514Sdarrenr#include <netinet/ip_var.h> 2822514Sdarrenr#include <netinet/tcpip.h> 2922514Sdarrenr#endif 3022514Sdarrenr#include "ip_compat.h" 3122514Sdarrenr#ifdef linux 3222514Sdarrenr#include <linux/sockios.h> 3322514Sdarrenr#include "tcpip.h" 3422514Sdarrenr#endif 3522514Sdarrenr#include "ipsd.h" 3622514Sdarrenr 3722514Sdarrenr#ifndef lint 3831183Speterstatic const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; 3980486Sdarrenrstatic const char rcsid[] = "@(#)$Id: ipsdr.c,v 2.1.4.1 2001/06/26 10:43:21 darrenr Exp $"; 4022514Sdarrenr#endif 4122514Sdarrenr 4222514Sdarrenrextern char *optarg; 4322514Sdarrenrextern int optind; 4422514Sdarrenr 4522514Sdarrenr#define NPORTS 21 4622514Sdarrenr 4722514Sdarrenru_short defports[NPORTS] = { 4822514Sdarrenr 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 4922514Sdarrenr 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 5022514Sdarrenr }; 5122514Sdarrenru_short pweights[NPORTS] = { 5222514Sdarrenr 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5322514Sdarrenr 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 5422514Sdarrenr }; 5522514Sdarrenr 5622514Sdarrenripsd_t *iphits[NPORTS]; 5722514Sdarrenrint pkts; 5822514Sdarrenr 5922514Sdarrenr 6022514Sdarrenrint ipcmp(sh1, sh2) 6122514Sdarrenrsdhit_t *sh1, *sh2; 6222514Sdarrenr{ 6322514Sdarrenr return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 6422514Sdarrenr} 6522514Sdarrenr 6622514Sdarrenr 6722514Sdarrenrint ssipcmp(sh1, sh2) 6822514Sdarrenripss_t *sh1, *sh2; 6922514Sdarrenr{ 7022514Sdarrenr return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; 7122514Sdarrenr} 7222514Sdarrenr 7322514Sdarrenr 7422514Sdarrenrint countpbits(num) 7522514Sdarrenru_long num; 7622514Sdarrenr{ 7722514Sdarrenr int i, j; 7822514Sdarrenr 7922514Sdarrenr for (i = 1, j = 0; i; i <<= 1) 8022514Sdarrenr if (num & i) 8122514Sdarrenr j++; 8222514Sdarrenr return j; 8322514Sdarrenr} 8422514Sdarrenr 8522514Sdarrenr 8622514Sdarrenr/* 8722514Sdarrenr * Check to see if we've already received a packet from this host for this 8822514Sdarrenr * port. 8922514Sdarrenr */ 9022514Sdarrenrint findhit(ihp, src, dport) 9122514Sdarrenripsd_t *ihp; 9222514Sdarrenrstruct in_addr src; 9322514Sdarrenru_short dport; 9422514Sdarrenr{ 9522514Sdarrenr int i, j, k; 9622514Sdarrenr sdhit_t *sh; 9722514Sdarrenr 9822514Sdarrenr sh = NULL; 9922514Sdarrenr 10022514Sdarrenr if (ihp->sd_sz == 4) { 10122514Sdarrenr for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 10222514Sdarrenr if (src.s_addr == sh->sh_ip.s_addr) 10322514Sdarrenr return 1; 10422514Sdarrenr } else { 10522514Sdarrenr for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 10622514Sdarrenr k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 10722514Sdarrenr if (!k) 10822514Sdarrenr return 1; 10922514Sdarrenr else if (k < 0) 11022514Sdarrenr i -= j; 11122514Sdarrenr else 11222514Sdarrenr i += j; 11322514Sdarrenr } 11422514Sdarrenr } 11522514Sdarrenr return 0; 11622514Sdarrenr} 11722514Sdarrenr 11822514Sdarrenr 11922514Sdarrenr/* 12022514Sdarrenr * Search for port number amongst the sorted array of targets we're 12122514Sdarrenr * interested in. 12222514Sdarrenr */ 12322514Sdarrenrint detect(srcip, dport, date) 12422514Sdarrenrstruct in_addr srcip; 12522514Sdarrenru_short dport; 12622514Sdarrenrtime_t date; 12722514Sdarrenr{ 12822514Sdarrenr ipsd_t *ihp; 12922514Sdarrenr sdhit_t *sh; 13022514Sdarrenr int i, j, k; 13122514Sdarrenr 13222514Sdarrenr for (i = 10, j = 4; j >= 0; j--) { 13322514Sdarrenr k = dport - defports[i]; 13422514Sdarrenr if (!k) { 13522514Sdarrenr ihp = iphits[i]; 13622514Sdarrenr if (findhit(ihp, srcip, dport)) 13722514Sdarrenr return 0; 13822514Sdarrenr sh = ihp->sd_hit + ihp->sd_cnt; 13922514Sdarrenr sh->sh_date = date; 14022514Sdarrenr sh->sh_ip = srcip; 14122514Sdarrenr if (++ihp->sd_cnt == ihp->sd_sz) 14222514Sdarrenr { 14322514Sdarrenr ihp->sd_sz += 8; 14422514Sdarrenr sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 14522514Sdarrenr ihp->sd_hit = sh; 14622514Sdarrenr } 14722514Sdarrenr qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 14822514Sdarrenr return 0; 14922514Sdarrenr } 15022514Sdarrenr if (k < 0) 15122514Sdarrenr i -= j; 15222514Sdarrenr else 15322514Sdarrenr i += j; 15422514Sdarrenr } 15522514Sdarrenr return -1; 15622514Sdarrenr} 15722514Sdarrenr 15822514Sdarrenr 15922514Sdarrenr/* 16022514Sdarrenr * Allocate initial storage for hosts 16122514Sdarrenr */ 16222514Sdarrenrsetuphits() 16322514Sdarrenr{ 16422514Sdarrenr int i; 16522514Sdarrenr 16622514Sdarrenr for (i = 0; i < NPORTS; i++) { 16722514Sdarrenr if (iphits[i]) { 16822514Sdarrenr if (iphits[i]->sd_hit) 16922514Sdarrenr free(iphits[i]->sd_hit); 17022514Sdarrenr free(iphits[i]); 17122514Sdarrenr } 17222514Sdarrenr iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 17322514Sdarrenr iphits[i]->sd_port = defports[i]; 17422514Sdarrenr iphits[i]->sd_cnt = 0; 17522514Sdarrenr iphits[i]->sd_sz = 4; 17622514Sdarrenr iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 17722514Sdarrenr } 17822514Sdarrenr} 17922514Sdarrenr 18022514Sdarrenr 18122514Sdarrenr/* 18222514Sdarrenr * Write statistics out to a file 18322514Sdarrenr */ 18422514Sdarrenraddfile(file) 18522514Sdarrenrchar *file; 18622514Sdarrenr{ 18722514Sdarrenr ipsd_t ipsd, *ips = &ipsd; 18822514Sdarrenr sdhit_t hit, *hp; 18922514Sdarrenr char fname[32]; 19022514Sdarrenr int i, fd, sz; 19122514Sdarrenr 19222514Sdarrenr if ((fd = open(file, O_RDONLY)) == -1) { 19322514Sdarrenr perror("open"); 19422514Sdarrenr return; 19522514Sdarrenr } 19622514Sdarrenr 19722514Sdarrenr printf("opened %s\n", file); 19822514Sdarrenr do { 19922514Sdarrenr if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) 20022514Sdarrenr break; 20122514Sdarrenr sz = ips->sd_sz * sizeof(*hp); 20222514Sdarrenr hp = (sdhit_t *)malloc(sz); 20322514Sdarrenr if (read(fd, hp, sz) != sz) 20422514Sdarrenr break; 20522514Sdarrenr for (i = 0; i < ips->sd_cnt; i++) 20622514Sdarrenr detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); 20722514Sdarrenr } while (1); 20822514Sdarrenr (void) close(fd); 20922514Sdarrenr} 21022514Sdarrenr 21122514Sdarrenr 21222514Sdarrenrreadfiles(dir) 21322514Sdarrenrchar *dir; 21422514Sdarrenr{ 21522514Sdarrenr struct direct **d; 21622514Sdarrenr int i, j; 21722514Sdarrenr 21822514Sdarrenr d = NULL; 21922514Sdarrenr i = scandir(dir, &d, NULL, NULL); 22022514Sdarrenr 22122514Sdarrenr for (j = 0; j < i; j++) { 22222514Sdarrenr if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) 22322514Sdarrenr continue; 22422514Sdarrenr addfile(d[j]->d_name); 22522514Sdarrenr } 22622514Sdarrenr} 22722514Sdarrenr 22822514Sdarrenr 22922514Sdarrenrvoid printreport(ss, num) 23022514Sdarrenripss_t *ss; 23122514Sdarrenrint num; 23222514Sdarrenr{ 23322514Sdarrenr struct in_addr ip; 23422514Sdarrenr ipss_t *sp; 23522514Sdarrenr int i, j, mask; 23622514Sdarrenr u_long ports; 23722514Sdarrenr 23822514Sdarrenr printf("Hosts detected: %d\n", num); 23922514Sdarrenr if (!num) 24022514Sdarrenr return; 24122514Sdarrenr for (i = 0; i < num; i++) 24222514Sdarrenr printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, 24322514Sdarrenr countpbits(ss[i].ss_ports)); 24422514Sdarrenr 24522514Sdarrenr printf("--------------------------\n"); 24622514Sdarrenr for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { 24722514Sdarrenr ip.s_addr = ss[0].ss_ip.s_addr & mask; 24822514Sdarrenr ports = ss[0].ss_ports; 24922514Sdarrenr for (i = 1; i < num; i++) { 25022514Sdarrenr sp = ss + i; 25122514Sdarrenr if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { 25222514Sdarrenr printf("Netmask: 0x%08x\n", mask); 25322514Sdarrenr printf("%s %d\n", inet_ntoa(ip), 25422514Sdarrenr countpbits(ports)); 25522514Sdarrenr ip.s_addr = sp->ss_ip.s_addr & mask; 25622514Sdarrenr ports = 0; 25722514Sdarrenr } 25822514Sdarrenr ports |= sp->ss_ports; 25922514Sdarrenr } 26022514Sdarrenr if (ports) { 26122514Sdarrenr printf("Netmask: 0x%08x\n", mask); 26222514Sdarrenr printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); 26322514Sdarrenr } 26422514Sdarrenr } 26522514Sdarrenr} 26622514Sdarrenr 26722514Sdarrenr 26822514Sdarrenrcollectips() 26922514Sdarrenr{ 27022514Sdarrenr ipsd_t *ips; 27122514Sdarrenr ipss_t *ss; 27222514Sdarrenr int i, num, nip, in, j, k; 27322514Sdarrenr 27422514Sdarrenr for (i = 0; i < NPORTS; i++) 27522514Sdarrenr nip += iphits[i]->sd_cnt; 27622514Sdarrenr 27722514Sdarrenr ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); 27822514Sdarrenr 27922514Sdarrenr for (in = 0, i = 0, num = 0; i < NPORTS; i++) { 28022514Sdarrenr ips = iphits[i]; 28122514Sdarrenr for (j = 0; j < ips->sd_cnt; j++) { 28222514Sdarrenr for (k = 0; k < num; k++) 28322514Sdarrenr if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, 28422514Sdarrenr sizeof(struct in_addr))) { 28522514Sdarrenr ss[k].ss_hits += pweights[i]; 28622514Sdarrenr ss[k].ss_ports |= (1 << i); 28722514Sdarrenr break; 28822514Sdarrenr } 28922514Sdarrenr if (k == num) { 29022514Sdarrenr ss[num].ss_ip = ips->sd_hit[j].sh_ip; 29122514Sdarrenr ss[num].ss_hits = pweights[i]; 29222514Sdarrenr ss[k].ss_ports |= (1 << i); 29322514Sdarrenr num++; 29422514Sdarrenr } 29522514Sdarrenr } 29622514Sdarrenr } 29722514Sdarrenr 29822514Sdarrenr qsort(ss, num, sizeof(*ss), ssipcmp); 29922514Sdarrenr 30022514Sdarrenr printreport(ss, num); 30122514Sdarrenr} 30222514Sdarrenr 30322514Sdarrenr 30422514Sdarrenrmain(argc, argv) 30522514Sdarrenrint argc; 30622514Sdarrenrchar *argv[]; 30722514Sdarrenr{ 30822514Sdarrenr char c, *name = argv[0], *dir = NULL; 30922514Sdarrenr int fd; 31022514Sdarrenr 31122514Sdarrenr setuphits(); 31222514Sdarrenr dir = dir ? dir : "."; 31322514Sdarrenr readfiles(dir); 31422514Sdarrenr collectips(); 31522514Sdarrenr} 316