pax_global_header00006660000000000000000000000064152117532450014517gustar00rootroot0000000000000052 comment=4883ba8654f1bd2b948fd841528ef42182002301 bird2-2.17.5/000077500000000000000000000000001521175324500126155ustar00rootroot00000000000000bird2-2.17.5/.dir-locals.el000066400000000000000000000002241521175324500152440ustar00rootroot00000000000000; BIRD project coding conventions ((c-mode (c-file-style . "bsd") (c-basic-offset . 2) (fill-column . 80) (show-trailing-whitespace . t))) bird2-2.17.5/.gitignore000066400000000000000000000003111521175324500146000ustar00rootroot00000000000000/autom4te.cache/ /obj/ /pkg/ /Makefile /bird /birdc /birdcl /bird.conf /bird.log /config.log /config.status /configure /sysdep/autoconf.h.in /sysdep/autoconf.h.in~ /cscope.* *.tar.gz /gitlab/docker.mk bird2-2.17.5/.gitlab-ci.yml000066400000000000000000002357741521175324500152730ustar00rootroot00000000000000########################################################### ##### ##### ##### DO NOT EDIT THIS FILE BY HAND ##### ##### ##### ########################################################### ##### ##### ##### This file is autogenerated from gitlab/. ##### ##### Edit those files and run `make gitlab` instead. ##### ##### ##### ########################################################### spec: inputs: netlab: description: "Manually run netlab tests" type: boolean default: false build: description: "Manually run build tests" type: boolean default: false packages: description: "Manually run packaging (will run also build tests anyway)" type: boolean default: false release-fixup: description: "Suffix for package build (if other than 1, this is a rebuild of a release)" type: number default: 1 release-desc: description: "Package build description (change this for release rebuild)" type: string default: "upstream package" docker-all: description: "Rebuild all dockers" type: boolean default: false docker-regex: description: "Rebuild dockers matching this regex" type: string default: 'NOTHING' # this is another hack because of gitlab syntax quirks docker-one: description: "Rebuild this one docker (keep empty for none)" type: string default: '' options: - '' - docbuilder - centos-7-amd64 - centos-8-amd64 - rocky-08-amd64 - rocky-09-amd64 - oracle-08-amd64 - oracle-09-amd64 - oracle-10-amd64 - opensuse-15.0-amd64 - opensuse-15.1-amd64 - opensuse-15.2-amd64 - opensuse-15.3-amd64 - opensuse-15.4-amd64 - opensuse-15.5-amd64 - opensuse-16.0-amd64 - fedora-33-amd64 - fedora-34-amd64 - fedora-35-amd64 - fedora-36-amd64 - fedora-37-amd64 - fedora-38-amd64 - fedora-39-amd64 - fedora-40-amd64 - fedora-41-amd64 - fedora-42-amd64 - fedora-43-amd64 - fedora-44-amd64 - debian-11-amd64 - debian-11-i386 - debian-12-amd64 - debian-12-i386 - debian-13-amd64 - debian-13-i386 - debian-testing-amd64 - debian-testing-i386 - ubuntu-18.04-amd64 - ubuntu-20.04-amd64 - ubuntu-22.04-amd64 - ubuntu-24.04-amd64 - ubuntu-25.04-amd64 - ubuntu-25.10-amd64 - ubuntu-26.04-amd64 --- variables: DEBIAN_FRONTEND: noninteractive LC_ALL: C.UTF-8 GIT_STRATEGY: fetch DOCKER_CMD: docker --config="$HOME/.docker/$CI_JOB_ID/" IMG_BASE: registry.nic.cz/labs/bird TOOLS_DIR: /home/gitlab-runner/bird-tools STAYRTR_BINARY: /usr/local/bin/stayrtr GITLAB_API_URL: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/ stages: - consistency - image - build - pkg - install - test ## Common rule snippets workflow: rules: - if: '($CI_PIPELINE_SOURCE == "web")' variables: wf_kind: manual wf_prefix: '[MAN] ' wf_desc: '$CI_COMMIT_TITLE' PKG_RELINFO: '$[[ inputs.release-desc ]]' PKG_FIXUP: '$[[ inputs.release-fixup ]]' - if: '($CI_PIPELINE_SOURCE == "schedule")' variables: wf_kind: scheduled wf_prefix: '[SCD] ' wf_desc: '$CI_COMMIT_TITLE' - if: '$CI_COMMIT_TAG' variables: wf_kind: tag wf_prefix: '[TAG] ' wf_desc: '$CI_COMMIT_TAG' - if: '($CI_PIPELINE_SOURCE == "push")' variables: wf_kind: regular wf_prefix: '' wf_desc: '$CI_COMMIT_TITLE' - if: '($CI_COMMIT_BRANCH =~ /^(stable-.*|thread-next|master)$/) && ($CI_COMMIT_MESSAGE =~ /^NEWS and version update/)' variables: wf_kind: release wf_prefix: '[RELEASE] ' wf_desc: '$CI_COMMIT_BRANCH' - if: '($CI_COMMIT_MESSAGE =~ /^NEWS and version update/)' variables: wf_kind: release-candidate wf_prefix: '[RC] ' wf_desc: '$CI_COMMIT_BRANCH' - when: always variables: wf_kind: unknown wf_prefix: '[$CI_PIPELINE_SOURCE] ' wf_desc: '$CI_COMMIT_TITLE' name: '$wf_prefix$wf_desc' # Note: We would love to just write "if: $[[ inputs.packages ]]" # but that's impossible because the value is expected to be a string. # # Should be fixable by several lines in # lib/gitlab/ci/pipeline/expression/statement.rb # but I don't have time to do that contribution to gitlab now.## Default rules for regular jobs .default-rules: # Manual, API and Scheduled jobs have an explicit input setting. # Do not run anything unless explicitly requested for these. - if: '($CI_PIPELINE_SOURCE == "web")' when: never - if: '($CI_PIPELINE_SOURCE == "api")' when: never - if: '($CI_PIPELINE_SOURCE == "schedule")' when: never # Do not run anything for WIP commits - if: '($CI_COMMIT_MESSAGE =~ /^(fixup! )*WIP/)' when: never # Tags only happen on releases, don't run full automation - if: '$CI_COMMIT_TAG' when: never - when: on_success ## Pipeline information dump pipeline-infodump: stage: consistency image: registry.nic.cz/labs/bird:docbuilder script: - | echo "### Variables ###" echo "\$CI_JOB_ID = $CI_JOB_ID" echo "\$CI_COMMIT_SHA = $CI_COMMIT_SHA" echo "\$CI_COMMIT_BRANCH = $CI_COMMIT_BRANCH" echo "\$CI_COMMIT_TAG = $CI_COMMIT_TAG" echo "\$CI_COMMIT_TITLE = $CI_COMMIT_TITLE" echo "\$CI_COMMIT_MESSAGE = $CI_COMMIT_MESSAGE" echo "\$CI_PIPELINE_SOURCE = $CI_PIPELINE_SOURCE" echo "\$CI_MERGE_REQUEST_IID = $CI_MERGE_REQUEST_IID" echo "\$GITLAB_API_URL = $GITLAB_API_URL" echo "\$wf_kind = $wf_kind" echo echo "### Inputs ###" echo "Netlab: $[[ inputs.netlab ]]" echo "Build: $[[ inputs.build ]]" echo "Packages: $[[ inputs.packages ]]" echo "Docker all: $[[ inputs.docker-all ]]" echo "Docker regex: $[[ inputs.docker-regex ]]" echo "Docker one: $[[ inputs.docker-one ]]" ## Pipeline consistency check pipeline-uptodate: stage: consistency image: registry.nic.cz/labs/bird:docbuilder script: - autoreconf -i - ./configure - touch gitlab/template.yml.j2 - make gitlab-venv - git status --porcelain - git diff --exit-code rules: - !reference [ .default-rules ] ## Build Docker consistency check docker-uptodate: stage: consistency image: registry.nic.cz/labs/bird:docbuilder script: - autoreconf -i - ./configure - touch gitlab/data.yml.j2 - make gitlab-docker VENV=1 - touch gitlab/docker/docbuilder/Dockerfile # Docbuilder is a static image, not rebuilt by the templates - find gitlab/docker/ -type f -not -newer gitlab/data.yml.j2 - '[ "`find gitlab/docker/ -type f -not -newer gitlab/data.yml.j2 | wc -l`" == "0" ]' - git status --porcelain - git diff --exit-code rules: - !reference [ .default-rules ] ## Consistency checks for stable branches commit-messages: stage: consistency image: registry.nic.cz/labs/bird:docbuilder script: - tools/git-check-commits rules: - if: '($CI_COMMIT_BRANCH =~ /^(stable-.*|thread-next|master)$/)' when: on_success - if: '($CI_COMMIT_MESSAGE =~ /^NEWS and version update/)' when: on_success - when: never ## Tag check tag-collect: stage: consistency image: registry.nic.cz/labs/bird:docbuilder script: - python3 -m venv venv - . venv/bin/activate - pip3 install requests - tools/git-check-tag-local $CI_COMMIT_TAG - tools/git-check-tag-ci $CI_COMMIT_SHA artifacts: paths: - obj/doc/bird-singlepage.html - obj/doc/prog-singlepage.html - bird-*.tar.gz - pkg/pkgs/* - pkg/srcpkgs/* rules: - if: '$CI_COMMIT_TAG' when: on_success - when: never ############################ ## Docker builder rebuild ## ############################ # We are running all the build / packaging tests in Dockers (unless otherwise) # and these are rules to build these docker images. These are expensive to run # and should run only if needed. # # Modify the appropriate dockerfile to rebuild these images .docker: &docker-build stage: image needs: [] # docker-uptodate maybe? script: - $DOCKER_CMD login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.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' "gitlab/docker/$IMG_NAME/Dockerfile"` - $DOCKER_CMD build -t "bird:$IMG_NAME" "gitlab/docker/$IMG_NAME" - $DOCKER_CMD tag "bird:$IMG_NAME" "$IMG_BASE:$IMG_NAME" - $DOCKER_CMD push "$IMG_BASE:$IMG_NAME" after_script: - rm -rf "$HOME/.docker/$CI_JOB_ID/" # cleanup the credentials tags: # That's Docker in Docker - dind docker-docbuilder: variables: IMG_NAME: "docbuilder" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"docbuilder" =~ /$[[ inputs.docker-regex ]]/' - if: '"docbuilder" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-centos-7-amd64: variables: IMG_NAME: "centos-7-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"centos-7-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"centos-7-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-centos-8-amd64: variables: IMG_NAME: "centos-8-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"centos-8-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"centos-8-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-rocky-08-amd64: variables: IMG_NAME: "rocky-08-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"rocky-08-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"rocky-08-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-rocky-09-amd64: variables: IMG_NAME: "rocky-09-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"rocky-09-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"rocky-09-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-oracle-08-amd64: variables: IMG_NAME: "oracle-08-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"oracle-08-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"oracle-08-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-oracle-09-amd64: variables: IMG_NAME: "oracle-09-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"oracle-09-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"oracle-09-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-oracle-10-amd64: variables: IMG_NAME: "oracle-10-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"oracle-10-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"oracle-10-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-15.0-amd64: variables: IMG_NAME: "opensuse-15.0-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-15.0-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-15.0-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-15.1-amd64: variables: IMG_NAME: "opensuse-15.1-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-15.1-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-15.1-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-15.2-amd64: variables: IMG_NAME: "opensuse-15.2-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-15.2-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-15.2-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-15.3-amd64: variables: IMG_NAME: "opensuse-15.3-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-15.3-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-15.3-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-15.4-amd64: variables: IMG_NAME: "opensuse-15.4-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-15.4-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-15.4-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-15.5-amd64: variables: IMG_NAME: "opensuse-15.5-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-15.5-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-15.5-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-opensuse-16.0-amd64: variables: IMG_NAME: "opensuse-16.0-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"opensuse-16.0-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"opensuse-16.0-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-33-amd64: variables: IMG_NAME: "fedora-33-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-33-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-33-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-34-amd64: variables: IMG_NAME: "fedora-34-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-34-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-34-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-35-amd64: variables: IMG_NAME: "fedora-35-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-35-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-35-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-36-amd64: variables: IMG_NAME: "fedora-36-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-36-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-36-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-37-amd64: variables: IMG_NAME: "fedora-37-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-37-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-37-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-38-amd64: variables: IMG_NAME: "fedora-38-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-38-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-38-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-39-amd64: variables: IMG_NAME: "fedora-39-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-39-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-39-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-40-amd64: variables: IMG_NAME: "fedora-40-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-40-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-40-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-41-amd64: variables: IMG_NAME: "fedora-41-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-41-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-41-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-42-amd64: variables: IMG_NAME: "fedora-42-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-42-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-42-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-43-amd64: variables: IMG_NAME: "fedora-43-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-43-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-43-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-fedora-44-amd64: variables: IMG_NAME: "fedora-44-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"fedora-44-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"fedora-44-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-11-amd64: variables: IMG_NAME: "debian-11-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-11-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-11-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-11-i386: variables: IMG_NAME: "debian-11-i386" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-11-i386" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-11-i386" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-12-amd64: variables: IMG_NAME: "debian-12-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-12-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-12-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-12-i386: variables: IMG_NAME: "debian-12-i386" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-12-i386" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-12-i386" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-13-amd64: variables: IMG_NAME: "debian-13-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-13-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-13-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-13-i386: variables: IMG_NAME: "debian-13-i386" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-13-i386" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-13-i386" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-testing-amd64: variables: IMG_NAME: "debian-testing-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-testing-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-testing-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-debian-testing-i386: variables: IMG_NAME: "debian-testing-i386" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"debian-testing-i386" =~ /$[[ inputs.docker-regex ]]/' - if: '"debian-testing-i386" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-18.04-amd64: variables: IMG_NAME: "ubuntu-18.04-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-18.04-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-18.04-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-20.04-amd64: variables: IMG_NAME: "ubuntu-20.04-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-20.04-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-20.04-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-22.04-amd64: variables: IMG_NAME: "ubuntu-22.04-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-22.04-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-22.04-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-24.04-amd64: variables: IMG_NAME: "ubuntu-24.04-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-24.04-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-24.04-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-25.04-amd64: variables: IMG_NAME: "ubuntu-25.04-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-25.04-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-25.04-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-25.10-amd64: variables: IMG_NAME: "ubuntu-25.10-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-25.10-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-25.10-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build docker-ubuntu-26.04-amd64: variables: IMG_NAME: "ubuntu-26.04-amd64" rules: # Only rebuild if explicitly requested - if: '"$[[ inputs.docker-all ]]" == "true"' - if: '"ubuntu-26.04-amd64" =~ /$[[ inputs.docker-regex ]]/' - if: '"ubuntu-26.04-amd64" == "$[[ inputs.docker-one ]]"' - when: never <<: *docker-build ##################################################### ## Linux distro build tests inside Docker builders ## ##################################################### ## Build stage # # Now we compile and run unit tests ... in every single distribution. # Every task needs its docker, see above. .build-base-rules: - if: '"$[[ inputs.build ]]" == "true"' - if: '"$[[ inputs.packages ]]" == "true"' - !reference [ .default-rules ] .build: &build-base stage: build rules: - !reference [ .build-base-rules ] script: - if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then export BRANCH=mergerequest-$CI_MERGE_REQUEST_IID; else export BRANCH=$CI_COMMIT_BRANCH; fi - tools/version && ( echo -n "BIRD version "; tools/version ) > version-expected - | STABLE_VERSION="`cat VERSION`" if [ "$CI_COMMIT_MESSAGE" == "NEWS and version update " ] || [ "$[[ inputs.release-fixup ]]" -gt "1" ]; then if [ "${STABLE_VERSION}" == "`tools/version`" ]; then echo "Stable version precheck OK" else echo "Stable version discrepancy: $STABLE_VERSION vs. $(tools/version)" exit 1 fi else if grep -qF "BIRD version ${STABLE_VERSION}+branch" version-expected; then true else echo -n "Commit $CI_COMMIT_SHA message $CI_COMMIT_MESSAGE expects version " cat version-expected exit 1 fi fi - | if [ -n "$CROSSBUILD_ARCH" ]; then dpkg-architecture -A $CROSSBUILD_ARCH > crossbuild.sh . crossbuild.sh export CONFIGURE_OPTIONS="--host=${DEB_TARGET_GNU_TYPE} ${CONFIGURE_OPTIONS}" export CROSS_RUN=qemu-${CROSSBUILD_ARCH} fi - autoreconf - ./configure CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS" ${CONFIGURE_OPTIONS} # Detect which make is available - MAKE=make - which gmake 2>/dev/null >/dev/null && MAKE=gmake - $MAKE VERBOSE=1 - $MAKE VERBOSE=1 TEST_RETRY_VERBOSE=1 check # Build docs when tools are available - if which linuxdoc pdflatex sgmlsasp >/dev/null ; then $MAKE docs ; fi # Check that the reported version is the right one - ${CROSS_RUN} ./bird --version |& grep -v 'Cannot disable transparent huge pages' | tee obj/version-built - diff obj/version-built version-expected .build-docker-linux-amd64: &build-docker-linux-amd64 <<: *build-base tags: - docker - linux - amd64 build-centos-7-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-centos-7-amd64 optional: true image: registry.nic.cz/labs/bird:centos-7-amd64 variables: CC: /opt/rh/devtoolset-8/root/usr/bin/gcc LC_ALL: en_US.UTF-8 build-centos-8-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-centos-8-amd64 optional: true image: registry.nic.cz/labs/bird:centos-8-amd64 build-rocky-08-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-rocky-08-amd64 optional: true image: registry.nic.cz/labs/bird:rocky-08-amd64 build-rocky-09-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-rocky-09-amd64 optional: true image: registry.nic.cz/labs/bird:rocky-09-amd64 build-oracle-08-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-oracle-08-amd64 optional: true image: registry.nic.cz/labs/bird:oracle-08-amd64 build-oracle-09-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-oracle-09-amd64 optional: true image: registry.nic.cz/labs/bird:oracle-09-amd64 build-oracle-10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-oracle-10-amd64 optional: true image: registry.nic.cz/labs/bird:oracle-10-amd64 build-opensuse-15.0-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-15.0-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-15.0-amd64 build-opensuse-15.1-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-15.1-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-15.1-amd64 build-opensuse-15.2-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-15.2-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-15.2-amd64 build-opensuse-15.3-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-15.3-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-15.3-amd64 build-opensuse-15.4-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-15.4-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-15.4-amd64 build-opensuse-15.5-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-15.5-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-15.5-amd64 build-opensuse-16.0-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-opensuse-16.0-amd64 optional: true image: registry.nic.cz/labs/bird:opensuse-16.0-amd64 build-fedora-33-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-33-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-33-amd64 build-fedora-34-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-34-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-34-amd64 build-fedora-35-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-35-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-35-amd64 build-fedora-36-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-36-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-36-amd64 build-fedora-37-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-37-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-37-amd64 build-fedora-38-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-38-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-38-amd64 build-fedora-39-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-39-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-39-amd64 build-fedora-40-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-40-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-40-amd64 build-fedora-41-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-41-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-41-amd64 build-fedora-42-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-42-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-42-amd64 build-fedora-43-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-43-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-43-amd64 build-fedora-44-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-fedora-44-amd64 optional: true image: registry.nic.cz/labs/bird:fedora-44-amd64 build-debian-11-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-11-amd64 optional: true image: registry.nic.cz/labs/bird:debian-11-amd64 build-debian-11-i386: <<: *build-docker-linux-amd64 needs: - job: docker-debian-11-i386 optional: true image: registry.nic.cz/labs/bird:debian-11-i386 build-debian-12-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-12-amd64 optional: true image: registry.nic.cz/labs/bird:debian-12-amd64 crossbuild-mips64el-debian-12-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-12-amd64 optional: true image: registry.nic.cz/labs/bird:debian-12-amd64 variables: CROSSBUILD_ARCH: mips64el crossbuild-s390x-debian-12-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-12-amd64 optional: true image: registry.nic.cz/labs/bird:debian-12-amd64 variables: CROSSBUILD_ARCH: s390x build-debian-12-i386: <<: *build-docker-linux-amd64 needs: - job: docker-debian-12-i386 optional: true image: registry.nic.cz/labs/bird:debian-12-i386 build-debian-13-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-amd64 optional: true image: registry.nic.cz/labs/bird:debian-13-amd64 crossbuild-arm64-debian-13-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-amd64 optional: true image: registry.nic.cz/labs/bird:debian-13-amd64 variables: CROSSBUILD_ARCH: arm64 crossbuild-armel-debian-13-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-amd64 optional: true image: registry.nic.cz/labs/bird:debian-13-amd64 variables: CROSSBUILD_ARCH: armel crossbuild-armhf-debian-13-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-amd64 optional: true image: registry.nic.cz/labs/bird:debian-13-amd64 variables: CROSSBUILD_ARCH: armhf crossbuild-riscv64-debian-13-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-amd64 optional: true image: registry.nic.cz/labs/bird:debian-13-amd64 variables: CROSSBUILD_ARCH: riscv64 crossbuild-s390x-debian-13-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-amd64 optional: true image: registry.nic.cz/labs/bird:debian-13-amd64 variables: CROSSBUILD_ARCH: s390x build-debian-13-i386: <<: *build-docker-linux-amd64 needs: - job: docker-debian-13-i386 optional: true image: registry.nic.cz/labs/bird:debian-13-i386 build-debian-testing-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-testing-amd64 optional: true image: registry.nic.cz/labs/bird:debian-testing-amd64 crossbuild-arm64-debian-testing-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-testing-amd64 optional: true image: registry.nic.cz/labs/bird:debian-testing-amd64 variables: CROSSBUILD_ARCH: arm64 crossbuild-armhf-debian-testing-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-testing-amd64 optional: true image: registry.nic.cz/labs/bird:debian-testing-amd64 variables: CROSSBUILD_ARCH: armhf crossbuild-riscv64-debian-testing-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-testing-amd64 optional: true image: registry.nic.cz/labs/bird:debian-testing-amd64 variables: CROSSBUILD_ARCH: riscv64 crossbuild-s390x-debian-testing-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-debian-testing-amd64 optional: true image: registry.nic.cz/labs/bird:debian-testing-amd64 variables: CROSSBUILD_ARCH: s390x build-debian-testing-i386: <<: *build-docker-linux-amd64 needs: - job: docker-debian-testing-i386 optional: true image: registry.nic.cz/labs/bird:debian-testing-i386 build-ubuntu-18.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-18.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-18.04-amd64 build-ubuntu-20.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-20.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-20.04-amd64 build-ubuntu-22.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-22.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-22.04-amd64 build-ubuntu-24.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-24.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64 crossbuild-arm64-ubuntu-24.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-24.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64 variables: CROSSBUILD_ARCH: arm64 crossbuild-armhf-ubuntu-24.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-24.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64 variables: CROSSBUILD_ARCH: armhf crossbuild-ppc64el-ubuntu-24.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-24.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64 variables: CROSSBUILD_ARCH: ppc64el crossbuild-riscv64-ubuntu-24.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-24.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64 variables: CROSSBUILD_ARCH: riscv64 crossbuild-s390x-ubuntu-24.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-24.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64 variables: CROSSBUILD_ARCH: s390x build-ubuntu-25.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64 crossbuild-armhf-ubuntu-25.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64 variables: CROSSBUILD_ARCH: armhf crossbuild-ppc64el-ubuntu-25.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64 variables: CROSSBUILD_ARCH: ppc64el crossbuild-riscv64-ubuntu-25.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64 variables: CROSSBUILD_ARCH: riscv64 crossbuild-s390x-ubuntu-25.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64 variables: CROSSBUILD_ARCH: s390x build-ubuntu-25.10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.10-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64 crossbuild-arm64-ubuntu-25.10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.10-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64 variables: CROSSBUILD_ARCH: arm64 crossbuild-armhf-ubuntu-25.10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.10-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64 variables: CROSSBUILD_ARCH: armhf crossbuild-ppc64el-ubuntu-25.10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.10-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64 variables: CROSSBUILD_ARCH: ppc64el crossbuild-riscv64-ubuntu-25.10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.10-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64 variables: CROSSBUILD_ARCH: riscv64 crossbuild-s390x-ubuntu-25.10-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-25.10-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64 variables: CROSSBUILD_ARCH: s390x build-ubuntu-26.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-26.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64 crossbuild-arm64-ubuntu-26.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-26.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64 variables: CROSSBUILD_ARCH: arm64 crossbuild-armhf-ubuntu-26.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-26.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64 variables: CROSSBUILD_ARCH: armhf crossbuild-ppc64el-ubuntu-26.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-26.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64 variables: CROSSBUILD_ARCH: ppc64el crossbuild-riscv64-ubuntu-26.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-26.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64 variables: CROSSBUILD_ARCH: riscv64 crossbuild-s390x-ubuntu-26.04-amd64: <<: *build-docker-linux-amd64 needs: - job: docker-ubuntu-26.04-amd64 optional: true image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64 variables: CROSSBUILD_ARCH: s390x ####################################################### ## A special task for preparing the release archives ## ####################################################### build-release: image: registry.nic.cz/labs/bird:docbuilder needs: - job: docker-docbuilder optional: true stage: build tags: - docker - linux script: - if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then export BRANCH=mergerequest-$CI_MERGE_REQUEST_IID; else export BRANCH=$CI_COMMIT_BRANCH; fi - autoreconf - ./configure --with-protocols= --disable-client - make obj/doc/bird-singlepage.html obj/doc/prog-singlepage.html - if grep '
PARSER FAILED ' obj/doc/bird-singlepage.html obj/doc/prog-singlepage.html; then echo "Documentation build is broken!"; false; fi
    - tools/make-archive
  artifacts:
    paths:
      - obj/doc/bird-singlepage.html
      - obj/doc/prog-singlepage.html
      - bird-*.tar.gz
    expire_in: 1 day
  rules: !reference [ .build-base-rules ]

