summaryrefslogtreecommitdiff
path: root/zebra/ioctl.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-02-22 19:10:32 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-02-27 11:11:24 +0100
commit4db21619552b3f6823bf1ae8103eac82aab628f7 (patch)
tree64e09003b0618157a0211ef7422978d2894ae14d /zebra/ioctl.c
parent0268f30e3cab287bb10e84f7663098ed9cbd50c7 (diff)
zebra: handle some ioctl operations for VRF
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>
Diffstat (limited to 'zebra/ioctl.c')
-rw-r--r--zebra/ioctl.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 8e3a1d1a03..d07d37056e 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -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");