155682Smarkm/* $FreeBSD$ */ 2120945Snectar 355682Smarkm/* 455682Smarkm * (C)opyright 1995-1998 Darren Reed. 555682Smarkm * 655682Smarkm * See the IPFILTER.LICENCE file for details on licencing. 755682Smarkm * 855682Smarkm */ 955682Smarkm#include <stdio.h> 1055682Smarkm#include <fcntl.h> 1155682Smarkm#include <signal.h> 1255682Smarkm#include <malloc.h> 1355682Smarkm#include <netdb.h> 1455682Smarkm#include <string.h> 1555682Smarkm#include <sys/dir.h> 1655682Smarkm#include <sys/types.h> 1755682Smarkm#include <sys/time.h> 1855682Smarkm#include <sys/socket.h> 1955682Smarkm#include <netinet/in.h> 2055682Smarkm#include <netinet/in_systm.h> 2155682Smarkm#include <netinet/ip.h> 2255682Smarkm#include <netinet/tcp.h> 2355682Smarkm#include <netinet/udp.h> 2455682Smarkm#include <netinet/ip_icmp.h> 2555682Smarkm#ifndef linux 2655682Smarkm#include <netinet/ip_var.h> 2755682Smarkm#include <netinet/tcpip.h> 2855682Smarkm#endif 2955682Smarkm#include "ip_compat.h" 3055682Smarkm#ifdef linux 3155682Smarkm#include <linux/sockios.h> 3255682Smarkm#include "tcpip.h" 3355682Smarkm#endif 3455682Smarkm#include "ipsd.h" 3555682Smarkm 3655682Smarkm#ifndef lint 3755682Smarkmstatic const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; 3855682Smarkmstatic const char rcsid[] = "@(#)$Id$"; 3955682Smarkm#endif 40127808Snectar 4155682Smarkmextern char *optarg; 4255682Smarkmextern int optind; 4355682Smarkm 4455682Smarkm#define NPORTS 21 4555682Smarkm 4655682Smarkmu_short defports[NPORTS] = { 4772445Sassar 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 4855682Smarkm 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 4955682Smarkm }; 5055682Smarkmu_short pweights[NPORTS] = { 5155682Smarkm 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5255682Smarkm 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 5355682Smarkm }; 5455682Smarkm 5555682Smarkmipsd_t *iphits[NPORTS]; 5655682Smarkmint pkts; 5755682Smarkm 5855682Smarkm 5955682Smarkmint ipcmp(sh1, sh2) 6055682Smarkm sdhit_t *sh1, *sh2; 6155682Smarkm{ 6255682Smarkm return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 6355682Smarkm} 6455682Smarkm 6555682Smarkm 6655682Smarkmint ssipcmp(sh1, sh2) 6755682Smarkm ipss_t *sh1, *sh2; 6855682Smarkm{ 6955682Smarkm return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; 7055682Smarkm} 7155682Smarkm 7255682Smarkm 7355682Smarkmint countpbits(num) 7455682Smarkm u_long num; 75127808Snectar{ 76127808Snectar int i, j; 7755682Smarkm 78127808Snectar for (i = 1, j = 0; i; i <<= 1) 79127808Snectar if (num & i) 80127808Snectar j++; 81127808Snectar return j; 82127808Snectar} 83127808Snectar 84127808Snectar 85127808Snectar/* 8655682Smarkm * Check to see if we've already received a packet from this host for this 8755682Smarkm * port. 8855682Smarkm */ 8955682Smarkmint findhit(ihp, src, dport) 9055682Smarkm ipsd_t *ihp; 9155682Smarkm struct in_addr src; 92127808Snectar u_short dport; 93127808Snectar{ 94127808Snectar int i, j, k; 9555682Smarkm sdhit_t *sh; 96127808Snectar 9755682Smarkm sh = NULL; 9855682Smarkm 9955682Smarkm if (ihp->sd_sz == 4) { 10055682Smarkm for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 101127808Snectar if (src.s_addr == sh->sh_ip.s_addr) 10255682Smarkm return 1; 103127808Snectar } else { 104127808Snectar for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 105127808Snectar k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 10655682Smarkm if (!k) 10755682Smarkm return 1; 10855682Smarkm else if (k < 0) 10955682Smarkm i -= j; 11055682Smarkm else 11155682Smarkm i += j; 11255682Smarkm } 11355682Smarkm } 11455682Smarkm return 0; 11555682Smarkm} 11655682Smarkm 11755682Smarkm 11855682Smarkm/* 11955682Smarkm * Search for port number amongst the sorted array of targets we're 12055682Smarkm * interested in. 12155682Smarkm */ 12255682Smarkmint detect(srcip, dport, date) 12355682Smarkm struct in_addr srcip; 12455682Smarkm u_short dport; 12555682Smarkm time_t date; 12655682Smarkm{ 12755682Smarkm ipsd_t *ihp; 12855682Smarkm sdhit_t *sh; 12955682Smarkm int i, j, k; 13055682Smarkm 13155682Smarkm for (i = 10, j = 4; j >= 0; j--) { 13255682Smarkm k = dport - defports[i]; 13355682Smarkm if (!k) { 13455682Smarkm ihp = iphits[i]; 13555682Smarkm if (findhit(ihp, srcip, dport)) 13655682Smarkm return 0; 13755682Smarkm sh = ihp->sd_hit + ihp->sd_cnt; 13855682Smarkm sh->sh_date = date; 13955682Smarkm sh->sh_ip = srcip; 14055682Smarkm if (++ihp->sd_cnt == ihp->sd_sz) 14155682Smarkm { 14255682Smarkm ihp->sd_sz += 8; 14355682Smarkm sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 14455682Smarkm ihp->sd_hit = sh; 14555682Smarkm } 14655682Smarkm qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 14755682Smarkm return 0; 14855682Smarkm } 14955682Smarkm if (k < 0) 15055682Smarkm i -= j; 15155682Smarkm else 15255682Smarkm i += j; 15355682Smarkm } 15455682Smarkm return -1; 15555682Smarkm} 15655682Smarkm 15755682Smarkm 15855682Smarkm/* 15955682Smarkm * Allocate initial storage for hosts 16055682Smarkm */ 16190926Snectarsetuphits() 16290926Snectar{ 16390926Snectar int i; 16490926Snectar 16590926Snectar for (i = 0; i < NPORTS; i++) { 16690926Snectar if (iphits[i]) { 16790926Snectar if (iphits[i]->sd_hit) 16857416Smarkm free(iphits[i]->sd_hit); 16957416Smarkm free(iphits[i]); 17057416Smarkm } 17155682Smarkm iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 17255682Smarkm iphits[i]->sd_port = defports[i]; 17355682Smarkm iphits[i]->sd_cnt = 0; 17455682Smarkm iphits[i]->sd_sz = 4; 17555682Smarkm iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 17655682Smarkm } 17755682Smarkm} 17855682Smarkm 17955682Smarkm 18055682Smarkm/* 18155682Smarkm * Write statistics out to a file 18255682Smarkm */ 18355682Smarkmaddfile(file) 18455682Smarkm char *file; 18555682Smarkm{ 18655682Smarkm ipsd_t ipsd, *ips = &ipsd; 18755682Smarkm sdhit_t hit, *hp; 18855682Smarkm char fname[32]; 18955682Smarkm int i, fd, sz; 19055682Smarkm 19155682Smarkm if ((fd = open(file, O_RDONLY)) == -1) { 19255682Smarkm perror("open"); 19355682Smarkm return; 19455682Smarkm } 19555682Smarkm 19655682Smarkm printf("opened %s\n", file); 19755682Smarkm do { 19855682Smarkm if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) 19955682Smarkm break; 20055682Smarkm sz = ips->sd_sz * sizeof(*hp); 20155682Smarkm hp = (sdhit_t *)malloc(sz); 20255682Smarkm if (read(fd, hp, sz) != sz) 20355682Smarkm break; 20455682Smarkm for (i = 0; i < ips->sd_cnt; i++) 20555682Smarkm detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); 20655682Smarkm } while (1); 20755682Smarkm (void) close(fd); 20855682Smarkm} 20955682Smarkm 21055682Smarkm 21155682Smarkmreadfiles(dir) 21255682Smarkm char *dir; 21355682Smarkm{ 21455682Smarkm struct direct **d; 21555682Smarkm int i, j; 21655682Smarkm 21755682Smarkm d = NULL; 21855682Smarkm i = scandir(dir, &d, NULL, NULL); 21955682Smarkm 22055682Smarkm for (j = 0; j < i; j++) { 22155682Smarkm if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) 22255682Smarkm continue; 22355682Smarkm addfile(d[j]->d_name); 22455682Smarkm } 22555682Smarkm} 22655682Smarkm 22755682Smarkm 22855682Smarkmvoid printreport(ss, num) 22955682Smarkm ipss_t *ss; 23055682Smarkm int num; 23155682Smarkm{ 23255682Smarkm struct in_addr ip; 23355682Smarkm ipss_t *sp; 23455682Smarkm int i, j, mask; 23555682Smarkm u_long ports; 23655682Smarkm 23755682Smarkm printf("Hosts detected: %d\n", num); 23855682Smarkm if (!num) 23955682Smarkm return; 24055682Smarkm for (i = 0; i < num; i++) 24155682Smarkm printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, 24255682Smarkm countpbits(ss[i].ss_ports)); 24355682Smarkm 24455682Smarkm printf("--------------------------\n"); 24555682Smarkm for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { 24655682Smarkm ip.s_addr = ss[0].ss_ip.s_addr & mask; 24755682Smarkm ports = ss[0].ss_ports; 24855682Smarkm for (i = 1; i < num; i++) { 24955682Smarkm sp = ss + i; 25055682Smarkm if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { 25155682Smarkm printf("Netmask: 0x%08x\n", mask); 25255682Smarkm printf("%s %d\n", inet_ntoa(ip), 25355682Smarkm countpbits(ports)); 25455682Smarkm ip.s_addr = sp->ss_ip.s_addr & mask; 25555682Smarkm ports = 0; 256102644Snectar } 257102644Snectar ports |= sp->ss_ports; 258102644Snectar } 259102644Snectar if (ports) { 260102644Snectar printf("Netmask: 0x%08x\n", mask); 261102644Snectar printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); 262102644Snectar } 263102644Snectar } 264102644Snectar} 265102644Snectar 266102644Snectar 267102644Snectarcollectips() 268102644Snectar{ 269102644Snectar ipsd_t *ips; 270102644Snectar ipss_t *ss; 271102644Snectar int i, num, nip, in, j, k; 272102644Snectar 273102644Snectar for (i = 0; i < NPORTS; i++) 274102644Snectar nip += iphits[i]->sd_cnt; 275102644Snectar 27655682Smarkm ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); 27755682Smarkm 278102644Snectar for (in = 0, i = 0, num = 0; i < NPORTS; i++) { 279102644Snectar ips = iphits[i]; 280102644Snectar for (j = 0; j < ips->sd_cnt; j++) { 281102644Snectar for (k = 0; k < num; k++) 282102644Snectar if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, 283102644Snectar sizeof(struct in_addr))) { 284102644Snectar ss[k].ss_hits += pweights[i]; 285102644Snectar ss[k].ss_ports |= (1 << i); 286102644Snectar break; 287102644Snectar } 288102644Snectar if (k == num) { 289102644Snectar ss[num].ss_ip = ips->sd_hit[j].sh_ip; 29055682Smarkm ss[num].ss_hits = pweights[i]; 291102644Snectar ss[k].ss_ports |= (1 << i); 292102644Snectar num++; 293102644Snectar } 294102644Snectar } 29555682Smarkm } 29655682Smarkm 29755682Smarkm qsort(ss, num, sizeof(*ss), ssipcmp); 29855682Smarkm 29955682Smarkm printreport(ss, num); 30055682Smarkm} 30155682Smarkm 30255682Smarkm 30355682Smarkmmain(argc, argv) 30455682Smarkm int argc; 30555682Smarkm char *argv[]; 30655682Smarkm{ 30755682Smarkm char c, *name = argv[0], *dir = NULL; 30855682Smarkm int fd; 30955682Smarkm 31055682Smarkm setuphits(); 31155682Smarkm dir = dir ? dir : "."; 31255682Smarkm readfiles(dir); 31355682Smarkm collectips(); 31455682Smarkm} 31555682Smarkm