# Packaging rules
# As we support some ancient versions of different distributions,
# we need to keep several different machineries. It's not so bad
# but it's bad nevertheless.
#
# We do NOT build separate documentation packages in these rules.

.pkg-base: &pkg-base
  rules:
  - if: '"$[[ inputs.packages ]]" == "true"'
  - if: '$CI_COMMIT_TAG'
    when: never
  - if: '($CI_COMMIT_MESSAGE =~ /^NEWS and version update/)'
    when: on_success
  - if: '($CI_COMMIT_BRANCH !~ /^(stable-.*|thread-next|master)$/)'
    when: never
  - !reference [ .default-rules ]

.pkg-deb: &pkg-deb
  <<: *pkg-base
  stage: pkg
  script:
    - if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then export BRANCH=mergerequest-$CI_MERGE_REQUEST_IID; else export BRANCH=$CI_COMMIT_BRANCH; fi
    - tools/make-deb
  artifacts:
    paths:
      - pkg/pkgs/*
      - pkg/srcpkgs/*

.pkg-rpm: &pkg-rpm
  <<: *pkg-base
  stage: pkg
  script:
    - if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then export BRANCH=mergerequest-$CI_MERGE_REQUEST_IID; else export BRANCH=$CI_COMMIT_BRANCH; fi
    - STABLE_BUILDDIR=true tools/make-rpm
  artifacts:
    paths:
      - pkg/pkgs/*
      - pkg/srcpkgs/*



pkg-centos-7-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-centos-7-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:centos-7-amd64
  variables:
    CC: /opt/rh/devtoolset-8/root/usr/bin/gcc
    LC_ALL: en_US.UTF-8

pkg-centos-8-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-centos-8-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:centos-8-amd64

pkg-rocky-08-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-rocky-08-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:rocky-08-amd64

pkg-rocky-09-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-rocky-09-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:rocky-09-amd64

pkg-oracle-08-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-oracle-08-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:oracle-08-amd64

pkg-oracle-09-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-oracle-09-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:oracle-09-amd64

pkg-oracle-10-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-oracle-10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:oracle-10-amd64

pkg-opensuse-15.0-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-15.0-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-15.0-amd64

pkg-opensuse-15.1-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-15.1-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-15.1-amd64

pkg-opensuse-15.2-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-15.2-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-15.2-amd64

pkg-opensuse-15.3-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-15.3-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-15.3-amd64

pkg-opensuse-15.4-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-15.4-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-15.4-amd64

pkg-opensuse-15.5-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-15.5-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-15.5-amd64

pkg-opensuse-16.0-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-opensuse-16.0-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:opensuse-16.0-amd64

pkg-fedora-33-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-33-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-33-amd64

pkg-fedora-34-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-34-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-34-amd64

pkg-fedora-35-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-35-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-35-amd64

pkg-fedora-36-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-36-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-36-amd64

pkg-fedora-37-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-37-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-37-amd64

pkg-fedora-38-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-38-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-38-amd64

pkg-fedora-39-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-39-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-39-amd64

pkg-fedora-40-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-40-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-40-amd64

pkg-fedora-41-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-41-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-41-amd64

pkg-fedora-42-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-42-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-42-amd64

pkg-fedora-43-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-43-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-43-amd64

pkg-fedora-44-amd64:
  <<: *pkg-rpm
  needs:
    - job: build-fedora-44-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:fedora-44-amd64

pkg-debian-11-amd64:
  <<: *pkg-deb
  needs:
    - job: build-debian-11-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-11-amd64


pkg-debian-11-i386:
  <<: *pkg-deb
  needs:
    - job: build-debian-11-i386
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-11-i386

pkg-debian-12-amd64:
  <<: *pkg-deb
  needs:
    - job: build-debian-12-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-12-amd64

crosspkg-mips64el-debian-12-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-mips64el-debian-12-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-12-amd64
  variables:
    CROSSBUILD_ARCH: mips64el

crosspkg-s390x-debian-12-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-debian-12-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-12-amd64
  variables:
    CROSSBUILD_ARCH: s390x


pkg-debian-12-i386:
  <<: *pkg-deb
  needs:
    - job: build-debian-12-i386
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-12-i386

pkg-debian-13-amd64:
  <<: *pkg-deb
  needs:
    - job: build-debian-13-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-amd64

crosspkg-arm64-debian-13-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-arm64-debian-13-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: arm64

crosspkg-armel-debian-13-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armel-debian-13-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: armel

crosspkg-armhf-debian-13-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armhf-debian-13-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: armhf

crosspkg-riscv64-debian-13-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-riscv64-debian-13-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: riscv64

crosspkg-s390x-debian-13-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-debian-13-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: s390x


pkg-debian-13-i386:
  <<: *pkg-deb
  needs:
    - job: build-debian-13-i386
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-13-i386

pkg-debian-testing-amd64:
  <<: *pkg-deb
  needs:
    - job: build-debian-testing-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-testing-amd64

crosspkg-arm64-debian-testing-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-arm64-debian-testing-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: arm64

crosspkg-armhf-debian-testing-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armhf-debian-testing-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: armhf

crosspkg-riscv64-debian-testing-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-riscv64-debian-testing-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: riscv64

crosspkg-s390x-debian-testing-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-debian-testing-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: s390x


pkg-debian-testing-i386:
  <<: *pkg-deb
  needs:
    - job: build-debian-testing-i386
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:debian-testing-i386

pkg-ubuntu-18.04-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-18.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-18.04-amd64


pkg-ubuntu-20.04-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-20.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-20.04-amd64


pkg-ubuntu-22.04-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-22.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-22.04-amd64


pkg-ubuntu-24.04-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-24.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64

crosspkg-arm64-ubuntu-24.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-arm64-ubuntu-24.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: arm64

crosspkg-armhf-ubuntu-24.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armhf-ubuntu-24.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: armhf

crosspkg-ppc64el-ubuntu-24.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-ppc64el-ubuntu-24.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el

crosspkg-riscv64-ubuntu-24.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-riscv64-ubuntu-24.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: riscv64

crosspkg-s390x-ubuntu-24.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-ubuntu-24.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: s390x


pkg-ubuntu-25.04-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-25.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64

crosspkg-armhf-ubuntu-25.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armhf-ubuntu-25.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: armhf

crosspkg-ppc64el-ubuntu-25.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-ppc64el-ubuntu-25.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el

crosspkg-riscv64-ubuntu-25.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-riscv64-ubuntu-25.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: riscv64

crosspkg-s390x-ubuntu-25.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-ubuntu-25.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: s390x


pkg-ubuntu-25.10-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-25.10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64

crosspkg-arm64-ubuntu-25.10-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-arm64-ubuntu-25.10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: arm64

crosspkg-armhf-ubuntu-25.10-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armhf-ubuntu-25.10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: armhf

crosspkg-ppc64el-ubuntu-25.10-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-ppc64el-ubuntu-25.10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el

crosspkg-riscv64-ubuntu-25.10-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-riscv64-ubuntu-25.10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: riscv64

crosspkg-s390x-ubuntu-25.10-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-ubuntu-25.10-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: s390x


pkg-ubuntu-26.04-amd64:
  <<: *pkg-deb
  needs:
    - job: build-ubuntu-26.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64

crosspkg-arm64-ubuntu-26.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-arm64-ubuntu-26.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: arm64

crosspkg-armhf-ubuntu-26.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-armhf-ubuntu-26.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: armhf

crosspkg-ppc64el-ubuntu-26.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-ppc64el-ubuntu-26.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el

crosspkg-riscv64-ubuntu-26.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-riscv64-ubuntu-26.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: riscv64

crosspkg-s390x-ubuntu-26.04-amd64:
  <<: *pkg-deb
  needs:
    - job: crossbuild-s390x-ubuntu-26.04-amd64
      artifacts: false
    - job: build-release
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: s390x



## Package installability checks

.install-deb: &install-deb
  <<: *pkg-base
  stage: install
  script:
    # setup crossbuild architecture
    - |
      if [ -n "$CROSSBUILD_ARCH" ]; then
        dpkg-architecture -A $CROSSBUILD_ARCH > crossbuild.sh
        . crossbuild.sh
        export CROSS_RUN=qemu-${CROSSBUILD_ARCH}
      fi
    # check that bird is _not_ installed now and no user or group bird exists
    - |
      if bird --version >/dev/null 2>&1; then
        echo "Error: BIRD unexpectedly installed"
        exit 1
      fi
      if id -g bird >/dev/null 2>&1; then
        echo "Error: User group 'bird' unexpectedly exist before installation"
        exit 1
      fi
      if id -u bird >/dev/null 2>&1; then
        echo "Error: User 'bird' unexpectedly exist before installation"
        exit 1
      fi
    # install packages
    - find pkg/pkgs/ -type f -name '*.deb' '(' -ls -exec dpkg -i '{}' ';' ')'
    # test that installation is successful
    - ./tools/test-install "$CI_COMMIT_MESSAGE"

.install-rpm: &install-rpm
  <<: *pkg-base
  stage: install
  script:
    # check that bird is _not_ installed now and no user or group bird exists
    - |
      if bird --version >/dev/null 2>&1; then
        echo "Error: BIRD unexpectedly installed"
        exit 1
      fi
      if id -g bird >/dev/null 2>&1; then
        echo "Error: User group 'bird' exist before installation"
        exit 1
      fi
      if id -u bird >/dev/null 2>&1; then
        echo "Error: User 'bird' exist before installation"
        exit 1
      fi
    # install packages
    - find pkg/pkgs/ -type f -name '*.rpm' '(' -ls -exec $RPM_INSTALL_CMD '{}' ';' ')'
    # test that installation is successful
    - ./tools/test-install "$CI_COMMIT_MESSAGE"


install-centos-7-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-centos-7-amd64
  image: registry.nic.cz/labs/bird:centos-7-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-centos-8-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-centos-8-amd64
  image: registry.nic.cz/labs/bird:centos-8-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-rocky-08-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-rocky-08-amd64
  image: registry.nic.cz/labs/bird:rocky-08-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-rocky-09-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-rocky-09-amd64
  image: registry.nic.cz/labs/bird:rocky-09-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-oracle-08-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-oracle-08-amd64
  image: registry.nic.cz/labs/bird:oracle-08-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-oracle-09-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-oracle-09-amd64
  image: registry.nic.cz/labs/bird:oracle-09-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-oracle-10-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-oracle-10-amd64
  image: registry.nic.cz/labs/bird:oracle-10-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-15.0-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-15.0-amd64
  image: registry.nic.cz/labs/bird:opensuse-15.0-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-15.1-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-15.1-amd64
  image: registry.nic.cz/labs/bird:opensuse-15.1-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-15.2-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-15.2-amd64
  image: registry.nic.cz/labs/bird:opensuse-15.2-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-15.3-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-15.3-amd64
  image: registry.nic.cz/labs/bird:opensuse-15.3-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-15.4-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-15.4-amd64
  image: registry.nic.cz/labs/bird:opensuse-15.4-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-15.5-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-15.5-amd64
  image: registry.nic.cz/labs/bird:opensuse-15.5-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-opensuse-16.0-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-opensuse-16.0-amd64
  image: registry.nic.cz/labs/bird:opensuse-16.0-amd64
  variables:
    RPM_INSTALL_CMD: zypper --non-interactive --no-gpg-checks in

install-fedora-33-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-33-amd64
  image: registry.nic.cz/labs/bird:fedora-33-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-34-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-34-amd64
  image: registry.nic.cz/labs/bird:fedora-34-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-35-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-35-amd64
  image: registry.nic.cz/labs/bird:fedora-35-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-36-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-36-amd64
  image: registry.nic.cz/labs/bird:fedora-36-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-37-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-37-amd64
  image: registry.nic.cz/labs/bird:fedora-37-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-38-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-38-amd64
  image: registry.nic.cz/labs/bird:fedora-38-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-39-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-39-amd64
  image: registry.nic.cz/labs/bird:fedora-39-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-40-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-40-amd64
  image: registry.nic.cz/labs/bird:fedora-40-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-41-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-41-amd64
  image: registry.nic.cz/labs/bird:fedora-41-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-42-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-42-amd64
  image: registry.nic.cz/labs/bird:fedora-42-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-43-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-43-amd64
  image: registry.nic.cz/labs/bird:fedora-43-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-fedora-44-amd64:
  <<: *install-rpm
  needs:
    - job: pkg-fedora-44-amd64
  image: registry.nic.cz/labs/bird:fedora-44-amd64
  variables:
    RPM_INSTALL_CMD: rpm -i

install-debian-11-amd64:
  <<: *install-deb
  needs:
    - job: pkg-debian-11-amd64
  image: registry.nic.cz/labs/bird:debian-11-amd64
  variables:

install-debian-11-i386:
  <<: *install-deb
  needs:
    - job: pkg-debian-11-i386
  image: registry.nic.cz/labs/bird:debian-11-i386
  variables:

install-debian-12-amd64:
  <<: *install-deb
  needs:
    - job: pkg-debian-12-amd64
  image: registry.nic.cz/labs/bird:debian-12-amd64
  variables:
crossinstall-mips64el-debian-12-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-mips64el-debian-12-amd64
  image: registry.nic.cz/labs/bird:debian-12-amd64
  variables:
    CROSSBUILD_ARCH: mips64el
crossinstall-s390x-debian-12-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-debian-12-amd64
  image: registry.nic.cz/labs/bird:debian-12-amd64
  variables:
    CROSSBUILD_ARCH: s390x

install-debian-12-i386:
  <<: *install-deb
  needs:
    - job: pkg-debian-12-i386
  image: registry.nic.cz/labs/bird:debian-12-i386
  variables:

install-debian-13-amd64:
  <<: *install-deb
  needs:
    - job: pkg-debian-13-amd64
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
crossinstall-arm64-debian-13-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-arm64-debian-13-amd64
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: arm64
crossinstall-armel-debian-13-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armel-debian-13-amd64
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: armel
crossinstall-armhf-debian-13-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armhf-debian-13-amd64
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: armhf
crossinstall-riscv64-debian-13-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-riscv64-debian-13-amd64
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: riscv64
crossinstall-s390x-debian-13-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-debian-13-amd64
  image: registry.nic.cz/labs/bird:debian-13-amd64
  variables:
    CROSSBUILD_ARCH: s390x

install-debian-13-i386:
  <<: *install-deb
  needs:
    - job: pkg-debian-13-i386
  image: registry.nic.cz/labs/bird:debian-13-i386
  variables:

install-debian-testing-amd64:
  <<: *install-deb
  needs:
    - job: pkg-debian-testing-amd64
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
crossinstall-arm64-debian-testing-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-arm64-debian-testing-amd64
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: arm64
crossinstall-armhf-debian-testing-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armhf-debian-testing-amd64
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: armhf
crossinstall-riscv64-debian-testing-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-riscv64-debian-testing-amd64
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: riscv64
crossinstall-s390x-debian-testing-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-debian-testing-amd64
  image: registry.nic.cz/labs/bird:debian-testing-amd64
  variables:
    CROSSBUILD_ARCH: s390x

install-debian-testing-i386:
  <<: *install-deb
  needs:
    - job: pkg-debian-testing-i386
  image: registry.nic.cz/labs/bird:debian-testing-i386
  variables:

install-ubuntu-18.04-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-18.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-18.04-amd64
  variables:

install-ubuntu-20.04-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-20.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-20.04-amd64
  variables:

install-ubuntu-22.04-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-22.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-22.04-amd64
  variables:

install-ubuntu-24.04-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-24.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
crossinstall-arm64-ubuntu-24.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-arm64-ubuntu-24.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: arm64
crossinstall-armhf-ubuntu-24.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armhf-ubuntu-24.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: armhf
crossinstall-ppc64el-ubuntu-24.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-ppc64el-ubuntu-24.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el
crossinstall-riscv64-ubuntu-24.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-riscv64-ubuntu-24.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: riscv64
crossinstall-s390x-ubuntu-24.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-ubuntu-24.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-24.04-amd64
  variables:
    CROSSBUILD_ARCH: s390x

install-ubuntu-25.04-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-25.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
crossinstall-armhf-ubuntu-25.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armhf-ubuntu-25.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: armhf
crossinstall-ppc64el-ubuntu-25.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-ppc64el-ubuntu-25.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el
crossinstall-riscv64-ubuntu-25.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-riscv64-ubuntu-25.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: riscv64
crossinstall-s390x-ubuntu-25.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-ubuntu-25.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.04-amd64
  variables:
    CROSSBUILD_ARCH: s390x

install-ubuntu-25.10-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-25.10-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
crossinstall-arm64-ubuntu-25.10-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-arm64-ubuntu-25.10-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: arm64
crossinstall-armhf-ubuntu-25.10-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armhf-ubuntu-25.10-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: armhf
crossinstall-ppc64el-ubuntu-25.10-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-ppc64el-ubuntu-25.10-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el
crossinstall-riscv64-ubuntu-25.10-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-riscv64-ubuntu-25.10-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: riscv64
crossinstall-s390x-ubuntu-25.10-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-ubuntu-25.10-amd64
  image: registry.nic.cz/labs/bird:ubuntu-25.10-amd64
  variables:
    CROSSBUILD_ARCH: s390x

install-ubuntu-26.04-amd64:
  <<: *install-deb
  needs:
    - job: pkg-ubuntu-26.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
crossinstall-arm64-ubuntu-26.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-arm64-ubuntu-26.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: arm64
crossinstall-armhf-ubuntu-26.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-armhf-ubuntu-26.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: armhf
crossinstall-ppc64el-ubuntu-26.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-ppc64el-ubuntu-26.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: ppc64el
crossinstall-riscv64-ubuntu-26.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-riscv64-ubuntu-26.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: riscv64
crossinstall-s390x-ubuntu-26.04-amd64:
  <<: *install-deb
  needs:
    - job: crosspkg-s390x-ubuntu-26.04-amd64
  image: registry.nic.cz/labs/bird:ubuntu-26.04-amd64
  variables:
    CROSSBUILD_ARCH: s390x


###################################
## Non-linux build tests in QEMU ##
###################################
.build-birdlab-base: &build-birdlab-base
  <<: *build-base
  stage: build
  needs: []
#  script:
#    - export BRANCH=$CI_COMMIT_BRANCH
#    - autoreconf
#    - ./configure $CONFIGURE_OPTIONS
#    - gmake
#    - gmake check


build-birdlab-openbsd-76:
  <<: *build-birdlab-base
  variables:
    AUTOCONF_VERSION: '2.72'
  tags:
    - birdlab-openbsd-76
    - amd64

build-birdlab-netbsd-09:
  <<: *build-birdlab-base
  tags:
    - birdlab-netbsd-09
    - amd64

build-birdlab-netbsd-10:
  <<: *build-birdlab-base
  tags:
    - birdlab-netbsd-10
    - amd64

build-birdlab-freebsd-13:
  <<: *build-birdlab-base
  tags:
    - birdlab-freebsd-13
    - amd64

build-birdlab-freebsd-13-netlink:
  <<: *build-birdlab-base
  variables:
    CONFIGURE_OPTIONS: --with-sysconfig=bsd-netlink --disable-client
  tags:
    - birdlab-freebsd-13
    - amd64

build-birdlab-freebsd-14:
  <<: *build-birdlab-base
  tags:
    - birdlab-freebsd-14
    - amd64

build-birdlab-freebsd-14-netlink:
  <<: *build-birdlab-base
  variables:
    CONFIGURE_OPTIONS: --with-sysconfig=bsd-netlink --disable-client
  tags:
    - birdlab-freebsd-14
    - amd64


#########################
## Partial build tests ##
#########################

.build-only: &build-only
  <<: *build-docker-linux-amd64
  image: registry.nic.cz/labs/bird:debian-12-amd64
  needs:
    - job: docker-debian-12-amd64
      optional: true


partial-build-linux-aggregator:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=aggregator

partial-build-linux-babel:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=babel

partial-build-linux-bfd:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=bfd

partial-build-linux-bgp:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=bgp

partial-build-linux-bgp,bmp:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=bgp,bmp

partial-build-linux-l3vpn:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=l3vpn

partial-build-linux-mrt:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=mrt

partial-build-linux-ospf:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=ospf

partial-build-linux-pipe:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=pipe

partial-build-linux-radv:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=radv

partial-build-linux-rip:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=rip

partial-build-linux-rpki:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=rpki

partial-build-linux-static:
  <<: *build-only
  variables:
    CONFIGURE_OPTIONS: --with-protocols=static


################################
## Netlab functionality tests ##
################################

.netlab-rules: &netlab-rules
  rules:
    - if: '"$[[ inputs.netlab ]]" == "true"'
    - !reference [ .default-rules ]

build-netlab:
  <<: *netlab-rules
  stage: build
  needs: []
  variables:
    BDIR: build-netlab
  tags:
    - netlab
    - amd64
  script:
    - if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then export BRANCH=mergerequest-$CI_MERGE_REQUEST_IID; else export BRANCH=$CI_COMMIT_BRANCH; fi
    - autoreconf
    - mkdir $BDIR
    - cd $BDIR
    - ../configure
    - make
  artifacts:
    paths:
      - $BDIR/bird
      - $BDIR/birdc
    expire_in: 2 hours

.netlab-test: &test-base
  <<: *netlab-rules
  stage: test
  needs: [build-netlab]
  tags:
    - netlab
    - amd64
  script:
    - sudo rm -rf netlab-failure
    - DIR=$(pwd)
    - cd $TOOLS_DIR
    - sudo git clean -fx
    - sudo git checkout -f master
    - git pull --ff-only
    - "mv $DIR/build-netlab/* netlab/common/"
    - ln -s $STAYRTR_BINARY netlab/common/stayrtr
    - cd netlab
    - sudo ./stop
    - ulimit -f 1048576 # Protect the filesystem from overflowing by log bloat
    - sudo ./runtest -s v2 -m check $TEST_NAME
  after_script:
    - DIR=$(pwd)
    - cd $TOOLS_DIR/netlab
    - sudo ./stop || echo "Stop failed"
    - "mkdir -p $DIR/netlab-failure"
    - git status --porcelain > $DIR/netlab-failure.log
    - for f in $(git status --porcelain | sed -rn 's#^.[^DRT] netlab/##p'); do mkdir -p $DIR/netlab-failure/$(dirname $f); sudo chmod a+rw $f; sudo mv $f $DIR/netlab-failure/$(dirname $f); done
  artifacts:
    when: on_failure
    untracked: true


test-babel-base:
  <<: *test-base
  variables:
    TEST_NAME: cf-babel-base

test-babel-auth:
  <<: *test-base
  variables:
    TEST_NAME: cf-babel-auth

test-ospf-base:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-base

test-ospf-default:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-default

test-ospf-priority:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-priority

test-ospf-nbma:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-nbma

test-ospf-ptmp:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-ptmp

test-ospf-authentication:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-authentication

test-ospf-bfd:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-bfd

test-ospf-custom:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-custom

test-ospf-area:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-area

test-ospf-vrf:
  <<: *test-base
  variables:
    TEST_NAME: cf-ospf-vrf

test-bgp-base:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-base

test-bgp-auth:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-auth

test-bgp-int:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-int

test-bgp-merged:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-merged

test-bgp-flowspec:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-flowspec

test-bgp-rs-multitab:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-rs-multitab

test-bgp-rs-singletab:
  <<: *test-base
  variables:
    TEST_NAME: cf-bgp-rs-singletab

test-ebgp-graceful:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-graceful

test-ebgp-loop:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-loop

test-ebgp-star:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-star

test-ebgp-role:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-role

test-ebgp-import-limit:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-import-limit

test-ebgp-hostname:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-hostname

test-ebgp-bfd-auth:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-bfd-auth

test-ibgp-loop:
  <<: *test-base
  variables:
    TEST_NAME: cf-ibgp-loop

test-ibgp-loop-big:
  <<: *test-base
  variables:
    TEST_NAME: cf-ibgp-loop-big

test-ibgp-flat:
  <<: *test-base
  variables:
    TEST_NAME: cf-ibgp-flat

test-ibgp-bfd-auth:
  <<: *test-base
  variables:
    TEST_NAME: cf-ibgp-bfd-auth

test-rip-base:
  <<: *test-base
  variables:
    TEST_NAME: cf-rip-base

test-rip-vrf:
  <<: *test-base
  variables:
    TEST_NAME: cf-rip-vrf

test-kernel-learn:
  <<: *test-base
  variables:
    TEST_NAME: cf-kernel-learn

test-mpls-bgp:
  <<: *test-base
  variables:
    TEST_NAME: cf-mpls-bgp

test-mpls-bgp-l3vpn:
  <<: *test-base
  variables:
    TEST_NAME: cf-mpls-bgp-l3vpn

test-pipe-collision:
  <<: *test-base
  variables:
    TEST_NAME: cf-pipe-collision

test-ebgp-refresh/gen/imno-basic-imex-basic:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/imno-basic-imex-basic

test-ebgp-refresh/gen/noex-basic-imno-enhanced:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/noex-basic-imno-enhanced

test-ebgp-refresh/gen/imex-basic-noex-none:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/imex-basic-noex-none

test-ebgp-refresh/gen/nono-enhanced-nono-basic:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/nono-enhanced-nono-basic

test-ebgp-refresh/gen/imno-none-imex-basic:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/imno-none-imex-basic

test-ebgp-refresh/gen/noex-none-imno-enhanced:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/noex-none-imno-enhanced

test-ebgp-refresh/gen/imex-none-noex-none:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/imex-none-noex-none

test-ebgp-refresh/gen/nono-none-nono-basic:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/nono-none-nono-basic

test-ebgp-refresh/gen/imno-enhanced-imex-enhanced:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/imno-enhanced-imex-enhanced

test-ebgp-refresh/gen/noex-enhanced-imno-enhanced:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/noex-enhanced-imno-enhanced

test-ebgp-refresh/gen/imex-enhanced-noex-enhanced:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/imex-enhanced-noex-enhanced

test-ebgp-refresh/gen/nono-enhanced-nono-enhanced:
  <<: *test-base
  variables:
    TEST_NAME: cf-ebgp-refresh/gen/nono-enhanced-nono-enhanced

bird2-2.17.5/.mailmap000066400000000000000000000000641521175324500142360ustar00rootroot00000000000000Maria Matejka 
Maria Matejka 
bird2-2.17.5/CONTRIBUTING.md000066400000000000000000000106071521175324500150520ustar00rootroot00000000000000# Contributing to BIRD

We welcome a broad range of contributions to BIRD with some limitations and
caveats.

BIRD is highly optimized for performance in both memory and computation time.
We generally don't accept obviously inefficient code and even though the
quality of the existing codebase quite varies, there should be good reasons
why to commit something slow or greedy.

There are several basic rules for contributing:

- your branch must have understandable commit messages
- your branch must be either:
  - rooted in the current thread-next, aiming for inclusion in BIRD 3
  - or rooted in the master branch; in this case, we may refuse your patch
    if it's completely unmergeable with thread-next
- when incorporating proposed fixes, you may have to rebase your branch
- please add automatic tests (see below)
- upfront and continuous consultation with the development team gives you a
  fast track for merging
- don't forget to update documentation

## Security issues

Please contact us on bird-support@network.cz for private disclosure of any
security issues. This includes any crash in or related to filters, induced by
CLI or by receiving a malformed message by a protocol.

## How to contribute

You can either send a patch (prepared by git format-patch) to our mailing-list
bird-users@network.cz, or you can send just a link to your repository and the
commit hash you're contributing.

## What if your contribution isn't mergable

If your code needs minor updates to align with our standards / taste, we'll
just do these modifications ourselves and either add these as a separate commit
or just update your commit noting this fact in the commit message.

If your code has some major flaws, misses the point or introduces another
problem (e.g. performance issues), we'll refuse your patch. Then we'll either
try to tell you how we prefer to reach the goal, or we may reimplement your
ideas ourselves. We'll mention your original contribution in the commit message.

## Specific kinds of contributions

### Substantial updates

If you feel like the BIRD internals need some major changes and you wish to
implement it, please contact the development team first. We're (as of May 2024)
developing two versions at once and we have some raw thoughts about BIRD's future
which we haven't published yet.

Beware that BIRD is more convoluted inside than it looks like on the surface,
and in many places the learning curve is _very_ steep.

### New protocol implementations

We generally welcome broadening of BIRD capabilities. Upfront consultation is
very much appreciated to align all parties on the development principles,
internal APIs, coding style and more.

### Refactoring and reformatting

Please don't send us _any_ refactoring proposals without previous explicit approval.

### Programmer's documentation, user documentation or tutorials

We welcome updates to enhance the documentation, including the algorithmic
principles, internal libraries and API. We keep our right to reject low quality
contributions altogether.

### Minor changes

Feel free to propose minor fixes in any part of BIRD.

## Testing

There is another repository, https://gitlab.nic.cz/labs/bird-tools.git, where
we store our automatic tests in the netlab/ directory. This repository is quite
messy and you may need some help with it. We're planning to move the Netlab
suite into the main git repository; after we do that, we'll require every
contribution to add tests (if applicable, of course).

These automatic tests are used by our [CI](misc/gitlab/).

## Crediting policy

The credits are scattered over all the source code files; in the commentary
section, you may find typically the original authors of these files or some
major contributors who felt like adding their names there. Overall, if you feel
like your name should be there, include this change in your commits please.

If your name should be changed, please do that change in the source code files.
If your name should be changed in the displayed git commit author / commiter
logs, please submit a patch on the `.mailmap` file.

We are planning to centralize the credits one day; we'll then update this file
accordingly.

## Meta

If some of these rules are breached, you may complain either at the mailing
list, or directly to CZ.NIC who is currently BIRD's maintainer.

If we don't reply within 3 weeks, please ping us. We don't intend to ghost you,
we are just overloaded.

This contributing policy also applies to itself.
bird2-2.17.5/INSTALL000066400000000000000000000031241521175324500136460ustar00rootroot00000000000000How to install BIRD
===================

There are packages available for most of the existing distributions, and it is
possibly a cleaner way to install BIRD than manually.

To install BIRD manually from the source tarball, you need to first build it.

$ ./configure
$ make

After this, you get binaries bird, birdc and birdcl which will run perfectly
from wherever you put them. You can install them to the system paths if you want.

# 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.

For debugging and development, it's recommended to use the -l flag for BIRD
binaries to use bird.conf and bird.ctl in the current directory, instead of
system-wide installation of an unstable version.


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

$ make docs
bird2-2.17.5/Makefile.in000066400000000000000000000207161521175324500146700ustar00rootroot00000000000000# Makefile for the BIRD Internet Routing Daemon
# (c) 1999--2000 Martin Mares 
# (c) 2016--2025 Maria Matejka 

# 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@
PANDOC=@PANDOC@

client=$(addprefix $(exedir)/,@CLIENT@)
daemon=$(exedir)/bird
protocols=@protocols@
PROTO_BUILD := $(protocols) dev kif krt

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@

# Find out which version we are actually building
# This is rewritten by the release tools by hardcoded version
VERSION := $(strip $(shell $(srcdir)/tools/version))

CFLAGS += -DBIRD_VERSION='"$(VERSION)"'

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 gitlab $(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
	$(E)echo GEN $@
	$(Q)echo  >$@ "/* Generated by Makefile, don't edit manually! */"
	$(Q)echo >>$@ "#define PATH_CONFIG_FILE \"@CONFIG_FILE@\""
	$(Q)echo >>$@ "#define PATH_CONTROL_SOCKET \"@CONTROL_SOCKET@\""
	$(Q)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)$(if $(CROSSBUILD_ARCH),qemu-$(CROSSBUILD_ARCH) )$* 2>/dev/null && touch $*.ok $(if $(TEST_RETRY_VERBOSE), || ($(if $(CROSSBUILD_ARCH),qemu-$(CROSSBUILD_ARCH) )$* -ftv && false))

test: testsclean check
check: tests tests_run
tests: $(tests_targets)
tests_run: $(tests_targets_ok)

STATIC_CHECKERS_ENABLE := nullability.NullableDereferenced nullability.NullablePassedToNonnull nullability.NullableReturnedFromNonnull optin.portability.UnixAPI valist.CopyToSelf valist.Uninitialized valist.Unterminated
STATIC_CHECKERS_DISABLE := deadcode.DeadStores
STATIC_SCAN_FLAGS := -o $(objdir)/static-scan/ $(addprefix -enable-checker ,$(STATIC_CHECKERS_ENABLE)) $(addprefix -disable-checker ,$(STATIC_CHECKERS_DISABLE))

static-scan:
	$(E)echo Running static code analysis
	$(Q)$(MAKE) clean
	$(Q)scan-build $(STATIC_SCAN_FLAGS) $(MAKE) -$(MAKEFLAGS)

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)/

# Packaging
archive:
	tools/make-archive

deb:
	tools/make-deb

rpm:
	tools/make-rpm

# Cleanup
clean::
	rm -f $(objdir)/sysdep/paths.h $(objdir)/nest/proto-build.c
	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

# Help dump
help:
	@echo "============================= BIRD make system ============================="
	@echo
	@echo "To build BIRD directly from sources, run './configure'. For more information"
	@echo "about that process, run './configure --help'."
	@echo "To build BIRD from Git repo, run 'autoreconf' before './configure'."
	@echo
	@echo "Source build options:"
	@echo "    make all                  Build BIRD binaries."
	@echo "    make test                 Build and run unit tests."
	@echo "    make docs                 Build documentation."
	@echo
	@echo "Partial build options:"
	@echo "    make obj/path/to/foo.o    Build an object file, don't link."
	@echo "    make obj/path/to/foo.E    Run only the C preprocessor."
	@echo "    make obj/path/to/foo.S    Generate an assembler dump."
	@echo
	@echo "Development tools:"
	@echo "    make static-scan          Run CLang static analyzer."
	@echo "    make tags                 Generate ETags cache."
	@echo "    make cscope               Generate CScope cache."
	@echo
	@echo "Auxiliary commands:"
	@echo "    make help                 Show this help."
	@echo "    make clean                Cleanup the build directory. Useful after"
	@echo "                              major changes or branch switch."
	@echo "    make distclean            Cleanup everything so that you will have to"
	@echo "                              run './configure' again."
	@echo "    make gitlab-local         Re-generate .gitlab-ci.yml without venv"
	@echo "    make gitlab-venv          Re-generate .gitlab-ci.yml inside a tmp venv"
	@echo
	@echo "Distribution commands:"
	@echo "    make install              Install binaries into the system."
	@echo "    make archive              Create a release archive (TGZ).
	@echo "                              This must exist for 'make deb' and 'make rpm'."
	@echo "    make deb                  Create a DEB package for the current system."
	@echo "    make rpm                  Create an RPM package for the current system."
