1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * watchfrr CLI functions.
5 * Copyright (C) 2016 David Lamparter for NetDEF, Inc.
19 pid_t integrated_write_pid
;
20 static int integrated_result_fd
;
22 DEFUN(config_write_integrated
,
23 config_write_integrated_cmd
,
25 "Write running configuration to memory, network, or terminal\n"
26 "Write integrated all-daemon frr.conf file\n")
29 sigset_t oldmask
, sigmask
;
31 const char *e_inprog
= "Configuration write already in progress.";
32 const char *e_dmn
= "Not all daemons are up, cannot write config.";
34 if (integrated_write_pid
!= -1) {
35 vty_out(vty
, "%% %s\n", e_inprog
);
39 /* check that all daemons are up before clobbering config */
40 if (!check_all_up()) {
41 vty_out(vty
, "%% %s\n", e_dmn
);
43 * vtysh interprets this return value to mean that it should
44 * not try to write the config itself
46 return CMD_WARNING_CONFIG_FAILED
;
52 /* need to temporarily block SIGCHLD because it could arrive between
53 * fork() call and setting the integrated_write_pid variable. This
54 * would mean the completion call gets lost and this hangs forever.
56 sigemptyset(&oldmask
);
57 sigemptyset(&sigmask
);
58 sigaddset(&sigmask
, SIGCHLD
);
59 sigprocmask(SIG_BLOCK
, &sigmask
, &oldmask
);
63 vty_out(vty
, "%% configuration write fork() failed: %s.\n",
64 safe_strerror(errno
));
65 sigprocmask(SIG_SETMASK
, &oldmask
, NULL
);
69 /* note: the VTY won't write a command return value to vtysh;
71 * session temporarily enters an intentional "hang" state. This
73 * to make sure latency in vtysh doing the config write (several
74 * seconds is not rare to see) does not interfere with
78 * The fd is duplicated here so we don't need to hold a vty
80 * (which could become invalid in the meantime).
82 integrated_write_pid
= child
;
83 integrated_result_fd
= dup(vty
->wfd
);
84 sigprocmask(SIG_SETMASK
, &oldmask
, NULL
);
88 /* redirect stdout/stderr to vty session. Note vty->wfd is marked
89 * CLOEXEC, but dup2 will clear that flag. */
93 /* don't allow the user to pass parameters, we're root here!
94 * should probably harden vtysh at some point too... */
96 execl(VTYSH_BIN_PATH
, "vtysh", "-N", pathspace
, "-w", NULL
);
98 execl(VTYSH_BIN_PATH
, "vtysh", "-w", NULL
);
100 /* unbuffered write; we just messed with stdout... */
102 snprintf(msg
, sizeof(msg
), "error executing %s: %s\n", VTYSH_BIN_PATH
,
103 safe_strerror(errno
));
104 write(1, msg
, strlen(msg
));
108 DEFUN_NOSH (show_debugging_watchfrr
,
109 show_debugging_watchfrr_cmd
,
110 "show debugging [watchfrr]",
115 cmd_show_lib_debugs(vty
);
120 DEFUN (show_watchfrr
,
126 watchfrr_status(vty
);
130 /* we don't have the other logging commands since watchfrr only accepts
131 * log config through command line options
133 DEFUN_NOSH (show_logging
,
137 "Show current logging configuration\n")
139 log_show_syslog(vty
);
143 #include "watchfrr/watchfrr_vty_clippy.c"
145 DEFPY (watchfrr_ignore_daemon
,
146 watchfrr_ignore_daemon_cmd
,
147 "[no] watchfrr ignore DAEMON$dname",
149 "Watchfrr Specific sub-command\n"
150 "Ignore a specified daemon when it does not respond to echo request\n"
151 "The daemon to ignore\n")
153 watchfrr_set_ignore_daemon(vty
, dname
, no
? false : true );
158 void integrated_write_sigchld(int status
)
160 uint8_t reply
[4] = {0, 0, 0, CMD_WARNING
};
162 if (WIFEXITED(status
)) {
163 zlog_info("configuration write completed with exit code %d",
164 WEXITSTATUS(status
));
165 reply
[3] = WEXITSTATUS(status
);
166 } else if (WIFSIGNALED(status
)) {
167 zlog_warn("configuration write terminated by signal %d",
170 zlog_warn("configuration write terminated");
173 if (reply
[3] != CMD_SUCCESS
) {
174 /* failure might be silent in vtysh without this */
175 static const char msg
[] = "% Configuration write failed.\n";
176 write(integrated_result_fd
, msg
, strlen(msg
));
179 /* don't care about failures here, if the connection is broken the
180 * return value will just be lost. */
181 write(integrated_result_fd
, reply
, sizeof(reply
));
182 close(integrated_result_fd
);
184 integrated_write_pid
= -1;
187 void watchfrr_vty_init(void)
189 integrated_write_pid
= -1;
190 install_element(ENABLE_NODE
, &config_write_integrated_cmd
);
191 install_element(ENABLE_NODE
, &show_debugging_watchfrr_cmd
);
193 install_element(ENABLE_NODE
, &watchfrr_ignore_daemon_cmd
);
195 install_element(CONFIG_NODE
, &show_debugging_watchfrr_cmd
);
196 install_element(VIEW_NODE
, &show_watchfrr_cmd
);
197 install_element(VIEW_NODE
, &show_logging_cmd
);