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