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 *)ð_key.eth_src, eth_key_src) || + !ovs_validate_and_copy_eth((uint8_t *)ð_key_mask.eth_src, eth_mask_src) || + !ovs_validate_and_copy_eth((uint8_t *)ð_key.eth_dst, eth_key_dst) || + !ovs_validate_and_copy_eth((uint8_t *)ð_key_mask.eth_dst, eth_mask_dst)) { + return -EINVAL; + } nl_msg_put_unspec(key, OVS_KEY_ATTR_ETHERNET, ð_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 *)ð_key.eth_src, + eth_key_src) || + !ovs_validate_and_copy_eth((uint8_t *)ð_key.eth_dst, + eth_key_dst)) { + return -EINVAL; + } nl_msg_put_unspec(key, OVS_KEY_ATTR_ETHERNET, ð_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