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