Blob Blame History Raw
From 3fb3e512bc90714907a520fb4a7ef84582bce6a7 Mon Sep 17 00:00:00 2001
Message-Id: <3fb3e512bc90714907a520fb4a7ef84582bce6a7.1578588395.git.lorenzo.bianconi@redhat.com>
In-Reply-To: <600a018ea1136e184b421c86da170b35d05e949f.1578588395.git.lorenzo.bianconi@redhat.com>
References: <600a018ea1136e184b421c86da170b35d05e949f.1578588395.git.lorenzo.bianconi@redhat.com>
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Date: Tue, 7 Jan 2020 17:50:06 +0100
Subject: [PATCH 3/3] RA Route Info Option: copy route info string in order to
 avoid truncated value

ipv6_ra_send can run 2 times in a row before prepare_ipv6_ras updates
the route info. Copy route info string in packet_put_ra_route_info_opt
in order to avoid sending truncated route info on the wire.
Moreover move ip6_hdr definition just before accessing it because the
packet can be reallocated if the data area is not big enough for packet
content

Fixes: 9f7f466af ("Add support for Route Info Option in RA - RFC 4191")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Numan Siddique <numans@ovn.org>
---
 ovn/controller/pinctrl.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -2473,13 +2473,14 @@ out:
 
 static void
 packet_put_ra_route_info_opt(struct dp_packet *b, ovs_be32 lifetime,
-                             char *route_list)
+                             char *route_data)
 {
     size_t prev_l4_size = dp_packet_l4_size(b);
-    struct ip6_hdr *nh = dp_packet_l3(b);
-    char *t0, *r0 = NULL;
+    char *route_list, *t0, *r0 = NULL;
     size_t size = 0;
 
+    route_list = xstrdup(route_data);
+
     for (t0 = strtok_r(route_list, ",", &r0); t0;
          t0 = strtok_r(NULL, ",", &r0)) {
         struct ovs_nd_route_info nd_rinfo;
@@ -2507,11 +2508,11 @@ packet_put_ra_route_info_opt(struct dp_p
                 uint8_t plen;
 
                 if (!extract_ip_addresses(t1, &route)) {
-                    return;
+                    goto out;
                 }
                 if (!route.n_ipv6_addrs) {
                     destroy_lport_addresses(&route);
-                    return;
+                    goto out;
                 }
 
                 nd_rinfo.prefix_len = route.ipv6_addrs->plen;
@@ -2526,17 +2527,20 @@ packet_put_ra_route_info_opt(struct dp_p
                 break;
             }
             default:
-                return;
+                goto out;
             }
         }
     }
 
+    struct ip6_hdr *nh = dp_packet_l3(b);
     nh->ip6_plen = htons(prev_l4_size + size);
     struct ovs_ra_msg *ra = dp_packet_l4(b);
     ra->icmph.icmp6_cksum = 0;
     uint32_t icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
     ra->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, ra,
                                                       prev_l4_size + size));
+out:
+    free(route_list);
 }
 
 /* Called with in the pinctrl_handler thread context. */
@@ -2580,7 +2584,7 @@ ipv6_ra_send(struct rconn *swconn, struc
     }
     if (ra->config->route_info.length) {
         packet_put_ra_route_info_opt(&packet, htonl(0xffffffff),
-                                     ra->config->route_info.string);
+                                     ds_cstr(&ra->config->route_info));
     }
 
     uint64_t ofpacts_stub[4096 / 8];