2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Kernel communication using routing socket.
|
|
|
|
* Copyright (C) 1999 Kunihiro Ishiguro
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
2017-07-26 19:49:15 +02:00
|
|
|
|
2024-01-04 22:09:47 +01:00
|
|
|
#include <net/route.h>
|
|
|
|
|
2017-07-26 19:49:15 +02:00
|
|
|
#ifndef HAVE_NETLINK
|
|
|
|
|
2016-01-15 16:36:33 +01:00
|
|
|
#include <net/if_types.h>
|
2016-09-22 04:59:57 +02:00
|
|
|
#ifdef __OpenBSD__
|
2016-06-02 13:28:15 +02:00
|
|
|
#include <netmpls/mpls.h>
|
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "if.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "sockunion.h"
|
|
|
|
#include "connected.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "ioctl.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "table.h"
|
|
|
|
#include "rib.h"
|
2003-06-04 15:59:38 +02:00
|
|
|
#include "privs.h"
|
2015-05-22 11:40:02 +02:00
|
|
|
#include "vrf.h"
|
2018-06-14 16:38:40 +02:00
|
|
|
#include "lib_errors.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-02-02 02:18:46 +01:00
|
|
|
#include "zebra/rt.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "zebra/interface.h"
|
2019-01-11 19:31:46 +01:00
|
|
|
#include "zebra/zebra_router.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "zebra/debug.h"
|
2005-11-24 16:15:17 +01:00
|
|
|
#include "zebra/kernel_socket.h"
|
2014-07-03 12:23:09 +02:00
|
|
|
#include "zebra/rib.h"
|
2018-06-28 19:22:00 +02:00
|
|
|
#include "zebra/zebra_errors.h"
|
2018-08-17 21:25:24 +02:00
|
|
|
#include "zebra/zebra_ptm.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2003-06-04 15:59:38 +02:00
|
|
|
extern struct zebra_privs_t zserv_privs;
|
|
|
|
|
2004-01-06 02:13:05 +01:00
|
|
|
/*
|
2014-12-02 20:51:49 +01:00
|
|
|
* Historically, the BSD routing socket has aligned data following a
|
|
|
|
* struct sockaddr to sizeof(long), which was 4 bytes on some
|
|
|
|
* platforms, and 8 bytes on others. NetBSD 6 changed the routing
|
|
|
|
* socket to align to sizeof(uint64_t), which is 8 bytes. OS X
|
|
|
|
* appears to align to sizeof(int), which is 4 bytes.
|
2004-01-06 02:13:05 +01:00
|
|
|
*
|
2014-12-02 20:51:49 +01:00
|
|
|
* Alignment of zero-sized sockaddrs is nonsensical, but historically
|
|
|
|
* BSD defines RT_ROUNDUP(0) to be the alignment interval (rather than
|
|
|
|
* 0). We follow this practice without questioning it, but it is a
|
2021-11-11 20:40:17 +01:00
|
|
|
* bug if frr calls ROUNDUP with 0.
|
2004-01-06 02:13:05 +01:00
|
|
|
*/
|
2023-11-04 09:30:31 +01:00
|
|
|
#define ROUNDUP_TYPE long
|
2014-12-02 20:51:49 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Because of these varying conventions, the only sane approach is for
|
|
|
|
* the <net/route.h> header to define some flavor of ROUNDUP macro.
|
|
|
|
*/
|
2015-03-03 21:04:20 +01:00
|
|
|
|
2018-12-05 14:50:25 +01:00
|
|
|
/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
|
2014-12-02 20:51:49 +01:00
|
|
|
#if defined(RT_ROUNDUP)
|
|
|
|
#define ROUNDUP(a) RT_ROUNDUP(a)
|
|
|
|
#endif /* defined(RT_ROUNDUP) */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If ROUNDUP has not yet been defined in terms of platform-provided
|
|
|
|
* defines, attempt to cope with heuristics.
|
|
|
|
*/
|
|
|
|
#if !defined(ROUNDUP)
|
|
|
|
|
|
|
|
/*
|
2017-08-26 01:41:07 +02:00
|
|
|
* If you're porting to a platform that changed RT_ROUNDUP but doesn't
|
|
|
|
* have it in its headers, this will break rather obviously and you'll
|
|
|
|
* have to fix it here.
|
2014-12-02 20:51:49 +01:00
|
|
|
*/
|
|
|
|
#define ROUNDUP(a) \
|
|
|
|
((a) > 0 ? (1 + (((a)-1) | (sizeof(ROUNDUP_TYPE) - 1))) \
|
|
|
|
: sizeof(ROUNDUP_TYPE))
|
|
|
|
|
|
|
|
#endif /* defined(ROUNDUP) */
|
|
|
|
|
2018-12-05 14:50:25 +01:00
|
|
|
|
|
|
|
#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 */
|
2004-01-06 02:13:05 +01:00
|
|
|
/*
|
|
|
|
* Given a pointer (sockaddr or void *), return the number of bytes
|
|
|
|
* taken up by the sockaddr and any padding needed for alignment.
|
|
|
|
*/
|
[autoconf] bugs 162,303,178: Fix 'present but can not be compiled' warnings
2007-05-09 Paul Jakma <paul.jakma@sun.com>
* configure.ac: sys/conf.h depends on sys/param.h, at least on
FBSD 6.2.
(bug #363) Should check for in_pktinfo for IRDP
2006-05-27 Paul Jakma <paul.jakma@sun.com>
* configure.ac: General cleanup of header and type checks, introducing
an internal define, QUAGGA_INCLUDES, to build up a list of
stuff to include so as to avoid 'present but cant be compiled'
warnings.
Misc additional checks of things missing according to autoscan.
Add LIBM, for bgpd's use of libm, so as to avoid burdening
LIBS, and all the binaries, with libm linkage.
Remove the bad practice of using m4 changequote(), just
quote the []'s in the case statements properly.
This should fix bugs 162, 303 and 178.
* */*.{c,h}: Update all HAVE_* to the standard autoconf namespaced
HAVE_* defines. I.e. HAVE_SA_LEN -> HAVE_STRUCT_SOCKADDR_SA_LEN,
* bgpd/Makefile.am: Add LIBM to bgpd's LDADD, for pow().
2007-05-10 04:38:51 +02:00
|
|
|
#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
|
2004-01-06 02:13:05 +01:00
|
|
|
#define SAROUNDUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len)
|
2017-01-13 13:57:57 +01:00
|
|
|
#else
|
2004-01-06 02:13:05 +01:00
|
|
|
/*
|
|
|
|
* One would hope all fixed-size structure definitions are aligned,
|
|
|
|
* but round them up nonetheless.
|
|
|
|
*/
|
|
|
|
#define SAROUNDUP(X) \
|
2003-09-24 02:05:45 +02:00
|
|
|
(((struct sockaddr *)(X))->sa_family == AF_INET \
|
|
|
|
? ROUNDUP(sizeof(struct sockaddr_in)) \
|
|
|
|
: (((struct sockaddr *)(X))->sa_family == AF_INET6 \
|
|
|
|
? ROUNDUP(sizeof(struct sockaddr_in6)) \
|
|
|
|
: (((struct sockaddr *)(X))->sa_family == AF_LINK \
|
2004-05-11 13:31:07 +02:00
|
|
|
? ROUNDUP(sizeof(struct sockaddr_dl)) \
|
|
|
|
: sizeof(struct sockaddr))))
|
[autoconf] bugs 162,303,178: Fix 'present but can not be compiled' warnings
2007-05-09 Paul Jakma <paul.jakma@sun.com>
* configure.ac: sys/conf.h depends on sys/param.h, at least on
FBSD 6.2.
(bug #363) Should check for in_pktinfo for IRDP
2006-05-27 Paul Jakma <paul.jakma@sun.com>
* configure.ac: General cleanup of header and type checks, introducing
an internal define, QUAGGA_INCLUDES, to build up a list of
stuff to include so as to avoid 'present but cant be compiled'
warnings.
Misc additional checks of things missing according to autoscan.
Add LIBM, for bgpd's use of libm, so as to avoid burdening
LIBS, and all the binaries, with libm linkage.
Remove the bad practice of using m4 changequote(), just
quote the []'s in the case statements properly.
This should fix bugs 162, 303 and 178.
* */*.{c,h}: Update all HAVE_* to the standard autoconf namespaced
HAVE_* defines. I.e. HAVE_SA_LEN -> HAVE_STRUCT_SOCKADDR_SA_LEN,
* bgpd/Makefile.am: Add LIBM to bgpd's LDADD, for pow().
2007-05-10 04:38:51 +02:00
|
|
|
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2015-03-03 21:04:20 +01:00
|
|
|
#endif /* !SA_SIZE */
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Routing socket message types. */
|
2008-08-14 18:59:25 +02:00
|
|
|
const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"},
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTM_DELETE, "RTM_DELETE"},
|
|
|
|
{RTM_CHANGE, "RTM_CHANGE"},
|
|
|
|
{RTM_GET, "RTM_GET"},
|
|
|
|
{RTM_LOSING, "RTM_LOSING"},
|
|
|
|
{RTM_REDIRECT, "RTM_REDIRECT"},
|
|
|
|
{RTM_MISS, "RTM_MISS"},
|
2018-12-21 20:03:05 +01:00
|
|
|
#ifdef RTM_LOCK
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTM_LOCK, "RTM_LOCK"},
|
2018-12-21 20:03:05 +01:00
|
|
|
#endif /* RTM_LOCK */
|
2006-09-13 14:13:08 +02:00
|
|
|
#ifdef OLDADD
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTM_OLDADD, "RTM_OLDADD"},
|
2006-09-13 14:13:08 +02:00
|
|
|
#endif /* RTM_OLDADD */
|
|
|
|
#ifdef RTM_OLDDEL
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTM_OLDDEL, "RTM_OLDDEL"},
|
2006-09-13 14:13:08 +02:00
|
|
|
#endif /* RTM_OLDDEL */
|
2019-04-02 15:26:45 +02:00
|
|
|
#ifdef RTM_RESOLVE
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTM_RESOLVE, "RTM_RESOLVE"},
|
2019-04-02 15:26:45 +02:00
|
|
|
#endif /* RTM_RESOLVE */
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTM_NEWADDR, "RTM_NEWADDR"},
|
|
|
|
{RTM_DELADDR, "RTM_DELADDR"},
|
|
|
|
{RTM_IFINFO, "RTM_IFINFO"},
|
|
|
|
#ifdef RTM_OIFINFO
|
|
|
|
{RTM_OIFINFO, "RTM_OIFINFO"},
|
|
|
|
#endif /* RTM_OIFINFO */
|
|
|
|
#ifdef RTM_NEWMADDR
|
|
|
|
{RTM_NEWMADDR, "RTM_NEWMADDR"},
|
|
|
|
#endif /* RTM_NEWMADDR */
|
|
|
|
#ifdef RTM_DELMADDR
|
|
|
|
{RTM_DELMADDR, "RTM_DELMADDR"},
|
|
|
|
#endif /* RTM_DELMADDR */
|
|
|
|
#ifdef RTM_IFANNOUNCE
|
|
|
|
{RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
|
|
|
|
#endif /* RTM_IFANNOUNCE */
|
2022-03-24 23:31:23 +01:00
|
|
|
#ifdef RTM_IEEE80211
|
|
|
|
{RTM_IEEE80211, "RTM_IEEE80211"},
|
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
{0}};
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2009-05-15 19:47:04 +02:00
|
|
|
static const struct message rtm_flag_str[] = {{RTF_UP, "UP"},
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTF_GATEWAY, "GATEWAY"},
|
|
|
|
{RTF_HOST, "HOST"},
|
|
|
|
{RTF_REJECT, "REJECT"},
|
|
|
|
{RTF_DYNAMIC, "DYNAMIC"},
|
|
|
|
{RTF_MODIFIED, "MODIFIED"},
|
|
|
|
{RTF_DONE, "DONE"},
|
|
|
|
#ifdef RTF_MASK
|
|
|
|
{RTF_MASK, "MASK"},
|
|
|
|
#endif /* RTF_MASK */
|
2009-12-03 19:43:11 +01:00
|
|
|
#ifdef RTF_CLONING
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTF_CLONING, "CLONING"},
|
2009-12-03 19:43:11 +01:00
|
|
|
#endif /* RTF_CLONING */
|
2016-08-04 15:07:24 +02:00
|
|
|
#ifdef RTF_XRESOLVE
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTF_XRESOLVE, "XRESOLVE"},
|
2016-08-04 15:07:24 +02:00
|
|
|
#endif /* RTF_XRESOLVE */
|
2016-01-12 19:41:44 +01:00
|
|
|
#ifdef RTF_LLINFO
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTF_LLINFO, "LLINFO"},
|
2016-01-12 19:41:44 +01:00
|
|
|
#endif /* RTF_LLINFO */
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTF_STATIC, "STATIC"},
|
|
|
|
{RTF_BLACKHOLE, "BLACKHOLE"},
|
2005-11-12 23:55:10 +01:00
|
|
|
#ifdef RTF_PRIVATE
|
|
|
|
{RTF_PRIVATE, "PRIVATE"},
|
|
|
|
#endif /* RTF_PRIVATE */
|
2002-12-13 21:15:29 +01:00
|
|
|
{RTF_PROTO1, "PROTO1"},
|
|
|
|
{RTF_PROTO2, "PROTO2"},
|
|
|
|
#ifdef RTF_PRCLONING
|
|
|
|
{RTF_PRCLONING, "PRCLONING"},
|
|
|
|
#endif /* RTF_PRCLONING */
|
|
|
|
#ifdef RTF_WASCLONED
|
|
|
|
{RTF_WASCLONED, "WASCLONED"},
|
|
|
|
#endif /* RTF_WASCLONED */
|
|
|
|
#ifdef RTF_PROTO3
|
|
|
|
{RTF_PROTO3, "PROTO3"},
|
|
|
|
#endif /* RTF_PROTO3 */
|
|
|
|
#ifdef RTF_PINNED
|
|
|
|
{RTF_PINNED, "PINNED"},
|
|
|
|
#endif /* RTF_PINNED */
|
|
|
|
#ifdef RTF_LOCAL
|
|
|
|
{RTF_LOCAL, "LOCAL"},
|
|
|
|
#endif /* RTF_LOCAL */
|
|
|
|
#ifdef RTF_BROADCAST
|
|
|
|
{RTF_BROADCAST, "BROADCAST"},
|
|
|
|
#endif /* RTF_BROADCAST */
|
|
|
|
#ifdef RTF_MULTICAST
|
|
|
|
{RTF_MULTICAST, "MULTICAST"},
|
|
|
|
#endif /* RTF_MULTICAST */
|
2005-11-12 23:55:10 +01:00
|
|
|
#ifdef RTF_MULTIRT
|
|
|
|
{RTF_MULTIRT, "MULTIRT"},
|
|
|
|
#endif /* RTF_MULTIRT */
|
|
|
|
#ifdef RTF_SETSRC
|
|
|
|
{RTF_SETSRC, "SETSRC"},
|
|
|
|
#endif /* RTF_SETSRC */
|
2002-12-13 21:15:29 +01:00
|
|
|
{0}};
|
|
|
|
|
|
|
|
/* Kernel routing update socket. */
|
|
|
|
int routing_sock = -1;
|
|
|
|
|
2018-11-14 20:45:30 +01:00
|
|
|
/* Kernel dataplane routing update socket, used in the dataplane pthread
|
|
|
|
* context.
|
|
|
|
*/
|
|
|
|
int dplane_routing_sock = -1;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Yes I'm checking ugly routing socket behavior. */
|
|
|
|
/* #define DEBUG */
|
|
|
|
|
2019-01-08 11:14:28 +01:00
|
|
|
size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf);
|
2018-12-05 14:51:25 +01:00
|
|
|
size_t rta_get(caddr_t sap, void *dest, size_t destlen);
|
2019-01-08 11:14:28 +01:00
|
|
|
size_t rta_getattr(caddr_t sap, void *destp, size_t destlen);
|
2018-12-05 14:51:25 +01:00
|
|
|
size_t rta_getsdlname(caddr_t sap, void *dest, short *destlen);
|
2019-01-17 23:24:31 +01:00
|
|
|
const char *rtatostr(unsigned int flags, char *buf, size_t buflen);
|
2018-12-05 14:51:25 +01:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Supported address family check. */
|
|
|
|
static inline int af_check(int family)
|
|
|
|
{
|
|
|
|
if (family == AF_INET)
|
|
|
|
return 1;
|
|
|
|
if (family == AF_INET6)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2019-01-08 11:14:28 +01:00
|
|
|
size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf)
|
2018-12-05 14:51:25 +01:00
|
|
|
{
|
|
|
|
struct sockaddr *sa = (struct sockaddr *)sap;
|
2019-01-08 13:32:28 +01:00
|
|
|
struct sockaddr_dl *sdl;
|
2018-12-05 14:51:25 +01:00
|
|
|
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 */
|
|
|
|
|
2019-01-08 11:14:28 +01:00
|
|
|
if (copylen > 0 && dest != NULL) {
|
|
|
|
if (checkaf && af_check(sa->sa_family) == 0)
|
|
|
|
return tlen;
|
2019-01-08 13:32:28 +01:00
|
|
|
/*
|
|
|
|
* Handle sockaddr_dl corner case:
|
|
|
|
* RTA_NETMASK might be AF_LINK, but it doesn't anything
|
|
|
|
* relevant (e.g. zeroed out fields). Check for this
|
|
|
|
* case and avoid warning log message.
|
|
|
|
*/
|
|
|
|
if (sa->sa_family == AF_LINK) {
|
|
|
|
sdl = (struct sockaddr_dl *)sa;
|
|
|
|
if (sdl->sdl_index == 0 || sdl->sdl_nlen == 0)
|
2019-01-17 23:46:11 +01:00
|
|
|
copylen = destlen;
|
2019-01-08 13:32:28 +01:00
|
|
|
}
|
2019-01-08 11:14:28 +01:00
|
|
|
|
2018-12-05 14:51:25 +01:00
|
|
|
if (copylen > destlen) {
|
2019-04-03 22:39:50 +02:00
|
|
|
zlog_warn(
|
|
|
|
"%s: destination buffer too small (%zu vs %zu)",
|
|
|
|
__func__, copylen, destlen);
|
2018-12-05 14:51:25 +01:00
|
|
|
memcpy(dest, sap, destlen);
|
|
|
|
} else
|
|
|
|
memcpy(dest, sap, copylen);
|
|
|
|
}
|
|
|
|
|
|
|
|
return tlen;
|
|
|
|
}
|
|
|
|
|
2019-01-08 11:14:28 +01:00
|
|
|
size_t rta_get(caddr_t sap, void *destp, size_t destlen)
|
|
|
|
{
|
|
|
|
return _rta_get(sap, destp, destlen, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t rta_getattr(caddr_t sap, void *destp, size_t destlen)
|
|
|
|
{
|
|
|
|
return _rta_get(sap, destp, destlen, false);
|
|
|
|
}
|
|
|
|
|
2018-12-05 14:51:25 +01:00
|
|
|
size_t rta_getsdlname(caddr_t sap, void *destp, short *destlen)
|
|
|
|
{
|
|
|
|
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sap;
|
|
|
|
uint8_t *dest = destp;
|
|
|
|
size_t tlen, copylen;
|
|
|
|
|
|
|
|
copylen = sdl->sdl_nlen;
|
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
2019-05-06 20:00:25 +02:00
|
|
|
struct sockaddr *sa = (struct sockaddr *)sap;
|
|
|
|
|
2018-12-05 14:51:25 +01:00
|
|
|
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) {
|
2019-04-03 22:39:50 +02:00
|
|
|
zlog_warn(
|
|
|
|
"%s: destination buffer too small (%zu vs %d)",
|
|
|
|
__func__, copylen, IFNAMSIZ);
|
2018-12-05 14:51:25 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-17 23:24:31 +01:00
|
|
|
const char *rtatostr(unsigned int flags, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
const char *flagstr, *bufstart;
|
|
|
|
int bit, wlen;
|
|
|
|
char ustr[32];
|
|
|
|
|
|
|
|
/* Hold the pointer to the buffer beginning. */
|
|
|
|
bufstart = buf;
|
|
|
|
|
|
|
|
for (bit = 1; bit; bit <<= 1) {
|
|
|
|
if ((flags & bit) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (bit) {
|
|
|
|
case RTA_DST:
|
|
|
|
flagstr = "DST";
|
|
|
|
break;
|
|
|
|
case RTA_GATEWAY:
|
|
|
|
flagstr = "GATEWAY";
|
|
|
|
break;
|
|
|
|
case RTA_NETMASK:
|
|
|
|
flagstr = "NETMASK";
|
|
|
|
break;
|
|
|
|
#ifdef RTA_GENMASK
|
|
|
|
case RTA_GENMASK:
|
|
|
|
flagstr = "GENMASK";
|
|
|
|
break;
|
|
|
|
#endif /* RTA_GENMASK */
|
|
|
|
case RTA_IFP:
|
|
|
|
flagstr = "IFP";
|
|
|
|
break;
|
|
|
|
case RTA_IFA:
|
|
|
|
flagstr = "IFA";
|
|
|
|
break;
|
|
|
|
#ifdef RTA_AUTHOR
|
|
|
|
case RTA_AUTHOR:
|
|
|
|
flagstr = "AUTHOR";
|
|
|
|
break;
|
|
|
|
#endif /* RTA_AUTHOR */
|
|
|
|
case RTA_BRD:
|
|
|
|
flagstr = "BRD";
|
|
|
|
break;
|
|
|
|
#ifdef RTA_SRC
|
|
|
|
case RTA_SRC:
|
|
|
|
flagstr = "SRC";
|
|
|
|
break;
|
|
|
|
#endif /* RTA_SRC */
|
|
|
|
#ifdef RTA_SRCMASK
|
|
|
|
case RTA_SRCMASK:
|
|
|
|
flagstr = "SRCMASK";
|
|
|
|
break;
|
|
|
|
#endif /* RTA_SRCMASK */
|
|
|
|
#ifdef RTA_LABEL
|
|
|
|
case RTA_LABEL:
|
|
|
|
flagstr = "LABEL";
|
|
|
|
break;
|
|
|
|
#endif /* RTA_LABEL */
|
|
|
|
|
|
|
|
default:
|
|
|
|
snprintf(ustr, sizeof(ustr), "0x%x", bit);
|
|
|
|
flagstr = ustr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
wlen = snprintf(buf, buflen, "%s,", flagstr);
|
|
|
|
buf += wlen;
|
|
|
|
buflen -= wlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for empty buffer. */
|
|
|
|
if (bufstart != buf)
|
|
|
|
buf--;
|
|
|
|
|
|
|
|
/* Remove the last comma. */
|
|
|
|
*buf = 0;
|
|
|
|
|
|
|
|
return bufstart;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Dump routing table flag for debug purpose. */
|
|
|
|
static void rtm_flag_dump(int flag)
|
|
|
|
{
|
2009-12-03 12:53:15 +01:00
|
|
|
const struct message *mes;
|
2002-12-13 21:15:29 +01:00
|
|
|
static char buf[BUFSIZ];
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-07-13 18:45:54 +02:00
|
|
|
buf[0] = '\0';
|
2002-12-13 21:15:29 +01:00
|
|
|
for (mes = rtm_flag_str; mes->key != 0; mes++) {
|
|
|
|
if (mes->key & flag) {
|
|
|
|
strlcat(buf, mes->str, BUFSIZ);
|
|
|
|
strlcat(buf, " ", BUFSIZ);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2004-12-07 22:12:56 +01:00
|
|
|
zlog_debug("Kernel: %s", buf);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef RTM_IFANNOUNCE
|
|
|
|
/* Interface adding function */
|
|
|
|
static int ifan_read(struct if_announcemsghdr *ifan)
|
|
|
|
{
|
|
|
|
struct interface *ifp;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-03-10 21:45:28 +01:00
|
|
|
ifp = if_lookup_by_index(ifan->ifan_index, VRF_DEFAULT);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
if (ifp)
|
|
|
|
assert((ifp->ifindex == ifan->ifan_index)
|
|
|
|
|| (ifp->ifindex == IFINDEX_INTERNAL));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-22 14:52:33 +02:00
|
|
|
if ((ifp == NULL) || ((ifp->ifindex == IFINDEX_INTERNAL)
|
|
|
|
&& (ifan->ifan_what == IFAN_ARRIVAL))) {
|
2005-11-12 23:55:10 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: creating interface for ifindex %d, name %s",
|
|
|
|
__func__, ifan->ifan_index, ifan->ifan_name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Create Interface */
|
2021-10-13 14:06:38 +02:00
|
|
|
ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT,
|
|
|
|
VRF_DEFAULT_NAME);
|
2017-10-03 03:06:04 +02:00
|
|
|
if_set_index(ifp, ifan->ifan_index);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2011-04-17 20:28:20 +02:00
|
|
|
if_get_metric(ifp);
|
2002-12-13 21:15:29 +01:00
|
|
|
if_add_update(ifp);
|
|
|
|
} else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
|
2022-03-25 01:02:33 +01:00
|
|
|
if_delete_update(&ifp);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-03-25 01:02:33 +01:00
|
|
|
if (ifp) {
|
|
|
|
if_get_flags(ifp);
|
|
|
|
if_get_mtu(ifp);
|
|
|
|
if_get_metric(ifp);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
2005-11-12 23:55:10 +01:00
|
|
|
zlog_debug("%s: interface %s index %d", __func__,
|
|
|
|
ifan->ifan_name, ifan->ifan_index);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* RTM_IFANNOUNCE */
|
|
|
|
|
2012-10-11 01:12:32 +02:00
|
|
|
#ifdef HAVE_BSD_IFI_LINK_STATE
|
2008-01-10 16:24:32 +01:00
|
|
|
/* BSD link detect translation */
|
|
|
|
static void bsd_linkdetect_translate(struct if_msghdr *ifm)
|
|
|
|
{
|
2008-01-11 16:57:13 +01:00
|
|
|
if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP)
|
|
|
|
|| (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
|
2008-01-10 16:24:32 +01:00
|
|
|
SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
|
|
|
|
else
|
|
|
|
UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
|
|
|
|
}
|
2012-10-11 01:12:32 +02:00
|
|
|
#endif /* HAVE_BSD_IFI_LINK_STATE */
|
2008-01-10 16:24:32 +01:00
|
|
|
|
2016-01-15 16:36:33 +01:00
|
|
|
static enum zebra_link_type sdl_to_zebra_link_type(unsigned int sdlt)
|
|
|
|
{
|
|
|
|
switch (sdlt) {
|
|
|
|
case IFT_ETHER:
|
|
|
|
return ZEBRA_LLT_ETHER;
|
|
|
|
case IFT_X25:
|
|
|
|
return ZEBRA_LLT_X25;
|
|
|
|
case IFT_FDDI:
|
|
|
|
return ZEBRA_LLT_FDDI;
|
|
|
|
case IFT_PPP:
|
|
|
|
return ZEBRA_LLT_PPP;
|
|
|
|
case IFT_LOOP:
|
|
|
|
return ZEBRA_LLT_LOOPBACK;
|
|
|
|
case IFT_SLIP:
|
|
|
|
return ZEBRA_LLT_SLIP;
|
|
|
|
case IFT_ARCNET:
|
|
|
|
return ZEBRA_LLT_ARCNET;
|
|
|
|
case IFT_ATM:
|
|
|
|
return ZEBRA_LLT_ATM;
|
|
|
|
case IFT_LOCALTALK:
|
|
|
|
return ZEBRA_LLT_LOCALTLK;
|
|
|
|
case IFT_HIPPI:
|
|
|
|
return ZEBRA_LLT_HIPPI;
|
|
|
|
#ifdef IFT_IEEE1394
|
|
|
|
case IFT_IEEE1394:
|
|
|
|
return ZEBRA_LLT_IEEE1394;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
default:
|
|
|
|
return ZEBRA_LLT_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-05 18:20:59 +01:00
|
|
|
/*
|
|
|
|
* Handle struct if_msghdr obtained from reading routing socket or
|
|
|
|
* sysctl (from interface_list). There may or may not be sockaddrs
|
|
|
|
* present after the header.
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
int ifm_read(struct if_msghdr *ifm)
|
|
|
|
{
|
2003-09-24 02:05:45 +02:00
|
|
|
struct interface *ifp = NULL;
|
2019-05-06 20:01:56 +02:00
|
|
|
struct sockaddr_dl *sdl = NULL;
|
2005-11-12 23:55:10 +01:00
|
|
|
char ifname[IFNAMSIZ];
|
|
|
|
short ifnlen = 0;
|
2018-12-05 14:51:25 +01:00
|
|
|
int maskbit;
|
2012-10-11 01:11:36 +02:00
|
|
|
caddr_t cp;
|
2019-01-17 23:24:31 +01:00
|
|
|
char fbuf[64];
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
/* terminate ifname at head (for strnlen) and tail (for safety) */
|
|
|
|
ifname[IFNAMSIZ - 1] = '\0';
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-05 18:20:59 +01:00
|
|
|
/* paranoia: sanity check structure */
|
|
|
|
if (ifm->ifm_msglen < sizeof(struct if_msghdr)) {
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_err(EC_ZEBRA_NETLINK_LENGTH_ERROR,
|
2022-09-22 20:34:40 +02:00
|
|
|
"%s: ifm->ifm_msglen %d too short", __func__,
|
2018-09-13 21:38:57 +02:00
|
|
|
ifm->ifm_msglen);
|
2004-01-05 18:20:59 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-05 18:20:59 +01:00
|
|
|
/*
|
2004-01-06 02:13:05 +01:00
|
|
|
* Check for a sockaddr_dl following the message. First, point to
|
|
|
|
* where a socakddr might be if one follows the message.
|
2004-01-05 18:20:59 +01:00
|
|
|
*/
|
2004-01-06 02:13:05 +01:00
|
|
|
cp = (void *)(ifm + 1);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-12-05 14:51:25 +01:00
|
|
|
/* 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);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
2019-01-17 23:24:31 +01:00
|
|
|
zlog_debug("%s: sdl ifname %s addrs {%s}", __func__,
|
|
|
|
(ifnlen ? ifname : "(nil)"),
|
|
|
|
rtatostr(ifm->ifm_addrs, fbuf, sizeof(fbuf)));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
/*
|
|
|
|
* Look up on ifindex first, because ifindices are the primary handle
|
|
|
|
* for
|
|
|
|
* interfaces across the user/kernel boundary, for most systems. (Some
|
|
|
|
* messages, such as up/down status changes on NetBSD, do not include a
|
|
|
|
* sockaddr_dl).
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2005-11-12 23:55:10 +01:00
|
|
|
if ((ifp = if_lookup_by_index(ifm->ifm_index, VRF_DEFAULT)) != NULL) {
|
|
|
|
/* we have an ifp, verify that the name matches as some systems,
|
|
|
|
* eg Solaris, have a 1:many association of ifindex:ifname
|
|
|
|
* if they dont match, we dont have the correct ifp and should
|
|
|
|
* set it back to NULL to let next check do lookup by name
|
2004-01-05 18:20:59 +01:00
|
|
|
*/
|
2005-04-02 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
Fix problems when netlink interfaces are renamed (same ifindex used
for a new interface). Start cleaning up some problems with the way
interface names are handled.
* interface.c: (if_new_intern_ifindex) Remove obsolete function.
(if_delete_update) After distributing the interface deletion message,
set ifp->ifindex to IFINDEX_INTERNAL.
(if_dump_vty) Detect pseudo interface by checking if ifp->ifindex is
IFINDEX_INTERNAL.
(zebra_interface) Check return code from interface_cmd.func.
Do not set internal ifindex values to if_new_intern_ifindex(),
since we now use IFINDEX_INTERNAL for all pseudo interfaces.
* kernel_socket.c: (ifm_read) Fix code and comments to reflect that
all internal interfaces now have ifp->ifindex set to IFINDEX_INTERNAL.
* rt_netlink.c: (set_ifindex) New function used to update ifp->ifindex.
Detects interface rename events by checking if that ifindex is already
being used. If it is, delete the old interface before assigning
the ifindex to the new interface.
(netlink_interface, netlink_link_change) Call set_ifindex to update
the ifindex.
* if.h: Remove define for IFINDEX_INTERNBASE and add define
IFINDEX_INTERNAL 0, since all internal (i.e. non-kernel) pseudo-
interfaces should have ifindex set to 0.
(if_new) Remove function.
(if_delete_retain) New function to delete an interface without
removing from iflist and freeing the structure.
(ifname2ifindex) New function.
* if.c: (if_new) Remove function (absorb into if_create).
(if_create) Replace function if_new with call to calloc.
Set ifp->ifindex to IFINDEX_INTERNAL. Fix off-by-one error
in assert to check length of interface name. Add error message
if interface with this name already exists.
(if_delete_retain) New function to delete an interface without
removing from iflist and freeing the structure.
(if_delete) Implement with help of if_delete_retain.
(ifindex2ifname) Reimplement using if_lookup_by_index.
(ifname2ifindex) New function to complement ifindex2ifname.
(interface) The interface command should check the name length
and fail with a warning message if it is too long.
(no_interface) Fix spelling in warning message.
(if_nametoindex) Reimplement using if_lookup_by_name.
(if_indextoname, ifaddr_ipv4_lookup) Reimplement using
if_lookup_by_index.
* bgp_zebra.c: (bgp_interface_delete) After deleting, set ifp->ifindex
to IFINDEX_INTERNAL.
* isis_zebra.c: (isis_zebra_if_del) Call if_delete_retain instead
of if_delete, since it is generally not safe to remove interface
structures. After deleting, set ifp->ifindex to IFINDEX_INTERNAL.
(zebra_interface_if_lookup) Tighten up code.
* ospf6_zebra.c: (ospf6_zebra_if_del) Previously, this whole function
was commented out. But this is not safe: we should at least update
the ifindex when the interface is deleted. So the new version
updates the interface status and sets ifp->ifindex to
IFINDEX_INTERNAL.
(ospf6_zebra_route_update) Use if_indextoname properly.
* ospf_vty.c: (show_ip_ospf_interface_sub) Show ifindex and interface
flags to help with debugging.
* ospf_zebra.c: (ospf_interface_delete) After deleting, set ifp->ifindex
to IFINDEX_INTERNAL.
(zebra_interface_if_lookup) Make function static. Tighten up code.
* rip_interface.c: (rip_interface_delete) After deleting, set
ifp->ifindex to IFINDEX_INTERNAL.
* ripng_interface.c: (ripng_interface_delete) After deleting, set
ifp->ifindex to IFINDEX_INTERNAL.
2005-04-02 20:38:43 +02:00
|
|
|
if (ifnlen && (strncmp(ifp->name, ifname, IFNAMSIZ) != 0)) {
|
2005-11-12 23:55:10 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
|
|
|
zlog_debug(
|
2018-10-25 20:06:59 +02:00
|
|
|
"%s: ifp name %s doesn't match sdl name %s",
|
2004-01-06 02:13:05 +01:00
|
|
|
__func__, ifp->name, ifname);
|
2004-01-05 18:20:59 +01:00
|
|
|
ifp = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2004-01-05 18:20:59 +01:00
|
|
|
}
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/*
|
2005-11-12 23:55:10 +01:00
|
|
|
* If we dont have an ifp, try looking up by name. Particularly as some
|
|
|
|
* systems (Solaris) have a 1:many mapping of ifindex:ifname - the
|
2017-07-17 14:03:14 +02:00
|
|
|
* ifname
|
2005-11-12 23:55:10 +01:00
|
|
|
* is therefore our unique handle to that interface.
|
2017-07-17 14:03:14 +02:00
|
|
|
*
|
2005-11-12 23:55:10 +01:00
|
|
|
* Interfaces specified in the configuration file for which the ifindex
|
|
|
|
* has not been determined will have ifindex == IFINDEX_INTERNAL, and
|
2017-07-17 14:03:14 +02:00
|
|
|
* such
|
2005-11-12 23:55:10 +01:00
|
|
|
* interfaces are found by this search, and then their ifindex values
|
2017-07-17 14:03:14 +02:00
|
|
|
* can
|
2005-11-12 23:55:10 +01:00
|
|
|
* be filled in.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2005-11-12 23:55:10 +01:00
|
|
|
if ((ifp == NULL) && ifnlen)
|
2019-06-24 01:46:39 +02:00
|
|
|
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/*
|
2005-11-12 23:55:10 +01:00
|
|
|
* If ifp still does not exist or has an invalid index
|
|
|
|
* (IFINDEX_INTERNAL),
|
|
|
|
* create or fill in an interface.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2017-03-10 21:45:28 +01:00
|
|
|
if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL)) {
|
2017-07-17 14:03:14 +02:00
|
|
|
/*
|
2004-01-06 02:13:05 +01:00
|
|
|
* To create or fill in an interface, a sockaddr_dl (via
|
|
|
|
* RTA_IFP) is required.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2005-11-12 23:55:10 +01:00
|
|
|
if (!ifnlen) {
|
2019-03-14 19:41:15 +01:00
|
|
|
zlog_debug("Interface index %d (new) missing ifname",
|
2018-08-16 22:10:32 +02:00
|
|
|
ifm->ifm_index);
|
2005-11-12 23:55:10 +01:00
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
#ifndef RTM_IFANNOUNCE
|
|
|
|
/* Down->Down interface should be ignored here.
|
|
|
|
* See further comment below.
|
|
|
|
*/
|
|
|
|
if (!CHECK_FLAG(ifm->ifm_flags, IFF_UP))
|
|
|
|
return 0;
|
|
|
|
#endif /* !RTM_IFANNOUNCE */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-09-24 02:05:45 +02:00
|
|
|
if (ifp == NULL) {
|
2005-11-12 23:55:10 +01:00
|
|
|
/* Interface that zebra was not previously aware of, so
|
|
|
|
* create. */
|
2021-10-13 14:06:38 +02:00
|
|
|
ifp = if_get_by_name(ifname, VRF_DEFAULT,
|
|
|
|
VRF_DEFAULT_NAME);
|
2005-11-12 23:55:10 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
|
|
|
zlog_debug("%s: creating ifp for ifindex %d",
|
|
|
|
__func__, ifm->ifm_index);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: updated/created ifp, ifname %s, ifindex %d",
|
|
|
|
__func__, ifp->name, ifp->ifindex);
|
2004-01-06 02:13:05 +01:00
|
|
|
/*
|
|
|
|
* Fill in newly created interface structure, or larval
|
2005-04-02 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
Fix problems when netlink interfaces are renamed (same ifindex used
for a new interface). Start cleaning up some problems with the way
interface names are handled.
* interface.c: (if_new_intern_ifindex) Remove obsolete function.
(if_delete_update) After distributing the interface deletion message,
set ifp->ifindex to IFINDEX_INTERNAL.
(if_dump_vty) Detect pseudo interface by checking if ifp->ifindex is
IFINDEX_INTERNAL.
(zebra_interface) Check return code from interface_cmd.func.
Do not set internal ifindex values to if_new_intern_ifindex(),
since we now use IFINDEX_INTERNAL for all pseudo interfaces.
* kernel_socket.c: (ifm_read) Fix code and comments to reflect that
all internal interfaces now have ifp->ifindex set to IFINDEX_INTERNAL.
* rt_netlink.c: (set_ifindex) New function used to update ifp->ifindex.
Detects interface rename events by checking if that ifindex is already
being used. If it is, delete the old interface before assigning
the ifindex to the new interface.
(netlink_interface, netlink_link_change) Call set_ifindex to update
the ifindex.
* if.h: Remove define for IFINDEX_INTERNBASE and add define
IFINDEX_INTERNAL 0, since all internal (i.e. non-kernel) pseudo-
interfaces should have ifindex set to 0.
(if_new) Remove function.
(if_delete_retain) New function to delete an interface without
removing from iflist and freeing the structure.
(ifname2ifindex) New function.
* if.c: (if_new) Remove function (absorb into if_create).
(if_create) Replace function if_new with call to calloc.
Set ifp->ifindex to IFINDEX_INTERNAL. Fix off-by-one error
in assert to check length of interface name. Add error message
if interface with this name already exists.
(if_delete_retain) New function to delete an interface without
removing from iflist and freeing the structure.
(if_delete) Implement with help of if_delete_retain.
(ifindex2ifname) Reimplement using if_lookup_by_index.
(ifname2ifindex) New function to complement ifindex2ifname.
(interface) The interface command should check the name length
and fail with a warning message if it is too long.
(no_interface) Fix spelling in warning message.
(if_nametoindex) Reimplement using if_lookup_by_name.
(if_indextoname, ifaddr_ipv4_lookup) Reimplement using
if_lookup_by_index.
* bgp_zebra.c: (bgp_interface_delete) After deleting, set ifp->ifindex
to IFINDEX_INTERNAL.
* isis_zebra.c: (isis_zebra_if_del) Call if_delete_retain instead
of if_delete, since it is generally not safe to remove interface
structures. After deleting, set ifp->ifindex to IFINDEX_INTERNAL.
(zebra_interface_if_lookup) Tighten up code.
* ospf6_zebra.c: (ospf6_zebra_if_del) Previously, this whole function
was commented out. But this is not safe: we should at least update
the ifindex when the interface is deleted. So the new version
updates the interface status and sets ifp->ifindex to
IFINDEX_INTERNAL.
(ospf6_zebra_route_update) Use if_indextoname properly.
* ospf_vty.c: (show_ip_ospf_interface_sub) Show ifindex and interface
flags to help with debugging.
* ospf_zebra.c: (ospf_interface_delete) After deleting, set ifp->ifindex
to IFINDEX_INTERNAL.
(zebra_interface_if_lookup) Make function static. Tighten up code.
* rip_interface.c: (rip_interface_delete) After deleting, set
ifp->ifindex to IFINDEX_INTERNAL.
* ripng_interface.c: (ripng_interface_delete) After deleting, set
ifp->ifindex to IFINDEX_INTERNAL.
2005-04-02 20:38:43 +02:00
|
|
|
* structure with ifindex IFINDEX_INTERNAL.
|
2004-01-06 02:13:05 +01:00
|
|
|
*/
|
2017-10-03 03:06:04 +02:00
|
|
|
if_set_index(ifp, ifm->ifm_index);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-10-11 01:12:32 +02:00
|
|
|
#ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
|
2008-01-10 16:24:32 +01:00
|
|
|
bsd_linkdetect_translate(ifm);
|
2012-10-11 01:12:32 +02:00
|
|
|
#endif /* HAVE_BSD_IFI_LINK_STATE */
|
2008-01-10 16:24:32 +01:00
|
|
|
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
if_flags_update(ifp, ifm->ifm_flags);
|
2002-12-13 21:15:29 +01:00
|
|
|
#if defined(__bsdi__)
|
|
|
|
if_kvm_get_mtu(ifp);
|
|
|
|
#else
|
|
|
|
if_get_mtu(ifp);
|
|
|
|
#endif /* __bsdi__ */
|
|
|
|
if_get_metric(ifp);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2009-11-25 21:36:06 +01:00
|
|
|
/*
|
|
|
|
* XXX sockaddr_dl contents can be larger than the structure
|
2012-09-26 14:52:39 +02:00
|
|
|
* definition. There are 2 big families here:
|
|
|
|
* - BSD has sdl_len + sdl_data[16] + overruns sdl_data
|
|
|
|
* we MUST use sdl_len here or we'll truncate data.
|
|
|
|
* - Solaris has no sdl_len, but sdl_data[244]
|
|
|
|
* presumably, it's not going to run past that, so sizeof()
|
|
|
|
* is fine here.
|
2018-12-05 14:51:25 +01:00
|
|
|
* a nonzero ifnlen from rta_getsdlname() means sdl is valid
|
2009-11-25 21:36:06 +01:00
|
|
|
*/
|
2016-01-15 16:36:33 +01:00
|
|
|
ifp->ll_type = ZEBRA_LLT_UNKNOWN;
|
|
|
|
ifp->hw_addr_len = 0;
|
2009-11-25 21:36:06 +01:00
|
|
|
if (ifnlen) {
|
2012-09-26 14:52:39 +02:00
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN
|
2016-01-15 16:36:33 +01:00
|
|
|
memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl,
|
|
|
|
sdl->sdl_len);
|
2012-09-26 14:52:39 +02:00
|
|
|
#else
|
2016-01-15 16:36:33 +01:00
|
|
|
memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl,
|
|
|
|
sizeof(struct sockaddr_dl));
|
2012-09-26 14:52:39 +02:00
|
|
|
#endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */
|
2016-01-15 16:36:33 +01:00
|
|
|
|
|
|
|
ifp->ll_type = sdl_to_zebra_link_type(sdl->sdl_type);
|
|
|
|
if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) {
|
|
|
|
memcpy(ifp->hw_addr, LLADDR(sdl),
|
|
|
|
sdl->sdl_alen);
|
|
|
|
ifp->hw_addr_len = sdl->sdl_alen;
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if_add_update(ifp);
|
|
|
|
} else
|
2004-01-05 18:20:59 +01:00
|
|
|
/*
|
|
|
|
* Interface structure exists. Adjust stored flags from
|
|
|
|
* notification. If interface has up->down or down->up
|
|
|
|
* transition, call state change routines (to adjust routes,
|
|
|
|
* notify routing daemons, etc.). (Other flag changes are stored
|
|
|
|
* but apparently do not trigger action.)
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-11-12 23:55:10 +01:00
|
|
|
if (ifp->ifindex != ifm->ifm_index) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug(
|
2020-03-27 12:35:23 +01:00
|
|
|
"%s: index mismatch, ifname %s, ifp index %d, ifm index %d",
|
2005-11-12 23:55:10 +01:00
|
|
|
__func__, ifp->name, ifp->ifindex,
|
|
|
|
ifm->ifm_index);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-10-11 01:12:32 +02:00
|
|
|
#ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
|
2008-01-10 16:24:32 +01:00
|
|
|
bsd_linkdetect_translate(ifm);
|
2012-10-11 01:12:32 +02:00
|
|
|
#endif /* HAVE_BSD_IFI_LINK_STATE */
|
2008-01-10 16:24:32 +01:00
|
|
|
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
/* update flags and handle operative->inoperative transition, if
|
|
|
|
* any */
|
|
|
|
if_flags_update(ifp, ifm->ifm_flags);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-07-29 16:36:00 +02:00
|
|
|
#ifndef RTM_IFANNOUNCE
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
if (!if_is_up(ifp)) {
|
|
|
|
/* No RTM_IFANNOUNCE on this platform, so we can never
|
|
|
|
* distinguish between ~IFF_UP and delete. We must
|
|
|
|
* presume
|
|
|
|
* it has been deleted.
|
|
|
|
* Eg, Solaris will not notify us of unplumb.
|
|
|
|
*
|
|
|
|
* XXX: Fixme - this should be runtime detected
|
|
|
|
* So that a binary compiled on a system with IFANNOUNCE
|
|
|
|
* will still behave correctly if run on a platform
|
|
|
|
* without
|
|
|
|
*/
|
2022-03-25 01:02:33 +01:00
|
|
|
if_delete_update(&ifp);
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
}
|
2005-07-29 16:36:00 +02:00
|
|
|
#endif /* RTM_IFANNOUNCE */
|
2022-03-25 01:02:33 +01:00
|
|
|
if (ifp && if_is_up(ifp)) {
|
2007-08-21 18:15:39 +02:00
|
|
|
#if defined(__bsdi__)
|
|
|
|
if_kvm_get_mtu(ifp);
|
|
|
|
#else
|
|
|
|
if_get_mtu(ifp);
|
|
|
|
#endif /* __bsdi__ */
|
|
|
|
if_get_metric(ifp);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
|
2022-03-25 01:02:33 +01:00
|
|
|
if (ifp) {
|
2002-12-13 21:15:29 +01:00
|
|
|
#ifdef HAVE_NET_RT_IFLIST
|
2022-03-25 01:02:33 +01:00
|
|
|
ifp->stats = ifm->ifm_data;
|
2002-12-13 21:15:29 +01:00
|
|
|
#endif /* HAVE_NET_RT_IFLIST */
|
2022-03-25 01:02:33 +01:00
|
|
|
ifp->speed = ifm->ifm_data.ifi_baudrate / 1000000;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2022-03-25 01:02:33 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
|
|
|
zlog_debug("%s: interface %s index %d", __func__,
|
|
|
|
ifp->name, ifp->ifindex);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Address read from struct ifa_msghdr. */
|
|
|
|
static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr,
|
|
|
|
union sockunion *mask, union sockunion *brd,
|
2005-11-12 23:55:10 +01:00
|
|
|
char *ifname, short *ifnlen)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
caddr_t pnt, end;
|
2007-05-17 17:00:41 +02:00
|
|
|
union sockunion dst;
|
|
|
|
union sockunion gateway;
|
2018-12-05 14:51:25 +01:00
|
|
|
int maskbit;
|
2019-01-17 23:24:31 +01:00
|
|
|
char fbuf[64];
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
pnt = (caddr_t)(ifm + 1);
|
|
|
|
end = ((caddr_t)ifm) + ifm->ifam_msglen;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Be sure structure is cleared */
|
|
|
|
memset(mask, 0, sizeof(union sockunion));
|
|
|
|
memset(addr, 0, sizeof(union sockunion));
|
[zebra] fix some small compile errors, mark several functions static
2005-11-23 Paul Jakma <paul.jakma@sun.com>
* (general) fix some small compile errors, and mark several
functions as static.
* kernel_socket.c: (ifan_read) should be static.
fix missing brackets.
(ifm_read,ifam_read,rtm_read_mesg,kernel_read) Make static
(ifam_read_mesg) make static. fix incorrect variable name.
(rtm_read) make static. Fix call to rib_delete_ipv4 which
should be rib_delete_ipv6.
(routing_socket,kernel_init) should be static. Void argument
should be specified as such, not left incomplete.
* rt_netlink.c: rt.h should be included, contains prototypes of
exported functions.
(kernel_delete_ipv6_old) fix sign of index argument.
* rt_socket.c: Exact same as previous. Also, make various
functions static.
* rtread_getmsg.c: Include zserv.h, which prototypes
route_read. Make static.
* rtread_sysctl.c: zserv.h and rt.h should be included.
fix definition of route_read.
2005-11-23 14:02:08 +01:00
|
|
|
memset(brd, 0, sizeof(union sockunion));
|
2007-05-17 17:00:41 +02:00
|
|
|
memset(&dst, 0, sizeof(union sockunion));
|
|
|
|
memset(&gateway, 0, sizeof(union sockunion));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* We fetch each socket variable into sockunion. */
|
2018-12-05 14:51:25 +01:00
|
|
|
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:
|
2019-01-08 11:14:28 +01:00
|
|
|
pnt += rta_getattr(pnt, mask, sizeof(*mask));
|
2018-12-05 14:51:25 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL) {
|
2019-01-17 17:37:53 +01:00
|
|
|
switch (sockunion_family(addr)) {
|
2006-05-17 17:04:59 +02:00
|
|
|
case AF_INET:
|
|
|
|
case AF_INET6: {
|
2019-01-17 17:37:53 +01:00
|
|
|
int masklen =
|
|
|
|
(sockunion_family(addr) == AF_INET)
|
|
|
|
? ip_masklen(mask->sin.sin_addr)
|
|
|
|
: ip6_masklen(mask->sin6.sin6_addr);
|
2006-05-17 17:04:59 +02:00
|
|
|
zlog_debug(
|
2021-07-12 22:46:44 +02:00
|
|
|
"%s: ifindex %d, ifname %s, ifam_addrs {%s}, ifam_flags 0x%x, addr %pSU/%d broad %pSU dst %pSU gateway %pSU",
|
2015-05-23 10:08:41 +02:00
|
|
|
__func__, ifm->ifam_index,
|
2019-01-17 23:24:31 +01:00
|
|
|
(ifnlen ? ifname : "(nil)"),
|
|
|
|
rtatostr(ifm->ifam_addrs, fbuf, sizeof(fbuf)),
|
2021-07-12 22:46:44 +02:00
|
|
|
ifm->ifam_flags, addr, masklen, brd, &dst,
|
|
|
|
&gateway);
|
2006-05-17 17:04:59 +02:00
|
|
|
} break;
|
|
|
|
default:
|
2019-01-17 23:24:31 +01:00
|
|
|
zlog_debug("%s: ifindex %d, ifname %s, ifam_addrs {%s}",
|
2006-05-17 17:04:59 +02:00
|
|
|
__func__, ifm->ifam_index,
|
|
|
|
(ifnlen ? ifname : "(nil)"),
|
2019-01-17 23:24:31 +01:00
|
|
|
rtatostr(ifm->ifam_addrs, fbuf,
|
|
|
|
sizeof(fbuf)));
|
2006-05-17 17:04:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Assert read up end point matches to end point */
|
2018-12-05 14:51:25 +01:00
|
|
|
pnt = (caddr_t)ROUNDUP((size_t)pnt);
|
2019-01-08 13:37:22 +01:00
|
|
|
if (pnt != (caddr_t)ROUNDUP((size_t)end))
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("ifam_read() doesn't read all socket data");
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Interface's address information get. */
|
|
|
|
int ifam_read(struct ifa_msghdr *ifam)
|
|
|
|
{
|
2005-11-12 23:55:10 +01:00
|
|
|
struct interface *ifp = NULL;
|
2005-11-03 Paul Jakma <paul.jakma@sun.com>
* connected.{c,h}: Include memory.h
(connected_add_ipv4) Use MTYPE for ifc label.
(connected_add_ipv6) Also should accept label. Store it in ifp.
(connected_del_ipv4) Taking label as argument is pointless.
* rt_netlink.c: (netlink_interface_addr) update label usage
for connected_{add,delete} functions.
* if_ioctl.c: (if_getaddrs) NULL label for connected_add_ipv6.
* if_ioctl_solaris.c: (interface_list_ioctl) Pass LIFC_NOXMIT
so we also find out about NOXMIT interfaces like VNI.
Bit of hackery to turn interface names into the primary
interface name, later with routing socket messages we only
will about primary interfaces anyway, so we must normalise
the name.
(if_get_addr) take label as argument, so it can
be passed to connected_add.
If label is provided, then it is interface name to issue the
ioctl for address information on, not the ifp name.
(interface_list) List AF_UNSPEC too, just in case.
* if_proc.c: (ifaddr_proc_ipv6) label for connected_add_ipv6.
* interface.c: (if_addr_wakeup) Some very bogus code - sets
IFF_RUNNING - add comment.
(if_refresh)
(ip_address_install) Use MTYPE for ifc label.
* ioctl_solaris.c: (if_mangle_up) New function. Hackery to make
IFF_UP reflect whether any addresses are left on the
interface, as we get signalled for IFF_UP flags change on the
primary interface only. Logical interfaces dont generate
IFINFO, but we do get an RTM_DELADDR.
(if_get_flags) Call if_mangle_up before return.
* kernel_socket.c: (ifam_read) Fixup calls to
connected_{add,delete} to match above changes. Rename gate
variable to brd, less confusing.
Pass the interface name as a label, if it is not same name
as ifp->name.
2005-11-03 13:35:21 +01:00
|
|
|
union sockunion addr, mask, brd;
|
2020-09-21 02:21:41 +02:00
|
|
|
bool dest_same = false;
|
2023-11-21 14:08:29 +01:00
|
|
|
char ifname[IFNAMSIZ];
|
2005-11-12 23:55:10 +01:00
|
|
|
short ifnlen = 0;
|
2021-07-20 16:12:04 +02:00
|
|
|
bool isalias = false;
|
|
|
|
uint32_t flags = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2023-11-21 14:08:29 +01:00
|
|
|
ifname[0] = ifname[IFNAMSIZ - 1] = '\0';
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-12 23:55:10 +01:00
|
|
|
/* Allocate and read address information. */
|
|
|
|
ifam_read_mesg(ifam, &addr, &mask, &brd, ifname, &ifnlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-03-10 21:45:28 +01:00
|
|
|
if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) {
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
|
2018-08-16 22:10:32 +02:00
|
|
|
"%s: no interface for ifname %s, index %d", __func__,
|
2005-11-12 23:55:10 +01:00
|
|
|
ifname, ifam->ifam_index);
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2023-11-21 14:08:29 +01:00
|
|
|
if (ifnlen && strncmp(ifp->name, ifname, IFNAMSIZ))
|
2021-07-20 16:12:04 +02:00
|
|
|
isalias = true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mark the alias prefixes as secondary
|
|
|
|
*/
|
|
|
|
if (isalias)
|
|
|
|
SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2007-05-17 17:00:41 +02:00
|
|
|
/* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
|
|
|
|
field contains a broadcast address or a peer address, so we are
|
|
|
|
forced to
|
|
|
|
rely upon the interface type. */
|
|
|
|
if (if_is_pointopoint(ifp))
|
|
|
|
SET_FLAG(flags, ZEBRA_IFA_PEER);
|
2020-09-21 02:21:41 +02:00
|
|
|
else {
|
|
|
|
if (memcmp(&addr, &brd, sizeof(addr)) == 0)
|
|
|
|
dest_same = true;
|
|
|
|
}
|
2007-05-17 17:00:41 +02:00
|
|
|
|
2007-03-06 14:43:05 +01:00
|
|
|
#if 0
|
|
|
|
/* it might seem cute to grab the interface metric here, however
|
|
|
|
* we're processing an address update message, and so some systems
|
|
|
|
* (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
|
|
|
|
* in deliberately, as comment.
|
|
|
|
*/
|
2006-01-17 19:03:04 +01:00
|
|
|
ifp->metric = ifam->ifam_metric;
|
2007-03-06 14:43:05 +01:00
|
|
|
#endif
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Add connected address. */
|
|
|
|
switch (sockunion_family(&addr)) {
|
|
|
|
case AF_INET:
|
|
|
|
if (ifam->ifam_type == RTM_NEWADDR)
|
2007-05-17 17:00:41 +02:00
|
|
|
connected_add_ipv4(ifp, flags, &addr.sin.sin_addr,
|
2002-12-13 21:15:29 +01:00
|
|
|
ip_masklen(mask.sin.sin_addr),
|
2020-09-21 02:21:41 +02:00
|
|
|
dest_same ? NULL : &brd.sin.sin_addr,
|
zebra: set connected route metric based on the devaddr metric
MACVLAN devices are typically used for applications such as VRR/VRRP that
require a second MAC address (virtual). These devices have a corresponding
SVI/VLAN device -
root@TORC11:~# ip addr show vlan1002
39: vlan1002@bridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9152 qdisc noqueue master vrf1 state UP group default
link/ether 00:02:00:00:00:2e brd ff:ff:ff:ff:ff:ff
inet6 2001:aa:1::2/64 scope global
valid_lft forever preferred_lft forever
root@TORC11:~# ip addr show vlan1002-v0
40: vlan1002-v0@vlan1002: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9152 qdisc noqueue master vrf1 state UP group default
link/ether 00:00:5e:00:01:01 brd ff:ff:ff:ff:ff:ff
inet6 2001:aa:1::a/64 metric 1024 scope global
valid_lft forever preferred_lft forever
root@TORC11:~#
The macvlan device is used primarily for RX (VR-IP/VR-MAC). And TX is via
the SVI. To acheive that functionality the macvlan network's metric
is set to a higher value.
Zebra currently ignores the devaddr metric sent by the kernel and hardcodes
it to 0. This commit eliminates that hardcoding. If the devaddr metric
is available (METRIC_MAX) it is used for setting up the connected route
otherwise we fallback to the dev/interface metric.
Setting the macvlan metric to a higher value ensures that zebra will always
select the connected route on the SVI (and subsequently use it for next hop
resolution etc.) -
root@TORC11:~# vtysh -c "show ip route vrf vrf1 2001:aa:1::/64"
Routing entry for 2001:aa:1::/64
Known via "connected", distance 0, metric 1024, vrf vrf1
Last update 11:30:56 ago
* directly connected, vlan1002-v0
Routing entry for 2001:aa:1::/64
Known via "connected", distance 0, metric 0, vrf vrf1, best
Last update 11:30:56 ago
* directly connected, vlan1002
root@TORC11:~#
Ticket: CM-23511
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
2019-01-15 00:45:33 +01:00
|
|
|
(isalias ? ifname : NULL),
|
|
|
|
METRIC_MAX);
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2007-05-17 17:00:41 +02:00
|
|
|
connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr,
|
2002-12-13 21:15:29 +01:00
|
|
|
ip_masklen(mask.sin.sin_addr),
|
2020-09-21 02:21:41 +02:00
|
|
|
dest_same ? NULL
|
|
|
|
: &brd.sin.sin_addr);
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
/* Unset interface index from link-local address when IPv6 stack
|
|
|
|
is KAME. */
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6.sin6_addr)) {
|
2015-09-16 05:36:20 +02:00
|
|
|
SET_IN6_LINKLOCAL_IFINDEX(addr.sin6.sin6_addr, 0);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (ifam->ifam_type == RTM_NEWADDR)
|
2007-05-17 17:00:41 +02:00
|
|
|
connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
|
2018-04-15 16:57:19 +02:00
|
|
|
NULL,
|
2002-12-13 21:15:29 +01:00
|
|
|
ip6_masklen(mask.sin6.sin6_addr),
|
zebra: set connected route metric based on the devaddr metric
MACVLAN devices are typically used for applications such as VRR/VRRP that
require a second MAC address (virtual). These devices have a corresponding
SVI/VLAN device -
root@TORC11:~# ip addr show vlan1002
39: vlan1002@bridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9152 qdisc noqueue master vrf1 state UP group default
link/ether 00:02:00:00:00:2e brd ff:ff:ff:ff:ff:ff
inet6 2001:aa:1::2/64 scope global
valid_lft forever preferred_lft forever
root@TORC11:~# ip addr show vlan1002-v0
40: vlan1002-v0@vlan1002: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9152 qdisc noqueue master vrf1 state UP group default
link/ether 00:00:5e:00:01:01 brd ff:ff:ff:ff:ff:ff
inet6 2001:aa:1::a/64 metric 1024 scope global
valid_lft forever preferred_lft forever
root@TORC11:~#
The macvlan device is used primarily for RX (VR-IP/VR-MAC). And TX is via
the SVI. To acheive that functionality the macvlan network's metric
is set to a higher value.
Zebra currently ignores the devaddr metric sent by the kernel and hardcodes
it to 0. This commit eliminates that hardcoding. If the devaddr metric
is available (METRIC_MAX) it is used for setting up the connected route
otherwise we fallback to the dev/interface metric.
Setting the macvlan metric to a higher value ensures that zebra will always
select the connected route on the SVI (and subsequently use it for next hop
resolution etc.) -
root@TORC11:~# vtysh -c "show ip route vrf vrf1 2001:aa:1::/64"
Routing entry for 2001:aa:1::/64
Known via "connected", distance 0, metric 1024, vrf vrf1
Last update 11:30:56 ago
* directly connected, vlan1002-v0
Routing entry for 2001:aa:1::/64
Known via "connected", distance 0, metric 0, vrf vrf1, best
Last update 11:30:56 ago
* directly connected, vlan1002
root@TORC11:~#
Ticket: CM-23511
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
2019-01-15 00:45:33 +01:00
|
|
|
(isalias ? ifname : NULL),
|
|
|
|
METRIC_MAX);
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2018-04-15 16:57:19 +02:00
|
|
|
connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL,
|
2017-08-28 04:39:18 +02:00
|
|
|
ip6_masklen(mask.sin6.sin6_addr));
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Unsupported family silently ignore... */
|
|
|
|
break;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com>
* (general) More solaris PF_ROUTE hacks. The IFF_UP mangling
for solaris was incomplete on the PF_ROUTE side. fix it.
This changeset generally uglifies things. For some future
work I'd like to see the state changes seperated out from
the details of the code. Differences between systems might
then be slightly easier to implement without convoluted
hacks.
Changes should be specific to Solaris mostly, however
also tested on FreeBSD 6.
* if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP
interfaces, we'll hear about them when/if interface goes up
through NEWADDR.
Update flags explicitely at end of it to kick mangling.
* ioctl_solaris.c: (if_mangle_up) removed to interface.c, in
kind.
(lifreq_set_name) more convenient to take the string, than
the ifp.
(if_get_flags_direct) new convenience function, returns
the actual flags. Used during bootstrap in if_ioctl_solaris.c
to peek at flags of logical interfaces to see whether or
not to ignore them.
(if_get_flags) ENXIO means it's gone, poke out IFF_UP and
kick flags update.
(if_{un,}set_flags) flags argument should be 64bit.
* ioctl.{c,h}: flags argument should be 64bit.
* interface.h: Add a 'primary_state' flag to struct zebra_if on
SUNOS_5.
Export if_flags_update.
* interface.c: (if_flags_mangle) moved over in kind from
ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as
much as is possible. Also keep track of the actual IFF_UP
value for the primary interface, so we can know when the ifp
must be deleted.
(if_flags_update) Take a new interface flags value, apply it
to the interface, and take whatever actions are required due
to flag transitions.
(if_refresh) flag state change logic is moved out to
previous. Just call if_get_flags, which will end up using
previous to effect the update of flags.
(if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL
and NOXMIT are though.
* kernel_socket.c: (ifm_read) Down->Down transitions shouldn't
create ifp, for non-IFANNOUNCE systems.
Use if_flags_update to update flags.
flag transition logic is now handled automatically through
if_flags_update.
(ifam_read) Better to call if_refresh *after* adding
connected addresses, as connected count affects IFF_UP on
IFF_UP-mangled systems.
On Solaris, Up->Down due to DELADDR means we need to delete
the ifp - the IFINFO might already have been and gone.
* rt.h: include other dependent headers.
2006-01-25 05:31:40 +01:00
|
|
|
/* Check interface flag for implicit up of the interface. */
|
|
|
|
if_refresh(ifp);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Interface function for reading kernel routing table information. */
|
|
|
|
static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest,
|
|
|
|
union sockunion *mask, union sockunion *gate,
|
2005-11-12 23:55:10 +01:00
|
|
|
char *ifname, short *ifnlen)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
caddr_t pnt, end;
|
2018-12-05 14:51:25 +01:00
|
|
|
int maskbit;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Pnt points out socket data start point. */
|
|
|
|
pnt = (caddr_t)(rtm + 1);
|
|
|
|
end = ((caddr_t)rtm) + rtm->rtm_msglen;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* rt_msghdr version check. */
|
|
|
|
if (rtm->rtm_version != RTM_VERSION)
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_warn(EC_ZEBRA_RTM_VERSION_MISMATCH,
|
2021-07-12 22:46:44 +02:00
|
|
|
"Routing message version different %d should be %d.This may cause problem",
|
2018-08-16 22:10:32 +02:00
|
|
|
rtm->rtm_version, RTM_VERSION);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Be sure structure is cleared */
|
|
|
|
memset(dest, 0, sizeof(union sockunion));
|
|
|
|
memset(gate, 0, sizeof(union sockunion));
|
|
|
|
memset(mask, 0, sizeof(union sockunion));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* We fetch each socket variable into sockunion. */
|
2018-12-05 14:51:25 +01:00
|
|
|
/* 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:
|
2019-01-18 21:28:58 +01:00
|
|
|
pnt += rta_getattr(pnt, mask, sizeof(*mask));
|
2018-12-05 14:51:25 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* If there is netmask information set it's family same as
|
|
|
|
destination family*/
|
|
|
|
if (rtm->rtm_addrs & RTA_NETMASK)
|
|
|
|
mask->sa.sa_family = dest->sa.sa_family;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Assert read up to the end of pointer. */
|
|
|
|
if (pnt != end)
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("rtm_read() doesn't read all socket data.");
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return rtm->rtm_flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rtm_read(struct rt_msghdr *rtm)
|
|
|
|
{
|
|
|
|
int flags;
|
2020-10-15 19:41:30 +02:00
|
|
|
uint32_t zebra_flags;
|
2002-12-13 21:15:29 +01:00
|
|
|
union sockunion dest, mask, gate;
|
2023-11-21 14:08:29 +01:00
|
|
|
char ifname[IFNAMSIZ + 1];
|
2005-11-12 23:55:10 +01:00
|
|
|
short ifnlen = 0;
|
2017-08-28 01:30:16 +02:00
|
|
|
struct nexthop nh;
|
2018-12-12 16:18:13 +01:00
|
|
|
struct prefix p;
|
|
|
|
ifindex_t ifindex = 0;
|
|
|
|
afi_t afi;
|
2019-01-17 23:24:31 +01:00
|
|
|
char fbuf[64];
|
2022-02-27 20:11:13 +01:00
|
|
|
int32_t proto = ZEBRA_ROUTE_KERNEL;
|
|
|
|
uint8_t distance = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
zebra_flags = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Read destination and netmask and gateway from rtm message
|
|
|
|
structure. */
|
2005-11-12 23:55:10 +01:00
|
|
|
flags = rtm_read_mesg(rtm, &dest, &mask, &gate, ifname, &ifnlen);
|
2007-08-17 16:16:30 +02:00
|
|
|
if (!(flags & RTF_DONE))
|
|
|
|
return;
|
2007-08-13 18:03:06 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
2019-01-17 23:24:31 +01:00
|
|
|
zlog_debug("%s: got rtm of type %d (%s) addrs {%s}", __func__,
|
2007-08-13 18:03:06 +02:00
|
|
|
rtm->rtm_type,
|
2019-01-17 23:24:31 +01:00
|
|
|
lookup_msg(rtm_type_str, rtm->rtm_type, NULL),
|
|
|
|
rtatostr(rtm->rtm_addrs, fbuf, sizeof(fbuf)));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
|
|
|
|
if (flags & RTF_CLONED)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
#ifdef RTF_WASCLONED /*freebsd*/
|
|
|
|
if (flags & RTF_WASCLONED)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2016-01-15 16:36:29 +01:00
|
|
|
if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE)
|
|
|
|
&& !(flags & RTF_UP))
|
2002-12-13 21:15:29 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* This is connected route. */
|
|
|
|
if (!(flags & RTF_GATEWAY))
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-02-27 20:11:13 +01:00
|
|
|
if (flags & RTF_PROTO1) {
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
|
2022-02-27 20:11:13 +01:00
|
|
|
proto = ZEBRA_ROUTE_STATIC;
|
|
|
|
distance = 255;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2010-02-05 04:31:56 +01:00
|
|
|
memset(&nh, 0, sizeof(nh));
|
2018-02-08 15:12:12 +01:00
|
|
|
|
|
|
|
nh.vrf_id = VRF_DEFAULT;
|
2003-05-25 21:21:25 +02:00
|
|
|
/* This is a reject or blackhole route */
|
2010-02-05 04:31:56 +01:00
|
|
|
if (flags & RTF_REJECT) {
|
|
|
|
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
|
|
|
nh.bh_type = BLACKHOLE_REJECT;
|
|
|
|
} else if (flags & RTF_BLACKHOLE) {
|
|
|
|
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
|
|
|
nh.bh_type = BLACKHOLE_NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-12-12 16:15:27 +01:00
|
|
|
/*
|
|
|
|
* Ignore our own messages.
|
|
|
|
*/
|
|
|
|
if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (dest.sa.sa_family == AF_INET) {
|
2018-12-12 16:18:13 +01:00
|
|
|
afi = AFI_IP;
|
2002-12-13 21:15:29 +01:00
|
|
|
p.family = AF_INET;
|
2016-08-24 07:39:08 +02:00
|
|
|
p.u.prefix4 = dest.sin.sin_addr;
|
2002-12-13 21:15:29 +01:00
|
|
|
if (flags & RTF_HOST)
|
2021-07-01 16:42:03 +02:00
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
|
|
|
p.prefixlen = ip_masklen(mask.sin.sin_addr);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2010-02-05 04:31:56 +01:00
|
|
|
if (!nh.type) {
|
|
|
|
nh.type = NEXTHOP_TYPE_IPV4;
|
|
|
|
nh.gate.ipv4 = gate.sin.sin_addr;
|
|
|
|
}
|
2018-12-12 16:18:13 +01:00
|
|
|
} else if (dest.sa.sa_family == AF_INET6) {
|
|
|
|
afi = AFI_IP6;
|
2002-12-13 21:15:29 +01:00
|
|
|
p.family = AF_INET6;
|
2016-08-24 07:39:08 +02:00
|
|
|
p.u.prefix6 = dest.sin6.sin6_addr;
|
2002-12-13 21:15:29 +01:00
|
|
|
if (flags & RTF_HOST)
|
2021-07-01 16:39:04 +02:00
|
|
|
p.prefixlen = IPV6_MAX_BITLEN;
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
|
|
|
p.prefixlen = ip6_masklen(mask.sin6.sin6_addr);
|
|
|
|
|
|
|
|
#ifdef KAME
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(&gate.sin6.sin6_addr)) {
|
|
|
|
ifindex = IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr);
|
|
|
|
SET_IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr, 0);
|
|
|
|
}
|
|
|
|
#endif /* KAME */
|
|
|
|
|
2010-02-05 04:31:56 +01:00
|
|
|
if (!nh.type) {
|
|
|
|
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
|
|
|
|
: NEXTHOP_TYPE_IPV6;
|
|
|
|
nh.gate.ipv6 = gate.sin6.sin6_addr;
|
|
|
|
nh.ifindex = ifindex;
|
|
|
|
}
|
2018-12-12 16:18:13 +01:00
|
|
|
} else
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-12-12 16:18:13 +01:00
|
|
|
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
|
|
|
|| rtm->rtm_type == RTM_CHANGE)
|
2022-02-27 20:11:13 +01:00
|
|
|
rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags,
|
2023-08-22 13:27:59 +02:00
|
|
|
&p, NULL, &nh, 0, rt_table_main_id, 0, 0, distance, 0,
|
2022-02-27 20:11:13 +01:00
|
|
|
false);
|
2018-12-12 16:18:13 +01:00
|
|
|
else
|
2022-02-27 20:11:13 +01:00
|
|
|
rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0,
|
2023-08-22 13:27:59 +02:00
|
|
|
zebra_flags, &p, NULL, &nh, 0, rt_table_main_id, 0,
|
2022-02-27 20:11:13 +01:00
|
|
|
distance, true);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Interface function for the kernel routing table updates. Support
|
[zebra] fix some small compile errors, mark several functions static
2005-11-23 Paul Jakma <paul.jakma@sun.com>
* (general) fix some small compile errors, and mark several
functions as static.
* kernel_socket.c: (ifan_read) should be static.
fix missing brackets.
(ifm_read,ifam_read,rtm_read_mesg,kernel_read) Make static
(ifam_read_mesg) make static. fix incorrect variable name.
(rtm_read) make static. Fix call to rib_delete_ipv4 which
should be rib_delete_ipv6.
(routing_socket,kernel_init) should be static. Void argument
should be specified as such, not left incomplete.
* rt_netlink.c: rt.h should be included, contains prototypes of
exported functions.
(kernel_delete_ipv6_old) fix sign of index argument.
* rt_socket.c: Exact same as previous. Also, make various
functions static.
* rtread_getmsg.c: Include zserv.h, which prototypes
route_read. Make static.
* rtread_sysctl.c: zserv.h and rt.h should be included.
fix definition of route_read.
2005-11-23 14:02:08 +01:00
|
|
|
* for RTM_CHANGE will be needed.
|
|
|
|
* Exported only for rt_socket.c
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
|
|
|
union sockunion *gate, union sockunion *mpls, unsigned int index,
|
2010-02-05 04:31:56 +01:00
|
|
|
enum blackhole_type bh_type, int metric)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
caddr_t pnt;
|
|
|
|
struct interface *ifp;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Sequencial number of routing message. */
|
|
|
|
static int msg_seq = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Struct of rt_msghdr and buffer for storing socket's data. */
|
|
|
|
struct {
|
|
|
|
struct rt_msghdr rtm;
|
|
|
|
char buf[512];
|
|
|
|
} msg;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-11-14 20:45:30 +01:00
|
|
|
if (dplane_routing_sock < 0)
|
2002-12-13 21:15:29 +01:00
|
|
|
return ZEBRA_ERR_EPERM;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Clear and set rt_msghdr values */
|
2022-05-11 12:16:44 +02:00
|
|
|
memset(&msg, 0, sizeof(msg));
|
2002-12-13 21:15:29 +01:00
|
|
|
msg.rtm.rtm_version = RTM_VERSION;
|
|
|
|
msg.rtm.rtm_type = message;
|
|
|
|
msg.rtm.rtm_seq = msg_seq++;
|
|
|
|
msg.rtm.rtm_addrs = RTA_DST;
|
|
|
|
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
|
|
|
msg.rtm.rtm_flags = RTF_UP;
|
2016-09-22 04:59:57 +02:00
|
|
|
#ifdef __OpenBSD__
|
2016-06-02 13:28:15 +02:00
|
|
|
msg.rtm.rtm_flags |= RTF_MPATH;
|
|
|
|
msg.rtm.rtm_fmask = RTF_MPLS;
|
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
msg.rtm.rtm_index = index;
|
|
|
|
|
|
|
|
if (metric != 0) {
|
|
|
|
msg.rtm.rtm_rmx.rmx_hopcount = metric;
|
|
|
|
msg.rtm.rtm_inits |= RTV_HOPCOUNT;
|
|
|
|
}
|
|
|
|
|
2017-03-10 21:45:28 +01:00
|
|
|
ifp = if_lookup_by_index(index, VRF_DEFAULT);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-01-15 16:36:29 +01:00
|
|
|
if (gate && (message == RTM_ADD || message == RTM_CHANGE))
|
2002-12-13 21:15:29 +01:00
|
|
|
msg.rtm.rtm_flags |= RTF_GATEWAY;
|
|
|
|
|
2009-12-03 19:43:11 +01:00
|
|
|
/* When RTF_CLONING is unavailable on BSD, should we set some
|
|
|
|
* other flag instead?
|
|
|
|
*/
|
|
|
|
#ifdef RTF_CLONING
|
2016-01-15 16:36:29 +01:00
|
|
|
if (!gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp
|
2002-12-13 21:15:29 +01:00
|
|
|
&& (ifp->flags & IFF_POINTOPOINT) == 0)
|
|
|
|
msg.rtm.rtm_flags |= RTF_CLONING;
|
2009-12-03 19:43:11 +01:00
|
|
|
#endif /* RTF_CLONING */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* If no protocol specific gateway is specified, use link
|
|
|
|
address for gateway. */
|
|
|
|
if (!gate) {
|
|
|
|
if (!ifp) {
|
2007-08-13 18:03:06 +02:00
|
|
|
char dest_buf[INET_ADDRSTRLEN] = "NULL",
|
|
|
|
mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
|
|
|
|
if (dest)
|
|
|
|
inet_ntop(AF_INET, &dest->sin.sin_addr,
|
|
|
|
dest_buf, INET_ADDRSTRLEN);
|
|
|
|
if (mask)
|
|
|
|
inet_ntop(AF_INET, &mask->sin.sin_addr,
|
|
|
|
mask_buf, INET_ADDRSTRLEN);
|
2018-08-16 22:10:32 +02:00
|
|
|
flog_warn(
|
2018-09-13 21:21:05 +02:00
|
|
|
EC_ZEBRA_RTM_NO_GATEWAY,
|
2007-08-13 18:03:06 +02:00
|
|
|
"%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
|
|
|
|
__func__, dest_buf, mask_buf, index);
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2016-01-15 16:36:33 +01:00
|
|
|
gate = (union sockunion *)&((struct zebra_if *)ifp->info)->sdl;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (mask)
|
|
|
|
msg.rtm.rtm_addrs |= RTA_NETMASK;
|
2016-01-15 16:36:29 +01:00
|
|
|
else if (message == RTM_ADD || message == RTM_CHANGE)
|
2002-12-13 21:15:29 +01:00
|
|
|
msg.rtm.rtm_flags |= RTF_HOST;
|
|
|
|
|
2016-09-22 04:59:57 +02:00
|
|
|
#ifdef __OpenBSD__
|
2016-06-02 13:28:15 +02:00
|
|
|
if (mpls) {
|
|
|
|
msg.rtm.rtm_addrs |= RTA_SRC;
|
|
|
|
msg.rtm.rtm_flags |= RTF_MPLS;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-06-02 13:28:15 +02:00
|
|
|
if (mpls->smpls.smpls_label
|
2018-02-01 00:24:06 +01:00
|
|
|
!= htonl(MPLS_LABEL_IMPLICIT_NULL << MPLS_LABEL_OFFSET))
|
2016-06-02 13:28:15 +02:00
|
|
|
msg.rtm.rtm_mpls = MPLS_OP_PUSH;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Tagging route with flags */
|
|
|
|
msg.rtm.rtm_flags |= (RTF_PROTO1);
|
|
|
|
|
2010-02-05 04:31:56 +01:00
|
|
|
switch (bh_type) {
|
|
|
|
case BLACKHOLE_UNSPEC:
|
|
|
|
break;
|
|
|
|
case BLACKHOLE_REJECT:
|
2003-05-25 21:21:25 +02:00
|
|
|
msg.rtm.rtm_flags |= RTF_REJECT;
|
2010-02-05 04:31:56 +01:00
|
|
|
break;
|
2023-01-30 16:05:58 +01:00
|
|
|
case BLACKHOLE_NULL:
|
|
|
|
case BLACKHOLE_ADMINPROHIB:
|
2010-02-05 04:31:56 +01:00
|
|
|
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
|
|
|
break;
|
|
|
|
}
|
2003-05-25 21:21:25 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#define SOCKADDRSET(X, R) \
|
|
|
|
if (msg.rtm.rtm_addrs & (R)) { \
|
2005-11-12 23:55:10 +01:00
|
|
|
int len = SAROUNDUP(X); \
|
2002-12-13 21:15:29 +01:00
|
|
|
memcpy(pnt, (caddr_t)(X), len); \
|
|
|
|
pnt += len; \
|
|
|
|
}
|
|
|
|
|
|
|
|
pnt = (caddr_t)msg.buf;
|
|
|
|
|
|
|
|
/* Write each socket data into rtm message buffer */
|
|
|
|
SOCKADDRSET(dest, RTA_DST);
|
|
|
|
SOCKADDRSET(gate, RTA_GATEWAY);
|
|
|
|
SOCKADDRSET(mask, RTA_NETMASK);
|
2016-09-22 04:59:57 +02:00
|
|
|
#ifdef __OpenBSD__
|
2016-06-02 13:28:15 +02:00
|
|
|
SOCKADDRSET(mpls, RTA_SRC);
|
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
msg.rtm.rtm_msglen = pnt - (caddr_t)&msg;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-11-14 20:45:30 +01:00
|
|
|
ret = write(dplane_routing_sock, &msg, msg.rtm.rtm_msglen);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (ret != msg.rtm.rtm_msglen) {
|
|
|
|
if (errno == EEXIST)
|
|
|
|
return ZEBRA_ERR_RTEXIST;
|
|
|
|
if (errno == ENETUNREACH)
|
|
|
|
return ZEBRA_ERR_RTUNREACH;
|
2007-08-13 18:03:06 +02:00
|
|
|
if (errno == ESRCH)
|
|
|
|
return ZEBRA_ERR_RTNOEXIST;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s: write : %s (%d)", __func__,
|
2018-08-16 22:10:32 +02:00
|
|
|
safe_strerror(errno), errno);
|
2007-08-13 18:03:06 +02:00
|
|
|
return ZEBRA_ERR_KERNEL;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2007-08-13 18:03:06 +02:00
|
|
|
return ZEBRA_ERR_NOERROR;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2023-03-07 20:22:48 +01:00
|
|
|
#include "frrevent.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "zebra/zserv.h"
|
|
|
|
|
|
|
|
/* For debug purpose. */
|
|
|
|
static void rtmsg_debug(struct rt_msghdr *rtm)
|
|
|
|
{
|
2019-01-17 23:24:31 +01:00
|
|
|
char fbuf[64];
|
|
|
|
|
2017-06-21 01:56:50 +02:00
|
|
|
zlog_debug("Kernel: Len: %d Type: %s", rtm->rtm_msglen,
|
|
|
|
lookup_msg(rtm_type_str, rtm->rtm_type, NULL));
|
2002-12-13 21:15:29 +01:00
|
|
|
rtm_flag_dump(rtm->rtm_flags);
|
2004-12-07 22:12:56 +01:00
|
|
|
zlog_debug("Kernel: message seq %d", rtm->rtm_seq);
|
2019-01-17 23:24:31 +01:00
|
|
|
zlog_debug("Kernel: pid %lld, rtm_addrs {%s}", (long long)rtm->rtm_pid,
|
|
|
|
rtatostr(rtm->rtm_addrs, fbuf, sizeof(fbuf)));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This is pretty gross, better suggestions welcome -- mhandler */
|
|
|
|
#ifndef RTAX_MAX
|
|
|
|
#ifdef RTA_NUMBITS
|
|
|
|
#define RTAX_MAX RTA_NUMBITS
|
|
|
|
#else
|
|
|
|
#define RTAX_MAX 8
|
|
|
|
#endif /* RTA_NUMBITS */
|
|
|
|
#endif /* RTAX_MAX */
|
|
|
|
|
|
|
|
/* Kernel routing table and interface updates via routing socket. */
|
2022-03-01 22:18:12 +01:00
|
|
|
static void kernel_read(struct event *thread)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
int sock;
|
|
|
|
int nbytes;
|
|
|
|
struct rt_msghdr *rtm;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-01-06 01:36:51 +01:00
|
|
|
/*
|
|
|
|
* This must be big enough for any message the kernel might send.
|
2004-01-08 16:44:29 +01:00
|
|
|
* Rather than determining how many sockaddrs of what size might be
|
|
|
|
* in each particular message, just use RTAX_MAX of sockaddr_storage
|
|
|
|
* for each. Note that the sockaddrs must be after each message
|
|
|
|
* definition, or rather after whichever happens to be the largest,
|
|
|
|
* since the buffer needs to be big enough for a message and the
|
|
|
|
* sockaddrs together.
|
2004-01-06 01:36:51 +01:00
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
union {
|
|
|
|
/* Routing information. */
|
|
|
|
struct {
|
|
|
|
struct rt_msghdr rtm;
|
2004-01-08 16:44:29 +01:00
|
|
|
struct sockaddr_storage addr[RTAX_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
} r;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Interface information. */
|
|
|
|
struct {
|
|
|
|
struct if_msghdr ifm;
|
2004-01-08 16:44:29 +01:00
|
|
|
struct sockaddr_storage addr[RTAX_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
} im;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Interface address information. */
|
|
|
|
struct {
|
|
|
|
struct ifa_msghdr ifa;
|
2004-01-08 16:44:29 +01:00
|
|
|
struct sockaddr_storage addr[RTAX_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
} ia;
|
|
|
|
|
|
|
|
#ifdef RTM_IFANNOUNCE
|
|
|
|
/* Interface arrival/departure */
|
|
|
|
struct {
|
|
|
|
struct if_announcemsghdr ifan;
|
2004-01-08 16:44:29 +01:00
|
|
|
struct sockaddr_storage addr[RTAX_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
} ian;
|
|
|
|
#endif /* RTM_IFANNOUNCE */
|
|
|
|
|
|
|
|
} buf;
|
|
|
|
|
|
|
|
/* Fetch routing socket. */
|
2022-12-25 16:26:52 +01:00
|
|
|
sock = EVENT_FD(thread);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-03-08 20:43:26 +01:00
|
|
|
nbytes = read(sock, &buf, sizeof(buf));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-10-04 21:32:26 +02:00
|
|
|
if (nbytes < 0) {
|
|
|
|
if (errno == ENOBUFS) {
|
2022-07-01 15:00:25 +02:00
|
|
|
#ifdef __FreeBSD__
|
|
|
|
/*
|
|
|
|
* ENOBUFS indicates a temporary resource
|
|
|
|
* shortage and is not harmful for consistency of
|
|
|
|
* reading the routing socket. Ignore it.
|
|
|
|
*/
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(zrouter.master, kernel_read, NULL, sock,
|
|
|
|
NULL);
|
2022-07-01 15:00:25 +02:00
|
|
|
return;
|
|
|
|
#else
|
2020-10-04 21:32:26 +02:00
|
|
|
flog_err(EC_ZEBRA_RECVMSG_OVERRUN,
|
|
|
|
"routing socket overrun: %s",
|
|
|
|
safe_strerror(errno));
|
|
|
|
/*
|
|
|
|
* In this case we are screwed.
|
|
|
|
* There is no good way to
|
|
|
|
* recover zebra at this point.
|
|
|
|
*/
|
|
|
|
exit(-1);
|
2022-07-01 15:00:25 +02:00
|
|
|
#endif
|
2020-10-04 21:32:26 +02:00
|
|
|
}
|
|
|
|
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "routing socket error: %s",
|
2018-08-16 22:10:32 +02:00
|
|
|
safe_strerror(errno));
|
2022-02-23 01:04:25 +01:00
|
|
|
return;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-10-04 21:32:26 +02:00
|
|
|
if (nbytes == 0)
|
2022-02-23 01:04:25 +01:00
|
|
|
return;
|
2020-10-04 21:32:26 +02:00
|
|
|
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(zrouter.master, kernel_read, NULL, sock, NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2003-05-25 23:04:54 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
|
|
|
rtmsg_debug(&buf.r.rtm);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
rtm = &buf.r.rtm;
|
|
|
|
|
2004-01-08 16:44:29 +01:00
|
|
|
/*
|
|
|
|
* Ensure that we didn't drop any data, so that processing routines
|
|
|
|
* can assume they have the whole message.
|
|
|
|
*/
|
2004-01-05 18:20:59 +01:00
|
|
|
if (rtm->rtm_msglen != nbytes) {
|
2022-09-22 20:34:40 +02:00
|
|
|
zlog_debug("%s: rtm->rtm_msglen %d, nbytes %d, type %d",
|
|
|
|
__func__, rtm->rtm_msglen, nbytes, rtm->rtm_type);
|
2022-02-23 01:04:25 +01:00
|
|
|
return;
|
2004-01-05 18:20:59 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
switch (rtm->rtm_type) {
|
|
|
|
case RTM_ADD:
|
|
|
|
case RTM_DELETE:
|
2005-09-12 18:58:52 +02:00
|
|
|
case RTM_CHANGE:
|
2002-12-13 21:15:29 +01:00
|
|
|
rtm_read(rtm);
|
|
|
|
break;
|
|
|
|
case RTM_IFINFO:
|
|
|
|
ifm_read(&buf.im.ifm);
|
|
|
|
break;
|
|
|
|
case RTM_NEWADDR:
|
|
|
|
case RTM_DELADDR:
|
|
|
|
ifam_read(&buf.ia.ifa);
|
|
|
|
break;
|
|
|
|
#ifdef RTM_IFANNOUNCE
|
|
|
|
case RTM_IFANNOUNCE:
|
|
|
|
ifan_read(&buf.ian.ifan);
|
|
|
|
break;
|
|
|
|
#endif /* RTM_IFANNOUNCE */
|
|
|
|
default:
|
2003-05-25 23:04:54 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
2022-03-24 23:31:23 +01:00
|
|
|
zlog_debug(
|
|
|
|
"Unprocessed RTM_type: %s(%d)",
|
|
|
|
lookup_msg(rtm_type_str, rtm->rtm_type, NULL),
|
|
|
|
rtm->rtm_type);
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make routing socket. */
|
2016-02-01 19:55:42 +01:00
|
|
|
static void routing_socket(struct zebra_ns *zns)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2022-02-26 21:40:15 +01:00
|
|
|
uint32_t default_rcvbuf;
|
|
|
|
socklen_t optlen;
|
|
|
|
|
2019-08-13 15:47:23 +02:00
|
|
|
frr_with_privs(&zserv_privs) {
|
2018-08-10 18:46:07 +02:00
|
|
|
routing_sock = ns_socket(AF_ROUTE, SOCK_RAW, 0, zns->ns_id);
|
2018-11-14 20:45:30 +01:00
|
|
|
|
|
|
|
dplane_routing_sock =
|
|
|
|
ns_socket(AF_ROUTE, SOCK_RAW, 0, zns->ns_id);
|
2018-08-10 18:46:07 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (routing_sock < 0) {
|
2018-09-13 21:38:57 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "Can't init kernel routing socket");
|
2002-12-13 21:15:29 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-11-14 20:45:30 +01:00
|
|
|
if (dplane_routing_sock < 0) {
|
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
|
|
|
"Can't init kernel dataplane routing socket");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-04 21:32:26 +02:00
|
|
|
#ifdef SO_RERROR
|
|
|
|
/* Allow reporting of route(4) buffer overflow errors */
|
|
|
|
int n = 1;
|
2020-10-05 09:10:42 +02:00
|
|
|
|
2020-10-04 21:32:26 +02:00
|
|
|
if (setsockopt(routing_sock, SOL_SOCKET, SO_RERROR, &n, sizeof(n)) < 0)
|
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
|
|
|
"Can't set SO_RERROR on routing socket");
|
|
|
|
#endif
|
|
|
|
|
2005-01-05 09:30:35 +01:00
|
|
|
/* XXX: Socket should be NONBLOCK, however as we currently
|
|
|
|
* discard failed writes, this will lead to inconsistencies.
|
|
|
|
* For now, socket must be blocking.
|
|
|
|
*/
|
|
|
|
/*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-02-26 21:40:15 +01:00
|
|
|
/*
|
|
|
|
* Attempt to set a more useful receive buffer size
|
|
|
|
*/
|
|
|
|
optlen = sizeof(default_rcvbuf);
|
|
|
|
if (getsockopt(routing_sock, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf,
|
|
|
|
&optlen) == -1)
|
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
|
|
|
"routing_sock sockopt SOL_SOCKET SO_RCVBUF");
|
|
|
|
else {
|
|
|
|
for (; rcvbufsize > default_rcvbuf &&
|
|
|
|
setsockopt(routing_sock, SOL_SOCKET, SO_RCVBUF,
|
|
|
|
&rcvbufsize, sizeof(rcvbufsize)) == -1 &&
|
|
|
|
errno == ENOBUFS;
|
|
|
|
rcvbufsize /= 2)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* kernel_read needs rewrite. */
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(zrouter.master, kernel_read, NULL, routing_sock, NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2023-04-27 05:02:09 +02:00
|
|
|
void interface_list_second(struct zebra_ns *zns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void interface_list_tunneldump(struct zebra_ns *zns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Exported interface function. This function simply calls
|
|
|
|
routing_socket (). */
|
2016-02-01 19:55:42 +01:00
|
|
|
void kernel_init(struct zebra_ns *zns)
|
2014-07-03 12:23:09 +02:00
|
|
|
{
|
2016-02-01 19:55:42 +01:00
|
|
|
routing_socket(zns);
|
2014-07-03 12:23:09 +02:00
|
|
|
}
|
|
|
|
|
2018-11-12 21:57:03 +01:00
|
|
|
void kernel_terminate(struct zebra_ns *zns, bool complete)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2014-07-03 12:23:09 +02:00
|
|
|
return;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-26 19:49:15 +02:00
|
|
|
|
2022-02-10 19:29:59 +01:00
|
|
|
/*
|
|
|
|
* Global init for platform-/OS-specific things
|
|
|
|
*/
|
|
|
|
void kernel_router_init(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Global deinit for platform-/OS-specific things
|
|
|
|
*/
|
|
|
|
void kernel_router_terminate(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-07-14 19:06:41 +02:00
|
|
|
/*
|
|
|
|
* Called by the dplane pthread to read incoming OS messages and dispatch them.
|
|
|
|
*/
|
|
|
|
int kernel_dplane_read(struct zebra_dplane_info *info)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-20 23:24:17 +01:00
|
|
|
void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
|
2020-07-15 15:11:21 +02:00
|
|
|
{
|
2020-07-31 00:15:51 +02:00
|
|
|
struct zebra_dplane_ctx *ctx;
|
2023-01-20 23:24:17 +01:00
|
|
|
struct dplane_ctx_list_head handled_list;
|
2022-06-29 13:43:50 +02:00
|
|
|
enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
2020-07-15 15:11:21 +02:00
|
|
|
|
2023-01-20 23:24:17 +01:00
|
|
|
dplane_ctx_q_init(&handled_list);
|
2020-07-31 00:15:51 +02:00
|
|
|
|
|
|
|
while (true) {
|
|
|
|
ctx = dplane_ctx_dequeue(ctx_list);
|
|
|
|
if (ctx == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A previous provider plugin may have asked to skip the
|
|
|
|
* kernel update.
|
|
|
|
*/
|
|
|
|
if (dplane_ctx_is_skip_kernel(ctx)) {
|
|
|
|
res = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
|
|
|
goto skip_one;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (dplane_ctx_get_op(ctx)) {
|
|
|
|
|
|
|
|
case DPLANE_OP_ROUTE_INSTALL:
|
|
|
|
case DPLANE_OP_ROUTE_UPDATE:
|
|
|
|
case DPLANE_OP_ROUTE_DELETE:
|
|
|
|
res = kernel_route_update(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_NH_INSTALL:
|
|
|
|
case DPLANE_OP_NH_UPDATE:
|
|
|
|
case DPLANE_OP_NH_DELETE:
|
|
|
|
res = kernel_nexthop_update(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_LSP_INSTALL:
|
|
|
|
case DPLANE_OP_LSP_UPDATE:
|
|
|
|
case DPLANE_OP_LSP_DELETE:
|
|
|
|
res = kernel_lsp_update(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_PW_INSTALL:
|
|
|
|
case DPLANE_OP_PW_UNINSTALL:
|
|
|
|
res = kernel_pw_update(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_ADDR_INSTALL:
|
|
|
|
case DPLANE_OP_ADDR_UNINSTALL:
|
|
|
|
res = kernel_address_update_ctx(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_MAC_INSTALL:
|
|
|
|
case DPLANE_OP_MAC_DELETE:
|
|
|
|
res = kernel_mac_update_ctx(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_NEIGH_INSTALL:
|
|
|
|
case DPLANE_OP_NEIGH_UPDATE:
|
|
|
|
case DPLANE_OP_NEIGH_DELETE:
|
|
|
|
case DPLANE_OP_VTEP_ADD:
|
|
|
|
case DPLANE_OP_VTEP_DELETE:
|
2020-08-06 13:07:01 +02:00
|
|
|
case DPLANE_OP_NEIGH_DISCOVER:
|
2020-07-31 00:15:51 +02:00
|
|
|
res = kernel_neigh_update_ctx(ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DPLANE_OP_RULE_ADD:
|
|
|
|
case DPLANE_OP_RULE_DELETE:
|
|
|
|
case DPLANE_OP_RULE_UPDATE:
|
|
|
|
res = kernel_pbr_rule_update(ctx);
|
|
|
|
break;
|
|
|
|
|
2022-01-26 07:10:43 +01:00
|
|
|
case DPLANE_OP_INTF_INSTALL:
|
|
|
|
case DPLANE_OP_INTF_UPDATE:
|
|
|
|
case DPLANE_OP_INTF_DELETE:
|
|
|
|
res = kernel_intf_update(ctx);
|
|
|
|
break;
|
|
|
|
|
2022-09-06 09:10:11 +02:00
|
|
|
case DPLANE_OP_TC_QDISC_INSTALL:
|
|
|
|
case DPLANE_OP_TC_QDISC_UNINSTALL:
|
|
|
|
case DPLANE_OP_TC_CLASS_ADD:
|
|
|
|
case DPLANE_OP_TC_CLASS_DELETE:
|
|
|
|
case DPLANE_OP_TC_CLASS_UPDATE:
|
|
|
|
case DPLANE_OP_TC_FILTER_ADD:
|
|
|
|
case DPLANE_OP_TC_FILTER_DELETE:
|
|
|
|
case DPLANE_OP_TC_FILTER_UPDATE:
|
2022-08-10 17:24:49 +02:00
|
|
|
res = kernel_tc_update(ctx);
|
|
|
|
break;
|
|
|
|
|
2020-07-31 00:15:51 +02:00
|
|
|
/* Ignore 'notifications' - no-op */
|
|
|
|
case DPLANE_OP_SYS_ROUTE_ADD:
|
|
|
|
case DPLANE_OP_SYS_ROUTE_DELETE:
|
|
|
|
case DPLANE_OP_ROUTE_NOTIFY:
|
|
|
|
case DPLANE_OP_LSP_NOTIFY:
|
|
|
|
res = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
|
|
|
break;
|
|
|
|
|
2022-06-29 13:43:50 +02:00
|
|
|
case DPLANE_OP_INTF_NETCONFIG:
|
|
|
|
res = kernel_intf_netconf_update(ctx);
|
2020-07-31 00:15:51 +02:00
|
|
|
break;
|
2022-06-29 13:43:50 +02:00
|
|
|
|
|
|
|
case DPLANE_OP_NONE:
|
|
|
|
case DPLANE_OP_BR_PORT_UPDATE:
|
|
|
|
case DPLANE_OP_IPTABLE_ADD:
|
|
|
|
case DPLANE_OP_IPTABLE_DELETE:
|
|
|
|
case DPLANE_OP_IPSET_ADD:
|
|
|
|
case DPLANE_OP_IPSET_DELETE:
|
|
|
|
case DPLANE_OP_IPSET_ENTRY_ADD:
|
|
|
|
case DPLANE_OP_IPSET_ENTRY_DELETE:
|
|
|
|
case DPLANE_OP_NEIGH_IP_INSTALL:
|
|
|
|
case DPLANE_OP_NEIGH_IP_DELETE:
|
|
|
|
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
|
|
|
case DPLANE_OP_GRE_SET:
|
|
|
|
case DPLANE_OP_INTF_ADDR_ADD:
|
|
|
|
case DPLANE_OP_INTF_ADDR_DEL:
|
2023-04-20 14:51:42 +02:00
|
|
|
case DPLANE_OP_STARTUP_STAGE:
|
2022-11-03 16:23:51 +01:00
|
|
|
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
2022-06-29 13:43:50 +02:00
|
|
|
zlog_err("Unhandled dplane data for %s",
|
|
|
|
dplane_op2str(dplane_ctx_get_op(ctx)));
|
|
|
|
res = ZEBRA_DPLANE_REQUEST_FAILURE;
|
2020-07-31 00:15:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
skip_one:
|
|
|
|
dplane_ctx_set_status(ctx, res);
|
|
|
|
|
|
|
|
dplane_ctx_enqueue_tail(&handled_list, ctx);
|
|
|
|
}
|
|
|
|
|
2023-01-20 23:24:17 +01:00
|
|
|
dplane_ctx_q_init(ctx_list);
|
2020-07-31 00:15:51 +02:00
|
|
|
dplane_ctx_list_append(ctx_list, &handled_list);
|
2020-07-15 15:11:21 +02:00
|
|
|
}
|
|
|
|
|
2017-07-26 19:49:15 +02:00
|
|
|
#endif /* !HAVE_NETLINK */
|