New upstream version 1.2.3
[quagga-debian.git] / nhrpd / nhrp_main.c
1 /* NHRP daemon main functions
2  * Copyright (c) 2014-2015 Timo Teräs
3  *
4  * This file is free software: you may copy, redistribute and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  */
9
10 #include <unistd.h>
11 #include <libgen.h>
12
13 #include "zebra.h"
14 #include "privs.h"
15 #include "getopt.h"
16 #include "thread.h"
17 #include "sigevent.h"
18 #include "version.h"
19 #include "log.h"
20 #include "memory.h"
21 #include "command.h"
22
23 #include "nhrpd.h"
24 #include "netlink.h"
25
26 unsigned int debug_flags = 0;
27
28 struct thread_master *master;
29 struct timeval current_time;
30 static const char *pid_file = PATH_NHRPD_PID;
31 static char config_default[] = SYSCONFDIR NHRP_DEFAULT_CONFIG;
32 static char *config_file = NULL;
33 static char *vty_addr = NULL;
34 static int vty_port = NHRP_VTY_PORT;
35 static int do_daemonise = 0;
36
37 /* nhrpd options. */
38 struct option longopts[] = {
39         { "daemon",      no_argument,       NULL, 'd'},
40         { "config_file", required_argument, NULL, 'f'},
41         { "pid_file",    required_argument, NULL, 'i'},
42         { "socket",      required_argument, NULL, 'z'},
43         { "help",        no_argument,       NULL, 'h'},
44         { "vty_addr",    required_argument, NULL, 'A'},
45         { "vty_port",    required_argument, NULL, 'P'},
46         { "user",        required_argument, NULL, 'u'},
47         { "group",       required_argument, NULL, 'g'},
48         { "version",     no_argument,       NULL, 'v'},
49         { 0 }
50 };
51
52 /* nhrpd privileges */
53 static zebra_capabilities_t _caps_p [] = {
54         ZCAP_NET_RAW,
55         ZCAP_NET_ADMIN,
56         ZCAP_DAC_OVERRIDE,      /* for now needed to write to /proc/sys/net/ipv4/<if>/send_redirect */
57 };
58
59 static struct zebra_privs_t nhrpd_privs = {
60 #ifdef QUAGGA_USER
61         .user = QUAGGA_USER,
62 #endif
63 #ifdef QUAGGA_GROUP
64         .group = QUAGGA_GROUP,
65 #endif
66 #ifdef VTY_GROUP
67         .vty_group = VTY_GROUP,
68 #endif
69         .caps_p = _caps_p,
70         .cap_num_p = ZEBRA_NUM_OF(_caps_p),
71 };
72
73 static void usage(const char *progname, int status)
74 {
75         if (status != 0)
76                 fprintf(stderr, "Try `%s --help' for more information.\n", progname);
77         else
78                 printf(
79 "Usage : %s [OPTION...]\n\
80 Daemon which manages NHRP protocol.\n\n\
81 -d, --daemon       Runs in daemon mode\n\
82 -f, --config_file  Set configuration file name\n\
83 -i, --pid_file     Set process identifier file name\n\
84 -z, --socket       Set path of zebra socket\n\
85 -A, --vty_addr     Set vty's bind address\n\
86 -P, --vty_port     Set vty's port number\n\
87 -u, --user         User to run as\n\
88 -g, --group        Group to run as\n\
89 -v, --version      Print program version\n\
90 -h, --help         Display this help and exit\n\
91 \n\
92 Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
93
94         exit(status);
95 }
96
97 static void parse_arguments(const char *progname, int argc, char **argv)
98 {
99         int opt;
100
101         while (1) {
102                 opt = getopt_long(argc, argv, "df:i:z:hA:P:u:g:v", longopts, 0);
103                 if(opt < 0) break;
104
105                 switch (opt) {
106                 case 0:
107                         break;
108                 case 'd':
109                         do_daemonise = -1;
110                         break;
111                 case 'f':
112                         config_file = optarg;
113                         break;
114                 case 'i':
115                         pid_file = optarg;
116                         break;
117                 case 'z':
118                         zclient_serv_path_set(optarg);
119                         break;
120                 case 'A':
121                         vty_addr = optarg;
122                         break;
123                 case 'P':
124                         vty_port = atoi (optarg);
125                         if (vty_port <= 0 || vty_port > 0xffff)
126                                 vty_port = NHRP_VTY_PORT;
127                         break;
128                 case 'u':
129                         nhrpd_privs.user = optarg;
130                         break;
131                 case 'g':
132                         nhrpd_privs.group = optarg;
133                         break;
134                 case 'v':
135                         print_version(progname);
136                         exit(0);
137                         break;
138                 case 'h':
139                         usage(progname, 0);
140                         break;
141                 default:
142                         usage(progname, 1);
143                         break;
144                 }
145         }
146 }
147
148 static void nhrp_sigusr1(void)
149 {
150         zlog_rotate(NULL);
151 }
152
153 static void nhrp_request_stop(void)
154 {
155         debugf(NHRP_DEBUG_COMMON, "Exiting...");
156
157         nhrp_shortcut_terminate();
158         nhrp_nhs_terminate();
159         nhrp_zebra_terminate();
160         vici_terminate();
161         evmgr_terminate();
162         nhrp_vc_terminate();
163         vrf_terminate();
164         /* memory_terminate(); */
165         /* vty_terminate(); */
166         cmd_terminate();
167         /* signal_terminate(); */
168         zprivs_terminate(&nhrpd_privs);
169
170         debugf(NHRP_DEBUG_COMMON, "Remove pid file.");
171         if (pid_file) unlink(pid_file);
172         debugf(NHRP_DEBUG_COMMON, "Done.");
173
174         closezlog(zlog_default);
175
176         exit(0);
177 }
178
179 static struct quagga_signal_t sighandlers[] = {
180         { .signal = SIGUSR1, .handler = &nhrp_sigusr1, },
181         { .signal = SIGINT,  .handler = &nhrp_request_stop, },
182         { .signal = SIGTERM, .handler = &nhrp_request_stop, },
183 };
184
185 int main(int argc, char **argv)
186 {
187         const char *progname;
188
189         /* Set umask before anything for security */
190         umask(0027);
191         progname = basename(argv[0]);
192         zlog_default = openzlog(progname, ZLOG_NHRP, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
193         zlog_set_level(NULL, ZLOG_DEST_STDOUT, LOG_WARNING);
194
195         parse_arguments(progname, argc, argv);
196
197         /* Library inits. */
198         master = thread_master_create();
199         zprivs_init(&nhrpd_privs);
200         signal_init(master, array_size(sighandlers), sighandlers);
201         cmd_init(1);
202         vty_init(master);
203         memory_init();
204         nhrp_interface_init();
205         vrf_init();
206         resolver_init();
207
208         /* Run with elevated capabilities, as for all netlink activity
209          * we need privileges anyway. */
210         nhrpd_privs.change(ZPRIVS_RAISE);
211
212         netlink_init();
213         evmgr_init();
214         nhrp_vc_init();
215         nhrp_packet_init();
216         vici_init();
217         nhrp_zebra_init();
218         nhrp_shortcut_init();
219
220         nhrp_config_init();
221
222         /* Get zebra configuration file. */
223         zlog_set_level(NULL, ZLOG_DEST_STDOUT, do_daemonise ? ZLOG_DISABLED : LOG_DEBUG);
224         vty_read_config(config_file, config_default);
225
226         if (do_daemonise && daemon(0, 0) < 0) {
227                 zlog_err("daemonise: %s", safe_strerror(errno));
228                 exit (1);
229         }
230
231         /* write pid file */
232         if (pid_output(pid_file) < 0) {
233                 zlog_err("error while writing pidfile");
234                 exit (1);
235         }
236
237         /* Create VTY socket */
238         vty_serv_sock(vty_addr, vty_port, NHRP_VTYSH_PATH);
239         zlog_notice("nhrpd starting: vty@%d", vty_port);
240
241         /* Main loop */
242         thread_main (master);
243
244         return 0;
245 }