Compare commits

...
34 Commits
Author SHA1 Message Date
Giacomo Tazzari 797a7afba4 Fix crash on SERVFAIL when --conntrack in use. 2013-04-22 13:16:37 +01:00
Simon Kelley 4b5ea12e90 Send TCP DNS messages in one write() call. Stops TCP stream fragmenting.
This is an optimisation, not a bugfix. Thanks to Jim Bos for spotting it.
2013-04-22 10:22:55 +01:00
Simon Kelley 2b6390fdc9 Bump Debian version number. 2013-04-19 10:23:50 +01:00
Simon Kelley bd08ae67f9 Allow option number zero in encapsulated DHCP options. 2013-04-19 10:22:06 +01:00
Dave Reisner 4582c0efe7 Fix wrong size in memset() call.
Thanks to Dave Reisner.
2013-04-18 21:02:41 +01:00
Simon Kelley 834f36fe6d Update French translation. 2013-04-17 13:52:49 +01:00
Simon Kelley 6f130def07 Manpage typos.
Thanks to Gildas Le Nadan.
2013-04-15 14:58:56 +01:00
Simon Kelley 3931a7bd85 FAQ typos.
Thanks to Moritz Warning.
2013-04-15 14:31:52 +01:00
Simon Kelley d9ee9c0872 Better error check on options parsing. 2013-04-12 11:17:55 +01:00
Simon Kelley 0b0a73c1c9 Fix crash on exceeding DHCP lease limit. 2013-04-11 14:07:02 +01:00
Simon Kelley 81925ab73a Manpage typos 2013-04-10 11:43:58 +01:00
Simon Kelley 9de1aa9b7f Fix parsing of IAID>MAXINT in leases file.
Thanks to Christof Meerwald for the bug report.
2013-04-10 11:17:12 +01:00
Simon Kelley 6f9aaa93e9 ->hwaddr_len must be zero always in DHCPv6 leases. 2013-04-10 10:25:26 +01:00
Simon Kelley 7e5664bdbc Fix trivial access of un-initialised memory.
Thanks to sven falpin for finding this.
2013-04-09 22:28:04 +01:00
Simon Kelley 83f28bef6c Manpage typos. 2013-04-03 14:46:46 +01:00
Simon Kelley 96c727fda6 Cope with duplicate dhcp-options with tags (last one wins). 2013-04-02 21:35:41 +01:00
Simon Kelley 49dc570a72 Manpage typo. 2013-04-02 20:27:07 +01:00
Simon Kelley cd1e04a234 Polish translation. 2013-04-02 20:11:48 +01:00
Simon Kelley 27cb314e54 Fix endless loop when dhcp-range goes away. 2013-04-02 20:06:39 +01:00
Simon Kelley 56a1142f03 SO_REUSEPORT may be defined, but not supported. 2013-04-02 17:02:58 +01:00
Simon Kelley 5b37aa8c19 Trivial change: 0->NULL for pointer constant. 2013-04-02 16:32:25 +01:00
Simon Kelley 8ac9787350 Fix lease time calculation when using DHCPv6 relay. 2013-03-30 21:34:19 +00:00
Simon Kelley 9f9bd08af8 Merged messages. 2013-03-22 15:11:53 +00:00
Simon Kelley 4c985dac39 Indentation. 2013-03-22 14:07:38 +00:00
Simon Kelley 3d77c0460d Typos in CHANGELOG 2013-03-22 10:03:50 +00:00
Simon Kelley 3ddad24608 Compile-in IPSET by default. 2013-03-21 17:56:06 +00:00
Simon Kelley 6e37ab595c Send prefix-class in DHCPREPLY as well as DHCPADVERTISE. 2013-03-19 20:50:11 +00:00
Simon Kelley a1a79edaea Bugfix for latest DHCPv6 update. 2013-03-15 21:19:57 +00:00
Simon Kelley 49333cbdbe Allow trailing '*' wildcard in interface names. 2013-03-15 20:30:51 +00:00
Simon Kelley de92b479d9 Make wildcard-configured addresses work on multiple networks. 2013-03-15 18:26:23 +00:00
Simon Kelley 0f128eb58c Clarifications for DNS-auth in man-page. 2013-03-11 21:21:35 +00:00
Simon Kelley c630924d66 Experimental support for DHCPv6 prefix-class option. 2013-03-07 20:59:28 +00:00
Simon Kelley ff59fc82b3 Split out context-marking from add_address. 2013-03-07 11:00:26 +00:00
Simon Kelley 52a1ae72f0 Another logic problem in refactor. 2013-03-06 22:43:26 +00:00
33 changed files with 7161 additions and 4553 deletions

No files matched your search

