Commit cd1d518e authored by nanahira's avatar nanahira

some rework

parent 34dded36
- hosts: wg - hosts: wg
become: true become: true
roles: roles:
- frp
- bird
- wireguard - wireguard
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
---
# defaults file for bird
bird_version: 2.0.7
; BIRD project coding conventions
((c-mode
(c-file-style . "bsd")
(c-basic-offset . 2)
(fill-column . 80)
(show-trailing-whitespace . t)))
/autom4te.cache/
/obj/
/Makefile
/bird
/birdc
/birdcl
/bird.conf
/bird.log
/config.log
/config.status
/configure
/sysdep/autoconf.h.in
/sysdep/autoconf.h.in~
/cscope.*
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-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-7-amd64: &centos-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
tags:
- freebsd
- i386
#only:
#- master
#- triggers
#- tags
.freebsd-11-amd64: &freebsd-11-amd64_env
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
- $MAKE check
build-debian-7-amd64:
<<: *debian-7-amd64_env
<<: *build_job
build-debian-8-amd64:
<<: *debian-8-amd64_env
<<: *build_job
build-debian-9-amd64:
<<: *debian-9-amd64_env
<<: *build_job
build-debian-testing-amd64:
<<: *debian-testing-amd64_env
<<: *build_job
build-fedora-25-amd64:
<<: *fedora-25-amd64_env
<<: *build_job
build-fedora-26-amd64:
<<: *fedora-26-amd64_env
<<: *build_job
build-centos-7-amd64:
<<: *centos-7-amd64_env
<<: *build_job
build-opensuse-42_3-amd64:
<<: *opensuse-42_3-amd64_env
<<: *build_job
build-ubuntu-14_04-amd64:
<<: *ubuntu-14_04-amd64_env
<<: *build_job
build-ubuntu-16_04-amd64:
<<: *ubuntu-16_04-amd64_env
<<: *build_job
build-debian-7-i386:
<<: *debian-7-i386_env
<<: *build_job
build-debian-8-i386:
<<: *debian-8-i386_env
<<: *build_job
build-debian-9-i386:
<<: *debian-9-i386_env
<<: *build_job
build-debian-testing-i386:
<<: *debian-testing-i386_env
<<: *build_job
build-freebsd-11-amd64:
<<: *freebsd-11-amd64_env
<<: *build_job
build-freebsd-11-i386:
<<: *freebsd-11-i386_env
<<: *build_job
This diff is collapsed.
How to install BIRD
===================
$ ./configure
$ make
# make install
Default location for configuration file is /usr/local/etc/bird.conf and
for control socket is /usr/local/var/run/bird.ctl . You can change that
by --prefix, --sysconfdir and --runstatedir configure options, e.g.:
$ ./configure --prefix=/usr --sysconfdir=/etc --runstatedir=/run
To compile current development BIRD source code from Git repository, you
also need Git (to download the source code) and Autoconf (to generate
the configure script and associated files using 'autoreconf' tool):
$ git clone https://gitlab.labs.nic.cz/labs/bird/
$ cd bird
$ autoreconf
Then continue as in usual installation above.
Requirements
============
For compiling BIRD you need these programs and libraries:
- GNU C Compiler (or LLVM Clang)
- GNU Make
- GNU Bison
- GNU M4
- Flex
- ncurses library
- GNU Readline library
- libssh library (optional, for RPKI-Router protocol)
For compiling BIRD documentation you also need:
- Linuxdoc-Tools
- LaTeX
# Makefile for the BIRD Internet Routing Daemon
# (c) 1999--2000 Martin Mares <mj@ucw.cz>
# (c) 2016 Jan Moskyto Matejka <mq@ucw.cz>
# Disable build-in rules
MAKEFLAGS += -r
# Variable definitions
CPPFLAGS=-I$(objdir) -I$(srcdir) @CPPFLAGS@
CFLAGS=$(CPPFLAGS) @CFLAGS@
LDFLAGS=@LDFLAGS@
M4FLAGS=@M4FLAGS@
BISONFLAGS=@BISONFLAGS@
LIBS=@LIBS@
DAEMON_LIBS=@DAEMON_LIBS@
CLIENT_LIBS=@CLIENT_LIBS@
CC=@CC@
M4=@M4@
BISON=@BISON@
FLEX=@FLEX@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
INSTALL_PROGRAM=@INSTALL_PROGRAM@
INSTALL_DATA=@INSTALL_DATA@
client=$(addprefix $(exedir)/,@CLIENT@)
daemon=$(exedir)/bird
protocols=@protocols@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
sbindir=@sbindir@
sysconfdir=@sysconfdir@
localstatedir=@localstatedir@
runstatedir=@runstatedir@
docdir=@prefix@/doc
srcdir := @srcdir@
objdir := @objdir@
exedir := @exedir@
git-label:=$(strip $(shell cd $(srcdir) && [ "$$(git rev-parse --show-toplevel)" = "$$(readlink -f .)" ] && git describe --always --dirty=-x 2>/dev/null))
ifneq ($(git-label),)
CFLAGS += -DGIT_LABEL="$(git-label)"
endif
ifeq ($(objdir),.)
objdir := $(realpath .)
endif
ifeq ($(VERBOSE),)
E:=@
Q:=@
else
E:=@\#
Q:=
endif
ifneq ($(COLOR),)
CFLAGS += -fdiagnostics-color=always
endif
# Meta rules
docgoals := docs userdocs progdocs
testgoals := check test tests tests_run
cleangoals := clean distclean testsclean
.PHONY: all daemon cli $(docgoals) $(testgoals) $(cleangoals) tags cscope prepare
all: daemon cli
daemon: $(daemon)
cli: $(client)
$(daemon): LIBS += $(DAEMON_LIBS)
# Include directories
dirs := client conf doc filter lib nest test $(addprefix proto/,$(protocols)) @sysdep_dirs@
# conf/Makefile declarations needed for all other modules
conf-lex-targets := $(addprefix $(objdir)/conf/,cf-lex.o)
conf-y-targets := $(addprefix $(objdir)/conf/,cf-parse.y keywords.h commands.h)
cf-local = $(conf-y-targets): $(s)config.Y
src-o-files = $(patsubst %.c,$(o)%.o,$(src))
tests-target-files = $(patsubst %.c,$(o)%,$(tests_src))
all-daemon = $(daemon): $(obj)
all-client = $(client): $(obj)
s = $(dir $(lastword $(MAKEFILE_LIST)))
ifeq ($(srcdir),.)
o = $(objdir)/$(s)
else
o = $(patsubst $(srcdir)%,$(objdir)%,$(s))
endif
define clean_in =
clean::
rm -f $(addprefix $(o),$(1))
endef
clean = $(eval $(call clean_in,$(1)))
# Include main Makefiles of the directories
include $(addsuffix /Makefile,$(addprefix $(srcdir)/,$(dirs)))
# Generic rules
# Object file rules
$(objdir)/%.o: $(srcdir)/%.c | prepare
$(E)echo CC -o $@ -c $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -c $<
$(objdir)/%.o: $(objdir)/%.c | prepare
$(E)echo CC -o $@ -c $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -c $<
# Debug: Preprocessed source rules
$(objdir)/%.E: $(srcdir)/%.c | prepare
$(E)echo CC -o $@ -E $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -E $<
$(objdir)/%.E: $(objdir)/%.c | prepare
$(E)echo CC -o $@ -E $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -E $<
# Debug: Assembler object rules
$(objdir)/%.S: $(srcdir)/%.c | prepare
$(E)echo CC -o $@ -S $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -S $<
$(objdir)/%.S: $(objdir)/%.c | prepare
$(E)echo CC -o $@ -S $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -S $<
# Finally include the computed dependencies:
DEPS = $(shell find $(objdir) -name '*.d')
# ## if there is at least one non-clean goal
ifneq ($(filter-out $(cleangoals),$(MAKECMDGOALS)),)
-include $(DEPS)
endif
# ## if the implicit goal is called
ifeq ($(MAKECMDGOALS),)
-include $(DEPS)
endif
# Rule for pre-generating all generated includables
# before compiling any C file
prepare: $(objdir)/sysdep/paths.h | $(objdir)/.dir-stamp
$(objdir)/.dir-stamp: Makefile
$(E)echo MKDIR -p $(addprefix $(objdir)/,$(dirs) doc)
$(Q)mkdir -p $(addprefix $(objdir)/,$(dirs) doc)
$(Q)touch $@
$(client) $(daemon):
$(E)echo LD $(LDFLAGS) -o $@ $^ $(LIBS)
$(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
$(objdir)/sysdep/paths.h: Makefile
echo >$@ "/* Generated by Makefile, don't edit manually! */"
echo >>$@ "#define PATH_CONFIG_FILE \"@CONFIG_FILE@\""
echo >>$@ "#define PATH_CONTROL_SOCKET \"@CONTROL_SOCKET@\""
if test -n "@iproutedir@" ; then echo >>$@ "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
# Unit tests rules
tests_targets_ok = $(addsuffix .ok,$(tests_targets))
$(tests_targets): %: %.o $(tests_objs) | prepare
$(E)echo LD $(LDFLAGS) -o $@ $< "..." $(LIBS)
$(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
# Hack to avoid problems with tests linking everything
$(tests_targets): LIBS += $(DAEMON_LIBS)
$(tests_targets_ok): %.ok: %
$(Q)$* 2>/dev/null && touch $*.ok
test: testsclean check
check: tests tests_run
tests: $(tests_targets)
tests_run: $(tests_targets_ok)
tags:
cd $(srcdir) ; etags -lc `find $(dirs) -name *.[chY]`
cscope:
cd $(srcdir) ; find $(dirs) -name *.[chY] > cscope.files ; cscope -b
# Install
install: all
$(INSTALL) -d $(DESTDIR)/$(sbindir) $(DESTDIR)/$(sysconfdir) $(DESTDIR)/$(runstatedir)
for BIN in bird @CLIENT@ ; do \
$(INSTALL_PROGRAM) $(exedir)/$$BIN $(DESTDIR)/$(sbindir)/$$BIN ; \
done
if ! test -f $(DESTDIR)/@CONFIG_FILE@ ; then \
$(INSTALL_DATA) $(srcdir)/doc/bird.conf.example $(DESTDIR)/@CONFIG_FILE@ ; \
else \
echo "Not overwriting old bird.conf" ; \
fi
install-docs:
$(INSTALL) -d $(DESTDIR)/$(docdir)
$(INSTALL_DATA) $(objdir)/doc/{bird,prog}{,-*}.html $(DESTDIR)/$(docdir)/
# Cleanup
clean::
rm -f $(objdir)/sysdep/paths.h
rm -f $(addprefix $(exedir)/,bird birdc birdcl)
find $(objdir) -name "*.[od]" -exec rm -f '{}' '+'
testsclean:
rm -f $(tests_targets_ok)
ifeq ($(objdir),obj)
distclean: clean
rm -rf $(objdir)
rm -f config.log config.status configure Makefile
else
distclean: clean
rm -rf * .dir-stamp
rm -f config.log config.status configure Makefile
endif
This diff is collapsed.
BIRD Internet Routing Daemon
Home page http://bird.network.cz/
Mailing list bird-users@network.cz
(c) 1998--2008 Martin Mares <mj@ucw.cz>
(c) 1998--2000 Pavel Machek <pavel@ucw.cz>
(c) 1998--2008 Ondrej Filip <feela@network.cz>
(c) 2009--2019 CZ.NIC z.s.p.o.
================================================================================
The BIRD project aims to develop a dynamic IP routing daemon with full support
of all modern routing protocols, easy to use configuration interface and
powerful route filtering language, primarily targeted on (but not limited to)
Linux and other UNIX-like systems and distributed under the GNU General
Public License.
What do we support
==================
o Both IPv4 and IPv6
o Multiple routing tables
o Border Gateway Protocol (BGPv4)
o Routing Information Protocol (RIPv2, RIPng)
o Open Shortest Path First protocol (OSPFv2, OSPFv3)
o Babel Routing Protocol (Babel)
o Bidirectional Forwarding Detection (BFD)
o IPv6 router advertisements
o Static routes
o Inter-table protocol
o Command-line interface allowing on-line control and inspection of
status of the daemon
o Soft reconfiguration, no need to use complex online commands to
change the configuration, just edit the configuration file and notify
BIRD to re-read it and it will smoothly switch itself to the new
configuration, not disturbing routing protocols unless they are
affected by the configuration changes
o Powerful language for route filtering, see doc/bird.conf.example
o Linux, FreeBSD, NetBSD and OpenBSD ports
How to install BIRD
===================
o From standard distribution package of your OS (recommended)
o From official binary packages for Debian and Red Hat Linux
ftp://bird.network.cz/pub/bird/debian/
ftp://bird.network.cz/pub/bird/redhat/
o From source code of the latest stable release version
ftp://bird.network.cz/pub/bird/
o From current development code in Git repository
https://gitlab.labs.nic.cz/labs/bird/
See the file INSTALL for information about installation from source code.
Documentation
=============
Online documentation is available at http://bird.network.cz/?get_doc or as HTML
files in the doc directory, you can install it by `make install-docs' and
rebuild it by `make docs', but you'll need SGMLtools and LaTeX to be installed
on your machine. You can also download a neatly formatted PDF version as
a separate archive (bird-doc-*.tar.gz) from ftp://bird.network.cz/pub/bird/
User support
============
If you want to help us debugging, enhancing and porting BIRD or just lurk
around to see what's going to develop, feel free to subscribe to the BIRD
users mailing list bird-users@network.cz, just send `subscribe' to
bird-request@network.cz. Bug reports, suggestions, feature requests and
code are welcome! We don't use gitlab issues for reporting, sorry.
Subscribe: http://bird.network.cz/mailman/listinfo/bird-users/
Archive: http://bird.network.cz/pipermail/bird-users/
Licence
=======
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
History
=======
BIRD development started as a student project at the Faculty of Math
and Physics, Charles University, Prague, Czech Republic under supervision
of RNDr. Libor Forst <forst@cuni.cz>. BIRD has been developed and supported
by CZ.NIC z.s.p.o. http://www.nic.cz/ since 2009.
Good Luck and enjoy the BIRD :)
The BIRD Team
dnl ** Additional Autoconf tests for BIRD configure script
dnl ** (c) 1999 Martin Mares <mj@ucw.cz>
AC_DEFUN([BIRD_CHECK_THREAD_LOCAL],
[
AC_CACHE_CHECK(
[whether _Thread_local is known],
[bird_cv_thread_local],
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM(
[
_Thread_local static int x = 42;
],
[]
)
],
[bird_cv_thread_local=yes],
[bird_cv_thread_local=no]
)
)
])
AC_DEFUN([BIRD_CHECK_PTHREADS],
[
bird_tmp_cflags="$CFLAGS"
CFLAGS="$CFLAGS -pthread"
AC_CACHE_CHECK(
[whether POSIX threads are available],
[bird_cv_lib_pthreads],
[
AC_LINK_IFELSE(
[
AC_LANG_PROGRAM(
[ #include <pthread.h> ],
[
pthread_t pt;
pthread_create(&pt, NULL, NULL, NULL);
pthread_spinlock_t lock;
pthread_spin_lock(&lock);
]
)
],
[bird_cv_lib_pthreads=yes],
[bird_cv_lib_pthreads=no]
)
]
)
CFLAGS="$bird_tmp_cflags"
])
AC_DEFUN([BIRD_CHECK_MPLS_KERNEL],
[
AC_CACHE_CHECK(
[for Linux MPLS headers],
[bird_cv_mpls_kernel],
[
AC_COMPILE_IFELSE(
[
AC_LANG_PROGRAM(
[
#include <linux/lwtunnel.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
void t(int arg);
],
[
t(AF_MPLS);
t(RTA_VIA);
t(RTA_NEWDST);
t(RTA_ENCAP_TYPE);
t(RTA_ENCAP);
struct rtvia rtvia;
t(LWTUNNEL_ENCAP_MPLS);
]
)
],
[bird_cv_mpls_kernel=yes],
[bird_cv_mpls_kernel=no]
)
]
)
])
AC_DEFUN([BIRD_CHECK_ANDROID_GLOB],
[
AC_CACHE_CHECK(
[for glob.h],
[bird_cv_lib_glob],
AC_LINK_IFELSE([
AC_LANG_PROGRAM(
[
#include <glob.h>
#include <stdlib.h>
],
[ glob(NULL, 0, NULL, NULL); ]
)
],
[bird_cv_lib_glob=yes],
[
bird_tmp_libs="$LIBS"
LIBS="$LIBS -landroid-glob"
AC_LINK_IFELSE([
AC_LANG_PROGRAM(
[
#include <glob.h>
#include <stdlib.h>
],
[ glob(NULL, 0, NULL, NULL); ]
)
],
[bird_cv_lib_glob=-landroid-glob],
[bird_cv_lib_glob=no]
)
LIBS="$bird_tmp_libs"
]
)
)
])
AC_DEFUN([BIRD_CHECK_ANDROID_LOG],
[
AC_CACHE_CHECK(
[for syslog lib flags],
[bird_cv_lib_log],
AC_LINK_IFELSE([
AC_LANG_PROGRAM(
[ #include <sys/syslog.h> ],
[ syslog(0, ""); ]
)
],
[bird_cv_lib_log=yes],
[
bird_tmp_libs="$LIBS"
LIBS="$LIBS -llog"
AC_LINK_IFELSE([
AC_LANG_PROGRAM(
[ #include <sys/syslog.h> ],
[ syslog(0, ""); ]
)
],
[bird_cv_lib_log=-llog],
[bird_cv_lib_log=no]
)
LIBS="$bird_tmp_libs"
]
)
)
])
AC_DEFUN([BIRD_CHECK_LTO],
[
bird_tmp_cflags="$CFLAGS"
bird_tmp_ldflags="$LDFLAGS"
CFLAGS="-flto"
LDFLAGS="-flto=4"
AC_CACHE_CHECK(
[whether link time optimizer is available],
[bird_cv_c_lto],
[
AC_LINK_IFELSE(
[AC_LANG_PROGRAM()],
[bird_cv_c_lto=yes],
[bird_cv_c_lto=no]
)
]
)
CFLAGS="$bird_tmp_cflags"
LDFLAGS="$bird_tmp_ldflags"
])
AC_DEFUN([BIRD_CHECK_GCC_OPTION],
[
bird_tmp_cflags="$CFLAGS"
CFLAGS="$3 $2"
AC_CACHE_CHECK(
[whether CC supports $2],
[$1],
[
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM()],
[$1=yes],
[$1=no]
)
]
)
CFLAGS="$bird_tmp_cflags"
])
AC_DEFUN([BIRD_ADD_GCC_OPTION],
[
if test "$$1" = yes ; then
CFLAGS="$CFLAGS $2"
fi
])
# BIRD_CHECK_PROG_FLAVOR_GNU(PROGRAM-PATH, IF-SUCCESS, [IF-FAILURE])
# copied from autoconf internal _AC_PATH_PROG_FLAVOR_GNU
AC_DEFUN([BIRD_CHECK_PROG_FLAVOR_GNU],
[
# Check for GNU $1
case `"$1" --version 2>&1` in
*GNU*)
$2
;;
m4_ifval([$3],
[*)
$3
;;
]
)
esac
])
AC_DEFUN([BIRD_CHECK_BISON_VERSION],
[
$1=`bison --version | ( read line; echo ${line##* } )`
case "$$1" in
1.* | 2.0* | 2.1* | 2.2* | 2.3*)
AC_MSG_ERROR([Provided Bison version $$1 is too old, need at least 2.4])
;;
2.*)
bird_bison_synclines=no
bird_bison_enhanced_error=no
;;
3.* | 4.* | 5.* | 6.* | 7.* | 8.* | 9.*)
bird_bison_synclines=yes
bird_bison_enhanced_error=yes
;;
*)
AC_MSG_ERROR([Couldn't parse Bison version $$1. Call the developers for help.])
;;
esac
])
class BIRDPrinter:
def __init__(self, val):
self.val = val
@classmethod
def lookup(cls, val):
if val.type.code != cls.typeCode:
return None
if val.type.tag != cls.typeTag:
return None
return cls(val)
class BIRDFValPrinter(BIRDPrinter):
"Print BIRD\s struct f_val"
typeCode = gdb.TYPE_CODE_STRUCT
typeTag = "f_val"
codemap = {
"T_INT": "i",
"T_BOOL": "i",
"T_PAIR": "i",
"T_QUAD": "i",
"T_ENUM_RTS": "i",
"T_ENUM_BGP_ORIGIN": "i",
"T_ENUM_SCOPE": "i",
"T_ENUM_RTC": "i",
"T_ENUM_RTD": "i",
"T_ENUM_ROA": "i",
"T_ENUM_NETTYPE": "i",
"T_ENUM_RA_PREFERENCE": "i",
"T_IP": "ip",
"T_NET": "net",
"T_STRING": "s",
"T_PATH_MASK": "path_mask",
"T_PATH": "ad",
"T_CLIST": "ad",
"T_EC": "ec",
"T_ECLIST": "ad",
"T_LC": "lc",
"T_LCLIST": "ad",
"T_RD": "ec",
"T_PATH_MASK_ITEM": "pmi",
"T_SET": "t",
"T_PREFIX_SET": "ti",
}
def to_string(self):
code = self.val['type']
if code.type.code != gdb.TYPE_CODE_ENUM or code.type.tag != "f_type":
raise Exception("Strange 'type' element in f_val")
if str(code) == "T_VOID":
return "T_VOID"
else:
return "(%(c)s) %(v)s" % { "c": code, "v": self.val['val'][self.codemap[str(code)]] }
def display_hint(self):
return "map"
class BIRDFValStackPrinter(BIRDPrinter):
"Print BIRD's struct f_val_stack"
typeCode = gdb.TYPE_CODE_STRUCT
typeTag = "f_val_stack"
def to_string(self):
cnt = self.val['cnt']
return ("Value stack (%(cnt)d):\n\t" % { "cnt": cnt }) + \
"\n\t".join([ (".val[%(n) 3d] = " % { "n": n}) + str(self.val['val'][n]) for n in range(cnt-1, -1, -1) ])
def display_hint(self):
return "map"
class BIRDFInstPrinter(BIRDPrinter):
"Print BIRD's struct f_inst"
typeCode = gdb.TYPE_CODE_STRUCT
typeTag = "f_inst"
def to_string(self):
code = self.val['fi_code']
if str(code) == "FI_NOP":
return str(code) + ": " + str(self.val.cast(gdb.lookup_type("const char [%(siz)d]" % { "siz": self.val.type.sizeof })))
return "%(code)s:\t%(lineno) 6dL\t%(size)6dS\tnext = %(next)s: .i_%(code)s = %(union)s" % {
"code": str(code),
"lineno": self.val['lineno'],
"size": self.val['size'],
"next": str(self.val['next']),
"union": str(self.val['i_' + str(code)])
}
# def children(self): # children iterator
def display_hint(self):
return "map"
class BIRDFLineItemPrinter(BIRDPrinter):
"Print BIRD's struct f_line_item"
typeCode = gdb.TYPE_CODE_STRUCT
typeTag = "f_line_item"
def to_string(self):
code = self.val['fi_code']
if str(code) == "FI_NOP":
return str(code) + ": " + str(self.val.cast(gdb.lookup_type("const char [%(siz)d]" % { "siz": self.val.type.sizeof })))
return "%(code)s:\t%(lineno) 6dL\t%(flags)2dF: .i_%(code)s = %(union)s" % {
"code": str(code),
"lineno": self.val['lineno'],
"flags": self.val['flags'],
"union": str(self.val['i_' + str(code)])
}
class BIRDFLinePrinter(BIRDPrinter):
"Print BIRD's struct f_line"
typeCode = gdb.TYPE_CODE_STRUCT
typeTag = "f_line"
def to_string(self):
cnt = self.val['len']
return ("FLine (%(cnt)d, args=%(args)d): " % { "cnt": cnt, "args" : self.val['args'] } + \
", ".join([
".items[%(n) 3d] = %(code)s" % {
"n": n,
"code": str(self.val['items'][n]['fi_code']),
} if n % 8 == 0 else str(self.val['items'][n]['fi_code']) for n in range(cnt)]))
class BIRDFExecStackPrinter(BIRDPrinter):
"Print BIRD's struct f_exec_stack"
typeCode = gdb.TYPE_CODE_STRUCT
typeTag = "f_exec_stack"
def to_string(self):
cnt = self.val['cnt']
return ("Exec stack (%(cnt)d):\n\t" % { "cnt": cnt }) + \
"\n\t".join([ ".item[%(n) 3d] = %(retflag)d V%(ventry) 3d P%(pos) 4d %(line)s" % {
"retflag": self.val['item'][n]['emask'],
"ventry": self.val['item'][n]['ventry'],
"pos": self.val['item'][n]['pos'],
"line": str(self.val['item'][n]['line'].dereference()),
"n": n
} for n in range(cnt-1, -1, -1) ])
def register_printers(objfile):
objfile.pretty_printers.append(BIRDFInstPrinter.lookup)
objfile.pretty_printers.append(BIRDFValPrinter.lookup)
objfile.pretty_printers.append(BIRDFValStackPrinter.lookup)
objfile.pretty_printers.append(BIRDFLineItemPrinter.lookup)
objfile.pretty_printers.append(BIRDFLinePrinter.lookup)
objfile.pretty_printers.append(BIRDFExecStackPrinter.lookup)
register_printers(gdb.current_objfile())
print("BIRD pretty printers loaded OK.")
src := commands.c util.c client.c
obj := $(src-o-files)
$(all-client)
$(conf-y-targets): $(s)cmds.Y
$(exedir)/birdc: $(o)birdc.o
$(exedir)/birdc: LIBS += $(CLIENT_LIBS)
$(exedir)/birdcl: $(o)birdcl.o
/*
* BIRD Client - Readline variant I/O
*
* (c) 1999--2004 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <curses.h>
#include "nest/bird.h"
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
static int input_hidden_end;
static int prompt_active;
/*** Input ***/
/* HACK: libreadline internals we need to access */
extern int _rl_vis_botlin;
extern void _rl_move_vert(int);
#define HISTORY "/.birdc_history"
static char *history_file;
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
input_got_line(char *cmd_buffer)
{
if (!cmd_buffer)
{
cleanup();
exit(0);
}
if (cmd_buffer[0])
{
add_history_dedup(cmd_buffer);
submit_command(cmd_buffer);
}
free(cmd_buffer);
}
void
input_start_list(void)
{
/* Leave the currently edited line and make space for listing */
_rl_move_vert(_rl_vis_botlin);
#ifdef HAVE_RL_CRLF
rl_crlf();
#endif
}
void
input_stop_list(void)
{
/* Reprint the currently edited line after listing */
rl_on_new_line();
rl_redisplay();
}
static int
input_complete(int arg UNUSED, int key UNUSED)
{
static int complete_flag;
char buf[256];
if (rl_last_func != input_complete)
complete_flag = 0;
switch (cmd_complete(rl_line_buffer, rl_point, buf, complete_flag))
{
case 0:
complete_flag = 1;
break;
case 1:
rl_insert_text(buf);
break;
default:
complete_flag = 1;
#ifdef HAVE_RL_DING
rl_ding();
#endif
}
return 0;
}
static int
input_help(int arg, int key UNUSED)
{
int i, in_string, in_bracket;
if (arg != 1)
return rl_insert(arg, '?');
in_string = in_bracket = 0;
for (i = 0; i < rl_point; i++)
{
if (rl_line_buffer[i] == '"')
in_string = ! in_string;
else if (! in_string)
{
if (rl_line_buffer[i] == '[')
in_bracket++;
else if (rl_line_buffer[i] == ']')
in_bracket--;
}
}
/* `?' inside string or path -> insert */
if (in_string || in_bracket)
return rl_insert(1, '?');
rl_begin_undo_group(); /* HACK: We want to display `?' at point position */
rl_insert_text("?");
rl_redisplay();
rl_end_undo_group();
input_start_list();
cmd_help(rl_line_buffer, rl_point);
rl_undo_command(1, 0);
input_stop_list();
return 0;
}
void
history_init(void)
{
const char *homedir = getenv("HOME");
if (!homedir)
homedir = ".";
history_file = malloc(strlen(homedir) + sizeof(HISTORY));
if (!history_file)
die("couldn't alloc enough memory for history file name");
sprintf(history_file, "%s%s", homedir, HISTORY);
read_history(history_file);
}
void
input_init(void)
{
if (interactive)
history_init();
rl_readline_name = "birdc";
rl_add_defun("bird-complete", input_complete, '\t');
rl_add_defun("bird-help", input_help, '?');
rl_callback_handler_install("bird> ", input_got_line);
// rl_get_screen_size();
term_lns = LINES;
term_cls = COLS;
prompt_active = 1;
// readline library does strange things when stdin is nonblocking.
// if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
// DIE("fcntl");
}
static void
input_reveal(void)
{
/* need this, otherwise some lib seems to eat pending output when
the prompt is displayed */
fflush(stdout);
tcdrain(STDOUT_FILENO);
rl_end = input_hidden_end;
rl_expand_prompt("bird> ");
rl_forced_update_display();
prompt_active = 1;
}
static void
input_hide(void)
{
input_hidden_end = rl_end;
rl_end = 0;
rl_expand_prompt("");
rl_redisplay();
prompt_active = 0;
}
void
input_notify(int prompt)
{
if (prompt == prompt_active)
return;
if (prompt)
input_reveal();
else
input_hide();
}
void
input_read(void)
{
rl_callback_read_char();
}
void
more_begin(void)
{
}
void
more_end(void)
{
}
void
cleanup(void)
{
if (init)
return;
input_hide();
if (interactive)
write_history(history_file);
rl_callback_handler_remove();
}
/*
* BIRD Client - Light variant I/O
*
* (c) 1999--2004 Martin Mares <mj@ucw.cz>
* (c) 2013 Tomas Hlavacek <tomas.hlavacek@nic.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <signal.h>
#include "nest/bird.h"
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
#include "sysdep/unix/unix.h"
#define INPUT_BUF_LEN 2048
struct termios tty_save;
void
input_start_list(void)
{
/* Empty in non-ncurses version. */
}
void
input_stop_list(void)
{
/* Empty in non-ncurses version. */
}
void
input_notify(int prompt)
{
/* No ncurses -> no status to reveal/hide, print prompt manually. */
if (!prompt)
return;
printf("bird> ");
fflush(stdout);
}
static int
lastnb(char *str, int i)
{
while (i--)
if ((str[i] != ' ') && (str[i] != '\t'))
return str[i];
return 0;
}
void
input_read(void)
{
char buf[INPUT_BUF_LEN];
if ((fgets(buf, INPUT_BUF_LEN, stdin) == NULL) || (buf[0] == 0))
{
putchar('\n');
cleanup();
exit(0);
}
int l = strlen(buf);
if ((l+1) == INPUT_BUF_LEN)
{
printf("Input too long.\n");
return;
}
if (buf[l-1] == '\n')
buf[--l] = '\0';
if (!interactive)
printf("%s\n", buf);
if (l == 0)
return;
if (lastnb(buf, l) == '?')
{
cmd_help(buf, strlen(buf));
return;
}
submit_command(buf);
}
static struct termios stored_tty;
static int more_active = 0;
void
more_begin(void)
{
static struct termios tty;
tty = stored_tty;
tty.c_lflag &= (~ECHO);
tty.c_lflag &= (~ICANON);
if (tcsetattr (0, TCSANOW, &tty) < 0)
DIE("tcsetattr");
more_active = 1;
}
void
more_end(void)
{
more_active = 0;
if (tcsetattr (0, TCSANOW, &stored_tty) < 0)
DIE("tcsetattr");
}
static void
sig_handler(int signal UNUSED)
{
cleanup();
exit(0);
}
void
input_init(void)
{
if (!interactive)
return;
if (tcgetattr(0, &stored_tty) < 0)
DIE("tcgetattr");
if (signal(SIGINT, sig_handler) == SIG_IGN)
signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, sig_handler) == SIG_IGN)
signal(SIGTERM, SIG_IGN);
struct winsize tws;
if (ioctl(0, TIOCGWINSZ, &tws) == 0)
{
term_lns = tws.ws_row;
term_cls = tws.ws_col;
}
}
void
cleanup(void)
{
if (more_active)
more_end();
}
/*
* BIRD Client
*
* (c) 1999--2004 Martin Mares <mj@ucw.cz>
* (c) 2013 Tomas Hlavacek <tmshlvck@gmail.com>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
/**
* DOC: BIRD client
*
* There are two variants of BIRD client: regular and light. regular
* variant depends on readline and ncurses libraries, while light
* variant uses just libc. Most of the code and the main() is common
* for both variants (in client.c file) and just a few functions are
* different (in birdc.c for regular and birdcl.c for light). Two
* binaries are generated by linking common object files like client.o
* (which is compiled from client.c just once) with either birdc.o or
* birdcl.o for each variant.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include "nest/bird.h"
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
#include "sysdep/unix/unix.h"
#define SERVER_READ_BUF_LEN 4096
static char *opt_list = "s:vrl";
static int verbose, restricted, once;
static char *init_cmd;
static char *server_path = PATH_CONTROL_SOCKET;
static int server_fd;
static byte server_read_buf[SERVER_READ_BUF_LEN];
static byte *server_read_pos = server_read_buf;
int init = 1; /* During intial sequence */
int busy = 1; /* Executing BIRD command */
int interactive; /* Whether stdin is terminal */
static int num_lines, skip_input;
int term_lns, term_cls;
/*** Parsing of arguments ***/
static void
usage(char *name)
{
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l]\n", name);
exit(1);
}
static void
parse_args(int argc, char **argv)
{
int server_changed = 0;
int c;
while ((c = getopt(argc, argv, opt_list)) >= 0)
switch (c)
{
case 's':
server_path = optarg;
server_changed = 1;
break;
case 'v':
verbose++;
break;
case 'r':
restricted = 1;
break;
case 'l':
if (!server_changed)
server_path = xbasename(server_path);
break;
default:
usage(argv[0]);
}
/* If some arguments are not options, we take it as commands */
if (optind < argc)
{
char *tmp;
int i;
int len = 0;
for (i = optind; i < argc; i++)
len += strlen(argv[i]) + 1;
tmp = init_cmd = malloc(len);
for (i = optind; i < argc; i++)
{
strcpy(tmp, argv[i]);
tmp += strlen(tmp);
*tmp++ = ' ';
}
tmp[-1] = 0;
once = 1;
interactive = 0;
}
}
/*** Input ***/
static void server_send(char *cmd);
static int
handle_internal_command(char *cmd)
{
if (!strncmp(cmd, "exit", 4) || !strncmp(cmd, "quit", 4))
{
cleanup();
exit(0);
}
if (!strncmp(cmd, "help", 4))
{
puts("Press `?' for context sensitive help.");
return 1;
}
return 0;
}
static void
submit_server_command(char *cmd)
{
busy = 1;
num_lines = 2;
server_send(cmd);
}
static inline void
submit_init_command(char *cmd_raw)
{
char *cmd = cmd_expand(cmd_raw);
if (!cmd)
{
cleanup();
exit(0);
}
submit_server_command(cmd);
free(cmd);
}
void
submit_command(char *cmd_raw)
{
char *cmd = cmd_expand(cmd_raw);
if (!cmd)
return;
if (!handle_internal_command(cmd))
submit_server_command(cmd);
free(cmd);
}
static void
init_commands(void)
{
if (restricted)
{
submit_server_command("restrict");
restricted = 0;
return;
}
if (init_cmd)
{
/* First transition - client received hello from BIRD
and there is waiting initial command */
submit_init_command(init_cmd);
init_cmd = NULL;
return;
}
if (once)
{
/* Initial command is finished and we want to exit */
cleanup();
exit(0);
}
input_init();
term_lns = (term_lns > 0) ? term_lns : 25;
term_cls = (term_cls > 0) ? term_cls : 80;
init = 0;
}
/*** Output ***/
void
more(void)
{
more_begin();
printf("--More--\015");
fflush(stdout);
redo:
switch (getchar())
{
case ' ':
num_lines = 2;
break;
case '\n':
case '\r':
num_lines--;
break;
case 'q':
skip_input = 1;
break;
default:
goto redo;
}
printf(" \015");
fflush(stdout);
more_end();
}
/*** Communication with server ***/
static void
server_connect(void)
{
struct sockaddr_un sa;
server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_fd < 0)
DIE("Cannot create socket");
if (strlen(server_path) >= sizeof(sa.sun_path))
die("server_connect: path too long");
bzero(&sa, sizeof(sa));
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, server_path);
if (connect(server_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
DIE("Unable to connect to server control socket (%s)", server_path);
if (fcntl(server_fd, F_SETFL, O_NONBLOCK) < 0)
DIE("fcntl");
}
#define PRINTF(LEN, PARGS...) do { if (!skip_input) len = printf(PARGS); } while(0)
static void
server_got_reply(char *x)
{
int code;
int len = 0;
if (*x == '+') /* Async reply */
PRINTF(len, ">>> %s\n", x+1);
else if (x[0] == ' ') /* Continuation */
PRINTF(len, "%s%s\n", verbose ? " " : "", x+1);
else if (strlen(x) > 4 &&
sscanf(x, "%d", &code) == 1 && code >= 0 && code < 10000 &&
(x[4] == ' ' || x[4] == '-'))
{
if (code)
PRINTF(len, "%s\n", verbose ? x : x+5);
if (x[4] == ' ')
{
busy = 0;
skip_input = 0;
return;
}
}
else
PRINTF(len, "??? <%s>\n", x);
if (interactive && busy && !skip_input && !init && (len > 0))
{
num_lines += (len + term_cls - 1) / term_cls; /* Divide and round up */
if (num_lines >= term_lns)
more();
}
}
static void
server_read(void)
{
int c;
byte *start, *p;
redo:
c = read(server_fd, server_read_pos, server_read_buf + sizeof(server_read_buf) - server_read_pos);
if (!c)
die("Connection closed by server");
if (c < 0)
{
if (errno == EINTR)
goto redo;
else
DIE("Server read error");
}
start = server_read_buf;
p = server_read_pos;
server_read_pos += c;
while (p < server_read_pos)
if (*p++ == '\n')
{
p[-1] = 0;
server_got_reply(start);
start = p;
}
if (start != server_read_buf)
{
int l = server_read_pos - start;
memmove(server_read_buf, start, l);
server_read_pos = server_read_buf + l;
}
else if (server_read_pos == server_read_buf + sizeof(server_read_buf))
{
strcpy(server_read_buf, "?<too-long>");
server_read_pos = server_read_buf + 11;
}
}
static void
select_loop(void)
{
int rv;
while (1)
{
if (init && !busy)
init_commands();
if (!init)
input_notify(!busy);
fd_set select_fds;
FD_ZERO(&select_fds);
FD_SET(server_fd, &select_fds);
if (!busy)
FD_SET(0, &select_fds);
rv = select(server_fd+1, &select_fds, NULL, NULL, NULL);
if (rv < 0)
{
if (errno == EINTR)
continue;
else
DIE("select");
}
if (FD_ISSET(0, &select_fds))
{
input_read();
continue;
}
if (FD_ISSET(server_fd, &select_fds))
{
server_read();
continue;
}
}
}
static void
wait_for_write(int fd)
{
while (1)
{
int rv;
fd_set set;
FD_ZERO(&set);
FD_SET(fd, &set);
rv = select(fd+1, NULL, &set, NULL, NULL);
if (rv < 0)
{
if (errno == EINTR)
continue;
else
DIE("select");
}
if (FD_ISSET(server_fd, &set))
return;
}
}
static void
server_send(char *cmd)
{
int l = strlen(cmd);
byte *z = alloca(l + 1);
memcpy(z, cmd, l);
z[l++] = '\n';
while (l)
{
int cnt = write(server_fd, z, l);
if (cnt < 0)
{
if (errno == EAGAIN)
wait_for_write(server_fd);
else if (errno == EINTR)
continue;
else
DIE("Server write error");
}
else
{
l -= cnt;
z += cnt;
}
}
}
int
main(int argc, char **argv)
{
interactive = isatty(0);
parse_args(argc, argv);
cmd_build_tree();
server_connect();
select_loop();
return 0;
}
/*
* BIRD Client
*
* (c) 1999--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
extern int init, busy, interactive;
extern int term_lns, term_cls;
/* birdc.c / birdcl.c */
void input_start_list(void);
void input_stop_list(void);
void input_init(void);
void input_notify(int prompt);
void input_read(void);
void more_begin(void);
void more_end(void);
void cleanup(void);
/* commands.c */
void cmd_build_tree(void);
void cmd_help(char *cmd, int len);
int cmd_complete(char *cmd, int len, char *buf, int again);
char *cmd_expand(char *cmd);
/* client.c */
void submit_command(char *cmd_raw);
/* die() with system error messages */
#define DIE(x, y...) die(x ": %s", ##y, strerror(errno))
#
# BIRD -- Internal Commands Of The Client
#
# (c) 2000 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
CF_CLI(QUIT,,, [[Quit the client]])
CF_CLI(EXIT,,, [[Exit the client]])
CF_CLI(HELP,,, [[Description of the help system]])
/*
* BIRD Client -- Command Handling
*
* (c) 1999--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "nest/bird.h"
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
struct cmd_info {
char *command;
char *args;
char *help;
int is_real_cmd;
};
static struct cmd_info command_table[] = {
#include "conf/commands.h"
};
struct cmd_node {
struct cmd_node *sibling, *son, **plastson;
struct cmd_info *cmd, *help;
int len;
signed char prio;
char token[1];
};
static struct cmd_node cmd_root;
#define isspace_(X) isspace((unsigned char) (X))
void
cmd_build_tree(void)
{
uint i;
cmd_root.plastson = &cmd_root.son;
for(i=0; i<ARRAY_SIZE(command_table); i++)
{
struct cmd_info *cmd = &command_table[i];
struct cmd_node *old, *new;
char *c = cmd->command;
old = &cmd_root;
while (*c)
{
char *d = c;
while (*c && !isspace_(*c))
c++;
for(new=old->son; new; new=new->sibling)
if (new->len == c-d && !memcmp(new->token, d, c-d))
break;
if (!new)
{
int size = sizeof(struct cmd_node) + c-d;
new = malloc(size);
bzero(new, size);
*old->plastson = new;
old->plastson = &new->sibling;
new->plastson = &new->son;
new->len = c-d;
memcpy(new->token, d, c-d);
new->prio = (new->len == 3 && (!memcmp(new->token, "roa", 3) || !memcmp(new->token, "rip", 3))) ? 0 : 1; /* Hack */
}
old = new;
while (isspace_(*c))
c++;
}
if (cmd->is_real_cmd)
old->cmd = cmd;
else
old->help = cmd;
}
}
static void
cmd_do_display_help(struct cmd_info *c)
{
char buf[strlen(c->command) + strlen(c->args) + 4];
sprintf(buf, "%s %s", c->command, c->args);
printf("%-45s %s\n", buf, c->help);
}
static void
cmd_display_help(struct cmd_info *c1, struct cmd_info *c2)
{
if (c1)
cmd_do_display_help(c1);
else if (c2)
cmd_do_display_help(c2);
}
static struct cmd_node *
cmd_find_abbrev(struct cmd_node *root, char *cmd, int len, int *pambiguous)
{
struct cmd_node *m, *best = NULL, *best2 = NULL;
*pambiguous = 0;
for(m=root->son; m; m=m->sibling)
{
if (m->len == len && !memcmp(m->token, cmd, len))
return m;
if (m->len > len && !memcmp(m->token, cmd, len))
{
if (best && best->prio > m->prio)
continue;
if (best && best->prio == m->prio)
best2 = best;
best = m;
}
}
if (best2)
{
*pambiguous = 1;
return NULL;
}
return best;
}
static void
cmd_list_ambiguous(struct cmd_node *root, char *cmd, int len)
{
struct cmd_node *m;
for(m=root->son; m; m=m->sibling)
if (m->len > len && !memcmp(m->token, cmd, len))
cmd_display_help(m->help, m->cmd);
}
void
cmd_help(char *cmd, int len)
{
char *end = cmd + len;
struct cmd_node *n, *m;
char *z;
int ambig;
n = &cmd_root;
while (cmd < end)
{
if (isspace_(*cmd))
{
cmd++;
continue;
}
z = cmd;
while (cmd < end && !isspace_(*cmd))
cmd++;
m = cmd_find_abbrev(n, z, cmd-z, &ambig);
if (ambig)
{
cmd_list_ambiguous(n, z, cmd-z);
return;
}
if (!m)
break;
n = m;
}
cmd_display_help(n->cmd, NULL);
for (m=n->son; m; m=m->sibling)
cmd_display_help(m->help, m->cmd);
}
static int
cmd_find_common_match(struct cmd_node *root, char *cmd, int len, int *pcount, char *buf)
{
struct cmd_node *m;
int best, best_prio, i;
*pcount = 0;
best = -1;
best_prio = -1;
for(m=root->son; m; m=m->sibling)
{
if (m->len < len || memcmp(m->token, cmd, len))
continue;
if (best_prio > m->prio)
continue;
if (best_prio < m->prio)
{
*pcount = 0;
best = -1;
}
(*pcount)++;
if (best < 0)
{
strcpy(buf, m->token + len);
best = m->len - len;
best_prio = m->prio;
}
else
{
i = 0;
while (i < best && i < m->len - len && buf[i] == m->token[len+i])
i++;
best = i;
}
}
return best;
}
int
cmd_complete(char *cmd, int len, char *buf, int again)
{
char *start = cmd;
char *end = cmd + len;
char *fin;
struct cmd_node *n, *m;
char *z;
int ambig, cnt = 0, common;
/* Find the last word we want to complete */
for(fin=end; fin > start && !isspace_(fin[-1]); fin--)
;
/* Find the context */
n = &cmd_root;
while (cmd < fin && n->son)
{
if (isspace_(*cmd))
{
cmd++;
continue;
}
z = cmd;
while (cmd < fin && !isspace_(*cmd))
cmd++;
m = cmd_find_abbrev(n, z, cmd-z, &ambig);
if (ambig)
{
if (!again)
return -1;
input_start_list();
cmd_list_ambiguous(n, z, cmd-z);
input_stop_list();
return 0;
}
if (!m)
return -1;
n = m;
}
/* Completion of parameters is not yet supported */
if (!n->son)
return -1;
/* We know the context, let's try to complete */
common = cmd_find_common_match(n, fin, end-fin, &cnt, buf);
if (!cnt)
return -1;
if (cnt == 1)
{
buf[common++] = ' ';
buf[common] = 0;
return 1;
}
if (common > 0)
{
buf[common] = 0;
return 1;
}
if (!again)
return -1;
input_start_list();
cmd_list_ambiguous(n, fin, end-fin);
input_stop_list();
return 0;
}
char *
cmd_expand(char *cmd)
{
struct cmd_node *n, *m;
char *c, *b, *args;
int ambig;
args = c = cmd;
n = &cmd_root;
while (*c)
{
if (isspace_(*c))
{
c++;
continue;
}
b = c;
while (*c && !isspace_(*c))
c++;
m = cmd_find_abbrev(n, b, c-b, &ambig);
if (!m)
{
if (!ambig)
break;
puts("Ambiguous command, possible expansions are:");
cmd_list_ambiguous(n, b, c-b);
return NULL;
}
args = c;
n = m;
}
if (!n->cmd)
{
puts("No such command. Press `?' for help.");
return NULL;
}
b = malloc(strlen(n->cmd->command) + strlen(args) + 1);
sprintf(b, "%s%s", n->cmd->command, args);
return b;
}
/*
* BIRD Client -- Utility Functions
*
* (c) 1999--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "nest/bird.h"
#include "lib/string.h"
#include "client/client.h"
/* Client versions of logging functions */
static void
vlog(const char *msg, va_list args)
{
char buf[1024];
int n = vsnprintf(buf, sizeof(buf), msg, args);
if (n < 0)
snprintf(buf, sizeof(buf), "???");
else if (n >= (int) sizeof(buf))
snprintf(buf + sizeof(buf) - 100, 100, " ... <too long>");
fputs(buf, stderr);
fputc('\n', stderr);
}
void
bug(const char *msg, ...)
{
va_list args;
va_start(args, msg);
cleanup();
fputs("Internal error: ", stderr);
vlog(msg, args);
vfprintf(stderr, msg, args);
va_end(args);
exit(1);
}
void
die(const char *msg, ...)
{
va_list args;
va_start(args, msg);
cleanup();
vlog(msg, args);
va_end(args);
exit(1);
}
src := cf-parse.tab.c cf-lex.c conf.c
obj := $(src-o-files)
$(all-daemon)
tests_objs := $(tests_objs) $(src-o-files)
ifdef DEBUG
BISON_DEBUG=-t
#FLEX_DEBUG=-d
endif
$(o)cf-parse.y: $(s)gen_parser.m4
$(o)keywords.h: $(s)gen_keywords.m4
$(o)commands.h: $(s)gen_commands.m4
$(conf-y-targets): $(s)confbase.Y $(s)flowspec.Y
$(M4) $(M4FLAGS) -P $(if $(word 2,$(filter %.m4,$^)),$(error "Too many M4 scripts for one target"),$(filter %.m4,$^)) $(filter %.Y,$^) >$@
$(o)cf-parse.tab.h: $(o)cf-parse.tab.c
$(o)cf-parse.tab.c: $(o)cf-parse.y
$(BISON) $(BISON_DEBUG) $(BISONFLAGS) -dv -pcf_ -b $(@:.tab.c=) $<
$(o)cf-lex.c: $(s)cf-lex.l
$(FLEX) $(FLEX_DEBUG) -f -s -B -8 -Pcf_ -o$@ $<
$(o)cf-lex.o: CFLAGS+=-Wno-sign-compare -Wno-unused-function
prepare: $(o)keywords.h $(o)commands.h $(o)cf-parse.tab.h
$(addprefix $(o), cf-parse.y keywords.h commands.h cf-parse.tab.h cf-parse.tab.c cf-lex.c): $(objdir)/.dir-stamp
$(call clean,cf-parse.tab.h cf-parse.tab.c cf-parse.y keywords.h commands.h cf-lex.c cf-parse.output)
This diff is collapsed.
This diff is collapsed.
/*
* BIRD Internet Routing Daemon -- Configuration File Handling
*
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_CONF_H_
#define _BIRD_CONF_H_
#include "sysdep/config.h"
#include "lib/ip.h"
#include "lib/hash.h"
#include "lib/resource.h"
#include "lib/timer.h"
/* Configuration structure */
struct config {
pool *pool; /* Pool the configuration is stored in */
linpool *mem; /* Linear pool containing configuration data */
list protos; /* Configured protocol instances (struct proto_config) */
list tables; /* Configured routing tables (struct rtable_config) */
list logfiles; /* Configured log files (sysdep) */
list tests; /* Configured unit tests (f_bt_test_suite) */
list symbols; /* Configured symbols in config order */
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
u32 router_id; /* Our Router ID */
unsigned proto_default_debug; /* Default protocol debug mask */
unsigned proto_default_mrtdump; /* Default protocol mrtdump mask */
struct timeformat tf_route; /* Time format for 'show route' */
struct timeformat tf_proto; /* Time format for 'show protocol' */
struct timeformat tf_log; /* Time format for the logfile */
struct timeformat tf_base; /* Time format for other purposes */
u32 gr_wait; /* Graceful restart wait timeout (sec) */
int cli_debug; /* Tracing of CLI connections and commands */
int latency_debug; /* I/O loop tracks duration of each event */
u32 latency_limit; /* Events with longer duration are logged (us) */
u32 watchdog_warning; /* I/O loop watchdog limit for warning (us) */
u32 watchdog_timeout; /* Watchdog timeout (in seconds, 0 = disabled) */
char *err_msg; /* Parser error message */
int err_lino; /* Line containing error */
int err_chno; /* Character where the parser stopped */
char *err_file_name; /* File name containing error */
char *file_name; /* Name of main configuration file */
int file_fd; /* File descriptor of main configuration file */
HASH(struct symbol) sym_hash; /* Lexer: symbol hash table */
struct config *fallback; /* Link to regular config for CLI parsing */
struct sym_scope *root_scope; /* Scope for root symbols */
int obstacle_count; /* Number of items blocking freeing of this config */
int shutdown; /* This is a pseudo-config for daemon shutdown */
int gr_down; /* This is a pseudo-config for graceful restart */
btime load_time; /* When we've got this configuration */
};
/* Please don't use these variables in protocols. Use proto_config->global instead. */
extern struct config *config; /* Currently active configuration */
extern struct config *new_config; /* Configuration being parsed */
struct config *config_alloc(const char *name);
int config_parse(struct config *);
int cli_parse(struct config *);
void config_free(struct config *);
int config_commit(struct config *, int type, uint timeout);
int config_confirm(void);
int config_undo(void);
int config_status(void);
btime config_timer_status(void);
void config_init(void);
void cf_error(const char *msg, ...) NORET;
void config_add_obstacle(struct config *);
void config_del_obstacle(struct config *);
void order_shutdown(int gr);
#define RECONFIG_NONE 0
#define RECONFIG_HARD 1
#define RECONFIG_SOFT 2
#define RECONFIG_UNDO 3
#define CONF_DONE 0
#define CONF_PROGRESS 1
#define CONF_QUEUED 2
#define CONF_UNQUEUED 3
#define CONF_CONFIRM 4
#define CONF_SHUTDOWN -1
#define CONF_NOTHING -2
/* Pools */
extern linpool *cfg_mem;
#define cfg_alloc(size) lp_alloc(cfg_mem, size)
#define cfg_allocu(size) lp_allocu(cfg_mem, size)
#define cfg_allocz(size) lp_allocz(cfg_mem, size)
char *cfg_strdup(const char *c);
void cfg_copy_list(list *dest, list *src, unsigned node_size);
/* Lexer */
extern int (*cf_read_hook)(byte *buf, uint max, int fd);
struct symbol {
node n; /* In list of symbols in config */
struct symbol *next;
struct sym_scope *scope;
int class; /* SYM_* */
uint flags; /* SYM_FLAG_* */
union {
struct proto_config *proto; /* For SYM_PROTO and SYM_TEMPLATE */
const struct f_line *function; /* For SYM_FUNCTION */
const struct filter *filter; /* For SYM_FILTER */
struct rtable_config *table; /* For SYM_TABLE */
struct f_dynamic_attr *attribute; /* For SYM_ATTRIBUTE */
struct f_val *val; /* For SYM_CONSTANT */
uint offset; /* For SYM_VARIABLE */
};
char name[0];
};
struct sym_scope {
struct sym_scope *next; /* Next on scope stack */
struct symbol *name; /* Name of this scope */
uint slots; /* Variable slots */
int active; /* Currently entered */
};
#define SYM_MAX_LEN 64
/* Remember to update cf_symbol_class_name() */
#define SYM_VOID 0
#define SYM_PROTO 1
#define SYM_TEMPLATE 2
#define SYM_FUNCTION 3
#define SYM_FILTER 4
#define SYM_TABLE 5
#define SYM_ATTRIBUTE 6
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
#define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff)
#define SYM_CONSTANT 0x200 /* 0x200-0x2ff are variable types */
#define SYM_CONSTANT_RANGE SYM_CONSTANT ... (SYM_CONSTANT | 0xff)
#define SYM_TYPE(s) ((s)->val->type)
#define SYM_VAL(s) ((s)->val->val)
/* Symbol flags */
#define SYM_FLAG_SAME 0x1 /* For SYM_FUNCTION and SYM_FILTER */
struct include_file_stack {
void *buffer; /* Internal lexer state */
char *file_name; /* File name */
int fd; /* File descriptor */
int lino; /* Current line num */
int chno; /* Current char num (on current line) */
int toklen; /* Current token length */
int depth; /* Include depth, 0 = cannot include */
struct include_file_stack *prev; /* Previous record in stack */
struct include_file_stack *up; /* Parent (who included this file) */
};
extern struct include_file_stack *ifs;
extern struct sym_scope *conf_this_scope;
int cf_lex(void);
void cf_lex_init(int is_cli, struct config *c);
void cf_lex_unwind(void);
struct symbol *cf_find_symbol(const struct config *cfg, const byte *c);
struct symbol *cf_get_symbol(const byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_localize_symbol(struct symbol *sym);
/**
* cf_define_symbol - define meaning of a symbol
* @sym: symbol to be defined
* @type: symbol class to assign
* @def: class dependent data
*
* Defines new meaning of a symbol. If the symbol is an undefined
* one (%SYM_VOID), it's just re-defined to the new type. If it's defined
* in different scope, a new symbol in current scope is created and the
* meaning is assigned to it. If it's already defined in the current scope,
* an error is reported via cf_error().
*
* Result: Pointer to the newly defined symbol. If we are in the top-level
* scope, it's the same @sym as passed to the function.
*/
#define cf_define_symbol(sym_, type_, var_, def_) ({ \
struct symbol *sym = cf_localize_symbol(sym_); \
sym->class = type_; \
sym->var_ = def_; \
sym; })
void cf_push_scope(struct symbol *);
void cf_pop_scope(void);
char *cf_symbol_class_name(struct symbol *sym);
/* Parser */
extern char *cf_text;
int cf_parse(void);
/* Sysdep hooks */
void sysdep_preconfig(struct config *);
int sysdep_commit(struct config *, struct config *);
void sysdep_shutdown_done(void);
#endif
This diff is collapsed.
/*
* BIRD -- Flow specification (RFC 5575) grammar
*
* (c) 2016 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
CF_HDR
#define PARSER 1
#include "nest/bird.h"
#include "lib/flowspec.h"
CF_DEFINES
struct flow_builder *this_flow;
CF_DECLS
%type <i32> flow_num_op flow_srcdst flow_logic_op flow_num_type_ flow_frag_val flow_neg
%type <net_ptr> net_flow4_ net_flow6_ net_flow_
CF_KEYWORDS(FLOW4, FLOW6, DST, SRC, PROTO, NEXT, HEADER, DPORT, SPORT, ICMP,
TYPE, CODE, TCP, FLAGS, LENGTH, DSCP, DONT_FRAGMENT, IS_FRAGMENT,
FIRST_FRAGMENT, LAST_FRAGMENT, FRAGMENT, LABEL, OFFSET)
CF_GRAMMAR
/* Network Flow Specification */
flow_num_op:
TRUE { $$ = FLOW_OP_TRUE; }
| '=' { $$ = FLOW_OP_EQ; }
| NEQ { $$ = FLOW_OP_NEQ; }
| '<' { $$ = FLOW_OP_LT; }
| LEQ { $$ = FLOW_OP_LEQ; }
| '>' { $$ = FLOW_OP_GT; }
| GEQ { $$ = FLOW_OP_GEQ; }
| FALSE { $$ = FLOW_OP_FALSE; }
;
flow_logic_op:
OR { $$ = FLOW_OP_OR; }
| AND { $$ = FLOW_OP_AND; }
;
flow_num_type_:
PROTO { $$ = FLOW_TYPE_IP_PROTOCOL; }
| NEXT HEADER { $$ = FLOW_TYPE_NEXT_HEADER; }
| PORT { $$ = FLOW_TYPE_PORT; }
| DPORT { $$ = FLOW_TYPE_DST_PORT; }
| SPORT { $$ = FLOW_TYPE_SRC_PORT; }
| ICMP TYPE { $$ = FLOW_TYPE_ICMP_TYPE; }
| ICMP CODE { $$ = FLOW_TYPE_ICMP_CODE; }
| LENGTH { $$ = FLOW_TYPE_PACKET_LENGTH; }
| DSCP { $$ = FLOW_TYPE_DSCP; }
;
flow_num_type: flow_num_type_{ flow_builder_set_type(this_flow, $1); };
flow_flag_type: TCP FLAGS { flow_builder_set_type(this_flow, FLOW_TYPE_TCP_FLAGS); };
flow_frag_type: FRAGMENT { flow_builder_set_type(this_flow, FLOW_TYPE_FRAGMENT); };
flow_label_type: LABEL { flow_builder_set_type(this_flow, FLOW_TYPE_LABEL); };
flow_srcdst:
DST { $$ = FLOW_TYPE_DST_PREFIX; }
| SRC { $$ = FLOW_TYPE_SRC_PREFIX; }
;
flow_num_opts:
flow_num_op expr {
flow_check_cf_value_length(this_flow, $2);
flow_builder_add_op_val(this_flow, $1, $2);
}
| flow_num_opts flow_logic_op flow_num_op expr {
flow_check_cf_value_length(this_flow, $4);
flow_builder_add_op_val(this_flow, $2 | $3, $4);
}
| flow_num_opt_ext
| flow_num_opts OR flow_num_opt_ext
;
flow_num_opt_ext_expr:
expr {
flow_check_cf_value_length(this_flow, $1);
flow_builder_add_op_val(this_flow, FLOW_OP_EQ, $1);
}
| expr DDOT expr {
flow_check_cf_value_length(this_flow, $1);
flow_check_cf_value_length(this_flow, $3);
flow_builder_add_op_val(this_flow, FLOW_OP_GEQ, $1);
flow_builder_add_op_val(this_flow, FLOW_OP_AND | FLOW_OP_LEQ, $3);
}
;
flow_num_opt_ext:
flow_num_opt_ext_expr
| flow_num_opt_ext ',' flow_num_opt_ext_expr
;
flow_bmk_opts:
flow_neg expr '/' expr {
flow_check_cf_bmk_values(this_flow, $1, $2, $4);
flow_builder_add_val_mask(this_flow, $1, $2, $4);
}
| flow_bmk_opts flow_logic_op flow_neg expr '/' expr {
flow_check_cf_bmk_values(this_flow, $3, $4, $6);
flow_builder_add_val_mask(this_flow, $2 | $3, $4, $6);
}
| flow_bmk_opts ',' flow_neg expr '/' expr {
flow_check_cf_bmk_values(this_flow, $3, $4, $6);
flow_builder_add_val_mask(this_flow, 0x40 | $3, $4, $6); /* AND */
}
;
flow_neg:
/* empty */ { $$ = 0x00; }
| '!' { $$ = 0x02; }
;
flow_frag_val:
DONT_FRAGMENT { $$ = 1; }
| IS_FRAGMENT { $$ = 2; }
| FIRST_FRAGMENT { $$ = 4; }
| LAST_FRAGMENT { $$ = 8; }
;
flow_frag_opts:
flow_neg flow_frag_val {
flow_builder_add_val_mask(this_flow, 0, ($1 ? 0 : $2), $2);
}
| flow_frag_opts flow_logic_op flow_neg flow_frag_val {
flow_builder_add_val_mask(this_flow, $2, ($3 ? 0 : $4), $4);
}
| flow_frag_opts ',' flow_neg flow_frag_val {
flow_builder_add_val_mask(this_flow, 0x40, ($3 ? 0 : $4), $4); /* AND */
}
;
flow4_item:
flow_srcdst net_ip {
flow_builder_set_type(this_flow, $1);
flow_builder4_add_pfx(this_flow, (net_addr_ip4 *) &($2));
}
| flow_num_type flow_num_opts
| flow_flag_type flow_bmk_opts
| flow_frag_type flow_frag_opts
;
flow6_item:
flow_srcdst net_ip6 {
flow_builder_set_type(this_flow, $1);
flow_builder6_add_pfx(this_flow, (net_addr_ip6 *) &($2), 0);
}
| flow_srcdst net_ip6 OFFSET NUM {
if ($4 > $2.pxlen)
cf_error("Prefix offset is higher than prefix length");
flow_builder_set_type(this_flow, $1);
flow_builder6_add_pfx(this_flow, (net_addr_ip6 *) &($2), $4);
}
| flow_num_type flow_num_opts
| flow_flag_type flow_bmk_opts
| flow_frag_type flow_frag_opts
| flow_label_type flow_bmk_opts
;
flow4_opts:
/* empty */
| flow4_opts flow4_item ';'
;
flow6_opts:
/* empty */
| flow6_opts flow6_item ';'
;
flow_builder_init:
{
if (this_flow == NULL)
this_flow = flow_builder_init(&root_pool);
else
flow_builder_clear(this_flow);
};
flow_builder_set_ipv4: { this_flow->ipv6 = 0; };
flow_builder_set_ipv6: { this_flow->ipv6 = 1; };
net_flow4_: FLOW4 '{' flow_builder_init flow_builder_set_ipv4 flow4_opts '}'
{
$$ = (net_addr *) flow_builder4_finalize(this_flow, cfg_mem);
flow4_validate_cf((net_addr_flow4 *) $$);
};
net_flow6_: FLOW6 '{' flow_builder_init flow_builder_set_ipv6 flow6_opts '}'
{
$$ = (net_addr *) flow_builder6_finalize(this_flow, cfg_mem);
flow6_validate_cf((net_addr_flow6 *) $$);
};
net_flow_: net_flow4_ | net_flow6_ ;
CF_CODE
CF_END
m4_divert(-1)m4_dnl
#
# BIRD -- Generator of CLI Command List
#
# (c) 2000 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
m4_define(CF_CLI, `m4_divert(0){ "m4_translit($1,A-Z,a-z)", "$3", "$4", 1 },
m4_divert(-1)')
m4_define(CF_CLI_CMD, `m4_divert(0){ "m4_translit($1,A-Z,a-z)", "$2", "$3", 1 },
m4_divert(-1)')
m4_define(CF_CLI_HELP, `m4_divert(0){ "m4_translit($1,A-Z,a-z)", "$2", "$3", 0 },
m4_divert(-1)')
# As we are processing C source, we must access all M4 primitives via
# m4_* and also set different quoting convention: `[[' and ']]'
m4_changequote([[,]])
m4_divert(-1)m4_dnl
#
# BIRD -- Generator of Configuration Keyword List
#
# (c) 1998--2000 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
# Common aliases
m4_define(DNL, `m4_dnl')
# Diversions used:
# 1 keywords
# Simple iterator
m4_define(CF_itera, `m4_ifelse($#, 1, [[CF_iter($1)]], [[CF_iter($1)[[]]CF_itera(m4_shift($@))]])')
m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)')
# We include all the headers
m4_define(CF_HDR, `m4_divert(0)')
m4_define(CF_DECLS, `m4_divert(-1)')
m4_define(CF_DEFINES, `m4_divert(-1)')
# Keywords are translated to C initializers
m4_define(CF_handle_kw, `m4_divert(1){ "m4_translit($1,[[A-Z]],[[a-z]])", $1, NULL },
m4_divert(-1)')
m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)CF_handle_kw($1)]])')
m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks
)DNL')
# CLI commands generate keywords as well
m4_define(CF_CLI, `CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
')
# Enums are translated to C initializers: use CF_ENUM(typename, prefix, values)
m4_define(CF_enum, `m4_divert(1){ "CF_enum_prefix[[]]$1", -((CF_enum_type<<16) | CF_enum_prefix[[]]$1), NULL },
m4_divert(-1)')
m4_define(CF_ENUM, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix]],$2)CF_iterate([[CF_enum]], [[m4_shift(m4_shift($@))]])DNL')
# After all configuration templates end, we generate the
m4_m4wrap(`
m4_divert(0)
static struct keyword keyword_list[] = {
m4_undivert(1){ NULL, -1, NULL } };
')
# As we are processing C source, we must access all M4 primitives via
# m4_* and also set different quoting convention: `[[' and ']]'
m4_changequote([[,]])
m4_divert(-1)m4_dnl
#
# BIRD -- Generator of Configuration Grammar
#
# (c) 1998--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
# Diversions used:
# 1 includes
# 2 types etc.
# 3 rules
# 4 C code
# Common aliases
m4_define(DNL, `m4_dnl')
# Define macros for defining sections
m4_define(CF_ZONE, `m4_divert($1)/* $2 from m4___file__ */')
m4_define(CF_HDR, `CF_ZONE(1, Headers)')
m4_define(CF_DEFINES, `CF_ZONE(1, Defines)')
m4_define(CF_DECLS, `CF_ZONE(2, Declarations)')
m4_define(CF_GRAMMAR, `CF_ZONE(3, Grammar)')
m4_define(CF_CODE, `CF_ZONE(4, C Code)')
m4_define(CF_END, `m4_divert(-1)')
# Simple iterator
m4_define(CF_itera, `m4_ifelse($#, 1, [[CF_iter($1)]], [[CF_iter($1)[[]]CF_itera(m4_shift($@))]])')
m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)')
# Keywords act as untyped %token
m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])')
m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks
)DNL')
# CLI commands
m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL
m4_divert(2)CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
m4_divert(3)cli_cmd: CF_cmd
CF_cmd: $1 $2 END')
m4_define(CF_CLI_CMD, `')
m4_define(CF_CLI_HELP, `')
# ENUM declarations are ignored
m4_define(CF_ENUM, `')
# After all configuration templates end, we finally generate the grammar file.
m4_m4wrap(`
m4_divert(0)DNL
%{
m4_undivert(1)DNL
%}
m4_undivert(2)DNL
%%
m4_undivert(3)DNL
%%
m4_undivert(4)DNL
')
# As we are processing C source, we must access all M4 primitives via
# m4_* and also set different quoting convention: `[[' and ']]'
m4_changequote([[,]])
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment