diff --git a/net-misc/frr/Manifest b/net-misc/frr/Manifest new file mode 100644 index 0000000..2508b97 --- /dev/null +++ b/net-misc/frr/Manifest @@ -0,0 +1 @@ +DIST frr-8.0.tar.gz 8195258 BLAKE2B 75d8d4410a5377dae3bf6938c3b095b163ad87776420a16c07d461bb3f635d623de642fa0ae483094788369c9dc6a04d5424107bf60c848ac54756c4bdb20c97 SHA512 fdf1e68c16e266a74221fb194851ef47c888e90324de2e42a4ca68b9dbce1ba6f45d73b9830bdb17774ecdde736111fa562201a5763c49092b6ce1f0a4d4865a diff --git a/net-misc/frr/files/frr-openrc-v1 b/net-misc/frr/files/frr-openrc-v1 new file mode 100644 index 0000000..9e2f1ab --- /dev/null +++ b/net-misc/frr/files/frr-openrc-v1 @@ -0,0 +1,300 @@ +#!/sbin/openrc-run +# +# FRR OpenRC init script. +# +# Copyright (C) 2020 Rafael F. Zalamena +# +# 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; only version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +description="FRR initialization script." + +# FRR variables. +frr_dir="/usr/lib/frr" +frr_state_dir="/run/frr" +config_file="/etc/frr/frr.conf" +daemon_file="/etc/frr/daemons" +daemon_db="/run/frrdb" +vty_config_file="/etc/frr/vtysh.conf" +frr_reload="$frr_dir/frr-reload.py" +frr_reload_log="$frr_state_dir/reload.log" + +# Don't change profile here, use $daemon_file. This is the default. +frr_profile="traditional" + +# watchfrr variables. +watchfrr_daemons='' +watchfrr_pidfile="$frr_state_dir/watchfrr.pid" + +# +# Helpers. +# +_check_daemon_binary() { + local daemon=$1 + + [ -x "$frr_dir/$daemon" ] && return 0 + + eerror "No binary found for $daemon in $frr_dir" + return 1 +} + +_load_daemon_list() { + # Load FRR daemons configuration file. + while read line <&3 ; do + case $line in + ""|"#"*) + # Skip empty/commented lines. + continue + ;; + + *d=*|*_instances=*|*_options=*|*_wrap=*) + # Load daemon options. + eval "$line" + ;; + + MAX_FDS=*|frr_profile=*|vtysh_enable=*) + # Load misc configuration. + eval "$line" + ;; + esac + done 3< $daemon_file + + # `zebra` and `staticd` are mandatory. + _check_daemon_binary 'zebra' || return 1 + _check_daemon_binary 'staticd' || return 1 + watchfrr_daemons='zebra staticd' + + # Create the watchfrr command line. + for daemon in \ + babeld bfdd bgpd eigrpd fabricd isisd ldpd nhrpd ospfd ospf6d pbrd \ + pimd ripd ripngd sharpd vrrpd \ + ; do + # Trick to read variable name with variable. + cdaemon=$(eval echo \$$daemon) + cdaemon_instances=$(eval echo \$${daemon}_instances) + + # Add daemon to command line if specified. + if [ ! -z $cdaemon ] && [ $cdaemon = 'yes' ]; then + _check_daemon_binary $daemon || return 1 + + # Multi instance daemon handling. + if [ ! -z $cdaemon_instances ]; then + for instance in $(echo $cdaemon_instances | tr ',' ' '); do + watchfrr_daemons="$watchfrr_daemons $daemon-$instance" + done + fi + + # Single instance daemon handling. + watchfrr_daemons="$watchfrr_daemons $daemon" + continue + fi + done +} + +_frr_start() { + # Apply MAX_FDS configuration if set. + if [ ! -z $MAX_FDS ]; then + veinfo " Setting maximum file descriptors to ${MAX_FDS}" + ulimit -n $MAX_FDS >/dev/null 2>/dev/null + fi + + # Save started daemons to state database. + rm -f -- $daemon_db + for daemon in $watchfrr_daemons; do + echo $daemon >> $daemon_db + veinfo " Starting $daemon..." + done + + veinfo " Starting watchfrr..." + + # Start watchfrr which will start all configured daemons. + eval $all_wrap $frr_dir/watchfrr -d -F $frr_profile $watchfrr_daemons + + veinfo " Loading configuration..." + + # After starting the daemons, lets load the configuration. + if [ $vtysh_enable = 'yes' ]; then + vtysh -b -n + else + veinfo " Configuration loading disabled (vtysh_enable=$vtysh_enable)" + fi +} + +_get_pid() { + local daemon=$1 + local pid_file="$frr_state_dir/$daemon.pid" + + # Test for file existence. + if [ ! -r "$pid_file" ]; then + eerror "Failed to find or read $daemon pid file" + return 1 + fi + + # Get PID if any. + pid=$(cat $pid_file) + if [ -z $pid ]; then + eerror "$daemon PID file empty" + return 1 + fi + + return 0 +} + +_stop_daemon() { + local daemon=$1 + local pid_file="$frr_state_dir/$daemon.pid" + + # Get daemon pid. + _get_pid $daemon + + # Ask daemon to quit. + kill -2 "$pid" + + # Test if daemon is still running. + attempts=1200 + while kill -0 "$pid" 2>/dev/null; do + sleep 0.5 + [ $((attempts - 1)) -gt 0 ] || break + done + + # Tell user about our situation. + if kill -0 "$pid" 2>/dev/null ; then + eerror "Failed to stop $daemon (PID=${pid})" + return 1 + else + rm -f -- $pid_file + fi +} + +_frr_stop() { + local failures=0 + + # Stop watchfrr first so it doesn't restart anyone. + veinfo " Stopping watchfrr..." + _stop_daemon watchfrr || failures=1 + + # Read started daemon database. + while read line <&3 ; do + case $line in + ""|"#"*) + # Skip empty/commented lines. + continue + ;; + + *) + # Get daemon name. + veinfo " Stopping $line..." + _stop_daemon $line || failures=1 + ;; + esac + done 3< $daemon_db + + # Remove daemon database file. + rm -f -- $daemon_db + + return $failures +} + +_check_watchfrr() { + _get_pid watchfrr || return 1 + return 0 +} + +# +# Main. +# +depend() { + # We need root to write logs. + need localmount + # Optionally wait for network to start. + use net + # Expect /run to be ready. + after bootmisc +} + +start_pre() { + # Check configuration file readability. + checkpath -f -m 0640 -o frr:frr $vty_config_file + checkpath -f -m 0640 -o frr:frr $daemon_file + checkpath -f -m 0640 -o frr:frr $config_file + + # Check run state directory. + checkpath -d -o frr $frr_state_dir + + # Load daemon list and peform checks. + _load_daemon_list +} + +start() { + # Load daemon list. + _load_daemon_list + + # Handle restarts. + if [ "$RC_CMD" = 'restart' ]; then + ebegin 'Reloading FRR configuration' + else + ebegin 'Starting FRR' + fi + + # Start FRR. + _frr_start + + # New daemons and watchfrr started, apply new configuration. + if [ "$RC_CMD" = 'restart' ]; then + "$frr_reload" --reload "$config_file" 2>/run/frr/reload.log + [ $? -ne 0 ] && ewarn " Failed to reload (check $frr_reload_log)" + # NOTE: we can't return bad status otherwise OpenRC will think we + # failed to start, lets print a helpful message instead. + fi + + eend 0 +} + +stop() { + local failures=0 + + # Handle restarts. + if [ "$RC_CMD" = 'restart' ]; then + # Load daemon list. + _load_daemon_list + + # We must restart 'watchfrr' in order to start new daemons. + veinfo " Stopping watchfrr..." + _stop_daemon watchfrr + + # Stop daemons that are no longer in configuration file. + for daemon in $(ls -1 /run/frr/*.pid | cut -d '.' -f 1); do + # Filter daemon name. + daemon=$(basename "$daemon") + + # Skip watchfrr. + [ "$daemon" = 'watchfrr' ] && continue + + echo "$watchfrr_daemons" | grep "$daemon" >/dev/null + if [ $? -ne 0 ]; then + veinfo " Stopping $daemon..." + _stop_daemon $daemon + fi + done + + return 0 + fi + + ebegin 'Stopping FRR' + _frr_stop || failures=1 + eend $failures 'some daemons failed to stop' +} + +status() { + _check_watchfrr || return 1 +} diff --git a/net-misc/frr/files/frr.pam b/net-misc/frr/files/frr.pam new file mode 100644 index 0000000..5cef5d9 --- /dev/null +++ b/net-misc/frr/files/frr.pam @@ -0,0 +1,26 @@ +#%PAM-1.0 +# + +##### if running frr as root: +# Only allow root (and possibly wheel) to use this because enable access +# is unrestricted. +auth sufficient pam_rootok.so + +# Uncomment the following line to implicitly trust users in the "wheel" group. +#auth sufficient pam_wheel.so trust use_uid +# Uncomment the following line to require a user to be in the "wheel" group. +#auth required pam_wheel.so use_uid +########################################################### + +# If using frr privileges and with a seperate group for vty access, then +# access can be controlled via the vty access group, and pam can simply +# check for valid user/password, eg: +# +# only allow local users. +#auth required pam_securetty.so +#auth include system-auth +#auth required pam_nologin.so +#account include system-auth +#password include system-auth +#session include system-auth +#session optional pam_console.so diff --git a/net-misc/frr/frr-8.0.ebuild b/net-misc/frr/frr-8.0.ebuild new file mode 100644 index 0000000..c753425 --- /dev/null +++ b/net-misc/frr/frr-8.0.ebuild @@ -0,0 +1,144 @@ +# Copyright 2020-2021 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +PYTHON_COMPAT=( python3_{7..10} ) +inherit autotools pam python-single-r1 systemd + +DESCRIPTION="The FRRouting Protocol Suite" +HOMEPAGE="https://frrouting.org/" +SRC_URI="https://github.com/FRRouting/frr/archive/${P}.tar.gz" +# FRR tarballs have weird format. +S="${WORKDIR}/frr-${P}" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64 ~arm64 ~x86" +IUSE="doc fpm grpc ipv6 kernel_linux nhrp ospfapi pam rpki snmp systemd test" +REQUIRED_USE="${PYTHON_REQUIRED_USE}" +RESTRICT="!test? ( test )" + +COMMON_DEPEND=" + ${PYTHON_DEPS} + acct-user/frr + dev-libs/json-c:0= + >=net-libs/libyang-2.0.0 + sys-libs/libcap + sys-libs/readline:0= + virtual/libcrypt:= + grpc? ( net-libs/grpc:= ) + nhrp? ( net-dns/c-ares:0= ) + pam? ( sys-libs/pam ) + rpki? ( >=net-libs/rtrlib-0.6.3[ssh] ) + snmp? ( net-analyzer/net-snmp:= )" + +BDEPEND=" + ~dev-util/clippy-"${PV}" + sys-devel/flex + virtual/yacc + doc? ( dev-python/sphinx )" + +DEPEND=" + ${COMMON_DEPEND} + test? ( $(python_gen_cond_dep 'dev-python/pytest[${PYTHON_USEDEP}]') )" + +RDEPEND=" + ${COMMON_DEPEND} + $(python_gen_cond_dep 'dev-python/ipaddr[${PYTHON_USEDEP}]') + !net-misc/quagga" + +src_prepare() { + default + + python_fix_shebang tools + eautoreconf +} + +src_configure() { + local myconf=( + --disable-static + --with-pkg-extra-version="-gentoo" + --enable-configfile-mask=0640 + --enable-logfile-mask=0640 + --prefix="${EPREFIX}"/usr + --libdir="${EPREFIX}"/usr/lib/frr + --sbindir="${EPREFIX}"/usr/lib/frr + --libexecdir="${EPREFIX}"/usr/lib/frr + --sysconfdir="${EPREFIX}"/etc/frr + --localstatedir="${EPREFIX}"/run/frr + --with-moduledir="${EPREFIX}"/usr/lib/frr/modules + --with-clippy="${BROOT}"/usr/bin/clippy + --enable-exampledir="${EPREFIX}"/usr/share/doc/${PF}/samples + --enable-user=frr + --enable-group=frr + --enable-vty-group=frr + --enable-multipath=64 + $(use_enable doc) + $(use_enable fpm) + $(use_enable grpc) + $(use_enable ipv6 ospf6d) + $(use_enable ipv6 ripngd) + $(use_enable ipv6 rtadv) + $(use_enable kernel_linux realms) + $(use_enable nhrp nhrpd) + $(usex ospfapi '--enable-ospfclient' '' '' '') + $(use_enable rpki) + $(use_enable snmp) + $(use_enable systemd) + ) + + econf "${myconf[@]}" +} + +src_compile() { + default + + use doc && emake -C doc html +} + +src_install() { + default + find "${ED}" -name '*.la' -delete || die + + # Install user documentation if asked + use doc && dodoc -r doc/user/_build/html + + # Create configuration directory with correct permissions + keepdir /etc/frr + fowners frr:frr /etc/frr + fperms 775 /etc/frr + + # Create logs directory with the correct permissions + keepdir /var/log/frr + fowners frr:frr /var/log/frr + fperms 775 /var/log/frr + + # Install the default configuration files + insinto /etc/frr + doins tools/etc/frr/vtysh.conf + doins tools/etc/frr/frr.conf + doins tools/etc/frr/daemons + + # Fix permissions/owners. + fowners frr:frr /etc/frr/vtysh.conf + fowners frr:frr /etc/frr/frr.conf + fowners frr:frr /etc/frr/daemons + fperms 640 /etc/frr/vtysh.conf + fperms 640 /etc/frr/frr.conf + fperms 640 /etc/frr/daemons + + # Install logrotate configuration + insinto /etc/logrotate.d + newins redhat/frr.logrotate frr + + # Install PAM configuration file + use pam && newpamd "${FILESDIR}"/frr.pam frr + + # Install init scripts + systemd_dounit tools/frr.service + newinitd "${FILESDIR}"/frr-openrc-v1 frr + + # Conflict files, installed by net-libs/libsmi, bug #758383 + rm "${ED}"/usr/share/yang/ietf-interfaces.yang || die +} diff --git a/net-misc/frr/metadata.xml b/net-misc/frr/metadata.xml new file mode 100644 index 0000000..dc5cd64 --- /dev/null +++ b/net-misc/frr/metadata.xml @@ -0,0 +1,20 @@ + + + + + pinkbyte@gentoo.org + Sergey Popov + + + jakov.smolic@sartura.hr + Jakov Smolic + + + Enable gRPC plugin + Build Next Hop Resolution Protocol daemon + Enable Forwarding Plane Manager support + Enable RPKI + Add support for PAM (via sys-libs/pam) to the Virtual Terminal Interface Shell (vtysh) + Build OSPFAPI support + +