On world IPv6 day I was asked by bz@ to re-spin the patch supplied in the PR with the second and third IPv6 fragment issues listed in the PR fixed, but not the first (discarding IPv6 packets with a fragment header but not fragmented). Attached is the revised patch, against 8.2R
--- ip_fw_log.c.orig    2011-06-24 19:46:44.000000000 +1200
+++ ip_fw_log.c 2011-06-24 20:14:55.724751000 +1200
@@ -168,6 +168,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
        char *action;
        int limit_reached = 0;
        char action2[40], proto[128], fragment[32];
+       u_short mf = 0;
 
        if (V_fw_verbose == 0) {
 #ifndef WITHOUT_BPF
@@ -337,6 +338,8 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
                        snprintf(dst, sizeof(dst), "[%s]",
                            ip6_sprintf(ip6buf, &args->f_id.dst_ip6));
 
+                       mf = offset & IP6F_MORE_FRAG;
+                       offset &= IP6F_OFF_MASK;
                        ip6 = (struct ip6_hdr *)ip;
                        tcp = (struct tcphdr *)(((char *)ip) + hlen);
                        udp = (struct udphdr *)(((char *)ip) + hlen);
@@ -406,13 +409,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 
 #ifdef INET6
                if (IS_IP6_FLOW_ID(&(args->f_id))) {
-                       if (offset & (IP6F_OFF_MASK | IP6F_MORE_FRAG))
+                 if (offset || mf)
                                snprintf(SNPARGS(fragment, 0),
                                    " (frag %08x:%d@%d%s)",
                                    args->f_id.extra,
                                    ntohs(ip6->ip6_plen) - hlen,
-                                   ntohs(offset & IP6F_OFF_MASK) << 3,
-                                   (offset & IP6F_MORE_FRAG) ? "+" : "");
+                                   ntohs(offset) << 3,
+                                   mf ? "+" : "");
                } else
 #endif
                {
--- ip_fw2.c.orig       2011-06-24 19:31:28.000000000 +1200
+++ ip_fw2.c    2011-06-24 20:14:55.724751000 +1200
@@ -838,16 +838,13 @@ ipfw_chk(struct ip_fw_args *args)
 
        /*
         * offset       The offset of a fragment. offset != 0 means that
-        *      we have a fragment at this offset of an IPv4 packet.
-        *      offset == 0 means that (if this is an IPv4 packet)
-        *      this is the first or only fragment.
-        *      For IPv6 offset == 0 means there is no Fragment Header. 
-        *      If offset != 0 for IPv6 always use correct mask to
-        *      get the correct offset because we add IP6F_MORE_FRAG
-        *      to be able to dectect the first fragment which would
-        *      otherwise have offset = 0.
+        *      we have a fragment at this offset.
+        *      offset == 0 means that this is the first or only fragment.
+        *
+        * mf The MF bit masked out of IPv6 packets.
         */
        u_short offset = 0;
+       u_short mf = 0;
 
        /*
         * Local copies of addresses. They are only valid if we have
@@ -940,7 +937,7 @@ do {                                                        
        \
                proto = ip6->ip6_nxt;
 
                /* Search extension headers to find upper layer protocols */
-               while (ulp == NULL) {
+               while (ulp == NULL && offset == 0) {
                        switch (proto) {
                        case IPPROTO_ICMPV6:
                                PULLUP_TO(hlen, ulp, struct icmp6_hdr);
@@ -1005,11 +1002,9 @@ do {                                                     
        \
                                proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
                                offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
                                        IP6F_OFF_MASK;
-                               /* Add IP6F_MORE_FRAG for offset of first
-                                * fragment to be != 0. */
-                               offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
+                               mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
                                        IP6F_MORE_FRAG;
-                               if (offset == 0) {
+                               if (offset == 0 && mf == 0) {
                                        printf("IPFW2: IPV6 - Invalid Fragment "
                                            "Header\n");
                                        if (V_fw_deny_unknown_exthdrs)
@@ -1650,7 +1645,7 @@ do {                                                      
        \
 
                        case O_LOG:
                                ipfw_log(f, hlen, args, m,
-                                           oif, offset, tablearg, ip);
+                                           oif, offset|mf, tablearg, ip);
                                match = 1;
                                break;
 
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to