ipsdr.c revision 255332
1248613Sdes/* $FreeBSD: head/contrib/ipfilter/ipsd/ipsdr.c 255332 2013-09-06 23:11:19Z cy $ */ 2204861Sdes 3204861Sdes/* 4204861Sdes * (C)opyright 1995-1998 Darren Reed. 5204861Sdes * 6218767Sdes * See the IPFILTER.LICENCE file for details on licencing. 7218767Sdes * 8218767Sdes */ 9218767Sdes#include <stdio.h> 10218767Sdes#include <fcntl.h> 11218767Sdes#include <signal.h> 12204861Sdes#include <malloc.h> 13204861Sdes#include <netdb.h> 14204861Sdes#include <string.h> 15204861Sdes#include <sys/dir.h> 16204861Sdes#include <sys/types.h> 17204861Sdes#include <sys/time.h> 18204861Sdes#include <sys/socket.h> 19204861Sdes#include <netinet/in.h> 20218767Sdes#include <netinet/in_systm.h> 21204861Sdes#include <netinet/ip.h> 22204861Sdes#include <netinet/tcp.h> 23204861Sdes#include <netinet/udp.h> 24204861Sdes#include <netinet/ip_icmp.h> 25248613Sdes#ifndef linux 26248613Sdes#include <netinet/ip_var.h> 27204861Sdes#include <netinet/tcpip.h> 28218767Sdes#endif 29225825Sdes#include "ip_compat.h" 30214979Sdes#ifdef linux 31214979Sdes#include <linux/sockios.h> 32214979Sdes#include "tcpip.h" 33214979Sdes#endif 34214979Sdes#include "ipsd.h" 35214979Sdes 36204861Sdes#ifndef lint 37204861Sdesstatic const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; 38214979Sdesstatic const char rcsid[] = "@(#)$Id$"; 39218767Sdes#endif 40214979Sdes 41214979Sdesextern char *optarg; 42214979Sdesextern int optind; 43214979Sdes 44214979Sdes#define NPORTS 21 45214979Sdes 46214979Sdesu_short defports[NPORTS] = { 47214979Sdes 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 48214979Sdes 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 49214979Sdes }; 50214979Sdesu_short pweights[NPORTS] = { 51214979Sdes 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52214979Sdes 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 53214979Sdes }; 54214979Sdes 55214979Sdesipsd_t *iphits[NPORTS]; 56214979Sdesint pkts; 57214979Sdes 58214979Sdes 59214979Sdesint ipcmp(sh1, sh2) 60214979Sdes sdhit_t *sh1, *sh2; 61214979Sdes{ 62214979Sdes return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 63214979Sdes} 64214979Sdes 65214979Sdes 66214979Sdesint ssipcmp(sh1, sh2) 67214979Sdes ipss_t *sh1, *sh2; 68214979Sdes{ 69214979Sdes return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; 70214979Sdes} 71214979Sdes 72214979Sdes 73214979Sdesint countpbits(num) 74214979Sdes u_long num; 75214979Sdes{ 76214979Sdes int i, j; 77214979Sdes 78214979Sdes for (i = 1, j = 0; i; i <<= 1) 79214979Sdes if (num & i) 80214979Sdes j++; 81214979Sdes return j; 82214979Sdes} 83214979Sdes 84214979Sdes 85214979Sdes/* 86214979Sdes * Check to see if we've already received a packet from this host for this 87214979Sdes * port. 88214979Sdes */ 89214979Sdesint findhit(ihp, src, dport) 90214979Sdes ipsd_t *ihp; 91214979Sdes struct in_addr src; 92214979Sdes u_short dport; 93214979Sdes{ 94214979Sdes int i, j, k; 95214979Sdes sdhit_t *sh; 96214979Sdes 97214979Sdes sh = NULL; 98214979Sdes 99214979Sdes if (ihp->sd_sz == 4) { 100214979Sdes for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 101214979Sdes if (src.s_addr == sh->sh_ip.s_addr) 102214979Sdes return 1; 103214979Sdes } else { 104214979Sdes for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 105214979Sdes k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 106214979Sdes if (!k) 107214979Sdes return 1; 108214979Sdes else if (k < 0) 109214979Sdes i -= j; 110214979Sdes else 111214979Sdes i += j; 112214979Sdes } 113214979Sdes } 114214979Sdes return 0; 115214979Sdes} 116214979Sdes 117214979Sdes 118214979Sdes/* 119214979Sdes * Search for port number amongst the sorted array of targets we're 120214979Sdes * interested in. 121214979Sdes */ 122214979Sdesint detect(srcip, dport, date) 123214979Sdes struct in_addr srcip; 124214979Sdes u_short dport; 125214979Sdes time_t date; 126214979Sdes{ 127214979Sdes ipsd_t *ihp; 128214979Sdes sdhit_t *sh; 129214979Sdes int i, j, k; 130214979Sdes 131214979Sdes for (i = 10, j = 4; j >= 0; j--) { 132214979Sdes k = dport - defports[i]; 133214979Sdes if (!k) { 134214979Sdes ihp = iphits[i]; 135214979Sdes if (findhit(ihp, srcip, dport)) 136214979Sdes return 0; 137214979Sdes sh = ihp->sd_hit + ihp->sd_cnt; 138214979Sdes sh->sh_date = date; 139214979Sdes sh->sh_ip = srcip; 140214979Sdes if (++ihp->sd_cnt == ihp->sd_sz) 141214979Sdes { 142214979Sdes ihp->sd_sz += 8; 143214979Sdes sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 144214979Sdes ihp->sd_hit = sh; 145214979Sdes } 146214979Sdes qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 147214979Sdes return 0; 148214979Sdes } 149214979Sdes if (k < 0) 150214979Sdes i -= j; 151214979Sdes else 152204861Sdes i += j; 153204861Sdes } 154204861Sdes return -1; 155204861Sdes} 156204861Sdes 157204861Sdes 158204861Sdes/* 159204861Sdes * Allocate initial storage for hosts 160204861Sdes */ 161204861Sdessetuphits() 162204861Sdes{ 163204861Sdes int i; 164204861Sdes 165218767Sdes for (i = 0; i < NPORTS; i++) { 166204861Sdes if (iphits[i]) { 167204861Sdes if (iphits[i]->sd_hit) 168204861Sdes free(iphits[i]->sd_hit); 169204861Sdes free(iphits[i]); 170204861Sdes } 171204861Sdes iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 172204861Sdes iphits[i]->sd_port = defports[i]; 173204861Sdes iphits[i]->sd_cnt = 0; 174204861Sdes iphits[i]->sd_sz = 4; 175204861Sdes iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 176204861Sdes } 177204861Sdes} 178204861Sdes 179204861Sdes 180204861Sdes/* 181204861Sdes * Write statistics out to a file 182204861Sdes */ 183204861Sdesaddfile(file) 184204861Sdes char *file; 185204861Sdes{ 186204861Sdes ipsd_t ipsd, *ips = &ipsd; 187248613Sdes sdhit_t hit, *hp; 188204861Sdes char fname[32]; 189204861Sdes int i, fd, sz; 190248613Sdes 191248613Sdes if ((fd = open(file, O_RDONLY)) == -1) { 192204861Sdes perror("open"); 193204861Sdes return; 194204861Sdes } 195204861Sdes 196204861Sdes printf("opened %s\n", file); 197248613Sdes do { 198248613Sdes if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) 199248613Sdes break; 200248613Sdes sz = ips->sd_sz * sizeof(*hp); 201248613Sdes hp = (sdhit_t *)malloc(sz); 202248613Sdes if (read(fd, hp, sz) != sz) 203248613Sdes break; 204248613Sdes for (i = 0; i < ips->sd_cnt; i++) 205248613Sdes detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); 206248613Sdes } while (1); 207248613Sdes (void) close(fd); 208248613Sdes} 209248613Sdes 210248613Sdes 211248613Sdesreadfiles(dir) 212248613Sdes char *dir; 213204861Sdes{ 214204861Sdes struct direct **d; 215204861Sdes int i, j; 216204861Sdes 217204861Sdes d = NULL; 218204861Sdes i = scandir(dir, &d, NULL, NULL); 219204861Sdes 220204861Sdes for (j = 0; j < i; j++) { 221204861Sdes if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) 222204861Sdes continue; 223204861Sdes addfile(d[j]->d_name); 224204861Sdes } 225204861Sdes} 226204861Sdes 227204861Sdes 228204861Sdesvoid printreport(ss, num) 229204861Sdes ipss_t *ss; 230204861Sdes int num; 231204861Sdes{ 232204861Sdes struct in_addr ip; 233204861Sdes ipss_t *sp; 234204861Sdes int i, j, mask; 235204861Sdes u_long ports; 236204861Sdes 237204861Sdes printf("Hosts detected: %d\n", num); 238204861Sdes if (!num) 239204861Sdes return; 240204861Sdes for (i = 0; i < num; i++) 241204861Sdes printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, 242204861Sdes countpbits(ss[i].ss_ports)); 243204861Sdes 244204861Sdes printf("--------------------------\n"); 245204861Sdes for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { 246204861Sdes ip.s_addr = ss[0].ss_ip.s_addr & mask; 247204861Sdes ports = ss[0].ss_ports; 248204861Sdes for (i = 1; i < num; i++) { 249204861Sdes sp = ss + i; 250214979Sdes if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { 251204861Sdes printf("Netmask: 0x%08x\n", mask); 252204861Sdes printf("%s %d\n", inet_ntoa(ip), 253204861Sdes countpbits(ports)); 254204861Sdes ip.s_addr = sp->ss_ip.s_addr & mask; 255204861Sdes ports = 0; 256204861Sdes } 257214979Sdes ports |= sp->ss_ports; 258218767Sdes } 259218767Sdes if (ports) { 260218767Sdes printf("Netmask: 0x%08x\n", mask); 261218767Sdes printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); 262218767Sdes } 263214979Sdes } 264214979Sdes} 265214979Sdes 266214979Sdes 267214979Sdescollectips() 268214979Sdes{ 269214979Sdes ipsd_t *ips; 270214979Sdes ipss_t *ss; 271214979Sdes int i, num, nip, in, j, k; 272214979Sdes 273214979Sdes for (i = 0; i < NPORTS; i++) 274214979Sdes nip += iphits[i]->sd_cnt; 275214979Sdes 276214979Sdes ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); 277214979Sdes 278214979Sdes for (in = 0, i = 0, num = 0; i < NPORTS; i++) { 279214979Sdes ips = iphits[i]; 280214979Sdes for (j = 0; j < ips->sd_cnt; j++) { 281214979Sdes for (k = 0; k < num; k++) 282218767Sdes if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, 283214979Sdes sizeof(struct in_addr))) { 284214979Sdes ss[k].ss_hits += pweights[i]; 285204861Sdes ss[k].ss_ports |= (1 << i); 286214979Sdes break; 287214979Sdes } 288214979Sdes if (k == num) { 289214979Sdes ss[num].ss_ip = ips->sd_hit[j].sh_ip; 290214979Sdes ss[num].ss_hits = pweights[i]; 291214979Sdes ss[k].ss_ports |= (1 << i); 292214979Sdes num++; 293214979Sdes } 294214979Sdes } 295214979Sdes } 296214979Sdes 297204861Sdes qsort(ss, num, sizeof(*ss), ssipcmp); 298214979Sdes 299204861Sdes printreport(ss, num); 300204861Sdes} 301204861Sdes 302204861Sdes 303204861Sdesmain(argc, argv) 304204861Sdes int argc; 305204861Sdes char *argv[]; 306204861Sdes{ 307204861Sdes char c, *name = argv[0], *dir = NULL; 308204861Sdes int fd; 309204861Sdes 310204861Sdes setuphits(); 311204861Sdes dir = dir ? dir : "."; 312204861Sdes readfiles(dir); 313204861Sdes collectips(); 314204861Sdes} 315214979Sdes