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.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 14905b738b..a37d74416b 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -30,6 +30,7 @@
*/
#define _LINUX_IN6_H
+#include <netinet/if_ether.h>
#include <linux/if_bridge.h>
#include <linux/if_link.h>
#include <net/if_arp.h>
@@ -66,6 +67,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 +346,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));
@@ -360,19 +363,23 @@ static int get_iflink_speed(const char *ifname)
/* initialize ethtool interface */
memset(&ecmd, 0, sizeof(ecmd));
ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */
- ifdata.ifr_data = (__caddr_t)&ecmd;
+ 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 +396,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 +622,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 +639,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])
@@ -640,11 +650,9 @@ static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h,
ifp = if_get_by_name(name, vrf_id, 0);
set_ifindex(ifp, ifi->ifi_index, zns);
ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (IS_ZEBRA_IF_VRF(ifp))
- 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)
@@ -652,6 +660,8 @@ static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h,
/* Set zebra interface type */
zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
+ if (IS_ZEBRA_IF_VRF(ifp))
+ SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
/* Update link. */
zebra_if_update_link(ifp, link_ifindex);
@@ -789,8 +799,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);
@@ -843,14 +857,14 @@ int kernel_address_delete_ipv4(struct interface *ifp, struct connected *ifc)
return netlink_address(RTM_DELADDR, AF_INET, ifp, ifc);
}
-int kernel_address_add_ipv6 (struct interface *ifp, struct connected *ifc)
+int kernel_address_add_ipv6(struct interface *ifp, struct connected *ifc)
{
- return netlink_address (RTM_NEWADDR, AF_INET6, ifp, ifc);
+ return netlink_address(RTM_NEWADDR, AF_INET6, ifp, ifc);
}
-int kernel_address_delete_ipv6 (struct interface *ifp, struct connected *ifc)
+int kernel_address_delete_ipv6(struct interface *ifp, struct connected *ifc)
{
- return netlink_address (RTM_DELADDR, AF_INET6, ifp, ifc);
+ return netlink_address(RTM_DELADDR, AF_INET6, ifp, ifc);
}
int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h,
@@ -1017,6 +1031,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 +1089,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 +1106,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 +1119,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 */
@@ -1127,15 +1144,15 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
/* Update interface information. */
set_ifindex(ifp, ifi->ifi_index, zns);
ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (IS_ZEBRA_IF_VRF(ifp))
- SET_FLAG(ifp->status,
- ZEBRA_INTERFACE_VRF_LOOPBACK);
ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
ifp->metric = 0;
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
/* Set interface type */
zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
+ if (IS_ZEBRA_IF_VRF(ifp))
+ SET_FLAG(ifp->status,
+ ZEBRA_INTERFACE_VRF_LOOPBACK);
/* Update link. */
zebra_if_update_link(ifp, link_ifindex);