]> git.proxmox.com Git - mirror_ovs.git/blobdiff - lib/packets.c
dpif-netdev: Reorder elements in dp_netdev_port structure.
[mirror_ovs.git] / lib / packets.c
index 1bf887e2269e1f0919fabb004595b6c073db50e8..990c407c51f9ed6cd54ff8ec65c9138f2a1e2c36 100644 (file)
@@ -140,10 +140,15 @@ eth_addr_is_reserved(const struct eth_addr ea)
     return false;
 }
 
+/* Attempts to parse 's' as an Ethernet address.  If successful, stores the
+ * address in 'ea' and returns true, otherwise zeros 'ea' and returns
+ * false.  This function checks trailing characters. */
 bool
 eth_addr_from_string(const char *s, struct eth_addr *ea)
 {
-    if (ovs_scan(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(*ea))) {
+    int n = 0;
+    if (ovs_scan(s, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(*ea), &n)
+        && !s[n]) {
         return true;
     } else {
         *ea = eth_addr_zero;
@@ -424,6 +429,24 @@ ip_parse(const char *s, ovs_be32 *ip)
     return inet_pton(AF_INET, s, ip) == 1;
 }
 
+/* Parses string 's', which must be an IP address with a port number
+ * with ":" as a separator (e.g.: 192.168.1.2:80).
+ * Stores the IP address into '*ip' and port number to '*port'. */
+char * OVS_WARN_UNUSED_RESULT
+ip_parse_port(const char *s, ovs_be32 *ip, ovs_be16 *port)
+{
+    int n = 0;
+    if (!ovs_scan_len(s, &n, IP_PORT_SCAN_FMT,
+                IP_PORT_SCAN_ARGS(ip, port))) {
+        return xasprintf("%s: invalid IP address or port number", s);
+    }
+
+    if (s[n]) {
+        return xasprintf("%s: invalid IP address or port number", s);
+    }
+    return NULL;
+}
+
 /* Parses string 's', which must be an IP address with an optional netmask or
  * CIDR prefix length.  Stores the IP address into '*ip', netmask into '*mask',
  * (255.255.255.255, if 's' lacks a netmask), and number of scanned characters
@@ -1319,29 +1342,36 @@ compose_arp__(struct dp_packet *b)
     dp_packet_set_l3(b, arp);
 }
 
-/* This function expect packet with ethernet header with correct
+/* This function expects packet with ethernet header with correct
  * l3 pointer set. */
 static void *
-compose_ipv6(struct dp_packet *packet, uint8_t proto, const ovs_be32 src[4],
-             const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl,
-             uint8_t key_hl, int size)
+compose_ipv6(struct dp_packet *packet, uint8_t proto,
+             const struct in6_addr *src, const struct in6_addr *dst,
+             uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size)
 {
     struct ip6_hdr *nh;
     void *data;
 
+    /* Copy 'src' and 'dst' to temporary buffers to prevent misaligned
+     * accesses. */
+    ovs_be32 sbuf[4], dbuf[4];
+    memcpy(sbuf, src, sizeof sbuf);
+    memcpy(dbuf, dst, sizeof dbuf);
+
     nh = dp_packet_l3(packet);
     nh->ip6_vfc = 0x60;
     nh->ip6_nxt = proto;
     nh->ip6_plen = htons(size);
     data = dp_packet_put_zeros(packet, size);
     dp_packet_set_l4(packet, data);
-    packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl);
+    packet_set_ipv6(packet, sbuf, dbuf, key_tc, key_fl, key_hl);
     return data;
 }
 
+/* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */
 void
-compose_nd(struct dp_packet *b, const struct eth_addr eth_src,
-           struct in6_addr *ipv6_src, struct in6_addr *ipv6_dst)
+compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,
+              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst)
 {
     struct in6_addr sn_addr;
     struct eth_addr eth_dst;
@@ -1353,11 +1383,8 @@ compose_nd(struct dp_packet *b, const struct eth_addr eth_src,
     ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);
 
     eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
-    ns = compose_ipv6(b, IPPROTO_ICMPV6,
-                      ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
-                      ALIGNED_CAST(ovs_be32 *, sn_addr.s6_addr),
-                      0, 0, 255,
-                      ND_MSG_LEN + ND_OPT_LEN);
+    ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr,
+                      0, 0, 255, ND_MSG_LEN + ND_OPT_LEN);
 
     ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
     ns->icmph.icmp6_code = 0;
@@ -1367,27 +1394,31 @@ compose_nd(struct dp_packet *b, const struct eth_addr eth_src,
     nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
     nd_opt->nd_opt_len = 1;
 
-    packet_set_nd(b, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
-                  eth_src, eth_addr_zero);
+    /* Copy target address to temp buffer to prevent misaligned access. */
+    ovs_be32 tbuf[4];
+    memcpy(tbuf, ipv6_dst->s6_addr, sizeof tbuf);
+    packet_set_nd(b, tbuf, eth_src, eth_addr_zero);
+
     ns->icmph.icmp6_cksum = 0;
     icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
     ns->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, ns,
                                                       ND_MSG_LEN + ND_OPT_LEN));
 }
 
+/* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */
 void
-compose_na(struct dp_packet *b,
-           const struct eth_addr eth_src, const struct eth_addr eth_dst,
-           const ovs_be32 ipv6_src[4], const ovs_be32 ipv6_dst[4],
-           ovs_be32 rso_flags)
+compose_nd_na(struct dp_packet *b,
+              const struct eth_addr eth_src, const struct eth_addr eth_dst,
+              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,
+              ovs_be32 rso_flags)
 {
     struct ovs_nd_msg *na;
     struct ovs_nd_opt *nd_opt;
     uint32_t icmp_csum;
 
     eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
-    na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255,
-                      ND_MSG_LEN + ND_OPT_LEN);
+    na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst,
+                      0, 0, 255, ND_MSG_LEN + ND_OPT_LEN);
 
     na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;
     na->icmph.icmp6_code = 0;
@@ -1397,7 +1428,11 @@ compose_na(struct dp_packet *b,
     nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
     nd_opt->nd_opt_len = 1;
 
-    packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src);
+    /* Copy target address to temp buffer to prevent misaligned access. */
+    ovs_be32 tbuf[4];
+    memcpy(tbuf, ipv6_src->s6_addr, sizeof tbuf);
+    packet_set_nd(b, tbuf, eth_addr_zero, eth_src);
+
     na->icmph.icmp6_cksum = 0;
     icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
     na->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, na,