#include "zebra/kernel_socket.h"
#include "zebra/rib.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_ptm.h"
extern struct zebra_privs_t zserv_privs;
* 0). We follow this practice without questioning it, but it is a
* bug if quagga calls ROUNDUP with 0.
*/
+#ifdef __APPLE__
+#define ROUNDUP_TYPE int
+#else
+#define ROUNDUP_TYPE long
+#endif
/*
* Because of these varying conventions, the only sane approach is for
* the <net/route.h> header to define some flavor of ROUNDUP macro.
*/
-#if defined(SA_SIZE)
-/* SAROUNDUP is the only thing we need, and SA_SIZE provides that */
-#define SAROUNDUP(a) SA_SIZE(a)
-#else /* !SA_SIZE */
-
+/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
#if defined(RT_ROUNDUP)
#define ROUNDUP(a) RT_ROUNDUP(a)
#endif /* defined(RT_ROUNDUP) */
* have it in its headers, this will break rather obviously and you'll
* have to fix it here.
*/
-
-/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
-#ifdef __APPLE__
-#define ROUNDUP_TYPE int
-#else
-#define ROUNDUP_TYPE long
-#endif
-
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a)-1) | (sizeof(ROUNDUP_TYPE) - 1))) \
: sizeof(ROUNDUP_TYPE))
#endif /* defined(ROUNDUP) */
+
+#if defined(SA_SIZE)
+/* SAROUNDUP is the only thing we need, and SA_SIZE provides that */
+#define SAROUNDUP(a) SA_SIZE(a)
+#else /* !SA_SIZE */
/*
* Given a pointer (sockaddr or void *), return the number of bytes
* taken up by the sockaddr and any padding needed for alignment.
#endif /* !SA_SIZE */
-/*
- * We use a call to an inline function to copy (PNT) to (DEST)
- * 1. Calculating the length of the copy requires an #ifdef to determine
- * if sa_len is a field and can't be used directly inside a #define
- * 2. So the compiler doesn't complain when DEST is NULL, which is only true
- * when we are skipping the copy and incrementing to the next SA
- */
-static inline void rta_copy(union sockunion *dest, caddr_t src)
-{
- int len;
- if (!dest)
- return;
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- len = (((struct sockaddr *)src)->sa_len > sizeof(*dest))
- ? sizeof(*dest)
- : ((struct sockaddr *)src)->sa_len;
-#else
- len = (SAROUNDUP(src) > sizeof(*dest)) ? sizeof(*dest) : SAROUNDUP(src);
-#endif
- memcpy(dest, src, len);
-}
-
-#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \
- if ((RTMADDRS) & (RTA)) { \
- int len = SAROUNDUP((PNT)); \
- if (af_check(((struct sockaddr *)(PNT))->sa_family)) \
- rta_copy((DEST), (PNT)); \
- (PNT) += len; \
- }
-#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \
- if ((RTMADDRS) & (RTA)) { \
- int len = SAROUNDUP((PNT)); \
- rta_copy((DEST), (PNT)); \
- (PNT) += len; \
- }
-
-#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \
- if ((RTMADDRS) & (RTA)) { \
- uint8_t *pdest = (uint8_t *)(DEST); \
- int len = SAROUNDUP((PNT)); \
- struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \
- if (IS_ZEBRA_DEBUG_KERNEL) \
- zlog_debug("%s: RTA_SDL_GET nlen %d, alen %d", \
- __func__, sdl->sdl_nlen, sdl->sdl_alen); \
- if (((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \
- && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len)) { \
- memcpy(pdest, sdl->sdl_data, sdl->sdl_nlen); \
- pdest[sdl->sdl_nlen] = '\0'; \
- (LEN) = sdl->sdl_nlen; \
- } \
- (PNT) += len; \
- } else { \
- (LEN) = 0; \
- }
/* Routing socket message types. */
const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"},
{RTM_DELETE, "RTM_DELETE"},
/* Kernel routing update socket. */
int routing_sock = -1;
+/* Kernel dataplane routing update socket, used in the dataplane pthread
+ * context.
+ */
+int dplane_routing_sock = -1;
+
/* Yes I'm checking ugly routing socket behavior. */
/* #define DEBUG */
+size_t rta_get(caddr_t sap, void *dest, size_t destlen);
+size_t rta_getsdlname(caddr_t sap, void *dest, short *destlen);
+
/* Supported address family check. */
static inline int af_check(int family)
{
return 0;
}
+size_t rta_get(caddr_t sap, void *destp, size_t destlen)
+{
+ struct sockaddr *sa = (struct sockaddr *)sap;
+ uint8_t *dest = destp;
+ size_t tlen, copylen;
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ copylen = sa->sa_len;
+ tlen = (copylen == 0) ? sizeof(ROUNDUP_TYPE) : ROUNDUP(copylen);
+#else /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
+ copylen = tlen = SAROUNDUP(sap);
+#endif /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+ if (copylen > 0 && dest != NULL && af_check(sa->sa_family)) {
+ if (copylen > destlen) {
+ zlog_warn("%s: destination buffer too small (%lu vs %lu)",
+ __func__, copylen, destlen);
+ memcpy(dest, sap, destlen);
+ } else
+ memcpy(dest, sap, copylen);
+ }
+
+ return tlen;
+}
+
+size_t rta_getsdlname(caddr_t sap, void *destp, short *destlen)
+{
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)sap;
+ struct sockaddr *sa = (struct sockaddr *)sap;
+ uint8_t *dest = destp;
+ size_t tlen, copylen;
+
+ copylen = sdl->sdl_nlen;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ tlen = (sa->sa_len == 0) ? sizeof(ROUNDUP_TYPE) : ROUNDUP(sa->sa_len);
+#else /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
+ tlen = SAROUNDUP(sap);
+#endif /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+ if (copylen > 0 && dest != NULL && sdl->sdl_family == AF_LINK) {
+ if (copylen > IFNAMSIZ) {
+ zlog_warn("%s: destination buffer too small (%lu vs %d)",
+ __func__, copylen, IFNAMSIZ);
+ memcpy(dest, sdl->sdl_data, IFNAMSIZ);
+ dest[IFNAMSIZ] = 0;
+ *destlen = IFNAMSIZ;
+ } else {
+ memcpy(dest, sdl->sdl_data, copylen);
+ dest[copylen] = 0;
+ *destlen = copylen;
+ }
+ } else
+ *destlen = 0;
+
+ return tlen;
+}
+
/* Dump routing table flag for debug purpose. */
static void rtm_flag_dump(int flag)
{
__func__, ifan->ifan_index, ifan->ifan_name);
/* Create Interface */
- ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT, 0);
+ ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT);
if_set_index(ifp, ifan->ifan_index);
if_get_metric(ifp);
struct sockaddr_dl *sdl;
char ifname[IFNAMSIZ];
short ifnlen = 0;
+ int maskbit;
caddr_t cp;
/* terminate ifname at head (for strnlen) and tail (for safety) */
cp = cp + 12;
#endif
- RTA_ADDR_GET(NULL, RTA_DST, ifm->ifm_addrs, cp);
- RTA_ADDR_GET(NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
- RTA_ATTR_GET(NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
- RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
- sdl = (struct sockaddr_dl *)cp;
- RTA_NAME_GET(ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
- RTA_ADDR_GET(NULL, RTA_IFA, ifm->ifm_addrs, cp);
- RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
- RTA_ADDR_GET(NULL, RTA_BRD, ifm->ifm_addrs, cp);
-#ifdef RTA_LABEL
- RTA_ATTR_GET(NULL, RTA_LABEL, ifm->ifm_addrs, cp);
-#endif
-#ifdef RTA_SRC
- RTA_ADDR_GET(NULL, RTA_SRC, ifm->ifm_addrs, cp);
-#endif
+ /* Look up for RTA_IFP and skip others. */
+ for (maskbit = 1; maskbit; maskbit <<= 1) {
+ if ((maskbit & ifm->ifm_addrs) == 0)
+ continue;
+ if (maskbit != RTA_IFP) {
+ cp += rta_get(cp, NULL, 0);
+ continue;
+ }
+
+ /* Save the pointer to the structure. */
+ sdl = (struct sockaddr_dl *)cp;
+ cp += rta_getsdlname(cp, ifname, &ifnlen);
+ }
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: sdl ifname %s", __func__,
* - Solaris has no sdl_len, but sdl_data[244]
* presumably, it's not going to run past that, so sizeof()
* is fine here.
- * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
+ * a nonzero ifnlen from rta_getsdlname() means sdl is valid
*/
ifp->ll_type = ZEBRA_LLT_UNKNOWN;
ifp->hw_addr_len = 0;
caddr_t pnt, end;
union sockunion dst;
union sockunion gateway;
+ int maskbit;
pnt = (caddr_t)(ifm + 1);
end = ((caddr_t)ifm) + ifm->ifam_msglen;
memset(&gateway, 0, sizeof(union sockunion));
/* We fetch each socket variable into sockunion. */
- RTA_ADDR_GET(&dst, RTA_DST, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET(&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
- RTA_ATTR_GET(mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
- RTA_NAME_GET(ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
- RTA_ADDR_GET(addr, RTA_IFA, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET(brd, RTA_BRD, ifm->ifam_addrs, pnt);
-#ifdef RTA_LABEL
- RTA_ATTR_GET(NULL, RTA_LABEL, ifm->ifam_addrs, pnt);
-#endif
-#ifdef RTA_SRC
- RTA_ADDR_GET(NULL, RTA_SRC, ifm->ifam_addrs, pnt);
-#endif
+ for (maskbit = 1; maskbit; maskbit <<= 1) {
+ if ((maskbit & ifm->ifam_addrs) == 0)
+ continue;
+
+ switch (maskbit) {
+ case RTA_DST:
+ pnt += rta_get(pnt, &dst, sizeof(dst));
+ break;
+ case RTA_GATEWAY:
+ pnt += rta_get(pnt, &gateway, sizeof(gateway));
+ break;
+ case RTA_NETMASK:
+ pnt += rta_get(pnt, mask, sizeof(*mask));
+ break;
+ case RTA_IFP:
+ pnt += rta_getsdlname(pnt, ifname, ifnlen);
+ break;
+ case RTA_IFA:
+ pnt += rta_get(pnt, addr, sizeof(*addr));
+ break;
+ case RTA_BRD:
+ pnt += rta_get(pnt, brd, sizeof(*brd));
+ break;
+
+ default:
+ pnt += rta_get(pnt, NULL, 0);
+ break;
+ }
+
+ if (pnt > end) {
+ zlog_warn("%s: overflow detected (pnt:%p end:%p)",
+ __func__, pnt, end);
+ break;
+ }
+ }
if (IS_ZEBRA_DEBUG_KERNEL) {
int family = sockunion_family(addr);
}
/* Assert read up end point matches to end point */
+ pnt = (caddr_t)ROUNDUP((size_t)pnt);
if (pnt != end)
zlog_debug("ifam_read() doesn't read all socket data");
}
char *ifname, short *ifnlen)
{
caddr_t pnt, end;
+ int maskbit;
/* Pnt points out socket data start point. */
pnt = (caddr_t)(rtm + 1);
memset(mask, 0, sizeof(union sockunion));
/* We fetch each socket variable into sockunion. */
- RTA_ADDR_GET(dest, RTA_DST, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET(gate, RTA_GATEWAY, rtm->rtm_addrs, pnt);
- RTA_ATTR_GET(mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET(NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
- RTA_NAME_GET(ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
- RTA_ADDR_GET(NULL, RTA_IFA, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET(NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET(NULL, RTA_BRD, rtm->rtm_addrs, pnt);
-#ifdef RTA_LABEL
-#if 0
- union sockunion label;
- memset(&label, 0, sizeof(label));
- RTA_ATTR_GET(&label, RTA_LABEL, rtm->rtm_addrs, pnt);
-#endif
- RTA_ATTR_GET(NULL, RTA_LABEL, rtm->rtm_addrs, pnt);
-#endif
-#ifdef RTA_SRC
- RTA_ADDR_GET(NULL, RTA_SRC, rtm->rtm_addrs, pnt);
-#endif
+ /* We fetch each socket variable into sockunion. */
+ for (maskbit = 1; maskbit; maskbit <<= 1) {
+ if ((maskbit & rtm->rtm_addrs) == 0)
+ continue;
+
+ switch (maskbit) {
+ case RTA_DST:
+ pnt += rta_get(pnt, dest, sizeof(*dest));
+ break;
+ case RTA_GATEWAY:
+ pnt += rta_get(pnt, gate, sizeof(*gate));
+ break;
+ case RTA_NETMASK:
+ pnt += rta_get(pnt, mask, sizeof(*mask));
+ break;
+ case RTA_IFP:
+ pnt += rta_getsdlname(pnt, ifname, ifnlen);
+ break;
+
+ default:
+ pnt += rta_get(pnt, NULL, 0);
+ break;
+ }
+
+ if (pnt > end) {
+ zlog_warn("%s: overflow detected (pnt:%p end:%p)",
+ __func__, pnt, end);
+ break;
+ }
+ }
/* If there is netmask information set it's family same as
destination family*/
char ifname[INTERFACE_NAMSIZ + 1];
short ifnlen = 0;
struct nexthop nh;
+ struct prefix p;
+ ifindex_t ifindex = 0;
+ afi_t afi;
zebra_flags = 0;
if (flags & RTF_PROTO1)
SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
- /* This is persistent route. */
- if (flags & RTF_STATIC)
- SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
-
memset(&nh, 0, sizeof(nh));
nh.vrf_id = VRF_DEFAULT;
nh.bh_type = BLACKHOLE_NULL;
}
- if (dest.sa.sa_family == AF_INET) {
- struct prefix p;
+ /*
+ * Ignore our own messages.
+ */
+ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
+ return;
+ if (dest.sa.sa_family == AF_INET) {
+ afi = AFI_IP;
p.family = AF_INET;
p.u.prefix4 = dest.sin.sin_addr;
if (flags & RTF_HOST)
else
p.prefixlen = ip_masklen(mask.sin.sin_addr);
- /* Catch self originated messages and match them against our
- * current RIB.
- * At the same time, ignore unconfirmed messages, they should be
- * tracked
- * by rtm_write() and kernel_rtm_ipv4().
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) {
- char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
- int ret;
- if (!IS_ZEBRA_DEBUG_RIB)
- return;
- ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p,
- &gate, VRF_DEFAULT);
- prefix2str(&p, buf, sizeof(buf));
- switch (rtm->rtm_type) {
- case RTM_ADD:
- case RTM_GET:
- case RTM_CHANGE:
- /* The kernel notifies us about a new route in
- FIB created by us.
- Do we have a correspondent entry in our RIB?
- */
- switch (ret) {
- case ZEBRA_RIB_NOTFOUND:
- zlog_debug(
- "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- inet_ntop(AF_INET, &gate.sin.sin_addr,
- gate_buf, INET_ADDRSTRLEN);
- zlog_debug(
- "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf, gate_buf);
- break;
- case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR
- */
- zlog_debug(
- "%s: %s %s: done Ok", __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- return;
- break;
- }
- break;
- case RTM_DELETE:
- /* The kernel notifies us about a route deleted
- by us. Do we still
- have it in the RIB? Do we have anything
- instead? */
- switch (ret) {
- case ZEBRA_RIB_FOUND_EXACT:
- zlog_debug(
- "%s: %s %s: desync: RR is still in RIB, while already not in FIB",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- zlog_debug(
- "%s: %s %s: desync: RR is still in RIB, plus gate differs",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- break;
- case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
- zlog_debug(
- "%s: %s %s: done Ok", __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- return;
- break;
- }
- break;
- default:
- zlog_debug(
- "%s: %s: warning: loopback RTM of type %s received",
- __func__, buf,
- lookup_msg(rtm_type_str, rtm->rtm_type,
- NULL));
- }
- return;
- }
-
- /* Change, delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, 0, true);
-
if (!nh.type) {
nh.type = NEXTHOP_TYPE_IPV4;
nh.gate.ipv4 = gate.sin.sin_addr;
}
-
- if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, 0, 0);
- else
- rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, true);
- }
- if (dest.sa.sa_family == AF_INET6) {
- /* One day we might have a debug section here like one in the
- * IPv4 case above. Just ignore own messages at the moment.
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
- return;
- struct prefix p;
- ifindex_t ifindex = 0;
-
+ } else if (dest.sa.sa_family == AF_INET6) {
+ afi = AFI_IP6;
p.family = AF_INET6;
p.u.prefix6 = dest.sin6.sin6_addr;
if (flags & RTF_HOST)
}
#endif /* KAME */
- /* CHANGE: delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, 0, true);
-
if (!nh.type) {
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
: NEXTHOP_TYPE_IPV6;
nh.gate.ipv6 = gate.sin6.sin6_addr;
nh.ifindex = ifindex;
}
+ } else
+ return;
- if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, 0, 0);
- else
- rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, true);
- }
+ /*
+ * CHANGE: delete the old prefix, we have no further information
+ * to specify the route really
+ */
+ if (rtm->rtm_type == RTM_CHANGE)
+ rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+ 0, zebra_flags, &p, NULL, NULL, 0, 0, 0, true);
+ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
+ || rtm->rtm_type == RTM_CHANGE)
+ rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
+ zebra_flags, &p, NULL, &nh, 0, 0, 0, 0, 0);
+ else
+ rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+ 0, zebra_flags, &p, NULL, &nh, 0, 0, 0, true);
}
/* Interface function for the kernel routing table updates. Support
char buf[512];
} msg;
- if (routing_sock < 0)
+ if (dplane_routing_sock < 0)
return ZEBRA_ERR_EPERM;
/* Clear and set rt_msghdr values */
msg.rtm.rtm_msglen = pnt - (caddr_t)&msg;
- ret = write(routing_sock, &msg, msg.rtm.rtm_msglen);
+ ret = write(dplane_routing_sock, &msg, msg.rtm.rtm_msglen);
if (ret != msg.rtm.rtm_msglen) {
if (errno == EEXIST)
{
frr_elevate_privs(&zserv_privs) {
routing_sock = ns_socket(AF_ROUTE, SOCK_RAW, 0, zns->ns_id);
+
+ dplane_routing_sock =
+ ns_socket(AF_ROUTE, SOCK_RAW, 0, zns->ns_id);
}
if (routing_sock < 0) {
return;
}
+ if (dplane_routing_sock < 0) {
+ flog_err_sys(EC_LIB_SOCKET,
+ "Can't init kernel dataplane routing socket");
+ return;
+ }
+
/* XXX: Socket should be NONBLOCK, however as we currently
* discard failed writes, this will lead to inconsistencies.
* For now, socket must be blocking.
routing_socket(zns);
}
-void kernel_terminate(struct zebra_ns *zns)
+void kernel_terminate(struct zebra_ns *zns, bool complete)
{
return;
}