kern/93754: [patch] dummynet changes ip_id, breaking fragment reassembly

Joerg Pernfuss elessar at bsdforen.de
Thu Feb 23 07:10:06 PST 2006


>Number:         93754
>Category:       kern
>Synopsis:       [patch] dummynet changes ip_id, breaking fragment reassembly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 23 15:10:02 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Joerg Pernfuss
>Release:        FreeBSD 5.4-STABLE i386
>Organization:
>Environment:
>Description:
"When forwarding fragmented packets through a dummynet pipe (ip_input -> ip_forward -> ip_output -> pipe -> ip_output) the last ip_output() in the chain that does the actual IP delivery sets ip_id of all fragments to different values, making it impossible to reassemble the packet at receive side."
(Taken from ru@'s description of the releng_6 patch)

A patch for RELENG_6 was already committed. The patch below is based on that commit, stripped of the ipv6 case (releng_5 has no dummynet ipv6) and the netgraph stuff (netgraph/ng_ipfw.[ch] was introduced with releng_6).

The problem was raised on de-bsd-questions@, i run 6.0-STABLE, so no uname(1) provided.
>How-To-Repeat:
Send fragmented ip packets through a dummynet pipe.
>Fix:
Either:
a) update your system to releng_6 after 2006-02-17 (problem was fixed there)

b) apply the following patch:
   cd /sys/inet; patch < /location/of/patch;
   rebuild your kernel, reboot

--- ip_dummynet.c       Tue Feb 21 01:01:23 2006
+++ ip_dummynet.c       Tue Feb 21 01:13:00 2006
@@ -453,7 +453,7 @@
        DUMMYNET_UNLOCK();
        switch (pkt->dn_dir) {
        case DN_TO_IP_OUT:
-           (void)ip_output(m, NULL, NULL, pkt->flags, NULL, NULL);
+           (void)ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
            break ;
 
        case DN_TO_IP_IN :
@@ -1128,7 +1128,6 @@
  *             NULL in ip_input, destination interface in ip_output,
  *             real_dst in bdg_forward
  * rule                matching rule, in case of multiple passes
- * flags       flags from the caller, only used in ip_output
  *
  */
 static int
@@ -1212,8 +1211,6 @@
     pkt->dn_dir = dir ;
 
     pkt->ifp = fwa->oif;
-    if (dir == DN_TO_IP_OUT)
-       pkt->flags = fwa->flags;
     if (q->head == NULL)
        q->head = m;
     else
--- ip_dummynet.h       Tue Feb 21 01:24:10 2006
+++ ip_dummynet.h       Tue Feb 21 01:28:26 2006
@@ -129,7 +129,6 @@
 
     dn_key output_time;                /* when the pkt is due for delivery     */
     struct ifnet *ifp;         /* interface, for ip_output             */
-    int flags ;                        /* flags, for ip_output (IPv6 ?)        */
 };
 #endif /* _KERNEL */
 
--- ip_fw.h     Tue Feb 21 01:25:14 2006
+++ ip_fw.h     Tue Feb 21 01:26:16 2006
@@ -435,8 +435,6 @@
        struct ip_fw    *rule;          /* matching rule                */
        struct ether_header *eh;        /* for bridged packets          */
 
-       int flags;                      /* for dummynet                 */
-
        struct ipfw_flow_id f_id;       /* grabbed from IP header       */
        u_int32_t       retval;
        struct inpcb    *inp;

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list