frr/ospfd/ospf_main.c

353 lines
7.8 KiB
C
Raw Normal View History

2002-12-13 21:15:29 +01:00
/*
* OSPFd main routine.
* Copyright (C) 1998, 99 Kunihiro Ishiguro, Toshiaki Takada
*
* 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.
*/
#include <zebra.h>
#include <lib/version.h>
2002-12-13 21:15:29 +01:00
#include "getopt.h"
#include "thread.h"
#include "prefix.h"
#include "linklist.h"
#include "if.h"
#include "vector.h"
#include "vty.h"
#include "command.h"
#include "filter.h"
#include "plist.h"
#include "stream.h"
#include "log.h"
#include "memory.h"
#include "privs.h"
#include "sigevent.h"
#include "zclient.h"
2002-12-13 21:15:29 +01:00
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_vty.h"
/* ospfd privileges */
zebra_capabilities_t _caps_p [] =
{
2005-09-29 Paul Jakma <paul.jakma@sun.com> * configure.ac: Add the test for Solaris least-privileges. Set defines for whether capabilities are supported and whether of the linux or solaris variety. Add missing-prototypes, missing-declarations, char-subscripts and cast-qual warnings to default cflags, cause Hasso enjoys warnings, and we really should clean the remaining ones up. (ie isisd..). * (*/*main.c) Update the zebra_capabilities_t arrays in the various daemons to match the changes made in lib/privs.h. * zebra.h: Solaris capabilities requires priv.h to be included. * privs.{c,h}: Add support for Solaris Least-Privileges. privs.h: Reduce some of the abstract capabilities, which do not have rough equivalents on both systems. Rename the net related caps to _NET, as they should have been in first place. (zprivs_terminate) should take the zebra_privs_t as argument so that it can update change pointer. Add an additional privilege state, ZPRIVS_UNKNOWN. * privs.c: (various capability functions) Add Solaris privileges variants. (zprivs_state) Use privs.c specific generic types to represent various capability/privilege related types, so that each can be typedef'd as appropriate on each platform. (zprivs_null_state) static added, to hold the state the null method should report (should be raised by default, and LOWERED if zprivs_terminate has been called) (zprivs_state_null) Report back the zprivs_null_state. (cap_map) Make it able to map abstract capability to multiple system capabilities. (zcaps2sys) Map to abstract capabilities to multiple system privileges/capabilities. (zprivs_init) move capability related init to seperate function, zprivs_caps_init. (zprivs_terminate) ditto, moved to zprivs_caps_terminate. Set the change_state callback to the NULL state, so the user can continue to run and use the callbacks.
2005-09-29 16:39:32 +02:00
ZCAP_NET_RAW,
ZCAP_BIND,
2005-09-29 Paul Jakma <paul.jakma@sun.com> * configure.ac: Add the test for Solaris least-privileges. Set defines for whether capabilities are supported and whether of the linux or solaris variety. Add missing-prototypes, missing-declarations, char-subscripts and cast-qual warnings to default cflags, cause Hasso enjoys warnings, and we really should clean the remaining ones up. (ie isisd..). * (*/*main.c) Update the zebra_capabilities_t arrays in the various daemons to match the changes made in lib/privs.h. * zebra.h: Solaris capabilities requires priv.h to be included. * privs.{c,h}: Add support for Solaris Least-Privileges. privs.h: Reduce some of the abstract capabilities, which do not have rough equivalents on both systems. Rename the net related caps to _NET, as they should have been in first place. (zprivs_terminate) should take the zebra_privs_t as argument so that it can update change pointer. Add an additional privilege state, ZPRIVS_UNKNOWN. * privs.c: (various capability functions) Add Solaris privileges variants. (zprivs_state) Use privs.c specific generic types to represent various capability/privilege related types, so that each can be typedef'd as appropriate on each platform. (zprivs_null_state) static added, to hold the state the null method should report (should be raised by default, and LOWERED if zprivs_terminate has been called) (zprivs_state_null) Report back the zprivs_null_state. (cap_map) Make it able to map abstract capability to multiple system capabilities. (zcaps2sys) Map to abstract capabilities to multiple system privileges/capabilities. (zprivs_init) move capability related init to seperate function, zprivs_caps_init. (zprivs_terminate) ditto, moved to zprivs_caps_terminate. Set the change_state callback to the NULL state, so the user can continue to run and use the callbacks.
2005-09-29 16:39:32 +02:00
ZCAP_NET_ADMIN,
};
struct zebra_privs_t ospfd_privs =
{
#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
.user = QUAGGA_USER,
.group = QUAGGA_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0
};
2002-12-13 21:15:29 +01:00
/* Configuration filename and directory. */
char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG;
/* OSPFd options. */
struct option longopts[] =
{
{ "daemon", no_argument, NULL, 'd'},
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
{ "socket", required_argument, NULL, 'z'},
{ "dryrun", no_argument, NULL, 'C'},
2002-12-13 21:15:29 +01:00
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
2004-10-11 18:27:03 +02:00
{ "apiserver", no_argument, NULL, 'a'},
2002-12-13 21:15:29 +01:00
{ "version", no_argument, NULL, 'v'},
{ 0 }
};
/* OSPFd program name */
/* Master of threads. */
struct thread_master *master;
/* Process ID saved for use by init system */
2004-10-08 10:17:22 +02:00
const char *pid_file = PATH_OSPFD_PID;
2002-12-13 21:15:29 +01:00
#ifdef SUPPORT_OSPF_API
2004-10-12 08:13:54 +02:00
extern int ospf_apiserver_enable;
#endif /* SUPPORT_OSPF_API */
2004-10-11 18:27:03 +02:00
2002-12-13 21:15:29 +01:00
/* Help information display. */
static void __attribute__ ((noreturn))
2002-12-13 21:15:29 +01:00
usage (char *progname, int status)
{
if (status != 0)
fprintf (stderr, "Try `%s --help' for more information.\n", progname);
else
{
printf ("Usage : %s [OPTION...]\n\
Daemon which manages OSPF.\n\n\
-d, --daemon Runs in daemon mode\n\
-f, --config_file Set configuration file name\n\
-i, --pid_file Set process identifier file name\n\
-z, --socket Set path of zebra socket\n\
2002-12-13 21:15:29 +01:00
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
2004-10-11 18:27:03 +02:00
-a. --apiserver Enable OSPF apiserver\n\
2002-12-13 21:15:29 +01:00
-v, --version Print program version\n\
-C, --dryrun Check configuration for validity and exit\n\
2002-12-13 21:15:29 +01:00
-h, --help Display this help and exit\n\
\n\
Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
}
exit (status);
}
2002-12-13 21:15:29 +01:00
/* SIGHUP handler. */
static void
sighup (void)
2002-12-13 21:15:29 +01:00
{
zlog (NULL, LOG_INFO, "SIGHUP received");
}
2005-10-29 Paul Jakma <paul.jakma@sun.com> * (general) RFC3137 stub-router support * ospfd.h: Add OSPF_OUTPUT_COST_INFINITE define. (struct ospf_master) Add a OSPF_MASTER_SHUTDOWN flag for options, to allow shutdown to distinguish between complete shutdown and shutdown of a subset of ospf instances. (struct ospf) Add stub_router_{startup,shutdown_}time, configuration of startup and shutdown time for stub-router. Add t_graceful_shutdown struct thread, timer for graceful shutdown, if needed. (struct ospf_area) Add stub_router_state - run time state of stub-router for an area. Add flags for ADMIN, IS and WAS states. Add t_stub_router, timer thread to resend router-lsa for an area. * ospf_lsa.c: (ospf_link_cost) new simple function to spit out either the given lnks cost or infinite cost if stub-router is in effect. (lsa_link_{ptop,broadcast,virtuallink,ptomp}_set) use previous function for transit-links. (ospf_stub_router_timer) timer thread for end of startup stub router. Change state as required for the area and setup re-origination of router-lsa. (ospf_stub_router_check) Check/do whether stub-router should be enabled, and whether it requires timer to be setup. (ospf_router_lsa_new) call previous function at top. (ospf_router_lsa_originate) no external callers, made static. * ospf_lsa.h: (ospf_router_lsa_originate) removed. * ospf_main.c: (sigint) make static. remove call to exit, as ospf_terminate now deals with exiting. * ospf_route.c: (ospf_terminate) removed, now in ospfd.c. * ospf_vty.c: (show_ip_ospf_area) print out state of stub-router, if active. (show_ip_ospf) print out configuration of stub-router support, and details of graceful-shutdown if the timer is active. ((no)?ospf_max_metric_router_lsa_{admin,startup,shutdown}) new commands to (de-)?configure stub-router support. (config_write_stub_router) write out config of stub-router. (ospf_config_write) call previous. (ospf_vty_init) install the new stub-router commands. * ospfd.c: various functions made static. (ospf_new) Set defaults for stub-router. Graceful shutdown is made to default on, just to be adventerous. (ospf_graceful_shutdown_finish) new function, final part of shutdown. (ospf_graceful_shutdown_timer) timer thread wrapper for graceful-shutdown. (ospf_graceful_shutdown_check) check whether to setup timer for shutdown or proceed directly to final shutdown. (ospf_terminate) moved here from ospf_route.c, call ospf_finish for each instance. (ospf_finish) renamed to ospf_finish_final and made static. (ospf_finish) new function, exported wrapper around ospf_graceful_shutdown_check. (ospf_finish_final) complete shutdown of an instance. Add missing TIMER_OFF's of two timer threads. (ospf_area_free) opaque self lsa timer should be turned off.
2005-10-29 14:50:09 +02:00
/* SIGINT / SIGTERM handler. */
static void
sigint (void)
2002-12-13 21:15:29 +01:00
{
2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * bgp_main.c: (sigint) Use zlog_notice for termination message. (main) Use zlog_notice for startup announcement. * isis_main.c: (sigint,sigterm) Use zlog_notice for termination message. (terminate) This function should be static, not global. (main) Use zlog_notice for startup announcement, and remove ifdef ZEBRA_VERSION. * version.h.in: Remove declaration for pid_output_lock, this function is now static, not global. * pid_output.c: (pid_output_lock) This function should be static, not global. And remove "old umask" error message, since it was really an unimportant debug message, not an error. (pid_output) Need to declare static function pid_output_lock. * ospf6_main.c: (sigint,sigterm) Use zlog_notice for termination message. (main) Remove commented-out call to pid_output_lock (which should never be called other than from inside pid_output). And use zlog_notice to print the startup message, which now includes the vty port. * ospf_main.c: (sigint) Use zlog_notice for termination message. (main) Issue a startup announcement using zlog_notice. * rip_main.c: (sigint) Use zlog_notice for termination message. (main) Add a startup announcement using zlog_notice. * ripng_main.c: (sighup) Remove spurious terminating message. (sigint) Use zlog_notice for termination message. (main) Issue a startup announcement using zlog_notice. * main.c: (sigint) Use zlog_notice for termination message. (main) Add a startup announcement using zlog_notice.
2004-12-03 17:36:46 +01:00
zlog_notice ("Terminating on signal");
2002-12-13 21:15:29 +01:00
ospf_terminate ();
}
/* SIGUSR1 handler. */
static void
sigusr1 (void)
2002-12-13 21:15:29 +01:00
{
zlog_rotate (NULL);
}
struct quagga_signal_t ospf_signals[] =
2002-12-13 21:15:29 +01:00
{
{
.signal = SIGHUP,
.handler = &sighup,
},
{
.signal = SIGUSR1,
.handler = &sigusr1,
},
{
.signal = SIGINT,
.handler = &sigint,
},
{
.signal = SIGTERM,
.handler = &sigint,
},
};
2002-12-13 21:15:29 +01:00
/* OSPFd main routine. */
int
main (int argc, char **argv)
{
char *p;
char *vty_addr = NULL;
int vty_port = OSPF_VTY_PORT;
2002-12-13 21:15:29 +01:00
int daemon_mode = 0;
char *config_file = NULL;
char *progname;
struct thread thread;
int dryrun = 0;
2002-12-13 21:15:29 +01:00
/* Set umask before anything for security */
umask (0027);
#ifdef SUPPORT_OSPF_API
/* OSPF apiserver is disabled by default. */
ospf_apiserver_enable = 0;
#endif /* SUPPORT_OSPF_API */
2002-12-13 21:15:29 +01:00
/* get program name */
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
while (1)
{
int opt;
opt = getopt_long (argc, argv, "df:i:z:hA:P:u:g:avC", longopts, 0);
2002-12-13 21:15:29 +01:00
if (opt == EOF)
break;
switch (opt)
{
case 0:
break;
case 'd':
daemon_mode = 1;
break;
case 'f':
config_file = optarg;
break;
case 'A':
vty_addr = optarg;
break;
case 'i':
pid_file = optarg;
break;
case 'z':
zclient_serv_path_set (optarg);
break;
2002-12-13 21:15:29 +01:00
case 'P':
/* Deal with atoi() returning 0 on failure, and ospfd not
listening on ospfd port... */
if (strcmp(optarg, "0") == 0)
{
vty_port = 0;
break;
}
vty_port = atoi (optarg);
if (vty_port <= 0 || vty_port > 0xffff)
vty_port = OSPF_VTY_PORT;
break;
2004-10-11 18:27:03 +02:00
case 'u':
ospfd_privs.user = optarg;
break;
case 'g':
ospfd_privs.group = optarg;
2004-10-11 18:27:03 +02:00
break;
#ifdef SUPPORT_OSPF_API
2004-10-11 18:27:03 +02:00
case 'a':
ospf_apiserver_enable = 1;
break;
#endif /* SUPPORT_OSPF_API */
2002-12-13 21:15:29 +01:00
case 'v':
print_version (progname);
exit (0);
break;
case 'C':
dryrun = 1;
break;
2002-12-13 21:15:29 +01:00
case 'h':
usage (progname, 0);
break;
default:
usage (progname, 1);
break;
}
}
/* Invoked by a priviledged user? -- endo. */
if (geteuid () != 0)
{
errno = EPERM;
perror (progname);
exit (1);
}
zlog_default = openzlog (progname, ZLOG_OSPF,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
/* OSPF master init. */
ospf_master_init ();
2002-12-13 21:15:29 +01:00
/* Initializations. */
master = om->master;
2002-12-13 21:15:29 +01:00
/* Library inits. */
zprivs_init (&ospfd_privs);
signal_init (master, array_size(ospf_signals), ospf_signals);
2002-12-13 21:15:29 +01:00
cmd_init (1);
debug_init ();
vty_init (master);
2002-12-13 21:15:29 +01:00
memory_init ();
access_list_init ();
prefix_list_init ();
/* OSPFd inits. */
ospf_if_init ();
ospf_zebra_init ();
/* OSPF vty inits. */
ospf_vty_init ();
ospf_vty_show_init ();
ospf_route_map_init ();
#ifdef HAVE_SNMP
ospf_snmp_init ();
#endif /* HAVE_SNMP */
#ifdef HAVE_OPAQUE_LSA
ospf_opaque_init ();
#endif /* HAVE_OPAQUE_LSA */
ospfd: ospfv2-fix-interface-mode-cmd.patch SYMPTOM: Interface mode OSPF area configuration is not retained after restarting quagga. Example - quagga(config)# interface swp49 quagga(config-if)# ip ospf area 0.0.0.0 quagga# sh run <snip> interface swp49 ip ospf area 0.0.0.0 ipv6 nd suppress-ra link-detect ! quagga# write memory * Restart quagga at this point* quagga# sh run <snip> interface swp49 ipv6 nd suppress-ra link-detect ! ISSUE: The issue is that the interface mode commands can reach the OSPF process even before 'router ospf' command that initializes the default OSPF instance, this is not getting handled properly in OSPF process. FIX: Initialize the default OSPF instance during OSPF process initializations, which is before 'router ospf' command is received in OSPF process. So, when interface mode command is received, it is guaranteed to have ospf instance to work with. Other way could be to call ospf_get() instead of ospf_lookup() while processing the config command callbacks, although OSPF needs to have at least one instance structure anyways, therefore calling it unconditionally in OSPF initializations should be fine too. There could be more elaborate fix(es) possible to handle this, like adding some ordering mechanism for commands as they are read by a process, or storing the received command and applying it after the commands its dependent upon are processed. For the issue at hand, initializing the default instance in main() serves the purpose well. Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com> Reviewed-by: Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:32 +02:00
/* Need to initialize the default ospf structure, so the interface mode
commands can be duly processed if they are received before 'router ospf',
when quagga(ospfd) is restarted */
if (!ospf_get())
{
zlog_err("OSPF instance init failed: %s", strerror(errno));
exit (1);
}
2002-12-13 21:15:29 +01:00
/* Get configuration file. */
vty_read_config (config_file, config_default);
2002-12-13 21:15:29 +01:00
/* Start execution only if not in dry-run mode */
if (dryrun)
return(0);
2002-12-13 21:15:29 +01:00
/* Change to the daemon program. */
if (daemon_mode && daemon (0, 0) < 0)
{
zlog_err("OSPFd daemon failed: %s", strerror(errno));
exit (1);
}
2002-12-13 21:15:29 +01:00
/* Process id file create. */
pid_output (pid_file);
/* Create VTY socket */
vty_serv_sock (vty_addr, vty_port, OSPF_VTYSH_PATH);
2002-12-13 21:15:29 +01:00
/* Print banner. */
2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * bgp_main.c: (sigint) Use zlog_notice for termination message. (main) Use zlog_notice for startup announcement. * isis_main.c: (sigint,sigterm) Use zlog_notice for termination message. (terminate) This function should be static, not global. (main) Use zlog_notice for startup announcement, and remove ifdef ZEBRA_VERSION. * version.h.in: Remove declaration for pid_output_lock, this function is now static, not global. * pid_output.c: (pid_output_lock) This function should be static, not global. And remove "old umask" error message, since it was really an unimportant debug message, not an error. (pid_output) Need to declare static function pid_output_lock. * ospf6_main.c: (sigint,sigterm) Use zlog_notice for termination message. (main) Remove commented-out call to pid_output_lock (which should never be called other than from inside pid_output). And use zlog_notice to print the startup message, which now includes the vty port. * ospf_main.c: (sigint) Use zlog_notice for termination message. (main) Issue a startup announcement using zlog_notice. * rip_main.c: (sigint) Use zlog_notice for termination message. (main) Add a startup announcement using zlog_notice. * ripng_main.c: (sighup) Remove spurious terminating message. (sigint) Use zlog_notice for termination message. (main) Issue a startup announcement using zlog_notice. * main.c: (sigint) Use zlog_notice for termination message. (main) Add a startup announcement using zlog_notice.
2004-12-03 17:36:46 +01:00
zlog_notice ("OSPFd %s starting: vty@%d", QUAGGA_VERSION, vty_port);
2002-12-13 21:15:29 +01:00
/* Fetch next active thread. */
while (thread_fetch (master, &thread))
thread_call (&thread);
/* Not reached. */
return (0);
2002-12-13 21:15:29 +01:00
}