Compare commits

..
12 Commits
15 changed files with 619 additions and 360 deletions

No files matched your search

+31
View File
@@ -24,6 +24,37 @@ version 2.61
Add --host-record. Thanks to Rob Zwissler for the
suggestion.
Invoke the DHCP script with action "tftp" when a TFTP file
transfer completes. The size of the file, address to which
it was sent and complete pathname are supplied. Note that
version 2.60 introduced some script incompatibilties
associated with DHCPv6, and this is a further change. To
be safe, scripts should ignore unknown actions, and if
not IPv6-aware, should exit if the environment
variable DNSMASQ_IAID is set. The use-case for this is
to track netboot/install. Suggestion from Shantanu
Gadgil.
Update contrib/port-forward/dnsmasq-portforward to reflect
the above.
Set the environment variable DNSMASQ_LOG_DHCP when running
the script id --log-dhcp is in effect, so that script can
taylor their logging verbosity. Suggestion from Malte
Forkel.
Arrange that addresses specified with --listen-address
work even if there is no interface carrying the
address. This is chiefly useful for IPv4 loopback
addresses, where any address in 127.0.0.0/8 is a valid
loopback address, but normally only 127.0.0.1 appears on
the lo interface. Thanks to Mathieu Trudel-Lapierre for
the idea and initial patch.
Fix crash, introduced in 2.60, when a DHCPINFORM is
received from a network which has no valid dhcp-range.
Thanks to Stephane Glondu for the bug report.
version 2.60
Fix compilation problem in Mac OS X Lion. Thanks to Olaf
+10
View File
@@ -34,11 +34,21 @@ if [ ${DNSMASQ_OLD_HOSTNAME} ] && [ ${action} = old ] ; then
hostname=${DNSMASQ_OLD_HOSTNAME}
fi
# IPv6 leases are not our concern. no NAT there!
if [ ${DNSMASQ_IAID} ] ; then
exit 0
fi
# action init is not relevant, and will only be seen when leasefile-ro is set.
if [ ${action} = init ] ; then
exit 0
fi
# action tftp is not relevant.
if [ ${action} = tftp ] ; then
exit 0
fi
if [ ${hostname} ]; then
ports=$(sed -n -e "/^${hostname}\ .*/ s/^.* //p" ${PORTSFILE})
+6
View File
@@ -7,6 +7,12 @@ dnsmasq (2.61-1) unstable; urgency=low
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 6 Mar 2012 19:45:43 +0000
dnsmasq (2.60-2) unstable; urgency=high
* Fix DHCPv4 segfault. (closes: #665008)
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 23 Mar 2012 09:37:23 +0000
dnsmasq (2.60-1) unstable; urgency=low
* New upstream.
+45 -14
View File
@@ -576,14 +576,14 @@ for details. Instead, the keyword
.B ra-names
may be used. This does the same at ra-only, but also enables a mode
which gives DNS names to dual-stack hosts which do SLAAC for
IPv6. Dnsmasq uses the hosts IPv4 lease to derive the name, network
IPv6. Dnsmasq uses the host's IPv4 lease to derive the name, network
segment and MAC address and assumes that the host will also have an
IPv6 address calculated using the SLAAC alogrithm, on the same network
segment. An AAAA record is added to the DNS for this IPv6
segment. The address is pinged, and if a reply is received, an AAAA
record is added to the DNS for this IPv6
address. Note that this is only happens for directly-connected
networks, (not one doing DHCP via a relay) and it will generate an
erroneous AAAA record if a host is using privacy extensions or does
not support IPv6. Use with care.
networks, (not one doing DHCP via a relay) and it will not work
if a host is using privacy extensions.
The interface:<interface name> section is not normally used. See the
NOTES section for details of this.
@@ -1069,7 +1069,8 @@ re-intialised. The enterprise-id is assigned by IANA, and the uid is a
string of hex octets unique to a particular device.
.TP
.B \-6 --dhcp-script=<path>
Whenever a new DHCP lease is created, or an old one destroyed, the
Whenever a new DHCP lease is created, or an old one destroyed, or a
TFTP file transfer completes, the
executable specified by this option is run. <path>
must be an absolute pathname, no PATH search occurs.
The arguments to the process
@@ -1119,6 +1120,8 @@ is known.
DNSMASQ_TAGS contains all the tags set during the
DHCP transaction, separated by spaces.
DNSMASQ_LOG_DHCP is set if --log-dhcp is in effect.
For IPv4 only:
DNSMASQ_CLIENT_ID if the host provided a client-id.
@@ -1145,6 +1148,8 @@ only supplied for
since these data are not held in dnsmasq's lease
database.
All file descriptors are
closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode).
@@ -1163,6 +1168,17 @@ all existing leases as they are read from the lease file. Expired
leases will be called with "del" and others with "old". When dnsmasq
receives a HUP signal, the script will be invoked for existing leases
with an "old " event.
There are two further actions which may appear as the first argument
to the script, "init" and "tftp". More may be added in the future, so
scripts should be written to ignore unknown actions. "init" is
decsribed below in
.B --leasefile-ro
The "tftp" action is invoked when a TFTP file transfer completes: the
arguments are the file size in bytes, the address to which the file
was sent, and the complete pathname of the file.
.TP
.B --dhcp-luascript=<path>
Specify a script written in Lua, to be run when leases are created,
@@ -1176,11 +1192,13 @@ function, and may provide
and
.B shutdown
functions, which are called, without arguments when dnsmasq starts up
and terminates.
and terminates. It may also provide a
.B tftp
function.
The
.B lease
method receives the information detailed in
function receives the information detailed in
.B --dhcp-script.
It gets two arguments, firstly the action, which is a string
containing, "add", "old" or "del", and secondly a table of tag value
@@ -1197,7 +1215,16 @@ for IPv4, and
.B client_duid, ip_address
and
.B hostname
for IPv6.
for IPv6.
The
.B tftp
function is called in the same way as the lease function, and the
table holds the tags
.B destination_address,
.B file_name
and
.B file_size.
.TP
.B --dhcp-scriptuser
Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag.
@@ -1292,13 +1319,17 @@ only a subset of this is needed, and dnsmasq can handle it, using
existing DHCP configuration to provide most data. When RA is enabled,
dnsmasq will advertise a prefix for each dhcp-range, with default
router and recursive DNS server as the relevant link-local address on
the machine running dnsmasq. The "managed address" bits are set,
except for a dhcp-range which is marked as "ra-only", in which case RA
is provided but no DHCPv6 service and the managed address bits are
cleared.
the machine running dnsmasq. The "managed address" bits are set, and
the "use SLAAC" bit is reset, except for a dhcp-range which is
marked as "ra-only" or "ra-names", in which case RA is provided but no
DHCPv6 service and the managed address bits are
cleared and the "use SLAAC" bit set. If the same subnet appears in a
normal dhcp-range and an "ra-only" dhcp-range, then the "managed
address" bits and the "use SLAAC" bits are all set, allowing SLAAC and
DHCP address to co-exist on the same subnet.
.B enable-ra
enables router advertisement for prefixes where dnsmasq is doing
DHCPv6. It is not needed to "ra-only" prefixes. Creating an "ra-only"
DHCPv6. It is not needed for "ra-only" prefixes. Creating an "ra-only"
prefix and not setting
.B enable-ra
sends advertisements only to "ra-only" prefixes.
+1 -1
View File
@@ -229,7 +229,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
if (c->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS))
continue;
else if (!match_netid(c->filter, netids, pass))
continue;
+57 -50
View File
@@ -23,7 +23,6 @@ struct daemon *daemon;
static volatile pid_t pid = 0;
static volatile int pipewrite;
static int alarm_queued = 0;
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
static void check_dns_listeners(fd_set *set, time_t now);
@@ -210,13 +209,6 @@ int main (int argc, char **argv)
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
if (!if_tmp->used)
{
prettyprint_addr(&if_tmp->addr, daemon->namebuff);
die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
}
}
else
create_wildcard_listeners();
@@ -557,23 +549,30 @@ int main (int argc, char **argv)
{
start = &dhcp_tmp->start6;
end = &dhcp_tmp->end6;
struct in6_addr subnet = dhcp_tmp->start6;
setaddr6part(&subnet, 0);
inet_ntop(AF_INET6, &subnet, daemon->dhcp_buff2, 256);
}
#endif
prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
prettyprint_time(daemon->namebuff, dhcp_tmp->lease_time);
inet_ntop(family, start, daemon->dhcp_buff, 256);
inet_ntop(family, end, daemon->dhcp_buff3, 256);
my_syslog(MS_DHCP | LOG_INFO,
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, lease time %s") :
(dhcp_tmp->flags & CONTEXT_RA_NAME) ?
_("router advertisement with DHCPv4-derived names on %.0s%s, lifetime %s") :
(dhcp_tmp->flags & CONTEXT_RA_ONLY) ?
_("router advertisement only on %.0s%s, lifetime %s") :
(dhcp_tmp->flags & CONTEXT_PROXY) ?
_("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, IP range %s -- %s, lease time %s"),
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->dhcp_buff2);
if ((dhcp_tmp->flags & CONTEXT_DHCP) || family == AF_INET)
my_syslog(MS_DHCP | LOG_INFO,
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, lease time %s") :
(dhcp_tmp->flags & CONTEXT_RA_STATELESS) ?
_("SLAAC and stateless DHCPv6 on %.0s%s%.0s") :
(dhcp_tmp->flags & CONTEXT_PROXY) ?
_("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, IP range %s -- %s, lease time %s"),
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
if (dhcp_tmp->flags & CONTEXT_RA_NAME)
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC and DHCPv4-derived names on %s"), daemon->dhcp_buff2);
if (dhcp_tmp->flags & CONTEXT_RA_ONLY)
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC on %s"), daemon->dhcp_buff2);
}
#ifdef HAVE_DHCP6
@@ -701,12 +700,12 @@ int main (int argc, char **argv)
{
FD_SET(daemon->dhcp6fd, &rset);
bump_maxfd(daemon->dhcp6fd, &maxfd);
if (daemon->ra_contexts)
{
FD_SET(daemon->icmp6fd, &rset);
bump_maxfd(daemon->icmp6fd, &maxfd);
}
}
if (daemon->ra_contexts)
{
FD_SET(daemon->icmp6fd, &rset);
bump_maxfd(daemon->icmp6fd, &maxfd);
}
#endif
@@ -722,6 +721,10 @@ int main (int argc, char **argv)
# ifdef HAVE_SCRIPT
while (helper_buf_empty() && do_script_run(now));
# ifdef HAVE_TFTP
while (helper_buf_empty() && do_tftp_script_run());
# endif
if (!helper_buf_empty())
{
FD_SET(daemon->helperfd, &wset);
@@ -730,6 +733,11 @@ int main (int argc, char **argv)
# else
/* need this for other side-effects */
while (do_script_run(now));
# ifdef HAVE_TFTP
while (do_tftp_script_run());
# endif
# endif
#endif
@@ -868,20 +876,14 @@ static void sig_handler(int sig)
/* now == 0 -> queue immediate callback */
void send_alarm(time_t event, time_t now)
{
if (now != 0 && event == 0)
return;
if ((now == 0 || difftime(event, now) <= 0.0))
if (now == 0 || event != 0)
{
if (!alarm_queued)
{
send_event(pipewrite, EVENT_ALARM, 0, NULL);
alarm_queued = 1;
}
/* alarm(0) or alarm(-ve) doesn't do what we want.... */
if ((now == 0 || difftime(event, now) <= 0.0))
send_event(pipewrite, EVENT_ALARM, 0, NULL);
else
alarm((unsigned)difftime(event, now));
}
else
alarm((unsigned)difftime(event, now));
}
void send_event(int fd, int event, int data, char *msg)
@@ -995,7 +997,6 @@ static void async_event(int pipe, time_t now)
break;
case EVENT_ALARM:
alarm_queued = 0;
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->dhcp6)
{
@@ -1283,18 +1284,19 @@ static void check_dns_listeners(fd_set *set, time_t now)
int confd;
struct irec *iface = NULL;
pid_t p;
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
if (confd == -1 ||
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
continue;
if (option_bool(OPT_NOWILD))
iface = listener->iface;
iface = listener->iface; /* May be NULL */
else
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
@@ -1302,14 +1304,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces() &&
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
if (enumerate_interfaces())
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
}
if (!iface)
if (!iface && !option_bool(OPT_NOWILD))
{
shutdown(confd, SHUT_RDWR);
close(confd);
@@ -1335,7 +1336,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
unsigned char *buff;
struct server *s;
int flags;
struct in_addr netmask;
if (iface)
netmask = iface->netmask;
else
netmask.s_addr = 0;
#ifndef NO_FORK
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
@@ -1353,7 +1360,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
buff = tcp_request(confd, now, &iface->addr, iface->netmask);
buff = tcp_request(confd, now, &tcp_addr, netmask);
shutdown(confd, SHUT_RDWR);
close(confd);
+19 -12
View File
@@ -395,7 +395,7 @@ struct irec {
struct listener {
int fd, tcpfd, tftpfd, family;
struct irec *iface; /* only valid for non-wildcard */
struct irec *iface; /* only sometimes valid for non-wildcard */
struct listener *next;
};
@@ -458,6 +458,7 @@ struct frec {
#define ACTION_OLD_HOSTNAME 2
#define ACTION_OLD 3
#define ACTION_ADD 4
#define ACTION_TFTP 5
#define LEASE_NEW 1 /* newly created */
#define LEASE_CHANGED 2 /* modified */
@@ -645,13 +646,15 @@ struct dhcp_context {
struct dhcp_context *next, *current;
};
#define CONTEXT_STATIC 1
#define CONTEXT_NETMASK 2
#define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8
#define CONTEXT_RA_ONLY 16
#define CONTEXT_RA_DONE 32
#define CONTEXT_RA_NAME 64
#define CONTEXT_STATIC 1
#define CONTEXT_NETMASK 2
#define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8
#define CONTEXT_RA_ONLY 16
#define CONTEXT_RA_DONE 32
#define CONTEXT_RA_NAME 64
#define CONTEXT_RA_STATELESS 128
#define CONTEXT_DHCP 256
struct ping_result {
struct in_addr addr;
@@ -803,7 +806,7 @@ extern struct daemon {
#endif
/* TFTP stuff */
struct tftp_transfer *tftp_trans;
struct tftp_transfer *tftp_trans, *tftp_done_trans;
/* utility string buffer, hold max sized IP address as string */
char *addrbuff;
@@ -910,9 +913,9 @@ unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask);
void server_gone(struct server *server);
struct frec *get_new_frec(time_t now, int *wait);
void send_from(int fd, int nowild, char *packet, size_t len,
int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source,
unsigned int iface);
unsigned int iface, int *errp);
/* network.c */
int indextoname(int fd, int index, char *name);
@@ -1035,11 +1038,14 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
#endif
/* helper.c */
#if defined(HAVE_DHCP) && !defined(NO_FORK)
#if defined(HAVE_SCRIPT)
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
void helper_write(void);
void queue_script(int action, struct dhcp_lease *lease,
char *hostname, time_t now);
#ifdef HAVE_TFTP
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
#endif
int helper_buf_empty(void);
#endif
@@ -1047,6 +1053,7 @@ int helper_buf_empty(void);
#ifdef HAVE_TFTP
void tftp_request(struct listener *listen, time_t now);
void check_tftp_listeners(fd_set *rset, time_t now);
int do_tftp_script_run(void);
#endif
/* conntrack.c */
+15 -8
View File
@@ -26,9 +26,9 @@ static struct randfd *allocate_rfd(int family);
/* Send a UDP packet with its source address set as "source"
unless nowild is true, when we just send it with the kernel default */
void send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source,
unsigned int iface)
int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source,
unsigned int iface, int *errp)
{
struct msghdr msg;
struct iovec iov[1];
@@ -110,8 +110,15 @@ void send_from(int fd, int nowild, char *packet, size_t len,
if (retry_send())
goto retry;
my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
if (errp)
*errp = errno;
else
my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
return 0;
}
return 1;
}
static unsigned int search_servers(time_t now, struct all_addr **addrpp,
@@ -432,7 +439,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (udpfd != -1)
{
plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
send_from(udpfd, option_bool(OPT_NOWILD), (char *)header, plen, udpaddr, dst_addr, dst_iface);
send_from(udpfd, option_bool(OPT_NOWILD), (char *)header, plen, udpaddr, dst_addr, dst_iface, NULL);
}
return 0;
@@ -621,7 +628,7 @@ void reply_query(int fd, int family, time_t now)
header->id = htons(forward->orig_id);
header->hb4 |= HB4_RA; /* recursion if available */
send_from(forward->fd, option_bool(OPT_NOWILD), daemon->packet, nn,
&forward->source, &forward->dest, forward->iface);
&forward->source, &forward->dest, forward->iface, NULL);
}
free_frec(forward); /* cancel */
}
@@ -660,7 +667,7 @@ void receive_query(struct listener *listen, time_t now)
/* packet buffer overwritten */
daemon->srv_save = NULL;
if (listen->family == AF_INET && option_bool(OPT_NOWILD))
if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD))
{
dst_addr_4 = listen->iface->addr.in.sin_addr;
netmask = listen->iface->netmask;
@@ -816,7 +823,7 @@ void receive_query(struct listener *listen, time_t now)
if (m >= 1)
{
send_from(listen->fd, option_bool(OPT_NOWILD), (char *)header,
m, &source_addr, &dst_addr, if_index);
m, &source_addr, &dst_addr, if_index, NULL);
daemon->local_answer++;
}
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
+269 -196
View File
@@ -192,18 +192,24 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
#endif
_exit(0);
}
is6 = !!(data.flags & (LEASE_TA | LEASE_NA));
if (data.action == ACTION_DEL)
action_str = "del";
else if (data.action == ACTION_ADD)
action_str = "add";
else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME)
action_str = "old";
else if (data.action == ACTION_TFTP)
{
action_str = "tftp";
is6 = (data.flags != AF_INET);
}
else
continue;
is6 = !!(data.flags & (LEASE_TA | LEASE_NA));
if (!is6)
{
/* stringify MAC into dhcp_buff */
@@ -271,13 +277,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
char *dot;
hostname = (char *)buf;
hostname[data.hostname_len - 1] = 0;
if (!legal_hostname(hostname))
hostname = NULL;
else if ((dot = strchr(hostname, '.')))
if (data.action != ACTION_TFTP)
{
domain = dot+1;
*dot = 0;
}
if (!legal_hostname(hostname))
hostname = NULL;
else if ((dot = strchr(hostname, '.')))
{
domain = dot+1;
*dot = 0;
}
}
}
extradata = buf + data.hostname_len;
@@ -289,116 +298,141 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN);
#endif
/* file length */
if (data.action == ACTION_TFTP)
sprintf(daemon->dhcp_buff, "%u", data.hwaddr_len);
#ifdef HAVE_LUASCRIPT
if (daemon->luascript)
{
lua_getglobal(lua, "lease"); /* function to call */
lua_pushstring(lua, action_str); /* arg1 - action */
lua_newtable(lua); /* arg2 - data table */
if (is6)
if (data.action == ACTION_TFTP)
{
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "client_duid");
lua_pushstring(lua, daemon->packet);
lua_setfield(lua, -2, "server_duid");
lua_pushstring(lua, daemon->dhcp_buff3);
lua_setfield(lua, -2, "iaid");
lua_getglobal(lua, "tftp");
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, "destination_address");
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "file_name");
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "file_size");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
}
if (!is6 && data.clid_len != 0)
{
lua_pushstring(lua, daemon->packet);
lua_setfield(lua, -2, "client_id");
}
if (strlen(data.interface) != 0)
{
lua_pushstring(lua, data.interface);
lua_setfield(lua, -2, "interface");
}
#ifdef HAVE_BROKEN_RTC
lua_pushnumber(lua, data.length);
lua_setfield(lua, -2, "lease_length");
#else
lua_pushnumber(lua, data.expires);
lua_setfield(lua, -2, "lease_expires");
#endif
if (hostname)
{
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "hostname");
}
if (domain)
{
lua_pushstring(lua, domain);
lua_setfield(lua, -2, "domain");
}
end = extradata + data.ed_len;
buf = extradata;
if (!is6)
buf = grab_extradata_lua(buf, end, "vendor_class");
#ifdef HAVE_DHCP6
else
for (i = 0; i < data.hwaddr_len; i++)
{
sprintf(daemon->dhcp_buff2, "vendor_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
}
{
lua_getglobal(lua, "lease"); /* function to call */
lua_pushstring(lua, action_str); /* arg1 - action */
lua_newtable(lua); /* arg2 - data table */
if (is6)
{
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "client_duid");
lua_pushstring(lua, daemon->packet);
lua_setfield(lua, -2, "server_duid");
lua_pushstring(lua, daemon->dhcp_buff3);
lua_setfield(lua, -2, "iaid");
}
if (!is6 && data.clid_len != 0)
{
lua_pushstring(lua, daemon->packet);
lua_setfield(lua, -2, "client_id");
}
if (strlen(data.interface) != 0)
{
lua_pushstring(lua, data.interface);
lua_setfield(lua, -2, "interface");
}
#ifdef HAVE_BROKEN_RTC
lua_pushnumber(lua, data.length);
lua_setfield(lua, -2, "lease_length");
#else
lua_pushnumber(lua, data.expires);
lua_setfield(lua, -2, "lease_expires");
#endif
buf = grab_extradata_lua(buf, end, "supplied_hostname");
if (!is6)
{
buf = grab_extradata_lua(buf, end, "cpewan_oui");
buf = grab_extradata_lua(buf, end, "cpewan_serial");
buf = grab_extradata_lua(buf, end, "cpewan_class");
if (hostname)
{
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "hostname");
}
if (domain)
{
lua_pushstring(lua, domain);
lua_setfield(lua, -2, "domain");
}
end = extradata + data.ed_len;
buf = extradata;
if (!is6)
buf = grab_extradata_lua(buf, end, "vendor_class");
#ifdef HAVE_DHCP6
else
for (i = 0; i < data.hwaddr_len; i++)
{
sprintf(daemon->dhcp_buff2, "vendor_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
}
#endif
buf = grab_extradata_lua(buf, end, "supplied_hostname");
if (!is6)
{
buf = grab_extradata_lua(buf, end, "cpewan_oui");
buf = grab_extradata_lua(buf, end, "cpewan_serial");
buf = grab_extradata_lua(buf, end, "cpewan_class");
}
buf = grab_extradata_lua(buf, end, "tags");
if (is6)
buf = grab_extradata_lua(buf, end, "relay_address");
else if (data.giaddr.s_addr != 0)
{
lua_pushstring(lua, inet_ntoa(data.giaddr));
lua_setfield(lua, -2, "relay_address");
}
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "user_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
}
if (data.action != ACTION_DEL && data.remaining_time != 0)
{
lua_pushnumber(lua, data.remaining_time);
lua_setfield(lua, -2, "time_remaining");
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "old_hostname");
}
if (!is6)
{
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "mac_address");
}
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "ip_address");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
buf = grab_extradata_lua(buf, end, "tags");
if (is6)
buf = grab_extradata_lua(buf, end, "relay_address");
else if (data.giaddr.s_addr != 0)
{
lua_pushstring(lua, inet_ntoa(data.giaddr));
lua_setfield(lua, -2, "relay_address");
}
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "user_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
}
if (data.action != ACTION_DEL && data.remaining_time != 0)
{
lua_pushnumber(lua, data.remaining_time);
lua_setfield(lua, -2, "time_remaining");
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "old_hostname");
}
if (!is6)
{
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "mac_address");
}
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "ip_address");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
#endif
@@ -439,81 +473,87 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
continue;
}
if (is6)
if (data.action != ACTION_TFTP)
{
my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err);
my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err);
}
if (!is6 && data.clid_len != 0)
my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err);
if (strlen(data.interface) != 0)
my_setenv("DNSMASQ_INTERFACE", data.interface, &err);
#ifdef HAVE_BROKEN_RTC
my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err);
#else
my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err);
#endif
if (domain)
my_setenv("DNSMASQ_DOMAIN", domain, &err);
end = extradata + data.ed_len;
buf = extradata;
if (!is6)
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
#ifdef HAVE_DHCP6
else
{
if (data.hwaddr_len != 0)
if (is6)
{
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err);
for (i = 0; i < data.hwaddr_len - 1; i++)
my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err);
my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err);
}
if (!is6 && data.clid_len != 0)
my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err);
if (strlen(data.interface) != 0)
my_setenv("DNSMASQ_INTERFACE", data.interface, &err);
#ifdef HAVE_BROKEN_RTC
my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err);
#else
my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err);
#endif
if (domain)
my_setenv("DNSMASQ_DOMAIN", domain, &err);
end = extradata + data.ed_len;
buf = extradata;
if (!is6)
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
#ifdef HAVE_DHCP6
else
{
if (data.hwaddr_len != 0)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i);
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err);
for (i = 0; i < data.hwaddr_len - 1; i++)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i);
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
}
}
}
}
#endif
buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err);
if (!is6)
{
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err);
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err);
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err);
}
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
if (is6)
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
else if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i);
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", daemon->dhcp_buff2, &err);
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);
hostname = NULL;
buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err);
if (!is6)
{
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err);
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err);
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err);
}
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
if (is6)
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
else if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i);
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", daemon->dhcp_buff2, &err);
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);
hostname = NULL;
}
}
if (option_bool(OPT_LOG_OPTS))
my_setenv("DNSMASQ_LOG_DHCP", "1", &err);
/* we need to have the event_fd around if exec fails */
if ((i = fcntl(event_fd, F_GETFD)) != -1)
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
@@ -584,11 +624,29 @@ static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end,
}
#endif
static void buff_alloc(size_t size)
{
if (size > buf_size)
{
struct script_data *new;
/* start with reasonable size, will almost never need extending. */
if (size < sizeof(struct script_data) + 200)
size = sizeof(struct script_data) + 200;
if (!(new = whine_malloc(size)))
return;
if (buf)
free(buf);
buf = new;
buf_size = size;
}
}
/* pack up lease data into a buffer */
void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
{
unsigned char *p;
size_t size;
unsigned int hostname_len = 0, clid_len = 0, ed_len = 0;
int fd = daemon->dhcpfd;
@@ -608,23 +666,7 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
if (hostname)
hostname_len = strlen(hostname) + 1;
size = sizeof(struct script_data) + clid_len + ed_len + hostname_len;
if (size > buf_size)
{
struct script_data *new;
/* start with reasonable size, will almost never need extending. */
if (size < sizeof(struct script_data) + 200)
size = sizeof(struct script_data) + 200;
if (!(new = whine_malloc(size)))
return;
if (buf)
free(buf);
buf = new;
buf_size = size;
}
buff_alloc(sizeof(struct script_data) + clid_len + ed_len + hostname_len);
buf->action = action;
buf->flags = lease->flags;
@@ -669,6 +711,37 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
bytes_in_buf = p - (unsigned char *)buf;
}
#ifdef HAVE_TFTP
/* This nastily re-uses DHCP-fields for TFTP stuff */
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
{
unsigned int filename_len;
/* no script */
if (daemon->helperfd == -1)
return;
filename_len = strlen(filename) + 1;
buff_alloc(sizeof(struct script_data) + filename_len);
memset(buf, 0, sizeof(struct script_data));
buf->action = ACTION_TFTP;
buf->hostname_len = filename_len;
buf->hwaddr_len = file_len;
if ((buf->flags = peer->sa.sa_family) == AF_INET)
buf->addr = peer->in.sin_addr;
#ifdef HAVE_IPV6
else
memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ);
#endif
memcpy((unsigned char *)(buf+1), filename, filename_len);
bytes_in_buf = sizeof(struct script_data) + filename_len;
}
#endif
int helper_buf_empty(void)
{
return bytes_in_buf == 0;
+20
View File
@@ -511,6 +511,7 @@ void create_bound_listeners(int dienow)
{
struct listener *new;
struct irec *iface;
struct iname *if_tmp;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad &&
@@ -521,6 +522,25 @@ void create_bound_listeners(int dienow)
daemon->listeners = new;
iface->done = 1;
}
/* Check for --listen-address options that haven't been used because there's
no interface with a matching address. These may be valid: eg it's possible
to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
If the address isn't valid the bind() will fail and we'll die().
The resulting listeners have the ->iface field NULL, and this has to be
handled by the DNS and TFTP code. It disables --localise-queries processing
(no netmask) and some MTU login the tftp code. */
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, 1, dienow)))
{
new->iface = NULL;
new->next = daemon->listeners;
daemon->listeners = new;
}
}
int is_dad_listeners(void)
+38 -42
View File
@@ -1959,7 +1959,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
case 'F': /* --dhcp-range */
{
int k, leasepos = 2;
char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
char *cp, *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
memset (new, 0, sizeof(*new));
@@ -2010,7 +2010,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
}
}
for (k = 1; k < 5; k++)
for (k = 1; k < 7; k++)
if (!(a[k] = split(a[k-1])))
break;
@@ -2020,17 +2020,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
{
new->next = daemon->dhcp;
daemon->dhcp = new;
new->end = new->start;
if (strcmp(a[1], "static") == 0)
{
new->end = new->start;
new->flags |= CONTEXT_STATIC;
}
new->flags |= CONTEXT_STATIC;
else if (strcmp(a[1], "proxy") == 0)
{
new->end = new->start;
new->flags |= CONTEXT_PROXY;
}
else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
new->flags |= CONTEXT_PROXY;
else if (!inet_pton(AF_INET, a[1], &new->end))
option = '?';
if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
@@ -2060,53 +2055,54 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
else if (inet_pton(AF_INET6, a[0], &new->start6))
{
new->prefix = 64; /* default */
new->end6 = new->start6;
for (leasepos = 1; leasepos < k; leasepos++)
{
if (strcmp(a[leasepos], "static") == 0)
new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
new->flags |= CONTEXT_RA_ONLY;
else if (strcmp(a[leasepos], "ra-names") == 0)
new->flags |= CONTEXT_RA_NAME;
else if (strcmp(a[leasepos], "ra-stateless") == 0)
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP;
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
new->flags |= CONTEXT_DHCP;
else
break;
}
if (strcmp(a[1], "static") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_STATIC;
}
else if (strcmp(a[1], "ra-only") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_RA_ONLY;
}
else if (strcmp(a[1], "ra-names") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_RA_NAME | CONTEXT_RA_ONLY;
}
else if (!inet_pton(AF_INET6, a[1], &new->end6))
option = '?';
if (new->flags & CONTEXT_RA_ONLY)
{
new->next = daemon->ra_contexts;
daemon->ra_contexts = new;
}
else
if (new->flags & CONTEXT_DHCP)
{
new->next = daemon->dhcp6;
daemon->dhcp6 = new;
}
else
{
new->next = daemon->ra_contexts;
daemon->ra_contexts = new;
}
/* bare integer < 128 is prefix value */
if (option != '?' && k >= 3)
if (option != '?' && leasepos < k)
{
int pref;
for (cp = a[2]; *cp; cp++)
for (cp = a[leasepos]; *cp; cp++)
if (!(*cp >= '0' && *cp <= '9'))
break;
if (!*cp && (pref = atoi(a[2])) <= 128)
if (!*cp && (pref = atoi(a[leasepos])) <= 128)
{
new->prefix = pref;
leasepos = 3;
if ((new->flags & CONTEXT_RA_ONLY) && new->prefix != 64)
leasepos++;
if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) &&
new->prefix != 64)
problem = _("prefix must be exactly 64 for RA subnets");
else if (new->prefix < 64)
problem = _("prefix must be at least 64");
}
}
if (!problem && !is_same_net6(&new->start6, &new->end6, new->prefix))
problem = _("inconsistent DHCPv6 range");
else if (addr6part(&new->start6) > addr6part(&new->end6))
@@ -2118,7 +2114,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
}
#endif
if (k >= leasepos+1)
if (leasepos < k)
{
if (strcmp(a[leasepos], "infinite") == 0)
new->lease_time = 0xffffffff;
+42 -12
View File
@@ -27,7 +27,7 @@
#include <netinet/icmp6.h>
struct ra_param {
int ind, managed, found_context, first;
int ind, managed, other, found_context, first;
char *if_name;
struct in6_addr link_local;
};
@@ -199,20 +199,21 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
struct ifreq ifr;
struct sockaddr_in6 addr;
struct dhcp_context *context;
save_counter(0);
ra = expand(sizeof(struct ra_packet));
ra->type = ND_ROUTER_ADVERT;
ra->code = 0;
ra->hop_limit = hop_limit;
ra->flags = 0;
ra->flags = 0x00;
ra->lifetime = htons(1800); /* AdvDefaultLifetime*/
ra->reachable_time = 0;
ra->retrans_time = 0;
parm.ind = iface;
parm.managed = 0;
parm.other = 0;
parm.found_context = 0;
parm.if_name = iface_name;
parm.first = 1;
@@ -246,8 +247,10 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
/* set managed bits unless we're providing only RA on this link */
if (parm.managed)
ra->flags = 0xc0;
ra->flags |= 0x80; /* M flag, managed, */
if (parm.other)
ra->flags |= 0x40; /* O flag, other */
/* decide where we're sending */
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -266,7 +269,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
inet_pton(AF_INET6, ALL_HOSTS, &addr.sin6_addr);
send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0),
(union mysockaddr *)&addr, (struct all_addr *)&parm.link_local, iface);
(union mysockaddr *)&addr, (struct all_addr *)&parm.link_local, iface, NULL);
}
@@ -293,12 +296,22 @@ static int add_prefixes(struct in6_addr *local, int prefix,
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
{
if (!(context->flags & CONTEXT_RA_ONLY))
int do_slaac = 0;
if ((context->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
{
do_slaac = 1;
if (context->flags & CONTEXT_RA_STATELESS)
param->other = 1;
}
else
{
/* don't do RA for non-ra-only unless --enable-ra is set */
if (!option_bool(OPT_RA))
continue;
param->managed = 1;
param->other = 1;
}
if (context->flags & CONTEXT_RA_DONE)
@@ -319,8 +332,25 @@ static int add_prefixes(struct in6_addr *local, int prefix,
{
tmp->flags |= CONTEXT_RA_DONE;
context->ra_time = 0;
/* if any dhcp-range with ra-only on this subnet
set the "do_slaac" bit */
if (tmp->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS))
{
do_slaac = 1;
if (context->flags & CONTEXT_RA_STATELESS)
param->other = 1;
}
else
{
/* don't do RA for non-ra-only unless --enable-ra is set */
if (!option_bool(OPT_RA))
continue;
param->managed = 1;
param->other = 1;
}
}
if ((opt = expand(sizeof(struct prefix_opt))))
{
u64 addrpart = addr6part(&context->start6);
@@ -335,7 +365,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
opt->len = 4;
opt->prefix_len = prefix;
/* autonomous only is we're not doing dhcp */
opt->flags = (context->flags & CONTEXT_RA_ONLY) ? 0xc0 : 0x00;
opt->flags = do_slaac ? 0x40 : 0x00;
opt->valid_lifetime = opt->preferred_lifetime = htonl(time);
opt->reserved = 0;
@@ -387,11 +417,11 @@ time_t periodic_ra(time_t now)
for (next_event = 0, context = daemon->ra_contexts; context; context = context->next)
if (context->ra_time != 0)
{
if (difftime(context->ra_time, now) < 0.0)
if (difftime(context->ra_time, now) <= 0.0)
break; /* overdue */
if (next_event == 0 || difftime(next_event, context->ra_time + 2) > 0.0)
next_event = context->ra_time + 2;
if (next_event == 0 || difftime(next_event, context->ra_time) > 0.0)
next_event = context->ra_time;
}
/* none overdue */
+2 -1
View File
@@ -2095,7 +2095,8 @@ static void do_options(struct dhcp_context *context,
struct dhcp_netid_list *id_list;
/* filter options based on tags, those we want get DHOPT_TAGOK bit set */
context->netid.next = NULL;
if (context)
context->netid.next = NULL;
tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
/* logging */
+17 -10
View File
@@ -131,14 +131,15 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
for (lease = leases; lease; lease = lease->next)
for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
{
/* confirmed? */
if (slaac->backoff == 0)
/* confirmed or given up? */
if (slaac->backoff == 0 || slaac->ping_time == 0)
continue;
if (difftime(slaac->ping_time, now) <= 0.0)
{
struct ping_packet *ping;
struct sockaddr_in6 addr;
int err;
save_counter(0);
ping = expand(sizeof(struct ping_packet));
@@ -155,16 +156,22 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = slaac->addr;
send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0),
(union mysockaddr *)&addr, (struct all_addr *)&slaac->local, lease->last_interface);
slaac->ping_time += (1 << (slaac->backoff - 1)) + (rand16()/21785); /* 0 - 3 */
if (slaac->backoff > 4)
slaac->ping_time += rand16()/4000; /* 0 - 15 */
slaac->backoff++;
if (send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0),
(union mysockaddr *)&addr, (struct all_addr *)&slaac->local,
lease->last_interface, &err))
{
slaac->ping_time += (1 << (slaac->backoff - 1)) + (rand16()/21785); /* 0 - 3 */
if (slaac->backoff > 4)
slaac->ping_time += rand16()/4000; /* 0 - 15 */
if (slaac->backoff < 12)
slaac->backoff++;
}
else if (err == EHOSTUNREACH)
slaac->ping_time = 0; /* Give up */
}
if (next_event == 0 || difftime(next_event, slaac->ping_time) >= 0.0)
if (slaac->ping_time != 0 &&
(next_event == 0 || difftime(next_event, slaac->ping_time) >= 0.0))
next_event = slaac->ping_time;
}
+47 -14
View File
@@ -57,7 +57,7 @@ void tftp_request(struct listener *listen, time_t now)
int mtuflag = IP_PMTUDISC_DONT;
#endif
char namebuff[IF_NAMESIZE];
char *name;
char *name = NULL;
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct interface_list *ir;
@@ -95,9 +95,20 @@ void tftp_request(struct listener *listen, time_t now)
if (option_bool(OPT_NOWILD))
{
addr = listen->iface->addr;
mtu = listen->iface->mtu;
name = listen->iface->name;
if (listen->iface)
{
addr = listen->iface->addr;
mtu = listen->iface->mtu;
name = listen->iface->name;
}
else
{
/* we're listening on an address that doesn't appear on an interface,
ask the kernel what the socket is bound to */
socklen_t tcp_len = sizeof(union mysockaddr);
if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
return;
}
}
else
{
@@ -211,15 +222,18 @@ void tftp_request(struct listener *listen, time_t now)
mtu = ifr.ifr_mtu;
}
/* check for per-interface prefix */
for (pref = daemon->if_prefix; pref; pref = pref->next)
if (strcmp(pref->interface, name) == 0)
prefix = pref->prefix;
/* wierd TFTP interfaces disable special options. */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, name) == 0)
special = 1;
if (name)
{
/* check for per-interface prefix */
for (pref = daemon->if_prefix; pref; pref = pref->next)
if (strcmp(pref->interface, name) == 0)
prefix = pref->prefix;
/* wierd TFTP interfaces disable special options. */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, name) == 0)
special = 1;
}
if (listen->family == AF_INET)
{
@@ -571,7 +585,9 @@ void check_tftp_listeners(fd_set *rset, time_t now)
my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff);
/* unlink */
*up = tmp;
free_transfer(transfer);
/* put on queue to be sent to script and deleted */
transfer->next = daemon->tftp_done_trans;
daemon->tftp_done_trans = transfer;
continue;
}
}
@@ -709,4 +725,21 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
}
}
int do_tftp_script_run(void)
{
struct tftp_transfer *transfer;
if ((transfer = daemon->tftp_done_trans))
{
daemon->tftp_done_trans = transfer->next;
#ifdef HAVE_SCRIPT
queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
#endif
free_transfer(transfer);
return 1;
}
return 0;
}
#endif