Microsoft compiler doesn't support C99 fully. In particular it doesn't
implement 'hh' length prefix-
http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.

Signed-off-by: Saurabh Shah <ssaur...@nicira.com>
---
 lib/bond.c        |    2 +-
 lib/meta-flow.c   |   32 ++++---
 lib/odp-util.c    |  247 +++++++++++++++++++++++++++++++++++------------------
 lib/ofp-parse.c   |    8 +-
 lib/packets.c     |   40 ++++++++-
 lib/packets.h     |   24 ++++--
 vswitchd/bridge.c |    4 +-
 7 files changed, 247 insertions(+), 110 deletions(-)

diff --git a/lib/bond.c b/lib/bond.c
index 5be1bae..ce7514b 100644
--- a/lib/bond.c
+++ b/lib/bond.c
@@ -1266,7 +1266,7 @@ bond_unixctl_hash(struct unixctl_conn *conn, int argc, 
const char *argv[],
         basis = 0;
     }
 
-    if (sscanf(mac_s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
+    if (sscanf(mac_s, ETH_X8_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
         == ETH_ADDR_SCAN_COUNT) {
         hash = bond_hash_src(mac, vlan, basis) & BOND_MASK;
 
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 9f39c18..1c5272c 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -2369,21 +2369,28 @@ mf_from_ethernet_string(const struct mf_field *mf, 
const char *s,
                         uint8_t mask[ETH_ADDR_LEN])
 {
     int n;
+    uint32_t mac_p[ETH_ADDR_LEN];
+    uint32_t mask_p[ETH_ADDR_LEN];
 
     ovs_assert(mf->n_bytes == ETH_ADDR_LEN);
 
     n = -1;
-    if (sscanf(s, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(mac), &n) > 0
+    if (sscanf(s, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(mac_p), &n) > 0
         && n == strlen(s)) {
-        memset(mask, 0xff, ETH_ADDR_LEN);
-        return NULL;
+        if (ovs_validate_and_copy_eth(mac, mac_p)) {
+            memset(mask, 0xff, ETH_ADDR_LEN);
+            return NULL;
+        }
     }
 
     n = -1;
     if (sscanf(s, ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT"%n",
-               ETH_ADDR_SCAN_ARGS(mac), ETH_ADDR_SCAN_ARGS(mask), &n) > 0
+               ETH_ADDR_SCAN_ARGS(mac_p), ETH_ADDR_SCAN_ARGS(mask_p), &n) > 0
         && n == strlen(s)) {
-        return NULL;
+        if (ovs_validate_and_copy_eth(mac, mac_p) &&
+            ovs_validate_and_copy_eth(mask, mask_p)) {
+            return NULL;
+        }
     }
 
     return xasprintf("%s: invalid Ethernet address", s);
@@ -2394,14 +2401,18 @@ mf_from_ipv4_string(const struct mf_field *mf, const 
char *s,
                     ovs_be32 *ip, ovs_be32 *mask)
 {
     int prefix;
+    uint32_t ip_p[IPV4_ADDR_LEN];
+    uint32_t mask_p[IPV4_ADDR_LEN];
 
     ovs_assert(mf->n_bytes == sizeof *ip);
 
-    if (sscanf(s, IP_SCAN_FMT"/"IP_SCAN_FMT,
-               IP_SCAN_ARGS(ip), IP_SCAN_ARGS(mask)) == IP_SCAN_COUNT * 2) {
+    if ((sscanf(s, IP_SCAN_FMT"/"IP_SCAN_FMT, IP_U32_SCAN_ARGS(ip_p),
+                IP_U32_SCAN_ARGS(mask_p)) == IP_SCAN_COUNT * 2) &&
+        ovs_validate_and_copy_ip(ip, ip_p) &&
+        ovs_validate_and_copy_ip(mask, mask_p)) {
         /* OK. */
-    } else if (sscanf(s, IP_SCAN_FMT"/%d",
-                      IP_SCAN_ARGS(ip), &prefix) == IP_SCAN_COUNT + 1) {
+    } else if ((sscanf(s, IP_SCAN_FMT"/%d", IP_U32_SCAN_ARGS(ip_p), &prefix) ==
+                IP_SCAN_COUNT + 1) && ovs_validate_and_copy_ip(ip, ip_p)) {
         if (prefix <= 0 || prefix > 32) {
             return xasprintf("%s: network prefix bits not between 1 and "
                              "32", s);
@@ -2410,7 +2421,8 @@ mf_from_ipv4_string(const struct mf_field *mf, const char 
*s,
         } else {
             *mask = htonl(((1u << prefix) - 1) << (32 - prefix));
         }
-    } else if (sscanf(s, IP_SCAN_FMT, IP_SCAN_ARGS(ip)) == IP_SCAN_COUNT) {
+    } else if ((sscanf(s, IP_SCAN_FMT, IP_U32_SCAN_ARGS(ip_p)) == 
IP_SCAN_COUNT) &&
+                ovs_validate_and_copy_ip(ip, ip_p)) {
         *mask = OVS_BE32_MAX;
     } else {
         return xasprintf("%s: invalid IP address", s);
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 6ac3853..c68a943 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -1618,20 +1618,31 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
         struct flow_tnl tun_key, tun_key_mask;
         unsigned long long tun_id_mask;
         int n = -1;
+        uint32_t tun_key_src[IPV4_ADDR_LEN];
+        uint32_t tun_key_dst[IPV4_ADDR_LEN];
+        uint32_t tun_mask_src[IPV4_ADDR_LEN];
+        uint32_t tun_mask_dst[IPV4_ADDR_LEN];
 
         if (mask && sscanf(s, 
"tunnel(tun_id=%31[x0123456789abcdefABCDEF]/%llx,"
                    "src="IP_SCAN_FMT"/"IP_SCAN_FMT",dst="IP_SCAN_FMT
                    "/"IP_SCAN_FMT",tos=%i/%i,ttl=%i/%i,flags%n",
                    tun_id_s, &tun_id_mask,
-                   IP_SCAN_ARGS(&tun_key.ip_src),
-                   IP_SCAN_ARGS(&tun_key_mask.ip_src),
-                   IP_SCAN_ARGS(&tun_key.ip_dst),
-                   IP_SCAN_ARGS(&tun_key_mask.ip_dst),
+                   IP_U32_SCAN_ARGS(tun_key_src),
+                   IP_U32_SCAN_ARGS(tun_mask_src),
+                   IP_U32_SCAN_ARGS(tun_key_dst),
+                   IP_U32_SCAN_ARGS(tun_mask_dst),
                    &tos, &tos_mask, &ttl, &ttl_mask,
                    &n) > 0 && n > 0) {
             int res;
             uint32_t flags;
 
+            if (!ovs_validate_and_copy_ip(&tun_key.ip_src, tun_key_src) ||
+                !ovs_validate_and_copy_ip(&tun_key_mask.ip_src, tun_mask_src) 
||
+                !ovs_validate_and_copy_ip(&tun_key.ip_dst, tun_key_dst) ||
+                !ovs_validate_and_copy_ip(&tun_key_mask.ip_dst, tun_mask_dst)) 
{
+               return -EINVAL;
+            }
+
             tun_key.tun_id = htonll(strtoull(tun_id_s, NULL, 0));
             tun_key_mask.tun_id = htonll(tun_id_mask);
             tun_key.ip_tos = tos;
@@ -1658,12 +1669,16 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
         } else if (sscanf(s, "tunnel(tun_id=%31[x0123456789abcdefABCDEF],"
                    "src="IP_SCAN_FMT",dst="IP_SCAN_FMT
                    ",tos=%i,ttl=%i,flags%n", tun_id_s,
-                    IP_SCAN_ARGS(&tun_key.ip_src),
-                    IP_SCAN_ARGS(&tun_key.ip_dst), &tos, &ttl,
+                    IP_U32_SCAN_ARGS(tun_key_src),
+                    IP_U32_SCAN_ARGS(tun_key_dst), &tos, &ttl,
                     &n) > 0 && n > 0) {
             int res;
             uint32_t flags;
 
+            if (!ovs_validate_and_copy_ip(&tun_key.ip_src, tun_key_src) ||
+                !ovs_validate_and_copy_ip(&tun_key.ip_dst, tun_key_dst)) {
+               return -EINVAL;
+            }
             tun_key.tun_id = htonll(strtoull(tun_id_s, NULL, 0));
             tun_key.ip_tos = tos;
             tun_key.ip_ttl = ttl;
@@ -1729,16 +1744,24 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
     {
         struct ovs_key_ethernet eth_key;
         struct ovs_key_ethernet eth_key_mask;
+        uint32_t eth_key_src[ETH_ADDR_LEN],  eth_key_dst[ETH_ADDR_LEN];
+        uint32_t eth_mask_src[ETH_ADDR_LEN],  eth_mask_dst[ETH_ADDR_LEN];
         int n = -1;
 
         if (mask && sscanf(s,
                    "eth(src="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT","
                         "dst="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT")%n",
-                ETH_ADDR_SCAN_ARGS(eth_key.eth_src),
-                ETH_ADDR_SCAN_ARGS(eth_key_mask.eth_src),
-                ETH_ADDR_SCAN_ARGS(eth_key.eth_dst),
-                ETH_ADDR_SCAN_ARGS(eth_key_mask.eth_dst), &n) > 0 && n > 0) {
-
+                ETH_ADDR_SCAN_ARGS(eth_key_src),
+                ETH_ADDR_SCAN_ARGS(eth_mask_src),
+                ETH_ADDR_SCAN_ARGS(eth_key_dst),
+                ETH_ADDR_SCAN_ARGS(eth_mask_dst), &n) > 0 && n > 0) {
+
+            if (!ovs_validate_and_copy_eth((uint8_t *)&eth_key.eth_src, 
eth_key_src) ||
+                !ovs_validate_and_copy_eth((uint8_t *)&eth_key_mask.eth_src, 
eth_mask_src) ||
+                !ovs_validate_and_copy_eth((uint8_t *)&eth_key.eth_dst, 
eth_key_dst) ||
+                !ovs_validate_and_copy_eth((uint8_t *)&eth_key_mask.eth_dst, 
eth_mask_dst)) {
+                return -EINVAL;
+            }
             nl_msg_put_unspec(key, OVS_KEY_ATTR_ETHERNET,
                               &eth_key, sizeof eth_key);
             nl_msg_put_unspec(mask, OVS_KEY_ATTR_ETHERNET,
@@ -1746,8 +1769,15 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
             return n;
         } else if (sscanf(s,
                    "eth(src="ETH_ADDR_SCAN_FMT",dst="ETH_ADDR_SCAN_FMT")%n",
-                   ETH_ADDR_SCAN_ARGS(eth_key.eth_src),
-                   ETH_ADDR_SCAN_ARGS(eth_key.eth_dst), &n) > 0 && n > 0) {
+                   ETH_ADDR_SCAN_ARGS(eth_key_src),
+                   ETH_ADDR_SCAN_ARGS(eth_key_dst), &n) > 0 && n > 0) {
+
+            if (!ovs_validate_and_copy_eth((uint8_t *)&eth_key.eth_src,
+                        eth_key_src) ||
+                !ovs_validate_and_copy_eth((uint8_t *)&eth_key.eth_dst,
+                      eth_key_dst)) {
+                return -EINVAL;
+            }
             nl_msg_put_unspec(key, OVS_KEY_ATTR_ETHERNET,
                               &eth_key, sizeof eth_key);
 
@@ -1869,8 +1899,10 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
 
 
     {
-        ovs_be32 ipv4_src, ipv4_src_mask;
-        ovs_be32 ipv4_dst, ipv4_dst_mask;
+        uint32_t ipv4_src[IPV4_ADDR_LEN];
+        uint32_t ipv4_dst[IPV4_ADDR_LEN];
+        uint32_t ipv4_src_mask[IPV4_ADDR_LEN];
+        uint32_t ipv4_dst_mask[IPV4_ADDR_LEN];
         int ipv4_proto, ipv4_proto_mask;
         int ipv4_tos, ipv4_tos_mask;
         int ipv4_ttl, ipv4_ttl_mask;
@@ -1883,18 +1915,21 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
                       "dst="IP_SCAN_FMT"/"IP_SCAN_FMT","
                       "proto=%i/%i,tos=%i/%i,ttl=%i/%i,"
                       "frag=%7[a-z]/%i)%n",
-                      IP_SCAN_ARGS(&ipv4_src), IP_SCAN_ARGS(&ipv4_src_mask),
-                      IP_SCAN_ARGS(&ipv4_dst), IP_SCAN_ARGS(&ipv4_dst_mask),
+                      IP_U32_SCAN_ARGS(ipv4_src), 
IP_U32_SCAN_ARGS(ipv4_src_mask),
+                      IP_U32_SCAN_ARGS(ipv4_dst), 
IP_U32_SCAN_ARGS(ipv4_dst_mask),
                       &ipv4_proto, &ipv4_proto_mask,
                       &ipv4_tos, &ipv4_tos_mask, &ipv4_ttl, &ipv4_ttl_mask,
                       frag, &ipv4_frag_mask, &n) > 0
             && n > 0
             && ovs_frag_type_from_string(frag, &ipv4_frag)) {
+
             struct ovs_key_ipv4 ipv4_key;
             struct ovs_key_ipv4 ipv4_mask;
 
-            ipv4_key.ipv4_src = ipv4_src;
-            ipv4_key.ipv4_dst = ipv4_dst;
+            if (!ovs_validate_and_copy_ip(&ipv4_key.ipv4_src, ipv4_src) ||
+                !ovs_validate_and_copy_ip(&ipv4_key.ipv4_dst, ipv4_dst)) {
+                return -EINVAL;
+            }
             ipv4_key.ipv4_proto = ipv4_proto;
             ipv4_key.ipv4_tos = ipv4_tos;
             ipv4_key.ipv4_ttl = ipv4_ttl;
@@ -1902,25 +1937,30 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
             nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV4,
                               &ipv4_key, sizeof ipv4_key);
 
-            ipv4_mask.ipv4_src = ipv4_src_mask;
-            ipv4_mask.ipv4_dst = ipv4_dst_mask;
+            if (!ovs_validate_and_copy_ip(&ipv4_mask.ipv4_src, ipv4_src_mask) 
||
+                !ovs_validate_and_copy_ip(&ipv4_mask.ipv4_dst, ipv4_dst_mask)) 
{
+                return -EINVAL;
+            }
             ipv4_mask.ipv4_proto = ipv4_proto_mask;
             ipv4_mask.ipv4_tos = ipv4_tos_mask;
             ipv4_mask.ipv4_ttl = ipv4_ttl_mask;
             ipv4_mask.ipv4_frag = ipv4_frag_mask;
+
             nl_msg_put_unspec(mask, OVS_KEY_ATTR_IPV4,
                               &ipv4_mask, sizeof ipv4_mask);
             return n;
         } else if (sscanf(s, "ipv4(src="IP_SCAN_FMT",dst="IP_SCAN_FMT","
                    "proto=%i,tos=%i,ttl=%i,frag=%7[a-z])%n",
-                   IP_SCAN_ARGS(&ipv4_src), IP_SCAN_ARGS(&ipv4_dst),
+                   IP_U32_SCAN_ARGS(ipv4_src), IP_U32_SCAN_ARGS(ipv4_dst),
                    &ipv4_proto, &ipv4_tos, &ipv4_ttl, frag, &n) > 0
             && n > 0
             && ovs_frag_type_from_string(frag, &ipv4_frag)) {
             struct ovs_key_ipv4 ipv4_key;
 
-            ipv4_key.ipv4_src = ipv4_src;
-            ipv4_key.ipv4_dst = ipv4_dst;
+            if (!ovs_validate_and_copy_ip(&ipv4_key.ipv4_src, ipv4_src) ||
+                !ovs_validate_and_copy_ip(&ipv4_key.ipv4_dst, ipv4_dst)) {
+                return -EINVAL;
+            }
             ipv4_key.ipv4_proto = ipv4_proto;
             ipv4_key.ipv4_tos = ipv4_tos;
             ipv4_key.ipv4_ttl = ipv4_ttl;
@@ -2197,14 +2237,16 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
     {
         struct ovs_key_icmpv6 icmpv6_key;
         struct ovs_key_icmpv6 icmpv6_mask;
-        int icmpv6_type_mask;
-        int icmpv6_code_mask;
+        int icmpv6_type, icmpv6_code;
+        int icmpv6_type_mask, icmpv6_code_mask;
         int n = -1;
 
-        if (mask && sscanf(s, "icmpv6(type=%"SCNi8"/%i,code=%"SCNi8"/%i)%n",
-                   &icmpv6_key.icmpv6_type, &icmpv6_type_mask,
-                   &icmpv6_key.icmpv6_code, &icmpv6_code_mask, &n) > 0
+        if (mask && sscanf(s, "icmpv6(type=%i/%i,code=%i/%i)%n",
+                   &icmpv6_type, &icmpv6_type_mask,
+                   &icmpv6_code, &icmpv6_code_mask, &n) > 0
             && n > 0) {
+            icmpv6_key.icmpv6_type = icmpv6_type;
+            icmpv6_key.icmpv6_code = icmpv6_code;
             nl_msg_put_unspec(key, OVS_KEY_ATTR_ICMPV6,
                               &icmpv6_key, sizeof icmpv6_key);
 
@@ -2213,9 +2255,11 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
             nl_msg_put_unspec(mask, OVS_KEY_ATTR_ICMPV6, &icmpv6_mask,
                               sizeof icmpv6_mask);
             return n;
-        } else if (sscanf(s, "icmpv6(type=%"SCNi8",code=%"SCNi8")%n",
-                   &icmpv6_key.icmpv6_type, &icmpv6_key.icmpv6_code,&n) > 0
+        } else if (sscanf(s, "icmpv6(type=%i,code=%i)%n",
+                   &icmpv6_type, &icmpv6_code,&n) > 0
             && n > 0) {
+            icmpv6_key.icmpv6_type = icmpv6_type;
+            icmpv6_key.icmpv6_code = icmpv6_code;
             nl_msg_put_unspec(key, OVS_KEY_ATTR_ICMPV6,
                               &icmpv6_key, sizeof icmpv6_key);
 
@@ -2229,21 +2273,22 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
     }
 
     {
-        ovs_be32 arp_sip, arp_sip_mask;
-        ovs_be32 arp_tip, arp_tip_mask;
+        uint32_t arp_sip[IPV4_ADDR_LEN], arp_sip_mask[IPV4_ADDR_LEN];
+        uint32_t arp_tip[IPV4_ADDR_LEN], arp_tip_mask[IPV4_ADDR_LEN];
+        uint32_t arp_sha[ETH_ADDR_LEN];
+        uint32_t arp_sha_mask[ETH_ADDR_LEN];
+        uint32_t arp_tha[ETH_ADDR_LEN];
+        uint32_t arp_tha_mask[ETH_ADDR_LEN];
+
         int arp_op, arp_op_mask;
-        uint8_t arp_sha[ETH_ADDR_LEN];
-        uint8_t arp_sha_mask[ETH_ADDR_LEN];
-        uint8_t arp_tha[ETH_ADDR_LEN];
-        uint8_t arp_tha_mask[ETH_ADDR_LEN];
         int n = -1;
 
         if (mask && sscanf(s, "arp(sip="IP_SCAN_FMT"/"IP_SCAN_FMT","
                    "tip="IP_SCAN_FMT"/"IP_SCAN_FMT","
                    "op=%i/%i,sha="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT","
                    "tha="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT")%n",
-                   IP_SCAN_ARGS(&arp_sip), IP_SCAN_ARGS(&arp_sip_mask),
-                   IP_SCAN_ARGS(&arp_tip), IP_SCAN_ARGS(&arp_tip_mask),
+                   IP_U32_SCAN_ARGS(arp_sip), IP_U32_SCAN_ARGS(arp_sip_mask),
+                   IP_U32_SCAN_ARGS(arp_tip), IP_U32_SCAN_ARGS(arp_tip_mask),
                    &arp_op, &arp_op_mask,
                    ETH_ADDR_SCAN_ARGS(arp_sha),
                    ETH_ADDR_SCAN_ARGS(arp_sha_mask),
@@ -2253,36 +2298,48 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
             struct ovs_key_arp arp_mask;
 
             memset(&arp_key, 0, sizeof arp_key);
-            arp_key.arp_sip = arp_sip;
-            arp_key.arp_tip = arp_tip;
+            if (!ovs_validate_and_copy_ip(&arp_key.arp_sip, arp_sip) ||
+                !ovs_validate_and_copy_ip(&arp_key.arp_tip, arp_tip) ||
+                !ovs_validate_and_copy_eth((uint8_t *) &arp_key.arp_sha,
+                    arp_sha) ||
+                !ovs_validate_and_copy_eth((uint8_t *) &arp_key.arp_tha,
+                    arp_tha)) {
+                return -EINVAL;
+            }
             arp_key.arp_op = htons(arp_op);
-            memcpy(arp_key.arp_sha, arp_sha, ETH_ADDR_LEN);
-            memcpy(arp_key.arp_tha, arp_tha, ETH_ADDR_LEN);
             nl_msg_put_unspec(key, OVS_KEY_ATTR_ARP, &arp_key, sizeof arp_key);
 
-            arp_mask.arp_sip = arp_sip_mask;
-            arp_mask.arp_tip = arp_tip_mask;
+            if (!ovs_validate_and_copy_ip(&arp_mask.arp_sip, arp_sip_mask) ||
+                !ovs_validate_and_copy_ip(&arp_mask.arp_tip, arp_tip_mask) ||
+                !ovs_validate_and_copy_eth((uint8_t *) &arp_mask.arp_sha,
+                    arp_sha_mask) ||
+                !ovs_validate_and_copy_eth((uint8_t *) &arp_mask.arp_tha,
+                    arp_tha_mask)) {
+                return -EINVAL;
+            }
             arp_mask.arp_op = htons(arp_op_mask);
-            memcpy(arp_mask.arp_sha, arp_sha_mask, ETH_ADDR_LEN);
-            memcpy(arp_mask.arp_tha, arp_tha_mask, ETH_ADDR_LEN);
             nl_msg_put_unspec(mask, OVS_KEY_ATTR_ARP,
                               &arp_mask, sizeof arp_mask);
             return n;
         } else if (sscanf(s, "arp(sip="IP_SCAN_FMT",tip="IP_SCAN_FMT","
                    "op=%i,sha="ETH_ADDR_SCAN_FMT",tha="ETH_ADDR_SCAN_FMT")%n",
-                   IP_SCAN_ARGS(&arp_sip),
-                   IP_SCAN_ARGS(&arp_tip),
+                   IP_U32_SCAN_ARGS(arp_sip),
+                   IP_U32_SCAN_ARGS(arp_tip),
                    &arp_op,
                    ETH_ADDR_SCAN_ARGS(arp_sha),
                    ETH_ADDR_SCAN_ARGS(arp_tha), &n) > 0 && n > 0) {
             struct ovs_key_arp arp_key;
 
             memset(&arp_key, 0, sizeof arp_key);
-            arp_key.arp_sip = arp_sip;
-            arp_key.arp_tip = arp_tip;
+            if (!ovs_validate_and_copy_ip(&arp_key.arp_sip, arp_sip) ||
+                !ovs_validate_and_copy_ip(&arp_key.arp_tip, arp_tip) ||
+                !ovs_validate_and_copy_eth((uint8_t *) &arp_key.arp_sha,
+                    arp_sha) ||
+                !ovs_validate_and_copy_eth((uint8_t *) &arp_key.arp_tha,
+                    arp_tha)) {
+                return -EINVAL;
+            }
             arp_key.arp_op = htons(arp_op);
-            memcpy(arp_key.arp_sha, arp_sha, ETH_ADDR_LEN);
-            memcpy(arp_key.arp_tha, arp_tha, ETH_ADDR_LEN);
             nl_msg_put_unspec(key, OVS_KEY_ATTR_ARP, &arp_key, sizeof arp_key);
 
             if (mask) {
@@ -2297,6 +2354,8 @@ parse_odp_key_mask_attr(const char *s, const struct simap 
*port_names,
     {
         char nd_target_s[IPV6_SCAN_LEN + 1];
         char nd_target_mask_s[IPV6_SCAN_LEN + 1];
+        uint32_t tmp_sll[ETH_ADDR_LEN], tmp_sll_mask[ETH_ADDR_LEN];
+        uint32_t tmp_tll[ETH_ADDR_LEN], tmp_tll_mask[ETH_ADDR_LEN];
         uint8_t nd_sll[ETH_ADDR_LEN];
         uint8_t nd_sll_mask[ETH_ADDR_LEN];
         uint8_t nd_tll[ETH_ADDR_LEN];
@@ -2309,61 +2368,79 @@ parse_odp_key_mask_attr(const char *s, const struct 
simap *port_names,
 
         if (mask && sscanf(s, "nd(target="IPV6_SCAN_FMT"/"IPV6_SCAN_FMT")%n",
                    nd_target_s, nd_target_mask_s, &n) > 0 && n > 0) {
-                put_nd_key(n, nd_target_s, NULL, NULL, key);
-                put_nd_mask(n, nd_target_mask_s, NULL, NULL, mask);
+            put_nd_key(n, nd_target_s, NULL, NULL, key);
+            put_nd_mask(n, nd_target_mask_s, NULL, NULL, mask);
         } else if (sscanf(s, "nd(target="IPV6_SCAN_FMT")%n",
                    nd_target_s, &n) > 0 && n > 0) {
-                put_nd_key(n, nd_target_s, NULL, NULL, key);
-                if (mask) {
-                    put_nd_mask(n, nd_target_mask_s, NULL, NULL, mask);
-                }
+            put_nd_key(n, nd_target_s, NULL, NULL, key);
+            if (mask) {
+                put_nd_mask(n, nd_target_mask_s, NULL, NULL, mask);
+            }
         } else if (mask && sscanf(s, "nd(target="IPV6_SCAN_FMT"/"IPV6_SCAN_FMT
                          ",sll="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT")%n",
                    nd_target_s, nd_target_mask_s,
-                   ETH_ADDR_SCAN_ARGS(nd_sll),
-                   ETH_ADDR_SCAN_ARGS(nd_sll_mask), &n) > 0 && n > 0) {
-            put_nd_key(n, nd_target_s, nd_sll, NULL, key);
-            put_nd_mask(n, nd_target_mask_s, nd_sll_mask, NULL, mask);
+                   ETH_ADDR_SCAN_ARGS(tmp_sll),
+                   ETH_ADDR_SCAN_ARGS(tmp_sll_mask), &n) > 0 && n > 0) {
+            if (ovs_validate_and_copy_eth(nd_sll, tmp_sll)
+                && ovs_validate_and_copy_eth(nd_sll_mask, tmp_sll_mask)) {
+                put_nd_key(n, nd_target_s, nd_sll, NULL, key);
+                put_nd_mask(n, nd_target_mask_s, nd_sll_mask, NULL, mask);
+            }
         } else if (sscanf(s, 
"nd(target="IPV6_SCAN_FMT",sll="ETH_ADDR_SCAN_FMT")%n",
-                   nd_target_s, ETH_ADDR_SCAN_ARGS(nd_sll), &n) > 0
+                   nd_target_s, ETH_ADDR_SCAN_ARGS(tmp_sll), &n) > 0
             && n > 0) {
-            put_nd_key(n, nd_target_s, nd_sll, NULL, key);
-            if (mask) {
-                put_nd_mask(n, nd_target_mask_s, nd_sll_mask, NULL, mask);
+            if (ovs_validate_and_copy_eth(nd_sll, tmp_sll)) {
+                put_nd_key(n, nd_target_s, nd_sll, NULL, key);
+                if (mask) {
+                    put_nd_mask(n, nd_target_mask_s, nd_sll_mask, NULL, mask);
+                }
             }
         } else if (mask && sscanf(s, "nd(target="IPV6_SCAN_FMT"/"IPV6_SCAN_FMT
                          ",tll="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT")%n",
                    nd_target_s, nd_target_mask_s,
-                   ETH_ADDR_SCAN_ARGS(nd_tll),
-                   ETH_ADDR_SCAN_ARGS(nd_tll_mask), &n) > 0 && n > 0) {
-            put_nd_key(n, nd_target_s, NULL, nd_tll, key);
-            put_nd_mask(n, nd_target_mask_s, NULL, nd_tll_mask, mask);
+                   ETH_ADDR_SCAN_ARGS(tmp_tll),
+                   ETH_ADDR_SCAN_ARGS(tmp_tll_mask), &n) > 0 && n > 0) {
+            if (ovs_validate_and_copy_eth(nd_tll, tmp_tll)
+                && ovs_validate_and_copy_eth(nd_tll_mask, tmp_tll_mask)) {
+                put_nd_key(n, nd_target_s, NULL, nd_tll, key);
+                put_nd_mask(n, nd_target_mask_s, NULL, nd_tll_mask, mask);
+            }
         } else if (sscanf(s, 
"nd(target="IPV6_SCAN_FMT",tll="ETH_ADDR_SCAN_FMT")%n",
-                   nd_target_s, ETH_ADDR_SCAN_ARGS(nd_tll), &n) > 0
+                   nd_target_s, ETH_ADDR_SCAN_ARGS(tmp_tll), &n) > 0
             && n > 0) {
-            put_nd_key(n, nd_target_s, NULL, nd_tll, key);
-            if (mask) {
-                put_nd_mask(n, nd_target_mask_s, NULL, nd_tll_mask, mask);
+            if (ovs_validate_and_copy_eth(nd_tll, tmp_tll)) {
+                put_nd_key(n, nd_target_s, NULL, nd_tll, key);
+                if (mask) {
+                    put_nd_mask(n, nd_target_mask_s, NULL, nd_tll_mask, mask);
+                }
             }
         } else if (mask && sscanf(s, "nd(target="IPV6_SCAN_FMT"/"IPV6_SCAN_FMT
                    ",sll="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT","
                    "tll="ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT")%n",
                    nd_target_s, nd_target_mask_s,
-                   ETH_ADDR_SCAN_ARGS(nd_sll), ETH_ADDR_SCAN_ARGS(nd_sll_mask),
-                   ETH_ADDR_SCAN_ARGS(nd_tll), ETH_ADDR_SCAN_ARGS(nd_tll_mask),
+                   ETH_ADDR_SCAN_ARGS(tmp_sll), 
ETH_ADDR_SCAN_ARGS(tmp_sll_mask),
+                   ETH_ADDR_SCAN_ARGS(tmp_tll), 
ETH_ADDR_SCAN_ARGS(tmp_tll_mask),
                    &n) > 0
             && n > 0) {
-            put_nd_key(n, nd_target_s, nd_sll, nd_tll, key);
-            put_nd_mask(n, nd_target_mask_s, nd_sll_mask, nd_tll_mask, mask);
+            if (ovs_validate_and_copy_eth(nd_sll, tmp_sll)
+                && ovs_validate_and_copy_eth(nd_sll_mask, tmp_sll_mask)
+                && ovs_validate_and_copy_eth(nd_tll, tmp_tll)
+                && ovs_validate_and_copy_eth(nd_tll_mask, tmp_tll_mask)) {
+                put_nd_key(n, nd_target_s, nd_sll, nd_tll, key);
+                put_nd_mask(n, nd_target_mask_s, nd_sll_mask, nd_tll_mask, 
mask);
+            }
         } else if (sscanf(s, 
"nd(target="IPV6_SCAN_FMT",sll="ETH_ADDR_SCAN_FMT","
                    "tll="ETH_ADDR_SCAN_FMT")%n",
-                   nd_target_s, ETH_ADDR_SCAN_ARGS(nd_sll),
-                   ETH_ADDR_SCAN_ARGS(nd_tll), &n) > 0
+                   nd_target_s, ETH_ADDR_SCAN_ARGS(tmp_sll),
+                   ETH_ADDR_SCAN_ARGS(tmp_tll), &n) > 0
             && n > 0) {
-            put_nd_key(n, nd_target_s, nd_sll, nd_tll, key);
-            if (mask) {
-                put_nd_mask(n, nd_target_mask_s,
-                            nd_sll_mask, nd_tll_mask, mask);
+            if (ovs_validate_and_copy_eth(nd_sll, tmp_sll)
+                && ovs_validate_and_copy_eth(nd_tll, tmp_tll)) {
+                put_nd_key(n, nd_target_s, nd_sll, nd_tll, key);
+                if (mask) {
+                    put_nd_mask(n, nd_target_mask_s,
+                                nd_sll_mask, nd_tll_mask, mask);
+                }
             }
         }
 
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 915dc90..5985c38 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -147,9 +147,11 @@ str_to_be64(const char *str, ovs_be64 *valuep)
 static char * WARN_UNUSED_RESULT
 str_to_mac(const char *str, uint8_t mac[6])
 {
-    if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
-        != ETH_ADDR_SCAN_COUNT) {
-        return xasprintf("invalid mac address %s", str);
+    uint32_t mac_tmp[ETH_ADDR_LEN];
+
+    if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac_tmp))
+        != ETH_ADDR_SCAN_COUNT || !ovs_validate_and_copy_eth(mac, mac_tmp)) {
+        ovs_fatal(0, "invalid mac address %s", str);
     }
     return NULL;
 }
diff --git a/lib/packets.c b/lib/packets.c
index dc1970a..58bf2f6 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -130,8 +130,10 @@ eth_addr_is_reserved(const uint8_t ea[ETH_ADDR_LEN])
 bool
 eth_addr_from_string(const char *s, uint8_t ea[ETH_ADDR_LEN])
 {
-    if (sscanf(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea))
-        == ETH_ADDR_SCAN_COUNT) {
+    uint32_t ea_tmp[ETH_ADDR_LEN];
+
+    if (sscanf(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea_tmp))
+        == ETH_ADDR_SCAN_COUNT && ovs_validate_and_copy_eth(ea, ea_tmp)) {
         return true;
     } else {
         memset(ea, 0, ETH_ADDR_LEN);
@@ -958,3 +960,37 @@ packet_format_tcp_flags(struct ds *s, uint16_t tcp_flags)
         ds_put_cstr(s, "[800]");
     }
 }
+
+static bool
+ovs_validate_and_copy__(uint8_t dst[], int dst_size, uint32_t src[], int 
src_size)
+{
+    int i = 0, size = 0;
+
+    if (!dst || !src || src_size < 0 || dst_size < 0) {
+        return false;
+    }
+
+    if (dst == (uint8_t *) src) {
+        return true;
+    }
+
+    size = (dst_size <= src_size)? dst_size : src_size;
+    for (i = 0; i < size && src[i] <= 0xff; i++) {
+        dst[i] = src[i];
+    }
+    return i==size;
+}
+
+inline bool
+ovs_validate_and_copy_eth(uint8_t dst[ETH_ADDR_LEN], uint32_t
+        src[ETH_ADDR_LEN])
+{
+    return ovs_validate_and_copy__(dst, ETH_ADDR_LEN, src, ETH_ADDR_LEN);
+}
+
+inline bool
+ovs_validate_and_copy_ip(ovs_be32 *dst, uint32_t src[IPV4_ADDR_LEN])
+{
+    return ovs_validate_and_copy__((uint8_t *)dst, IPV4_ADDR_LEN, src,
+            IPV4_ADDR_LEN);
+}
diff --git a/lib/packets.h b/lib/packets.h
index f4f00ce..850acc1 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -34,6 +34,7 @@ struct ds;
 bool dpid_from_string(const char *s, uint64_t *dpidp);
 
 #define ETH_ADDR_LEN           6
+#define IPV4_ADDR_LEN          4
 
 static const uint8_t eth_addr_broadcast[ETH_ADDR_LEN] OVS_UNUSED
     = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -186,7 +187,8 @@ ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, 
uint8_t bos,
  *     ...
  * }
  */
-#define ETH_ADDR_SCAN_FMT "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8
+#define ETH_ADDR_SCAN_FMT "%x:%x:%x:%x:%x:%x"
+#define ETH_X8_ADDR_SCAN_FMT 
"%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8
 #define ETH_ADDR_SCAN_ARGS(ea) \
         &(ea)[0], &(ea)[1], &(ea)[2], &(ea)[3], &(ea)[4], &(ea)[5]
 #define ETH_ADDR_SCAN_COUNT 6
@@ -382,16 +384,18 @@ mpls_lse_to_bos(ovs_be32 mpls_lse)
  * int a, b;
  *
  * if (sscanf(string, "%d"IP_SCAN_FMT"%d",
- *     &a, IP_SCAN_ARGS(&ip), &b) == 1 + IP_SCAN_COUNT + 1) {
+ *     &a, IP_U32_SCAN_ARGS(&ip), &b) == 1 + IP_SCAN_COUNT + 1) {
  *     ...
  * }
  */
-#define IP_SCAN_FMT "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8
-#define IP_SCAN_ARGS(ip)                                    \
-        ((void) (ovs_be32) *(ip), &((uint8_t *) ip)[0]),    \
-        &((uint8_t *) ip)[1],                               \
-        &((uint8_t *) ip)[2],                               \
-        &((uint8_t *) ip)[3]
+#define IP_SCAN_FMT "%u.%u.%u.%u"
+
+#define IP_U32_SCAN_ARGS(ip)                        \
+        &(ip)[0],                               \
+        &(ip)[1],                               \
+        &(ip)[2],                               \
+        &(ip)[3]
+
 #define IP_SCAN_COUNT 4
 
 /* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N
@@ -647,4 +651,8 @@ void packet_set_sctp_port(struct ofpbuf *, ovs_be16 src, 
ovs_be16 dst);
 uint16_t packet_get_tcp_flags(const struct ofpbuf *, const struct flow *);
 void packet_format_tcp_flags(struct ds *, uint16_t);
 
+bool ovs_validate_and_copy_eth(uint8_t dst[ETH_ADDR_LEN],
+                               uint32_t src[ETH_ADDR_LEN]);
+bool ovs_validate_and_copy_ip(ovs_be32 *dst, uint32_t src[IPV4_ADDR_LEN]);
+
 #endif /* packets.h */
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index fecae60..85f5993 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -3293,6 +3293,7 @@ port_configure_lacp(struct port *port, struct 
lacp_settings *s)
 {
     const char *lacp_time, *system_id;
     int priority;
+    uint32_t tmp_id[ETH_ADDR_LEN];
 
     if (!enable_lacp(port, &s->active)) {
         return NULL;
@@ -3303,11 +3304,12 @@ port_configure_lacp(struct port *port, struct 
lacp_settings *s)
     system_id = smap_get(&port->cfg->other_config, "lacp-system-id");
     if (system_id) {
         if (sscanf(system_id, ETH_ADDR_SCAN_FMT,
-                   ETH_ADDR_SCAN_ARGS(s->id)) != ETH_ADDR_SCAN_COUNT) {
+                   ETH_ADDR_SCAN_ARGS(tmp_id)) != ETH_ADDR_SCAN_COUNT) {
             VLOG_WARN("port %s: LACP system ID (%s) must be an Ethernet"
                       " address.", port->name, system_id);
             return NULL;
         }
+        ovs_validate_and_copy_eth(s->id, tmp_id);
     } else {
         memcpy(s->id, port->bridge->ea, ETH_ADDR_LEN);
     }
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to