Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9009d74652 | ||
|
|
1ad24ae15c |
95
CHANGELOG
95
CHANGELOG
@@ -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
19
FAQ
@@ -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?
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -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
|
||||
|
||||
@@ -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.
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
107
man/es/dnsmasq.8
107
man/es/dnsmasq.8
@@ -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/pt_BR.po
662
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
314
src/cache.c
314
src/cache.c
@@ -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;
|
||||
|
||||
16
src/config.h
16
src/config.h
@@ -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
|
||||
|
||||
39
src/dbus.c
39
src/dbus.c
@@ -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
|
||||
|
||||
109
src/dhcp.c
109
src/dhcp.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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++;
|
||||
|
||||
39
src/helper.c
39
src/helper.c
@@ -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
252
src/isc.c
@@ -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
|
||||
|
||||
124
src/lease.c
124
src/lease.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
181
src/option.c
181
src/option.c
@@ -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);
|
||||
}
|
||||
|
||||
245
src/rfc1035.c
245
src/rfc1035.c
@@ -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++;
|
||||
}
|
||||
|
||||
179
src/rfc2131.c
179
src/rfc2131.c
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user