NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/45929: ipnat does not remove rules with -r



>Number:         45929
>Category:       kern
>Synopsis:       ipnat does not remove rules with -r
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 05 13:55:00 +0000 2012
>Originator:     Darren Reed
>Release:        NetBSD 5.99.63
>Organization:
>Description:
        There are two issues current with ipnat. The most serious is
that "ipnat -rf /etc/ipnat.conf" will not remove NAT rules because the
"-r" function will not work. Another side effect of this is that it is
possile to load the same rule twice - rule matching is broken. Finally,
if ipfilter is disabled and ipnat is run, it will print a very broken
error message:
:ioctl(SIOCGNATS)
whereas what it should print is this:
130003:ioctl(SIOCGNATS) ioctl on device denied, ipfitler is disabled
>How-To-Repeat:
        
>Fix:

Index: ip_fil_netbsd.c
===================================================================
RCS file: /room/netbsd/src/sys/dist/ipf/netinet/ip_fil_netbsd.c,v
retrieving revision 1.59
diff -c -r1.59 ip_fil_netbsd.c
*** ip_fil_netbsd.c     1 Feb 2012 02:21:19 -0000       1.59
--- ip_fil_netbsd.c     5 Feb 2012 13:01:39 -0000
***************
*** 638,644 ****
        }
  
        if (ipfmain.ipf_running <= 0) {
!               if (unit != IPL_LOGIPF) {
                        ipfmain.ipf_interror = 130003;
                        return EIO;
                }
--- 638,644 ----
        }
  
        if (ipfmain.ipf_running <= 0) {
!               if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) {
                        ipfmain.ipf_interror = 130003;
                        return EIO;
                }
Index: ip_nat.c
===================================================================
RCS file: /room/netbsd/src/sys/dist/ipf/netinet/ip_nat.c,v
retrieving revision 1.46
diff -c -r1.46 ip_nat.c
*** ip_nat.c    1 Feb 2012 02:21:20 -0000       1.46
--- ip_nat.c    5 Feb 2012 13:40:44 -0000
***************
*** 229,234 ****
--- 229,235 ----
  static        void    ipf_nat_addrdr(ipf_nat_softc_t *, ipnat_t *);
  static        int     ipf_nat_builddivertmp(ipf_nat_softc_t *, ipnat_t *);
  static        int     ipf_nat_clearlist(ipf_main_softc_t *, ipf_nat_softc_t 
*);
+ static        int     ipf_nat_cmp_rules(ipnat_t *, ipnat_t *);
  static        int     ipf_nat_decap(fr_info_t *, nat_t *);
  static        void    ipf_nat_del_active(int, u_32_t *);
  static        void    ipf_nat_del_map_mask(ipf_nat_softc_t *, int);
***************
*** 1273,1280 ****
                MUTEX_ENTER(&softn->ipf_nat_io);
                for (np = &softn->ipf_nat_list; ((n = *np) != NULL);
                     np = &n->in_next)
!                       if (!bcmp((char *)&nat->in_v, (char *)&n->in_v,
!                                       IPN_CMPSIZ))
                                break;
        }
  
--- 1274,1280 ----
                MUTEX_ENTER(&softn->ipf_nat_io);
                for (np = &softn->ipf_nat_list; ((n = *np) != NULL);
                     np = &n->in_next)
!                       if (ipf_nat_cmp_rules(nat, n) == 0)
                                break;
        }
  
***************
*** 8896,8898 ****
--- 8896,8958 ----
  
        RWLOCK_EXIT(&softc->ipf_nat);
  }
+ 
+ 
+ /* ------------------------------------------------------------------------ */
+ /* Function:    ipf_nat_cmp_rules                                           */
+ /* Returns:     int   - 0 == success, else rules do not match.              */
+ /* Parameters:  n1(I) - first rule to compare                               */
+ /*              n2(I) - first rule to compare                               */
+ /*                                                                          */
+ /* Compare two rules using pointers to each rule. A straight bcmp will not  */
+ /* work as some fields (such as in_dst, in_pkts) actually do change once    */
+ /* the rule has been loaded into the kernel. Whilst this function returns   */
+ /* various non-zero returns, they're strictly to aid in debugging. Use of   */
+ /* this function should simply care if the result is zero or not.           */
+ /* ------------------------------------------------------------------------ */
+ static int
+ ipf_nat_cmp_rules(ipnat_t *n1, ipnat_t *n2)
+ {
+       if (n1->in_size != n2->in_size)
+               return 1;
+ 
+       if (bcmp((char *)&n1->in_v, (char *)&n2->in_v,
+                offsetof(ipnat_t, in_ndst) - offsetof(ipnat_t, in_v)) != 0)
+               return 2;
+ 
+       if (bcmp((char *)&n1->in_tuc, (char *)&n2->in_tuc,
+                offsetof(ipnat_t, in_pkts) - offsetof(ipnat_t, in_tuc)) != 0)
+               return 3;
+       if (bcmp((char *)&n1->in_namelen, (char *)&n2->in_namelen,
+                n1->in_size  - offsetof(ipnat_t, in_namelen)) != 0)
+               return 4;
+       if (n1->in_ndst.na_atype != n2->in_ndst.na_atype)
+               return 5;
+       if (n1->in_ndst.na_function != n2->in_ndst.na_function)
+               return 6;
+       if (bcmp((char *)&n1->in_ndst.na_addr, (char *)&n2->in_ndst.na_addr,
+                sizeof(n1->in_ndst.na_addr)))
+               return 7;
+       if (n1->in_nsrc.na_atype != n2->in_nsrc.na_atype)
+               return 8;
+       if (n1->in_nsrc.na_function != n2->in_nsrc.na_function)
+               return 9;
+       if (bcmp((char *)&n1->in_nsrc.na_addr, (char *)&n2->in_nsrc.na_addr,
+                sizeof(n1->in_nsrc.na_addr)))
+               return 10;
+       if (n1->in_odst.na_atype != n2->in_odst.na_atype)
+               return 11;
+       if (n1->in_odst.na_function != n2->in_odst.na_function)
+               return 12;
+       if (bcmp((char *)&n1->in_odst.na_addr, (char *)&n2->in_odst.na_addr,
+                sizeof(n1->in_odst.na_addr)))
+               return 13;
+       if (n1->in_osrc.na_atype != n2->in_osrc.na_atype)
+               return 14;
+       if (n1->in_osrc.na_function != n2->in_osrc.na_function)
+               return 15;
+       if (bcmp((char *)&n1->in_osrc.na_addr, (char *)&n2->in_osrc.na_addr,
+                sizeof(n1->in_osrc.na_addr)))
+               return 16;
+       return 0;
+ }



Home | Main Index | Thread Index | Old Index