From 2b906eca2a06b2d351118041bc9a7b8d118eb626 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 31 Jul 2013 15:22:12 -0700 Subject: [PATCH] netdev-bsd: Correctly handle IPv4 netmasks. netdev_bsd_get_in4() did not set anything in its 'netmask' output argument if the IPv4 address was cached, leaving it indeterminate. It would also mark the cache as valid even if there was an error retrieving the netmask. This fixes both problems. Found by inspection. Signed-off-by: Ben Pfaff CC: Ed Maste --- lib/netdev-bsd.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c index 65e1d2591..79643e117 100644 --- a/lib/netdev-bsd.c +++ b/lib/netdev-bsd.c @@ -83,6 +83,7 @@ struct netdev_bsd { int ifindex; uint8_t etheraddr[ETH_ADDR_LEN]; struct in_addr in4; + struct in_addr netmask; struct in6_addr in6; int mtu; int carrier; @@ -1098,8 +1099,8 @@ cleanup: } /* - * 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 + * '*netmask' to its netmask and returns true. Otherwise, returns false. */ static int netdev_bsd_get_in4(const struct netdev *netdev_, struct in_addr *in4, @@ -1121,15 +1122,16 @@ netdev_bsd_get_in4(const struct netdev *netdev_, struct in_addr *in4, sin = (struct sockaddr_in *) &ifr.ifr_addr; netdev->in4 = sin->sin_addr; - netdev->cache_valid |= VALID_IN4; error = netdev_bsd_do_ioctl(netdev_get_kernel_name(netdev_), &ifr, SIOCGIFNETMASK, "SIOCGIFNETMASK"); if (error) { return error; } - *netmask = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr; + netdev->netmask = sin->sin_addr; + netdev->cache_valid |= VALID_IN4; } *in4 = netdev->in4; + *netmask = netdev->netmask; return in4->s_addr == INADDR_ANY ? EADDRNOTAVAIL : 0; } @@ -1148,11 +1150,14 @@ netdev_bsd_set_in4(struct netdev *netdev_, struct in_addr addr, error = do_set_addr(netdev_, SIOCSIFADDR, "SIOCSIFADDR", addr); if (!error) { - netdev->cache_valid |= VALID_IN4; - netdev->in4 = addr; if (addr.s_addr != INADDR_ANY) { error = do_set_addr(netdev_, SIOCSIFNETMASK, "SIOCSIFNETMASK", mask); + if (!error) { + netdev->cache_valid |= VALID_IN4; + netdev->in4 = addr; + netdev->netmask = mask; + } } netdev_bsd_changed(netdev); } -- 2.47.0