Merge commit '98bb80a243b58c43453e9be69d19d0350286549c' into int-new
This commit is contained in:
commit
4ff15a75c5
28 changed files with 795 additions and 133 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -11,3 +11,4 @@
|
||||||
/config.status
|
/config.status
|
||||||
/configure
|
/configure
|
||||||
/sysdep/autoconf.h.in
|
/sysdep/autoconf.h.in
|
||||||
|
/sysdep/autoconf.h.in~
|
||||||
|
|
349
.gitlab-ci.yml
Normal file
349
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
variables:
|
||||||
|
DEBIAN_FRONTEND: noninteractive
|
||||||
|
LC_ALL: C
|
||||||
|
GIT_STRATEGY: fetch
|
||||||
|
DOCKER_CMD: docker --config="$HOME/.docker/$CI_JOB_ID/"
|
||||||
|
IMG_BASE: registry.labs.nic.cz/labs/bird
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- image
|
||||||
|
- build
|
||||||
|
|
||||||
|
.docker: &docker_build
|
||||||
|
stage: image
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- $DOCKER_CMD login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.labs.nic.cz
|
||||||
|
# Make sure we refresh the base image if it updates (eg. security updates, etc)
|
||||||
|
# If we do just the build, cache is always reused and the freshness of the
|
||||||
|
# base image is never checked. However, pull always asks and updates the
|
||||||
|
# image only if it changed ‒ therefore, the cache is used unless there's a
|
||||||
|
# change.
|
||||||
|
- $DOCKER_CMD pull `sed -ne 's/^FROM //p' "misc/docker/$IMG_NAME/Dockerfile"`
|
||||||
|
- $DOCKER_CMD build -t "bird:$IMG_NAME" "misc/docker/$IMG_NAME"
|
||||||
|
- $DOCKER_CMD tag "bird:$IMG_NAME" "$IMG_BASE:$IMG_NAME"
|
||||||
|
- $DOCKER_CMD push "$IMG_BASE:$IMG_NAME"
|
||||||
|
after_script:
|
||||||
|
- rm -f "$HOME/.docker/$CI_JOB_ID/" # cleanup the credentials
|
||||||
|
tags:
|
||||||
|
# That's Docker in Docker
|
||||||
|
- dind
|
||||||
|
|
||||||
|
docker_debian-7-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-7-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-8-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-8-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-9-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-9-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-testing-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-testing-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-7-i386:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-7-i386"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-8-i386:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-8-i386"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-9-i386:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-9-i386"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_debian-testing-i386:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "debian-testing-i386"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_fedora-25-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "fedora-25-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_fedora-26-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "fedora-26-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_centos-6-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "centos-6-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_centos-7-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "centos-7-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_opensuse-42_3-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "opensuse-42.3-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_ubuntu-14_04-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "ubuntu-14.04-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
docker_ubuntu-16_04-amd64:
|
||||||
|
variables:
|
||||||
|
IMG_NAME: "ubuntu-16.04-amd64"
|
||||||
|
<<: *docker_build
|
||||||
|
|
||||||
|
.debian-7-i386: &debian-7-i386_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-7-i386
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-8-i386: &debian-8-i386_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-8-i386
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-9-i386: &debian-9-i386_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-9-i386
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-testing-i386: &debian-testing-i386_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-testing-i386
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-7-amd64: &debian-7-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-7-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-8-amd64: &debian-8-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-8-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-9-amd64: &debian-9-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-9-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.debian-testing-amd64: &debian-testing-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:debian-testing-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.fedora-25-amd64: &fedora-25-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:fedora-25-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.fedora-26-amd64: &fedora-26-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:fedora-26-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.centos-6-amd64: ¢os-6-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:centos-6-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.centos-7-amd64: ¢os-7-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:centos-7-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.opensuse-42_3-amd64: &opensuse-42_3-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:opensuse-42.3-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.ubuntu-14_04-amd64: &ubuntu-14_04-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:ubuntu-14.04-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
.ubuntu-16_04-amd64: &ubuntu-16_04-amd64_env
|
||||||
|
image: registry.labs.nic.cz/labs/bird:ubuntu-16.04-amd64
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
- amd64
|
||||||
|
|
||||||
|
# TODO We want to copy these BSDs to our own virtual machines, to make sure someone doesn't update them by accident.
|
||||||
|
.freebsd-11-i386: &freebsd-11-i386_env
|
||||||
|
variables:
|
||||||
|
CPPFLAGS: "-I/usr/local/include"
|
||||||
|
LDFLAGS: "-L/usr/local/lib"
|
||||||
|
tags:
|
||||||
|
- freebsd
|
||||||
|
- i386
|
||||||
|
#only:
|
||||||
|
#- master
|
||||||
|
#- triggers
|
||||||
|
#- tags
|
||||||
|
|
||||||
|
.freebsd-11-amd64: &freebsd-11-amd64_env
|
||||||
|
variables:
|
||||||
|
CPPFLAGS: "-I/usr/local/include"
|
||||||
|
LDFLAGS: "-L/usr/local/lib"
|
||||||
|
tags:
|
||||||
|
- freebsd
|
||||||
|
- amd64
|
||||||
|
#only:
|
||||||
|
#- master
|
||||||
|
#- triggers
|
||||||
|
#- tags
|
||||||
|
|
||||||
|
.build: &build_job
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- autoreconf
|
||||||
|
- ./configure CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS"
|
||||||
|
# Detect which make is available
|
||||||
|
- MAKE=make
|
||||||
|
- which gmake 2>/dev/null >/dev/null && MAKE=gmake
|
||||||
|
- $MAKE
|
||||||
|
# Run tests if they are available (eg. don't fail if "check" isn't a valid make target)
|
||||||
|
- $MAKE check || [ "$?" = 2 ]
|
||||||
|
|
||||||
|
build-debian-7-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-7-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-8-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-8-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-9-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-9-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-testing-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-testing-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-fedora-25-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *fedora-25-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-fedora-26-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *fedora-26-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-centos-6-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *centos-6-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-centos-7-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *centos-7-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-opensuse-42_3-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *opensuse-42_3-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-ubuntu-14_04-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *ubuntu-14_04-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-ubuntu-16_04-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *ubuntu-16_04-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-7-i386:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-7-i386_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-8-i386:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-8-i386_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-9-i386:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-9-i386_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-debian-testing-i386:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *debian-testing-i386_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-freebsd-11-amd64:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *freebsd-11-amd64_env
|
||||||
|
<<: *build_job
|
||||||
|
|
||||||
|
build-freebsd-11-i386:
|
||||||
|
variables:
|
||||||
|
IPV6: "no"
|
||||||
|
<<: *freebsd-11-i386_env
|
||||||
|
<<: *build_job
|
45
TODO
45
TODO
|
@ -1,45 +0,0 @@
|
||||||
Core
|
|
||||||
~~~~
|
|
||||||
- socket open failure should not be fatal
|
|
||||||
- &&,||: priorities
|
|
||||||
- static: allow specifying a per-route filter program for setting route attributes?
|
|
||||||
|
|
||||||
Globals
|
|
||||||
~~~~~~~
|
|
||||||
- right usage of DBG vs. debug
|
|
||||||
- logging and tracing; use appropriate log levels
|
|
||||||
- check incoming packets and log errors!!
|
|
||||||
- check log calls for trailing newlines and log levels followed by comma
|
|
||||||
- check if all protocols set proper packet priorities and TTL's.
|
|
||||||
- try compiling with -Wunused
|
|
||||||
- does everybody test return value of sk_open?
|
|
||||||
- protocols: implement CLI hooks and per-procotol CLI commands
|
|
||||||
- protocols: implement reconfigure hook
|
|
||||||
- protocols: use locking
|
|
||||||
- check use of system includes and sprintf()
|
|
||||||
|
|
||||||
Various ideas
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
- client: Ctrl-R eats one more enter
|
|
||||||
- bgp: timing of updates?
|
|
||||||
- netlink: import Linux route attributes to our rta's, so that they can be filtered?
|
|
||||||
- config: executable config files
|
|
||||||
- filters: user defined attributes?
|
|
||||||
- io: use poll if available
|
|
||||||
- route recalculation timing and flap dampening [see RFC2439 for algorithms]
|
|
||||||
- aggregate engine: standard route aggregation and summarization [RFC2519]
|
|
||||||
- aggregate engine: injection of manually configured pseudo-static routes
|
|
||||||
- generate default route if any working BGP connection exists (aggregate engine again?)
|
|
||||||
- generate default route to IGP's (aggregate engine yet another time?)
|
|
||||||
- look at RFC 2386 (QoS-based routing)
|
|
||||||
- cli: show tables?
|
|
||||||
|
|
||||||
OSPF
|
|
||||||
~~~~
|
|
||||||
- check incoming packets using neighbor cache
|
|
||||||
- RFC2328 appendix E: Use a better algorithm
|
|
||||||
- automatic generation of external route tags (RFC1403)
|
|
||||||
- RFC2370 opaque LSA's
|
|
||||||
- Limit export rate of external LSAs (like Gated does)
|
|
||||||
- Bugfix in link state retransmission list (aging)
|
|
||||||
- Graceful OSPF restart - RFC3623
|
|
|
@ -25,9 +25,10 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
|
|
@ -3660,6 +3660,12 @@ dsc-iface
|
||||||
as a default router. For <cf/sensitive/ option, see <ref id="radv-trigger" name="trigger">.
|
as a default router. For <cf/sensitive/ option, see <ref id="radv-trigger" name="trigger">.
|
||||||
Default: 3 * <cf/max ra interval/, <cf/sensitive/ yes.
|
Default: 3 * <cf/max ra interval/, <cf/sensitive/ yes.
|
||||||
|
|
||||||
|
<tag><label id="radv-iface-linger-time">linger time <m/expr/</tag>
|
||||||
|
When a prefix disappears, it is advertised for some time with 0
|
||||||
|
lifetime, to inform clients the prefix is no longer usable. This option
|
||||||
|
sets the time for how long it is advertised (in seconds). Maximum is
|
||||||
|
3600, 0 means disabled. Default: 300.
|
||||||
|
|
||||||
<tag><label id="radv-iface-default-preference-low">default preference low|medium|high</tag>
|
<tag><label id="radv-iface-default-preference-low">default preference low|medium|high</tag>
|
||||||
This option specifies the Default Router Preference value to advertise
|
This option specifies the Default Router Preference value to advertise
|
||||||
to hosts. Default: medium.
|
to hosts. Default: medium.
|
||||||
|
|
12
lib/net.h
12
lib/net.h
|
@ -526,6 +526,18 @@ int net_classify(const net_addr *N);
|
||||||
int net_format(const net_addr *N, char *buf, int buflen);
|
int net_format(const net_addr *N, char *buf, int buflen);
|
||||||
int rd_format(const u64 rd, char *buf, int buflen);
|
int rd_format(const u64 rd, char *buf, int buflen);
|
||||||
|
|
||||||
|
static inline int ipa_in_net_ip4(ip4_addr a, const net_addr_ip4 *n)
|
||||||
|
{ return ip4_zero(ip4_and(ip4_xor(a, n->prefix), ip4_mkmask(n->pxlen))); }
|
||||||
|
|
||||||
|
static inline int net_in_net_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
|
||||||
|
{ return (a->pxlen >= b->pxlen) && ipa_in_net_ip4(a->prefix, b); }
|
||||||
|
|
||||||
|
static inline int ipa_in_net_ip6(ip6_addr a, const net_addr_ip6 *n)
|
||||||
|
{ return ip6_zero(ip6_and(ip6_xor(a, n->prefix), ip6_mkmask(n->pxlen))); }
|
||||||
|
|
||||||
|
static inline int net_in_net_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b)
|
||||||
|
{ return (a->pxlen >= b->pxlen) && ipa_in_net_ip6(a->prefix, b); }
|
||||||
|
|
||||||
int ipa_in_netX(const ip_addr A, const net_addr *N);
|
int ipa_in_netX(const ip_addr A, const net_addr *N);
|
||||||
int net_in_netX(const net_addr *A, const net_addr *N);
|
int net_in_netX(const net_addr *A, const net_addr *N);
|
||||||
|
|
||||||
|
|
11
misc/docker/centos-6-amd64/Dockerfile
Normal file
11
misc/docker/centos-6-amd64/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM centos:6
|
||||||
|
RUN yum -y upgrade
|
||||||
|
RUN yum -y install \
|
||||||
|
autoconf \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
pkgconfig \
|
||||||
|
'readline-devel' \
|
||||||
|
'pkgconfig(ncurses)' \
|
||||||
|
gcc \
|
||||||
|
make
|
11
misc/docker/centos-7-amd64/Dockerfile
Normal file
11
misc/docker/centos-7-amd64/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM centos:7
|
||||||
|
RUN yum -y upgrade
|
||||||
|
RUN yum -y install \
|
||||||
|
autoconf \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
pkgconfig \
|
||||||
|
'readline-devel' \
|
||||||
|
'pkgconfig(ncurses)' \
|
||||||
|
gcc \
|
||||||
|
make
|
12
misc/docker/debian-7-amd64/Dockerfile
Normal file
12
misc/docker/debian-7-amd64/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM debian:wheezy-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-7-i386/Dockerfile
Normal file
12
misc/docker/debian-7-i386/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM i386/debian:wheezy-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-8-amd64/Dockerfile
Normal file
12
misc/docker/debian-8-amd64/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM debian:jessie-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-8-i386/Dockerfile
Normal file
12
misc/docker/debian-8-i386/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM i386/debian:jessie-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-9-amd64/Dockerfile
Normal file
12
misc/docker/debian-9-amd64/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM debian:stretch-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-9-i386/Dockerfile
Normal file
12
misc/docker/debian-9-i386/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM i386/debian:stretch-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-testing-amd64/Dockerfile
Normal file
12
misc/docker/debian-testing-amd64/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM debian:testing-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/debian-testing-i386/Dockerfile
Normal file
12
misc/docker/debian-testing-i386/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM i386/debian:testing-slim
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
10
misc/docker/fedora-25-amd64/Dockerfile
Normal file
10
misc/docker/fedora-25-amd64/Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
FROM fedora:25
|
||||||
|
RUN dnf -y upgrade
|
||||||
|
RUN dnf -y install \
|
||||||
|
autoconf \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
pkgconfig \
|
||||||
|
'readline-devel' \
|
||||||
|
'pkgconfig(ncurses)' \
|
||||||
|
gcc
|
10
misc/docker/fedora-26-amd64/Dockerfile
Normal file
10
misc/docker/fedora-26-amd64/Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
FROM fedora:26
|
||||||
|
RUN dnf -y upgrade
|
||||||
|
RUN dnf -y install \
|
||||||
|
autoconf \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
pkgconfig \
|
||||||
|
'readline-devel' \
|
||||||
|
'pkgconfig(ncurses)' \
|
||||||
|
gcc
|
11
misc/docker/opensuse-42.3-amd64/Dockerfile
Normal file
11
misc/docker/opensuse-42.3-amd64/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM opensuse:42.3
|
||||||
|
RUN zypper -n up
|
||||||
|
RUN zypper -n install \
|
||||||
|
autoconf \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
pkgconfig \
|
||||||
|
readline-devel \
|
||||||
|
ncurses-devel \
|
||||||
|
gcc \
|
||||||
|
gmake
|
12
misc/docker/ubuntu-14.04-amd64/Dockerfile
Normal file
12
misc/docker/ubuntu-14.04-amd64/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM ubuntu:14.04
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
12
misc/docker/ubuntu-16.04-amd64/Dockerfile
Normal file
12
misc/docker/ubuntu-16.04-amd64/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM ubuntu:16.04
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN sed -i 's/deb.debian.org/ftp.cz.debian.org/' /etc/apt/sources.list
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y upgrade
|
||||||
|
RUN apt-get -y install \
|
||||||
|
autoconf \
|
||||||
|
build-essential \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
ncurses-dev \
|
||||||
|
libreadline-dev
|
|
@ -145,9 +145,9 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
|
||||||
if (p->ifa_notify && (p->proto_state != PS_DOWN))
|
if (p->ifa_notify && (p->proto_state != PS_DOWN))
|
||||||
{
|
{
|
||||||
if (p->debug & D_IFACES)
|
if (p->debug & D_IFACES)
|
||||||
log(L_TRACE "%s < %s address %N on interface %s %s",
|
log(L_TRACE "%s < address %N on interface %s %s",
|
||||||
p->name, (a->flags & IA_PRIMARY) ? "primary" : "secondary",
|
p->name, &a->prefix, a->iface->name,
|
||||||
&a->prefix, a->iface->name, (c & IF_CHANGE_UP) ? "added" : "removed");
|
(c & IF_CHANGE_UP) ? "added" : "removed");
|
||||||
p->ifa_notify(p, c, a);
|
p->ifa_notify(p, c, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ static u8 radv_mult_val; /* Used by radv_mult for second return value */
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
|
CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
|
||||||
MANAGED, OTHER, CONFIG, LINK, MTU, REACHABLE, TIME, RETRANS,
|
MANAGED, OTHER, CONFIG, LINGER, LINK, MTU, REACHABLE, TIME, RETRANS,
|
||||||
TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
|
TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
|
||||||
LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
|
LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
|
||||||
LOCAL, TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH)
|
LOCAL, TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH)
|
||||||
|
@ -80,6 +80,7 @@ radv_iface_start:
|
||||||
RADV_IFACE->max_ra_int = DEFAULT_MAX_RA_INT;
|
RADV_IFACE->max_ra_int = DEFAULT_MAX_RA_INT;
|
||||||
RADV_IFACE->min_delay = DEFAULT_MIN_DELAY;
|
RADV_IFACE->min_delay = DEFAULT_MIN_DELAY;
|
||||||
RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
|
RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
|
||||||
|
RADV_IFACE->linger_time = DEFAULT_LINGER_TIME;
|
||||||
RADV_IFACE->default_lifetime = -1;
|
RADV_IFACE->default_lifetime = -1;
|
||||||
RADV_IFACE->default_lifetime_sensitive = 1;
|
RADV_IFACE->default_lifetime_sensitive = 1;
|
||||||
RADV_IFACE->default_preference = RA_PREF_MEDIUM;
|
RADV_IFACE->default_preference = RA_PREF_MEDIUM;
|
||||||
|
@ -94,6 +95,7 @@ radv_iface_item:
|
||||||
| LINK MTU expr { RADV_IFACE->link_mtu = $3; }
|
| LINK MTU expr { RADV_IFACE->link_mtu = $3; }
|
||||||
| REACHABLE TIME expr { RADV_IFACE->reachable_time = $3; if ($3 > 3600000) cf_error("Reachable time must be in range 0-3600000"); }
|
| REACHABLE TIME expr { RADV_IFACE->reachable_time = $3; if ($3 > 3600000) cf_error("Reachable time must be in range 0-3600000"); }
|
||||||
| RETRANS TIMER expr { RADV_IFACE->retrans_timer = $3; }
|
| RETRANS TIMER expr { RADV_IFACE->retrans_timer = $3; }
|
||||||
|
| LINGER TIME expr { RADV_IFACE->linger_time = $3; if ($3 > 3600) cf_error("Linger time must be in range 0-3600"); }
|
||||||
| CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if ($4 > 255) cf_error("Current hop limit must be in range 0-255"); }
|
| CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if ($4 > 255) cf_error("Current hop limit must be in range 0-255"); }
|
||||||
| DEFAULT LIFETIME expr radv_sensitive {
|
| DEFAULT LIFETIME expr radv_sensitive {
|
||||||
RADV_IFACE->default_lifetime = $3;
|
RADV_IFACE->default_lifetime = $3;
|
||||||
|
|
|
@ -70,36 +70,6 @@ struct radv_opt_dnssl
|
||||||
char domain[];
|
char domain[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct radv_prefix_config default_prefix = {
|
|
||||||
.onlink = 1,
|
|
||||||
.autonomous = 1,
|
|
||||||
.valid_lifetime = DEFAULT_VALID_LIFETIME,
|
|
||||||
.preferred_lifetime = DEFAULT_PREFERRED_LIFETIME
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static struct radv_prefix_config *
|
|
||||||
radv_prefix_match(struct radv_iface *ifa, struct ifa *a)
|
|
||||||
{
|
|
||||||
struct radv_proto *p = ifa->ra;
|
|
||||||
struct radv_config *cf = (struct radv_config *) (p->p.cf);
|
|
||||||
struct radv_prefix_config *pc;
|
|
||||||
|
|
||||||
if (a->scope <= SCOPE_LINK)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
WALK_LIST(pc, ifa->cf->pref_list)
|
|
||||||
if (net_in_netX(&a->prefix, (net_addr *) &pc->prefix))
|
|
||||||
return pc;
|
|
||||||
|
|
||||||
WALK_LIST(pc, cf->pref_list)
|
|
||||||
if (net_in_netX(&a->prefix, (net_addr *) &pc->prefix))
|
|
||||||
return pc;
|
|
||||||
|
|
||||||
return &default_prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend)
|
radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend)
|
||||||
{
|
{
|
||||||
|
@ -234,6 +204,36 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix *px,
|
||||||
|
char **buf, char *bufend)
|
||||||
|
{
|
||||||
|
struct radv_prefix_config *pc = px->cf;
|
||||||
|
|
||||||
|
if (*buf + sizeof(struct radv_opt_prefix) > bufend)
|
||||||
|
{
|
||||||
|
log(L_WARN "%s: Too many prefixes on interface %s",
|
||||||
|
ifa->ra->p.name, ifa->iface->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct radv_opt_prefix *op = (void *) *buf;
|
||||||
|
op->type = OPT_PREFIX;
|
||||||
|
op->length = 4;
|
||||||
|
op->pxlen = px->prefix.pxlen;
|
||||||
|
op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) |
|
||||||
|
(pc->autonomous ? OPT_PX_AUTONOMOUS : 0);
|
||||||
|
op->valid_lifetime = (ifa->ra->active || !pc->valid_lifetime_sensitive) ?
|
||||||
|
htonl(pc->valid_lifetime) : 0;
|
||||||
|
op->preferred_lifetime = (ifa->ra->active || !pc->preferred_lifetime_sensitive) ?
|
||||||
|
htonl(pc->preferred_lifetime) : 0;
|
||||||
|
op->reserved = 0;
|
||||||
|
op->prefix = ip6_hton(px->prefix.prefix);
|
||||||
|
*buf += sizeof(*op);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
radv_prepare_ra(struct radv_iface *ifa)
|
radv_prepare_ra(struct radv_iface *ifa)
|
||||||
{
|
{
|
||||||
|
@ -269,39 +269,13 @@ radv_prepare_ra(struct radv_iface *ifa)
|
||||||
buf += sizeof (*om);
|
buf += sizeof (*om);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ifa *addr;
|
struct radv_prefix *prefix;
|
||||||
WALK_LIST(addr, ifa->iface->addrs)
|
WALK_LIST(prefix, ifa->prefixes)
|
||||||
{
|
{
|
||||||
if (addr->prefix.type != NET_IP6)
|
if (radv_prepare_prefix(ifa, prefix, &buf, bufend) < 0)
|
||||||
continue;
|
|
||||||
|
|
||||||
struct radv_prefix_config *pc;
|
|
||||||
pc = radv_prefix_match(ifa, addr);
|
|
||||||
|
|
||||||
if (!pc || pc->skip)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (buf + sizeof(struct radv_opt_prefix) > bufend)
|
|
||||||
{
|
|
||||||
log(L_WARN "%s: Too many prefixes on interface %s", p->p.name, ifa->iface->name);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct radv_opt_prefix *op = (void *) buf;
|
|
||||||
op->type = OPT_PREFIX;
|
|
||||||
op->length = 4;
|
|
||||||
op->pxlen = net6_pxlen(&addr->prefix);
|
|
||||||
op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) |
|
|
||||||
(pc->autonomous ? OPT_PX_AUTONOMOUS : 0);
|
|
||||||
op->valid_lifetime = (p->active || !pc->valid_lifetime_sensitive) ?
|
|
||||||
htonl(pc->valid_lifetime) : 0;
|
|
||||||
op->preferred_lifetime = (p->active || !pc->preferred_lifetime_sensitive) ?
|
|
||||||
htonl(pc->preferred_lifetime) : 0;
|
|
||||||
op->reserved = 0;
|
|
||||||
op->prefix = ip6_hton(net6_prefix(&addr->prefix));
|
|
||||||
buf += sizeof(*op);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! ic->rdnss_local)
|
if (! ic->rdnss_local)
|
||||||
if (radv_prepare_rdnss(ifa, &cf->rdnss_list, &buf, bufend) < 0)
|
if (radv_prepare_rdnss(ifa, &cf->rdnss_list, &buf, bufend) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -408,7 +382,7 @@ radv_err_hook(sock *sk, int err)
|
||||||
int
|
int
|
||||||
radv_sk_open(struct radv_iface *ifa)
|
radv_sk_open(struct radv_iface *ifa)
|
||||||
{
|
{
|
||||||
sock *sk = sk_new(ifa->ra->p.pool);
|
sock *sk = sk_new(ifa->pool);
|
||||||
sk->type = SK_IP;
|
sk->type = SK_IP;
|
||||||
sk->subtype = SK_IPV6;
|
sk->subtype = SK_IPV6;
|
||||||
sk->dport = ICMPV6_PROTO;
|
sk->dport = ICMPV6_PROTO;
|
||||||
|
|
|
@ -51,6 +51,16 @@ radv_timer(timer *tm)
|
||||||
|
|
||||||
RADV_TRACE(D_EVENTS, "Timer fired on %s", ifa->iface->name);
|
RADV_TRACE(D_EVENTS, "Timer fired on %s", ifa->iface->name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If some dead prefixes expired, regenerate the prefix list and the packet.
|
||||||
|
* We do so by pretending there was a change on the interface.
|
||||||
|
*
|
||||||
|
* This sets the timer, but we replace it just at the end of this function
|
||||||
|
* (replacing a timer is fine).
|
||||||
|
*/
|
||||||
|
if (ifa->prefix_expires && (ifa->prefix_expires <= current_time()))
|
||||||
|
radv_iface_notify(ifa, RA_EV_GC);
|
||||||
|
|
||||||
radv_send_ra(ifa, 0);
|
radv_send_ra(ifa, 0);
|
||||||
|
|
||||||
/* Update timer */
|
/* Update timer */
|
||||||
|
@ -68,7 +78,136 @@ radv_timer(timer *tm)
|
||||||
tm_start(ifa->timer, t);
|
tm_start(ifa->timer, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* ev_name[] = { NULL, "Init", "Change", "RS" };
|
static struct radv_prefix_config default_prefix = {
|
||||||
|
.onlink = 1,
|
||||||
|
.autonomous = 1,
|
||||||
|
.valid_lifetime = DEFAULT_VALID_LIFETIME,
|
||||||
|
.preferred_lifetime = DEFAULT_PREFERRED_LIFETIME
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct radv_prefix_config dead_prefix = {
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Find a corresponding config for the given prefix */
|
||||||
|
static struct radv_prefix_config *
|
||||||
|
radv_prefix_match(struct radv_iface *ifa, net_addr_ip6 *px)
|
||||||
|
{
|
||||||
|
struct radv_proto *p = ifa->ra;
|
||||||
|
struct radv_config *cf = (struct radv_config *) (p->p.cf);
|
||||||
|
struct radv_prefix_config *pc;
|
||||||
|
|
||||||
|
WALK_LIST(pc, ifa->cf->pref_list)
|
||||||
|
if (net_in_net_ip6(px, &pc->prefix))
|
||||||
|
return pc;
|
||||||
|
|
||||||
|
WALK_LIST(pc, cf->pref_list)
|
||||||
|
if (net_in_net_ip6(px, &pc->prefix))
|
||||||
|
return pc;
|
||||||
|
|
||||||
|
return &default_prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go through the list of prefixes, compare them with configs and decide if we
|
||||||
|
* want them or not.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
radv_prepare_prefixes(struct radv_iface *ifa)
|
||||||
|
{
|
||||||
|
struct radv_proto *p = ifa->ra;
|
||||||
|
struct radv_iface_config *cf = ifa->cf;
|
||||||
|
struct radv_prefix *pfx;
|
||||||
|
|
||||||
|
/* First mark all the prefixes as unused */
|
||||||
|
WALK_LIST(pfx, ifa->prefixes)
|
||||||
|
pfx->mark = 0;
|
||||||
|
|
||||||
|
/* Find all the prefixes we want to use and make sure they are in the list. */
|
||||||
|
struct ifa *addr;
|
||||||
|
WALK_LIST(addr, ifa->iface->addrs)
|
||||||
|
{
|
||||||
|
if ((addr->prefix.type != NET_IP6) ||
|
||||||
|
(addr->scope <= SCOPE_LINK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
net_addr_ip6 *prefix = (void *) &addr->prefix;
|
||||||
|
struct radv_prefix_config *pc = radv_prefix_match(ifa, prefix);
|
||||||
|
|
||||||
|
if (!pc || pc->skip)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Do we have it already? */
|
||||||
|
struct radv_prefix *existing = NULL;
|
||||||
|
WALK_LIST(pfx, ifa->prefixes)
|
||||||
|
if (net_equal_ip6(&pfx->prefix, prefix))
|
||||||
|
{
|
||||||
|
existing = pfx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existing)
|
||||||
|
{
|
||||||
|
RADV_TRACE(D_EVENTS, "Adding new prefix %N on %s",
|
||||||
|
prefix, ifa->iface->name);
|
||||||
|
|
||||||
|
existing = mb_allocz(ifa->pool, sizeof *existing);
|
||||||
|
net_copy_ip6(&existing->prefix, prefix);
|
||||||
|
add_tail(&ifa->prefixes, NODE existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the information (it may have changed, or even bring a prefix back
|
||||||
|
* to life).
|
||||||
|
*/
|
||||||
|
existing->alive = 1;
|
||||||
|
existing->mark = 1;
|
||||||
|
existing->cf = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Garbage-collect the prefixes. If something isn't used, it dies (but isn't
|
||||||
|
* dropped just yet). If something is dead and rots there for long enough,
|
||||||
|
* clean it up.
|
||||||
|
*/
|
||||||
|
btime now_ = current_time();
|
||||||
|
btime expires = now_ + cf->linger_time S;
|
||||||
|
btime expires_min = 0;
|
||||||
|
struct radv_prefix *next;
|
||||||
|
WALK_LIST_DELSAFE(pfx, next, ifa->prefixes)
|
||||||
|
{
|
||||||
|
if (pfx->alive && !pfx->mark)
|
||||||
|
{
|
||||||
|
RADV_TRACE(D_EVENTS, "Marking prefix %N on %s as dead",
|
||||||
|
pfx->prefix, ifa->iface->name);
|
||||||
|
|
||||||
|
pfx->alive = 0;
|
||||||
|
pfx->expires = expires;
|
||||||
|
pfx->cf = &dead_prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pfx->alive)
|
||||||
|
{
|
||||||
|
if (pfx->expires <= now_)
|
||||||
|
{
|
||||||
|
RADV_TRACE(D_EVENTS, "Removing prefix %N on %s",
|
||||||
|
pfx->prefix, ifa->iface->name);
|
||||||
|
|
||||||
|
rem_node(NODE pfx);
|
||||||
|
mb_free(pfx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Find minimum expiration time */
|
||||||
|
if (!expires_min || (pfx->expires < expires_min))
|
||||||
|
expires_min = pfx->expires;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ifa->prefix_expires = expires_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* ev_name[] = { NULL, "Init", "Change", "RS", "Garbage collect" };
|
||||||
|
|
||||||
void
|
void
|
||||||
radv_iface_notify(struct radv_iface *ifa, int event)
|
radv_iface_notify(struct radv_iface *ifa, int event)
|
||||||
|
@ -83,6 +222,7 @@ radv_iface_notify(struct radv_iface *ifa, int event)
|
||||||
switch (event)
|
switch (event)
|
||||||
{
|
{
|
||||||
case RA_EV_CHANGE:
|
case RA_EV_CHANGE:
|
||||||
|
case RA_EV_GC:
|
||||||
ifa->plen = 0;
|
ifa->plen = 0;
|
||||||
case RA_EV_INIT:
|
case RA_EV_INIT:
|
||||||
ifa->initial = MAX_INITIAL_RTR_ADVERTISEMENTS;
|
ifa->initial = MAX_INITIAL_RTR_ADVERTISEMENTS;
|
||||||
|
@ -92,6 +232,8 @@ radv_iface_notify(struct radv_iface *ifa, int event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
radv_prepare_prefixes(ifa);
|
||||||
|
|
||||||
/* Update timer */
|
/* Update timer */
|
||||||
btime t = ifa->last + ifa->cf->min_delay S - current_time();
|
btime t = ifa->last + ifa->cf->min_delay S - current_time();
|
||||||
tm_start(ifa->timer, t);
|
tm_start(ifa->timer, t);
|
||||||
|
@ -137,16 +279,18 @@ radv_iface_add(struct object_lock *lock)
|
||||||
static void
|
static void
|
||||||
radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf)
|
radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf)
|
||||||
{
|
{
|
||||||
pool *pool = p->p.pool;
|
|
||||||
struct radv_iface *ifa;
|
struct radv_iface *ifa;
|
||||||
|
|
||||||
RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name);
|
RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name);
|
||||||
|
|
||||||
|
pool *pool = rp_new(p->p.pool, iface->name);
|
||||||
ifa = mb_allocz(pool, sizeof(struct radv_iface));
|
ifa = mb_allocz(pool, sizeof(struct radv_iface));
|
||||||
|
ifa->pool = pool;
|
||||||
ifa->ra = p;
|
ifa->ra = p;
|
||||||
ifa->cf = cf;
|
ifa->cf = cf;
|
||||||
ifa->iface = iface;
|
ifa->iface = iface;
|
||||||
ifa->addr = iface->llv6;
|
ifa->addr = iface->llv6;
|
||||||
|
init_list(&ifa->prefixes);
|
||||||
|
|
||||||
add_tail(&p->iface_list, NODE ifa);
|
add_tail(&p->iface_list, NODE ifa);
|
||||||
|
|
||||||
|
@ -172,11 +316,7 @@ radv_iface_remove(struct radv_iface *ifa)
|
||||||
|
|
||||||
rem_node(NODE ifa);
|
rem_node(NODE ifa);
|
||||||
|
|
||||||
rfree(ifa->sk);
|
rfree(ifa->pool);
|
||||||
rfree(ifa->timer);
|
|
||||||
rfree(ifa->lock);
|
|
||||||
|
|
||||||
mb_free(ifa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#define DEFAULT_MAX_RA_INT 600
|
#define DEFAULT_MAX_RA_INT 600
|
||||||
#define DEFAULT_MIN_DELAY 3
|
#define DEFAULT_MIN_DELAY 3
|
||||||
#define DEFAULT_CURRENT_HOP_LIMIT 64
|
#define DEFAULT_CURRENT_HOP_LIMIT 64
|
||||||
|
#define DEFAULT_LINGER_TIME 300
|
||||||
|
|
||||||
#define DEFAULT_VALID_LIFETIME 86400
|
#define DEFAULT_VALID_LIFETIME 86400
|
||||||
#define DEFAULT_PREFERRED_LIFETIME 14400
|
#define DEFAULT_PREFERRED_LIFETIME 14400
|
||||||
|
@ -64,6 +65,9 @@ struct radv_iface_config
|
||||||
u32 max_ra_int;
|
u32 max_ra_int;
|
||||||
u32 min_delay;
|
u32 min_delay;
|
||||||
|
|
||||||
|
u32 linger_time; /* How long a dead prefix should still be advertised with 0
|
||||||
|
lifetime */
|
||||||
|
|
||||||
u8 rdnss_local; /* Global list is not used for RDNSS */
|
u8 rdnss_local; /* Global list is not used for RDNSS */
|
||||||
u8 dnssl_local; /* Global list is not used for DNSSL */
|
u8 dnssl_local; /* Global list is not used for DNSSL */
|
||||||
|
|
||||||
|
@ -118,6 +122,19 @@ struct radv_proto
|
||||||
u8 active; /* Whether radv is active w.r.t. triggers */
|
u8 active; /* Whether radv is active w.r.t. triggers */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct radv_prefix /* One prefix we advertise */
|
||||||
|
{
|
||||||
|
node n;
|
||||||
|
net_addr_ip6 prefix;
|
||||||
|
|
||||||
|
u8 alive; /* Is the prefix alive? If not, we advertise it
|
||||||
|
with 0 lifetime, so clients stop using it */
|
||||||
|
u8 mark; /* A temporary mark for processing */
|
||||||
|
btime expires; /* The time when we drop this prefix from
|
||||||
|
advertising. It is valid only if !alive. */
|
||||||
|
struct radv_prefix_config *cf; /* The config tied to this prefix */
|
||||||
|
};
|
||||||
|
|
||||||
struct radv_iface
|
struct radv_iface
|
||||||
{
|
{
|
||||||
node n;
|
node n;
|
||||||
|
@ -125,6 +142,9 @@ struct radv_iface
|
||||||
struct radv_iface_config *cf; /* Related config, must be updated in reconfigure */
|
struct radv_iface_config *cf; /* Related config, must be updated in reconfigure */
|
||||||
struct iface *iface;
|
struct iface *iface;
|
||||||
struct ifa *addr; /* Link-local address of iface */
|
struct ifa *addr; /* Link-local address of iface */
|
||||||
|
struct pool *pool; /* A pool for interface-specific things */
|
||||||
|
list prefixes; /* The prefixes we advertise (struct radv_prefix) */
|
||||||
|
btime prefix_expires; /* When the soonest prefix expires (0 = none dead) */
|
||||||
|
|
||||||
timer *timer;
|
timer *timer;
|
||||||
struct object_lock *lock;
|
struct object_lock *lock;
|
||||||
|
@ -132,12 +152,13 @@ struct radv_iface
|
||||||
|
|
||||||
btime last; /* Time of last sending of RA */
|
btime last; /* Time of last sending of RA */
|
||||||
u16 plen; /* Length of prepared RA in tbuf, or 0 if not valid */
|
u16 plen; /* Length of prepared RA in tbuf, or 0 if not valid */
|
||||||
byte initial; /* List of active ifaces */
|
byte initial; /* How many RAs are still to be sent as initial */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RA_EV_INIT 1 /* Switch to initial mode */
|
#define RA_EV_INIT 1 /* Switch to initial mode */
|
||||||
#define RA_EV_CHANGE 2 /* Change of options or prefixes */
|
#define RA_EV_CHANGE 2 /* Change of options or prefixes */
|
||||||
#define RA_EV_RS 3 /* Received RS */
|
#define RA_EV_RS 3 /* Received RS */
|
||||||
|
#define RA_EV_GC 4 /* Internal garbage collection of prefixes */
|
||||||
|
|
||||||
/* Default Router Preferences (RFC 4191) */
|
/* Default Router Preferences (RFC 4191) */
|
||||||
#define RA_PREF_LOW 0x18
|
#define RA_PREF_LOW 0x18
|
||||||
|
|
|
@ -165,7 +165,7 @@ struct ks_msg
|
||||||
{
|
{
|
||||||
struct rt_msghdr rtm;
|
struct rt_msghdr rtm;
|
||||||
struct sockaddr_storage buf[RTAX_MAX];
|
struct sockaddr_storage buf[RTAX_MAX];
|
||||||
};
|
} PACKED;
|
||||||
|
|
||||||
#define ROUNDUP(a) \
|
#define ROUNDUP(a) \
|
||||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||||
|
|
|
@ -83,22 +83,26 @@ struct rtvia {
|
||||||
/*
|
/*
|
||||||
* Structure nl_parse_state keeps state of received route processing. Ideally,
|
* Structure nl_parse_state keeps state of received route processing. Ideally,
|
||||||
* we could just independently parse received Netlink messages and immediately
|
* we could just independently parse received Netlink messages and immediately
|
||||||
* propagate received routes to the rest of BIRD, but Linux kernel represents
|
* propagate received routes to the rest of BIRD, but older Linux kernel (before
|
||||||
* and announces IPv6 ECMP routes not as one route with multiple next hops (like
|
* version 4.11) represents and announces IPv6 ECMP routes not as one route with
|
||||||
* RTA_MULTIPATH in IPv4 ECMP), but as a set of routes with the same prefix.
|
* multiple next hops (like RTA_MULTIPATH in IPv4 ECMP), but as a sequence of
|
||||||
|
* routes with the same prefix. More recent kernels work as with IPv4.
|
||||||
*
|
*
|
||||||
* Therefore, BIRD keeps currently processed route in nl_parse_state structure
|
* Therefore, BIRD keeps currently processed route in nl_parse_state structure
|
||||||
* and postpones its propagation until we expect it to be final; i.e., when
|
* and postpones its propagation until we expect it to be final; i.e., when
|
||||||
* non-matching route is received or when the scan ends. When another matching
|
* non-matching route is received or when the scan ends. When another matching
|
||||||
* route is received, it is merged with the already processed route to form an
|
* route is received, it is merged with the already processed route to form an
|
||||||
* ECMP route. Note that merging is done only for IPv6 (merge == 1), but the
|
* ECMP route. Note that merging is done only for IPv6 (merge == 1), but the
|
||||||
* postponing is done in both cases (for simplicity). All IPv4 routes are just
|
* postponing is done in both cases (for simplicity). All IPv4 routes or IPv6
|
||||||
* considered non-matching.
|
* routes with RTA_MULTIPATH set are just considered non-matching.
|
||||||
*
|
*
|
||||||
* This is ignored for asynchronous notifications (every notification is handled
|
* This is ignored for asynchronous notifications (every notification is handled
|
||||||
* as a separate route). It is not an issue for our routes, as we ignore such
|
* as a separate route). It is not an issue for our routes, as we ignore such
|
||||||
* notifications anyways. But importing alien IPv6 ECMP routes does not work
|
* notifications anyways. But importing alien IPv6 ECMP routes does not work
|
||||||
* properly.
|
* properly with older kernels.
|
||||||
|
*
|
||||||
|
* Whatever the kernel version is, IPv6 ECMP routes are sent as multiple routes
|
||||||
|
* for the same prefix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct nl_parse_state
|
struct nl_parse_state
|
||||||
|
@ -348,6 +352,12 @@ static struct nl_want_attrs nexthop_attr_want4[BIRD_RTA_MAX] = {
|
||||||
[RTA_ENCAP] = { 1, 0, 0 },
|
[RTA_ENCAP] = { 1, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct nl_want_attrs nexthop_attr_want6[BIRD_RTA_MAX] = {
|
||||||
|
[RTA_GATEWAY] = { 1, 1, sizeof(ip6_addr) },
|
||||||
|
[RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) },
|
||||||
|
[RTA_ENCAP] = { 1, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
static struct nl_want_attrs encap_mpls_want[BIRD_RTA_MAX] = {
|
static struct nl_want_attrs encap_mpls_want[BIRD_RTA_MAX] = {
|
||||||
[RTA_DST] = { 1, 0, 0 },
|
[RTA_DST] = { 1, 0, 0 },
|
||||||
};
|
};
|
||||||
|
@ -374,6 +384,7 @@ static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = {
|
||||||
[RTA_PRIORITY] = { 1, 1, sizeof(u32) },
|
[RTA_PRIORITY] = { 1, 1, sizeof(u32) },
|
||||||
[RTA_PREFSRC] = { 1, 1, sizeof(ip6_addr) },
|
[RTA_PREFSRC] = { 1, 1, sizeof(ip6_addr) },
|
||||||
[RTA_METRICS] = { 1, 0, 0 },
|
[RTA_METRICS] = { 1, 0, 0 },
|
||||||
|
[RTA_MULTIPATH] = { 1, 0, 0 },
|
||||||
[RTA_FLOW] = { 1, 1, sizeof(u32) },
|
[RTA_FLOW] = { 1, 1, sizeof(u32) },
|
||||||
[RTA_TABLE] = { 1, 1, sizeof(u32) },
|
[RTA_TABLE] = { 1, 1, sizeof(u32) },
|
||||||
[RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) },
|
[RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) },
|
||||||
|
@ -631,7 +642,7 @@ nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nexthop *
|
static struct nexthop *
|
||||||
nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
nl_parse_multipath(struct krt_proto *p, struct rtattr *ra, int af)
|
||||||
{
|
{
|
||||||
/* Temporary buffer for multicast nexthops */
|
/* Temporary buffer for multicast nexthops */
|
||||||
static struct nexthop *nh_buffer;
|
static struct nexthop *nh_buffer;
|
||||||
|
@ -670,7 +681,22 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
||||||
|
|
||||||
/* Nonexistent RTNH_PAYLOAD ?? */
|
/* Nonexistent RTNH_PAYLOAD ?? */
|
||||||
nl_attr_len = nh->rtnh_len - RTNH_LENGTH(0);
|
nl_attr_len = nh->rtnh_len - RTNH_LENGTH(0);
|
||||||
nl_parse_attrs(RTNH_DATA(nh), nexthop_attr_want4, a, sizeof(a));
|
switch (af)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
if (!nl_parse_attrs(RTNH_DATA(nh), nexthop_attr_want4, a, sizeof(a)))
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AF_INET6:
|
||||||
|
if (!nl_parse_attrs(RTNH_DATA(nh), nexthop_attr_want6, a, sizeof(a)))
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (a[RTA_GATEWAY])
|
if (a[RTA_GATEWAY])
|
||||||
{
|
{
|
||||||
rv->gw = rta_get_ipa(a[RTA_GATEWAY]);
|
rv->gw = rta_get_ipa(a[RTA_GATEWAY]);
|
||||||
|
@ -1520,9 +1546,9 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
case RTN_UNICAST:
|
case RTN_UNICAST:
|
||||||
ra->dest = RTD_UNICAST;
|
ra->dest = RTD_UNICAST;
|
||||||
|
|
||||||
if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET))
|
if (a[RTA_MULTIPATH])
|
||||||
{
|
{
|
||||||
struct nexthop *nh = nl_parse_multipath(p, a[RTA_MULTIPATH]);
|
struct nexthop *nh = nl_parse_multipath(p, a[RTA_MULTIPATH], i->rtm_family);
|
||||||
if (!nh)
|
if (!nh)
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Received strange multipath route %N", net->n.addr);
|
log(L_ERR "KRT: Received strange multipath route %N", net->n.addr);
|
||||||
|
@ -1699,8 +1725,10 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ideally, now we would send the received route to the rest of kernel code.
|
* Ideally, now we would send the received route to the rest of kernel code.
|
||||||
* But IPv6 ECMP routes are sent as a sequence of routes, so we postpone it
|
* But IPv6 ECMP routes before 4.11 are sent as a sequence of routes, so we
|
||||||
* and merge next hops until the end of the sequence.
|
* postpone it and merge next hops until the end of the sequence. Note that
|
||||||
|
* proper multipath updates are rejected by nl_mergable_route(), so it is
|
||||||
|
* always the first case for them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!s->net)
|
if (!s->net)
|
||||||
|
|
Loading…
Reference in a new issue