version 1.1.1.3, 2016/11/02 09:57:01
|
version 1.1.1.4, 2021/03/17 00:56:46
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
Line 18
|
Line 18
|
|
|
#ifdef HAVE_SCRIPT |
#ifdef HAVE_SCRIPT |
|
|
/* This file has code to fork a helper process which recieves data via a pipe | /* This file has code to fork a helper process which receives data via a pipe |
shared with the main process and which is responsible for calling a script when |
shared with the main process and which is responsible for calling a script when |
DHCP leases change. |
DHCP leases change. |
|
|
Line 64 struct script_data
|
Line 64 struct script_data
|
#ifdef HAVE_TFTP |
#ifdef HAVE_TFTP |
off_t file_len; |
off_t file_len; |
#endif |
#endif |
#ifdef HAVE_IPV6 |
|
struct in6_addr addr6; |
struct in6_addr addr6; |
#endif |
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
int iaid, vendorclass_count; | int vendorclass_count; |
| unsigned int iaid; |
#endif |
#endif |
unsigned char hwaddr[DHCP_CHADDR_MAX]; |
unsigned char hwaddr[DHCP_CHADDR_MAX]; |
char interface[IF_NAMESIZE]; |
char interface[IF_NAMESIZE]; |
Line 82 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 81 int create_helper(int event_fd, int err_fd, uid_t uid,
|
pid_t pid; |
pid_t pid; |
int i, pipefd[2]; |
int i, pipefd[2]; |
struct sigaction sigact; |
struct sigaction sigact; |
| unsigned char *alloc_buff = NULL; |
| |
/* create the pipe through which the main program sends us commands, |
/* create the pipe through which the main program sends us commands, |
then fork our process. */ |
then fork our process. */ |
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1) |
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1) |
Line 97 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 97 int create_helper(int event_fd, int err_fd, uid_t uid,
|
return pipefd[1]; |
return pipefd[1]; |
} |
} |
|
|
/* ignore SIGTERM, so that we can clean up when the main process gets hit | /* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit |
and SIGALRM so that we can use sleep() */ |
and SIGALRM so that we can use sleep() */ |
sigact.sa_handler = SIG_IGN; |
sigact.sa_handler = SIG_IGN; |
sigact.sa_flags = 0; |
sigact.sa_flags = 0; |
sigemptyset(&sigact.sa_mask); |
sigemptyset(&sigact.sa_mask); |
sigaction(SIGTERM, &sigact, NULL); |
sigaction(SIGTERM, &sigact, NULL); |
sigaction(SIGALRM, &sigact, NULL); |
sigaction(SIGALRM, &sigact, NULL); |
|
sigaction(SIGINT, &sigact, NULL); |
|
|
if (!option_bool(OPT_DEBUG) && uid != 0) |
if (!option_bool(OPT_DEBUG) && uid != 0) |
{ |
{ |
Line 130 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 131 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Don't close err_fd, in case the lua-init fails. |
Don't close err_fd, in case the lua-init fails. |
Note that we have to do this before lua init |
Note that we have to do this before lua init |
so we don't close any lua fds. */ |
so we don't close any lua fds. */ |
for (max_fd--; max_fd >= 0; max_fd--) | close_fds(max_fd, pipefd[0], event_fd, err_fd); |
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && | |
max_fd != STDIN_FILENO && max_fd != pipefd[0] && | |
max_fd != event_fd && max_fd != err_fd) | |
close(max_fd); | |
|
|
#ifdef HAVE_LUASCRIPT |
#ifdef HAVE_LUASCRIPT |
if (daemon->luascript) |
if (daemon->luascript) |
Line 187 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 184 int create_helper(int event_fd, int err_fd, uid_t uid,
|
struct script_data data; |
struct script_data data; |
char *p, *action_str, *hostname = NULL, *domain = NULL; |
char *p, *action_str, *hostname = NULL, *domain = NULL; |
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; |
int is6, err = 0; |
int is6, err = 0; |
|
int pipeout[2]; |
|
|
free(alloc_buff); | /* Free rarely-allocated memory from previous iteration. */ |
| if (alloc_buff) |
| { |
| free(alloc_buff); |
| alloc_buff = NULL; |
| } |
|
|
/* we read zero bytes when pipe closed: this is our signal to exit */ |
/* we read zero bytes when pipe closed: this is our signal to exit */ |
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1)) |
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1)) |
Line 300 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 303 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
if (!is6) |
if (!is6) |
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN); |
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN); |
#ifdef HAVE_IPV6 |
|
else |
else |
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN); |
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN); |
#endif |
|
|
|
#ifdef HAVE_TFTP |
#ifdef HAVE_TFTP |
/* file length */ |
/* file length */ |
Line 472 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 473 int create_helper(int event_fd, int err_fd, uid_t uid,
|
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) |
{ |
{ |
Line 504 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 543 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
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) |
{ |
{ |
Line 556 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 604 int create_helper(int event_fd, int err_fd, uid_t uid,
|
buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err); |
|
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err); |
} |
} |
|
|
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); |
Line 579 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 628 int create_helper(int event_fd, int err_fd, uid_t uid,
|
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); |
Line 775 void queue_tftp(off_t file_len, char *filename, union
|
Line 825 void queue_tftp(off_t file_len, char *filename, union
|
|
|
if ((buf->flags = peer->sa.sa_family) == AF_INET) |
if ((buf->flags = peer->sa.sa_family) == AF_INET) |
buf->addr = peer->in.sin_addr; |
buf->addr = peer->in.sin_addr; |
#ifdef HAVE_IPV6 |
|
else |
else |
buf->addr6 = peer->in6.sin6_addr; |
buf->addr6 = peer->in6.sin6_addr; |
#endif |
|
|
|
memcpy((unsigned char *)(buf+1), filename, filename_len); |
memcpy((unsigned char *)(buf+1), filename, filename_len); |
|
|
Line 786 void queue_tftp(off_t file_len, char *filename, union
|
Line 834 void queue_tftp(off_t file_len, char *filename, union
|
} |
} |
#endif |
#endif |
|
|
void queue_arp(int action, unsigned char *mac, int maclen, int family, struct all_addr *addr) | void queue_arp(int action, unsigned char *mac, int maclen, int family, union all_addr *addr) |
{ |
{ |
/* no script */ |
/* no script */ |
if (daemon->helperfd == -1) |
if (daemon->helperfd == -1) |
Line 799 void queue_arp(int action, unsigned char *mac, int mac
|
Line 847 void queue_arp(int action, unsigned char *mac, int mac
|
buf->hwaddr_len = maclen; |
buf->hwaddr_len = maclen; |
buf->hwaddr_type = ARPHRD_ETHER; |
buf->hwaddr_type = ARPHRD_ETHER; |
if ((buf->flags = family) == AF_INET) |
if ((buf->flags = family) == AF_INET) |
buf->addr = addr->addr.addr4; | buf->addr = addr->addr4; |
#ifdef HAVE_IPV6 | |
else |
else |
buf->addr6 = addr->addr.addr6; | buf->addr6 = addr->addr6; |
#endif | |
|
|
memcpy(buf->hwaddr, mac, maclen); |
memcpy(buf->hwaddr, mac, maclen); |
|
|