mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
26
Commits
v2.73rc8
...
v2.74test1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60176c7bf4 | ||
|
|
362c9303da | ||
|
|
5e95a552ee | ||
|
|
90cb222551 | ||
|
|
850163288d | ||
|
|
e3ec6f0bd7 | ||
|
|
f7bfbdc872 | ||
|
|
4918bd5505 | ||
|
|
9bad339af8 | ||
|
|
ba4fc0f996 | ||
|
|
2fd5bc952d | ||
|
|
0ddb8769bb | ||
|
|
654f59e762 | ||
|
|
d91b1fd402 | ||
|
|
c6d82c9ba6 | ||
|
|
4d25cf89d5 | ||
|
|
24e9207e13 | ||
|
|
89130d91d6 | ||
|
|
d644b2a17d | ||
|
|
bd7bfa21c4 | ||
|
|
403de05925 | ||
|
|
46c89f2bd0 | ||
|
|
23facf0d77 | ||
|
|
549b1a478c | ||
|
|
7f8565b94c | ||
|
|
06568c6636 |
No files matched your search
@@ -1,3 +1,11 @@
|
||||
version 2.74
|
||||
Fix reversion in 2.73 where --conf-file would attempt to
|
||||
read the default file, rather than no file.
|
||||
|
||||
Fix inotify code to handle dangling symlinks better and
|
||||
not SEGV in some circumstances.
|
||||
|
||||
|
||||
version 2.73
|
||||
Fix crash at startup when an empty suffix is supplied to
|
||||
--conf-dir, also trivial memory leak. Thanks to
|
||||
@@ -121,6 +129,20 @@ version 2.73
|
||||
Allow DHCPv4 options T1 and T2 to be set using --dhcp-option.
|
||||
Thanks to Kevin Benton for patches and work on this.
|
||||
|
||||
Fix code for DHCPCONFIRM DHCPv6 messages to confirm addresses
|
||||
in the correct subnet, even of not in dynamic address
|
||||
allocation range. Thanks to Steve Hirsch for spotting
|
||||
the problem.
|
||||
|
||||
Add AddDhcpLease and DeleteDhcpLease DBus methods. Thanks
|
||||
to Nicolas Cavallari for the patch.
|
||||
|
||||
Allow configuration of router advertisements without the
|
||||
"on-link" bit set. Thanks to Neil Jerram for the patch.
|
||||
|
||||
Extend --bridge-interface to DHCPv6 and router
|
||||
advertisements. Thanks to Neil Jerram for the patch.
|
||||
|
||||
|
||||
version 2.72
|
||||
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
|
||||
|
||||
@@ -117,7 +117,7 @@ install-i18n : all-i18n install-common
|
||||
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
|
||||
|
||||
merge :
|
||||
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
|
||||
@cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile dnsmasq.pot
|
||||
for f in `cd $(PO); echo *.po`; do \
|
||||
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
|
||||
done
|
||||
|
||||
@@ -169,6 +169,80 @@ Return an array of strings, each string is the IP address of an upstream
|
||||
server which has been found to loop queries back to this dnsmasq instance, and
|
||||
it therefore not being used.
|
||||
|
||||
AddDhcpLease
|
||||
------------
|
||||
|
||||
Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
|
||||
database, as if a client requested and obtained a lease.
|
||||
|
||||
If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
|
||||
|
||||
Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
|
||||
D-Bus signal and will run the configured DHCP lease script accordingly.
|
||||
|
||||
This function takes many arguments which are the lease parameters:
|
||||
- A string with the textual representation of the IPv4 or IPv6 address of the
|
||||
client.
|
||||
|
||||
Examples:
|
||||
"192.168.1.115"
|
||||
"1003:1234:abcd::1%eth0"
|
||||
"2001:db8:abcd::1"
|
||||
|
||||
- A string representing the hardware address of the client, using the same
|
||||
format as the one used in the lease database.
|
||||
|
||||
Examples:
|
||||
|
||||
"00:23:45:67:89:ab"
|
||||
"06-00:20:e0:3b:13:af" (token ring)
|
||||
|
||||
- The hostname of the client, as an array of bytes (so there is no problem
|
||||
with non-ASCII character encoding). May be empty.
|
||||
|
||||
Example (for "hostname.or.fqdn"):
|
||||
[104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
|
||||
|
||||
- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
|
||||
empty.
|
||||
|
||||
Examples:
|
||||
|
||||
DHCPv6 DUID:
|
||||
[0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
|
||||
DHCPv4 client identifier:
|
||||
[255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
|
||||
|
||||
- The duration of the lease, in seconds. If the lease is updated, then
|
||||
the duration replaces the previous duration.
|
||||
|
||||
Example:
|
||||
|
||||
7200
|
||||
|
||||
- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
|
||||
byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
|
||||
|
||||
Example (for IPv6):
|
||||
|
||||
203569230
|
||||
|
||||
- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
|
||||
address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
|
||||
(IA_NA). For DHCPv4 leases, this must be set to false.
|
||||
|
||||
RemoveDhcpLease
|
||||
---------------
|
||||
|
||||
Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
|
||||
database, as if a client sent a release message to abandon a lease.
|
||||
|
||||
This function takes only one parameter: the text representation of the
|
||||
IPv4 or IPv6 address of the lease to remove.
|
||||
|
||||
Note that this function will trigger the DhcpLeaseRemoved signal and the
|
||||
configured DHCP lease script will be run with the "del" action.
|
||||
|
||||
|
||||
|
||||
2. SIGNALS
|
||||
|
||||
Vendored
+14
-2
@@ -1,13 +1,25 @@
|
||||
dnsmasq (2.74-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:54:11 +0000
|
||||
|
||||
dnsmasq (2.73-2) unstable; urgency=low
|
||||
|
||||
* Fix behaviour of empty --conf-file (closes: #790341)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:46:42 +0000
|
||||
|
||||
dnsmasq (2.73-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
* New upstream. (closes: #786996)
|
||||
* Tweak field width in cache dump to avoid truncating IPv6
|
||||
addresses. (closes: #771557)
|
||||
* Add newline at the end of example config file. (LP: #1416895)
|
||||
* Make Debian package build reproducible. (closes: #777323)
|
||||
* Add Requires=network.target to systemd unit.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 11 Feb 2015 21:59:42 +0000
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 4 Jun 2015 22:31:42 +0000
|
||||
|
||||
dnsmasq (2.72-3) unstable; urgency=medium
|
||||
|
||||
|
||||
Vendored
+7
-3
@@ -24,6 +24,7 @@ DEB_COPTS = $(COPTS)
|
||||
TARGET = install-i18n
|
||||
|
||||
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
|
||||
BUILD_DATE := $(shell dpkg-parsechangelog --show-field Date)
|
||||
|
||||
# Force package version based on git tags.
|
||||
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
|
||||
@@ -118,8 +119,9 @@ binary-indep: checkroot
|
||||
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
|
||||
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
|
||||
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
|
||||
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -T -pdnsmasq -Pdebian/daemon
|
||||
find debian/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/daemon
|
||||
chmod -R g-ws debian/daemon
|
||||
dpkg --build debian/daemon ..
|
||||
@@ -169,9 +171,10 @@ endif
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
||||
endif
|
||||
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
|
||||
find debian/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/base
|
||||
chmod -R g-ws debian/base
|
||||
dpkg --build debian/base ..
|
||||
@@ -196,9 +199,10 @@ ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
|
||||
strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
||||
endif
|
||||
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps -Tdebian/utils-substvars debian/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
|
||||
find debian/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/utils
|
||||
chmod -R g-ws debian/utils
|
||||
dpkg --build debian/utils ..
|
||||
|
||||
@@ -251,6 +251,13 @@
|
||||
# the IP address 192.168.0.60
|
||||
#dhcp-host=id:01:02:02:04,192.168.0.60
|
||||
|
||||
# Always give the Infiniband interface with hardware address
|
||||
# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
|
||||
# ip address 192.168.0.61. The client id is derived from the prefix
|
||||
# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
|
||||
# hex digits of the hardware address.
|
||||
#dhcp-host=id:ff:00:00:00:00:00:02:00:00:02:c9:00:f4:52:14:03:00:28:05:81,192.168.0.61
|
||||
|
||||
# Always give the host with client identifier "marjorie"
|
||||
# the IP address 192.168.0.60
|
||||
#dhcp-host=id:marjorie,192.168.0.60
|
||||
|
||||
+13
-8
@@ -654,7 +654,7 @@ Provide DS records to act a trust anchors for DNSSEC
|
||||
validation. Typically these will be the DS record(s) for Zone Signing
|
||||
key(s) of the root zone,
|
||||
but trust anchors for limited domains are also possible. The current
|
||||
root-zone trust anchors may be donwloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||
.TP
|
||||
.B --dnssec-check-unsigned
|
||||
As a default, dnsmasq does not check that unsigned DNS replies are
|
||||
@@ -833,7 +833,7 @@ and
|
||||
for details.)
|
||||
|
||||
For IPv6, the mode may be some combination of
|
||||
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter.
|
||||
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter, off-link.
|
||||
|
||||
.B ra-only
|
||||
tells dnsmasq to offer Router Advertisement only on this subnet,
|
||||
@@ -873,6 +873,9 @@ enables a mode where router address(es) rather than prefix(es) are included in t
|
||||
This is described in RFC-3775 section 7.2 and is used in mobile IPv6. In this mode the interval option
|
||||
is also included, as described in RFC-3775 section 7.3.
|
||||
|
||||
.B off-link
|
||||
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
|
||||
|
||||
.TP
|
||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||
Specify per host parameters for the DHCP server. This allows a machine
|
||||
@@ -1388,7 +1391,7 @@ enables dynamic allocation. With tags, only when the tags are all
|
||||
set. It may be repeated with different tag sets.
|
||||
.TP
|
||||
.B \-5, --no-ping
|
||||
(IPv4 only) By default, the DHCP server will attempt to ensure that an address in
|
||||
(IPv4 only) By default, the DHCP server will attempt to ensure that an address is
|
||||
not in use before allocating it to a host. It does this by sending an
|
||||
ICMP echo request (aka "ping") to the address in question. If it gets
|
||||
a reply, then the address must already be in use, and another is
|
||||
@@ -1597,11 +1600,13 @@ option also forces the leasechange script to be called on changes
|
||||
to the client-id and lease length and expiry time.
|
||||
.TP
|
||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||
Treat DHCP request packets arriving at any of the <alias> interfaces
|
||||
as if they had arrived at <interface>. This option is necessary when
|
||||
using "old style" bridging on BSD platforms, since
|
||||
packets arrive at tap interfaces which don't have an IP address.
|
||||
A trailing '*' wildcard can be used in each <alias>.
|
||||
Treat DHCP (v4 and v6) request and IPv6 Router Solicit packets
|
||||
arriving at any of the <alias> interfaces as if they had arrived at
|
||||
<interface>. This option allows dnsmasq to provide DHCP and RA
|
||||
service over unaddressed and unbridged Ethernet interfaces, e.g. on an
|
||||
OpenStack compute host where each such interface is a TAP interface to
|
||||
a VM, or as in "old style bridging" on BSD platforms. A trailing '*'
|
||||
wildcard can be used in each <alias>.
|
||||
.TP
|
||||
.B \-s, --domain=<domain>[,<address range>[,local]]
|
||||
Specifies DNS domains for the DHCP server. Domains may be be given
|
||||
|
||||
+8
-4
@@ -1062,10 +1062,14 @@ esta opci
|
||||
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
|
||||
.TP
|
||||
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
|
||||
Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
|
||||
como si hubieran llegado a la interface <nombre de interface>. Esta opción
|
||||
es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
|
||||
los paquetes llegan a interfaces tap que no tienen una dirección IP.
|
||||
Tratar paquetes de pedidos DHCP (v4 y v6) y de IPv6 Router Solicit que
|
||||
llegan a cualquiera de las interfaces <alias> como si hubieran llegado
|
||||
a la interface <nombre de interface>. Esta opción permite que dnsmasq
|
||||
puede proporcionar los servicios DHCP y RA a través de interfaces
|
||||
ethernet sin dirección y sin puente; por ejemplo en un nodo de cálculo
|
||||
de OpenStack, donde cada una de esas interfaces es una interfaz TAP
|
||||
para una máquina virtual, o al usar bridging estilo viejo en
|
||||
plataformas BSD.
|
||||
.TP
|
||||
.B \-s, --domain=<dominio>[,<rango de IPs>]
|
||||
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
|
||||
|
||||
+12
-6
@@ -852,7 +852,7 @@ et
|
||||
pour plus de détails).
|
||||
|
||||
Pour IPv6, le mode peut-être une combinaison des valeurs
|
||||
.B ra-only, slaac, ra-names, ra-stateless.
|
||||
.B ra-only, slaac, ra-names, ra-stateless, off-link.
|
||||
|
||||
.B ra-only
|
||||
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
|
||||
@@ -888,6 +888,9 @@ peut-être combiné avec
|
||||
et
|
||||
.B slaac.
|
||||
|
||||
.B off-link
|
||||
indique à dnsmasq d'annoncer le préfixe sans le bit L (sur lien).
|
||||
|
||||
.TP
|
||||
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
|
||||
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
|
||||
@@ -1655,11 +1658,14 @@ changement d'état de bail à chaque changement de l'identifiant de client, de
|
||||
longueur de bail ou de date d'expiration.
|
||||
.TP
|
||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||
Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
|
||||
comme si elles arrivaient de l'interface <interface>. Cette option est
|
||||
nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
|
||||
BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
|
||||
pas d'adresse IP. Chaque <alias> peut finir avec un simple '*' joker.
|
||||
Traiter les requêtes DHCP (v4 et v6) et IPv6 Router Solicit arrivant
|
||||
sur n'importe laquelle des interfaces <alias> comme si elles
|
||||
arrivaient de l'interface <interface>. Cette option permet à dnsmasq
|
||||
de fournir les service DHCP et RA sur les interfaces ethernet non
|
||||
adressés et non pontés; par exemple sur un hôte de calcul d'OpenStack
|
||||
où chaque telle interface est une interface TAP à une machine
|
||||
virtuelle, ou lors de l'utilisation de pont ethernet "ancien mode" sur
|
||||
plate-forme BSD. Chaque <alias> peut finir avec un simple '*' joker.
|
||||
.TP
|
||||
.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
|
||||
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
|
||||
|
||||
+413
-389
File diff suppressed because it is too large.
Load diff
+193
-2
@@ -70,6 +70,21 @@ const char* introspection_xml_template =
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
#ifdef HAVE_DHCP
|
||||
" <method name=\"AddDhcpLease\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"ay\"/>\n"
|
||||
" <arg name=\"clid\" type=\"ay\"/>\n"
|
||||
" <arg name=\"lease_duration\" type=\"u\"/>\n"
|
||||
" <arg name=\"ia_id\" type=\"u\"/>\n"
|
||||
" <arg name=\"is_temporary\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"DeleteDhcpLease\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
|
||||
" </method>\n"
|
||||
#endif
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
@@ -421,18 +436,184 @@ static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
my_syslog(LOG_INFO, "Enabling --%s option from D-Bus", name);
|
||||
my_syslog(LOG_INFO, _("Enabling --%s option from D-Bus"), name);
|
||||
set_option_bool(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_syslog(LOG_INFO, "Disabling --%s option from D-Bus", name);
|
||||
my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
|
||||
reset_option_bool(flag);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
static DBusMessage *dbus_add_lease(DBusMessage* message)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
const char *ipaddr, *hwaddr, *hostname, *tmp;
|
||||
const unsigned char* clid;
|
||||
int clid_len, hostname_len, hw_len, hw_type;
|
||||
dbus_uint32_t expires, ia_id;
|
||||
dbus_bool_t is_temporary;
|
||||
struct all_addr addr;
|
||||
time_t now = dnsmasq_time();
|
||||
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
|
||||
|
||||
DBusMessageIter iter, array_iter;
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected string as first argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected string as second argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &hwaddr);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected byte array as third argument");
|
||||
|
||||
dbus_message_iter_recurse(&iter, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
|
||||
tmp = memchr(hostname, '\0', hostname_len);
|
||||
if (tmp)
|
||||
{
|
||||
if (tmp == &hostname[hostname_len - 1])
|
||||
hostname_len--;
|
||||
else
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Hostname contains an embedded NUL character");
|
||||
}
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected byte array as fourth argument");
|
||||
|
||||
dbus_message_iter_recurse(&iter, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected uint32 as fifth argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &expires);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected uint32 as sixth argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &ia_id);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected uint32 as sixth argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &is_temporary);
|
||||
|
||||
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
||||
{
|
||||
if (ia_id != 0 || is_temporary)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"ia_id and is_temporary must be zero for IPv4 lease");
|
||||
|
||||
if (!(lease = lease_find_by_addr(addr.addr.addr4)))
|
||||
lease = lease4_allocate(addr.addr.addr4);
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
||||
{
|
||||
if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
|
||||
lease = lease6_allocate(&addr.addr.addr6,
|
||||
is_temporary ? LEASE_TA : LEASE_NA);
|
||||
lease_set_iaid(lease, ia_id);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s'", ipaddr);
|
||||
|
||||
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
|
||||
&hw_type);
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
|
||||
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
|
||||
clid_len, now, 0);
|
||||
lease_set_expires(lease, expires, now);
|
||||
if (hostname_len != 0)
|
||||
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
|
||||
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *dbus_del_lease(DBusMessage* message)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
DBusMessageIter iter;
|
||||
const char *ipaddr;
|
||||
DBusMessage *reply;
|
||||
struct all_addr addr;
|
||||
dbus_bool_t ret = 1;
|
||||
time_t now = dnsmasq_time();
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected string as first argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||
|
||||
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
||||
lease = lease_find_by_addr(addr.addr.addr4);
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
||||
lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
|
||||
#endif
|
||||
else
|
||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s'", ipaddr);
|
||||
|
||||
if (lease)
|
||||
{
|
||||
lease_prune(lease, now);
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
}
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
if ((reply = dbus_message_new_method_return(message)))
|
||||
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
|
||||
return reply;
|
||||
}
|
||||
#endif
|
||||
|
||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *user_data)
|
||||
@@ -490,6 +671,16 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
|
||||
}
|
||||
#ifdef HAVE_DHCP
|
||||
else if (strcmp(method, "AddDhcpLease") == 0)
|
||||
{
|
||||
reply = dbus_add_lease(message);
|
||||
}
|
||||
else if (strcmp(method, "DeleteDhcpLease") == 0)
|
||||
{
|
||||
reply = dbus_del_lease(message);
|
||||
}
|
||||
#endif
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache = 1;
|
||||
else
|
||||
|
||||
+8
-5
@@ -225,10 +225,11 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
||||
#endif
|
||||
|
||||
/* One form of bridging on BSD has the property that packets
|
||||
can be recieved on bridge interfaces which do not have an IP address.
|
||||
We allow these to be treated as aliases of another interface which does have
|
||||
an IP address with --dhcp-bridge=interface,alias,alias */
|
||||
/* If the interface on which the DHCP request was received is an
|
||||
alias of some other interface (as specified by the
|
||||
--bridge-interface option), change ifr.ifr_name so that we look
|
||||
for DHCP contexts associated with the aliased interface instead
|
||||
of with the aliasing one. */
|
||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||
{
|
||||
for (alias = bridge->alias; alias; alias = alias->next)
|
||||
@@ -236,7 +237,9 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
{
|
||||
if (!(iface_index = if_nametoindex(bridge->iface)))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("unknown interface %s in bridge-interface"),
|
||||
bridge->iface);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
+27
-1
@@ -144,6 +144,8 @@ void dhcp6_packet(time_t now)
|
||||
|
||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
|
||||
{
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
@@ -160,6 +162,30 @@ void dhcp6_packet(time_t now)
|
||||
memset(&parm.fallback, 0, IN6ADDRSZ);
|
||||
memset(&parm.ll_addr, 0, IN6ADDRSZ);
|
||||
memset(&parm.ula_addr, 0, IN6ADDRSZ);
|
||||
|
||||
/* If the interface on which the DHCPv6 request was received is
|
||||
an alias of some other interface (as specified by the
|
||||
--bridge-interface option), change parm.ind so that we look
|
||||
for DHCPv6 contexts associated with the aliased interface
|
||||
instead of with the aliasing one. */
|
||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||
{
|
||||
for (alias = bridge->alias; alias; alias = alias->next)
|
||||
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
|
||||
{
|
||||
parm.ind = if_nametoindex(bridge->iface);
|
||||
if (!parm.ind)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("unknown interface %s in bridge-interface"),
|
||||
bridge->iface);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (alias)
|
||||
break;
|
||||
}
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
|
||||
@@ -208,7 +234,7 @@ void dhcp6_packet(time_t now)
|
||||
/* May have configured relay, but not DHCP server */
|
||||
if (!daemon->doing_dhcp6)
|
||||
return;
|
||||
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
|
||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||
|
||||
+7
-7
@@ -84,15 +84,15 @@ struct dns_header {
|
||||
u16 qdcount,ancount,nscount,arcount;
|
||||
};
|
||||
|
||||
#define HB3_QR 0x80
|
||||
#define HB3_QR 0x80 /* Query */
|
||||
#define HB3_OPCODE 0x78
|
||||
#define HB3_AA 0x04
|
||||
#define HB3_TC 0x02
|
||||
#define HB3_RD 0x01
|
||||
#define HB3_AA 0x04 /* Authoritative Answer */
|
||||
#define HB3_TC 0x02 /* TrunCated */
|
||||
#define HB3_RD 0x01 /* Recursion Desired */
|
||||
|
||||
#define HB4_RA 0x80
|
||||
#define HB4_AD 0x20
|
||||
#define HB4_CD 0x10
|
||||
#define HB4_RA 0x80 /* Recursion Available */
|
||||
#define HB4_AD 0x20 /* Authenticated Data */
|
||||
#define HB4_CD 0x10 /* Checking Disabled */
|
||||
#define HB4_RCODE 0x0f
|
||||
|
||||
#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3)
|
||||
|
||||
+17
-5
@@ -1755,14 +1755,22 @@ int icmp_ping(struct in_addr addr)
|
||||
better not use any resources our caller has in use...)
|
||||
but we remain deaf to signals or further DHCP packets. */
|
||||
|
||||
int fd;
|
||||
/* There can be a problem using dnsmasq_time() to end the loop, since
|
||||
it's not monotonic, and can go backwards if the system clock is
|
||||
tweaked, leading to the code getting stuck in this loop and
|
||||
ignoring DHCP requests. To fix this, we check to see if select returned
|
||||
as a result of a timeout rather than a socket becoming available. We
|
||||
only allow this to happen as many times as it takes to get to the wait time
|
||||
in quarter-second chunks. This provides a fallback way to end loop. */
|
||||
|
||||
int fd, rc;
|
||||
struct sockaddr_in saddr;
|
||||
struct {
|
||||
struct ip ip;
|
||||
struct icmp icmp;
|
||||
} packet;
|
||||
unsigned short id = rand16();
|
||||
unsigned int i, j;
|
||||
unsigned int i, j, timeout_count;
|
||||
int gotreply = 0;
|
||||
time_t start, now;
|
||||
|
||||
@@ -1794,8 +1802,8 @@ int icmp_ping(struct in_addr addr)
|
||||
while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
|
||||
(struct sockaddr *)&saddr, sizeof(saddr))));
|
||||
|
||||
for (now = start = dnsmasq_time();
|
||||
difftime(now, start) < (float)PING_WAIT;)
|
||||
for (now = start = dnsmasq_time(), timeout_count = 0;
|
||||
(difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set rset, wset;
|
||||
@@ -1820,11 +1828,15 @@ int icmp_ping(struct in_addr addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0)
|
||||
rc = select(maxfd+1, &rset, &wset, NULL, &tv);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
}
|
||||
else if (rc == 0)
|
||||
timeout_count++;
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
|
||||
@@ -868,6 +868,7 @@ struct dhcp_context {
|
||||
#define CONTEXT_USED (1u<<15)
|
||||
#define CONTEXT_OLD (1u<<16)
|
||||
#define CONTEXT_V6 (1u<<17)
|
||||
#define CONTEXT_RA_OFF_LINK (1u<<18)
|
||||
|
||||
struct ping_result {
|
||||
struct in_addr addr;
|
||||
|
||||
+39
-11
@@ -1223,8 +1223,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
||||
val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons);
|
||||
/* Note dnssec_validate_reply() will have cached positive answers */
|
||||
|
||||
if (val == STAT_NO_SIG || val == STAT_INSECURE)
|
||||
if (val == STAT_INSECURE)
|
||||
val = STAT_BOGUS;
|
||||
|
||||
if (val == STAT_NO_SIG)
|
||||
return val;
|
||||
|
||||
p = (unsigned char *)(header+1);
|
||||
extract_name(header, plen, &p, name, 1, 4);
|
||||
@@ -1493,13 +1496,13 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
|
||||
{
|
||||
/* Normal case, name falls between NSEC name and next domain name,
|
||||
wrap around case, name falls between NSEC name (rc == -1) and end */
|
||||
if (hostname_cmp(workspace2, name) == 1 || hostname_cmp(workspace1, workspace2) == 1)
|
||||
if (hostname_cmp(workspace2, name) >= 0 || hostname_cmp(workspace1, workspace2) >= 0)
|
||||
return STAT_SECURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wrap around case, name falls between start and next domain name */
|
||||
if (hostname_cmp(workspace1, workspace2) == 1 && hostname_cmp(workspace2, name) == 1)
|
||||
if (hostname_cmp(workspace1, workspace2) >= 0 && hostname_cmp(workspace2, name) >=0 )
|
||||
return STAT_SECURE;
|
||||
}
|
||||
}
|
||||
@@ -1632,17 +1635,17 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (rc <= 0)
|
||||
else if (rc < 0)
|
||||
{
|
||||
/* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
|
||||
wrap around case, name-hash falls between NSEC3 name-hash and end */
|
||||
if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
|
||||
if (memcmp(p, digest, digest_len) >= 0 || memcmp(workspace2, p, digest_len) >= 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wrap around case, name falls between start and next domain name */
|
||||
if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
|
||||
if (memcmp(workspace2, p, digest_len) >= 0 && memcmp(p, digest, digest_len) >= 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1875,11 +1878,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
|
||||
if (neganswer && !have_answer)
|
||||
*neganswer = 1;
|
||||
|
||||
|
||||
/* No data, therefore no sigs */
|
||||
if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
|
||||
return STAT_NO_SIG;
|
||||
|
||||
{
|
||||
*keyname = 0;
|
||||
return STAT_NO_SIG;
|
||||
}
|
||||
|
||||
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
|
||||
{
|
||||
if (!extract_name(header, plen, &p1, name, 1, 10))
|
||||
@@ -1948,6 +1954,19 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
{
|
||||
if (class)
|
||||
*class = class1; /* Class for DS or DNSKEY */
|
||||
|
||||
if (rc == STAT_NO_SIG)
|
||||
{
|
||||
/* If we dropped off the end of a CNAME chain, return
|
||||
STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
|
||||
if DS records in CNAME chains. */
|
||||
if (cname_count == CNAME_CHAIN || i < ntohs(header->ancount))
|
||||
/* No CNAME chain, or no sig in answer section, return empty name. */
|
||||
*keyname = 0;
|
||||
else if (!extract_name(header, plen, &qname, keyname, 1, 0))
|
||||
return STAT_BOGUS;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2060,8 +2079,17 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
|
||||
/* First marshall the NSEC records, if we've not done it previously */
|
||||
if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
|
||||
return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
|
||||
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
|
||||
{
|
||||
/* No NSEC records. If we dropped off the end of a CNAME chain, return
|
||||
STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
|
||||
if DS records in CNAME chains. */
|
||||
if (cname_count == CNAME_CHAIN) /* No CNAME chain, return empty name. */
|
||||
*keyname = 0;
|
||||
else if (!extract_name(header, plen, &qname, keyname, 1, 0))
|
||||
return STAT_BOGUS;
|
||||
return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
|
||||
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
|
||||
}
|
||||
|
||||
/* Get name of missing answer */
|
||||
if (!extract_name(header, plen, &qname, name, 1, 0))
|
||||
|
||||
+36
-5
@@ -769,7 +769,8 @@ void reply_query(int fd, int family, time_t now)
|
||||
header->arcount = htons(0);
|
||||
if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
|
||||
{
|
||||
header->hb3 &= ~(HB3_QR | HB3_TC);
|
||||
header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
|
||||
header->hb4 &= ~(HB4_RA | HB4_RCODE);
|
||||
forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0, 0);
|
||||
return;
|
||||
}
|
||||
@@ -850,7 +851,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
Avoid caching a reply with sigs if there's a vaildated break in the
|
||||
DS chain, so we don't return replies from cache missing sigs. */
|
||||
status = STAT_INSECURE_DS;
|
||||
else if (status == STAT_NO_NS)
|
||||
else if (status == STAT_NO_NS || status == STAT_NO_SIG)
|
||||
status = STAT_BOGUS;
|
||||
}
|
||||
else if (forward->flags & FREC_CHECK_NOSIGN)
|
||||
@@ -996,7 +997,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
Avoid caching a reply with sigs if there's a vaildated break in the
|
||||
DS chain, so we don't return replies from cache missing sigs. */
|
||||
status = STAT_INSECURE_DS;
|
||||
else if (status == STAT_NO_NS)
|
||||
else if (status == STAT_NO_NS || status == STAT_NO_SIG)
|
||||
status = STAT_BOGUS;
|
||||
}
|
||||
else if (forward->flags & FREC_CHECK_NOSIGN)
|
||||
@@ -1455,6 +1456,21 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
|
||||
if (status == STAT_BOGUS)
|
||||
return STAT_BOGUS;
|
||||
|
||||
if (status == STAT_NO_SIG && *keyname != 0)
|
||||
{
|
||||
/* There is a validated CNAME chain that doesn't end in a DS record. Start
|
||||
the search again in that domain. */
|
||||
blockdata_free(forward->orig_domain);
|
||||
forward->name_start = strlen(keyname);
|
||||
forward->name_len = forward->name_start + 1;
|
||||
if (!(forward->orig_domain = blockdata_alloc(keyname, forward->name_len)))
|
||||
return STAT_BOGUS;
|
||||
|
||||
strcpy(name, keyname);
|
||||
status = 0; /* force to cache when we iterate. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* There's a proven DS record, or we're within a zone, where there doesn't need
|
||||
to be a DS record. Add a name and try again.
|
||||
If we've already tried the whole name, then fail */
|
||||
@@ -1571,6 +1587,21 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
|
||||
return STAT_INSECURE;
|
||||
}
|
||||
|
||||
if (status == STAT_NO_SIG && *keyname != 0)
|
||||
{
|
||||
/* There is a validated CNAME chain that doesn't end in a DS record. Start
|
||||
the search again in that domain. */
|
||||
blockdata_free(block);
|
||||
name_len = strlen(keyname) + 1;
|
||||
name_start = name + name_len - 1;
|
||||
|
||||
if (!(block = blockdata_alloc(keyname, name_len)))
|
||||
return STAT_BOGUS;
|
||||
|
||||
strcpy(name, keyname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status == STAT_BOGUS)
|
||||
{
|
||||
free(packet);
|
||||
@@ -1626,7 +1657,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
{
|
||||
if (new_status == STAT_NO_DS)
|
||||
new_status = STAT_INSECURE_DS;
|
||||
else if (new_status == STAT_NO_NS)
|
||||
else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG)
|
||||
new_status = STAT_BOGUS;
|
||||
}
|
||||
}
|
||||
@@ -1691,7 +1722,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
{
|
||||
if (new_status == STAT_NO_DS)
|
||||
new_status = STAT_INSECURE_DS;
|
||||
else if (new_status == STAT_NO_NS)
|
||||
else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG)
|
||||
new_status = STAT_BOGUS; /* Validated no DS */
|
||||
}
|
||||
}
|
||||
|
||||
+67
-16
@@ -18,6 +18,7 @@
|
||||
#ifdef HAVE_INOTIFY
|
||||
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/param.h> /* For MAXSYMLINKS */
|
||||
|
||||
/* the strategy is to set a inotify on the directories containing
|
||||
resolv files, for any files in the directory which are close-write
|
||||
@@ -35,10 +36,56 @@
|
||||
static char *inotify_buffer;
|
||||
#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1)
|
||||
|
||||
/* If path is a symbolic link, return the path it
|
||||
points to, made absolute if relative.
|
||||
If path doesn't exist or is not a symlink, return NULL.
|
||||
Return value is malloc'ed */
|
||||
static char *my_readlink(char *path)
|
||||
{
|
||||
ssize_t rc;
|
||||
size_t size = 64;
|
||||
char *buf;
|
||||
|
||||
while (1)
|
||||
{
|
||||
buf = safe_malloc(size);
|
||||
rc = readlink(path, buf, size);
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
/* Not link or doesn't exist. */
|
||||
if (errno == EINVAL || errno == ENOENT)
|
||||
return NULL;
|
||||
else
|
||||
die(_("cannot access path %s: %s"), path, EC_MISC);
|
||||
}
|
||||
else if (rc < size-1)
|
||||
{
|
||||
char *d;
|
||||
|
||||
buf[rc] = 0;
|
||||
if (buf[0] != '/' && ((d = strrchr(path, '/'))))
|
||||
{
|
||||
/* Add path to relative link */
|
||||
char *new_buf = safe_malloc((d - path) + strlen(buf) + 2);
|
||||
*(d+1) = 0;
|
||||
strcpy(new_buf, path);
|
||||
strcat(new_buf, buf);
|
||||
free(buf);
|
||||
buf = new_buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Buffer too small, increase and retry */
|
||||
size += 64;
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void inotify_dnsmasq_init()
|
||||
{
|
||||
struct resolvc *res;
|
||||
|
||||
inotify_buffer = safe_malloc(INOTIFY_SZ);
|
||||
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
|
||||
@@ -47,19 +94,22 @@ void inotify_dnsmasq_init()
|
||||
|
||||
for (res = daemon->resolv_files; res; res = res->next)
|
||||
{
|
||||
char *d = NULL, *path;
|
||||
|
||||
if (!(path = realpath(res->name, NULL)))
|
||||
char *d, *new_path, *path = safe_malloc(strlen(res->name) + 1);
|
||||
int links = MAXSYMLINKS;
|
||||
|
||||
strcpy(path, res->name);
|
||||
|
||||
/* Follow symlinks until we reach a non-symlink, or a non-existant file. */
|
||||
while ((new_path = my_readlink(path)))
|
||||
{
|
||||
/* realpath will fail if the file doesn't exist, but
|
||||
dnsmasq copes with missing files, so fall back
|
||||
and assume that symlinks are not in use in that case. */
|
||||
if (errno == ENOENT)
|
||||
path = res->name;
|
||||
else
|
||||
die(_("cannot cannonicalise resolv-file %s: %s"), res->name, EC_MISC);
|
||||
if (links-- == 0)
|
||||
die(_("too many symlinks following %s"), res->name, EC_MISC);
|
||||
free(path);
|
||||
path = new_path;
|
||||
}
|
||||
|
||||
|
||||
res->wd = -1;
|
||||
|
||||
if ((d = strrchr(path, '/')))
|
||||
{
|
||||
*d = 0; /* make path just directory */
|
||||
@@ -70,10 +120,11 @@ void inotify_dnsmasq_init()
|
||||
|
||||
if (res->wd == -1 && errno == ENOENT)
|
||||
die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC);
|
||||
|
||||
if (res->wd == -1)
|
||||
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
|
||||
}
|
||||
}
|
||||
|
||||
if (res->wd == -1)
|
||||
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -2699,6 +2699,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
new->flags |= CONTEXT_RA_ROUTER | CONTEXT_RA;
|
||||
else if (strcmp(a[leasepos], "ra-stateless") == 0)
|
||||
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
|
||||
else if (strcmp(a[leasepos], "off-link") == 0)
|
||||
new->flags |= CONTEXT_RA_OFF_LINK;
|
||||
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
|
||||
new->flags |= CONTEXT_DHCP;
|
||||
else if (strstr(a[leasepos], "constructor:") == a[leasepos])
|
||||
@@ -4369,7 +4371,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
{
|
||||
char *buff = opt_malloc(MAXDNAME);
|
||||
int option, conffile_opt = '7', testmode = 0;
|
||||
char *arg, *conffile = NULL;
|
||||
char *arg, *conffile = CONFFILE;
|
||||
|
||||
opterr = 0;
|
||||
|
||||
@@ -4486,11 +4488,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
if (conffile)
|
||||
{
|
||||
one_file(conffile, conffile_opt);
|
||||
free(conffile);
|
||||
}
|
||||
else
|
||||
{
|
||||
one_file(CONFFILE, conffile_opt);
|
||||
if (conffile_opt == 0)
|
||||
free(conffile);
|
||||
}
|
||||
|
||||
/* port might not be known when the address is parsed - fill in here */
|
||||
|
||||
+133
-11
@@ -40,7 +40,18 @@ struct search_param {
|
||||
char name[IF_NAMESIZE+1];
|
||||
};
|
||||
|
||||
struct alias_param {
|
||||
int iface;
|
||||
struct dhcp_bridge *bridge;
|
||||
int num_alias_ifs;
|
||||
int max_alias_ifs;
|
||||
int *alias_ifs;
|
||||
};
|
||||
|
||||
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
|
||||
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest,
|
||||
int send_iface);
|
||||
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||
static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
unsigned int preferred, unsigned int valid, void *vparam);
|
||||
@@ -181,6 +192,7 @@ void icmp6_packet(time_t now)
|
||||
else if (packet[0] == ND_ROUTER_SOLICIT)
|
||||
{
|
||||
char *mac = "";
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
|
||||
/* look for link-layer address option for logging */
|
||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||
@@ -191,12 +203,37 @@ void icmp6_packet(time_t now)
|
||||
|
||||
if (!option_bool(OPT_QUIET_RA))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||
/* source address may not be valid in solicit request. */
|
||||
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
||||
|
||||
/* If the incoming interface is an alias of some other one (as
|
||||
specified by the --bridge-interface option), send an RA using
|
||||
the context of the aliased interface. */
|
||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||
{
|
||||
int bridge_index = if_nametoindex(bridge->iface);
|
||||
if (bridge_index)
|
||||
{
|
||||
for (alias = bridge->alias; alias; alias = alias->next)
|
||||
if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE))
|
||||
{
|
||||
/* Send an RA on if_index with information from
|
||||
bridge_index. */
|
||||
send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index);
|
||||
break;
|
||||
}
|
||||
if (alias)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the incoming interface wasn't an alias, send an RA using
|
||||
the context of the incoming interface. */
|
||||
if (!bridge)
|
||||
/* source address may not be valid in solicit request. */
|
||||
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
|
||||
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface)
|
||||
{
|
||||
struct ra_packet *ra;
|
||||
struct ra_param parm;
|
||||
@@ -313,8 +350,10 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
opt->type = ICMP6_OPT_PREFIX;
|
||||
opt->len = 4;
|
||||
opt->prefix_len = context->prefix;
|
||||
/* autonomous only if we're not doing dhcp, always set "on-link" */
|
||||
opt->flags = do_slaac ? 0xC0 : 0x80;
|
||||
/* autonomous only if we're not doing dhcp, set
|
||||
"on-link" unless "off-link" was specified */
|
||||
opt->flags = (do_slaac ? 0x40 : 0) |
|
||||
((context->flags & CONTEXT_RA_OFF_LINK) ? 0 : 0x80);
|
||||
opt->valid_lifetime = htonl(context->saved_valid - old);
|
||||
opt->preferred_lifetime = htonl(0);
|
||||
opt->reserved = 0;
|
||||
@@ -368,7 +407,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
}
|
||||
#endif
|
||||
|
||||
iface_enumerate(AF_LOCAL, &iface, add_lla);
|
||||
iface_enumerate(AF_LOCAL, &send_iface, add_lla);
|
||||
|
||||
/* RDNSS, RFC 6106, use relevant DHCP6 options */
|
||||
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
|
||||
@@ -476,7 +515,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
else
|
||||
{
|
||||
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
|
||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
|
||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
|
||||
}
|
||||
|
||||
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
|
||||
@@ -485,6 +524,13 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
|
||||
}
|
||||
|
||||
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
|
||||
{
|
||||
/* Send an RA on the same interface that the RA content is based
|
||||
on. */
|
||||
send_ra_alias(now, iface, iface_name, dest, iface);
|
||||
}
|
||||
|
||||
static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
unsigned int preferred, unsigned int valid, void *vparam)
|
||||
@@ -514,6 +560,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
int deprecate = 0;
|
||||
int constructed = 0;
|
||||
int adv_router = 0;
|
||||
int off_link = 0;
|
||||
unsigned int time = 0xffffffff;
|
||||
struct dhcp_context *context;
|
||||
|
||||
@@ -586,6 +633,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
context->ra_time = 0;
|
||||
context->flags |= CONTEXT_RA_DONE;
|
||||
real_prefix = context->prefix;
|
||||
off_link = (context->flags & CONTEXT_RA_OFF_LINK);
|
||||
}
|
||||
|
||||
param->first = 0;
|
||||
@@ -636,8 +684,9 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
opt->type = ICMP6_OPT_PREFIX;
|
||||
opt->len = 4;
|
||||
opt->prefix_len = real_prefix;
|
||||
/* autonomous only if we're not doing dhcp, always set "on-link" */
|
||||
opt->flags = 0x80;
|
||||
/* autonomous only if we're not doing dhcp, set
|
||||
"on-link" unless "off-link" was specified */
|
||||
opt->flags = (off_link ? 0 : 0x80);
|
||||
if (do_slaac)
|
||||
opt->flags |= 0x40;
|
||||
if (adv_router)
|
||||
@@ -683,6 +732,7 @@ time_t periodic_ra(time_t now)
|
||||
struct search_param param;
|
||||
struct dhcp_context *context;
|
||||
time_t next_event;
|
||||
struct alias_param aparam;
|
||||
|
||||
param.now = now;
|
||||
param.iface = 0;
|
||||
@@ -730,12 +780,84 @@ time_t periodic_ra(time_t now)
|
||||
if (tmp->name && wildcard_match(tmp->name, param.name))
|
||||
break;
|
||||
if (!tmp)
|
||||
send_ra(now, param.iface, param.name, NULL);
|
||||
{
|
||||
send_ra(now, param.iface, param.name, NULL);
|
||||
|
||||
/* Also send on all interfaces that are aliases of this
|
||||
one. */
|
||||
for (aparam.bridge = daemon->bridges;
|
||||
aparam.bridge;
|
||||
aparam.bridge = aparam.bridge->next)
|
||||
if ((int)if_nametoindex(aparam.bridge->iface) == param.iface)
|
||||
{
|
||||
/* Count the number of alias interfaces for this
|
||||
'bridge', by calling iface_enumerate with
|
||||
send_ra_to_aliases and NULL alias_ifs. */
|
||||
aparam.iface = param.iface;
|
||||
aparam.alias_ifs = NULL;
|
||||
aparam.num_alias_ifs = 0;
|
||||
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => %d alias(es)",
|
||||
param.name, daemon->addrbuff, aparam.num_alias_ifs);
|
||||
|
||||
/* Allocate memory to store the alias interface
|
||||
indices. */
|
||||
aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs *
|
||||
sizeof(int));
|
||||
if (aparam.alias_ifs)
|
||||
{
|
||||
/* Use iface_enumerate again to get the alias
|
||||
interface indices, then send on each of
|
||||
those. */
|
||||
aparam.max_alias_ifs = aparam.num_alias_ifs;
|
||||
aparam.num_alias_ifs = 0;
|
||||
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
|
||||
for (; aparam.num_alias_ifs; aparam.num_alias_ifs--)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => i/f %d",
|
||||
param.name, daemon->addrbuff,
|
||||
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
|
||||
send_ra_alias(now,
|
||||
param.iface,
|
||||
param.name,
|
||||
NULL,
|
||||
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
|
||||
}
|
||||
free(aparam.alias_ifs);
|
||||
}
|
||||
|
||||
/* The source interface can only appear in at most
|
||||
one --bridge-interface. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return next_event;
|
||||
}
|
||||
|
||||
|
||||
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm)
|
||||
{
|
||||
struct alias_param *aparam = (struct alias_param *)parm;
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
struct dhcp_bridge *alias;
|
||||
|
||||
(void)type;
|
||||
(void)mac;
|
||||
(void)maclen;
|
||||
|
||||
if (if_indextoname(index, ifrn_name))
|
||||
for (alias = aparam->bridge->alias; alias; alias = alias->next)
|
||||
if (wildcard_matchn(alias->iface, ifrn_name, IFNAMSIZ))
|
||||
{
|
||||
if (aparam->alias_ifs && (aparam->num_alias_ifs < aparam->max_alias_ifs))
|
||||
aparam->alias_ifs[aparam->num_alias_ifs] = index;
|
||||
aparam->num_alias_ifs++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int iface_search(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
int preferred, int valid, void *vparam)
|
||||
|
||||
+4
-48
@@ -77,53 +77,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
|
||||
p = l + (unsigned char *)header;
|
||||
}
|
||||
else if (label_type == 0x80)
|
||||
return 0; /* reserved */
|
||||
else if (label_type == 0x40)
|
||||
{ /* ELT */
|
||||
unsigned int count, digs;
|
||||
|
||||
if ((l & 0x3f) != 1)
|
||||
return 0; /* we only understand bitstrings */
|
||||
|
||||
if (!isExtract)
|
||||
return 0; /* Cannot compare bitsrings */
|
||||
|
||||
count = *p++;
|
||||
if (count == 0)
|
||||
count = 256;
|
||||
digs = ((count-1)>>2)+1;
|
||||
|
||||
/* output is \[x<hex>/siz]. which is digs+7/8/9 chars */
|
||||
namelen += digs+7;
|
||||
if (count > 9)
|
||||
namelen++;
|
||||
if (count > 99)
|
||||
namelen++;
|
||||
if (namelen+1 >= MAXDNAME)
|
||||
return 0;
|
||||
|
||||
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
|
||||
return 0;
|
||||
|
||||
*cp++ = '\\';
|
||||
*cp++ = '[';
|
||||
*cp++ = 'x';
|
||||
for (j=0; j<digs; j++)
|
||||
{
|
||||
unsigned int dig;
|
||||
if (j%2 == 0)
|
||||
dig = *p >> 4;
|
||||
else
|
||||
dig = *p++ & 0x0f;
|
||||
|
||||
*cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
|
||||
}
|
||||
cp += sprintf((char *)cp, "/%d]", count);
|
||||
/* do this here to overwrite the zero char from sprintf */
|
||||
*cp++ = '.';
|
||||
}
|
||||
else
|
||||
else if (label_type == 0x00)
|
||||
{ /* label_type = 0 -> label. */
|
||||
namelen += l + 1; /* include period */
|
||||
if (namelen >= MAXDNAME)
|
||||
@@ -176,12 +130,14 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
retvalue = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isExtract)
|
||||
*cp++ = '.';
|
||||
else if (*cp != 0 && *cp++ != '.')
|
||||
retvalue = 2;
|
||||
}
|
||||
else
|
||||
return 0; /* label types 0x40 and 0x80 not supported */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -805,9 +805,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (service->type == type)
|
||||
break;
|
||||
|
||||
if (!service || !service->basename)
|
||||
return 0;
|
||||
for (; context; context = context->current)
|
||||
if (match_netid(context->filter, tagif_netid, 1) &&
|
||||
is_same_net(mess->ciaddr, context->start, context->netmask))
|
||||
break;
|
||||
|
||||
if (!service || !service->basename || !context)
|
||||
return 0;
|
||||
|
||||
clear_packet(mess, end);
|
||||
|
||||
mess->yiaddr = mess->ciaddr;
|
||||
|
||||
+1
-1
@@ -1089,7 +1089,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
{
|
||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||
|
||||
if (!address6_available(state->context, req_addr, tagif, 1))
|
||||
if (!address6_valid(state->context, req_addr, tagif, 1))
|
||||
{
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6NOTONLINK);
|
||||
|
||||
Reference in new issue
Block a user