Return netmask along with IP address when querying through netdev
[sliver-openvswitch.git] / lib / netdev.c
index a43a3ca..07cfca4 100644 (file)
@@ -781,10 +781,12 @@ netdev_set_advertisements(struct netdev *netdev, uint32_t advertise)
     return do_ethtool(netdev, &ecmd, ETHTOOL_SSET, "ETHTOOL_SSET");
 }
 
-/* If 'netdev' has an assigned IPv4 address, sets '*in4' to that address (if
- * 'in4' is non-null) and returns true.  Otherwise, returns false. */
+/* If 'netdev' has an assigned IPv4 address, sets '*in4' to that address
+ * and '*mask' to the netmask (if they are non-null) and returns true.
+ * Otherwise, returns false. */
 bool
-netdev_nodev_get_in4(const char *netdev_name, struct in_addr *in4)
+netdev_nodev_get_in4(const char *netdev_name, struct in_addr *in4,
+                     struct in_addr *mask)
 {
     struct ifreq ifr;
     struct in_addr ip = { INADDR_ANY };
@@ -804,13 +806,25 @@ netdev_nodev_get_in4(const char *netdev_name, struct in_addr *in4)
     if (in4) {
         *in4 = ip;
     }
+
+    if (mask) {
+        if (ioctl(af_inet_sock, SIOCGIFNETMASK, &ifr) == 0) {
+            struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
+            *mask = sin->sin_addr;
+        } else {
+            VLOG_DBG_RL(&rl, "%s: ioctl(SIOCGIFNETMASK) failed: %s",
+                        netdev_name, strerror(errno));
+        }
+    }
+
     return ip.s_addr != INADDR_ANY;
 }
 
 bool
-netdev_get_in4(const struct netdev *netdev, struct in_addr *in4)
+netdev_get_in4(const struct netdev *netdev, struct in_addr *in4, struct
+               in_addr *mask)
 {
-    return netdev_nodev_get_in4(netdev->name, in4);
+    return netdev_nodev_get_in4(netdev->name, in4, mask);
 }
 
 static void
@@ -1309,7 +1323,7 @@ netdev_find_dev_by_in4(const struct in_addr *in4, char **netdev_name)
     struct svec dev_list;
 
     /* Check the hint first. */
-    if (*netdev_name && (netdev_nodev_get_in4(*netdev_name, &dev_in4)) 
+    if (*netdev_name && (netdev_nodev_get_in4(*netdev_name, &dev_in4, NULL))
             && (dev_in4.s_addr == in4->s_addr)) {
         return true;
     }
@@ -1319,7 +1333,7 @@ netdev_find_dev_by_in4(const struct in_addr *in4, char **netdev_name)
     netdev_enumerate(&dev_list);
 
     for (i=0; i<dev_list.n; i++) {
-        if ((netdev_nodev_get_in4(dev_list.names[i], &dev_in4)) 
+        if ((netdev_nodev_get_in4(dev_list.names[i], &dev_in4, NULL))
                 && (dev_in4.s_addr == in4->s_addr)) {
             *netdev_name = xstrdup(dev_list.names[i]);
             svec_destroy(&dev_list);