mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 11:30:30 +00:00
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>
This commit is contained in:
parent
0268f30e3c
commit
4db2161955
@ -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 {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user