diff --git a/COMMUNITY.md b/COMMUNITY.md index 52777da968..704c47a95e 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -2,6 +2,16 @@ [TOC] +## General note on this document + +This document is "descriptive/post-factual" in that it documents pratices that +are in use; it is not "definitive/pre-factual" in prescribing practices. + +This means that when a procedure changes, it is agreed upon, then put into +practice, and then documented here. If this document doesn't match reality, +it's the document that needs to be updated, not reality. + + ## Git Structure The master Git for PROJECT resides on Github at @@ -10,20 +20,21 @@ The master Git for PROJECT resides on Github at ![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg "git branch mechanics") -There are 3 main branches for development and a release branch for each +There is one main branch for development and a release branch for each major release. -New contributions are done against the head of the Develop branch. The CI +New contributions are done against the head of the master branch. The CI systems will pick up the Github Pull Requests or the new patch from -Patchwork, run some basic build and functional tests and will merge them -into the branch automatically on success. - -Code on the develop branch will then be further tested and reviewed by the -community and merged to master on a regular interval. +Patchwork, run some basic build and functional tests. For each major release (1.0, 1.1 etc) a new release branch is created based on the master. +There was an attempt to use a "develop" branch automatically maintained by +the CI system. This is not currently in active use, though the system is +operational. If the "develop" branch is in active use and this paragraph +is still here, this document obviously wasn't updated. + ## Programming language, Tools and Libraries @@ -250,16 +261,72 @@ Portions: ### Code styling / format -GNU coding standards apply. Indentation follows the result of invoking GNU -indent (as of 2.2.8a) with the `-nut -nfc1` arguments. +Coding style standards in FRR vary depending on location. Pre-existing +code uses GNU coding standards. New code may use Linux kernel coding style. + +GNU coding style apply to the following parts: + +* lib/ +* zebra/ +* bgpd/ +* ospfd/ +* ospf6d/ +* isisd/ +* ripd/ +* ripngd/ +* vtysh/ + +Linux kernel coding style applies to: + +* nhrpd/ +* watchfrr/ +* pimd/ +* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch] + +BSD coding style applies to: + +* ldpd/ + +**Whitespace changes in untouched parts of the code are not acceptable in +patches that change actual code.** To change/fix formatting issues, please +create a separate patch that only does formatting changes and nothing else. + +It is acceptable to rewrap entire files to Linux kernel style, but this +**MUST** come as a separate patch that does nothing other than this +reformatting. + + +#### GNU style + +For GNU coding style, Indentation follows the result of invoking GNU indent: ``` indent -nut -nfc1 file_for_submission.c ``` -Please don’t reformat existing files (or only sections modified by your -changes), even if they don’t follow the standard. This makes it very hard to -highlight the changes +Originally, tabs were used instead of spaces, with tabs are every 8 columns. +However, tab interoperability issues mean space characters are now preferred for +new changes. We generally only clean up whitespace when code is unmaintainable +due to whitespace issues, to minimise merging conflicts. + + +#### Linux kernel & BSD style + +These styles are documented externally: + +* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle). +* [http://man.openbsd.org/style](http://man.openbsd.org/style) + +They are relatively similar but differ in details. + +pimd deviates from Linux kernel style in using 2 spaces for indentation, with +Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`. +It is acceptable to convert indentation in pimd/ to Linux kernel style, but +please convert an entire file at a time. (Rationale: apart from 2-space +indentation, the styles are sufficiently close to not upset when mixed.) + +Unlike GNU style, these styles use tabs, not spaces. + ### Compile-Time conditional code @@ -307,4 +374,4 @@ of their debugs. CLI's are a complicated ugly beast. Additions or changes to the CLI should use a DEFUN to encapsulate one setting as much as is possible. Additionally as new DEFUN's are added to the system, documentation -should be provided for the new commands. \ No newline at end of file +should be provided for the new commands. diff --git a/ChangeLog b/ChangeLog index a201bb6819..ec7e6cdde8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -ChangeLog information for FreeRangeRouting is for now recorded in source-code +ChangeLog information for FRRouting is for now recorded in source-code management system. Please see: - http://www.freerangerouting.org/ + http://www.frrouting.org/ diff --git a/Makefile.am b/Makefile.am index aa978b7d25..89e7ea890e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,3 +17,5 @@ EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \ tools/zebra.el tools/multiple-bgpd.sh ACLOCAL_AMFLAGS = -I m4 + +noinst_HEADERS = defaults.h diff --git a/REPORTING-BUGS b/REPORTING-BUGS index ea36ff5eed..01f25a2051 100644 --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -1,5 +1,5 @@ -This file describes the procedure for reporting FreeRangeRouting bugs. You are not -obliged to follow this format, but it would be great help for FreeRangeRouting developers +This file describes the procedure for reporting FRRouting bugs. You are not +obliged to follow this format, but it would be great help for FRRouting developers if you report a bug as described below. Bugs submitted with woefully incomplete information may be summarily @@ -10,10 +10,10 @@ non-response to requests to reconfirm or supply additional information. Report bugs on Github Issue Tracker at - https://github.com/freerangerouting/frr/issues + https://github.com/frrouting/frr/issues Please supply the following information: -1. Your FreeRangeRouting version or if it is from git then the commit reference. +1. Your FRRouting version or if it is from git then the commit reference. Please try to report bugs against git master or the latest release. 2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any specific options you compiled Quagga with. diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 50afc7ed64..b6ed9a4d6d 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -67,6 +67,7 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libbgp.a +module_LTLIBRARIES = sbin_PROGRAMS = bgpd bin_PROGRAMS = bgp_btoa @@ -75,7 +76,7 @@ libbgp_a_SOURCES = \ bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \ bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \ bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ - bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \ + bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \ bgp_mplsvpn.c bgp_nexthop.c \ bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \ bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \ @@ -89,7 +90,7 @@ noinst_HEADERS = \ bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \ bgp_ecommunity.h bgp_lcommunity.h \ bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ - bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \ + bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \ bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h @@ -101,6 +102,15 @@ bgp_btoa_SOURCES = bgp_btoa.c bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS) +if SNMP +module_LTLIBRARIES += bgpd_snmp.la +endif + +bgpd_snmp_la_SOURCES = bgp_snmp.c +bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la + examplesdir = $(exampledir) dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgpd.conf.vnc.sample diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 7dc7f053d6..2bbdca595c 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_dump.h" #include "bgpd/bgp_open.h" #include "bgpd/bgp_advertise.h" -#ifdef HAVE_SNMP -#include "bgpd/bgp_snmp.h" -#endif /* HAVE_SNMP */ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" +DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) +DEFINE_HOOK(peer_established, (struct peer *peer), (peer)) + /* Definition of display strings corresponding to FSM events. This should be * kept consistent with the events defined in bgpd.h */ @@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer) zlog_debug ("%s remove from all update group", peer->host); update_group_remove_peer_afs(peer); -#ifdef HAVE_SNMP - bgpTrapBackwardTransition (peer); -#endif /* HAVE_SNMP */ + hook_call(peer_backward_transition, peer); /* Reset peer synctime */ peer->synctime = 0; @@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer) zlog_debug ("%s graceful restart timer stopped", peer->host); } -#ifdef HAVE_SNMP - bgpTrapEstablished (peer); -#endif /* HAVE_SNMP */ + hook_call(peer_established, peer); /* Reset uptime, send keepalive, send current table. */ peer->uptime = bgp_clock (); diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index e47d07702b..4d0b48f529 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *); */ extern void bgp_adjust_routeadv (struct peer *); +#include "hook.h" +DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) +DECLARE_HOOK(peer_established, (struct peer *peer), (peer)) + #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 5e6218e8a3..f45d683848 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include -#ifdef HAVE_SNMP #include #include @@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "thread.h" #include "smux.h" #include "filter.h" +#include "hook.h" +#include "libfrr.h" +#include "version.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -38,7 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_attr.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_fsm.h" -#include "bgpd/bgp_snmp.h" /* BGP4-MIB described in RFC1657. */ #define BGP4MIB 1,3,6,1,2,1,15 @@ -838,7 +839,7 @@ static struct trap_object bgpTrapList[] = {3, {3, 1, BGPPEERSTATE}} }; -void +static int bgpTrapEstablished (struct peer *peer) { int ret; @@ -847,7 +848,7 @@ bgpTrapEstablished (struct peer *peer) ret = inet_aton (peer->host, &addr); if (ret == 0) - return; + return 0; oid_copy_addr (index, &addr, IN_ADDR_SIZE); @@ -857,9 +858,10 @@ bgpTrapEstablished (struct peer *peer) index, IN_ADDR_SIZE, bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), BGPESTABLISHED); + return 0; } -void +static int bgpTrapBackwardTransition (struct peer *peer) { int ret; @@ -868,7 +870,7 @@ bgpTrapBackwardTransition (struct peer *peer) ret = inet_aton (peer->host, &addr); if (ret == 0) - return; + return 0; oid_copy_addr (index, &addr, IN_ADDR_SIZE); @@ -878,12 +880,29 @@ bgpTrapBackwardTransition (struct peer *peer) index, IN_ADDR_SIZE, bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), BGPBACKWARDTRANSITION); + return 0; } -void -bgp_snmp_init (void) +static int +bgp_snmp_init (struct thread_master *tm) { - smux_init (bm->master); + smux_init (tm); REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + return 0; } -#endif /* HAVE_SNMP */ + +static int +bgp_snmp_module_init (void) +{ + hook_register(peer_established, bgpTrapEstablished); + hook_register(peer_backward_transition, bgpTrapBackwardTransition); + hook_register(frr_late_init, bgp_snmp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "bgpd_snmp", + .version = FRR_VERSION, + .description = "bgpd AgentX SNMP module", + .init = bgp_snmp_module_init +) diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h deleted file mode 100644 index 7a0d9dd007..0000000000 --- a/bgpd/bgp_snmp.h +++ /dev/null @@ -1,28 +0,0 @@ -/* BGP4 SNMP support - Copyright (C) 1999, 2000 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra 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, or (at your option) any -later version. - -GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -#ifndef _QUAGGA_BGP_SNMP_H -#define _QUAGGA_BGP_SNMP_H - -extern void bgp_snmp_init (void); -extern void bgpTrapEstablished (struct peer *); -extern void bgpTrapBackwardTransition (struct peer *); - -#endif /* _QUAGGA_BGP_SNMP_H */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 30243e80b2..25bd757840 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -72,9 +72,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nht.h" -#ifdef HAVE_SNMP -#include "bgpd/bgp_snmp.h" -#endif /* HAVE_SNMP */ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" @@ -2937,10 +2934,18 @@ bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; bgp->dynamic_neighbors_count = 0; +#if DFLT_BGP_IMPORT_CHECK bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK); +#endif +#if DFLT_BGP_SHOW_HOSTNAME bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME); +#endif +#if DFLT_BGP_LOG_NEIGHBOR_CHANGES bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); +#endif +#if DFLT_BGP_DETERMINISTIC_MED bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); +#endif bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; bgp->as = *as; @@ -7379,8 +7384,11 @@ bgp_config_write (struct vty *vty) inet_ntoa (bgp->router_id_static), VTY_NEWLINE); /* BGP log-neighbor-changes. */ - if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) - vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) + != DFLT_BGP_LOG_NEIGHBOR_CHANGES) + vty_out (vty, " %sbgp log-neighbor-changes%s", + bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) ? "" : "no ", + VTY_NEWLINE); /* BGP configuration. */ if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) @@ -7396,8 +7404,11 @@ bgp_config_write (struct vty *vty) bgp->default_local_pref, VTY_NEWLINE); /* BGP default show-hostname */ - if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)) - vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE); + if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + != DFLT_BGP_SHOW_HOSTNAME) + vty_out (vty, " %sbgp default show-hostname%s", + bgp_flag_check (bgp, BGP_FLAG_SHOW_HOSTNAME) ? "" : "no ", + VTY_NEWLINE); /* BGP default subgroup-pkt-queue-max. */ if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) @@ -7440,8 +7451,11 @@ bgp_config_write (struct vty *vty) vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE); /* BGP deterministic-med. */ - if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) + != DFLT_BGP_DETERMINISTIC_MED) + vty_out (vty, " %sbgp deterministic-med%s", + bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) ? "" : "no ", + VTY_NEWLINE); /* BGP update-delay. */ bgp_config_write_update_delay (vty, bgp); @@ -7517,8 +7531,11 @@ bgp_config_write (struct vty *vty) } /* BGP network import check. */ - if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) - vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) + != DFLT_BGP_IMPORT_CHECK) + vty_out (vty, " %sbgp network import-check%s", + bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) ? "" : "no ", + VTY_NEWLINE); /* BGP flag dampening. */ if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], @@ -7647,6 +7664,8 @@ bgp_if_finish (struct bgp *bgp) } } +extern void bgp_snmp_init (void); + void bgp_init (void) { @@ -7695,10 +7714,6 @@ bgp_init (void) /* Community list initialize. */ bgp_clist = community_list_init (); -#ifdef HAVE_SNMP - bgp_snmp_init (); -#endif /* HAVE_SNMP */ - /* BFD init */ bgp_bfd_init(); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9ccc0e39de..a72974bc1d 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -31,6 +31,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "routemap.h" #include "linklist.h" +#include "defaults.h" #include "bgp_memory.h" #define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */ @@ -1068,12 +1069,13 @@ struct bgp_nlri #define BGP_EVENTS_MAX 15 /* BGP timers default value. */ +/* note: the DFLT_ ones depend on compile-time "defaults" selection */ #define BGP_INIT_START_TIMER 1 -#define BGP_DEFAULT_HOLDTIME 9 -#define BGP_DEFAULT_KEEPALIVE 3 +#define BGP_DEFAULT_HOLDTIME DFLT_BGP_HOLDTIME +#define BGP_DEFAULT_KEEPALIVE DFLT_BGP_KEEPALIVE #define BGP_DEFAULT_EBGP_ROUTEADV 0 #define BGP_DEFAULT_IBGP_ROUTEADV 0 -#define BGP_DEFAULT_CONNECT_RETRY 10 +#define BGP_DEFAULT_CONNECT_RETRY DFLT_BGP_TIMERS_CONNECT /* BGP default local preference. */ #define BGP_DEFAULT_LOCAL_PREF 100 diff --git a/configure.ac b/configure.ac index e46e44a8b7..b4a3e37fd2 100755 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ ## -## Configure template file for FreeRangeRouting. +## Configure template file for FRRouting. ## autoconf will generate configure script. ## ## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro @@ -7,9 +7,9 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 2.1-dev, [https://github.com/freerangerouting/frr/issues]) -PACKAGE_URL="https://freerangerouting.org/" -PACKAGE_FULLNAME="FreeRangeRouting" +AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues]) +PACKAGE_URL="https://frrouting.org/" +PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) CONFIG_ARGS="$ac_configure_args" @@ -55,6 +55,13 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow AC_SUBST(pkgsrcdir) AC_SUBST(pkgsrcrcdir) +AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [ + moduledir="$withval" +], [ + moduledir="\${libdir}/frr/modules" +]) +AC_SUBST([moduledir], [$moduledir]) + AC_ARG_ENABLE(tcmalloc, AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]), [case "${enableval}" in @@ -66,6 +73,10 @@ LIBS="$LIBS -ltcmalloc_minimal" esac],[tcmalloc_enabled=false]) +dnl Thanks autoconf, but we don't want a default -g -O2. We have our own +dnl flag determination logic. +CFLAGS="${CFLAGS:-}" + dnl -------------------- dnl Check CC and friends dnl -------------------- @@ -78,6 +89,7 @@ AM_PROG_CC_C_O dnl remove autoconf default "-g -O2" CFLAGS="$orig_cflags" AC_PROG_CC_C99 +dnl NB: see C11 below AC_PROG_EGREP PKG_PROG_PKG_CONFIG @@ -89,7 +101,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false]) dnl try and enable CFLAGS that are useful for Quagga dnl - specifically, options to control warnings -AC_USE_SYSTEM_EXTENSIONS() +AC_USE_SYSTEM_EXTENSIONS AC_DEFUN([AC_C_FLAG], [{ AC_LANG_PUSH(C) ac_c_flag_save="$CFLAGS" @@ -115,6 +127,13 @@ dnl ICC won't bail on unknown options without -diag-error 10006 dnl need to do this first so we get useful results for the other options AC_C_FLAG([-diag-error 10006]) +dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something +ac_cc="$CC" +CC="${CC% -std=gnu99}" +CC="${CC% -std=c99}" + +AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"]) + dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here if test "z$orig_cflags" = "z"; then AC_C_FLAG([-g]) @@ -170,6 +189,18 @@ AC_LINK_IFELSE( ]) AC_LANG_POP(C) +dnl ---------- +dnl Essentials +dnl ---------- + +AX_PTHREAD([ + CC="$PTHREAD_CC" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" +], [ + AC_MSG_FAILURE([This Quagga version needs pthreads]) +]) + dnl -------------- dnl Check programs dnl -------------- @@ -352,15 +383,18 @@ AC_SUBST(MPLS_METHOD) if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) + DFLT_NAME="datacenter" +else + DFLT_NAME="traditional" fi +AC_SUBST(DFLT_NAME) +AC_DEFINE_UNQUOTED(DFLT_NAME,["$DFLT_NAME"], Name of the configuration default set) if test "${enable_shell_access}" = "yes"; then AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash) fi -if test "${enable_fpm}" = "yes"; then - AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support) -fi +AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) if test "x${enable_dev_build}" = "xyes"; then AC_DEFINE(DEV_BUILD,,Build for development) @@ -529,6 +563,72 @@ AC_CHECK_HEADERS([stropts.h sys/ksym.h \ linux/version.h asm/types.h \ sys/cdefs.h]) +ac_stdatomic_ok=false +AC_DEFINE(FRR_AUTOCONF_ATOMIC, 1, [did autoconf checks for atomic funcs]) +AC_CHECK_HEADER([stdatomic.h],[ + + AC_MSG_CHECKING([whether _Atomic qualifier works]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#include +int main(int argc, char **argv) { + _Atomic int i = 0; + return i; +} +]])], [ + AC_DEFINE(HAVE_STDATOMIC_H, 1, [found stdatomic.h]) + AC_MSG_RESULT([yes]) + ac_stdatomic_ok=true + ], [ + AC_MSG_RESULT([no]) + ]) +]) + +AS_IF([$ac_stdatomic_ok], [true], [ + AC_MSG_CHECKING([for __atomic_* builtins]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + __atomic_store_n (&i, 0, __ATOMIC_RELEASE); + return __atomic_load_n (&i, __ATOMIC_ACQUIRE); +} +]])], [ + AC_DEFINE(HAVE___ATOMIC, 1, [found __atomic builtins]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + dnl FreeBSD 9 has a broken stdatomic.h where _Atomic doesn't work + AC_MSG_CHECKING([for __sync_* builtins]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + __sync_fetch_and_sub (&i, 1); + return __sync_val_compare_and_swap (&i, 0, 1); +} +]])], [ + AC_DEFINE(HAVE___SYNC, 1, [found __sync builtins]) + AC_MSG_RESULT([yes]) + + AC_MSG_CHECKING([for __sync_swap builtin]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + return __sync_swap (&i, 2); +} +]])], [ + AC_DEFINE(HAVE___SYNC_SWAP, 1, [found __sync_swap builtin]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + ], [ + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([stdatomic.h unavailable and $CC has neither __atomic nor __sync builtins]) + ]) + ]) +]) + dnl Utility macro to avoid retyping includes all the time m4_define([FRR_INCLUDES], [#ifdef SUNOS_5 @@ -1317,8 +1417,8 @@ if test "${enable_snmp}" != ""; then if test x"$NETSNMP_CONFIG" = x"no"; then AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config]) fi - LIBS="$LIBS `${NETSNMP_CONFIG} --agent-libs`" - CFLAGS="`${NETSNMP_CONFIG} --base-cflags` $CFLAGS" + SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`" + SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`" AC_MSG_CHECKING([whether we can link to Net-SNMP]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ int main(void); @@ -1330,7 +1430,6 @@ int main(void); ])],[AC_MSG_RESULT(yes)],[ AC_MSG_RESULT(no) AC_MSG_ERROR([--enable-snmp given but not usable])]) - AC_DEFINE(HAVE_SNMP,,SNMP) case "${enable_snmp}" in yes) SNMP_METHOD=agentx @@ -1346,6 +1445,53 @@ int main(void); AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd]) AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd) fi +AM_CONDITIONAL([SNMP], [test "x${SNMP_METHOD}" != "x"]) +AC_SUBST(SNMP_LIBS) +AC_SUBST(SNMP_CFLAGS) + +dnl --------------- +dnl dlopen & dlinfo +dnl --------------- +AC_SEARCH_LIBS(dlopen, [dl dld], [], [ + AC_MSG_ERROR([unable to find the dlopen()]) +]) + +AC_CHECK_HEADERS([link.h]) + +AC_MSG_CHECKING([for dlinfo(RTLD_DI_ORIGIN)]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_LINK_H +#include +#endif +#include +]], [[ + char origin[1]; + dlinfo (NULL, RTLD_DI_ORIGIN, &origin); +]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN]) +], [ + AC_MSG_RESULT(no) +]) + +AC_MSG_CHECKING([for dlinfo(RTLD_DI_LINKMAP)]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_LINK_H +#include +#endif +#include +]], [[ + struct link_map *lm = NULL; + dlinfo (NULL, RTLD_DI_LINKMAP, &lm); +]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP]) +], [ + AC_MSG_RESULT(no) +]) + dnl --------------------------- dnl sockaddr and netinet checks @@ -1646,14 +1792,18 @@ AC_DEFINE_UNQUOTED(VTYSH_BIN_PATH, "$vtysh_bin",path to vtysh binary) CFG_SYSCONF="$sysconfdir" CFG_SBIN="$sbindir" CFG_STATE="$frr_statedir" +CFG_MODULE="$moduledir" for I in 1 2 3 4 5 6 7 8 9 10; do eval CFG_SYSCONF="\"$CFG_SYSCONF\"" eval CFG_SBIN="\"$CFG_SBIN\"" eval CFG_STATE="\"$CFG_STATE\"" + eval CFG_MODULE="\"$CFG_MODULE\"" done AC_SUBST(CFG_SYSCONF) AC_SUBST(CFG_SBIN) AC_SUBST(CFG_STATE) +AC_SUBST(CFG_MODULE) +AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules) dnl --------------------------- dnl Check htonl works correctly @@ -1681,6 +1831,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile snapcraft/Makefile snapcraft/snapcraft.yaml lib/version.h + tests/lib/cli/test_cli.refout doc/defines.texi doc/bgpd.8 doc/isisd.8 @@ -1716,7 +1867,7 @@ AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl]) AC_OUTPUT echo " -FreeRangeRouting configuration +FRRouting configuration ------------------------------ FRR version : ${PACKAGE_VERSION} host operating system : ${host_os} @@ -1728,6 +1879,7 @@ linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM} state file directory : ${frr_statedir} config file directory : `eval echo \`echo ${sysconfdir}\`` example directory : `eval echo \`echo ${exampledir}\`` +module directory : ${CFG_MODULE} user to run as : ${enable_user} group to run as : ${enable_group} group for vty sockets : ${enable_vty_group} diff --git a/debian/README.Debian b/debian/README.Debian index caded52075..4cf35d7e32 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -14,7 +14,7 @@ available forcing you to explicitly type "apt-get install frr" to upgrade it. * What is frr? ================= -http://www.freerangerouting.org/ +http://www.frrouting.org/ FRR is a routing software suite, providing implementations of OSPFv2, OSPFv3, RIP v1 and v2, RIPng, ISIS, PIM, BGP and LDP for Unix platforms, particularly FreeBSD and Linux and also NetBSD, to mention a few. FRR is a fork of Quagga diff --git a/debian/copyright b/debian/copyright index 6a5ed98f91..7b873abd31 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,7 +1,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Frr -Upstream-Contact: maintainers@freerangerouting.org, security@freerangerouting.org -Source: http://www.freerangerouting.org/ +Upstream-Contact: maintainers@frrouting.org, security@frrouting.org +Source: http://www.frrouting.org/ Files: * Copyright: 1996-2003 by the original Zebra authors: diff --git a/defaults.h b/defaults.h new file mode 100644 index 0000000000..57e35f3ce6 --- /dev/null +++ b/defaults.h @@ -0,0 +1,54 @@ +/* + * FRR switchable defaults. + * Copyright (C) 2017 David Lamparter for NetDEF, Inc. + * + * This file is part of FRRouting (FRR). + * + * FRR 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, or (at your option) any later version. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FRR_DEFAULTS_H +#define _FRR_DEFAULTS_H + +#include "config.h" + +#ifdef HAVE_CUMULUS + +#define DFLT_BGP_IMPORT_CHECK 1 +#define DFLT_BGP_TIMERS_CONNECT 10 +#define DFLT_BGP_HOLDTIME 9 +#define DFLT_BGP_KEEPALIVE 3 +#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 1 +#define DFLT_BGP_SHOW_HOSTNAME 1 +#define DFLT_BGP_DETERMINISTIC_MED 1 + +#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1 +#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1 + +#else /* !HAVE_CUMULUS */ + +#define DFLT_BGP_IMPORT_CHECK 0 +#define DFLT_BGP_TIMERS_CONNECT 120 +#define DFLT_BGP_HOLDTIME 180 +#define DFLT_BGP_KEEPALIVE 60 +#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 0 +#define DFLT_BGP_SHOW_HOSTNAME 0 +#define DFLT_BGP_DETERMINISTIC_MED 0 + +#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 0 +#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 0 + +#endif /* !HAVE_CUMULUS */ + +#endif /* _FRR_DEFAULTS_H */ diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index 3829962d4a..9f40418fff 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -18,7 +18,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk readline-devel \ texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \ - flex c-ares-devel epel-release + flex c-ares-devel epel-release rpm-build libcap-devel texi2html Install newer version of bison (CentOS 6 package source is too old) from CentOS 7 @@ -69,7 +69,7 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -78,7 +78,7 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ diff --git a/doc/Building_FRR_on_CentOS7.md b/doc/Building_FRR_on_CentOS7.md index 41c88b5593..0ab5c0ff54 100644 --- a/doc/Building_FRR_on_CentOS7.md +++ b/doc/Building_FRR_on_CentOS7.md @@ -15,7 +15,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk readline-devel \ texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \ - bison flex pytest c-ares-devel python-devel + bison flex pytest c-ares-devel python-devel rpm-build To build from git (in difference to building from distribution tar.gz as created by `make dist`), the python development libraries are needed. (Make sure you've installed EPEL libraries as shown above for this to work) @@ -32,7 +32,7 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -41,7 +41,7 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index 1acbb802f6..b902033d5e 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -32,14 +32,14 @@ any packages** sudo addgroup --system --gid 92 frr sudo addgroup --system --gid 85 frrvty sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ - --gecos "FRR FreeRangeRouting suite" --shell /bin/false frr + --gecos "FRR FRRouting suite" --shell /bin/false frr sudo usermode ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ diff --git a/doc/Building_FRR_on_Fedora24.md b/doc/Building_FRR_on_Fedora24.md index 0b9872bb09..941126da42 100644 --- a/doc/Building_FRR_on_Fedora24.md +++ b/doc/Building_FRR_on_Fedora24.md @@ -22,7 +22,7 @@ using any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just @@ -31,7 +31,7 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ diff --git a/doc/Building_FRR_on_FreeBSD10.md b/doc/Building_FRR_on_FreeBSD10.md index 5f50bee0d9..36ef573bb0 100644 --- a/doc/Building_FRR_on_FreeBSD10.md +++ b/doc/Building_FRR_on_FreeBSD10.md @@ -41,7 +41,7 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh export MAKE=gmake diff --git a/doc/Building_FRR_on_FreeBSD11.md b/doc/Building_FRR_on_FreeBSD11.md index 9b327af1fd..d6affd688b 100644 --- a/doc/Building_FRR_on_FreeBSD11.md +++ b/doc/Building_FRR_on_FreeBSD11.md @@ -41,7 +41,7 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh export MAKE=gmake diff --git a/doc/Building_FRR_on_FreeBSD9.md b/doc/Building_FRR_on_FreeBSD9.md index 2fd4f1095c..41d3148ad7 100644 --- a/doc/Building_FRR_on_FreeBSD9.md +++ b/doc/Building_FRR_on_FreeBSD9.md @@ -49,7 +49,7 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh export MAKE=gmake diff --git a/doc/Building_FRR_on_NetBSD6.md b/doc/Building_FRR_on_NetBSD6.md index 3a2dea7c20..542a7f489e 100644 --- a/doc/Building_FRR_on_NetBSD6.md +++ b/doc/Building_FRR_on_NetBSD6.md @@ -45,7 +45,7 @@ Get FRR, compile it and install it (from Git) (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh MAKE=gmake diff --git a/doc/Building_FRR_on_NetBSD7.md b/doc/Building_FRR_on_NetBSD7.md index 38a116f4f1..821a6109f2 100644 --- a/doc/Building_FRR_on_NetBSD7.md +++ b/doc/Building_FRR_on_NetBSD7.md @@ -39,7 +39,7 @@ Get FRR, compile it and install it (from Git) (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh MAKE=gmake diff --git a/doc/Building_FRR_on_OmniOS.md b/doc/Building_FRR_on_OmniOS.md index a64b054417..2e9871467b 100644 --- a/doc/Building_FRR_on_OmniOS.md +++ b/doc/Building_FRR_on_OmniOS.md @@ -87,7 +87,7 @@ any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh export MAKE=gmake diff --git a/doc/Building_FRR_on_OpenBSD6.md b/doc/Building_FRR_on_OpenBSD6.md index 14a703b1d3..a59452a72b 100644 --- a/doc/Building_FRR_on_OpenBSD6.md +++ b/doc/Building_FRR_on_OpenBSD6.md @@ -34,7 +34,7 @@ any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh export LDFLAGS="-L/usr/local/lib" diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index 03d66af629..154907d9df 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -72,7 +72,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ @@ -102,20 +102,20 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ldpd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index 5de2fd8bb9..33ef896a9a 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -32,7 +32,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ @@ -62,19 +62,19 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index 996b8da898..18724859fb 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -33,7 +33,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr ./bootstrap.sh ./configure \ @@ -63,20 +63,20 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ldpd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/basic.texi b/doc/basic.texi index cea33eaa81..05d72bc80f 100644 --- a/doc/basic.texi +++ b/doc/basic.texi @@ -18,6 +18,7 @@ daemons. * Config Commands:: Commands used in config files * Terminal Mode Commands:: Common commands used in a VTY * Common Invocation Options:: Starting the daemons +* Loadable Module Support:: Using extension modules * Virtual Terminal Interfaces:: Interacting with the daemons @end menu @@ -372,6 +373,51 @@ Print program version. @end table +@node Loadable Module Support +@section Loadable Module Support + +FRR supports loading extension modules at startup. Loading, reloading or +unloading modules at runtime is not supported (yet). To load a module, use +the following command line option at daemon startup: + +@table @samp +@item -M @var{module:options} +@itemx --module @var{module:options} + +Load the specified module, optionally passing options to it. If the module +name contains a slash (/), it is assumed to be a full pathname to a file to +be loaded. If it does not contain a slash, the +@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of +the given name; first with the daemon name prepended (e.g. @code{zebra_mod} +for @code{mod}), then without the daemon name prepended. + +This option is available on all daemons, though some daemons may not have +any modules available to be loaded. +@end table + + +@subsection The SNMP Module + +If SNMP is enabled during compile-time and installed as part of the package, +the @code{snmp} module can be loaded for the @command{zebra}, +@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons. + +The module ignores any options passed to it. Refer to @ref{SNMP Support} +for information on its usage. + + +@subsection The FPM Module + +If FPM is enabled during compile-time and installed as part of the package, +the @code{fpm} module can be loaded for the @command{zebra} daemon. This +provides the Forwarding Plane Manager ("FPM") API. + +The module expects its argument to be either @code{netlink} or +@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the +default, and @code{protobuf} may not be available if the module was built +without protobuf support. Refer to @ref{zebra FIB push interface} for more +information. + @node Virtual Terminal Interfaces @section Virtual Terminal Interfaces diff --git a/doc/bgpd.8.in b/doc/bgpd.8.in index 9026f2cdee..0df1b1dcea 100644 --- a/doc/bgpd.8.in +++ b/doc/bgpd.8.in @@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@ ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B bgpd @@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR. \fB\-S\fR, \fB\-\-skip_runas\fR Skip setting the process effective user and group. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBbgpd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/defines.texi.in b/doc/defines.texi.in index 43d7442939..0fadba964a 100644 --- a/doc/defines.texi.in +++ b/doc/defines.texi.in @@ -13,6 +13,7 @@ @set INSTALL_PREFIX_ETC @CFG_SYSCONF@ @set INSTALL_PREFIX_SBIN @CFG_SBIN@ @set INSTALL_PREFIX_STATE @CFG_STATE@ +@set INSTALL_PREFIX_MODULES @CFG_MODULE@ @set INSTALL_USER @enable_user@ @set INSTALL_GROUP @enable_group@ @set INSTALL_VTY_GROUP @enable_vty_group@ diff --git a/doc/dev-modules.md b/doc/dev-modules.md new file mode 100644 index 0000000000..87bc963188 --- /dev/null +++ b/doc/dev-modules.md @@ -0,0 +1,119 @@ +# Module and Hook support (developer docs) + +## What it does + +It uses `dlopen()` to load DSOs at startup. + + +## Limitations + +* can't load, unload, or reload during runtime. This just needs some work + and can probably be done in the future. +* doesn't fix any of the "things need to be changed in the code in the library" + issues. Most prominently, you can't add a CLI node because CLI nodes are + listed in the library... +* if your module crashes, the daemon crashes. Should be obvious. +* **does not provide a stable API or ABI**. Your module must match a version + of FRR and you may have to update it frequently to match changes. +* **does not create a license boundary**. Your module will need to link + libzebra and include header files from the daemons, meaning it will be + GPL-encumbered. + + +## Installation + +Look for `moduledir` in `configure.ac`, default is normally +`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`. + +The daemon's name is prepended when looking for a module, e.g. "snmp" tries +to find "zebra_snmp" first when used in zebra. This is just to make it nicer +for the user, with the snmp module having the same name everywhere. + +Modules can be packaged separately from FRR. The SNMP and FPM modules are +good candidates for this because they have dependencies (net-snmp / protobuf) +that are not FRR dependencies. However, any distro packages should have an +"exact-match" dependency onto the FRR package. Using a module from a +different FRR version will probably blow up nicely. + +For snapcraft (and during development), modules can be loaded with full path +(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output +files in the .libs directory, so during development you have to use +`./zebra -M .libs/zebra_snmp.so`. + + +## Creating a module + +... best to look at the existing SNMP or FPM modules. + +Basic boilerplate: + +``` +#include "hook.h" +#include "module.h" + +static int +module_init (void) +{ + hook_register(frr_late_init, module_late_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "my module", + .version = "0.0", + .description = "my module", + .init = module_init, +) +``` + +The `frr_late_init` hook will be called after the daemon has finished its +other startup and is about to enter the main event loop; this is the best +place for most initialisation. + + +## Compiler & Linker magic + +There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility` +attributes to restrict it to the current module. If you get a linker error +with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be +possible, though one way to get it would be to not include libzebra (which +provides a fallback definition for the symbol). + +libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable +modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use +the definition in libzebra; same applies if the main executable doesn't use +`FRR_DAEMON_INFO` (e.g. all testcases). + +The deciding factor here is "what dynamic linker unit are you using the symbol +from." If you're in a library function and want to know who called you, you +can't use `THIS_MODULE` (because that'll just tell you you're in the library). +Put a macro around your function that adds `THIS_MODULE` in the *caller's +code calling your function*. + +The idea is to use this in the future for module unloading. Hooks already +remember which module they were installed by, as groundwork for a function +that removes all of a module's installed hooks. + +There's also the `frr_module` symbol in modules, pretty much a standard entry +point for loadable modules. + + +## Hooks + +Hooks are just points in the code where you can register your callback to +be called. The parameter list is specific to the hook point. Since there is +no stable API, the hook code has some extra type safety checks making sure +you get a compiler warning when the hook parameter list doesn't match your +callback. Don't ignore these warnings. + + +## Relation to MTYPE macros + +The MTYPE macros, while primarily designed to decouple MTYPEs from the library +and beautify the code, also work very nicely with loadable modules -- both +constructors and destructors are executed when loading/unloading modules. + +This means there is absolutely no change required to MTYPEs, you can just use +them in a module and they will even clean up themselves when we implement +module unloading and an unload happens. In fact, it's impossible to create +a bug where unloading fails to de-register a MTYPE. diff --git a/doc/frr.texi b/doc/frr.texi index a64dc9e729..b08bb6fd04 100644 --- a/doc/frr.texi +++ b/doc/frr.texi @@ -7,7 +7,7 @@ @setfilename frr.info @c Set variables - sourced from defines.texi @include defines.texi -@settitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} +@settitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @c %**end of header @c automake will automatically generate version.texi @@ -48,16 +48,16 @@ This file documents the Frr Software Routing Suite which manages common TCP/IP routing protocols. This is Edition @value{EDITION}, last updated @value{UPDATED} of -@cite{The Frr Manual}, for @uref{http://www.freerangerouting.org/,,@value{PACKAGE_NAME}} +@cite{The Frr Manual}, for @uref{http://www.frrouting.org/,,@value{PACKAGE_NAME}} Version @value{VERSION}. @insertcopying @end ifinfo @titlepage -@title @uref{http://www.freerangerouting.org,,Frr} +@title @uref{http://www.frrouting.org,,Frr} @subtitle A routing software package for TCP/IP networks -@subtitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} @value{VERSION} +@subtitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @value{VERSION} @subtitle @value{UPDATED-MONTH} @author @value{AUTHORS} @@ -72,9 +72,9 @@ Version @value{VERSION}. @node Top @top Frr -- With Virtual Network Control -@uref{http://www.freerangerouting.org,,Frr} is an advanced routing software package +@uref{http://www.frrouting.org,,Frr} is an advanced routing software package that provides a suite of TCP/IP based routing protocols. This is the Manual -for @value{PACKAGE_STRING}. @uref{http://www.freerangerouting.org,,Frr} is a fork of +for @value{PACKAGE_STRING}. @uref{http://www.frrouting.org,,Frr} is a fork of @uref{http://www.quagga.net,,Quagga}. @insertcopying diff --git a/doc/git_branches.svg b/doc/git_branches.svg index 3943eeacc8..0c2c96e39e 100644 --- a/doc/git_branches.svg +++ b/doc/git_branches.svg @@ -1,3 +1,720 @@ - -1.0ReleaseBranchMaster(Stable)Develop1.1ReleaseBranchVersion 1.0.a1Version 1.1.a1Version 1.1.a2Version 1.1.b1Patch Email (Patchwork)Github Pull RequestGithub Pull RequestPatch Email (Patchwork)Patch Email (Patchwork)Github Pull RequestGithub Pull RequestGithub Pull RequestPatch Email (Patchwork)Github Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestVersion 1.0.a2Version 1.0.b1Version 1.0.0Version 1.1.0Version 1.1.1Version 1.1.2 + + + + + image/svg+xml + + + + + + + + + + + + + + + 1.0ReleaseBranch + + + + + + + + + + Master(Stable) + + + + + + + + + 1.1ReleaseBranch + Version 1.0.a1 + Version 1.1.a1 + Version 1.1.a2 + + + + + Version 1.1.b1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Patch Email (Patchwork) + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Github Pull Request + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + + + + + + + + + Version 1.0.a2 + Version 1.0.b1 + Version 1.0.0 + Version 1.1.0 + Version 1.1.1 + Version 1.1.2 + + + + + + + + + + + + + + + + + + diff --git a/doc/isisd.8.in b/doc/isisd.8.in index 9ffcbc618d..542c289935 100644 --- a/doc/isisd.8.in +++ b/doc/isisd.8.in @@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B isisd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBisisd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ldpd.8.in b/doc/ldpd.8.in index 1683de46ca..2d68a31a50 100644 --- a/doc/ldpd.8.in +++ b/doc/ldpd.8.in @@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ldpd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBldpd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/main.texi b/doc/main.texi index dfe02e1b5d..706baa25f7 100644 --- a/doc/main.texi +++ b/doc/main.texi @@ -385,7 +385,8 @@ ip protocol rip route-map RM1 Zebra supports a 'FIB push' interface that allows an external component to learn the forwarding information computed by the Frr -routing suite. +routing suite. This is a loadable module that needs to be enabled +at startup as described in @ref{Loadable Module Support}. In Frr, the Routing Information Base (RIB) resides inside zebra. Routing protocols communicate their best routes to zebra, and @@ -440,9 +441,9 @@ independently. @end itemize As mentioned before, zebra encodes routes sent to the FPM in netlink -format by default. The format can be controlled via the -@code{--fpm_format} command-line option to zebra, which currently -takes the values @code{netlink} and @code{protobuf}. +format by default. The format can be controlled via the FPM module's +load-time option to zebra, which currently takes the values @code{netlink} +and @code{protobuf}. The zebra FPM interface uses replace semantics. That is, if a 'route add' message for a prefix is followed by another 'route add' message, diff --git a/doc/nhrpd.8.in b/doc/nhrpd.8.in index c5e4f7e324..09b662ae7c 100644 --- a/doc/nhrpd.8.in +++ b/doc/nhrpd.8.in @@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B nhrpd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBnhrpd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ospf6d.8.in b/doc/ospf6d.8.in index 7f94782bea..02d9d8083d 100644 --- a/doc/ospf6d.8.in +++ b/doc/ospf6d.8.in @@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ospf6d @@ -64,6 +67,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBospf6d\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ospfd.8.in b/doc/ospfd.8.in index 1b86551ca5..6bad777711 100644 --- a/doc/ospfd.8.in +++ b/doc/ospfd.8.in @@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ospfd @@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-a\fR, \fB\-\-apiserver \fR Enable OSPF apiserver. Default is disabled. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBospfd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/overview.texi b/doc/overview.texi index 370ada3f8a..7ecf3d95c3 100644 --- a/doc/overview.texi +++ b/doc/overview.texi @@ -2,7 +2,7 @@ @chapter Overview @cindex Overview - @uref{http://www.freerangerouting.org,,Frr} is a routing software package that + @uref{http://www.frrouting.org,,Frr} is a routing software package that provides TCP/IP based routing services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, IS-IS, BGP-4, and BGP-4+ (@pxref{Supported RFCs}). Frr also supports special BGP Route Reflector and Route Server @@ -275,12 +275,12 @@ November 1995.} The official Frr web-site is located at: -@uref{http://www.freerangerouting.org/} +@uref{http://www.frrouting.org/} and contains further information, as well as links to additional resources. -@uref{http://www.freerangerouting.org/,Frr} is a fork of Quagga, whose +@uref{http://www.frrouting.org/,Frr} is a fork of Quagga, whose web-site is located at: @uref{http://www.quagga.net/}. @@ -298,7 +298,7 @@ comments or suggestions to Frr, please subscribe to: @uref{http://lists.nox.tf/listinfo/frr-users}. -The @uref{http://www.freerangerouting.org/,,Frr} site has further information on +The @uref{http://www.frrouting.org/,,Frr} site has further information on the available mailing lists, see: @uref{http://lists.nox.tf/lists.php} @@ -315,7 +315,7 @@ the available mailing lists, see: If you think you have found a bug, please send a bug report to: -@uref{http://github.com/freerangerouting/frr/issues} +@uref{http://github.com/frrouting/frr/issues} When you send a bug report, please be careful about the points below. @@ -334,4 +334,4 @@ arguments to the configure script please note that too. Bug reports are very important for us to improve the quality of Frr. Frr is still in the development stage, but please don't hesitate to -send a bug report to @uref{http://github.com/freerangerouting/frr/issues}. +send a bug report to @uref{http://github.com/frrouting/frr/issues}. diff --git a/doc/pimd.8.in b/doc/pimd.8.in index 60b844b1e7..3fb060e564 100644 --- a/doc/pimd.8.in +++ b/doc/pimd.8.in @@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B pimd @@ -70,6 +73,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBpimd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .TP diff --git a/doc/ripd.8.in b/doc/ripd.8.in index 6db5ac3649..a84668e6dd 100644 --- a/doc/ripd.8.in +++ b/doc/ripd.8.in @@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ripd @@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBripd\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBripd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ripngd.8.in b/doc/ripngd.8.in index 4c5f2bb114..98039219a7 100644 --- a/doc/ripngd.8.in +++ b/doc/ripngd.8.in @@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ripngd @@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBripd\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBripngd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/snmp.texi b/doc/snmp.texi index c2c889de76..d9656941d0 100644 --- a/doc/snmp.texi +++ b/doc/snmp.texi @@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol (@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the routing protocol MIBs available through it. +Note that SNMP Support needs to be enabled at compile-time and loaded as +module on daemon startup. Refer to @ref{Loadable Module Support} on +the latter. + @menu * Getting and installing an SNMP agent:: * AgentX configuration:: diff --git a/doc/watchfrr.8.in b/doc/watchfrr.8.in index 813f87abd3..82098e1b0d 100644 --- a/doc/watchfrr.8.in +++ b/doc/watchfrr.8.in @@ -108,13 +108,13 @@ Set the logging (LOG_DEBUG), but higher number can be supplied if extra debugging messages are required. .TP -.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number +.BI \-\-min\-restart\-interval " number Set the minimum .I number of seconds to wait between invocations of the daemon restart commands (the default value is "60"). .TP -.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number +.BI \-\-max\-restart\-interval " number Set the maximum .I number of seconds to wait between invocations of the daemon restart commands (the diff --git a/doc/zebra.8.in b/doc/zebra.8.in index 4599a85635..f5b8bd4d80 100644 --- a/doc/zebra.8.in +++ b/doc/zebra.8.in @@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B zebra @@ -86,6 +89,14 @@ maximum before starting zebra. Note that this affects Linux only. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR and \fBfpm\fR modules may be +available for \fBzebra\fR, if the package was built with SNMP and FPM support +respectively. The \fBfpm\fR module takes an additional colon-separated +argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR. +It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 6ec7771ec2..dd07a9c6f5 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -279,6 +279,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), MSG_DONTWAIT, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + + if (bytesread < 0) + zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); + return ISIS_WARNING; } /* @@ -322,10 +326,10 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) addr_len = sizeof (s_addr); /* we can read directly to the stream */ - bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd, - circuit->interface->mtu, 0, - (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); + stream_recvfrom (circuit->rcv_stream, circuit->fd, + circuit->interface->mtu, 0, + (struct sockaddr *) &s_addr, + (socklen_t *) &addr_len); if (s_addr.sll_pkttype == PACKET_OUTGOING) { diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index db46078f20..554fa563ad 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -68,7 +68,6 @@ remove_excess_adjs (struct list *adjs) if (candidate->sys_type < adj->sys_type) { excess = node; - candidate = adj; continue; } if (candidate->sys_type > adj->sys_type) @@ -78,7 +77,6 @@ remove_excess_adjs (struct list *adjs) if (comp > 0) { excess = node; - candidate = adj; continue; } if (comp < 0) @@ -87,7 +85,6 @@ remove_excess_adjs (struct list *adjs) if (candidate->circuit->circuit_id > adj->circuit->circuit_id) { excess = node; - candidate = adj; continue; } @@ -98,7 +95,6 @@ remove_excess_adjs (struct list *adjs) if (comp > 0) { excess = node; - candidate = adj; continue; } } diff --git a/ldpd/interface.c b/ldpd/interface.c index 17b3237b37..b7f473d396 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -49,37 +49,48 @@ iface_compare(struct iface *a, struct iface *b) } struct iface * -if_new(struct kif *kif) +if_new(const char *name) { struct iface *iface; if ((iface = calloc(1, sizeof(*iface))) == NULL) fatal("if_new: calloc"); - strlcpy(iface->name, kif->ifname, sizeof(iface->name)); - LIST_INIT(&iface->addr_list); - if (kif->ifindex) - if_update_info(iface, kif); + strlcpy(iface->name, name, sizeof(iface->name)); /* ipv4 */ iface->ipv4.af = AF_INET; iface->ipv4.iface = iface; iface->ipv4.enabled = 0; - iface->ipv4.state = IF_STA_DOWN; - RB_INIT(&iface->ipv4.adj_tree); /* ipv6 */ iface->ipv6.af = AF_INET6; iface->ipv6.iface = iface; iface->ipv6.enabled = 0; - iface->ipv6.state = IF_STA_DOWN; - RB_INIT(&iface->ipv6.adj_tree); return (iface); } void -if_exit(struct iface *iface) +ldpe_if_init(struct iface *iface) +{ + log_debug("%s: interface %s", __func__, iface->name); + + LIST_INIT(&iface->addr_list); + + /* ipv4 */ + iface->ipv4.iface = iface; + iface->ipv4.state = IF_STA_DOWN; + RB_INIT(&iface->ipv4.adj_tree); + + /* ipv6 */ + iface->ipv6.iface = iface; + iface->ipv6.state = IF_STA_DOWN; + RB_INIT(&iface->ipv6.adj_tree); +} + +void +ldpe_if_exit(struct iface *iface) { struct if_addr *if_addr; diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index ca40636e09..92d865210a 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b) } struct l2vpn_if * -l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; @@ -125,9 +125,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_if_new: calloc"); lif->l2vpn = l2vpn; - strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); - lif->ifindex = kif->ifindex; - lif->flags = kif->flags; + strlcpy(lif->ifname, ifname, sizeof(lif->ifname)); return (lif); } @@ -140,6 +138,14 @@ l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif)); } +void +l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif) +{ + lif->ifindex = kif->ifindex; + lif->flags = kif->flags; + memcpy(lif->mac, kif->mac, sizeof(lif->mac)); +} + void l2vpn_if_update(struct l2vpn_if *lif) { @@ -174,7 +180,7 @@ l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b) } struct l2vpn_pw * -l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; @@ -182,8 +188,7 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_pw_new: calloc"); pw->l2vpn = l2vpn; - strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); - pw->ifindex = kif->ifindex; + strlcpy(pw->ifname, ifname, sizeof(pw->ifname)); return (pw); } @@ -219,6 +224,12 @@ l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); } +void +l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif) +{ + pw->ifindex = kif->ifindex; +} + void l2vpn_pw_init(struct l2vpn_pw *pw) { @@ -463,37 +474,6 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm) } } -void -l2vpn_sync_pws(int af, union ldpd_addr *addr) -{ - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; - struct fec fec; - struct fec_node *fn; - struct fec_nh *fnh; - - RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) - continue; - - l2vpn_pw_fec(pw, &fec); - fn = (struct fec_node *)fec_find(&ft, &fec); - if (fn == NULL) - continue; - fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *) - &pw->lsr_id, 0, 0); - if (fnh == NULL) - continue; - - if (l2vpn_pw_ok(pw, fnh)) - lde_send_change_klabel(fn, fnh); - else - lde_send_delete_klabel(fn, fnh); - } - } -} - void l2vpn_pw_ctl(pid_t pid) { diff --git a/ldpd/lde.c b/ldpd/lde.c index 53fde32fd9..d8a2924b31 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -439,13 +439,14 @@ static int lde_dispatch_parent(struct thread *thread) { static struct ldpd_conf *nconf; - struct iface *niface; + struct iface *iface, *niface; struct tnbr *ntnbr; struct nbr_params *nnbrp; - static struct l2vpn *nl2vpn; - struct l2vpn_if *nlif; - struct l2vpn_pw *npw; + static struct l2vpn *l2vpn, *nl2vpn; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; + struct kif *kif; struct kroute *kr; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -468,6 +469,31 @@ lde_dispatch_parent(struct thread *thread) break; switch (imsg.hdr.type) { + case IMSG_IFSTATUS: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct kif)) + fatalx("IFSTATUS imsg with wrong len"); + kif = imsg.data; + + iface = if_lookup_name(ldeconf, kif->ifname); + if (iface) { + if_update_info(iface, kif); + break; + } + + RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { + lif = l2vpn_if_find(l2vpn, kif->ifname); + if (lif) { + l2vpn_if_update_info(lif, kif); + break; + } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } + } + break; case IMSG_NETWORK_ADD: case IMSG_NETWORK_UPDATE: if (imsg.hdr.len != IMSG_HEADER_SIZE + @@ -540,12 +566,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(niface, imsg.data, sizeof(struct iface)); - LIST_INIT(&niface->addr_list); - RB_INIT(&niface->ipv4.adj_tree); - RB_INIT(&niface->ipv6.adj_tree); - niface->ipv4.iface = niface; - niface->ipv6.iface = niface; - RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: @@ -578,7 +598,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); - nlif->l2vpn = nl2vpn; RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: @@ -586,7 +605,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: @@ -594,11 +612,11 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(ldeconf, nconf); + ldp_clear_config(nconf); nconf = NULL; break; case IMSG_DEBUG_UPDATE: @@ -725,10 +743,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv4.prefixlen == 32) - l2vpn_sync_pws(AF_INET, (union ldpd_addr *) - &fn->fec.u.ipv4.prefix); break; case FEC_TYPE_IPV6: memset(&kr, 0, sizeof(kr)); @@ -743,10 +757,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv6.prefixlen == 128) - l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) - &fn->fec.u.ipv6.prefix); break; case FEC_TYPE_PWID: if (fn->local_label == NO_LABEL || @@ -792,10 +802,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv4.prefixlen == 32) - l2vpn_sync_pws(AF_INET, (union ldpd_addr *) - &fn->fec.u.ipv4.prefix); break; case FEC_TYPE_IPV6: memset(&kr, 0, sizeof(kr)); @@ -810,10 +816,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv6.prefixlen == 128) - l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) - &fn->fec.u.ipv6.prefix); break; case FEC_TYPE_PWID: pw = (struct l2vpn_pw *) fn->data; diff --git a/ldpd/lde.h b/ldpd/lde.h index d1089b44f4..57791cd1b0 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -212,13 +212,15 @@ struct l2vpn *l2vpn_find(struct ldpd_conf *, const char *); void l2vpn_del(struct l2vpn *); void l2vpn_init(struct l2vpn *); void l2vpn_exit(struct l2vpn *); -struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *); +struct l2vpn_if *l2vpn_if_new(struct l2vpn *, const char *); struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *); +void l2vpn_if_update_info(struct l2vpn_if *, struct kif *); void l2vpn_if_update(struct l2vpn_if *); -struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *); +struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *); +void l2vpn_pw_update_info(struct l2vpn_pw *, struct kif *); void l2vpn_pw_init(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *); @@ -231,7 +233,6 @@ void l2vpn_send_pw_status_wcard(struct lde_nbr *, uint32_t, void l2vpn_recv_pw_status(struct lde_nbr *, struct notify_msg *); void l2vpn_recv_pw_status_wcard(struct lde_nbr *, struct notify_msg *); -void l2vpn_sync_pws(int, union ldpd_addr *); void l2vpn_pw_ctl(pid_t); void l2vpn_binding_ctl(pid_t); diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index 0b05e6fbf1..8510a394ec 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -80,6 +80,5 @@ int ldp_vty_debug(struct vty *, struct vty_arg *[]); int ldp_vty_show_debugging(struct vty *, struct vty_arg *[]); void ldp_vty_init(void); -void ldp_vty_if_init(void); #endif /* _LDP_VTY_H_ */ diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index bab5e17368..e4fc7b0054 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -32,29 +32,15 @@ #include "vty.h" #include "ldp_vty.h" -static int interface_config_write(struct vty *); static void ldp_af_iface_config_write(struct vty *, int); static void ldp_af_config_write(struct vty *, int, struct ldpd_conf *, struct ldpd_af_conf *); static void ldp_l2vpn_pw_config_write(struct vty *, struct l2vpn_pw *); -static void ldp_vty_push_node(struct vty *, int, void *); -static void *ldp_vty_get_node(struct vty *, void *, int); static int ldp_vty_get_af(struct vty *); static int ldp_iface_is_configured(struct ldpd_conf *, const char *); static int ldp_vty_nbr_session_holdtime(struct vty *, struct vty_arg *[]); static int ldp_vty_af_session_holdtime(struct vty *, struct vty_arg *[]); -static struct iface *vty_iface; -static struct l2vpn *vty_l2vpn; -static struct l2vpn_pw *vty_pw; - -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 -}; - struct cmd_node ldp_node = { LDP_NODE, @@ -122,26 +108,6 @@ ldp_get_address(const char *str, int *af, union ldpd_addr *addr) return (-1); } -static int -interface_config_write(struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - int write = 0; - - for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), node, ifp)) { - vty_out(vty, "!%s", VTY_NEWLINE); - vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE); - if (ifp->desc) - vty_out(vty, " description %s%s", ifp->desc, - VTY_NEWLINE); - - write++; - } - - return (write); -} - static void ldp_af_iface_config_write(struct vty *vty, int af) { @@ -419,94 +385,6 @@ ldp_l2vpn_config_write(struct vty *vty) return (0); } -void -ldp_vty_push_node(struct vty *vty, int node, void *ptr) -{ - if (global.sighup) { - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - vty_iface = ptr; - break; - case LDP_L2VPN_NODE: - vty_l2vpn = ptr; - break; - case LDP_PSEUDOWIRE_NODE: - vty_pw = ptr; - break; - default: - fatalx("ldp_vty_push_node: unexpected node"); - } - vty->node = node; - return; - } - - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - VTY_PUSH_CONTEXT(node, (struct iface *)ptr); - break; - case LDP_L2VPN_NODE: - VTY_PUSH_CONTEXT(node, (struct l2vpn *)ptr); - break; - case LDP_PSEUDOWIRE_NODE: - VTY_PUSH_CONTEXT_SUB(node, (struct l2vpn_pw *)ptr); - break; - default: - fatalx("ldp_vty_push_node: unexpected node"); - } -} - -void * -ldp_vty_get_node(struct vty *vty, void *parent, int node) -{ - struct iface *iface; - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; - - if (global.sighup) { - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - return (vty_iface); - case LDP_L2VPN_NODE: - return (vty_l2vpn); - case LDP_PSEUDOWIRE_NODE: - return (vty_pw); - default: - fatalx("ldp_vty_get_node: unexpected node"); - } - } - - /* - * Since VTY_GET_CONTEXT() returns a pointer to an element of ldpd_conf, - * we have to find the equivalent element inside vty_conf (which should - * always exist as vty_conf is a duplicate of ldpd_conf). - */ - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - iface = VTY_GET_CONTEXT(iface); - if (iface) - return (if_lookup_name(vty_conf, iface->name)); - break; - case LDP_L2VPN_NODE: - l2vpn = VTY_GET_CONTEXT(l2vpn); - if (l2vpn) - return (l2vpn_find(vty_conf, l2vpn->name)); - break; - case LDP_PSEUDOWIRE_NODE: - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - if (pw) - return (l2vpn_pw_find(parent, pw->ifname)); - break; - default: - fatalx("ldp_vty_get_node: unexpected node"); - } - - return (NULL); -} - static int ldp_vty_get_af(struct vty *vty) { @@ -684,7 +562,7 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) case LDP_IPV4_IFACE_NODE: case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); - iface = ldp_vty_get_node(vty, NULL, vty->node); + iface = VTY_GET_CONTEXT(iface); VTY_CHECK_CONTEXT(iface); ia = iface_af_get(iface, af); @@ -692,6 +570,7 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) ia->hello_holdtime = 0; else ia->hello_holdtime = secs; + ldp_reload(vty_conf); break; default: @@ -784,7 +663,7 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) case LDP_IPV4_IFACE_NODE: case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); - iface = ldp_vty_get_node(vty, NULL, vty->node); + iface = VTY_GET_CONTEXT(iface); VTY_CHECK_CONTEXT(iface); ia = iface_af_get(iface, af); @@ -792,6 +671,7 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) ia->hello_interval = 0; else ia->hello_interval = secs; + ldp_reload(vty_conf); break; default: @@ -853,14 +733,14 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - nbrp = nbr_params_find(vty_conf, lsr_id); - secs = strtol(seconds_str, &ep, 10); if (*ep != '\0' || secs < MIN_KEEPALIVE || secs > MAX_KEEPALIVE) { vty_out(vty, "%% Invalid holdtime%s", VTY_NEWLINE); return (CMD_SUCCESS); } + nbrp = nbr_params_find(vty_conf, lsr_id); + if (disable) { if (nbrp == NULL) return (CMD_SUCCESS); @@ -871,6 +751,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); } else if (nbrp->keepalive == secs) return (CMD_SUCCESS); @@ -935,8 +816,6 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) int af; struct iface *iface; struct iface_af *ia; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -957,7 +836,9 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) ia->enabled = 0; ia->hello_holdtime = 0; ia->hello_interval = 0; + ldp_reload(vty_conf); + return (CMD_SUCCESS); } @@ -968,23 +849,14 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - iface = if_new(&kif); - + iface = if_new(ifname); ia = iface_af_get(iface, af); ia->enabled = 1; RB_INSERT(iface_head, &vty_conf->iface_tree, iface); + QOBJ_REG(iface, iface); + ldp_reload(vty_conf); } else { - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ia = iface_af_get(iface, af); if (!ia->enabled) { ia->enabled = 1; @@ -994,10 +866,10 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) switch (af) { case AF_INET: - ldp_vty_push_node(vty, LDP_IPV4_IFACE_NODE, iface); + VTY_PUSH_CONTEXT(LDP_IPV4_IFACE_NODE, iface); break; case AF_INET6: - ldp_vty_push_node(vty, LDP_IPV6_IFACE_NODE, iface); + VTY_PUSH_CONTEXT(LDP_IPV6_IFACE_NODE, iface); break; default: break; @@ -1065,9 +937,12 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) if (tnbr == NULL) return (CMD_SUCCESS); + QOBJ_UNREG(tnbr); RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr); free(tnbr); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } @@ -1077,6 +952,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) tnbr = tnbr_new(af, &addr); tnbr->flags |= F_TNBR_CONFIGURED; RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr); + QOBJ_REG(tnbr, tnbr); ldp_reload(vty_conf); @@ -1331,6 +1207,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); } else if (nbrp->auth.method == AUTH_MD5SIG && strcmp(nbrp->auth.md5key, password_str) == 0) return (CMD_SUCCESS); @@ -1391,6 +1268,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[]) if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); } nbrp->flags |= F_NBRP_GTSM; @@ -1412,6 +1290,8 @@ int ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) { struct l2vpn *l2vpn; + struct l2vpn_if *lif; + struct l2vpn_pw *pw; const char *name_str; int disable; @@ -1424,23 +1304,34 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) if (l2vpn == NULL) return (CMD_SUCCESS); + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) + QOBJ_UNREG(lif); + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) + QOBJ_UNREG(pw); + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) + QOBJ_UNREG(pw); + QOBJ_UNREG(l2vpn); RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } if (l2vpn) { - ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); + VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); } l2vpn = l2vpn_new(name_str); l2vpn->type = L2VPN_TYPE_VPLS; RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); + QOBJ_REG(l2vpn, l2vpn); + + VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); ldp_reload(vty_conf); - ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); } @@ -1448,16 +1339,13 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); const char *ifname; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - if (disable) memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname)); else @@ -1471,7 +1359,7 @@ ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); char *ep; int mtu; const char *mtu_str; @@ -1486,9 +1374,6 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - if (disable) l2vpn->mtu = DEFAULT_L2VPN_MTU; else @@ -1502,7 +1387,7 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); int pw_type; const char *type_str; int disable; @@ -1515,9 +1400,6 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) else pw_type = PW_TYPE_ETHERNET_TAGGED; - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - if (disable) l2vpn->pw_type = DEFAULT_PW_TYPE; else @@ -1531,27 +1413,26 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); struct l2vpn_if *lif; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); lif = l2vpn_if_find(l2vpn, ifname); if (disable) { if (lif == NULL) return (CMD_SUCCESS); + QOBJ_UNREG(lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } @@ -1563,16 +1444,9 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - lif = l2vpn_if_new(l2vpn, &kif); + lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); + QOBJ_REG(lif, l2vpn_if); ldp_reload(vty_conf); @@ -1582,32 +1456,34 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); struct l2vpn_pw *pw; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); pw = l2vpn_pw_find(l2vpn, ifname); if (disable) { if (pw == NULL) return (CMD_SUCCESS); - RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + QOBJ_UNREG(pw); + if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0) + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + else + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } if (pw) { - ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); + VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); } @@ -1616,20 +1492,14 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - pw = l2vpn_pw_new(l2vpn, &kif); + pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + QOBJ_REG(pw, l2vpn_pw); + + VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); ldp_reload(vty_conf); - ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); } @@ -1637,19 +1507,13 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); const char *preference_str; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; preference_str = vty_get_arg_value(args, "preference"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->flags |= F_PW_CWORD_CONF; else { @@ -1667,8 +1531,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); int af; union ldpd_addr addr; const char *addr_str; @@ -1683,11 +1546,6 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) { pw->af = AF_UNSPEC; memset(&pw->addr, 0, sizeof(pw->addr)); @@ -1706,8 +1564,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); struct in_addr lsr_id; const char *lsr_id_str; int disable; @@ -1721,11 +1578,6 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->lsr_id.s_addr = INADDR_ANY; else @@ -1739,8 +1591,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); char *ep; uint32_t pwid; const char *pwid_str; @@ -1755,11 +1606,6 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->pwid = 0; else @@ -1773,17 +1619,11 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->flags |= F_PW_STATUSTLV_CONF; else @@ -1794,41 +1634,25 @@ ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } -void -ldp_vty_if_init(void) -{ - /* Install interface node. */ - install_node (&interface_node, interface_config_write); - if_cmd_init (); -} - struct iface * iface_new_api(struct ldpd_conf *conf, const char *name) { const char *ifname = name; struct iface *iface; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return NULL; - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - iface = if_new(&kif); + iface = if_new(name); RB_INSERT(iface_head, &conf->iface_tree, iface); + QOBJ_REG(iface, iface); return (iface); } void iface_del_api(struct ldpd_conf *conf, struct iface *iface) { + QOBJ_UNREG(iface); RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } @@ -1847,12 +1671,14 @@ tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr) tnbr = tnbr_new(af, addr); tnbr->flags |= F_TNBR_CONFIGURED; RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr); + QOBJ_REG(tnbr, tnbr); return (tnbr); } void tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr) { + QOBJ_UNREG(tnbr); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1867,12 +1693,14 @@ nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id) nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); return (nbrp); } void nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp) { + QOBJ_UNREG(nbrp); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } @@ -1888,6 +1716,7 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name) l2vpn = l2vpn_new(name); l2vpn->type = L2VPN_TYPE_VPLS; RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn); + QOBJ_REG(l2vpn, l2vpn); return (l2vpn); } @@ -1898,17 +1727,21 @@ l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn) struct l2vpn_pw *pw; while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { + QOBJ_UNREG(lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { + QOBJ_UNREG(pw); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); } while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { + QOBJ_UNREG(pw); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } + QOBJ_UNREG(l2vpn); RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); free(l2vpn); } @@ -1918,28 +1751,20 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return (NULL); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - lif = l2vpn_if_new(l2vpn, &kif); + lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); + QOBJ_REG(lif, l2vpn_if); return (lif); } void l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif) { + QOBJ_UNREG(lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } @@ -1949,29 +1774,21 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return (NULL); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - pw = l2vpn_pw_new(l2vpn, &kif); + pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + QOBJ_REG(pw, l2vpn_pw); return (pw); } void l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw) { + QOBJ_UNREG(pw); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index dfd5af9748..a149b7fe35 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -1049,7 +1049,7 @@ show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) static int show_lib_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) { - struct ctl_rt *rt; + struct ctl_rt *rt = NULL; char dstnet[BUFSIZ]; static int upstream, downstream; size_t buflen; @@ -1172,7 +1172,7 @@ static int show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params, json_object *json) { - struct ctl_rt *rt; + struct ctl_rt *rt = NULL; char dstnet[BUFSIZ]; static json_object *json_lib_entry; static json_object *json_adv_labels; diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index c41a0dbd91..702b5c5eaa 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -180,7 +180,7 @@ kif_redistribute(const char *ifname) continue; ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { ifc2kaddr(ifp, ifc, &ka); @@ -222,7 +222,7 @@ ldp_interface_add(int command, struct zclient *zclient, zebra_size_t length, ifp->ifindex, ifp->mtu); ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); return (0); } @@ -270,7 +270,7 @@ ldp_interface_status_change(int command, struct zclient *zclient, debug_zebra_in("interface %s state update", ifp->name); ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); link_new = (ifp->flags & IFF_UP) && (ifp->flags & IFF_RUNNING); if (link_new) { diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 3023d94469..9729499e28 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -56,6 +56,7 @@ static int main_imsg_send_config(struct ldpd_conf *); static void ldp_config_normalize(struct ldpd_conf *); static void ldp_config_reset_main(struct ldpd_conf *); static void ldp_config_reset_af(struct ldpd_conf *, int); +static void ldp_config_reset_l2vpns(struct ldpd_conf *); static void merge_global(struct ldpd_conf *, struct ldpd_conf *); static void merge_af(int, struct ldpd_af_conf *, struct ldpd_af_conf *); @@ -131,9 +132,8 @@ sighup(void) log_info("SIGHUP received"); /* reset vty_conf */ - ldp_clear_config(vty_conf); - vty_conf = config_new_empty(); ldp_config_reset_main(vty_conf); + ldp_config_reset_l2vpns(vty_conf); /* read configuration file without applying any changes */ global.sighup = 1; @@ -338,20 +338,20 @@ main(int argc, char *argv[]) vrf_init(); access_list_init(); ldp_vty_init(); - ldp_vty_if_init(); ldp_zebra_init(master); /* create base configuration with sane defaults */ ldpd_conf = config_new_empty(); ldp_config_reset_main(ldpd_conf); - QOBJ_REG(ldpd_conf, ldpd_conf); /* * Create vty_conf as a duplicate of the main configuration. All * configuration requests (e.g. CLI) act on vty_conf and then call * ldp_reload() to merge the changes into ldpd_conf. */ - vty_conf = ldp_dup_config(ldpd_conf); + vty_conf = config_new_empty(); + ldp_config_reset_main(vty_conf); + QOBJ_REG(vty_conf, ldpd_conf); /* read configuration file and daemonize */ frr_config_fork(); @@ -416,7 +416,11 @@ ldpd_shutdown(void) close(iev_lde->ibuf.fd); config_clear(ldpd_conf); - QOBJ_UNREG(ldpd_conf); + + ldp_config_reset_main(vty_conf); + ldp_config_reset_l2vpns(vty_conf); + QOBJ_UNREG(vty_conf); + free(vty_conf); log_debug("waiting for children to terminate"); do { @@ -993,16 +997,16 @@ ldp_reload(struct ldpd_conf *xconf) merge_config(ldpd_conf, xconf); - vty_conf = ldp_dup_config(ldpd_conf); - return (0); } static void ldp_config_normalize(struct ldpd_conf *xconf) { + struct iface *iface, *itmp; + struct nbr_params *nbrp, *ntmp; struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + struct l2vpn_pw *pw, *ptmp; if (!(xconf->flags & F_LDPD_ENABLED)) ldp_config_reset_main(xconf); @@ -1011,22 +1015,51 @@ ldp_config_normalize(struct ldpd_conf *xconf) ldp_config_reset_af(xconf, AF_INET); if (!(xconf->ipv6.flags & F_LDPD_AF_ENABLED)) ldp_config_reset_af(xconf, AF_INET6); + + RB_FOREACH_SAFE(iface, iface_head, &xconf->iface_tree, itmp) { + if (iface->ipv4.enabled || iface->ipv6.enabled) + continue; + + QOBJ_UNREG(iface); + RB_REMOVE(iface_head, &vty_conf->iface_tree, iface); + free(iface); + } + + RB_FOREACH_SAFE(nbrp, nbrp_head, &xconf->nbrp_tree, ntmp) { + if (nbrp->flags & (F_NBRP_KEEPALIVE|F_NBRP_GTSM)) + continue; + if (nbrp->auth.method != AUTH_NONE) + continue; + + QOBJ_UNREG(nbrp); + RB_REMOVE(nbrp_head, &vty_conf->nbrp_tree, nbrp); + free(nbrp); + } } RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - if (pw->flags & F_PW_STATIC_NBR_ADDR) - continue; + RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) { + if (!(pw->flags & F_PW_STATIC_NBR_ADDR)) { + pw->af = AF_INET; + pw->addr.v4 = pw->lsr_id; + } - pw->af = AF_INET; - pw->addr.v4 = pw->lsr_id; + if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) + continue; + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); } - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { - if (pw->flags & F_PW_STATIC_NBR_ADDR) - continue; + RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, + ptmp) { + if (!(pw->flags & F_PW_STATIC_NBR_ADDR)) { + pw->af = AF_INET; + pw->addr.v4 = pw->lsr_id; + } - pw->af = AF_INET; - pw->addr.v4 = pw->lsr_id; + if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0) + continue; + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw); } } } @@ -1038,11 +1071,13 @@ ldp_config_reset_main(struct ldpd_conf *conf) struct nbr_params *nbrp; while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) { + QOBJ_UNREG(iface); RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) { + QOBJ_UNREG(nbrp); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } @@ -1075,6 +1110,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af) if (tnbr->af != af) continue; + QOBJ_UNREG(tnbr); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1089,70 +1125,33 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af) af_conf->flags = 0; } -struct ldpd_conf * -ldp_dup_config(struct ldpd_conf *conf) +static void +ldp_config_reset_l2vpns(struct ldpd_conf *conf) { - struct ldpd_conf *xconf; - struct iface *iface, *xi; - struct tnbr *tnbr, *xt; - struct nbr_params *nbrp, *xn; - struct l2vpn *l2vpn, *xl; - struct l2vpn_if *lif, *xf; - struct l2vpn_pw *pw, *xp; + struct l2vpn *l2vpn; + struct l2vpn_if *lif; + struct l2vpn_pw *pw; -#define COPY(a, b) do { \ - a = calloc(1, sizeof(*a)); \ - if (a == NULL) \ - fatal(__func__); \ - *a = *b; \ - } while (0) - - COPY(xconf, conf); - RB_INIT(&xconf->iface_tree); - RB_INIT(&xconf->tnbr_tree); - RB_INIT(&xconf->nbrp_tree); - RB_INIT(&xconf->l2vpn_tree); - - RB_FOREACH(iface, iface_head, &conf->iface_tree) { - COPY(xi, iface); - xi->ipv4.iface = xi; - xi->ipv6.iface = xi; - RB_INSERT(iface_head, &xconf->iface_tree, xi); - } - RB_FOREACH(tnbr, tnbr_head, &conf->tnbr_tree) { - COPY(xt, tnbr); - RB_INSERT(tnbr_head, &xconf->tnbr_tree, xt); - } - RB_FOREACH(nbrp, nbrp_head, &conf->nbrp_tree) { - COPY(xn, nbrp); - RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn); - } - RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) { - COPY(xl, l2vpn); - RB_INIT(&xl->if_tree); - RB_INIT(&xl->pw_tree); - RB_INIT(&xl->pw_inactive_tree); - RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl); - - RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) { - COPY(xf, lif); - xf->l2vpn = xl; - RB_INSERT(l2vpn_if_head, &xl->if_tree, xf); + while ((l2vpn = RB_ROOT(&conf->l2vpn_tree)) != NULL) { + while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { + QOBJ_UNREG(lif); + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); + free(lif); } - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - COPY(xp, pw); - xp->l2vpn = xl; - RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp); + while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { + QOBJ_UNREG(pw); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); + free(pw); } - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { - COPY(xp, pw); - xp->l2vpn = xl; - RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp); + while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { + QOBJ_UNREG(pw); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + free(pw); } + QOBJ_UNREG(l2vpn); + RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); + free(l2vpn); } -#undef COPY - - return (xconf); } void @@ -1183,6 +1182,13 @@ ldp_clear_config(struct ldpd_conf *xconf) free(xconf); } +#define COPY(a, b) do { \ + a = malloc(sizeof(*a)); \ + if (a == NULL) \ + fatal(__func__); \ + *a = *b; \ + } while (0) + void merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) { @@ -1193,7 +1199,6 @@ merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) merge_tnbrs(conf, xconf); merge_nbrps(conf, xconf); merge_l2vpns(conf, xconf); - free(xconf); } static void @@ -1337,31 +1342,34 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) { /* find deleted interfaces */ if ((xi = if_lookup_name(xconf, iface->name)) == NULL) { - RB_REMOVE(iface_head, &conf->iface_tree, iface); - switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: - if_exit(iface); + ldpe_if_exit(iface); break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_UNREG (iface); break; } + RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } } RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) { /* find new interfaces */ if ((iface = if_lookup_name(conf, xi->name)) == NULL) { - RB_REMOVE(iface_head, &xconf->iface_tree, xi); - RB_INSERT(iface_head, &conf->iface_tree, xi); + COPY(iface, xi); + RB_INSERT(iface_head, &conf->iface_tree, iface); - if (ldpd_process == PROC_MAIN) { - QOBJ_REG (xi, iface); + switch (ldpd_process) { + case PROC_LDP_ENGINE: + ldpe_if_init(iface); + break; + case PROC_LDE_ENGINE: + break; + case PROC_MAIN: /* resend addresses to activate new interfaces */ - kif_redistribute(xi->name); + kif_redistribute(iface->name); + break; } continue; } @@ -1369,8 +1377,6 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* update existing interfaces */ merge_iface_af(&iface->ipv4, &xi->ipv4); merge_iface_af(&iface->ipv6, &xi->ipv6); - RB_REMOVE(iface_head, &xconf->iface_tree, xi); - free(xi); } } @@ -1398,17 +1404,13 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* find deleted tnbrs */ if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) { switch (ldpd_process) { - case PROC_LDE_ENGINE: - RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); - free(tnbr); - break; case PROC_LDP_ENGINE: tnbr->flags &= ~F_TNBR_CONFIGURED; tnbr_check(conf, tnbr); break; + case PROC_LDE_ENGINE: case PROC_MAIN: RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); - QOBJ_UNREG (tnbr); free(tnbr); break; } @@ -1417,17 +1419,15 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) { /* find new tnbrs */ if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) { - RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); - RB_INSERT(tnbr_head, &conf->tnbr_tree, xt); + COPY(tnbr, xt); + RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr); switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: - tnbr_update(xt); + tnbr_update(tnbr); break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_REG (xt, tnbr); break; } continue; @@ -1436,8 +1436,6 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* update existing tnbrs */ if (!(tnbr->flags & F_TNBR_CONFIGURED)) tnbr->flags |= F_TNBR_CONFIGURED; - RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); - free(xt); } } @@ -1452,8 +1450,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* find deleted nbrps */ if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) { switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr); if (nbr) { @@ -1471,8 +1467,8 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) nbr_establish_connection(nbr); } break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_UNREG (nbrp); break; } RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); @@ -1482,33 +1478,31 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) { /* find new nbrps */ if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) { - RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); - RB_INSERT(nbrp_head, &conf->nbrp_tree, xn); + COPY(nbrp, xn); + RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp); switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: - nbr = nbr_find_ldpid(xn->lsr_id.s_addr); + nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr); if (nbr) { session_shutdown(nbr, S_SHUTDOWN, 0, 0); - nbr->auth.method = xn->auth.method; + nbr->auth.method = nbrp->auth.method; #ifdef __OpenBSD__ - if (pfkey_establish(nbr, xn) == -1) + if (pfkey_establish(nbr, nbrp) == -1) fatalx("pfkey setup failed"); #else sock_set_md5sig( (ldp_af_global_get(&global, nbr->af))->ldp_session_socket, nbr->af, &nbr->raddr, - xn->auth.md5key); + nbrp->auth.md5key); #endif if (nbr_session_active_role(nbr)) nbr_establish_connection(nbr); } break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_REG (xn, nbr_params); break; } continue; @@ -1553,8 +1547,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) nbr_establish_connection(nbr); } } - RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); - free(xn); } } @@ -1562,14 +1554,10 @@ static void merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) { struct l2vpn *l2vpn, *ltmp, *xl; - struct l2vpn_if *lif; - struct l2vpn_pw *pw; RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) { /* find deleted l2vpns */ if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) { - RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); - switch (ldpd_process) { case PROC_LDE_ENGINE: l2vpn_exit(l2vpn); @@ -1578,58 +1566,35 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) ldpe_l2vpn_exit(l2vpn); break; case PROC_MAIN: - RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) - QOBJ_UNREG (lif); - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) - QOBJ_UNREG (pw); - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) - QOBJ_UNREG (pw); - QOBJ_UNREG (l2vpn); break; } + RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); } } RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) { - struct l2vpn_pw *xp, *ptmp; - - /* check if the pseudowires should be enabled or disabled */ - RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { - if (xp->lsr_id.s_addr != INADDR_ANY && xp->pwid != 0) - continue; - RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - } - RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { - if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0) - continue; - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp); - } - /* find new l2vpns */ if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { - RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); - RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl); + COPY(l2vpn, xl); + RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn); + RB_INIT(&l2vpn->if_tree); + RB_INIT(&l2vpn->pw_tree); + RB_INIT(&l2vpn->pw_inactive_tree); switch (ldpd_process) { case PROC_LDE_ENGINE: - l2vpn_init(xl); + l2vpn_init(l2vpn); break; case PROC_LDP_ENGINE: - ldpe_l2vpn_init(xl); + ldpe_l2vpn_init(l2vpn); break; case PROC_MAIN: - QOBJ_REG (xl, l2vpn); break; } - continue; } /* update existing l2vpns */ merge_l2vpn(conf, l2vpn, xl); - RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); - free(xl); } } @@ -1649,8 +1614,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) { /* find deleted interfaces */ if ((xf = l2vpn_if_find(xl, lif->ifname)) == NULL) { - if (ldpd_process == PROC_MAIN) - QOBJ_UNREG (lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } @@ -1658,16 +1621,19 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) { /* find new interfaces */ if ((lif = l2vpn_if_find(l2vpn, xf->ifname)) == NULL) { - RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); - RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); - xf->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) - QOBJ_REG (xf, l2vpn_if); - continue; - } + COPY(lif, xf); + RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); + lif->l2vpn = l2vpn; - RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); - free(xf); + switch (ldpd_process) { + case PROC_LDP_ENGINE: + case PROC_LDE_ENGINE: + break; + case PROC_MAIN: + kif_redistribute(lif->ifname); + break; + } + } } /* merge active pseudowires */ @@ -1682,7 +1648,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) ldpe_l2vpn_pw_exit(pw); break; case PROC_MAIN: - QOBJ_UNREG (pw); break; } @@ -1693,19 +1658,19 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { /* find new active pseudowires */ if ((pw = l2vpn_pw_find_active(l2vpn, xp->ifname)) == NULL) { - RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp); - xp->l2vpn = l2vpn; + COPY(pw, xp); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw); + pw->l2vpn = l2vpn; switch (ldpd_process) { case PROC_LDE_ENGINE: - l2vpn_pw_init(xp); + l2vpn_pw_init(pw); break; case PROC_LDP_ENGINE: - ldpe_l2vpn_pw_init(xp); + ldpe_l2vpn_pw_init(pw); break; case PROC_MAIN: - QOBJ_REG (xp, l2vpn_pw); + kif_redistribute(pw->ifname); break; } continue; @@ -1772,9 +1737,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) l2vpn->pw_type = previous_pw_type; l2vpn->mtu = previous_mtu; } - - RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - free(xp); } /* merge inactive pseudowires */ @@ -1782,19 +1744,24 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) /* find deleted inactive pseudowires */ if ((xp = l2vpn_pw_find_inactive(xl, pw->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); - if (ldpd_process == PROC_MAIN) - QOBJ_UNREG (pw); free(pw); } } RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { /* find new inactive pseudowires */ if ((pw = l2vpn_pw_find_inactive(l2vpn, xp->ifname)) == NULL) { - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); - xp->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) - QOBJ_REG (xp, l2vpn_pw); + COPY(pw, xp); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + pw->l2vpn = l2vpn; + + switch (ldpd_process) { + case PROC_LDE_ENGINE: + case PROC_LDP_ENGINE: + break; + case PROC_MAIN: + kif_redistribute(pw->ifname); + break; + } continue; } @@ -1806,9 +1773,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname)); pw->ifindex = xp->ifindex; pw->flags = xp->flags; - - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - free(xp); } l2vpn->pw_type = xl->pw_type; @@ -1852,5 +1816,6 @@ config_clear(struct ldpd_conf *conf) xconf->trans_pref = conf->trans_pref; xconf->flags = conf->flags; merge_config(conf, xconf); + free(xconf); free(conf); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index a0474a5a2d..d2fc5aa3af 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -706,7 +706,6 @@ struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int); int ldp_is_dual_stack(struct ldpd_conf *); in_addr_t ldp_rtr_id_get(struct ldpd_conf *); int ldp_reload(struct ldpd_conf *); -struct ldpd_conf *ldp_dup_config(struct ldpd_conf *); void ldp_clear_config(struct ldpd_conf *); void merge_config(struct ldpd_conf *, struct ldpd_conf *); struct ldpd_conf *config_new_empty(void); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 96a7052ec6..1bec3d2a95 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -256,8 +256,8 @@ ldpe_dispatch_main(struct thread *thread) struct tnbr *ntnbr; struct nbr_params *nnbrp; static struct l2vpn *l2vpn, *nl2vpn; - struct l2vpn_if *lif = NULL, *nlif; - struct l2vpn_pw *npw; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -305,12 +305,15 @@ ldpe_dispatch_main(struct thread *thread) RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) { lif = l2vpn_if_find(l2vpn, kif->ifname); if (lif) { - lif->flags = kif->flags; - memcpy(lif->mac, kif->mac, - sizeof(lif->mac)); + l2vpn_if_update_info(lif, kif); l2vpn_if_update(lif); break; } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } } break; case IMSG_NEWADDR: @@ -449,12 +452,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(niface, imsg.data, sizeof(struct iface)); - LIST_INIT(&niface->addr_list); - RB_INIT(&niface->ipv4.adj_tree); - RB_INIT(&niface->ipv6.adj_tree); - niface->ipv4.iface = niface; - niface->ipv6.iface = niface; - RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: @@ -487,7 +484,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); - nlif->l2vpn = nl2vpn; RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: @@ -495,7 +491,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: @@ -503,11 +498,11 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(leconf, nconf); + ldp_clear_config(nconf); nconf = NULL; global.conf_seqnum++; break; diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index 8215d08407..a3f41a8b9f 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -214,8 +214,9 @@ void mapping_list_add(struct mapping_head *, struct map *); void mapping_list_clr(struct mapping_head *); /* interface.c */ -struct iface *if_new(struct kif *); -void if_exit(struct iface *); +struct iface *if_new(const char *); +void ldpe_if_init(struct iface *); +void ldpe_if_exit(struct iface *); struct iface *if_lookup(struct ldpd_conf *, unsigned short); struct iface *if_lookup_name(struct ldpd_conf *, const char *); void if_update_info(struct iface *, struct kif *); diff --git a/lib/Makefile.am b/lib/Makefile.am index 1a8c7af42b..75947e6146 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,7 +20,7 @@ libfrr_la_SOURCES = \ command.c \ sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \ filter.c routemap.c distribute.c stream.c log.c plist.c \ - zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \ + zclient.c sockopt.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \ ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \ imsg-buffer.c imsg.c skiplist.c \ @@ -31,13 +31,30 @@ libfrr_la_SOURCES = \ spf_backoff.c \ libfrr.c \ strlcpy.c \ - strlcat.c + strlcat.c \ + module.c \ + hook.c \ + # end BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h libfrr_la_LIBADD = @LIBCAP@ +if SNMP +lib_LTLIBRARIES += libfrrsnmp.la +endif + +libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +libfrrsnmp_la_LDFLAGS = -version-info 0:0:0 +libfrrsnmp_la_LIBADD = libfrr.la $(SNMP_LIBS) +libfrrsnmp_la_SOURCES = \ + agentx.c \ + smux.c \ + snmp.c \ + #end + pkginclude_HEADERS = \ + frratomic.h \ buffer.h checksum.h filter.h getopt.h hash.h \ if.h linklist.h log.h \ graph.h command_match.h \ @@ -54,6 +71,8 @@ pkginclude_HEADERS = \ monotime.h \ spf_backoff.h \ srcdest_table.h \ + module.h \ + hook.h \ libfrr.h \ # end diff --git a/lib/agentx.c b/lib/agentx.c index 4175e7ba92..11d5c9385d 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -21,7 +21,7 @@ #include -#if defined HAVE_SNMP && defined SNMP_AGENTX +#ifdef SNMP_AGENTX #include #include #include @@ -315,4 +315,4 @@ smux_trap (struct variable *vp, size_t vp_len, return 1; } -#endif /* HAVE_SNMP */ +#endif /* SNMP_AGENTX */ diff --git a/lib/command.c b/lib/command.c index bfff581d9b..993d6f9055 100644 --- a/lib/command.c +++ b/lib/command.c @@ -41,6 +41,7 @@ #include "vrf.h" #include "command_match.h" #include "qobj.h" +#include "defaults.h" DEFINE_MTYPE( LIB, HOST, "Host config") DEFINE_MTYPE( LIB, STRVEC, "String vector") @@ -1536,6 +1537,23 @@ DEFUN (show_version, return CMD_SUCCESS; } +/* "Set" version ... ignore version tags */ +DEFUN (frr_version_defaults, + frr_version_defaults_cmd, + "frr LINE...", + "FRRouting global parameters\n" + "version configuration was written by\n" + "set of configuration defaults used\n" + "version string\n") +{ + if (vty->type == VTY_TERM || vty->type == VTY_SHELL) + /* only print this when the user tries to do run it */ + vty_out (vty, "%% NOTE: This command currently does nothing.%s" + "%% It is written to the configuration for future reference.%s", + VTY_NEWLINE, VTY_NEWLINE); + return CMD_SUCCESS; +} + /* Help display function for all node. */ DEFUN (config_help, config_help_cmd, @@ -1636,6 +1654,37 @@ DEFUN (show_commandtree, return cmd_list_cmds (vty, argc == 3); } +static void +vty_write_config (struct vty *vty) +{ + size_t i; + struct cmd_node *node; + + if (vty->type == VTY_TERM) + { + vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE, + VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + } + + vty_out (vty, "frr version %s%s", FRR_VER_SHORT, VTY_NEWLINE); + vty_out (vty, "frr defaults %s%s", DFLT_NAME, VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + + for (i = 0; i < vector_active (cmdvec); i++) + if ((node = vector_slot (cmdvec, i)) && node->func + && (node->vtysh || vty->type != VTY_SHELL)) + { + if ((*node->func) (vty)) + vty_out (vty, "!%s", VTY_NEWLINE); + } + + if (vty->type == VTY_TERM) + { + vty_out (vty, "end%s",VTY_NEWLINE); + } +} + /* Write current configuration into file. */ DEFUN (config_write, @@ -1647,9 +1696,7 @@ DEFUN (config_write, "Write configuration to terminal\n") { int idx_type = 1; - unsigned int i; int fd, dirfd; - struct cmd_node *node; char *config_file, *slash; char *config_file_tmp = NULL; char *config_file_sav = NULL; @@ -1660,32 +1707,10 @@ DEFUN (config_write, // if command was 'write terminal' or 'show running-config' if (argc == 2 && (!strcmp(argv[idx_type]->text, "terminal") || !strcmp(argv[0]->text, "show"))) - { - if (vty->type == VTY_SHELL_SERV) - { - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh) - { - if ((*node->func) (vty)) - vty_out (vty, "!%s", VTY_NEWLINE); - } - } - else - { - vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE, - VTY_NEWLINE); - vty_out (vty, "!%s", VTY_NEWLINE); - - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func) - { - if ((*node->func) (vty)) - vty_out (vty, "!%s", VTY_NEWLINE); - } - vty_out (vty, "end%s",VTY_NEWLINE); - } - return CMD_SUCCESS; - } + { + vty_write_config (vty); + return CMD_SUCCESS; + } if (host.noconfig) return CMD_SUCCESS; @@ -1749,13 +1774,7 @@ DEFUN (config_write, vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! "); vty_time_print (file_vty, 1); vty_out (file_vty, "!\n"); - - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func) - { - if ((*node->func) (file_vty)) - vty_out (file_vty, "!\n"); - } + vty_write_config (file_vty); vty_close (file_vty); if (stat(config_file, &conf_stat) >= 0) @@ -1817,7 +1836,9 @@ DEFUN (copy_runningconf_startupconf, "Copy running config to... \n" "Copy running config to startup config (same as write file)\n") { - return config_write (self, vty, argc, argv); + if (!host.noconfig) + vty_write_config (vty); + return CMD_SUCCESS; } /** -- **/ @@ -2694,6 +2715,7 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &hostname_cmd); install_element (CONFIG_NODE, &no_hostname_cmd); + install_element (CONFIG_NODE, &frr_version_defaults_cmd); if (terminal > 0) { diff --git a/lib/frratomic.h b/lib/frratomic.h new file mode 100644 index 0000000000..183790aeb0 --- /dev/null +++ b/lib/frratomic.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FRRATOMIC_H +#define _FRRATOMIC_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef FRR_AUTOCONF_ATOMIC +#error autoconf checks for atomic functions were not properly run +#endif + +/* ISO C11 */ +#ifdef HAVE_STDATOMIC_H +#include + +/* gcc 4.7 and newer */ +#elif defined(HAVE___ATOMIC) + +#define _Atomic volatile + +#define memory_order_relaxed __ATOMIC_RELAXED +#define memory_order_consume __ATOMIC_CONSUME +#define memory_order_acquire __ATOMIC_ACQUIRE +#define memory_order_release __ATOMIC_RELEASE +#define memory_order_acq_rel __ATOMIC_ACQ_REL +#define memory_order_seq_cst __ATOMIC_SEQ_CST + +#define atomic_load_explicit __atomic_load_n +#define atomic_store_explicit __atomic_store_n +#define atomic_exchange_explicit __atomic_exchange_n +#define atomic_fetch_add_explicit __atomic_fetch_add +#define atomic_fetch_sub_explicit __atomic_fetch_sub + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ + __atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2) + +/* gcc 4.1 and newer, + * clang 3.3 (possibly older) + * + * __sync_swap isn't in gcc's documentation, but clang has it + * + * note __sync_synchronize() + */ +#elif defined(HAVE___SYNC) + +#define _Atomic volatile + +#define memory_order_relaxed 0 +#define memory_order_consume 0 +#define memory_order_acquire 0 +#define memory_order_release 0 +#define memory_order_acq_rel 0 +#define memory_order_seq_cst 0 + +#define atomic_load_explicit(ptr, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \ + __sync_synchronize(); rval; }) +#define atomic_store_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + *(ptr) = (val); \ + __sync_synchronize(); (void)0; }) +#ifdef HAVE___SYNC_SWAP +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_swap((ptr, val), 0); \ + __sync_synchronize(); rval; }) +#else /* !HAVE___SYNC_SWAP */ +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \ + __sync_synchronize(); \ + typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \ + do { \ + old1 = old2; \ + old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \ + } while (old1 != old2); \ + __sync_synchronize(); \ + old2; \ + }) +#endif /* !HAVE___SYNC_SWAP */ +#define atomic_fetch_add_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \ + __sync_synchronize(); rval; }) +#define atomic_fetch_sub_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \ + __sync_synchronize(); rval; }) + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ + ({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \ + typeof(desire) _desire = (desire); \ + __sync_synchronize(); \ + typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \ + __sync_synchronize(); \ + bool ret = (rval == *_expect); *_expect = rval; ret; }) + +#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */ +#error no atomic functions... +#endif + +#endif /* _FRRATOMIC_H */ diff --git a/lib/hook.c b/lib/hook.c new file mode 100644 index 0000000000..04d803cd8d --- /dev/null +++ b/lib/hook.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "memory.h" +#include "hook.h" + +DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry") + +void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, + struct frrmod_runtime *module, const char *funcname) +{ + struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)); + he->hookfn = funcptr; + he->hookarg = arg; + he->has_arg = has_arg; + he->module = module; + he->fnname = funcname; + + he->next = hook->entries; + hook->entries = he; +} + +void _hook_unregister(struct hook *hook, void *funcptr, + void *arg, bool has_arg) +{ + struct hookent *he, **prev; + + for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next) + if (he->hookfn == funcptr && he->hookarg == arg + && he->has_arg == has_arg) + { + *prev = he->next; + XFREE(MTYPE_HOOK_ENTRY, he); + break; + } +} + diff --git a/lib/hook.h b/lib/hook.h new file mode 100644 index 0000000000..0cb7ab5c7d --- /dev/null +++ b/lib/hook.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _FRR_HOOK_H +#define _FRR_HOOK_H + +#include + +#include "module.h" +#include "memory.h" + +/* type-safe subscribable hook points + * + * where "type-safe" applies to the function pointers used for subscriptions + * + * overall usage: + * - to create a hook: + * + * mydaemon.h: + * #include "hook.h" + * DECLARE_HOOK (some_update_event, (struct eventinfo *info), (info)) + * + * mydaemon.c: + * DEFINE_HOOK (some_update_event, (struct eventinfo *info), (info)) + * ... + * hook_call (some_update_event, info) + * + * Note: the second and third macro args must be the hook function's + * parameter list, with the same names for each parameter. The second + * macro arg is with types (used for defining things), the third arg is + * just the names (used for passing along parameters). + * + * Do not use parameter names starting with "hook", these can collide with + * names used by the hook code itself. + * + * The return value is always "int" for now; hook_call will sum up the + * return values from each registered user. Default is 0. + * + * There are no pre-defined semantics for the value, in most cases it is + * ignored. For success/failure indication, 0 should be success, and + * handlers should make sure to only return 0 or 1 (not -1 or other values). + * + * + * - to use a hook / create a handler: + * + * #include "mydaemon.h" + * int event_handler (struct eventinfo *info) { ... } + * hook_register (some_update_event, event_handler); + * + * or, if you need an argument to be passed along (addonptr will be added + * as first argument when calling the handler): + * + * #include "mydaemon.h" + * int event_handler (void *addonptr, struct eventinfo *info) { ... } + * hook_register_arg (some_update_event, event_handler, addonptr); + * + * (addonptr isn't typesafe, but that should be manageable.) + */ + +/* TODO: + * - hook_unregister_all_module() + * - introspection / CLI / debug + * - testcases ;) + * + * For loadable modules, the idea is that hooks could be automatically + * unregistered when a module is unloaded. + * + * It's also possible to add a constructor (MTYPE style) to DEFINE_HOOK, + * which would make it possible for the CLI to show all hooks and all + * registered handlers. + */ + +struct hookent { + struct hookent *next; + void *hookfn; /* actually a function pointer */ + void *hookarg; + bool has_arg; + struct frrmod_runtime *module; + const char *fnname; +}; + +struct hook { + const char *name; + struct hookent *entries; +}; + +/* subscribe/add callback function to a hook + * + * always use hook_register(), which uses the static inline helper from + * DECLARE_HOOK in order to get type safety + */ +extern void _hook_register(struct hook *hook, void *funcptr, void *arg, + bool has_arg, struct frrmod_runtime *module, + const char *funcname); +#define hook_register(hookname, func) \ + _hook_register(&_hook_ ## hookname, \ + _hook_typecheck_ ## hookname (func), \ + NULL, false, THIS_MODULE, #func) +#define hook_register_arg(hookname, func, arg) \ + _hook_register(&_hook_ ## hookname, \ + _hook_typecheck_arg_ ## hookname (func), \ + arg, true, THIS_MODULE, #func) + +extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, + bool has_arg); +#define hook_unregister(hookname, func) \ + _hook_unregister(&_hook_ ## hookname, \ + _hook_typecheck_ ## hookname (func), NULL, false) +#define hook_unregister_arg(hookname, func, arg) \ + _hook_unregister(&_hook_ ## hookname, \ + _hook_typecheck_arg_ ## hookname (func), arg, true) + +/* invoke hooks + * this is private (static) to the file that has the DEFINE_HOOK statement + */ +#define hook_call(hookname, ...) \ + hook_call_ ## hookname (__VA_ARGS__) + +/* helpers to add the void * arg */ +#define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__) +#define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__) + +/* use in header file - declares the hook and its arguments + * usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2)) + * as above, "passlist" must use the same order and same names as "arglist" + * + * theoretically passlist is not neccessary, but let's keep things simple and + * use exact same args on DECLARE and DEFINE. + */ +#define DECLARE_HOOK(hookname, arglist, passlist) \ + extern struct hook _hook_ ## hookname; \ + __attribute__((unused)) \ + static void *_hook_typecheck_ ## hookname ( \ + int (*funcptr) arglist) { \ + return (void *)funcptr; } \ + __attribute__((unused)) \ + static void *_hook_typecheck_arg_ ## hookname ( \ + int (*funcptr) HOOK_ADDDEF arglist) { \ + return (void *)funcptr; } + +/* use in source file - contains hook-related definitions. + */ +#define DEFINE_HOOK(hookname, arglist, passlist) \ + struct hook _hook_ ## hookname = { \ + .name = #hookname, \ + .entries = NULL, \ + }; \ + static int hook_call_ ## hookname arglist { \ + int hooksum = 0; \ + struct hookent *he = _hook_ ## hookname .entries; \ + void *hookarg; \ + union { \ + void *voidptr; \ + int (*fptr) arglist; \ + int (*farg) HOOK_ADDDEF arglist; \ + } hookp; \ + for (; he; he = he->next) { \ + hookarg = he->hookarg; \ + hookp.voidptr = he->hookfn; \ + if (!he->has_arg) \ + hooksum += hookp.fptr passlist; \ + else \ + hooksum += hookp.farg HOOK_ADDARG passlist; \ + } \ + return hooksum; \ + } + +#endif /* _FRR_HOOK_H */ diff --git a/lib/if.h b/lib/if.h index 49f2a52478..e8e84ffc88 100644 --- a/lib/if.h +++ b/lib/if.h @@ -229,6 +229,9 @@ struct interface /* Interface metric */ uint32_t metric; + /* Interface Speed in Mb/s */ + uint32_t speed; + /* Interface MTU. */ unsigned int mtu; /* IPv4 MTU */ unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */ diff --git a/lib/libfrr.c b/lib/libfrr.c index b7ce0679c3..64f8be2ca6 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -28,6 +28,9 @@ #include "memory_vty.h" #include "zclient.h" #include "log_int.h" +#include "module.h" + +DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; @@ -64,14 +67,16 @@ static const struct option lo_always[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "daemon", no_argument, NULL, 'd' }, + { "module", no_argument, NULL, 'M' }, { "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, { NULL } }; static const struct optspec os_always = { - "hvdi:", + "hvdM:", " -h, --help Display this help and exit\n" " -v, --version Print program version\n" " -d, --daemon Runs in daemon mode\n" + " -M, --module Load specified module\n" " --vty_socket Override vty socket path\n", lo_always }; @@ -184,12 +189,18 @@ void frr_help_exit(int status) exit(status); } +struct option_chain { + struct option_chain *next; + const char *arg; +}; +static struct option_chain *modules = NULL, **modnext = &modules; static int errors = 0; static int frr_opt(int opt) { static int vty_port_set = 0; static int vty_addr_set = 0; + struct option_chain *oc; char *err; switch (opt) { @@ -203,6 +214,13 @@ static int frr_opt(int opt) case 'd': di->daemon_mode = 1; break; + case 'M': + oc = XMALLOC(MTYPE_TMP, sizeof(*oc)); + oc->arg = optarg; + oc->next = NULL; + *modnext = oc; + modnext = &oc->next; + break; case 'i': if (di->flags & FRR_NO_CFG_PID_DRY) return 1; @@ -295,9 +313,12 @@ int frr_getopt(int argc, char * const argv[], int *longindex) return opt; } +static struct thread_master *master; struct thread_master *frr_init(void) { - struct thread_master *master; + struct option_chain *oc; + struct frrmod_runtime *module; + char moderr[256]; srandom(time(NULL)); @@ -307,6 +328,17 @@ struct thread_master *frr_init(void) zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl); #endif + frrmod_init(di->module); + while (modules) { + modules = (oc = modules)->next; + module = frrmod_load(oc->arg, moderr, sizeof(moderr)); + if (!module) { + fprintf(stderr, "%s\n", moderr); + exit(1); + } + XFREE(MTYPE_TMP, oc); + } + zprivs_init(di->privs); master = thread_master_create(); @@ -324,6 +356,8 @@ struct thread_master *frr_init(void) void frr_config_fork(void) { + hook_call(frr_late_init, master); + if (di->instance) { snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf", frr_sysconfdir, di->name, di->instance); diff --git a/lib/libfrr.h b/lib/libfrr.h index d37f406f5b..a40fc34892 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -26,6 +26,8 @@ #include "thread.h" #include "log.h" #include "getopt.h" +#include "module.h" +#include "hook.h" #define FRR_NO_PRIVSEP (1 << 0) #define FRR_NO_TCPVTY (1 << 1) @@ -40,6 +42,7 @@ struct frr_daemon_info { const char *name; const char *logname; unsigned short instance; + struct frrmod_runtime *module; char *vty_addr; int vty_port; @@ -67,15 +70,22 @@ struct frr_daemon_info { * i.e. "ZEBRA" or "BGP" * * note that this macro is also a latch-on point for other changes (e.g. - * upcoming plugin support) that need to place some per-daemon things. Each + * upcoming module support) that need to place some per-daemon things. Each * daemon should have one of these. */ #define FRR_DAEMON_INFO(execname, constname, ...) \ static struct frr_daemon_info execname ##_di = { \ .name = # execname, \ .logname = # constname, \ + .module = THIS_MODULE, \ __VA_ARGS__ \ - }; + }; \ + FRR_COREMOD_SETUP( \ + .name = # execname, \ + .description = # execname " daemon", \ + .version = FRR_VERSION, \ + ) \ + /* end */ extern void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv); @@ -86,6 +96,7 @@ extern void frr_help_exit(int status); extern struct thread_master *frr_init(void); +DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) extern void frr_config_fork(void); extern void frr_vty_serv(void); diff --git a/lib/log.c b/lib/log.c index 69225dbf7a..0f2a580028 100644 --- a/lib/log.c +++ b/lib/log.c @@ -734,6 +734,17 @@ openzlog (const char *progname, const char *protoname, u_short instance, openlog (progname, syslog_flags, zl->facility); zlog_default = zl; + +#ifdef HAVE_GLIBC_BACKTRACE + /* work around backtrace() using lazily resolved dynamically linked + * symbols, which will otherwise cause funny breakage in the SEGV handler. + * (particularly, the dynamic linker can call malloc(), which uses locks + * in programs linked with -pthread, thus can deadlock.) */ + void *bt[4]; + backtrace (bt, array_size(bt)); + free (backtrace_symbols (bt, 0)); + backtrace_symbols_fd (bt, 0, 0); +#endif } void @@ -1059,7 +1070,7 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_VNC; else if (strmatch (s, "vnc-direct")) return ZEBRA_ROUTE_VNC_DIRECT; - else if (strncmp (s, "n", 1) == 0) + else if (strmatch (s, "nhrp")) return ZEBRA_ROUTE_NHRP; } if (afi == AFI_IP6) @@ -1084,7 +1095,7 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_VNC; else if (strmatch (s, "vnc-direct")) return ZEBRA_ROUTE_VNC_DIRECT; - else if (strncmp (s, "n", 1) == 0) + else if (strmatch (s, "nhrp")) return ZEBRA_ROUTE_NHRP; } return -1; diff --git a/lib/memory.c b/lib/memory.c index ad55366f64..c6207adb98 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -27,119 +27,107 @@ struct memgroup **mg_insert = &mg_first; DEFINE_MGROUP(LIB, "libfrr") DEFINE_MTYPE(LIB, TMP, "Temporary memory") -static inline void -mt_count_alloc (struct memtype *mt, size_t size) +static inline void mt_count_alloc(struct memtype *mt, size_t size) { - mt->n_alloc++; + size_t oldsize; - if (mt->size == 0) - mt->size = size; - else if (mt->size != size) - mt->size = SIZE_VAR; + atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed); + + oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); + if (oldsize == 0) + oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed); + if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR) + atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed); } -static inline void -mt_count_free (struct memtype *mt) +static inline void mt_count_free(struct memtype *mt) { - assert(mt->n_alloc); - mt->n_alloc--; + assert(mt->n_alloc); + atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed); } -static inline void * -mt_checkalloc (struct memtype *mt, void *ptr, size_t size) +static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size) { - if (__builtin_expect(ptr == NULL, 0)) - { - memory_oom (size, mt->name); - return NULL; - } - mt_count_alloc (mt, size); - return ptr; + if (__builtin_expect(ptr == NULL, 0)) { + memory_oom(size, mt->name); + return NULL; + } + mt_count_alloc(mt, size); + return ptr; } -void * -qmalloc (struct memtype *mt, size_t size) +void *qmalloc(struct memtype *mt, size_t size) { - return mt_checkalloc (mt, malloc (size), size); + return mt_checkalloc(mt, malloc(size), size); } -void * -qcalloc (struct memtype *mt, size_t size) +void *qcalloc(struct memtype *mt, size_t size) { - return mt_checkalloc (mt, calloc (size, 1), size); + return mt_checkalloc(mt, calloc(size, 1), size); } -void * -qrealloc (struct memtype *mt, void *ptr, size_t size) +void *qrealloc(struct memtype *mt, void *ptr, size_t size) { - if (ptr) - mt_count_free (mt); - return mt_checkalloc (mt, ptr ? realloc (ptr, size) : malloc (size), size); + if (ptr) + mt_count_free(mt); + return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size); } -void * -qstrdup (struct memtype *mt, const char *str) +void *qstrdup(struct memtype *mt, const char *str) { - return mt_checkalloc (mt, strdup (str), strlen (str) + 1); + return mt_checkalloc(mt, strdup(str), strlen(str) + 1); } -void -qfree (struct memtype *mt, void *ptr) +void qfree(struct memtype *mt, void *ptr) { - if (ptr) - mt_count_free (mt); - free (ptr); + if (ptr) + mt_count_free(mt); + free(ptr); } -int -qmem_walk (qmem_walk_fn *func, void *arg) +int qmem_walk(qmem_walk_fn *func, void *arg) { - struct memgroup *mg; - struct memtype *mt; - int rv; + struct memgroup *mg; + struct memtype *mt; + int rv; - for (mg = mg_first; mg; mg = mg->next) - { - if ((rv = func (arg, mg, NULL))) - return rv; - for (mt = mg->types; mt; mt = mt->next) - if ((rv = func (arg, mg, mt))) - return rv; - } - return 0; + for (mg = mg_first; mg; mg = mg->next) { + if ((rv = func(arg, mg, NULL))) + return rv; + for (mt = mg->types; mt; mt = mt->next) + if ((rv = func(arg, mg, mt))) + return rv; + } + return 0; } -struct exit_dump_args -{ - const char *prefix; - int error; +struct exit_dump_args { + const char *prefix; + int error; }; -static int -qmem_exit_walker (void *arg, struct memgroup *mg, struct memtype *mt) +static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) { - struct exit_dump_args *eda = arg; + struct exit_dump_args *eda = arg; - if (!mt) - { - fprintf (stderr, "%s: showing active allocations in memory group %s\n", - eda->prefix, mg->name); - } - else if (mt->n_alloc) - { - char size[32]; - eda->error++; - snprintf (size, sizeof (size), "%10zu", mt->size); - fprintf (stderr, "%s: memstats: %-30s: %6zu * %s\n", - eda->prefix, mt->name, mt->n_alloc, - mt->size == SIZE_VAR ? "(variably sized)" : size); - } - return 0; + if (!mt) { + fprintf(stderr, "%s: showing active allocations in " + "memory group %s\n", + eda->prefix, mg->name); + + } else if (mt->n_alloc) { + char size[32]; + eda->error++; + snprintf(size, sizeof(size), "%10zu", mt->size); + fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", + eda->prefix, mt->name, mt->n_alloc, + mt->size == SIZE_VAR ? "(variably sized)" : size); + } + return 0; } -void -log_memstats_stderr (const char *prefix) +void log_memstats_stderr(const char *prefix) { - struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; - qmem_walk (qmem_exit_walker, &eda); + struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; + qmem_walk(qmem_exit_walker, &eda); } diff --git a/lib/memory.h b/lib/memory.h index 477a6162dc..9e8803a8b2 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -18,23 +18,22 @@ #define _QUAGGA_MEMORY_H #include +#include #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) #define SIZE_VAR ~0UL -struct memtype -{ - struct memtype *next, **ref; - const char *name; - size_t n_alloc; - size_t size; +struct memtype { + struct memtype *next, **ref; + const char *name; + _Atomic size_t n_alloc; + _Atomic size_t size; }; -struct memgroup -{ - struct memgroup *next, **ref; - struct memtype *types, **insert; - const char *name; +struct memgroup { + struct memgroup *next, **ref; + struct memtype *types, **insert; + const char *name; }; #if defined(__clang__) @@ -82,14 +81,14 @@ struct memgroup * DEFINE_MGROUP(MYDAEMON, "my daemon memory") * DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON, * "this mtype is used in multiple files in mydaemon") - * foo = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*foo)) + * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo)) * * mydaemon_io.c - * bar = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*bar)) + * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar)) * * DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO, * "this mtype is used only in this file") - * baz = qmalloc (MTYPE_MYDAEMON_IO, sizeof (*baz)) + * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz)) * * Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced * by not having these as part of the macro arguments) @@ -155,15 +154,15 @@ DECLARE_MGROUP(LIB) DECLARE_MTYPE(TMP) -extern void *qmalloc (struct memtype *mt, size_t size) +extern void *qmalloc(struct memtype *mt, size_t size) __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); -extern void *qcalloc (struct memtype *mt, size_t size) +extern void *qcalloc(struct memtype *mt, size_t size) __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); -extern void *qrealloc (struct memtype *mt, void *ptr, size_t size) +extern void *qrealloc(struct memtype *mt, void *ptr, size_t size) __attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL)); extern void *qstrdup (struct memtype *mt, const char *str) __attribute__ ((malloc, nonnull (1) _RET_NONNULL)); -extern void qfree (struct memtype *mt, void *ptr) +extern void qfree(struct memtype *mt, void *ptr) __attribute__ ((nonnull (1))); #define XMALLOC(mtype, size) qmalloc(mtype, size) @@ -183,10 +182,10 @@ static inline size_t mtype_stats_alloc(struct memtype *mt) * * return value: 0: continue, !0: abort walk. qmem_walk will return the * last value from qmem_walk_fn. */ -typedef int qmem_walk_fn (void *arg, struct memgroup *mg, struct memtype *mt); -extern int qmem_walk (qmem_walk_fn *func, void *arg); -extern void log_memstats_stderr (const char *); +typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt); +extern int qmem_walk(qmem_walk_fn *func, void *arg); +extern void log_memstats_stderr(const char *); -extern void memory_oom (size_t size, const char *name); +extern void memory_oom(size_t size, const char *name); #endif /* _QUAGGA_MEMORY_H */ diff --git a/lib/memory_vty.c b/lib/memory_vty.c index 149b329130..6d63bc2d53 100644 --- a/lib/memory_vty.c +++ b/lib/memory_vty.c @@ -1,23 +1,22 @@ /* - * Memory management routine + * Memory and dynamic module VTY routine + * * Copyright (C) 1998 Kunihiro Ishiguro + * Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc. * - * This file is part of GNU Zebra. + * 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. * - * GNU Zebra 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, 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. * - * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -25,9 +24,12 @@ #if (defined(GNU_LINUX) && defined(HAVE_MALLINFO)) #include #endif /* HAVE_MALLINFO */ +#include +#include #include "log.h" #include "memory.h" +#include "module.h" #include "memory_vty.h" /* Looking up memory status from vty interface. */ @@ -110,10 +112,55 @@ DEFUN (show_memory, return CMD_SUCCESS; } +DEFUN (show_modules, + show_modules_cmd, + "show modules", + "Show running system information\n" + "Loaded modules\n") +{ + struct frrmod_runtime *plug = frrmod_list; + + vty_out (vty, "%-12s %-25s %s%s%s", + "Module Name", "Version", "Description", + VTY_NEWLINE, VTY_NEWLINE); + while (plug) + { + const struct frrmod_info *i = plug->info; + + vty_out (vty, "%-12s %-25s %s%s", i->name, i->version, i->description, + VTY_NEWLINE); + if (plug->dl_handle) + { +#ifdef HAVE_DLINFO_ORIGIN + char origin[MAXPATHLEN] = ""; + dlinfo (plug->dl_handle, RTLD_DI_ORIGIN, &origin); +# ifdef HAVE_DLINFO_LINKMAP + const char *name; + struct link_map *lm = NULL; + dlinfo (plug->dl_handle, RTLD_DI_LINKMAP, &lm); + if (lm) + { + name = strrchr(lm->l_name, '/'); + name = name ? name + 1 : lm->l_name; + vty_out (vty, "\tfrom: %s/%s%s", origin, name, VTY_NEWLINE); + } +# else + vty_out (vty, "\tfrom: %s %s", origin, plug->load_name, VTY_NEWLINE); +# endif +#else + vty_out (vty, "\tfrom: %s%s", plug->load_name, VTY_NEWLINE); +#endif + } + plug = plug->next; + } + return CMD_SUCCESS; +} + void memory_init (void) { install_element (VIEW_NODE, &show_memory_cmd); + install_element (VIEW_NODE, &show_modules_cmd); } /* Stats querying from users */ diff --git a/lib/module.c b/lib/module.c new file mode 100644 index 0000000000..4ebe3c0da2 --- /dev/null +++ b/lib/module.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "module.h" +#include "memory.h" +#include "version.h" + +DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name") +DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments") + +static struct frrmod_info frrmod_default_info = { + .name = "libfrr", + .version = FRR_VERSION, + .description = "libfrr core module", +}; +union _frrmod_runtime_u frrmod_default = { + .r.info = &frrmod_default_info, + .r.finished_loading = 1, +}; + +// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE) +// union _frrmod_runtime_u _frrmod_this_module +// __attribute__((weak, alias("frrmod_default"))); +// elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA) +#pragma weak _frrmod_this_module = frrmod_default +// else +// error need weak symbol support +// endif + +struct frrmod_runtime *frrmod_list = &frrmod_default.r; +static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next; +static const char *execname = NULL; + +void frrmod_init(struct frrmod_runtime *modinfo) +{ + modinfo->finished_loading = 1; + *frrmod_last = modinfo; + frrmod_last = &modinfo->next; + + execname = modinfo->info->name; +} + +struct frrmod_runtime *frrmod_load(const char *spec, + char *err, size_t err_len) +{ + void *handle = NULL; + char name[PATH_MAX], fullpath[PATH_MAX], *args; + struct frrmod_runtime *rtinfo, **rtinfop; + const struct frrmod_info *info; + + snprintf(name, sizeof(name), "%s", spec); + args = strchr(name, ':'); + if (args) + *args++ = '\0'; + + if (!strchr(name, '/')) { + if (!handle && execname) { + snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", + MODULE_PATH, execname, name); + handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + } + if (!handle) { + snprintf(fullpath, sizeof(fullpath), "%s/%s.so", + MODULE_PATH, name); + handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + } + } + if (!handle) { + snprintf(fullpath, sizeof(fullpath), "%s", name); + handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + } + if (!handle) { + if (err) + snprintf(err, err_len, + "loading module \"%s\" failed: %s", + name, dlerror()); + return NULL; + } + + rtinfop = dlsym(handle, "frr_module"); + if (!rtinfop) { + dlclose(handle); + if (err) + snprintf(err, err_len, + "\"%s\" is not a Quagga module: %s", + name, dlerror()); + return NULL; + } + rtinfo = *rtinfop; + rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name); + rtinfo->dl_handle = handle; + if (args) + rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args); + info = rtinfo->info; + + if (rtinfo->finished_loading) { + dlclose(handle); + if (err) + snprintf(err, err_len, + "module \"%s\" already loaded", + name); + goto out_fail; + } + + if (info->init && info->init()) { + dlclose(handle); + if (err) + snprintf(err, err_len, + "module \"%s\" initialisation failed", + name); + goto out_fail; + } + + rtinfo->finished_loading = 1; + + *frrmod_last = rtinfo; + frrmod_last = &rtinfo->next; + return rtinfo; + +out_fail: + if (rtinfo->load_args) + XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args); + XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name); + return NULL; +} + +#if 0 +void frrmod_unload(struct frrmod_runtime *module) +{ +} +#endif diff --git a/lib/module.h b/lib/module.h new file mode 100644 index 0000000000..cb66e60976 --- /dev/null +++ b/lib/module.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _FRR_MODULE_H +#define _FRR_MODULE_H + +#include +#include + +#if !defined(__GNUC__) +# error module code needs GCC visibility extensions +#elif __GNUC__ < 4 +# error module code needs GCC visibility extensions +#else +# define DSO_PUBLIC __attribute__ ((visibility ("default"))) +# define DSO_SELF __attribute__ ((visibility ("protected"))) +# define DSO_LOCAL __attribute__ ((visibility ("hidden"))) +#endif + +struct frrmod_runtime; + +struct frrmod_info { + /* single-line few-word title */ + const char *name; + /* human-readable version number, should not contain spaces */ + const char *version; + /* one-paragraph description */ + const char *description; + + int (*init)(void); +}; + +/* primary entry point structure to be present in loadable module under + * "_frrmod_this_module" dlsym() name + * + * note space for future extensions is reserved below, so other modules + * (e.g. memory management, hooks) can add fields + * + * const members/info are in frrmod_info. + */ +struct frrmod_runtime { + struct frrmod_runtime *next; + + const struct frrmod_info *info; + void *dl_handle; + bool finished_loading; + + char *load_name; + char *load_args; +}; + +/* space-reserving foo */ +struct _frrmod_runtime_size { + struct frrmod_runtime r; + /* this will barf if frrmod_runtime exceeds 1024 bytes ... */ + uint8_t space[1024 - sizeof(struct frrmod_runtime)]; +}; +union _frrmod_runtime_u { + struct frrmod_runtime r; + struct _frrmod_runtime_size s; +}; + +extern union _frrmod_runtime_u _frrmod_this_module; +#define THIS_MODULE (&_frrmod_this_module.r) + +#define FRR_COREMOD_SETUP(...) \ + static const struct frrmod_info _frrmod_info = { __VA_ARGS__ }; \ + DSO_LOCAL union _frrmod_runtime_u _frrmod_this_module = { \ + .r.info = &_frrmod_info, \ + }; +#define FRR_MODULE_SETUP(...) \ + FRR_COREMOD_SETUP(__VA_ARGS__) \ + DSO_SELF struct frrmod_runtime *frr_module = &_frrmod_this_module.r; + +extern struct frrmod_runtime *frrmod_list; + +extern void frrmod_init(struct frrmod_runtime *modinfo); +extern struct frrmod_runtime *frrmod_load(const char *spec, + char *err, size_t err_len); +#if 0 +/* not implemented yet */ +extern void frrmod_unload(struct frrmod_runtime *module); +#endif + +#endif /* _FRR_MODULE_H */ diff --git a/lib/privs.c b/lib/privs.c index 376d6f3365..decd4bb7db 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -731,7 +731,7 @@ zprivs_init(struct zebra_privs_t *zprivs) if (zprivs->user) { ngroups = sizeof(groups); - if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 ) + if (getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups) < 0) { /* cant use log.h here as it depends on vty */ fprintf (stderr, "privs_init: could not getgrouplist for user %s\n", diff --git a/lib/sigevent.c b/lib/sigevent.c index 09f07180ce..b2059a17bf 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -233,6 +233,18 @@ core_handler(int signo #endif ) { + /* make sure we don't hang in here. default for SIGALRM is terminate. + * - if we're in backtrace for more than a second, abort. */ + struct sigaction sa_default = { .sa_handler = SIG_DFL }; + sigaction (SIGALRM, &sa_default, NULL); + + sigset_t sigset; + sigemptyset (&sigset); + sigaddset (&sigset, SIGALRM); + sigprocmask (SIG_UNBLOCK, &sigset, NULL); + + alarm (1); + zlog_signal(signo, "aborting..." #ifdef SA_SIGINFO , siginfo, program_counter(context) @@ -326,6 +338,11 @@ trap_default_signals(void) #else act.sa_handler = sigmap[i].handler; act.sa_flags = 0; +#endif +#ifdef SA_RESETHAND + /* don't try to print backtraces recursively */ + if (sigmap[i].handler == core_handler) + act.sa_flags |= SA_RESETHAND; #endif } if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0) diff --git a/lib/smux.c b/lib/smux.c index 3abfadcd28..370b8f138e 100644 --- a/lib/smux.c +++ b/lib/smux.c @@ -21,7 +21,7 @@ #include -#if defined HAVE_SNMP && defined SNMP_SMUX +#ifdef SNMP_SMUX #include #include @@ -1445,4 +1445,4 @@ smux_start(void) /* Schedule first connection. */ smux_event (SMUX_SCHEDULE, 0); } -#endif /* HAVE_SNMP */ +#endif /* SNMP_SMUX */ diff --git a/lib/snmp.c b/lib/snmp.c index f6f9845e2d..1cbd41c720 100644 --- a/lib/snmp.c +++ b/lib/snmp.c @@ -21,7 +21,6 @@ #include -#ifdef HAVE_SNMP #include #include @@ -130,4 +129,3 @@ smux_header_table (struct variable *v, oid *name, size_t *length, int exact, return MATCH_SUCCEEDED; } -#endif /* HAVE_SNMP */ diff --git a/lib/thread.c b/lib/thread.c index 6138e79718..e707fc584c 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -1037,28 +1037,6 @@ thread_process_fds_helper (struct thread_master *m, struct thread *thread, threa #if defined(HAVE_POLL) -#if defined(HAVE_SNMP) -/* add snmp fds to poll set */ -static void -add_snmp_pollfds(struct thread_master *m, fd_set *snmpfds, int fdsetsize) -{ - int i; - m->handler.pfdcountsnmp = m->handler.pfdcount; - /* cycle trough fds and add neccessary fds to poll set */ - for (i=0;ihandler.pfdcountsnmp <= m->handler.pfdsize); - - m->handler.pfds[m->handler.pfdcountsnmp].fd = i; - m->handler.pfds[m->handler.pfdcountsnmp].events = POLLIN; - m->handler.pfdcountsnmp++; - } - } -} -#endif - /* check poll events */ static void check_pollfds(struct thread_master *m, fd_set *readfd, int num) diff --git a/lib/version.h.in b/lib/version.h.in index adc8278189..d9eabb9f81 100644 --- a/lib/version.h.in +++ b/lib/version.h.in @@ -39,8 +39,9 @@ #define FRR_SMUX_NAME "@PACKAGE_NAME@" #define FRR_PTM_NAME "@PACKAGE_NAME@" -#define FRR_FULL_NAME "FreeRangeRouting" +#define FRR_FULL_NAME "FRRouting" #define FRR_VERSION "@PACKAGE_VERSION@" GIT_SUFFIX +#define FRR_VER_SHORT "@PACKAGE_VERSION@" #define FRR_BUG_ADDRESS "@PACKAGE_BUGREPORT@" #define FRR_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al." #define FRR_CONFIG_ARGS "@CONFIG_ARGS@" diff --git a/lib/zclient.c b/lib/zclient.c index 4455644345..71b95ae7db 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1003,6 +1003,8 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | metric | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | speed | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifmtu | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifmtu6 | @@ -1185,6 +1187,7 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp) ifp->ptm_enable = stream_getc (s); ifp->ptm_status = stream_getc (s); ifp->metric = stream_getl (s); + ifp->speed = stream_getl (s); ifp->mtu = stream_getl (s); ifp->mtu6 = stream_getl (s); ifp->bandwidth = stream_getl (s); diff --git a/m4/.gitignore b/m4/.gitignore index 3f3bd0a735..798188b0b9 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -4,4 +4,5 @@ Makefile.in .arch-ids *~ *.loT - +!ax_pthread.m4 +!ax_sys_weak_alias.m4 diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 new file mode 100644 index 0000000000..d383ad5c6d --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,332 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also link it with them as well. e.g. you should link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threads programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name +# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# 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 3 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 21 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test x"$ax_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case ${host_os} in + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + ;; + + darwin*) + ax_pthread_flags="-pthread $ax_pthread_flags" + ;; +esac + +# Clang doesn't consider unrecognized options an error unless we specify +# -Werror. We throw in some extra Clang-specific options to ensure that +# this doesn't happen for GCC, which also accepts -Werror. + +AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) +save_CFLAGS="$CFLAGS" +ax_pthread_extra_flags="-Werror" +CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], + [AC_MSG_RESULT([yes])], + [ax_pthread_extra_flags= + AC_MSG_RESULT([no])]) +CFLAGS="$save_CFLAGS" + +if test x"$ax_pthread_ok" = xno; then +for flag in $ax_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + if test x"$ax_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $attr; return attr /* ; */])], + [attr_name=$attr; break], + []) + done + AC_MSG_RESULT([$attr_name]) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case ${host_os} in + aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; + osf* | hpux*) flag="-D_REENTRANT";; + solaris*) + if test "$GCC" = "yes"; then + flag="-D_REENTRANT" + else + # TODO: What about Clang on Solaris? + flag="-mt -D_REENTRANT" + fi + ;; + esac + AC_MSG_RESULT([$flag]) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != xyes; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$ax_pthread_ok" = xyes; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 73b6aaccf6..4c1d97a489 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -425,7 +425,6 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p) nbma_natoa = NULL; if (natted) { nbma_natoa = nbma_addr; - nbma_addr = &p->peer->vc->remote.nbma; } holdtime = htons(cie->holding_time); diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 06fc7a30af..75dd8ffe46 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -7,6 +7,7 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libospf6.a +module_LTLIBRARIES = sbin_PROGRAMS = ospf6d libospf6_a_SOURCES = \ @@ -14,7 +15,7 @@ libospf6_a_SOURCES = \ ospf6_network.c ospf6_message.c ospf6_lsa.c ospf6_lsdb.c \ ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \ ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \ - ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c ospf6_snmp.c \ + ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c \ ospf6d.c ospf6_bfd.c noinst_HEADERS = \ @@ -22,7 +23,7 @@ noinst_HEADERS = \ ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \ ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \ ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \ - ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h ospf6_snmp.h \ + ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h \ ospf6d.h ospf6_bfd.h ospf6d_SOURCES = \ @@ -30,5 +31,13 @@ ospf6d_SOURCES = \ ospf6d_LDADD = ../lib/libfrr.la @LIBCAP@ +if SNMP +module_LTLIBRARIES += ospf6d_snmp.la +endif +ospf6d_snmp_la_SOURCES = ospf6_snmp.c +ospf6d_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ospf6d_snmp_la_LIBADD = ../lib/libfrrsnmp.la + examplesdir = $(exampledir) dist_examples_DATA = ospf6d.conf.sample diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 8e0779df92..8cf7f4afaa 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -41,12 +41,14 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_spf.h" -#include "ospf6_snmp.h" #include "ospf6d.h" #include "ospf6_bfd.h" DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names") DEFINE_QOBJ_TYPE(ospf6_interface) +DEFINE_HOOK(ospf6_interface_change, + (struct ospf6_interface *oi, int state, int old_state), + (oi, state, old_state)) unsigned char conf_debug_ospf6_interface = 0; @@ -518,16 +520,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi) OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); } -#ifdef HAVE_SNMP - /* Terminal state or regression */ - if ((next_state == OSPF6_INTERFACE_POINTTOPOINT) || - (next_state == OSPF6_INTERFACE_DROTHER) || - (next_state == OSPF6_INTERFACE_BDR) || - (next_state == OSPF6_INTERFACE_DR) || - (next_state < prev_state)) - ospf6TrapIfStateChange (oi); -#endif - + hook_call(ospf6_interface_change, oi, next_state, prev_state); } diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 179477a634..846cde4191 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -23,6 +23,7 @@ #define OSPF6_INTERFACE_H #include "qobj.h" +#include "hook.h" #include "if.h" /* Debug option */ @@ -182,4 +183,8 @@ extern void install_element_ospf6_clear_interface (void); extern int config_write_ospf6_debug_interface (struct vty *vty); extern void install_element_ospf6_debug_interface (void); +DECLARE_HOOK(ospf6_interface_change, + (struct ospf6_interface *oi, int state, int old_state), + (oi, state, old_state)) + #endif /* OSPF6_INTERFACE_H */ diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index ec79a1552b..118210dfc7 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -38,7 +38,6 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_flood.h" -#include "ospf6_snmp.h" #include "ospf6d.h" #include "ospf6_bfd.h" #include "ospf6_abr.h" @@ -47,6 +46,10 @@ #include "ospf6_spf.h" #include "ospf6_zebra.h" +DEFINE_HOOK(ospf6_neighbor_change, + (struct ospf6_neighbor *on, int state, int next_state), + (on, state, next_state)) + unsigned char conf_debug_ospf6_neighbor = 0; const char *ospf6_neighbor_state_str[] = @@ -202,13 +205,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e next_state != OSPF6_NEIGHBOR_LOADING)) ospf6_maxage_remove (on->ospf6_if->area->ospf6); -#ifdef HAVE_SNMP - /* Terminal state or regression */ - if ((next_state == OSPF6_NEIGHBOR_FULL) || - (next_state == OSPF6_NEIGHBOR_TWOWAY) || - (next_state < prev_state)) - ospf6TrapNbrStateChange (on); -#endif + hook_call(ospf6_neighbor_change, on, next_state, prev_state); ospf6_bfd_trigger_event(on, prev_state, next_state); } diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index f9e197e99b..c275ff830e 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -22,6 +22,8 @@ #ifndef OSPF6_NEIGHBOR_H #define OSPF6_NEIGHBOR_H +#include "hook.h" + /* Debug option */ extern unsigned char conf_debug_ospf6_neighbor; #define OSPF6_DEBUG_NEIGHBOR_STATE 0x01 @@ -179,4 +181,8 @@ extern void ospf6_neighbor_init (void); extern int config_write_ospf6_debug_neighbor (struct vty *vty); extern void install_element_ospf6_debug_neighbor (void); +DECLARE_HOOK(ospf6_neighbor_change, + (struct ospf6_neighbor *on, int state, int next_state), + (on, state, next_state)) + #endif /* OSPF6_NEIGHBOR_H */ diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index 86cfd17c83..96f1e3dd21 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -21,8 +21,6 @@ #include -#ifdef HAVE_SNMP - #include #include @@ -32,6 +30,8 @@ #include "vector.h" #include "vrf.h" #include "smux.h" +#include "libfrr.h" +#include "version.h" #include "ospf6_proto.h" #include "ospf6_lsa.h" @@ -45,7 +45,6 @@ #include "ospf6_abr.h" #include "ospf6_asbr.h" #include "ospf6d.h" -#include "ospf6_snmp.h" /* OSPFv3-MIB */ #define OSPFv3MIB 1,3,6,1,2,1,191 @@ -1139,11 +1138,18 @@ static struct trap_object ospf6IfTrapList[] = {4, {1, 7, 1, OSPFv3IFAREAID}} }; -void -ospf6TrapNbrStateChange (struct ospf6_neighbor *on) +static int +ospf6TrapNbrStateChange (struct ospf6_neighbor *on, + int next_state, int prev_state) { oid index[3]; + /* Terminal state or regression */ + if ((next_state != OSPF6_NEIGHBOR_FULL) && + (next_state != OSPF6_NEIGHBOR_TWOWAY) && + (next_state >= prev_state)) + return 0; + index[0] = on->ospf6_if->interface->ifindex; index[1] = on->ospf6_if->instance_id; index[2] = ntohl (on->router_id); @@ -1155,13 +1161,23 @@ ospf6TrapNbrStateChange (struct ospf6_neighbor *on) ospf6NbrTrapList, sizeof ospf6NbrTrapList / sizeof (struct trap_object), NBRSTATECHANGE); + return 0; } -void -ospf6TrapIfStateChange (struct ospf6_interface *oi) +static int +ospf6TrapIfStateChange (struct ospf6_interface *oi, + int next_state, int prev_state) { oid index[2]; + /* Terminal state or regression */ + if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) && + (next_state != OSPF6_INTERFACE_DROTHER) && + (next_state != OSPF6_INTERFACE_BDR) && + (next_state != OSPF6_INTERFACE_DR) && + (next_state >= prev_state)) + return 0; + index[0] = oi->interface->ifindex; index[1] = oi->instance_id; @@ -1172,15 +1188,30 @@ ospf6TrapIfStateChange (struct ospf6_interface *oi) ospf6IfTrapList, sizeof ospf6IfTrapList / sizeof (struct trap_object), IFSTATECHANGE); + return 0; } /* Register OSPFv3-MIB. */ -void +static int ospf6_snmp_init (struct thread_master *master) { smux_init (master); REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); + return 0; } -#endif /* HAVE_SNMP */ +static int +ospf6_snmp_module_init (void) +{ + hook_register(ospf6_interface_change, ospf6TrapIfStateChange); + hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange); + hook_register(frr_late_init, ospf6_snmp_init); + return 0; +} +FRR_MODULE_SETUP( + .name = "ospf6d_snmp", + .version = FRR_VERSION, + .description = "ospf6d AgentX SNMP module", + .init = ospf6_snmp_module_init, +) diff --git a/ospf6d/ospf6_snmp.h b/ospf6d/ospf6_snmp.h deleted file mode 100644 index fa1b0c37a8..0000000000 --- a/ospf6d/ospf6_snmp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* OSPFv3 SNMP support - * Copyright (C) 2004 Yasuhiro Ohara - * - * This file is part of GNU Zebra. - * - * GNU Zebra 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, or (at your option) any - * later version. - * - * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef OSPF6_SNMP_H -#define OSPF6_SNMP_H - -extern void ospf6TrapNbrStateChange (struct ospf6_neighbor *); -extern void ospf6TrapIfStateChange (struct ospf6_interface *); -extern void ospf6_snmp_init (struct thread_master *); - -#endif /*OSPF6_SNMP_H*/ - - diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 74e49a21bb..f2a1c8c2ec 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -29,6 +29,7 @@ #include "table.h" #include "thread.h" #include "command.h" +#include "defaults.h" #include "ospf6_proto.h" #include "ospf6_message.h" @@ -160,7 +161,10 @@ ospf6_create (void) o->distance_table = route_table_init (); /* Enable "log-adjacency-changes" */ +#if DFLT_OSPF6_LOG_ADJACENCY_CHANGES SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); +#endif + QOBJ_REG (o, ospf6); return o; @@ -391,7 +395,6 @@ DEFUN (no_ospf6_log_adjacency_changes_detail, VTY_DECLVAR_CONTEXT(ospf6, ospf6); UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); - UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); return CMD_SUCCESS; } @@ -470,21 +473,9 @@ DEFUN (no_ospf6_distance, DEFUN (ospf6_distance_ospf6, ospf6_distance_ospf6_cmd, - "distance ospf6 ", + "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}", "Administrative distance\n" - "OSPF6 distance\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" - "Distance for external routes\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" - "Distance for external routes\n" + "OSPF6 administrative distance\n" "Intra-area routes\n" "Distance for intra-area routes\n" "Inter-area routes\n" @@ -493,53 +484,23 @@ DEFUN (ospf6_distance_ospf6, "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf6, o); - - char *intra, *inter, *external; - intra = inter = external = NULL; - int idx = 0; - if (argv_find (argv, argc, "intra-area", &idx)) - intra = argv[++idx]->arg; - if (argv_find (argv, argc, "intra-area", &idx)) - { - vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } + if (argv_find (argv, argc, "intra-area", &idx)) + o->distance_intra = atoi(argv[idx + 1]->arg); idx = 0; if (argv_find (argv, argc, "inter-area", &idx)) - inter = argv[++idx]->arg; - if (argv_find (argv, argc, "inter-area", &idx)) - { - vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - + o->distance_inter = atoi(argv[idx + 1]->arg); idx = 0; if (argv_find (argv, argc, "external", &idx)) - external = argv[++idx]->arg; - if (argv_find (argv, argc, "external", &idx)) - { - vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - - - if (intra) - o->distance_intra = atoi (intra); - - if (inter) - o->distance_inter = atoi (inter); - - if (external) - o->distance_external = atoi (external); + o->distance_external = atoi(argv[idx + 1]->arg); return CMD_SUCCESS; } DEFUN (no_ospf6_distance_ospf6, no_ospf6_distance_ospf6_cmd, - "no distance ospf6 [ ]", + "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]", NO_STR "Administrative distance\n" "OSPF6 distance\n" @@ -548,70 +509,16 @@ DEFUN (no_ospf6_distance_ospf6, "Inter-area routes\n" "Distance for inter-area routes\n" "External routes\n" - "Distance for external routes\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" - "Distance for external routes\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf6, o); - - char *intra, *inter, *external; - intra = inter = external = NULL; - - if (argc == 3) - { - /* If no arguments are given, clear all distance information */ - o->distance_intra = 0; - o->distance_inter = 0; - o->distance_external = 0; - return CMD_SUCCESS; - } - int idx = 0; - if (argv_find (argv, argc, "intra-area", &idx)) - intra = argv[++idx]->arg; - if (argv_find (argv, argc, "intra-area", &idx)) - { - vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - idx = 0; - if (argv_find (argv, argc, "inter-area", &idx)) - inter = argv[++idx]->arg; - if (argv_find (argv, argc, "inter-area", &idx)) - { - vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - - idx = 0; - if (argv_find (argv, argc, "external", &idx)) - external = argv[++idx]->arg; - if (argv_find (argv, argc, "external", &idx)) - { - vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - if (argc < 3) /* should not happen */ - return CMD_WARNING; - - if (intra) - o->distance_intra = 0; - - if (inter) - o->distance_inter = 0; - - if (external) + if (argv_find (argv, argc, "intra-area", &idx) || argc == 3) + idx = o->distance_intra = 0; + if (argv_find (argv, argc, "inter-area", &idx) || argc == 3) + idx = o->distance_inter = 0; + if (argv_find (argv, argc, "external", &idx) || argc == 3) o->distance_external = 0; return CMD_SUCCESS; @@ -1118,8 +1025,10 @@ config_write_ospf6 (struct vty *vty) { if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE); + else if (!DFLT_OSPF6_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes%s", VTY_NEWLINE); } - else + else if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES) { vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE); } diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 2aaed5fcbf..036cc6d4c8 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -45,10 +45,6 @@ #include "ospf6d.h" #include "ospf6_bfd.h" -#ifdef HAVE_SNMP -#include "ospf6_snmp.h" -#endif /*HAVE_SNMP*/ - char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; struct route_node * @@ -1215,10 +1211,6 @@ ospf6_init (void) ospf6_asbr_init (); ospf6_abr_init (); -#ifdef HAVE_SNMP - ospf6_snmp_init (master); -#endif /*HAVE_SNMP*/ - ospf6_bfd_init(); install_node (&debug_node, config_write_ospf6_debug); diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 71e0df0dc5..c6a5ec91d2 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -6,13 +6,14 @@ DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 noinst_LIBRARIES = libfrrospf.a +module_LTLIBRARIES = sbin_PROGRAMS = ospfd libfrrospf_a_SOURCES = \ ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \ ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \ ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \ - ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \ + ospf_lsdb.c ospf_asbr.c ospf_routemap.c \ ospf_opaque.c ospf_te.c ospf_ri.c ospf_vty.c ospf_api.c ospf_apiserver.c \ ospf_bfd.c ospf_memory.c ospf_dump_api.c @@ -26,13 +27,21 @@ ospfdheader_HEADERS = \ noinst_HEADERS = \ ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \ ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \ - ospf_flood.h ospf_snmp.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \ + ospf_flood.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \ ospf_bfd.h ospf_memory.h ospfd_SOURCES = ospf_main.c ospfd_LDADD = libfrrospf.a ../lib/libfrr.la @LIBCAP@ @LIBM@ +if SNMP +module_LTLIBRARIES += ospfd_snmp.la +endif +ospfd_snmp_la_SOURCES = ospf_snmp.c +ospfd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +ospfd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ospfd_snmp_la_LIBADD = ../lib/libfrrsnmp.la + EXTRA_DIST = OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt examplesdir = $(exampledir) diff --git a/ospfd/ospf_dump_api.c b/ospfd/ospf_dump_api.c index 20e7740d32..5ef262ce54 100644 --- a/ospfd/ospf_dump_api.c +++ b/ospfd/ospf_dump_api.c @@ -2,7 +2,7 @@ * OSPFd dump routine (parts used by ospfclient). * Copyright (C) 1999, 2000 Toshiaki Takada * - * This file is part of FreeRangeRouting (FRR). + * This file is part of FRRouting (FRR). * * FRR 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 diff --git a/ospfd/ospf_dump_api.h b/ospfd/ospf_dump_api.h index c3ff1e3f54..1cd8257f0c 100644 --- a/ospfd/ospf_dump_api.h +++ b/ospfd/ospf_dump_api.h @@ -2,7 +2,7 @@ * OSPFd dump routine (parts used by ospfclient). * Copyright (C) 1999 Toshiaki Takada * - * This file is part of FreeRangeRouting (FRR). + * This file is part of FRRouting (FRR). * * FRR 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 diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 4fb206589a..b4a282a52a 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -47,11 +47,10 @@ #include "ospfd/ospf_abr.h" #include "ospfd/ospf_network.h" #include "ospfd/ospf_dump.h" -#ifdef HAVE_SNMP -#include "ospfd/ospf_snmp.h" -#endif /* HAVE_SNMP */ DEFINE_QOBJ_TYPE(ospf_interface) +DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd)) +DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd)) int ospf_if_get_output_cost (struct ospf_interface *oi) @@ -993,9 +992,7 @@ void ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data) { listnode_add (ospf->vlinks, vl_data); -#ifdef HAVE_SNMP - ospf_snmp_vl_add (vl_data); -#endif /* HAVE_SNMP */ + hook_call(ospf_vl_add, vl_data); } void @@ -1004,9 +1001,7 @@ ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data) ospf_vl_shutdown (vl_data); ospf_vl_if_delete (vl_data); -#ifdef HAVE_SNMP - ospf_snmp_vl_delete (vl_data); -#endif /* HAVE_SNMP */ + hook_call(ospf_vl_delete, vl_data); listnode_delete (ospf->vlinks, vl_data); ospf_vl_data_free (vl_data); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index bd51bbf422..39202f777a 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -24,6 +24,7 @@ #define _ZEBRA_OSPF_INTERFACE_H #include "qobj.h" +#include "hook.h" #include "ospfd/ospf_packet.h" #include "ospfd/ospf_spf.h" @@ -309,4 +310,7 @@ extern u_char ospf_default_iftype (struct interface *ifp); state of the interface. */ extern void ospf_if_set_multicast (struct ospf_interface *); +DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd)) +DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd)) + #endif /* _ZEBRA_OSPF_INTERFACE_H */ diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 9630616acc..717c99c21f 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -43,7 +43,10 @@ #include "ospfd/ospf_packet.h" #include "ospfd/ospf_flood.h" #include "ospfd/ospf_abr.h" -#include "ospfd/ospf_snmp.h" + +DEFINE_HOOK(ospf_ism_change, + (struct ospf_interface *oi, int state, int oldstate), + (oi, state, oldstate)) /* elect DR and BDR. Refer to RFC2319 section 9.4 */ static struct ospf_neighbor * @@ -545,19 +548,7 @@ ism_change_state (struct ospf_interface *oi, int state) oi->state = state; oi->state_change++; -#ifdef HAVE_SNMP - /* Terminal state or regression */ - if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) || - (state == ISM_PointToPoint) || (state < old_state)) - { - /* ospfVirtIfStateChange */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - ospfTrapVirtIfStateChange (oi); - /* ospfIfStateChange */ - else - ospfTrapIfStateChange (oi); - } -#endif + hook_call(ospf_ism_change, oi, state, old_state); /* Set multicast memberships appropriately for new state. */ ospf_if_set_multicast(oi); diff --git a/ospfd/ospf_ism.h b/ospfd/ospf_ism.h index f0357a4824..fa8e6d70f6 100644 --- a/ospfd/ospf_ism.h +++ b/ospfd/ospf_ism.h @@ -24,6 +24,8 @@ #ifndef _ZEBRA_OSPF_ISM_H #define _ZEBRA_OSPF_ISM_H +#include "hook.h" + /* OSPF Interface State Machine Status. */ #define ISM_DependUpon 0 #define ISM_Down 1 @@ -35,10 +37,6 @@ #define ISM_DR 7 #define OSPF_ISM_STATE_MAX 8 -/* Because DR/DROther values are exhanged wrt RFC */ -#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \ - ((x) == ISM_DR) ? ISM_DROther : (x)) - /* OSPF Interface State Machine Event. */ #define ISM_NoEvent 0 #define ISM_InterfaceUp 1 @@ -111,4 +109,8 @@ extern int ospf_ism_event (struct thread *); extern void ism_change_status (struct ospf_interface *, int); extern int ospf_hello_timer (struct thread *thread); +DECLARE_HOOK(ospf_ism_change, + (struct ospf_interface *oi, int state, int oldstate), + (oi, state, oldstate)) + #endif /* _ZEBRA_OSPF_ISM_H */ diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index f462c207e4..38718b35d5 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -225,9 +225,6 @@ main (int argc, char **argv) ospf_bfd_init(); ospf_route_map_init (); -#ifdef HAVE_SNMP - ospf_snmp_init (); -#endif /* HAVE_SNMP */ ospf_opaque_init (); /* Need to initialize the default ospf structure, so the interface mode diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 01617055ce..97f3f6a382 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -48,9 +48,12 @@ #include "ospfd/ospf_dump.h" #include "ospfd/ospf_flood.h" #include "ospfd/ospf_abr.h" -#include "ospfd/ospf_snmp.h" #include "ospfd/ospf_bfd.h" +DEFINE_HOOK(ospf_nsm_change, + (struct ospf_neighbor *on, int state, int oldstate), + (on, state, oldstate)) + static void nsm_clear_adj (struct ospf_neighbor *); /* OSPF NSM Timer functions. */ @@ -838,35 +841,12 @@ ospf_nsm_event (struct thread *thread) /* If state is changed. */ if (next_state != nbr->state) { + int old_state = nbr->state; + nsm_notice_state_change (nbr, next_state, event); -#ifdef HAVE_SNMP - int send_trap_virt = 0; - int send_trap = 0; - /* Terminal state or regression */ - if ((next_state == NSM_Full) - || (next_state == NSM_TwoWay) - || (next_state < nbr->state)) - { - /* ospfVirtNbrStateChange */ - if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK) - send_trap_virt = 1; - /* ospfNbrStateChange trap */ - else - /* To/From FULL, only managed by DR */ - if (((next_state != NSM_Full) && (nbr->state != NSM_Full)) - || (nbr->oi->state == ISM_DR)) - send_trap = 1; - } -#endif nsm_change_state (nbr, next_state); -#ifdef HAVE_SNMP - if (send_trap_virt) { - ospfTrapVirtNbrStateChange(nbr); - } else if (send_trap) { - ospfTrapNbrStateChange(nbr); - } -#endif + hook_call(ospf_nsm_change, nbr, next_state, old_state); } /* Make sure timer is set. */ diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index 9b7e14a4ae..4531f6ec7d 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -24,6 +24,8 @@ #ifndef _ZEBRA_OSPF_NSM_H #define _ZEBRA_OSPF_NSM_H +#include "hook.h" + /* OSPF Neighbor State Machine State. */ #define NSM_DependUpon 0 #define NSM_Deleted 1 @@ -86,5 +88,9 @@ extern int ospf_db_summary_isempty (struct ospf_neighbor *); extern int ospf_db_summary_count (struct ospf_neighbor *); extern void ospf_db_summary_clear (struct ospf_neighbor *); +DECLARE_HOOK(ospf_nsm_change, + (struct ospf_neighbor *on, int state, int oldstate), + (on, state, oldstate)) + #endif /* _ZEBRA_OSPF_NSM_H */ diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 4afbda8788..32449d5597 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -24,7 +24,6 @@ #include -#ifdef HAVE_SNMP #include #include @@ -35,6 +34,8 @@ #include "command.h" #include "memory.h" #include "smux.h" +#include "libfrr.h" +#include "version.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -47,7 +48,7 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_ism.h" #include "ospfd/ospf_dump.h" -#include "ospfd/ospf_snmp.h" +#include "ospfd/ospf_zebra.h" /* OSPF2-MIB. */ #define OSPF2MIB 1,3,6,1,2,1,14 @@ -205,6 +206,10 @@ #define IPADDRESS ASN_IPADDRESS #define STRING ASN_OCTET_STR +/* Because DR/DROther values are exhanged wrt RFC */ +#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \ + ((x) == ISM_DR) ? ISM_DROther : (x)) + /* Declare static local variables for convenience. */ SNMP_LOCAL_VARIABLES @@ -1429,7 +1434,7 @@ ospf_snmp_if_free (struct ospf_snmp_if *osif) XFREE (MTYPE_TMP, osif); } -void +static int ospf_snmp_if_delete (struct interface *ifp) { struct listnode *node, *nnode; @@ -1441,12 +1446,13 @@ ospf_snmp_if_delete (struct interface *ifp) { list_delete_node (ospf_snmp_iflist, node); ospf_snmp_if_free (osif); - return; + break; } } + return 0; } -void +static int ospf_snmp_if_update (struct interface *ifp) { struct listnode *node; @@ -1511,6 +1517,7 @@ ospf_snmp_if_update (struct interface *ifp) osif->ifp = ifp; listnode_add_after (ospf_snmp_iflist, pn, osif); + return 0; } static int @@ -1914,7 +1921,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact, static struct route_table *ospf_snmp_vl_table; -void +static int ospf_snmp_vl_add (struct ospf_vl_data *vl_data) { struct prefix_ls lp; @@ -1931,9 +1938,10 @@ ospf_snmp_vl_add (struct ospf_vl_data *vl_data) route_unlock_node (rn); rn->info = vl_data; + return 0; } -void +static int ospf_snmp_vl_delete (struct ospf_vl_data *vl_data) { struct prefix_ls lp; @@ -1947,10 +1955,11 @@ ospf_snmp_vl_delete (struct ospf_vl_data *vl_data) rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp); if (! rn) - return; + return 0; rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); + return 0; } static struct ospf_vl_data * @@ -2651,7 +2660,7 @@ static struct trap_object ospfVirtIfTrapList[] = {3, {9, 1, OSPFVIRTIFSTATE}} }; -void +static void ospfTrapNbrStateChange (struct ospf_neighbor *on) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2673,7 +2682,7 @@ ospfTrapNbrStateChange (struct ospf_neighbor *on) NBRSTATECHANGE); } -void +static void ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2692,7 +2701,29 @@ ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) VIRTNBRSTATECHANGE); } -void +static int +ospf_snmp_nsm_change (struct ospf_neighbor *nbr, + int next_state, int old_state) +{ + /* Terminal state or regression */ + if ((next_state == NSM_Full) + || (next_state == NSM_TwoWay) + || (next_state < old_state)) + { + /* ospfVirtNbrStateChange */ + if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospfTrapVirtNbrStateChange(nbr); + /* ospfNbrStateChange trap */ + else + /* To/From FULL, only managed by DR */ + if (((next_state != NSM_Full) && (nbr->state != NSM_Full)) + || (nbr->oi->state == ISM_DR)) + ospfTrapNbrStateChange(nbr); + } + return 0; +} + +static void ospfTrapIfStateChange (struct ospf_interface *oi) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2713,7 +2744,7 @@ ospfTrapIfStateChange (struct ospf_interface *oi) IFSTATECHANGE); } -void +static void ospfTrapVirtIfStateChange (struct ospf_interface *oi) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2731,13 +2762,53 @@ ospfTrapVirtIfStateChange (struct ospf_interface *oi) sizeof ospfVirtIfTrapList / sizeof (struct trap_object), VIRTIFSTATECHANGE); } + +static int +ospf_snmp_ism_change (struct ospf_interface *oi, + int state, int old_state) +{ + /* Terminal state or regression */ + if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) || + (state == ISM_PointToPoint) || (state < old_state)) + { + /* ospfVirtIfStateChange */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospfTrapVirtIfStateChange (oi); + /* ospfIfStateChange */ + else + ospfTrapIfStateChange (oi); + } + return 0; +} + /* Register OSPF2-MIB. */ -void -ospf_snmp_init () +static int +ospf_snmp_init (struct thread_master *tm) { ospf_snmp_iflist = list_new (); ospf_snmp_vl_table = route_table_init (); - smux_init (om->master); + smux_init (tm); REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid); + return 0; } -#endif /* HAVE_SNMP */ + +static int +ospf_snmp_module_init (void) +{ + hook_register(ospf_if_update, ospf_snmp_if_update); + hook_register(ospf_if_delete, ospf_snmp_if_delete); + hook_register(ospf_vl_add, ospf_snmp_vl_add); + hook_register(ospf_vl_delete, ospf_snmp_vl_delete); + hook_register(ospf_ism_change, ospf_snmp_ism_change); + hook_register(ospf_nsm_change, ospf_snmp_nsm_change); + + hook_register(frr_late_init, ospf_snmp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "ospfd_snmp", + .version = FRR_VERSION, + .description = "ospfd AgentX SNMP module", + .init = ospf_snmp_module_init, +) diff --git a/ospfd/ospf_snmp.h b/ospfd/ospf_snmp.h deleted file mode 100644 index 413d1d7f79..0000000000 --- a/ospfd/ospf_snmp.h +++ /dev/null @@ -1,38 +0,0 @@ -/* OSPFv2 SNMP support - * Copyright (C) 2000 IP Infusion Inc. - * - * Written by Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra 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, or (at your option) any - * later version. - * - * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef _ZEBRA_OSPF_SNMP_H -#define _ZEBRA_OSPF_SNMP_H - -extern void ospf_snmp_if_update (struct interface *); -extern void ospf_snmp_if_delete (struct interface *); - -extern void ospf_snmp_vl_add (struct ospf_vl_data *); -extern void ospf_snmp_vl_delete (struct ospf_vl_data *); - -extern void ospfTrapIfStateChange (struct ospf_interface *); -extern void ospfTrapVirtIfStateChange (struct ospf_interface *); -extern void ospfTrapNbrStateChange (struct ospf_neighbor *); -extern void ospfTrapVirtNbrStateChange (struct ospf_neighbor *); - -#endif /* _ZEBRA_OSPF_SNMP_H */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index c51e176c74..49474df826 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -34,6 +34,7 @@ #include "log.h" #include "zclient.h" #include +#include "defaults.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_asbr.h" @@ -2137,7 +2138,6 @@ DEFUN (no_ospf_log_adjacency_changes_detail, { VTY_DECLVAR_CONTEXT(ospf, ospf); - UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); return CMD_SUCCESS; } @@ -7458,7 +7458,7 @@ DEFUN (no_ospf_default_metric, DEFUN (ospf_distance, ospf_distance_cmd, "distance (1-255)", - "Define an administrative distance\n" + "Administrative distance\n" "OSPF Administrative distance\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); @@ -7473,7 +7473,7 @@ DEFUN (no_ospf_distance, no_ospf_distance_cmd, "no distance (1-255)", NO_STR - "Define an administrative distance\n" + "Administrative distance\n" "OSPF Administrative distance\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); @@ -7485,10 +7485,10 @@ DEFUN (no_ospf_distance, DEFUN (no_ospf_distance_ospf, no_ospf_distance_ospf_cmd, - "no distance ospf []", + "no distance ospf [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]", NO_STR - "Define an administrative distance\n" - "OSPF Administrative distance\n" + "Administrative distance\n" + "OSPF administrative distance\n" "Intra-area routes\n" "Distance for intra-area routes\n" "Inter-area routes\n" @@ -7497,42 +7497,26 @@ DEFUN (no_ospf_distance_ospf, "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_area_distance = 3; + int idx = 0; if (!ospf) return CMD_SUCCESS; - if (argc < 3) - return CMD_WARNING; - - if (!ospf) - return CMD_SUCCESS; - - if (argv[idx_area_distance]->arg != NULL) - ospf->distance_intra = 0; - - if (argv[1] != NULL) - ospf->distance_inter = 0; - - if (argv[2] != NULL) + if (argv_find (argv, argc, "intra-area", &idx) || argc == 3) + idx = ospf->distance_intra = 0; + if (argv_find (argv, argc, "inter-area", &idx) || argc == 3) + idx = ospf->distance_inter = 0; + if (argv_find (argv, argc, "external", &idx) || argc == 3) ospf->distance_external = 0; - if (argv[idx_area_distance]->arg || argv[1] || argv[2]) - return CMD_SUCCESS; - - /* If no arguments are given, clear all distance information */ - ospf->distance_intra = 0; - ospf->distance_inter = 0; - ospf->distance_external = 0; - return CMD_SUCCESS; } DEFUN (ospf_distance_ospf, ospf_distance_ospf_cmd, - "distance ospf []", - "Define an administrative distance\n" - "OSPF Administrative distance\n" + "distance ospf {intra-area (1-255)|inter-area (1-255)|external (1-255)}", + "Administrative distance\n" + "OSPF administrative distance\n" "Intra-area routes\n" "Distance for intra-area routes\n" "Inter-area routes\n" @@ -7541,26 +7525,16 @@ DEFUN (ospf_distance_ospf, "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_area_distance = 2; + int idx = 0; - if (argc < 3) /* should not happen */ - return CMD_WARNING; - - if (!argv[idx_area_distance]->arg && !argv[1] && !argv[2]) - { - vty_out(vty, "%% Command incomplete. (Arguments required)%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - if (strcmp (argv[idx_area_distance]->text, "intra") == 0) - ospf->distance_intra = atoi(argv[idx_area_distance+1]->arg); - - if (strcmp (argv[idx_area_distance]->text, "inter") == 0) - ospf->distance_inter = atoi(argv[idx_area_distance+1]->arg); - - if (strcmp (argv[idx_area_distance]->text, "external") == 0) - ospf->distance_external = atoi(argv[idx_area_distance+1]->arg); + if (argv_find (argv, argc, "intra-area", &idx)) + ospf->distance_intra = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find (argv, argc, "inter-area", &idx)) + ospf->distance_inter = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find (argv, argc, "external", &idx)) + ospf->distance_external = atoi(argv[idx + 1]->arg); return CMD_SUCCESS; } @@ -8832,8 +8806,10 @@ ospf_config_write (struct vty *vty) { if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE); + else if (!DFLT_OSPF_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes%s", VTY_NEWLINE); } - else + else if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) { vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index cb14273eed..abb6db0347 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -50,11 +50,11 @@ #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_nsm.h" #include "ospfd/ospf_zebra.h" -#ifdef HAVE_SNMP -#include "ospfd/ospf_snmp.h" -#endif /* HAVE_SNMP */ #include "ospfd/ospf_te.h" +DEFINE_HOOK(ospf_if_update, (struct interface *ifp), (ifp)) +DEFINE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp)) + /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -112,9 +112,7 @@ ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length, ospf_if_update (NULL, ifp); -#ifdef HAVE_SNMP - ospf_snmp_if_update (ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_update, ifp); return 0; } @@ -143,9 +141,7 @@ ospf_interface_delete (int command, struct zclient *zclient, ("Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d", ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); -#ifdef HAVE_SNMP - ospf_snmp_if_delete (ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_delete, ifp); for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) if (rn->info) @@ -277,9 +273,7 @@ ospf_interface_address_add (int command, struct zclient *zclient, ospf_if_update (NULL, c->ifp); -#ifdef HAVE_SNMP - ospf_snmp_if_update (c->ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_update, c->ifp); return 0; } @@ -324,9 +318,7 @@ ospf_interface_address_delete (int command, struct zclient *zclient, /* Call interface hook functions to clean up */ ospf_if_free (oi); -#ifdef HAVE_SNMP - ospf_snmp_if_update (c->ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_update, c->ifp); connected_free (c); diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 8e93ed2691..22c71a49e1 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -24,6 +24,7 @@ #define _ZEBRA_OSPF_ZEBRA_H #include "vty.h" +#include "hook.h" #define EXTERNAL_METRIC_TYPE_1 0 #define EXTERNAL_METRIC_TYPE_2 1 @@ -79,5 +80,8 @@ extern int ospf_distance_unset (struct vty *, struct ospf *, const char *, const char *, const char *); extern void ospf_zebra_init(struct thread_master *, u_short); +DECLARE_HOOK(ospf_if_update, (struct interface *ifp), (ifp)) +DECLARE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp)) + #endif /* _ZEBRA_OSPF_ZEBRA_H */ diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 7cd3903678..30b1e9622f 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -35,6 +35,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "plist.h" #include "sockopt.h" #include "bfd.h" +#include "defaults.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -292,7 +293,10 @@ ospf_new (u_short instance) new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; /* Enable "log-adjacency-changes" */ +#if DFLT_OSPF_LOG_ADJACENCY_CHANGES SET_FLAG(new->config, OSPF_LOG_ADJACENCY_CHANGES); +#endif + QOBJ_REG (new, ospf); return new; diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index a3bd0ca12f..9198d5c620 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -574,7 +574,6 @@ extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *); extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *); extern void ospf_route_map_init (void); -extern void ospf_snmp_init (void); extern void ospf_master_init (struct thread_master *master); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index e6582e2b17..ee88e7d8ea 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -876,10 +876,8 @@ pim_igmp_read (struct thread *t) if (errno == EINTR) continue; if (errno == EWOULDBLOCK || errno == EAGAIN) - { - cont = 0; break; - } + goto done; } } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 90e30ea3d6..2fb243b9bd 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -577,10 +577,8 @@ static int mroute_read(struct thread *t) if (errno == EINTR) continue; if (errno == EWOULDBLOCK || errno == EAGAIN) - { - cont = 0; - break; - } + break; + if (PIM_DEBUG_MROUTE) zlog_warn("%s: failure reading fd=%d: errno=%d: %s", __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index c9ae673224..fe96d01a06 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -111,42 +111,6 @@ pim_nexthop_cache_find (struct pim_rpf *rpf) } -static int -pim_rp_list_cmp (void *v1, void *v2) -{ - struct rp_info *rp1 = (struct rp_info *) v1; - struct rp_info *rp2 = (struct rp_info *) v2; - - if (rp1 == rp2) - return 0; - - if (!rp1 && rp2) - return -1; - - if (rp1 && !rp2) - return 1; - - /* - * Sort by RP IP address - */ - if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) - return -1; - - if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) - return 1; - - /* - * Sort by group IP address - */ - if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) - return -1; - - if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) - return 1; - - return -1; -} - struct pim_nexthop_cache * pim_nexthop_cache_add (struct pim_rpf *rpf_addr) { @@ -462,10 +426,13 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) return 0; } -/* This API is used to parse Registered address nexthop update coming from Zebra */ -void -pim_parse_nexthop_update (struct zclient *zclient, int command, - vrf_id_t vrf_id) +/* + * This API is used to parse Registered address nexthop update + * coming from Zebra + */ +int +pim_parse_nexthop_update (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { struct stream *s; struct prefix p; @@ -512,9 +479,16 @@ pim_parse_nexthop_update (struct zclient *zclient, int command, zlog_debug ("%s: NHT addr %s is not in local cached DB.", __PRETTY_FUNCTION__, buf); } - return; + return 0; } } + else + { + /* + * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE + */ + return 0; + } pnc->last_update = pim_time_monotonic_sec (); distance = stream_getc (s); @@ -644,4 +618,5 @@ pim_parse_nexthop_update (struct zclient *zclient, int command, if (listcount (pnc->upstream_list)) pim_update_upstream_nh (pnc); + return 0; } diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 6e6602b3be..5348ec3704 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -48,8 +48,8 @@ struct pim_nexthop_cache struct list *upstream_list; }; -void pim_parse_nexthop_update (struct zclient *zclient, int command, - vrf_id_t vrf_id); +int pim_parse_nexthop_update (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id); int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, struct rp_info *rp); void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index bc13e10a61..9886cd6ad2 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -310,10 +310,8 @@ static int pim_sock_read(struct thread *t) if (errno == EINTR) continue; if (errno == EWOULDBLOCK || errno == EAGAIN) - { - cont = 0; - break; - } + break; + if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("Received errno: %d %s", errno, safe_strerror (errno)); goto done; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index effc212722..65a3e8714f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -54,7 +54,7 @@ pim_register_join (struct pim_upstream *up) { if (PIM_DEBUG_PIM_EVENTS) zlog_debug ("%s register setup skipped as group is SSM", up->sg_str); - return; + return; } pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 8afc87956d..d52f266ea3 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -54,21 +54,12 @@ pim_rp_info_free (struct rp_info *rp_info) XFREE (MTYPE_PIM_RP, rp_info); } -static int +int pim_rp_list_cmp (void *v1, void *v2) { struct rp_info *rp1 = (struct rp_info *)v1; struct rp_info *rp2 = (struct rp_info *)v2; - if (rp1 == rp2) - return 0; - - if (!rp1 && rp2) - return -1; - - if (rp1 && !rp2) - return 1; - /* * Sort by RP IP address */ @@ -87,10 +78,7 @@ pim_rp_list_cmp (void *v1, void *v2) if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) return 1; - if (rp1 == tail) - return 1; - - return -1; + return 0; } void diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index e5580cfa63..84ab9be482 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -61,4 +61,6 @@ struct pim_rpf *pim_rp_g (struct in_addr group); #define RP(G) pim_rp_g ((G)) void pim_rp_show_information (struct vty *vty, u_char uj); + +int pim_rp_list_cmp (void *v1, void *v2); #endif diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 33efb7c966..53a3a197c7 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -582,14 +582,6 @@ void sched_rpf_cache_refresh(void) 0, qpim_rpf_cache_refresh_delay_msec); } -static int -pim_zebra_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - pim_parse_nexthop_update (zclient, command, vrf_id); - return 0; -} - static void pim_zebra_connected (struct zclient *zclient) { @@ -617,7 +609,7 @@ void pim_zebra_init(void) zclient->interface_down = pim_zebra_if_state_down; zclient->interface_address_add = pim_zebra_if_address_add; zclient->interface_address_delete = pim_zebra_if_address_del; - zclient->nexthop_update = pim_zebra_nexthop_update; + zclient->nexthop_update = pim_parse_nexthop_update; zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); if (PIM_DEBUG_PIM_TRACE) { diff --git a/pimd/pimd.c b/pimd/pimd.c index e76e202bd3..3d3f4d6aee 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -108,10 +108,17 @@ pim_vrf_enable (struct vrf *vrf) { pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); if (pimg == NULL) - zlog_err ("%s %s: pim class init failure ", __FILE__, - __PRETTY_FUNCTION__); + { + zlog_err ("%s %s: pim class init failure ", __FILE__, + __PRETTY_FUNCTION__); + /* + * We will crash and burn otherwise + */ + exit(1); + } + + pimg->send_v6_secondary = 1; - pimg->send_v6_secondary = 1; } return 0; } @@ -196,12 +203,18 @@ static void pim_instance_terminate (void) { /* Traverse and cleanup rpf_hash */ - if (pimg && pimg->rpf_hash) + if (pimg->rpf_hash) { hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); hash_free (pimg->rpf_hash); + pimg->rpf_hash = NULL; + } + + if (pimg->ssm_info) + { + pim_ssm_terminate (pimg->ssm_info); + pimg->ssm_info = NULL; } - pim_ssm_terminate (pimg->ssm_info); XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); } diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md index db3c7d45c8..6bec5d65cd 100644 --- a/redhat/README.rpm_build.md +++ b/redhat/README.rpm_build.md @@ -1,4 +1,4 @@ -Building your own FreeRangeRouting RPM +Building your own FRRouting RPM ====================================== (Tested on CentOS 6, CentOS 7 and Fedora 22.) @@ -12,7 +12,7 @@ Building your own FreeRangeRouting RPM 2. Checkout FRR under a **unpriviledged** user account - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr 3. Run Bootstrap and make distribution tar.gz diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index bb23931b13..c32e3e3af8 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -8,7 +8,7 @@ # rpms again and again on the same day, so the newer rpms can be installed. # bumping the number each time. -####################### FreeRangeRouting (FRR) configure options ######################### +####################### FRRouting (FRR) configure options ######################### # with-feature options %{!?with_tcp_zebra: %global with_tcp_zebra 0 } %{!?with_pam: %global with_pam 0 } @@ -73,7 +73,7 @@ %{!?frr_gid: %global frr_gid 92 } %{!?vty_gid: %global vty_gid 85 } -%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospfd6d +%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospf6d %if %{with_ldpd} %define daemon_ldpd ldpd @@ -107,8 +107,8 @@ Version: %{rpmversion} Release: @CONFDATE@%{release_rev}%{?dist} License: GPLv2+ Group: System Environment/Daemons -Source0: http://www.freerangerouting.org/releases/frr/%{name}-%{frrversion}.tar.gz -URL: http://www.freerangerouting.org +Source0: http://www.frrouting.org/releases/frr/%{name}-%{frrversion}.tar.gz +URL: http://www.frrouting.org Requires: ncurses json-c Requires(pre): /sbin/install-info Requires(preun): /sbin/install-info @@ -135,14 +135,14 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-root Obsoletes: bird gated mrt zebra frr-sysvinit %description -FreeRangeRouting is a free software that manages TCP/IP based routing +FRRouting is a free software that manages TCP/IP based routing protocol. It takes multi-server and multi-thread approach to resolve the current complexity of the Internet. -FreeRangeRouting supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng, PIM, -LDP and NHRP. +FRRouting supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng, PIM, LDP +and NHRP. -FreeRangeRouting is a fork of Quagga. +FRRouting is a fork of Quagga. %package contrib Summary: contrib tools for frr @@ -315,7 +315,7 @@ if getent group %frr_user >/dev/null; then : ; else \ fi if getent passwd %frr_user >/dev/null ; then : ; else \ /usr/sbin/useradd -u %frr_uid -g %frr_gid \ - -M -r -s /sbin/nologin -c "FreeRangeRouting suite" \ + -M -r -s /sbin/nologin -c "FRRouting suite" \ -d %_localstatedir %frr_user 2> /dev/null || : ; \ fi %if 0%{?vty_group:1} @@ -594,8 +594,8 @@ rm -rf %{buildroot} * Tue Feb 14 2017 Timo Teräs - %{version} - add nhrpd -* Fri Jan 6 2017 Martin Winter -- Renamed to frr for FreeRangeRouting fork of Quagga +* Fri Jan 6 2017 Martin Winter - %{version} +- Renamed to frr for FRRouting fork of Quagga * Thu Feb 11 2016 Paul Jakma - remove with_ipv6 conditionals, always build v6 diff --git a/ripd/Makefile.am b/ripd/Makefile.am index 7967ff1535..9c034f0c38 100644 --- a/ripd/Makefile.am +++ b/ripd/Makefile.am @@ -7,11 +7,12 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = librip.a +module_LTLIBRARIES = sbin_PROGRAMS = ripd librip_a_SOURCES = \ rip_memory.c \ - ripd.c rip_zebra.c rip_interface.c rip_debug.c rip_snmp.c \ + ripd.c rip_zebra.c rip_interface.c rip_debug.c \ rip_routemap.c rip_peer.c rip_offset.c noinst_HEADERS = \ @@ -23,6 +24,14 @@ ripd_SOURCES = \ ripd_LDADD = ../lib/libfrr.la @LIBCAP@ +if SNMP +module_LTLIBRARIES += ripd_snmp.la +endif +ripd_snmp_la_SOURCES = rip_snmp.c +ripd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +ripd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ripd_snmp_la_LIBADD = ../lib/libfrrsnmp.la + examplesdir = $(exampledir) dist_examples_DATA = ripd.conf.sample diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 4c750faf4c..a4ee2ba570 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -42,6 +42,9 @@ #include "ripd/rip_debug.h" #include "ripd/rip_interface.h" +DEFINE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) +DEFINE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) + /* static prototypes */ static void rip_enable_apply (struct interface *); static void rip_passive_interface_apply (struct interface *); @@ -673,9 +676,7 @@ rip_interface_address_add (int command, struct zclient *zclient, /* Check if this prefix needs to be redistributed */ rip_apply_address_add(ifc); -#ifdef HAVE_SNMP - rip_ifaddr_add (ifc->ifp, ifc); -#endif /* HAVE_SNMP */ + hook_call(rip_ifaddr_add, ifc); } return 0; @@ -723,9 +724,7 @@ rip_interface_address_delete (int command, struct zclient *zclient, zlog_debug ("connected address %s/%d is deleted", inet_ntoa (p->u.prefix4), p->prefixlen); -#ifdef HAVE_SNMP - rip_ifaddr_delete (ifc->ifp, ifc); -#endif /* HAVE_SNMP */ + hook_call(rip_ifaddr_del, ifc); /* Chech wether this prefix needs to be removed */ rip_apply_address_del(ifc); diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index fede5bed07..06cd3cef6c 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -21,16 +21,18 @@ #include -#ifdef HAVE_SNMP #include #include #include "if.h" +#include "vrf.h" #include "log.h" #include "prefix.h" #include "command.h" #include "table.h" #include "smux.h" +#include "libfrr.h" +#include "version.h" #include "ripd/ripd.h" @@ -174,24 +176,27 @@ rip2Globals (struct variable *v, oid name[], size_t *length, return NULL; } -void -rip_ifaddr_add (struct interface *ifp, struct connected *ifc) +static int +rip_snmp_ifaddr_add (struct connected *ifc) { + struct interface *ifp = ifc->ifp; struct prefix *p; struct route_node *rn; p = ifc->address; if (p->family != AF_INET) - return; + return 0; rn = route_node_get (rip_ifaddr_table, p); rn->info = ifp; + return 0; } -void -rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) +static int +rip_snmp_ifaddr_del (struct connected *ifc) { + struct interface *ifp = ifc->ifp; struct prefix *p; struct route_node *rn; struct interface *i; @@ -199,11 +204,11 @@ rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) p = ifc->address; if (p->family != AF_INET) - return; + return 0; rn = route_node_lookup (rip_ifaddr_table, p); if (! rn) - return; + return 0; i = rn->info; if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ)) { @@ -211,6 +216,7 @@ rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) route_unlock_node (rn); route_unlock_node (rn); } + return 0; } static struct interface * @@ -582,12 +588,29 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length, } /* Register RIPv2-MIB. */ -void -rip_snmp_init () +static int +rip_snmp_init (struct thread_master *master) { rip_ifaddr_table = route_table_init (); smux_init (master); REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); + return 0; } -#endif /* HAVE_SNMP */ + +static int +rip_snmp_module_init (void) +{ + hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); + hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); + + hook_register(frr_late_init, rip_snmp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "ripd_snmp", + .version = FRR_VERSION, + .description = "ripd AgentX SNMP module", + .init = rip_snmp_module_init, +) diff --git a/ripd/ripd.c b/ripd/ripd.c index 45d5bf1ead..b668b0a0b4 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -4064,11 +4064,6 @@ rip_init (void) /* Debug related init. */ rip_debug_init (); - /* SNMP init. */ -#ifdef HAVE_SNMP - rip_snmp_init (); -#endif /* HAVE_SNMP */ - /* Access list install. */ access_list_init (); access_list_add_hook (rip_distribute_update_all_wrapper); diff --git a/ripd/ripd.h b/ripd/ripd.h index 68b3d1fc6e..eeb008e3d5 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -23,6 +23,7 @@ #define _ZEBRA_RIP_H #include "qobj.h" +#include "hook.h" #include "rip_memory.h" /* RIP version number. */ @@ -391,7 +392,6 @@ extern void rip_if_init (void); extern void rip_if_down_all (void); extern void rip_route_map_init (void); extern void rip_route_map_reset (void); -extern void rip_snmp_init (void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_reset (void); extern void rip_offset_init (void); @@ -432,8 +432,6 @@ extern void rip_offset_clean (void); extern void rip_info_free (struct rip_info *); extern u_char rip_distance_apply (struct rip_info *); extern void rip_redistribute_clean (void); -extern void rip_ifaddr_add (struct interface *, struct connected *); -extern void rip_ifaddr_delete (struct interface *, struct connected *); extern struct rip_info *rip_ecmp_add (struct rip_info *); extern struct rip_info *rip_ecmp_replace (struct rip_info *); @@ -448,4 +446,8 @@ extern struct thread_master *master; /* RIP statistics for SNMP. */ extern long rip_global_route_changes; extern long rip_global_queries; + +DECLARE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) +DECLARE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) + #endif /* _ZEBRA_RIP_H */ diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am index 15813be72f..75f768e942 100644 --- a/snapcraft/Makefile.am +++ b/snapcraft/Makefile.am @@ -1,11 +1,25 @@ EXTRA_DIST = snapcraft.yaml \ - scripts/Makefile scripts/zebra-service scripts/bgpd-service \ - scripts/isisd-service scripts/ripd-service scripts/ripngd-service \ - scripts/ospf6d-service scripts/ospfd-service \ - scripts/isisd-service scripts/pimd-service \ - scripts/ldpd-service \ - defaults/bgpd.conf.default defaults/isisd.conf.default \ - defaults/ospf6d.conf.default defaults/ospfd.conf.default \ - defaults/pimd.conf.default defaults/zebra.conf.default \ - defaults/ripd.conf.default defaults/ripngd.conf.default \ - defaults/ldpd.conf.default defaults/vtysh.conf.default + README.snap_build.md \ + README.usage.md \ + scripts/Makefile \ + scripts/bgpd-service \ + scripts/isisd-service \ + scripts/ldpd-service \ + scripts/ospf6d-service \ + scripts/ospfd-service \ + scripts/pimd-service \ + scripts/ripd-service \ + scripts/ripngd-service \ + scripts/zebra-service \ + defaults/bgpd.conf.default \ + defaults/isisd.conf.default \ + defaults/ldpd.conf.default \ + defaults/ospf6d.conf.default \ + defaults/ospfd.conf.default \ + defaults/pimd.conf.default \ + defaults/ripd.conf.default \ + defaults/ripngd.conf.default \ + defaults/vtysh.conf.default \ + defaults/zebra.conf.default \ + helpers \ + snap diff --git a/snapcraft/README.snap_build.md b/snapcraft/README.snap_build.md index 341b210f71..c4db51bd6a 100644 --- a/snapcraft/README.snap_build.md +++ b/snapcraft/README.snap_build.md @@ -1,4 +1,4 @@ -Building your own FreeRangeRouting Snap +Building your own FRRouting Snap ======================================== (Tested on Ubuntu 16.04 with Snap Version 2, does not work on Ubuntu 15.x which uses earlier versions of snaps) @@ -7,9 +7,9 @@ which uses earlier versions of snaps) sudo apt-get install snapcraft -2. Checkout FreeRangeRouting under a **unpriviledged** user account +2. Checkout FRRouting under a **unpriviledged** user account - git clone https://github.com/freerangerouting/frr.git + git clone https://github.com/frrouting/frr.git cd frr 3. Run Bootstrap and make distribution tar.gz @@ -56,8 +56,8 @@ The Snap will be auto-started and running. Operations ========== -### FreeRangeRouting Daemons -At this time, all FreeRangeRouting daemons are auto-started. +### FRRouting Daemons +At this time, all FRRouting daemons are auto-started. A daemon can be stopped/started with (ie ospf6d) @@ -69,7 +69,7 @@ or disabled/enabled with systemctl disable snap.frr.ospf6d.service systemctl enable snap.frr.ospf6d.service -### FreeRangeRouting Commands +### FRRouting Commands All the commands are prefixed with frr. frr.vtysh -> vtysh diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md index 2d2b32b6b7..aaff59438a 100644 --- a/snapcraft/README.usage.md +++ b/snapcraft/README.usage.md @@ -1,14 +1,14 @@ -Using the FreeRangeRouting Snap +Using the FRRouting Snap =============================== After installing the Snap, the priviledged plug need to be connected: snap connect frr:network-control ubuntu-core:network-control -Enabling/Disabling FreeRangeRouting Daemons +Enabling/Disabling FRRouting Daemons ------------------------------------------- -By default (at this time), all FreeRangeRouting daemons will be enabled +By default (at this time), all FRRouting daemons will be enabled on installation. If you want to disable a specific daemon, then use the systemctl commands @@ -24,7 +24,7 @@ Commands defined by this snap ----------------------------- - `frr.vtysh`: - FreeRangeRouting VTY Shell (configuration tool) + FRRouting VTY Shell (configuration tool) - `frr.version`: Returns output of `zebra --version` to display version and configured options @@ -62,10 +62,10 @@ FAQ Sourcecode available ==================== -The source for this SNAP is available as part of the FreeRangeRouting +The source for this SNAP is available as part of the FRRouting Source Code Distribution. - https://github.com/freerangerouting/frr.git + https://github.com/frrouting/frr.git Instructions for rebuilding the snap are in `README.snap_build.md` diff --git a/snapcraft/setup/gui/icon.png b/snapcraft/setup/gui/icon.png deleted file mode 100644 index e8f68e6dde..0000000000 Binary files a/snapcraft/setup/gui/icon.png and /dev/null differ diff --git a/snapcraft/snap/gui/icon.png b/snapcraft/snap/gui/icon.png new file mode 100644 index 0000000000..3ab3f8fc16 Binary files /dev/null and b/snapcraft/snap/gui/icon.png differ diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index a703766f0b..a20a1d0392 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -1,11 +1,11 @@ name: frr version: @VERSION@ -summary: FreeRangeRouting BGP/OSPFv2/OSPFv3/ISIS/RIP/RIPng/PIM/LDP routing daemon +summary: FRRouting BGP/OSPFv2/OSPFv3/ISIS/RIP/RIPng/PIM/LDP routing daemon description: BGP/OSPFv2/OSPFv3/ISIS/RIP/RIPng/PIM routing daemon - FreeRangeRouting (FRR) is free software which manages TCP/IP based routing + FRRouting (FRR) is free software which manages TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3, IS-IS, RIPv1, RIPv2, RIPng, PIM and LDP as well as the IPv6 versions of these. - FreeRangeRouting (frr) is a fork of Quagga. + FRRouting (frr) is a fork of Quagga. confinement: strict grade: devel diff --git a/solaris/README.txt b/solaris/README.txt index 01f725b8fa..589570d881 100644 --- a/solaris/README.txt +++ b/solaris/README.txt @@ -15,13 +15,13 @@ Requirements: i.manifest must be at least version 1.5. Place these scripts in this directory if you are using Solaris 10 GA (which does not ship with - these scripts), or in the solaris/ directory in the FreeRangeRouting source. + these scripts), or in the solaris/ directory in the FRRouting source. Package creation instructions: ------------------------------ -1. Configure and build FreeRangeRouting (frr) in the top level build directory as per normal, eg: +1. Configure and build FRRouting (frr) in the top level build directory as per normal, eg: ./configure --prefix=/usr/local/frr \ --localstatedir=/var/run/frr \ @@ -102,7 +102,7 @@ Install and post-install configuration notes: # # svcs -l ripd fmri svc:/network/routing/frr:ripd - name FreeRangeRouting: ripd, RIPv1/2 IPv4 routing protocol daemon. + name FRRouting: ripd, RIPv1/2 IPv4 routing protocol daemon. enabled true state online next_state none @@ -117,7 +117,7 @@ Install and post-install configuration notes: - Configuration of startup options is by way of SMF properties in a property group named 'frr'. The defaults should automatically be - inline with how you configured FreeRangeRouting in Step 1 above. + inline with how you configured FRRouting in Step 1 above. - By default the VTY interface is disabled. To change this, see below for how to set the 'frr/vty_port' property as appropriate for @@ -176,11 +176,11 @@ Install and post-install configuration notes: - As SMF is dependency aware, restarting network/zebra will restart all the other daemons. - - To upgrade from one set of FreeRangeRouting packages to a newer release, + - To upgrade from one set of FRRouting packages to a newer release, one must first pkgrm the installed packages. When one pkgrm's FRRsmf all property configuration will be lost, and any customisations will have to redone after installing the updated FRRsmf package. - These packages are not supported by Sun Microsystems, report bugs via the - usual FreeRangeRouting channels, ie Issue Tracker. Improvements/contributions of course would be greatly appreciated. + usual FRRouting channels, ie Issue Tracker. Improvements/contributions of course would be greatly appreciated. diff --git a/solaris/depend.daemons.in b/solaris/depend.daemons.in index 64fb03ac19..a8ce943e31 100644 --- a/solaris/depend.daemons.in +++ b/solaris/depend.daemons.in @@ -1,4 +1,4 @@ -P FRRlibs FreeRangeRouting common runtime libraries +P FRRlibs FRRouting common runtime libraries @PACKAGE_VERSION@,REV=@CONFDATE@ P SUNWcsu Core Solaris, (Usr) P SUNWcsr Core Solaris Libraries (Root) diff --git a/solaris/depend.dev.in b/solaris/depend.dev.in index 5d8bf16ed6..1b65724a04 100644 --- a/solaris/depend.dev.in +++ b/solaris/depend.dev.in @@ -1,2 +1,2 @@ -P FRRlibs FreeRangeRouting common runtime libraries +P FRRlibs FRRouting common runtime libraries @PACKAGE_VERSION@,REV=@CONFDATE@ diff --git a/solaris/depend.libs.in b/solaris/depend.libs.in index 6ead0b2867..04f04efd01 100644 --- a/solaris/depend.libs.in +++ b/solaris/depend.libs.in @@ -1,5 +1,5 @@ P SUNWcslr Core Solaris Libraries (Root) P SUNWcsl Core Solaris, (Shared Libs) P SUNWlibmsr Math & Microtasking Libraries (Root) -R FRRdaemons FreeRangeRouting daemons +R FRRdaemons FRRouting daemons R FRRdev diff --git a/solaris/depend.smf.in b/solaris/depend.smf.in index 66b11eba2a..b3b1bd778c 100644 --- a/solaris/depend.smf.in +++ b/solaris/depend.smf.in @@ -1,4 +1,4 @@ -P FRRaemons FreeRangeRouting daemons +P FRRaemons FRRouting daemons @PACKAGE_VERSION@,REV=@CONFDATE@ P SUNWcsu Core Solaris, (Usr) P SUNWcsr Core Solaris Libraries (Root) diff --git a/solaris/frr.init.in b/solaris/frr.init.in index 580fd9b35c..bd9ab85e69 100755 --- a/solaris/frr.init.in +++ b/solaris/frr.init.in @@ -3,20 +3,20 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# This file is part of FreeRangeRouting. +# This file is part of FRRouting. # -# FreeRangeRouting is free software; you can redistribute it and/or modify +# FRRouting 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, or (at your option) any # later version. # -# FreeRangeRouting is distributed in the hope that it will be useful, but +# FRRouting 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 FreeRangeRouting; see the file COPYING. If not, write to +# along with FRRouting; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # @@ -74,7 +74,7 @@ handle_routeadm_upgrade () { upgrade_config () { DAEMON=$1 - # handle upgrade of SUNWzebra to FreeRangeRouting + # handle upgrade of SUNWzebra to FRRouting if [ -d "/etc/frr" -a ! -f "/etc/frr/${DAEMON}.conf" ] ; then if [ -f "/etc/sfw/zebra/${DAEMON}.conf" ] ; then cp "/etc/sfw/zebra/${DAEMON}.conf" \ @@ -216,7 +216,7 @@ case "${DAEMON}" in ;; esac -# Older FreeRangeRouting SMF packages pass daemon args on the commandline +# Older FRRouting SMF packages pass daemon args on the commandline # Newer SMF routeadm model uses properties for each argument # so we must handle that. if [ smf_present -a -f "$ROUTEADMINCLUDE" ]; then diff --git a/solaris/frr.xml.in b/solaris/frr.xml.in index 5ac7e52721..08a9a11c0f 100644 --- a/solaris/frr.xml.in +++ b/solaris/frr.xml.in @@ -1,20 +1,20 @@ + option name, consult FRRouting documentation --> +