]> git.proxmox.com Git - mirror_frr.git/blob - lib/libfrr.c
vtysh: only show error codes once
[mirror_frr.git] / lib / libfrr.c
1 /*
2 * libfrr overall management functions
3 *
4 * Copyright (C) 2016 David Lamparter for NetDEF, Inc.
5 *
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22 #include <sys/un.h>
23
24 #include <sys/types.h>
25 #include <sys/wait.h>
26
27 #include "libfrr.h"
28 #include "getopt.h"
29 #include "privs.h"
30 #include "vty.h"
31 #include "command.h"
32 #include "version.h"
33 #include "memory_vty.h"
34 #include "log_vty.h"
35 #include "zclient.h"
36 #include "log_int.h"
37 #include "module.h"
38 #include "network.h"
39 #include "lib_errors.h"
40 #include "db.h"
41 #include "northbound_cli.h"
42 #include "northbound_db.h"
43 #include "debug.h"
44
45 DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm))
46 DEFINE_KOOH(frr_early_fini, (), ())
47 DEFINE_KOOH(frr_fini, (), ())
48
49 const char frr_sysconfdir[] = SYSCONFDIR;
50 char frr_vtydir[256];
51 #ifdef HAVE_SQLITE3
52 const char frr_dbdir[] = DAEMON_DB_DIR;
53 #endif
54 const char frr_moduledir[] = MODULE_PATH;
55
56 char frr_protoname[256] = "NONE";
57 char frr_protonameinst[256] = "NONE";
58
59 char config_default[512];
60 char frr_zclientpath[256];
61 static char pidfile_default[1024];
62 #ifdef HAVE_SQLITE3
63 static char dbfile_default[512];
64 #endif
65 static char vtypath_default[512];
66
67 bool debug_memstats_at_exit = false;
68 static bool nodetach_term, nodetach_daemon;
69
70 static char comb_optstr[256];
71 static struct option comb_lo[64];
72 static struct option *comb_next_lo = &comb_lo[0];
73 static char comb_helpstr[4096];
74
75 struct optspec {
76 const char *optstr;
77 const char *helpstr;
78 const struct option *longopts;
79 };
80
81 static void opt_extend(const struct optspec *os)
82 {
83 const struct option *lo;
84
85 strlcat(comb_optstr, os->optstr, sizeof(comb_optstr));
86 strlcat(comb_helpstr, os->helpstr, sizeof(comb_helpstr));
87 for (lo = os->longopts; lo->name; lo++)
88 memcpy(comb_next_lo++, lo, sizeof(*lo));
89 }
90
91
92 #define OPTION_VTYSOCK 1000
93 #define OPTION_MODULEDIR 1002
94 #define OPTION_LOG 1003
95 #define OPTION_LOGLEVEL 1004
96 #define OPTION_TCLI 1005
97 #define OPTION_DB_FILE 1006
98 #define OPTION_LOGGING 1007
99
100 static const struct option lo_always[] = {
101 {"help", no_argument, NULL, 'h'},
102 {"version", no_argument, NULL, 'v'},
103 {"daemon", no_argument, NULL, 'd'},
104 {"module", no_argument, NULL, 'M'},
105 {"vty_socket", required_argument, NULL, OPTION_VTYSOCK},
106 {"moduledir", required_argument, NULL, OPTION_MODULEDIR},
107 {"log", required_argument, NULL, OPTION_LOG},
108 {"log-level", required_argument, NULL, OPTION_LOGLEVEL},
109 {"tcli", no_argument, NULL, OPTION_TCLI},
110 {"command-log-always", no_argument, NULL, OPTION_LOGGING},
111 {NULL}};
112 static const struct optspec os_always = {
113 "hvdM:",
114 " -h, --help Display this help and exit\n"
115 " -v, --version Print program version\n"
116 " -d, --daemon Runs in daemon mode\n"
117 " -M, --module Load specified module\n"
118 " --vty_socket Override vty socket path\n"
119 " --moduledir Override modules directory\n"
120 " --log Set Logging to stdout, syslog, or file:<name>\n"
121 " --log-level Set Logging Level to use, debug, info, warn, etc\n"
122 " --tcli Use transaction-based CLI\n",
123 lo_always};
124
125
126 static const struct option lo_cfg_pid_dry[] = {
127 {"pid_file", required_argument, NULL, 'i'},
128 {"config_file", required_argument, NULL, 'f'},
129 #ifdef HAVE_SQLITE3
130 {"db_file", required_argument, NULL, OPTION_DB_FILE},
131 #endif
132 {"pathspace", required_argument, NULL, 'N'},
133 {"dryrun", no_argument, NULL, 'C'},
134 {"terminal", no_argument, NULL, 't'},
135 {NULL}};
136 static const struct optspec os_cfg_pid_dry = {
137 "f:i:CtN:",
138 " -f, --config_file Set configuration file name\n"
139 " -i, --pid_file Set process identifier file name\n"
140 #ifdef HAVE_SQLITE3
141 " --db_file Set database file name\n"
142 #endif
143 " -N, --pathspace Insert prefix into config & socket paths\n"
144 " -C, --dryrun Check configuration for validity and exit\n"
145 " -t, --terminal Open terminal session on stdio\n"
146 " -d -t Daemonize after terminal session ends\n",
147 lo_cfg_pid_dry};
148
149
150 static const struct option lo_zclient[] = {
151 {"socket", required_argument, NULL, 'z'},
152 {NULL}};
153 static const struct optspec os_zclient = {
154 "z:", " -z, --socket Set path of zebra socket\n", lo_zclient};
155
156
157 static const struct option lo_vty[] = {
158 {"vty_addr", required_argument, NULL, 'A'},
159 {"vty_port", required_argument, NULL, 'P'},
160 {NULL}};
161 static const struct optspec os_vty = {
162 "A:P:",
163 " -A, --vty_addr Set vty's bind address\n"
164 " -P, --vty_port Set vty's port number\n",
165 lo_vty};
166
167
168 static const struct option lo_user[] = {{"user", required_argument, NULL, 'u'},
169 {"group", required_argument, NULL, 'g'},
170 {NULL}};
171 static const struct optspec os_user = {"u:g:",
172 " -u, --user User to run as\n"
173 " -g, --group Group to run as\n",
174 lo_user};
175
176
177 bool frr_zclient_addr(struct sockaddr_storage *sa, socklen_t *sa_len,
178 const char *path)
179 {
180 memset(sa, 0, sizeof(*sa));
181
182 if (!path)
183 path = frr_zclientpath;
184
185 if (!strncmp(path, ZAPI_TCP_PATHNAME, strlen(ZAPI_TCP_PATHNAME))) {
186 /* note: this functionality is disabled at bottom */
187 int af;
188 int port = ZEBRA_PORT;
189 char *err = NULL;
190 struct sockaddr_in *sin = NULL;
191 struct sockaddr_in6 *sin6 = NULL;
192
193 path += strlen(ZAPI_TCP_PATHNAME);
194
195 switch (path[0]) {
196 case '4':
197 path++;
198 af = AF_INET;
199 break;
200 case '6':
201 path++;
202 /* fallthrough */
203 default:
204 af = AF_INET6;
205 break;
206 }
207
208 switch (path[0]) {
209 case '\0':
210 break;
211 case ':':
212 path++;
213 port = strtoul(path, &err, 10);
214 if (*err || !*path)
215 return false;
216 break;
217 default:
218 return false;
219 }
220
221 sa->ss_family = af;
222 switch (af) {
223 case AF_INET:
224 sin = (struct sockaddr_in *)sa;
225 sin->sin_port = htons(port);
226 sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
227 *sa_len = sizeof(struct sockaddr_in);
228 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
229 sin->sin_len = *sa_len;
230 #endif
231 break;
232 case AF_INET6:
233 sin6 = (struct sockaddr_in6 *)sa;
234 sin6->sin6_port = htons(port);
235 inet_pton(AF_INET6, "::1", &sin6->sin6_addr);
236 *sa_len = sizeof(struct sockaddr_in6);
237 #ifdef SIN6_LEN
238 sin6->sin6_len = *sa_len;
239 #endif
240 break;
241 }
242
243 #if 1
244 /* force-disable this path, because tcp-zebra is a
245 * SECURITY ISSUE. there are no checks at all against
246 * untrusted users on the local system connecting on TCP
247 * and injecting bogus routing data into the entire routing
248 * domain.
249 *
250 * The functionality is only left here because it may be
251 * useful during development, in order to be able to get
252 * tcpdump or wireshark watching ZAPI as TCP. If you want
253 * to do that, flip the #if 1 above to #if 0. */
254 memset(sa, 0, sizeof(*sa));
255 return false;
256 #endif
257 } else {
258 /* "sun" is a #define on solaris */
259 struct sockaddr_un *suna = (struct sockaddr_un *)sa;
260
261 suna->sun_family = AF_UNIX;
262 strlcpy(suna->sun_path, path, sizeof(suna->sun_path));
263 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
264 *sa_len = suna->sun_len = SUN_LEN(suna);
265 #else
266 *sa_len = sizeof(suna->sun_family) + strlen(suna->sun_path);
267 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
268 #if 0
269 /* this is left here for future reference; Linux abstract
270 * socket namespace support can be enabled by replacing
271 * above #if 0 with #ifdef GNU_LINUX.
272 *
273 * THIS IS A SECURITY ISSUE, the abstract socket namespace
274 * does not have user/group permission control on sockets.
275 * we'd need to implement SCM_CREDENTIALS support first to
276 * check that only proper users can connect to abstract
277 * sockets. (same problem as tcp-zebra, except there is a
278 * fix with SCM_CREDENTIALS. tcp-zebra has no such fix.)
279 */
280 if (suna->sun_path[0] == '@')
281 suna->sun_path[0] = '\0';
282 #endif
283 }
284 return true;
285 }
286
287 static struct frr_daemon_info *di = NULL;
288
289 void frr_init_vtydir(void)
290 {
291 snprintf(frr_vtydir, sizeof(frr_vtydir), DAEMON_VTY_DIR, "", "");
292 }
293
294 void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv)
295 {
296 di = daemon;
297
298 /* basename(), opencoded. */
299 char *p = strrchr(argv[0], '/');
300 di->progname = p ? p + 1 : argv[0];
301
302 umask(0027);
303
304 opt_extend(&os_always);
305 if (!(di->flags & FRR_NO_CFG_PID_DRY))
306 opt_extend(&os_cfg_pid_dry);
307 if (!(di->flags & FRR_NO_PRIVSEP))
308 opt_extend(&os_user);
309 if (!(di->flags & FRR_NO_ZCLIENT))
310 opt_extend(&os_zclient);
311 if (!(di->flags & FRR_NO_TCPVTY))
312 opt_extend(&os_vty);
313 if (di->flags & FRR_DETACH_LATER)
314 nodetach_daemon = true;
315
316 frr_init_vtydir();
317 snprintf(config_default, sizeof(config_default), "%s/%s.conf",
318 frr_sysconfdir, di->name);
319 snprintf(pidfile_default, sizeof(pidfile_default), "%s/%s.pid",
320 frr_vtydir, di->name);
321 snprintf(frr_zclientpath, sizeof(frr_zclientpath),
322 ZEBRA_SERV_PATH, "", "");
323 #ifdef HAVE_SQLITE3
324 snprintf(dbfile_default, sizeof(dbfile_default), "%s/%s.db",
325 frr_dbdir, di->name);
326 #endif
327
328 strlcpy(frr_protoname, di->logname, sizeof(frr_protoname));
329 strlcpy(frr_protonameinst, di->logname, sizeof(frr_protonameinst));
330
331 di->cli_mode = FRR_CLI_CLASSIC;
332 }
333
334 void frr_opt_add(const char *optstr, const struct option *longopts,
335 const char *helpstr)
336 {
337 const struct optspec main_opts = {optstr, helpstr, longopts};
338 opt_extend(&main_opts);
339 }
340
341 void frr_help_exit(int status)
342 {
343 FILE *target = status ? stderr : stdout;
344
345 if (status != 0)
346 fprintf(stderr, "Invalid options.\n\n");
347
348 if (di->printhelp)
349 di->printhelp(target);
350 else
351 fprintf(target, "Usage: %s [OPTION...]\n\n%s%s%s\n\n%s",
352 di->progname, di->proghelp, di->copyright ? "\n\n" : "",
353 di->copyright ? di->copyright : "", comb_helpstr);
354 fprintf(target, "\nReport bugs to %s\n", FRR_BUG_ADDRESS);
355 exit(status);
356 }
357
358 struct option_chain {
359 struct option_chain *next;
360 const char *arg;
361 };
362
363 static struct option_chain *modules = NULL, **modnext = &modules;
364 static int errors = 0;
365
366 static int frr_opt(int opt)
367 {
368 static int vty_port_set = 0;
369 static int vty_addr_set = 0;
370 struct option_chain *oc;
371 char *err;
372
373 switch (opt) {
374 case 'h':
375 frr_help_exit(0);
376 break;
377 case 'v':
378 print_version(di->progname);
379 exit(0);
380 break;
381 case 'd':
382 di->daemon_mode = 1;
383 break;
384 case 'M':
385 oc = XMALLOC(MTYPE_TMP, sizeof(*oc));
386 oc->arg = optarg;
387 oc->next = NULL;
388 *modnext = oc;
389 modnext = &oc->next;
390 break;
391 case 'i':
392 if (di->flags & FRR_NO_CFG_PID_DRY)
393 return 1;
394 di->pid_file = optarg;
395 break;
396 case 'f':
397 if (di->flags & FRR_NO_CFG_PID_DRY)
398 return 1;
399 di->config_file = optarg;
400 break;
401 case 'N':
402 if (di->flags & FRR_NO_CFG_PID_DRY)
403 return 1;
404 if (di->pathspace) {
405 fprintf(stderr,
406 "-N/--pathspace option specified more than once!\n");
407 errors++;
408 break;
409 }
410 if (di->zpathspace)
411 fprintf(stderr,
412 "-N option overriden by -z for zebra named socket path\n");
413
414 if (strchr(optarg, '/') || strchr(optarg, '.')) {
415 fprintf(stderr,
416 "slashes or dots are not permitted in the --pathspace option.\n");
417 errors++;
418 break;
419 }
420 di->pathspace = optarg;
421
422 if (!di->zpathspace)
423 snprintf(frr_zclientpath, sizeof(frr_zclientpath),
424 ZEBRA_SERV_PATH, "/", di->pathspace);
425 snprintf(frr_vtydir, sizeof(frr_vtydir), DAEMON_VTY_DIR, "/",
426 di->pathspace);
427 snprintf(pidfile_default, sizeof(pidfile_default), "%s/%s.pid",
428 frr_vtydir, di->name);
429 break;
430 #ifdef HAVE_SQLITE3
431 case OPTION_DB_FILE:
432 if (di->flags & FRR_NO_CFG_PID_DRY)
433 return 1;
434 di->db_file = optarg;
435 break;
436 #endif
437 case 'C':
438 if (di->flags & FRR_NO_CFG_PID_DRY)
439 return 1;
440 di->dryrun = 1;
441 break;
442 case 't':
443 if (di->flags & FRR_NO_CFG_PID_DRY)
444 return 1;
445 di->terminal = 1;
446 break;
447 case 'z':
448 di->zpathspace = true;
449 if (di->pathspace)
450 fprintf(stderr,
451 "-z option overrides -N option for zebra named socket path\n");
452 if (di->flags & FRR_NO_ZCLIENT)
453 return 1;
454 strlcpy(frr_zclientpath, optarg, sizeof(frr_zclientpath));
455 break;
456 case 'A':
457 if (di->flags & FRR_NO_TCPVTY)
458 return 1;
459 if (vty_addr_set) {
460 fprintf(stderr,
461 "-A option specified more than once!\n");
462 errors++;
463 break;
464 }
465 vty_addr_set = 1;
466 di->vty_addr = optarg;
467 break;
468 case 'P':
469 if (di->flags & FRR_NO_TCPVTY)
470 return 1;
471 if (vty_port_set) {
472 fprintf(stderr,
473 "-P option specified more than once!\n");
474 errors++;
475 break;
476 }
477 vty_port_set = 1;
478 di->vty_port = strtoul(optarg, &err, 0);
479 if (*err || !*optarg) {
480 fprintf(stderr,
481 "invalid port number \"%s\" for -P option\n",
482 optarg);
483 errors++;
484 break;
485 }
486 break;
487 case OPTION_VTYSOCK:
488 if (di->vty_sock_path) {
489 fprintf(stderr,
490 "--vty_socket option specified more than once!\n");
491 errors++;
492 break;
493 }
494 di->vty_sock_path = optarg;
495 break;
496 case OPTION_MODULEDIR:
497 if (di->module_path) {
498 fprintf(stderr,
499 "----moduledir option specified more than once!\n");
500 errors++;
501 break;
502 }
503 di->module_path = optarg;
504 break;
505 case OPTION_TCLI:
506 di->cli_mode = FRR_CLI_TRANSACTIONAL;
507 break;
508 case 'u':
509 if (di->flags & FRR_NO_PRIVSEP)
510 return 1;
511 di->privs->user = optarg;
512 break;
513 case 'g':
514 if (di->flags & FRR_NO_PRIVSEP)
515 return 1;
516 di->privs->group = optarg;
517 break;
518 case OPTION_LOG:
519 di->early_logging = optarg;
520 break;
521 case OPTION_LOGLEVEL:
522 di->early_loglevel = optarg;
523 break;
524 case OPTION_LOGGING:
525 di->log_always = true;
526 break;
527 default:
528 return 1;
529 }
530 return 0;
531 }
532
533 int frr_getopt(int argc, char *const argv[], int *longindex)
534 {
535 int opt;
536 int lidx;
537
538 comb_next_lo->name = NULL;
539
540 do {
541 opt = getopt_long(argc, argv, comb_optstr, comb_lo, &lidx);
542 if (frr_opt(opt))
543 break;
544 } while (opt != -1);
545
546 if (opt == -1 && errors)
547 frr_help_exit(1);
548 if (longindex)
549 *longindex = lidx;
550 return opt;
551 }
552
553 static void frr_mkdir(const char *path, bool strip)
554 {
555 char buf[256];
556 mode_t prev;
557 int ret;
558 struct zprivs_ids_t ids;
559
560 if (strip) {
561 char *slash = strrchr(path, '/');
562 size_t plen;
563 if (!slash)
564 return;
565 plen = slash - path;
566 if (plen > sizeof(buf) - 1)
567 return;
568 memcpy(buf, path, plen);
569 buf[plen] = '\0';
570 path = buf;
571 }
572
573 /* o+rx (..5) is needed for the frrvty group to work properly;
574 * without it, users in the frrvty group can't access the vty sockets.
575 */
576 prev = umask(0022);
577 ret = mkdir(path, 0755);
578 umask(prev);
579
580 if (ret != 0) {
581 /* if EEXIST, return without touching the permissions,
582 * so user-set custom permissions are left in place
583 */
584 if (errno == EEXIST)
585 return;
586
587 flog_err(EC_LIB_SYSTEM_CALL, "failed to mkdir \"%s\": %s", path,
588 strerror(errno));
589 return;
590 }
591
592 zprivs_get_ids(&ids);
593 if (chown(path, ids.uid_normal, ids.gid_normal))
594 flog_err(EC_LIB_SYSTEM_CALL, "failed to chown \"%s\": %s", path,
595 strerror(errno));
596 }
597
598 static struct thread_master *master;
599 struct thread_master *frr_init(void)
600 {
601 struct option_chain *oc;
602 struct frrmod_runtime *module;
603 char moderr[256];
604 char p_instance[16] = "", p_pathspace[256] = "";
605 const char *dir;
606 dir = di->module_path ? di->module_path : frr_moduledir;
607
608 srandom(time(NULL));
609
610 if (di->instance) {
611 snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]",
612 di->logname, di->instance);
613 snprintf(p_instance, sizeof(p_instance), "-%d", di->instance);
614 }
615 if (di->pathspace)
616 snprintf(p_pathspace, sizeof(p_pathspace), "%s/",
617 di->pathspace);
618
619 snprintf(config_default, sizeof(config_default), "%s%s%s%s.conf",
620 frr_sysconfdir, p_pathspace, di->name, p_instance);
621 snprintf(pidfile_default, sizeof(pidfile_default), "%s/%s%s.pid",
622 frr_vtydir, di->name, p_instance);
623 #ifdef HAVE_SQLITE3
624 snprintf(dbfile_default, sizeof(dbfile_default), "%s/%s%s%s.db",
625 frr_dbdir, p_pathspace, di->name, p_instance);
626 #endif
627
628 zprivs_preinit(di->privs);
629
630 openzlog(di->progname, di->logname, di->instance,
631 LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
632
633 command_setup_early_logging(di->early_logging, di->early_loglevel);
634
635 if (!frr_zclient_addr(&zclient_addr, &zclient_addr_len,
636 frr_zclientpath)) {
637 fprintf(stderr, "Invalid zserv socket path: %s\n",
638 frr_zclientpath);
639 exit(1);
640 }
641
642 /* don't mkdir these as root... */
643 if (!(di->flags & FRR_NO_PRIVSEP)) {
644 if (!di->pid_file || !di->vty_path)
645 frr_mkdir(frr_vtydir, false);
646 if (di->pid_file)
647 frr_mkdir(di->pid_file, true);
648 if (di->vty_path)
649 frr_mkdir(di->vty_path, true);
650 }
651
652 frrmod_init(di->module);
653 while (modules) {
654 modules = (oc = modules)->next;
655 module = frrmod_load(oc->arg, dir, moderr, sizeof(moderr));
656 if (!module) {
657 fprintf(stderr, "%s\n", moderr);
658 exit(1);
659 }
660 XFREE(MTYPE_TMP, oc);
661 }
662
663 zprivs_init(di->privs);
664
665 master = thread_master_create(NULL);
666 signal_init(master, di->n_signals, di->signals);
667
668 #ifdef HAVE_SQLITE3
669 if (!di->db_file)
670 di->db_file = dbfile_default;
671 db_init(di->db_file);
672 #endif
673
674 if (di->flags & FRR_LIMITED_CLI)
675 cmd_init(-1);
676 else
677 cmd_init(1);
678
679 vty_init(master, di->log_always);
680 memory_init();
681 log_filter_cmd_init();
682
683 log_ref_init();
684 log_ref_vty_init();
685 lib_error_init();
686
687 yang_init();
688
689 debug_init_cli();
690
691 nb_init(master, di->yang_modules, di->n_yang_modules);
692 if (nb_db_init() != NB_OK)
693 flog_warn(EC_LIB_NB_DATABASE,
694 "%s: failed to initialize northbound database",
695 __func__);
696
697 return master;
698 }
699
700 const char *frr_get_progname(void)
701 {
702 return di ? di->progname : NULL;
703 }
704
705 enum frr_cli_mode frr_get_cli_mode(void)
706 {
707 return di ? di->cli_mode : FRR_CLI_CLASSIC;
708 }
709
710 static int rcvd_signal = 0;
711
712 static void rcv_signal(int signum)
713 {
714 rcvd_signal = signum;
715 /* poll() is interrupted by the signal; handled below */
716 }
717
718 static void frr_daemon_wait(int fd)
719 {
720 struct pollfd pfd[1];
721 int ret;
722 pid_t exitpid;
723 int exitstat;
724 sigset_t sigs, prevsigs;
725
726 sigemptyset(&sigs);
727 sigaddset(&sigs, SIGTSTP);
728 sigaddset(&sigs, SIGQUIT);
729 sigaddset(&sigs, SIGINT);
730 sigprocmask(SIG_BLOCK, &sigs, &prevsigs);
731
732 struct sigaction sa = {
733 .sa_handler = rcv_signal, .sa_flags = SA_RESETHAND,
734 };
735 sigemptyset(&sa.sa_mask);
736 sigaction(SIGTSTP, &sa, NULL);
737 sigaction(SIGQUIT, &sa, NULL);
738 sigaction(SIGINT, &sa, NULL);
739
740 do {
741 char buf[1];
742 ssize_t nrecv;
743
744 pfd[0].fd = fd;
745 pfd[0].events = POLLIN;
746
747 rcvd_signal = 0;
748
749 #if defined(HAVE_PPOLL)
750 ret = ppoll(pfd, 1, NULL, &prevsigs);
751 #elif defined(HAVE_POLLTS)
752 ret = pollts(pfd, 1, NULL, &prevsigs);
753 #else
754 /* racy -- only used on FreeBSD 9 */
755 sigset_t tmpsigs;
756 sigprocmask(SIG_SETMASK, &prevsigs, &tmpsigs);
757 ret = poll(pfd, 1, -1);
758 sigprocmask(SIG_SETMASK, &tmpsigs, NULL);
759 #endif
760 if (ret < 0 && errno != EINTR && errno != EAGAIN) {
761 perror("poll()");
762 exit(1);
763 }
764 switch (rcvd_signal) {
765 case SIGTSTP:
766 send(fd, "S", 1, 0);
767 do {
768 nrecv = recv(fd, buf, sizeof(buf), 0);
769 } while (nrecv == -1
770 && (errno == EINTR || errno == EAGAIN));
771
772 raise(SIGTSTP);
773 sigaction(SIGTSTP, &sa, NULL);
774 send(fd, "R", 1, 0);
775 break;
776 case SIGINT:
777 send(fd, "I", 1, 0);
778 break;
779 case SIGQUIT:
780 send(fd, "Q", 1, 0);
781 break;
782 }
783 } while (ret <= 0);
784
785 exitpid = waitpid(-1, &exitstat, WNOHANG);
786 if (exitpid == 0)
787 /* child successfully went to main loop & closed socket */
788 exit(0);
789
790 /* child failed one way or another ... */
791 if (WIFEXITED(exitstat) && WEXITSTATUS(exitstat) == 0)
792 /* can happen in --terminal case if exit is fast enough */
793 (void)0;
794 else if (WIFEXITED(exitstat))
795 fprintf(stderr, "%s failed to start, exited %d\n", di->name,
796 WEXITSTATUS(exitstat));
797 else if (WIFSIGNALED(exitstat))
798 fprintf(stderr, "%s crashed in startup, signal %d\n", di->name,
799 WTERMSIG(exitstat));
800 else
801 fprintf(stderr, "%s failed to start, unknown problem\n",
802 di->name);
803 exit(1);
804 }
805
806 static int daemon_ctl_sock = -1;
807
808 static void frr_daemonize(void)
809 {
810 int fds[2];
811 pid_t pid;
812
813 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) {
814 perror("socketpair() for daemon control");
815 exit(1);
816 }
817 set_cloexec(fds[0]);
818 set_cloexec(fds[1]);
819
820 pid = fork();
821 if (pid < 0) {
822 perror("fork()");
823 exit(1);
824 }
825 if (pid == 0) {
826 /* child */
827 close(fds[0]);
828 if (setsid() < 0) {
829 perror("setsid()");
830 exit(1);
831 }
832
833 daemon_ctl_sock = fds[1];
834 return;
835 }
836
837 close(fds[1]);
838 frr_daemon_wait(fds[0]);
839 }
840
841 /*
842 * Why is this a thread?
843 *
844 * The read in of config for integrated config happens *after*
845 * thread execution starts( because it is passed in via a vtysh -b -n )
846 * While if you are not using integrated config we want the ability
847 * to read the config in after thread execution starts, so that
848 * we can match this behavior.
849 */
850 static int frr_config_read_in(struct thread *t)
851 {
852 if (!vty_read_config(NULL, di->config_file, config_default) &&
853 di->backup_config_file) {
854 char *orig = XSTRDUP(MTYPE_TMP, host_config_get());
855
856 zlog_info("Attempting to read backup config file: %s specified",
857 di->backup_config_file);
858 vty_read_config(NULL, di->backup_config_file, config_default);
859
860 host_config_set(orig);
861 XFREE(MTYPE_TMP, orig);
862 }
863
864 /*
865 * Update the shared candidate after reading the startup configuration.
866 */
867 pthread_rwlock_rdlock(&running_config->lock);
868 {
869 nb_config_replace(vty_shared_candidate_config, running_config,
870 true);
871 }
872 pthread_rwlock_unlock(&running_config->lock);
873
874 return 0;
875 }
876
877 void frr_config_fork(void)
878 {
879 hook_call(frr_late_init, master);
880
881 if (!(di->flags & FRR_NO_CFG_PID_DRY)) {
882 /* Don't start execution if we are in dry-run mode */
883 if (di->dryrun) {
884 frr_config_read_in(NULL);
885 exit(0);
886 }
887
888 thread_add_event(master, frr_config_read_in, NULL, 0,
889 &di->read_in);
890 }
891
892 if (di->daemon_mode || di->terminal)
893 frr_daemonize();
894
895 if (!di->pid_file)
896 di->pid_file = pidfile_default;
897 pid_output(di->pid_file);
898 }
899
900 static void frr_vty_serv(void)
901 {
902 /* allow explicit override of vty_path in the future
903 * (not currently set anywhere) */
904 if (!di->vty_path) {
905 const char *dir;
906 char defvtydir[256];
907
908 snprintf(defvtydir, sizeof(defvtydir), "%s", frr_vtydir);
909
910 dir = di->vty_sock_path ? di->vty_sock_path : defvtydir;
911
912 if (di->instance)
913 snprintf(vtypath_default, sizeof(vtypath_default),
914 "%s/%s-%d.vty", dir, di->name, di->instance);
915 else
916 snprintf(vtypath_default, sizeof(vtypath_default),
917 "%s/%s.vty", dir, di->name);
918
919 di->vty_path = vtypath_default;
920 }
921
922 vty_serv_sock(di->vty_addr, di->vty_port, di->vty_path);
923 }
924
925 static void frr_check_detach(void)
926 {
927 if (nodetach_term || nodetach_daemon)
928 return;
929
930 if (daemon_ctl_sock != -1)
931 close(daemon_ctl_sock);
932 daemon_ctl_sock = -1;
933 }
934
935 static void frr_terminal_close(int isexit)
936 {
937 int nullfd;
938
939 nodetach_term = false;
940 frr_check_detach();
941
942 if (!di->daemon_mode || isexit) {
943 printf("\n%s exiting\n", di->name);
944 if (!isexit)
945 raise(SIGINT);
946 return;
947 } else {
948 printf("\n%s daemonizing\n", di->name);
949 fflush(stdout);
950 }
951
952 nullfd = open("/dev/null", O_RDONLY | O_NOCTTY);
953 if (nullfd == -1) {
954 flog_err_sys(EC_LIB_SYSTEM_CALL,
955 "%s: failed to open /dev/null: %s", __func__,
956 safe_strerror(errno));
957 } else {
958 dup2(nullfd, 0);
959 dup2(nullfd, 1);
960 dup2(nullfd, 2);
961 close(nullfd);
962 }
963 }
964
965 static struct thread *daemon_ctl_thread = NULL;
966
967 static int frr_daemon_ctl(struct thread *t)
968 {
969 char buf[1];
970 ssize_t nr;
971
972 nr = recv(daemon_ctl_sock, buf, sizeof(buf), 0);
973 if (nr < 0 && (errno == EINTR || errno == EAGAIN))
974 goto out;
975 if (nr <= 0)
976 return 0;
977
978 switch (buf[0]) {
979 case 'S': /* SIGTSTP */
980 vty_stdio_suspend();
981 if (send(daemon_ctl_sock, "s", 1, 0) < 0)
982 zlog_err("%s send(\"s\") error (SIGTSTP propagation)",
983 (di && di->name ? di->name : ""));
984 break;
985 case 'R': /* SIGTCNT [implicit] */
986 vty_stdio_resume();
987 break;
988 case 'I': /* SIGINT */
989 di->daemon_mode = false;
990 raise(SIGINT);
991 break;
992 case 'Q': /* SIGQUIT */
993 di->daemon_mode = true;
994 vty_stdio_close();
995 break;
996 }
997
998 out:
999 thread_add_read(master, frr_daemon_ctl, NULL, daemon_ctl_sock,
1000 &daemon_ctl_thread);
1001 return 0;
1002 }
1003
1004 void frr_detach(void)
1005 {
1006 nodetach_daemon = false;
1007 frr_check_detach();
1008 }
1009
1010 void frr_run(struct thread_master *master)
1011 {
1012 char instanceinfo[64] = "";
1013
1014 frr_vty_serv();
1015
1016 if (di->instance)
1017 snprintf(instanceinfo, sizeof(instanceinfo), "instance %u ",
1018 di->instance);
1019
1020 zlog_notice("%s %s starting: %svty@%d%s", di->name, FRR_VERSION,
1021 instanceinfo, di->vty_port, di->startinfo);
1022
1023 if (di->terminal) {
1024 nodetach_term = true;
1025
1026 vty_stdio(frr_terminal_close);
1027 if (daemon_ctl_sock != -1) {
1028 set_nonblocking(daemon_ctl_sock);
1029 thread_add_read(master, frr_daemon_ctl, NULL,
1030 daemon_ctl_sock, &daemon_ctl_thread);
1031 }
1032 } else if (di->daemon_mode) {
1033 int nullfd = open("/dev/null", O_RDONLY | O_NOCTTY);
1034 if (nullfd == -1) {
1035 flog_err_sys(EC_LIB_SYSTEM_CALL,
1036 "%s: failed to open /dev/null: %s",
1037 __func__, safe_strerror(errno));
1038 } else {
1039 dup2(nullfd, 0);
1040 dup2(nullfd, 1);
1041 dup2(nullfd, 2);
1042 close(nullfd);
1043 }
1044
1045 frr_check_detach();
1046 }
1047
1048 /* end fixed stderr startup logging */
1049 zlog_startup_stderr = false;
1050
1051 struct thread thread;
1052 while (thread_fetch(master, &thread))
1053 thread_call(&thread);
1054 }
1055
1056 void frr_early_fini(void)
1057 {
1058 hook_call(frr_early_fini);
1059 }
1060
1061 void frr_fini(void)
1062 {
1063 FILE *fp;
1064 char filename[128];
1065 int have_leftovers;
1066
1067 hook_call(frr_fini);
1068
1069 /* memory_init -> nothing needed */
1070 vty_terminate();
1071 cmd_terminate();
1072 nb_terminate();
1073 yang_terminate();
1074 #ifdef HAVE_SQLITE3
1075 db_close();
1076 #endif
1077 log_ref_fini();
1078 zprivs_terminate(di->privs);
1079 /* signal_init -> nothing needed */
1080 thread_master_free(master);
1081 master = NULL;
1082 closezlog();
1083 /* frrmod_init -> nothing needed / hooks */
1084
1085 if (!debug_memstats_at_exit)
1086 return;
1087
1088 have_leftovers = log_memstats(stderr, di->name);
1089
1090 /* in case we decide at runtime that we want exit-memstats for
1091 * a daemon, but it has no stderr because it's daemonized
1092 * (only do this if we actually have something to print though)
1093 */
1094 if (!have_leftovers)
1095 return;
1096
1097 snprintf(filename, sizeof(filename), "/tmp/frr-memstats-%s-%llu-%llu",
1098 di->name, (unsigned long long)getpid(),
1099 (unsigned long long)time(NULL));
1100
1101 fp = fopen(filename, "w");
1102 if (fp) {
1103 log_memstats(fp, di->name);
1104 fclose(fp);
1105 }
1106 }
1107
1108 #ifdef INTERP
1109 static const char interp[]
1110 __attribute__((section(".interp"), used)) = INTERP;
1111 #endif
1112 /*
1113 * executable entry point for libfrr.so
1114 *
1115 * note that libc initialization is skipped for this so the set of functions
1116 * that can be called is rather limited
1117 */
1118 extern void _libfrr_version(void)
1119 __attribute__((visibility("hidden"), noreturn));
1120 void _libfrr_version(void)
1121 {
1122 const char banner[] =
1123 FRR_FULL_NAME " " FRR_VERSION ".\n"
1124 FRR_COPYRIGHT GIT_INFO "\n"
1125 "configured with:\n " FRR_CONFIG_ARGS "\n";
1126 write(1, banner, sizeof(banner) - 1);
1127 _exit(0);
1128 }