Compare commits

...
24 Commits
Author SHA1 Message Date
Simon Kelley 4038ae2005 Fix crash in DHCPv6 information-request handler. 2013-02-19 16:47:07 +00:00
Simon Kelley dd1721c799 DHCPv4 relay-agent options exposed to DHCP-script. 2013-02-18 21:04:04 +00:00
Simon Kelley a21e27bc99 Support DHCP DNS server option if we're not doing DNS. 2013-02-17 16:41:35 +00:00
Simon Kelley b0ff858e78 Fix FTBFS if HAVE_BROKEN_RTC defined. 2013-02-06 09:57:47 +00:00
Simon Kelley 54dae552b1 Fix previous commit. 2013-02-05 17:55:10 +00:00
Simon Kelley 25c4198f7c Fix use-after-free 2013-02-05 14:56:02 +00:00
Simon Kelley 4ead40cf67 Fix use-after-free 2013-02-05 14:51:14 +00:00
Simon Kelley 04a0612e8a Remove dead code. 2013-02-05 14:47:46 +00:00
Simon Kelley aa608c84b4 Fix wrong syntax check. 2013-02-05 14:42:59 +00:00
Simon Kelley 38365ff040 Theoretical memory leak fix. 2013-02-05 14:35:54 +00:00
Simon Kelley 9c4270bcd9 Fix memory leak. 2013-02-04 22:07:57 +00:00
Simon Kelley 46b066565e Don't leak sockets when getsockname fails. 2013-02-04 21:47:59 +00:00
Simon Kelley 4dc9c657ad Memory leak. 2013-02-04 21:43:52 +00:00
Simon Kelley 39595cfe31 Fix memory leak. 2013-02-04 21:40:07 +00:00
Simon Kelley ffa3d7d6a2 Copy-and-paste error 2013-02-04 21:35:43 +00:00
Simon Kelley aa67fe7a8c Catch NULL pointer deref if qdcount == 0 2013-02-04 21:32:34 +00:00
Simon Kelley bb2509fd2c Typo in filter_constructed_dhcp() 2013-02-04 21:25:21 +00:00
Simon Kelley 61744359de Change copyright messages to include 2013. 2013-01-31 14:34:40 +00:00
Simon Kelley 095f62551f Update manpage for --dhcp-authoritative DHCPv6 behaviour. 2013-01-30 11:31:02 +00:00
Simon Kelley e25db1f273 Handle wrong interface for locally-routed packets. 2013-01-29 22:10:26 +00:00
Simon Kelley 79cb46c0e9 Man page typos. 2013-01-23 19:49:21 +00:00
Simon Kelley 22ce550e53 Correct behaviour for TCP queries to allowed address via banned interface. 2013-01-22 13:53:04 +00:00
Simon Kelley 30393100c1 Wildcard IPv6 addresses in --dhcp-host, for constructed ranges. 2013-01-17 16:34:16 +00:00
Simon Kelley 459380965a Fix last commit. 2013-01-15 21:57:42 +00:00
35 changed files with 351 additions and 116 deletions

No files matched your search

