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