Compare commits

..
1 Commits
Author SHA1 Message Date
Simon Kelley 9009d74652 import of dnsmasq-2.46.tar.gz 2012-01-05 17:31:14 +00:00
38 changed files with 4374 additions and 3918 deletions

No files matched your search

+86 -3
View File
@@ -2595,7 +2595,7 @@ version 2.44
Jean Wolter for finding this. Jean Wolter for finding this.
Change implementation of min_port to work even if min-port Change implementation of min_port to work even if min-port
as large. is large.
Patch to enable compilation of latest Mac OS X. Thanks to Patch to enable compilation of latest Mac OS X. Thanks to
David Gilman. David Gilman.
@@ -2603,9 +2603,92 @@ version 2.44
Update Spanish translation. Thanks to Christopher Chatham. Update Spanish translation. Thanks to Christopher Chatham.
version 2.45 version 2.45
Fix total DNS failure in release 2.43 unless --min-port Fix total DNS failure in release 2.44 unless --min-port
specified. Thanks to Steven Barth and Grant Coady for specified. Thanks to Steven Barth and Grant Coady for
bugreport. Also reject out-of-range port spec, which could bugreport. Also reject out-of-range port spec, which could
break things too: suggestion from Gilles Espinasse. break things too: suggestion from Gilles Espinasse.
version 2.46
Allow --bootp-dynamic to take a netid tag, so that it may
be selectively enabled. Thanks to Olaf Westrik for the
suggestion.
Remove ISC-leasefile reading code. This has been
deprecated for a long time, and last time I removed it, it
ended up going back by request of one user. This time,
it's gone for good; otherwise it would need to be
re-worked to support multiple domains (see below).
Support DHCP clients in multiple DNS domains. This is a
long-standing request. Clients are assigned to a domain
based in their IP address.
Add --dhcp-fqdn flag, which changes behaviour if DNS names
assigned to DHCP clients. When this is set, there must be
a domain associated with each client, and only
fully-qualified domain names are added to the DNS. The
advantage is that the only the FQDN needs to be unique,
so that two or more DHCP clients can share a hostname, as
long as they are in different domains.
Set environment variable DNSMASQ_DOMAIN when invoking
lease-change script. This may be useful information to
have now that it's variable.
Tighten up data-checking code for DNS packet
handling. Thanks to Steve Dodd who found certain illegal
packets which could crash dnsmasq. No memory overwrite was
possible, so this is not a security issue beond the DoS
potential.
Update example config dhcp option 47, the previous
suggestion generated and illegal, zero-length,
option. Thanks to Matthias Andree for finding this.
Rewrite hosts-file reading code to remove the limit of
1024 characters per line. John C Meuser found this.
Create a net-id tag with the name of the interface on
which the DHCP request was received.
Fixed minor memory leak in DBus code, thanks to Jeremy
Laine for the patch.
Emit DBus signals as the DHCP lease database
changes. Thanks to Jeremy Laine for the patch.
Allow for more that one MAC address in a dhcp-host
line. This configuration tells dnsmasq that it's OK to
abandon a DHCP lease of the fixed address to one MAC
address, if another MAC address in the dhcp-host statement
asks for an address. This is useful to give a fixed
address to a host which has two network interfaces
(say, a laptop with wired and wireless interfaces.)
It's very important to ensure that only one interface
at a time is up, since dnsmasq abandons the first lease
and re-uses the address before the leased time has
elapsed. John Gray suggested this.
Tweak the response to a DHCP request packet with a wrong
server-id when --dhcp-authoritative is set; dnsmasq now
returns a DHCPNAK, rather than silently ignoring the
packet. Thanks to Chris Marget for spotting this
improvement.
Add --cname option. This provides a limited alias
function, usable for DHCP names. Thanks to AJ Weber for
suggestions on this.
Updated contrib/webmin with latest version from Neil
Fisher.
Updated Polish translation. Thanks to Jan Psota.
Correct the text names for DHCP options 64 and 65 to be
"nis+-domain" and "nis+-servers".
Updated Spanish translation. Thanks to Chris Chatham.
Force re-reading of /etc/resolv.conf when an "interface
up" event occurs.
+19
View File
@@ -16,6 +16,14 @@ A: The high ports that dnsmasq opens are for replies from the upstream
you to specify the UDP port to be used for this purpose. If not you to specify the UDP port to be used for this purpose. If not
specified, the operating system will select an available port number specified, the operating system will select an available port number
just as it did before. just as it did before.
Second addendum: following the discovery of a security flaw in the
DNS protocol, dnsmasq from version 2.43 has changed behavior. It
now uses a new, randomly selected, port for each query. The old
default behaviour (use one port allocated by the OS) is available by
setting --query-port=0, and setting the query port to a positive
value is still works. You should think hard and know what you are
doing before using either of these options.
Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify
that? that?
@@ -324,6 +332,17 @@ A: By default, the identity of a machine is determined by using the
method for setting the client-id varies with DHCP client software, method for setting the client-id varies with DHCP client software,
dhcpcd uses the "-I" flag. Windows uses a registry setting, dhcpcd uses the "-I" flag. Windows uses a registry setting,
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
Addendum:
From version 2.46, dnsmasq has a solution to this which doesn't
involve setting client-IDs. It's possible to put more than one MAC
address in a --dhcp-host configuration. This tells dnsmasq that it
should use the specified IP for any of the specified MAC addresses,
and furthermore it gives dnsmasq permission to sumarily abandon a
lease to one of the MAC addresses if another one comes along. Note
that this will work fine only as longer as only one interface is
up at any time. There is no way for dnsmasq to enforce this
constraint: if you configure multiple MAC addresses and violate
this rule, bad things will happen.
Q: Can dnsmasq do DHCP on IP-alias interfaces? Q: Can dnsmasq do DHCP on IP-alias interfaces?
+1 -1
View File
@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2007 Simon Kelley # dnsmasq is Copyright (c) 2000-2008 Simon Kelley
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
CFLAGS = -Wall -W -O2 CFLAGS = -Wall -W -O2
OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \ OBJS = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o helper.o tftp.o log.o
Binary file not shown.
+37
View File
@@ -21,6 +21,9 @@ and avoids startup races with the provider of nameserver information.
Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
and a single object: /uk/org/thekelleys/dnsmasq and a single object: /uk/org/thekelleys/dnsmasq
1. METHODS
----------
Methods are of the form Methods are of the form
uk.org.thekelleys.<method> uk.org.thekelleys.<method>
@@ -91,4 +94,38 @@ Each call to SetServers completely replaces the set of servers
specified by via the DBus, but it leaves any servers specified via the specified by via the DBus, but it leaves any servers specified via the
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone. command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
2. SIGNALS
----------
If dnsmasq's DHCP server is active, it will send signals over DBUS whenever
the DHCP lease database changes. Think of these signals as transactions on
a database with the IP address acting as the primary key.
Signals are of the form:
uk.org.thekelleys.<signal>
and their parameters are:
STRING "192.168.1.115"
STRING "01:23:45:67:89:ab"
STRING "hostname.or.fqdn"
Available signals are:
DhcpLeaseAdded
---------------
This signal is emitted when a DHCP lease for a given IP address is created.
DhcpLeaseDeleted
----------------
This signal is emitted when a DHCP lease for a given IP address is deleted.
DhcpLeaseUpdated
----------------
This signal is emitted when a DHCP lease for a given IP address is updated.
+20 -2
View File
@@ -122,6 +122,12 @@
# 3) Provides the domain part for "expand-hosts" # 3) Provides the domain part for "expand-hosts"
#domain=thekelleys.org.uk #domain=thekelleys.org.uk
# Set a different domain for a particular subnet
#domain=wireless.thekelleys.org.uk,192.168.2.0/24
# Same idea, but range rather then subnet
#domain=reserved.thekelleys.org.uk,192.68.3.100,192.168.3.200
# Uncomment this to enable the integrated DHCP server, you need # Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and optionally # to supply the range of addresses available for lease and optionally
# a lease time. If you have more than one network, you will need to # a lease time. If you have more than one network, you will need to
@@ -157,6 +163,14 @@
# the name fred and IP address 192.168.0.60 and lease time 45 minutes # the name fred and IP address 192.168.0.60 and lease time 45 minutes
#dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m #dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m
# Give a host with ethernet address 11:22:33:44:55:66 or
# 12:34:56:78:90:12 the IP address 192.168.0.60. Dnsmasq will assume
# that these two ethernet interfaces will never be in use at the same
# time, and give the IP address to the second, even if it is already
# in use by the first. Useful for laptops with wired and wireless
# addresses.
#dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.60
# Give the machine which says its name is "bert" IP address # Give the machine which says its name is "bert" IP address
# 192.168.0.70 and an infinite lease # 192.168.0.70 and an infinite lease
#dhcp-host=bert,192.168.0.70,infinite #dhcp-host=bert,192.168.0.70,infinite
@@ -270,12 +284,12 @@
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt # http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
# adapted for a typical dnsmasq installation where the host running # adapted for a typical dnsmasq installation where the host running
# dnsmasq is also the host running samba. # dnsmasq is also the host running samba.
# you may want to uncomment them if you use Windows clients and Samba. # you may want to uncomment some or all of them if you use
# Windows clients and Samba.
#dhcp-option=19,0 # option ip-forwarding off #dhcp-option=19,0 # option ip-forwarding off
#dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s) #dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s)
#dhcp-option=45,0.0.0.0 # netbios datagram distribution server #dhcp-option=45,0.0.0.0 # netbios datagram distribution server
#dhcp-option=46,8 # netbios node type #dhcp-option=46,8 # netbios node type
#dhcp-option=47 # empty netbios scope.
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client # Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
# probably doesn't support this...... # probably doesn't support this......
@@ -458,6 +472,10 @@
#Example zeroconf #Example zeroconf
#txt-record=_http._tcp.example.com,name=value,paper=A4 #txt-record=_http._tcp.example.com,name=value,paper=A4
# Provide an alias for a "local" DNS name. Note that this _only_ works
# for targets which are names from DHCP or /etc/hosts. Give host
# "bert" another name, bertrand
#cname=bertand,bert
# For debugging purposes, log each DNS query as it passes through # For debugging purposes, log each DNS query as it passes through
# dnsmasq. # dnsmasq.
+68 -13
View File
@@ -385,6 +385,14 @@ Return a PTR DNS record.
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>] .B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
Return an NAPTR DNS record, as specified in RFC3403. Return an NAPTR DNS record, as specified in RFC3403.
.TP .TP
.B --cname=<cname>,<target>
Return a CNAME record which indicates that <cname> is really
<target>. There are significant limitations on the target; it must be a
DNS name which is known to dnsmasq from /etc/hosts (or additional
hosts files) or from DHCP. If the target does not satisfy this
criteria, the whole cname is ignored. The cname must be unique, but it
is permissable to have more than one cname pointing to the same target.
.TP
.B --interface-name=<name>,<interface> .B --interface-name=<name>,<interface>
Return a DNS record associating the name with the primary address on Return a DNS record associating the name with the primary address on
the given interface. This flag specifies an A record for the given the given interface. This flag specifies an A record for the given
@@ -465,9 +473,11 @@ hardware addresses to identify hosts by prefixing with 'id:'. Thus:
refers to the host with client identifier 01:02:03:04. It is also refers to the host with client identifier 01:02:03:04. It is also
allowed to specify the client ID as text, like this: allowed to specify the client ID as text, like this:
.B --dhcp-host=id:clientidastext,..... .B --dhcp-host=id:clientidastext,.....
The special option id:* means "ignore any client-id 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 and use MAC addresses only." This is useful when a client presents a client-id sometimes
but not others. but not others.
If a name appears in /etc/hosts, the associated address can be If a name appears in /etc/hosts, the associated address can be
allocated to a DHCP lease, but only if a allocated to a DHCP lease, but only if a
.B --dhcp-host .B --dhcp-host
@@ -478,8 +488,10 @@ instance
.B --dhcp-host=00:20:e0:3b:13:af,ignore .B --dhcp-host=00:20:e0:3b:13:af,ignore
This is This is
useful when there is another DHCP server on the network which should useful when there is another DHCP server on the network which should
be used by some machines. The net:<network-id> sets the network-id tag be used by some machines.
whenever this dhcp-host directive is in use.This can be used to
The net:<network-id> sets the network-id tag
whenever this dhcp-host directive is in use. This can be used to
selectively send DHCP options just for this host. When a host matches any selectively send DHCP options just for this host. When a host matches any
dhcp-host directive (or one implied by /etc/ethers) then the special dhcp-host directive (or one implied by /etc/ethers) then the special
network-id tag "known" is set. This allows dnsmasq to be configured to network-id tag "known" is set. This allows dnsmasq to be configured to
@@ -490,13 +502,25 @@ wildcard bytes, so for example
.B --dhcp-host=00:20:e0:3b:13:*,ignore .B --dhcp-host=00:20:e0:3b:13:*,ignore
will cause dnsmasq to ignore a range of hardware addresses. Note that will cause dnsmasq to ignore a range of hardware addresses. Note that
the "*" will need to be escaped or quoted on a command line, but not the "*" will need to be escaped or quoted on a command line, but not
in the configuration file. Hardware addresses normally match any in the configuration file.
Hardware addresses normally match any
network (ARP) type, but it is possible to restrict them to a single network (ARP) type, but it is possible to restrict them to a single
ARP type by preceding them with the ARP-type (in HEX) and "-". so ARP type by preceding them with the ARP-type (in HEX) and "-". so
.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 .B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4
will only match a will only match a
Token-Ring hardware address, since the ARP-address type for token ring Token-Ring hardware address, since the ARP-address type for token ring
is 6. is 6.
As a special case, it is possible to include more than one
hardware address. This allows an IP address to be associated with
multiple hardware addresses, and gives dnsmasq permission to abandon a
DHCP lease to one of the hardware addresses when another one asks for
a lease. Beware that this is a dangerous thing to do, it will only
work reliably if only one of the hardware addresses is active at any
time and there is no way for dnsmasq to enforce this. It is, however
useful, for instance to allocate a stable IP address to a laptop which
has both wired and wireless interfaces.
.TP .TP
.B --dhcp-hostsfile=<file> .B --dhcp-hostsfile=<file>
Read DHCP host information from the specified file. The file contains Read DHCP host information from the specified file. The file contains
@@ -693,11 +717,13 @@ port number is used for the server and the port number plus one used
for the client. Finally, two port numbers allows arbitrary for the client. Finally, two port numbers allows arbitrary
specification of both server and client ports for DHCP. specification of both server and client ports for DHCP.
.TP .TP
.B \-3, --bootp-dynamic .B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
Enable dynamic allocation of IP addresses to BOOTP clients. Use this Enable dynamic allocation of IP addresses to BOOTP clients. Use this
with care, since each address allocated to a BOOTP client is leased with care, since each address allocated to a BOOTP client is leased
forever, and therefore becomes permanently unavailable for re-use by forever, and therefore becomes permanently unavailable for re-use by
other hosts. other hosts. if this is given without tags, then it unconditionally
enables dynamic allocation. With tags, only when the tags are all
set. It may be repeated with different tag sets.
.TP .TP
.B \-5, --no-ping .B \-5, --no-ping
By default, the DHCP server will attempt to ensure that an address in By default, the DHCP server will attempt to ensure that an address in
@@ -723,18 +749,22 @@ removed in a future release.
.TP .TP
.B \-6 --dhcp-script=<path> .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, the
binary specified by this option is run. The arguments to the process executable specified by this option is run. The arguments to the process
are "add", "old" or "del", the MAC are "add", "old" or "del", the MAC
address of the host (or "<null>"), the IP address, and the hostname, address of the host, the IP address, and the hostname,
if known. "add" means a lease has been created, "del" means it has if known. "add" means a lease has been created, "del" means it has
been destroyed, "old" is a notification of an existing lease when been destroyed, "old" is a notification of an existing lease when
dnsmasq starts or a change to MAC address or hostname of an existing dnsmasq starts or a change to MAC address or hostname of an existing
lease (also, lease length or expiry and client-id, if leasefile-ro is set). lease (also, lease length or expiry and client-id, if leasefile-ro is set).
The process is run as root (assuming that dnsmasq was originally run as If the MAC address is from a network type other than ethernet,
it will have the network type prepended, eg "06-01:23:45:67:89:ab" for
token ring. The process is run as root (assuming that dnsmasq was originally run as
root) even if dnsmasq is configured to change UID to an unprivileged user. root) even if dnsmasq is configured to change UID to an unprivileged user.
The environment is inherited from the invoker of dnsmasq, and if the The environment is inherited from the invoker of dnsmasq, and if the
host provided a client-id, this is stored in the environment variable host provided a client-id, this is stored in the environment variable
DNSMASQ_CLIENT_ID. If the client provides vendor-class or user-class DNSMASQ_CLIENT_ID. If the fully-qualified domain name of the host is
known, the domain part is stored in DNSMASQ_DOMAIN.
If the client provides vendor-class or user-class
information, these are provided in DNSMASQ_VENDOR_CLASS and information, these are provided in DNSMASQ_VENDOR_CLASS and
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
"add" actions or "old" actions when a host resumes an existing lease, "add" actions or "old" actions when a host resumes an existing lease,
@@ -785,8 +815,9 @@ as if they had arrived at <interface>. This option is only available
on BSD platforms, and is necessary when using "old style" bridging, since on BSD platforms, and is necessary when using "old style" bridging, since
packets arrive at tap interfaces which don't have an IP address. packets arrive at tap interfaces which don't have an IP address.
.TP .TP
.B \-s, --domain=<domain> .B \-s, --domain=<domain>[,<address range>]
Specifies the domain for the DHCP server. This has two effects; Specifies DNS domains for the DHCP server. Domains may be be given
unconditionally (without the IP range) or for limited IP ranges. This has two effects;
firstly it causes the DHCP server to return the domain to any hosts firstly it causes the DHCP server to return the domain to any hosts
which request it, and secondly it sets the domain which it is legal which request it, and secondly it sets the domain which it is legal
for DHCP-configured hosts to claim. The intention is to constrain for DHCP-configured hosts to claim. The intention is to constrain
@@ -803,7 +834,28 @@ and have a machine whose DHCP hostname is "laptop". The IP address for that mach
.B dnsmasq .B dnsmasq
both as "laptop" and "laptop.thekelleys.org.uk". If the domain is both as "laptop" and "laptop.thekelleys.org.uk". If the domain is
given as "#" then the domain is read from the first "search" directive given as "#" then the domain is read from the first "search" directive
in /etc/resolv.conf (or equivalent). in /etc/resolv.conf (or equivalent). The address range can be of the form
<ip address>,<ip address> or <ip address>/<netmask> or just a single
<ip address>. See
.B --dhcp-fqdn
which can change the behaviour of dnsmasq with domains.
.TP
.B --dhcp-fqdn
In the default mode, dnsmasq inserts the unqualified names of
DHCP clients into the DNS. For this reason, the names must be unique,
even if two clients which have the same name are in different
domains. If a second DHCP client appears which has the same name as an
existing client, the name is transfered to the new client. If
.B --dhcp-fqdn
is set, this behaviour changes: the unqualified name is no longer
put in the DNS, only the qualified name. Two DHCP clients with the
same name may both keep the name, provided that the domain part is
different (ie the fully qualified names differ.) To ensure that all
names have a domain part, there must be at least
.B --domain
without an address specified when
.B --dhcp-fqdn
is set.
.TP .TP
.B --enable-tftp .B --enable-tftp
Enable the TFTP server function. This is deliberately limited to that Enable the TFTP server function. This is deliberately limited to that
@@ -1006,6 +1058,9 @@ collects a set of valid network-id tags, one from the
.B dhcp-range .B dhcp-range
used to allocate the address, one from any matching used to allocate the address, one from any matching
.B dhcp-host .B dhcp-host
(and "known" if a dhcp-host matches)
the tag "bootp" for BOOTP requests, a tag whose name is the
name if the interface on which the request arrived,
and possibly many from matching vendor classes and user and possibly many from matching vendor classes and user
classes sent by the DHCP client. Any classes sent by the DHCP client. Any
.B dhcp-option .B dhcp-option
+80 -27
View File
@@ -414,8 +414,15 @@ Retornar un r
.B --naptr-record=<nombre>,<orden>,<preferencia>,<opciones>,<servicio>,<regexp>[,<remplazo>] .B --naptr-record=<nombre>,<orden>,<preferencia>,<opciones>,<servicio>,<regexp>[,<remplazo>]
Retornar un récord DNS NAPTR, como especificado en RFC3403. Retornar un récord DNS NAPTR, como especificado en RFC3403.
.TP .TP
.B --cname=<cname>,<target>
Retornar un expediente CNAME que indica que <cname> es realmente <target>. Hay
limitaciones significativas en el target. Debe ser un nombre DNS que le es conocido
a dnsmasq desde /etc/hosts (o archivos hosts adicionales) o de DHCP. Si el target
no satisface este criterio, el cname entero es ignorado. El cname debe ser único,
pero es permisible tener más de un cname indicando el mismo target.
.TP
.B --interface-name=<nombre>,<interface> .B --interface-name=<nombre>,<interface>
Retornar un récord DNS, asociando el nombre con la dirección primaria Retornar un expediente DNS, asociando el nombre con la dirección primaria
en la interface brindada. Esta opción especifica un expediente tipo A en la interface brindada. Esta opción especifica un expediente tipo A
para el nombre brindado de la misma forma que una línea de /etc/hosts, para el nombre brindado de la misma forma que una línea de /etc/hosts,
excepto que la dirección no es constante y es en vez tomada de la excepto que la dirección no es constante y es en vez tomada de la
@@ -500,9 +507,11 @@ hardware para identificar hosts prefijando 'id:'. O sea que:
se refiere al host con identificador de cliente 01:02:03:04. se refiere al host con identificador de cliente 01:02:03:04.
También se permite especificar el ID de cliente como texto, así: También se permite especificar el ID de cliente como texto, así:
.B --dhcp-host=id:iddeclientecomotexto,..... .B --dhcp-host=id:iddeclientecomotexto,.....
La opción especial id:* significa "ignorar cualquier ID de cliente La opción especial id:* significa "ignorar cualquier ID de cliente
y usar solamente direcciones MAC." Esto es útil cuando un cliente y usar solamente direcciones MAC." Esto es útil cuando un cliente
presenta un ID de cliente algunas veces pero otras no. presenta un ID de cliente algunas veces pero otras no.
Si un nombre aparece en /etc/hosts, la dirección asociada puede Si un nombre aparece en /etc/hosts, la dirección asociada puede
ser alocada a un arriendo DHCP, pero solo si existe una opción ser alocada a un arriendo DHCP, pero solo si existe una opción
.B --dhcp-host .B --dhcp-host
@@ -511,14 +520,16 @@ le dice a dnsmasq que no debe ofrecer jam
una máquina. La máquina puede ser especificada por dirección de una máquina. La máquina puede ser especificada por dirección de
hardware, ID de cliente, o nombre de host, por ejemplo: hardware, ID de cliente, o nombre de host, por ejemplo:
.B --dhcp-host=00:20:e0:3b:13:af,ignore .B --dhcp-host=00:20:e0:3b:13:af,ignore
Esto es útil cuando hay otro servidor DHCP en la red para ser Esto es útil cuando hay otro servidor DHCP en la red que debe ser
usado por algúnas máquinas. El net:<network-id> fija la etiqueta usado por algúnas máquinas.
network-id cuando sea que esta directiva dhcp-host está en uso.
Esto puede ser usado para enviar selectivamente opciones DHCP El net:<network-id> fija la etiqueta network-id cuando sea que
a este host. Cuando un host coincide con cualquier directiva esta directiva dhcp-host está en uso. Esto puede ser usado para
dhcp-host (o una implicada por /etc/ethers) entonces la etiqueta enviar selectivamente opciones DHCP a este host. Cuando un host
network-id especial "known" es fijada. Esto permite que dnsmasq sea coincide con cualquier directiva dhcp-host (o una implicada por
configurado para ignorar pedidos desde máquinas desconocidas usando /etc/ethers) entonces la etiqueta network-id especial "known" es
fijada. Esto permite que dnsmasq sea configurado para ignorar
pedidos desde máquinas desconocidas usando
.B --dhcp-ignore=#known .B --dhcp-ignore=#known
Direcciones ethernet (pero no client-ids) pueden tener bytes Direcciones ethernet (pero no client-ids) pueden tener bytes
comodínes, así que por ejemplo comodínes, así que por ejemplo
@@ -526,12 +537,23 @@ comod
causará que dnsmasq ignore un rango de direcciones ethernet. Nótese causará que dnsmasq ignore un rango de direcciones ethernet. Nótese
que el "*" necesitará ser escapado o escrito entre comillas en la que el "*" necesitará ser escapado o escrito entre comillas en la
línea de comandos, pero no en el archivo de configuración. línea de comandos, pero no en el archivo de configuración.
Direcciones de hardware normalmente coinciden con cualquier Direcciones de hardware normalmente coinciden con cualquier
tipo de red (ARP), pero es posible restringirlas a un tipo ARP tipo de red (ARP), pero es posible restringirlas a un tipo ARP
singular precediendolo con el tipo ARP (en HEX) y "-". Así que singular precediendolo con el tipo ARP (en HEX) y "-". Así que
.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 .B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4
solo coincidiría con una dirección de hardware Token-Ring, dado que solo coincidiría con una dirección de hardware Token-Ring, dado que
el tipo ARP para Token-Ring es 6. el tipo ARP para Token-Ring es 6.
Como caso especial, es posible incluir más de una dirección de
hardware. Esto permite que una dirección IP sea asociada con
direcciones de hardware múltiples, y le brinda a dnsmasq permiso
para abandonar un arriendo DHCP a una de las direcciones de hardware
cuando otra pide un arriendo. Nótese que esto es algo peligroso,
sólo funcionará dependiblemente si una de las direcciones de hardware
está activa en cualquier momento y dnsmasq no tiene forma de enforzar
esto. Pero es útil, por ejemplo, para alocar una dirección IP estable
a una laptop que tiene interfaces alámbricas e inalámbricas.
.TP .TP
.B --dhcp-hostsfile=<archivo> .B --dhcp-hostsfile=<archivo>
Leer información host DHCP desde el archivo especificado. El archivo contiene información de un host por línea. El formato de una línea es igual que texto hacia la derecha de '=' en --dhcp-host. La ventaja de almacenar información host DHCP en este archivo es que puede ser cambiada sin tener que reiniciar dnsmasq. El archivo será re-leído cuando dnsmasq recibe un SIGHUP. Leer información host DHCP desde el archivo especificado. El archivo contiene información de un host por línea. El formato de una línea es igual que texto hacia la derecha de '=' en --dhcp-host. La ventaja de almacenar información host DHCP en este archivo es que puede ser cambiada sin tener que reiniciar dnsmasq. El archivo será re-leído cuando dnsmasq recibe un SIGHUP.
@@ -731,11 +753,14 @@ es usado para el servidor y el n
para el cliente. Finalmente, dos números permiten que se especifiquen para el cliente. Finalmente, dos números permiten que se especifiquen
ambos los puertos de servidor y cliente para DHCP. ambos los puertos de servidor y cliente para DHCP.
.TP .TP
.B \-3, --bootp-dynamic .B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
Habilitar alocación dinámica de direcciones IP a clientes BOOTP. Usar Habilitar alocación dinámica de direcciones IP a clientes BOOTP. Usar
esto con cuidado, ya que cada dirección alocada a un cliente BOOTP esto con cuidado, ya que cada dirección alocada a un cliente BOOTP
es arrendada para siempre, y consecuentemente queda no-disponible es arrendada para siempre, y consecuentemente queda no-disponible
para re-uso por otros hosts. para re-uso por otros hosts. Si esto es brindado sin etiquetas,
entonces incondicionalmente habilita alocación dinámica. Con
etiquetas, solo cuando todas las etiquetas están fijadas. Puede
ser repetido con diferentes juegos de etiquetas.
.TP .TP
.B \-5, --no-ping .B \-5, --no-ping
Por predetermindado, el servidor DHCP tratará de asegurarse que una Por predetermindado, el servidor DHCP tratará de asegurarse que una
@@ -763,20 +788,24 @@ en instalaciones nuevas, y ser
.TP .TP
.B \-6 --dhcp-script=<path> .B \-6 --dhcp-script=<path>
Cuando un arriendo DHCP nuevo es creado, o uno viejo es Cuando un arriendo DHCP nuevo es creado, o uno viejo es
destruido, el binario especificado por esta opción es ejecutado. destruido, el ejecutable especificado por esta opción es ejecutado.
Los argumentos para el binario son "add", "old", o "del", la dirección Los argumentos para el binario son "add", "old", o "del", la dirección
MAC del host (o "<null>"), la dirección IP, y el hostname, si es MAC del host, la dirección IP, y el hostname, si es
conocido. "add" significa que un arriendo ha sido creado, "del" que conocido. "add" significa que un arriendo ha sido creado, "del" que
ha sido destruido, y "old" es una notificación de un arriendo existente ha sido destruido, y "old" es una notificación de un arriendo existente
cuando dnsmasq inicia o un cambio a una MAC o nombre host de un arriendo cuando dnsmasq inicia o un cambio a una MAC o nombre host de un arriendo
existente (también, tiempo de arriendo o vencimiento y client-id, si existente (también, tiempo de arriendo o vencimiento y client-id, si
leasefile-ro está fijado). El proceso es ejecutado como root (asumiendo leasefile-ro está fijado). Si la dirección MAC es de un tipo de red
que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq está que no es ethernet, tendrá el tipo de red precolocado, por ejemplo
configurado para cambiar su UID a un usuario sin privilegios. "06-01:23:45:67:89:ab" para token ring. El proceso es ejecutado como root
(asumiendo que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq
está configurado para cambiar su UID a un usuario sin privilegios.
El ambiente es heredado del usuario que ha invocado a dnsmasq, y si el El ambiente es heredado del usuario que ha invocado a dnsmasq, y si el
host brindó un client-id, es almacenado en la variable de ambiente host brindó un client-id, es almacenado en la variable de ambiente
DNSMASQ_CLIENT_ID. Si el cliente brinda información de clase de vendedor DNSMASQ_CLIENT_ID. Si el dominio completamente calificado del host
o usuario, estos son brindados en las variables DNSMASQ_VENDOR_CLASS y es conocido, la parte de dominio es almacenada en DNSMASQ_DOMAIN. Si
el cliente brinda información de clase de vendedoro usuario,
estos son brindados en las variables DNSMASQ_VENDOR_CLASS y
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add" DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add"
y "old" cuando un host resume un arriendo existente, dado a que estos y "old" cuando un host resume un arriendo existente, dado a que estos
datos no son almacenados en la base de datos de arriendos de dnsmasq. datos no son almacenados en la base de datos de arriendos de dnsmasq.
@@ -829,11 +858,12 @@ est
puentes "estilo viejo", ya que los paquetes llegan a interfaces tap que no puentes "estilo viejo", ya que los paquetes llegan a interfaces tap que no
tienen una dirección IP. tienen una dirección IP.
.TP .TP
.B \-s, --domain=<dominio> .B \-s, --domain=<dominio>[,<rango de IPs>]
Especifica el dominio para el servidor DHCP. Esto tiene dos efectos: Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
Primeramente, causa que el servidor DHCP le devuelva el dominio a brindados incondicionalmente (sin el rango de IPs) o para rangos limitados. Esto
cualquier host que lo pida. Segundamente, fija el dominio para el cual tiene dos efectos: Primeramente, causa que el servidor DHCP le devuelva el
es legal para hosts configurados mediante DHCP reclamar. La intención es dominio a cualquier host que lo pida. Segundamente, fija el dominio para el
cual es legal para hosts configurados mediante DHCP reclamar. La intención es
restringir nombres de host para que un host no-confiado en la LAN no restringir nombres de host para que un host no-confiado en la LAN no
pueda proclamar su nombre vía DHCP, como por ejemplo "microsoft.com" y pueda proclamar su nombre vía DHCP, como por ejemplo "microsoft.com" y
capturar tráfico no destinado a ella. Si ningún sufijo de dominio es capturar tráfico no destinado a ella. Si ningún sufijo de dominio es
@@ -850,7 +880,28 @@ de esa m
.B dnsmasq .B dnsmasq
como "laptop" y "laptop.thekelleys.org.uk". Si el dominio es brindado como "laptop" y "laptop.thekelleys.org.uk". Si el dominio es brindado
como "#" entonces el dominio es leido desde la primera directiva search como "#" entonces el dominio es leido desde la primera directiva search
en /etc/resolv.conf (o equivalente). en /etc/resolv.conf (o equivalente). El rango de direcciones puede ser
<dirección IP>,<dirección IP> or <dirección IP>/<máscara de subred>. Ver
.B --dhcp-fqdn el cual puede cambiar el comportamiento de dnsmasq con
dominios.
.TP
.B --dhcp-fqdn
En el modo predeterminado, dnsmasq pone los nombres no-calificados
de clientes DHCP en el DNS. Por esta razón, los nombres deben ser únicos,
aún si dos clientes que tienen el mismo nombre están en dominios
diferentes. Si un segundo cliente DHCP aparece el cual tiene el mismo
nombre que un cliente existente, el nombre es transferido al cliente nuevo. Si
.B --dhcp-fqdn
está fijado, este comportamiento cambia: El nombre no-calificado
no es puesto en el DNS, solo el nombre calificado. Dos clientes DHCP con
el mismo nombre pueden ambos quedarse con el nombre, con tal que la parte
de dominio sea diferente (o sea que los nombres completamente calificados
difieran). Para asegurar que todos los nombres tengan una parte de dominio,
debe haber al menos
.B --domain
sin una dirección especificada cuando
.B --dhcp-fqdn
está fijado.
.TP .TP
.B --enable-tftp .B --enable-tftp
Habilitar la función de servidor TFTP. Esto está deliberadamente limitado Habilitar la función de servidor TFTP. Esto está deliberadamente limitado
@@ -1056,9 +1107,11 @@ una del
.B dhcp-range .B dhcp-range
usado para alocar la dirección, una de cualquier usado para alocar la dirección, una de cualquier
.B dhcp-host .B dhcp-host
que coincida, y posiblemente muchas de clases de vendedor y usuario que coincida (y "known" si un dhcp-host coincide), la etiqueta "bootp"
que coinicdan que hayan sido enviadas por el cliente DHCP. para pedidos BOOTP, una etiqueta cuyo nombre es el nombre de la
Cualquier opción interface donde llegó el pedido, y posiblemente muchas de clases
de vendedor y usuario que coincidan que hayan sido enviadas por
el cliente DHCP. Cualquier opción
.B dhcp-option .B dhcp-option
que tenga etiquetas network-id será usada en preferencia de una opción que tenga etiquetas network-id será usada en preferencia de una opción
.B dhcp-option, .B dhcp-option,
+325 -329
View File
File diff suppressed because it is too large. Load diff
+318 -302
View File
File diff suppressed because it is too large. Load diff
+325 -329
View File
File diff suppressed because it is too large. Load diff
+318 -302
View File
File diff suppressed because it is too large. Load diff
+324 -311
View File
File diff suppressed because it is too large. Load diff
+325 -329
View File
File diff suppressed because it is too large. Load diff
+315 -302
View File
File diff suppressed because it is too large. Load diff
+301 -305
View File
File diff suppressed because it is too large. Load diff
+325 -329
View File
File diff suppressed because it is too large. Load diff
+315 -302
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
+205 -109
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -642,150 +642,224 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
unsigned short flags, int index, int addr_dup) unsigned short flags, int index, int addr_dup)
{ {
struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6)); struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6));
int i; int i, nameexists = 0;
struct cname *a;
/* Remove duplicates in hosts files. */ /* Remove duplicates in hosts files. */
if (lookup && (lookup->flags & F_HOSTS) && if (lookup && (lookup->flags & F_HOSTS))
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
free(cache);
else
{ {
/* Ensure there is only one address -> name mapping (first one trumps) nameexists = 1;
We do this by steam here, first we see if the address is the same as if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
the last one we saw, which eliminates most in the case of an ad-block {
file with thousands of entries for the same address. free(cache);
Then we search and bail at the first matching address that came from return;
a HOSTS file. Since the first host entry gets reverse, we know }
then that it must exist without searching exhaustively for it. */ }
if (addr_dup) /* Ensure there is only one address -> name mapping (first one trumps)
flags &= ~F_REVERSE; We do this by steam here, first we see if the address is the same as
else the last one we saw, which eliminates most in the case of an ad-block
for (i=0; i<hash_size; i++) file with thousands of entries for the same address.
{ Then we search and bail at the first matching address that came from
for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next) a HOSTS file. Since the first host entry gets reverse, we know
if ((lookup->flags & F_HOSTS) && then that it must exist without searching exhaustively for it. */
(lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
memcmp(&lookup->addr.addr, addr, addrlen) == 0) if (addr_dup)
{ flags &= ~F_REVERSE;
flags &= ~F_REVERSE; else
break; for (i=0; i<hash_size; i++)
} {
if (lookup) for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next)
if ((lookup->flags & F_HOSTS) &&
(lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
{
flags &= ~F_REVERSE;
break; break;
} }
if (lookup)
break;
}
cache->flags = flags;
cache->uid = index;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache);
/* don't need to do alias stuff for second and subsequent addresses. */
if (!nameexists)
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(cache->name.sname, a->target) &&
(lookup = whine_malloc(sizeof(struct crec) + strlen(a->alias)+1-SMALLDNAME)))
{
lookup->flags = F_FORWARD | F_IMMORTAL | F_HOSTS | F_CNAME;
strcpy(lookup->name.sname, a->alias);
lookup->addr.cname.cache = cache;
lookup->addr.cname.uid = index;
cache_hash(lookup);
}
}
static int eatspace(FILE *f)
{
int c, nl = 0;
while (1)
{
if ((c = getc(f)) == '#')
while (c != '\n' && c != EOF)
c = getc(f);
cache->flags = flags; if (c == EOF)
cache->uid = index; return 1;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache); if (!isspace(c))
{
ungetc(c, f);
return nl;
}
if (c == '\n')
nl = 1;
}
}
static int gettok(FILE *f, char *token)
{
int c, count = 0;
while (1)
{
if ((c = getc(f)) == EOF)
return (count == 0) ? EOF : 1;
if (isspace(c) || c == '#')
{
ungetc(c, f);
return eatspace(f);
}
if (count < (MAXDNAME - 1))
{
token[count++] = c;
token[count] = 0;
}
} }
} }
static int read_hostsfile(char *filename, int opts, char *buff, char *domain_suffix, int index, int cache_size) static int read_hostsfile(char *filename, int index, int cache_size)
{ {
FILE *f = fopen(filename, "r"); FILE *f = fopen(filename, "r");
char *line; char *token = daemon->namebuff, *domain_suffix = NULL;
int addr_count = 0, name_count = cache_size, lineno = 0; int addr_count = 0, name_count = cache_size, lineno = 0;
unsigned short flags, saved_flags = 0; unsigned short flags = 0, saved_flags = 0;
struct all_addr addr, saved_addr; struct all_addr addr, saved_addr;
int atnl, addrlen = 0, addr_dup;
if (!f) if (!f)
{ {
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno)); my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
return 0; return 0;
} }
while ((line = fgets(buff, MAXDNAME, f))) eatspace(f);
while ((atnl = gettok(f, token)) != EOF)
{ {
char *token = strtok(line, " \t\n\r"); addr_dup = 0;
int addrlen, addr_dup = 0;
lineno++; lineno++;
if (!token || (*token == '#'))
continue;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (inet_pton(AF_INET, token, &addr) > 0) if (inet_pton(AF_INET, token, &addr) > 0)
{ {
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
addrlen = INADDRSZ; addrlen = INADDRSZ;
domain_suffix = get_domain(addr.addr.addr4);
} }
else if (inet_pton(AF_INET6, token, &addr) > 0) else if (inet_pton(AF_INET6, token, &addr) > 0)
{ {
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
addrlen = IN6ADDRSZ; addrlen = IN6ADDRSZ;
domain_suffix = daemon->domain_suffix;
} }
#else #else
if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1) if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
{ {
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
addrlen = INADDRSZ; addrlen = INADDRSZ;
domain_suffix = get_domain(addr.addr.addr4);
} }
#endif #endif
else else
{ {
my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno); my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
while (atnl == 0)
atnl = gettok(f, token);
continue; continue;
} }
if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
addr_dup = 1;
else
{
saved_flags = flags;
saved_addr = addr;
}
addr_count++;
/* rehash every 1000 names. */
if ((name_count - cache_size) > 1000)
{
rehash(name_count);
cache_size = name_count;
}
while (atnl == 0)
{
struct crec *cache;
int fqdn;
if ((atnl = gettok(f, token)) == EOF)
break;
fqdn = !!strchr(token, '.');
if (canonicalise(token))
{
/* If set, add a version of the name with a default domain appended */
if ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn &&
(cache = whine_malloc(sizeof(struct crec) +
strlen(token)+2+strlen(domain_suffix)-SMALLDNAME)))
{
strcpy(cache->name.sname, token);
strcat(cache->name.sname, ".");
strcat(cache->name.sname, domain_suffix);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
addr_dup = 1;
name_count++;
}
if ((cache = whine_malloc(sizeof(struct crec) + strlen(token)+1-SMALLDNAME)))
{
strcpy(cache->name.sname, token);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
name_count++;
}
}
else
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
}
}
if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
addr_dup = 1;
else
{
saved_flags = flags;
saved_addr = addr;
}
addr_count++;
/* rehash every 1000 names. */
if ((name_count - cache_size) > 1000)
{
rehash(name_count);
cache_size = name_count;
}
while ((token = strtok(NULL, " \t\n\r")) && (*token != '#'))
{
struct crec *cache;
int fqdn = !!strchr(token, '.');
if (canonicalise(token))
{
/* If set, add a version of the name with a default domain appended */
if ((opts & OPT_EXPAND) && domain_suffix && !fqdn &&
(cache = whine_malloc(sizeof(struct crec) +
strlen(token)+2+strlen(domain_suffix)-SMALLDNAME)))
{
strcpy(cache->name.sname, token);
strcat(cache->name.sname, ".");
strcat(cache->name.sname, domain_suffix);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
addr_dup = 1;
name_count++;
}
if ((cache = whine_malloc(sizeof(struct crec) + strlen(token)+1-SMALLDNAME)))
{
strcpy(cache->name.sname, token);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
name_count++;
}
}
else
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
}
}
fclose(f); fclose(f);
rehash(name_count); rehash(name_count);
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
return name_count; return name_count;
} }
void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *addn_hosts) void cache_reload(struct hostsfile *addn_hosts)
{ {
struct crec *cache, **up, *tmp; struct crec *cache, **up, *tmp;
int i, total_size = daemon->cachesize; int i, total_size = daemon->cachesize;
@@ -815,18 +889,18 @@ void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *a
up = &cache->hash_next; up = &cache->hash_next;
} }
if ((opts & OPT_NO_HOSTS) && !addn_hosts) if ((daemon->options & OPT_NO_HOSTS) && !addn_hosts)
{ {
if (daemon->cachesize > 0) if (daemon->cachesize > 0)
my_syslog(LOG_INFO, _("cleared cache")); my_syslog(LOG_INFO, _("cleared cache"));
return; return;
} }
if (!(opts & OPT_NO_HOSTS)) if (!(daemon->options & OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, opts, buff, domain_suffix, 0, total_size); total_size = read_hostsfile(HOSTSFILE, 0, total_size);
while (addn_hosts) while (addn_hosts)
{ {
total_size = read_hostsfile(addn_hosts->fname, opts, buff, domain_suffix, addn_hosts->index, total_size); total_size = read_hostsfile(addn_hosts->fname, addn_hosts->index, total_size);
addn_hosts = addn_hosts->next; addn_hosts = addn_hosts->next;
} }
} }
@@ -851,13 +925,11 @@ void cache_unhash_dhcp(void)
void cache_add_dhcp_entry(char *host_name, void cache_add_dhcp_entry(char *host_name,
struct in_addr *host_address, time_t ttd) struct in_addr *host_address, time_t ttd)
{ {
struct crec *crec = NULL; struct crec *crec = NULL, *aliasc;
unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE; unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
int in_hosts = 0; int in_hosts = 0;
struct cname *a;
if (!host_name)
return;
while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME))) while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME)))
{ {
/* check all addresses associated with name */ /* check all addresses associated with name */
@@ -911,10 +983,34 @@ void cache_add_dhcp_entry(char *host_name,
crec->ttd = ttd; crec->ttd = ttd;
crec->addr.addr.addr.addr4 = *host_address; crec->addr.addr.addr.addr4 = *host_address;
crec->name.namep = host_name; crec->name.namep = host_name;
crec->uid = uid++;
cache_hash(crec); cache_hash(crec);
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(host_name, a->target))
{
if ((aliasc = dhcp_spare))
dhcp_spare = dhcp_spare->next;
else /* need new one */
aliasc = whine_malloc(sizeof(struct crec));
if (aliasc)
{
aliasc->flags = F_FORWARD | F_DHCP | F_CNAME;
if (ttd == 0)
aliasc->flags |= F_IMMORTAL;
else
aliasc->ttd = ttd;
aliasc->name.namep = a->alias;
aliasc->addr.cname.cache = crec;
aliasc->addr.cname.uid = crec->uid;
cache_hash(aliasc);
}
}
} }
} }
void dump_cache(time_t now) void dump_cache(time_t now)
{ {
struct server *serv, *serv1; struct server *serv, *serv1;
+2 -14
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define VERSION "2.45" #define VERSION "2.46"
#define FTABSIZ 150 /* max number of outstanding requests (default) */ #define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */ #define MAX_PROCS 20 /* max no children for TCP requests */
@@ -115,10 +115,6 @@ HAVE_BROKEN_RTC
NOTE: when enabling or disabling this, be sure to delete any old NOTE: when enabling or disabling this, be sure to delete any old
leases file, otherwise dnsmasq may get very confused. leases file, otherwise dnsmasq may get very confused.
HAVE_ISC_READER
define this to include the old ISC dhcpcd integration. Note that you cannot
set both HAVE_ISC_READER and HAVE_BROKEN_RTC.
HAVE_TFTP HAVE_TFTP
define this to get dnsmasq's built-in TFTP server. define this to get dnsmasq's built-in TFTP server.
@@ -141,9 +137,6 @@ HAVE_BSD_BRIDGE
Define this to enable the --bridge-interface option, useful on some Define this to enable the --bridge-interface option, useful on some
BSD systems. BSD systems.
HAVE_LARGFILE
Define this if the C library supports large (>2GB) files probably true everywhere
except some builds of uclibc
NOTES: NOTES:
For Linux you should define For Linux you should define
@@ -166,13 +159,8 @@ NOTES:
/* platform independent options- uncomment to enable */ /* platform independent options- uncomment to enable */
#define HAVE_TFTP #define HAVE_TFTP
/* #define HAVE_BROKEN_RTC */ /* #define HAVE_BROKEN_RTC */
/* #define HAVE_ISC_READER */
/* #define HAVE_DBUS */ /* #define HAVE_DBUS */
#if defined(HAVE_BROKEN_RTC) && defined(HAVE_ISC_READER)
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
#endif
/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */ /* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
#ifdef NO_TFTP #ifdef NO_TFTP
#undef HAVE_TFTP #undef HAVE_TFTP
+37 -2
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -283,7 +283,10 @@ char *dbus_init(void)
daemon->dbus = connection; daemon->dbus = connection;
if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up"))) if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
dbus_connection_send(connection, message, NULL); {
dbus_connection_send(connection, message, NULL);
dbus_message_unref(message);
}
return NULL; return NULL;
} }
@@ -352,4 +355,36 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
} }
} }
void emit_dbus_signal(int action, char *mac, char *hostname, char *addr)
{
DBusConnection *connection = (DBusConnection *)daemon->dbus;
DBusMessage* message = NULL;
DBusMessageIter args;
const char *action_str;
if (!connection)
return;
if (action == ACTION_DEL)
action_str = "DhcpLeaseDeleted";
else if (action == ACTION_ADD)
action_str = "DhcpLeaseAdded";
else if (action == ACTION_OLD)
action_str = "DhcpLeaseUpdated";
else
return;
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
return;
dbus_message_iter_init_append(message, &args);
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &addr) &&
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) &&
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname))
dbus_connection_send(connection, message, NULL);
dbus_message_unref(message);
}
#endif #endif
+70 -39
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -635,6 +635,19 @@ static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *
return 0; return 0;
} }
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
{
struct hwaddr_config *conf_addr;
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
if (conf_addr->wildcard_mask == 0 &&
conf_addr->hwaddr_len == len &&
(conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
return 1;
return 0;
}
struct dhcp_config *find_config(struct dhcp_config *configs, struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context, struct dhcp_context *context,
@@ -643,7 +656,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
int hw_type, char *hostname) int hw_type, char *hostname)
{ {
struct dhcp_config *config; struct dhcp_config *config;
struct hwaddr_config *conf_addr;
if (clid) if (clid)
for (config = configs; config; config = config->next) for (config = configs; config; config = config->next)
if (config->flags & CONFIG_CLID) if (config->flags & CONFIG_CLID)
@@ -663,11 +677,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
for (config = configs; config; config = config->next) for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_HWADDR) && if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
config->wildcard_mask == 0 &&
config->hwaddr_len == hw_len &&
(config->hwaddr_type == hw_type || config->hwaddr_type == 0) &&
memcmp(config->hwaddr, hwaddr, hw_len) == 0 &&
is_addr_in_context(context, config)) is_addr_in_context(context, config))
return config; return config;
@@ -679,14 +689,14 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
return config; return config;
for (config = configs; config; config = config->next) for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_HWADDR) && for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
config->wildcard_mask != 0 && if (conf_addr->wildcard_mask != 0 &&
config->hwaddr_len == hw_len && conf_addr->hwaddr_len == hw_len &&
(config->hwaddr_type == hw_type || config->hwaddr_type == 0) && (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
is_addr_in_context(context, config) && is_addr_in_context(context, config) &&
memcmp_masked(config->hwaddr, hwaddr, hw_len, config->wildcard_mask)) memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask))
return config; return config;
return NULL; return NULL;
} }
@@ -720,6 +730,7 @@ void dhcp_read_ethers(void)
/* cannot have a clid */ /* cannot have a clid */
if (config->flags & CONFIG_NAME) if (config->flags & CONFIG_NAME)
free(config->hostname); free(config->hostname);
free(config->hwaddr);
free(config); free(config);
} }
else else
@@ -766,7 +777,7 @@ void dhcp_read_ethers(void)
} }
else else
{ {
if (!canonicalise(ip) || strip_hostname(ip)) if (!canonicalise(ip))
{ {
my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno); my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
continue; continue;
@@ -782,19 +793,24 @@ void dhcp_read_ethers(void)
if (!config) if (!config)
{ {
for (config = daemon->dhcp_conf; config; config = config->next) for (config = daemon->dhcp_conf; config; config = config->next)
if ((config->flags & CONFIG_HWADDR) && {
config->wildcard_mask == 0 && struct hwaddr_config *conf_addr = config->hwaddr;
config->hwaddr_len == ETHER_ADDR_LEN && if (conf_addr &&
(config->hwaddr_type == ARPHRD_ETHER || config->hwaddr_type == 0) && conf_addr->next == NULL &&
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0) conf_addr->wildcard_mask == 0 &&
break; conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
(conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
break;
}
if (!config) if (!config)
{ {
if (!(config = whine_malloc(sizeof(struct dhcp_config)))) if (!(config = whine_malloc(sizeof(struct dhcp_config))))
continue; continue;
config->flags = CONFIG_FROM_ETHERS; config->flags = CONFIG_FROM_ETHERS;
config->wildcard_mask = 0; config->hwaddr = NULL;
config->domain = NULL;
config->next = daemon->dhcp_conf; config->next = daemon->dhcp_conf;
daemon->dhcp_conf = config; daemon->dhcp_conf = config;
} }
@@ -813,10 +829,17 @@ void dhcp_read_ethers(void)
config->addr = addr; config->addr = addr;
} }
config->flags |= CONFIG_HWADDR | CONFIG_NOCLID; config->flags |= CONFIG_NOCLID;
memcpy(config->hwaddr, hwaddr, ETHER_ADDR_LEN); if (!config->hwaddr)
config->hwaddr_len = ETHER_ADDR_LEN; config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
config->hwaddr_type = ARPHRD_ETHER; if (config->hwaddr)
{
memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
config->hwaddr->hwaddr_type = ARPHRD_ETHER;
config->hwaddr->wildcard_mask = 0;
config->hwaddr->next = NULL;
}
count++; count++;
} }
@@ -852,15 +875,9 @@ void check_dhcp_hosts(int fatal)
configs->flags &= ~CONFIG_ADDR; configs->flags &= ~CONFIG_ADDR;
} }
/* split off domain part */
if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname))) if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
{ configs->domain = domain;
if (fatal)
die(_("illegal domain %s in dhcp-config directive."), domain, EC_BADCONF);
else
my_syslog(LOG_ERR, _("illegal domain %s in %s."), domain, daemon->dhcp_hosts_file);
free(configs->hostname);
configs->flags &= ~CONFIG_NAME;
}
} }
} }
} }
@@ -918,6 +935,7 @@ char *host_from_dns(struct in_addr addr)
{ {
struct crec *lookup; struct crec *lookup;
char *hostname = NULL; char *hostname = NULL;
char *d1, *d2;
if (daemon->port == 0) if (daemon->port == 0)
return NULL; /* DNS disabled. */ return NULL; /* DNS disabled. */
@@ -928,14 +946,16 @@ char *host_from_dns(struct in_addr addr)
hostname = daemon->dhcp_buff; hostname = daemon->dhcp_buff;
strncpy(hostname, cache_get_name(lookup), 256); strncpy(hostname, cache_get_name(lookup), 256);
hostname[255] = 0; hostname[255] = 0;
if (strip_hostname(hostname)) d1 = strip_hostname(hostname);
d2 = get_domain(addr);
if (d1 && (!d2 || hostname_isequal(d1, d2)))
hostname = NULL; hostname = NULL;
} }
return hostname; return hostname;
} }
/* return illegal domain or NULL if OK */ /* return domain or NULL if none. */
char *strip_hostname(char *hostname) char *strip_hostname(char *hostname)
{ {
char *dot = strchr(hostname, '.'); char *dot = strchr(hostname, '.');
@@ -944,9 +964,20 @@ char *strip_hostname(char *hostname)
return NULL; return NULL;
*dot = 0; /* truncate */ *dot = 0; /* truncate */
if (strlen(dot+1) != 0)
if (*(dot+1) && (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix)))
return dot+1; return dot+1;
return NULL; return NULL;
} }
char *get_domain(struct in_addr addr)
{
struct cond_domain *c;
for (c = daemon->cond_domain; c; c = c->next)
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return c->domain;
return daemon->domain_suffix;
}
+8 -19
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -36,10 +36,6 @@ static char *compile_opts =
#ifdef HAVE_BSD_BRIDGE #ifdef HAVE_BSD_BRIDGE
"BSD-bridge " "BSD-bridge "
#endif #endif
#ifndef HAVE_ISC_READER
"no-"
#endif
"ISC-leasefile "
#ifndef HAVE_DBUS #ifndef HAVE_DBUS
"no-" "no-"
#endif #endif
@@ -66,7 +62,7 @@ static void poll_resolv(void);
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
int bind_fallback = 0; int bind_fallback = 0;
time_t now, last = 0; time_t now;
struct sigaction sigact; struct sigaction sigact;
struct iname *if_tmp; struct iname *if_tmp;
int piperead, pipefd[2], err_pipe[2]; int piperead, pipefd[2], err_pipe[2];
@@ -117,10 +113,6 @@ int main (int argc, char **argv)
if (daemon->dhcp) if (daemon->dhcp)
daemon->lease_file = LEASEFILE; daemon->lease_file = LEASEFILE;
} }
#ifndef HAVE_ISC_READER
else if (!daemon->dhcp)
die(_("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"), NULL, EC_BADCONF);
#endif
/* Close any file descriptors we inherited apart from std{in|out|err} */ /* Close any file descriptors we inherited apart from std{in|out|err} */
for (i = 0; i < max_fd; i++) for (i = 0; i < max_fd; i++)
@@ -633,14 +625,11 @@ int main (int argc, char **argv)
/* Check for changes to resolv files once per second max. */ /* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */ /* Don't go silent for long periods if the clock goes backwards. */
if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < -1.0) if (daemon->last_resolv == 0 ||
difftime(now, daemon->last_resolv) > 1.0 ||
difftime(now, daemon->last_resolv) < -1.0)
{ {
last = now; daemon->last_resolv = now;
#ifdef HAVE_ISC_READER
if (daemon->lease_file && !daemon->dhcp)
load_dhcp(now);
#endif
if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL)) if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
poll_resolv(); poll_resolv();
@@ -912,7 +901,7 @@ static void poll_resolv()
warned = 0; warned = 0;
check_servers(); check_servers();
if (daemon->options & OPT_RELOAD) if (daemon->options & OPT_RELOAD)
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts); cache_reload(daemon->addn_hosts);
} }
else else
{ {
@@ -929,7 +918,7 @@ static void poll_resolv()
void clear_cache_and_reload(time_t now) void clear_cache_and_reload(time_t now)
{ {
if (daemon->port != 0) if (daemon->port != 0)
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts); cache_reload(daemon->addn_hosts);
if (daemon->dhcp) if (daemon->dhcp)
{ {
+35 -18
View File
@@ -172,7 +172,7 @@ struct event_desc {
#define OPT_AUTHORITATIVE (1u<<17) #define OPT_AUTHORITATIVE (1u<<17)
#define OPT_LOCALISE (1u<<18) #define OPT_LOCALISE (1u<<18)
#define OPT_DBUS (1u<<19) #define OPT_DBUS (1u<<19)
#define OPT_BOOTP_DYNAMIC (1u<<20) #define OPT_DHCP_FQDN (1u<<20)
#define OPT_NO_PING (1u<<21) #define OPT_NO_PING (1u<<21)
#define OPT_LEASE_RO (1u<<22) #define OPT_LEASE_RO (1u<<22)
#define OPT_ALL_SERVERS (1u<<23) #define OPT_ALL_SERVERS (1u<<23)
@@ -229,6 +229,11 @@ struct ptr_record {
struct ptr_record *next; struct ptr_record *next;
}; };
struct cname {
char *alias, *target;
struct cname *next;
};
struct interface_name { struct interface_name {
char *name; /* domain name */ char *name; /* domain name */
char *intr; /* interface name */ char *intr; /* interface name */
@@ -425,23 +430,28 @@ struct dhcp_netid_list {
struct dhcp_netid_list *next; struct dhcp_netid_list *next;
}; };
struct hwaddr_config {
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
unsigned int wildcard_mask;
struct hwaddr_config *next;
};
struct dhcp_config { struct dhcp_config {
unsigned int flags; unsigned int flags;
int clid_len; /* length of client identifier */ int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */ unsigned char *clid; /* clientid */
int hwaddr_len, hwaddr_type; char *hostname, *domain;
unsigned char hwaddr[DHCP_CHADDR_MAX];
char *hostname;
struct dhcp_netid netid; struct dhcp_netid netid;
struct in_addr addr; struct in_addr addr;
time_t decline_time; time_t decline_time;
unsigned int lease_time, wildcard_mask; unsigned int lease_time;
struct hwaddr_config *hwaddr;
struct dhcp_config *next; struct dhcp_config *next;
}; };
#define CONFIG_DISABLE 1 #define CONFIG_DISABLE 1
#define CONFIG_CLID 2 #define CONFIG_CLID 2
#define CONFIG_HWADDR 4
#define CONFIG_TIME 8 #define CONFIG_TIME 8
#define CONFIG_NAME 16 #define CONFIG_NAME 16
#define CONFIG_ADDR 32 #define CONFIG_ADDR 32
@@ -503,6 +513,12 @@ struct dhcp_bridge {
}; };
#endif #endif
struct cond_domain {
char *domain;
struct in_addr start, end;
struct cond_domain *next;
};
struct dhcp_context { struct dhcp_context {
unsigned int lease_time, addr_epoch; unsigned int lease_time, addr_epoch;
struct in_addr netmask, broadcast; struct in_addr netmask, broadcast;
@@ -565,16 +581,19 @@ extern struct daemon {
unsigned int options; unsigned int options;
struct resolvc default_resolv, *resolv_files; struct resolvc default_resolv, *resolv_files;
time_t last_resolv;
struct mx_srv_record *mxnames; struct mx_srv_record *mxnames;
struct naptr *naptr; struct naptr *naptr;
struct txt_record *txt; struct txt_record *txt;
struct ptr_record *ptr; struct ptr_record *ptr;
struct cname *cnames;
struct interface_name *int_names; struct interface_name *int_names;
char *mxtarget; char *mxtarget;
char *lease_file; char *lease_file;
char *username, *groupname, *scriptuser; char *username, *groupname, *scriptuser;
int group_set, osport; int group_set, osport;
char *domain_suffix; char *domain_suffix;
struct cond_domain *cond_domain;
char *runfile; char *runfile;
char *lease_change_command; char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except; struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
@@ -593,7 +612,7 @@ extern struct daemon {
struct dhcp_vendor *dhcp_vendors; struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs; struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config; struct dhcp_boot *boot_config;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast; struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
char *dhcp_hosts_file, *dhcp_opts_file; char *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max; int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port; int dhcp_server_port, dhcp_client_port;
@@ -660,7 +679,7 @@ void cache_end_insert(void);
void cache_start_insert(void); void cache_start_insert(void);
struct crec *cache_insert(char *name, struct all_addr *addr, struct crec *cache_insert(char *name, struct all_addr *addr,
time_t now, unsigned long ttl, unsigned short flags); time_t now, unsigned long ttl, unsigned short flags);
void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *addn_hosts); void cache_reload(struct hostsfile *addn_hosts);
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd); void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd);
void cache_unhash_dhcp(void); void cache_unhash_dhcp(void);
void dump_cache(time_t now); void dump_cache(time_t now);
@@ -749,17 +768,17 @@ struct in_addr get_ifaddr(char *intr);
/* dhcp.c */ /* dhcp.c */
void dhcp_init(void); void dhcp_init(void);
void dhcp_packet(time_t now); void dhcp_packet(time_t now);
char *get_domain(struct in_addr addr);
struct dhcp_context *address_available(struct dhcp_context *context, struct dhcp_context *address_available(struct dhcp_context *context,
struct in_addr addr, struct in_addr addr,
struct dhcp_netid *netids); struct dhcp_netid *netids);
struct dhcp_context *narrow_context(struct dhcp_context *context, struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr, struct in_addr taddr,
struct dhcp_netid *netids); struct dhcp_netid *netids);
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly); int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);int address_allocate(struct dhcp_context *context,
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len, struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now); struct dhcp_netid *netids, time_t now);
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
struct dhcp_config *find_config(struct dhcp_config *configs, struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context, struct dhcp_context *context,
unsigned char *clid, int clid_len, unsigned char *clid, int clid_len,
@@ -771,6 +790,7 @@ void check_dhcp_hosts(int fatal);
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr); struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
char *strip_hostname(char *hostname); char *strip_hostname(char *hostname);
char *host_from_dns(struct in_addr addr); char *host_from_dns(struct in_addr addr);
char *get_domain(struct in_addr addr);
/* lease.c */ /* lease.c */
void lease_update_file(time_t now); void lease_update_file(time_t now);
@@ -779,8 +799,7 @@ void lease_init(time_t now);
struct dhcp_lease *lease_allocate(struct in_addr addr); struct dhcp_lease *lease_allocate(struct in_addr addr);
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int hw_len, int hw_type, int clid_len); unsigned char *clid, int hw_len, int hw_type, int clid_len);
void lease_set_hostname(struct dhcp_lease *lease, char *name, void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth);
char *suffix, int auth);
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now); void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
void lease_set_interface(struct dhcp_lease *lease, int interface); void lease_set_interface(struct dhcp_lease *lease, int interface);
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type, struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
@@ -794,6 +813,8 @@ void rerun_scripts(void);
/* rfc2131.c */ /* rfc2131.c */
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int *is_inform); size_t sz, time_t now, int unicast_dest, int *is_inform);
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out);
/* dnsmasq.c */ /* dnsmasq.c */
int make_icmp_sock(void); int make_icmp_sock(void);
@@ -801,11 +822,6 @@ int icmp_ping(struct in_addr addr);
void send_event(int fd, int event, int data); void send_event(int fd, int event, int data);
void clear_cache_and_reload(time_t now); void clear_cache_and_reload(time_t now);
/* isc.c */
#ifdef HAVE_ISC_READER
void load_dhcp(time_t now);
#endif
/* netlink.c */ /* netlink.c */
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
void netlink_init(void); void netlink_init(void);
@@ -827,6 +843,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)());
char *dbus_init(void); char *dbus_init(void);
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset); void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset); void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
void emit_dbus_signal(int action, char *mac, char *hostname, char *addr);
#endif #endif
/* helper.c */ /* helper.c */
+11 -7
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -381,8 +381,8 @@ static size_t process_reply(HEADER *header, time_t now,
size_t plen; size_t plen;
/* If upstream is advertising a larger UDP packet size /* If upstream is advertising a larger UDP packet size
than we allow, trim it so that we don't get overlarge than we allow, trim it so that we don't get overlarge
requests for the client. We can't do this for signed packets. */ requests for the client. We can't do this for signed packets. */
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign) if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
{ {
@@ -918,19 +918,23 @@ static struct randfd *allocate_rfd(int family)
(eg) TFTP. Once we have a reasonable number, randomness should be OK */ (eg) TFTP. Once we have a reasonable number, randomness should be OK */
for (i = 0; i < RANDOM_SOCKS; i++) for (i = 0; i < RANDOM_SOCKS; i++)
if (daemon->randomsocks[i].refcount == 0 && if (daemon->randomsocks[i].refcount == 0)
(daemon->randomsocks[i].fd = random_sock(family)) != -1)
{ {
if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
break;
daemon->randomsocks[i].refcount = 1; daemon->randomsocks[i].refcount = 1;
daemon->randomsocks[i].family = family; daemon->randomsocks[i].family = family;
return &daemon->randomsocks[i]; return &daemon->randomsocks[i];
} }
/* No free ones, grab an existing one */ /* No free ones or cannot get new socket, grab an existing one */
for (i = 0; i < RANDOM_SOCKS; i++) for (i = 0; i < RANDOM_SOCKS; i++)
{ {
int j = (i+finger) % RANDOM_SOCKS; int j = (i+finger) % RANDOM_SOCKS;
if (daemon->randomsocks[j].family == family && daemon->randomsocks[j].refcount != 0xffff) if (daemon->randomsocks[j].refcount != 0 &&
daemon->randomsocks[j].family == family &&
daemon->randomsocks[j].refcount != 0xffff)
{ {
finger = j; finger = j;
daemon->randomsocks[j].refcount++; daemon->randomsocks[j].refcount++;
+27 -12
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
#ifndef NO_FORK #ifndef NO_FORK
static void my_setenv(const char *name, const char *value, int *error); static void my_setenv(const char *name, const char *value, int *error);
struct script_data struct script_data
{ {
unsigned char action, hwaddr_len, hwaddr_type; unsigned char action, hwaddr_len, hwaddr_type;
@@ -130,13 +130,13 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
/* stringify MAC into dhcp_buff */ /* stringify MAC into dhcp_buff */
p = daemon->dhcp_buff; p = daemon->dhcp_buff;
if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0) if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0)
p += sprintf(p, "%.2x-", data.hwaddr_type); p += sprintf(p, "%.2x-", data.hwaddr_type);
for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++) for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++)
{ {
p += sprintf(p, "%.2x", data.hwaddr[i]); p += sprintf(p, "%.2x", data.hwaddr[i]);
if (i != data.hwaddr_len - 1) if (i != data.hwaddr_len - 1)
p += sprintf(p, ":"); p += sprintf(p, ":");
} }
/* and CLID into packet */ /* and CLID into packet */
if (!read_write(pipefd[0], buf, data.clid_len, 1)) if (!read_write(pipefd[0], buf, data.clid_len, 1))
@@ -237,10 +237,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (data.hostname_len != 0) if (data.hostname_len != 0)
{ {
char *dot;
hostname = (char *)buf; hostname = (char *)buf;
hostname[data.hostname_len - 1] = 0; hostname[data.hostname_len - 1] = 0;
if (!canonicalise(hostname)) if (!canonicalise(hostname))
hostname = NULL; hostname = NULL;
else if ((dot = strchr(hostname, '.')))
{
my_setenv("DNSMASQ_DOMAIN", dot+1, &err);
*dot = 0;
}
} }
if (data.action == ACTION_OLD_HOSTNAME && hostname) if (data.action == ACTION_OLD_HOSTNAME && hostname)
@@ -299,7 +305,15 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
{ {
unsigned char *p; unsigned char *p;
size_t size; size_t size;
unsigned int i, hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0; int i;
unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0;
#ifdef HAVE_DBUS
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
lease->hwaddr, lease->clid_len, lease->clid, &i);
print_mac(daemon->namebuff, p, i);
emit_dbus_signal(action, daemon->namebuff, hostname ? hostname : "", inet_ntoa(lease->addr));
#endif
/* no script */ /* no script */
if (daemon->helperfd == -1) if (daemon->helperfd == -1)
@@ -320,7 +334,7 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
{ {
struct script_data *new; struct script_data *new;
/* start with resonable size, will almost never need extending. */ /* start with reasonable size, will almost never need extending. */
if (size < sizeof(struct script_data) + 200) if (size < sizeof(struct script_data) + 200)
size = sizeof(struct script_data) + 200; size = sizeof(struct script_data) + 200;
@@ -378,8 +392,9 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
memcpy(p, lease->userclass, uclass_len); memcpy(p, lease->userclass, uclass_len);
p += uclass_len; p += uclass_len;
} }
/* substitute * for space */ /* substitute * for space: spaces are allowed in hostnames (for DNS-SD)
for (i = 0; i < hostname_len; i++) and are likley to be a security hole in most scripts. */
for (i = 0; i < (int)hostname_len; i++)
if ((daemon->options & OPT_LEASE_RO) && hostname[i] == ' ') if ((daemon->options & OPT_LEASE_RO) && hostname[i] == ' ')
*(p++) = '*'; *(p++) = '*';
else else
-252
View File
@@ -1,252 +0,0 @@
/* dnsmasq is Copyright (c) 2000-2007 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
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Code in this file is based on contributions by John Volpe. */
#include "dnsmasq.h"
#ifdef HAVE_ISC_READER
#define MAXTOK 50
struct isc_lease {
char *name, *fqdn;
time_t expires;
struct in_addr addr;
struct isc_lease *next;
};
static struct isc_lease *leases = NULL;
static off_t lease_file_size = (off_t)0;
static ino_t lease_file_inode = (ino_t)0;
static int logged_lease = 0;
static int next_token (char *token, int buffsize, FILE * fp)
{
int c, count = 0;
char *cp = token;
while((c = getc(fp)) != EOF)
{
if (c == '#')
do { c = getc(fp); } while (c != '\n' && c != EOF);
if (c == ' ' || c == '\t' || c == '\n' || c == ';')
{
if (count)
break;
}
else if ((c != '"') && (count<buffsize-1))
{
*cp++ = c;
count++;
}
}
*cp = 0;
return count ? 1 : 0;
}
void load_dhcp(time_t now)
{
char *hostname = daemon->namebuff;
char token[MAXTOK], *dot;
struct in_addr host_address;
time_t ttd, tts;
FILE *fp;
struct isc_lease *lease, *tmp, **up;
struct stat statbuf;
if (stat(daemon->lease_file, &statbuf) == -1)
{
if (!logged_lease)
my_syslog(LOG_WARNING, _("failed to access %s: %s"), daemon->lease_file, strerror(errno));
logged_lease = 1;
return;
}
logged_lease = 0;
if ((statbuf.st_size <= lease_file_size) &&
(statbuf.st_ino == lease_file_inode))
return;
lease_file_size = statbuf.st_size;
lease_file_inode = statbuf.st_ino;
if (!(fp = fopen (daemon->lease_file, "r")))
{
my_syslog (LOG_ERR, _("failed to load %s: %s"), daemon->lease_file, strerror(errno));
return;
}
my_syslog (LOG_INFO, _("reading %s"), daemon->lease_file);
while ((next_token(token, MAXTOK, fp)))
{
if (strcmp(token, "lease") == 0)
{
hostname[0] = '\0';
ttd = tts = (time_t)(-1);
if (next_token(token, MAXTOK, fp) &&
(host_address.s_addr = inet_addr(token)) != (in_addr_t) -1)
{
if (next_token(token, MAXTOK, fp) && *token == '{')
{
while (next_token(token, MAXTOK, fp) && *token != '}')
{
if ((strcmp(token, "client-hostname") == 0) ||
(strcmp(token, "hostname") == 0))
{
if (next_token(hostname, MAXDNAME, fp))
if (!canonicalise(hostname))
{
*hostname = 0;
my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
}
}
else if ((strcmp(token, "ends") == 0) ||
(strcmp(token, "starts") == 0))
{
struct tm lease_time;
int is_ends = (strcmp(token, "ends") == 0);
if (next_token(token, MAXTOK, fp) && /* skip weekday */
next_token(token, MAXTOK, fp) && /* Get date from lease file */
sscanf (token, "%d/%d/%d",
&lease_time.tm_year,
&lease_time.tm_mon,
&lease_time.tm_mday) == 3 &&
next_token(token, MAXTOK, fp) &&
sscanf (token, "%d:%d:%d:",
&lease_time.tm_hour,
&lease_time.tm_min,
&lease_time.tm_sec) == 3)
{
/* There doesn't seem to be a universally available library function
which converts broken-down _GMT_ time to seconds-in-epoch.
The following was borrowed from ISC dhcpd sources, where
it is noted that it might not be entirely accurate for odd seconds.
Since we're trying to get the same answer as dhcpd, that's just
fine here. */
static const int months [11] = { 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334 };
time_t time = ((((((365 * (lease_time.tm_year - 1970) + /* Days in years since '70 */
(lease_time.tm_year - 1969) / 4 + /* Leap days since '70 */
(lease_time.tm_mon > 1 /* Days in months this year */
? months [lease_time.tm_mon - 2]
: 0) +
(lease_time.tm_mon > 2 && /* Leap day this year */
!((lease_time.tm_year - 1972) & 3)) +
lease_time.tm_mday - 1) * 24) + /* Day of month */
lease_time.tm_hour) * 60) +
lease_time.tm_min) * 60) + lease_time.tm_sec;
if (is_ends)
ttd = time;
else
tts = time; }
}
}
/* missing info? */
if (!*hostname)
continue;
if (ttd == (time_t)(-1))
continue;
/* We use 0 as infinite in ttd */
if ((tts != -1) && (ttd == tts - 1))
ttd = (time_t)0;
else if (difftime(now, ttd) > 0)
continue;
if ((dot = strchr(hostname, '.')))
{
if (!daemon->domain_suffix || hostname_isequal(dot+1, daemon->domain_suffix))
{
my_syslog(LOG_WARNING,
_("Ignoring DHCP lease for %s because it has an illegal domain part"),
hostname);
continue;
}
*dot = 0;
}
for (lease = leases; lease; lease = lease->next)
if (hostname_isequal(lease->name, hostname))
{
lease->expires = ttd;
lease->addr = host_address;
break;
}
if (!lease && (lease = whine_malloc(sizeof(struct isc_lease))))
{
lease->expires = ttd;
lease->addr = host_address;
lease->fqdn = NULL;
lease->next = leases;
if (!(lease->name = whine_malloc(strlen(hostname)+1)))
free(lease);
else
{
leases = lease;
strcpy(lease->name, hostname);
if (daemon->domain_suffix &&
(lease->fqdn = whine_malloc(strlen(hostname) + strlen(daemon->domain_suffix) + 2)))
{
strcpy(lease->fqdn, hostname);
strcat(lease->fqdn, ".");
strcat(lease->fqdn, daemon->domain_suffix);
}
}
}
}
}
}
}
fclose(fp);
/* prune expired leases */
for (lease = leases, up = &leases; lease; lease = tmp)
{
tmp = lease->next;
if (lease->expires != (time_t)0 && difftime(now, lease->expires) > 0)
{
*up = lease->next; /* unlink */
free(lease->name);
if (lease->fqdn)
free(lease->fqdn);
free(lease);
}
else
up = &lease->next;
}
/* remove all existing DHCP cache entries */
cache_unhash_dhcp();
for (lease = leases; lease; lease = lease->next)
{
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires);
}
}
#endif
+80 -44
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -103,7 +103,7 @@ void lease_init(time_t now)
/* unprotect spaces */ /* unprotect spaces */
for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*')) for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*'))
*p = ' '; *p = ' ';
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0); lease_set_hostname(lease, daemon->dhcp_buff, 0);
} }
/* set these correctly: the "old" events are generated later from /* set these correctly: the "old" events are generated later from
@@ -151,9 +151,9 @@ void lease_update_from_configs(void)
lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
(config->flags & CONFIG_NAME) && (config->flags & CONFIG_NAME) &&
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr)) (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
lease_set_hostname(lease, config->hostname, daemon->domain_suffix, 1); lease_set_hostname(lease, config->hostname, 1);
else if ((name = host_from_dns(lease->addr))) else if ((name = host_from_dns(lease->addr)))
lease_set_hostname(lease, name, daemon->domain_suffix, 1); /* updates auth flag only */ lease_set_hostname(lease, name, 1); /* updates auth flag only */
} }
static void ourprintf(int *errp, char *format, ...) static void ourprintf(int *errp, char *format, ...)
@@ -254,8 +254,11 @@ void lease_update_dns(void)
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
{ {
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires); if (lease->fqdn)
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires); cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
if (!(daemon->options & OPT_DHCP_FQDN) && lease->hostname)
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
} }
dns_dirty = 0; dns_dirty = 0;
@@ -412,11 +415,33 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
} }
void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int auth) static void kill_name(struct dhcp_lease *lease)
{
/* run script to say we lost our old name */
/* this shouldn't happen unless updates are very quick and the
script very slow, we just avoid a memory leak if it does. */
free(lease->old_hostname);
/* If we know the fqdn, pass that. The helper will derive the
unqualified name from it, free the unqulaified name here. */
if (lease->fqdn)
{
lease->old_hostname = lease->fqdn;
free(lease->hostname);
}
else
lease->old_hostname = lease->hostname;
lease->hostname = lease->fqdn = NULL;
}
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth)
{ {
struct dhcp_lease *lease_tmp; struct dhcp_lease *lease_tmp;
char *new_name = NULL, *new_fqdn = NULL; char *new_name = NULL, *new_fqdn = NULL;
if (lease->hostname && name && hostname_isequal(lease->hostname, name)) if (lease->hostname && name && hostname_isequal(lease->hostname, name))
{ {
lease->auth_name = auth; lease->auth_name = auth;
@@ -433,44 +458,47 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int
if (name) if (name)
{ {
for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next) if ((new_name = whine_malloc(strlen(name) + 1)))
if (lease_tmp->hostname && hostname_isequal(lease_tmp->hostname, name))
{
if (lease_tmp->auth_name && !auth)
return;
/* this shouldn't happen unless updates are very quick and the
script very slow, we just avoid a memory leak if it does. */
free(lease_tmp->old_hostname);
lease_tmp->old_hostname = lease_tmp->hostname;
lease_tmp->hostname = NULL;
if (lease_tmp->fqdn)
{
new_fqdn = lease_tmp->fqdn;
lease_tmp->fqdn = NULL;
}
break;
}
if (!new_name && (new_name = whine_malloc(strlen(name) + 1)))
strcpy(new_name, name);
if (suffix && !new_fqdn && (new_fqdn = whine_malloc(strlen(name) + strlen(suffix) + 2)))
{ {
strcpy(new_fqdn, name); char *suffix = get_domain(lease->addr);
strcat(new_fqdn, "."); strcpy(new_name, name);
strcat(new_fqdn, suffix); if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2)))
{
strcpy(new_fqdn, name);
strcat(new_fqdn, ".");
strcat(new_fqdn, suffix);
}
}
/* Depending on mode, we check either unqualified name or FQDN. */
for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
{
if (daemon->options & OPT_DHCP_FQDN)
{
if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) )
continue;
}
else
{
if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
continue;
}
if (lease_tmp->auth_name && !auth)
{
free(new_name);
free(new_fqdn);
return;
}
kill_name(lease_tmp);
break;
} }
} }
if (lease->hostname) if (lease->hostname)
{ kill_name(lease);
/* run script to say we lost our old name */
free(lease->old_hostname);
lease->old_hostname = lease->hostname;
}
free(lease->fqdn);
lease->hostname = new_name; lease->hostname = new_name;
lease->fqdn = new_fqdn; lease->fqdn = new_fqdn;
lease->auth_name = auth; lease->auth_name = auth;
@@ -506,6 +534,13 @@ int do_script_run(time_t now)
{ {
struct dhcp_lease *lease; struct dhcp_lease *lease;
#ifdef HAVE_DBUS
/* If we're going to be sending DBus signals, but the connection is not yet up,
delay everything until it is. */
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
return 0;
#endif
if (old_leases) if (old_leases)
{ {
lease = old_leases; lease = old_leases;
@@ -522,13 +557,13 @@ int do_script_run(time_t now)
} }
else else
{ {
kill_name(lease);
#ifndef NO_FORK #ifndef NO_FORK
queue_script(ACTION_DEL, lease, lease->hostname, now); queue_script(ACTION_DEL, lease, lease->old_hostname, now);
#endif #endif
old_leases = lease->next; old_leases = lease->next;
free(lease->hostname); free(lease->old_hostname);
free(lease->fqdn);
free(lease->clid); free(lease->clid);
free(lease->vendorclass); free(lease->vendorclass);
free(lease->userclass); free(lease->userclass);
@@ -555,7 +590,8 @@ int do_script_run(time_t now)
(lease->aux_changed && (daemon->options & OPT_LEASE_RO))) (lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
{ {
#ifndef NO_FORK #ifndef NO_FORK
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now); queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease,
lease->fqdn ? lease->fqdn : lease->hostname, now);
#endif #endif
lease->new = lease->changed = lease->aux_changed = 0; lease->new = lease->changed = lease->aux_changed = 0;
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
+17 -10
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -237,7 +237,7 @@ static void nl_err(struct nlmsghdr *h)
failing. */ failing. */
static void nl_routechange(struct nlmsghdr *h) static void nl_routechange(struct nlmsghdr *h)
{ {
if (h->nlmsg_type == RTM_NEWROUTE && daemon->srv_save) if (h->nlmsg_type == RTM_NEWROUTE)
{ {
struct rtmsg *rtm = NLMSG_DATA(h); struct rtmsg *rtm = NLMSG_DATA(h);
int fd; int fd;
@@ -245,17 +245,24 @@ static void nl_routechange(struct nlmsghdr *h)
if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK) if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK)
return; return;
if (daemon->srv_save->sfd) /* Force re-reading resolv file right now, for luck. */
fd = daemon->srv_save->sfd->fd; daemon->last_resolv = 0;
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
fd = daemon->rfd_save->fd;
else
return;
while(sendto(fd, daemon->packet, daemon->packet_len, 0, if (daemon->srv_save)
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send()); {
if (daemon->srv_save->sfd)
fd = daemon->srv_save->sfd->fd;
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
fd = daemon->rfd_save->fd;
else
return;
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
}
} }
} }
#endif #endif
+4 -7
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -442,7 +442,7 @@ struct listener *create_bound_listeners(void)
} }
/* return a UDP socket bound to a random port, have to coper with straying into /* return a UDP socket bound to a random port, have to cope with straying into
occupied port nos and reserved ones. */ occupied port nos and reserved ones. */
int random_sock(int family) int random_sock(int family)
{ {
@@ -452,10 +452,7 @@ int random_sock(int family)
{ {
union mysockaddr addr; union mysockaddr addr;
unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port; unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
int i, tries = 3 * ports_avail; int tries = ports_avail < 30 ? 3 * ports_avail : 100;
if (tries > 100)
tries = 100;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sa.sa_family = family; addr.sa.sa_family = family;
@@ -463,7 +460,7 @@ int random_sock(int family)
/* don't loop forever if all ports in use. */ /* don't loop forever if all ports in use. */
if (fix_fd(fd)) if (fix_fd(fd))
for (i = tries; i != 0; i--) while(tries--)
{ {
unsigned short port = rand16(); unsigned short port = rand16();
+120 -21
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ struct myoption {
}; };
#endif #endif
#define OPTSTRING "9531yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:" #define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
/* options which don't have a one-char version */ /* options which don't have a one-char version */
#define LOPT_RELOAD 256 #define LOPT_RELOAD 256
@@ -96,6 +96,8 @@ struct myoption {
#define LOPT_LOCAL 286 #define LOPT_LOCAL 286
#define LOPT_NAPTR 287 #define LOPT_NAPTR 287
#define LOPT_MINPORT 288 #define LOPT_MINPORT 288
#define LOPT_DHCP_FQDN 289
#define LOPT_CNAME 290
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -160,7 +162,7 @@ static const struct myoption opts[] =
{"localise-queries", 0, 0, 'y'}, {"localise-queries", 0, 0, 'y'},
{"txt-record", 1, 0, 'Y'}, {"txt-record", 1, 0, 'Y'},
{"enable-dbus", 0, 0, '1'}, {"enable-dbus", 0, 0, '1'},
{"bootp-dynamic", 0, 0, '3'}, {"bootp-dynamic", 2, 0, '3'},
{"dhcp-mac", 1, 0, '4'}, {"dhcp-mac", 1, 0, '4'},
{"no-ping", 0, 0, '5'}, {"no-ping", 0, 0, '5'},
{"dhcp-script", 1, 0, '6'}, {"dhcp-script", 1, 0, '6'},
@@ -200,6 +202,8 @@ static const struct myoption opts[] =
{"dhcp-alternate-port", 2, 0, LOPT_ALTPORT }, {"dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
{"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR }, {"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
{"min-port", 1, 0, LOPT_MINPORT }, {"min-port", 1, 0, LOPT_MINPORT },
{"dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
{"cname", 1, 0, LOPT_CNAME },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
@@ -240,8 +244,8 @@ static struct {
{ LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL }, { LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
{ LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL }, { LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
{ LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL }, { LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
{ 'J', ARG_DUP, "<tag>", gettext_noop("Don't do DHCP for hosts with tag set."), NULL }, { 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
{ LOPT_BROADCAST, ARG_DUP, "<tag>", gettext_noop("Force broadcast replies for hosts with tag set."), NULL }, { LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
{ 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL }, { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
{ 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL }, { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
{ 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE }, { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
@@ -261,7 +265,7 @@ static struct {
{ 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
{ 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL }, { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
{ LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL }, { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
{ 's', ARG_ONE, "<domain>", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL }, { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
{ 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL }, { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
{ 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL }, { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
{ LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL }, { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
@@ -281,7 +285,7 @@ static struct {
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE }, { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
{ '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL }, { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
{ '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL }, { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
{ '3', OPT_BOOTP_DYNAMIC, NULL, gettext_noop("Enable dynamic address allocation for bootp."), NULL }, { '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL }, { '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
#ifdef HAVE_BSD_BRIDGE #ifdef HAVE_BSD_BRIDGE
{ LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL }, { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
@@ -293,7 +297,7 @@ static struct {
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL }, { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
{ '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
{ LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE }, { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
{ LOPT_NO_NAMES, ARG_DUP, "[=<id>]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL }, { LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
{ LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL }, { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
{ LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL }, { LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
{ LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL }, { LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
@@ -311,6 +315,8 @@ static struct {
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL }, { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL }, { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL }, { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
@@ -373,8 +379,8 @@ static const struct {
{ "T2", 59, OT_INTERNAL }, { "T2", 59, OT_INTERNAL },
{ "vendor-class", 60, 0 }, { "vendor-class", 60, 0 },
{ "client-id", 61,OT_INTERNAL }, { "client-id", 61,OT_INTERNAL },
{ "nis-domain", 64, 0 }, { "nis+-domain", 64, 0 },
{ "nis-server", 65, OT_ADDR_LIST }, { "nis+-server", 65, OT_ADDR_LIST },
{ "tftp-server", 66, 0 }, { "tftp-server", 66, 0 },
{ "bootfile-name", 67, 0 }, { "bootfile-name", 67, 0 },
{ "mobile-ip-home", 68, OT_ADDR_LIST }, { "mobile-ip-home", 68, OT_ADDR_LIST },
@@ -957,7 +963,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{ {
char *file = opt_string_alloc(arg); char *file = opt_string_alloc(arg);
if (file) if (file)
one_file(file, nest, 0); {
one_file(file, nest, 0);
free(file);
}
break; break;
} }
@@ -1001,6 +1010,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
} }
closedir(dir_stream); closedir(dir_stream);
free(directory);
break; break;
} }
@@ -1127,10 +1137,49 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 's': /* --domain */ case 's': /* --domain */
if (strcmp (arg, "#") == 0) if (strcmp (arg, "#") == 0)
daemon->options |= OPT_RESOLV_DOMAIN; daemon->options |= OPT_RESOLV_DOMAIN;
else if (!canonicalise_opt(arg))
option = '?';
else else
daemon->domain_suffix = opt_string_alloc(arg); {
comma = split(arg);
if (!canonicalise_opt(arg))
option = '?';
else
{
char *d = opt_string_alloc(arg);
if (comma)
{
struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
unhide_metas(comma);
if ((arg = strchr(comma, '/')))
{
int mask;
*arg++ = 0;
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
!atoi_check(arg, &mask))
option = '?';
else
{
mask = (1 << (32 - mask)) - 1;
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
new->end.s_addr = new->start.s_addr | htonl(mask);
}
}
else if ((arg = split(comma)))
{
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
(new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
option = '?';
}
else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
option = '?';
new->domain = d;
new->next = daemon->cond_domain;
daemon->cond_domain = new;
}
else
daemon->domain_suffix = d;
}
}
break; break;
case 'u': /* --user */ case 'u': /* --user */
@@ -1406,7 +1455,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case LOPT_MINPORT: /* --min-port */ case LOPT_MINPORT: /* --min-port */
if (!atoi_check16(arg, &daemon->min_port)) if (!atoi_check16(arg, &daemon->min_port))
option = '?'; option = '?';
break; break;
case '0': /* --dns-forward-max */ case '0': /* --dns-forward-max */
@@ -1656,7 +1705,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new = opt_malloc(sizeof(struct dhcp_config)); new = opt_malloc(sizeof(struct dhcp_config));
new->next = daemon->dhcp_conf; new->next = daemon->dhcp_conf;
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0; new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
new->hwaddr = NULL;
if ((a[0] = arg)) if ((a[0] = arg))
for (k = 1; k < 6; k++) for (k = 1; k < 6; k++)
@@ -1706,8 +1756,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
} }
else else
{ {
new->hwaddr_len = parse_hex(a[j], new->hwaddr, DHCP_CHADDR_MAX, &new->wildcard_mask, &new->hwaddr_type); struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
new->flags |= CONFIG_HWADDR; newhw->next = new->hwaddr;
new->hwaddr = newhw;
newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
&newhw->wildcard_mask, &newhw->hwaddr_type);
} }
} }
else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1) else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
@@ -1768,6 +1821,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{ {
new->flags |= CONFIG_NAME; new->flags |= CONFIG_NAME;
strcpy(new->hostname, a[j]); strcpy(new->hostname, a[j]);
new->domain = NULL;
} }
} }
} }
@@ -1850,7 +1904,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
else else
{ {
struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac)); struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
new->netid.net = opt_string_alloc(arg); if (strstr(arg, "net:") == arg)
new->netid.net = opt_string_alloc(arg+4);
else
new->netid.net = opt_string_alloc(arg);
unhide_metas(comma); unhide_metas(comma);
new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type); new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
new->next = daemon->dhcp_macs; new->next = daemon->dhcp_macs;
@@ -1873,7 +1930,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
char *p; char *p;
int dig = 0; int dig = 0;
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor)); struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
new->netid.net = opt_string_alloc(arg); if (strstr(arg, "net:") == arg)
new->netid.net = opt_string_alloc(arg+4);
else
new->netid.net = opt_string_alloc(arg);
/* check for hex string - must digits may include : must not have nothing else, /* check for hex string - must digits may include : must not have nothing else,
only allowed for agent-options. */ only allowed for agent-options. */
for (p = comma; *p; p++) for (p = comma; *p; p++)
@@ -1944,6 +2004,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 'J': /* --dhcp-ignore */ case 'J': /* --dhcp-ignore */
case LOPT_NO_NAMES: /* --dhcp-ignore-names */ case LOPT_NO_NAMES: /* --dhcp-ignore-names */
case LOPT_BROADCAST: /* --dhcp-broadcast */ case LOPT_BROADCAST: /* --dhcp-broadcast */
case '3': /* --bootp-dynamic */
{ {
struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list)); struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
struct dhcp_netid *list = NULL; struct dhcp_netid *list = NULL;
@@ -1957,6 +2018,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->next = daemon->force_broadcast; new->next = daemon->force_broadcast;
daemon->force_broadcast = new; daemon->force_broadcast = new;
} }
else if (option == '3')
{
new->next = daemon->bootp_dynamic;
daemon->bootp_dynamic = new;
}
else else
{ {
new->next = daemon->dhcp_ignore_names; new->next = daemon->dhcp_ignore_names;
@@ -1968,7 +2034,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
comma = split(arg); comma = split(arg);
member->next = list; member->next = list;
list = member; list = member;
member->net = opt_string_alloc(arg); if (strstr(arg, "net:") == arg)
member->net = opt_string_alloc(arg+4);
else
member->net = opt_string_alloc(arg);
arg = comma; arg = comma;
} }
@@ -2033,6 +2102,26 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->intr = opt_string_alloc(comma); new->intr = opt_string_alloc(comma);
break; break;
} }
case LOPT_CNAME: /* --cname */
{
struct cname *new;
if (!(comma = split(arg)))
option = '?';
else
{
for (new = daemon->cnames; new; new = new->next)
if (hostname_isequal(new->alias, arg))
problem = _("duplicate CNAME");
new = opt_malloc(sizeof(struct cname));
new->next = daemon->cnames;
daemon->cnames = new;
new->alias = opt_string_alloc(arg);
new->target = opt_string_alloc(comma);
}
break;
}
case LOPT_PTR: /* --ptr-record */ case LOPT_PTR: /* --ptr-record */
{ {
@@ -2387,6 +2476,13 @@ void reread_dhcp(void)
if (configs->flags & CONFIG_BANK) if (configs->flags & CONFIG_BANK)
{ {
struct hwaddr_config *mac, *tmp;
for (mac = configs->hwaddr; mac; mac = tmp)
{
tmp = mac->next;
free(mac);
}
if (configs->flags & CONFIG_CLID) if (configs->flags & CONFIG_CLID)
free(configs->clid); free(configs->clid);
if (configs->flags & CONFIG_NETID) if (configs->flags & CONFIG_NETID)
@@ -2394,6 +2490,7 @@ void reread_dhcp(void)
if (configs->flags & CONFIG_NAME) if (configs->flags & CONFIG_NAME)
free(configs->hostname); free(configs->hostname);
*up = configs->next; *up = configs->next;
free(configs); free(configs);
} }
@@ -2639,4 +2736,6 @@ void read_opts(int argc, char **argv, char *compile_opts)
srv->name = opt_string_alloc(buff); srv->name = opt_string_alloc(buff);
} }
} }
else if (daemon->options & OPT_DHCP_FQDN)
die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
} }
+135 -110
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,8 +21,14 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp,
unsigned long ttl, unsigned int *offset, unsigned short type, unsigned long ttl, unsigned int *offset, unsigned short type,
unsigned short class, char *format, ...); unsigned short class, char *format, ...);
#define CHECK_LEN(header, pp, plen, len) \
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
#define ADD_RDLEN(header, pp, plen, len) \
(!CHECK_LEN(header, pp, plen, len) ? 0 : (int)((pp) += (len)), 1)
static int extract_name(HEADER *header, size_t plen, unsigned char **pp, static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
char *name, int isExtract) char *name, int isExtract, int extrabytes)
{ {
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL; unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
unsigned int j, l, hops = 0; unsigned int j, l, hops = 0;
@@ -31,19 +37,47 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
if (isExtract) if (isExtract)
*cp = 0; *cp = 0;
while ((l = *p++)) while (1)
{ {
unsigned int label_type = l & 0xc0; unsigned int label_type;
if (!CHECK_LEN(header, p, plen, 1))
return 0;
if ((l = *p++) == 0)
/* end marker */
{
/* check that there are the correct no of bytes after the name */
if (!CHECK_LEN(header, p, plen, extrabytes))
return 0;
if (isExtract)
{
if (cp != (unsigned char *)name)
cp--;
*cp = 0; /* terminate: lose final period */
}
else if (*cp != 0)
retvalue = 2;
if (p1) /* we jumped via compression */
*pp = p1;
else
*pp = p;
return retvalue;
}
label_type = l & 0xc0;
if (label_type == 0xc0) /* pointer */ if (label_type == 0xc0) /* pointer */
{ {
if ((size_t)(p - (unsigned char *)header) >= plen) if (!CHECK_LEN(header, p, plen, 1))
return 0; return 0;
/* get offset */ /* get offset */
l = (l&0x3f) << 8; l = (l&0x3f) << 8;
l |= *p++; l |= *p++;
if (l >= plen)
return 0;
if (!p1) /* first jump, save location to go back to */ if (!p1) /* first jump, save location to go back to */
p1 = p; p1 = p;
@@ -74,7 +108,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
/* output is \[x<hex>/siz]. which is digs+9 chars */ /* output is \[x<hex>/siz]. which is digs+9 chars */
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME) if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
return 0; return 0;
if ((size_t)(p - (unsigned char *)header + ((count-1)>>3)) >= plen) if (!CHECK_LEN(header, p, plen, (count-1)>>3))
return 0; return 0;
*cp++ = '\\'; *cp++ = '\\';
@@ -98,8 +132,9 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
{ /* label_type = 0 -> label. */ { /* label_type = 0 -> label. */
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME) if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
return 0; return 0;
if ((size_t)(p - (unsigned char *)header) >= plen) if (!CHECK_LEN(header, p, plen, l))
return 0; return 0;
for(j=0; j<l; j++, p++) for(j=0; j<l; j++, p++)
if (isExtract) if (isExtract)
{ {
@@ -132,26 +167,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
else if (*cp != 0 && *cp++ != '.') else if (*cp != 0 && *cp++ != '.')
retvalue = 2; retvalue = 2;
} }
if ((unsigned int)(p - (unsigned char *)header) >= plen)
return 0;
} }
if (isExtract)
{
if (cp != (unsigned char *)name)
cp--;
*cp = 0; /* terminate: lose final period */
}
else if (*cp != 0)
retvalue = 2;
if (p1) /* we jumped via compression */
*pp = p1;
else
*pp = p;
return retvalue;
} }
/* Max size of input string (for IPv6) is 75 chars.) */ /* Max size of input string (for IPv6) is 75 chars.) */
@@ -261,15 +277,17 @@ static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
return 0; return 0;
} }
static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen) static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen, int extrabytes)
{ {
while(1) while(1)
{ {
unsigned int label_type = (*ansp) & 0xc0; unsigned int label_type;
if ((unsigned int)(ansp - (unsigned char *)header) >= plen) if (!CHECK_LEN(header, ansp, plen, 1))
return NULL; return NULL;
label_type = (*ansp) & 0xc0;
if (label_type == 0xc0) if (label_type == 0xc0)
{ {
/* pointer for compression. */ /* pointer for compression. */
@@ -283,6 +301,9 @@ static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen
/* Extended label type */ /* Extended label type */
unsigned int count; unsigned int count;
if (!CHECK_LEN(header, ansp, plen, 2))
return NULL;
if (((*ansp++) & 0x3f) != 1) if (((*ansp++) & 0x3f) != 1)
return NULL; /* we only understand bitstrings */ return NULL; /* we only understand bitstrings */
@@ -296,12 +317,17 @@ static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen
else else
{ /* label type == 0 Bottom six bits is length */ { /* label type == 0 Bottom six bits is length */
unsigned int len = (*ansp++) & 0x3f; unsigned int len = (*ansp++) & 0x3f;
if (!ADD_RDLEN(header, ansp, plen, len))
return NULL;
if (len == 0) if (len == 0)
break; /* zero length label marks the end. */ break; /* zero length label marks the end. */
ansp += len;
} }
} }
if (!CHECK_LEN(header, ansp, plen, extrabytes))
return NULL;
return ansp; return ansp;
} }
@@ -313,12 +339,10 @@ static unsigned char *skip_questions(HEADER *header, size_t plen)
for (q = ntohs(header->qdcount); q != 0; q--) for (q = ntohs(header->qdcount); q != 0; q--)
{ {
if (!(ansp = skip_name(ansp, header, plen))) if (!(ansp = skip_name(ansp, header, plen, 4)))
return NULL; return NULL;
ansp += 4; /* class and type */ ansp += 4; /* class and type */
} }
if ((unsigned int)(ansp - (unsigned char *)header) > plen)
return NULL;
return ansp; return ansp;
} }
@@ -329,13 +353,12 @@ static unsigned char *skip_section(unsigned char *ansp, int count, HEADER *heade
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
if (!(ansp = skip_name(ansp, header, plen))) if (!(ansp = skip_name(ansp, header, plen, 10)))
return NULL; return NULL;
ansp += 8; /* type, class, TTL */ ansp += 8; /* type, class, TTL */
GETSHORT(rdlen, ansp); GETSHORT(rdlen, ansp);
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen) if (!ADD_RDLEN(header, ansp, plen, rdlen))
return NULL; return NULL;
ansp += rdlen;
} }
return ansp; return ansp;
@@ -355,7 +378,7 @@ unsigned int questions_crc(HEADER *header, size_t plen, char *name)
for (q = ntohs(header->qdcount); q != 0; q--) for (q = ntohs(header->qdcount); q != 0; q--)
{ {
if (!extract_name(header, plen, &p, name, 1)) if (!extract_name(header, plen, &p, name, 1, 4))
return crc; /* bad packet */ return crc; /* bad packet */
for (p1 = (unsigned char *)name; *p1; p1++) for (p1 = (unsigned char *)name; *p1; p1++)
@@ -381,7 +404,7 @@ unsigned int questions_crc(HEADER *header, size_t plen, char *name)
} }
p += 4; p += 4;
if ((unsigned int)(p - (unsigned char *)header) > plen) if (!CHECK_LEN(header, p, plen, 0))
return crc; /* bad packet */ return crc; /* bad packet */
} }
@@ -393,12 +416,13 @@ size_t resize_packet(HEADER *header, size_t plen, unsigned char *pheader, size_t
{ {
unsigned char *ansp = skip_questions(header, plen); unsigned char *ansp = skip_questions(header, plen);
/* if packet is malformed, just return as-is. */
if (!ansp) if (!ansp)
return 0; return plen;
if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
header, plen))) header, plen)))
return 0; return plen;
/* restore pseudoheader */ /* restore pseudoheader */
if (pheader && ntohs(header->arcount) == 0) if (pheader && ntohs(header->arcount) == 0)
@@ -432,7 +456,7 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
{ {
for (i = ntohs(header->qdcount); i != 0; i--) for (i = ntohs(header->qdcount); i != 0; i--)
{ {
if (!(ansp = skip_name(ansp, header, plen))) if (!(ansp = skip_name(ansp, header, plen, 4)))
return NULL; return NULL;
GETSHORT(type, ansp); GETSHORT(type, ansp);
@@ -458,7 +482,7 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
for (i = 0; i < arcount; i++) for (i = 0; i < arcount; i++)
{ {
unsigned char *save, *start = ansp; unsigned char *save, *start = ansp;
if (!(ansp = skip_name(ansp, header, plen))) if (!(ansp = skip_name(ansp, header, plen, 10)))
return NULL; return NULL;
GETSHORT(type, ansp); GETSHORT(type, ansp);
@@ -466,9 +490,8 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
GETSHORT(class, ansp); GETSHORT(class, ansp);
ansp += 4; /* TTL */ ansp += 4; /* TTL */
GETSHORT(rdlen, ansp); GETSHORT(rdlen, ansp);
if ((size_t)(ansp + rdlen - (unsigned char *)header) > plen) if (!ADD_RDLEN(header, ansp, plen, rdlen))
return NULL; return NULL;
ansp += rdlen;
if (type == T_OPT) if (type == T_OPT)
{ {
if (len) if (len)
@@ -508,7 +531,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
for (i = count; i != 0; i--) for (i = count; i != 0; i--)
{ {
if (!(p = skip_name(p, header, qlen))) if (!(p = skip_name(p, header, qlen, 10)))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
@@ -521,7 +544,10 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
struct doctor *doctor; struct doctor *doctor;
struct in_addr addr; struct in_addr addr;
/* alignment */ if (!CHECK_LEN(header, p, qlen, INADDRSZ))
return 0;
/* alignment */
memcpy(&addr, p, INADDRSZ); memcpy(&addr, p, INADDRSZ);
for (doctor = daemon->doctors; doctor; doctor = doctor->next) for (doctor = daemon->doctors; doctor; doctor = doctor->next)
@@ -536,10 +562,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
} }
} }
p += rdlen; if (!ADD_RDLEN(header, p, qlen, rdlen))
return 0; /* bad packet */
if ((size_t)(p - (unsigned char *)header) > qlen)
return 0; /* bad packet */
} }
return p; return p;
@@ -559,7 +583,7 @@ static int find_soa(HEADER *header, size_t qlen)
for (i = ntohs(header->nscount); i != 0; i--) for (i = ntohs(header->nscount); i != 0; i--)
{ {
if (!(p = skip_name(p, header, qlen))) if (!(p = skip_name(p, header, qlen, 10)))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
@@ -574,10 +598,10 @@ static int find_soa(HEADER *header, size_t qlen)
minttl = ttl; minttl = ttl;
/* MNAME */ /* MNAME */
if (!(p = skip_name(p, header, qlen))) if (!(p = skip_name(p, header, qlen, 0)))
return 0; return 0;
/* RNAME */ /* RNAME */
if (!(p = skip_name(p, header, qlen))) if (!(p = skip_name(p, header, qlen, 20)))
return 0; return 0;
p += 16; /* SERIAL REFRESH RETRY EXPIRE */ p += 16; /* SERIAL REFRESH RETRY EXPIRE */
@@ -585,13 +609,10 @@ static int find_soa(HEADER *header, size_t qlen)
if (ttl < minttl) if (ttl < minttl)
minttl = ttl; minttl = ttl;
} }
else else if (!ADD_RDLEN(header, p, qlen, rdlen))
p += rdlen;
if ((size_t)(p - (unsigned char *)header) > qlen)
return 0; /* bad packet */ return 0; /* bad packet */
} }
/* rewrite addresses in additioal section too */ /* rewrite addresses in additioal section too */
if (!do_doctor(p, ntohs(header->arcount), header, qlen)) if (!do_doctor(p, ntohs(header->arcount), header, qlen))
return 0; return 0;
@@ -633,7 +654,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
unsigned long cttl = ULONG_MAX, attl; unsigned long cttl = ULONG_MAX, attl;
namep = p; namep = p;
if (!extract_name(header, qlen, &p, name, 1)) if (!extract_name(header, qlen, &p, name, 1, 4))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
@@ -661,8 +682,8 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
{ {
unsigned char *tmp = namep; unsigned char *tmp = namep;
/* the loop body overwrites the original name, so get it back here. */ /* the loop body overwrites the original name, so get it back here. */
if (!extract_name(header, qlen, &tmp, name, 1) || if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
!(res = extract_name(header, qlen, &p1, name, 0))) !(res = extract_name(header, qlen, &p1, name, 0, 10)))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(aqtype, p1); GETSHORT(aqtype, p1);
@@ -677,7 +698,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR)) if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
{ {
if (!extract_name(header, qlen, &p1, name, 1)) if (!extract_name(header, qlen, &p1, name, 1, 0))
return 0; return 0;
if (aqtype == T_CNAME) if (aqtype == T_CNAME)
@@ -692,7 +713,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
} }
p1 = endrr; p1 = endrr;
if ((size_t)(p1 - (unsigned char *)header) > qlen) if (!CHECK_LEN(header, p1, qlen, 0))
return 0; /* bad packet */ return 0; /* bad packet */
} }
} }
@@ -737,7 +758,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
for (j = ntohs(header->ancount); j != 0; j--) for (j = ntohs(header->ancount); j != 0; j--)
{ {
if (!(res = extract_name(header, qlen, &p1, name, 0))) if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(aqtype, p1); GETSHORT(aqtype, p1);
@@ -763,14 +784,17 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
if (attl < cttl) if (attl < cttl)
cttl = attl; cttl = attl;
if (!extract_name(header, qlen, &p1, name, 1)) if (!extract_name(header, qlen, &p1, name, 1, 0))
return 0; return 0;
goto cname_loop1; goto cname_loop1;
} }
else else
{ {
found = 1; found = 1;
/* copy address into aligned storage */ /* copy address into aligned storage */
if (!CHECK_LEN(header, p1, qlen, addrlen))
return 0; /* bad packet */
memcpy(&addr, p1, addrlen); memcpy(&addr, p1, addrlen);
/* check for returned address in private space */ /* check for returned address in private space */
@@ -790,7 +814,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
} }
p1 = endrr; p1 = endrr;
if ((size_t)(p1 - (unsigned char *)header) > qlen) if (!CHECK_LEN(header, p1, qlen, 0))
return 0; /* bad packet */ return 0; /* bad packet */
} }
} }
@@ -839,7 +863,7 @@ unsigned short extract_request(HEADER *header, size_t qlen, char *name, unsigned
if (ntohs(header->qdcount) != 1 || header->opcode != QUERY) if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
return 0; /* must be exactly one query. */ return 0; /* must be exactly one query. */
if (!extract_name(header, qlen, &p, name, 1)) if (!extract_name(header, qlen, &p, name, 1, 4))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
@@ -953,7 +977,7 @@ int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
for (i = ntohs(header->ancount); i != 0; i--) for (i = ntohs(header->ancount); i != 0; i--)
{ {
if (!extract_name(header, qlen, &p, name, 1)) if (!extract_name(header, qlen, &p, name, 1, 10))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
@@ -962,19 +986,25 @@ int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (qclass == C_IN && qtype == T_A) if (qclass == C_IN && qtype == T_A)
for (baddrp = baddr; baddrp; baddrp = baddrp->next) {
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) if (!CHECK_LEN(header, p, qlen, INADDRSZ))
{ return 0;
/* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */ for (baddrp = baddr; baddrp; baddrp = baddrp->next)
cache_start_insert(); if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG); {
cache_end_insert(); /* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */
return 1; cache_start_insert();
} cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
cache_end_insert();
return 1;
}
}
p += rdlen; if (!ADD_RDLEN(header, p, qlen, rdlen))
return 0;
} }
return 0; return 0;
@@ -1073,6 +1103,18 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp, unsigne
return 1; return 1;
} }
static unsigned long crec_ttl(struct crec *crecp, time_t now)
{
/* Return 0 ttl for DHCP entries, which might change
before the lease expires. */
if (crecp->flags & (F_IMMORTAL | F_DHCP))
return daemon->local_ttl;
return crecp->ttd - now;
}
/* return zero if we can't answer from cache, or packet size if we can */ /* return zero if we can't answer from cache, or packet size if we can */
size_t answer_request(HEADER *header, char *limit, size_t qlen, size_t answer_request(HEADER *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask, time_t now) struct in_addr local_addr, struct in_addr local_netmask, time_t now)
@@ -1137,7 +1179,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
nameoffset = p - (unsigned char *)header; nameoffset = p - (unsigned char *)header;
/* now extract name as .-concatenated string into name */ /* now extract name as .-concatenated string into name */
if (!extract_name(header, qlen, &p, name, 1)) if (!extract_name(header, qlen, &p, name, 1, 4))
return 0; /* bad packet */ return 0; /* bad packet */
GETSHORT(qtype, p); GETSHORT(qtype, p);
@@ -1239,18 +1281,11 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
auth = 0; auth = 0;
if (!dryrun) if (!dryrun)
{ {
unsigned long ttl;
/* Return 0 ttl for DHCP entries, which might change
before the lease expires. */
if (crecp->flags & (F_IMMORTAL | F_DHCP))
ttl = daemon->local_ttl;
else
ttl = crecp->ttd - now;
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
record_source(daemon->addn_hosts, crecp->uid)); record_source(daemon->addn_hosts, crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), NULL,
T_PTR, C_IN, "d", cache_get_name(crecp))) T_PTR, C_IN, "d", cache_get_name(crecp)))
anscount++; anscount++;
} }
@@ -1358,7 +1393,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
if (!dryrun) if (!dryrun)
{ {
log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid)); log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, crecp->ttd - now, &nameoffset, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), &nameoffset,
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache))) T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
anscount++; anscount++;
} }
@@ -1391,17 +1427,11 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
ans = 1; ans = 1;
if (!dryrun) if (!dryrun)
{ {
unsigned long ttl;
if (crecp->flags & (F_IMMORTAL | F_DHCP))
ttl = daemon->local_ttl;
else
ttl = crecp->ttd - now;
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr, log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
record_source(daemon->addn_hosts, crecp->uid)); record_source(daemon->addn_hosts, crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, type, C_IN, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), NULL, type, C_IN,
type == T_A ? "4" : "6", &crecp->addr)) type == T_A ? "4" : "6", &crecp->addr))
anscount++; anscount++;
} }
@@ -1529,7 +1559,6 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
crecp = NULL; crecp = NULL;
while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6))) while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
{ {
unsigned long ttl;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
int type = crecp->flags & F_IPV4 ? T_A : T_AAAA; int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
#else #else
@@ -1538,12 +1567,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
if (crecp->flags & F_NEG) if (crecp->flags & F_NEG)
continue; continue;
if (crecp->flags & (F_IMMORTAL | F_DHCP)) if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
ttl = daemon->local_ttl; crec_ttl(crecp, now), NULL, type, C_IN,
else
ttl = crecp->ttd - now;
if (add_resource_record(header, limit, NULL, rec->offset, &ansp, ttl, NULL, type, C_IN,
crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr)) crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
addncount++; addncount++;
} }
+116 -63
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -90,14 +90,14 @@ static void do_options(struct dhcp_context *context,
struct dhcp_packet *mess, struct dhcp_packet *mess,
unsigned char *real_end, unsigned char *real_end,
unsigned char *req_options, unsigned char *req_options,
char *hostname, char *hostname,
char *domain, char *config_domain,
struct dhcp_netid *netid, struct dhcp_netid *netid,
struct in_addr subnet_addr, struct in_addr subnet_addr,
unsigned char fqdn_flags, unsigned char fqdn_flags,
int null_term, int null_term,
unsigned char *agent_id); unsigned char *agent_id);
static unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out);
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
@@ -112,13 +112,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0; int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0;
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
unsigned char *end = (unsigned char *)(mess + 1); unsigned char *end = (unsigned char *)(mess + 1);
char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL; char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
int hostname_auth = 0, borken_opt = 0; int hostname_auth = 0, borken_opt = 0;
unsigned char *req_options = NULL; unsigned char *req_options = NULL;
char *message = NULL; char *message = NULL;
unsigned int time; unsigned int time;
struct dhcp_config *config; struct dhcp_config *config;
struct dhcp_netid *netid = NULL; struct dhcp_netid *netid;
struct in_addr subnet_addr, fallback, override; struct in_addr subnet_addr, fallback, override;
unsigned short fuzz = 0; unsigned short fuzz = 0;
unsigned int mess_type = 0; unsigned int mess_type = 0;
@@ -126,9 +126,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
unsigned char *agent_id = NULL; unsigned char *agent_id = NULL;
unsigned char *emac = NULL; unsigned char *emac = NULL;
int emac_len = 0; int emac_len = 0;
struct dhcp_netid known_id; struct dhcp_netid known_id, iface_id;
subnet_addr.s_addr = override.s_addr = 0; subnet_addr.s_addr = override.s_addr = 0;
/* set tag with name == interface */
iface_id.net = iface_name;
iface_id.next = NULL;
netid = &iface_id;
if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX) if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
return 0; return 0;
@@ -359,8 +364,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
end = mess->options + 64; /* BOOTP vend area is only 64 bytes */ end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
if (have_config(config, CONFIG_NAME)) if (have_config(config, CONFIG_NAME))
hostname = config->hostname; {
hostname = config->hostname;
domain = config->domain;
}
if (have_config(config, CONFIG_NETID)) if (have_config(config, CONFIG_NETID))
{ {
config->netid.next = netid; config->netid.next = netid;
@@ -389,8 +397,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (!message) if (!message)
{ {
int nailed = 0;
if (have_config(config, CONFIG_ADDR)) if (have_config(config, CONFIG_ADDR))
{ {
nailed = 1;
logaddr = &config->addr; logaddr = &config->addr;
mess->yiaddr = config->addr; mess->yiaddr = config->addr;
if ((lease = lease_find_by_addr(config->addr)) && if ((lease = lease_find_by_addr(config->addr)) &&
@@ -399,8 +410,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0)) memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
message = _("address in use"); message = _("address in use");
} }
else if (!(daemon->options & OPT_BOOTP_DYNAMIC))
message = _("no address configured");
else else
{ {
if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) || if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
@@ -419,27 +428,35 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
mess->yiaddr = lease->addr; mess->yiaddr = lease->addr;
} }
if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
message = _("wrong network");
else if (context->netid.net)
{
context->netid.next = netid;
netid = &context->netid;
}
if (!message && !nailed)
{
for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
if ((!id_list->list) || match_netid(id_list->list, netid, 0))
break;
if (!id_list)
message = _("no address configured");
}
if (!message && if (!message &&
!lease && !lease &&
(!(lease = lease_allocate(mess->yiaddr)))) (!(lease = lease_allocate(mess->yiaddr))))
message = _("no leases left"); message = _("no leases left");
if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
message = _("wrong network");
if (!message) if (!message)
{ {
logaddr = &mess->yiaddr; logaddr = &mess->yiaddr;
if (context->netid.net)
{
context->netid.next = netid;
netid = &context->netid;
}
lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0); lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
if (hostname) if (hostname)
lease_set_hostname(lease, hostname, daemon->domain_suffix, 1); lease_set_hostname(lease, hostname, 1);
/* infinite lease unless nailed in dhcp-host line. */ /* infinite lease unless nailed in dhcp-host line. */
lease_set_expires(lease, lease_set_expires(lease,
have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff, have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
@@ -447,8 +464,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease_set_interface(lease, int_index); lease_set_interface(lease, int_index);
clear_packet(mess, end, NULL); clear_packet(mess, end, NULL);
do_options(context, mess, end, NULL, do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
hostname, netid, subnet_addr, 0, 0, NULL); domain, netid, subnet_addr, 0, 0, NULL);
} }
} }
@@ -518,6 +535,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (have_config(config, CONFIG_NAME)) if (have_config(config, CONFIG_NAME))
{ {
hostname = config->hostname; hostname = config->hostname;
domain = config->domain;
hostname_auth = 1; hostname_auth = 1;
/* be careful not to send an OFFER with a hostname not matching the DISCOVER. */ /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname)) if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
@@ -525,9 +543,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
} }
else if (client_hostname) else if (client_hostname)
{ {
char *d = strip_hostname(client_hostname); domain = strip_hostname(client_hostname);
if (d)
my_syslog(LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), d, client_hostname);
if (strlen(client_hostname) != 0) if (strlen(client_hostname) != 0)
{ {
@@ -540,7 +556,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0, struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
mess->chaddr, mess->hlen, mess->chaddr, mess->hlen,
mess->htype, hostname); mess->htype, hostname);
if (new && !have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR)) if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
{ {
config = new; config = new;
/* set "known" tag for known hosts */ /* set "known" tag for known hosts */
@@ -710,7 +726,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{ {
char *addrs = inet_ntoa(config->addr); char *addrs = inet_ntoa(config->addr);
if ((ltmp = lease_find_by_addr(config->addr)) && ltmp != lease) if ((ltmp = lease_find_by_addr(config->addr)) &&
ltmp != lease &&
!config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
{ {
int len; int len;
unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len, unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
@@ -771,8 +789,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_T1, 4, (time/2)); option_put(mess, end, OPTION_T1, 4, (time/2));
option_put(mess, end, OPTION_T2, 4, (time*7)/8); option_put(mess, end, OPTION_T2, 4, (time*7)/8);
} }
do_options(context, mess, end, req_options, offer_hostname, do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
netid, subnet_addr, fqdn_flags, borken_opt, agent_id); domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
return dhcp_packet_size(mess, netid); return dhcp_packet_size(mess, netid);
@@ -797,14 +815,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (option_addr(opt).s_addr != override.s_addr) if (option_addr(opt).s_addr != override.s_addr)
return 0; return 0;
} }
else else
{ {
for (; context; context = context->current) for (; context; context = context->current)
if (context->local.s_addr == option_addr(opt).s_addr) if (context->local.s_addr == option_addr(opt).s_addr)
break; break;
if (!context) if (!context)
return 0; {
/* In auth mode, a REQUEST sent to the wrong server
should be faulted, so that the client establishes
communication with us, otherwise, silently ignore. */
if (!(daemon->options & OPT_AUTHORITATIVE))
return 0;
message = _("wrong server-ID");
}
} }
/* If a lease exists for this host and another address, squash it. */ /* If a lease exists for this host and another address, squash it. */
@@ -888,18 +913,33 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config) else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
message = _("address reserved"); message = _("address reserved");
else if ((ltmp = lease_find_by_addr(mess->yiaddr)) && ltmp != lease) else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
message = _("address in use"); {
/* If a host is configured with more than one MAC address, it's OK to 'nix
else if (emac_len == 0) a lease from one of it's MACs to give the address to another. */
message = _("no unique-id"); if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
{
else if (!lease) my_syslog(LOG_INFO, _("abandoning lease to %s of %s"),
{ print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
if ((lease = lease_allocate(mess->yiaddr))) inet_ntoa(ltmp->addr));
do_classes = 1; lease = ltmp;
}
else else
message = _("no leases left"); message = _("address in use");
}
if (!message)
{
if (emac_len == 0)
message = _("no unique-id");
else if (!lease)
{
if ((lease = lease_allocate(mess->yiaddr)))
do_classes = 1;
else
message = _("no leases left");
}
} }
} }
@@ -984,7 +1024,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
hostname = NULL; hostname = NULL;
} }
if (hostname) if (hostname)
lease_set_hostname(lease, hostname, daemon->domain_suffix, hostname_auth); lease_set_hostname(lease, hostname, hostname_auth);
lease_set_expires(lease, time, now); lease_set_expires(lease, time, now);
lease_set_interface(lease, int_index); lease_set_interface(lease, int_index);
@@ -1007,8 +1047,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz); option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz); option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
} }
do_options(context, mess, end, req_options, hostname, do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
netid, subnet_addr, fqdn_flags, borken_opt, agent_id); domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
} }
return dhcp_packet_size(mess, netid); return dhcp_packet_size(mess, netid);
@@ -1063,8 +1103,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease_set_interface(lease, int_index); lease_set_interface(lease, int_index);
} }
do_options(context, mess, end, req_options, hostname, do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
netid, subnet_addr, fqdn_flags, borken_opt, agent_id); domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
*is_inform = 1; /* handle reply differently */ *is_inform = 1; /* handle reply differently */
return dhcp_packet_size(mess, netid); return dhcp_packet_size(mess, netid);
@@ -1081,7 +1121,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
then the client-id is using the usual encoding and use the rest of the then the client-id is using the usual encoding and use the rest of the
client-id: if not we can use the whole client-id. This should give client-id: if not we can use the whole client-id. This should give
sane MAC address logs. */ sane MAC address logs. */
static unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out) int clid_len, unsigned char *clid, int *len_out)
{ {
if (hwlen == 0 && clid && clid_len > 3) if (hwlen == 0 && clid && clid_len > 3)
@@ -1291,6 +1331,7 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
unsigned char *overload; unsigned char *overload;
size_t ret; size_t ret;
struct dhcp_netid_list *id_list; struct dhcp_netid_list *id_list;
struct dhcp_netid *n;
/* We do logging too */ /* We do logging too */
if (netid && (daemon->options & OPT_LOG_OPTS)) if (netid && (daemon->options & OPT_LOG_OPTS))
@@ -1299,9 +1340,17 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
*p = 0; *p = 0;
for (; netid; netid = netid->next) for (; netid; netid = netid->next)
{ {
strncat (p, netid->net, MAXDNAME); /* kill dupes. */
if (netid->next) for (n = netid->next; n; n = n->next)
strncat (p, ", ", MAXDNAME); if (strcmp(netid->net, n->net) == 0)
break;
if (!n)
{
strncat (p, netid->net, MAXDNAME);
if (netid->next)
strncat (p, ", ", MAXDNAME);
}
} }
p[MAXDNAME - 1] = 0; p[MAXDNAME - 1] = 0;
my_syslog(LOG_INFO, _("tags: %s"), p); my_syslog(LOG_INFO, _("tags: %s"), p);
@@ -1531,7 +1580,8 @@ static void do_options(struct dhcp_context *context,
struct dhcp_packet *mess, struct dhcp_packet *mess,
unsigned char *real_end, unsigned char *real_end,
unsigned char *req_options, unsigned char *req_options,
char *hostname, char *hostname,
char *domain, char *config_domain,
struct dhcp_netid *netid, struct dhcp_netid *netid,
struct in_addr subnet_addr, struct in_addr subnet_addr,
unsigned char fqdn_flags, unsigned char fqdn_flags,
@@ -1545,6 +1595,9 @@ static void do_options(struct dhcp_context *context,
unsigned char f0 = 0, s0 = 0; unsigned char f0 = 0, s0 = 0;
int done_file = 0, done_server = 0; int done_file = 0, done_server = 0;
if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
my_syslog(LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname);
/* logging */ /* logging */
if ((daemon->options & OPT_LOG_OPTS) && req_options) if ((daemon->options & OPT_LOG_OPTS) && req_options)
{ {
@@ -1681,9 +1734,9 @@ static void do_options(struct dhcp_context *context,
!option_find2(netid, config_opts, OPTION_DNSSERVER)) !option_find2(netid, config_opts, OPTION_DNSSERVER))
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr)); option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
if (daemon->domain_suffix && in_list(req_options, OPTION_DOMAINNAME) && if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
!option_find2(netid, config_opts, OPTION_DOMAINNAME)) !option_find2(netid, config_opts, OPTION_DOMAINNAME))
option_put_string(mess, end, OPTION_DOMAINNAME, daemon->domain_suffix, null_term); option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
/* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */ /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
if (hostname) if (hostname)
@@ -1700,8 +1753,8 @@ static void do_options(struct dhcp_context *context,
else if (null_term) else if (null_term)
len++; len++;
if (daemon->domain_suffix) if (domain)
len += strlen(daemon->domain_suffix) + 1; len += strlen(domain) + 1;
if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len))) if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
{ {
@@ -1712,19 +1765,19 @@ static void do_options(struct dhcp_context *context,
if (fqdn_flags & 0x04) if (fqdn_flags & 0x04)
{ {
p = do_rfc1035_name(p, hostname); p = do_rfc1035_name(p, hostname);
if (daemon->domain_suffix) if (domain)
p = do_rfc1035_name(p, daemon->domain_suffix); p = do_rfc1035_name(p, domain);
*p++ = 0; *p++ = 0;
} }
else else
{ {
memcpy(p, hostname, strlen(hostname)); memcpy(p, hostname, strlen(hostname));
p += strlen(hostname); p += strlen(hostname);
if (daemon->domain_suffix) if (domain)
{ {
*(p++) = '.'; *(p++) = '.';
memcpy(p, daemon->domain_suffix, strlen(daemon->domain_suffix)); memcpy(p, domain, strlen(domain));
p += strlen(daemon->domain_suffix); p += strlen(domain);
} }
if (null_term) if (null_term)
*(p++) = 0; *(p++) = 0;
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley /* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by