#include <linux/udp.h>
#include <linux/in.h>
#include <linux/rcupdate.h>
+#include <net/ip.h>
#include "openflow.h"
#include "compat.h"
/* 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);
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;
+ }
}
}
}