blob: f0a23ebc237b978cb1b609781e971277bfdeaaaf [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 */
hassofa2b17e2004-03-04 17:45:00 +0000100
101#ifdef MAXPATHLEN
102char _cwd[MAXPATHLEN];
103#else
paul718e3742002-12-13 20:15:29 +0000104char _cwd[64];
hassofa2b17e2004-03-04 17:45:00 +0000105#endif
106
paul718e3742002-12-13 20:15:29 +0000107char _progpath[64];
108int _argc;
109char **_argv;
110char **_envp;
111
112/* Help information display. */
113static void
114usage (char *progname, int status)
115{
116 if (status != 0)
117 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
118 else
119 {
120 printf ("Usage : %s [OPTION...]\n\n\
121Daemon which manages OSPF version 3.\n\n\
122-d, --daemon Runs in daemon mode\n\
123-f, --config_file Set configuration file name\n\
124-i, --pid_file Set process identifier file name\n\
125-A, --vty_addr Set vty's bind address\n\
126-P, --vty_port Set vty's port number\n\
pauledd7c242003-06-04 13:59:38 +0000127-u, --user User and group to run as\n\
paul718e3742002-12-13 20:15:29 +0000128-v, --version Print program version\n\
129-h, --help Display this help and exit\n\
130\n\
131Report bugs to yasu@sfc.wide.ad.jp\n", progname);
132 }
133
134 exit (status);
135}
136
137
138void
139_reload ()
140{
141 zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) reloaded",
paule8f29842003-08-12 13:08:31 +0000142 QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
paul718e3742002-12-13 20:15:29 +0000143 ospf6_zebra_finish ();
144 vty_finish ();
145 execve (_progpath, _argv, _envp);
146}
147
148void
149terminate (int i)
150{
151 ospf6_delete (ospf6);
152 unlink (PATH_OSPF6D_PID);
153 zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) terminated",
paule8f29842003-08-12 13:08:31 +0000154 QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
paul718e3742002-12-13 20:15:29 +0000155 exit (i);
156}
157
158/* SIGHUP handler. */
159void
160sighup (int sig)
161{
162 zlog_info ("SIGHUP received");
163 _reload ();
164}
165
166/* SIGINT handler. */
167void
168sigint (int sig)
169{
170 zlog_info ("SIGINT received");
171 terminate (0);
172}
173
174/* SIGTERM handler. */
175void
176sigterm (int sig)
177{
178 zlog_info ("SIGTERM received");
179 terminate (0);
180}
181
182/* SIGUSR1 handler. */
183void
184sigusr1 (int sig)
185{
186 zlog_info ("SIGUSR1 received");
187 zlog_rotate (NULL);
188}
189
190/* Signale wrapper. */
191RETSIGTYPE *
192signal_set (int signo, void (*func)(int))
193{
194 int ret;
195 struct sigaction sig;
196 struct sigaction osig;
197
198 sig.sa_handler = func;
199 sigemptyset (&sig.sa_mask);
200 sig.sa_flags = 0;
201#ifdef SA_RESTART
202 sig.sa_flags |= SA_RESTART;
203#endif /* SA_RESTART */
204
205 ret = sigaction (signo, &sig, &osig);
206
207 if (ret < 0)
208 return (SIG_ERR);
209 else
210 return (osig.sa_handler);
211}
212
213/* Initialization of signal handles. */
214void
215signal_init ()
216{
217 signal_set (SIGHUP, sighup);
218 signal_set (SIGINT, sigint);
219 signal_set (SIGTERM, sigterm);
220 signal_set (SIGPIPE, SIG_IGN);
221#ifdef SIGTSTP
222 signal_set (SIGTSTP, SIG_IGN);
223#endif
224#ifdef SIGTTIN
225 signal_set (SIGTTIN, SIG_IGN);
226#endif
227#ifdef SIGTTOU
228 signal_set (SIGTTOU, SIG_IGN);
229#endif
230 signal_set (SIGUSR1, sigusr1);
231}
232
233/* Main routine of ospf6d. Treatment of argument and start ospf finite
234 state machine is handled here. */
235int
236main (int argc, char *argv[], char *envp[])
237{
238 char *p;
239 int opt;
240 char *vty_addr = NULL;
paul4fc4e7a2003-01-22 19:47:09 +0000241 int vty_port = OSPF6_VTY_PORT;
paul718e3742002-12-13 20:15:29 +0000242 char *config_file = NULL;
243 char *progname;
244 struct thread thread;
245 int flag;
246
247 /* Set umask before anything for security */
248 umask (0027);
249
250 /* Preserve name of myself. */
251 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
252
253 /* for reload */
254 _argc = argc;
255 _argv = argv;
256 _envp = envp;
257 getcwd (_cwd, sizeof (_cwd));
258 if (*argv[0] == '.')
259 snprintf (_progpath, sizeof (_progpath), "%s/%s", _cwd, _argv[0]);
260 else
261 snprintf (_progpath, sizeof (_progpath), "%s", argv[0]);
262
263 /* Command line argument treatment. */
264 while (1)
265 {
paul96735ee2003-08-10 02:51:22 +0000266 opt = getopt_long (argc, argv, "df:i:hp:A:P:u:v", longopts, 0);
paul718e3742002-12-13 20:15:29 +0000267
268 if (opt == EOF)
269 break;
270
271 switch (opt)
272 {
273 case 0:
274 break;
275 case 'd':
276 daemon_mode = 1;
277 break;
278 case 'f':
279 config_file = optarg;
280 break;
281 case 'A':
282 vty_addr = optarg;
283 break;
284 case 'i':
285 pid_file = optarg;
286 break;
287 case 'P':
paul4fc4e7a2003-01-22 19:47:09 +0000288 /* Deal with atoi() returning 0 on failure, and ospf6d not
289 listening on ospf6d port... */
290 if (strcmp(optarg, "0") == 0)
291 {
292 vty_port = 0;
293 break;
294 }
paul718e3742002-12-13 20:15:29 +0000295 vty_port = atoi (optarg);
paul4fc4e7a2003-01-22 19:47:09 +0000296 vty_port = (vty_port ? vty_port : OSPF6_VTY_PORT);
297 break;
pauledd7c242003-06-04 13:59:38 +0000298 case 'u':
299 ospf6d_privs.user = ospf6d_privs.group = optarg;
300 break;
paul718e3742002-12-13 20:15:29 +0000301 case 'v':
302 print_version (progname);
303 exit (0);
304 break;
305 case 'h':
306 usage (progname, 0);
307 break;
308 default:
309 usage (progname, 1);
310 break;
311 }
312 }
313
314 /* thread master */
315 master = thread_master_create ();
316
317 /* Initializations. */
318 if (! daemon_mode)
319 flag = ZLOG_STDOUT;
320 else
hassoe26bbeb2003-05-25 21:39:29 +0000321 flag = ZLOG_NOLOG;
paul718e3742002-12-13 20:15:29 +0000322
323 zlog_default = openzlog (progname, flag, ZLOG_OSPF6,
hassoe26bbeb2003-05-25 21:39:29 +0000324 LOG_CONS|LOG_NDELAY|LOG_PID,
paul718e3742002-12-13 20:15:29 +0000325 LOG_DAEMON);
pauledd7c242003-06-04 13:59:38 +0000326 zprivs_init (&ospf6d_privs);
paul718e3742002-12-13 20:15:29 +0000327 signal_init ();
328 cmd_init (1);
paulb21b19c2003-06-15 01:28:29 +0000329 vty_init (master);
paul718e3742002-12-13 20:15:29 +0000330 ospf6_init ();
331 memory_init ();
332 sort_node ();
333
334 /* parse config file */
335 vty_read_config (config_file, config_current, config_default);
336
337 if (daemon_mode)
338 daemon (0, 0);
339
340 /* pid file create */
341#if 0
342 pid_output_lock (pid_file);
343#else
344 pid_output (pid_file);
345#endif
346
347 /* Make ospf protocol socket. */
348 ospf6_serv_sock ();
349 thread_add_read (master, ospf6_receive, NULL, ospf6_sock);
350
351 /* Make ospf vty socket. */
paul4fc4e7a2003-01-22 19:47:09 +0000352 vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
paul718e3742002-12-13 20:15:29 +0000353
hassoe26bbeb2003-05-25 21:39:29 +0000354#ifdef DEBUG
paul718e3742002-12-13 20:15:29 +0000355 /* Print start message */
356 zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) starts",
paule8f29842003-08-12 13:08:31 +0000357 QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
hassoe26bbeb2003-05-25 21:39:29 +0000358#endif
paul718e3742002-12-13 20:15:29 +0000359
360 /* Start finite state machine, here we go! */
361 while (thread_fetch (master, &thread))
362 thread_call (&thread);
363
364 /* Log in case thread failed */
365 zlog_warn ("Thread failed");
366 terminate (0);
367
368 /* Not reached. */
369 exit (0);
370}
371