This looks like a good idea but the patch got wordwrapped at some point
so it's not possible to apply it with "git am".  I think that
SubmittingPatches has some pointers on how to send undamaged patches.

On Thu, Nov 07, 2013 at 11:22:24AM -0800, Saurabh Shah wrote:
> 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

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

Reply via email to