frr/ospf6d/ospf6_main.c
Chirag Shah dd2395e1c6 ospf6d: fix ospf6d crash during sigterm/shutdown
During signterm (shutdown) ospf6_clean calls route_remove
for brouter_table, during route_remove brouter_table remove
hook function is invoked which in turns calls router_remove
is any of the LSA has max age or cost is infinity,
which leads to stack corruption trying to delete same
route node.
Similar to 'no router ospf6' or 'no area ..' command
where lsdb is cleanedup then brouter route table
clean up is called.

Clean some of route trace to have route related fields.

Ticket:CM-17932

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-10-06 10:01:46 -07:00

213 lines
4.1 KiB
C

/*
* Copyright (C) 1999 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 this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include <lib/version.h>
#include <stdlib.h>
#include "getopt.h"
#include "thread.h"
#include "log.h"
#include "command.h"
#include "vty.h"
#include "memory.h"
#include "memory_vty.h"
#include "if.h"
#include "filter.h"
#include "prefix.h"
#include "plist.h"
#include "privs.h"
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
#include "bfd.h"
#include "libfrr.h"
#include "ospf6d.h"
#include "ospf6_top.h"
#include "ospf6_message.h"
#include "ospf6_asbr.h"
#include "ospf6_lsa.h"
#include "ospf6_interface.h"
#include "ospf6_zebra.h"
/* Default configuration file name for ospf6d. */
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
/* Default port values. */
#define OSPF6_VTY_PORT 2606
/* ospf6d privileges */
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
struct zebra_privs_t ospf6d_privs = {
#if defined(FRR_USER)
.user = FRR_USER,
#endif
#if defined FRR_GROUP
.group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = 2,
.cap_num_i = 0};
/* ospf6d options, we use GNU getopt library. */
struct option longopts[] = {{0}};
/* Master of threads. */
struct thread_master *master;
static void __attribute__((noreturn)) ospf6_exit(int status)
{
struct listnode *node;
struct interface *ifp;
frr_early_fini();
if (ospf6)
ospf6_delete(ospf6);
bfd_gbl_exit();
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
if (ifp->info != NULL)
ospf6_interface_delete(ifp->info);
ospf6_message_terminate();
ospf6_asbr_terminate();
ospf6_lsa_terminate();
vrf_terminate();
if (zclient) {
zclient_stop(zclient);
zclient_free(zclient);
}
frr_fini();
exit(status);
}
/* SIGHUP handler. */
static void sighup(void)
{
zlog_info("SIGHUP received");
}
/* SIGINT handler. */
static void sigint(void)
{
zlog_notice("Terminating on signal SIGINT");
ospf6_exit(0);
}
/* SIGTERM handler. */
static void sigterm(void)
{
zlog_notice("Terminating on signal SIGTERM");
ospf6_exit(0);
}
/* SIGUSR1 handler. */
static void sigusr1(void)
{
zlog_info("SIGUSR1 received");
zlog_rotate();
}
struct quagga_signal_t ospf6_signals[] = {
{
.signal = SIGHUP,
.handler = &sighup,
},
{
.signal = SIGINT,
.handler = &sigint,
},
{
.signal = SIGTERM,
.handler = &sigterm,
},
{
.signal = SIGUSR1,
.handler = &sigusr1,
},
};
FRR_DAEMON_INFO(ospf6d, OSPF6, .vty_port = OSPF6_VTY_PORT,
.proghelp = "Implementation of the OSPFv3 routing protocol.",
.signals = ospf6_signals,
.n_signals = array_size(ospf6_signals),
.privs = &ospf6d_privs, )
/* Main routine of ospf6d. Treatment of argument and starting ospf finite
state machine is handled here. */
int main(int argc, char *argv[], char *envp[])
{
int opt;
frr_preinit(&ospf6d_di, argc, argv);
frr_opt_add("", longopts, "");
/* Command line argument treatment. */
while (1) {
opt = frr_getopt(argc, argv, NULL);
if (opt == EOF)
break;
switch (opt) {
case 0:
break;
default:
frr_help_exit(1);
break;
}
}
if (geteuid() != 0) {
errno = EPERM;
perror(ospf6d_di.progname);
exit(1);
}
/* thread master */
master = frr_init();
vrf_init(NULL, NULL, NULL, NULL);
access_list_init();
prefix_list_init();
/* initialize ospf6 */
ospf6_init();
frr_config_fork();
frr_run(master);
/* Not reached. */
ospf6_exit(0);
}