1/* $FreeBSD$ */ 2 3/* 4 * (C)opyright 1995-1998 Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 */ 9#include <stdio.h> 10#include <fcntl.h> 11#include <signal.h> 12#include <malloc.h> 13#include <netdb.h> 14#include <string.h> 15#include <sys/dir.h> 16#include <sys/types.h> 17#include <sys/time.h> 18#include <sys/socket.h> 19#include <netinet/in.h> 20#include <netinet/in_systm.h> 21#include <netinet/ip.h> 22#include <netinet/tcp.h> 23#include <netinet/udp.h> 24#include <netinet/ip_icmp.h> 25#ifndef linux 26#include <netinet/ip_var.h> 27#include <netinet/tcpip.h> 28#endif 29#include "ip_compat.h" 30#ifdef linux 31#include <linux/sockios.h> 32#include "tcpip.h" 33#endif 34#include "ipsd.h" 35 36#ifndef lint 37static const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; 38static const char rcsid[] = "@(#)$Id$"; 39#endif 40 41extern char *optarg; 42extern int optind; 43 44#define NPORTS 21 45 46u_short defports[NPORTS] = { 47 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 48 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 49 }; 50u_short pweights[NPORTS] = { 51 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 53 }; 54 55ipsd_t *iphits[NPORTS]; 56int pkts; 57 58 59int ipcmp(sh1, sh2) 60 sdhit_t *sh1, *sh2; 61{ 62 return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 63} 64 65 66int ssipcmp(sh1, sh2) 67 ipss_t *sh1, *sh2; 68{ 69 return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; 70} 71 72 73int countpbits(num) 74 u_long num; 75{ 76 int i, j; 77 78 for (i = 1, j = 0; i; i <<= 1) 79 if (num & i) 80 j++; 81 return j; 82} 83 84 85/* 86 * Check to see if we've already received a packet from this host for this 87 * port. 88 */ 89int findhit(ihp, src, dport) 90 ipsd_t *ihp; 91 struct in_addr src; 92 u_short dport; 93{ 94 int i, j, k; 95 sdhit_t *sh; 96 97 sh = NULL; 98 99 if (ihp->sd_sz == 4) { 100 for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 101 if (src.s_addr == sh->sh_ip.s_addr) 102 return 1; 103 } else { 104 for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 105 k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 106 if (!k) 107 return 1; 108 else if (k < 0) 109 i -= j; 110 else 111 i += j; 112 } 113 } 114 return 0; 115} 116 117 118/* 119 * Search for port number amongst the sorted array of targets we're 120 * interested in. 121 */ 122int detect(srcip, dport, date) 123 struct in_addr srcip; 124 u_short dport; 125 time_t date; 126{ 127 ipsd_t *ihp; 128 sdhit_t *sh; 129 int i, j, k; 130 131 for (i = 10, j = 4; j >= 0; j--) { 132 k = dport - defports[i]; 133 if (!k) { 134 ihp = iphits[i]; 135 if (findhit(ihp, srcip, dport)) 136 return 0; 137 sh = ihp->sd_hit + ihp->sd_cnt; 138 sh->sh_date = date; 139 sh->sh_ip = srcip; 140 if (++ihp->sd_cnt == ihp->sd_sz) 141 { 142 ihp->sd_sz += 8; 143 sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 144 ihp->sd_hit = sh; 145 } 146 qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 147 return 0; 148 } 149 if (k < 0) 150 i -= j; 151 else 152 i += j; 153 } 154 return -1; 155} 156 157 158/* 159 * Allocate initial storage for hosts 160 */ 161setuphits() 162{ 163 int i; 164 165 for (i = 0; i < NPORTS; i++) { 166 if (iphits[i]) { 167 if (iphits[i]->sd_hit) 168 free(iphits[i]->sd_hit); 169 free(iphits[i]); 170 } 171 iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 172 iphits[i]->sd_port = defports[i]; 173 iphits[i]->sd_cnt = 0; 174 iphits[i]->sd_sz = 4; 175 iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 176 } 177} 178 179 180/* 181 * Write statistics out to a file 182 */ 183addfile(file) 184 char *file; 185{ 186 ipsd_t ipsd, *ips = &ipsd; 187 sdhit_t hit, *hp; 188 char fname[32]; 189 int i, fd, sz; 190 191 if ((fd = open(file, O_RDONLY)) == -1) { 192 perror("open"); 193 return; 194 } 195 196 printf("opened %s\n", file); 197 do { 198 if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) 199 break; 200 sz = ips->sd_sz * sizeof(*hp); 201 hp = (sdhit_t *)malloc(sz); 202 if (read(fd, hp, sz) != sz) 203 break; 204 for (i = 0; i < ips->sd_cnt; i++) 205 detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); 206 } while (1); 207 (void) close(fd); 208} 209 210 211readfiles(dir) 212 char *dir; 213{ 214 struct direct **d; 215 int i, j; 216 217 d = NULL; 218 i = scandir(dir, &d, NULL, NULL); 219 220 for (j = 0; j < i; j++) { 221 if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) 222 continue; 223 addfile(d[j]->d_name); 224 } 225} 226 227 228void printreport(ss, num) 229 ipss_t *ss; 230 int num; 231{ 232 struct in_addr ip; 233 ipss_t *sp; 234 int i, j, mask; 235 u_long ports; 236 237 printf("Hosts detected: %d\n", num); 238 if (!num) 239 return; 240 for (i = 0; i < num; i++) 241 printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, 242 countpbits(ss[i].ss_ports)); 243 244 printf("--------------------------\n"); 245 for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { 246 ip.s_addr = ss[0].ss_ip.s_addr & mask; 247 ports = ss[0].ss_ports; 248 for (i = 1; i < num; i++) { 249 sp = ss + i; 250 if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { 251 printf("Netmask: 0x%08x\n", mask); 252 printf("%s %d\n", inet_ntoa(ip), 253 countpbits(ports)); 254 ip.s_addr = sp->ss_ip.s_addr & mask; 255 ports = 0; 256 } 257 ports |= sp->ss_ports; 258 } 259 if (ports) { 260 printf("Netmask: 0x%08x\n", mask); 261 printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); 262 } 263 } 264} 265 266 267collectips() 268{ 269 ipsd_t *ips; 270 ipss_t *ss; 271 int i, num, nip, in, j, k; 272 273 for (i = 0; i < NPORTS; i++) 274 nip += iphits[i]->sd_cnt; 275 276 ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); 277 278 for (in = 0, i = 0, num = 0; i < NPORTS; i++) { 279 ips = iphits[i]; 280 for (j = 0; j < ips->sd_cnt; j++) { 281 for (k = 0; k < num; k++) 282 if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, 283 sizeof(struct in_addr))) { 284 ss[k].ss_hits += pweights[i]; 285 ss[k].ss_ports |= (1 << i); 286 break; 287 } 288 if (k == num) { 289 ss[num].ss_ip = ips->sd_hit[j].sh_ip; 290 ss[num].ss_hits = pweights[i]; 291 ss[k].ss_ports |= (1 << i); 292 num++; 293 } 294 } 295 } 296 297 qsort(ss, num, sizeof(*ss), ssipcmp); 298 299 printreport(ss, num); 300} 301 302 303main(argc, argv) 304 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