bird2-2.17.5/NEWS000066400000000000000000000725771521175324500133360ustar00rootroot00000000000000Version 2.17.5 (2026-06-09)
  o BGP: Fix several issues in Flowspec handling
  o BMP: Fix off-by-one buffer overflow
  o OSPF: Fix handling of LLS data length field
  o OSPF: Fix OOB read in authentication check
  o OSPF: Fix OOB read in Router-LSA validation
  o Filters: Fix path matching when AS path is too long.
  o OSPF: Fix infinite loop in OSPF Graceful Restart

Version 2.17.4 (2026-04-01)
  o ASPA: Fix downstream validation
  o BGP: Fix restart behavior on reconfiguration
  o Filters: Fix string attributes
  o Logging: Fix error handling

Version 2.17.3 (2025-12-04)
  o RAdv: Fix flags for deprecated prefixes
  o BMP: Fix crash when exporting a route with non-bgp attributes

Version 2.17.2 (2025-09-03)
  o ASPA check fix for AS_SET
  o Invalid check fix in text_or_ipa grammar

Version 2.17.1 (2025-04-29)
  o BSD: Fix build on NetBSD
  o BGP: Fix crash when incoming connection for disabled protocol arrives
  o Documentation fixes

Version 2.17 (2025-04-01)
  o Babel: next hop control for IPv4
  o BGP: link-local next hop format configuration
  o TCP-AO implementation for Linux

Version 2.16.2 (2025-04-01)
  o BFD: password reconfiguration crash fix
  o L3VPN attribute fix
  o Table removal rare crash fix
  o Logging minor fix

Version 2.16.1 (2025-01-10)
  o ASPA: fixed parser bug in static protocol
  o ASPA: fixed static protocol reconfiguration
  o Babel: fixed seqno comparison
  o BSD: fixed onlink flag assumption with Netlink
  o Fixed memory alignment issues
  o Fixed possible rte src collisions in L3VPN

Version 2.16 (2024-12-04)
  o BFD: Set password per session
  o BFD: Accept zero checksum for IPv6-UDP
  o BMP: Refactoring and optimizations
  o OSPF: Allow loopback nexthop in OSPFv3-IPv4
  o RPKI: TCP-MD5 authentication option
  o Filters: Add enum types to filter grammar
  o CLI: Configurable additional control sockets
  o CLI: Timeformat command
  o CLI: Dump commands need a target file
  o ASPA support in filters, Static and RPKI
  o Formalized contributions and credits policy
  o Many bugfixes and improvements

Version 2.15.1 (2024-03-22)
  o OSPF: Fix regression in handling PtP links
  o RPKI: Handle connection resets properly
  o Static: Reject invalid combination of options
  o Fix builds with limited set of protocols

Version 2.15 (2024-03-10)
  o BGP: Send hold timer
  o BGP: New options to specify required BGP capabilities
  o BFD: Improvements to 'show bfd sessions' command
  o RPKI: New 'local address' configuration option
  o Linux: Support for more route attributes, including
    TCP congestion control algorithm
  o Support for UDP logging
  o Static routes can have both nexthop and interface specified
  o Completion of command options in BIRD client
  o Many bugfixes and improvements

Version 2.14 (2023-10-06)
  o MPLS subsystem
  o L3VPN: BGP/MPLS VPNs (RFC 4364)
  o BGP: Access to unknown route attributes
  o RAdv: Custom options
  o Babel: RTT metric extension
  o BMP: Refactored route monitoring
  o BMP: Multiple instances of BMP protocol
  o BMP: Both pre-policy and post-policy monitoring
  o Experimental route aggregation
  o Filter: Method framework
  o Filter: Functions have return type statements
  o Filter: New bytestring data type
  o Kernel: Option to learn kernel routes
  o Many bugfixes and improvements

  Notes:

  User-defined filter functions that return values now should have return type
  statements. We still accept functions without such statement, if they could be
  properly typed.

  For loops allowed to use both existing iterator variables or ones defined in
  the for statement. We no longer support the first case, all iterator variables
  must be defined in the for statement (e.g. 'for int i in bgp_path ...').

  Due to oversight, VRF interfaces were not included in respective VRFs, this is
  fixed now.


Version 2.13.1 (2023-06-23)
  o BGP: Fix role check when no capability option is present
  o Filter: Fixed segfault when a case option had an empty block

  This is a bugfix version.

Version 2.13 (2023-04-21)
  o Babel: IPv4 via IPv6 extension (RFC 9229)
  o Babel: Improve authentication on lossy networks
  o BGP: New 'allow bgp_med' option
  o BSD: Support for IPv4 routes with IPv6 nexthop on FreeBSD
  o Experimental BMP protocol implementation
  o Important bugfixes

  Notes:

  We changed versioning scheme from .. to more common
  .. . From now on, you may expect that BIRD 2.13.x will be
  strictly only fixing bugs found in 2.13, whereas BIRD 2.14 will also contain
  new features.

  This BIRD version contains an alpha release of BMP protocol implementation.
  It is not ready for production usage and therefore it is not compiled by
  default and have to be enabled during installation.


Version 2.0.12 (2023-01-23)
  o Filter: New 'onlink' route attribute
  o Compile-time option to use 4-way tries instead of 16-way ones
  o BSD: Support for kernel route metric and other improvements
  o Important bugfixes

Version 2.0.11 (2022-11-12)
  o BGP roles (RFC 9234)
  o BGP: Keepalive time scaling
  o BGP: New 'min hold time' and 'min keepalive time' options
  o BGP: New 'next hop prefer global' option
  o Filter: For loops and direct recursion
  o Filter: Mixed declarations of local variables
  o Filter: Improved static type checks
  o Filter: Literal [] for empty set
  o Linux: Netlink KRT improvements
  o BSD: Experimental support for Netlink API
  o Memory management improvements
  o Many bugfixes

  Notes:

  In contrast to prior versions, configured keepalive time in BGP now scales
  with negotiated hold time to maintain proportion between the keepalive time
  and the hold time.

  The Linux KRT was updated to use the recent API for IPv6 ECMP routes instead
  of the legacy one. Consequently, the Linux versions older than 4.11 are no
  longer supported, at least for IPv6 ECMP routes. Also, routing table scanning
  now runs separately for each table to avoid congestion.

  There is a minor change in recursive next hop processing. Previously,
  recursive next hop must be resolved through a non-recursive route, now it must
  be resolved through a prefix where both the best route and all routes with the
  same preference (as the best route) are non-recursive. The old behavior might
  lead in some corner cases to an infinite loop of recursive next hop resolution
  due to a priority inversion.

  There is a minor change in the 'configure undo' command, it is no longer
  available after failed reconfiguration, as the old configuration is already
  released.


Version 2.0.10 (2022-06-16)
  o BGP performance improvements
  o BFD: New 'strict bind' option
  o RPKI: VRF support
  o Allow use of 240.0.0.0/4 as a private range
  o BIRD client uses exit status to report errors
  o Important bugfixes

Version 2.0.9 (2022-02-09)
  o BGP: Flowspec validation procedure
  o Babel: MAC authentication support
  o Routing table configuration blocks
  o Optional prefix trie in routing table for faster LPM/interval queries
  o CLI: New 'show route in ' command
  o Filter: Faster (16-way) prefix sets
  o Filter: MPLS label route attribute
  o Filter: Operators to pick community components
  o Filter: Operators to find minimum and maximum element of lists
  o BGP: New 'free bind' option
  o BGP: Log route updates that were changed to withdraws
  o BGP: Improved 'invalid next hop' error reporting
  o OSPF: Allow ifaces with host address as unnumbered PtP or PtMP ifaces
  o OSPF: All packets on PtP networks should be sent to AllSPFRouters address
  o Scripts for apkg-powered upstream packaging for deb and rpm
  o Support for Blake2s and Blake2b hash functions
  o Security keys / passwords can be entered in hexadecimal digits
  o Memory statistics split into Effective and Overhead
  o Linux: New option 'netlink rx buffer' to specify netlink socket buffer size
  o BSD: Assume onlink flag on ifaces with only host addresses
  o Many bugfixes

  Notes:

  For OSPF on PtP network, BIRD now sends all packets to multicast AllSPFRouters
  address (as required in RFC 2328 8.1). This likely breaks setups with multiple
  neighbors on a network configured as PtP, which worked in previous versions.
  Such links should be configured as PtMP.

  Since Linux 5.3, netlink socket can be flooded by route cache entries during
  route table scan. This version mitigates that issue by using strict netlink
  filtering.


Version 2.0.8 (2021-03-18)
  o Automatic channel reloads based on RPKI changes
  o Multiple static routes with the same network
  o Use bitmaps to keep track of exported routes
  o Per-channel debug flags
  o CLI commands show info from multiple protocols
  o Linux: IPv4 routes with IPv6 nexthops
  o Filter: Optimized redesign of prefix sets
  o Filter: Improved type checking of user filters
  o Filter: New src/dst accessors for Flowspec and SADR
  o Filter: New 'weight' route attribute
  o Filter: BGP path mask loop operator
  o Filter: Remove quitbird command
  o RIP: Demand circuit support (RFC 2091)
  o BGP: New 'allow as sets' and 'enforce first as' options
  o BGP: Support for BGP hostname capability
  o BGP: Support for MD5SIG with dynamic BGP
  o BFD: Optional separation of IPv4 / IPv6 BFD instances
  o BFD: Per-peer session options
  o RPKI: Allow build without libSSH
  o RPKI: New 'ignore max length' option
  o OSPF: Redesign of handling of unnumbered PtPs
  o OSPF: Allow key id 0 in authentication
  o Babel: Use onlink flag for routes with unreachable next hop
  o Many bugfixes

  Notes:

  Automatic channel reloads based on RPKI changes are enabled by default,
  but require import table enabled when used in BGP import filter.

  BIRD now uses bitmaps to keep track of exported routes instead of
  re-evaluation of export filters. That should improve speed and accuracy in
  route export handling during reconfiguration, but takes some more memory.

  Per-channel debug logging and some CLI commands (like 'show ospf neighbors')
  defaulting to all protocol instances lead to some minor changes in log and
  CLI output. Caution is recommended when logs or CLI output are monitored by
  scripts.


Version 2.0.7 (2019-10-11)
  o BGP: Accumulated IGP metric (RFC 7311)
  o Important filter reconfiguration bugfix
  o Several other bugfixes

Version 2.0.6 (2019-09-10)
  o RAdv: Solicited unicast RAs
  o BGP: Optional Adj-RIB-Out
  o BGP: Extended optional parameters length
  o Filter: Sets and set expressions in path masks
  o Several important bugfixes

Version 2.0.5 (2019-08-01)
  o OSPF Graceful restart (RFC 3623, RFC 5187)
  o BGP: Dynamic BGP
  o BGP: Promiscuous ASN mode
  o BGP: Mandatory option for channels
  o BFD: Support for VRFs
  o Graceful restart command
  o Redesigned filtering code
  o Many bugfixes

  Notes:

  Previous version introduced an error in handling of OSPF NSSA-LSA, causing
  compatibility issues with proper implementations. The error is fixed in this
  version, therefore there are compatibility issues in OSPF NSSA areas between
  this and previous version.


Version 2.0.4 (2019-02-27)
  o OSPF: Opaque LSAs (RFC 5250)
  o OSPF: DN-bit handling (RFC 4576)
  o Preferred route counters are back
  o Important BGP bugfix
  o Several bugfixes related to route propagation
  o some minor bugfixes

Version 2.0.3 (2019-01-05)
  o MRT table dumps (RFC 6396)
  o BGP Long-lived graceful restart
  o BGP: Optional import table (Adj-RIB-In)
  o BGP: Extend 'next hop keep' and 'next hop self' options
  o BGP: Improved VRF support
  o OSPF: Authentication trailer for OSPFv3 (RFC 7166)
  o Babel: New option to randomize router ID
  o Filter: Custom route attributes
  o Filter: Support for src accessor to SADR source prefix
  o Filter: Support for VPN_RD sets
  o Filter: Make ifname attribute modifiable
  o Perf: Protocol to measure BIRD performance internally
  o More verbose error messages in config processing
  o Log file size limit / log rotation
  o Many bugfixes

  Notes:

  Export of routes to RS EBGP (route server) sessions from other sources than
  RS EBGP sessions was changed that ASN is no longer prepended to BGP_PATH in
  that case. The change does not affect regular BGP configurations or regular
  route servers that have only RS EBGP peers.

  For BGP route servers and route reflectors, the default value of option
  'next hop keep' was changed to a more appropriate value.

  Attributes for OSPF and Babel metrics are no longer reset when exported to
  these protocols and could be set anywhere in BIRD. As a result, OSPF metric is
  kept when a route is reannounced between OSPF instances. Also, when route is
  exported to OSPF with both ospf_metric1 and ospf_metric2 attributes it is now
  propagated as OSPF-E2 route instead of as OSPF-E1 route.

  Compiling BIRD with --enable-debug no longer automatically activates debug
  mode (-d option) nor local mode (-l option). Also, debug mode with output to
  file (-D option) no longer not forces foreground mode (-f option).

  The configure script now uses standard option --runstatedir, the old option
  --with-runtimedir is deprecated.


Version 2.0.2 (2018-03-22)
  o Source-specific routing support for Linux kernel and Babel
  o BGP: New option 'disable after cease'
  o Filter: Allow silent filter execution
  o Filter: Fixed stack overflow in BGP mask expressions.
  o Several bugfixes

  Notes:

  Syntax prefix:netmask for IPv4 prefixes was dropped. Just use prefix/pxlen.


Version 2.0.1 (2018-01-16)
  o Linux MPLS kernel support
  o Better handling of channels inherited from templates
  o Default EBGP Route Propagation Behavior without Policies (RFC 8212)
  o Many bugfixes

  Notes:

  To satisfy requirements of RFC 8212, external BGP protocols now require
  explicit configuration of import and export policies.


Version 2.0.0 (2017-12-11)
  o Integrated IPv4 + IPv6 design
  o Support for MPLS next hops
  o Support for VPNv4 and VPNv6 networks
  o Microsecond timers infrastructure
  o Basic VRF support
  o Babel: Support for dual-stack IPv4/IPv6
  o Babel: Many improvements and bugfixes
  o Major BGP protocol redesign
  o Full support for Multiprotocol BGP
  o BGP multicast support (SAFI 2)
  o BGP flowspec support (RFC 5575)
  o BGP with MPLS labels (RFC 3107)
  o BGP MPLS/VPN support (RFC 4364)
  o BGP 6PE - IPv6 NLRI over IPv4 MPLS (RFC 4798)
  o BGP IPv4 NLRI with an IPv6 Next Hop (RFC 5549)
  o BGP Confederations (RFC 5065)
  o BGP Shutdown communication (RFC 8203)
  o BGP: Allow exchanging LOCAL_PREF with eBGP peers
  o BGP: Allow to specify interface for regular sessions
  o OSPF: Support of address families in OSPFv3
  o OSPF: Enable ECMP and Link detection by default
  o RAdv: Support for more specific routes (RFC 4191)
  o RAdv: Proper handling of prefix retraction
  o RIP: Enable ECMP and Link detection by default
  o Redesign of RPKI handling
  o New RPKI-Router protocol
  o Static: Minor overhaul
  o Static: Support for all new route types
  o Kenrel: Default Linux kernel metric changed to 32
  o Kernel: Fix IPv6 ECMP handling with Linux 4.11+
  o Update of show route command
  o BIRD client persistent history
  o New build system
  o Unit tests
  o ...

  Notes:

  Tables are now defined with appropriate net type keyword. Protocols and tables
  are now connected by explicit channels, most related protocol options (table,
  import, export, ...) are now channel options. See doc/bird.conf.example2 for
  configuration examples. Some options were removed/replaced.


