Set l4 pointer properly in buffers that contain IP options.
authorBen Pfaff <blp@nicira.com>
Fri, 28 Mar 2008 00:34:05 +0000 (17:34 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 28 Mar 2008 00:50:33 +0000 (17:50 -0700)
The important part of this change is handling of IP options.  The
rest is intended to ensure that packet->l3 and packet->l4 never
point outside the valid range of a packet in the presence of a
minimum-length Ethernet frame.  Other code (particularly in forward.c)
assumes that if the IP protocol is TCP or UDP, then packet->l4 points
to a tcp_header or udp_header.  Whether this is a good idea is
debatable--it probably warrants clean-up, at least--but that what's
there now.

lib/flow.c

index 2ba560c9172f0f4ec0ef681f923c8586e70b3993..ab065acb80a80dc1d1ebbea7af9b697ff7a78760 100644 (file)
@@ -72,18 +72,25 @@ flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow)
         if (flow->dl_type == htons(ETH_TYPE_IP)) {
             const struct ip_header *nh = buffer_at(&b, 0, sizeof *nh);
             if (nh) {
+                int ip_len = IP_IHL(nh->ip_ihl_ver) * 4;
+                if (ip_len < IP_HEADER_LEN) {
+                    return;
+                }
+
                 flow->nw_src = nh->ip_src;
                 flow->nw_dst = nh->ip_dst;
                 flow->nw_proto = nh->ip_proto;
-                packet->l4 = b.data + IP_HEADER_LEN;
                 if (flow->nw_proto == IP_TYPE_TCP
                     || flow->nw_proto == IP_TYPE_UDP) {
-                    int udp_ofs = IP_IHL(nh->ip_ihl_ver) * 4;
-                    const struct udp_header *th
-                        = buffer_at(&b, udp_ofs, sizeof *th);
+                    const struct udp_header *th;
+                    th = packet->l4 = buffer_at(&b, ip_len, sizeof *th);
                     if (th) {
                         flow->tp_src = th->udp_src;
                         flow->tp_dst = th->udp_dst;
+                    } else {
+                        /* Avoid tricking other code into thinking that this
+                         * packet has an L4 header. */
+                        flow->nw_proto = 0;
                     }
                 }
             }