summaryrefslogtreecommitdiff
path: root/zebra/if_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/if_netlink.c')
-rw-r--r--zebra/if_netlink.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 14905b738b..639f70a6b4 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -66,6 +66,7 @@
#include "zebra/kernel_netlink.h"
#include "zebra/if_netlink.h"
+extern struct zebra_privs_t zserv_privs;
/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
names and ifindex values. */
@@ -344,12 +345,13 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb,
}
}
-static int get_iflink_speed(const char *ifname)
+static int get_iflink_speed(struct interface *interface)
{
struct ifreq ifdata;
struct ethtool_cmd ecmd;
int sd;
int rc;
+ const char *ifname = interface->name;
/* initialize struct */
memset(&ifdata, 0, sizeof(ifdata));
@@ -363,16 +365,20 @@ static int get_iflink_speed(const char *ifname)
ifdata.ifr_data = (__caddr_t)&ecmd;
/* use ioctl to get IP address of an interface */
- sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog_err("Can't raise privileges");
+ sd = vrf_socket(PF_INET, SOCK_DGRAM, IPPROTO_IP,
+ interface->vrf_id, NULL);
if (sd < 0) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Failure to read interface %s speed: %d %s",
ifname, errno, safe_strerror(errno));
return 0;
}
-
/* Get the current link state for the interface */
- rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata);
+ rc = vrf_ioctl(interface->vrf_id, sd, SIOCETHTOOL, (char *)&ifdata);
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog_err("Can't lower privileges");
if (rc < 0) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
@@ -389,7 +395,7 @@ static int get_iflink_speed(const char *ifname)
uint32_t kernel_get_speed(struct interface *ifp)
{
- return get_iflink_speed(ifp->name);
+ return get_iflink_speed(ifp);
}
static int netlink_extract_bridge_info(struct rtattr *link_data,
@@ -615,13 +621,14 @@ static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h,
}
/* If VRF, create the VRF structure itself. */
- if (zif_type == ZEBRA_IF_VRF) {
+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
netlink_vrf_change(h, tb[IFLA_LINKINFO], name);
vrf_id = (vrf_id_t)ifi->ifi_index;
}
if (tb[IFLA_MASTER]) {
- if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) {
+ if (slave_kind && (strcmp(slave_kind, "vrf") == 0)
+ && !vrf_is_backend_netns()) {
zif_slave_type = ZEBRA_IF_SLAVE_VRF;
vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]);
} else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) {
@@ -631,6 +638,8 @@ static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h,
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
+ if (vrf_is_backend_netns())
+ vrf_id = (vrf_id_t)ns_id;
/* If linking to another interface, note it. */
if (tb[IFLA_LINK])
@@ -644,7 +653,7 @@ static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h,
SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
ifp->metric = 0;
- ifp->speed = get_iflink_speed(name);
+ ifp->speed = get_iflink_speed(ifp);
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
if (desc)
@@ -789,8 +798,12 @@ static int netlink_address(int cmd, int family, struct interface *ifp,
char buf[NL_PKT_BUF_SIZE];
} req;
- struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_ns *zns;
+ if (vrf_is_backend_netns())
+ zns = zebra_ns_lookup((ns_id_t)ifp->vrf_id);
+ else
+ zns = zebra_ns_lookup(NS_DEFAULT);
p = ifc->address;
memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
@@ -1017,6 +1030,7 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
+ /* assume if not default zns, then new VRF */
if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) {
/* If this is not link add/delete message so print warning. */
zlog_warn("netlink_link_change: wrong kernel message %d",
@@ -1074,7 +1088,7 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
}
/* If VRF, create or update the VRF structure itself. */
- if (zif_type == ZEBRA_IF_VRF) {
+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
netlink_vrf_change(h, tb[IFLA_LINKINFO], name);
vrf_id = (vrf_id_t)ifi->ifi_index;
}
@@ -1091,7 +1105,8 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
if (h->nlmsg_type == RTM_NEWLINK) {
if (tb[IFLA_MASTER]) {
- if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) {
+ if (slave_kind && (strcmp(slave_kind, "vrf") == 0)
+ && !vrf_is_backend_netns()) {
zif_slave_type = ZEBRA_IF_SLAVE_VRF;
vrf_id =
*(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]);
@@ -1103,7 +1118,8 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
-
+ if (vrf_is_backend_netns())
+ vrf_id = (vrf_id_t)ns_id;
if (ifp == NULL
|| !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
/* Add interface notification from kernel */