Version 1.6.3 (2016-12-21)
  o Large BGP communities
  o BFD authentication (MD5, SHA1)
  o SHA1 and SHA2 authentication for RIP and OSPF
  o Improved documentation
  o Several bug fixes

Version 1.6.2 (2016-09-29)
  o Fixes serious bug introduced in the previous version

Version 1.6.1 (2016-09-22)
  o Support for IPv6 ECMP
  o Better handling of IPv6 tentative addresses
  o Several updates and fixes in Babel protocol
  o Filter: New !~ operator
  o Filter: ASN ranges in bgpmask
  o KRT: New kernel protocol option 'metric'
  o KRT: New route attribute 'krt_scope'
  o Improved BIRD help messages
  o Fixes memory leak in BGP multipath
  o Fixes handling of empty path segments in BGP AS_PATH
  o Several bug fixes

Version 1.6.0 (2016-04-29)
  o Major RIP protocol redesign
  o New Babel routing protocol
  o BGP multipath support
  o KRT: Add support for plenty of kernel route metrics
  o KRT: Allow more than 256 routing tables
  o Static: Allow to specify attributes for static routes
  o Static: Support for BFD controlled static routes
  o FreeBSD: Setup password for BGP MD5 authentication
  o IO: Remove socket number limit
  o Plenty of bug fixes

  Upgrade notes:

  For RIP, most protocol options were moved to interface blocks.


Version 1.5.0 (2015-04-20)
  o Major OSPF protocol redesign.
  o OSPFv2 multi-instance extension (RFC 6549).
  o BGP AS-wide unique router ID (RFC 6286).
  o BGP enhanced route refresh (RFC 7313).
  o Link state support in BGP.
  o Latency tracking and internal watchdog.
  o Uses high port range for BFD on BSD.
  o Increase max symbol length to 64.
  o Allows to define unnamed protocols from templates.
  o Fixes two serious bugs in BGP.
  o Several bugfixes and minor improvements.
  o Several minor option changes:
     - OSPF: Protocol-wide 'instance id' option added.
     - BGP: Parameters to option 'neighbor' extended.
     - BGP: Separate option 'interface' added.
     - BGP: Option 'start delay time' renamed to 'connect delay time'.
     - BGP: Option 'route limit' deprecated.

  Upgrade notes:

  For OSPF, there are deep internal changes, but user-visible changes
  are limited to log messages and minor changes in formatting of command
  output.

  For BGP, version 1.5.0 is essentially a minor release. There are two
  deprecated options ('start delay time' and 'route limit') and some
  minor formatting changes.


Version 1.4.5 (2014-10-06)
  o New 'show route noexport' command option.
  o Port option for BGP sessions.
  o Better constant handling in set literals.
  o Better rate filtering of log messages.
  o Several minor bugfixes.

Version 1.4.4 (2014-07-09)
  o Extended OSPF multipath support.
  o Default router preference for RAdv.
  o Significant changes in socket layer.
  o Important bugfix in BGP.
  o Several minor bugfixes.

Version 1.4.3 (2014-04-14)
  o Important bugfix in IPv6 BGP.

Version 1.4.2 (2014-04-02)
  o Important bugfix in BFD.

Version 1.4.1 (2014-03-31)
  o BGP add-path support (RFC draft).
  o BGP graceful restart (RFC 4724).
  o OSPF: many changes in socket layer.
  o OSPF: support for secondary addresses in BSD.
  o OSPF: names for vlink pseudointerfaces (vlinkX).
  o Several bugfixes.

Version 1.4.0 (2013-11-25)
  o BFD protocol (RFC 5880).
  o BFD support for OSPF and BGP.
  o New 'allow local as' option for BGP.
  o Filters allows setting gw, ifname and ifindex.
  o Filter operator 'delete/filter' extended to bgp_paths.
  o Filter operator 'len' extended to [e]clists.
  o BIRD client now allows shorthands for noninteractive commands.
  o Flag -P for PID file support.
  o Flag -f added to force BIRD to run in foreground.
  o Protocol export/import/receive limits are checked during reconfiguration.
  o Several bugfixes and minor improvements.
  o Several minor but incompatible changes:
     - IBGP is multihop by default.
     - Changes primary address selection on BSD to the first one.
     - Integers in filters are handled as unsigned.
     - ISO 8601 time formats used by default.
     - Import of device routes from kernel protocol allowed.
     - Last state change now tracks just protocol state change.
     - Minor changes to default router ID calculation.

Version 1.3.11 (2013-07-27)
  o OSPF stub router option (RFC 3137).
  o TTL security for OSPF and RIP.
  o Protocol packet priority and traffic class handling.
  o Multiple routing tables support for FreeBSD and OpenBSD.
  o Extends constants to all filter data types.
  o Implements eval command.
  o 'bgppath ~ int set' filter operation.
  o Several bugfixes.

Version 1.3.10 (2013-04-30)
  o Lightweight BIRD client for embedded environments.
  o Dynamic IPv6 router advertisements.
  o New 'next hop keep' option for BGP.
  o Smart default routing table for 'show route export/preexport/protocol'.
  o Automatic router ID selection could be configured to use address of loopback.
  o Allows configured global addresses of NBMA neighbors in OSPFv3.
  o Allows BIRD commands from UNIX shell even in restricted mode.
  o Route limits inherited from templates can be disabled.
  o Symbol names enclosed by apostrophes can contain dots.
  o Several bugfixes.

Version 1.3.9 (2013-01-11)
  o BIRD can be configured to keep and show filtered routes.
  o Separate receive and import limits.
  o Several new reconfiguration cmd options (undo, timeout, check).
  o Configurable automatic router ID selection.
  o Dragonfly BSD support.
  o Fixed OSPFv3 vlinks.
  o Several minor bugfixes.

Version 1.3.8 (2012-08-07)
  o Generalized import and export route limits.
  o RDNSS and DNSSL support for RAdv.
  o Include in config file support wildcards.
  o History deduplication in BIRD client.
  o New route attributes krt_source, krt_metric.
  o Different instance ID support for OSPFv3.
  o Real broadcast mode for OSPFv2.
  o Several minor bugfixes.

Version 1.3.7 (2012-03-22)
  o Route Origin Authorization basics.
  o RIPng working again.
  o Extended clist operations in filters.
  o Fixes several bugs in BSD iface handling.
  o Several minor bugfixes and enhancements.

Version 1.3.6 (2012-01-20)
  o Important bugfix in BGP.

Version 1.3.5 (2012-01-10)
  o Protocol templates.
  o Deterministic MED option for BGP.
  o Support for link-local addresses in BGP and static protocols.
  o Several bugfixes.

Version 1.3.4 (2011-10-10)
  o Static recursive routes.
  o Several bugfixes.

Version 1.3.3 (2011-09-11)
  o OSPF NSSA.
  o BGP extended communities.
  o BGP TTL security.
  o Configuration option "include" added (based on patch from Alexander V. Chernikov).
  o Some minor bugfixes.

Version 1.3.2 (2011-07-08)
  o Allows run with restricted privileges.
  o Community list filter operation.
  o Fixes several problems in filter syntax:
     - Fixes several conflicts in the grammar.
     - Fixes a bug in (a..b, c) pair patterns.
     - Makes pair patterns orthogonal.
     - Allows term expressions in pair patterns without additional ( ).
     - Allows several comma separated values in switch cases.
  o Many bugfixes.

Version 1.3.1 (2011-05-02)
  o Added Linux kernel route attributes krt_prefsrc and krt_realm.
  o Added BGP option 'med metric' related to MED handling.
  o Allows to use constants from /etc/iproute2/rt_* files.
  o Several bugfixes.

Version 1.3.0 (2011-03-31)
  o Proper iBGP (can be used with IGP).
  o Multipath support (OSPF and static).
  o L2 link state detection.
  o IPv6 router advertisements.
  o Much improved OSPF reconfiguration.
  o Point-to-MultiPoint interfaces (OSPF).
  o Minor changes and improvements in config file grammar.
  o Better community list matching.
  o Changes default behavior of BGP IPv6 socket to v6only.
    Use 'listen bgp dual' for the old behavior.
  o Changes default for handling missing link-local addresses on
    route servers. Use 'missing lladdr drop' for the old behavior.
  o Important bugfix for OSPF.
  o Several minor bugfixes.

Version 1.2.5 (2010-10-10)
  o Several mostly minor bugfixes.

Version 1.2.4 (2010-08-03)
  o Added 'show memory' command.
  o Important bugfix in IPv6 BGP.
  o Several minor bugfixes.

Version 1.2.3 (2010-06-01)
  o Pattern matching for community lists.
  o Many fixes in OSPF protocol (esp. in multi-areas and vlinks).
  o Several minor bugfixes.

Version 1.2.2 (2010-04-10)
  o Much better BSD kernel support (IPv6, alien routes, ...).
  o Deep OSPF socket changes, fixes OSPFv2/v3 behavior on BSD.
  o OSPFv2 in Linux now supports more non-stub IP prefixes
    on one physical iface.
  o Export of device routes to the kernel is more restricted.
  o Routes with strange scope not allowed in BIRD routing tables.
  o New filterable route attributes bgp_originator_id,
    bgp_cluster_list and ospf_router_id.
  o Restricted read-only CLI (option -r).
  o Pattern matching for 'show protocols' command.
  o BGP protocol details in 'show protocols all' command.
  o Configurable syslog name (and default on IPv6 changed).
  o Statistic counters for pipes were fixed.
  o Many bugfixes in BGP, OSPF, filters, ...

Version 1.2.1 (2010-02-11)
  o Option 'interpret communities' allows to override implicit handling
    of well-known communities.
  o 'configure' command uses route reload when filters change.
  o Adds router ID of advertising router as OSPF route attribute.
  o 'show route' command indicates primary route and shows OSPF Router ID.
  o Configurable date/time formats.
  o Symbol names can be enclosed by '' and so include hyphen and start with number.
  o Several minor bugfixes.

Version 1.2.0 (2010-01-05)
  o Implements OSPFv3 (IPv6 support for OSPF). Because the code is
    shared with OSPFv2 and there were deep changes in it, we suggest
    caution during upgrade to OSPF users. Some advanced features
    (like NSSA, vlinks and authentication) are not yet implemented.
  o Implements MRTdump - binary logging protocol compatible with other
    routing daemons. Only BGP part of MRTdump is yet implemented.
  o Changes default value of BGP attribute LOCAL_PREF from 0 to 100.
    Use 'default bgp_local_pref 0' BGP protocol option for the old
    behavior. The new value is suggested by RFC 4277.
  o Changes default mode of pipes from opaque to transparent.
    Use 'mode opaque' protocol option if the old behavior is needed.
    Opaque pipe mode is deprecated and might be removed in the future.

Version 1.1.7 (2009-12-20)
  o Implements BGP Route Refresh (RFC 2918).
  o Implements route reload command.
  o Deep changes and bugfixes in pipe protocol.
  o Bugfix in OSPF premature aging of LSA.
  o Bugfix in OSPF next hop calculation.
  o Bugfix in core related to route withdraws.
  o Several minor bugfixes.

Version 1.1.6 (2009-11-19)
  o Implements RFC 5004 - prefer older external routes.
  o There is a change how route servers handle missing IPv6 link
    local addresses in next hop atribute - see 'missing lladdr'
    option.
  o Several minor features (description field, parse check option).
  o Several minor bugfixes.

Version 1.1.5 (2009-10-29)
  o Better scalability of BGP.
  o New accessors for AS path - first and last.
  o Allows to set protocol-specific router ID.
  o Allows import kernel 'onlink' routes.
  o Endianity check in buildsystem changed.

Version 1.1.4 (2009-10-02)
  o BGP passive option.
  o Several minor bugfixes.

Version 1.1.3 (2009-09-11)
  o Bugfix in core
  o Bugfix in BGP related to AS2->AS4 conversion.

Version 1.1.2 (2009-08-23)
  o Allow more kernel routing tables in IPv6.
  o Bugfix in core

Version 1.1.1 (2009-08-14)
  o 'more' style paging in BIRD client.
  o Important core bug fixed.
  o Portability to non-x86 related bugfixes.
  o As usual, miscellaneous bugfixes.

Version 1.1.0 (2009-06-28)
  o Parametrized pair and path mask expressions in the filter language.
  o Transparent pipe mode allows to implement BGP route server with
    independent route policy for each peer.
  o Kernel route table synchronization does not allow overwriting
    of alien routes.
  o Configurable BGP import route limits.
  o During BGP error delay, incoming connections are rejected.
  o BGP route statistics.
  o Better support for multiple network addresses on OSPF interfaces.
  o As usual, miscellaneous bugfixes.

Version 1.0.15 (2009-05-25)
  o FreeBSD and NetBSD port renewed. OpenBSD port introduced.
  o import/preimport 'show route' modifiers was renamed to export/preexport
    for consistency with filters.
  o Minor change in the grammar of 'interface' config option.
  o Many bugfixes in IPv6 BGP.
  o As usual, miscellaneous bugfixes.

Version 1.0.14 (2009-04-28)
  o A lot of bugfixes in BGP, OSPF and core.
  o A bugfix in filters in the pipe protocol. It is recommended to
    check whether the new behavior of used pipe filters is consistent
    with expectations.
  o Reimplementation of prefix sets and a slight change in the meaning
    of some prefix set patterns.

Version 1.0.13 (2009-03-14)
  o A lot of bugfixes in BGP, OSPF and core
  o A new syntax for BGP masks

Version 1.0.12 (2008-11-12)
  o new BGP features: BGP MD5, ASN32, BGP route reflector
  o BGP bugfixes

...

Version 1.0.9 (2004-07-15)
  o  Minor bugfix in RIP
  o  A lot of OSPF code rewritten, OSPF supports multiple areas,
     virtual links, MD5 authentication. It is fully compatible
     with rfc2329.

Version 1.0.8 (2004-06-07)
  o  A lot of bug fixes in RIP, OSPF and BGP (thanx to Andreas Steinmetz)
  o  FreeBSD and NetBSD port introduced
  o  Complete code clean up

Version 1.0.7 (2003-08-20)
  o  OSPF bug fixes

Version 1.0.6 (2003-04-06)

  o  No more byte order problems in RIP authentication. Thanks to
     Eric Leblond  for a patch.
  o  Fixed interoperability problems with Cisco and Zebra when talking
     IPv6 BGP.
  o  Handle more primary addresses with different scopes gracefully.
     IPv6 needs that.
  o  Comparison of prefixes in filters doesn't ignore their lengts.
  o  As usually, OSPF bug fixes.
  o  Documentation building tools now work with recent linuxdoc-tools.

Version 1.0.5 (2001-06-09)

  o  Minor cleanups in the libraries.
  o  Removed a couple of warnings when compiling with newer glibc.
  o  OSPF bug fixes.

Version 1.0.4 (2000-09-04)

  o  Fixed a serious bug in 1.0.3.

Version 1.0.3 (2000-09-03)

  o  OSPF works better on NBMA networks. Some configuration tags added.

Version 1.0.2 (2000-08-24)

  o  Minor bug fixes to OSPF.

Version 1.0.1 (2000-06-22)

  o  Updated documentation and fixed a couple of bugs.

Version 1.0.0 (2000-06-09)

  o  First stable release.

Version 0.0.0 (2000-05-13)

  o  First public development release.
bird2-2.17.5/README000066400000000000000000000104141521175324500134750ustar00rootroot00000000000000                       BIRD Internet Routing Daemon

                     Home page  http://bird.nic.cz/
                  Mailing list  bird-users@network.cz

                (c) 1998--2008  Martin Mares 
                (c) 1998--2000  Pavel Machek 
                (c) 1998--2008  Ondrej Filip 
                (c) 2009--now   CZ.NIC z.s.p.o.

================================================================================

BIRD is a dynamic IP routing daemon with full support of most 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 repositories for Debian and Ubuntu
	   https://pkg.labs.nic.cz/doc/?project=bird
	o  From source code of the latest stable release version
	   https://bird.nic.cz/get-bird/
	o  From current development code in Git repository
	   https://gitlab.nic.cz/labs/bird/

See the file INSTALL for information about installation from source code.

Documentation
=============

Online documentation is available at https://bird.nic.cz/doc/latest/.

You can also build separate HTML files and PDF from the doc directory by
`make docs' and install it by `make install-docs', but you'll need SGMLtools
and LaTeX to be installed on your machine.

You can also download a neatly formatted PDF version (packed in TGZ)
from the online documentation page at https://bird.nic.cz/doc/latest/

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.

Subscribe:	http://bird.network.cz/mailman/listinfo/bird-users/
Archive:	http://bird.network.cz/pipermail/bird-users/

Please don't send security issues to the mailing-list, contact us instead at
bird-support@network.cz which is a private e-mail address where you also can
get commercial support for your BIRD deployment.

We don't use our gitlab issues for reporting but we're partially tracking
the core developent team's work there publicly.

Contributing
============

Please see the CONTRIBUTING.md file to find how to contribute to BIRD.

