1/* zebra daemon main routine. 2 * Copyright (C) 1997, 98 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#include <lib/version.h> 25#include "getopt.h" 26#include "command.h" 27#include "thread.h" 28#include "filter.h" 29#include "memory.h" 30#include "prefix.h" 31#include "log.h" 32#include "plist.h" 33#include "privs.h" 34#include "sigevent.h" 35 36#include "zebra/rib.h" 37#include "zebra/zserv.h" 38#include "zebra/debug.h" 39#include "zebra/router-id.h" 40#include "zebra/irdp.h" 41#include "zebra/rtadv.h" 42#include "zebra/zebra_fpm.h" 43 44/* Zebra instance */ 45struct zebra_t zebrad = 46{ 47 .rtm_table_default = 0, 48}; 49 50/* process id. */ 51pid_t pid; 52 53/* Pacify zclient.o in libzebra, which expects this variable. */ 54struct thread_master *master; 55 56/* Route retain mode flag. */ 57int retain_mode = 0; 58 59/* Don't delete kernel route. */ 60int keep_kernel_mode = 0; 61 62#ifdef HAVE_NETLINK 63/* Receive buffer size for netlink socket */ 64u_int32_t nl_rcvbufsize = 0; 65#endif /* HAVE_NETLINK */ 66 67/* Command line options. */ 68struct option longopts[] = 69{ 70 { "batch", no_argument, NULL, 'b'}, 71 { "daemon", no_argument, NULL, 'd'}, 72 { "keep_kernel", no_argument, NULL, 'k'}, 73 { "config_file", required_argument, NULL, 'f'}, 74 { "pid_file", required_argument, NULL, 'i'}, 75 { "socket", required_argument, NULL, 'z'}, 76 { "help", no_argument, NULL, 'h'}, 77 { "vty_addr", required_argument, NULL, 'A'}, 78 { "vty_port", required_argument, NULL, 'P'}, 79 { "retain", no_argument, NULL, 'r'}, 80 { "dryrun", no_argument, NULL, 'C'}, 81#ifdef HAVE_NETLINK 82 { "nl-bufsize", required_argument, NULL, 's'}, 83#endif /* HAVE_NETLINK */ 84 { "user", required_argument, NULL, 'u'}, 85 { "group", required_argument, NULL, 'g'}, 86 { "version", no_argument, NULL, 'v'}, 87 { 0 } 88}; 89 90zebra_capabilities_t _caps_p [] = 91{ 92 ZCAP_NET_ADMIN, 93 ZCAP_SYS_ADMIN, 94 ZCAP_NET_RAW, 95}; 96 97/* zebra privileges to run with */ 98struct zebra_privs_t zserv_privs = 99{ 100#if defined(QUAGGA_USER) && defined(QUAGGA_GROUP) 101 .user = QUAGGA_USER, 102 .group = QUAGGA_GROUP, 103#endif 104#ifdef VTY_GROUP 105 .vty_group = VTY_GROUP, 106#endif 107 .caps_p = _caps_p, 108 .cap_num_p = array_size(_caps_p), 109 .cap_num_i = 0 110}; 111 112/* Default configuration file path. */ 113char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE; 114 115/* Process ID saved for use by init system */ 116const char *pid_file = PATH_ZEBRA_PID; 117 118/* Help information display. */ 119static void 120usage (char *progname, int status) 121{ 122 if (status != 0) 123 fprintf (stderr, "Try `%s --help' for more information.\n", progname); 124 else 125 { 126 printf ("Usage : %s [OPTION...]\n\n"\ 127 "Daemon which manages kernel routing table management and "\ 128 "redistribution between different routing protocols.\n\n"\ 129 "-b, --batch Runs in batch mode\n"\ 130 "-d, --daemon Runs in daemon mode\n"\ 131 "-f, --config_file Set configuration file name\n"\ 132 "-i, --pid_file Set process identifier file name\n"\ 133 "-z, --socket Set path of zebra socket\n"\ 134 "-k, --keep_kernel Don't delete old routes which installed by "\ 135 "zebra.\n"\ 136 "-C, --dryrun Check configuration for validity and exit\n"\ 137 "-A, --vty_addr Set vty's bind address\n"\ 138 "-P, --vty_port Set vty's port number\n"\ 139 "-r, --retain When program terminates, retain added route "\ 140 "by zebra.\n"\ 141 "-u, --user User to run as\n"\ 142 "-g, --group Group to run as\n", progname); 143#ifdef HAVE_NETLINK 144 printf ("-s, --nl-bufsize Set netlink receive buffer size\n"); 145#endif /* HAVE_NETLINK */ 146 printf ("-v, --version Print program version\n"\ 147 "-h, --help Display this help and exit\n"\ 148 "\n"\ 149 "Report bugs to %s\n", ZEBRA_BUG_ADDRESS); 150 } 151 152 exit (status); 153} 154 155/* SIGHUP handler. */ 156static void 157sighup (void) 158{ 159 zlog_info ("SIGHUP received"); 160 161 /* Reload of config file. */ 162 ; 163} 164 165/* SIGINT handler. */ 166static void 167sigint (void) 168{ 169 zlog_notice ("Terminating on signal"); 170 171 if (!retain_mode) 172 rib_close (); 173#ifdef HAVE_IRDP 174 irdp_finish(); 175#endif 176 177 exit (0); 178} 179 180/* SIGUSR1 handler. */ 181static void 182sigusr1 (void) 183{ 184 zlog_rotate (NULL); 185} 186 187struct quagga_signal_t zebra_signals[] = 188{ 189 { 190 .signal = SIGHUP, 191 .handler = &sighup, 192 }, 193 { 194 .signal = SIGUSR1, 195 .handler = &sigusr1, 196 }, 197 { 198 .signal = SIGINT, 199 .handler = &sigint, 200 }, 201 { 202 .signal = SIGTERM, 203 .handler = &sigint, 204 }, 205}; 206 207/* Main startup routine. */ 208int 209main (int argc, char **argv) 210{ 211 char *p; 212 char *vty_addr = NULL; 213 int vty_port = ZEBRA_VTY_PORT; 214 int dryrun = 0; 215 int batch_mode = 0; 216 int daemon_mode = 0; 217 char *config_file = NULL; 218 char *progname; 219 struct thread thread; 220 char *zserv_path = NULL; 221 222 /* Set umask before anything for security */ 223 umask (0027); 224 225 /* preserve my name */ 226 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); 227 228 zlog_default = openzlog (progname, ZLOG_ZEBRA, 229 LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); 230 231 while (1) 232 { 233 int opt; 234 235#ifdef HAVE_NETLINK 236 opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vs:C", longopts, 0); 237#else 238 opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vC", longopts, 0); 239#endif /* HAVE_NETLINK */ 240 241 if (opt == EOF) 242 break; 243 244 switch (opt) 245 { 246 case 0: 247 break; 248 case 'b': 249 batch_mode = 1; 250 case 'd': 251 daemon_mode = 1; 252 break; 253 case 'k': 254 keep_kernel_mode = 1; 255 break; 256 case 'C': 257 dryrun = 1; 258 break; 259 case 'f': 260 config_file = optarg; 261 break; 262 case 'A': 263 vty_addr = optarg; 264 break; 265 case 'i': 266 pid_file = optarg; 267 break; 268 case 'z': 269 zserv_path = optarg; 270 break; 271 case 'P': 272 /* Deal with atoi() returning 0 on failure, and zebra not 273 listening on zebra port... */ 274 if (strcmp(optarg, "0") == 0) 275 { 276 vty_port = 0; 277 break; 278 } 279 vty_port = atoi (optarg); 280 if (vty_port <= 0 || vty_port > 0xffff) 281 vty_port = ZEBRA_VTY_PORT; 282 break; 283 case 'r': 284 retain_mode = 1; 285 break; 286#ifdef HAVE_NETLINK 287 case 's': 288 nl_rcvbufsize = atoi (optarg); 289 break; 290#endif /* HAVE_NETLINK */ 291 case 'u': 292 zserv_privs.user = optarg; 293 break; 294 case 'g': 295 zserv_privs.group = optarg; 296 break; 297 case 'v': 298 print_version (progname); 299 exit (0); 300 break; 301 case 'h': 302 usage (progname, 0); 303 break; 304 default: 305 usage (progname, 1); 306 break; 307 } 308 } 309 310 /* Make master thread emulator. */ 311 zebrad.master = thread_master_create (); 312 313 /* privs initialise */ 314 zprivs_init (&zserv_privs); 315 316 /* Vty related initialize. */ 317 signal_init (zebrad.master, array_size(zebra_signals), zebra_signals); 318 cmd_init (1); 319 vty_init (zebrad.master); 320 memory_init (); 321 322 /* Zebra related initialize. */ 323 zebra_init (); 324 rib_init (); 325 zebra_if_init (); 326 zebra_debug_init (); 327 router_id_init(); 328 zebra_vty_init (); 329 access_list_init (); 330 prefix_list_init (); 331#ifdef RTADV 332 rtadv_init (); 333#endif 334#ifdef HAVE_IRDP 335 irdp_init(); 336#endif 337 338 /* For debug purpose. */ 339 /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ 340 341 /* Make kernel routing socket. */ 342 kernel_init (); 343 interface_list (); 344 route_read (); 345 346#ifdef HAVE_SNMP 347 zebra_snmp_init (); 348#endif /* HAVE_SNMP */ 349 350#ifdef HAVE_FPM 351 zfpm_init (zebrad.master, 1, 0); 352#else 353 zfpm_init (zebrad.master, 0, 0); 354#endif 355 356 /* Process the configuration file. Among other configuration 357 * directives we can meet those installing static routes. Such 358 * requests will not be executed immediately, but queued in 359 * zebra->ribq structure until we enter the main execution loop. 360 * The notifications from kernel will show originating PID equal 361 * to that after daemon() completes (if ever called). 362 */ 363 vty_read_config (config_file, config_default); 364 365 /* Don't start execution if we are in dry-run mode */ 366 if (dryrun) 367 return(0); 368 369 /* Clean up rib. */ 370 rib_weed_tables (); 371 372 /* Exit when zebra is working in batch mode. */ 373 if (batch_mode) 374 exit (0); 375 376 /* Daemonize. */ 377 if (daemon_mode && daemon (0, 0) < 0) 378 { 379 zlog_err("Zebra daemon failed: %s", strerror(errno)); 380 exit (1); 381 } 382 383 /* Output pid of zebra. */ 384 pid_output (pid_file); 385 386 /* After we have successfully acquired the pidfile, we can be sure 387 * about being the only copy of zebra process, which is submitting 388 * changes to the FIB. 389 * Clean up zebra-originated routes. The requests will be sent to OS 390 * immediately, so originating PID in notifications from kernel 391 * will be equal to the current getpid(). To know about such routes, 392 * we have to have route_read() called before. 393 */ 394 if (! keep_kernel_mode) 395 rib_sweep_route (); 396 397 /* Needed for BSD routing socket. */ 398 pid = getpid (); 399 400 /* This must be done only after locking pidfile (bug #403). */ 401 zebra_zserv_socket_init (zserv_path); 402 403 /* Make vty server socket. */ 404 vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH); 405 406 /* Print banner. */ 407 zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port); 408 409 while (thread_fetch (zebrad.master, &thread)) 410 thread_call (&thread); 411 412 /* Not reached... */ 413 return 0; 414} 415