version 1.1.1.1, 2013/07/29 19:37:40
|
version 1.1.1.5, 2023/09/27 11:02:07
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2022 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 61 struct script_data
|
Line 61 struct script_data
|
#else |
#else |
time_t expires; |
time_t expires; |
#endif |
#endif |
|
#ifdef HAVE_TFTP |
|
off_t file_len; |
|
#endif |
|
struct in6_addr addr6; |
|
#ifdef HAVE_DHCP6 |
|
int vendorclass_count; |
|
unsigned int iaid; |
|
#endif |
unsigned char hwaddr[DHCP_CHADDR_MAX]; |
unsigned char hwaddr[DHCP_CHADDR_MAX]; |
char interface[IF_NAMESIZE]; |
char interface[IF_NAMESIZE]; |
|
|
}; |
}; |
|
|
static struct script_data *buf = NULL; |
static struct script_data *buf = NULL; |
Line 74 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 89 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 122 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 179 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 211 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 222 int create_helper(int event_fd, int err_fd, uid_t uid,
|
action_str = "tftp"; |
action_str = "tftp"; |
is6 = (data.flags != AF_INET); |
is6 = (data.flags != AF_INET); |
} |
} |
else | else if (data.action == ACTION_ARP) |
continue; | { |
| action_str = "arp-add"; |
| is6 = (data.flags != AF_INET); |
| } |
| else if (data.action == ACTION_ARP_DEL) |
| { |
| action_str = "arp-del"; |
| is6 = (data.flags != AF_INET); |
| data.action = ACTION_ARP; |
| } |
| else if (data.action == ACTION_RELAY_SNOOP) |
| { |
| is6 = 1; |
| action_str = "relay-snoop"; |
| } |
| else |
| continue; |
|
|
if (!is6) | /* stringify MAC into dhcp_buff */ |
| p = daemon->dhcp_buff; |
| if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0) |
| p += sprintf(p, "%.2x-", data.hwaddr_type); |
| for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++) |
{ |
{ |
/* stringify MAC into dhcp_buff */ | p += sprintf(p, "%.2x", data.hwaddr[i]); |
p = daemon->dhcp_buff; | if (i != data.hwaddr_len - 1) |
if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0) | p += sprintf(p, ":"); |
p += sprintf(p, "%.2x-", data.hwaddr_type); | |
for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++) | |
{ | |
p += sprintf(p, "%.2x", data.hwaddr[i]); | |
if (i != data.hwaddr_len - 1) | |
p += sprintf(p, ":"); | |
} | |
} |
} |
| |
/* supplied data may just exceed normal buffer (unlikely) */ |
/* supplied data may just exceed normal buffer (unlikely) */ |
if ((data.hostname_len + data.ed_len + data.clid_len) > MAXDNAME && |
if ((data.hostname_len + data.ed_len + data.clid_len) > MAXDNAME && |
!(alloc_buff = buf = malloc(data.hostname_len + data.ed_len + data.clid_len))) |
!(alloc_buff = buf = malloc(data.hostname_len + data.ed_len + data.clid_len))) |
Line 239 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 262 int create_helper(int event_fd, int err_fd, uid_t uid,
|
continue; |
continue; |
|
|
/* CLID into packet */ |
/* CLID into packet */ |
if (!is6) | for (p = daemon->packet, i = 0; i < data.clid_len; i++) |
for (p = daemon->packet, i = 0; i < data.clid_len; i++) | { |
{ | p += sprintf(p, "%.2x", buf[i]); |
p += sprintf(p, "%.2x", buf[i]); | if (i != data.clid_len - 1) |
if (i != data.clid_len - 1) | |
p += sprintf(p, ":"); |
p += sprintf(p, ":"); |
} | } |
| |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
else | if (is6) |
{ |
{ |
/* or IAID and server DUID for IPv6 */ |
/* or IAID and server DUID for IPv6 */ |
sprintf(daemon->dhcp_buff3, "%s%u", data.flags & LEASE_TA ? "T" : "", data.hwaddr_type); | sprintf(daemon->dhcp_buff3, "%s%u", data.flags & LEASE_TA ? "T" : "", data.iaid); |
for (p = daemon->packet, i = 0; i < daemon->duid_len; i++) | for (p = daemon->dhcp_packet.iov_base, i = 0; i < daemon->duid_len; i++) |
{ |
{ |
p += sprintf(p, "%.2x", daemon->duid[i]); |
p += sprintf(p, "%.2x", daemon->duid[i]); |
if (i != daemon->duid_len - 1) |
if (i != daemon->duid_len - 1) |
p += sprintf(p, ":"); |
p += sprintf(p, ":"); |
} |
} |
|
|
/* duid not MAC for IPv6 */ |
|
for (p = daemon->dhcp_buff, i = 0; i < data.clid_len; i++) |
|
{ |
|
p += sprintf(p, "%.2x", buf[i]); |
|
if (i != data.clid_len - 1) |
|
p += sprintf(p, ":"); |
|
} |
|
} |
} |
#endif |
#endif |
|
|
Line 275 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 291 int create_helper(int event_fd, int err_fd, uid_t uid,
|
char *dot; |
char *dot; |
hostname = (char *)buf; |
hostname = (char *)buf; |
hostname[data.hostname_len - 1] = 0; |
hostname[data.hostname_len - 1] = 0; |
if (data.action != ACTION_TFTP) | if (data.action != ACTION_TFTP && data.action != ACTION_RELAY_SNOOP) |
{ |
{ |
if (!legal_hostname(hostname)) |
if (!legal_hostname(hostname)) |
hostname = NULL; |
hostname = NULL; |
Line 291 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 307 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_DHCP6 |
|
else |
else |
inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN); | inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN); |
#endif | |
|
|
|
#ifdef HAVE_TFTP |
/* file length */ |
/* file length */ |
if (data.action == ACTION_TFTP) |
if (data.action == ACTION_TFTP) |
sprintf(daemon->dhcp_buff, "%u", data.hwaddr_len); | sprintf(is6 ? daemon->packet : daemon->dhcp_buff, "%lu", (unsigned long)data.file_len); |
| #endif |
| |
#ifdef HAVE_LUASCRIPT |
#ifdef HAVE_LUASCRIPT |
if (daemon->luascript) |
if (daemon->luascript) |
{ |
{ |
Line 316 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 332 int create_helper(int event_fd, int err_fd, uid_t uid,
|
lua_setfield(lua, -2, "destination_address"); |
lua_setfield(lua, -2, "destination_address"); |
lua_pushstring(lua, hostname); |
lua_pushstring(lua, hostname); |
lua_setfield(lua, -2, "file_name"); |
lua_setfield(lua, -2, "file_name"); |
lua_pushstring(lua, daemon->dhcp_buff); | lua_pushstring(lua, is6 ? daemon->packet : daemon->dhcp_buff); |
lua_setfield(lua, -2, "file_size"); |
lua_setfield(lua, -2, "file_size"); |
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ |
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ |
} |
} |
} |
} |
|
else if (data.action == ACTION_RELAY_SNOOP) |
|
{ |
|
lua_getglobal(lua, "snoop"); |
|
if (lua_type(lua, -1) != LUA_TFUNCTION) |
|
lua_pop(lua, 1); /* tftp function optional */ |
|
else |
|
{ |
|
lua_pushstring(lua, action_str); /* arg1 - action */ |
|
lua_newtable(lua); /* arg2 - data table */ |
|
lua_pushstring(lua, daemon->addrbuff); |
|
lua_setfield(lua, -2, "client_address"); |
|
lua_pushstring(lua, hostname); |
|
lua_setfield(lua, -2, "prefix"); |
|
lua_pushstring(lua, data.interface); |
|
lua_setfield(lua, -2, "client_interface"); |
|
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ |
|
} |
|
} |
|
else if (data.action == ACTION_ARP) |
|
{ |
|
lua_getglobal(lua, "arp"); |
|
if (lua_type(lua, -1) != LUA_TFUNCTION) |
|
lua_pop(lua, 1); /* arp function optional */ |
|
else |
|
{ |
|
lua_pushstring(lua, action_str); /* arg1 - action */ |
|
lua_newtable(lua); /* arg2 - data table */ |
|
lua_pushstring(lua, daemon->addrbuff); |
|
lua_setfield(lua, -2, "client_address"); |
|
lua_pushstring(lua, daemon->dhcp_buff); |
|
lua_setfield(lua, -2, "mac_address"); |
|
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */ |
|
} |
|
} |
else |
else |
{ |
{ |
lua_getglobal(lua, "lease"); /* function to call */ |
lua_getglobal(lua, "lease"); /* function to call */ |
Line 329 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 379 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
if (is6) |
if (is6) |
{ |
{ |
lua_pushstring(lua, daemon->dhcp_buff); |
|
lua_setfield(lua, -2, "client_duid"); |
|
lua_pushstring(lua, daemon->packet); |
lua_pushstring(lua, daemon->packet); |
|
lua_setfield(lua, -2, "client_duid"); |
|
lua_pushstring(lua, daemon->dhcp_packet.iov_base); |
lua_setfield(lua, -2, "server_duid"); |
lua_setfield(lua, -2, "server_duid"); |
lua_pushstring(lua, daemon->dhcp_buff3); |
lua_pushstring(lua, daemon->dhcp_buff3); |
lua_setfield(lua, -2, "iaid"); |
lua_setfield(lua, -2, "iaid"); |
Line 371 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 421 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
end = extradata + data.ed_len; |
end = extradata + data.ed_len; |
buf = extradata; |
buf = extradata; |
|
|
|
lua_pushnumber(lua, data.ed_len == 0 ? 1 : 0); |
|
lua_setfield(lua, -2, "data_missing"); |
|
|
if (!is6) |
if (!is6) |
buf = grab_extradata_lua(buf, end, "vendor_class"); |
buf = grab_extradata_lua(buf, end, "vendor_class"); |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
else | else if (data.vendorclass_count != 0) |
for (i = 0; i < data.hwaddr_len; i++) | { |
{ | sprintf(daemon->dhcp_buff2, "vendor_class_id"); |
sprintf(daemon->dhcp_buff2, "vendor_class%i", i); | buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); |
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); | for (i = 0; i < data.vendorclass_count - 1; i++) |
} | { |
| sprintf(daemon->dhcp_buff2, "vendor_class%i", i); |
| buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); |
| } |
| } |
#endif |
#endif |
|
|
buf = grab_extradata_lua(buf, end, "supplied_hostname"); |
buf = grab_extradata_lua(buf, end, "supplied_hostname"); |
Line 394 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 451 int create_helper(int event_fd, int err_fd, uid_t uid,
|
buf = grab_extradata_lua(buf, end, "subscriber_id"); |
buf = grab_extradata_lua(buf, end, "subscriber_id"); |
buf = grab_extradata_lua(buf, end, "remote_id"); |
buf = grab_extradata_lua(buf, end, "remote_id"); |
} |
} |
| |
| buf = grab_extradata_lua(buf, end, "requested_options"); |
| buf = grab_extradata_lua(buf, end, "mud_url"); |
buf = grab_extradata_lua(buf, end, "tags"); |
buf = grab_extradata_lua(buf, end, "tags"); |
|
|
if (is6) |
if (is6) |
buf = grab_extradata_lua(buf, end, "relay_address"); |
buf = grab_extradata_lua(buf, end, "relay_address"); |
else if (data.giaddr.s_addr != 0) |
else if (data.giaddr.s_addr != 0) |
{ |
{ |
lua_pushstring(lua, inet_ntoa(data.giaddr)); | inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN); |
| lua_pushstring(lua, daemon->dhcp_buff2); |
lua_setfield(lua, -2, "relay_address"); |
lua_setfield(lua, -2, "relay_address"); |
} |
} |
|
|
Line 423 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 483 int create_helper(int event_fd, int err_fd, uid_t uid,
|
lua_setfield(lua, -2, "old_hostname"); |
lua_setfield(lua, -2, "old_hostname"); |
} |
} |
|
|
if (!is6) | if (!is6 || data.hwaddr_len != 0) |
{ |
{ |
lua_pushstring(lua, daemon->dhcp_buff); |
lua_pushstring(lua, daemon->dhcp_buff); |
lua_setfield(lua, -2, "mac_address"); |
lua_setfield(lua, -2, "mac_address"); |
Line 441 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 501 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 473 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 571 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) | if (data.action != ACTION_TFTP && data.action != ACTION_ARP && data.action != ACTION_RELAY_SNOOP) |
{ |
{ |
if (is6) | #ifdef HAVE_DHCP6 |
{ | my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err); |
my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err); | my_setenv("DNSMASQ_SERVER_DUID", is6 ? daemon->dhcp_packet.iov_base : NULL, &err); |
my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err); | my_setenv("DNSMASQ_MAC", is6 && data.hwaddr_len != 0 ? daemon->dhcp_buff : NULL, &err); |
} | #endif |
|
|
if (!is6 && data.clid_len != 0) | my_setenv("DNSMASQ_CLIENT_ID", !is6 && data.clid_len != 0 ? daemon->packet : NULL, &err); |
my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err); | my_setenv("DNSMASQ_INTERFACE", strlen(data.interface) != 0 ? data.interface : NULL, &err); |
|
|
if (strlen(data.interface) != 0) |
|
my_setenv("DNSMASQ_INTERFACE", data.interface, &err); |
|
|
|
#ifdef HAVE_BROKEN_RTC |
#ifdef HAVE_BROKEN_RTC |
sprintf(daemon->dhcp_buff2, "%u", data.length); |
sprintf(daemon->dhcp_buff2, "%u", data.length); |
my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err); |
my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err); |
Line 496 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 600 int create_helper(int event_fd, int err_fd, uid_t uid,
|
my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); |
my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); |
#endif |
#endif |
|
|
if (domain) | my_setenv("DNSMASQ_DOMAIN", domain, &err); |
my_setenv("DNSMASQ_DOMAIN", domain, &err); | |
|
|
end = extradata + data.ed_len; |
end = extradata + data.ed_len; |
buf = extradata; |
buf = extradata; |
|
|
|
if (data.ed_len == 0) |
|
my_setenv("DNSMASQ_DATA_MISSING", "1", &err); |
|
|
if (!is6) |
if (!is6) |
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err); |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
else |
else |
{ |
{ |
if (data.hwaddr_len != 0) | if (data.vendorclass_count != 0) |
{ |
{ |
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err); |
for (i = 0; i < data.hwaddr_len - 1; i++) | for (i = 0; i < data.vendorclass_count - 1; i++) |
{ |
{ |
sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i); |
sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i); |
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); |
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); |
Line 531 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 637 int create_helper(int event_fd, int err_fd, uid_t uid,
|
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_MUD_URL", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); |
| |
if (is6) |
if (is6) |
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err); |
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err); |
else if (data.giaddr.s_addr != 0) | else |
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err); | { |
| const char *giaddr = NULL; |
| if (data.giaddr.s_addr != 0) |
| giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN); |
| my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &err); |
| } |
|
|
for (i = 0; buf; i++) |
for (i = 0; buf; i++) |
{ |
{ |
Line 544 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 657 int create_helper(int event_fd, int err_fd, uid_t uid,
|
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); |
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); |
} |
} |
|
|
if (data.action != ACTION_DEL && data.remaining_time != 0) | sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); |
{ | my_setenv("DNSMASQ_TIME_REMAINING", data.action != ACTION_DEL && data.remaining_time != 0 ? daemon->dhcp_buff2 : NULL, &err); |
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); | |
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); | |
} | |
|
|
if (data.action == ACTION_OLD_HOSTNAME && hostname) | my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err); |
{ | if (data.action == ACTION_OLD_HOSTNAME) |
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err); | hostname = NULL; |
hostname = NULL; | |
} | my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err); |
} |
} |
| |
if (option_bool(OPT_LOG_OPTS)) | |
my_setenv("DNSMASQ_LOG_DHCP", "1", &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); |
close(pipefd[0]); |
close(pipefd[0]); |
|
|
|
if (data.action == ACTION_RELAY_SNOOP) |
|
strcpy(daemon->packet, data.interface); |
|
|
p = strrchr(daemon->lease_change_command, '/'); |
p = strrchr(daemon->lease_change_command, '/'); |
if (err == 0) |
if (err == 0) |
{ |
{ |
execl(daemon->lease_change_command, |
execl(daemon->lease_change_command, |
p ? p+1 : daemon->lease_change_command, | p ? p+1 : daemon->lease_change_command, action_str, |
action_str, daemon->dhcp_buff, daemon->addrbuff, hostname, (char*)NULL); | (is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff, |
| daemon->addrbuff, hostname, (char*)NULL); |
err = errno; |
err = errno; |
} |
} |
/* failed, send event so the main process logs the problem */ |
/* failed, send event so the main process logs the problem */ |
Line 581 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 692 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
static void my_setenv(const char *name, const char *value, int *error) |
static void my_setenv(const char *name, const char *value, int *error) |
{ |
{ |
if (*error == 0 && setenv(name, value, 1) != 0) | if (*error == 0) |
*error = errno; | { |
| if (!value) |
| unsetenv(name); |
| else if (setenv(name, value, 1) != 0) |
| *error = errno; |
| } |
} |
} |
|
|
static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err) |
static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err) |
{ |
{ |
unsigned char *next; | unsigned char *next = NULL; |
| char *val = NULL; |
|
|
if (!buf || (buf == end)) | if (buf && (buf != end)) |
return NULL; | |
| |
for (next = buf; *next != 0; next++) | |
if (next == end) | |
return NULL; | |
| |
if (next != buf) | |
{ |
{ |
char *p; | for (next = buf; ; next++) |
/* No "=" in value */ | if (next == end) |
if ((p = strchr((char *)buf, '='))) | { |
*p = 0; | next = NULL; |
my_setenv(env, (char *)buf, err); | break; |
} | } |
| else if (*next == 0) |
| break; |
|
|
return next + 1; | if (next && (next != buf)) |
| { |
| char *p; |
| /* No "=" in value */ |
| if ((p = strchr((char *)buf, '='))) |
| *p = 0; |
| val = (char *)buf; |
| } |
| } |
| |
| my_setenv(env, val, err); |
| |
| return next ? next + 1 : NULL; |
} |
} |
|
|
#ifdef HAVE_LUASCRIPT |
#ifdef HAVE_LUASCRIPT |
Line 656 void queue_script(int action, struct dhcp_lease *lease
|
Line 780 void queue_script(int action, struct dhcp_lease *lease
|
unsigned int hostname_len = 0, clid_len = 0, ed_len = 0; |
unsigned int hostname_len = 0, clid_len = 0, ed_len = 0; |
int fd = daemon->dhcpfd; |
int fd = daemon->dhcpfd; |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
int is6 = !!(lease->flags & (LEASE_TA | LEASE_NA)); |
|
|
|
if (!daemon->dhcp) |
if (!daemon->dhcp) |
fd = daemon->dhcp6fd; |
fd = daemon->dhcp6fd; |
#endif |
#endif |
Line 678 void queue_script(int action, struct dhcp_lease *lease
|
Line 800 void queue_script(int action, struct dhcp_lease *lease
|
buf->action = action; |
buf->action = action; |
buf->flags = lease->flags; |
buf->flags = lease->flags; |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
if (is6) | buf->vendorclass_count = lease->vendorclass_count; |
buf->hwaddr_len = lease->vendorclass_count; | buf->addr6 = lease->addr6; |
else | buf->iaid = lease->iaid; |
#endif |
#endif |
buf->hwaddr_len = lease->hwaddr_len; | buf->hwaddr_len = lease->hwaddr_len; |
buf->hwaddr_type = lease->hwaddr_type; |
buf->hwaddr_type = lease->hwaddr_type; |
buf->clid_len = clid_len; |
buf->clid_len = clid_len; |
buf->ed_len = ed_len; |
buf->ed_len = ed_len; |
Line 723 void queue_script(int action, struct dhcp_lease *lease
|
Line 845 void queue_script(int action, struct dhcp_lease *lease
|
bytes_in_buf = p - (unsigned char *)buf; |
bytes_in_buf = p - (unsigned char *)buf; |
} |
} |
|
|
|
#ifdef HAVE_DHCP6 |
|
void queue_relay_snoop(struct in6_addr *client, int if_index, struct in6_addr *prefix, int prefix_len) |
|
{ |
|
/* no script */ |
|
if (daemon->helperfd == -1) |
|
return; |
|
|
|
inet_ntop(AF_INET6, prefix, daemon->addrbuff, ADDRSTRLEN); |
|
|
|
/* 5 for /nnn and zero on the end of the prefix. */ |
|
buff_alloc(sizeof(struct script_data) + ADDRSTRLEN + 5); |
|
memset(buf, 0, sizeof(struct script_data)); |
|
|
|
buf->action = ACTION_RELAY_SNOOP; |
|
buf->addr6 = *client; |
|
buf->hostname_len = sprintf((char *)(buf+1), "%s/%u", daemon->addrbuff, prefix_len) + 1; |
|
|
|
indextoname(daemon->dhcp6fd, if_index, buf->interface); |
|
|
|
bytes_in_buf = sizeof(struct script_data) + buf->hostname_len; |
|
} |
|
#endif |
|
|
#ifdef HAVE_TFTP |
#ifdef HAVE_TFTP |
/* This nastily re-uses DHCP-fields for TFTP stuff */ |
/* This nastily re-uses DHCP-fields for TFTP stuff */ |
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer) |
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer) |
Line 739 void queue_tftp(off_t file_len, char *filename, union
|
Line 884 void queue_tftp(off_t file_len, char *filename, union
|
|
|
buf->action = ACTION_TFTP; |
buf->action = ACTION_TFTP; |
buf->hostname_len = filename_len; |
buf->hostname_len = filename_len; |
buf->hwaddr_len = file_len; | buf->file_len = file_len; |
|
|
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 |
memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ); | buf->addr6 = peer->in6.sin6_addr; |
#endif | |
|
|
memcpy((unsigned char *)(buf+1), filename, filename_len); |
memcpy((unsigned char *)(buf+1), filename, filename_len); |
|
|
Line 754 void queue_tftp(off_t file_len, char *filename, union
|
Line 897 void queue_tftp(off_t file_len, char *filename, union
|
} |
} |
#endif |
#endif |
|
|
|
void queue_arp(int action, unsigned char *mac, int maclen, int family, union all_addr *addr) |
|
{ |
|
/* no script */ |
|
if (daemon->helperfd == -1) |
|
return; |
|
|
|
buff_alloc(sizeof(struct script_data)); |
|
memset(buf, 0, sizeof(struct script_data)); |
|
|
|
buf->action = action; |
|
buf->hwaddr_len = maclen; |
|
buf->hwaddr_type = ARPHRD_ETHER; |
|
if ((buf->flags = family) == AF_INET) |
|
buf->addr = addr->addr4; |
|
else |
|
buf->addr6 = addr->addr6; |
|
|
|
memcpy(buf->hwaddr, mac, maclen); |
|
|
|
bytes_in_buf = sizeof(struct script_data); |
|
} |
|
|
int helper_buf_empty(void) |
int helper_buf_empty(void) |
{ |
{ |
return bytes_in_buf == 0; |
return bytes_in_buf == 0; |
Line 780 void helper_write(void)
|
Line 945 void helper_write(void)
|
} |
} |
} |
} |
|
|
#endif | #endif /* HAVE_SCRIPT */ |
| |
| |
| |