Merge branch 'master' of ssh://git.nic.cz/bird
This commit is contained in:
commit
72b2db8db7
45 changed files with 526 additions and 1386 deletions
17
aclocal.m4
vendored
17
aclocal.m4
vendored
|
@ -133,23 +133,6 @@ if test "$bird_cv_struct_ip_mreqn" = yes ; then
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN(BIRD_CHECK_LINUX_VERSION,
|
|
||||||
[AC_CACHE_CHECK([Linux kernel version], bird_cv_sys_linux_version, [
|
|
||||||
AC_REQUIRE_CPP()dnl
|
|
||||||
cat > conftest.$ac_ext <<EOF
|
|
||||||
[#]line __oline__ "configure"
|
|
||||||
#include "confdefs.h"
|
|
||||||
#include <linux/version.h>
|
|
||||||
VERSION: UTS_RELEASE
|
|
||||||
EOF
|
|
||||||
bird_cv_sys_linux_version=`eval "$ac_cpp conftest.$ac_ext" 2>&AC_FD_CC | sed '/^VERSION/!d;s/^VERSION: "//;s/".*//'`
|
|
||||||
rm -rf conftest*
|
|
||||||
if test -z "$bird_cv_sys_linux_version" ; then
|
|
||||||
AC_MSG_RESULT([unknown])
|
|
||||||
AC_MSG_ERROR([Cannot determine kernel version])
|
|
||||||
fi
|
|
||||||
])])
|
|
||||||
|
|
||||||
AC_DEFUN(BIRD_CHECK_GCC_OPTIONS,
|
AC_DEFUN(BIRD_CHECK_GCC_OPTIONS,
|
||||||
[AC_CACHE_VAL(bird_cv_c_option_no_pointer_sign, [
|
[AC_CACHE_VAL(bird_cv_c_option_no_pointer_sign, [
|
||||||
cat >conftest.c <<EOF
|
cat >conftest.c <<EOF
|
||||||
|
|
|
@ -135,6 +135,14 @@ submit_server_command(char *cmd)
|
||||||
num_lines = 2;
|
num_lines = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_history_dedup(char *cmd)
|
||||||
|
{
|
||||||
|
/* Add history line if it differs from the last one */
|
||||||
|
HIST_ENTRY *he = history_get(history_length);
|
||||||
|
if (!he || strcmp(he->line, cmd))
|
||||||
|
add_history(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
got_line(char *cmd_buffer)
|
got_line(char *cmd_buffer)
|
||||||
|
@ -151,7 +159,7 @@ got_line(char *cmd_buffer)
|
||||||
cmd = cmd_expand(cmd_buffer);
|
cmd = cmd_expand(cmd_buffer);
|
||||||
if (cmd)
|
if (cmd)
|
||||||
{
|
{
|
||||||
add_history(cmd);
|
add_history_dedup(cmd);
|
||||||
|
|
||||||
if (!handle_internal_command(cmd))
|
if (!handle_internal_command(cmd))
|
||||||
submit_server_command(cmd);
|
submit_server_command(cmd);
|
||||||
|
@ -159,7 +167,7 @@ got_line(char *cmd_buffer)
|
||||||
free(cmd);
|
free(cmd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
add_history(cmd_buffer);
|
add_history_dedup(cmd_buffer);
|
||||||
}
|
}
|
||||||
free(cmd_buffer);
|
free(cmd_buffer);
|
||||||
}
|
}
|
||||||
|
|
38
configure.in
38
configure.in
|
@ -10,14 +10,17 @@ AC_ARG_ENABLE(debug,[ --enable-debug enable internal debugging routine
|
||||||
AC_ARG_ENABLE(memcheck, [ --enable-memcheck check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
|
AC_ARG_ENABLE(memcheck, [ --enable-memcheck check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
|
||||||
AC_ARG_ENABLE(client, [ --enable-client enable building of BIRD client (default: enabled)],,enable_client=yes)
|
AC_ARG_ENABLE(client, [ --enable-client enable building of BIRD client (default: enabled)],,enable_client=yes)
|
||||||
AC_ARG_ENABLE(ipv6, [ --enable-ipv6 enable building of IPv6 version (default: disabled)],,enable_ipv6=no)
|
AC_ARG_ENABLE(ipv6, [ --enable-ipv6 enable building of IPv6 version (default: disabled)],,enable_ipv6=no)
|
||||||
|
AC_ARG_WITH(suffix, [ --with-suffix=STRING use specified suffix for BIRD files (default: 6 for IPv6 version)],[given_suffix="yes"])
|
||||||
AC_ARG_WITH(sysconfig, [ --with-sysconfig=FILE use specified BIRD system configuration file])
|
AC_ARG_WITH(sysconfig, [ --with-sysconfig=FILE use specified BIRD system configuration file])
|
||||||
AC_ARG_WITH(protocols, [ --with-protocols=LIST include specified routing protocols (default: all)],,[with_protocols="all"])
|
AC_ARG_WITH(protocols, [ --with-protocols=LIST include specified routing protocols (default: all)],,[with_protocols="all"])
|
||||||
AC_ARG_WITH(sysinclude, [ --with-sysinclude=PATH search for system includes on specified place])
|
AC_ARG_WITH(sysinclude, [ --with-sysinclude=PATH search for system includes on specified place])
|
||||||
|
AC_ARG_WITH(runtimedir, [ --with-runtimedir=PATH path for runtime files (default: $(localstatedir)/run)],[runtimedir="$with_runtimedir"],[runtimedir="\$(localstatedir)/run"])
|
||||||
AC_ARG_WITH(iproutedir, [ --with-iproutedir=PATH path to iproute2 config files (default: /etc/iproute2)],[given_iproutedir="yes"])
|
AC_ARG_WITH(iproutedir, [ --with-iproutedir=PATH path to iproute2 config files (default: /etc/iproute2)],[given_iproutedir="yes"])
|
||||||
AC_ARG_VAR([FLEX], [location of the Flex program])
|
AC_ARG_VAR([FLEX], [location of the Flex program])
|
||||||
AC_ARG_VAR([BISON], [location of the Bison program])
|
AC_ARG_VAR([BISON], [location of the Bison program])
|
||||||
AC_ARG_VAR([M4], [location of the M4 program])
|
AC_ARG_VAR([M4], [location of the M4 program])
|
||||||
|
|
||||||
|
|
||||||
if test "$srcdir" = . ; then
|
if test "$srcdir" = . ; then
|
||||||
# Building in current directory => create obj directory holding all objects
|
# Building in current directory => create obj directory holding all objects
|
||||||
objdir=obj
|
objdir=obj
|
||||||
|
@ -39,21 +42,37 @@ esac
|
||||||
AC_SUBST(objdir)
|
AC_SUBST(objdir)
|
||||||
AC_SUBST(exedir)
|
AC_SUBST(exedir)
|
||||||
AC_SUBST(srcdir_rel_mf)
|
AC_SUBST(srcdir_rel_mf)
|
||||||
|
AC_SUBST(runtimedir)
|
||||||
|
|
||||||
if test "$enable_ipv6" = yes ; then
|
if test "$enable_ipv6" = yes ; then
|
||||||
ip=ipv6
|
ip=ipv6
|
||||||
SUFFIX6=6
|
SUFFIX=6
|
||||||
all_protocols=bgp,ospf,pipe,radv,rip,static
|
all_protocols=bgp,ospf,pipe,radv,rip,static
|
||||||
else
|
else
|
||||||
ip=ipv4
|
ip=ipv4
|
||||||
SUFFIX6=""
|
SUFFIX=""
|
||||||
all_protocols=bgp,ospf,pipe,rip,static
|
all_protocols=bgp,ospf,pipe,rip,static
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$given_suffix" = yes ; then
|
||||||
|
SUFFIX="$with_suffix"
|
||||||
|
fi
|
||||||
|
AC_SUBST(SUFFIX)
|
||||||
|
|
||||||
if test "$with_protocols" = all ; then
|
if test "$with_protocols" = all ; then
|
||||||
with_protocols="$all_protocols"
|
with_protocols="$all_protocols"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$enable_debug" = yes ; then
|
||||||
|
CONFIG_FILE="bird$SUFFIX.conf"
|
||||||
|
CONTROL_SOCKET="bird$SUFFIX.ctl"
|
||||||
|
else
|
||||||
|
CONFIG_FILE="\$(sysconfdir)/bird$SUFFIX.conf"
|
||||||
|
CONTROL_SOCKET="$runtimedir/bird$SUFFIX.ctl"
|
||||||
|
fi
|
||||||
|
AC_SUBST(CONFIG_FILE)
|
||||||
|
AC_SUBST(CONTROL_SOCKET)
|
||||||
|
|
||||||
AC_SEARCH_LIBS(clock_gettime,[c rt posix4])
|
AC_SEARCH_LIBS(clock_gettime,[c rt posix4])
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
|
@ -105,19 +124,11 @@ elif test -f sysconfig.h ; then
|
||||||
sysdesc=sysconfig
|
sysdesc=sysconfig
|
||||||
else
|
else
|
||||||
case "$ip:$host_os" in
|
case "$ip:$host_os" in
|
||||||
ipv4:linux*) BIRD_CHECK_LINUX_VERSION
|
ipv6:linux*) sysdesc=linux-v6
|
||||||
default_iproutedir="/etc/iproute2"
|
default_iproutedir="/etc/iproute2"
|
||||||
case $bird_cv_sys_linux_version in
|
|
||||||
1.*|2.0.*) sysdesc=linux-20 ;;
|
|
||||||
*) sysdesc=linux-22 ;;
|
|
||||||
esac
|
|
||||||
;;
|
;;
|
||||||
ipv6:linux*) BIRD_CHECK_LINUX_VERSION
|
ipv4:linux*) sysdesc=linux
|
||||||
default_iproutedir="/etc/iproute2"
|
default_iproutedir="/etc/iproute2"
|
||||||
case $bird_cv_sys_linux_version in
|
|
||||||
1.*|2.0.*) AC_MSG_ERROR([This version of Linux doesn't support IPv6.]) ;;
|
|
||||||
*) sysdesc=linux-v6 ;;
|
|
||||||
esac
|
|
||||||
;;
|
;;
|
||||||
ipv6:netbsd*) sysdesc=bsd-v6
|
ipv6:netbsd*) sysdesc=bsd-v6
|
||||||
CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
|
CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
|
||||||
|
@ -180,7 +191,7 @@ AC_MSG_RESULT(ok)
|
||||||
AC_SUBST(protocols)
|
AC_SUBST(protocols)
|
||||||
|
|
||||||
case $sysdesc in
|
case $sysdesc in
|
||||||
*/linux-22*|*/linux-v6*)
|
*/linux*|*/linux-v6*)
|
||||||
AC_CHECK_HEADER(linux/rtnetlink.h,,[AC_MSG_ERROR([Appropriate version of Linux kernel headers not found.])],[
|
AC_CHECK_HEADER(linux/rtnetlink.h,,[AC_MSG_ERROR([Appropriate version of Linux kernel headers not found.])],[
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -233,7 +244,6 @@ if test "$enable_client" = yes ; then
|
||||||
fi
|
fi
|
||||||
AC_SUBST(CLIENT)
|
AC_SUBST(CLIENT)
|
||||||
AC_SUBST(CLIENT_LIBS)
|
AC_SUBST(CLIENT_LIBS)
|
||||||
AC_SUBST(SUFFIX6)
|
|
||||||
|
|
||||||
mkdir -p $objdir/sysdep
|
mkdir -p $objdir/sysdep
|
||||||
AC_CONFIG_HEADERS([$objdir/sysdep/autoconf.h:sysdep/autoconf.h.in])
|
AC_CONFIG_HEADERS([$objdir/sysdep/autoconf.h:sysdep/autoconf.h.in])
|
||||||
|
|
|
@ -1072,7 +1072,16 @@ undefined value is regarded as empty clist for most purposes.
|
||||||
routes). Read-only.
|
routes). Read-only.
|
||||||
|
|
||||||
<tag><m/enum/ dest</tag>
|
<tag><m/enum/ dest</tag>
|
||||||
Type of destination the packets should be sent to (<cf/RTD_ROUTER/ for forwarding to a neighboring router, <cf/RTD_DEVICE/ for routing to a directly-connected network, <cf/RTD_BLACKHOLE/ for packets to be silently discarded, <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
|
Type of destination the packets should be sent to
|
||||||
|
(<cf/RTD_ROUTER/ for forwarding to a neighboring router,
|
||||||
|
<cf/RTD_DEVICE/ for routing to a directly-connected network,
|
||||||
|
<cf/RTD_MULTIPATH/ for multipath destinations,
|
||||||
|
<cf/RTD_BLACKHOLE/ for packets to be silently discarded,
|
||||||
|
<cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that
|
||||||
|
should be returned with ICMP host unreachable / ICMP
|
||||||
|
administratively prohibited messages). Can be changed, but
|
||||||
|
only to <cf/RTD_BLACKHOLE/, <cf/RTD_UNREACHABLE/ or
|
||||||
|
<cf/RTD_PROHIBIT/.
|
||||||
|
|
||||||
<tag><m/int/ igp_metric</tag>
|
<tag><m/int/ igp_metric</tag>
|
||||||
The optional attribute that can be used to specify a distance
|
The optional attribute that can be used to specify a distance
|
||||||
|
|
|
@ -703,7 +703,7 @@ static_attr:
|
||||||
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); }
|
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); }
|
||||||
| SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); $$->a1.i = 1; }
|
| SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); $$->a1.i = 1; }
|
||||||
| CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = OFFSETOF(struct rta, cast); }
|
| CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = OFFSETOF(struct rta, cast); }
|
||||||
| DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); }
|
| DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); $$->a1.i = 1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
term:
|
term:
|
||||||
|
|
|
@ -852,12 +852,25 @@ interpret(struct f_inst *what)
|
||||||
{
|
{
|
||||||
struct rta *rta = (*f_rte)->attrs;
|
struct rta *rta = (*f_rte)->attrs;
|
||||||
switch (what->aux) {
|
switch (what->aux) {
|
||||||
case T_ENUM:
|
|
||||||
* ((char *) rta + what->a2.i) = v1.val.i;
|
|
||||||
break;
|
|
||||||
case T_IP:
|
case T_IP:
|
||||||
* (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
|
* (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_ENUM_SCOPE:
|
||||||
|
rta->scope = v1.val.i;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_ENUM_RTD:
|
||||||
|
i = v1.val.i;
|
||||||
|
if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
|
||||||
|
runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
|
||||||
|
rta->dest = i;
|
||||||
|
rta->gw = IPA_NONE;
|
||||||
|
rta->iface = NULL;
|
||||||
|
rta->nexthops = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bug( "Unknown type in set of static attribute" );
|
bug( "Unknown type in set of static attribute" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
|
||||||
|
|
||||||
// static inline void put_as(byte *data, u32 as) { put_u32(data, as); }
|
// static inline void put_as(byte *data, u32 as) { put_u32(data, as); }
|
||||||
// static inline u32 get_as(byte *data) { return get_u32(data); }
|
// static inline u32 get_as(byte *data) { return get_u32(data); }
|
||||||
|
|
||||||
|
|
|
@ -62,3 +62,4 @@
|
||||||
/* We have stdint.h */
|
/* We have stdint.h */
|
||||||
#undef HAVE_STDINT_H
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
#define CONFIG_PATH ?
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
krt-scan.h
|
|
||||||
krt-iface.h
|
|
||||||
sysio.h
|
|
||||||
krt-set.h
|
|
||||||
krt-sock.c
|
krt-sock.c
|
||||||
krt-sock.h
|
krt-sys.h
|
||||||
|
sysio.h
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Socket Route Syncer -- Dummy Include File
|
|
||||||
*
|
|
||||||
* (c) 2004 Ondrej Filip <feela@network.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_IFACE_H_
|
|
||||||
#define _BIRD_KRT_IFACE_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't have split iface/scan/set parts. See krt-sock.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct krt_if_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_if_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
|
||||||
static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- *BSD Kernel Route Syncer -- Scanning
|
|
||||||
*
|
|
||||||
* (c) 2004 Ondrej Filip <feela@network.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SCAN_H_
|
|
||||||
#define _BIRD_KRT_SCAN_H_
|
|
||||||
|
|
||||||
struct krt_scan_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_scan_status {
|
|
||||||
list temp_ifs; /* Temporary interfaces */
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int krt_scan_params_same(struct krt_scan_params *o UNUSED, struct krt_scan_params *n UNUSED) { return 1; }
|
|
||||||
static inline void krt_scan_copy_params(struct krt_scan_params *d UNUSED, struct krt_scan_params *s UNUSED) { }
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,17 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Socket Route Syncer -- Dummy Include File
|
|
||||||
*
|
|
||||||
* (c) 2004 Ondrej Filip <feela@network.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SET_H_
|
|
||||||
#define _BIRD_KRT_SET_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't have split iface/scan/set parts. See krt-sock.h.
|
|
||||||
*/
|
|
||||||
#include "lib/krt-sock.h"
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -33,7 +33,19 @@
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
|
|
||||||
int rt_sock = 0;
|
|
||||||
|
#ifndef RTAX_MAX
|
||||||
|
#define RTAX_MAX 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ks_msg
|
||||||
|
{
|
||||||
|
struct rt_msghdr rtm;
|
||||||
|
struct sockaddr_storage buf[RTAX_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int rt_sock = 0;
|
||||||
|
|
||||||
int
|
int
|
||||||
krt_capable(rte *e)
|
krt_capable(rte *e)
|
||||||
|
@ -189,7 +201,7 @@ krt_sock_send(int cmd, rte *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_set_notify(struct krt_proto *p UNUSED, net *n, rte *new, rte *old,
|
krt_replace_rte(struct krt_proto *p UNUSED, net *n, rte *new, rte *old,
|
||||||
struct ea_list *eattrs UNUSED)
|
struct ea_list *eattrs UNUSED)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -206,45 +218,6 @@ krt_set_notify(struct krt_proto *p UNUSED, net *n, rte *new, rte *old,
|
||||||
n->n.flags &= ~KRF_SYNC_ERROR;
|
n->n.flags &= ~KRF_SYNC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
krt_set_hook(sock *sk, int size UNUSED)
|
|
||||||
{
|
|
||||||
struct ks_msg msg;
|
|
||||||
int l = read(sk->fd, (char *)&msg, sizeof(msg));
|
|
||||||
|
|
||||||
if(l <= 0)
|
|
||||||
log(L_ERR "krt-sock: read failed");
|
|
||||||
else
|
|
||||||
krt_read_msg((struct proto *)sk->data, &msg, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_set_start(struct krt_proto *x, int first UNUSED)
|
|
||||||
{
|
|
||||||
sock *sk_rt;
|
|
||||||
static int ks_open_tried = 0;
|
|
||||||
|
|
||||||
if (ks_open_tried)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ks_open_tried = 1;
|
|
||||||
|
|
||||||
DBG("KRT: Opening kernel socket\n");
|
|
||||||
|
|
||||||
if( (rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0)
|
|
||||||
die("Cannot open kernel socket for routes");
|
|
||||||
|
|
||||||
sk_rt = sk_new(krt_pool);
|
|
||||||
sk_rt->type = SK_MAGIC;
|
|
||||||
sk_rt->rx_hook = krt_set_hook;
|
|
||||||
sk_rt->fd = rt_sock;
|
|
||||||
sk_rt->data = x;
|
|
||||||
if (sk_open(sk_rt))
|
|
||||||
bug("krt-sock: sk_open failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
|
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -648,32 +621,6 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_construct(struct krt_config *c UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_preconfig(struct config *c UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_postconfig(struct krt_config *c UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_start(struct krt_proto *x, int first UNUSED)
|
|
||||||
{
|
|
||||||
init_list(&x->scan.temp_ifs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
|
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
|
||||||
{
|
{
|
||||||
|
@ -732,13 +679,13 @@ static size_t krt_buflen = 32768;
|
||||||
static size_t kif_buflen = 4096;
|
static size_t kif_buflen = 4096;
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_scan_fire(struct krt_proto *p)
|
krt_do_scan(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP);
|
krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_if_scan(struct kif_proto *p)
|
kif_do_scan(struct kif_proto *p)
|
||||||
{
|
{
|
||||||
struct proto *P = (struct proto *)p;
|
struct proto *P = (struct proto *)p;
|
||||||
if_start_update();
|
if_start_update();
|
||||||
|
@ -746,14 +693,47 @@ krt_if_scan(struct kif_proto *p)
|
||||||
if_end_update();
|
if_end_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
void
|
krt_sock_hook(sock *sk, int size UNUSED)
|
||||||
krt_set_construct(struct krt_config *c UNUSED)
|
|
||||||
{
|
{
|
||||||
|
struct ks_msg msg;
|
||||||
|
int l = read(sk->fd, (char *)&msg, sizeof(msg));
|
||||||
|
|
||||||
|
if(l <= 0)
|
||||||
|
log(L_ERR "krt-sock: read failed");
|
||||||
|
else
|
||||||
|
krt_read_msg((struct proto *)sk->data, &msg, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
krt_sys_start(struct krt_proto *x, int first UNUSED)
|
||||||
|
{
|
||||||
|
sock *sk_rt;
|
||||||
|
static int ks_open_tried = 0;
|
||||||
|
|
||||||
|
if (ks_open_tried)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ks_open_tried = 1;
|
||||||
|
|
||||||
|
DBG("KRT: Opening kernel socket\n");
|
||||||
|
|
||||||
|
if( (rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0)
|
||||||
|
die("Cannot open kernel socket for routes");
|
||||||
|
|
||||||
|
sk_rt = sk_new(krt_pool);
|
||||||
|
sk_rt->type = SK_MAGIC;
|
||||||
|
sk_rt->rx_hook = krt_sock_hook;
|
||||||
|
sk_rt->fd = rt_sock;
|
||||||
|
sk_rt->data = x;
|
||||||
|
if (sk_open(sk_rt))
|
||||||
|
bug("krt-sock: sk_open failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sys_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
||||||
{
|
{
|
||||||
if (!krt_buffer)
|
if (!krt_buffer)
|
||||||
return;
|
return;
|
||||||
|
@ -762,23 +742,14 @@ krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
||||||
krt_buffer = NULL;
|
krt_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_if_io_init(void)
|
kif_sys_start(struct kif_proto *p UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_if_construct(struct kif_config *c UNUSED)
|
kif_sys_shutdown(struct kif_proto *p UNUSED)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_start(struct kif_proto *p UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_shutdown(struct kif_proto *p UNUSED)
|
|
||||||
{
|
{
|
||||||
if (!kif_buffer)
|
if (!kif_buffer)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Route Syncer -- Setting
|
|
||||||
*
|
|
||||||
* (c) 2004 Ondrej Filip <feela@network.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SOCK_H_
|
|
||||||
#define _BIRD_KRT_SOCK_H_
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
#include "lib/socket.h"
|
|
||||||
|
|
||||||
#ifndef RTAX_MAX
|
|
||||||
#define RTAX_MAX 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct ks_msg
|
|
||||||
{
|
|
||||||
struct rt_msghdr rtm;
|
|
||||||
struct sockaddr_storage buf[RTAX_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern int krt_set_sock;
|
|
||||||
|
|
||||||
struct krt_set_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_set_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
|
||||||
static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
|
|
||||||
|
|
||||||
void krt_read_msg(struct proto *p, struct ks_msg *msg, int scan);
|
|
||||||
|
|
||||||
#endif
|
|
49
sysdep/bsd/krt-sys.h
Normal file
49
sysdep/bsd/krt-sys.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* BIRD -- *BSD Kernel Route Syncer
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_KRT_SYS_H_
|
||||||
|
#define _BIRD_KRT_SYS_H_
|
||||||
|
|
||||||
|
|
||||||
|
/* Kernel interfaces */
|
||||||
|
|
||||||
|
struct kif_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kif_status {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline void kif_sys_init(struct kif_proto *p UNUSED) { }
|
||||||
|
static inline int kif_sys_reconfigure(struct kif_proto *p UNUSED, struct kif_config *n UNUSED, struct kif_config *o UNUSED) { return 1; }
|
||||||
|
|
||||||
|
static inline void kif_sys_preconfig(struct config *c UNUSED) { }
|
||||||
|
static inline void kif_sys_postconfig(struct kif_config *c UNUSED) { }
|
||||||
|
static inline void kif_sys_init_config(struct kif_config *c UNUSED) { }
|
||||||
|
static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
|
||||||
|
|
||||||
|
|
||||||
|
/* Kernel routes */
|
||||||
|
|
||||||
|
struct krt_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_status {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
||||||
|
static inline int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n UNUSED, struct krt_config *o UNUSED) { return 1; }
|
||||||
|
|
||||||
|
static inline void krt_sys_preconfig(struct config *c UNUSED) { }
|
||||||
|
static inline void krt_sys_postconfig(struct krt_config *c UNUSED) { }
|
||||||
|
static inline void krt_sys_init_config(struct krt_config *c UNUSED) { }
|
||||||
|
static inline void krt_sys_copy_config(struct krt_config *d UNUSED, struct krt_config *s UNUSED) { }
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,19 +5,9 @@ CONFIG_AUTO_ROUTES Device routes are added automagically by the kernel
|
||||||
CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us
|
CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us
|
||||||
CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
|
CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
|
||||||
CONFIG_ALL_TABLES_AT_ONCE Kernel scanner wants to process all tables at once
|
CONFIG_ALL_TABLES_AT_ONCE Kernel scanner wants to process all tables at once
|
||||||
|
|
||||||
CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
|
CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
|
||||||
CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
|
|
||||||
|
|
||||||
CONFIG_UNIX_IFACE Use Unix interface scanner
|
|
||||||
CONFIG_UNIX_SET Use Unix route setting
|
|
||||||
CONFIG_UNIX_DONTROUTE Use setsockopts DONTROUTE (undef for *BSD)
|
|
||||||
CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD)
|
CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD)
|
||||||
CONFIG_LINUX_SCAN Use Linux /proc/net/route scanner
|
CONFIG_UNIX_DONTROUTE Use setsockopts DONTROUTE (undef for *BSD)
|
||||||
|
|
||||||
CONFIG_ALL_MULTICAST krt-iface: All devices support multicasting (i.e., ignore IFF_MULTICAST)
|
|
||||||
CONFIG_UNNUM_MULTICAST krt-iface: We support multicasts on unnumbered PtP devices
|
|
||||||
|
|
||||||
CONFIG_LINUX_MC_MREQN Linux: Use struct mreqn for multicasting
|
|
||||||
CONFIG_LINUX_MC_MREQ Linux: Use struct mreq
|
|
||||||
CONFIG_LINUX_MC_MREQ_BIND Linux: Use struct mreq and SO_BINDTODEVICE
|
|
||||||
|
|
||||||
|
CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
|
||||||
|
|
|
@ -10,14 +10,8 @@
|
||||||
|
|
||||||
#define CONFIG_AUTO_ROUTES
|
#define CONFIG_AUTO_ROUTES
|
||||||
#define CONFIG_SELF_CONSCIOUS
|
#define CONFIG_SELF_CONSCIOUS
|
||||||
#undef CONFIG_MULTIPLE_TABLES
|
|
||||||
|
|
||||||
#undef CONFIG_UNIX_IFACE
|
|
||||||
#undef CONFIG_UNIX_SET
|
|
||||||
|
|
||||||
#define CONFIG_SKIP_MC_BIND
|
#define CONFIG_SKIP_MC_BIND
|
||||||
#define CONFIG_ALL_MULTICAST
|
|
||||||
#define CONFIG_UNNUM_MULTICAST
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Link: sysdep/unix
|
Link: sysdep/unix
|
||||||
|
|
|
@ -8,15 +8,8 @@
|
||||||
|
|
||||||
#define CONFIG_AUTO_ROUTES
|
#define CONFIG_AUTO_ROUTES
|
||||||
#define CONFIG_SELF_CONSCIOUS
|
#define CONFIG_SELF_CONSCIOUS
|
||||||
#undef CONFIG_MULTIPLE_TABLES
|
|
||||||
|
|
||||||
#undef CONFIG_UNIX_IFACE
|
|
||||||
#undef CONFIG_UNIX_SET
|
|
||||||
#undef CONFIG_UNIX_DONTROUTE
|
|
||||||
|
|
||||||
#define CONFIG_SKIP_MC_BIND
|
#define CONFIG_SKIP_MC_BIND
|
||||||
#define CONFIG_ALL_MULTICAST
|
|
||||||
#define CONFIG_UNNUM_MULTICAST
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Link: sysdep/unix
|
Link: sysdep/unix
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Configuration for Linux 2.0 based systems
|
|
||||||
*
|
|
||||||
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef CONFIG_AUTO_ROUTES
|
|
||||||
#undef CONFIG_SELF_CONSCIOUS
|
|
||||||
#undef CONFIG_MULTIPLE_TABLES
|
|
||||||
|
|
||||||
#define CONFIG_UNIX_IFACE
|
|
||||||
#define CONFIG_UNIX_SET
|
|
||||||
#define CONFIG_UNIX_DONTROUTE
|
|
||||||
#undef CONFIG_SKIP_MC_BIND
|
|
||||||
#define CONFIG_LINUX_SCAN
|
|
||||||
|
|
||||||
#define CONFIG_LINUX_MC_MREQ_BIND
|
|
||||||
#define CONFIG_ALL_MULTICAST
|
|
||||||
#define CONFIG_UNNUM_MULTICAST
|
|
||||||
|
|
||||||
/*
|
|
||||||
Link: sysdep/linux
|
|
||||||
Link: sysdep/unix
|
|
||||||
*/
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Configuration for Linux 2.1/2.2 based systems without Netlink
|
|
||||||
*
|
|
||||||
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CONFIG_AUTO_ROUTES
|
|
||||||
#undef CONFIG_SELF_CONSCIOUS
|
|
||||||
#undef CONFIG_MULTIPLE_TABLES
|
|
||||||
|
|
||||||
#define CONFIG_UNIX_IFACE
|
|
||||||
#define CONFIG_UNIX_SET
|
|
||||||
#define CONFIG_UNIX_DONTROUTE
|
|
||||||
#undef CONFIG_SKIP_MC_BIND
|
|
||||||
#define CONFIG_LINUX_SCAN
|
|
||||||
|
|
||||||
#define CONFIG_LINUX_MC_MREQN
|
|
||||||
#define CONFIG_ALL_MULTICAST
|
|
||||||
#define CONFIG_UNNUM_MULTICAST
|
|
||||||
|
|
||||||
/*
|
|
||||||
Link: sysdep/linux
|
|
||||||
Link: sysdep/unix
|
|
||||||
*/
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Configuration for Linux 2.2 based systems running IPv6
|
* Configuration for Linux based systems running IPv6
|
||||||
*
|
*
|
||||||
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
||||||
*
|
*
|
||||||
|
@ -9,20 +9,13 @@
|
||||||
#define IPV6
|
#define IPV6
|
||||||
|
|
||||||
#define CONFIG_AUTO_ROUTES
|
#define CONFIG_AUTO_ROUTES
|
||||||
#define CONFIG_ALL_MULTICAST
|
|
||||||
#define CONFIG_SELF_CONSCIOUS
|
#define CONFIG_SELF_CONSCIOUS
|
||||||
|
|
||||||
/*
|
|
||||||
* Netlink supports multiple tables, but kernel IPv6 code doesn't, so we
|
|
||||||
* treat it as a multiple table system with number of tables set to 1.
|
|
||||||
*/
|
|
||||||
#define CONFIG_MULTIPLE_TABLES
|
#define CONFIG_MULTIPLE_TABLES
|
||||||
#define CONFIG_ALL_TABLES_AT_ONCE
|
#define CONFIG_ALL_TABLES_AT_ONCE
|
||||||
|
|
||||||
#define CONFIG_RESTRICTED_PRIVILEGES
|
#define CONFIG_RESTRICTED_PRIVILEGES
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Link: sysdep/linux/netlink
|
|
||||||
Link: sysdep/linux
|
Link: sysdep/linux
|
||||||
Link: sysdep/unix
|
Link: sysdep/unix
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Configuration for Linux 2.2 based systems
|
* Configuration for Linux based systems
|
||||||
*
|
*
|
||||||
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
||||||
*
|
*
|
||||||
|
@ -10,17 +10,13 @@
|
||||||
#define CONFIG_SELF_CONSCIOUS
|
#define CONFIG_SELF_CONSCIOUS
|
||||||
#define CONFIG_MULTIPLE_TABLES
|
#define CONFIG_MULTIPLE_TABLES
|
||||||
#define CONFIG_ALL_TABLES_AT_ONCE
|
#define CONFIG_ALL_TABLES_AT_ONCE
|
||||||
|
|
||||||
#define CONFIG_MC_PROPER_SRC
|
#define CONFIG_MC_PROPER_SRC
|
||||||
|
|
||||||
#undef CONFIG_SKIP_MC_BIND
|
|
||||||
|
|
||||||
#define CONFIG_LINUX_MC_MREQN
|
|
||||||
#define CONFIG_UNIX_DONTROUTE
|
#define CONFIG_UNIX_DONTROUTE
|
||||||
|
|
||||||
#define CONFIG_RESTRICTED_PRIVILEGES
|
#define CONFIG_RESTRICTED_PRIVILEGES
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Link: sysdep/linux/netlink
|
|
||||||
Link: sysdep/linux
|
Link: sysdep/linux
|
||||||
Link: sysdep/unix
|
Link: sysdep/unix
|
||||||
*/
|
*/
|
|
@ -37,23 +37,4 @@ typedef u16 word;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Path to configuration file */
|
|
||||||
#ifdef IPV6
|
|
||||||
# ifdef DEBUGGING
|
|
||||||
# define PATH_CONFIG "bird6.conf"
|
|
||||||
# define PATH_CONTROL_SOCKET "bird6.ctl"
|
|
||||||
# else
|
|
||||||
# define PATH_CONFIG PATH_CONFIG_DIR "/bird6.conf"
|
|
||||||
# define PATH_CONTROL_SOCKET PATH_CONTROL_SOCKET_DIR "/bird6.ctl"
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# ifdef DEBUGGING
|
|
||||||
# define PATH_CONFIG "bird.conf"
|
|
||||||
# define PATH_CONTROL_SOCKET "bird.ctl"
|
|
||||||
# else
|
|
||||||
# define PATH_CONFIG PATH_CONFIG_DIR "/bird.conf"
|
|
||||||
# define PATH_CONTROL_SOCKET PATH_CONTROL_SOCKET_DIR "/bird.ctl"
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#ifdef CONFIG_LINUX_SCAN
|
krt-sys.h
|
||||||
krt-scan.c
|
netlink.c
|
||||||
krt-scan.h
|
netlink.Y
|
||||||
#endif
|
|
||||||
sysio.h
|
sysio.h
|
||||||
syspriv.h
|
syspriv.h
|
||||||
|
|
|
@ -1,199 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Linux Routing Table Scanning
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
|
|
||||||
#undef LOCAL_DEBUG
|
|
||||||
|
|
||||||
#include "nest/bird.h"
|
|
||||||
#include "nest/route.h"
|
|
||||||
#include "nest/protocol.h"
|
|
||||||
#include "nest/iface.h"
|
|
||||||
#include "lib/timer.h"
|
|
||||||
#include "lib/unix.h"
|
|
||||||
#include "lib/krt.h"
|
|
||||||
#include "lib/string.h"
|
|
||||||
|
|
||||||
static int krt_scan_fd = -1;
|
|
||||||
|
|
||||||
struct iface *
|
|
||||||
krt_temp_iface(struct krt_proto *p, char *name)
|
|
||||||
{
|
|
||||||
struct iface *i;
|
|
||||||
|
|
||||||
WALK_LIST(i, p->scan.temp_ifs)
|
|
||||||
if (!strcmp(i->name, name))
|
|
||||||
return i;
|
|
||||||
i = mb_allocz(p->p.pool, sizeof(struct iface));
|
|
||||||
strcpy(i->name, name);
|
|
||||||
add_tail(&p->scan.temp_ifs, &i->n);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
krt_parse_entry(byte *ent, struct krt_proto *p)
|
|
||||||
{
|
|
||||||
u32 dest0, gw0, mask0;
|
|
||||||
ip_addr dest, gw, mask;
|
|
||||||
unsigned int flags;
|
|
||||||
int masklen;
|
|
||||||
net *net;
|
|
||||||
byte *iface = ent;
|
|
||||||
rte *e;
|
|
||||||
|
|
||||||
if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
|
|
||||||
{
|
|
||||||
log(L_ERR "krt read: unable to parse `%s'", ent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (*ent != '\t')
|
|
||||||
ent++;
|
|
||||||
*ent = 0;
|
|
||||||
|
|
||||||
dest = ipa_from_u32(dest0);
|
|
||||||
ipa_ntoh(dest);
|
|
||||||
gw = ipa_from_u32(gw0);
|
|
||||||
ipa_ntoh(gw);
|
|
||||||
mask = ipa_from_u32(mask0);
|
|
||||||
ipa_ntoh(mask);
|
|
||||||
if ((masklen = ipa_mklen(mask)) < 0)
|
|
||||||
{
|
|
||||||
log(L_ERR "krt read: invalid netmask %08x", mask0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DBG("Got %I/%d via %I flags %x\n", dest, masklen, gw, flags);
|
|
||||||
|
|
||||||
if (!(flags & RTF_UP))
|
|
||||||
{
|
|
||||||
DBG("Down.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (flags & RTF_HOST)
|
|
||||||
masklen = 32;
|
|
||||||
if (flags & (RTF_DYNAMIC | RTF_MODIFIED)) /* Redirect route */
|
|
||||||
{
|
|
||||||
log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
net = net_get(p->p.table, dest, masklen);
|
|
||||||
|
|
||||||
rta a = {
|
|
||||||
.proto = &p->p,
|
|
||||||
.source = RTS_INHERIT,
|
|
||||||
.scope = SCOPE_UNIVERSE,
|
|
||||||
.cast = RTC_UNICAST
|
|
||||||
};
|
|
||||||
|
|
||||||
if (flags & RTF_GATEWAY)
|
|
||||||
{
|
|
||||||
neighbor *ng = neigh_find(&p->p, &gw, 0);
|
|
||||||
if (ng && ng->scope)
|
|
||||||
a.iface = ng->iface;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
a.dest = RTD_ROUTER;
|
|
||||||
a.gw = gw;
|
|
||||||
}
|
|
||||||
else if (flags & RTF_REJECT)
|
|
||||||
{
|
|
||||||
a.dest = RTD_UNREACHABLE;
|
|
||||||
a.gw = IPA_NONE;
|
|
||||||
}
|
|
||||||
else if (isalpha(iface[0]))
|
|
||||||
{
|
|
||||||
a.dest = RTD_DEVICE;
|
|
||||||
a.gw = IPA_NONE;
|
|
||||||
a.iface = krt_temp_iface(p, iface);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = rte_get_temp(&a);
|
|
||||||
e->net = net;
|
|
||||||
e->u.krt.src = KRT_SRC_UNKNOWN;
|
|
||||||
krt_got_route(p, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_fire(struct krt_proto *p)
|
|
||||||
{
|
|
||||||
byte buf[32768];
|
|
||||||
int l, seen_hdr;
|
|
||||||
|
|
||||||
if (krt_scan_fd < 0)
|
|
||||||
{
|
|
||||||
krt_scan_fd = open("/proc/net/route", O_RDONLY);
|
|
||||||
if (krt_scan_fd < 0)
|
|
||||||
die("/proc/net/route: %m");
|
|
||||||
}
|
|
||||||
else if (lseek(krt_scan_fd, 0, SEEK_SET) < 0)
|
|
||||||
{
|
|
||||||
log(L_ERR "krt seek: %m");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
seen_hdr = 0;
|
|
||||||
while ((l = read(krt_scan_fd, buf, sizeof(buf))) > 0)
|
|
||||||
{
|
|
||||||
byte *z = buf;
|
|
||||||
if (l & 127)
|
|
||||||
{
|
|
||||||
log(L_ERR "krt read: misaligned entry: l=%d", l);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (l >= 128)
|
|
||||||
{
|
|
||||||
if (seen_hdr++)
|
|
||||||
krt_parse_entry(z, p);
|
|
||||||
z += 128;
|
|
||||||
l -= 128;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l < 0)
|
|
||||||
{
|
|
||||||
log(L_ERR "krt read: %m");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DBG("KRT scan done, seen %d lines\n", seen_hdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_construct(struct krt_config *c)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_preconfig(struct config *c)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_postconfig(struct krt_config *c)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_start(struct krt_proto *x, int first)
|
|
||||||
{
|
|
||||||
init_list(&x->scan.temp_ifs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_shutdown(struct krt_proto *x, int last)
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Linux Kernel Route Syncer -- Scanning
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SCAN_H_
|
|
||||||
#define _BIRD_KRT_SCAN_H_
|
|
||||||
|
|
||||||
struct krt_scan_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_scan_status {
|
|
||||||
list temp_ifs; /* Temporary interfaces */
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int krt_scan_params_same(struct krt_scan_params *o, struct krt_scan_params *n) { return 1; }
|
|
||||||
|
|
||||||
#endif
|
|
46
sysdep/linux/krt-sys.h
Normal file
46
sysdep/linux/krt-sys.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* BIRD -- Linux Kernel Netlink Route Syncer
|
||||||
|
*
|
||||||
|
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_KRT_SYS_H_
|
||||||
|
#define _BIRD_KRT_SYS_H_
|
||||||
|
|
||||||
|
|
||||||
|
/* Kernel interfaces */
|
||||||
|
|
||||||
|
struct kif_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kif_status {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline void kif_sys_init(struct kif_proto *p UNUSED) { }
|
||||||
|
static inline int kif_sys_reconfigure(struct kif_proto *p UNUSED, struct kif_config *n UNUSED, struct kif_config *o UNUSED) { return 1; }
|
||||||
|
|
||||||
|
static inline void kif_sys_preconfig(struct config *c UNUSED) { }
|
||||||
|
static inline void kif_sys_postconfig(struct kif_config *c UNUSED) { }
|
||||||
|
static inline void kif_sys_init_config(struct kif_config *c UNUSED) { }
|
||||||
|
static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_config *s UNUSED) { }
|
||||||
|
|
||||||
|
|
||||||
|
/* Kernel routes */
|
||||||
|
|
||||||
|
#define NL_NUM_TABLES 256
|
||||||
|
|
||||||
|
struct krt_params {
|
||||||
|
int table_id; /* Kernel table ID we sync with */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_status {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -20,7 +20,7 @@ nl_item:
|
||||||
KERNEL TABLE expr {
|
KERNEL TABLE expr {
|
||||||
if ($3 <= 0 || $3 >= NL_NUM_TABLES)
|
if ($3 <= 0 || $3 >= NL_NUM_TABLES)
|
||||||
cf_error("Kernel routing table number out of range");
|
cf_error("Kernel routing table number out of range");
|
||||||
THIS_KRT->scan.table_id = $3;
|
THIS_KRT->sys.table_id = $3;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -548,7 +548,7 @@ nl_parse_addr(struct nlmsghdr *h)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_if_scan(struct kif_proto *p UNUSED)
|
kif_do_scan(struct kif_proto *p UNUSED)
|
||||||
{
|
{
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||||
r.r.rtm_family = BIRD_AF;
|
r.r.rtm_family = BIRD_AF;
|
||||||
r.r.rtm_dst_len = net->n.pxlen;
|
r.r.rtm_dst_len = net->n.pxlen;
|
||||||
r.r.rtm_tos = 0;
|
r.r.rtm_tos = 0;
|
||||||
r.r.rtm_table = KRT_CF->scan.table_id;
|
r.r.rtm_table = KRT_CF->sys.table_id;
|
||||||
r.r.rtm_protocol = RTPROT_BIRD;
|
r.r.rtm_protocol = RTPROT_BIRD;
|
||||||
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
|
||||||
|
@ -687,7 +687,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_set_notify(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs)
|
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -940,7 +940,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_scan_fire(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
|
krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
|
||||||
{
|
{
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
|
|
||||||
|
@ -1084,36 +1084,9 @@ nl_open_async(void)
|
||||||
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
|
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_scan_preconfig(struct config *c UNUSED)
|
krt_sys_start(struct krt_proto *p, int first)
|
||||||
{
|
{
|
||||||
bzero(&nl_cf_table, sizeof(nl_cf_table));
|
nl_table_map[KRT_CF->sys.table_id] = p;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_postconfig(struct krt_config *x)
|
|
||||||
{
|
|
||||||
int id = x->scan.table_id;
|
|
||||||
|
|
||||||
if (nl_cf_table[id/8] & (1 << (id%8)))
|
|
||||||
cf_error("Multiple kernel syncers defined for table #%d", id);
|
|
||||||
nl_cf_table[id/8] |= (1 << (id%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_construct(struct krt_config *x)
|
|
||||||
{
|
|
||||||
#ifndef IPV6
|
|
||||||
x->scan.table_id = RT_TABLE_MAIN;
|
|
||||||
#else
|
|
||||||
x->scan.table_id = 254;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_scan_start(struct krt_proto *p, int first)
|
|
||||||
{
|
|
||||||
init_list(&p->scan.temp_ifs);
|
|
||||||
nl_table_map[KRT_CF->scan.table_id] = p;
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
nl_open();
|
nl_open();
|
||||||
|
@ -1122,13 +1095,55 @@ krt_scan_start(struct krt_proto *p, int first)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_scan_shutdown(struct krt_proto *p UNUSED, int last UNUSED)
|
krt_sys_shutdown(struct krt_proto *p UNUSED, int last UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
|
||||||
|
{
|
||||||
|
return n->sys.table_id == o->sys.table_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_if_start(struct kif_proto *p UNUSED)
|
krt_sys_preconfig(struct config *c UNUSED)
|
||||||
|
{
|
||||||
|
bzero(&nl_cf_table, sizeof(nl_cf_table));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sys_postconfig(struct krt_config *x)
|
||||||
|
{
|
||||||
|
int id = x->sys.table_id;
|
||||||
|
|
||||||
|
if (nl_cf_table[id/8] & (1 << (id%8)))
|
||||||
|
cf_error("Multiple kernel syncers defined for table #%d", id);
|
||||||
|
nl_cf_table[id/8] |= (1 << (id%8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sys_init_config(struct krt_config *cf)
|
||||||
|
{
|
||||||
|
cf->sys.table_id = RT_TABLE_MAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
|
||||||
|
{
|
||||||
|
d->sys.table_id = s->sys.table_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
kif_sys_start(struct kif_proto *p UNUSED)
|
||||||
{
|
{
|
||||||
nl_open();
|
nl_open();
|
||||||
nl_open_async();
|
nl_open_async();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kif_sys_shutdown(struct kif_proto *p UNUSED)
|
||||||
|
{
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
krt-iface.h
|
|
||||||
krt-set.h
|
|
||||||
krt-scan.h
|
|
||||||
netlink.c
|
|
||||||
netlink.Y
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Netlink Interface Syncer -- Dummy Include File
|
|
||||||
*
|
|
||||||
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_IFACE_H_
|
|
||||||
#define _BIRD_KRT_IFACE_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't have split iface/scan/set parts. See krt-scan.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct krt_if_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_if_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void krt_if_construct(struct kif_config *c UNUSED) { };
|
|
||||||
static inline void krt_if_shutdown(struct kif_proto *p UNUSED) { };
|
|
||||||
static inline void krt_if_io_init(void) { };
|
|
||||||
|
|
||||||
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
|
||||||
static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Linux Kernel Netlink Route Syncer -- Scanning
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SCAN_H_
|
|
||||||
#define _BIRD_KRT_SCAN_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't have split iface/scan/set for Netlink. All options
|
|
||||||
* and run-time parameters are declared here instead of splitting
|
|
||||||
* to krt-set.h, krt-iface.h and this file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NL_NUM_TABLES 256
|
|
||||||
|
|
||||||
struct krt_scan_params {
|
|
||||||
int table_id; /* Kernel table ID we sync with */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_scan_status {
|
|
||||||
list temp_ifs; /* Temporary interfaces */
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int krt_scan_params_same(struct krt_scan_params *o, struct krt_scan_params *n)
|
|
||||||
{
|
|
||||||
return o->table_id == n->table_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void krt_scan_copy_params(struct krt_scan_params *d UNUSED, struct krt_scan_params *s UNUSED) { }
|
|
||||||
/* table_id copied in krt_copy_config() */
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Netlink Route Syncer -- Dummy Include File
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SET_H_
|
|
||||||
#define _BIRD_KRT_SET_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't have split iface/scan/set parts. See krt-scan.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct krt_set_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_set_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void krt_set_construct(struct krt_config *c UNUSED) { };
|
|
||||||
static inline void krt_set_start(struct krt_proto *p UNUSED, int first UNUSED) { };
|
|
||||||
static inline void krt_set_shutdown(struct krt_proto *p UNUSED, int last UNUSED) { };
|
|
||||||
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
|
||||||
static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -57,45 +57,6 @@ get_inaddr(ip_addr *a, struct in_addr *ia)
|
||||||
ipa_ntoh(*a);
|
ipa_ntoh(*a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Multicasting in Linux systems is a real mess. Not only different kernels
|
|
||||||
* have different interfaces, but also different libc's export it in different
|
|
||||||
* ways. Horrible.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(CONFIG_LINUX_MC_MREQ) || defined(CONFIG_LINUX_MC_MREQ_BIND)
|
|
||||||
/*
|
|
||||||
* Older kernels support only struct mreq which matches interfaces by their
|
|
||||||
* addresses and thus fails on unnumbered devices. On newer 2.0 kernels
|
|
||||||
* we can use SO_BINDTODEVICE to circumvent this problem.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MREQ_IFA struct in_addr
|
|
||||||
#define MREQ_GRP struct ip_mreq
|
|
||||||
static inline void fill_mreq_ifa(struct in_addr *m, struct iface *ifa UNUSED, ip_addr saddr, ip_addr maddr UNUSED)
|
|
||||||
{
|
|
||||||
set_inaddr(m, saddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void fill_mreq_grp(struct ip_mreq *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
|
|
||||||
{
|
|
||||||
bzero(m, sizeof(*m));
|
|
||||||
#ifdef CONFIG_LINUX_MC_MREQ_BIND
|
|
||||||
m->imr_interface.s_addr = INADDR_ANY;
|
|
||||||
#else
|
|
||||||
set_inaddr(&m->imr_interface, saddr);
|
|
||||||
#endif
|
|
||||||
set_inaddr(&m->imr_multiaddr, maddr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_LINUX_MC_MREQN
|
|
||||||
/*
|
|
||||||
* 2.1 and newer kernels use struct mreqn which passes ifindex, so no
|
|
||||||
* problems with unnumbered devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_IP_MREQN
|
#ifndef HAVE_STRUCT_IP_MREQN
|
||||||
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
|
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
|
||||||
|
@ -107,24 +68,19 @@ struct ip_mreqn
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MREQ_IFA struct ip_mreqn
|
|
||||||
#define MREQ_GRP struct ip_mreqn
|
|
||||||
#define fill_mreq_ifa fill_mreq
|
|
||||||
#define fill_mreq_grp fill_mreq
|
|
||||||
|
|
||||||
static inline void fill_mreq(struct ip_mreqn *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
|
static inline void fill_mreqn(struct ip_mreqn *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
|
||||||
{
|
{
|
||||||
bzero(m, sizeof(*m));
|
bzero(m, sizeof(*m));
|
||||||
m->imr_ifindex = ifa->index;
|
m->imr_ifindex = ifa->index;
|
||||||
set_inaddr(&m->imr_address, saddr);
|
set_inaddr(&m->imr_address, saddr);
|
||||||
set_inaddr(&m->imr_multiaddr, maddr);
|
set_inaddr(&m->imr_multiaddr, maddr);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_setup_multicast(sock *s)
|
sysio_setup_multicast(sock *s)
|
||||||
{
|
{
|
||||||
MREQ_IFA m;
|
struct ip_mreqn m;
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
||||||
|
@ -134,18 +90,15 @@ sysio_setup_multicast(sock *s)
|
||||||
return "IP_MULTICAST_TTL";
|
return "IP_MULTICAST_TTL";
|
||||||
|
|
||||||
/* This defines where should we send _outgoing_ multicasts */
|
/* This defines where should we send _outgoing_ multicasts */
|
||||||
fill_mreq_ifa(&m, s->iface, s->saddr, IPA_NONE);
|
fill_mreqn(&m, s->iface, s->saddr, IPA_NONE);
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
||||||
return "IP_MULTICAST_IF";
|
return "IP_MULTICAST_IF";
|
||||||
|
|
||||||
#if defined(CONFIG_LINUX_MC_MREQ_BIND) || defined(CONFIG_LINUX_MC_MREQN)
|
/* Is this necessary? */
|
||||||
{
|
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
strcpy(ifr.ifr_name, s->iface->name);
|
strcpy(ifr.ifr_name, s->iface->name);
|
||||||
if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
|
if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
|
||||||
return "SO_BINDTODEVICE";
|
return "SO_BINDTODEVICE";
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -153,10 +106,10 @@ sysio_setup_multicast(sock *s)
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_join_group(sock *s, ip_addr maddr)
|
sysio_join_group(sock *s, ip_addr maddr)
|
||||||
{
|
{
|
||||||
MREQ_GRP m;
|
struct ip_mreqn m;
|
||||||
|
|
||||||
/* And this one sets interface for _receiving_ multicasts from */
|
/* And this one sets interface for _receiving_ multicasts from */
|
||||||
fill_mreq_grp(&m, s->iface, s->saddr, maddr);
|
fill_mreqn(&m, s->iface, s->saddr, maddr);
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
|
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
|
||||||
return "IP_ADD_MEMBERSHIP";
|
return "IP_ADD_MEMBERSHIP";
|
||||||
|
|
||||||
|
@ -166,10 +119,10 @@ sysio_join_group(sock *s, ip_addr maddr)
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_leave_group(sock *s, ip_addr maddr)
|
sysio_leave_group(sock *s, ip_addr maddr)
|
||||||
{
|
{
|
||||||
MREQ_GRP m;
|
struct ip_mreqn m;
|
||||||
|
|
||||||
/* And this one sets interface for _receiving_ multicasts from */
|
/* And this one sets interface for _receiving_ multicasts from */
|
||||||
fill_mreq_grp(&m, s->iface, s->saddr, maddr);
|
fill_mreqn(&m, s->iface, s->saddr, maddr);
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
|
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
|
||||||
return "IP_DROP_MEMBERSHIP";
|
return "IP_DROP_MEMBERSHIP";
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,3 @@ random.c
|
||||||
krt.c
|
krt.c
|
||||||
krt.h
|
krt.h
|
||||||
krt.Y
|
krt.Y
|
||||||
|
|
||||||
#ifdef CONFIG_UNIX_IFACE
|
|
||||||
krt-iface.c
|
|
||||||
krt-iface.h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_UNIX_SET
|
|
||||||
krt-set.c
|
|
||||||
krt-set.h
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,233 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Interface Scanning and Syncing
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
* (c) 2004 Ondrej Filip <feela@network.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#undef LOCAL_DEBUG
|
|
||||||
|
|
||||||
#include "nest/bird.h"
|
|
||||||
#include "nest/iface.h"
|
|
||||||
#include "nest/route.h"
|
|
||||||
#include "nest/protocol.h"
|
|
||||||
#include "lib/timer.h"
|
|
||||||
#include "lib/krt.h"
|
|
||||||
#include "lib/string.h"
|
|
||||||
|
|
||||||
#include "unix.h"
|
|
||||||
|
|
||||||
int if_scan_sock = -1;
|
|
||||||
|
|
||||||
static void
|
|
||||||
scan_ifs(struct ifreq *r, int cnt)
|
|
||||||
{
|
|
||||||
struct iface i, *pi;
|
|
||||||
struct ifa a;
|
|
||||||
char *err, *colon;
|
|
||||||
unsigned fl;
|
|
||||||
ip_addr netmask;
|
|
||||||
int l, scope;
|
|
||||||
sockaddr *sa;
|
|
||||||
|
|
||||||
if_start_update();
|
|
||||||
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
|
|
||||||
{
|
|
||||||
int sec = 0;
|
|
||||||
bzero(&i, sizeof(i));
|
|
||||||
bzero(&a, sizeof(a));
|
|
||||||
if (colon = strchr(r->ifr_name, ':'))
|
|
||||||
{
|
|
||||||
/* It's an alias -- let's interpret it as a secondary interface address */
|
|
||||||
sec = 1;
|
|
||||||
*colon = 0;
|
|
||||||
}
|
|
||||||
strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
|
|
||||||
|
|
||||||
if(ioctl(if_scan_sock, SIOCGIFADDR,r)<0) continue;
|
|
||||||
|
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL, 1);
|
|
||||||
if (ipa_nonzero(a.ip))
|
|
||||||
{
|
|
||||||
l = ipa_classify(a.ip);
|
|
||||||
if (l < 0 || !(l & IADDR_HOST))
|
|
||||||
{
|
|
||||||
log(L_ERR "%s: Invalid interface address", i.name);
|
|
||||||
a.ip = IPA_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
a.scope = l & IADDR_SCOPE_MASK;
|
|
||||||
if (a.scope == SCOPE_HOST)
|
|
||||||
i.flags |= IF_LOOPBACK | IF_IGNORE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
|
|
||||||
{
|
|
||||||
err = "SIOCGIFFLAGS";
|
|
||||||
faulty:
|
|
||||||
log(L_ERR "%s(%s): %m", err, i.name);
|
|
||||||
bad:
|
|
||||||
i.flags = (i.flags & ~IF_ADMIN_UP) | IF_SHUTDOWN;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fl = r->ifr_flags;
|
|
||||||
if (fl & IFF_UP)
|
|
||||||
i.flags |= IF_ADMIN_UP;
|
|
||||||
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
|
|
||||||
{ err = "SIOCGIFNETMASK"; goto faulty; }
|
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL, 0);
|
|
||||||
l = ipa_mklen(netmask);
|
|
||||||
if (l < 0)
|
|
||||||
{
|
|
||||||
log(L_ERR "%s: Invalid netmask (%x)", i.name, netmask);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
a.pxlen = l;
|
|
||||||
|
|
||||||
if (fl & IFF_POINTOPOINT)
|
|
||||||
{
|
|
||||||
a.flags |= IA_PEER;
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
|
|
||||||
{ err = "SIOCGIFDSTADDR"; goto faulty; }
|
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1);
|
|
||||||
a.prefix = a.opposite;
|
|
||||||
a.pxlen = BITS_PER_IP_ADDRESS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
|
|
||||||
if (fl & IFF_LOOPBACK)
|
|
||||||
i.flags |= IF_LOOPBACK | IF_IGNORE;
|
|
||||||
if (1
|
|
||||||
#ifndef CONFIG_ALL_MULTICAST
|
|
||||||
&& (fl & IFF_MULTICAST)
|
|
||||||
#endif
|
|
||||||
#ifndef CONFIG_UNNUM_MULTICAST
|
|
||||||
&& !(a.flags & IA_PEER)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
i.flags |= IF_MULTICAST;
|
|
||||||
|
|
||||||
scope = ipa_classify(a.ip);
|
|
||||||
if (scope < 0)
|
|
||||||
{
|
|
||||||
log(L_ERR "%s: Invalid address", i.name);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
a.scope = scope & IADDR_SCOPE_MASK;
|
|
||||||
|
|
||||||
if (a.pxlen < 32)
|
|
||||||
{
|
|
||||||
a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
|
|
||||||
if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd))
|
|
||||||
{
|
|
||||||
log(L_ERR "%s: Using network or broadcast address for interface", i.name);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
if (fl & IFF_BROADCAST)
|
|
||||||
i.flags |= IF_BROADCAST;
|
|
||||||
if (a.pxlen < 30)
|
|
||||||
i.flags |= IF_MULTIACCESS;
|
|
||||||
if (a.pxlen == 30)
|
|
||||||
ifa.opposite = ipa_opposite_m2(ifa.ip);
|
|
||||||
if (a.pxlen == 31)
|
|
||||||
ifa.opposite = ipa_opposite_m1(ifa.ip);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
a.brd = a.opposite;
|
|
||||||
a.scope = SCOPE_UNIVERSE;
|
|
||||||
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0)
|
|
||||||
{ err = "SIOCGIFMTU"; goto faulty; }
|
|
||||||
i.mtu = r->ifr_mtu;
|
|
||||||
|
|
||||||
#ifdef SIOCGIFINDEX
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFINDEX, r) >= 0)
|
|
||||||
i.index = r->ifr_ifindex;
|
|
||||||
else if (errno != EINVAL)
|
|
||||||
DBG("SIOCGIFINDEX failed: %m\n");
|
|
||||||
else /* defined, but not supported by the kernel */
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* The kernel doesn't give us real ifindices, but we still need them
|
|
||||||
* at least for OSPF unnumbered links. So let's make them up ourselves.
|
|
||||||
*/
|
|
||||||
if (pi = if_find_by_name(i.name))
|
|
||||||
i.index = pi->index;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static int if_index_counter = 1;
|
|
||||||
i.index = if_index_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
pi = NULL;
|
|
||||||
if (sec)
|
|
||||||
{
|
|
||||||
a.flags |= IA_SECONDARY;
|
|
||||||
pi = if_find_by_index(i.index);
|
|
||||||
}
|
|
||||||
if (!pi)
|
|
||||||
pi = if_update(&i);
|
|
||||||
a.iface = pi;
|
|
||||||
ifa_update(&a);
|
|
||||||
}
|
|
||||||
if_end_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_scan(struct kif_proto *p)
|
|
||||||
{
|
|
||||||
struct ifconf ic;
|
|
||||||
static int last_ifbuf_size = 4*sizeof(struct ifreq);
|
|
||||||
int res;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
ic.ifc_buf = alloca(last_ifbuf_size);
|
|
||||||
ic.ifc_len = last_ifbuf_size;
|
|
||||||
res = ioctl(if_scan_sock, SIOCGIFCONF, &ic);
|
|
||||||
if (res < 0 && errno != EFAULT)
|
|
||||||
die("SIOCCGIFCONF: %m");
|
|
||||||
if (res >= 0 && ic.ifc_len <= last_ifbuf_size)
|
|
||||||
break;
|
|
||||||
last_ifbuf_size *= 2;
|
|
||||||
DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
|
|
||||||
}
|
|
||||||
scan_ifs(ic.ifc_req, ic.ifc_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_construct(struct kif_config *c)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_start(struct kif_proto *p)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_shutdown(struct kif_proto *p)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_if_io_init(void)
|
|
||||||
{
|
|
||||||
if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
|
||||||
DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
|
|
||||||
if (if_scan_sock < 0)
|
|
||||||
die("Cannot create scanning socket: %m");
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Interface Syncer
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_IFACE_H_
|
|
||||||
#define _BIRD_KRT_IFACE_H_
|
|
||||||
|
|
||||||
struct krt_if_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_if_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int if_scan_sock;
|
|
||||||
|
|
||||||
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
|
||||||
static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Routing Table Syncing
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
|
|
||||||
#undef LOCAL_DEBUG
|
|
||||||
|
|
||||||
#include "nest/bird.h"
|
|
||||||
#include "nest/iface.h"
|
|
||||||
#include "nest/route.h"
|
|
||||||
#include "nest/protocol.h"
|
|
||||||
#include "lib/unix.h"
|
|
||||||
#include "lib/krt.h"
|
|
||||||
#include "lib/string.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
krt_capable(rte *e)
|
|
||||||
{
|
|
||||||
rta *a = e->attrs;
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUTO_ROUTES
|
|
||||||
if (a->source == RTS_DEVICE)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
return
|
|
||||||
a->cast == RTC_UNICAST &&
|
|
||||||
(a->dest == RTD_ROUTER
|
|
||||||
|| a->dest == RTD_DEVICE
|
|
||||||
#ifdef RTF_REJECT
|
|
||||||
|| a->dest == RTD_UNREACHABLE
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
krt_ioctl(int ioc, rte *e, char *name)
|
|
||||||
{
|
|
||||||
net *net = e->net;
|
|
||||||
struct rtentry re;
|
|
||||||
rta *a = e->attrs;
|
|
||||||
|
|
||||||
bzero(&re, sizeof(re));
|
|
||||||
fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
|
|
||||||
fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
|
|
||||||
re.rt_flags = RTF_UP;
|
|
||||||
if (net->n.pxlen == 32)
|
|
||||||
re.rt_flags |= RTF_HOST;
|
|
||||||
switch (a->dest)
|
|
||||||
{
|
|
||||||
case RTD_ROUTER:
|
|
||||||
fill_in_sockaddr((struct sockaddr_in *) &re.rt_gateway, a->gw, 0);
|
|
||||||
re.rt_flags |= RTF_GATEWAY;
|
|
||||||
break;
|
|
||||||
case RTD_DEVICE:
|
|
||||||
if (!a->iface)
|
|
||||||
return;
|
|
||||||
re.rt_dev = a->iface->name;
|
|
||||||
break;
|
|
||||||
#ifdef RTF_REJECT
|
|
||||||
case RTD_UNREACHABLE:
|
|
||||||
re.rt_flags |= RTF_REJECT;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
bug("krt set: unknown flags, but not filtered");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(if_scan_sock, ioc, &re) < 0)
|
|
||||||
log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_set_notify(struct krt_proto *p, net *net, rte *new, rte *old)
|
|
||||||
{
|
|
||||||
if (old)
|
|
||||||
{
|
|
||||||
DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
|
|
||||||
krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
|
|
||||||
}
|
|
||||||
if (new)
|
|
||||||
{
|
|
||||||
DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
|
|
||||||
krt_ioctl(SIOCADDRT, new, "SIOCADDRT");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_set_start(struct krt_proto *x, int first)
|
|
||||||
{
|
|
||||||
if (if_scan_sock < 0)
|
|
||||||
bug("krt set: missing socket");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_set_construct(struct krt_config *c)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_set_shutdown(struct krt_proto *x, int last)
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* BIRD -- Unix Kernel Route Syncer -- Setting
|
|
||||||
*
|
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
|
||||||
*
|
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BIRD_KRT_SET_H_
|
|
||||||
#define _BIRD_KRT_SET_H_
|
|
||||||
|
|
||||||
struct krt_set_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_set_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
|
||||||
static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -25,17 +25,7 @@ CF_GRAMMAR
|
||||||
|
|
||||||
CF_ADDTO(proto, kern_proto '}')
|
CF_ADDTO(proto, kern_proto '}')
|
||||||
|
|
||||||
kern_proto_start: proto_start KERNEL {
|
kern_proto_start: proto_start KERNEL { this_proto = krt_init_config($1); }
|
||||||
#ifndef CONFIG_MULTIPLE_TABLES
|
|
||||||
if (cf_krt)
|
|
||||||
cf_error("Kernel protocol already defined");
|
|
||||||
#endif
|
|
||||||
cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), $1);
|
|
||||||
THIS_KRT->scan_time = 60;
|
|
||||||
THIS_KRT->learn = THIS_KRT->persist = 0;
|
|
||||||
krt_scan_construct(THIS_KRT);
|
|
||||||
krt_set_construct(THIS_KRT);
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
CF_ADDTO(kern_proto, kern_proto_start proto_name '{')
|
CF_ADDTO(kern_proto, kern_proto_start proto_name '{')
|
||||||
|
@ -62,14 +52,7 @@ kern_item:
|
||||||
|
|
||||||
CF_ADDTO(proto, kif_proto '}')
|
CF_ADDTO(proto, kif_proto '}')
|
||||||
|
|
||||||
kif_proto_start: proto_start DEVICE {
|
kif_proto_start: proto_start DEVICE { this_proto = kif_init_config($1); }
|
||||||
if (cf_kif)
|
|
||||||
cf_error("Kernel device protocol already defined");
|
|
||||||
cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct kif_config), $1);
|
|
||||||
THIS_KIF->scan_time = 60;
|
|
||||||
init_list(&THIS_KIF->primary);
|
|
||||||
krt_if_construct(THIS_KIF);
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
CF_ADDTO(kif_proto, kif_proto_start proto_name '{')
|
CF_ADDTO(kif_proto, kif_proto_start proto_name '{')
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
* Either with a single routing table and single KRT protocol [traditional UNIX]
|
* Either with a single routing table and single KRT protocol [traditional UNIX]
|
||||||
* or with many routing tables and separate KRT protocols for all of them
|
* or with many routing tables and separate KRT protocols for all of them
|
||||||
* or with many routing tables, but every scan including all tables, so we start
|
* or with many routing tables, but every scan including all tables, so we start
|
||||||
* separate KRT protocols which cooperate with each other [Linux 2.2].
|
* separate KRT protocols which cooperate with each other [Linux].
|
||||||
* In this case, we keep only a single scan timer.
|
* In this case, we keep only a single scan timer.
|
||||||
*
|
*
|
||||||
* We use FIB node flags in the routing table to keep track of route
|
* We use FIB node flags in the routing table to keep track of route
|
||||||
|
@ -34,6 +34,15 @@
|
||||||
* When starting up, we cheat by looking if there is another
|
* When starting up, we cheat by looking if there is another
|
||||||
* KRT instance to be initialized later and performing table scan
|
* KRT instance to be initialized later and performing table scan
|
||||||
* only once for all the instances.
|
* only once for all the instances.
|
||||||
|
*
|
||||||
|
* The code uses OS-dependent parts for kernel updates and scans. These parts are
|
||||||
|
* in more specific sysdep directories (e.g. sysdep/linux) in functions krt_sys_*
|
||||||
|
* and kif_sys_* (and some others like krt_replace_rte()) and krt-sys.h header file.
|
||||||
|
* This is also used for platform specific protocol options and route attributes.
|
||||||
|
*
|
||||||
|
* There was also an old code that used traditional UNIX ioctls for these tasks.
|
||||||
|
* It was unmaintained and later removed. For reference, see sysdep/krt-* files
|
||||||
|
* in commit 396dfa9042305f62da1f56589c4b98fac57fc2f6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -66,25 +75,17 @@ krt_io_init(void)
|
||||||
{
|
{
|
||||||
krt_pool = rp_new(&root_pool, "Kernel Syncer");
|
krt_pool = rp_new(&root_pool, "Kernel Syncer");
|
||||||
krt_filter_lp = lp_new(krt_pool, 4080);
|
krt_filter_lp = lp_new(krt_pool, 4080);
|
||||||
krt_if_io_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interfaces
|
* Interfaces
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct proto_config *cf_kif;
|
static struct kif_config *kif_cf;
|
||||||
|
|
||||||
static struct kif_proto *kif_proto;
|
static struct kif_proto *kif_proto;
|
||||||
static timer *kif_scan_timer;
|
static timer *kif_scan_timer;
|
||||||
static bird_clock_t kif_last_shot;
|
static bird_clock_t kif_last_shot;
|
||||||
|
|
||||||
static void
|
|
||||||
kif_preconfig(struct protocol *P UNUSED, struct config *c UNUSED)
|
|
||||||
{
|
|
||||||
cf_kif = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kif_scan(timer *t)
|
kif_scan(timer *t)
|
||||||
{
|
{
|
||||||
|
@ -92,7 +93,7 @@ kif_scan(timer *t)
|
||||||
|
|
||||||
KRT_TRACE(p, D_EVENTS, "Scanning interfaces");
|
KRT_TRACE(p, D_EVENTS, "Scanning interfaces");
|
||||||
kif_last_shot = now;
|
kif_last_shot = now;
|
||||||
krt_if_scan(p);
|
kif_do_scan(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -112,45 +113,6 @@ kif_request_scan(void)
|
||||||
tm_start(kif_scan_timer, 1);
|
tm_start(kif_scan_timer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct proto *
|
|
||||||
kif_init(struct proto_config *c)
|
|
||||||
{
|
|
||||||
struct kif_proto *p = proto_new(c, sizeof(struct kif_proto));
|
|
||||||
return &p->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
kif_start(struct proto *P)
|
|
||||||
{
|
|
||||||
struct kif_proto *p = (struct kif_proto *) P;
|
|
||||||
|
|
||||||
kif_proto = p;
|
|
||||||
krt_if_start(p);
|
|
||||||
|
|
||||||
/* Start periodic interface scanning */
|
|
||||||
kif_scan_timer = tm_new(P->pool);
|
|
||||||
kif_scan_timer->hook = kif_scan;
|
|
||||||
kif_scan_timer->data = p;
|
|
||||||
kif_scan_timer->recurrent = KIF_CF->scan_time;
|
|
||||||
kif_scan(kif_scan_timer);
|
|
||||||
tm_start(kif_scan_timer, KIF_CF->scan_time);
|
|
||||||
|
|
||||||
return PS_UP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
kif_shutdown(struct proto *P)
|
|
||||||
{
|
|
||||||
struct kif_proto *p = (struct kif_proto *) P;
|
|
||||||
|
|
||||||
tm_stop(kif_scan_timer);
|
|
||||||
krt_if_shutdown(p);
|
|
||||||
kif_proto = NULL;
|
|
||||||
|
|
||||||
return PS_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
prefer_scope(struct ifa *a, struct ifa *b)
|
prefer_scope(struct ifa *a, struct ifa *b)
|
||||||
{ return (a->scope > SCOPE_LINK) && (b->scope <= SCOPE_LINK); }
|
{ return (a->scope > SCOPE_LINK) && (b->scope <= SCOPE_LINK); }
|
||||||
|
@ -193,13 +155,53 @@ kif_choose_primary(struct iface *i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct proto *
|
||||||
|
kif_init(struct proto_config *c)
|
||||||
|
{
|
||||||
|
struct kif_proto *p = proto_new(c, sizeof(struct kif_proto));
|
||||||
|
|
||||||
|
kif_sys_init(p);
|
||||||
|
return &p->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kif_start(struct proto *P)
|
||||||
|
{
|
||||||
|
struct kif_proto *p = (struct kif_proto *) P;
|
||||||
|
|
||||||
|
kif_proto = p;
|
||||||
|
kif_sys_start(p);
|
||||||
|
|
||||||
|
/* Start periodic interface scanning */
|
||||||
|
kif_scan_timer = tm_new(P->pool);
|
||||||
|
kif_scan_timer->hook = kif_scan;
|
||||||
|
kif_scan_timer->data = p;
|
||||||
|
kif_scan_timer->recurrent = KIF_CF->scan_time;
|
||||||
|
kif_scan(kif_scan_timer);
|
||||||
|
tm_start(kif_scan_timer, KIF_CF->scan_time);
|
||||||
|
|
||||||
|
return PS_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kif_shutdown(struct proto *P)
|
||||||
|
{
|
||||||
|
struct kif_proto *p = (struct kif_proto *) P;
|
||||||
|
|
||||||
|
tm_stop(kif_scan_timer);
|
||||||
|
kif_sys_shutdown(p);
|
||||||
|
kif_proto = NULL;
|
||||||
|
|
||||||
|
return PS_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kif_reconfigure(struct proto *p, struct proto_config *new)
|
kif_reconfigure(struct proto *p, struct proto_config *new)
|
||||||
{
|
{
|
||||||
struct kif_config *o = (struct kif_config *) p->cf;
|
struct kif_config *o = (struct kif_config *) p->cf;
|
||||||
struct kif_config *n = (struct kif_config *) new;
|
struct kif_config *n = (struct kif_config *) new;
|
||||||
|
|
||||||
if (!kif_params_same(&o->iface, &n->iface))
|
if (!kif_sys_reconfigure((struct kif_proto *) p, n, o))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (o->scan_time != n->scan_time)
|
if (o->scan_time != n->scan_time)
|
||||||
|
@ -224,6 +226,28 @@ kif_reconfigure(struct proto *p, struct proto_config *new)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
kif_preconfig(struct protocol *P UNUSED, struct config *c)
|
||||||
|
{
|
||||||
|
kif_cf = NULL;
|
||||||
|
kif_sys_preconfig(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct proto_config *
|
||||||
|
kif_init_config(int class)
|
||||||
|
{
|
||||||
|
if (kif_cf)
|
||||||
|
cf_error("Kernel device protocol already defined");
|
||||||
|
|
||||||
|
kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, sizeof(struct kif_config), class);
|
||||||
|
kif_cf->scan_time = 60;
|
||||||
|
init_list(&kif_cf->primary);
|
||||||
|
|
||||||
|
kif_sys_init_config(kif_cf);
|
||||||
|
return (struct proto_config *) kif_cf;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kif_copy_config(struct proto_config *dest, struct proto_config *src)
|
kif_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
{
|
{
|
||||||
|
@ -231,13 +255,13 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
struct kif_config *s = (struct kif_config *) src;
|
struct kif_config *s = (struct kif_config *) src;
|
||||||
|
|
||||||
/* Shallow copy of everything (just scan_time currently) */
|
/* Shallow copy of everything (just scan_time currently) */
|
||||||
proto_copy_rest(dest, src, sizeof(struct krt_config));
|
proto_copy_rest(dest, src, sizeof(struct kif_config));
|
||||||
|
|
||||||
/* Copy primary addr list */
|
/* Copy primary addr list */
|
||||||
cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item));
|
cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item));
|
||||||
|
|
||||||
/* Fix sysdep parts */
|
/* Fix sysdep parts */
|
||||||
kif_copy_params(&d->iface, &s->iface);
|
kif_sys_copy_config(d, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -551,18 +575,13 @@ krt_flush_routes(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
net *n = (net *) f;
|
net *n = (net *) f;
|
||||||
rte *e = n->routes;
|
rte *e = n->routes;
|
||||||
if (e)
|
if (e && (n->n.flags & KRF_INSTALLED))
|
||||||
{
|
|
||||||
rta *a = e->attrs;
|
|
||||||
if ((n->n.flags & KRF_INSTALLED) &&
|
|
||||||
a->source != RTS_DEVICE && a->source != RTS_INHERIT)
|
|
||||||
{
|
{
|
||||||
/* FIXME: this does not work if gw is changed in export filter */
|
/* FIXME: this does not work if gw is changed in export filter */
|
||||||
krt_set_notify(p, e->net, NULL, e, NULL);
|
krt_replace_rte(p, e->net, NULL, e, NULL);
|
||||||
n->n.flags &= ~KRF_INSTALLED;
|
n->n.flags &= ~KRF_INSTALLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,7 +736,7 @@ krt_prune(struct krt_proto *p)
|
||||||
if (new && (f->flags & KRF_INSTALLED))
|
if (new && (f->flags & KRF_INSTALLED))
|
||||||
{
|
{
|
||||||
krt_trace_in(p, new, "reinstalling");
|
krt_trace_in(p, new, "reinstalling");
|
||||||
krt_set_notify(p, n, new, NULL, tmpa);
|
krt_replace_rte(p, n, new, NULL, tmpa);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KRF_SEEN:
|
case KRF_SEEN:
|
||||||
|
@ -726,11 +745,11 @@ krt_prune(struct krt_proto *p)
|
||||||
break;
|
break;
|
||||||
case KRF_UPDATE:
|
case KRF_UPDATE:
|
||||||
krt_trace_in(p, new, "updating");
|
krt_trace_in(p, new, "updating");
|
||||||
krt_set_notify(p, n, new, old, tmpa);
|
krt_replace_rte(p, n, new, old, tmpa);
|
||||||
break;
|
break;
|
||||||
case KRF_DELETE:
|
case KRF_DELETE:
|
||||||
krt_trace_in(p, old, "deleting");
|
krt_trace_in(p, old, "deleting");
|
||||||
krt_set_notify(p, n, NULL, old, NULL);
|
krt_replace_rte(p, n, NULL, old, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bug("krt_prune: invalid route status");
|
bug("krt_prune: invalid route status");
|
||||||
|
@ -766,7 +785,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
krt_trace_in(p, e, "[redirect] deleting");
|
krt_trace_in(p, e, "[redirect] deleting");
|
||||||
krt_set_notify(p, net, NULL, e, NULL);
|
krt_replace_rte(p, net, NULL, e, NULL);
|
||||||
}
|
}
|
||||||
/* If !new, it is probably echo of our deletion */
|
/* If !new, it is probably echo of our deletion */
|
||||||
break;
|
break;
|
||||||
|
@ -800,7 +819,7 @@ krt_scan(timer *t UNUSED)
|
||||||
p = SKIP_BACK(struct krt_proto, instance_node, HEAD(krt_instance_list));
|
p = SKIP_BACK(struct krt_proto, instance_node, HEAD(krt_instance_list));
|
||||||
if (p->instance_node.next)
|
if (p->instance_node.next)
|
||||||
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
|
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
|
||||||
krt_scan_fire(NULL);
|
krt_do_scan(NULL);
|
||||||
WALK_LIST(q, krt_instance_list)
|
WALK_LIST(q, krt_instance_list)
|
||||||
{
|
{
|
||||||
p = SKIP_BACK(struct krt_proto, instance_node, q);
|
p = SKIP_BACK(struct krt_proto, instance_node, q);
|
||||||
|
@ -810,14 +829,45 @@ krt_scan(timer *t UNUSED)
|
||||||
#else
|
#else
|
||||||
p = t->data;
|
p = t->data;
|
||||||
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
|
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
|
||||||
krt_scan_fire(p);
|
krt_do_scan(p);
|
||||||
krt_prune(p);
|
krt_prune(p);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates
|
* Updates
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static struct ea_list *
|
||||||
|
krt_make_tmp_attrs(rte *rt, struct linpool *pool)
|
||||||
|
{
|
||||||
|
struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr));
|
||||||
|
|
||||||
|
l->next = NULL;
|
||||||
|
l->flags = EALF_SORTED;
|
||||||
|
l->count = 2;
|
||||||
|
|
||||||
|
l->attrs[0].id = EA_KRT_SOURCE;
|
||||||
|
l->attrs[0].flags = 0;
|
||||||
|
l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
|
||||||
|
l->attrs[0].u.data = rt->u.krt.proto;
|
||||||
|
|
||||||
|
l->attrs[1].id = EA_KRT_METRIC;
|
||||||
|
l->attrs[1].flags = 0;
|
||||||
|
l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP;
|
||||||
|
l->attrs[1].u.data = rt->u.krt.metric;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
|
||||||
|
{
|
||||||
|
/* EA_KRT_SOURCE is read-only */
|
||||||
|
rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
|
krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
|
||||||
{
|
{
|
||||||
|
@ -853,37 +903,37 @@ krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
|
||||||
else
|
else
|
||||||
net->n.flags &= ~KRF_INSTALLED;
|
net->n.flags &= ~KRF_INSTALLED;
|
||||||
if (p->initialized) /* Before first scan we don't touch the routes */
|
if (p->initialized) /* Before first scan we don't touch the routes */
|
||||||
krt_set_notify(p, net, new, old, eattrs);
|
krt_replace_rte(p, net, new, old, eattrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krt_rte_same(rte *a, rte *b)
|
||||||
|
{
|
||||||
|
/* src is always KRT_SRC_ALIEN and type is irrelevant */
|
||||||
|
return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Protocol glue
|
* Protocol glue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct proto_config *cf_krt;
|
struct krt_config *krt_cf;
|
||||||
|
|
||||||
static void
|
static struct proto *
|
||||||
krt_preconfig(struct protocol *P UNUSED, struct config *c)
|
krt_init(struct proto_config *c)
|
||||||
{
|
{
|
||||||
cf_krt = NULL;
|
struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
|
||||||
krt_scan_preconfig(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
p->p.accept_ra_types = RA_OPTIMAL;
|
||||||
krt_postconfig(struct proto_config *C)
|
p->p.make_tmp_attrs = krt_make_tmp_attrs;
|
||||||
{
|
p->p.store_tmp_attrs = krt_store_tmp_attrs;
|
||||||
struct krt_config *c = (struct krt_config *) C;
|
p->p.import_control = krt_import_control;
|
||||||
|
p->p.rt_notify = krt_notify;
|
||||||
|
p->p.rte_same = krt_rte_same;
|
||||||
|
|
||||||
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
krt_sys_init(p);
|
||||||
struct krt_config *first = (struct krt_config *) cf_krt;
|
return &p->p;
|
||||||
if (first->scan_time != c->scan_time)
|
|
||||||
cf_error("All kernel syncers must use the same table scan interval");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (C->table->krt_attached)
|
|
||||||
cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name);
|
|
||||||
C->table->krt_attached = C;
|
|
||||||
krt_scan_postconfig(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static timer *
|
static timer *
|
||||||
|
@ -920,8 +970,7 @@ krt_start(struct proto *P)
|
||||||
krt_learn_init(p);
|
krt_learn_init(p);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
krt_scan_start(p, first);
|
krt_sys_start(p, first);
|
||||||
krt_set_start(p, first);
|
|
||||||
|
|
||||||
/* Start periodic routing table scanning */
|
/* Start periodic routing table scanning */
|
||||||
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
||||||
|
@ -955,8 +1004,7 @@ krt_shutdown(struct proto *P)
|
||||||
if (p->initialized && !KRT_CF->persist)
|
if (p->initialized && !KRT_CF->persist)
|
||||||
krt_flush_routes(p);
|
krt_flush_routes(p);
|
||||||
|
|
||||||
krt_set_shutdown(p, last);
|
krt_sys_shutdown(p, last);
|
||||||
krt_scan_shutdown(p, last);
|
|
||||||
|
|
||||||
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
||||||
if (last)
|
if (last)
|
||||||
|
@ -966,69 +1014,55 @@ krt_shutdown(struct proto *P)
|
||||||
return PS_DOWN;
|
return PS_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ea_list *
|
|
||||||
krt_make_tmp_attrs(rte *rt, struct linpool *pool)
|
|
||||||
{
|
|
||||||
struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr));
|
|
||||||
|
|
||||||
l->next = NULL;
|
|
||||||
l->flags = EALF_SORTED;
|
|
||||||
l->count = 2;
|
|
||||||
|
|
||||||
l->attrs[0].id = EA_KRT_SOURCE;
|
|
||||||
l->attrs[0].flags = 0;
|
|
||||||
l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
|
|
||||||
l->attrs[0].u.data = rt->u.krt.proto;
|
|
||||||
|
|
||||||
l->attrs[1].id = EA_KRT_METRIC;
|
|
||||||
l->attrs[1].flags = 0;
|
|
||||||
l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP;
|
|
||||||
l->attrs[1].u.data = rt->u.krt.metric;
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
|
|
||||||
{
|
|
||||||
/* EA_KRT_SOURCE is read-only */
|
|
||||||
rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
krt_rte_same(rte *a, rte *b)
|
|
||||||
{
|
|
||||||
/* src is always KRT_SRC_ALIEN and type is irrelevant */
|
|
||||||
return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct proto *
|
|
||||||
krt_init(struct proto_config *c)
|
|
||||||
{
|
|
||||||
struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
|
|
||||||
|
|
||||||
p->p.accept_ra_types = RA_OPTIMAL;
|
|
||||||
p->p.make_tmp_attrs = krt_make_tmp_attrs;
|
|
||||||
p->p.store_tmp_attrs = krt_store_tmp_attrs;
|
|
||||||
p->p.import_control = krt_import_control;
|
|
||||||
p->p.rt_notify = krt_notify;
|
|
||||||
p->p.rte_same = krt_rte_same;
|
|
||||||
|
|
||||||
return &p->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_reconfigure(struct proto *p, struct proto_config *new)
|
krt_reconfigure(struct proto *p, struct proto_config *new)
|
||||||
{
|
{
|
||||||
struct krt_config *o = (struct krt_config *) p->cf;
|
struct krt_config *o = (struct krt_config *) p->cf;
|
||||||
struct krt_config *n = (struct krt_config *) new;
|
struct krt_config *n = (struct krt_config *) new;
|
||||||
|
|
||||||
return o->scan_time == n->scan_time
|
if (!krt_sys_reconfigure((struct krt_proto *) p, n, o))
|
||||||
&& o->learn == n->learn /* persist needn't be the same */
|
return 0;
|
||||||
&& o->devroutes == n->devroutes
|
|
||||||
&& krt_set_params_same(&o->set, &n->set)
|
/* persist needn't be the same */
|
||||||
&& krt_scan_params_same(&o->scan, &n->scan)
|
return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
|
||||||
;
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
krt_preconfig(struct protocol *P UNUSED, struct config *c)
|
||||||
|
{
|
||||||
|
krt_cf = NULL;
|
||||||
|
krt_sys_preconfig(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
krt_postconfig(struct proto_config *C)
|
||||||
|
{
|
||||||
|
struct krt_config *c = (struct krt_config *) C;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ALL_TABLES_AT_ONCE
|
||||||
|
if (krt_cf->scan_time != c->scan_time)
|
||||||
|
cf_error("All kernel syncers must use the same table scan interval");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (C->table->krt_attached)
|
||||||
|
cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name);
|
||||||
|
C->table->krt_attached = C;
|
||||||
|
krt_sys_postconfig(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct proto_config *
|
||||||
|
krt_init_config(int class)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_MULTIPLE_TABLES
|
||||||
|
if (krt_cf)
|
||||||
|
cf_error("Kernel protocol already defined");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class);
|
||||||
|
krt_cf->scan_time = 60;
|
||||||
|
|
||||||
|
krt_sys_init_config(krt_cf);
|
||||||
|
return (struct proto_config *) krt_cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1041,8 +1075,7 @@ krt_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
proto_copy_rest(dest, src, sizeof(struct krt_config));
|
proto_copy_rest(dest, src, sizeof(struct krt_config));
|
||||||
|
|
||||||
/* Fix sysdep parts */
|
/* Fix sysdep parts */
|
||||||
krt_set_copy_params(&d->set, &s->set);
|
krt_sys_copy_config(d, s);
|
||||||
krt_scan_copy_params(&d->scan, &s->scan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -15,9 +15,7 @@ struct krt_proto;
|
||||||
struct kif_config;
|
struct kif_config;
|
||||||
struct kif_proto;
|
struct kif_proto;
|
||||||
|
|
||||||
#include "lib/krt-scan.h"
|
#include "lib/krt-sys.h"
|
||||||
#include "lib/krt-set.h"
|
|
||||||
#include "lib/krt-iface.h"
|
|
||||||
|
|
||||||
/* Flags stored in net->n.flags, rest are in nest/route.h */
|
/* Flags stored in net->n.flags, rest are in nest/route.h */
|
||||||
|
|
||||||
|
@ -45,8 +43,7 @@ extern struct protocol proto_unix_kernel;
|
||||||
|
|
||||||
struct krt_config {
|
struct krt_config {
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
struct krt_set_params set;
|
struct krt_params sys; /* Sysdep params */
|
||||||
struct krt_scan_params scan;
|
|
||||||
int persist; /* Keep routes when we exit */
|
int persist; /* Keep routes when we exit */
|
||||||
int scan_time; /* How often we re-scan routes */
|
int scan_time; /* How often we re-scan routes */
|
||||||
int learn; /* Learn routes from other sources */
|
int learn; /* Learn routes from other sources */
|
||||||
|
@ -55,9 +52,7 @@ struct krt_config {
|
||||||
|
|
||||||
struct krt_proto {
|
struct krt_proto {
|
||||||
struct proto p;
|
struct proto p;
|
||||||
struct krt_set_status set;
|
struct krt_status sys; /* Sysdep state */
|
||||||
struct krt_scan_status scan;
|
|
||||||
struct krt_if_status iface;
|
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
struct rtable krt_table; /* Internal table of inherited routes */
|
struct rtable krt_table; /* Internal table of inherited routes */
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,7 +64,6 @@ struct krt_proto {
|
||||||
int initialized; /* First scan has already been finished */
|
int initialized; /* First scan has already been finished */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct proto_config *cf_krt;
|
|
||||||
extern pool *krt_pool;
|
extern pool *krt_pool;
|
||||||
|
|
||||||
#define KRT_CF ((struct krt_config *)p->p.cf)
|
#define KRT_CF ((struct krt_config *)p->p.cf)
|
||||||
|
@ -79,6 +73,7 @@ extern pool *krt_pool;
|
||||||
if (pr->p.debug & fl) \
|
if (pr->p.debug & fl) \
|
||||||
{ log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0)
|
{ log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0)
|
||||||
|
|
||||||
|
struct proto_config * kif_init_config(int class);
|
||||||
void kif_request_scan(void);
|
void kif_request_scan(void);
|
||||||
void krt_got_route(struct krt_proto *p, struct rte *e);
|
void krt_got_route(struct krt_proto *p, struct rte *e);
|
||||||
void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
|
void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
|
||||||
|
@ -101,46 +96,49 @@ struct kif_primary_item {
|
||||||
|
|
||||||
struct kif_config {
|
struct kif_config {
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
struct krt_if_params iface;
|
struct kif_params sys; /* Sysdep params */
|
||||||
int scan_time; /* How often we re-scan interfaces */
|
int scan_time; /* How often we re-scan interfaces */
|
||||||
list primary; /* Preferences for primary addresses (struct kif_primary_item) */
|
list primary; /* Preferences for primary addresses (struct kif_primary_item) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kif_proto {
|
struct kif_proto {
|
||||||
struct proto p;
|
struct proto p;
|
||||||
struct krt_if_status iface;
|
struct kif_status sys; /* Sysdep state */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct proto_config *cf_kif;
|
|
||||||
|
|
||||||
#define KIF_CF ((struct kif_config *)p->p.cf)
|
#define KIF_CF ((struct kif_config *)p->p.cf)
|
||||||
|
|
||||||
/* krt-scan.c */
|
struct proto_config * krt_init_config(int class);
|
||||||
|
|
||||||
void krt_scan_preconfig(struct config *);
|
|
||||||
void krt_scan_postconfig(struct krt_config *);
|
|
||||||
void krt_scan_construct(struct krt_config *);
|
|
||||||
void krt_scan_start(struct krt_proto *, int);
|
|
||||||
void krt_scan_shutdown(struct krt_proto *, int);
|
|
||||||
|
|
||||||
void krt_scan_fire(struct krt_proto *);
|
/* krt sysdep */
|
||||||
|
|
||||||
/* krt-set.c */
|
void krt_sys_init(struct krt_proto *);
|
||||||
|
void krt_sys_start(struct krt_proto *, int);
|
||||||
|
void krt_sys_shutdown(struct krt_proto *, int);
|
||||||
|
int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o);
|
||||||
|
|
||||||
void krt_set_construct(struct krt_config *);
|
void krt_sys_preconfig(struct config *);
|
||||||
void krt_set_start(struct krt_proto *, int);
|
void krt_sys_postconfig(struct krt_config *);
|
||||||
void krt_set_shutdown(struct krt_proto *, int);
|
void krt_sys_init_config(struct krt_config *);
|
||||||
|
void krt_sys_copy_config(struct krt_config *, struct krt_config *);
|
||||||
|
|
||||||
int krt_capable(rte *e);
|
int krt_capable(rte *e);
|
||||||
void krt_set_notify(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs);
|
void krt_do_scan(struct krt_proto *);
|
||||||
|
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs);
|
||||||
|
|
||||||
/* krt-iface.c */
|
|
||||||
|
|
||||||
void krt_if_construct(struct kif_config *);
|
/* kif sysdep */
|
||||||
void krt_if_start(struct kif_proto *);
|
|
||||||
void krt_if_shutdown(struct kif_proto *);
|
void kif_sys_init(struct kif_proto *);
|
||||||
|
void kif_sys_start(struct kif_proto *);
|
||||||
|
void kif_sys_shutdown(struct kif_proto *);
|
||||||
|
int kif_sys_reconfigure(struct kif_proto *, struct kif_config *, struct kif_config *);
|
||||||
|
|
||||||
|
void kif_sys_init_config(struct kif_config *);
|
||||||
|
void kif_sys_copy_config(struct kif_config *, struct kif_config *);
|
||||||
|
|
||||||
|
void kif_do_scan(struct kif_proto *);
|
||||||
|
|
||||||
void krt_if_scan(struct kif_proto *);
|
|
||||||
void krt_if_io_init(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -151,7 +151,7 @@ read_iproute_table(char *file, char *prefix, int max)
|
||||||
#endif // PATH_IPROUTE_DIR
|
#endif // PATH_IPROUTE_DIR
|
||||||
|
|
||||||
|
|
||||||
static char *config_name = PATH_CONFIG;
|
static char *config_name = PATH_CONFIG_FILE;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cf_read(byte *dest, unsigned int len, int fd)
|
cf_read(byte *dest, unsigned int len, int fd)
|
||||||
|
|
|
@ -48,21 +48,21 @@ userdocs progdocs: .dir-stamp
|
||||||
|
|
||||||
sysdep/paths.h:
|
sysdep/paths.h:
|
||||||
echo >sysdep/paths.h "/* Generated by Makefile, don't edit manually! */"
|
echo >sysdep/paths.h "/* Generated by Makefile, don't edit manually! */"
|
||||||
echo >>sysdep/paths.h "#define PATH_CONFIG_DIR \"$(sysconfdir)\""
|
echo >>sysdep/paths.h "#define PATH_CONFIG_FILE \"@CONFIG_FILE@\""
|
||||||
echo >>sysdep/paths.h "#define PATH_CONTROL_SOCKET_DIR \"$(localstatedir)/run\""
|
echo >>sysdep/paths.h "#define PATH_CONTROL_SOCKET \"@CONTROL_SOCKET@\""
|
||||||
if test -n "@iproutedir@" ; then echo >>sysdep/paths.h "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
|
if test -n "@iproutedir@" ; then echo >>sysdep/paths.h "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
cd $(srcdir) ; etags -lc `find $(static-dirs) $(addprefix $(objdir)/,$(dynamic-dirs)) $(client-dirs) -name *.[chY]`
|
cd $(srcdir) ; etags -lc `find $(static-dirs) $(addprefix $(objdir)/,$(dynamic-dirs)) $(client-dirs) -name *.[chY]`
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
$(INSTALL) -d $(DESTDIR)/$(sbindir) $(DESTDIR)/$(sysconfdir) $(DESTDIR)/$(localstatedir)/run
|
$(INSTALL) -d $(DESTDIR)/$(sbindir) $(DESTDIR)/$(sysconfdir) $(DESTDIR)/@runtimedir@
|
||||||
$(INSTALL_PROGRAM) -s $(exedir)/bird $(DESTDIR)/$(sbindir)/bird@SUFFIX6@
|
$(INSTALL_PROGRAM) -s $(exedir)/bird $(DESTDIR)/$(sbindir)/bird@SUFFIX@
|
||||||
if test -n "@CLIENT@" ; then \
|
if test -n "@CLIENT@" ; then \
|
||||||
$(INSTALL_PROGRAM) -s $(exedir)/birdc $(DESTDIR)/$(sbindir)/birdc@SUFFIX6@ ; \
|
$(INSTALL_PROGRAM) -s $(exedir)/birdc $(DESTDIR)/$(sbindir)/birdc@SUFFIX@ ; \
|
||||||
fi
|
fi
|
||||||
if ! test -f $(DESTDIR)/$(sysconfdir)/bird@SUFFIX6@.conf ; then \
|
if ! test -f $(DESTDIR)/@CONFIG_FILE@ ; then \
|
||||||
$(INSTALL_DATA) $(srcdir)/doc/bird.conf.example $(DESTDIR)/$(sysconfdir)/bird@SUFFIX6@.conf ; \
|
$(INSTALL_DATA) $(srcdir)/doc/bird.conf.example $(DESTDIR)/@CONFIG_FILE@ ; \
|
||||||
else \
|
else \
|
||||||
echo "Not overwriting old bird@SUFFIX@.conf" ; \
|
echo "Not overwriting old bird@SUFFIX@.conf" ; \
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue