Greetings,
I have been beating my head for 3 days and searched the archives and
googled the net - so I decided to bother you guys and beg for help.
Attached is a program named ipfistat.c that is a hack to create the
Ipfstat like output that I need based on interface. I can get the
general stats with no problem and I can get hit counts for each rule
by rule number. My problem is getting ahold of the interface and the
flags. You should be able to run it and do no damage - it only reads
kmem and does printf.
Specifically, when I load fp->fr_flags it comes in NULL and the same
with the interface. I have tried to make it as close to ipfilter as
possible and most of it is a collection of cut, paste and hack (as is
most of my programming) and so it looks very much like ipfilter (mostly
same naming, I use ipfilter includes and the output looks like
ipstat -vhio when you run my ipfistat 3
I am running on FreeBSD Release 4.
I noticed that the printbin() from ipstat dumps 336 bytes to the
screen for each rule. My program only loads 328 bytes. I don't know
why but I doubt that what I need is in there. I am just convinced
that I have missed some small piece of information that I did not
notice in the man 4 ipf screen.
Please, please... If you know how to get the rule flags and
interface... Thank you in advance for your help.
Thanks!
Jeff Brower
Program follows:
/*
Almost all of this is a cut and paste hack from several programs
that make up the great and powerful ipfilter package. This is
a great package and I love it. That said, this hack is an attempt
to get ahold of the filter stats on a per rule basis and summarize
them by interface (rather than by rule, or in general, like you can
get from ipstat). I'm a novice at this - so be kind.
This program is written for Jeff Brower's fun and joy only. I can
guarantee that it will not work as it is and may never work in any
useful way on your system or mine. If you are interested in the
final version after I can get it working feel free to drop me an
email at [EMAIL PROTECTED] to see if I ever got it going.
In the meantime, the code in this program is indeed mostly cut and
paste from ipfilter programs - and so I proclaim the program subject
to the same copyright that it carries:
IPFILTER: Copyright (C) 1993-2001 by Darren Reed
Please see the IPFILTER.LICENCE file for details
Additionally, I declare this particular program subject to the
Beer License. If you like this and you meet me, buy me a beer.
Jeff Brower - [EMAIL PROTECTED]
*/
/* ipfistat.c compile comand: gcc -lkvm ipfistat.c -o ipfistat
*/
#include <stdio.h>
#include <fcntl.h>
#include </usr/include/sys/ioctl.h>
#include </usr/include/netinet/in.h>
#include </usr/src/sys/contrib/ipfilter/netinet/ip_compat.h>
#include </usr/src/sys/contrib/ipfilter/netinet/ip_fil.h>
#include <kvm.h>
static int kvm_fd = -1;
static char *kvm_errstr = NULL;
static char *kvm_kern = NULL;
static char *kvm_core = NULL;
static kvm_t *kvm_f = NULL;
static int noiselevel = 0;
int kmemcpy(buf, pos, n)
register char *buf;
long pos;
register int n;
{
register int r;
if (!n)
return 0;
while ((r = kvm_read(kvm_f, pos, buf, (size_t)n)) < n)
if (r <= 0) {
fprintf(stderr, "pos=0x%x ", (u_int)pos);
perror("kmemcpy:read");
return -1;
}
else
{
buf += r;
pos += r;
n -= r;
}
return 0;
}
static void bindump(fp)
struct frentry *fp;
{
int i = sizeof(*fp), j=0;
u_char *s;
for (s = (u_char *)fp; i; i--, s++) {
j++;
printf("%02x ", *s);
if (j == 16) {
printf("\n");
j = 0;
}
}
printf("\n\n");
}
static void printifname(format, name, ifp)
char *format, *name;
void *ifp;
{
printf("%s%s", format, name);
if ((ifp == NULL) && strcmp(name, "-") && strcmp(name, "*"))
printf("(!)");
}
static void printfr(fp)
struct frentry *fp;
{
printf("Hits: %ld\tRule: [", fp->fr_hits);
if (fp->fr_flags == NULL) printf("(Flags are NULL!) ");
if (fp->fr_flags & FR_PASS) printf("pass ");
if (fp->fr_flags & FR_NOMATCH) printf("nomatch ");
if (fp->fr_flags & FR_BLOCK) printf("block ");
if (fp->fr_flags & FR_OUTQUE) printf("out "); else printf("in ");
if (fp->fr_flags & FR_QUICK) printf("quick ");
if (*fp->fr_ifname) {
printifname("on ", fp->fr_ifname, fp->fr_ifa);
}
printf("]\n");
}
static void printlist(fp)
frentry_t *fp;
{
struct frentry fb;
int n;
for (n = 1; fp; n++) {
if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
perror("kmemcpy");
return;
}
fp = &fb;
if (noiselevel > 1) {
printf("Line %d\t", n); /* print line number */
printfr(fp); /* print the rule */
}
if (noiselevel > 2) {
bindump(fp); /* binary dump of rule */
}
if (fp->fr_grp)
printlist(fp->fr_grp);
fp = fp->fr_next;
}
}
static void showlist(fiop)
struct friostat *fiop;
{
struct frentry *fp = NULL;
int set;
set = fiop->f_active;
fp = (struct frentry *)fiop->f_fin[set];
if (!fp) { return; }
printlist(fp);
fp = (struct frentry *)fiop->f_fout[set];
if (!fp) { return; }
printlist(fp);
}
main(int argc, char **argv)
{
/* define some variables we need */
friostat_t fio;
friostat_t *fiop = &fio;
int fd, n;
char *name = NULL;
char *device = IPL_NAME;
/* Edit the parameter for verbosity */
if (argc!=2) {
fprintf(stderr, "Missing verbosity level (0, 1, 2, 3).\n");
exit(-1);
}
if (sscanf(argv[1], "%i", &noiselevel) != 1) {
fprintf(stderr, "Whoops! What you entered was not a number.\n");
exit(-1);
}
if ( (noiselevel < 0) || (noiselevel > 3) ) {
fprintf(stderr, "Whoops! 0=Quiet 1=Some 2=Verbose 3=Chatty\n");
exit(-1);
}
/* open up the kernel memory file handle */
kvm_f = kvm_open(kvm_kern, kvm_core, NULL, O_RDONLY, kvm_errstr);
if (kvm_f == NULL) {
perror("kvm_open:open");
exit(-1);
}
/* open up the file handle for the SIOC call in ipfilter */
if ((fd = open(device, O_RDONLY)) < 0) {
perror("open");
exit(-1);
}
/* Do the ioctl SIOC call to GET the Filter Stats (SIOCGFS) */
bzero((char *)&fio, sizeof(fio));
if (ioctl(fd, SIOCGETFS, &fiop) == -1) {
perror("ioctl(SIOCGETFS)");
exit(-1);
}
if (noiselevel > 0) {
printf(" Input Packets:\t\tblocked %lu passed %lu nomatch %lu",
fio.f_st[0].fr_block,
fio.f_st[0].fr_pass,
fio.f_st[0].fr_nom);
printf(" counted %lu short %lu\n",
fio.f_st[0].fr_acct,
fio.f_st[0].fr_short);
printf("Output Packets:\t\tblocked %lu passed %lu nomatch %lu",
fio.f_st[1].fr_block,
fio.f_st[1].fr_pass,
fio.f_st[1].fr_nom);
printf(" counted %lu short %lu\n",
fio.f_st[1].fr_acct,
fio.f_st[1].fr_short);
}
showlist(fiop);
return 0;
}