mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Capture and log STDOUT and STDERR output from dhcp-script.
This commit is contained in:
committed by
Simon Kelley
parent
bc515b71ec
commit
c77fb9d8f0
@@ -88,7 +88,12 @@ version 2.77
|
|||||||
|
|
||||||
Add mtu setting facility to --ra-param. Thanks to David
|
Add mtu setting facility to --ra-param. Thanks to David
|
||||||
Flamand for the patch.
|
Flamand for the patch.
|
||||||
|
|
||||||
|
Capture STDOUT and STDERR output from dhcp-script and log
|
||||||
|
it as part of the dnsmasq log stream. Makes life easier
|
||||||
|
for diagnosing unexpected problems in scripts.
|
||||||
|
Thanks to Petr Mensik for the patch.
|
||||||
|
|
||||||
|
|
||||||
version 2.76
|
version 2.76
|
||||||
Include 0.0.0.0/8 in DNS rebind checks. This range
|
Include 0.0.0.0/8 in DNS rebind checks. This range
|
||||||
|
|||||||
@@ -1577,8 +1577,8 @@ database.
|
|||||||
|
|
||||||
|
|
||||||
All file descriptors are
|
All file descriptors are
|
||||||
closed except stdin, stdout and stderr which are open to /dev/null
|
closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq.
|
||||||
(except in debug mode).
|
(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq).
|
||||||
|
|
||||||
The script is not invoked concurrently: at most one instance
|
The script is not invoked concurrently: at most one instance
|
||||||
of the script is ever running (dnsmasq waits for an instance of script to exit
|
of the script is ever running (dnsmasq waits for an instance of script to exit
|
||||||
|
|||||||
@@ -1302,6 +1302,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
daemon->tcp_pids[i] = 0;
|
daemon->tcp_pids[i] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if defined(HAVE_SCRIPT)
|
||||||
case EVENT_KILLED:
|
case EVENT_KILLED:
|
||||||
my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
|
my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
|
||||||
break;
|
break;
|
||||||
@@ -1315,12 +1316,19 @@ static void async_event(int pipe, time_t now)
|
|||||||
daemon->lease_change_command, strerror(ev.data));
|
daemon->lease_change_command, strerror(ev.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EVENT_SCRIPT_LOG:
|
||||||
|
my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
|
||||||
|
free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
/* necessary for fatal errors in helper */
|
/* necessary for fatal errors in helper */
|
||||||
case EVENT_USER_ERR:
|
case EVENT_USER_ERR:
|
||||||
case EVENT_DIE:
|
case EVENT_DIE:
|
||||||
case EVENT_LUA_ERR:
|
case EVENT_LUA_ERR:
|
||||||
fatal_event(&ev, msg);
|
fatal_event(&ev, msg);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case EVENT_REOPEN:
|
case EVENT_REOPEN:
|
||||||
/* Note: this may leave TCP-handling processes with the old file still open.
|
/* Note: this may leave TCP-handling processes with the old file still open.
|
||||||
|
|||||||
@@ -145,30 +145,31 @@ struct event_desc {
|
|||||||
int event, data, msg_sz;
|
int event, data, msg_sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EVENT_RELOAD 1
|
#define EVENT_RELOAD 1
|
||||||
#define EVENT_DUMP 2
|
#define EVENT_DUMP 2
|
||||||
#define EVENT_ALARM 3
|
#define EVENT_ALARM 3
|
||||||
#define EVENT_TERM 4
|
#define EVENT_TERM 4
|
||||||
#define EVENT_CHILD 5
|
#define EVENT_CHILD 5
|
||||||
#define EVENT_REOPEN 6
|
#define EVENT_REOPEN 6
|
||||||
#define EVENT_EXITED 7
|
#define EVENT_EXITED 7
|
||||||
#define EVENT_KILLED 8
|
#define EVENT_KILLED 8
|
||||||
#define EVENT_EXEC_ERR 9
|
#define EVENT_EXEC_ERR 9
|
||||||
#define EVENT_PIPE_ERR 10
|
#define EVENT_PIPE_ERR 10
|
||||||
#define EVENT_USER_ERR 11
|
#define EVENT_USER_ERR 11
|
||||||
#define EVENT_CAP_ERR 12
|
#define EVENT_CAP_ERR 12
|
||||||
#define EVENT_PIDFILE 13
|
#define EVENT_PIDFILE 13
|
||||||
#define EVENT_HUSER_ERR 14
|
#define EVENT_HUSER_ERR 14
|
||||||
#define EVENT_GROUP_ERR 15
|
#define EVENT_GROUP_ERR 15
|
||||||
#define EVENT_DIE 16
|
#define EVENT_DIE 16
|
||||||
#define EVENT_LOG_ERR 17
|
#define EVENT_LOG_ERR 17
|
||||||
#define EVENT_FORK_ERR 18
|
#define EVENT_FORK_ERR 18
|
||||||
#define EVENT_LUA_ERR 19
|
#define EVENT_LUA_ERR 19
|
||||||
#define EVENT_TFTP_ERR 20
|
#define EVENT_TFTP_ERR 20
|
||||||
#define EVENT_INIT 21
|
#define EVENT_INIT 21
|
||||||
#define EVENT_NEWADDR 22
|
#define EVENT_NEWADDR 22
|
||||||
#define EVENT_NEWROUTE 23
|
#define EVENT_NEWROUTE 23
|
||||||
#define EVENT_TIME_ERR 24
|
#define EVENT_TIME_ERR 24
|
||||||
|
#define EVENT_SCRIPT_LOG 25
|
||||||
|
|
||||||
/* Exit codes. */
|
/* Exit codes. */
|
||||||
#define EC_GOOD 0
|
#define EC_GOOD 0
|
||||||
@@ -243,8 +244,9 @@ struct event_desc {
|
|||||||
|
|
||||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
||||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||||
#define MS_TFTP LOG_USER
|
#define MS_TFTP LOG_USER
|
||||||
#define MS_DHCP LOG_DAEMON
|
#define MS_DHCP LOG_DAEMON
|
||||||
|
#define MS_SCRIPT LOG_MAIL
|
||||||
|
|
||||||
struct all_addr {
|
struct all_addr {
|
||||||
union {
|
union {
|
||||||
|
|||||||
56
src/helper.c
56
src/helper.c
@@ -14,6 +14,7 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_SCRIPT
|
#ifdef HAVE_SCRIPT
|
||||||
@@ -135,7 +136,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
max_fd != STDIN_FILENO && max_fd != pipefd[0] &&
|
max_fd != STDIN_FILENO && max_fd != pipefd[0] &&
|
||||||
max_fd != event_fd && max_fd != err_fd)
|
max_fd != event_fd && max_fd != err_fd)
|
||||||
close(max_fd);
|
close(max_fd);
|
||||||
|
|
||||||
#ifdef HAVE_LUASCRIPT
|
#ifdef HAVE_LUASCRIPT
|
||||||
if (daemon->luascript)
|
if (daemon->luascript)
|
||||||
{
|
{
|
||||||
@@ -189,6 +190,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
unsigned char *buf = (unsigned char *)daemon->namebuff;
|
unsigned char *buf = (unsigned char *)daemon->namebuff;
|
||||||
unsigned char *end, *extradata, *alloc_buff = NULL;
|
unsigned char *end, *extradata, *alloc_buff = NULL;
|
||||||
int is6, err = 0;
|
int is6, err = 0;
|
||||||
|
int pipeout[2];
|
||||||
|
|
||||||
free(alloc_buff);
|
free(alloc_buff);
|
||||||
|
|
||||||
@@ -472,16 +474,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
if (!daemon->lease_change_command)
|
if (!daemon->lease_change_command)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Pipe to capture stdout and stderr from script */
|
||||||
|
if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* possible fork errors are all temporary resource problems */
|
/* possible fork errors are all temporary resource problems */
|
||||||
while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
|
while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
continue;
|
{
|
||||||
|
if (!option_bool(OPT_DEBUG))
|
||||||
|
{
|
||||||
|
close(pipeout[0]);
|
||||||
|
close(pipeout[1]);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* wait for child to complete */
|
/* wait for child to complete */
|
||||||
if (pid != 0)
|
if (pid != 0)
|
||||||
{
|
{
|
||||||
|
if (!option_bool(OPT_DEBUG))
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
close(pipeout[1]);
|
||||||
|
|
||||||
|
/* Read lines sent to stdout/err by the script and pass them back to be logged */
|
||||||
|
if (!(fp = fdopen(pipeout[0], "r")))
|
||||||
|
close(pipeout[0]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
|
||||||
|
{
|
||||||
|
/* do not include new lines, log will append them */
|
||||||
|
size_t len = strlen(daemon->packet);
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
--len;
|
||||||
|
if (daemon->packet[len] == '\n')
|
||||||
|
daemon->packet[len] = 0;
|
||||||
|
}
|
||||||
|
send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* reap our children's children, if necessary */
|
/* reap our children's children, if necessary */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -504,6 +544,15 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!option_bool(OPT_DEBUG))
|
||||||
|
{
|
||||||
|
/* map stdout/stderr of script to pipeout */
|
||||||
|
close(pipeout[0]);
|
||||||
|
dup2(pipeout[1], STDOUT_FILENO);
|
||||||
|
dup2(pipeout[1], STDERR_FILENO);
|
||||||
|
close(pipeout[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
|
if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
|
||||||
{
|
{
|
||||||
@@ -580,7 +629,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
hostname = NULL;
|
hostname = NULL;
|
||||||
|
|
||||||
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
|
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we need to have the event_fd around if exec fails */
|
/* we need to have the event_fd around if exec fails */
|
||||||
if ((i = fcntl(event_fd, F_GETFD)) != -1)
|
if ((i = fcntl(event_fd, F_GETFD)) != -1)
|
||||||
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
|
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
|
||||||
|
|||||||
@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...)
|
|||||||
func = "-tftp";
|
func = "-tftp";
|
||||||
else if ((LOG_FACMASK & priority) == MS_DHCP)
|
else if ((LOG_FACMASK & priority) == MS_DHCP)
|
||||||
func = "-dhcp";
|
func = "-dhcp";
|
||||||
|
else if ((LOG_FACMASK & priority) == MS_SCRIPT)
|
||||||
|
func = "-script";
|
||||||
|
|
||||||
#ifdef LOG_PRI
|
#ifdef LOG_PRI
|
||||||
priority = LOG_PRI(priority);
|
priority = LOG_PRI(priority);
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user