2002-12-13 21:15:29 +01:00
|
|
|
/*
|
|
|
|
* Kernel routing table updates by routing socket.
|
|
|
|
* Copyright (C) 1997, 98 Kunihiro Ishiguro
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
2017-05-13 10:25:29 +02:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2002-12-13 21:15:29 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
2017-07-26 19:49:15 +02:00
|
|
|
|
|
|
|
#ifndef HAVE_NETLINK
|
|
|
|
|
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 "log.h"
|
2003-06-04 15:59:38 +02:00
|
|
|
#include "privs.h"
|
2017-05-15 07:38:26 +02:00
|
|
|
#include "vxlan.h"
|
2018-06-14 16:38:40 +02:00
|
|
|
#include "lib_errors.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "zebra/debug.h"
|
|
|
|
#include "zebra/rib.h"
|
[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
|
|
|
#include "zebra/rt.h"
|
2007-08-13 18:03:06 +02:00
|
|
|
#include "zebra/kernel_socket.h"
|
2016-06-02 13:28:15 +02:00
|
|
|
#include "zebra/zebra_mpls.h"
|
2018-08-24 19:14:09 +02:00
|
|
|
#include "zebra/zebra_errors.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2003-06-04 15:59:38 +02:00
|
|
|
extern struct zebra_privs_t zserv_privs;
|
|
|
|
|
2015-09-16 06:55:38 +02:00
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Adjust netmask socket length. Return value is a adjusted sin_len
|
|
|
|
value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int sin_masklen(struct in_addr mask)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
char *p, *lim;
|
|
|
|
int len;
|
|
|
|
struct sockaddr_in sin;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (mask.s_addr == 0)
|
|
|
|
return sizeof(long);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sin.sin_addr = mask;
|
|
|
|
len = sizeof(struct sockaddr_in);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
lim = (char *)&sin.sin_addr;
|
|
|
|
p = lim + sizeof(sin.sin_addr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
while (*--p == 0 && p >= lim)
|
|
|
|
len--;
|
|
|
|
return len;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2015-09-16 06:55:38 +02:00
|
|
|
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-08-22 22:01:54 +02:00
|
|
|
#ifdef __OpenBSD__
|
2018-01-21 22:11:50 +01:00
|
|
|
static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label,
|
2017-08-22 22:01:54 +02:00
|
|
|
struct sockaddr_mpls *smpls)
|
|
|
|
{
|
|
|
|
if (nh_label->num_labels > 1) {
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_warn(EC_ZEBRA_MAX_LABELS_PUSH,
|
2018-08-16 22:10:32 +02:00
|
|
|
"%s: can't push %u labels at "
|
|
|
|
"once (maximum is 1)",
|
|
|
|
__func__, nh_label->num_labels);
|
2017-08-22 22:01:54 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(smpls, 0, sizeof(*smpls));
|
|
|
|
smpls->smpls_len = sizeof(*smpls);
|
|
|
|
smpls->smpls_family = AF_MPLS;
|
|
|
|
smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-12-17 22:28:47 +01:00
|
|
|
#ifdef SIN6_LEN
|
|
|
|
/* Calculate sin6_len value for netmask socket value. */
|
|
|
|
static int sin6_masklen(struct in6_addr mask)
|
|
|
|
{
|
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
char *p, *lim;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&mask))
|
|
|
|
return sizeof(long);
|
|
|
|
|
|
|
|
sin6.sin6_addr = mask;
|
|
|
|
len = sizeof(struct sockaddr_in6);
|
|
|
|
|
|
|
|
lim = (char *)&sin6.sin6_addr;
|
|
|
|
p = lim + sizeof(sin6.sin6_addr);
|
|
|
|
|
|
|
|
while (*--p == 0 && p >= lim)
|
|
|
|
len--;
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
#endif /* SIN6_LEN */
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Interface between zebra message and rtm message. */
|
2018-12-17 20:23:02 +01:00
|
|
|
static int kernel_rtm(int cmd, const struct prefix *p,
|
|
|
|
const struct nexthop_group *ng, uint32_t metric)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
{
|
2018-12-17 19:57:04 +01:00
|
|
|
union sockunion *mask = NULL;
|
|
|
|
union sockunion sin_dest, sin_mask, sin_gate;
|
2016-09-22 04:59:57 +02:00
|
|
|
#ifdef __OpenBSD__
|
2017-07-17 14:03:14 +02:00
|
|
|
struct sockaddr_mpls smpls;
|
2016-06-02 13:28:15 +02:00
|
|
|
#endif
|
2017-07-17 14:03:14 +02:00
|
|
|
union sockunion *smplsp = NULL;
|
|
|
|
struct nexthop *nexthop;
|
|
|
|
int nexthop_num = 0;
|
|
|
|
ifindex_t ifindex = 0;
|
|
|
|
int gate = 0;
|
|
|
|
int error;
|
|
|
|
char prefix_buf[PREFIX_STRLEN];
|
2010-02-05 04:31:56 +01:00
|
|
|
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_RIB)
|
|
|
|
prefix2str(p, prefix_buf, sizeof(prefix_buf));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-12-17 20:23:02 +01:00
|
|
|
memset(&sin_dest, 0, sizeof(sin_dest));
|
|
|
|
memset(&sin_gate, 0, sizeof(sin_gate));
|
2018-12-17 19:57:04 +01:00
|
|
|
memset(&sin_mask, 0, sizeof(sin_mask));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-12-17 20:23:02 +01:00
|
|
|
switch (p->family) {
|
|
|
|
case AF_INET:
|
|
|
|
sin_dest.sin.sin_family = AF_INET;
|
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
|
|
|
sin_dest.sin.sin_len = sizeof(sin_dest);
|
|
|
|
sin_gate.sin.sin_len = sizeof(sin_gate);
|
|
|
|
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
|
|
|
sin_dest.sin.sin_addr = p->u.prefix4;
|
|
|
|
sin_gate.sin.sin_family = AF_INET;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
sin_dest.sin6.sin6_family = AF_INET6;
|
|
|
|
#ifdef SIN6_LEN
|
|
|
|
sin_dest.sin6.sin6_len = sizeof(sin_dest);
|
|
|
|
#endif /* SIN6_LEN */
|
|
|
|
sin_dest.sin6.sin6_addr = p->u.prefix6;
|
|
|
|
sin_gate.sin6.sin6_family = AF_INET6;
|
[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
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
2018-12-17 20:23:02 +01:00
|
|
|
sin_gate.sin6.sin6_len = sizeof(sin_gate);
|
[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_IN_SIN_LEN */
|
2018-12-17 20:23:02 +01:00
|
|
|
break;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Make gateway. */
|
2018-08-17 21:25:24 +02:00
|
|
|
for (ALL_NEXTHOPS_PTR(ng, nexthop)) {
|
2017-07-17 14:03:14 +02:00
|
|
|
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gate = 0;
|
|
|
|
char gate_buf[INET_ADDRSTRLEN] = "NULL";
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX We need to refrain from kernel operations in some cases,
|
|
|
|
* but this if statement seems overly cautious - what about
|
|
|
|
* other than ADD and DELETE?
|
|
|
|
*/
|
2018-03-06 20:02:52 +01:00
|
|
|
if ((cmd == RTM_ADD && NEXTHOP_IS_ACTIVE(nexthop->flags))
|
2018-08-17 21:25:24 +02:00
|
|
|
|| (cmd == RTM_DELETE)) {
|
2018-12-17 20:23:02 +01:00
|
|
|
switch (nexthop->type) {
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
2018-12-17 19:57:04 +01:00
|
|
|
sin_gate.sin.sin_addr = nexthop->gate.ipv4;
|
2018-12-17 20:23:02 +01:00
|
|
|
sin_gate.sin.sin_family = AF_INET;
|
|
|
|
ifindex = nexthop->ifindex;
|
2017-07-17 14:03:14 +02:00
|
|
|
gate = 1;
|
2018-12-17 20:23:02 +01:00
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
|
|
|
sin_gate.sin6.sin6_addr = nexthop->gate.ipv6;
|
|
|
|
sin_gate.sin6.sin6_family = AF_INET6;
|
2017-07-17 14:03:14 +02:00
|
|
|
ifindex = nexthop->ifindex;
|
2018-12-17 20:23:02 +01:00
|
|
|
/* Under kame set interface index to link local address */
|
|
|
|
#ifdef KAME
|
|
|
|
|
|
|
|
#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
|
|
|
|
do { \
|
|
|
|
(a).s6_addr[2] = ((i) >> 8) & 0xff; \
|
|
|
|
(a).s6_addr[3] = (i)&0xff; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(
|
|
|
|
&sin_gate.sin6.sin6_addr))
|
|
|
|
SET_IN6_LINKLOCAL_IFINDEX(
|
|
|
|
sin_gate.sin6.sin6_addr,
|
|
|
|
ifindex);
|
|
|
|
#endif /* KAME */
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
gate = 1;
|
2018-12-17 20:23:02 +01:00
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
ifindex = nexthop->ifindex;
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_BLACKHOLE:
|
|
|
|
bh_type = nexthop->bh_type;
|
|
|
|
switch (p->family) {
|
|
|
|
case AFI_IP: {
|
|
|
|
struct in_addr loopback;
|
|
|
|
loopback.s_addr =
|
|
|
|
htonl(INADDR_LOOPBACK);
|
|
|
|
sin_gate.sin.sin_addr = loopback;
|
|
|
|
gate = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AFI_IP6:
|
|
|
|
break;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2018-12-17 20:23:02 +01:00
|
|
|
switch (p->family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (gate && p->prefixlen == 32)
|
|
|
|
mask = NULL;
|
|
|
|
else {
|
|
|
|
masklen2ip(p->prefixlen,
|
|
|
|
&sin_mask.sin.sin_addr);
|
|
|
|
sin_mask.sin.sin_family = AF_INET;
|
[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
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
2018-12-17 20:23:02 +01:00
|
|
|
sin_mask.sin.sin_len = sin_masklen(
|
|
|
|
sin_mask.sin.sin_addr);
|
[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_IN_SIN_LEN */
|
2018-12-17 20:23:02 +01:00
|
|
|
mask = &sin_mask;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (gate && p->prefixlen == 128)
|
|
|
|
mask = NULL;
|
|
|
|
else {
|
|
|
|
masklen2ip6(p->prefixlen,
|
|
|
|
&sin_mask.sin6.sin6_addr);
|
|
|
|
sin_mask.sin6.sin6_family = AF_INET6;
|
|
|
|
#ifdef SIN6_LEN
|
|
|
|
sin_mask.sin6.sin6_len = sin6_masklen(
|
|
|
|
sin_mask.sin6.sin6_addr);
|
|
|
|
#endif /* SIN6_LEN */
|
|
|
|
mask = &sin_mask;
|
|
|
|
}
|
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-09-22 04:59:57 +02:00
|
|
|
#ifdef __OpenBSD__
|
2017-08-22 22:01:54 +02:00
|
|
|
if (nexthop->nh_label
|
|
|
|
&& !kernel_rtm_add_labels(nexthop->nh_label,
|
|
|
|
&smpls))
|
|
|
|
continue;
|
|
|
|
smplsp = (union sockunion *)&smpls;
|
2016-06-02 13:28:15 +02:00
|
|
|
#endif
|
2018-12-17 19:57:04 +01:00
|
|
|
error = rtm_write(cmd, &sin_dest, mask,
|
|
|
|
gate ? &sin_gate : NULL, smplsp,
|
|
|
|
ifindex, bh_type, metric);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-08-17 22:53:24 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL) {
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!gate) {
|
|
|
|
zlog_debug(
|
2018-08-17 21:25:24 +02:00
|
|
|
"%s: %s: attention! gate not found for re",
|
|
|
|
__func__, prefix_buf);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else
|
2018-12-17 20:23:02 +01:00
|
|
|
inet_ntop(p->family == AFI_IP ? AF_INET
|
|
|
|
: AF_INET6,
|
2018-12-17 19:57:04 +01:00
|
|
|
&sin_gate.sin.sin_addr,
|
2017-07-17 14:03:14 +02:00
|
|
|
gate_buf, INET_ADDRSTRLEN);
|
|
|
|
}
|
|
|
|
switch (error) {
|
2018-12-17 20:23:02 +01:00
|
|
|
/* We only flag nexthops as being in FIB if
|
|
|
|
* rtm_write() did its work. */
|
2017-07-17 14:03:14 +02:00
|
|
|
case ZEBRA_ERR_NOERROR:
|
|
|
|
nexthop_num++;
|
2018-08-17 22:53:24 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
2017-07-17 14:03:14 +02:00
|
|
|
zlog_debug(
|
|
|
|
"%s: %s: successfully did NH %s",
|
|
|
|
__func__, prefix_buf, gate_buf);
|
2018-08-17 22:53:24 +02:00
|
|
|
if (cmd == RTM_ADD)
|
2018-12-17 20:23:02 +01:00
|
|
|
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
|
2018-12-17 20:23:02 +01:00
|
|
|
/* The only valid case for this error is
|
|
|
|
* kernel's failure to install a multipath
|
|
|
|
* route, which is common for FreeBSD. This
|
|
|
|
* should be
|
|
|
|
* ignored silently, but logged as an error
|
|
|
|
* otherwise.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
case ZEBRA_ERR_RTEXIST:
|
|
|
|
if (cmd != RTM_ADD)
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 21:34:28 +02:00
|
|
|
EC_LIB_SYSTEM_CALL,
|
2017-07-17 14:03:14 +02:00
|
|
|
"%s: rtm_write() returned %d for command %d",
|
|
|
|
__func__, error, cmd);
|
|
|
|
continue;
|
|
|
|
|
2018-12-17 20:23:02 +01:00
|
|
|
/* Note any unexpected status returns */
|
2017-07-17 14:03:14 +02:00
|
|
|
default:
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 21:34:28 +02:00
|
|
|
EC_LIB_SYSTEM_CALL,
|
2017-07-17 14:03:14 +02:00
|
|
|
"%s: %s: rtm_write() unexpectedly returned %d for command %s",
|
|
|
|
__func__,
|
|
|
|
prefix2str(p, prefix_buf,
|
|
|
|
sizeof(prefix_buf)),
|
|
|
|
error,
|
|
|
|
lookup_msg(rtm_type_str, cmd, NULL));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} /* if (cmd and flags make sense) */
|
2018-08-17 22:53:24 +02:00
|
|
|
else if (IS_ZEBRA_DEBUG_KERNEL)
|
2017-07-17 14:03:14 +02:00
|
|
|
zlog_debug("%s: odd command %s for flags %d", __func__,
|
|
|
|
lookup_msg(rtm_type_str, cmd, NULL),
|
|
|
|
nexthop->flags);
|
|
|
|
} /* for (ALL_NEXTHOPS(...))*/
|
|
|
|
|
|
|
|
/* If there was no useful nexthop, then complain. */
|
2018-10-24 17:34:50 +02:00
|
|
|
if (nexthop_num == 0) {
|
|
|
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
2018-08-17 21:25:24 +02:00
|
|
|
zlog_debug("%s: No useful nexthops were found in RIB prefix %s",
|
|
|
|
__func__, prefix2str(p, prefix_buf,
|
|
|
|
sizeof(prefix_buf)));
|
2018-10-24 17:34:50 +02:00
|
|
|
return 1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
return 0; /*XXX*/
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2018-08-17 21:25:24 +02:00
|
|
|
/*
|
|
|
|
* Update or delete a prefix from the kernel,
|
|
|
|
* using info from a dataplane context struct.
|
|
|
|
*/
|
2018-09-19 19:25:12 +02:00
|
|
|
enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
|
2018-08-17 21:25:24 +02:00
|
|
|
{
|
|
|
|
enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
|
|
|
|
|
|
|
if (dplane_ctx_get_src(ctx) != NULL) {
|
|
|
|
zlog_err("route add: IPv6 sourcedest routes unsupported!");
|
|
|
|
res = ZEBRA_DPLANE_REQUEST_FAILURE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2018-11-16 13:26:51 +01:00
|
|
|
frr_elevate_privs(&zserv_privs) {
|
2018-08-17 22:53:24 +02:00
|
|
|
|
|
|
|
if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE)
|
|
|
|
kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
|
|
|
|
dplane_ctx_get_ng(ctx),
|
|
|
|
dplane_ctx_get_metric(ctx));
|
|
|
|
else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL)
|
|
|
|
kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
|
|
|
|
dplane_ctx_get_ng(ctx),
|
|
|
|
dplane_ctx_get_metric(ctx));
|
|
|
|
else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
|
|
|
|
/* Must do delete and add separately -
|
|
|
|
* no update available
|
|
|
|
*/
|
|
|
|
kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
|
|
|
|
dplane_ctx_get_old_ng(ctx),
|
|
|
|
dplane_ctx_get_old_metric(ctx));
|
|
|
|
|
|
|
|
kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
|
|
|
|
dplane_ctx_get_ng(ctx),
|
|
|
|
dplane_ctx_get_metric(ctx));
|
|
|
|
} else {
|
|
|
|
zlog_err("Invalid routing socket update op %s (%u)",
|
|
|
|
dplane_op2str(dplane_ctx_get_op(ctx)),
|
|
|
|
dplane_ctx_get_op(ctx));
|
|
|
|
res = ZEBRA_DPLANE_REQUEST_FAILURE;
|
|
|
|
}
|
|
|
|
} /* Elevated privs */
|
2018-08-17 21:25:24 +02:00
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
|
2017-12-19 12:23:32 +01:00
|
|
|
int llalen, ns_id_t ns_id)
|
2016-08-04 15:07:32 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
/* TODO */
|
|
|
|
return 0;
|
2016-08-04 15:07:32 +02:00
|
|
|
}
|
2017-01-18 04:01:36 +01:00
|
|
|
|
2017-06-06 16:18:17 +02:00
|
|
|
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute)
|
2017-01-18 04:01:36 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-01-18 04:01:36 +01:00
|
|
|
}
|
2017-05-15 07:38:26 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
|
2017-05-15 07:38:26 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-05-15 07:38:26 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
|
2017-05-15 07:38:26 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-05-15 07:38:26 +02:00
|
|
|
}
|
2017-05-15 07:44:13 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
|
2018-09-10 19:13:20 +02:00
|
|
|
struct in_addr vtep_ip, bool sticky)
|
2017-05-15 07:44:13 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-05-15 07:44:13 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
|
2018-08-29 02:02:40 +02:00
|
|
|
struct in_addr vtep_ip)
|
2017-05-15 07:44:13 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-05-15 07:44:13 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
|
2018-07-07 06:46:46 +02:00
|
|
|
struct ethaddr *mac, uint8_t flags)
|
2017-05-15 07:44:13 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-05-15 07:44:13 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
|
2017-05-15 07:44:13 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2017-05-15 07:44:13 +02:00
|
|
|
}
|
2017-06-13 14:59:32 +02:00
|
|
|
|
|
|
|
extern int kernel_interface_set_master(struct interface *master,
|
|
|
|
struct interface *slave)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2017-08-02 15:39:38 +02:00
|
|
|
|
2018-01-11 01:01:57 +01:00
|
|
|
uint32_t kernel_get_speed(struct interface *ifp)
|
|
|
|
{
|
|
|
|
return ifp->speed;
|
|
|
|
}
|
|
|
|
|
2017-07-26 19:49:15 +02:00
|
|
|
#endif /* !HAVE_NETLINK */
|