]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_main.c
Merge remote-tracking branch 'origin/stable/2.0'
[mirror_frr.git] / ospf6d / ospf6_main.c
1 /*
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 <lib/version.h>
24 #include <stdlib.h>
25
26 #include "getopt.h"
27 #include "thread.h"
28 #include "log.h"
29 #include "command.h"
30 #include "vty.h"
31 #include "memory.h"
32 #include "memory_vty.h"
33 #include "if.h"
34 #include "filter.h"
35 #include "prefix.h"
36 #include "plist.h"
37 #include "privs.h"
38 #include "sigevent.h"
39 #include "zclient.h"
40 #include "vrf.h"
41 #include "bfd.h"
42 #include "sockopt.h"
43
44 #include "ospf6d.h"
45 #include "ospf6_top.h"
46 #include "ospf6_message.h"
47 #include "ospf6_asbr.h"
48 #include "ospf6_lsa.h"
49 #include "ospf6_interface.h"
50 #include "ospf6_zebra.h"
51
52 /* Default configuration file name for ospf6d. */
53 #define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
54
55 /* VTY Socket prefix */
56 char vty_sock_path[MAXPATHLEN] = OSPF6_VTYSH_PATH;
57
58 /* Default port values. */
59 #define OSPF6_VTY_PORT 2606
60
61 /* ospf6d privileges */
62 zebra_capabilities_t _caps_p [] =
63 {
64 ZCAP_NET_RAW,
65 ZCAP_BIND
66 };
67
68 struct zebra_privs_t ospf6d_privs =
69 {
70 #if defined(FRR_USER)
71 .user = FRR_USER,
72 #endif
73 #if defined FRR_GROUP
74 .group = FRR_GROUP,
75 #endif
76 #ifdef VTY_GROUP
77 .vty_group = VTY_GROUP,
78 #endif
79 .caps_p = _caps_p,
80 .cap_num_p = 2,
81 .cap_num_i = 0
82 };
83
84 /* ospf6d options, we use GNU getopt library. */
85 #define OPTION_VTYSOCK 1000
86 struct option longopts[] =
87 {
88 { "daemon", no_argument, NULL, 'd'},
89 { "config_file", required_argument, NULL, 'f'},
90 { "pid_file", required_argument, NULL, 'i'},
91 { "socket", required_argument, NULL, 'z'},
92 { "vty_addr", required_argument, NULL, 'A'},
93 { "vty_port", required_argument, NULL, 'P'},
94 { "vty_socket", required_argument, NULL, OPTION_VTYSOCK},
95 { "user", required_argument, NULL, 'u'},
96 { "group", required_argument, NULL, 'g'},
97 { "version", no_argument, NULL, 'v'},
98 { "dryrun", no_argument, NULL, 'C'},
99 { "help", no_argument, NULL, 'h'},
100 { 0 }
101 };
102
103 /* Configuration file and directory. */
104 char config_default[] = SYSCONFDIR OSPF6_DEFAULT_CONFIG;
105
106 /* ospf6d program name. */
107 char *progname;
108
109 /* is daemon? */
110 int daemon_mode = 0;
111
112 /* Master of threads. */
113 struct thread_master *master;
114
115 /* Process ID saved for use by init system */
116 const char *pid_file = PATH_OSPF6D_PID;
117
118 /* Help information display. */
119 static void
120 usage (char *progname, int status)
121 {
122 if (status != 0)
123 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
124 else
125 {
126 printf ("Usage : %s [OPTION...]\n\n\
127 Daemon which manages OSPF version 3.\n\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 -z, --socket Set path of zebra socket\n\
132 -A, --vty_addr Set vty's bind address\n\
133 -P, --vty_port Set vty's port number\n\
134 --vty_socket Override vty socket path\n\
135 -u, --user User to run as\n\
136 -g, --group Group to run as\n\
137 -v, --version Print program version\n\
138 -C, --dryrun Check configuration for validity and exit\n\
139 -h, --help Display this help and exit\n\
140 \n\
141 Report bugs to %s\n", progname, FRR_BUG_ADDRESS);
142 }
143
144 exit (status);
145 }
146
147 static void __attribute__ ((noreturn))
148 ospf6_exit (int status)
149 {
150 struct listnode *node;
151 struct interface *ifp;
152
153 if (ospf6)
154 ospf6_delete (ospf6);
155
156 bfd_gbl_exit();
157
158 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
159 if (ifp->info != NULL)
160 ospf6_interface_delete(ifp->info);
161
162 ospf6_message_terminate ();
163 ospf6_asbr_terminate ();
164 ospf6_lsa_terminate ();
165
166 vrf_terminate ();
167 vty_terminate ();
168 cmd_terminate ();
169
170 if (zclient)
171 zclient_free (zclient);
172
173 if (master)
174 thread_master_free (master);
175
176 if (zlog_default)
177 closezlog (zlog_default);
178
179 exit (status);
180 }
181
182 /* SIGHUP handler. */
183 static void
184 sighup (void)
185 {
186 zlog_info ("SIGHUP received");
187 }
188
189 /* SIGINT handler. */
190 static void
191 sigint (void)
192 {
193 zlog_notice ("Terminating on signal SIGINT");
194 ospf6_exit (0);
195 }
196
197 /* SIGTERM handler. */
198 static void
199 sigterm (void)
200 {
201 zlog_notice ("Terminating on signal SIGTERM");
202 ospf6_clean();
203 ospf6_exit (0);
204 }
205
206 /* SIGUSR1 handler. */
207 static void
208 sigusr1 (void)
209 {
210 zlog_info ("SIGUSR1 received");
211 zlog_rotate (NULL);
212 }
213
214 struct quagga_signal_t ospf6_signals[] =
215 {
216 {
217 .signal = SIGHUP,
218 .handler = &sighup,
219 },
220 {
221 .signal = SIGINT,
222 .handler = &sigint,
223 },
224 {
225 .signal = SIGTERM,
226 .handler = &sigterm,
227 },
228 {
229 .signal = SIGUSR1,
230 .handler = &sigusr1,
231 },
232 };
233
234 /* Main routine of ospf6d. Treatment of argument and starting ospf finite
235 state machine is handled here. */
236 int
237 main (int argc, char *argv[], char *envp[])
238 {
239 char *p;
240 int opt;
241 char *vty_addr = NULL;
242 int vty_port = 0;
243 char *config_file = NULL;
244 struct thread thread;
245 int dryrun = 0;
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 /* Seed random number for LSA ID */
254 srandom (time(NULL));
255
256 /* Command line argument treatment. */
257 while (1)
258 {
259 opt = getopt_long (argc, argv, "df:i:z:hp:A:P:u:g:vC", longopts, 0);
260
261 if (opt == EOF)
262 break;
263
264 switch (opt)
265 {
266 case 0:
267 break;
268 case 'd':
269 daemon_mode = 1;
270 break;
271 case 'f':
272 config_file = optarg;
273 break;
274 case 'A':
275 vty_addr = optarg;
276 break;
277 case 'i':
278 pid_file = optarg;
279 break;
280 case 'z':
281 zclient_serv_path_set (optarg);
282 break;
283 case 'P':
284 /* Deal with atoi() returning 0 on failure, and ospf6d not
285 listening on ospf6d port... */
286 if (strcmp(optarg, "0") == 0)
287 {
288 vty_port = 0;
289 break;
290 }
291 vty_port = atoi (optarg);
292 if (vty_port <= 0 || vty_port > 0xffff)
293 vty_port = OSPF6_VTY_PORT;
294 break;
295 case OPTION_VTYSOCK:
296 set_socket_path(vty_sock_path, OSPF6_VTYSH_PATH, optarg, sizeof (vty_sock_path));
297 break;
298 case 'u':
299 ospf6d_privs.user = optarg;
300 break;
301 case 'g':
302 ospf6d_privs.group = optarg;
303 break;
304 case 'v':
305 print_version (progname);
306 exit (0);
307 break;
308 case 'C':
309 dryrun = 1;
310 break;
311 case 'h':
312 usage (progname, 0);
313 break;
314 default:
315 usage (progname, 1);
316 break;
317 }
318 }
319
320 if (geteuid () != 0)
321 {
322 errno = EPERM;
323 perror (progname);
324 exit (1);
325 }
326
327 /* thread master */
328 master = thread_master_create ();
329
330 /* Initializations. */
331 zlog_default = openzlog (progname, ZLOG_OSPF6, 0,
332 LOG_CONS|LOG_NDELAY|LOG_PID,
333 LOG_DAEMON);
334 zprivs_init (&ospf6d_privs);
335 #if defined(HAVE_CUMULUS)
336 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
337 #endif
338
339 /* initialize zebra libraries */
340 signal_init (master, array_size(ospf6_signals), ospf6_signals);
341 cmd_init (1);
342 vty_init (master);
343 memory_init ();
344 vrf_init ();
345 access_list_init ();
346 prefix_list_init ();
347
348 /* initialize ospf6 */
349 ospf6_init ();
350
351 /* parse config file */
352 vty_read_config (config_file, config_default);
353
354 /* Start execution only if not in dry-run mode */
355 if (dryrun)
356 return(0);
357
358 if (daemon_mode && daemon (0, 0) < 0)
359 {
360 zlog_err("OSPF6d daemon failed: %s", strerror(errno));
361 exit (1);
362 }
363
364 /* pid file create */
365 pid_output (pid_file);
366
367 /* Make ospf6 vty socket. */
368 if (!vty_port)
369 vty_port = OSPF6_VTY_PORT;
370 vty_serv_sock (vty_addr, vty_port, vty_sock_path);
371
372 /* Print start message */
373 zlog_notice ("OSPF6d (Quagga-%s ospf6d-%s) starts: vty@%d",
374 FRR_VERSION, OSPF6_DAEMON_VERSION,vty_port);
375
376 /* Start finite state machine, here we go! */
377 while (thread_fetch (master, &thread))
378 thread_call (&thread);
379
380 /* Log in case thread failed */
381 zlog_warn ("Thread failed");
382
383 /* Not reached. */
384 ospf6_exit (0);
385 }
386
387