> I've been ipf user for long time. I now mostly switched to FreeBSD IPFW
> because of my colleagues know it better and because it's rule numbering.
> 
> After reading the manual page of ipfilter again I thought I must have
> been blind in the past because it seems to have something similar. It
> works differently then IPFW and seems almost useless to me after some
> testing. Of course there's always a chance I understand/use it the wrong
> way and it can be used similarly to IPFW rule numbers.
..
> ipfilter accepts the numbers (as stated in ipf(5)) but don't store the
> number AFAIK. When I add rules 100, 200 and 150 with ipfilter they are
> listed in 'wrong' order with ipfstat -in.

I suspect this is a bug...

> From the manual page one can get another impression how it might work -
> that the number is the absolute position in the list. It doesn't seem to
> really work this way either. The operation changes a little when I use
> '@' in front of the number but still doesn't work. From the
> documentation it would seem '@' is mandatory.

Kinda...

> I'd like to either know what the number in ipfilter really means or
> implement the functionality as done in IPFW. I offer my help - I believe
> the change shouldn't be too difficult to code and I'm a (kernel) C
> programmer.

It should but because it's not documented, it's relatively unused and
untested.  So in reading this, I went and tested it, found some problems
and have attached a patch that should give you what you want.

Loading this rule set:
100 pass in all
200 pass in proto tcp all
110 pass in proto udp all
110 pass in from localhost to any
pass in all
pass in from localhost to any
@0 100 pass in from localhost to any
@1 pass in from any to localhost
@0 pass in from 1.1.1.1 to any
@1 110 pass in from 2.2.2.2 to any
@2 pass in from 3.3.3.3 to any

Comes out looking like this with ipfstat:
pass in from 1.1.1.1/32 to any
pass in all
pass in from 3.3.3.3/32 to any
pass in from any to 127.0.0.1/32
pass in from 127.0.0.1/32 to any
100 pass in from 127.0.0.1/32 to any
100 pass in all
110 pass in proto udp from any to any
110 pass in from 2.2.2.2/32 to any
110 pass in from 127.0.0.1/32 to any
200 pass in proto tcp from any to any

Darren

Index: lib/printfr.c
===================================================================
RCS file: /devel/CVS/IP-Filter/lib/printfr.c,v
retrieving revision 1.43.2.10
diff -c -r1.43.2.10 printfr.c
*** lib/printfr.c       16 Mar 2005 15:38:13 -0000      1.43.2.10
--- lib/printfr.c       10 May 2005 16:23:20 -0000
***************
*** 105,110 ****
--- 105,113 ----
        if ((fp->fr_type & FR_T_BUILTIN) != 0)
                printf("# Builtin: ");
  
+       if (fp->fr_collect != 0)
+               printf("%u ", fp->fr_collect);
+ 
        if (fp->fr_type == FR_T_CALLFUNC) {
                ;
        } else if (fp->fr_func != NULL) {
Index: fil.c
===================================================================
RCS file: /devel/CVS/IP-Filter/fil.c,v
retrieving revision 2.243.2.57
diff -c -r2.243.2.57 fil.c
*** fil.c       28 Mar 2005 10:47:50 -0000      2.243.2.57
--- fil.c       10 May 2005 20:29:26 -0000
***************
*** 3993,4002 ****
                fprev = &fg->fg_start;
        }
  
-       for (f = *fprev; (f = *fprev) != NULL; fprev = &f->fr_next)
-               if (fp->fr_collect <= f->fr_collect)
-                       break;
        ftail = fprev;
  
        /*
         * Copy in extra data for the rule.
--- 3993,4007 ----
                fprev = &fg->fg_start;
        }
  
        ftail = fprev;
+       for (f = *ftail; (f = *ftail) != NULL; ftail = &f->fr_next) {
+               if (fp->fr_collect <= f->fr_collect) {
+                       ftail = fprev;
+                       f = NULL;
+                       break;
+               }
+               fprev = ftail;
+       }
  
        /*
         * Copy in extra data for the rule.
***************
*** 4135,4148 ****
        WRITE_ENTER(&ipf_mutex);
        bzero((char *)frcache, sizeof(frcache));
  
!       for (; (f = *ftail) != NULL; ftail = &f->fr_next)
!               if ((fp->fr_cksum == f->fr_cksum) &&
!                   (f->fr_dsize == fp->fr_dsize) &&
!                   !bcmp((char *)&f->fr_func,
!                         (char *)&fp->fr_func, FR_CMPSIZ) &&
!                   (!ptr || !f->fr_data ||
                     !bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize)))
                        break;
  
        /*
         * If zero'ing statistics, copy current to caller and zero.
--- 4140,4156 ----
        WRITE_ENTER(&ipf_mutex);
        bzero((char *)frcache, sizeof(frcache));
  
!       for (; (f = *ftail) != NULL; ftail = &f->fr_next) {
!               if ((fp->fr_cksum != f->fr_cksum) ||
!                   (f->fr_dsize != fp->fr_dsize))
!                       continue;
!               if (bcmp((char *)&f->fr_func, (char *)&fp->fr_func, FR_CMPSIZ))
!                       continue;
!               if ((!ptr && !f->fr_data) ||
!                   (ptr && f->fr_data &&
                     !bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize)))
                        break;
+       }
  
        /*
         * If zero'ing statistics, copy current to caller and zero.
***************
*** 4188,4199 ****
        }
  
        if (!f) {
!               if (req == (ioctlcmd_t)SIOCINAFR ||
!                   req == (ioctlcmd_t)SIOCINIFR) {
                        ftail = fprev;
                        if (fp->fr_hits != 0) {
!                               while (--fp->fr_hits && (f = *ftail))
                                        ftail = &f->fr_next;
                        }
                        f = NULL;
                        ptr = NULL;
--- 4196,4235 ----
        }
  
        if (!f) {
!               /*
!                * At the end of this, ftail must point to the place where the
!                * new rule is to be saved/inserted/added.
!                * For SIOCAD*FR, this should be the last rule in the group of
!                * rules that have equal fr_collect fields.
!                * For SIOCIN*FR, ...
!                */
!               if (req == (ioctlcmd_t)SIOCADAFR ||
!                   req == (ioctlcmd_t)SIOCADIFR) {
! 
!                       for (ftail = fprev; (f = *ftail) != NULL; ) {
!                               if (f->fr_collect > fp->fr_collect)
!                                       break;
!                               ftail = &f->fr_next;
!                       }
!                       f = NULL;
!                       ptr = NULL;
!                       error = 0;
!               } else if (req == (ioctlcmd_t)SIOCINAFR ||
!                          req == (ioctlcmd_t)SIOCINIFR) {
!                       while ((f = *fprev) != NULL) {
!                               if (f->fr_collect >= fp->fr_collect)
!                                       break;
!                               fprev = &f->fr_next;
!                       }
                        ftail = fprev;
                        if (fp->fr_hits != 0) {
!                               while (fp->fr_hits && (f = *ftail)) {
!                                       if (f->fr_collect != fp->fr_collect)
!                                               break;
!                                       fprev = ftail;
                                        ftail = &f->fr_next;
+                                       fp->fr_hits--;
+                               }
                        }
                        f = NULL;
                        ptr = NULL;

Reply via email to