blob: 56ea2713afc20cbb678bc0fd43e428727d44a619 [file] [log] [blame]
Timo Teräsdafa05e2017-01-19 17:27:01 +02001/* 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>
Paul Jakmaf2a4b8f2017-01-20 14:45:47 +000011#include <libgen.h>
Timo Teräsdafa05e2017-01-19 17:27:01 +020012
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
26unsigned int debug_flags = 0;
27
28struct thread_master *master;
29struct timeval current_time;
30static const char *pid_file = PATH_NHRPD_PID;
31static char config_default[] = SYSCONFDIR NHRP_DEFAULT_CONFIG;
32static char *config_file = NULL;
33static char *vty_addr = NULL;
34static int vty_port = NHRP_VTY_PORT;
35static int do_daemonise = 0;
36
37/* nhrpd options. */
38struct 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 */
53static 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
59static 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
73static 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\
80Daemon 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\
92Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
93
94 exit(status);
95}
96
97static 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
148static void nhrp_sigusr1(void)
149{
150 zlog_rotate(NULL);
151}
152
153static 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
179static 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
185int main(int argc, char **argv)
186{
187 struct thread thread;
188 const char *progname;
189
190 /* Set umask before anything for security */
191 umask(0027);
192 progname = basename(argv[0]);
193 zlog_default = openzlog(progname, ZLOG_NHRP, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
194 zlog_set_level(NULL, ZLOG_DEST_STDOUT, LOG_WARNING);
195
196 parse_arguments(progname, argc, argv);
197
198 /* Library inits. */
199 master = thread_master_create();
200 zprivs_init(&nhrpd_privs);
201 signal_init(master, array_size(sighandlers), sighandlers);
202 cmd_init(1);
203 vty_init(master);
204 memory_init();
205 nhrp_interface_init();
206 vrf_init();
207 resolver_init();
208
209 /* Run with elevated capabilities, as for all netlink activity
210 * we need privileges anyway. */
211 nhrpd_privs.change(ZPRIVS_RAISE);
212
213 netlink_init();
214 evmgr_init();
215 nhrp_vc_init();
216 nhrp_packet_init();
217 vici_init();
218 nhrp_zebra_init();
219 nhrp_shortcut_init();
220
221 nhrp_config_init();
222
223 /* Get zebra configuration file. */
224 zlog_set_level(NULL, ZLOG_DEST_STDOUT, do_daemonise ? ZLOG_DISABLED : LOG_DEBUG);
225 vty_read_config(config_file, config_default);
226
227 if (do_daemonise && daemon(0, 0) < 0) {
228 zlog_err("daemonise: %s", safe_strerror(errno));
229 exit (1);
230 }
231
232 /* write pid file */
233 if (pid_output(pid_file) < 0) {
234 zlog_err("error while writing pidfile");
235 exit (1);
236 }
237
238 /* Create VTY socket */
239 vty_serv_sock(vty_addr, vty_port, NHRP_VTYSH_PATH);
240 zlog_notice("nhrpd starting: vty@%d", vty_port);
241
242 /* Main loop */
243 while (thread_fetch(master, &thread))
244 thread_call(&thread);
245
246 return 0;
247}