Compare commits

..

2 Commits
v2.44 ... v2.46

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

View File

@@ -2595,7 +2595,100 @@ version 2.44
Jean Wolter for finding this.
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
David Gilman.
Update Spanish translation. Thanks to Christopher Chatham.
version 2.45
Fix total DNS failure in release 2.44 unless --min-port
specified. Thanks to Steven Barth and Grant Coady for
bugreport. Also reject out-of-range port spec, which could
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
FAQ
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
specified, the operating system will select an available port number
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
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,
dhcpcd uses the "-I" flag. Windows uses a registry setting,
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?

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
# it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
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 \
helper.o tftp.o log.o

Binary file not shown.

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
and a single object: /uk/org/thekelleys/dnsmasq
1. METHODS
----------
Methods are of the form
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
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.

View File

@@ -122,6 +122,12 @@
# 3) Provides the domain part for "expand-hosts"
#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
# 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
@@ -157,6 +163,14 @@
# 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
# 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
# 192.168.0.70 and an infinite lease
#dhcp-host=bert,192.168.0.70,infinite
@@ -270,12 +284,12 @@
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
# adapted for a typical dnsmasq installation where the host running
# 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=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=46,8 # netbios node type
#dhcp-option=47 # empty netbios scope.
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
# probably doesn't support this......
@@ -458,6 +472,10 @@
#Example zeroconf
#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
# dnsmasq.

View File

@@ -385,6 +385,14 @@ Return a PTR DNS record.
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
Return an NAPTR DNS record, as specified in RFC3403.
.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>
Return a DNS record associating the name with the primary address on
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
allowed to specify the client ID as text, like this:
.B --dhcp-host=id:clientidastext,.....
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
but not others.
If a name appears in /etc/hosts, the associated address can be
allocated to a DHCP lease, but only if a
.B --dhcp-host
@@ -478,8 +488,10 @@ instance
.B --dhcp-host=00:20:e0:3b:13:af,ignore
This is
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
whenever this dhcp-host directive is in use.This can be used to
be used by some machines.
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
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
@@ -490,13 +502,25 @@ wildcard bytes, so for example
.B --dhcp-host=00:20:e0:3b:13:*,ignore
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
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
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
will only match a
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
.B --dhcp-hostsfile=<file>
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
specification of both server and client ports for DHCP.
.TP
.B \-3, --bootp-dynamic
.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
Enable dynamic allocation of IP addresses to BOOTP clients. Use this
with care, since each address allocated to a BOOTP client is leased
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
.B \-5, --no-ping
By default, the DHCP server will attempt to ensure that an address in
@@ -723,18 +749,22 @@ removed in a future release.
.TP
.B \-6 --dhcp-script=<path>
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
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
been destroyed, "old" is a notification of an existing lease when
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).
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.
The environment is inherited from the invoker of dnsmasq, and if the
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
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
"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
packets arrive at tap interfaces which don't have an IP address.
.TP
.B \-s, --domain=<domain>
Specifies the domain for the DHCP server. This has two effects;
.B \-s, --domain=<domain>[,<address range>]
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
which request it, and secondly it sets the domain which it is legal
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
both as "laptop" and "laptop.thekelleys.org.uk". If the domain is
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
.B --enable-tftp
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
used to allocate the address, one from any matching
.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
classes sent by the DHCP client. Any
.B dhcp-option

View File

