ipsdr.c revision 285830
1263936Sbr/* $FreeBSD: releng/10.2/contrib/ipfilter/ipsd/ipsdr.c 255332 2013-09-06 23:11:19Z cy $ */ 2263936Sbr 3263936Sbr/* 4263936Sbr * (C)opyright 1995-1998 Darren Reed. 5263936Sbr * 6263936Sbr * See the IPFILTER.LICENCE file for details on licencing. 7263936Sbr * 8263936Sbr */ 9263936Sbr#include <stdio.h> 10263936Sbr#include <fcntl.h> 11263936Sbr#include <signal.h> 12263936Sbr#include <malloc.h> 13263936Sbr#include <netdb.h> 14263936Sbr#include <string.h> 15263936Sbr#include <sys/dir.h> 16263936Sbr#include <sys/types.h> 17263936Sbr#include <sys/time.h> 18263936Sbr#include <sys/socket.h> 19263936Sbr#include <netinet/in.h> 20263936Sbr#include <netinet/in_systm.h> 21263936Sbr#include <netinet/ip.h> 22263936Sbr#include <netinet/tcp.h> 23263936Sbr#include <netinet/udp.h> 24263936Sbr#include <netinet/ip_icmp.h> 25263936Sbr#ifndef linux 26263936Sbr#include <netinet/ip_var.h> 27263936Sbr#include <netinet/tcpip.h> 28263936Sbr#endif 29263936Sbr#include "ip_compat.h" 30263936Sbr#ifdef linux 31263936Sbr#include <linux/sockios.h> 32263936Sbr#include "tcpip.h" 33263936Sbr#endif 34263936Sbr#include "ipsd.h" 35263936Sbr 36263936Sbr#ifndef lint 37263936Sbrstatic const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; 38263936Sbrstatic const char rcsid[] = "@(#)$Id$"; 39263936Sbr#endif 40263936Sbr 41263936Sbrextern char *optarg; 42263936Sbrextern int optind; 43263936Sbr 44263936Sbr#define NPORTS 21 45263936Sbr 46263936Sbru_short defports[NPORTS] = { 47263936Sbr 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 48263936Sbr 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 49263936Sbr }; 50263936Sbru_short pweights[NPORTS] = { 51263936Sbr 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52263936Sbr 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 53263936Sbr }; 54263936Sbr 55263936Sbripsd_t *iphits[NPORTS]; 56263936Sbrint pkts; 57263936Sbr 58263936Sbr 59263936Sbrint ipcmp(sh1, sh2) 60263936Sbr sdhit_t *sh1, *sh2; 61263936Sbr{ 62263936Sbr return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 63263936Sbr} 64263936Sbr 65263936Sbr 66263936Sbrint ssipcmp(sh1, sh2) 67263936Sbr ipss_t *sh1, *sh2; 68263936Sbr{ 69263936Sbr return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; 70263936Sbr} 71263936Sbr 72263936Sbr 73263936Sbrint countpbits(num) 74263936Sbr u_long num; 75263936Sbr{ 76263936Sbr int i, j; 77263936Sbr 78263936Sbr for (i = 1, j = 0; i; i <<= 1) 79263936Sbr if (num & i) 80263936Sbr j++; 81263936Sbr return j; 82263936Sbr} 83263936Sbr 84263936Sbr 85263936Sbr/* 86263936Sbr * Check to see if we've already received a packet from this host for this 87263936Sbr * port. 88263936Sbr */ 89263936Sbrint findhit(ihp, src, dport) 90263936Sbr ipsd_t *ihp; 91263936Sbr struct in_addr src; 92263936Sbr u_short dport; 93263936Sbr{ 94263936Sbr int i, j, k; 95263936Sbr sdhit_t *sh; 96263936Sbr 97263936Sbr sh = NULL; 98263936Sbr 99263936Sbr if (ihp->sd_sz == 4) { 100263936Sbr for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 101263936Sbr if (src.s_addr == sh->sh_ip.s_addr) 102263936Sbr return 1; 103263936Sbr } else { 104263936Sbr for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 105263936Sbr k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 106263936Sbr if (!k) 107263936Sbr return 1; 108263936Sbr else if (k < 0) 109263936Sbr i -= j; 110263936Sbr else 111263936Sbr i += j; 112263936Sbr } 113263936Sbr } 114263936Sbr return 0; 115263936Sbr} 116263936Sbr 117263936Sbr 118263936Sbr/* 119263936Sbr * Search for port number amongst the sorted array of targets we're 120263936Sbr * interested in. 121263936Sbr */ 122263936Sbrint detect(srcip, dport, date) 123263936Sbr struct in_addr srcip; 124263936Sbr u_short dport; 125263936Sbr time_t date; 126263936Sbr{ 127263936Sbr ipsd_t *ihp; 128263936Sbr sdhit_t *sh; 129263936Sbr int i, j, k; 130263936Sbr 131263936Sbr for (i = 10, j = 4; j >= 0; j--) { 132263936Sbr k = dport - defports[i]; 133263936Sbr if (!k) { 134263936Sbr ihp = iphits[i]; 135263936Sbr if (findhit(ihp, srcip, dport)) 136263936Sbr return 0; 137263936Sbr sh = ihp->sd_hit + ihp->sd_cnt; 138263936Sbr sh->sh_date = date; 139263936Sbr sh->sh_ip = srcip; 140263936Sbr if (++ihp->sd_cnt == ihp->sd_sz) 141263936Sbr { 142263936Sbr ihp->sd_sz += 8; 143263936Sbr sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 144263936Sbr ihp->sd_hit = sh; 145263936Sbr } 146263936Sbr qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 147263936Sbr return 0; 148263936Sbr } 149263936Sbr if (k < 0) 150263936Sbr i -= j; 151263936Sbr else 152263936Sbr i += j; 153263936Sbr } 154263936Sbr return -1; 155263936Sbr} 156263936Sbr 157263936Sbr 158263936Sbr/* 159263936Sbr * Allocate initial storage for hosts 160263936Sbr */ 161263936Sbrsetuphits() 162263936Sbr{ 163263936Sbr int i; 164263936Sbr 165263936Sbr for (i = 0; i < NPORTS; i++) { 166263936Sbr if (iphits[i]) { 167263936Sbr if (iphits[i]->sd_hit) 168263936Sbr free(iphits[i]->sd_hit); 169263936Sbr free(iphits[i]); 170263936Sbr } 171263936Sbr iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 172263936Sbr iphits[i]->sd_port = defports[i]; 173263936Sbr iphits[i]->sd_cnt = 0; 174263936Sbr iphits[i]->sd_sz = 4; 175263936Sbr iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 176263936Sbr } 177263936Sbr} 178263936Sbr 179263936Sbr 180263936Sbr/* 181263936Sbr * Write statistics out to a file 182263936Sbr */ 183263936Sbraddfile(file) 184263936Sbr char *file; 185263936Sbr{ 186263936Sbr ipsd_t ipsd, *ips = &ipsd; 187263936Sbr sdhit_t hit, *hp; 188263936Sbr char fname[32]; 189263936Sbr int i, fd, sz; 190263936Sbr 191263936Sbr if ((fd = open(file, O_RDONLY)) == -1) { 192263936Sbr perror("open"); 193263936Sbr return; 194263936Sbr } 195263936Sbr 196263936Sbr printf("opened %s\n", file); 197263936Sbr do { 198263936Sbr if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) 199263936Sbr break; 200263936Sbr sz = ips->sd_sz * sizeof(*hp); 201263936Sbr hp = (sdhit_t *)malloc(sz); 202263936Sbr if (read(fd, hp, sz) != sz) 203263936Sbr break; 204263936Sbr for (i = 0; i < ips->sd_cnt; i++) 205263936Sbr detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); 206263936Sbr } while (1); 207263936Sbr (void) close(fd); 208263936Sbr} 209263936Sbr 210263936Sbr 211263936Sbrreadfiles(dir) 212263936Sbr char *dir; 213263936Sbr{ 214263936Sbr struct direct **d; 215263936Sbr int i, j; 216263936Sbr 217263936Sbr d = NULL; 218263936Sbr i = scandir(dir, &d, NULL, NULL); 219263936Sbr 220263936Sbr for (j = 0; j < i; j++) { 221263936Sbr if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) 222263936Sbr continue; 223263936Sbr addfile(d[j]->d_name); 224263936Sbr } 225263936Sbr} 226263936Sbr 227263936Sbr 228263936Sbrvoid printreport(ss, num) 229263936Sbr ipss_t *ss; 230263936Sbr int num; 231263936Sbr{ 232263936Sbr struct in_addr ip; 233263936Sbr ipss_t *sp; 234263936Sbr int i, j, mask; 235263936Sbr u_long ports; 236263936Sbr 237263936Sbr printf("Hosts detected: %d\n", num); 238263936Sbr if (!num) 239263936Sbr return; 240263936Sbr for (i = 0; i < num; i++) 241263936Sbr printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, 242263936Sbr countpbits(ss[i].ss_ports)); 243263936Sbr 244263936Sbr printf("--------------------------\n"); 245263936Sbr for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { 246263936Sbr ip.s_addr = ss[0].ss_ip.s_addr & mask; 247263936Sbr ports = ss[0].ss_ports; 248263936Sbr for (i = 1; i < num; i++) { 249263936Sbr sp = ss + i; 250263936Sbr if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { 251263936Sbr printf("Netmask: 0x%08x\n", mask); 252263936Sbr printf("%s %d\n", inet_ntoa(ip), 253263936Sbr countpbits(ports)); 254263936Sbr ip.s_addr = sp->ss_ip.s_addr & mask; 255263936Sbr ports = 0; 256263936Sbr } 257263936Sbr ports |= sp->ss_ports; 258263936Sbr } 259263936Sbr if (ports) { 260263936Sbr printf("Netmask: 0x%08x\n", mask); 261263936Sbr printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); 262263936Sbr } 263263936Sbr } 264263936Sbr} 265263936Sbr 266263936Sbr 267263936Sbrcollectips() 268263936Sbr{ 269263936Sbr ipsd_t *ips; 270263936Sbr ipss_t *ss; 271263936Sbr int i, num, nip, in, j, k; 272263936Sbr 273263936Sbr for (i = 0; i < NPORTS; i++) 274263936Sbr nip += iphits[i]->sd_cnt; 275263936Sbr 276263936Sbr ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); 277263936Sbr 278263936Sbr for (in = 0, i = 0, num = 0; i < NPORTS; i++) { 279263936Sbr ips = iphits[i]; 280263936Sbr for (j = 0; j < ips->sd_cnt; j++) { 281263936Sbr for (k = 0; k < num; k++) 282263936Sbr if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, 283263936Sbr sizeof(struct in_addr))) { 284263936Sbr ss[k].ss_hits += pweights[i]; 285263936Sbr ss[k].ss_ports |= (1 << i); 286263936Sbr break; 287263936Sbr } 288263936Sbr if (k == num) { 289263936Sbr ss[num].ss_ip = ips->sd_hit[j].sh_ip; 290263936Sbr ss[num].ss_hits = pweights[i]; 291263936Sbr ss[k].ss_ports |= (1 << i); 292263936Sbr num++; 293263936Sbr } 294263936Sbr } 295263936Sbr } 296263936Sbr 297263936Sbr qsort(ss, num, sizeof(*ss), ssipcmp); 298263936Sbr 299263936Sbr printreport(ss, num); 300263936Sbr} 301263936Sbr 302263936Sbr 303263936Sbrmain(argc, argv) 304263936Sbr int argc; 305 char *argv[]; 306{ 307 char c, *name = argv[0], *dir = NULL; 308 int fd; 309 310 setuphits(); 311 dir = dir ? dir : "."; 312 readfiles(dir); 313 collectips(); 314} 315