+24 -2
View File
@@ -1,3 +1,9 @@
version 2.67
Fix crash if upstream server returns SERVFAIL when
--conntrack in use. Thanks to Giacomo Tazzari for finding
this and supplying the patch.
version 2.66
Add the ability to act as an authoritative DNS
server. Dnsmasq can now answer queries from the wider 'net
@@ -33,7 +39,7 @@ version 2.66
Add DNSMASQ_CIRCUIT_ID, DNSMASQ_SUBCRIBER_ID,
DNSMASQ_REMOTE_ID variables to the environment of the
lease-change script (and the correponding Lua). These hold
lease-change script (and the corresponding Lua). These hold
information inserted into the DHCP request by a DHCP relay
agent. Thanks to Lakefield Communications for providing a
bounty for this addition.
@@ -47,9 +53,25 @@ version 2.66
patch.
Don't erroneously reject some option names in --dhcp-match
options. Thnaks to Benedikt Hochstrasser for the bug report.
options. Thanks to Benedikt Hochstrasser for the bug report.
Allow a trailing '*' wildcard in all interface-name
configurations. Thanks to Christian Parpart for the patch.
Handle the situation where libc headers define
SO_REUSEPORT, but the kernel in use doesn't, to cope with
the introduction of this option to Linux. Thanks to Rich
Felker for the bug report.
Update Polish translation. Thanks to Jan Psota.
Fix crash if the configured DHCP lease limit is
reached. Regression occurred in 2.61. Thanks to Tsachi for
the bug report.
Update the French translation. Thanks to Gildas le Nadan.
version 2.65
Fix regression which broke forwarding of queries sent via
TCP which are not for A and AAAA and which were directed to
+2 -2
View File
@@ -22,7 +22,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
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
value 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
@@ -112,7 +112,7 @@ A: Resolver code sometime does strange things when given names without
hostname will fix things. (ie "ping myhost" fails, but "ping
myhost." works. The solution is to make sure that all your hosts
have a domain set ("domain" in resolv.conf, or set a domain in
your DHCP server, see below fr Windows XP and Mac OS X).
your DHCP server, see below for Windows XP and Mac OS X).
Any domain will do, but "localnet" is traditional. Now when you
resolve "myhost" the resolver will attempt to look up
"myhost.localnet" so you need to have dnsmasq reply to that name.
+6
View File
@@ -1,3 +1,9 @@
dnsmasq (2.67-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 19 Apr 2013 10:23:31 +0000
dnsmasq (2.66-1) unstable; urgency=low
* New upstream.
+2 -4
View File
@@ -33,10 +33,8 @@ ifeq ($(DEB_BUILD_ARCH_OS),linux)
endif
endif
ifeq (,$(filter noipset,$(DEB_BUILD_OPTIONS)))
ifeq ($(DEB_BUILD_ARCH_OS),linux)
COPTS += -DHAVE_IPSET
endif
ifneq (,$(filter noipset,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_IPSET
endif
ifneq (,$(filter nodhcp6,$(DEB_BUILD_OPTIONS)))
+37 -16
View File
@@ -22,7 +22,10 @@ send any desired set of DHCP options, including vendor-encapsulated
options. It includes a secure, read-only,
TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP. The PXE support is full featured, and includes a proxy mode which supplies PXE information to clients whilst DHCP address allocation is done by another server.
.PP
The dnsmasq DHCPv6 server provides the same set of features as the DHCPv4 server, and in addition, it includes router advertisements and a neat feature which allows nameing for clients which use DHCPv4 and RA only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
The dnsmasq DHCPv6 server provides the same set of features as the
DHCPv4 server, and in addition, it includes router advertisements and
a neat feature which allows nameing for clients which use DHCPv4 and
stateless autoconfiguration only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
.PP
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows uneeded functions to be omitted from the compiled binary.
.SH OPTIONS
@@ -171,7 +174,12 @@ options. IP alias interfaces (eg "eth1:0") cannot be used with
.B --interface
or
.B --except-interface
options, use --listen-address instead.
options, use --listen-address instead. A simple wildcard, consisting
of a trailing '*', can be used in
.B \--interface
and
.B \--except-interface
options.
.TP
.B \-I, --except-interface=<interface name>
Do not listen on the specified interface. Note that the order of
@@ -184,7 +192,7 @@ options does not matter and that
options always override the others.
.TP
.B --auth-server=<domain>,<interface>|<ip-address>
Enable DNS authoritative mode for queries arriving at an interface or address. Note that the the interface or address
Enable DNS authoritative mode for queries arriving at an interface or address. Note that the interface or address
need not be mentioned in
.B --interface
or
@@ -553,7 +561,8 @@ Define a DNS zone for which dnsmasq acts as authoritative server. Locally define
will be served, except that A and AAAA records must be in one of the
specified subnets, or in a subnet corresponding to a contructed DHCP
range. The subnet(s) are also used to define in-addr.arpa and
ipv6.arpa domains which are served for reverse-DNS queries.
ipv6.arpa domains which are served for reverse-DNS queries. For IPv4
subnets, the prefix length is limited to the values 8, 16 or 24.
.TP
.B --auth-soa=<serial>[,<hostmaster>[,<refresh>[,<retry>[,<expiry>]]]]
Specify fields in the SOA record associated with authoritative
@@ -563,12 +572,12 @@ zones. Note that this is optional, all the values are set to sane defaults.
Specify any secondary servers for a zone for which dnsmasq is
authoritative. These servers must be configured to get zone data from
dnsmasq by zone transfer, and answer queries for the same
authoritative zones and dnsmasq.
authoritative zones as dnsmasq.
.TP
.B --auth-peer=<ip-address>[,<ip-address>[,<ip-address>...]]
Specify the addresses of secondary servers which are allowed to
initiate zone transfer (AXFR) requests for zones for which dnsmasq is
authoritative. If this option is not given, then AXFR requests wil be
authoritative. If this option is not given, then AXFR requests will be
accepted from any secondary.
.TP
.B --conntrack
@@ -581,9 +590,9 @@ compiled in and the kernel must have conntrack support
included and configured. This option cannot be combined with
--query-port.
.TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag],]<start-IPv6addr>[,<end-IPv6addr>|constuctor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
Enable the DHCP server. Addresses will be given out from the range
<start-addr> to <end-addr> and from statically defined addresses given
@@ -619,9 +628,9 @@ IPv6 (only) supports another type of range. In this, the start address and optio
.B constructor:<interface>.
This forms a template which describes how to create ranges, based on the addresses assigned to the interface. For instance
.B --dhcp-range=::1,::4,constructor:eth0
.B --dhcp-range=::1,::400,constructor:eth0
will look for addreses of the form <network>::1 on eth0 and then create a range from <network>::1 to <network>::400. If the interface is assigned more than one network, then the corresponding ranges will be automatically created, and then deprecated and finally removed again as the address is deprecated and then deleted. The interface name may have a final "*" wildcard.
will look for addresses of the form <network>::1 on eth0 and then create a range from <network>::1 to <network>::400. If the interface is assigned more than one network, then the corresponding ranges will be automatically created, and then deprecated and finally removed again as the address is deprecated and then deleted. The interface name may have a final "*" wildcard.
The optional
.B set:<tag>
@@ -725,7 +734,7 @@ may contain an IPv4 address or an IPv6 address, or both. IPv6 addresses must be
.B --dhcp-host=laptop,[1234::56]
IPv6 addresses may contain only the host-identifier part:
.B --dhcp-host=laptop,[::56]
in which case thay act as wildcards in constructed dhcp ranges, with
in which case they act as wildcards in constructed dhcp ranges, with
the appropriate network part inserted.
Note that in IPv6 DHCP, the hardware address is not normally
available, so a client must be identified by client-id (called client
@@ -1715,7 +1724,7 @@ Configuring dnsmasq to act as an authoritative DNS server is
complicated by the fact that it involves configuration of external DNS
servers to provide delegation. We will walk through three scenarios of
increasing complexity. Prerequisites for all of these scenarios
are a globally accesible IP address, an A or AAAA record pointing to that address,
are a globally accessible IP address, an A or AAAA record pointing to that address,
and an external DNS server capable of doing delegation of the zone in
question. For the first part of this explanation, we will call the A (or AAAA) record
for the globally accessible address server.example.com, and the zone
@@ -1753,7 +1762,7 @@ we have
.fi
.nf
our.zone.com A 192.0.43.10
our.zone.com A 1.2.3.4
our.zone.com NS our.zone.com
.fi
@@ -1766,11 +1775,23 @@ record. If the external address is static, this can be done with an
.B /etc/hosts
entry or
.B --host-record.
If the external address is dynamic,
then it must be done using something like
.nf
.B --interface-name=our.zone.com,eth0
.B auth-server=our.zone.com,eth0
.B host-record=our.zone.com,1.2.3.4
.B auth-zone=our.zone.com,1.2.3.0/24
.fi
If the external address is dynamic, the address
associated with our.zone.com must be derived from the address of the
relevant interface. This is done using
.B interface-name
Something like:
.nf
.B auth-server=our.zone.com,eth0
.B interface-name=our.zone.com,eth0
.B auth-zone=our.zone.com,1.2.3.0/24
.fi
Our final configuration builds on that above, but also adds a
+294 -19
View File
@@ -6,24 +6,40 @@ Dnsmasq \- Un serveur DHCP et cache DNS poids-plume.
.I [OPTION]...
.SH "DESCRIPTION"
.BR dnsmasq
est un serveur DHCP et DNS à faible empreinte mémoire. Il offre à la fois les
services DNS et DHCP pour un réseau local (LAN).
est un serveur à faible empreinte mémoire faisant DNS, TFTP, PXE, annonces de
routeurs et DHCP. Il offre à la fois les services DNS et DHCP pour un réseau
local (LAN).
.PP
Dnsmasq accepte les requêtes DNS et y réponds soit en utilisant un petit cache
local, soit en effectuant une requête à un serveur DNS récursif externe (par
exemple celui de votre fournisseur d'accès internet). Il charge le contenu du
fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
globaux soient tout de même résolus, et assure également la résolution de nom
pour les hôtes présents dans le service DHCP.
pour les hôtes présents dans le service DHCP. Il peut aussi agir en temps que
serveur DNS faisant autorité pour un ou plusieurs domaines, permettant à des
noms locaux d'apparaitre dans le DNS global.
.PP
Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les
réseaux multiples. Il envoie par défaut un jeu raisonnable de paramètres DHCP, et
peut être configuré pour envoyer n'importe quel option DHCP.
réseaux multiples. Il fournit par défaut un jeu raisonnable de paramètres DHCP,
et peut être configuré pour fournir n'importe quelle option DHCP.
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP.
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. Le
support PXE est complet, et comprend un mode proxy permettant de fournir des
informations PXE aux clients alors que l'allocation DHCP est effectuée par un
autre serveur.
.PP
Dnsmasq supporte IPv6 et contient un démon minimaliste capable de faire des
annonces routeurs ("router-advertisements").
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionalités
que le serveur DHCPv4, mais aussi le support des annonces de routeurs ainsi
qu'une fonctionalité permettant l'addition de ressources AAAA pour des
clients utilisant DHCPv4 et la configuration IPv6 sans état (stateless
autoconfiguration).
Il inclut le support d'allocations d'adresses (à la fois en DHCPv6 et en
annonces de routeurs - RA) pour des sous-réseaux dynamiquement délégués via
une délégation de préfixe DHCPv6.
.PP
Dnsmasq est developpé pour de petits systèmes embarqués. It tends à avoir
l'empreinte mémoire la plus faible possible pour les fonctions supportées,
et permet d'exclure les fonctions inutiles du binaire compilé.
.SH OPTIONS
Notes : Il est possible d'utiliser des options sans leur donner de paramètre.
Dans ce cas, la fonction correspondante sera désactivée. Par exemple
@@ -76,9 +92,16 @@ l'absence d'enregistrement SOA.
.TP
.B --max-ttl=<durée>
Définie la valeur de TTL maximum qui sera fournie aux clients. La valeur maximum
de TTL spécifiée sera fournie aux clients en remplacement de la vraie valeur de TTL
si cette dernière est supérieure. La valeur réelle de TTL est cependant conservée dans
le cache afin d'éviter de saturer les serveurs DNS en amont.
de TTL spécifiée sera fournie aux clients en remplacement de la vraie valeur de
TTL si cette dernière est supérieure. La valeur réelle de TTL est cependant
conservée dans le cache afin d'éviter de saturer les serveurs DNS en amont.
.TP
.B --max-cache-ttl=<durée>
Définie la valeur de TTL maximum pour les entrées dans le cache
.TP
.B --auth-ttl=<durée>
Définie la valeur de TTL retournée pour les réponses du serveur faisant
autorité.
.TP
.B \-k, --keep-in-foreground
Ne pas aller en tâche de fond au lancement, mais en dehors de cela, fonctionner
@@ -90,7 +113,10 @@ Mode debug (déverminage) : ne pas aller en tâche de fond, ne pas écrire de
fichier pid, ne pas changer d'identifiant utilisateur, générer un état complet
du cache lors de la réception d'un signal SIGUSR1, envoyer les logs sur la
sortie standard d'erreur ("stderr") de même que dans le syslog, ne pas créer de
processus fils pour traiter les requêtes TCP.
processus fils pour traiter les requêtes TCP. A noter que cette option est à
user pour du déverminage seulement : pour empêcher dnsmasq se fonctionner en
mode démon en production, utiliser
.B -k.
.TP
.B \-q, --log-queries
Enregistrer les résultats des requêtes DNS traitées par Dnsmasq dans un fichier
@@ -185,7 +211,11 @@ ni
.B \--except-interface.
Utiliser l'option
.B --listen-address
à la place.
à la place. Un simple joker, consistant d'un '*' final, peut-être utilisé dans
les options
.B \--interface
et
.B \--except-interface
.TP
.B \-I, --except-interface=<interface name>
Ne pas écouter sur l'interface spécifiée. Notez que l'ordre dans lesquelles les
@@ -198,6 +228,21 @@ et
sont fournies n'importe pas, et que l'option
.B --except-interface
l'emporte toujours sur les autres.
.TP
.B --auth-server=<domaine>,<interface>|<addresse IP>
Active le mode DNS faisant autorité pour les requêtes arrivant sur cette
interface ou sur cette adresse. Noter que l'interface ou l'adresse n'ont
pas besoin d'être mentionées ni dans
.B --interface
ni dans
.B --listen-address
En effet,
.B --auth-server
va passer outre ceux-ci et fournir un service DNS différent sur l'interface
spécifiée. La valeur de <domaine> est l'enregistrement de type "colle"
("glue record"). Il doit correspondre dans le service DNS global avec un
enregistrement de type A et/ou AAAA pointant sur l'adresse sur laquelle dnsmasq
écoute pour le mode DNS faisant autorité.
.TP
.B \-2, --no-dhcp-interface=<nom d'interface>
Ne pas fournir de service DHCP sur l'interface spécifiée, mais fournir tout de
@@ -312,11 +357,14 @@ Ne pas lire le contenu du fichier /etc/resolv.conf. N'obtenir l'adresse des
serveurs de nom amont que depuis la ligne de commande ou le fichier de
configuration de Dnsmasq.
.TP
.B \-1, --enable-dbus
.B \-1, --enable-dbus[=<nom de service>]
Autoriser la mise à jour de la configuration de Dnsmasq par le biais d'appel de
méthodes DBus. Il est possible par ce biais de mettre à jour l'adresse de
serveurs DNS amont (et les domaines correspondants) et de vider le cache. Cette
option nécessite que Dnsmasq soit compilé avec le support DBus.
option nécessite que Dnsmasq soit compilé avec le support DBus. Si un nom de
service est fourni, dnsmasq fourni un service à ce nom, plutôt qu'avec la
valeur par défaut :
.B uk.org.thekelleys.dnsmasq
.TP
.B \-o, --strict-order
Par défaut, Dnsmasq envoie les requêtes à n'importe lequel des serveurs amonts
@@ -455,6 +503,12 @@ n'ayant de réponse ni dans /etc/hosts, ni dans les baux DHCP, et n'étant pas
transmise à un serveur spécifique par le biais d'une directive
.B --server.
.TP
.B --ipset=/<domaine>/[domaine/]<ipset>[,<ipset>]
Obtient les adresses IP des domaines spécifiés et les place dans les groupes
d'IP netfilter (ipset) indiqués. Domaines et sous-domaines sont résolus de la
même façon que pour --address. Ces groupes d'IP doivent déjà exister. Voir
ipset(8) pour plus de détails.
.TP
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préference>]
Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom
donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans
@@ -611,6 +665,34 @@ Si vous utilisez le premier mode DNSSEC, la validation par le resolveur des
clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les
données nécessaires par un client pour effectuer la validation lui-même.
.TP
.B --auth-zone=<domaine>[,<sous-réseau>[,<sous-réseau>.....]]
Définie une zone DNS pour laquelle dnsmasq agit en temps que serveur faisant
autorité. Les enregistrements DNS définis localement et correspondant à ce
domaine seront fournis, à ceci près que les enregistrements A et AAAA doivent
se situer dans l'un des sous-réseaux précisés si ceux-ci sont définis, ou dans
un réseau correspondant à une plage DHCP. Le ou les sous-réseaux sont également
utilisé pour définir les domaines in-addr.arpa et ipv6.arpa servant à
l'interrogation DNS inverse. Dans le cas d'IPv4, la longueur du masque de
réseau doit être de 8, 16 ou 24.
.TP
.B --auth-soa=<numéro de série>[,<mainteneur de zone (hostmaster)>[,<rafraichissement>[,<nombre de réessais>[,<expiration>]]]]
Spécifie les champs de l'enregistrement de type SOA (Start Of Authority)
associé à une zone pour laquelle le serveur fait autorité. A noter que cela est
optionnel, les valeurs par défaut devant convenir à la majorité des cas.
.TP
.B --auth-sec-servers=<domaine>[,<domaine>[,<domaine>...]]
Spécifie un ou plusieurs serveur de nom secondaires pour une zone pour
laquelle dnsmasq fait autorité. Ces serveurs doivent-être configurés pour
récupérer auprès de dnsmasq les informations liées à la zone au travers d'un
transfert de zone, et répondre aux requêtes pour toutes les zones pour
lesquelles dnsmasq fait autorité.
.TP
.B --auth-peer=<adresse IP>[,<adresse IP>[,<adresse IP>...]]
Spécifie la ou les adresses de serveurs secondaires autorisés à initier des
requêtes de transfert de zone (AXFR) pour les zones pour lesquelles
dnsmasq fait autorité. Si cette option n'est pas fournie, les requêtes AXFR
seront acceptées pour tous les serveurs secondaires.
.TP
.B --conntrack
Lis le marquage de suivi de connexion Linux associé aux requêtes DNS entrantes
et positionne la même marque au trafic amont utilisé pour répondre à ces
@@ -623,7 +705,8 @@ configuré pour cela. Cette option ne peut pas être combinée avec
.TP
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.TP
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>[,<adresse IPv6 de fin>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
<adresse de début> et <adresse de fin> et à partir des adresses définies
statiquement dans l'option
@@ -663,6 +746,22 @@ d'IPv4, la longueur de préfixe n'est pas automatiquement déduite de la
configuration de l'interface. La taille minimale pour la longueur de préfixe
est 64.
Pour IPv6 (et IPv6 uniquement), il est possible de définir les plages d'une
autre façon. Dans ce cas, l'adresse de départ et l'adresse de fin optionnelle
contiennent uniquement la partie réseau (par exemple ::1) et sont suivies par
.B constructor:<interface>.
Cela forme un modèle décrivant comment construire la plage, à partir des
adresses assignées à l'interface. Par exemple
.B --dhcp-range=::1,::400,constructor:eth0
provoque la recherche d'adresses de la forme <réseau>::1 sur eth0 et crée une
plage allant de <réseau>::1 à <réseau>:400. Si une interface est assignée à
plus d'un réseau, les plages correspondantes seront automatiquement créées,
rendues obsolètes puis supprimées lorsque l'adress est rendue obsolète puis
supprimée. Le nom de l'interface peut être spécifié avec un caractère joker '*'
final.
L'identifiant de label optionnel
.B set:<label>
fournie une étiquette alphanumérique qui identifie ce réseau, afin de permettre
@@ -677,7 +776,13 @@ Le mot clef optionnel <mode> peut être égal à
spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls
les hôtes possédant des adresses IP statiques fournies via
.B dhcp-host
ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP.
ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP. Il est
possible d'activer un mode "fourre-tout" en définissant un réseau statique
comportant uniquement des zéros, c'est à dire :
.B --dhcp=range=::,static
Cela permet de retourner des réponses à tous les paquets de type
Information-request (requête d'information) en mode DHCPv6 sans état sur le
sous-réseau configuré.
Pour IPv4, le <mode> peut est égal à
.B proxy
@@ -762,6 +867,10 @@ Un seul
peut contenir une adresse IPv4, une adresse IPv6, ou les deux en même temps.
Les adresses IPv6 doivent-être mises entre crochets comme suit :
.B --dhcp-host=laptop,[1234::56]
Les adresses IPv6 peuvent ne contenir que la partie identifiant de client :
.B --dhcp-host=laptop,[::56]
Dans ce cas, lorsque des plages dhcp sont définies automatiquement par le biais
de constructeurs, la partie réseau correspondante est rajoutée à l'adresse.
A noter que pour le DHCP IPv6, l'adresse matérielle n'est en principe pas
disponible, aussi un client doit-être identifié par un identifiant de client
(appellé "DUID client") ou un nom d'hôte.
@@ -1204,14 +1313,16 @@ créant des milliers de baux et utilisant beaucoup de mémoire dans le processus
Dnsmasq.
.TP
.B \-K, --dhcp-authoritative
(IPv4 seulement) Cette option doit être donnée lorsque Dnsmasq est le seul
serveur DHCP sur le réseau. Cela change le comportement par défaut qui est
Doit être spécifié lorsque dnsmasq est réellement le seul serveur DHCP
sur le réseau. Pour DHCPv4, cela change le comportement par défaut qui est
celui d'un strict respect des RFC, afin que les requêtes DHCP pour des baux
inconnus par des hôtes inconnus ne soient pas ignorées. Cela permet à de
nouveaux hôtes d'obtenir des baux sans tenir compte de fastidieuses
temporisations ("timeout"). Cela permet également à Dnsmasq de reconstruire
sa base de données contenant les baux sans que les clients n'aient besoin de
redemander un bail, si celle-ci est perdue.
Dans le cas de DHCPv6, cela positionne la priorité des réponses à 255 (le
maximum) au lieu de 0 (le minimum).
.TP
.B --dhcp-alternate-port[=<port serveur>[,<port client>]]
(IPv4 seulement) Change les ports utilisés par défaut pour le DHCP. Si cette
@@ -1319,6 +1430,9 @@ Pour IPv4 seulement :
DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client.
DNSMASQ_CIRCUIT_ID, DNSMASQ_SUBSCRIBER_ID, DNSMASQ_REMOTE_ID si un relai DHCP a
rajouté l'une de ces options.
Si le client fournit une information de classe de vendeur, DNSMASQ_VENDOR_CLASS.
Pour IPv6 seulement :
@@ -1847,6 +1961,167 @@ supprime la nécessité des associations statiques). Le paramètre
que le label "bootp", permettant un certain contrôle sur les options retournées
aux différentes classes d'hôtes.
.SH CONFIGURATION EN TEMPS QUE SERVEUR FAISANT AUTORITÉ
.PP
Configurer dnsmasq pour agir en temps que serveur DNS faisant autorité est
compliqué par le fait que cela implique la configuration de serveurs DNS
externes pour mettre en place la délégation. Seront présentés ci-dessous trois
scénarios de complexité croissante. Le pré-requis pour chacun de ces scénarios
est l'existence d'une adresse IP globalement disponible, d'un enregistrement de
type A ou AAAA pointant vers cette adresse, ainsi que d'un serveur DNS externe
capable d'effectuer la délégation de la zone en question. Pour la première
partie de ces explications, nous allons appeller serveur.exemple.com
l'enregistrement A (ou AAAA) de l'adresse globalement accessible, et
notre.zone.com la zone pour laquelle dnsmasq fait autorité.
La configuration la plus simple consiste en deux lignes de configuration,
sous la forme :
.nf
.B auth-server=serveur.exemple.com,eth0
.B auth-zone=notre.zone.com,1.2.3.0/24
.fi
ainsi que deux enregistrements dans le DNS externe :
.nf
serveur.exemple.com A 192.0.43.10
notre.zone.com NS serveur.exemple.com
.fi
eth0 est l'interface réseau externe sur laquelle dnsmasq écoute, dont l'adresse
IP (globalement accessible) est 192.0.43.10.
A noter que l'adresse IP externe peut parfaitement être dynamique (par exemple
attribuée par un FAI via DHCP ou PPP). Dans ce cas, l'enregistrement de type A
doit être lié à cet enregistrement dynamique par l'une ou l'autre des techniques
habituelles de système DNS dynamique.
Un exemple plus complexe mais en pratique plus utile correspond au cas où
l'adresse IP globalement accessible se trouve dans la zone pour laquelle
dnsmasq fait autorité, le plus souvent à la racine. Dans ce cas nous avons :
.nf
.B auth-server=notre.zone.com,eth0
.B auth-zone=notre.zone.com,1.2.3.0/24
.fi
.nf
notre.zone.com A 1.2.3.4
notre.zone.com NS our.zone.com
.fi
L'enregistrement A pour notre.zone.com est dorénavant un enregistrement "colle"
qui résoud le problème de poule et d'oeuf consistant à trouver l'adresse IP
du serveur de nom pour notre.zone.com lorsque l'enregistrement se trouve dans
la zone en question. Il s'agit du seul rôle de cet enregistrement : comme dnsmasq
fait désormais autorité pour notre.zone.com, il doit également fournir cet
enregistrement. Si l'adresse externe est statique, cela peut-être réalisé par
le biais d'une entrée dans
.B /etc/hosts
ou via un
.B --host-record.
.nf
.B auth-server=notre.zone.com,eth0
.B host-record=notre.zone.com,1.2.3.4
.B auth-zone=notre.zone.com,1.2.3.0/24
.fi
Si l'adresse externe est dynamique, l'adresse associée à notre.zone.com doit
être dérivée de l'interface correspondante. Cela peut être fait en utilisant
.B interface-name
Sous la forme :
.nf
.B auth-server=notre.zone.com,eth0
.B interface-name=notre.zone.com,eth0
.B auth-zone=notre.zone.com,1.2.3.0/24
.fi
La configuration finale rajoute à cette base un serveur DNS secondaire. Il
s'agit d'un autre serveur DNS qui apprend les données DNS de la zone en
effectuant un transfert de zone, et qui joue le rôle de serveur de secours
au cas où le serveur principal devenait inaccessible. La configuration
de ce serveur secondaire sort du cadre de cette page de manuel. Les éléments
de configuration à rajouter dans dnsmasq sont les simples :
.nf
.B auth-sec-servers=secondaire.monfai.com
.fi
et
.nf
notre.zone.com NS secondaire.monfai.com
.fi
L'addition d'une option auth-sec-servers active les transferts de zone dans
dnsmasq, ce qui permet au serveur secondaire de venir collecter les données
DNS. Si vous souhaitez restreindre l'accès à ces données à des hôtes
spécifiques, vous pouvez le faire via :
.nf
.B auth-peer=<adresse IP du serveur secondaire>
.fi
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
et ipv6.arpa associés aux sous-réseaux définis dans la déclaration de zone
auth-zone, ce qui fait que les requêtes DNS inversées (de l'adresse vers
le nom) peuvent-simplement être configurées avec un enregistrement NS
adéquat. Par exemple, comme nous définissons plus haut les adresses
1.2.3.0/24 :
.nf
3.2.1.in-addr.arpa NS notre.zone.com
.fi
Veuillez noter que pour l'instant, les zones inverses ne sont pas
disponibles dans les transferts de zone, donc il est inutile de configurer
de serveur secondaire pour la résolution inverse.
.PP
Lorsque dnsmasq est configuré en temps que serveur faisant autorité,
les données suivantes sont utilisées pour peupler la zone considérée :
.PP
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record
, pour autant que les noms des enregistrements se trouvent dans la zone en
question.
.PP
.B --cname
pour peu que le nom soit dans le domaine. Si la cible du CNAME n'est
pas pleinement qualifiée, alors elle est qualifiée avec le nom de la
zone pour laquelle le serveur fait autorité.
.PP
Les adresses IPv4 et IPv6 extraites de /etc/hosts (et
.B --addn-hosts
) ainsi que les options
.B --host-record
fournissant des adresses situées dans l'un des sous-réseaux spécifiés dans
.B --auth-zone.
.PP
Adresses spécifiées par
.B --interface-name.
Dans ce cas, l'adresse n'est pas limitée à l'un des sous-réseaux donné dans
.B --auth-zone.
.PP
Les adresses de baux DHCP, si l'adresse est située dans l'un des sous-réseaux de
.B --auth-zone
OU dans une plage DHCP construite. Dans le mode par défaut, où le bail
DHCP a un nom non qualifié, et éventuellement pour un nom qualifié construit
via
.B --domain
, alors le nom dans la zone faisant autorité est construit à partir du nom
non qualifié et du nom de domaine de la zone. Cela peut on non être égal
celui fourni par
.B --domain.
Si l'option
.B --dhcp-fqdn
est fournie, alors les noms pleinemenet qualifiés associés aux baux DHCP
sont utilisés, dès lors qu'ils correspondent au nom de domaine associé
à la zone.
.SH CODES DE SORTIE
.PP
0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est
+595 -413
View File
File diff suppressed because it is too large. Load diff
+651 -443
View File
File diff suppressed because it is too large. Load diff
+600 -405
View File
File diff suppressed because it is too large. Load diff
+642 -445
View File
File diff suppressed because it is too large. Load diff
+685 -461
View File
File diff suppressed because it is too large. Load diff
+600 -405
View File
File diff suppressed because it is too large. Load diff
+649 -442
View File
File diff suppressed because it is too large. Load diff
+582 -415
View File
File diff suppressed because it is too large. Load diff
+600 -405
View File
File diff suppressed because it is too large. Load diff
+649 -442
View File
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -721,10 +721,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
daemon->soa_retry, daemon->soa_expiry,
daemon->auth_ttl))
anscount++;
}
}
}
/* done all questions, set up header and return length of result */
/* clear authoritative and truncated flags, set QR flag */
+2 -2
View File
@@ -135,12 +135,12 @@ RESOLVFILE
#define HAVE_TFTP
#define HAVE_SCRIPT
#define HAVE_AUTH
#define HAVE_IPSET
/* #define HAVE_LUASCRIPT */
/* #define HAVE_BROKEN_RTC */
/* #define HAVE_DBUS */
/* #define HAVE_IDN */
/* #define HAVE_CONNTRACK */
/* #define HAVE_IPSET */
/* Default locations for important system files. */
@@ -327,7 +327,7 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_AUTH
#endif
#ifndef HAVE_LINUX_NETWORK
#if defined(NO_IPSET) || !defined(HAVE_LINUX_NETWORK)
#undef HAVE_IPSET
#endif
+12 -6
View File
@@ -91,6 +91,7 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
{
struct dhcp_netid *tagif = run_tag_if(tags);
struct dhcp_opt *opt;
struct dhcp_opt *tmp;
/* flag options which are valid with the current tag set (sans context tags) */
for (opt = opts; opt; opt = opt->next)
@@ -135,7 +136,6 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) && !opt->netid)
{
struct dhcp_opt *tmp;
for (tmp = opts; tmp; tmp = tmp->next)
if (tmp->opt == opt->opt && (tmp->flags & DHOPT_TAGOK))
break;
@@ -145,6 +145,13 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring duplicate dhcp-option %d"), tmp->opt);
}
/* Finally, eliminate duplicate options later in the chain, and therefore earlier in the config file. */
for (opt = opts; opt; opt = opt->next)
if (opt->flags & DHOPT_TAGOK)
for (tmp = opt->next; tmp; tmp = tmp->next)
if (tmp->opt == opt->opt)
tmp->flags &= ~DHOPT_TAGOK;
return tagif;
}
@@ -505,7 +512,7 @@ void display_opts6(void)
}
#endif
u16 lookup_dhcp_opt(int prot, char *name)
int lookup_dhcp_opt(int prot, char *name)
{
const struct opttab_t *t;
int i;
@@ -521,10 +528,10 @@ u16 lookup_dhcp_opt(int prot, char *name)
if (strcasecmp(t[i].name, name) == 0)
return t[i].val;
return 0;
return -1;
}
u16 lookup_dhcp_len(int prot, u16 val)
int lookup_dhcp_len(int prot, int val)
{
const struct opttab_t *t;
int i;
@@ -714,8 +721,7 @@ void log_context(int family, struct dhcp_context *context)
template = p;
p += sprintf(p, ", ");
sprintf(p, "template for %s%s", context->template_interface,
(context->flags & CONTEXT_WILDCARD) ? "*" : "");
sprintf(p, "template for %s", context->template_interface);
}
#endif
+13 -5
View File
@@ -65,14 +65,22 @@ static int make_fd(int port)
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 67. That's OK if they serve different networks.
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
Need to set REUSEADDR|REUSEPORT to make this posible.
Handle the case that REUSEPORT is defined, but the kernel doesn't
support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
int rc = -1, porterr = 0;
#ifdef SO_REUSEPORT
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
#else
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
errno != ENOPROTOOPT)
porterr = 1;
#endif
if (rc == -1 && !porterr)
rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
if (rc == -1)
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
}
@@ -252,7 +260,7 @@ void dhcp_packet(time_t now, int pxe_fd)
}
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
/* unlinked contexts are marked by context->current == context */
+5
View File
@@ -59,6 +59,11 @@
#define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39
/* replace this with the real number when allocated.
defining this also enables the relevant code. */
/* #define OPTION6_PREFIX_CLASS 99 */
#define DHCP6SUCCESS 0
#define DHCP6UNSPEC 1
#define DHCP6NOADDRS 2
+50 -35
View File
@@ -48,16 +48,24 @@ void dhcp6_init(void)
!set_ipv6pktinfo(fd))
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
/* When bind-interfaces is set, there might be more than one dnmsasq
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 547. That's OK if they serve different networks.
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
Need to set REUSEADDR|REUSEPORT to make this posible.
Handle the case that REUSEPORT is defined, but the kernel doesn't
support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
int rc = -1, porterr = 0;
#ifdef SO_REUSEPORT
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
#else
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
errno != ENOPROTOOPT)
porterr = 1;
#endif
if (rc == -1 && !porterr)
rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
if (rc == -1)
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL, EC_BADNET);
}
@@ -120,11 +128,11 @@ void dhcp6_packet(time_t now)
return;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
parm.current = NULL;
@@ -153,7 +161,7 @@ void dhcp6_packet(time_t now)
{
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
break;
if (!tmp && !parm.addr_match)
@@ -266,7 +274,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
}
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int iaid, struct dhcp_netid *netids, struct in6_addr *ans)
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -286,7 +294,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= 1; pass++)
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS | CONTEXT_USED))
continue;
@@ -296,7 +304,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
{
if (option_bool(OPT_CONSEC_ADDR))
/* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c);
start = lease_find_max_addr6(c) + serial;
else
start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
@@ -326,13 +334,14 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
} while (addr != start);
}
return 0;
return NULL;
}
/* can dynamically allocate addr */
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
struct dhcp_netid *netids,
int plain_range)
{
u64 start, end, addr = addr6part(taddr);
struct dhcp_context *tmp;
@@ -347,7 +356,7 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
is_same_net6(&tmp->end6, taddr, tmp->prefix) &&
addr >= start &&
addr <= end &&
match_netid(tmp->filter, netids, 1))
match_netid(tmp->filter, netids, plain_range))
return tmp;
}
@@ -356,44 +365,52 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
/* address OK if configured */
struct dhcp_context *address6_valid(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
struct in6_addr *taddr,
struct dhcp_netid *netids,
int plain_range)
{
struct dhcp_context *tmp;
for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
match_netid(tmp->filter, netids, 1))
match_netid(tmp->filter, netids, plain_range))
return tmp;
return NULL;
}
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
{
/* expand wildcard on contructed contexts */
if ((config->flags & CONFIG_WILDCARD) &&
(context->flags & CONTEXT_CONSTRUCTED))
if (!config || !(config->flags & CONFIG_ADDR6))
return 0;
if ((config->flags & CONFIG_WILDCARD) && context->prefix == 64)
{
u64 addrpart = addr6part(&config->addr6);
config->addr6 = context->start6;
setaddr6part(&config->addr6, addrpart);
*addr = context->start6;
setaddr6part(addr, addr6part(&config->addr6));
return 1;
}
if (is_same_net6(&context->start6, &config->addr6, context->prefix))
{
*addr = config->addr6;
return 1;
}
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6))
return 1;
return 0;
}
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr)
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
{
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
return 1;
if (!(config->flags & CONFIG_ADDR6) ||
(config->flags & CONFIG_WILDCARD))
return 1;
for (; context; context = context->current)
if (is_same_net6(&config->addr6, &context->start6, context->prefix))
return 1;
return 0;
}
@@ -521,9 +538,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
}
}
else if (addr6part(local) == addr6part(&template->start6) &&
strncmp(template->template_interface, ifrn_name, strlen(template->template_interface)) == 0 &&
(strlen(template->template_interface) == strlen(ifrn_name) || (template->flags & CONTEXT_WILDCARD)))
else if (addr6part(local) == addr6part(&template->start6) && wildcard_match(template->template_interface, ifrn_name))
{
start6 = *local;
setaddr6part(&start6, addr6part(&template->start6));
+16 -8
View File
@@ -543,6 +543,7 @@ struct dhcp_lease {
int backoff; /* zero -> confirmed */
struct slaac_address *next;
} *slaac_address;
int vendorclass_count;
#endif
struct dhcp_lease *next;
};
@@ -684,7 +685,7 @@ struct cond_domain {
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class {
int class;
struct dhcp_netid netid;
struct dhcp_netid tag;
struct prefix_class *next;
};
#endif
@@ -721,7 +722,7 @@ struct dhcp_context {
#define CONTEXT_CONSTRUCTED 2048
#define CONTEXT_GC 4096
#define CONTEXT_RA 8192
#define CONTEXT_WILDCARD 16384
#define CONTEXT_CONF_USED 16384
#define CONTEXT_USED 32768
struct ping_result {
@@ -829,6 +830,9 @@ extern struct daemon {
unsigned char *duid_config;
char *dbus_name;
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *prefix_classes;
#endif
/* globally used stuff for DNS */
char *packet; /* packet buffer */
@@ -976,6 +980,8 @@ char *print_mac(char *buff, unsigned char *mac, int len);
void bump_maxfd(int fd, int *max);
int read_write(int fd, unsigned char *packet, int size, int rw);
int wildcard_match(const char* wildcard, const char* match);
/* log.c */
void die(char *message, char *arg1, int exit_code);
int log_start(struct passwd *ent_pw, int errfd);
@@ -1171,14 +1177,16 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
void dhcp6_init(void);
void dhcp6_packet(time_t now);
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int iaid, struct dhcp_netid *netids, struct in6_addr *ans);
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr);
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids);
struct dhcp_netid *netids,
int plain_range);
struct dhcp_context *address6_valid(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids);
struct dhcp_netid *netids,
int plain_range);
struct dhcp_config *find_config6(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *duid, int duid_len,
@@ -1208,8 +1216,8 @@ void log_tags(struct dhcp_netid *netid, u32 xid);
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
void dhcp_update_configs(struct dhcp_config *configs);
void display_opts(void);
u16 lookup_dhcp_opt(int prot, char *name);
u16 lookup_dhcp_len(int prot, u16 val);
int lookup_dhcp_opt(int prot, char *name);
int lookup_dhcp_len(int prot, int val);
char *option_string(int prot, unsigned int opt, unsigned char *val,
int opt_len, char *buf, int buf_len);
#ifdef HAVE_LINUX_NETWORK
+17 -22
View File
@@ -328,8 +328,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct server *firstsentto = start;
int forwarded = 0;
if (udpaddr && option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, ((char *) header) + PACKETSZ, udpaddr);
if (option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, ((char *) header) + PACKETSZ, &forward->source);
while (1)
{
@@ -372,7 +372,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
if (get_incoming_mark(udpaddr, dst_addr, 0, &mark))
if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
#endif
@@ -680,7 +680,7 @@ void receive_query(struct listener *listen, time_t now)
dst_addr_4.s_addr = 0;
netmask.s_addr = 0;
if (listen->iface && option_bool(OPT_NOWILD))
if (option_bool(OPT_NOWILD) && listen->iface)
{
auth_dns = listen->iface->dns_auth;
@@ -880,9 +880,12 @@ unsigned char *tcp_request(int confd, time_t now,
unsigned short qtype;
unsigned int gotname;
unsigned char c1, c2;
/* Max TCP packet + slop */
unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
struct dns_header *header;
/* Max TCP packet + slop + size */
unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
unsigned char *payload = &packet[2];
/* largest field in header is 16-bits, so this is still sufficiently aligned */
struct dns_header *header = (struct dns_header *)payload;
u16 *length = (u16 *)packet;
struct server *last_server;
struct in_addr dst_addr_4;
union mysockaddr peer_addr;
@@ -896,14 +899,12 @@ unsigned char *tcp_request(int confd, time_t now,
if (!packet ||
!read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
!(size = c1 << 8 | c2) ||
!read_write(confd, packet, size, 1))
!read_write(confd, payload, size, 1))
return packet;
if (size < (int)sizeof(struct dns_header))
continue;
header = (struct dns_header *)packet;
/* save state of "cd" flag in query */
checking_disabled = header->hb4 & HB4_CD;
@@ -1020,12 +1021,9 @@ unsigned char *tcp_request(int confd, time_t now,
#endif
}
c1 = size >> 8;
c2 = size;
*length = htons(size);
if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
!read_write(last_server->tcpfd, &c2, 1, 0) ||
!read_write(last_server->tcpfd, packet, size, 0) ||
if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
!read_write(last_server->tcpfd, &c1, 1, 1) ||
!read_write(last_server->tcpfd, &c2, 1, 1))
{
@@ -1035,7 +1033,7 @@ unsigned char *tcp_request(int confd, time_t now,
}
m = (c1 << 8) | c2;
if (!read_write(last_server->tcpfd, packet, m, 1))
if (!read_write(last_server->tcpfd, payload, m, 1))
return packet;
if (!gotname)
@@ -1071,12 +1069,9 @@ unsigned char *tcp_request(int confd, time_t now,
check_log_writer(NULL);
c1 = m>>8;
c2 = m;
if (m == 0 ||
!read_write(confd, &c1, 1, 0) ||
!read_write(confd, &c2, 1, 0) ||
!read_write(confd, packet, m, 0))
*length = htons(m);
if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
return packet;
}
}
+8 -2
View File
@@ -655,8 +655,9 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
unsigned char *p;
unsigned int hostname_len = 0, clid_len = 0, ed_len = 0;
int fd = daemon->dhcpfd;
#ifdef HAVE_DHCP6
int is6 = !!(lease->flags & (LEASE_TA | LEASE_NA));
#ifdef HAVE_DHCP6
if (!daemon->dhcp)
fd = daemon->dhcp6fd;
#endif
@@ -676,7 +677,12 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
buf->action = action;
buf->flags = lease->flags;
buf->hwaddr_len = lease->hwaddr_len;
#ifdef HAVE_DHCP6
if (is6)
buf->hwaddr_len = lease->vendorclass_count;
else
#endif
buf->hwaddr_len = lease->hwaddr_len;
buf->hwaddr_type = lease->hwaddr_type;
buf->clid_len = clid_len;
buf->ed_len = ed_len;
+1 -1
View File
@@ -110,7 +110,7 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
return -1;
}
memset(buffer, 0, sizeof(buffer));
memset(buffer, 0, BUFF_SZ);
nlh = (struct nlmsghdr *)buffer;
nlh->nlmsg_len = NL_ALIGN(sizeof(struct nlmsghdr));
+14 -5
View File
@@ -115,7 +115,7 @@ void lease_init(time_t now)
s++;
}
hw_type = atoi(s);
hw_type = strtoul(s, NULL, 10);
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
{
@@ -595,6 +595,8 @@ struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_typ
if (!first)
first = leases;
else
first = first->next;
for (lease = first; lease; lease = lease->next)
{
@@ -701,8 +703,11 @@ static struct dhcp_lease *lease_allocate(void)
struct dhcp_lease *lease4_allocate(struct in_addr addr)
{
struct dhcp_lease *lease = lease_allocate();
lease->addr = addr;
lease->hwaddr_len = 256; /* illegal value */
if (lease)
{
lease->addr = addr;
lease->hwaddr_len = 256; /* illegal value */
}
return lease;
}
@@ -711,8 +716,12 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr)
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
{
struct dhcp_lease *lease = lease_allocate();
memcpy(lease->hwaddr, addrp, sizeof(*addrp)) ;
lease->flags |= lease_type;
if (lease)
{
memcpy(lease->hwaddr, addrp, sizeof(*addrp)) ;
lease->flags |= lease_type;
}
return lease;
}
+3 -3
View File
@@ -123,7 +123,7 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
ret = 0;
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
if (tmp->name && wildcard_match(tmp->name, name))
ret = tmp->used = 1;
if (addr)
@@ -143,7 +143,7 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
}
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
if (tmp->name && wildcard_match(tmp->name, name))
ret = 0;
@@ -291,7 +291,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
}
else
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
{
tftp_ok = 0;
dhcp_ok = 0;
+50 -19
View File
@@ -128,6 +128,9 @@ struct myoption {
#define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318
#define LOPT_IPSET 319
#ifdef OPTION6_PREFIX_CLASS
#define LOPT_PREF_CLSS 320
#endif
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -261,6 +264,9 @@ static const struct myoption opts[] =
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
{ "ipset", 1, 0, LOPT_IPSET },
#ifdef OPTION6_PREFIX_CLASS
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
#endif
{ NULL, 0, 0, 0 }
};
@@ -400,6 +406,9 @@ static struct {
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
{ 0, 0, NULL, NULL, NULL }
};
@@ -741,6 +750,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
struct dhcp_netid *np = NULL;
u16 opt_len = 0;
int is6 = 0;
int option_ok = 0;
new->len = 0;
new->flags = flags;
@@ -760,16 +770,19 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
{
new->opt = atoi(arg);
opt_len = 0;
option_ok = 1;
break;
}
if (strstr(arg, "option:") == arg)
{
new->opt = lookup_dhcp_opt(AF_INET, arg+7);
opt_len = lookup_dhcp_len(AF_INET, new->opt);
/* option:<optname> must follow tag and vendor string. */
if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH)
new->opt = 0;
if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1)
{
opt_len = lookup_dhcp_len(AF_INET, new->opt);
/* option:<optname> must follow tag and vendor string. */
if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
option_ok = 1;
}
break;
}
#ifdef HAVE_DHCP6
@@ -783,13 +796,16 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
{
new->opt = atoi(arg+8);
opt_len = 0;
option_ok = 1;
}
else
{
new->opt = lookup_dhcp_opt(AF_INET6, arg+8);
opt_len = lookup_dhcp_len(AF_INET6, new->opt);
if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH)
new->opt = 0;
if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1)
{
opt_len = lookup_dhcp_len(AF_INET6, new->opt);
if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH)
option_ok = 1;
}
}
/* option6:<opt>|<optname> must follow tag and vendor string. */
is6 = 1;
@@ -812,7 +828,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
new->flags |= DHOPT_RFC3925;
if (flags == DHOPT_MATCH)
{
new->opt = 1; /* avoid error below */
option_ok = 1;
break;
}
}
@@ -839,16 +855,16 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
if (opt_len == 0 &&
!(new->flags & DHOPT_RFC3925))
opt_len = lookup_dhcp_len(AF_INET6 ,new->opt);
opt_len = lookup_dhcp_len(AF_INET6, new->opt);
}
else
#endif
if (opt_len == 0 &&
!(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
opt_len = lookup_dhcp_len(AF_INET ,new->opt);
opt_len = lookup_dhcp_len(AF_INET, new->opt);
/* option may be missing with rfc3925 match */
if (new->opt == 0)
if (!option_ok)
ret_err(_("bad dhcp-option"));
if (comma)
@@ -2366,11 +2382,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->flags |= CONTEXT_DHCP;
else if (strstr(a[leasepos], "constructor:") == a[leasepos])
{
if (a[leasepos][strlen(a[leasepos])-1] == '*')
{
a[leasepos][strlen(a[leasepos])-1] = 0;
new->flags |= CONTEXT_WILDCARD;
}
new->template_interface = opt_string_alloc(a[leasepos] + 12);
new->flags |= CONTEXT_TEMPLATE;
}
@@ -2414,6 +2425,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
}
#endif
else
ret_err(_("bad dhcp-range"));
if (leasepos < k)
{
@@ -2943,7 +2956,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
}
break;
#ifdef OPTION6_PREFIX_CLASS
case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
{
struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
if (!(comma = split(arg)) ||
!atoi_check16(comma, &new->class))
ret_err(gen_err);
new->tag.net = opt_string_alloc(set_prefix(arg));
new->next = daemon->prefix_classes;
daemon->prefix_classes = new;
break;
}
#endif
case 'U': /* --dhcp-vendorclass */
case 'j': /* --dhcp-userclass */
case LOPT_CIRCUIT: /* --dhcp-circuitid */
+2 -2
View File
@@ -158,7 +158,7 @@ void icmp6_packet(time_t now)
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, interface) == 0))
if (tmp->name && wildcard_match(tmp->name, interface))
return;
if (packet[1] != 0)
@@ -533,7 +533,7 @@ time_t periodic_ra(time_t now)
{
struct iname *tmp;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, interface) == 0))
if (tmp->name && wildcard_match(tmp->name, interface))
break;
if (!tmp)
send_ra(now, param.iface, interface, NULL);
+329 -120
View File
@@ -29,6 +29,9 @@ struct state {
char *iface_name;
void *packet_options, *end;
struct dhcp_netid *tags, *context_tags;
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *send_prefix_class;
#endif
};
static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **relay_tagsp, struct dhcp_context *context,
@@ -45,11 +48,19 @@ static void get_context_tag(struct state *state, struct dhcp_context *context);
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
static int build_ia(struct state *state, int *t1cntr);
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
#ifdef OPTION6_PREFIX_CLASS
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context);
#endif
static void mark_context_used(struct state *state, struct dhcp_context *context, struct in6_addr *addr);
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
static int check_address(struct state *state, struct in6_addr *addr);
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, unsigned int requested_time,
unsigned int *min_time, struct in6_addr *addr, int update_lease, time_t now);
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
static int add_local_addrs(struct dhcp_context *context);
struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, struct dhcp_context *context);
static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
unsigned int *preferred_timep, unsigned int lease_time, unsigned int requested_time);
#define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
#define opt6_type(opt) (opt6_uint(opt, -4, 2))
@@ -113,6 +124,7 @@ static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **
is_same_net6(link_address, &c->start6, c->prefix) &&
is_same_net6(link_address, &c->end6, c->prefix))
{
c->preferred = c->valid = 0xffffffff;
c->current = context;
context = c;
}
@@ -204,6 +216,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
struct dhcp_context *context_tmp;
unsigned int ignore = 0;
struct state state;
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *p;
int dump_all_prefix_classes = 0;
#endif
state.packet_options = inbuff + 4;
state.end = inbuff + sz;
@@ -221,6 +237,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
state.client_hostname = NULL;
state.iface_name = iface_name;
state.fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
#ifdef OPTION6_PREFIX_CLASS
state.send_prefix_class = NULL;
#endif
/* set tag with name == interface */
iface_id.net = iface_name;
@@ -460,7 +479,32 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (have_config(config, CONFIG_DISABLE))
ignore = 1;
}
#ifdef OPTION6_PREFIX_CLASS
/* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
if (daemon->prefix_classes && (msg_type == DHCP6SOLICIT || msg_type == DHCP6REQUEST))
{
void *oro;
if ((oro = opt6_find(state.packet_options, state.end, OPTION6_ORO, 0)))
for (i = 0; i < opt6_len(oro) - 1; i += 2)
if (opt6_uint(oro, i, 2) == OPTION6_PREFIX_CLASS)
{
dump_all_prefix_classes = 1;
break;
}
if (msg_type != DHCP6SOLICIT || dump_all_prefix_classes)
/* Add the tags associated with prefix classes so we can use the DHCP ranges.
Not done for SOLICIT as we add them one-at-time. */
for (p = daemon->prefix_classes; p ; p = p->next)
{
p->tag.next = state.tags;
state.tags = &p->tag;
}
}
#endif
tagif = run_tag_if(state.tags);
/* if all the netids in the ignore list are present, ignore this client */
@@ -495,8 +539,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
case DHCP6SOLICIT:
{
void *rapid_commit = opt6_find(state.packet_options, state.end, OPTION6_RAPID_COMMIT, 0);
int used_config = 0, address_assigned = 0;
int address_assigned = 0;
/* tags without all prefix-class tags */
struct dhcp_netid *solicit_tags = tagif;
struct dhcp_context *c;
if (rapid_commit)
{
o = new_opt6(OPTION6_RAPID_COMMIT);
@@ -506,111 +553,180 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* set reply message type */
*outmsgtypep = rapid_commit ? DHCP6REPLY : DHCP6ADVERTISE;
log6_packet(&state, "DHCPSOLICIT", NULL, ignore ? "ignored" : NULL);
log6_packet(&state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
if (ignore)
return 0;
/* reset USED bits in leases */
lease6_reset();
/* Can use configured address max once per prefix */
for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_CONF_USED;
for (opt = state.packet_options; opt; opt = opt6_next(opt, state.end))
{
void *ia_option, *ia_end;
unsigned int min_time = 0xffffffff;
int t1cntr;
int config_ok = 0;
struct dhcp_context *c;
int ia_counter;
/* set unless we're sending a particular prefix-class, when we
want only dhcp-ranges with the correct tags set and not those without any tags. */
int plain_range = 1;
u32 lease_time, requested_time;
struct dhcp_lease *ltmp;
struct in6_addr *req_addr;
struct in6_addr addr;
if (!check_ia(&state, opt, &ia_end, &ia_option))
continue;
if (have_config(config, CONFIG_ADDR6))
/* reset USED bits in contexts - one address per prefix per IAID */
for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_USED;
#ifdef OPTION6_PREFIX_CLASS
if (daemon->prefix_classes && state.ia_type == OPTION6_IA_NA)
{
struct dhcp_lease *config_lease = lease6_find_by_addr(&config->addr6, 128, 0);
void *prefix_opt;
int prefix_class;
config_ok = 1;
if (config_lease &&
(config_lease->clid_len != state.clid_len ||
memcmp(config_lease->clid, state.clid, state.clid_len) != 0 ||
config_lease->hwaddr_type != state.iaid))
config_ok = 0; /* configured address leased elsewhere */
if (dump_all_prefix_classes)
/* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
plain_range = 0;
else
{
if ((prefix_opt = opt6_find(opt6_ptr(opt, 12), ia_end, OPTION6_PREFIX_CLASS, 2)))
{
prefix_class = opt6_uint(prefix_opt, 0, 2);
for (p = daemon->prefix_classes; p ; p = p->next)
if (p->class == prefix_class)
break;
if (!p)
my_syslog(MS_DHCP | LOG_WARNING, _("unknown prefix-class %d"), prefix_class);
else
{
/* add tag to list, and exclude undecorated dhcp-ranges */
p->tag.next = state.tags;
solicit_tags = run_tag_if(&p->tag);
plain_range = 0;
state.send_prefix_class = p;
}
}
else
{
/* client didn't ask for a prefix class, lets see if we can find one. */
for (p = daemon->prefix_classes; p ; p = p->next)
{
p->tag.next = NULL;
if (match_netid(&p->tag, solicit_tags, 1))
break;
}
if (p)
{
plain_range = 0;
state.send_prefix_class = p;
}
}
if (p && option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, "%u prefix class %d tag:%s", state.xid, p->class, p->tag.net);
}
}
/* reset USED bits in leases */
lease6_reset();
#endif
o = build_ia(&state, &t1cntr);
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
req_addr = opt6_ptr(ia_option, 0);
ltmp = lease6_find_by_addr(req_addr, 128, 0);
requested_time = opt6_uint(ia_option, 16, 4);
/* reset USED bits in contexts - one address per prefix per IAID */
for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_USED;
if ((c = address6_valid(context, req_addr, tagif)))
if ((c = address6_valid(context, req_addr, solicit_tags, plain_range)))
{
lease_time = c->lease_time;
/* If the client asks for an address on the same network as a configured address,
offer the configured address instead, to make moving to newly-configured
addresses automatic. */
if (!used_config && config_ok && is_same_net6(req_addr, &config->addr6, c->prefix))
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(&state, &addr))
{
req_addr = &config->addr6;
used_config = 1;
req_addr = &addr;
mark_config_used(c, &addr);
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
}
else if (!(c = address6_available(context, req_addr, tagif)))
else if (!(c = address6_available(context, req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */
else if (ltmp &&
(ltmp->clid_len != state.clid_len ||
memcmp(ltmp->clid, state.clid, state.clid_len) != 0 ||
ltmp->hwaddr_type != state.iaid))
else if (!check_address(&state, req_addr))
continue; /* address leased elsewhere */
/* add address to output packet */
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
state.send_prefix_class = prefix_class_from_context(c);
#endif
add_address(&state, c, lease_time, requested_time, &min_time, req_addr, rapid_commit != NULL, now);
mark_context_used(&state, context, req_addr);
get_context_tag(&state, c);
address_assigned = 1;
}
}
/* Suggest configured address */
if (!used_config && config_ok && (c = address6_valid(context, &config->addr6, tagif)))
{
used_config = 1;
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
/* add address to output packet */
add_address(&state, c, lease_time, requested_time, &min_time, &config->addr6, rapid_commit != NULL, now);
get_context_tag(&state, c);
address_assigned = 1;
}
/* Suggest configured address(es) */
for (c = context; c; c = c->current)
if (!(c->flags & CONTEXT_CONF_USED) &&
match_netid(c->filter, solicit_tags, plain_range) &&
config_valid(config, c, &addr) &&
check_address(&state, &addr))
{
mark_config_used(context, &addr);
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = c->lease_time;
/* add address to output packet */
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
state.send_prefix_class = prefix_class_from_context(c);
#endif
add_address(&state, c, lease_time, lease_time, &min_time, &addr, rapid_commit != NULL, now);
mark_context_used(&state, context, &addr);
get_context_tag(&state, c);
address_assigned = 1;
}
/* return addresses for existing leases */
ltmp = NULL;
while ((ltmp = lease6_find_by_client(ltmp, state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state.clid, state.clid_len, state.iaid)))
{
req_addr = (struct in6_addr *)ltmp->hwaddr;
if ((c = address6_available(context, req_addr, tagif)))
if ((c = address6_available(context, req_addr, solicit_tags, plain_range)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
state.send_prefix_class = prefix_class_from_context(c);
#endif
add_address(&state, c, c->lease_time, c->lease_time, &min_time, req_addr, rapid_commit != NULL, now);
mark_context_used(&state, context, req_addr);
get_context_tag(&state, c);
address_assigned = 1;
}
}
/* Return addresses for all valid contexts which don't yet have one */
while ((c = address6_allocate(context, state.clid, state.clid_len, state.iaid, tagif, &addr)))
while ((c = address6_allocate(context, state.clid, state.clid_len, state.iaid, ia_counter, solicit_tags, plain_range, &addr)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
state.send_prefix_class = prefix_class_from_context(c);
#endif
add_address(&state, c, c->lease_time, c->lease_time, &min_time, &addr, rapid_commit != NULL, now);
mark_context_used(&state, context, &addr);
get_context_tag(&state, c);
address_assigned = 1;
}
@@ -623,7 +739,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS);
put_opt6_string("Oh hai from dnsmasq");
put_opt6_string(_("success"));
end_opt6(o1);
/* If --dhcp-authoritative is set, we can tell client not to wait for
@@ -638,9 +754,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* no address, return error */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS);
put_opt6_string("No addresses available");
put_opt6_string(_("no addresses available"));
end_opt6(o1);
log6_packet(&state, "DHCPADVERTISE", NULL, _("No addresses available"));
log6_packet(&state, "DHCPADVERTISE", NULL, _("no addresses available"));
}
break;
@@ -653,7 +769,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* set reply message type */
*outmsgtypep = DHCP6REPLY;
log6_packet(&state, "DHCPREQUEST", NULL, ignore ? "ignored" : NULL);
log6_packet(&state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
if (ignore)
return 0;
@@ -675,24 +791,28 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
u32 requested_time = opt6_uint(ia_option, 16, 4);
struct dhcp_context *dynamic, *c;
unsigned int lease_time;
if ((dynamic = address6_available(context, req_addr, tagif)) || (c = address6_valid(context, req_addr, tagif)))
struct in6_addr addr;
int config_ok = 0;
if ((c = address6_valid(context, req_addr, tagif, 1)))
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
if ((dynamic = address6_available(context, req_addr, tagif, 1)) || c)
{
if (!dynamic && !(have_config(config, CONFIG_ADDR6) || !IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr)))
if (!dynamic && !config_ok)
{
/* Static range, not configured. */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address unavailable");
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
else if (lease6_find_by_addr(req_addr, 128, 0) &&
!lease6_find(state.clid, state.clid_len, state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state.iaid, req_addr))
else if (!check_address(&state, req_addr))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address in use");
put_opt6_string(_("address in use"));
end_opt6(o1);
}
else
@@ -702,22 +822,24 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
lease_time = dynamic->lease_time;
if (have_config(config, CONFIG_ADDR6) &&
IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr) &&
have_config(config, CONFIG_TIME))
if (config_ok && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
state.send_prefix_class = prefix_class_from_context(c);
#endif
add_address(&state, dynamic, lease_time, requested_time, &min_time, req_addr, 1, now);
get_context_tag(&state, dynamic);
address_assigned = 1;
}
}
else if (msg_type == DHCP6REQUEST)
else
{
/* requested address not on the correct link */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Not on link");
put_opt6_string(_("not on link"));
end_opt6(o1);
}
}
@@ -730,7 +852,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS);
put_opt6_string("Oh hai from dnsmasq");
put_opt6_string(_("success"));
end_opt6(o1);
}
else
@@ -738,9 +860,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* no address, return error */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS);
put_opt6_string("No addresses available");
put_opt6_string(_("no addresses available"));
end_opt6(o1);
log6_packet(&state, "DHCPREPLY", NULL, _("No addresses available"));
log6_packet(&state, "DHCPREPLY", NULL, _("no addresses available"));
}
tagif = add_options(&state, fallback, context);
@@ -772,14 +894,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
struct dhcp_lease *lease = NULL;
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
u32 requested_time = opt6_uint(ia_option, 16, 4);
unsigned int lease_time;
unsigned int preferred_time = 0; /* in case renewal inappropriate */
unsigned int valid_time = 0;
char *message = NULL;
struct dhcp_context *this_context;
struct dhcp_config *valid_config = config;
/* don't use a config to set lease time if it specifies an address which isn't this. */
if (have_config(config, CONFIG_ADDR6) && !IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr))
valid_config = NULL;
if (!(lease = lease6_find(state.clid, state.clid_len,
state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state.iaid, req_addr)))
@@ -790,48 +909,54 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
save_counter(iacntr);
t1cntr = 0;
log6_packet(&state, "DHCPREPLY", req_addr, "lease not found");
log6_packet(&state, "DHCPREPLY", req_addr, _("lease not found"));
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING);
put_opt6_string("No binding found");
put_opt6_string(_("no binding found"));
end_opt6(o1);
break;
}
if ((this_context = address6_available(context, req_addr, tagif)) ||
(this_context = address6_valid(context, req_addr, tagif)))
if ((this_context = address6_available(context, req_addr, tagif, 1)) ||
(this_context = address6_valid(context, req_addr, tagif, 1)))
{
struct in6_addr addr;
unsigned int lease_time;
get_context_tag(&state, this_context);
lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = this_context->lease_time;
if (requested_time < 120u )
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time, requested_time);
lease_set_expires(lease, lease_time, now);
lease_set_expires(lease, valid_time, now);
if (state.ia_type == OPTION6_IA_NA && state.hostname)
{
char *addr_domain = get_domain6(req_addr);
if (!state.send_domain)
state.send_domain = addr_domain;
lease_set_hostname(lease, state.hostname, state.hostname_auth, addr_domain, state.domain);
lease_set_hostname(lease, state.hostname, state.hostname_auth, addr_domain, state.domain);
message = state.hostname;
}
if (lease_time < min_time)
min_time = lease_time;
if (preferred_time == 0)
message = _("deprecated");
}
else
message = _("address invalid");
log6_packet(&state, "DHCPREPLY", req_addr, state.hostname);
log6_packet(&state, "DHCPREPLY", req_addr, message);
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(req_addr, sizeof(*req_addr));
/* preferred lifetime */
put_opt6_long(!this_context || (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
put_opt6_long(!this_context ? 0 : lease_time); /* valid lifetime */
put_opt6_long(preferred_time);
put_opt6_long(valid_time);
end_opt6(o1);
}
@@ -861,11 +986,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
if (!address6_available(context, req_addr, tagif))
if (!address6_available(context, req_addr, tagif, 1))
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Confirm failed");
put_opt6_string(_("confirm failed"));
end_opt6(o1);
return 1;
}
@@ -876,7 +1001,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS );
put_opt6_string("All addresses still on link");
put_opt6_string(_("all addresses still on link"));
end_opt6(o1);
break;
}
@@ -890,7 +1015,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
context->netid.next = NULL;
state.context_tags = &context->netid;
}
log6_packet(&state, "DHCPINFORMATION-REQUEST", NULL, ignore ? "ignored" : state.hostname);
log6_packet(&state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state.hostname);
if (ignore)
return 0;
*outmsgtypep = DHCP6REPLY;
@@ -946,7 +1071,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING);
put_opt6_string("No binding found");
put_opt6_string(_("no binding found"));
end_opt6(o1);
end_opt6(o);
@@ -955,7 +1080,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS);
put_opt6_string("Release received");
put_opt6_string(_("release received"));
end_opt6(o1);
break;
@@ -1023,7 +1148,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING);
put_opt6_string("No binding found");
put_opt6_string(_("no binding found"));
end_opt6(o1);
end_opt6(o);
@@ -1257,6 +1382,22 @@ static void get_context_tag(struct state *state, struct dhcp_context *context)
}
}
}
#ifdef OPTION6_PREFIX_CLASS
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context)
{
struct prefix_class *p;
struct dhcp_netid *t;
for (p = daemon->prefix_classes; p ; p = p->next)
for (t = context->filter; t; t = t->next)
if (strcmp(p->tag.net, t->net) == 0)
return p;
return NULL;
}
#endif
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
{
state->ia_type = opt6_type(opt);
@@ -1325,24 +1466,25 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, unsigned int requested_time,
unsigned int *min_time, struct in6_addr *addr, int do_update, time_t now)
{
unsigned int valid_time = (context->valid < lease_time) ? context->valid : lease_time;
unsigned int valid_time, preferred_time;
int o = new_opt6(OPTION6_IAADDR);
struct dhcp_lease *lease;
put_opt6(addr, sizeof(*addr));
calculate_times(context, min_time, &valid_time, &preferred_time, lease_time, requested_time);
/* preferred lifetime */
if (requested_time < 120u )
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
if (lease_time < *min_time)
*min_time = lease_time;
put_opt6(addr, sizeof(*addr));
put_opt6_long(preferred_time);
put_opt6_long(valid_time);
#ifdef OPTION6_PREFIX_CLASS
if (state->send_prefix_class)
{
int o1 = new_opt6(OPTION6_PREFIX_CLASS);
put_opt6_short(state->send_prefix_class->class);
end_opt6(o1);
}
#endif
put_opt6_long((context->preferred < lease_time) ? context->preferred : lease_time);
put_opt6_long(valid_time); /* valid lifetime */
end_opt6(o);
if (do_update)
@@ -1369,15 +1511,75 @@ static void add_address(struct state *state, struct dhcp_context *context, unsig
}
}
/* Mark that we have an address for this prefix. */
for (context = state->context; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
context->flags |= CONTEXT_USED;
log6_packet(state, do_update ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
}
static void mark_context_used(struct state *state, struct dhcp_context *context, struct in6_addr *addr)
{
/* Mark that we have an address for this prefix. */
#ifdef OPTION6_PREFIX_CLASS
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix) &&
(!state->send_prefix_class || state->send_prefix_class == prefix_class_from_context(context)))
context->flags |= CONTEXT_USED;
#else
(void)state; /* warning */
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
context->flags |= CONTEXT_USED;
#endif
}
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
{
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
context->flags |= CONTEXT_CONF_USED;
}
/* make sure address not leased to another CLID/IAID */
static int check_address(struct state *state, struct in6_addr *addr)
{
struct dhcp_lease *lease;
if (!(lease = lease6_find_by_addr(addr, 128, 0)))
return 1;
if (lease->clid_len != state->clid_len ||
memcmp(lease->clid, state->clid, state->clid_len) != 0 ||
lease->hwaddr_type != state->iaid)
return 0;
return 1;
}
static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
unsigned int *preferred_timep, unsigned int lease_time, unsigned int requested_time)
{
unsigned int preferred_time, valid_time;
if (requested_time < 120u )
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
valid_time = (context->valid < lease_time) ? context->valid : lease_time;
preferred_time = (context->preferred < lease_time) ? context->preferred : lease_time;
if (context->flags & CONTEXT_DEPRECATE)
preferred_time = 0;
if (preferred_time != 0 && preferred_time < *min_time)
*min_time = preferred_time;
if (valid_time != 0 && valid_time < *min_time)
*min_time = valid_time;
*valid_timep = valid_time;
*preferred_timep = preferred_time;
}
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now)
{
struct dhcp_lease *lease = lease6_find_by_addr(addr, 128, 0);
@@ -1407,12 +1609,12 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
free(lease->extradata);
lease->extradata = NULL;
lease->extradata_size = lease->extradata_len = 0;
lease->hwaddr_len = 0; /* surrogate for no of vendor classes */
lease->vendorclass_count = 0;
if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
{
void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
lease->hwaddr_len++;
lease->vendorclass_count++;
/* send enterprise number first */
sprintf(daemon->dhcp_buff2, "%u", opt6_uint(class_opt, 0, 4));
lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
@@ -1420,7 +1622,7 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
if (opt6_len(class_opt) >= 6)
for (enc_opt = opt6_ptr(class_opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
{
lease->hwaddr_len++;
lease->vendorclass_count++;
lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
}
}
@@ -1506,6 +1708,13 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
optname = "iaaddr";
ia_options = opt6_ptr(opt, 24);
}
#ifdef OPTION6_PREFIX_CLASS
else if (type == OPTION6_PREFIX_CLASS)
{
optname = "prefix-class";
sprintf(daemon->namebuff, "class=%u", opt6_uint(opt, 0, 2));
}
#endif
else if (type == OPTION6_STATUS_CODE)
{
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
+1 -1
View File
@@ -209,7 +209,7 @@ void tftp_request(struct listener *listen, time_t now)
#ifdef HAVE_DHCP
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
if (tmp->name && wildcard_match(tmp->name, name))
return;
#endif
+17
View File
@@ -581,3 +581,20 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
return 1;
}
/* Basically match a string value against a wildcard pattern. */
int wildcard_match(const char* wildcard, const char* match)
{
while (*wildcard && *match)
{
if (*wildcard == '*')
return 1;
if (*wildcard != *match)
return 0;
++wildcard;
++match;
}
return *wildcard == *match;
}