@@ -414,8 +414,15 @@ Retornar un r
.B --naptr-record=<nombre>,<orden>,<preferencia>,<opciones>,<servicio>,<regexp>[,<remplazo>]
Retornar un récord DNS NAPTR, como especificado en RFC3403.
.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>
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
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
@@ -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.
También se permite especificar el ID de cliente como texto, así:
.B --dhcp-host=id:iddeclientecomotexto,.....
La opción especial id:* significa "ignorar cualquier ID de cliente
y usar solamente direcciones MAC." Esto es útil cuando un cliente
presenta un ID de cliente algunas veces pero otras no.
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
.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
hardware, ID de cliente, o nombre de host, por ejemplo:
.B --dhcp-host=00:20:e0:3b:13:af,ignore
Esto es útil cuando hay otro servidor DHCP en la red para ser
usado por algúnas máquinas. El net:<network-id> fija la etiqueta
network-id cuando sea que esta directiva dhcp-host está en uso.
Esto puede ser usado para enviar selectivamente opciones DHCP
a este host. Cuando un host coincide con cualquier directiva
dhcp-host (o una implicada por /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
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 network-id cuando sea que
esta directiva dhcp-host está en uso. Esto puede ser usado para
enviar selectivamente opciones DHCP a este host. Cuando un host
coincide con cualquier directiva dhcp-host (o una implicada por
/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
Direcciones ethernet (pero no client-ids) pueden tener bytes
comodínes, así que por ejemplo
@@ -526,12 +537,23 @@ comod
causará que dnsmasq ignore un rango de direcciones ethernet. Nótese
que el "*" necesitará ser escapado o escrito entre comillas en la
línea de comandos, pero no en el archivo de configuración.
Direcciones de hardware normalmente coinciden con cualquier
tipo de red (ARP), pero es posible restringirlas a un tipo ARP
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
solo coincidiría con una dirección de hardware Token-Ring, dado que
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
.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.
@@ -731,11 +753,14 @@ es usado para el servidor y el n
para el cliente. Finalmente, dos números permiten que se especifiquen
ambos los puertos de servidor y cliente para DHCP.
.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
esto con cuidado, ya que cada dirección alocada a un cliente BOOTP
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
.B \-5, --no-ping
Por predetermindado, el servidor DHCP tratará de asegurarse que una
@@ -763,20 +788,24 @@ en instalaciones nuevas, y ser
.TP
.B \-6 --dhcp-script=<path>
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
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
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
existente (también, tiempo de arriendo o vencimiento y client-id, si
leasefile-ro está fijado). 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.
leasefile-ro está fijado). Si la dirección MAC es de un tipo de red
que no es ethernet, tendrá el tipo de red precolocado, por ejemplo
"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
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
o usuario, estos son brindados en las variables DNSMASQ_VENDOR_CLASS y
DNSMASQ_CLIENT_ID. Si el dominio completamente calificado del host
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"
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.
@@ -829,11 +858,12 @@ est
puentes "estilo viejo", ya que los paquetes llegan a interfaces tap que no
tienen una dirección IP.
.TP
.B \-s, --domain=<dominio>
Especifica el dominio para el servidor DHCP. Esto tiene dos efectos:
Primeramente, causa que el servidor DHCP le devuelva el 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
.B \-s, --domain=<dominio>[,<rango de IPs>]
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
brindados incondicionalmente (sin el rango de IPs) o para rangos limitados. Esto
tiene dos efectos: Primeramente, causa que el servidor DHCP le devuelva el
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
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
@@ -850,7 +880,28 @@ de esa m
.B dnsmasq
como "laptop" y "laptop.thekelleys.org.uk". Si el dominio es brindado
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
.B --enable-tftp
Habilitar la función de servidor TFTP. Esto está deliberadamente limitado
@@ -1056,9 +1107,11 @@ una del
.B dhcp-range
usado para alocar la dirección, una de cualquier
.B dhcp-host
que coincida, y posiblemente muchas de clases de vendedor y usuario
que coinicdan que hayan sido enviadas por el cliente DHCP.
Cualquier opción
que coincida (y "known" si un dhcp-host coincide), la etiqueta "bootp"
para pedidos BOOTP, una etiqueta cuyo nombre es el nombre de la
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
que tenga etiquetas network-id será usada en preferencia de una opción
.B dhcp-option,

662
po/de.po

File diff suppressed because it is too large Load Diff

620
po/es.po

File diff suppressed because it is too large Load Diff

662
po/fi.po

File diff suppressed because it is too large Load Diff

620
po/fr.po

File diff suppressed because it is too large Load Diff

635
po/id.po

File diff suppressed because it is too large Load Diff

662
po/it.po

File diff suppressed because it is too large Load Diff

617
po/no.po

File diff suppressed because it is too large Load Diff

606
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

617
po/ro.po

File diff suppressed because it is too large Load Diff

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
it under the terms of the GNU General Public License as published by

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
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)
{
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. */
if (lookup && (lookup->flags & F_HOSTS) &&
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
free(cache);
else
if (lookup && (lookup->flags & F_HOSTS))
{
/* Ensure there is only one address -> name mapping (first one trumps)
We do this by steam here, first we see if the address is the same as
the last one we saw, which eliminates most in the case of an ad-block
file with thousands of entries for the same address.
Then we search and bail at the first matching address that came from
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)
flags &= ~F_REVERSE;
else
for (i=0; i<hash_size; i++)
{
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;
}
if (lookup)
nameexists = 1;
if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
{
free(cache);
return;
}
}
/* Ensure there is only one address -> name mapping (first one trumps)
We do this by steam here, first we see if the address is the same as
the last one we saw, which eliminates most in the case of an ad-block
file with thousands of entries for the same address.
Then we search and bail at the first matching address that came from
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)
flags &= ~F_REVERSE;
else
for (i=0; i<hash_size; i++)
{
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;
}
}
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;
cache->uid = index;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache);
if (c == EOF)
return 1;
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");
char *line;
char *token = daemon->namebuff, *domain_suffix = NULL;
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;
int atnl, addrlen = 0, addr_dup;
if (!f)
{
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
return 0;
}
while ((line = fgets(buff, MAXDNAME, f)))
eatspace(f);
while ((atnl = gettok(f, token)) != EOF)
{
char *token = strtok(line, " \t\n\r");
int addrlen, addr_dup = 0;
addr_dup = 0;
lineno++;
if (!token || (*token == '#'))
continue;
#ifdef HAVE_IPV6
if (inet_pton(AF_INET, token, &addr) > 0)
{
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
addrlen = INADDRSZ;
domain_suffix = get_domain(addr.addr.addr4);
}
else if (inet_pton(AF_INET6, token, &addr) > 0)
{
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
addrlen = IN6ADDRSZ;
domain_suffix = daemon->domain_suffix;
}
#else
if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
{
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
addrlen = INADDRSZ;
if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
{
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
addrlen = INADDRSZ;
domain_suffix = get_domain(addr.addr.addr4);
}
#endif
else
{
my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
while (atnl == 0)
atnl = gettok(f, token);
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);
rehash(name_count);
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_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;
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;
}
if ((opts & OPT_NO_HOSTS) && !addn_hosts)
if ((daemon->options & OPT_NO_HOSTS) && !addn_hosts)
{
if (daemon->cachesize > 0)
my_syslog(LOG_INFO, _("cleared cache"));
return;
}
if (!(opts & OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, opts, buff, domain_suffix, 0, total_size);
if (!(daemon->options & OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, 0, total_size);
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;
}
}
@@ -851,13 +925,11 @@ void cache_unhash_dhcp(void)
void cache_add_dhcp_entry(char *host_name,
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;
int in_hosts = 0;
if (!host_name)
return;
struct cname *a;
while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME)))
{
/* check all addresses associated with name */
@@ -911,10 +983,34 @@ void cache_add_dhcp_entry(char *host_name,
crec->ttd = ttd;
crec->addr.addr.addr.addr4 = *host_address;
crec->name.namep = host_name;
crec->uid = uid++;
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)
{
struct server *serv, *serv1;

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
it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define VERSION "2.44"
#define VERSION "2.46"
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#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
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
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
BSD systems.
HAVE_LARGFILE
Define this if the C library supports large (>2GB) files probably true everywhere
except some builds of uclibc
NOTES:
For Linux you should define
@@ -166,13 +159,8 @@ NOTES:
/* platform independent options- uncomment to enable */
#define HAVE_TFTP
/* #define HAVE_BROKEN_RTC */
/* #define HAVE_ISC_READER */
/* #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 */
#ifdef NO_TFTP
#undef HAVE_TFTP

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
it under the terms of the GNU General Public License as published by
@@ -283,7 +283,10 @@ char *dbus_init(void)
daemon->dbus = connection;
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;
}
@@ -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

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
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;
}
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_context *context,
@@ -643,7 +656,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
int hw_type, char *hostname)
{
struct dhcp_config *config;
struct hwaddr_config *conf_addr;
if (clid)
for (config = configs; config; config = config->next)
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)
if ((config->flags & CONFIG_HWADDR) &&
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 &&
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
is_addr_in_context(context, config))
return config;
@@ -679,14 +689,14 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
return config;
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_HWADDR) &&
config->wildcard_mask != 0 &&
config->hwaddr_len == hw_len &&
(config->hwaddr_type == hw_type || config->hwaddr_type == 0) &&
is_addr_in_context(context, config) &&
memcmp_masked(config->hwaddr, hwaddr, hw_len, config->wildcard_mask))
return config;
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
if (conf_addr->wildcard_mask != 0 &&
conf_addr->hwaddr_len == hw_len &&
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
is_addr_in_context(context, config) &&
memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask))
return config;
return NULL;
}
@@ -720,6 +730,7 @@ void dhcp_read_ethers(void)
/* cannot have a clid */
if (config->flags & CONFIG_NAME)
free(config->hostname);
free(config->hwaddr);
free(config);
}
else
@@ -766,7 +777,7 @@ void dhcp_read_ethers(void)
}
else
{
if (!canonicalise(ip) || strip_hostname(ip))
if (!canonicalise(ip))
{
my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
continue;
@@ -782,19 +793,24 @@ void dhcp_read_ethers(void)
if (!config)
{
for (config = daemon->dhcp_conf; config; config = config->next)
if ((config->flags & CONFIG_HWADDR) &&
config->wildcard_mask == 0 &&
config->hwaddr_len == ETHER_ADDR_LEN &&
(config->hwaddr_type == ARPHRD_ETHER || config->hwaddr_type == 0) &&
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
break;
{
struct hwaddr_config *conf_addr = config->hwaddr;
if (conf_addr &&
conf_addr->next == NULL &&
conf_addr->wildcard_mask == 0 &&
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 = whine_malloc(sizeof(struct dhcp_config))))
continue;
config->flags = CONFIG_FROM_ETHERS;
config->wildcard_mask = 0;
config->hwaddr = NULL;
config->domain = NULL;
config->next = daemon->dhcp_conf;
daemon->dhcp_conf = config;
}
@@ -813,10 +829,17 @@ void dhcp_read_ethers(void)
config->addr = addr;
}
config->flags |= CONFIG_HWADDR | CONFIG_NOCLID;
memcpy(config->hwaddr, hwaddr, ETHER_ADDR_LEN);
config->hwaddr_len = ETHER_ADDR_LEN;
config->hwaddr_type = ARPHRD_ETHER;
config->flags |= CONFIG_NOCLID;
if (!config->hwaddr)
config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
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++;
}
@@ -852,15 +875,9 @@ void check_dhcp_hosts(int fatal)
configs->flags &= ~CONFIG_ADDR;
}
/* split off domain part */
if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
{
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;
}
configs->domain = domain;
}
}
}
@@ -918,6 +935,7 @@ char *host_from_dns(struct in_addr addr)
{
struct crec *lookup;
char *hostname = NULL;
char *d1, *d2;
if (daemon->port == 0)
return NULL; /* DNS disabled. */
@@ -928,14 +946,16 @@ char *host_from_dns(struct in_addr addr)
hostname = daemon->dhcp_buff;
strncpy(hostname, cache_get_name(lookup), 256);
hostname[255] = 0;
if (strip_hostname(hostname))
d1 = strip_hostname(hostname);
d2 = get_domain(addr);
if (d1 && (!d2 || hostname_isequal(d1, d2)))
hostname = NULL;
}
return hostname;
}
/* return illegal domain or NULL if OK */
/* return domain or NULL if none. */
char *strip_hostname(char *hostname)
{
char *dot = strchr(hostname, '.');
@@ -944,9 +964,20 @@ char *strip_hostname(char *hostname)
return NULL;
*dot = 0; /* truncate */
if (*(dot+1) && (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix)))
if (strlen(dot+1) != 0)
return dot+1;
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;
}

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
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
"BSD-bridge "
#endif
#ifndef HAVE_ISC_READER
"no-"
#endif
"ISC-leasefile "
#ifndef HAVE_DBUS
"no-"
#endif
@@ -66,7 +62,7 @@ static void poll_resolv(void);
int main (int argc, char **argv)
{
int bind_fallback = 0;
time_t now, last = 0;
time_t now;
struct sigaction sigact;
struct iname *if_tmp;
int piperead, pipefd[2], err_pipe[2];
@@ -117,10 +113,6 @@ int main (int argc, char **argv)
if (daemon->dhcp)
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} */
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. */
/* 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;
#ifdef HAVE_ISC_READER
if (daemon->lease_file && !daemon->dhcp)
load_dhcp(now);
#endif
daemon->last_resolv = now;
if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
poll_resolv();
@@ -912,7 +901,7 @@ static void poll_resolv()
warned = 0;
check_servers();
if (daemon->options & OPT_RELOAD)
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
cache_reload(daemon->addn_hosts);
}
else
{
@@ -929,7 +918,7 @@ static void poll_resolv()
void clear_cache_and_reload(time_t now)
{
if (daemon->port != 0)
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
cache_reload(daemon->addn_hosts);
if (daemon->dhcp)
{

View File

@@ -172,7 +172,7 @@ struct event_desc {
#define OPT_AUTHORITATIVE (1u<<17)
#define OPT_LOCALISE (1u<<18)
#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_LEASE_RO (1u<<22)
#define OPT_ALL_SERVERS (1u<<23)
@@ -229,6 +229,11 @@ struct ptr_record {
struct ptr_record *next;
};
struct cname {
char *alias, *target;
struct cname *next;
};
struct interface_name {
char *name; /* domain name */
char *intr; /* interface name */
@@ -425,23 +430,28 @@ struct dhcp_netid_list {
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 {
unsigned int flags;
int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
char *hostname;
char *hostname, *domain;
struct dhcp_netid netid;
struct in_addr addr;
time_t decline_time;
unsigned int lease_time, wildcard_mask;
unsigned int lease_time;
struct hwaddr_config *hwaddr;
struct dhcp_config *next;
};
#define CONFIG_DISABLE 1
#define CONFIG_CLID 2
#define CONFIG_HWADDR 4
#define CONFIG_TIME 8
#define CONFIG_NAME 16
#define CONFIG_ADDR 32
@@ -503,6 +513,12 @@ struct dhcp_bridge {
};
#endif
struct cond_domain {
char *domain;
struct in_addr start, end;
struct cond_domain *next;
};
struct dhcp_context {
unsigned int lease_time, addr_epoch;
struct in_addr netmask, broadcast;
@@ -565,16 +581,19 @@ extern struct daemon {
unsigned int options;
struct resolvc default_resolv, *resolv_files;
time_t last_resolv;
struct mx_srv_record *mxnames;
struct naptr *naptr;
struct txt_record *txt;
struct ptr_record *ptr;
struct cname *cnames;
struct interface_name *int_names;
char *mxtarget;
char *lease_file;
char *username, *groupname, *scriptuser;
int group_set, osport;
char *domain_suffix;
struct cond_domain *cond_domain;
char *runfile;
char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
@@ -593,7 +612,7 @@ extern struct daemon {
struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs;
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;
int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port;
@@ -660,7 +679,7 @@ void cache_end_insert(void);
void cache_start_insert(void);
struct crec *cache_insert(char *name, struct all_addr *addr,
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_unhash_dhcp(void);
void dump_cache(time_t now);
@@ -749,17 +768,17 @@ struct in_addr get_ifaddr(char *intr);
/* dhcp.c */
void dhcp_init(void);
void dhcp_packet(time_t now);
char *get_domain(struct in_addr addr);
struct dhcp_context *address_available(struct dhcp_context *context,
struct in_addr addr,
struct dhcp_netid *netids);
struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr,
struct dhcp_netid *netids);
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
int address_allocate(struct dhcp_context *context,
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
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_context *context,
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);
char *strip_hostname(char *hostname);
char *host_from_dns(struct in_addr addr);
char *get_domain(struct in_addr addr);
/* lease.c */
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);
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int hw_len, int hw_type, int clid_len);
void lease_set_hostname(struct dhcp_lease *lease, char *name,
char *suffix, int auth);
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth);
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
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,
@@ -794,6 +813,8 @@ void rerun_scripts(void);
/* rfc2131.c */
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);
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out);
/* dnsmasq.c */
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 clear_cache_and_reload(time_t now);
/* isc.c */
#ifdef HAVE_ISC_READER
void load_dhcp(time_t now);
#endif
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
void netlink_init(void);
@@ -827,6 +843,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)());
char *dbus_init(void);
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 emit_dbus_signal(int action, char *mac, char *hostname, char *addr);
#endif
/* helper.c */

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
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;
/* If upstream is advertising a larger UDP packet size
than we allow, trim it so that we don't get overlarge
requests for the client. We can't do this for signed packets. */
than we allow, trim it so that we don't get overlarge
requests for the client. We can't do this for signed packets. */
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 */
for (i = 0; i < RANDOM_SOCKS; i++)
if (daemon->randomsocks[i].refcount == 0 &&
(daemon->randomsocks[i].fd = random_sock(family)) != -1)
if (daemon->randomsocks[i].refcount == 0)
{
if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
break;
daemon->randomsocks[i].refcount = 1;
daemon->randomsocks[i].family = family;
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++)
{
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;
daemon->randomsocks[j].refcount++;

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
it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
#ifndef NO_FORK
static void my_setenv(const char *name, const char *value, int *error);
struct script_data
{
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 */
p = daemon->dhcp_buff;
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++)
{
p += sprintf(p, "%.2x", data.hwaddr[i]);
if (i != data.hwaddr_len - 1)
p += sprintf(p, ":");
}
{
p += sprintf(p, "%.2x", data.hwaddr[i]);
if (i != data.hwaddr_len - 1)
p += sprintf(p, ":");
}
/* and CLID into packet */
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)
{
char *dot;
hostname = (char *)buf;
hostname[data.hostname_len - 1] = 0;
if (!canonicalise(hostname))
hostname = NULL;
else if ((dot = strchr(hostname, '.')))
{
my_setenv("DNSMASQ_DOMAIN", dot+1, &err);
*dot = 0;
}
}
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;
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 */
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;
/* 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)
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);
p += uclass_len;
}
/* substitute * for space */
for (i = 0; i < hostname_len; i++)
/* substitute * for space: spaces are allowed in hostnames (for DNS-SD)
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] == ' ')
*(p++) = '*';
else

252
src/isc.c
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

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
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 */
for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(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
@@ -151,9 +151,9 @@ void lease_update_from_configs(void)
lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
(config->flags & CONFIG_NAME) &&
(!(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)))
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, ...)
@@ -254,8 +254,11 @@ void lease_update_dns(void)
for (lease = leases; lease; lease = lease->next)
{
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
if (lease->fqdn)
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;
@@ -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;
char *new_name = NULL, *new_fqdn = NULL;
if (lease->hostname && name && hostname_isequal(lease->hostname, name))
{
lease->auth_name = auth;
@@ -433,44 +458,47 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int
if (name)
{
for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
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)))
if ((new_name = whine_malloc(strlen(name) + 1)))
{
strcpy(new_fqdn, name);
strcat(new_fqdn, ".");
strcat(new_fqdn, suffix);
char *suffix = get_domain(lease->addr);
strcpy(new_name, name);
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)
{
/* run script to say we lost our old name */
free(lease->old_hostname);
lease->old_hostname = lease->hostname;
}
kill_name(lease);
free(lease->fqdn);
lease->hostname = new_name;
lease->fqdn = new_fqdn;
lease->auth_name = auth;
@@ -506,6 +534,13 @@ int do_script_run(time_t now)
{
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)
{
lease = old_leases;
@@ -522,13 +557,13 @@ int do_script_run(time_t now)
}
else
{
kill_name(lease);
#ifndef NO_FORK
queue_script(ACTION_DEL, lease, lease->hostname, now);
queue_script(ACTION_DEL, lease, lease->old_hostname, now);
#endif
old_leases = lease->next;
free(lease->hostname);
free(lease->fqdn);
free(lease->old_hostname);
free(lease->clid);
free(lease->vendorclass);
free(lease->userclass);
@@ -555,7 +590,8 @@ int do_script_run(time_t now)
(lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
{
#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
lease->new = lease->changed = lease->aux_changed = 0;

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
it under the terms of the GNU General Public License as published by

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
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. */
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);
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)
return;
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;
/* Force re-reading resolv file right now, for luck. */
daemon->last_resolv = 0;
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
if (daemon->srv_save)
{
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

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
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. */
int random_sock(int family)
{
@@ -451,19 +451,21 @@ int random_sock(int family)
if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
{
union mysockaddr addr;
unsigned short ports_avail = 65536u - (unsigned short)daemon->min_port;
int i;
unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
int tries = ports_avail < 30 ? 3 * ports_avail : 100;
memset(&addr, 0, sizeof(addr));
addr.sa.sa_family = family;
/* don't loop forever if all ports in use. */
if (fix_fd(fd))
for (i = ports_avail; i != 0; i--)
while(tries--)
{
unsigned short port = rand16();
if (daemon->min_port != 0)
port = htons(daemon->min_port + (port % ports_avail));
port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
if (family == AF_INET)
{

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
it under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ struct myoption {
};
#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 */
#define LOPT_RELOAD 256
@@ -96,6 +96,8 @@ struct myoption {
#define LOPT_LOCAL 286
#define LOPT_NAPTR 287
#define LOPT_MINPORT 288
#define LOPT_DHCP_FQDN 289
#define LOPT_CNAME 290
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -160,7 +162,7 @@ static const struct myoption opts[] =
{"localise-queries", 0, 0, 'y'},
{"txt-record", 1, 0, 'Y'},
{"enable-dbus", 0, 0, '1'},
{"bootp-dynamic", 0, 0, '3'},
{"bootp-dynamic", 2, 0, '3'},
{"dhcp-mac", 1, 0, '4'},
{"no-ping", 0, 0, '5'},
{"dhcp-script", 1, 0, '6'},
@@ -200,6 +202,8 @@ static const struct myoption opts[] =
{"dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
{"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
{"min-port", 1, 0, LOPT_MINPORT },
{"dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
{"cname", 1, 0, LOPT_CNAME },
{ 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_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 },
{ 'J', ARG_DUP, "<tag>", 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 },
{ 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP 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_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 },
@@ -261,7 +265,7 @@ static struct {
{ '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 },
{ 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, "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 },
@@ -281,7 +285,7 @@ static struct {
{ '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 },
{ '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 },
#ifdef HAVE_BSD_BRIDGE
{ 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 },
{ '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_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_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 },
@@ -311,6 +315,8 @@ static struct {
{ 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_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 }
};
@@ -373,8 +379,8 @@ static const struct {
{ "T2", 59, OT_INTERNAL },
{ "vendor-class", 60, 0 },
{ "client-id", 61,OT_INTERNAL },
{ "nis-domain", 64, 0 },
{ "nis-server", 65, OT_ADDR_LIST },
{ "nis+-domain", 64, 0 },
{ "nis+-server", 65, OT_ADDR_LIST },
{ "tftp-server", 66, 0 },
{ "bootfile-name", 67, 0 },
{ "mobile-ip-home", 68, OT_ADDR_LIST },
@@ -529,6 +535,16 @@ static int atoi_check(char *a, int *res)
return 1;
}
static int atoi_check16(char *a, int *res)
{
if (!(atoi_check(a, res)) ||
*res < 0 ||
*res > 0xffff)
return 0;
return 1;
}
static void add_txt(char *name, char *txt)
{
size_t len = strlen(txt);
@@ -947,7 +963,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{
char *file = opt_string_alloc(arg);
if (file)
one_file(file, nest, 0);
{
one_file(file, nest, 0);
free(file);
}
break;
}
@@ -991,6 +1010,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
}
closedir(dir_stream);
free(directory);
break;
}
@@ -1067,7 +1087,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if ((comma = split(arg)))
{
char *prefstr;
if ((prefstr=split(comma)) && !atoi_check(prefstr, &pref))
if ((prefstr=split(comma)) && !atoi_check16(prefstr, &pref))
problem = _("bad MX preference");
}
@@ -1117,10 +1137,49 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 's': /* --domain */
if (strcmp (arg, "#") == 0)
daemon->options |= OPT_RESOLV_DOMAIN;
else if (!canonicalise_opt(arg))
option = '?';
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;
case 'u': /* --user */
@@ -1289,7 +1348,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if ((portno = strchr(source+1, '#')))
{
*portno = 0;
if (!atoi_check(portno+1, &source_port))
if (!atoi_check16(portno+1, &source_port))
problem = _("bad port");
}
}
@@ -1297,7 +1356,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if ((portno = strchr(arg, '#'))) /* is there a port no. */
{
*portno = 0;
if (!atoi_check(portno+1, &serv_port))
if (!atoi_check16(portno+1, &serv_port))
problem = _("bad port");
}
@@ -1390,13 +1449,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
}
case 'p': /* --port */
if (!atoi_check(arg, &daemon->port))
if (!atoi_check16(arg, &daemon->port))
option = '?';
break;
case LOPT_MINPORT: /* --min-port */
if (!atoi_check(arg, &daemon->min_port))
option = '?';
if (!atoi_check16(arg, &daemon->min_port))
option = '?';
break;
case '0': /* --dns-forward-max */
@@ -1422,7 +1481,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
}
case 'Q': /* --query-port */
if (!atoi_check(arg, &daemon->query_port))
if (!atoi_check16(arg, &daemon->query_port))
option = '?';
/* if explicitly set to zero, use single OS ephemeral port
and disable random ports */
@@ -1459,8 +1518,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case LOPT_TFTPPORTS: /* --tftp-port-range */
if (!(comma = split(arg)) ||
!atoi_check(arg, &daemon->start_tftp_port) ||
!atoi_check(comma, &daemon->end_tftp_port))
!atoi_check16(arg, &daemon->start_tftp_port) ||
!atoi_check16(comma, &daemon->end_tftp_port))
problem = _("bad port range");
if (daemon->start_tftp_port > daemon->end_tftp_port)
@@ -1646,7 +1705,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new = opt_malloc(sizeof(struct dhcp_config));
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))
for (k = 1; k < 6; k++)
@@ -1696,8 +1756,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
}
else
{
new->hwaddr_len = parse_hex(a[j], new->hwaddr, DHCP_CHADDR_MAX, &new->wildcard_mask, &new->hwaddr_type);
new->flags |= CONFIG_HWADDR;
struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
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)
@@ -1758,6 +1821,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{
new->flags |= CONFIG_NAME;
strcpy(new->hostname, a[j]);
new->domain = NULL;
}
}
}
@@ -1840,7 +1904,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
else
{
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);
new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
new->next = daemon->dhcp_macs;
@@ -1863,7 +1930,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
char *p;
int dig = 0;
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,
only allowed for agent-options. */
for (p = comma; *p; p++)
@@ -1923,8 +1993,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
else
{
comma = split(arg);
if (!atoi_check(arg, &daemon->dhcp_server_port) ||
(comma && !atoi_check(comma, &daemon->dhcp_client_port)))
if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
(comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
problem = _("invalid port number");
if (!comma)
daemon->dhcp_client_port = daemon->dhcp_server_port+1;
@@ -1934,6 +2004,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 'J': /* --dhcp-ignore */
case LOPT_NO_NAMES: /* --dhcp-ignore-names */
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 = NULL;
@@ -1947,6 +2018,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->next = daemon->force_broadcast;
daemon->force_broadcast = new;
}
else if (option == '3')
{
new->next = daemon->bootp_dynamic;
daemon->bootp_dynamic = new;
}
else
{
new->next = daemon->dhcp_ignore_names;
@@ -1958,7 +2034,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
comma = split(arg);
member->next = list;
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;
}
@@ -2023,6 +2102,26 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->intr = opt_string_alloc(comma);
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 */
{
@@ -2058,8 +2157,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if (k < 6 ||
!canonicalise_opt(a[0]) ||
!atoi_check(a[1], &order) ||
!atoi_check(a[2], &pref) ||
!atoi_check16(a[1], &order) ||
!atoi_check16(a[2], &pref) ||
(k == 7 && !canonicalise_opt(a[6])))
problem = _("bad NAPTR record");
else
@@ -2167,21 +2266,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{
arg = comma;
comma = split(arg);
if (!atoi_check(arg, &port))
if (!atoi_check16(arg, &port))
problem = _("invalid port number");
if (comma)
{
arg = comma;
comma = split(arg);
if (!atoi_check(arg, &priority))
if (!atoi_check16(arg, &priority))
problem = _("invalid priority");
if (comma)
{
arg = comma;
comma = split(arg);
if (!atoi_check(arg, &weight))
if (!atoi_check16(arg, &weight))
problem = _("invalid weight");
}
}
@@ -2377,6 +2476,13 @@ void reread_dhcp(void)
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)
free(configs->clid);
if (configs->flags & CONFIG_NETID)
@@ -2384,6 +2490,7 @@ void reread_dhcp(void)
if (configs->flags & CONFIG_NAME)
free(configs->hostname);
*up = configs->next;
free(configs);
}
@@ -2629,4 +2736,6 @@ void read_opts(int argc, char **argv, char *compile_opts)
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);
}

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
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 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,
char *name, int isExtract)
char *name, int isExtract, int extrabytes)
{
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
unsigned int j, l, hops = 0;
@@ -31,19 +37,47 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
if (isExtract)
*cp = 0;
while ((l = *p++))
{
unsigned int label_type = l & 0xc0;
while (1)
{
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 ((size_t)(p - (unsigned char *)header) >= plen)
if (!CHECK_LEN(header, p, plen, 1))
return 0;
/* get offset */
l = (l&0x3f) << 8;
l |= *p++;
if (l >= plen)
return 0;
if (!p1) /* first jump, save location to go back to */
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 */
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
return 0;
if ((size_t)(p - (unsigned char *)header + ((count-1)>>3)) >= plen)
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
return 0;
*cp++ = '\\';
@@ -98,8 +132,9 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
{ /* label_type = 0 -> label. */
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
return 0;
if ((size_t)(p - (unsigned char *)header) >= plen)
if (!CHECK_LEN(header, p, plen, l))
return 0;
for(j=0; j<l; j++, p++)
if (isExtract)
{
@@ -132,26 +167,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
else if (*cp != 0 && *cp++ != '.')
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.) */
@@ -261,15 +277,17 @@ static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
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)
{
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;
label_type = (*ansp) & 0xc0;
if (label_type == 0xc0)
{
/* pointer for compression. */
@@ -283,6 +301,9 @@ static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen
/* Extended label type */
unsigned int count;
if (!CHECK_LEN(header, ansp, plen, 2))
return NULL;
if (((*ansp++) & 0x3f) != 1)
return NULL; /* we only understand bitstrings */
@@ -296,12 +317,17 @@ static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen
else
{ /* label type == 0 Bottom six bits is length */
unsigned int len = (*ansp++) & 0x3f;
if (!ADD_RDLEN(header, ansp, plen, len))
return NULL;
if (len == 0)
break; /* zero length label marks the end. */
ansp += len;
}
}
if (!CHECK_LEN(header, ansp, plen, extrabytes))
return NULL;
return ansp;
}
@@ -313,12 +339,10 @@ static unsigned char *skip_questions(HEADER *header, size_t plen)
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;
ansp += 4; /* class and type */
}
if ((unsigned int)(ansp - (unsigned char *)header) > plen)
return NULL;
return ansp;
}
@@ -329,13 +353,12 @@ static unsigned char *skip_section(unsigned char *ansp, int count, HEADER *heade
for (i = 0; i < count; i++)
{
if (!(ansp = skip_name(ansp, header, plen)))
if (!(ansp = skip_name(ansp, header, plen, 10)))
return NULL;
ansp += 8; /* type, class, TTL */
GETSHORT(rdlen, ansp);
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
if (!ADD_RDLEN(header, ansp, plen, rdlen))
return NULL;
ansp += rdlen;
}
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--)
{
if (!extract_name(header, plen, &p, name, 1))
if (!extract_name(header, plen, &p, name, 1, 4))
return crc; /* bad packet */
for (p1 = (unsigned char *)name; *p1; p1++)
@@ -381,7 +404,7 @@ unsigned int questions_crc(HEADER *header, size_t plen, char *name)
}
p += 4;
if ((unsigned int)(p - (unsigned char *)header) > plen)
if (!CHECK_LEN(header, p, plen, 0))
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);
/* if packet is malformed, just return as-is. */
if (!ansp)
return 0;
return plen;
if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
header, plen)))
return 0;
return plen;
/* restore pseudoheader */
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--)
{
if (!(ansp = skip_name(ansp, header, plen)))
if (!(ansp = skip_name(ansp, header, plen, 4)))
return NULL;
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++)
{
unsigned char *save, *start = ansp;
if (!(ansp = skip_name(ansp, header, plen)))
if (!(ansp = skip_name(ansp, header, plen, 10)))
return NULL;
GETSHORT(type, ansp);
@@ -466,9 +490,8 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
GETSHORT(class, ansp);
ansp += 4; /* TTL */
GETSHORT(rdlen, ansp);
if ((size_t)(ansp + rdlen - (unsigned char *)header) > plen)
if (!ADD_RDLEN(header, ansp, plen, rdlen))
return NULL;
ansp += rdlen;
if (type == T_OPT)
{
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--)
{
if (!(p = skip_name(p, header, qlen)))
if (!(p = skip_name(p, header, qlen, 10)))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -521,7 +544,10 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
struct doctor *doctor;
struct in_addr addr;
/* alignment */
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
return 0;
/* alignment */
memcpy(&addr, p, INADDRSZ);
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 ((size_t)(p - (unsigned char *)header) > qlen)
return 0; /* bad packet */
if (!ADD_RDLEN(header, p, qlen, rdlen))
return 0; /* bad packet */
}
return p;
@@ -559,7 +583,7 @@ static int find_soa(HEADER *header, size_t qlen)
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 */
GETSHORT(qtype, p);
@@ -574,10 +598,10 @@ static int find_soa(HEADER *header, size_t qlen)
minttl = ttl;
/* MNAME */
if (!(p = skip_name(p, header, qlen)))
if (!(p = skip_name(p, header, qlen, 0)))
return 0;
/* RNAME */
if (!(p = skip_name(p, header, qlen)))
if (!(p = skip_name(p, header, qlen, 20)))
return 0;
p += 16; /* SERIAL REFRESH RETRY EXPIRE */
@@ -585,13 +609,10 @@ static int find_soa(HEADER *header, size_t qlen)
if (ttl < minttl)
minttl = ttl;
}
else
p += rdlen;
if ((size_t)(p - (unsigned char *)header) > qlen)
else if (!ADD_RDLEN(header, p, qlen, rdlen))
return 0; /* bad packet */
}
/* rewrite addresses in additioal section too */
if (!do_doctor(p, ntohs(header->arcount), header, qlen))
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;
namep = p;
if (!extract_name(header, qlen, &p, name, 1))
if (!extract_name(header, qlen, &p, name, 1, 4))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -661,8 +682,8 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
{
unsigned char *tmp = namep;
/* the loop body overwrites the original name, so get it back here. */
if (!extract_name(header, qlen, &tmp, name, 1) ||
!(res = extract_name(header, qlen, &p1, name, 0)))
if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
!(res = extract_name(header, qlen, &p1, name, 0, 10)))
return 0; /* bad packet */
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 (!extract_name(header, qlen, &p1, name, 1))
if (!extract_name(header, qlen, &p1, name, 1, 0))
return 0;
if (aqtype == T_CNAME)
@@ -692,7 +713,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
}
p1 = endrr;
if ((size_t)(p1 - (unsigned char *)header) > qlen)
if (!CHECK_LEN(header, p1, qlen, 0))
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--)
{
if (!(res = extract_name(header, qlen, &p1, name, 0)))
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
return 0; /* bad packet */
GETSHORT(aqtype, p1);
@@ -763,14 +784,17 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
if (attl < cttl)
cttl = attl;
if (!extract_name(header, qlen, &p1, name, 1))
if (!extract_name(header, qlen, &p1, name, 1, 0))
return 0;
goto cname_loop1;
}
else
{
found = 1;
/* copy address into aligned storage */
if (!CHECK_LEN(header, p1, qlen, addrlen))
return 0; /* bad packet */
memcpy(&addr, p1, addrlen);
/* 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;
if ((size_t)(p1 - (unsigned char *)header) > qlen)
if (!CHECK_LEN(header, p1, qlen, 0))
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)
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 */
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--)
{
if (!extract_name(header, qlen, &p, name, 1))
if (!extract_name(header, qlen, &p, name, 1, 10))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -962,19 +986,25 @@ int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
GETSHORT(rdlen, p);
if (qclass == C_IN && qtype == T_A)
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
{
/* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */
cache_start_insert();
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
cache_end_insert();
return 1;
}
{
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
return 0;
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
{
/* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */
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;
@@ -1073,6 +1103,18 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp, unsigne
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 */
size_t answer_request(HEADER *header, char *limit, size_t qlen,
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;
/* 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 */
GETSHORT(qtype, p);
@@ -1239,18 +1281,11 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
auth = 0;
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,
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)))
anscount++;
}
@@ -1358,7 +1393,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
if (!dryrun)
{
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)))
anscount++;
}
@@ -1391,17 +1427,11 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
ans = 1;
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,
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))
anscount++;
}
@@ -1529,7 +1559,6 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
crecp = NULL;
while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
{
unsigned long ttl;
#ifdef HAVE_IPV6
int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
#else
@@ -1538,12 +1567,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
if (crecp->flags & F_NEG)
continue;
if (crecp->flags & (F_IMMORTAL | F_DHCP))
ttl = daemon->local_ttl;
else
ttl = crecp->ttd - now;
if (add_resource_record(header, limit, NULL, rec->offset, &ansp, ttl, NULL, type, C_IN,
if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
crec_ttl(crecp, now), NULL, type, C_IN,
crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
addncount++;
}

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
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,
unsigned char *real_end,
unsigned char *req_options,
char *hostname,
char *hostname,
char *domain, char *config_domain,
struct dhcp_netid *netid,
struct in_addr subnet_addr,
unsigned char fqdn_flags,
int null_term,
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);
@@ -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;
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
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;
unsigned char *req_options = NULL;
char *message = NULL;
unsigned int time;
struct dhcp_config *config;
struct dhcp_netid *netid = NULL;
struct dhcp_netid *netid;
struct in_addr subnet_addr, fallback, override;
unsigned short fuzz = 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 *emac = NULL;
int emac_len = 0;
struct dhcp_netid known_id;
struct dhcp_netid known_id, iface_id;
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)
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 */
if (have_config(config, CONFIG_NAME))
hostname = config->hostname;
{
hostname = config->hostname;
domain = config->domain;
}
if (have_config(config, CONFIG_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)
{
int nailed = 0;
if (have_config(config, CONFIG_ADDR))
{
nailed = 1;
logaddr = &config->addr;
mess->yiaddr = 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))
message = _("address in use");
}
else if (!(daemon->options & OPT_BOOTP_DYNAMIC))
message = _("no address configured");
else
{
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;
}
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 &&
!lease &&
(!(lease = lease_allocate(mess->yiaddr))))
message = _("no leases left");
if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
message = _("wrong network");
if (!message)
{
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);
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. */
lease_set_expires(lease,
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);
clear_packet(mess, end, NULL);
do_options(context, mess, end, NULL,
hostname, netid, subnet_addr, 0, 0, NULL);
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
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))
{
hostname = config->hostname;
domain = config->domain;
hostname_auth = 1;
/* 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))
@@ -525,9 +543,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
else if (client_hostname)
{
char *d = strip_hostname(client_hostname);
if (d)
my_syslog(LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), d, client_hostname);
domain = strip_hostname(client_hostname);
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,
mess->chaddr, mess->hlen,
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;
/* 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);
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;
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_T2, 4, (time*7)/8);
}
do_options(context, mess, end, req_options, offer_hostname,
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
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)
return 0;
}
else
else
{
for (; context; context = context->current)
if (context->local.s_addr == option_addr(opt).s_addr)
break;
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. */
@@ -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)
message = _("address reserved");
else if ((ltmp = lease_find_by_addr(mess->yiaddr)) && ltmp != lease)
message = _("address in use");
else if (emac_len == 0)
message = _("no unique-id");
else if (!lease)
{
if ((lease = lease_allocate(mess->yiaddr)))
do_classes = 1;
else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
{
/* If a host is configured with more than one MAC address, it's OK to 'nix
a lease from one of it's MACs to give the address to another. */
if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
{
my_syslog(LOG_INFO, _("abandoning lease to %s of %s"),
print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
inet_ntoa(ltmp->addr));
lease = ltmp;
}
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;
}
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_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_T2, 4, ((time/8)*7) - fuzz);
}
do_options(context, mess, end, req_options, hostname,
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
}
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);
}
do_options(context, mess, end, req_options, hostname,
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
*is_inform = 1; /* handle reply differently */
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
client-id: if not we can use the whole client-id. This should give
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)
{
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;
size_t ret;
struct dhcp_netid_list *id_list;
struct dhcp_netid *n;
/* We do logging too */
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;
for (; netid; netid = netid->next)
{
strncat (p, netid->net, MAXDNAME);
if (netid->next)
strncat (p, ", ", MAXDNAME);
/* kill dupes. */
for (n = netid->next; n; n = n->next)
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;
my_syslog(LOG_INFO, _("tags: %s"), p);
@@ -1531,7 +1580,8 @@ static void do_options(struct dhcp_context *context,
struct dhcp_packet *mess,
unsigned char *real_end,
unsigned char *req_options,
char *hostname,
char *hostname,
char *domain, char *config_domain,
struct dhcp_netid *netid,
struct in_addr subnet_addr,
unsigned char fqdn_flags,
@@ -1545,6 +1595,9 @@ static void do_options(struct dhcp_context *context,
unsigned char f0 = 0, s0 = 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 */
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_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_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> */
if (hostname)
@@ -1700,8 +1753,8 @@ static void do_options(struct dhcp_context *context,
else if (null_term)
len++;
if (daemon->domain_suffix)
len += strlen(daemon->domain_suffix) + 1;
if (domain)
len += strlen(domain) + 1;
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)
{
p = do_rfc1035_name(p, hostname);
if (daemon->domain_suffix)
p = do_rfc1035_name(p, daemon->domain_suffix);
if (domain)
p = do_rfc1035_name(p, domain);
*p++ = 0;
}
else
{
memcpy(p, hostname, strlen(hostname));
p += strlen(hostname);
if (daemon->domain_suffix)
if (domain)
{
*(p++) = '.';
memcpy(p, daemon->domain_suffix, strlen(daemon->domain_suffix));
p += strlen(daemon->domain_suffix);
memcpy(p, domain, strlen(domain));
p += strlen(domain);
}
if (null_term)
*(p++) = 0;

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
it under the terms of the GNU General Public License as published by

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
it under the terms of the GNU General Public License as published by