]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: handle some ioctl operations for VRF
authorPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 22 Feb 2018 18:10:32 +0000 (19:10 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 27 Feb 2018 10:11:24 +0000 (11:11 +0100)
A new API is available for interface ioctl operations on Linux:
vrf_if_ioctl. This is the unified API that permits doing ioctl
operations on a per interface basis.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
zebra/if_ioctl.c
zebra/ioctl.c
zebra/ioctl.h
zebra/ioctl_solaris.c

index 1d108886de669532f3f7dcbb166b30ac611c9b07..09fc0850181f0e6dd8d8342f6979596acaa7d430 100644 (file)
@@ -146,7 +146,7 @@ static int if_get_hwaddr(struct interface *ifp)
        ifreq.ifr_addr.sa_family = AF_INET;
 
        /* Fetch Hardware address if available. */
-       ret = if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq);
+       ret = vrf_if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq, ifp->vrf_id);
        if (ret < 0)
                ifp->hw_addr_len = 0;
        else {
index 8e3a1d1a036307ea1d024dda8124579556a8dc42..d07d37056ec43a3d8bc173aac944a9245d93620a 100644 (file)
@@ -59,6 +59,7 @@ int if_ioctl(u_long request, caddr_t buffer)
        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock < 0) {
                int save_errno = errno;
+
                if (zserv_privs.change(ZPRIVS_LOWER))
                        zlog_err("Can't lower privileges");
                zlog_err("Cannot create UDP socket: %s",
@@ -78,6 +79,39 @@ int if_ioctl(u_long request, caddr_t buffer)
        return 0;
 }
 
+/* call ioctl system call */
+int vrf_if_ioctl(u_long request, caddr_t buffer, vrf_id_t vrf_id)
+{
+       int sock;
+       int ret;
+       int err = 0;
+
+       if (zserv_privs.change(ZPRIVS_RAISE))
+               zlog_err("Can't raise privileges");
+       sock = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
+       if (sock < 0) {
+               int save_errno = errno;
+
+               if (zserv_privs.change(ZPRIVS_LOWER))
+                       zlog_err("Can't lower privileges");
+               zlog_err("Cannot create UDP socket: %s",
+                        safe_strerror(save_errno));
+               exit(1);
+       }
+       ret = vrf_ioctl(vrf_id, sock, request, buffer);
+       if (ret < 0)
+               err = errno;
+       if (zserv_privs.change(ZPRIVS_LOWER))
+               zlog_err("Can't lower privileges");
+       close(sock);
+
+       if (ret < 0) {
+               errno = err;
+               return ret;
+       }
+       return 0;
+}
+
 #ifndef HAVE_NETLINK
 static int if_ioctl_ipv6(u_long request, caddr_t buffer)
 {
@@ -90,6 +124,7 @@ static int if_ioctl_ipv6(u_long request, caddr_t buffer)
        sock = socket(AF_INET6, SOCK_DGRAM, 0);
        if (sock < 0) {
                int save_errno = errno;
+
                if (zserv_privs.change(ZPRIVS_LOWER))
                        zlog_err("Can't lower privileges");
                zlog_err("Cannot create IPv6 datagram socket: %s",
@@ -122,7 +157,7 @@ void if_get_metric(struct interface *ifp)
 
        ifreq_set_name(&ifreq, ifp);
 
-       if (if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq) < 0)
+       if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf_id) < 0)
                return;
        ifp->metric = ifreq.ifr_metric;
        if (ifp->metric == 0)
@@ -140,7 +175,7 @@ void if_get_mtu(struct interface *ifp)
        ifreq_set_name(&ifreq, ifp);
 
 #if defined(SIOCGIFMTU)
-       if (if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq) < 0) {
+       if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf_id) < 0) {
                zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU)");
                ifp->mtu6 = ifp->mtu = -1;
                return;
@@ -376,9 +411,9 @@ void if_get_flags(struct interface *ifp)
 
        ifreq_set_name(&ifreq, ifp);
 
-       ret = if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq);
+       ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
        if (ret < 0) {
-               zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s",
+               zlog_err("vrf_if_ioctl(SIOCGIFFLAGS) failed: %s",
                         safe_strerror(errno));
                return;
        }
@@ -423,7 +458,7 @@ int if_set_flags(struct interface *ifp, uint64_t flags)
        ifreq.ifr_flags = ifp->flags;
        ifreq.ifr_flags |= flags;
 
-       ret = if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq);
+       ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
 
        if (ret < 0) {
                zlog_info("can't set interface flags");
@@ -444,7 +479,7 @@ int if_unset_flags(struct interface *ifp, uint64_t flags)
        ifreq.ifr_flags = ifp->flags;
        ifreq.ifr_flags &= ~flags;
 
-       ret = if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq);
+       ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
 
        if (ret < 0) {
                zlog_info("can't unset interface flags");
index 02f8e6b880127cbe375da1eafd7e68b9cc220c9f..1a6e14ed4dcd9dce576549607b7e2ec3eebec7a9 100644 (file)
@@ -25,6 +25,7 @@
 /* Prototypes. */
 extern void ifreq_set_name(struct ifreq *, struct interface *);
 extern int if_ioctl(u_long, caddr_t);
+extern int vrf_if_ioctl(u_long request, caddr_t buffer, vrf_id_t vrf_id);
 
 extern int if_set_flags(struct interface *, uint64_t);
 extern int if_unset_flags(struct interface *, uint64_t);
index e8b65925f881815743187831e6ceafaca8a32630..f429c42440a95165bf2db52772c2f30fbf3c95b1 100644 (file)
@@ -30,6 +30,7 @@
 #include "log.h"
 #include "privs.h"
 #include "vty.h"
+#include "vrf.h"
 
 #include "zebra/rib.h"
 #include "zebra/rt.h"
@@ -44,6 +45,11 @@ void lifreq_set_name(struct lifreq *lifreq, const char *ifname)
        strncpy(lifreq->lifr_name, ifname, IFNAMSIZ);
 }
 
+int vrf_if_ioctl(u_long request, caddr_t buffer, vrf_id_t vrf_id)
+{
+       return if_ioctl(request, buffer);
+}
+
 /* call ioctl system call */
 int if_ioctl(u_long request, caddr_t buffer)
 {