License
=======

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, see .

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 . 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
bird2-2.17.5/VERSION000066400000000000000000000000071521175324500136620ustar00rootroot000000000000002.17.5
bird2-2.17.5/aclocal.m4000066400000000000000000000106701521175324500144610ustar00rootroot00000000000000dnl ** Additional Autoconf tests for BIRD configure script
dnl ** (c) 1999 Martin Mares 

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_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 
	      #include 
	      #include 
	      #include 
	      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 
	  #include 
	],
        [ 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 
	      #include 
	    ],
            [ 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  ],
        [ syslog(0, ""); ]
      )
    ],
    [bird_cv_lib_log=yes],
      [
        bird_tmp_libs="$LIBS"
        LIBS="$LIBS -llog"
        AC_LINK_IFELSE([
          AC_LANG_PROGRAM(
            [ #include  ],
            [ 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
])

AC_DEFUN([BIRD_CHECK_AND_ADD_GCC_OPTION],
[
  BIRD_CHECK_GCC_OPTION($@)
  BIRD_ADD_GCC_OPTION($1,$2)
])

# 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
])
bird2-2.17.5/bird-gdb.py000066400000000000000000000123401521175324500146410ustar00rootroot00000000000000class 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_RTD": "i",
            "T_ENUM_ROA": "i",
            "T_ENUM_NET_TYPE": "i",
            "T_ENUM_RA_PREFERENCE": "i",
            "T_ENUM_AF": "i",
            "T_IP": "ip",
            "T_NET": "net",
            "T_STRING": "s",
            "T_BYTESTRING": "bs",
            "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.")
bird2-2.17.5/bird.conf000066400000000000000000000020201521175324500143760ustar00rootroot00000000000000/*
 *	This is a simple example configuration file with no aim for completeness.
 *	See documentation for full description.
 */

# Router ID in IPv4 format
router id 62.168.0.1;

# Load device information from kernel.
protocol device {}

# Generate direct routes for interfaces. Useful on BSD.
protocol direct {
	ipv4;
	disabled;
}

protocol direct {
	ipv6;
	disabled;
}

# Feed routes to kernel FIB
protocol kernel {
	ipv4 { export all; import all; };
	learn;			# Learn all routes from the kernel
#	scan time 10;		# Scan kernel tables every 10 seconds
}

protocol kernel {
	ipv6 { import all; };
	learn;
}

# Static route feed
protocol static {
	ipv4 { export all; };
	route 10.0.0.0/24 via 55.55.55.44;
	route 10.10.0.0/16 blackhole;
	route 10.20.0.0/20 unreachable;
	route 10.30.50.0/28 prohibit;
}

protocol static {
	ipv6 { export all; };
	route 2001:db8:1::/48 via 5555::6666;
	route 2001:db8:2::/48 blackhole;
	route 2001:db8:3::/48 prohibit;
	route 2001:db8:4::/48 unreachable;
}

protocol rip {
	ipv4;
}

protocol rip ng {
	ipv6;
}
bird2-2.17.5/client/000077500000000000000000000000001521175324500140735ustar00rootroot00000000000000bird2-2.17.5/client/Doc000066400000000000000000000000371521175324500145230ustar00rootroot00000000000000H Client
S client.c commands.c
bird2-2.17.5/client/Makefile000066400000000000000000000003131521175324500155300ustar00rootroot00000000000000src := 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
bird2-2.17.5/client/birdc.c000066400000000000000000000105201521175324500153200ustar00rootroot00000000000000/*
 *	BIRD Client - Readline variant I/O
 *
 *	(c) 1999--2004 Martin Mares 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include 
#include 
#include 
#include 

#include 
#include 
#include 

#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);
  /*  ? is "internal". Do not submit command in non interactive session */
  if (!interactive)
    rl_replace_line("", 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();
}
bird2-2.17.5/client/birdcl.c000066400000000000000000000046151521175324500155040ustar00rootroot00000000000000/*
 *	BIRD Client - Light variant I/O
 *
 *	(c) 1999--2004 Martin Mares 
 *      (c) 2013 Tomas Hlavacek 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include 
#include 
#include 
#include 
#include 

#include 
#include 

#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();
}
bird2-2.17.5/client/client.c000066400000000000000000000201461521175324500155200ustar00rootroot00000000000000/*
 *	BIRD Client
 *
 *	(c) 1999--2004 Martin Mares 
 *	(c) 2013 Tomas Hlavacek 
 *
 *	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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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 */
int last_code;		/* Last return code */

static int num_lines, skip_input;
int term_lns, term_cls;


/*** Parsing of arguments ***/

static void
usage(char *name)
{
  fprintf(stderr, "Usage: %s [-s ] [-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(1);
  }

  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((last_code < 8000) ? 0 : 1);
    }

  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);

      last_code = code;

      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, "?");
      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;
}
bird2-2.17.5/client/client.h000066400000000000000000000013661521175324500155300ustar00rootroot00000000000000/*
 *	BIRD Client
 *
 *	(c) 1999--2000 Martin Mares 
 *
 *	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))
bird2-2.17.5/client/cmds.Y000066400000000000000000000004511521175324500151530ustar00rootroot00000000000000#
#	BIRD -- Internal Commands Of The Client
#
#	(c) 2000 Martin Mares 
#
#	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]])
bird2-2.17.5/client/commands.c000066400000000000000000000154271521175324500160510ustar00rootroot00000000000000/*
 *	BIRD Client -- Command Handling
 *
 *	(c) 1999--2000 Martin Mares 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include 
#include 
#include 

#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;
  int is_option;
};

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;
  u8 final;
  s8 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; icommand;

      new = &cmd_root;
      while (*c)
	{
	  /* Walk through the keywords in the command from start of the command
	   * to its end */
	  char *d = c;
	  while (*c && !isspace_(*c))
	    c++;
	  old = new;
	  for(new=old->son; new; new=new->sibling)
	    if (new->len == c-d && !memcmp(new->token, d, c-d))
	      break;
	  if (!new)
	    {
	      /* If new keyword is not stored yet */
	      int size = sizeof(struct cmd_node) + c-d;
	      new = malloc(size);
	      bzero(new, size);
	      /* Making this keyword child of the previons
	       * keyword in the command */
	      *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 */
	    }
	  while (isspace_(*c))
	    c++;
	}

      /* In new there is now stored the last keyword in command.
       * Only this command is going to contain cmd and help */
      if (cmd->is_real_cmd)
	new->cmd = cmd;
      else
	new->help = cmd;

      if (cmd->is_option)
	old->final = 1;
    }
}

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_node *m)
{
  /* Go through children of the base keyword. Each keyword has its own node. */
  for (struct cmd_node *mm = m->son; mm; mm = mm->sibling)
  {
    /* Print hints for all of the children of given keyword. */
    if (mm->help)
      cmd_do_display_help(mm->help);
    else if (mm->cmd)
      cmd_do_display_help(mm->cmd);
    else
    {
      /* This child does not contain hint, let's try its children instead
       * (this child might be first part of multi keyword command) */
      cmd_display_help(mm);
    }
  }
}

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);
}

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 && !n->final)
    {
      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;
    }

  if (n && n->cmd)
    cmd_do_display_help(n->cmd);

  /* Currently no help for options */
  if (n->final)
    return;

  cmd_display_help(n);
}

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 && !n->final)
    {
      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 && !n->final)
    {
      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;
}
bird2-2.17.5/client/util.c000066400000000000000000000017601521175324500152200ustar00rootroot00000000000000/*
 *	BIRD Client -- Utility Functions
 *
 *	(c) 1999--2000 Martin Mares 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include 
#include 
#include 

#include "nest/bird.h"
#include "lib/string.h"
#include "client/client.h"

/* Client versions of logging functions */

static void
vlog_cli(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, " ... ");
  fputs(buf, stderr);
  fputc('\n', stderr);
}

void
bug(const char *msg, ...)
{
  va_list args;

  va_start(args, msg);
  cleanup();
  fputs("Internal error: ", stderr);
  vlog_cli(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_cli(msg, args);
  va_end(args);
  exit(1);
}
bird2-2.17.5/conf/000077500000000000000000000000001521175324500135425ustar00rootroot00000000000000bird2-2.17.5/conf/Doc000066400000000000000000000000441521175324500141700ustar00rootroot00000000000000H Configuration
S conf.c
S cf-lex.l
bird2-2.17.5/conf/Makefile000066400000000000000000000020001521175324500151720ustar00rootroot00000000000000src := 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)
bird2-2.17.5/conf/cf-lex.l000066400000000000000000000517771521175324500151160ustar00rootroot00000000000000/*
 *	BIRD -- Configuration Lexer
 *
 *	(c) 1998--2000 Martin Mares 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

/**
 * DOC: Lexical analyzer
 *
 * The lexical analyzer used for configuration files and CLI commands
 * is generated using the |flex| tool accompanied by a couple of
 * functions maintaining the hash tables containing information about
 * symbols and keywords.
 *
 * Each symbol is represented by a &symbol structure containing name
 * of the symbol, its lexical scope, symbol class (%SYM_PROTO for a
 * name of a protocol, %SYM_CONSTANT for a constant etc.) and class
 * dependent data.  When an unknown symbol is encountered, it's
 * automatically added to the symbol table with class %SYM_VOID.
 *
 * The keyword tables are generated from the grammar templates
 * using the |gen_keywords.m4| script.
 */

%{
#undef REJECT     /* Avoid name clashes */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PARSER 1

#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "filter/filter.h"
#include "filter/f-inst.h"
#include "conf/conf.h"
#include "conf/cf-parse.tab.h"
#include "lib/string.h"
#include "lib/hash.h"

#include "conf/keywords.h"

/* Could be defined by Bison in cf-parse.tab.h, inteferes with SYM hash */
#ifdef SYM
#undef SYM
#endif


static uint cf_hash(const byte *c);

#define SYM_KEY(n)		n->name
#define SYM_NEXT(n)		n->next
#define SYM_EQ(a,b)		!strcmp(a,b)
#define SYM_FN(k)		cf_hash(k)
#define SYM_ORDER		4 /* Initial */

#define SYM_REHASH		sym_rehash
#define SYM_PARAMS		/8, *1, 2, 2, 4, 20


HASH_DEFINE_REHASH_FN(SYM, struct symbol)

struct sym_scope *global_root_scope;
pool *global_root_scope_pool;
linpool *global_root_scope_linpool;

linpool *cfg_mem;

int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
struct include_file_stack *ifs;
static struct include_file_stack *ifs_head;

#define QUOTED_BUFFER_SIZE  4096
static BUFFER_(char) quoted_buffer;
static char quoted_buffer_data[QUOTED_BUFFER_SIZE];
static inline void quoted_buffer_init(void) {
  quoted_buffer.used = 0;
  quoted_buffer.size = QUOTED_BUFFER_SIZE;
  quoted_buffer.data = quoted_buffer_data;
}

#define MAX_INCLUDE_DEPTH 8

#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd);
#define YY_NO_UNPUT
#define YY_FATAL_ERROR(msg) cf_error(msg)
#define YY_USER_ACTION ifs->chno += yyleng; ifs->toklen = yyleng;

static void cf_include(char *arg, int alen);
static int check_eof(void);

static enum yytokentype cf_lex_symbol(const char *data);

%}

%option noyywrap
%option noinput
%option nounput
%option noreject

%x COMMENT CCOMM CLI QUOTED APOSTROPHED INCLUDE

ALPHA [a-zA-Z_]
DIGIT [0-9]
XIGIT [0-9a-fA-F]
ALNUM [a-zA-Z_0-9]
WHITE [ \t]

%%
^{WHITE}*include{WHITE}*\" {
  if (!ifs->depth)
    cf_error("Include not allowed in CLI");

  BEGIN(INCLUDE);
}

[^"\n]+["]{WHITE}*; {
  char *start, *end;

  start = yytext;

  end = strchr(start, '"');
  *end = 0;

  if (start == end)
    cf_error("Include with empty argument");

  cf_include(start, end-start);

  BEGIN(INITIAL);
}

["]	        cf_error("Include with empty argument");
.		cf_error("Unterminated include");
\n		cf_error("Unterminated include");
<>	cf_error("Unterminated include");


{DIGIT}+:{DIGIT}+ {
  uint len1 UNUSED, len2;
  u64 l, v;
  char *e;

  errno = 0;
  l = bstrtoul10(yytext, &e);
  if (!e || (*e != ':') || (errno == ERANGE) || (l >> 32))
    cf_error("ASN out of range");

  if (l >> 16)
  {
    len1 = 32;
    len2 = 16;
    v = (2ULL << 48) | (((u64) l) << len2);
  }
  else
  {
    len1 = 16;
    len2 = 32;
    v = 0 | (((u64) l) << len2);
  }

  errno = 0;
  l = bstrtoul10(e+1, &e);
  if (!e || *e || (errno == ERANGE) || (l >> len2))
    cf_error("Number out of range");
  v |= l;

  cf_lval.rd = rd_from_u64(v);
  return VPN_RD;
}

[02]:{DIGIT}+:{DIGIT}+ {
  uint len1, len2;
  u64 l, v;
  char *e;

  if (yytext[0] == '0')
  {
    len1 = 16;
    len2 = 32;
    v = 0;
  }
  else
  {
    len1 = 32;
    len2 = 16;
    v = 2ULL << 48;
  }

  errno = 0;
  l = bstrtoul10(yytext+2, &e);
  if (!e || (*e != ':') || (errno == ERANGE) || (l >> len1))
    cf_error("ASN out of range");
  v |= ((u64) l) << len2;

  errno = 0;
  l = bstrtoul10(e+1, &e);
  if (!e || *e || (errno == ERANGE) || (l >> len2))
    cf_error("Number out of range");
  v |= l;

  cf_lval.rd = rd_from_u64(v);
  return VPN_RD;
}

{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
  unsigned long int l;
  ip4_addr ip4;
  u64 v;
  char *e;

  v = 1ULL << 48;

  e = strchr(yytext, ':');
  *e++ = '\0';
  if (!ip4_pton(yytext, &ip4))
    cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext);
  v |= ((u64) ip4_to_u32(ip4)) << 16;

  errno = 0;
  l = bstrtoul10(e, &e);
  if (!e || *e || (errno == ERANGE) || (l >> 16))
    cf_error("Number out of range");
  v |= l;

  cf_lval.rd = rd_from_u64(v);
  return VPN_RD;
}

{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
  if (!ip4_pton(yytext, &cf_lval.ip4))
    cf_error("Invalid IPv4 address %s", yytext);
  return IP4;
}

({XIGIT}{2}){16,}|{XIGIT}{2}(:{XIGIT}{2}){15,}|hex:({XIGIT}{2}*|{XIGIT}{2}(:{XIGIT}{2})*) {
  char *s = yytext;
  struct adata *bs;

  /* Skip 'hex:' prefix */
  if (s[0] == 'h' && s[1] == 'e' && s[2] == 'x' && s[3] == ':')
    s += 4;

  int len = bstrhextobin(s, NULL);
  if (len < 0)
    cf_error("Invalid hex string");

  bs = cfg_allocz(sizeof(struct adata) + len);
  bs->length = bstrhextobin(s, bs->data);
  ASSERT(bs->length == len);

  cf_lval.bs = bs;
  return BYTETEXT;
}

