| /* |
| * (C)opyright 1995-1998 Darren Reed. |
| * |
| * See the IPFILTER.LICENCE file for details on licencing. |
| * |
| */ |
| #include <stdio.h> |
| #include <fcntl.h> |
| #include <signal.h> |
| #include <malloc.h> |
| #include <netdb.h> |
| #include <string.h> |
| #include <sys/dir.h> |
| #include <sys/types.h> |
| #include <sys/time.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <netinet/in_systm.h> |
| #include <netinet/ip.h> |
| #include <netinet/tcp.h> |
| #include <netinet/udp.h> |
| #include <netinet/ip_icmp.h> |
| #ifndef linux |
| #include <netinet/ip_var.h> |
| #include <netinet/tcpip.h> |
| #endif |
| #include "ip_compat.h" |
| #ifdef linux |
| #include <linux/sockios.h> |
| #include "tcpip.h" |
| #endif |
| #include "ipsd.h" |
| |
| #ifndef lint |
| static const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed"; |
| static const char rcsid[] = "@(#)$Id$"; |
| #endif |
| |
| extern char *optarg; |
| extern int optind; |
| |
| #define NPORTS 21 |
| |
| u_short defports[NPORTS] = { |
| 7, 9, 20, 21, 23, 25, 53, 69, 79, 111, |
| 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0 |
| }; |
| u_short pweights[NPORTS] = { |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |
| }; |
| |
| ipsd_t *iphits[NPORTS]; |
| int pkts; |
| |
| |
| int ipcmp(sh1, sh2) |
| sdhit_t *sh1, *sh2; |
| { |
| return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr; |
| } |
| |
| |
| int ssipcmp(sh1, sh2) |
| ipss_t *sh1, *sh2; |
| { |
| return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr; |
| } |
| |
| |
| int countpbits(num) |
| u_long num; |
| { |
| int i, j; |
| |
| for (i = 1, j = 0; i; i <<= 1) |
| if (num & i) |
| j++; |
| return j; |
| } |
| |
| |
| /* |
| * Check to see if we've already received a packet from this host for this |
| * port. |
| */ |
| int findhit(ihp, src, dport) |
| ipsd_t *ihp; |
| struct in_addr src; |
| u_short dport; |
| { |
| int i, j, k; |
| sdhit_t *sh; |
| |
| sh = NULL; |
| |
| if (ihp->sd_sz == 4) { |
| for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++) |
| if (src.s_addr == sh->sh_ip.s_addr) |
| return 1; |
| } else { |
| for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) { |
| k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr; |
| if (!k) |
| return 1; |
| else if (k < 0) |
| i -= j; |
| else |
| i += j; |
| } |
| } |
| return 0; |
| } |
| |
| |
| /* |
| * Search for port number amongst the sorted array of targets we're |
| * interested in. |
| */ |
| int detect(srcip, dport, date) |
| struct in_addr srcip; |
| u_short dport; |
| time_t date; |
| { |
| ipsd_t *ihp; |
| sdhit_t *sh; |
| int i, j, k; |
| |
| for (i = 10, j = 4; j >= 0; j--) { |
| k = dport - defports[i]; |
| if (!k) { |
| ihp = iphits[i]; |
| if (findhit(ihp, srcip, dport)) |
| return 0; |
| sh = ihp->sd_hit + ihp->sd_cnt; |
| sh->sh_date = date; |
| sh->sh_ip = srcip; |
| if (++ihp->sd_cnt == ihp->sd_sz) |
| { |
| ihp->sd_sz += 8; |
| sh = realloc(sh, ihp->sd_sz * sizeof(*sh)); |
| ihp->sd_hit = sh; |
| } |
| qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp); |
| return 0; |
| } |
| if (k < 0) |
| i -= j; |
| else |
| i += j; |
| } |
| return -1; |
| } |
| |
| |
| /* |
| * Allocate initial storage for hosts |
| */ |
| setuphits() |
| { |
| int i; |
| |
| for (i = 0; i < NPORTS; i++) { |
| if (iphits[i]) { |
| if (iphits[i]->sd_hit) |
| free(iphits[i]->sd_hit); |
| free(iphits[i]); |
| } |
| iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t)); |
| iphits[i]->sd_port = defports[i]; |
| iphits[i]->sd_cnt = 0; |
| iphits[i]->sd_sz = 4; |
| iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4); |
| } |
| } |
| |
| |
| /* |
| * Write statistics out to a file |
| */ |
| addfile(file) |
| char *file; |
| { |
| ipsd_t ipsd, *ips = &ipsd; |
| sdhit_t hit, *hp; |
| char fname[32]; |
| int i, fd, sz; |
| |
| if ((fd = open(file, O_RDONLY)) == -1) { |
| perror("open"); |
| return; |
| } |
| |
| printf("opened %s\n", file); |
| do { |
| if (read(fd, ips, sizeof(*ips)) != sizeof(*ips)) |
| break; |
| sz = ips->sd_sz * sizeof(*hp); |
| hp = (sdhit_t *)malloc(sz); |
| if (read(fd, hp, sz) != sz) |
| break; |
| for (i = 0; i < ips->sd_cnt; i++) |
| detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date); |
| } while (1); |
| (void) close(fd); |
| } |
| |
| |
| readfiles(dir) |
| char *dir; |
| { |
| struct direct **d; |
| int i, j; |
| |
| d = NULL; |
| i = scandir(dir, &d, NULL, NULL); |
| |
| for (j = 0; j < i; j++) { |
| if (strncmp(d[j]->d_name, "ipsd-hits.", 10)) |
| continue; |
| addfile(d[j]->d_name); |
| } |
| } |
| |
| |
| void printreport(ss, num) |
| ipss_t *ss; |
| int num; |
| { |
| struct in_addr ip; |
| ipss_t *sp; |
| int i, j, mask; |
| u_long ports; |
| |
| printf("Hosts detected: %d\n", num); |
| if (!num) |
| return; |
| for (i = 0; i < num; i++) |
| printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits, |
| countpbits(ss[i].ss_ports)); |
| |
| printf("--------------------------\n"); |
| for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) { |
| ip.s_addr = ss[0].ss_ip.s_addr & mask; |
| ports = ss[0].ss_ports; |
| for (i = 1; i < num; i++) { |
| sp = ss + i; |
| if (ip.s_addr != (sp->ss_ip.s_addr & mask)) { |
| printf("Netmask: 0x%08x\n", mask); |
| printf("%s %d\n", inet_ntoa(ip), |
| countpbits(ports)); |
| ip.s_addr = sp->ss_ip.s_addr & mask; |
| ports = 0; |
| } |
| ports |= sp->ss_ports; |
| } |
| if (ports) { |
| printf("Netmask: 0x%08x\n", mask); |
| printf("%s %d\n", inet_ntoa(ip), countpbits(ports)); |
| } |
| } |
| } |
| |
| |
| collectips() |
| { |
| ipsd_t *ips; |
| ipss_t *ss; |
| int i, num, nip, in, j, k; |
| |
| for (i = 0; i < NPORTS; i++) |
| nip += iphits[i]->sd_cnt; |
| |
| ss = (ipss_t *)malloc(sizeof(ipss_t) * nip); |
| |
| for (in = 0, i = 0, num = 0; i < NPORTS; i++) { |
| ips = iphits[i]; |
| for (j = 0; j < ips->sd_cnt; j++) { |
| for (k = 0; k < num; k++) |
| if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip, |
| sizeof(struct in_addr))) { |
| ss[k].ss_hits += pweights[i]; |
| ss[k].ss_ports |= (1 << i); |
| break; |
| } |
| if (k == num) { |
| ss[num].ss_ip = ips->sd_hit[j].sh_ip; |
| ss[num].ss_hits = pweights[i]; |
| ss[k].ss_ports |= (1 << i); |
| num++; |
| } |
| } |
| } |
| |
| qsort(ss, num, sizeof(*ss), ssipcmp); |
| |
| printreport(ss, num); |
| } |
| |
| |
| main(argc, argv) |
| int argc; |
| char *argv[]; |
| { |
| char c, *name = argv[0], *dir = NULL; |
| int fd; |
| |
| setuphits(); |
| dir = dir ? dir : "."; |
| readfiles(dir); |
| collectips(); |
| } |