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