diff options
author | Jesse Gross <jesse@nicira.com> | 2015-09-11 09:01:05 -0700 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2015-09-13 08:13:11 -0700 |
commit | f41256d709d1733262b7538613237b34e801f457 (patch) | |
tree | fb6100bbd18d8995d749cf8585b1204aa1631846 | |
parent | 9d4aeccaf69861616cb0715d10e3f1f3e2a14e51 (diff) | |
download | openvswitch-f41256d709d1733262b7538613237b34e801f457.tar.gz |
tunnel: Validate IP header for userspace tunneling.
Currently, when doing userspace tunneling we don't perform much in
the way of integrity checks on the incoming IP header. The case of
tunneling is different from the usual case of switching since we are
acting as the endpoint here and should not allow invalid packets to
pass.
This adds checks for IP checksum, version, total length, and options and
drops packets that don't pass.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
-rw-r--r-- | lib/netdev-vport.c | 27 | ||||
-rw-r--r-- | tests/tunnel-push-pop.at | 6 |
2 files changed, 30 insertions, 3 deletions
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index eceaa813e..ff505637e 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -844,6 +844,7 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl) { struct ip_header *nh; void *l4; + int l3_size; nh = dp_packet_l3(packet); l4 = dp_packet_l4(packet); @@ -852,6 +853,32 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl) return NULL; } + if (csum(nh, IP_IHL(nh->ip_ihl_ver) * 4)) { + VLOG_WARN_RL(&err_rl, "ip packet has invalid checksum"); + return NULL; + } + + if (IP_VER(nh->ip_ihl_ver) != 4) { + VLOG_WARN_RL(&err_rl, "ipv4 packet has invalid version (%d)", + IP_VER(nh->ip_ihl_ver)); + return NULL; + } + + l3_size = dp_packet_size(packet) - + ((char *)nh - (char *)dp_packet_data(packet)); + + if (ntohs(nh->ip_tot_len) > l3_size) { + VLOG_WARN_RL(&err_rl, "ip packet is truncated (IP length %d, actual %d)", + ntohs(nh->ip_tot_len), l3_size); + return NULL; + } + + if (IP_IHL(nh->ip_ihl_ver) * 4 > sizeof(struct ip_header)) { + VLOG_WARN_RL(&err_rl, "ip options not supported on tunnel packets " + "(%d bytes)", IP_IHL(nh->ip_ihl_ver) * 4); + return NULL; + } + tnl->ip_src = get_16aligned_be32(&nh->ip_src); tnl->ip_dst = get_16aligned_be32(&nh->ip_dst); tnl->ip_tos = nh->ip_tos; diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 502e41fe1..98f22ea2b 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -109,7 +109,7 @@ AT_CHECK([tail -1 stdout], [0], ]) dnl Check decapsulation of GRE packet -AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402f99080101025c0101025820006558000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820006558000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) ovs-appctl time/warp 1000 AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl @@ -117,7 +117,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl ]) dnl Check GRE only accepts encapsulated Ethernet frames -AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402f99080101025c0101025820000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) ovs-appctl time/warp 1000 AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl @@ -130,7 +130,7 @@ AT_CHECK([ovs-ofctl monitor int-br 65534 --detach --no-chdir --pidfile 2> ofctl_ AT_CHECK([ovs-ofctl del-flows int-br]) AT_CHECK([ovs-ofctl add-flow int-br "tun_metadata0=0xa/0xf,actions=5,controller"]) -AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab64080045000096794640004011ba630101025c01010258308817c1008200000400655800007b00ffff80010000000affff00010000000bfe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab64080045000096794640004011ba5b0101025c01010258308817c1008200000400655800007b00ffff80010000000affff00010000000bfe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 2]) OVS_APP_EXIT_AND_WAIT(ovs-ofctl) |