version 1.1.1.1, 2013/07/29 19:37:40
|
version 1.1.1.2, 2014/06/15 16:31:38
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2014 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 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 |
|
#ifdef HAVE_IPV6 |
|
struct in6_addr addr6; |
|
#endif |
|
#ifdef HAVE_DHCP6 |
|
int iaid, vendorclass_count; |
|
#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 215 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 223 int create_helper(int event_fd, int err_fd, uid_t uid,
|
continue; |
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 244 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 293 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,
|
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN); |
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN); |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
else |
else |
inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN); | inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN); |
#endif |
#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 316 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 */ |
} |
} |
Line 329 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 329 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 375 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 375 int create_helper(int event_fd, int err_fd, uid_t uid,
|
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 423 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 427 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 476 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 480 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
if (data.action != ACTION_TFTP) |
if (data.action != ACTION_TFTP) |
{ |
{ |
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 497 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; |
Line 507 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 507 int create_helper(int event_fd, int err_fd, uid_t uid,
|
#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 535 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 535 int create_helper(int event_fd, int err_fd, uid_t uid,
|
|
|
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); | my_setenv("DNSMASQ_RELAY_ADDRESS", data.giaddr.s_addr != 0 ? inet_ntoa(data.giaddr) : NULL, &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 544 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; | |
} | |
} |
} |
|
|
if (option_bool(OPT_LOG_OPTS)) | my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err); |
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); |
Line 570 int create_helper(int event_fd, int err_fd, uid_t uid,
|
Line 564 int create_helper(int event_fd, int err_fd, uid_t uid,
|
{ |
{ |
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, daemon->dhcp_buff, daemon->addrbuff, hostname, (char*)NULL); | action_str, is6 ? 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 576 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 664 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 684 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 739 void queue_tftp(off_t file_len, char *filename, union
|
Line 745 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 |
#ifdef HAVE_IPV6 |
else |
else |
memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ); | buf->addr6 = peer->in6.sin6_addr; |
#endif |
#endif |
|
|
memcpy((unsigned char *)(buf+1), filename, filename_len); |
memcpy((unsigned char *)(buf+1), filename, filename_len); |