netdev-bsd: Fix sign extension bug in ifr_flags on FreeBSD.
[cascardo/ovs.git] / lib / netdev-bsd.c
index ef1e649..671de37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013 Gaetano Catalli.
+ * Copyright (c) 2011, 2013, 2014 Gaetano Catalli.
  * Copyright (c) 2013, 2014 YAMAMOTO Takashi.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -548,7 +548,7 @@ struct pcap_arg {
 static void
 proc_pkt(u_char *args_, const struct pcap_pkthdr *hdr, const u_char *packet)
 {
-    struct pcap_arg *args = (struct pcap_arg *)args_;
+    struct pcap_arg *args = ALIGNED_CAST(struct pcap_arg *, args_);
 
     if (args->size < hdr->len) {
         VLOG_WARN_RL(&rl, "packet truncated");
@@ -714,7 +714,7 @@ netdev_bsd_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
                 }
             }
         } else if (retval != size) {
-            VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIuSIZE"d bytes of "
+            VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIuSIZE" bytes of "
                          "%"PRIuSIZE") on %s", retval, size, name);
             error = EMSGSIZE;
         } else {
@@ -996,7 +996,7 @@ netdev_bsd_get_stats(const struct netdev *netdev_, struct netdev_stats *stats)
                         netdev_get_name(netdev_), ovs_strerror(errno));
             return errno;
         } else if (!strcmp(ifmd.ifmd_name, netdev_get_name(netdev_))) {
-            convert_stats(netdev, stats, &ifdr.ifdr_data);
+            convert_stats(netdev_, stats, &ifmd.ifmd_data);
             break;
         }
     }
@@ -1183,7 +1183,7 @@ netdev_bsd_get_in4(const struct netdev *netdev_, struct in_addr *in4,
         if (!error) {
             const struct sockaddr_in *sin;
 
-            sin = (struct sockaddr_in *) &ifr.ifr_addr;
+            sin = ALIGNED_CAST(struct sockaddr_in *, &ifr.ifr_addr);
             netdev->in4 = sin->sin_addr;
             netdev->cache_valid |= VALID_IN4;
             error = af_inet_ifreq_ioctl(netdev_get_kernel_name(netdev_), &ifr,
@@ -1251,7 +1251,7 @@ netdev_bsd_get_in6(const struct netdev *netdev_, struct in6_addr *in6)
         for (ifa = head; ifa; ifa = ifa->ifa_next) {
             if (ifa->ifa_addr->sa_family == AF_INET6 &&
                     !strcmp(ifa->ifa_name, netdev_name)) {
-                sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+                sin6 = ALIGNED_CAST(struct sockaddr_in6 *, ifa->ifa_addr);
                 if (sin6) {
                     memcpy(&netdev->in6, &sin6->sin6_addr, sin6->sin6_len);
                     netdev->cache_valid |= VALID_IN6;
@@ -1363,14 +1363,14 @@ netdev_bsd_get_next_hop(const struct in_addr *host OVS_UNUSED,
 
             if ((i == RTA_GATEWAY) && sa->sa_family == AF_INET) {
                 const struct sockaddr_in * const sin =
-                  (const struct sockaddr_in *)sa;
+                  ALIGNED_CAST(const struct sockaddr_in *, sa);
 
                 *next_hop = sin->sin_addr;
                 gateway = true;
             }
             if ((i == RTA_IFP) && sa->sa_family == AF_LINK) {
                 const struct sockaddr_dl * const sdl =
-                  (const struct sockaddr_dl *)sa;
+                  ALIGNED_CAST(const struct sockaddr_dl *, sa);
                 char *kernel_name;
 
                 kernel_name = xmemdup0(sdl->sdl_data, sdl->sdl_nlen);
@@ -1679,7 +1679,7 @@ get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN])
     for (ifa = head; ifa; ifa = ifa->ifa_next) {
         if (ifa->ifa_addr->sa_family == AF_LINK) {
             if (!strcmp(ifa->ifa_name, netdev_name)) {
-                sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+                sdl = ALIGNED_CAST(struct sockaddr_dl *, ifa->ifa_addr);
                 if (sdl) {
                     memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
                     freeifaddrs(head);
@@ -1771,7 +1771,7 @@ static int
 ifr_get_flags(const struct ifreq *ifr)
 {
 #ifdef HAVE_STRUCT_IFREQ_IFR_FLAGSHIGH
-    return (ifr->ifr_flagshigh << 16) | ifr->ifr_flags;
+    return (ifr->ifr_flagshigh << 16) | (ifr->ifr_flags & 0xffff);
 #else
     return ifr->ifr_flags;
 #endif
@@ -1780,12 +1780,15 @@ ifr_get_flags(const struct ifreq *ifr)
 static void
 ifr_set_flags(struct ifreq *ifr, int flags)
 {
-    ifr->ifr_flags = flags;
 #ifdef HAVE_STRUCT_IFREQ_IFR_FLAGSHIGH
+    ifr->ifr_flags = flags & 0xffff;
     ifr->ifr_flagshigh = flags >> 16;
+#else
+    ifr->ifr_flags = flags;
 #endif
 }
 
+#if defined(__NetBSD__)
 /* Calls ioctl() on an AF_LINK sock, passing the specified 'command' and
  * 'arg'.  Returns 0 if successful, otherwise a positive errno value. */
 int
@@ -1807,3 +1810,4 @@ af_link_ioctl(unsigned long command, const void *arg)
             : ioctl(sock, command, arg) == -1 ? errno
             : 0);
 }
+#endif