|
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); |
| |
|