+27 -2
View File
@@ -16,8 +16,33 @@ version 2.66
this idea.
Fix crash on startup on Solaris 11. Regression probably
introduced in 2.61. Thanks to Geoff Johnstone for the patch.
introduced in 2.61. Thanks to Geoff Johnstone for the
patch.
Add code to make behaviour for TCP DNS requests that same
as for UDP requests, when a request arrives for an allowed
address, but via a banned interface. This change is only
active on Linux, since the relevant API is missing (AFAIK)
on other platforms. Many thanks to Tomas Hozza for
spotting the problem, and doing invaluable discovery of
the obscure and undocumented API required for the solution.
Don't send the default DHCP option advertising dnsmasq as
the local DNS server if dnsmasq is configured to not act
as DNS server, or it's configured to a non-standard port.
Add DNSMASQ_CIRCUIT_ID, DNSMASQ_SUBCRIBER_ID,
DNSMASQ_REMOTE_ID variables to the environment of the
lease-change script (and the correponding Lua). These hold
information inserted into the DHCP request by a DHCP relay
agent. Thanks to Lakefield Communications for providing a
bounty for this addition.
Fixed crash, introduced in 2.64, whilst handling DHCPv6
information-requests with some common configurations.
Thanks to Robert M. Albrecht for the bug report and
chasing the problem.
version 2.65
Fix regression which broke forwarding of queries sent via
+1 -1
View File
@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2012 Simon Kelley
# dnsmasq is Copyright (c) 2000-2013 Simon Kelley
#
# 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
-4
View File
@@ -255,10 +255,6 @@ int main(int argc, char **argv)
struct ifreq ifr;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
struct iovec iov;
iov.iov_len = 200;
iov.iov_base = malloc(iov.iov_len);
if (argc < 4 || argc > 5)
{
+1 -1
View File
@@ -1,4 +1,4 @@
dnsmasq is Copyright (c) 2000-2012 Simon Kelley
dnsmasq is Copyright (c) 2000-2013 Simon Kelley
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
+16 -6
View File
@@ -717,7 +717,13 @@ A single
.B dhcp-host
may contain an IPv4 address or an IPv6 address, or both. IPv6 addresses must be bracketed by square brackets thus:
.B --dhcp-host=laptop,[1234::56]
Note that in IPv6 DHCP, the hardware address is not normally available, so a client must be identified by client-id (called client DUID in IPv6-land) or hostname.
IPv6 addresses may contain only the host-identifier part:
.B --dhcp-host=laptop,[::56]
in which case thay act as wildcards in constructed dhcp ranges, with
the appropriate network part inserted.
Note that in IPv6 DHCP, the hardware address is not normally
available, so a client must be identified by client-id (called client
DUID in IPv6-land) or hostname.
The special option id:* means "ignore any client-id
and use MAC addresses only." This is useful when a client presents a client-id sometimes
@@ -1116,12 +1122,13 @@ create thousands of leases and use lots of memory in the dnsmasq
process.
.TP
.B \-K, --dhcp-authoritative
(IPv4 only) Should be set when dnsmasq is definitely the only DHCP server on a network.
It changes the behaviour from strict RFC compliance so that DHCP requests on
Should be set when dnsmasq is definitely the only DHCP server on a network.
For DHCPv4, it changes the behaviour from strict RFC compliance so that DHCP requests on
unknown leases from unknown hosts are not ignored. This allows new hosts
to get a lease without a tedious timeout under all circumstances. It also
allows dnsmasq to rebuild its lease database without each client needing to
reacquire a lease, if the database is lost.
reacquire a lease, if the database is lost. For DHCPv6 it sets the
priority in replies to 255 (the maximum) instead of 0 (the minimum).
.TP
.B --dhcp-alternate-port[=<server port>[,<client port>]]
(IPv4 only) Change the ports used for DHCP from the default. If this option is
@@ -1223,6 +1230,9 @@ For IPv4 only:
DNSMASQ_CLIENT_ID if the host provided a client-id.
DNSMASQ_CIRCUIT_ID, DNSMASQ_SUBSCRIBER_ID, DNSMASQ_REMOTE_ID if a
DHCP relay-agent added any of these options.
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS.
For IPv6 only:
@@ -1709,7 +1719,7 @@ The simplest configuration consists of two lines of dnsmasq configuration; somet
.nf
.B auth-server=server.example.com,eth0
.B auth=zone=our.zone.com,1.2.3.0/24
.B auth-zone=our.zone.com,1.2.3.0/24
.fi
and two records in the external DNS
@@ -1733,7 +1743,7 @@ we have
.nf
.B auth-server=our.zone.com,eth0
.B auth=zone=our.zone.com,1.2.3.0/24
.B auth-zone=our.zone.com,1.2.3.0/24
.fi
.nf
+3 -3
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -51,7 +51,7 @@ static int filter_constructed_dhcp(struct auth_zone *zone, int flag, struct all_
#ifdef HAVE_DHCP6
struct dhcp_context *context;
if (flag | F_IPV6)
if (flag & F_IPV6)
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_CONSTRUCTED) &&
is_same_net6(&(addr_u->addr.addr6), &context->start6, context->prefix))
@@ -470,7 +470,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
/* Add auth section */
if (auth)
if (auth && zone)
{
char *authname;
int newoffset, offset = 0;
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+19 -12
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -91,16 +91,19 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
static void remove_watch(DBusWatch *watch, void *data)
{
struct watch **up, *w;
struct watch **up, *w, *tmp;
for (up = &(daemon->watches), w = daemon->watches; w; w = w->next)
if (w->watch == watch)
{
*up = w->next;
free(w);
}
else
up = &(w->next);
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
{
tmp = w->next;
if (w->watch == watch)
{
*up = tmp;
free(w);
}
else
up = &(w->next);
}
w = data; /* no warning */
}
@@ -340,9 +343,11 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
}
/* dup the string because it gets modified during parsing */
if (dup)
free(dup);
if (!(dup = str_domain = whine_malloc(strlen(str)+1)))
break;
strcpy(str_domain, str);
/* point to address part of old string for error message */
@@ -400,9 +405,11 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
}
/* dup the string because it gets modified during parsing */
if (dup)
free(dup);
if (!(dup = str_addr = whine_malloc(strlen(str)+1)))
break;
strcpy(str_addr, str);
}
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+14 -6
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -399,11 +399,19 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
{
if (!context) /* called via find_config() from lease_update_from_configs() */
return 1;
/* expand wildcard on contructed contexts */
if ((config->flags & CONFIG_WILDCARD) &&
(context->flags & CONTEXT_CONSTRUCTED))
{
u64 addrpart = addr6part(&config->addr6);
config->addr6 = context->start6;
setaddr6part(&config->addr6, addrpart);
return 1;
}
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6))
return 1;
return 0;
}
@@ -612,10 +620,10 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_GC)
{
*up = context->next;
free(context);
param.newone = 1; /* include deletion */
if (context->flags & CONTEXT_RA_NAME)
param.newname = 1;
param.newname = 1;
free(context);
}
else
up = &context->next;
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+61 -23
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -158,10 +158,10 @@ int main (int argc, char **argv)
now = dnsmasq_time();
/* Create a serial at startup is not configured. */
/* Create a serial at startup if not configured. */
if (daemon->authinterface && daemon->soa_sn == 0)
#ifdef HAVE_BROKEN_RTC
die(_("zone serial must be configured in --auth-soa"));
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
#else
daemon->soa_sn = now;
#endif
@@ -1337,7 +1337,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
{
int confd;
int confd, client_ok = 1;
struct irec *iface = NULL;
pid_t p;
union mysockaddr tcp_addr;
@@ -1345,28 +1345,66 @@ static void check_dns_listeners(fd_set *set, time_t now)
while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1 ||
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
if (confd == -1)
continue;
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
{
/* 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
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces())
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
close(confd);
continue;
}
if (!iface && !(option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND)))
if (option_bool(OPT_NOWILD))
iface = listener->iface; /* May be NULL */
else
{
int if_index;
char intr_name[IF_NAMESIZE];
/* In full wildcard mode, need to refresh interface list.
This happens automagically in CLEVERBIND */
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
/* if we can find the arrival interface, check it's one that's allowed */
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
indextoname(listener->tcpfd, if_index, intr_name))
{
struct all_addr addr;
addr.addr.addr4 = tcp_addr.in.sin_addr;
#ifdef HAVE_IPV6
if (tcp_addr.sa.sa_family == AF_INET6)
addr.addr.addr6 = tcp_addr.in6.sin6_addr;
#endif
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index)
break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
client_ok = 0;
}
if (option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
{
/* 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
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
if (!iface)
client_ok = 0;
}
}
if (!client_ok)
{
shutdown(confd, SHUT_RDWR);
close(confd);
+5 -2
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define COPYRIGHT "Copyright (c) 2000-2012 Simon Kelley"
#define COPYRIGHT "Copyright (c) 2000-2013 Simon Kelley"
#ifndef NO_LARGEFILE
/* Ensure we can use files >2GB (log files may grow this big) */
@@ -593,6 +593,7 @@ struct dhcp_config {
#define CONFIG_DECLINED 1024 /* address declined by client */
#define CONFIG_BANK 2048 /* from dhcp hosts file */
#define CONFIG_ADDR6 4096
#define CONFIG_WILDCARD 8192
struct dhcp_opt {
int opt, len, flags;
@@ -1001,7 +1002,9 @@ void create_wildcard_listeners(void);
void create_bound_listeners(int die);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
int fix_fd(int fd);
int tcp_interface(int fd, int af);
struct in_addr get_ifaddr(char *intr);
#ifdef HAVE_IPV6
int set_ipv6pktinfo(int fd);
+11 -4
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -763,10 +763,17 @@ void receive_query(struct listener *listen, time_t now)
/* enforce available interface configuration */
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
if (!indextoname(listen->fd, if_index, ifr.ifr_name))
return;
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name))
return;
}
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
{
struct irec *iface;
@@ -780,7 +787,7 @@ void receive_query(struct listener *listen, time_t now)
break;
/* interface may be new */
if (!iface)
if (!iface && !option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
for (iface = daemon->interfaces; iface; iface = iface->next)
+8 -2
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -397,6 +397,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
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, "circuit_id");
buf = grab_extradata_lua(buf, end, "subscriber_id");
buf = grab_extradata_lua(buf, end, "remote_id");
}
buf = grab_extradata_lua(buf, end, "tags");
@@ -528,10 +531,13 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
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_CIRCUIT_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_TAGS", &err);
if (is6)
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
else if (data.giaddr.s_addr != 0)
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+116 -9
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -170,7 +170,40 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
return ret;
}
/* Fix for problem that the kernel sometimes reports the loopback inerface as the
arrival interface when a packet originates locally, even when sent to address of
an interface other than the loopback. Accept packet if it arrived via a loopback
interface, even when we're not accepting packets that way, as long as the destination
address is one we're believing. Interface list must be up-to-date before calling. */
int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
{
struct ifreq ifr;
struct irec *iface;
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
ifr.ifr_flags & IFF_LOOPBACK)
{
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->addr.sa.sa_family == family)
{
if (family == AF_INET)
{
if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
return 1;
}
#ifdef HAVE_IPV6
else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
return 1;
#endif
}
}
return 0;
}
static int iface_allowed(struct irec **irecp, int if_index,
union mysockaddr *addr, struct in_addr netmask, int dad)
{
@@ -225,14 +258,17 @@ static int iface_allowed(struct irec **irecp, int if_index,
if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
break;
if (!lo &&
(lo = whine_malloc(sizeof(struct iname))) &&
(lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
if (!lo && (lo = whine_malloc(sizeof(struct iname))))
{
strcpy(lo->name, ifr.ifr_name);
lo->used = 1;
lo->next = daemon->if_names;
daemon->if_names = lo;
if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
{
strcpy(lo->name, ifr.ifr_name);
lo->used = 1;
lo->next = daemon->if_names;
daemon->if_names = lo;
}
else
free(lo);
}
}
@@ -459,6 +495,77 @@ int set_ipv6pktinfo(int fd)
return 0;
}
#endif
/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
int tcp_interface(int fd, int af)
{
int if_index = 0;
#ifdef HAVE_LINUX_NETWORK
int opt = 1;
struct cmsghdr *cmptr;
struct msghdr msg;
/* use mshdr do that the CMSDG_* macros are available */
msg.msg_control = daemon->packet;
msg.msg_controllen = daemon->packet_buff_sz;
/* we overwrote the buffer... */
daemon->srv_save = NULL;
if (af == AF_INET)
{
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex;
}
}
#ifdef HAVE_IPV6
else
{
/* Only the RFC-2292 API has the ability to find the interface for TCP connections,
it was removed in RFC-3542 !!!!
Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
uses the old ABI, and should work with pre- and post-3542 kernel headers */
#ifdef IPV6_2292PKTOPTIONS
# define PKTOPTIONS IPV6_2292PKTOPTIONS
#else
# define PKTOPTIONS IPV6_PKTOPTIONS
#endif
if (set_ipv6pktinfo(fd) &&
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
{
union {
unsigned char *c;
struct in6_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi6_ifindex;
}
}
}
#endif /* IPV6 */
#endif /* Linux */
return if_index;
}
static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
{
+16 -7
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -1369,14 +1369,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
strcat(path, "/");
strcat(path, ent->d_name);
/* files must be readable */
if (stat(path, &buf) == -1)
die(_("cannot access %s: %s"), path, EC_FILE);
/* only reg files allowed. */
if (!S_ISREG(buf.st_mode))
continue;
/* files must be readable */
one_file(path, 0);
/* only reg files allowed. */
if (S_ISREG(buf.st_mode))
one_file(path, 0);
free(path);
}
@@ -2378,7 +2378,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (!(*cp >= '0' && *cp <= '9'))
break;
if (!cp || (leasepos+1 < k))
if (*cp || (leasepos+1 < k))
ret_err(_("bad dhcp-range"));
new->lease_time = atoi(a[leasepos]) * fac;
@@ -2468,6 +2468,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (!inet_pton(AF_INET6, arg, &new->addr6))
ret_err(_("bad IPv6 address"));
for (i= 0; i < 8; i++)
if (new->addr6.s6_addr[i] != 0)
break;
/* set WILDCARD if network part all zeros */
if (i == 8)
new->flags |= CONFIG_WILDCARD;
new->flags |= CONFIG_ADDR6;
}
@@ -2628,6 +2636,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else
{
new->set = NULL;
free(newtag);
break;
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+18 -4
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -1256,7 +1256,20 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
add_extradata_opt(lease, oui);
add_extradata_opt(lease, serial);
add_extradata_opt(lease, class);
if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
{
add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
}
else
{
add_extradata_opt(lease, NULL);
add_extradata_opt(lease, NULL);
add_extradata_opt(lease, NULL);
}
/* space-concat tag set */
if (!tagif_netid)
add_extradata_opt(lease, NULL);
@@ -1739,7 +1752,7 @@ static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, i
if (overload[2] & 2)
{
p = dhcp_skip_opts(mess->sname);
if (p + len + 3 >= mess->sname + sizeof(mess->file))
if (p + len + 3 >= mess->sname + sizeof(mess->sname))
p = NULL;
}
}
@@ -2234,7 +2247,8 @@ static void do_options(struct dhcp_context *context,
!option_find2(OPTION_ROUTER))
option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
if (in_list(req_options, OPTION_DNSSERVER) &&
if (daemon->port == NAMESERVER_PORT &&
in_list(req_options, OPTION_DNSSERVER) &&
!option_find2(OPTION_DNSSERVER))
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
}
+5 -5
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -576,8 +576,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (ltmp && ltmp->clid &&
(ltmp->clid_len != clid_len || memcmp(ltmp->clid, clid, clid_len) != 0 || ltmp->hwaddr_type != iaid))
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s:%d"),
daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len), lease->hwaddr_type);
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s#%d"),
daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len), ltmp->hwaddr_type);
else if (have_config(config, CONFIG_DECLINED) &&
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
@@ -1027,7 +1027,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
/* We can't discriminate contexts based on address, as we don't know it.
If there is only one possible context, we can use its tags */
if (context && !context->current)
if (context && context->netid.net && !context->current)
{
context->netid.next = NULL;
context_tags = &context->netid;
@@ -1265,7 +1265,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
end_opt6(o);
}
if (!done_dns &&
if (daemon->port == NAMESERVER_PORT && !done_dns &&
(!IN6_IS_ADDR_UNSPECIFIED(&context->local6) ||
!IN6_IS_ADDR_UNSPECIFIED(fallback)))
{
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
+12 -7
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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
@@ -61,6 +61,7 @@ void tftp_request(struct listener *listen, time_t now)
char *name = NULL;
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct all_addr addra;
union {
struct cmsghdr align; /* this ensures alignment */
@@ -189,18 +190,22 @@ void tftp_request(struct listener *listen, time_t now)
return;
name = namebuff;
addra.addr.addr4 = addr.in.sin_addr;
#ifdef HAVE_IPV6
if (listen->family == AF_INET6)
addra.addr.addr6 = addr.in6.sin6_addr;
#endif
if (!iface_check(listen->family, &addra, name, NULL))
{
if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, NULL))
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name))
return;
}
else
#endif
if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, NULL))
return;
#ifdef HAVE_DHCP
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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