320 lines
5.8 KiB
C
320 lines
5.8 KiB
C
|
/* $NetBSD: ipsdr.c,v 1.1.1.1 1999/12/11 22:24:07 veego Exp $ */
|
||
|
|
||
|
/*
|
||
|
* (C)opyright 1995-1998 Darren Reed.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms are permitted
|
||
|
* provided that this notice is preserved and due credit is given
|
||
|
* to the original author and the contributors.
|
||
|
*
|
||
|
* The author of this software makes no garuntee about the
|
||
|
* performance of this package or its suitability to fulfill any purpose.
|
||
|
*
|
||
|
*/
|
||
|
#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: ipsdr.c,v 2.1 1999/08/04 17:30:57 darrenr Exp";
|
||
|
#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();
|
||
|
}
|