Don't try to extract UDP/TCP port numbers from IP fragments.
authorBen Pfaff <blp@nicira.com>
Mon, 4 Aug 2008 21:45:59 +0000 (14:45 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 4 Aug 2008 21:45:59 +0000 (14:45 -0700)
datapath/flow.c
lib/flow.c

index e3e1eb92a5460b53c427384d592229e25cc5723c..d4c4802138f76602d15ada6bb2c69fa3b61b5e75 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/udp.h>
 #include <linux/in.h>
 #include <linux/rcupdate.h>
+#include <net/ip.h>
 
 #include "openflow.h"
 #include "compat.h"
@@ -251,7 +252,8 @@ void flow_extract(struct sk_buff *skb, uint16_t in_port,
 
                /* Transport layer. */
                if ((key->nw_proto != IPPROTO_TCP && key->nw_proto != IPPROTO_UDP)
-                               || skb->len < th_ofs + sizeof(struct udphdr)) {
+                   || skb->len < th_ofs + sizeof(struct udphdr)
+                   || nh->frag_off & htons(IP_MF | IP_OFFSET)) {
                        goto no_th;
                }
                th = udp_hdr(skb);
index 7340e7d48a54d643795f9d48b44a77748bc90058..4fcf58a8218ec65be921bde8b8690b90c686efde 100644 (file)
@@ -149,27 +149,29 @@ flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow)
                 flow->nw_dst = nh->ip_dst;
                 flow->nw_proto = nh->ip_proto;
                 packet->l4 = b.data;
-                if (flow->nw_proto == IP_TYPE_TCP) {
-                    const struct tcp_header *tcp = pull_tcp(&b);
-                    if (tcp) {
-                        flow->tp_src = tcp->tcp_src;
-                        flow->tp_dst = tcp->tcp_dst;
-                        packet->l7 = b.data;
-                    } else {
-                        /* Avoid tricking other code into thinking that this
-                         * packet has an L4 header. */
-                        flow->nw_proto = 0;
-                    }
-                } else if (flow->nw_proto == IP_TYPE_UDP) {
-                    const struct udp_header *udp = pull_udp(&b);
-                    if (udp) {
-                        flow->tp_src = udp->udp_src;
-                        flow->tp_dst = udp->udp_dst;
-                        packet->l7 = b.data;
-                    } else {
-                        /* Avoid tricking other code into thinking that this
-                         * packet has an L4 header. */
-                        flow->nw_proto = 0;
+                if (!IP_IS_FRAGMENT(nh->ip_frag_off)) {
+                    if (flow->nw_proto == IP_TYPE_TCP) {
+                        const struct tcp_header *tcp = pull_tcp(&b);
+                        if (tcp) {
+                            flow->tp_src = tcp->tcp_src;
+                            flow->tp_dst = tcp->tcp_dst;
+                            packet->l7 = b.data;
+                        } else {
+                            /* Avoid tricking other code into thinking that
+                             * this packet has an L4 header. */
+                            flow->nw_proto = 0;
+                        }
+                    } else if (flow->nw_proto == IP_TYPE_UDP) {
+                        const struct udp_header *udp = pull_udp(&b);
+                        if (udp) {
+                            flow->tp_src = udp->udp_src;
+                            flow->tp_dst = udp->udp_dst;
+                            packet->l7 = b.data;
+                        } else {
+                            /* Avoid tricking other code into thinking that
+                             * this packet has an L4 header. */
+                            flow->nw_proto = 0;
+                        }
                     }
                 }
             }