#include "vrf.h"
#include "vrf_int.h"
#include "mpls.h"
+#include "lib_errors.h"
#include "vty.h"
#include "zebra/zserv.h"
#include "zebra/zebra_mpls.h"
#include "zebra/kernel_netlink.h"
#include "zebra/if_netlink.h"
+#include "zebra/zebra_errors.h"
extern struct zebra_privs_t zserv_privs;
if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL)
&& (oifp != ifp)) {
if (ifi_index == IFINDEX_INTERNAL)
- zlog_err(
- "Netlink is setting interface %s ifindex to reserved "
- "internal value %u",
+ flog_err(
+ LIB_ERR_INTERFACE,
+ "Netlink is setting interface %s ifindex to reserved internal value %u",
ifp->name, ifi_index);
else {
if (IS_ZEBRA_DEBUG_KERNEL)
"interface index %d was renamed from %s to %s",
ifi_index, oifp->name, ifp->name);
if (if_is_up(oifp))
- zlog_err(
- "interface rename detected on up interface: index %d "
- "was renamed from %s to %s, results are uncertain!",
+ flog_err(
+ LIB_ERR_INTERFACE,
+ "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!",
ifi_index, oifp->name, ifp->name);
if_delete_update(oifp);
}
hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
if (hw_addr_len > INTERFACE_HWADDR_MAX)
- zlog_warn("Hardware address is too large: %d",
- hw_addr_len);
+ zlog_debug("Hardware address is too large: %d",
+ hw_addr_len);
else {
ifp->hw_addr_len = hw_addr_len;
memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]),
*zif_type = ZEBRA_IF_VXLAN;
else if (strcmp(kind, "macvlan") == 0)
*zif_type = ZEBRA_IF_MACVLAN;
+ else if (strcmp(kind, "veth") == 0)
+ *zif_type = ZEBRA_IF_VETH;
}
#define parse_rtattr_nested(tb, max, rta) \
vrf = vrf_get((vrf_id_t)ifi->ifi_index,
name); // It would create vrf
if (!vrf) {
- zlog_err("VRF %s id %u not created", name,
- ifi->ifi_index);
+ flog_err(LIB_ERR_INTERFACE, "VRF %s id %u not created",
+ name, ifi->ifi_index);
return;
}
/* Enable the created VRF. */
if (!vrf_enable(vrf)) {
- zlog_err("Failed to enable VRF %s id %u", name,
- ifi->ifi_index);
+ flog_err(LIB_ERR_INTERFACE,
+ "Failed to enable VRF %s id %u", name,
+ ifi->ifi_index);
return;
}
vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index);
if (!vrf) {
- zlog_warn("%s: vrf not found", __func__);
+ flog_warn(ZEBRA_ERR_VRF_NOT_FOUND, "%s: vrf not found",
+ __func__);
return;
}
ifdata.ifr_data = (caddr_t)&ecmd;
/* use ioctl to get IP address of an interface */
- 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;
- }
+ frr_elevate_privs(&zserv_privs) {
+ 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 = vrf_ioctl(interface->vrf_id, sd, SIOCETHTOOL, (char *)&ifdata);
- if (zserv_privs.change(ZPRIVS_LOWER))
- zlog_err("Can't lower privileges");
+ rc = vrf_ioctl(interface->vrf_id, sd, SIOCETHTOOL,
+ (char *)&ifdata);
+ }
if (rc < 0) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
/* The interface should already be known, if not discard. */
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index);
if (!ifp) {
- zlog_warn("Cannot find bridge IF %s(%u)", name, ifi->ifi_index);
+ zlog_debug("Cannot find bridge IF %s(%u)", name,
+ ifi->ifi_index);
return 0;
}
if (!IS_ZEBRA_IF_VXLAN(ifp))
SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
/* Update link. */
- zebra_if_update_link(ifp, link_ifindex);
+ zebra_if_update_link(ifp, link_ifindex, ns_id);
/* Hardware type and address. */
ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type);
zns = zebra_ns_lookup(ns_id);
ifa = NLMSG_DATA(h);
- if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6)
+ if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) {
+ flog_warn(
+ ZEBRA_ERR_UNKNOWN_FAMILY,
+ "Invalid address family: %u received from kernel interface addr change: %u",
+ ifa->ifa_family, h->nlmsg_type);
return 0;
+ }
if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
return 0;
ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index);
if (ifp == NULL) {
- zlog_err(
+ flog_err(
+ LIB_ERR_INTERFACE,
"netlink_interface_addr can't find interface by index %d",
ifa->ifa_index);
return -1;
/* Register interface address to the interface. */
if (ifa->ifa_family == AF_INET) {
+ if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
+ zlog_err(
+ "Invalid prefix length: %u received from kernel interface addr change: %u",
+ ifa->ifa_prefixlen, h->nlmsg_type);
+ return -1;
+ }
if (h->nlmsg_type == RTM_NEWADDR)
connected_add_ipv4(ifp, flags, (struct in_addr *)addr,
ifa->ifa_prefixlen,
ifa->ifa_prefixlen, (struct in_addr *)broad);
}
if (ifa->ifa_family == AF_INET6) {
+ if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) {
+ zlog_err(
+ "Invalid prefix length: %u received from kernel interface addr change: %u",
+ ifa->ifa_prefixlen, h->nlmsg_type);
+ return -1;
+ }
if (h->nlmsg_type == RTM_NEWADDR) {
/* Only consider valid addresses; we'll not get a
* notification from
return 0;
}
-/* helper function called by if_netlink_change
- * to delete interfaces in case the interface moved
- * to an other netns
- */
-static void if_netlink_check_ifp_instance_consistency(uint16_t cmd,
- struct interface *ifp,
- ns_id_t ns_id)
-{
- struct interface *other_ifp;
-
- /*
- * look if interface name is also found on other netns
- * - only if vrf backend is netns
- * - do not concern lo interface
- * - then remove previous one
- * - for new link case, check found interface is not active
- */
- if (!vrf_is_backend_netns() ||
- !strcmp(ifp->name, "lo"))
- return;
- other_ifp = if_lookup_by_name_not_ns(ns_id, ifp->name);
- if (!other_ifp)
- return;
- /* because previous interface may be inactive,
- * interface is moved back to default vrf
- * then one may find the same pointer; ignore
- */
- if (other_ifp == ifp)
- return;
- if ((cmd == RTM_NEWLINK)
- && (CHECK_FLAG(other_ifp->status, ZEBRA_INTERFACE_ACTIVE)))
- return;
- if (IS_ZEBRA_DEBUG_KERNEL && cmd == RTM_NEWLINK) {
- zlog_debug("RTM_NEWLINK %s(%u, VRF %u) replaces %s(%u, VRF %u)\n",
- ifp->name,
- ifp->ifindex,
- ifp->vrf_id,
- other_ifp->name,
- other_ifp->ifindex,
- other_ifp->vrf_id);
- } else if (IS_ZEBRA_DEBUG_KERNEL && cmd == RTM_DELLINK) {
- zlog_debug("RTM_DELLINK %s(%u, VRF %u) is replaced by %s(%u, VRF %u)\n",
- ifp->name,
- ifp->ifindex,
- ifp->vrf_id,
- other_ifp->name,
- other_ifp->ifindex,
- other_ifp->vrf_id);
- }
- /* the found interface replaces the current one
- * remove it
- */
- if (cmd == RTM_DELLINK)
- if_delete(ifp);
- else
- if_delete(other_ifp);
- /* the found interface is replaced by the current one
- * suppress it
- */
-}
-
int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
{
int len;
/* 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",
- h->nlmsg_type);
+ zlog_debug("netlink_link_change: wrong kernel message %d",
+ h->nlmsg_type);
+ return 0;
+ }
+
+ if (!(ifi->ifi_family == AF_UNSPEC || ifi->ifi_family == AF_BRIDGE
+ || ifi->ifi_family == AF_INET6)) {
+ flog_warn(
+ ZEBRA_ERR_UNKNOWN_FAMILY,
+ "Invalid address family: %u received from kernel link change: %u",
+ ifi->ifi_family, h->nlmsg_type);
return 0;
}
/* Update interface information. */
set_ifindex(ifp, ifi->ifi_index, zns);
ifp->flags = ifi->ifi_flags & 0x0000fffff;
+ if (!tb[IFLA_MTU]) {
+ zlog_debug(
+ "RTM_NEWLINK for interface %s(%u) without MTU set",
+ name, ifi->ifi_index);
+ return 0;
+ }
ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
ifp->metric = 0;
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
ZEBRA_INTERFACE_VRF_LOOPBACK);
/* Update link. */
- zebra_if_update_link(ifp, link_ifindex);
+ zebra_if_update_link(ifp, link_ifindex, ns_id);
netlink_interface_update_hw_addr(tb, ifp);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
- if_netlink_check_ifp_instance_consistency(RTM_NEWLINK,
- ifp, ns_id);
} else if (ifp->vrf_id != vrf_id) {
/* VRF change for an interface. */
if (IS_ZEBRA_DEBUG_KERNEL)
bridge_ifindex, ifi->ifi_flags);
set_ifindex(ifp, ifi->ifi_index, zns);
+ if (!tb[IFLA_MTU]) {
+ zlog_debug(
+ "RTM_NEWLINK for interface %s(%u) without MTU set",
+ name, ifi->ifi_index);
+ return 0;
+ }
ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
ifp->metric = 0;
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
- if_netlink_check_ifp_instance_consistency(RTM_NEWLINK,
- ifp, ns_id);
}
} else {
/* Delete interface notification from kernel */
if (ifp == NULL) {
- zlog_warn("RTM_DELLINK for unknown interface %s(%u)",
- name, ifi->ifi_index);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_DELLINK for unknown interface %s(%u)",
+ name, ifi->ifi_index);
return 0;
}
if (!IS_ZEBRA_IF_VRF(ifp))
if_delete_update(ifp);
- if_netlink_check_ifp_instance_consistency(RTM_DELLINK,
- ifp, ns_id);
}
return 0;