({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
  if (!ip6_pton(yytext, &cf_lval.ip6))
    cf_error("Invalid IPv6 address %s", yytext);
  return IP6;
}

0x{XIGIT}+ {
  char *e;
  unsigned long int l;
  errno = 0;
  l = bstrtoul16(yytext+2, &e);
  if (!e || *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
    cf_error("Number out of range");
  cf_lval.i = l;
  return NUM;
}

{DIGIT}+ {
  char *e;
  unsigned long int l;
  errno = 0;
  l = bstrtoul10(yytext, &e);
  if (!e || *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
    cf_error("Number out of range");
  cf_lval.i = l;
  return NUM;
}

else: {
  /* Hack to distinguish if..else from else: in case */
  return ELSECOL;
}

['] {
  BEGIN(APOSTROPHED);
  quoted_buffer_init();
}

{ALNUM}|[-]|[.:]	BUFFER_PUSH(quoted_buffer) = yytext[0];
\n			cf_error("Unterminated symbol");
<>		cf_error("Unterminated symbol");
['] {
  BEGIN(INITIAL);
  BUFFER_PUSH(quoted_buffer) = 0;
  return cf_lex_symbol(quoted_buffer_data);
}
.			cf_error("Invalid character in apostrophed symbol");

({ALPHA}{ALNUM}*) {
  return cf_lex_symbol(yytext);
}

(.|\n) {
  BEGIN(INITIAL);
  return CLI_MARKER;
}

\.\. {
  return DDOT;
}

[={}:;,.()+*/%<>~\[\]?!\|-] {
  return yytext[0];
}

["] {
  BEGIN(QUOTED);
  quoted_buffer_init();
}

\n	cf_error("Unterminated string");
<> cf_error("Unterminated string");
["]	{
  BEGIN(INITIAL);
  BUFFER_PUSH(quoted_buffer) = 0;
  cf_lval.t = cfg_strdup(quoted_buffer_data);
  return TEXT;
}

.	BUFFER_PUSH(quoted_buffer) = yytext[0];

<>	{ if (check_eof()) return END; }

{WHITE}+

\n	ifs->lino++; ifs->chno = 0;

#	BEGIN(COMMENT);

\/\*	BEGIN(CCOMM);

.	cf_error("Unknown character");

\n {
  ifs->lino++;
  ifs->chno = 0;
  BEGIN(INITIAL);
}

.

\*\/	BEGIN(INITIAL);
\n	ifs->lino++; ifs->chno = 0;
\/\*	cf_error("Comment nesting not supported");
<>	cf_error("Unterminated comment");
.

\!\= return NEQ;
\!\~ return NMA;
\<\= return LEQ;
\>\= return GEQ;
\&\& return AND;
\|\| return OR;
\-\> return IMP;

\[\= return PO;
\=\] return PC;

%%

static uint
cf_hash(const byte *c)
{
  uint h = 13 << 24;

  while (*c)
    h = h + (h >> 2) + (h >> 5) + ((uint) *c++ << 24);
  return h;
}

/*
 * IFS stack - it contains structures needed for recursive processing
 * of include in config files. On the top of the stack is a structure
 * for currently processed file. Other structures are either for
 * active files interrupted because of include directive (these have
 * fd and flex buffer) or for inactive files scheduled to be processed
 * later (when parent requested including of several files by wildcard
 * match - these do not have fd and flex buffer yet).
 *
 * FIXME: Most of these ifs and include functions are really sysdep/unix.
 */

static struct include_file_stack *
push_ifs(struct include_file_stack *old)
{
  struct include_file_stack *ret;
  ret = cfg_allocz(sizeof(struct include_file_stack));
  ret->lino = 1;
  ret->prev = old;
  return ret;
}

static struct include_file_stack *
pop_ifs(struct include_file_stack *old)
{
 yy_delete_buffer(old->buffer);
 close(old->fd);
 return old->prev;
}

static void
enter_ifs(struct include_file_stack *new)
{
  if (!new->buffer)
    {
      new->fd = open(new->file_name, O_RDONLY);
      if (new->fd < 0)
        {
          ifs = ifs->up;
	  cf_error("Unable to open included file %s: %m", new->file_name);
        }

      new->buffer = yy_create_buffer(NULL, YY_BUF_SIZE);
    }

  yy_switch_to_buffer(new->buffer);
}

/**
 * cf_lex_unwind - unwind lexer state during error
 *
 * cf_lex_unwind() frees the internal state on IFS stack when the lexical
 * analyzer is terminated by cf_error().
 */
void
cf_lex_unwind(void)
{
  struct include_file_stack *n;

  for (n = ifs; n != ifs_head; n = n->prev)
    {
      /* Memory is freed automatically */
      if (n->buffer)
	yy_delete_buffer(n->buffer);
      if (n->fd)
        close(n->fd);
    }

  ifs = ifs_head;
}

static void
cf_include(char *arg, int alen)
{
  struct include_file_stack *base_ifs = ifs;
  int new_depth, rv, i;
  char *patt;
  glob_t g = {};

  new_depth = ifs->depth + 1;
  if (new_depth > MAX_INCLUDE_DEPTH)
    cf_error("Max include depth reached");

  /* expand arg to properly handle relative filenames */
  if (*arg != '/')
    {
      int dlen = strlen(ifs->file_name);
      char *dir = alloca(dlen + 1);
      patt = alloca(dlen + alen + 2);
      memcpy(dir, ifs->file_name, dlen + 1);
      sprintf(patt, "%s/%s", dirname(dir), arg);
    }
  else
    patt = arg;

  /* Skip globbing if there are no wildcards, mainly to get proper
     response when the included config file is missing */
  if (!strpbrk(arg, "?*["))
    {
      ifs = push_ifs(ifs);
      ifs->file_name = cfg_strdup(patt);
      ifs->depth = new_depth;
      ifs->up = base_ifs;
      enter_ifs(ifs);
      return;
    }

  /* Expand the pattern */
  rv = glob(patt, GLOB_ERR | GLOB_NOESCAPE, NULL, &g);
  if (rv == GLOB_ABORTED)
    cf_error("Unable to match pattern %s: %m", patt);
  if ((rv != 0) || (g.gl_pathc <= 0))
    return;

  /*
   * Now we put all found files to ifs stack in reverse order, they
   * will be activated and processed in order as ifs stack is popped
   * by pop_ifs() and enter_ifs() in check_eof().
   */
  for(i = g.gl_pathc - 1; i >= 0; i--)
    {
      char *fname = g.gl_pathv[i];
      struct stat fs;

      if (stat(fname, &fs) < 0)
	{
	  globfree(&g);
	  cf_error("Unable to stat included file %s: %m", fname);
	}

      if (fs.st_mode & S_IFDIR)
        continue;

      /* Prepare new stack item */
      ifs = push_ifs(ifs);
      ifs->file_name = cfg_strdup(fname);
      ifs->depth = new_depth;
      ifs->up = base_ifs;
    }

  globfree(&g);
  enter_ifs(ifs);
}

static int
check_eof(void)
{
  if (ifs == ifs_head)
    {
      /* EOF in main config file */
      ifs->lino = 1; /* Why this? */
      return 1;
    }

  ifs = pop_ifs(ifs);
  enter_ifs(ifs);
  return 0;
}

static inline void cf_swap_soft_scope(struct config *conf);

struct symbol *
cf_new_symbol(struct sym_scope *scope, pool *p, struct linpool *lp, const byte *c)
{
  if (scope->readonly)
    cf_error("Unknown symbol %s", c);

  struct symbol *s;

  uint l = strlen(c);
  if (l > SYM_MAX_LEN)
    cf_error("Symbol too long");

  s = lp_alloc(lp, sizeof(struct symbol) + l + 1);
  *s = (struct symbol) { .scope = scope, .class = SYM_VOID, };
  strcpy(s->name, c);

  if (!scope->hash.data)
    HASH_INIT(scope->hash, p, SYM_ORDER);

  HASH_INSERT2(scope->hash, SYM, p, s);

  if (new_config && (scope == new_config->root_scope))
    add_tail(&(new_config->symbols), &(s->n));

  return s;
}

/**
 * cf_find_symbol_scope - find a symbol by name
 * @scope: config scope
 * @c: symbol name
 *
 * This functions searches the symbol table in the scope @scope for a symbol of
 * given name. First it examines the current scope, then the underlying one
 * and so on until it either finds the symbol and returns a pointer to its
 * &symbol structure or reaches the end of the scope chain and returns %NULL to
 * signify no match.
 */
struct symbol *
cf_find_symbol_scope(const struct sym_scope *scope, const byte *c)
{
  struct symbol *s;

  /* Find the symbol here or anywhere below */
  while (scope)
    if (scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c)))
      return s;
    else
      scope = scope->next;

  return NULL;
}

/**
 * cf_get_symbol - get a symbol by name
 * @c: symbol name
 *
 * This functions searches the symbol table of the currently parsed config
 * (@new_config) for a symbol of given name. It returns either the already
 * existing symbol or a newly allocated undefined (%SYM_VOID) symbol if no
 * existing symbol is found.
 */
struct symbol *
cf_get_symbol(struct config *conf, const byte *c)
{
  return cf_find_symbol_scope(conf->current_scope, c) ?: (
      cf_swap_soft_scope(conf),
      cf_new_symbol(conf->current_scope, conf->pool, conf->mem, c)
      );
}

/**
 * cf_localize_symbol - get the local instance of given symbol
 * @sym: the symbol to localize
 *
 * This functions finds the symbol that is local to current scope
 * for purposes of cf_define_symbol().
 */
struct symbol *
cf_localize_symbol(struct config *conf, struct symbol *sym)
{
  /* If the symbol type is void, it has been recently allocated just in this scope. */
  if (!sym->class)
    return sym;

  /* If the scope is the current, it is already defined in this scope. */
  if (cf_symbol_is_local(conf, sym))
    cf_error("Symbol '%s' already defined", sym->name);

  /* Not allocated here yet, doing it now. */
  cf_swap_soft_scope(conf);
  return cf_new_symbol(conf->current_scope, conf->pool, conf->mem, sym->name);
}

struct symbol *
cf_default_name(struct config *conf, char *template, int *counter)
{
  char buf[SYM_MAX_LEN];
  struct symbol *s;
  char *perc = strchr(template, '%');

  for(;;)
    {
      bsprintf(buf, template, ++(*counter));
      s = cf_get_symbol(conf, buf);
      if (s->class == SYM_VOID)
	return s;
      if (!perc)
	break;
    }
  cf_error("Unable to generate default name");
}

static enum yytokentype
cf_lex_symbol(const char *data)
{
  /* Have we defined such a symbol? */
  struct symbol *sym = cf_get_symbol(new_config, data);
  cf_lval.s = sym;

  switch (sym->class)
  {
    case SYM_KEYWORD:
    {
      int val = sym->keyword->value;
      if (val > 0) return val;
      cf_lval.i = -val;
      return ENUM_TOKEN;
    }
    case SYM_METHOD:
      return (sym->method->arg_num > 1) ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE;
    case SYM_VOID:
      return CF_SYM_UNDEFINED;
    default:
      return CF_SYM_KNOWN;
  }
}

void f_type_methods_register(void);

/**
 * cf_lex_init - initialize the lexer
 * @is_cli: true if we're going to parse CLI command, false for configuration
 * @c: configuration structure
 *
 * cf_lex_init() initializes the lexical analyzer and prepares it for
 * parsing of a new input.
 */
void
cf_lex_init(int is_cli, struct config *c)
{
  if (!global_root_scope_pool)
  {
    global_root_scope_pool = rp_new(&root_pool, "Keywords pool");
    global_root_scope_linpool = lp_new(global_root_scope_pool);
    global_root_scope = lp_allocz(global_root_scope_linpool, sizeof(*global_root_scope));

    for (const struct keyword *k = keyword_list; k->name; k++)
    {
      struct symbol *sym = cf_new_symbol(global_root_scope, global_root_scope_pool, global_root_scope_linpool, k->name);
      sym->class = SYM_KEYWORD;
      sym->keyword = k;
    }

    global_root_scope->readonly = 1;

    f_type_methods_register();
  }

  ifs_head = ifs = push_ifs(NULL);
  if (!is_cli)
    {
      ifs->file_name = c->file_name;
      ifs->fd = c->file_fd;
      ifs->depth = 1;
    }

  yyrestart(NULL);
  ifs->buffer = YY_CURRENT_BUFFER;

  if (is_cli)
    BEGIN(CLI);
  else
    BEGIN(INITIAL);

  c->root_scope = c->current_scope = cfg_allocz(sizeof(struct sym_scope));
  c->root_scope->active = 1;

  if (is_cli)
    c->current_scope->next = config->root_scope;
  else
    c->current_scope->next = global_root_scope;
}

/**
 * cf_push_scope - enter new scope
 * @sym: symbol representing scope name
 *
 * If we want to enter a new scope to process declarations inside
 * a nested block, we can just call cf_push_scope() to push a new
 * scope onto the scope stack which will cause all new symbols to be
 * defined in this scope and all existing symbols to be sought for
 * in all scopes stored on the stack.
 */
void
cf_push_scope(struct config *conf, struct symbol *sym)
{
  struct sym_scope *s = cfg_allocz(sizeof(struct sym_scope));

  s->next = conf->current_scope;
  conf->current_scope = s;
  s->active = 1;
  s->name = sym;
  s->slots = 0;
}

/**
 * cf_pop_scope - leave a scope
 *
 * cf_pop_scope() pops the topmost scope from the scope stack,
 * leaving all its symbols in the symbol table, but making them
 * invisible to the rest of the config.
 */
void
cf_pop_scope(struct config *conf)
{
  ASSERT(!conf->current_scope->soft_scopes);

  conf->current_scope->active = 0;
  conf->current_scope = conf->current_scope->next;

  ASSERT(conf->current_scope);
}

/**
 * cf_push_soft_scope - enter new soft scope
 *
 * If we want to enter a new anonymous scope that most likely will not contain
 * any symbols, we can use cf_push_soft_scope() insteas of cf_push_scope().
 * Such scope will be converted to a regular scope on first use.
 */
void
cf_push_soft_scope(struct config *conf)
{
  if (conf->current_scope->soft_scopes < 0xfe)
    conf->current_scope->soft_scopes++;
  else
    cf_push_block_scope(conf);
}

/**
 * cf_pop_soft_scope - leave a soft scope
 *
 * Leave a soft scope entered by cf_push_soft_scope().
 */
void
cf_pop_soft_scope(struct config *conf)
{
  if (conf->current_scope->soft_scopes)
    conf->current_scope->soft_scopes--;
  else
    cf_pop_block_scope(conf);
}

/**
 * cf_swap_soft_scope - convert soft scope to regular scope
 *
 * Soft scopes cannot hold symbols, so they must be converted to regular scopes
 * on first use. It is done automatically by cf_new_symbol().
 */
static inline void
cf_swap_soft_scope(struct config *conf)
{
  if (conf->current_scope->soft_scopes)
  {
    conf->current_scope->soft_scopes--;
    cf_push_block_scope(conf);
  }
}

/**
 * cf_symbol_class_name - get name of a symbol class
 * @sym: symbol
 *
 * This function returns a string representing the class
 * of the given symbol.
 */
char *
cf_symbol_class_name(struct symbol *sym)
{
  switch (sym->class)
    {
    case SYM_VOID:
      return "undefined";
    case SYM_PROTO:
      return "protocol";
    case SYM_TEMPLATE:
      return "protocol template";
    case SYM_FUNCTION:
      return "function";
    case SYM_FILTER:
      return "filter";
    case SYM_TABLE:
      return "routing table";
    case SYM_ATTRIBUTE:
      return "custom attribute";
    case SYM_MPLS_DOMAIN:
      return "MPLS domain";
    case SYM_MPLS_RANGE:
      return "MPLS label range";
    case SYM_CONSTANT_RANGE:
      return "constant";
    case SYM_VARIABLE_RANGE:
      return "variable";
    default:
      return "unknown type";
    }
}


/**
 * DOC: Parser
 *
 * Both the configuration and CLI commands are analyzed using a syntax
 * driven parser generated by the |bison| tool from a grammar which
 * is constructed from information gathered from grammar snippets by
 * the |gen_parser.m4| script.
 *
 * Grammar snippets are files (usually with extension |.Y|) contributed
 * by various BIRD modules in order to provide information about syntax of their
 * configuration and their CLI commands. Each snipped consists of several
 * sections, each of them starting with a special keyword: |CF_HDR| for
 * a list of |#include| directives needed by the C code, |CF_DEFINES|
 * for a list of C declarations, |CF_DECLS| for |bison| declarations
 * including keyword definitions specified as |CF_KEYWORDS|, |CF_GRAMMAR|
 * for the grammar rules, |CF_CODE| for auxiliary C code and finally
 * |CF_END| at the end of the snippet.
 *
 * To create references between the snippets, it's possible to define
 * multi-part rules by utilizing the |CF_ADDTO| macro which adds a new
 * alternative to a multi-part rule.
 *
 * CLI commands are defined using a |CF_CLI| macro. Its parameters are:
 * the list of keywords determining the command, the list of parameters,
 * help text for the parameters and help text for the command.
 *
 * Values of |enum| filter types can be defined using |CF_ENUM| with
 * the following parameters: name of filter type, prefix common for all
 * literals of this type and names of all the possible values.
 */
bird2-2.17.5/conf/conf.c000066400000000000000000000401521521175324500146350ustar00rootroot00000000000000/*
 *	BIRD Internet Routing Daemon -- Configuration File Handling
 *
 *	(c) 1998--2000 Martin Mares 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

/**
 * DOC: Configuration manager
 *
 * Configuration of BIRD is complex, yet straightforward. There are three
 * modules taking care of the configuration: config manager (which takes care
 * of storage of the config information and controls switching between configs),
 * lexical analyzer and parser.
 *
 * The configuration manager stores each config as a &config structure
 * accompanied by a linear pool from which all information associated
 * with the config and pointed to by the &config structure is allocated.
 *
 * There can exist up to four different configurations at one time: an active
 * one (pointed to by @config), configuration we are just switching from
 * (@old_config), one queued for the next reconfiguration (@future_config; if
 * there is one and the user wants to reconfigure once again, we just free the
 * previous queued config and replace it with the new one) and finally a config
 * being parsed (@new_config). The stored @old_config is also used for undo
 * reconfiguration, which works in a similar way. Reconfiguration could also
 * have timeout (using @config_timer) and undo is automatically called if the
 * new configuration is not confirmed later. The new config (@new_config) and
 * associated linear pool (@cfg_mem) is non-NULL only during parsing.
 *
 * Loading of new configuration is very simple: just call config_alloc() to get
 * a new &config structure, then use config_parse() to parse a configuration
 * file and fill all fields of the structure and finally ask the config manager
 * to switch to the new config by calling config_commit().
 *
 * CLI commands are parsed in a very similar way -- there is also a stripped-down
 * &config structure associated with them and they are lex-ed and parsed by the
 * same functions, only a special fake token is prepended before the command
 * text to make the parser recognize only the rules corresponding to CLI commands.
 */

#include 
#include 

#undef LOCAL_DEBUG

#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/iface.h"
#include "nest/mpls.h"
#include "lib/resource.h"
#include "lib/string.h"
#include "lib/event.h"
#include "lib/timer.h"
#include "conf/conf.h"
#include "filter/filter.h"
#include "sysdep/unix/unix.h"


static jmp_buf conf_jmpbuf;

struct config *config, *new_config;
pool *config_pool;

static struct config *old_config;	/* Old configuration */
static struct config *future_config;	/* New config held here if recon requested during recon */
static int old_cftype;			/* Type of transition old_config -> config (RECONFIG_SOFT/HARD) */
static int future_cftype;		/* Type of scheduled transition, may also be RECONFIG_UNDO */
/* Note that when future_cftype is RECONFIG_UNDO, then future_config is NULL,
   therefore proper check for future scheduled config checks future_cftype */

static event *config_event;		/* Event for finalizing reconfiguration */
static timer *config_timer;		/* Timer for scheduled configuration rollback */

/* These are public just for cmd_show_status(), should not be accessed elsewhere */
int shutting_down;			/* Shutdown requested, do not accept new config changes */
int configuring;			/* Reconfiguration is running */
int undo_available;			/* Undo was not requested from last reconfiguration */
/* Note that both shutting_down and undo_available are related to requests, not processing */

/**
 * config_alloc - allocate a new configuration
 * @name: name of the config
 *
 * This function creates new &config structure, attaches a resource
 * pool and a linear memory pool to it and makes it available for
 * further use. Returns a pointer to the structure.
 */
struct config *
config_alloc(const char *name)
{
  pool *p = rp_new(config_pool, "Config");
  linpool *l = lp_new_default(p);
  struct config *c = lp_allocz(l, sizeof(struct config));

  /* Duplication of name string in local linear pool */
  uint nlen = strlen(name) + 1;
  char *ndup = lp_allocu(l, nlen);
  memcpy(ndup, name, nlen);

  init_list(&c->tests);
  init_list(&c->symbols);
  c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
  c->pool = p;
  c->mem = l;
  c->file_name = ndup;
  c->load_time = current_time();
  c->tf_route = c->tf_proto = TM_ISO_SHORT_MS;
  c->tf_base = c->tf_log = TM_ISO_LONG_MS;
  c->gr_wait = DEFAULT_GR_WAIT;

  return c;
}

/**
 * config_parse - parse a configuration
 * @c: configuration
 *
 * config_parse() reads input by calling a hook function pointed to
 * by @cf_read_hook and parses it according to the configuration
 * grammar. It also calls all the preconfig and postconfig hooks
 * before, resp. after parsing.
 *
 * Result: 1 if the config has been parsed successfully, 0 if any
 * error has occurred (such as anybody calling cf_error()) and
 * the @err_msg field has been set to the error message.
 */
int
config_parse(struct config *c)
{
  int done = 0;
  DBG("Parsing configuration file `%s'\n", c->file_name);
  new_config = c;
  cfg_mem = c->mem;
  if (setjmp(conf_jmpbuf))
    goto cleanup;

  cf_lex_init(0, c);
  sysdep_preconfig(c);
  protos_preconfig(c);
  mpls_preconfig(c);
  rt_preconfig(c);
  cf_parse();
  rt_postconfig(c);

  if (EMPTY_LIST(c->protos))
    cf_error("No protocol is specified in the config file");

  /*
  if (!c->router_id)
    cf_error("Router ID must be configured manually");
  */

  done = 1;

cleanup:
  new_config = NULL;
  cfg_mem = NULL;
  return done;
}

/**
 * cli_parse - parse a CLI command
 * @c: temporary config structure
 *
 * cli_parse() is similar to config_parse(), but instead of a configuration,
 * it parses a CLI command. See the CLI module for more information.
 */
int
cli_parse(struct config *c)
{
  int done = 0;
  new_config = c;
  cfg_mem = c->mem;
  if (setjmp(conf_jmpbuf))
    goto cleanup;

  cf_lex_init(1, c);
  cf_parse();
  done = 1;

cleanup:
  new_config = NULL;
  cfg_mem = NULL;
  return done;
}

/**
 * config_free - free a configuration
 * @c: configuration to be freed
 *
 * This function takes a &config structure and frees all resources
 * associated with it.
 */
void
config_free(struct config *c)
{
  if (!c)
    return;

  ASSERT(!c->obstacle_count);

  rfree(c->pool);
}

/**
 * config_free_old - free stored old configuration
 *
 * This function frees the old configuration (%old_config) that is saved for the
 * purpose of undo. It is useful before parsing a new config when reconfig is
 * requested, to avoid keeping three (perhaps memory-heavy) configs together.
 * Configuration is not freed when it is still active during reconfiguration.
 */
void
config_free_old(void)
{
  if (!old_config || old_config->obstacle_count)
    return;

  tm_stop(config_timer);
  undo_available = 0;

  config_free(old_config);
  old_config = NULL;
}

void
config_add_obstacle(struct config *c)
{
  DBG("+++ adding obstacle %d\n", c->obstacle_count);
  c->obstacle_count++;
}

void
config_del_obstacle(struct config *c)
{
  DBG("+++ deleting obstacle %d\n", c->obstacle_count);
  c->obstacle_count--;
  if (!c->obstacle_count && (c != config))
    ev_schedule(config_event);
}

static int
global_commit(struct config *new, struct config *old)
{
  if (!new->hostname)
    {
      new->hostname = get_hostname(new->mem);

      if (!new->hostname)
        log(L_WARN "Cannot determine hostname");
    }

  if (!old)
    return 0;

  if (!new->router_id)
    {
      new->router_id = old->router_id;

      if (new->router_id_from)
	{
	  u32 id = if_choose_router_id(new->router_id_from, old->router_id);
	  if (!id)
	    log(L_WARN "Cannot determine router ID, using old one");
	  else
	    new->router_id = id;
	}
    }

  return 0;
}

static int
config_do_commit(struct config *c, int type)
{
  if (type == RECONFIG_UNDO)
    {
      c = old_config;
      type = old_cftype;
    }
  else
    config_free(old_config);

  old_config = config;
  old_cftype = type;
  config = c;

  configuring = 1;
  if (old_config && !config->shutdown)
    log(L_INFO "Reconfiguring");

  if (old_config)
    old_config->obstacle_count++;

  DBG("filter_commit\n");
  filter_commit(c, old_config);
  DBG("sysdep_commit\n");
  int force_restart = sysdep_commit(c, old_config);
  DBG("global_commit\n");
  force_restart |= global_commit(c, old_config);
  mpls_commit(c, old_config);
  DBG("rt_commit\n");
  rt_commit(c, old_config);
  DBG("protos_commit\n");
  protos_commit(c, old_config, force_restart, type);

  int obs = 0;
  if (old_config)
    obs = --old_config->obstacle_count;

  DBG("do_commit finished with %d obstacles remaining\n", obs);
  return !obs;
}

static void
config_done(void *unused UNUSED)
{
  if (config->shutdown)
    sysdep_shutdown_done();

  configuring = 0;
  if (old_config)
    log(L_INFO "Reconfigured");

  if (future_cftype)
    {
      int type = future_cftype;
      struct config *conf = future_config;
      future_cftype = RECONFIG_NONE;
      future_config = NULL;

      log(L_INFO "Reconfiguring to queued configuration");
      if (config_do_commit(conf, type))
	config_done(NULL);
    }
}

/**
 * config_commit - commit a configuration
 * @c: new configuration
 * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)
 * @timeout: timeout for undo (in seconds; or 0 for no timeout)
 *
 * When a configuration is parsed and prepared for use, the
 * config_commit() function starts the process of reconfiguration.
 * It checks whether there is already a reconfiguration in progress
 * in which case it just queues the new config for later processing.
 * Else it notifies all modules about the new configuration by calling
 * their commit() functions which can either accept it immediately
 * or call config_add_obstacle() to report that they need some time
 * to complete the reconfiguration. After all such obstacles are removed
 * using config_del_obstacle(), the old configuration is freed and
 * everything runs according to the new one.
 *
 * When @timeout is nonzero, the undo timer is activated with given
 * timeout. The timer is deactivated when config_commit(),
 * config_confirm() or config_undo() is called.
 *
 * Result: %CONF_DONE if the configuration has been accepted immediately,
 * %CONF_PROGRESS if it will take some time to switch to it, %CONF_QUEUED
 * if it's been queued due to another reconfiguration being in progress now
 * or %CONF_SHUTDOWN if BIRD is in shutdown mode and no new configurations
 * are accepted.
 */
int
config_commit(struct config *c, int type, uint timeout)
{
  if (shutting_down)
    {
      config_free(c);
      return CONF_SHUTDOWN;
    }

  undo_available = 1;
  if (timeout)
    tm_start(config_timer, timeout S);
  else
    tm_stop(config_timer);

  if (configuring)
    {
      if (future_cftype)
	{
	  log(L_INFO "Queueing new configuration, ignoring the one already queued");
	  config_free(future_config);
	}
      else
	log(L_INFO "Queueing new configuration");

      future_cftype = type;
      future_config = c;
      return CONF_QUEUED;
    }

  if (config_do_commit(c, type))
    {
      config_done(NULL);
      return CONF_DONE;
    }
  return CONF_PROGRESS;
}

/**
 * config_confirm - confirm a commited configuration
 *
 * When the undo timer is activated by config_commit() with nonzero timeout,
 * this function can be used to deactivate it and therefore confirm
 * the current configuration.
 *
 * Result: %CONF_CONFIRM when the current configuration is confirmed,
 * %CONF_NONE when there is nothing to confirm (i.e. undo timer is not active).
 */
int
config_confirm(void)
{
  if (config_timer->expires == 0)
    return CONF_NOTHING;

  tm_stop(config_timer);

  return CONF_CONFIRM;
}

/**
 * config_undo - undo a configuration
 *
 * Function config_undo() can be used to change the current
 * configuration back to stored %old_config. If no reconfiguration is
 * running, this stored configuration is commited in the same way as a
 * new configuration in config_commit(). If there is already a
 * reconfiguration in progress and no next reconfiguration is
 * scheduled, then the undo is scheduled for later processing as
 * usual, but if another reconfiguration is already scheduled, then
 * such reconfiguration is removed instead (i.e. undo is applied on
 * the last commit that scheduled it).
 *
 * Result: %CONF_DONE if the configuration has been accepted immediately,
 * %CONF_PROGRESS if it will take some time to switch to it, %CONF_QUEUED
 * if it's been queued due to another reconfiguration being in progress now,
 * %CONF_UNQUEUED if a scheduled reconfiguration is removed, %CONF_NOTHING
 * if there is no relevant configuration to undo (the previous config request
 * was config_undo() too)  or %CONF_SHUTDOWN if BIRD is in shutdown mode and
 * no new configuration changes  are accepted.
 */
int
config_undo(void)
{
  if (shutting_down)
    return CONF_SHUTDOWN;

  if (!undo_available || !old_config)
    return CONF_NOTHING;

  undo_available = 0;
  tm_stop(config_timer);

  if (configuring)
    {
      if (future_cftype)
	{
	  config_free(future_config);
	  future_config = NULL;

	  log(L_INFO "Removing queued configuration");
	  future_cftype = RECONFIG_NONE;
	  return CONF_UNQUEUED;
	}
      else
	{
	  log(L_INFO "Queueing undo configuration");
	  future_cftype = RECONFIG_UNDO;
	  return CONF_QUEUED;
	}
    }

  if (config_do_commit(NULL, RECONFIG_UNDO))
    {
      config_done(NULL);
      return CONF_DONE;
    }
  return CONF_PROGRESS;
}

int
config_status(void)
{
  if (shutting_down)
    return CONF_SHUTDOWN;

  if (configuring)
    return future_cftype ? CONF_QUEUED : CONF_PROGRESS;

  return CONF_DONE;
}

btime
config_timer_status(void)
{
  return tm_active(config_timer) ? tm_remains(config_timer) : -1;
}

extern void cmd_reconfig_undo_notify(void);

static void
config_timeout(timer *t UNUSED)
{
  log(L_INFO "Config timeout expired, starting undo");
  cmd_reconfig_undo_notify();

  int r = config_undo();
  if (r < 0)
    log(L_ERR "Undo request failed");
}

void
config_init(void)
{
  config_pool = rp_new(&root_pool, "Configurations");

  config_event = ev_new(config_pool);
  config_event->hook = config_done;

  config_timer = tm_new(config_pool);
  config_timer->hook = config_timeout;
}

/**
 * order_shutdown - order BIRD shutdown
 *
 * This function initiates shutdown of BIRD. It's accomplished by asking
 * for switching to an empty configuration.
 */
void
order_shutdown(int gr)
{
  struct config *c;

  if (shutting_down)
    return;

  if (!gr)
    log(L_INFO "Shutting down");
  else
    log(L_INFO "Shutting down for graceful restart");

  c = lp_alloc(config->mem, sizeof(struct config));
  memcpy(c, config, sizeof(struct config));
  init_list(&c->protos);
  init_list(&c->tables);
  init_list(&c->mpls_domains);
  init_list(&c->symbols);
  c->cli = (struct cli_config_list) {};
  memset(c->def_tables, 0, sizeof(c->def_tables));
  c->shutdown = 1;
  c->gr_down = gr;

  config_commit(c, RECONFIG_HARD, 0);
  shutting_down = 1;
}

/**
 * cf_error - report a configuration error
 * @msg: printf-like format string
 *
 * cf_error() can be called during execution of config_parse(), that is
 * from the parser, a preconfig hook or a postconfig hook, to report an
 * error in the configuration.
 */
void
cf_error(const char *msg, ...)
{
  char buf[1024];
  va_list args;

  va_start(args, msg);
  if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
    strcpy(buf, "");
  va_end(args);
  new_config->err_msg = cfg_strdup(buf);
  new_config->err_lino = ifs->lino;
  new_config->err_chno = ifs->chno - ifs->toklen + 1;
  new_config->err_file_name = ifs->file_name;
  cf_lex_unwind();
  longjmp(conf_jmpbuf, 1);
}

/**
 * cfg_strdup - copy a string to config memory
 * @c: string to copy
 *
 * cfg_strdup() creates a new copy of the string in the memory
 * pool associated with the configuration being currently parsed.
 * It's often used when a string literal occurs in the configuration
 * and we want to preserve it for further use.
 */
char *
cfg_strdup(const char *c)
{
  int l = strlen(c) + 1;
  char *z = cfg_allocu(l);
  memcpy(z, c, l);
  return z;
}


void
cfg_copy_list(list *dest, list *src, unsigned node_size)
{
  node *dn, *sn;

  init_list(dest);
  WALK_LIST(sn, *src)
  {
    dn = cfg_alloc(node_size);
    memcpy(dn, sn, node_size);
    memset(dn, 0, sizeof(node));
    add_tail(dest, dn);
  }
}
bird2-2.17.5/conf/conf.h000066400000000000000000000233771521175324500146540ustar00rootroot00000000000000/*
 *	BIRD Internet Routing Daemon -- Configuration File Handling
 *
 *	(c) 1998--2000 Martin Mares 
 *
 *	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"
#include "lib/tlists.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 mpls_domains;			/* Configured MPLS domains (struct mpls_domain_config) */
  list logfiles;			/* Configured log files (sysdep) */
  list tests;				/* Configured unit tests (f_bt_test_suite) */
  list symbols;				/* Configured symbols in config order */
  TLIST_STRUCT_DEF(cli_config, struct cli_config) cli; /* Configured CLI sockets */

  int mrtdump_file;			/* Configured MRTDump file (sysdep, fd in unix) */
  const 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 */
  const char *hostname;			/* Hostname */
  u32 proto_default_debug;		/* Default protocol debug mask */
  u32 proto_default_mrtdump;		/* Default protocol mrtdump mask */
  u32 channel_default_debug;		/* Default channel debug mask */
  u32 table_default_debug;		/* Default table debug 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 */

  struct sym_scope *root_scope;		/* Scope for root symbols */
  struct sym_scope *current_scope;	/* Current scope where we are actually in while parsing */
  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 *);
