ipsdr.c revision 22514
190075Sobrien/* 2169689Skan * (C)opyright December 1995 Darren Reed. 3132718Skan * 490075Sobrien * This software may be freely distributed as long as it is not altered 5132718Skan * in any way and that this messagge always accompanies it. 690075Sobrien * 7132718Skan * The author of this software makes no garuntee about the 890075Sobrien * performance of this package or its suitability to fulfill any purpose. 990075Sobrien * 1090075Sobrien */ 1190075Sobrien#include <stdio.h> 12132718Skan#include <fcntl.h> 1390075Sobrien#include <signal.h> 1490075Sobrien#include <malloc.h> 1590075Sobrien#include <netdb.h> 1690075Sobrien#include <string.h> 1790075Sobrien#include <sys/dir.h> 18132718Skan#include <sys/types.h> 19169689Skan#include <sys/time.h> 20169689Skan#include <sys/socket.h> 2190075Sobrien#include <netinet/in.h> 2290075Sobrien#include <netinet/in_systm.h> 2390075Sobrien#include <netinet/ip.h> 2490075Sobrien#include <netinet/tcp.h> 25117395Skan#include <netinet/udp.h> 26117395Skan#include <netinet/ip_icmp.h> 2790075Sobrien#ifndef linux 2890075Sobrien#include <netinet/ip_var.h> 2990075Sobrien#include <netinet/tcpip.h> 3090075Sobrien#endif 31132718Skan#include "ip_compat.h" 3290075Sobrien#ifdef linux 33132718Skan#include <linux/sockios.h> 34132718Skan#include "tcpip.h" 35132718Skan#endif 3690075Sobrien#include "ipsd.h" 37169689Skan 38169689Skan#ifndef lint 39169689Skanstatic char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; 40169689Skan#endif 41169689Skan 42132718Skanextern char *optarg; 43132718Skanextern int optind; 44169689Skan 45132718Skan#define NPORTS 21 46132718Skan 47132718Skanu_short defports[NPORTS] = { 48132718Skan 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, 49169689Skan 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 50132718Skan }; 51169689Skanu_short pweights[NPORTS] = { 52169689Skan 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 53169689Skan 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 54169689Skan }; 55132718Skan 56132718Skanipsd_t *iphits[NPORTS]; 57132718Skanint pkts; 58169689Skan 5990075Sobrien 60132718Skanint ipcmp(sh1, sh2) 61132718Skansdhit_t *sh1, *sh2; 62132718Skan{ 6390075Sobrien return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; 64132718Skan} 65169689Skan 66132718Skan 6790075Sobrienint ssipcmp(sh1, sh2) 68132718Skanipss_t *sh1, *sh2; 69132718Skan{ 70132718Skan return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; 71169689Skan} 72132718Skan 73132718Skan 74132718Skanint countpbits(num) 75132718Skanu_long num; 7690075Sobrien{ 7790075Sobrien int i, j; 7890075Sobrien 7990075Sobrien for (i = 1, j = 0; i; i <<= 1) 80132718Skan if (num & i) 81132718Skan j++; 82132718Skan return j; 83132718Skan} 84132718Skan 8590075Sobrien 8690075Sobrien/* 87132718Skan * Check to see if we've already received a packet from this host for this 88132718Skan * port. 89169689Skan */ 90132718Skanint findhit(ihp, src, dport) 9190075Sobrienipsd_t *ihp; 9290075Sobrienstruct in_addr src; 93132718Skanu_short dport; 94132718Skan{ 95132718Skan int i, j, k; 96132718Skan sdhit_t *sh; 97132718Skan 98132718Skan sh = NULL; 99132718Skan 100132718Skan if (ihp->sd_sz == 4) { 10190075Sobrien for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) 102132718Skan if (src.s_addr == sh->sh_ip.s_addr) 103132718Skan return 1; 104122180Skan } else { 10590075Sobrien for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { 10690075Sobrien k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; 107132718Skan if (!k) 10890075Sobrien return 1; 109117395Skan else if (k < 0) 110132718Skan i -= j; 111169689Skan else 112169689Skan i += j; 113169689Skan } 114169689Skan } 115 return 0; 116} 117 118 119/* 120 * Search for port number amongst the sorted array of targets we're 121 * interested in. 122 */ 123int detect(srcip, dport, date) 124struct in_addr srcip; 125u_short dport; 126time_t date; 127{ 128 ipsd_t *ihp; 129 sdhit_t *sh; 130 int i, j, k; 131 132 for (i = 10, j = 4; j >= 0; j--) { 133 k = dport - defports[i]; 134 if (!k) { 135 ihp = iphits[i]; 136 if (findhit(ihp, srcip, dport)) 137 return 0; 138 sh = ihp->sd_hit + ihp->sd_cnt; 139 sh->sh_date = date; 140 sh->sh_ip = srcip; 141 if (++ihp->sd_cnt == ihp->sd_sz) 142 { 143 ihp->sd_sz += 8; 144 sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); 145 ihp->sd_hit = sh; 146 } 147 qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); 148 return 0; 149 } 150 if (k < 0) 151 i -= j; 152 else 153 i += j; 154 } 155 return -1; 156} 157 158 159/* 160 * Allocate initial storage for hosts 161 */ 162setuphits() 163{ 164 int i; 165 166 for (i = 0; i < NPORTS; i++) { 167 if (iphits[i]) { 168 if (iphits[i]->sd_hit) 169 free(iphits[i]->sd_hit); 170 free(iphits[i]); 171 } 172 iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); 173 iphits[i]->sd_port = defports[i]; 174 iphits[i]->sd_cnt = 0; 175 iphits[i]->sd_sz = 4; 176 iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); 177 } 178} 179 180 181/* 182 * Write statistics out to a file 183 */ 184addfile(file) 185char *file; 186{ 187 ipsd_t ipsd, *ips = &ipsd; 188 sdhit_t hit, *hp; 189 char fname[32]; 190 int i, fd, sz; 191 192 if ((fd = open(file, O_RDONLY)) == -1) { 193 perror("open"); 194 return; 195 } 196 197 printf("opened %s\n", file); 198 do { 199 if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) 200 break; 201 sz = ips->sd_sz * sizeof(*hp); 202 hp = (sdhit_t *)malloc(sz); 203 if (read(fd, hp, sz) != sz) 204 break; 205 for (i = 0; i < ips->sd_cnt; i++) 206 detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); 207 } while (1); 208 (void) close(fd); 209} 210 211 212readfiles(dir) 213char *dir; 214{ 215 struct direct **d; 216 int i, j; 217 218 d = NULL; 219 i = scandir(dir, &d, NULL, NULL); 220 221 for (j = 0; j < i; j++) { 222 if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) 223 continue; 224 addfile(d[j]->d_name); 225 } 226} 227 228 229void printreport(ss, num) 230ipss_t *ss; 231int num; 232{ 233 struct in_addr ip; 234 ipss_t *sp; 235 int i, j, mask; 236 u_long ports; 237 238 printf("Hosts detected: %d\n", num); 239 if (!num) 240 return; 241 for (i = 0; i < num; i++) 242 printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, 243 countpbits(ss[i].ss_ports)); 244 245 printf("--------------------------\n"); 246 for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { 247 ip.s_addr = ss[0].ss_ip.s_addr & mask; 248 ports = ss[0].ss_ports; 249 for (i = 1; i < num; i++) { 250 sp = ss + i; 251 if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { 252 printf("Netmask: 0x%08x\n", mask); 253 printf("%s %d\n", inet_ntoa(ip), 254 countpbits(ports)); 255 ip.s_addr = sp->ss_ip.s_addr & mask; 256 ports = 0; 257 } 258 ports |= sp->ss_ports; 259 } 260 if (ports) { 261 printf("Netmask: 0x%08x\n", mask); 262 printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); 263 } 264 } 265} 266 267 268collectips() 269{ 270 ipsd_t *ips; 271 ipss_t *ss; 272 int i, num, nip, in, j, k; 273 274 for (i = 0; i < NPORTS; i++) 275 nip += iphits[i]->sd_cnt; 276 277 ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); 278 279 for (in = 0, i = 0, num = 0; i < NPORTS; i++) { 280 ips = iphits[i]; 281 for (j = 0; j < ips->sd_cnt; j++) { 282 for (k = 0; k < num; k++) 283 if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, 284 sizeof(struct in_addr))) { 285 ss[k].ss_hits += pweights[i]; 286 ss[k].ss_ports |= (1 << i); 287 break; 288 } 289 if (k == num) { 290 ss[num].ss_ip = ips->sd_hit[j].sh_ip; 291 ss[num].ss_hits = pweights[i]; 292 ss[k].ss_ports |= (1 << i); 293 num++; 294 } 295 } 296 } 297 298 qsort(ss, num, sizeof(*ss), ssipcmp); 299 300 printreport(ss, num); 301} 302 303 304main(argc, argv) 305int argc; 306char *argv[]; 307{ 308 char c, *name = argv[0], *dir = NULL; 309 int fd; 310 311 setuphits(); 312 dir = dir ? dir : "."; 313 readfiles(dir); 314 collectips(); 315} 316