blob: 29349a038d28f548a9c2c9c36f689b32eed0e6c3 [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>
11
12#include "zebra.h"
13#include "privs.h"
14#include "getopt.h"
15#include "thread.h"
16#include "sigevent.h"
17#include "version.h"
18#include "log.h"
19#include "memory.h"
20#include "command.h"
21
22#include "nhrpd.h"
23#include "netlink.h"
24
25unsigned int debug_flags = 0;
26
27struct thread_master *master;
28struct timeval current_time;
29static const char *pid_file = PATH_NHRPD_PID;
30static char config_default[] = SYSCONFDIR NHRP_DEFAULT_CONFIG;
31static char *config_file = NULL;
32static char *vty_addr = NULL;
33static int vty_port = NHRP_VTY_PORT;
34static int do_daemonise = 0;
35
36/* nhrpd options. */
37struct option longopts[] = {
38 { "daemon", no_argument, NULL, 'd'},
39 { "config_file", required_argument, NULL, 'f'},
40 { "pid_file", required_argument, NULL, 'i'},
41 { "socket", required_argument, NULL, 'z'},
42 { "help", no_argument, NULL, 'h'},
43 { "vty_addr", required_argument, NULL, 'A'},
44 { "vty_port", required_argument, NULL, 'P'},
45 { "user", required_argument, NULL, 'u'},
46 { "group", required_argument, NULL, 'g'},
47 { "version", no_argument, NULL, 'v'},
48 { 0 }
49};
50
51/* nhrpd privileges */
52static zebra_capabilities_t _caps_p [] = {
53 ZCAP_NET_RAW,
54 ZCAP_NET_ADMIN,
55 ZCAP_DAC_OVERRIDE, /* for now needed to write to /proc/sys/net/ipv4/<if>/send_redirect */
56};
57
58static struct zebra_privs_t nhrpd_privs = {
59#ifdef QUAGGA_USER
60 .user = QUAGGA_USER,
61#endif
62#ifdef QUAGGA_GROUP
63 .group = QUAGGA_GROUP,
64#endif
65#ifdef VTY_GROUP
66 .vty_group = VTY_GROUP,
67#endif
68 .caps_p = _caps_p,
69 .cap_num_p = ZEBRA_NUM_OF(_caps_p),
70};
71
72static void usage(const char *progname, int status)
73{
74 if (status != 0)
75 fprintf(stderr, "Try `%s --help' for more information.\n", progname);
76 else
77 printf(
78"Usage : %s [OPTION...]\n\
79Daemon which manages NHRP protocol.\n\n\
80-d, --daemon Runs in daemon mode\n\
81-f, --config_file Set configuration file name\n\
82-i, --pid_file Set process identifier file name\n\
83-z, --socket Set path of zebra socket\n\
84-A, --vty_addr Set vty's bind address\n\
85-P, --vty_port Set vty's port number\n\
86-u, --user User to run as\n\
87-g, --group Group to run as\n\
88-v, --version Print program version\n\
89-h, --help Display this help and exit\n\
90\n\
91Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
92
93 exit(status);
94}
95
96static void parse_arguments(const char *progname, int argc, char **argv)
97{
98 int opt;
99
100 while (1) {
101 opt = getopt_long(argc, argv, "df:i:z:hA:P:u:g:v", longopts, 0);
102 if(opt < 0) break;
103
104 switch (opt) {
105 case 0:
106 break;
107 case 'd':
108 do_daemonise = -1;
109 break;
110 case 'f':
111 config_file = optarg;
112 break;
113 case 'i':
114 pid_file = optarg;
115 break;
116 case 'z':
117 zclient_serv_path_set(optarg);
118 break;
119 case 'A':
120 vty_addr = optarg;
121 break;
122 case 'P':
123 vty_port = atoi (optarg);
124 if (vty_port <= 0 || vty_port > 0xffff)
125 vty_port = NHRP_VTY_PORT;
126 break;
127 case 'u':
128 nhrpd_privs.user = optarg;
129 break;
130 case 'g':
131 nhrpd_privs.group = optarg;
132 break;
133 case 'v':
134 print_version(progname);
135 exit(0);
136 break;
137 case 'h':
138 usage(progname, 0);
139 break;
140 default:
141 usage(progname, 1);
142 break;
143 }
144 }
145}
146
147static void nhrp_sigusr1(void)
148{
149 zlog_rotate(NULL);
150}
151
152static void nhrp_request_stop(void)
153{
154 debugf(NHRP_DEBUG_COMMON, "Exiting...");
155
156 nhrp_shortcut_terminate();
157 nhrp_nhs_terminate();
158 nhrp_zebra_terminate();
159 vici_terminate();
160 evmgr_terminate();
161 nhrp_vc_terminate();
162 vrf_terminate();
163 /* memory_terminate(); */
164 /* vty_terminate(); */
165 cmd_terminate();
166 /* signal_terminate(); */
167 zprivs_terminate(&nhrpd_privs);
168
169 debugf(NHRP_DEBUG_COMMON, "Remove pid file.");
170 if (pid_file) unlink(pid_file);
171 debugf(NHRP_DEBUG_COMMON, "Done.");
172
173 closezlog(zlog_default);
174
175 exit(0);
176}
177
178static struct quagga_signal_t sighandlers[] = {
179 { .signal = SIGUSR1, .handler = &nhrp_sigusr1, },
180 { .signal = SIGINT, .handler = &nhrp_request_stop, },
181 { .signal = SIGTERM, .handler = &nhrp_request_stop, },
182};
183
184int main(int argc, char **argv)
185{
186 struct thread thread;
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 while (thread_fetch(master, &thread))
243 thread_call(&thread);
244
245 return 0;
246}