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