blob: be46f3fee3a03a9bcfce6984bf649e87e225fb90 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Copyright (C) 1999 Yasuhiro Ohara
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
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23#include "getopt.h"
24#include "thread.h"
25#include "log.h"
26#include "version.h"
27#include "command.h"
28#include "vty.h"
29#include "memory.h"
pauledd7c242003-06-04 13:59:38 +000030#include "privs.h"
paul718e3742002-12-13 20:15:29 +000031
32#include "ospf6d.h"
33#include "ospf6_network.h"
34
35void ospf6_init ();
36void ospf6_terminate ();
37void nexthop_init ();
38int ospf6_receive (struct thread *);
39
40extern int ospf6_sock;
41
42/* Default configuration file name for ospf6d. */
43#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
44/* Default port values. */
45#define OSPF6_VTY_PORT 2606
46
pauledd7c242003-06-04 13:59:38 +000047/* ospf6d privileges */
48zebra_capabilities_t _caps_p [] =
49{
50 ZCAP_RAW,
51 ZCAP_BIND
52};
53
54struct zebra_privs_t ospf6d_privs =
55{
pauld81fadf2003-08-14 05:32:12 +000056#if defined(QUAGGA_USER)
57 .user = QUAGGA_USER,
pauledd7c242003-06-04 13:59:38 +000058#endif
pauld81fadf2003-08-14 05:32:12 +000059#if defined QUAGGA_GROUP
60 .group = QUAGGA_GROUP,
61#endif
62#ifdef VTY_GROUP
63 .vty_group = VTY_GROUP,
pauledd7c242003-06-04 13:59:38 +000064#endif
65 .caps_p = _caps_p,
66 .cap_num_p = 2,
67 .cap_num_i = 0
68};
69
paul718e3742002-12-13 20:15:29 +000070/* ospf6d options, we use GNU getopt library. */
71struct option longopts[] =
72{
73 { "daemon", no_argument, NULL, 'd'},
74 { "config_file", required_argument, NULL, 'f'},
75 { "pid_file", required_argument, NULL, 'i'},
76 { "vty_addr", required_argument, NULL, 'A'},
77 { "vty_port", required_argument, NULL, 'P'},
pauledd7c242003-06-04 13:59:38 +000078 { "user", required_argument, NULL, 'u'},
paul718e3742002-12-13 20:15:29 +000079 { "version", no_argument, NULL, 'v'},
80 { "help", no_argument, NULL, 'h'},
81 { 0 }
82};
83
84/* Configuration file and directory. */
85char config_current[] = OSPF6_DEFAULT_CONFIG;
86char config_default[] = SYSCONFDIR OSPF6_DEFAULT_CONFIG;
87
88/* ospf6d program name. */
89
90/* is daemon? */
91int daemon_mode = 0;
92
93/* Master of threads. */
94struct thread_master *master;
95
96/* Process ID saved for use by init system */
97char *pid_file = PATH_OSPF6D_PID;
98
99/* for reload */
100char _cwd[64];
101char _progpath[64];
102int _argc;
103char **_argv;
104char **_envp;
105
106/* Help information display. */
107static void
108usage (char *progname, int status)
109{
110 if (status != 0)
111 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
112 else
113 {
114 printf ("Usage : %s [OPTION...]\n\n\
115Daemon which manages OSPF version 3.\n\n\
116-d, --daemon Runs in daemon mode\n\
117-f, --config_file Set configuration file name\n\
118-i, --pid_file Set process identifier file name\n\
119-A, --vty_addr Set vty's bind address\n\
120-P, --vty_port Set vty's port number\n\
pauledd7c242003-06-04 13:59:38 +0000121-u, --user User and group to run as\n\
paul718e3742002-12-13 20:15:29 +0000122-v, --version Print program version\n\
123-h, --help Display this help and exit\n\
124\n\
125Report bugs to yasu@sfc.wide.ad.jp\n", progname);
126 }
127
128 exit (status);
129}
130
131
132void
133_reload ()
134{
135 zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) reloaded",
paule8f29842003-08-12 13:08:31 +0000136 QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
paul718e3742002-12-13 20:15:29 +0000137 ospf6_zebra_finish ();
138 vty_finish ();
139 execve (_progpath, _argv, _envp);
140}
141
142void
143terminate (int i)
144{
145 ospf6_delete (ospf6);
146 unlink (PATH_OSPF6D_PID);
147 zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) terminated",
paule8f29842003-08-12 13:08:31 +0000148 QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
paul718e3742002-12-13 20:15:29 +0000149 exit (i);
150}
151
152/* SIGHUP handler. */
153void
154sighup (int sig)
155{
156 zlog_info ("SIGHUP received");
157 _reload ();
158}
159
160/* SIGINT handler. */
161void
162sigint (int sig)
163{
164 zlog_info ("SIGINT received");
165 terminate (0);
166}
167
168/* SIGTERM handler. */
169void
170sigterm (int sig)
171{
172 zlog_info ("SIGTERM received");
173 terminate (0);
174}
175
176/* SIGUSR1 handler. */
177void
178sigusr1 (int sig)
179{
180 zlog_info ("SIGUSR1 received");
181 zlog_rotate (NULL);
182}
183
184/* Signale wrapper. */
185RETSIGTYPE *
186signal_set (int signo, void (*func)(int))
187{
188 int ret;
189 struct sigaction sig;
190 struct sigaction osig;
191
192 sig.sa_handler = func;
193 sigemptyset (&sig.sa_mask);
194 sig.sa_flags = 0;
195#ifdef SA_RESTART
196 sig.sa_flags |= SA_RESTART;
197#endif /* SA_RESTART */
198
199 ret = sigaction (signo, &sig, &osig);
200
201 if (ret < 0)
202 return (SIG_ERR);
203 else
204 return (osig.sa_handler);
205}
206
207/* Initialization of signal handles. */
208void
209signal_init ()
210{
211 signal_set (SIGHUP, sighup);
212 signal_set (SIGINT, sigint);
213 signal_set (SIGTERM, sigterm);
214 signal_set (SIGPIPE, SIG_IGN);
215#ifdef SIGTSTP
216 signal_set (SIGTSTP, SIG_IGN);
217#endif
218#ifdef SIGTTIN
219 signal_set (SIGTTIN, SIG_IGN);
220#endif
221#ifdef SIGTTOU
222 signal_set (SIGTTOU, SIG_IGN);
223#endif
224 signal_set (SIGUSR1, sigusr1);
225}
226
227/* Main routine of ospf6d. Treatment of argument and start ospf finite
228 state machine is handled here. */
229int
230main (int argc, char *argv[], char *envp[])
231{
232 char *p;
233 int opt;
234 char *vty_addr = NULL;
paul4fc4e7a2003-01-22 19:47:09 +0000235 int vty_port = OSPF6_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000236 char *config_file = NULL;
237 char *progname;
238 struct thread thread;
239 int flag;
240
241 /* Set umask before anything for security */
242 umask (0027);
243
244 /* Preserve name of myself. */
245 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
246
247 /* for reload */
248 _argc = argc;
249 _argv = argv;
250 _envp = envp;
251 getcwd (_cwd, sizeof (_cwd));
252 if (*argv[0] == '.')
253 snprintf (_progpath, sizeof (_progpath), "%s/%s", _cwd, _argv[0]);
254 else
255 snprintf (_progpath, sizeof (_progpath), "%s", argv[0]);
256
257 /* Command line argument treatment. */
258 while (1)
259 {
paul96735ee2003-08-10 02:51:22 +0000260 opt = getopt_long (argc, argv, "df:i:hp:A:P:u:v", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000261
262 if (opt == EOF)
263 break;
264
265 switch (opt)
266 {
267 case 0:
268 break;
269 case 'd':
270 daemon_mode = 1;
271 break;
272 case 'f':
273 config_file = optarg;
274 break;
275 case 'A':
276 vty_addr = optarg;
277 break;
278 case 'i':
279 pid_file = optarg;
280 break;
281 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000282 /* Deal with atoi() returning 0 on failure, and ospf6d not
283 listening on ospf6d port... */
284 if (strcmp(optarg, "0") == 0)
285 {
286 vty_port = 0;
287 break;
288 }
paul718e3742002-12-13 20:15:29 +0000289 vty_port = atoi (optarg);
paul4fc4e7a2003-01-22 19:47:09 +0000290 vty_port = (vty_port ? vty_port : OSPF6_VTY_PORT);
291 break;
pauledd7c242003-06-04 13:59:38 +0000292 case 'u':
293 ospf6d_privs.user = ospf6d_privs.group = optarg;
294 break;
paul718e3742002-12-13 20:15:29 +0000295 case 'v':
296 print_version (progname);
297 exit (0);
298 break;
299 case 'h':
300 usage (progname, 0);
301 break;
302 default:
303 usage (progname, 1);
304 break;
305 }
306 }
307
308 /* thread master */
309 master = thread_master_create ();
310
311 /* Initializations. */
312 if (! daemon_mode)
313 flag = ZLOG_STDOUT;
314 else
hassoe26bbeb2003-05-25 21:39:29 +0000315 flag = ZLOG_NOLOG;
paul718e3742002-12-13 20:15:29 +0000316
317 zlog_default = openzlog (progname, flag, ZLOG_OSPF6,
hassoe26bbeb2003-05-25 21:39:29 +0000318 LOG_CONS|LOG_NDELAY|LOG_PID,
paul718e3742002-12-13 20:15:29 +0000319 LOG_DAEMON);
pauledd7c242003-06-04 13:59:38 +0000320 zprivs_init (&ospf6d_privs);
paul718e3742002-12-13 20:15:29 +0000321 signal_init ();
322 cmd_init (1);
paulb21b19c2003-06-15 01:28:29 +0000323 vty_init (master);
paul718e3742002-12-13 20:15:29 +0000324 ospf6_init ();
325 memory_init ();
326 sort_node ();
327
328 /* parse config file */
329 vty_read_config (config_file, config_current, config_default);
330
331 if (daemon_mode)
332 daemon (0, 0);
333
334 /* pid file create */
335#if 0
336 pid_output_lock (pid_file);
337#else
338 pid_output (pid_file);
339#endif
340
341 /* Make ospf protocol socket. */
342 ospf6_serv_sock ();
343 thread_add_read (master, ospf6_receive, NULL, ospf6_sock);
344
345 /* Make ospf vty socket. */
paul4fc4e7a2003-01-22 19:47:09 +0000346 vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
paul718e3742002-12-13 20:15:29 +0000347
hassoe26bbeb2003-05-25 21:39:29 +0000348#ifdef DEBUG
paul718e3742002-12-13 20:15:29 +0000349 /* Print start message */
350 zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) starts",
paule8f29842003-08-12 13:08:31 +0000351 QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
hassoe26bbeb2003-05-25 21:39:29 +0000352#endif
paul718e3742002-12-13 20:15:29 +0000353
354 /* Start finite state machine, here we go! */
355 while (thread_fetch (master, &thread))
356 thread_call (&thread);
357
358 /* Log in case thread failed */
359 zlog_warn ("Thread failed");
360 terminate (0);
361
362 /* Not reached. */
363 exit (0);
364}
365