1/*
2 * zebra daemon main routine.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "version.h"
26#include "getopt.h"
27#include "command.h"
28#include "thread.h"
29#include "filter.h"
30#include "memory.h"
31#include "prefix.h"
32#ifdef FOX_RIP_DEBUG
33#include "log.h"
34#endif /* FOX_RIP_DEBUG */
35#include "zebra/rib.h"
36#include "zebra/zserv.h"
37#ifdef FOX_RIP_DEBUG
38#include "zebra/debug.h"
39#endif /* FOX_RIP_DEBUG */
40#include "zebra/rib.h"
41
42
43/* Master of threads. */
44struct thread_master *master;
45
46/* process id. */
47pid_t old_pid;
48pid_t pid;
49
50/* Route retain mode flag. */
51int retain_mode = 0;
52
53/* Don't delete kernel route. */
54int keep_kernel_mode = 0;
55
56/* Command line options. */
57struct option longopts[] =
58{
59  { "batch",       no_argument,       NULL, 'b'},
60  { "daemon",      no_argument,       NULL, 'd'},
61  { "keep_kernel", no_argument,       NULL, 'k'},
62  { "log_mode",    no_argument,       NULL, 'l'},
63  { "config_file", required_argument, NULL, 'f'},
64  { "pid_file",    required_argument, NULL, 'i'},
65  { "help",        no_argument,       NULL, 'h'},
66  { "vty_addr",    required_argument, NULL, 'A'},
67  { "vty_port",    required_argument, NULL, 'P'},
68  { "retain",      no_argument,       NULL, 'r'},
69  { "version",     no_argument,       NULL, 'v'},
70  { 0 }
71};
72
73/* Default configuration file path. */
74char config_current[] = DEFAULT_CONFIG_FILE;
75char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE;
76
77/* Process ID saved for use by init system */
78char *pid_file = PATH_ZEBRA_PID;
79
80/* Help information display. */
81static void
82usage (char *progname, int status)
83{
84  if (status != 0)
85    fprintf (stderr, "Try `%s --help' for more information.\n", progname);
86  else
87    {
88      printf ("Usage : %s [OPTION...]\n\n\
89Daemon which manages kernel routing table management and \
90redistribution between different routing protocols.\n\n\
91-b, --batch        Runs in batch mode\n\
92-d, --daemon       Runs in daemon mode\n\
93-f, --config_file  Set configuration file name\n\
94-i, --pid_file     Set process identifier file name\n\
95-k, --keep_kernel  Don't delete old routes which installed by zebra.\n\
96-l, --log_mode     Set verbose log mode flag\n\
97-A, --vty_addr     Set vty's bind address\n\
98-P, --vty_port     Set vty's port number\n\
99-r, --retain       When program terminates, retain added route by zebra.\n\
100-v, --version      Print program version\n\
101-h, --help         Display this help and exit\n\
102\n\
103Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
104    }
105
106  exit (status);
107}
108
109/* SIGHUP handler. */
110void
111sighup (int sig)
112{
113#ifdef FOX_RIP_DEBUG
114  zlog_info ("SIGHUP received");
115#endif /* FOX_RIP_DEBUG */
116  /* Reload of config file. */
117  ;
118}
119
120/* SIGINT handler. */
121void
122sigint (int sig)
123{
124  /* Decrared in rib.c */
125  void rib_close ();
126#ifdef FOX_RIP_DEBUG
127  zlog_info ("Terminating on signal");
128#endif /* FOX_RIP_DEBUG */
129  if (!retain_mode)
130    rib_close ();
131
132  exit (0);
133}
134
135/* SIGUSR1 handler. */
136void
137sigusr1 (int sig)
138{
139#ifdef FOX_RIP_DEBUG
140  zlog_rotate (NULL);
141#endif /* FOX_RIP_DEBUG */
142}
143
144/* Signale wrapper. */
145RETSIGTYPE *
146signal_set (int signo, void (*func)(int))
147{
148  int ret;
149  struct sigaction sig;
150  struct sigaction osig;
151
152  sig.sa_handler = func;
153  sigemptyset (&sig.sa_mask);
154  sig.sa_flags = 0;
155#ifdef SA_RESTART
156  sig.sa_flags |= SA_RESTART;
157#endif /* SA_RESTART */
158
159  ret = sigaction (signo, &sig, &osig);
160
161  if (ret < 0)
162    return (SIG_ERR);
163  else
164    return (osig.sa_handler);
165}
166
167/* Initialization of signal handles. */
168void
169signal_init ()
170{
171  signal_set (SIGHUP, sighup);
172  signal_set (SIGINT, sigint);
173  signal_set (SIGTERM, sigint);
174  signal_set (SIGPIPE, SIG_IGN);
175  signal_set (SIGUSR1, sigusr1);
176}
177
178/* Main startup routine. */
179int
180main (int argc, char **argv)
181{
182  char *p;
183  char *vty_addr = NULL;
184  int vty_port = 0;
185  int batch_mode = 0;
186  int daemon_mode = 0;
187  char *config_file = NULL;
188  char *progname;
189  struct thread thread;
190  void rib_weed_tables ();
191  int Mcast_fox=0;
192
193  /* Set umask before anything for security */
194  umask (0027);
195
196  /* preserve my name */
197  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
198
199#ifdef FOX_RIP_DEBUG
200  zlog_default = openzlog (progname, ZLOG_STDOUT, ZLOG_ZEBRA,
201			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
202#endif /* FOX_RIP_DEBUG */
203  while (1)
204    {
205      int opt;
206
207      opt = getopt_long (argc, argv, "bdklf:hA:P:rvm", longopts, 0);
208
209      if (opt == EOF)
210	break;
211
212      switch (opt)
213	{
214	case 0:
215	  break;
216	case 'b':
217	  batch_mode = 1;
218	case 'd':
219	  daemon_mode = 1;
220	  break;
221	case 'k':
222	  keep_kernel_mode = 1;
223	  break;
224	case 'l':
225	  /* log_mode = 1; */
226	  break;
227	case 'f':
228	  config_file = optarg;
229	  break;
230	case 'A':
231	  vty_addr = optarg;
232	  break;
233        case 'i':
234          pid_file = optarg;
235          break;
236	case 'P':
237	  vty_port = atoi (optarg);
238	  break;
239	case 'r':
240	  retain_mode = 1;
241	  break;
242	case 'v':
243#ifdef FOX_CMD_SUPPORT
244	  print_version (progname);
245#endif /* FOX_RIP_DEBUG */
246	  exit (0);
247	  break;
248	case 'h':
249	  usage (progname, 0);
250	  break;
251	default:
252	  usage (progname, 1);
253	  break;
254	}
255    }
256
257  /* Make master thread emulator. */
258  master = thread_master_create ();
259
260  /* Vty related initialize. */
261  signal_init ();
262  cmd_init (1);
263  vty_init ();
264
265#ifdef FOX_CMD_SUPPORT
266  memory_init ();
267#endif /* FOX_CMD_SUPPORT */
268
269  /* Zebra related initialize. */
270  zebra_init ();
271  rib_init ();
272  zebra_if_init ();
273
274#ifdef FOX_RIP_DEBUG
275  zebra_debug_init ();
276#endif /* FOX_RIP_DEBUG */
277
278  access_list_init ();
279
280#ifdef RTADV
281  rtadv_init ();
282#endif
283
284  /* For debug purpose. */
285  /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
286
287  /* Make kernel routing socket. */
288  kernel_init ();
289  interface_list ();
290  route_read ();
291
292  /* Sort VTY commands. */
293  sort_node ();
294
295#ifdef HAVE_SNMP
296  zebra_snmp_init ();
297#endif /* HAVE_SNMP */
298
299  /* Clean up self inserted route. */
300  if (! keep_kernel_mode)
301    rib_sweep_route ();
302
303  /* Configuration file read*/
304  vty_read_config (config_file, config_current, config_default);
305
306  /* Clean up rib. */
307  rib_weed_tables ();
308
309  /* Exit when zebra is working in batch mode. */
310  if (batch_mode)
311    exit (0);
312
313  /* Needed for BSD routing socket. */
314  old_pid = getpid ();
315
316  /* Daemonize. */
317  if (daemon_mode)
318    daemon (0, 0);
319
320  /* Output pid of zebra. */
321  pid_output (pid_file);
322
323  /* Needed for BSD routing socket. */
324  pid = getpid ();
325
326#ifdef FOX_CMD_SUPPORT
327  /* Make vty server socket. */
328  vty_serv_sock (vty_addr,
329		 vty_port ? vty_port : ZEBRA_VTY_PORT, ZEBRA_VTYSH_PATH);
330#endif /* FOX_CMD_SUPPORT */
331
332  while (thread_fetch (master, &thread))
333    thread_call (&thread);
334
335  /* Not reached... */
336  exit (0);
337}
338