void config_free_old(void);
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;
#define cf_warn(msg, args...)  log(L_WARN "%s:%d:%d: " msg, ifs->file_name, ifs->lino, ifs->chno - ifs->toklen + 1, ##args)
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 pool *config_pool;
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 keyword {
  byte *name;
  int value;
};

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 mpls_domain_config *mpls_domain;	/* For SYM_MPLS_DOMAIN */
    struct mpls_range_config *mpls_range;	/* For SYM_MPLS_RANGE */
    struct f_val *val;			/* For SYM_CONSTANT */
    uint offset;			/* For SYM_VARIABLE */
    const struct keyword *keyword;	/* For SYM_KEYWORD */
    const struct f_method *method;	/* For SYM_METHOD */
  };

  char name[0];
};

struct sym_scope {
  struct sym_scope *next;		/* Next on scope stack */
  struct symbol *name;			/* Name of this scope */

  HASH(struct symbol) hash;		/* Local symbol hash */

  uint slots;				/* Variable slots */
  byte soft_scopes;			/* Number of soft scopes above */
  byte active:1;			/* Currently entered */
  byte block:1;				/* No independent stack frame */
  byte readonly:1;			/* Do not add new symbols */
};

extern struct sym_scope *global_root_scope;
extern pool *global_root_scope_pool;
extern linpool *global_root_scope_linpool;


#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_KEYWORD 7
#define SYM_METHOD 8
#define SYM_MPLS_DOMAIN 9
#define SYM_MPLS_RANGE 10

#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;

int cf_lex(void);
void cf_lex_init(int is_cli, struct config *c);
void cf_lex_unwind(void);

struct symbol *cf_find_symbol_scope(const struct sym_scope *scope, const byte *c);
static inline struct symbol *cf_find_symbol_cfg(const struct config *cfg, const byte *c)
{ return cf_find_symbol_scope(cfg->root_scope, c); }

#define cf_find_symbol(where, what) _Generic(*(where), \
    struct config: cf_find_symbol_cfg, \
    struct sym_scope: cf_find_symbol_scope \
    )((where), (what))

struct symbol *cf_get_symbol(struct config *conf, const byte *c);
struct symbol *cf_default_name(struct config *conf, char *template, int *counter);
struct symbol *cf_localize_symbol(struct config *conf, struct symbol *sym);

static inline int cf_symbol_is_local(struct config *conf, struct symbol *sym)
{ return (sym->scope == conf->current_scope) && !conf->current_scope->soft_scopes; }

/* internal */
struct symbol *cf_new_symbol(struct sym_scope *scope, pool *p, struct linpool *lp, const byte *c);

/**
 * 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(conf_, osym_, type_, var_, def_) ({ \
    struct symbol *sym_ = cf_localize_symbol(conf_, osym_); \
    sym_->class = type_; \
    sym_->var_ = def_; \
    sym_; })

#define cf_create_symbol(conf_, name_, type_, var_, def_) \
  cf_define_symbol(conf_, cf_get_symbol(conf_, name_), type_, var_, def_)

void cf_push_scope(struct config *, struct symbol *);
void cf_pop_scope(struct config *);
void cf_push_soft_scope(struct config *);
void cf_pop_soft_scope(struct config *);

static inline void cf_push_block_scope(struct config *conf)
{ cf_push_scope(conf, NULL); conf->current_scope->block = 1; }

static inline void cf_pop_block_scope(struct config *conf)
{ ASSERT(conf->current_scope->block); cf_pop_scope(conf); }

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
bird2-2.17.5/conf/confbase.Y000066400000000000000000000252131521175324500154570ustar00rootroot00000000000000/*
 *	BIRD -- Configuration Parser Top
 *
 *	(c) 1998--2000 Martin Mares 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

CF_HDR

#define PARSER 1

#include "nest/bird.h"
#include "conf/conf.h"
#include "lib/resource.h"
#include "lib/socket.h"
#include "lib/timer.h"
#include "lib/string.h"
#include "nest/protocol.h"
#include "nest/iface.h"
#include "nest/route.h"
#include "nest/bfd.h"
#include "nest/cli.h"
#include "filter/filter.h"

/* FIXME: Turn on YYERROR_VERBOSE and work around lots of bison bugs? */

CF_DEFINES

static void
check_u16(uint val)
{
  if (val > 0xFFFF)
    cf_error("Value %u out of range (0-65535)", val);
}

#define cf_assert(cond, ...) do { if (!(cond)) cf_error(__VA_ARGS__); } while (0)
static inline void cf_assert_symbol(const struct symbol *sym, uint class) {
  switch (class) {
    case SYM_PROTO: cf_assert(sym->class == SYM_PROTO, "Protocol name required"); break;
    case SYM_TEMPLATE: cf_assert(sym->class == SYM_TEMPLATE, "Protocol template name required"); break;
    case SYM_FUNCTION: cf_assert(sym->class == SYM_FUNCTION, "Function name required"); break;
    case SYM_FILTER: cf_assert(sym->class == SYM_FILTER, "Filter name required"); break;
    case SYM_TABLE: cf_assert(sym->class == SYM_TABLE, "Table name required"); break;
    case SYM_ATTRIBUTE: cf_assert(sym->class == SYM_ATTRIBUTE, "Custom attribute name required"); break;
    case SYM_MPLS_DOMAIN: cf_assert(sym->class == SYM_MPLS_DOMAIN, "MPLS domain name required"); break;
    case SYM_MPLS_RANGE: cf_assert(sym->class == SYM_MPLS_RANGE, "MPLS range name required"); break;
    case SYM_VARIABLE: cf_assert((sym->class & ~0xff) == SYM_VARIABLE, "Variable name required"); break;
    case SYM_CONSTANT: cf_assert((sym->class & ~0xff) == SYM_CONSTANT, "Constant name required"); break;
    default: bug("This shall not happen");
  }
}

CF_DECLS

%union {
  uint i;
  u32 i32;
  u64 i64;
  vpn_rd rd;
  ip_addr a;
  ip4_addr ip4;
  ip6_addr ip6;
  net_addr net;
  net_addr *net_ptr;
  struct symbol *s;
  struct keyword *kw;
  const char *t;
  struct rtable_config *r;
  struct channel_config *cc;
  struct channel *c;
  struct f_inst *x;
  struct {
    struct f_inst *begin, *end;
  } xp;
  enum filter_return fret;
  enum ec_subtype ecs;
  struct f_dynamic_attr fda;
  struct f_static_attr fsa;
  struct f_lval flv;
  struct f_line *fl;
  struct f_arg *fa;
  const struct filter *f;
  struct f_tree *e;
  struct f_trie *trie;
  struct f_val v;
  struct password_item *p;
  struct rt_show_data *ra;
  struct sym_show_data *sd;
  struct lsadb_show_data *ld;
  struct mrt_dump_data *md;
  struct mpls_show_ranges_cmd *msrc;
  struct bfd_show_sessions_cmd *bssc;
  struct iface *iface;
  void *g;
  btime time;
  struct f_prefix px;
  struct proto_spec ps;
  struct channel_limit cl;
  struct timeformat tf;
  struct timeformat *tfp;
  mpls_label_stack *mls;
  const struct adata *bs;
  struct aggr_item_node *ai;
}

%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
%token GEQ LEQ NEQ AND OR IMP
%token PO PC
%token  NUM ENUM_TOKEN
%token  IP4
%token  IP6
%token  VPN_RD
%token  CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS
%token  TEXT
%token  BYTETEXT
%type  ipa_scope

%type  expr bool pxlen4
%type