[ovs-dev] [PATCH 15/18] implement set_etheraddr for NetBSD

YAMAMOTO Takashi yamamoto at valinux.co.jp
Thu Jan 31 10:49:49 UTC 2013


From: YAMAMOTO Takashi <yamt at mwd.biglobe.ne.jp>

Signed-off-by: YAMAMOTO Takashi <yamamoto at valinux.co.jp>
---
 lib/netdev-bsd.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 69 insertions(+), 7 deletions(-)

diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index 76782ec..615a26f 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -1494,13 +1494,7 @@ static int
 set_etheraddr(const char *netdev_name, int hwaddr_family,
               int hwaddr_len, const uint8_t mac[ETH_ADDR_LEN])
 {
-#if defined(__NetBSD__)
-    (void)netdev_name;
-    (void)hwaddr_family;
-    (void)hwaddr_len;
-    (void)mac;
-    return ENOTSUP; /* XXX */
-#else
+#if defined(__FreeBSD__)
     struct ifreq ifr;
 
     memset(&ifr, 0, sizeof ifr);
@@ -1514,6 +1508,74 @@ set_etheraddr(const char *netdev_name, int hwaddr_family,
         return errno;
     }
     return 0;
+#elif defined(__NetBSD__)
+    struct if_laddrreq req;
+    struct sockaddr_dl *sdl;
+    struct sockaddr_storage oldaddr;
+    int ret;
+    int s;
+
+    /*
+     * get the old address, add new one, and then remove old one.
+     */
+
+    if (hwaddr_len != ETH_ADDR_LEN) {
+        /* just to be safe about sockaddr storage size */
+        return ENOTSUP;
+    }
+    s = socket(AF_LINK, SOCK_DGRAM, 0);
+    if (s == -1) {
+        return errno;
+    }
+    memset(&req, 0, sizeof(req));
+    strncpy(req.iflr_name, netdev_name, sizeof(req.iflr_name));
+    req.addr.ss_len = sizeof(req.addr);
+    req.addr.ss_family = hwaddr_family;
+    sdl = (struct sockaddr_dl *)&req.addr;
+    sdl->sdl_alen = hwaddr_len;
+    ret = ioctl(s, SIOCGLIFADDR, &req);
+    if (ret == -1) {
+        int saved_errno = errno;
+
+        close(s);
+        return saved_errno;
+    }
+    if (!memcmp(&sdl->sdl_data[sdl->sdl_nlen], mac, hwaddr_len)) {
+        close(s);
+        return 0;
+    }
+    oldaddr = req.addr;
+
+    memset(&req, 0, sizeof(req));
+    strncpy(req.iflr_name, netdev_name, sizeof(req.iflr_name));
+    req.flags = IFLR_ACTIVE;
+    sdl = (struct sockaddr_dl *)&req.addr;
+    sdl->sdl_len = offsetof(struct sockaddr_dl, sdl_data) + hwaddr_len;
+    sdl->sdl_alen = hwaddr_len;
+    sdl->sdl_family = hwaddr_family;
+    memcpy(sdl->sdl_data, mac, hwaddr_len);
+    ret = ioctl(s, SIOCALIFADDR, &req);
+    if (ret == -1) {
+        int saved_errno = errno;
+
+        close(s);
+        return saved_errno;
+    }
+
+    memset(&req, 0, sizeof(req));
+    strncpy(req.iflr_name, netdev_name, sizeof(req.iflr_name));
+    req.addr = oldaddr;
+    ret = ioctl(s, SIOCDLIFADDR, &req);
+    if (ret == -1) {
+        int saved_errno = errno;
+
+        close(s);
+        return saved_errno;
+    }
+    close(s);
+    return 0;
+#else
+#error not implemented
 #endif
 }
 
-- 
1.7.12




More information about the dev mailing list