diff options
| author | Philippe Guibert <philippe.guibert@6wind.com> | 2018-02-22 19:10:32 +0100 |
|---|---|---|
| committer | Philippe Guibert <philippe.guibert@6wind.com> | 2018-02-27 11:11:24 +0100 |
| commit | 4db21619552b3f6823bf1ae8103eac82aab628f7 (patch) | |
| tree | 64e09003b0618157a0211ef7422978d2894ae14d /zebra/ioctl.c | |
| parent | 0268f30e3cab287bb10e84f7663098ed9cbd50c7 (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.c | 47 |
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"); |
