Compare commits

...
46 Commits
Author SHA1 Message Date
Simon Kelley 56ad6c9be1 Bump debian version. 2013-12-08 15:58:29 +00:00
Jan Psota fa04c83d86 Update Polish translation. 2013-12-08 15:43:03 +00:00
Vladislav Grishenko 4c82efc5ac Relax rules in prefix length in (IPv6) dhcp-range. 2013-12-03 16:05:30 +00:00
Simon Kelley 5f45d6a715 Update Debian changelog. 2013-12-03 13:43:56 +00:00
Simon Kelley 2329bef5ba Check arrival interface of IPv6 requests, even in --bind-interfaces. 2013-12-03 13:41:16 +00:00
Simon Kelley 62ab3ccd3d Only set scope_id in addresses to bind() for linklocal addresses.
FreeBSD complains otherwise.
2013-12-03 11:53:53 +00:00
Matthias Andree 71aaa5a791 Fix previous errno saving fix. 2013-12-03 11:20:45 +00:00
Simon Kelley 08619211f8 Garbage collect listening sockets when their address is deleted.
In --bind-dynamic mode, stop listening on an address when it's
removed from an interface. 6rd and 6to4 tunnels can go through
lots of addresses.
2013-12-02 14:43:48 +00:00
Simon Kelley 3dffbc3ebf Don't overwrite errno before generating message. 2013-12-02 13:22:37 +00:00
Simon Kelley 0d6eb134f5 Do immediate RA when a prefix goes from old->current. 2013-11-26 13:30:12 +00:00
Vladislav Grishenko 50db3492e2 Fix compiler warning. 2013-11-26 11:09:31 +00:00
Vladislav Grishenko 3b19596122 Fix compiler warnings. 2013-11-26 11:08:21 +00:00
Vladislav Grishenko d082faf3e4 Fix compiler warning. 2013-11-26 11:04:24 +00:00
Vladislav Grishenko 99e8891f85 Fix compiler warning. 2013-11-26 11:02:29 +00:00
Simon Kelley 532066ee2d Add missing malloc() return-code check. 2013-11-26 10:14:47 +00:00
Simon Kelley 254390644a Segfault with some CNAMEs. Also memory leak on reload of /etc/hosts. 2013-11-25 21:14:51 +00:00
Simon Kelley 241fa9c6c8 Remove arc4random, we have a good RNG and it's a portability problem. 2013-11-22 11:17:37 +00:00
Simon Kelley e142a83296 Merge messages to .po files. 2013-11-22 10:38:55 +00:00
Simon Kelley f7029f5c08 Extend /4 and /6 syntax to --interface-name 2013-11-21 15:10:02 +00:00
Simon Kelley c50f25a3ea Allow empty subnet list in --auth-zone 2013-11-21 11:29:27 +00:00
Simon Kelley f25e6c6d33 Support /4 and /6 suffixes in interface names in --auth-server 2013-11-17 12:23:42 +00:00
Simon Kelley 587ad4f271 Fix crash introduced in 376d48c7f1 2013-11-15 15:47:51 +00:00
Simon Kelley 4452292064 When advertising ONLY deleted IPv6 prefixes, set router lifetime to zero. 2013-11-15 14:45:04 +00:00
Simon Kelley dd9d9ce54c Fix problems when advertising deleted IPv6 prefixes. 2013-11-15 11:24:00 +00:00
Simon Kelley 32b4e4cb7c Auth-DNS manpage update. 2013-11-14 10:36:55 +00:00
Simon Kelley 376d48c7f1 Allow interface name to specify subnets in --auth-zone. 2013-11-13 13:04:30 +00:00
Simon Kelley 6586e8352a Use random address allocation for DHCPv6 temporary addresses. 2013-11-07 14:20:13 +00:00
Simon Kelley 3511a92869 Fix start-up order for making DHCPv6 DUID
Previously, if the DUID wasn't read from the lease-file or
script, a new one was created _after_ the helper process fork,
so for that first run, the script calls got an empty DUID.

Also, use a DUID_LL format DUID when there's no stable lease
storage, as well as when the RTC is broken. That has a chance of
evaluating to the same value on each startup.
2013-11-07 10:28:11 +00:00
Simon Kelley 44de649e5c Make private functions "static" 2013-11-06 11:36:57 +00:00
Brad Smith 29c122af83 Fix FTBFS on openBSD-current. 2013-11-04 14:11:18 +00:00
Simon Kelley 6dbdc972c4 Fix FTBFS on OS X >=10.7 Need to select a IPv6 sockopt API. 2013-10-28 14:22:57 +00:00
Simon Kelley 7b174c250d Fix check for local domains in CNAME case. Fixes d56a604a96 2013-10-28 13:14:03 +00:00
Jeremy Lavergne 50d7f721ee Fix FTBFS on MacOS 2013-10-28 11:26:30 +00:00
Simon Kelley eec5c1e21c Fix parsing of synth-domain=domain,addr,addr,prefix 2013-10-25 10:37:30 +01:00
Gildas 1f776a4aa2 Update French translation. 2013-10-25 10:05:22 +01:00
Kevin Darbyshire-Bryant 227ddad9b5 Fix logic botch in quiet-dhcp option. 2013-10-24 17:47:00 +01:00
Gildas a9bf81ad91 Message typo. 2013-10-24 13:31:40 +01:00
Simon Kelley 6008bdbbc1 Fix botch in determining if auth query is local. 2013-10-21 21:47:03 +01:00
Simon Kelley 93bafe619d Fix CNAME botch in auth code, also set RA flag for local queries. 2013-10-21 21:19:34 +01:00
Simon Kelley 8ab91e9f7f Get NXDOMAIN right on non-A/AAAA query for name known via interface-name. 2013-10-21 20:50:04 +01:00
Simon Kelley 5731050062 Get NXDOMAIN right for local queries to auth zones. 2013-10-21 18:26:20 +01:00
Simon Kelley fb63dd1345 Handle two interface-names, different interface, same name. 2013-10-21 18:19:35 +01:00
Simon Kelley 5f8002fcd7 Restore NS and SOA records to local auth queries. 2013-10-21 17:40:18 +01:00
Simon Kelley 19b1689161 Don't filter by subnet when handling local queries for auth-zones. 2013-10-20 10:19:39 +01:00
Simon Kelley b485ed97aa Always answer queries for authoritative zones locally, never forward. 2013-10-18 22:00:39 +01:00
René van Dorst 53c4c5c859 Fix crash at startup when dhcp-host with client-ids is present. 2013-10-18 14:05:32 +01:00
32 changed files with 4960 additions and 3994 deletions

No files matched your search

+53
View File
@@ -1,3 +1,56 @@
version 2.68
Use random addresses for DHCPv6 temporary address
allocations, instead of algorithmically determined stable
addresses.
Fix bug which meant that the DHCPv6 DUID was not available
in DHCP script runs during the lifetime of the dnsmasq
process which created the DUID de-novo. Once the DUID was
created and stored in the lease file and dnsmasq
restarted, this bug disappeared.
Fix bug introduced in 2.67 which could result in erroneous
NXDOMAIN returns to CNAME queries.
Fix build failures on MacOS X and openBSD.
Allow subnet specifications in --auth-zone to be interface
names as well as address literals. This makes it possible
to configure authoritative DNS when local address ranges
are dynamic and works much better than the previous
work-around which exempted contructed DHCP ranges from the
IP address filtering. As a consequence, that work-around
is removed. Under certain circumstances, this change wil
break existing configuration: if you're relying on the
contructed-range exception, you need to change --auth-zone
to specify the same interface as is used to construct your
DHCP ranges, probably with a trailing "/6" like this:
--auth-zone=example.com,eth0/6 to limit the addresses to
IPv6 addresses of eth0.
Fix problems when advertising deleted IPv6 prefixes. If
the prefix is deleted (rather than replaced), it doesn't
get advertised with zero preferred time. Thanks to Tsachi
for the bug report.
Fix segfault with some locally configured CNAMEs. Thanks
to Andrew Childs for spotting the problem.
Fix memory leak on re-reading /etc/hosts and friends,
introduced in 2.67.
Check the arrival interface of incoming DNS and TFTP
requests via IPv6, even in --bind-interfaces mode. This
isn't possible for IPv4 and can generate scary warnings,
but as it's always possible for IPv6 (the API always
exists) then we should do it always.
Tweak the rules on prefix-lengths in --dhcp-range for
IPv6. The new rule is that the specified prefix length
must be larger than or equal to the prefix length of the
corresponding address on the local interface.
version 2.67
Fix crash if upstream server returns SERVFAIL when
--conntrack in use. Thanks to Giacomo Tazzari for finding
+6
View File
@@ -1,3 +1,9 @@
dnsmasq (2.68-1) unstable; urgency=low
* New upstream. (closes: #730553)
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 8 Dec 2013 15:57:32 +0000
dnsmasq (2.67-1) unstable; urgency=low
* New upstream.
+45 -25
View File
@@ -199,7 +199,12 @@ or
.B --listen-address
configuration, indeed
.B --auth-server
will overide these and provide a different DNS service on the specified interface. The <domain> is the "glue record". It should resolve in the global DNS to a A and/or AAAA record which points to the address dnsmasq is listening on.
will overide these and provide a different DNS service on the
specified interface. The <domain> is the "glue record". It should
resolve in the global DNS to a A and/or AAAA record which points to
the address dnsmasq is listening on. When an interface is specified,
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
addresses associated with the interface.
.TP
.B \-2, --no-dhcp-interface=<interface name>
Do not provide DHCP or TFTP on the specified interface, but do provide DNS service.
@@ -509,11 +514,13 @@ record (which is always in the C_IN class). The value of the record is
given by the hex data, which may be of the form 01:23:45 or 01 23 45 or
012345 or any mixture of these.
.TP
.B --interface-name=<name>,<interface>
.B --interface-name=<name>,<interface>[/4|/6]
Return a DNS record associating the name with the primary address on
the given interface. This flag specifies an A record for the given
the given interface. This flag specifies an A or AAAA record for the given
name in the same way as an /etc/hosts line, except that the address is
not constant, but taken from the given interface. If the interface is
not constant, but taken from the given interface. The interface may be
followed by "/4" or "/6" to specify that only IPv4 or IPv6 addresses
of the interface should be used. If the interface is
down, not configured or non-existent, an empty record is returned. The
matching PTR record is also created, mapping the interface address to
the name. More than one name may be associated with an interface
@@ -588,16 +595,28 @@ needed for a client to do validation itself.
.TP
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
will be served. A and AAAA records must be in one of the
specified subnets, or in a subnet corresponding to a constructed DHCP
range. (This can be overridden with
.B constructor-noauth:
) The subnet(s) are also used to define in-addr.arpa and
will be served. If subnet(s) are given, A and AAAA records must be in one of the
specified subnets.
As alternative to directly specifying the subnets, it's possible to
give the name of an interface, in which case the subnets implied by
that interface's configured addresses and netmask/prefix-length are
used; this is useful when using constructed DHCP ranges as the actual
address is dynamic and not known when configuring dnsmasq. The
interface addresses may be confined to only IPv6 addresses using
<interface>/6 or to only IPv4 using <interface>/4. This is useful when
an interface has dynamically determined global IPv6 addresses which should
appear in the zone, but RFC1918 IPv4 addresses which should not.
Interface-name and address-literal subnet specifications may be used
freely in the same --auth-zone declaration.
The subnet(s) are also used to define in-addr.arpa and
ipv6.arpa domains which are served for reverse-DNS queries. If not
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
For IPv4 subnets, the prefix length should be have the value 8, 16 or 24
unless you are familiar with RFC 2317 and have arranged the
in-addr.arpa delegation accordingly.
in-addr.arpa delegation accordingly. Note that if no subnets are
specified, then no reverse queries are answered.
.TP
.B --auth-soa=<serial>[,<hostmaster>[,<refresh>[,<retry>[,<expiry>]]]]
Specify fields in the SOA record associated with authoritative
@@ -654,7 +673,8 @@ always optional. It is always
allowed to have more than one dhcp-range in a single subnet.
For IPv6, the parameters are slightly different: instead of netmask
and broadcast address, there is an optional prefix length. If not
and broadcast address, there is an optional prefix length which must
be equal to or larger then the prefix length on the local interface. If not
given, this defaults to 64. Unlike the IPv4 case, the prefix length is not
automatically derived from the interface configuration. The mimimum
size of the prefix length is 64.
@@ -680,12 +700,6 @@ then the address can be simply ::
.B --dhcp-range=::,constructor:eth0
There is a variant of the constructor: syntax using the keyword
.B constructor-noauth.
See
.B --auth-zone
for an explanation of this.
The optional
.B set:<tag>
sets an alphanumeric label which marks this network so that
@@ -1899,9 +1913,13 @@ 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
.B auth-zone=our.zone.com,1.2.3.0/24,eth0
.fi
(The "eth0" argument in auth-zone adds the subnet containing eth0's
dynamic address to the zone, so that the interface-name returns the
address in outside queries.)
Our final configuration builds on that above, but also adds a
secondary DNS server. This is another DNS server which learns the DNS data
for the zone by doing zones transfer, and acts as a backup should
@@ -1959,18 +1977,20 @@ IPv4 and IPv6 addresses from /etc/hosts (and
.B --addn-hosts
) and
.B --host-record
and
.B --interface-name
provided the address falls into one of the subnets specified in the
.B --auth-zone.
.PP
Addresses specified by
.B --interface-name.
In this case, the address is not contrained to a subnet from
.B --auth-zone.
.PP
Addresses of DHCP leases, provided the address falls into one of the subnets specified in the
.B --auth-zone.
(If contructed DHCP ranges are is use, which depend on the address dynamically
assigned to an interface, then the form of
.B --auth-zone
OR a constructed DHCP range. In the default mode, where a DHCP lease
which defines subnets by the dynamic address of an interface should
be used to ensure this condition is met.)
.PP
In the default mode, where a DHCP lease
has an unqualified name, and possibly a qualified name constructed
using
.B --domain
+142 -22
View File
@@ -403,7 +403,8 @@ noms de domains entourés par des '/', selon une syntaxe similaire à l'option
Ne pas vérifier régulièrement si le fichier /etc/resolv.conf a été modifié.
.TP
.B --clear-on-reload
Lorsque le fichier /etc/resolv.conf est relu, vider le cache DNS.
Lorsque le fichier /etc/resolv.conf est relu, ou si les serveurs amonts sont
configurés via DBus, vider le cache DNS.
Cela est utile si les nouveaux serveurs sont susceptibles d'avoir des données
différentes de celles stockées dans le cache.
.TP
@@ -596,9 +597,9 @@ Retourne un enregistrement de type NAPTR, tel que spécifié dans le RFC3403.
.TP
.B --cname=<cname>,<cible>
Retourne un enregistrement de type CNAME qui indique que <cname> est en
réalité <cible>. Il existe des contraintes significatives sur la valeur
de cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts
(ou un fichier hôtes additionnel), ou via DHCP, ou par un autre
réalité <cible>. Il existe des contraintes importantes sur la valeur
cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts
(ou un fichier hôtes additionnel), via DHCP, via interface--name ou par un autre
.B --cname.
Si une cible ne satisfait pas ces critères, le CNAME est ignoré. Le CNAME
doit être unique, mais il est autorisé d'avoir plus d'un CNAME pointant
@@ -622,6 +623,24 @@ Plus d'un nom peut être associé à une interface donnée en répétant cette o
plusieurs fois; dans ce cas, l'enregistrement inverse pointe vers le nom fourni
dans la première instance de cette option.
.TP
.B --synth-domain=<domaine>,<plage d'adresses>[,<préfixe>]
Créé des enregistrements A/AAAA ou PTR pour une plage d'adresses. Les
enregistrements utilisent l'adresse ainsi que les points (ou les deux points
dans le cas d'IPv6) remplacés par des tirets.
Un exemple devrait rendre cela plus clair :
La configuration
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal-
permet de retourner internal-192-168-0-56.thekelleys.org.uk lors d'une requête
sur l'adresse 192.168.0.56 et vice-versa pour la requête inverse. La même
logique s'applique pour IPv6, avec la particularité suivante : les adresses
IPv6 pouvant commencer par '::', mais les noms DNS ne pouvant pas commencer
par '-', si aucun préfixe n'est donné, un zéro est ajouté en début de nom.
Ainsi, ::1 devient 0--1.
La plage d'adresses peut-être de la forme
<adresse IP>,<adresse IP> ou <adresse IP>/<masque réseau>
.TP
.B --add-mac
Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises aux serveurs
amonts. Cela peut être utilisé dans un but de filtrage DNS par les serveurs
@@ -630,7 +649,20 @@ même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme
utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée,
aussi cette fonctionalité doit être considérée comme expérimentale. Notez
également qu'exposer les adresses MAC de la sorte peut avoir des implications
en termes de sécurité et de vie privée.
en termes de sécurité et de vie privée. L'avertissement donné pour --add-subnet
s'applique également ici.
.TP
.B --add-subnet[[=<longueur de préfixe IPv4>],<longueur de préfixe IPv6>]
Rajoute l'adresse de sous-réseau du requêteur aux requêtes DNS transmises
aux serveurs amonts. La quantité d'adresses transmises dépend du paramètre
longueur du préfixe : 32 (ou 128 dans le cas d'IPv6) transmet la totalité
de l'adresse, 0 n'en transmet aucun mais marque néanmoins la requête ce qui
fait qu'aucun serveur amont ne rajoutera d'adresse client. La valeur par
défaut est zéro et pour IPv4 et pour IPv6. A noter que les serveurs amonts
peuvent-être configurés pour retourner des valeurs différentes en fonction
de cette information mais que le cache de dnsmasq n'en tient pas compte.
Si une instance de dnsmasq est configurée de telle maniêre que des valeurs
différentes pourraient-être rencontrés, alors le cache devrait être désactivé.
.TP
.B \-c, --cache-size=<taille>
Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
@@ -665,15 +697,20 @@ 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>.....]]
.B --auth-zone=<domaine>[,<sous-réseau>[/<longueur de préfixe>][,<sous-réseau>[/<longueur de préfixe>].....]]
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.
domaine seront fournis. Les enregistrements A et AAAA doivent se situer dans
l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage DHCP
(ce comportement peut-être désactivé par
.B constructor-noauth:
). Le ou les sous-réseaux sont également utilisé(s) pour définir les domaines
in-addr.arpa et ipv6.arpa servant à l'interrogation DNS inverse. Si la longueur
de préfixe n'est pas spécifiée, elle sera par défaut de 24 pour IPv4 et 64 pour
IPv6. Dans le cas d'IPv4, la longueur du masque de réseau devrait-être de 8, 16
ou 24, sauf si en cas de mise en place d'une délégation de la zone in-addr.arpa
conforme au RFC 2317.
.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)
@@ -762,6 +799,27 @@ 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.
provoque la recherche d'adresses sur eth0 et crée une plage allant de
<réseau>::1 à <réseau>:400. Si l'interface est assignée à
plus d'un réseau, les plages correspondantes seront respectivement
automatiquement créées, rendues obsolètes et supprimées lorsque l'adresse
est rendue obsolète et supprimée. Le nom de l'interface peut être spécifié avec
un caractère joker '*' final. Les adresses autoconfigurées, privées ou
obsolètes ne conviennent pas.
Si une plage dhcp-range est uniquement utilisée pour du DHCP sans-état
("stateless") ou de l'autoconfiguration sans état ("SLAAC"), alors l'adresse
peut-être indiquée sous la forme '::'
.B --dhcp-range=::,constructor:eth0
Il existe une variante de la syntaxe constructor: qui consiste en l'utilisation
du mot-clef
.B constructor-noauth.
Voir
.B --auth-zone
pour des explications à ce sujet.
L'identifiant de label optionnel
.B set:<label>
fournie une étiquette alphanumérique qui identifie ce réseau, afin de permettre
@@ -853,9 +911,9 @@ sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pa
besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
déclaration de plage d'adresses dhcp-range.
Il est possible
d'utiliser des identifiants clients plutôt que des adresses matérielles pour
identifier les hôtes, en préfixant par ceux-ci par 'id:'. Ainsi,
Il est possible d'utiliser des identifiants clients (appellé "DUID client" dans
le monde IPv6) plutôt que des adresses matérielles pour identifier les hôtes,
en préfixant ceux-ci par 'id:'. Ainsi,
.B --dhcp-host=id:01:02:03:04,.....
réfère à l'hôte d'identifiant 01:02:03:04. Il est également possible de
spécifier l'identifiant client sous la forme d'une chaîne de caractères, comme
@@ -871,11 +929,13 @@ 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.
L'option spéciale id:* signifie : "ignorer tout identifiant client et n'utiliser
A noter que pour le DHCP IPv6, l'adresse matérielle n'est pas toujours
disponible, bien que ce soit toujours le cas pour des clients directement
connectés (sur le même domaine de broadcast) ou pour des clients utilisant
des relais DHCP qui supportent la RFC 6939.
En DHCPv4, l'option spéciale id:* signifie : "ignorer tout identifiant client et n'utiliser
que l'adresse matérielle". Cela est utile lorsqu'un client présente un
identifiant client mais pas les autres.
@@ -1079,6 +1139,40 @@ quelques rares cas, perturber des clients vieux ou défectueux. Cette
option force le comportement à l'utilisation des valeurs "simples et sûres"
afin d'éviter des problèmes dans de tels cas.
.TP
.B --dhcp-relay=<adresse locale>,<adresse de serveur>[,<interface]
Configure dnsmasq en temps que relais DHCP. L'adresse locale est une
adresse allouée à l'une interface de la machine sur laquelle tourne dnsmasq.
Toutes les requêtes DHCP arrivant sur cette interface seront relayées au
serveur DHCP distant correspondant à l'adresse de serveur indiquée. Il est
possible de relayer depuis une unique adresse locale vers différents serveurs
distant en spécifiant plusieurs fois l'option dhcp-relay avec la même adresse
locale et différentes adresses de serveur. L'adresse de serveur doit-être
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut-être
l'adresse de multicast ff05::1:3 correspondant à tous les serveurs DHCP. Dans
ce cas, l'interface doit-étre spécifiée et ne peut comporter de caractère
joker. Elle sera utilisée pour indiquer l'interface à partir de laquelle le
multicast pourra atteindre le serveur DHCP.
Le contrôle d'accès pour les clients DHCP suivent les mêmes règles que pour
les serveurs DHCP : voir --interface, --except-interface, etc. Le nom
d'interface optionel dans l'option dhcp-relay comporte une autre fonction :
il contrôle l'interface sur laquelle la réponse du serveur sera acceptée. Cela
sert par exemple dans des configurations à 3 interfaces : une à partir de
laquelle les requêtes sont relayées, une seconde permettant de se connecter à
un serveur DHCP, et une troisième reliée à un réseau non-sécurisé tel
qu'internet. Cela permet d'éviter l'arrivée de requêtes usurpées via cette
troisième interface.
Il est permis de configurer dnsmasq pour fonctionner comme serveur DHCP sur
certaines interfaces et en temps que relais sur d'autres. Cependant, même s'il
est possible de configurer dnsmasq de telle manière qu'il soit à la fois
serveur et relais pour une même interface, cela n'est pas supporté et la
fonction de relais prendra le dessus.
Le relais DHCPv4 et le relais DHCPv6 sont tous les deux supportés, mais il
n'est pas possible de relayer des requêtes DHCPv4 à un serveur DHCPv6 et
vice-versa.
.TP
.B \-U, --dhcp-vendorclass=set:<label>,[enterprise:<numéro IANA d'enterprise>,]<classe de vendeur>
Associe une chaîne de classe de vendeur à un label. La plupart
@@ -1113,7 +1207,7 @@ d'impression différent pour les hôtes de la classe "comptes" et ceux de la
classe "ingénierie".
.TP
.B \-4, --dhcp-mac=set:<label>,<adresse MAC>
(IPv4 uniquement) Associe une adresse matérielle (MAC) à un label. L'adresse
Associe une adresse matérielle (MAC) à un label. L'adresse
matérielle peut inclure des jokers. Par exemple
.B --dhcp-mac=set:3com,01:34:23:*:*:*
permet de définir le label "3com" pour n'importe quel hôte dont l'adresse
@@ -1354,6 +1448,11 @@ Traces additionnelles pour le service DHCP : enregistre toutes les options
envoyées aux clients DHCP et les labels utilisés pour la
détermination de celles-ci.
.TP
.B --quiet-dhcp, --quiet-dhcp6, --quiet-ra
Supprime les logs des opérations de routine des protocoles concernés. Les
erreurs et les problèmes seront toujours enregistrés. L'option --log-dhcp
prends le pas sur --quiet-dhcp et quiet-dhcp6.
.TP
.B \-l, --dhcp-leasefile=<chemin de fichier>
Utilise le fichier dont le chemin est fourni pour stocker les informations de
baux DHCP.
@@ -1447,6 +1546,8 @@ pour chaque appel au script.
DNSMASQ_IAID contenant l'IAID pour le bail. Si le bail est une allocation
temporaire, cela est préfixé par le caractère 'T'.
DNSMASQ_MAC contient l'adresse MAC du client, si celle-ci est connue.
A noter que le nom d'hôte fourni, la classe de vendeur ou les données de classe
d'utilisateur sont uniquement fournies pour les actions "add" ou l'action "old"
lorsqu'un hôte reprend un bail existant, puisque ces informations ne sont pas
@@ -1649,11 +1750,30 @@ dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
DNSSL.
.TP
.B --enable-tftp
.B --ra-param=<interface>,[high|low],[[<intervalle d'annonce routeur>],<durée de vie route>]
Configure pour une interface donnée des valeurs pour les annonces routeurs
différentes des valeurs par défaut. La valeur par défaut du champ priorité
pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
"low" (basse). Par exemple :
.B --ra-param=eth0,high.
Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
.B --ra-param=eth0,60.
La durée de vie de la route peut-être changée ou mise à zéro, auquel cas
le routeur peut annoncer les préfixes mais pas de route :
.B --ra-parm=eth0,0,0
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
Ces trois paramètres peuvent-être configurés en une fois :
.B --ra-param=low,60,1200
La valeur pour l'interface peut inclure un caractère joker.
.TP
.B --enable-tftp[=<interface>[,<interface>]]
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
un accès en lecture est possible; les extensions tsize et blksize sont supportées
(tsize est seulement supporté en mode octet).
(tsize est seulement supporté en mode octet). Sans argument optionel, le service
TFTP est fourni sur les mêmes interfaces que le service DHCP. Si une liste
d'interfaces est fournie, cela définit les interfaces sur lesquelles le
service TFTP sera activé.
.TP
.B --tftp-root=<répertoire>[,<interface>]
Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le
+401 -352
View File
File diff suppressed because it is too large. Load diff
+401 -351
View File
File diff suppressed because it is too large. Load diff
+422 -374
View File
File diff suppressed because it is too large. Load diff
+420 -372
View File
File diff suppressed because it is too large. Load diff
+401 -352
View File
File diff suppressed because it is too large. Load diff
+422 -374
View File
File diff suppressed because it is too large. Load diff
+400 -352
View File
File diff suppressed because it is too large. Load diff
+407 -356
View File
File diff suppressed because it is too large. Load diff
+422 -374
View File
File diff suppressed because it is too large. Load diff
+400 -352
View File
File diff suppressed because it is too large. Load diff
+82 -75
View File
@@ -18,27 +18,26 @@
#ifdef HAVE_AUTH
static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
struct subnet *subnet;
struct addrlist *subnet;
for (subnet = zone->subnet; subnet; subnet = subnet->next)
{
if (subnet->is6 && (flag & F_IPV4))
continue;
if (!subnet->is6)
if (!(subnet->flags & ADDRLIST_IPV6))
{
struct in_addr addr = addr_u->addr.addr4;
struct in_addr mask;
struct in_addr netmask, addr = addr_u->addr.addr4;
if (!(flag & F_IPV4))
continue;
mask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
netmask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
if (is_same_net(addr, subnet->addr4, mask))
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
return subnet;
}
#ifdef HAVE_IPV6
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr6, subnet->prefixlen))
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
return subnet;
#endif
@@ -46,23 +45,16 @@ static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_a
return NULL;
}
static int filter_constructed_dhcp(struct auth_zone *zone, int flag, struct all_addr *addr_u)
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
#ifdef HAVE_DHCP6
struct dhcp_context *context;
if (flag & F_IPV6)
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_CONSTRUCTED) &&
!(context->flags & CONTEXT_NOAUTH) &&
is_same_net6(&(addr_u->addr.addr6), &context->start6, context->prefix))
return 1;
#endif
/* No zones specified, no filter */
if (!zone->subnet)
return 1;
return filter_zone(zone, flag, addr_u) != NULL;
return find_subnet(zone, flag, addr_u) != NULL;
}
static int in_zone(struct auth_zone *zone, char *name, char **cut)
int in_zone(struct auth_zone *zone, char *name, char **cut)
{
size_t namelen = strlen(name);
size_t domainlen = strlen(zone->domain);
@@ -89,7 +81,7 @@ static int in_zone(struct auth_zone *zone, char *name, char **cut)
}
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr)
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query)
{
char *name = daemon->namebuff;
unsigned char *p, *ansp;
@@ -97,9 +89,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
int nameoffset, axfroffset = 0;
int q, anscount = 0, authcount = 0;
struct crec *crecp;
int auth = 1, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
struct auth_zone *zone = NULL;
struct subnet *subnet = NULL;
struct addrlist *subnet = NULL;
char *cut;
struct mx_srv_record *rec, *move, **up;
struct txt_record *txt;
@@ -110,7 +102,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
return 0;
/* determine end of question section (we put answers there) */
if (!(ansp = skip_questions(header, qlen)))
return 0; /* bad packet */
@@ -144,16 +136,19 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (!(flag = in_arpa_name_2_addr(name, &addr)))
continue;
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = filter_zone(zone, flag, &addr)))
break;
if (!zone)
if (!local_query)
{
auth = 0;
continue;
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = find_subnet(zone, flag, &addr)))
break;
if (!zone)
{
auth = 0;
continue;
}
}
intr = NULL;
if (flag == F_IPV4)
@@ -161,8 +156,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
struct addrlist *addrlist;
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
break;
if (addrlist)
@@ -177,8 +172,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
struct addrlist *addrlist;
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
break;
if (addrlist)
@@ -194,7 +189,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (in_zone(zone, intr->name, NULL))
{
found = 1;
log_query(flag| F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", intr->name))
@@ -358,25 +353,22 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (hostname_isequal(name, intr->name))
{
struct addrlist *addrlist;
addrlist = intr->addr4;
#ifdef HAVE_IPV6
if (qtype == T_AAAA)
addrlist = intr->addr6;
#endif
nxdomain = 0;
for (; addrlist; addrlist = addrlist->next)
if (filter_constructed_dhcp(zone, flag, &addrlist->addr))
{
found = 1;
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &addrlist->addr))
anscount++;
}
}
if (flag)
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
(local_query || filter_zone(zone, flag, &addrlist->addr)))
{
found = 1;
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &addrlist->addr))
anscount++;
}
}
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(name, a->alias) )
@@ -390,7 +382,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
@@ -403,7 +395,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (qtype == T_SOA)
{
soa = 1; /* inhibits auth section */
auth = soa = 1; /* inhibits auth section */
found = 1;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
}
@@ -436,6 +428,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
return 0;
}
auth = 1;
soa = 1; /* inhibits auth section */
ns = 1; /* ensure we include NS records! */
axfr = 1;
@@ -445,6 +438,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
else if (qtype == T_NS)
{
auth = 1;
ns = 1; /* inhibits auth section */
found = 1;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
@@ -462,7 +456,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
nxdomain = 0;
if ((crecp->flags & flag) &&
(filter_constructed_dhcp(zone, flag, &(crecp->addr.addr))))
(local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
{
*cut = '.'; /* restore domain part */
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
@@ -485,7 +479,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
do
{
nxdomain = 0;
if ((crecp->flags & flag) && filter_constructed_dhcp(zone, flag, &(crecp->addr.addr)))
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
{
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
found = 1;
@@ -516,9 +510,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
authname = name;
if (!subnet->is6)
if (!(subnet->flags & ADDRLIST_IPV6))
{
in_addr_t a = ntohl(subnet->addr4.s_addr) >> 8;
in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;
char *p = name;
if (subnet->prefixlen >= 24)
@@ -538,7 +532,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
{
int dig = ((unsigned char *)&subnet->addr6)[i>>3];
int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
}
p += sprintf(p, "ip6.arpa");
@@ -674,15 +668,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (cut)
*cut = 0;
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
if (filter_constructed_dhcp(zone, F_IPV4, &addrlist->addr) &&
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (!(addrlist->flags & ADDRLIST_IPV6) &&
(local_query || filter_zone(zone, F_IPV4, &addrlist->addr)) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
anscount++;
#ifdef HAVE_IPV6
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
if (filter_constructed_dhcp(zone, F_IPV6, &addrlist->addr) &&
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if ((addrlist->flags & ADDRLIST_IPV6) &&
(local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
anscount++;
@@ -722,7 +718,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if ((crecp->flags & F_DHCP) && !option_bool(OPT_DHCP_FQDN))
{
char *cache_name = cache_get_name(crecp);
if (!strchr(cache_name, '.') && filter_constructed_dhcp(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))
if (!strchr(cache_name, '.') &&
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
{
qtype = T_A;
#ifdef HAVE_IPV6
@@ -739,7 +736,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
{
strcpy(name, cache_get_name(crecp));
if (in_zone(zone, name, &cut) && filter_constructed_dhcp(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))
if (in_zone(zone, name, &cut) &&
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
{
qtype = T_A;
#ifdef HAVE_IPV6
@@ -774,8 +772,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
/* done all questions, set up header and return length of result */
/* clear authoritative and truncated flags, set QR flag */
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
/* clear RA flag */
header->hb4 &= ~HB4_RA;
if (local_query)
{
/* set RA flag */
header->hb4 |= HB4_RA;
}
else
{
/* clear RA flag */
header->hb4 &= ~HB4_RA;
}
/* authoritive */
if (auth)
@@ -785,7 +792,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (trunc)
header->hb3 |= HB3_TC;
if (anscount == 0 && auth && nxdomain)
if ((auth || local_query) && nxdomain)
SET_RCODE(header, NXDOMAIN);
else
SET_RCODE(header, NOERROR); /* no error */
+2 -1
View File
@@ -29,6 +29,7 @@
# include <net/if_var.h>
#endif
#include <netinet/in_var.h>
#include <netinet6/in6_var.h>
#ifndef SA_SIZE
#define SA_SIZE(sa) \
@@ -145,7 +146,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
int i, j, prefix = 0;
u32 valid = 0xffffffff, preferred = 0xffffffff;
int flags = 0;
#ifdef HAVE_BSD_NETWORK
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
struct in6_ifreq ifr6;
memset(&ifr6, 0, sizeof(ifr6));
+21 -18
View File
@@ -320,7 +320,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -330,7 +330,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
((flags & crecp->flags & F_TYPE) || ((crecp->flags | flags) & F_CNAME)) &&
hostname_isequal(cache_get_name(crecp), name))
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
return 0;
*up = crecp->hash_next;
cache_unlink(crecp);
@@ -354,13 +354,13 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
}
}
else if (!(crecp->flags & (F_HOSTS | F_DHCP)) &&
else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
(flags & crecp->flags & F_REVERSE) &&
(flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
@@ -558,7 +558,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
(crecp->flags & prot) &&
hostname_isequal(cache_get_name(crecp), name))
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
{
*chainp = crecp;
chainp = &crecp->next;
@@ -599,7 +599,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
{
/* expired entry, free it */
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -649,7 +649,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
if ((crecp->flags & prot) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
{
*chainp = crecp;
chainp = &crecp->next;
@@ -665,7 +665,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
else
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -923,7 +923,7 @@ void cache_reload(void)
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
{
tmp = cache->hash_next;
if (cache->flags & F_HOSTS)
if (cache->flags & (F_HOSTS | F_CONFIG))
{
*up = cache->hash_next;
free(cache);
@@ -945,15 +945,15 @@ void cache_reload(void)
/* Add CNAMEs to interface_names to the cache */
for (a = daemon->cnames; a; a = a->next)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(a->target, intr->name))
if (hostname_isequal(a->target, intr->name) &&
((cache = whine_malloc(sizeof(struct crec)))))
{
struct crec *aliasc = safe_malloc(sizeof(struct crec));
aliasc->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
aliasc->name.namep = a->alias;
aliasc->addr.cname.target.int_name = intr;
aliasc->addr.cname.uid = -1;
cache_hash(aliasc);
add_hosts_cname(aliasc); /* handle chains */
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr;
cache->addr.cname.uid = -1;
cache_hash(cache);
add_hosts_cname(cache); /* handle chains */
}
/* borrow the packet buffer for a temporary by-address hash */
@@ -1083,7 +1083,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
{
/* check all addresses associated with name */
if (crec->flags & F_HOSTS)
if (crec->flags & (F_HOSTS | F_CONFIG))
{
if (crec->flags & F_CNAME)
my_syslog(MS_DHCP | LOG_WARNING,
@@ -1161,6 +1161,9 @@ void dump_cache(time_t now)
daemon->cachesize, cache_live_freed, cache_inserted);
my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
daemon->queries_forwarded, daemon->local_answer);
#ifdef HAVE_AUTH
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
#endif
/* sum counts from different records for same server */
for (serv = daemon->servers; serv; serv = serv->next)
+4 -14
View File
@@ -189,10 +189,6 @@ HAVE_SOLARIS_NETWORK
HAVE_GETOPT_LONG
defined when GNU-style getopt_long available.
HAVE_ARC4RANDOM
defined if arc4random() available to get better security from DNS spoofs
by using really random ids (OpenBSD)
HAVE_SOCKADDR_SA_LEN
defined if struct sockaddr has sa_len field (*BSD)
*/
@@ -201,7 +197,6 @@ HAVE_SOCKADDR_SA_LEN
#if defined(__uClinux__)
#define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
/* Never use fork() on uClinux. Note that this is subtly different from the
--keep-in-foreground option, since it also suppresses forking new
@@ -215,7 +210,6 @@ HAVE_SOCKADDR_SA_LEN
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
# define HAVE_GETOPT_LONG
#endif
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
# define NO_FORK
@@ -230,7 +224,6 @@ HAVE_SOCKADDR_SA_LEN
#elif defined(__linux__)
#define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#elif defined(__FreeBSD__) || \
@@ -242,29 +235,26 @@ HAVE_SOCKADDR_SA_LEN
#if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG
#endif
#if !defined(__FreeBSD_kernel__)
# define HAVE_ARC4RANDOM
#endif
#define HAVE_SOCKADDR_SA_LEN
#elif defined(__APPLE__)
#define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG
#define HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN
/* Define before sys/socket.h is included so we get socklen_t */
#define _BSD_SOCKLEN_T_
/* Select the RFC_3542 version of the IPv6 socket API.
Define before netinet6/in6.h is included. */
#define __APPLE_USE_RFC_3542
#elif defined(__NetBSD__)
#define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN
#elif defined(__sun) || defined(__sun__)
#define HAVE_SOLARIS_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#define ETHER_ADDR_LEN 6
+3 -2
View File
@@ -315,8 +315,9 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
return config;
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
cope with that here */
if (!(context->flags & CONTEXT_V6) && *clid == 0 && config->clid_len == clid_len-1 &&
cope with that here. This is IPv4 only. context==NULL implies IPv4,
see lease_update_from_configs() */
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 &&
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
is_config_in_context(context, config))
return config;
+44 -27
View File
@@ -330,9 +330,9 @@ static int complete_context6(struct in6_addr *local, int prefix,
{
if ((context->flags & CONTEXT_DHCP) &&
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
@@ -394,7 +394,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
return NULL;
}
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
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
@@ -411,9 +411,13 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
u64 j;
/* hash hwaddr: use the SDBM hashing algorithm. This works
for MAC addresses, let's see how it manages with client-ids! */
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
for MAC addresses, let's see how it manages with client-ids!
For temporary addresses, we generate a new random one each time. */
if (temp_addr)
j = rand64();
else
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
for (c = context; c; c = c->current)
@@ -423,7 +427,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
continue;
else
{
if (option_bool(OPT_CONSEC_ADDR))
if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
/* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c) + serial;
else
@@ -523,6 +527,8 @@ int config_valid(struct dhcp_config *config, struct dhcp_context *context, struc
void make_duid(time_t now)
{
(void)now;
if (daemon->duid_config)
{
unsigned char *p;
@@ -535,8 +541,14 @@ void make_duid(time_t now)
}
else
{
time_t newnow = 0;
/* If we have no persistent lease database, or a non-stable RTC, use DUID_LL (newnow == 0) */
#ifndef HAVE_BROKEN_RTC
/* rebase epoch to 1/1/2000 */
time_t newnow = now - 946684800;
if (!option_bool(OPT_LEASE_RO) || daemon->lease_change_command)
newnow = now - 946684800;
#endif
iface_enumerate(AF_LOCAL, &newnow, make_duid1);
@@ -555,23 +567,27 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo
unsigned char *p;
(void)index;
(void)parm;
time_t newnow = *((time_t *)parm);
if (type >= 256)
return 1;
#ifdef HAVE_BROKEN_RTC
daemon->duid = p = safe_malloc(maclen + 4);
daemon->duid_len = maclen + 4;
PUTSHORT(3, p); /* DUID_LL */
PUTSHORT(type, p); /* address type */
#else
daemon->duid = p = safe_malloc(maclen + 8);
daemon->duid_len = maclen + 8;
PUTSHORT(1, p); /* DUID_LLT */
PUTSHORT(type, p); /* address type */
PUTLONG(*((time_t *)parm), p); /* time */
#endif
if (newnow == 0)
{
daemon->duid = p = safe_malloc(maclen + 4);
daemon->duid_len = maclen + 4;
PUTSHORT(3, p); /* DUID_LL */
PUTSHORT(type, p); /* address type */
}
else
{
daemon->duid = p = safe_malloc(maclen + 8);
daemon->duid_len = maclen + 8;
PUTSHORT(1, p); /* DUID_LLT */
PUTSHORT(type, p); /* address type */
PUTLONG(*((time_t *)parm), p); /* time */
}
memcpy(p, mac, maclen);
return 0;
@@ -615,9 +631,9 @@ static int construct_worker(struct in6_addr *local, int prefix,
if (!(template->flags & CONTEXT_TEMPLATE))
{
/* non-template entries, just fill in interface and local addresses */
if (prefix == template->prefix &&
is_same_net6(local, &template->start6, prefix) &&
is_same_net6(local, &template->end6, prefix))
if (prefix <= template->prefix &&
is_same_net6(local, &template->start6, template->prefix) &&
is_same_net6(local, &template->end6, template->prefix))
{
template->if_index = if_index;
template->local6 = *local;
@@ -625,7 +641,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
}
else if (wildcard_match(template->template_interface, ifrn_name) &&
template->prefix == prefix)
template->prefix >= prefix)
{
start6 = *local;
setaddr6part(&start6, addr6part(&template->start6));
@@ -645,6 +661,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicted(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;
+7 -1
View File
@@ -273,6 +273,9 @@ int main (int argc, char **argv)
/* after enumerate_interfaces() */
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
join_multicast(1);
/* After netlink_init() and before create_helper() */
lease_make_duid(now);
#endif
if (daemon->port != 0)
@@ -633,7 +636,10 @@ int main (int argc, char **argv)
if (bind_fallback)
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
warn_bound_listeners();
if (option_bool(OPT_NOWILD))
warn_bound_listeners();
warn_int_names();
if (!option_bool(OPT_NOWILD))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
+31 -22
View File
@@ -280,18 +280,28 @@ struct ptr_record {
struct cname {
char *alias, *target;
struct cname *next;
};
#define ADDRLIST_LITERAL 1
#define ADDRLIST_IPV6 2
struct addrlist {
struct all_addr addr;
int flags, prefixlen;
struct addrlist *next;
};
#define AUTH6 1
#define AUTH4 2
struct auth_zone {
char *domain;
struct subnet {
int is6, prefixlen;
struct in_addr addr4;
#ifdef HAVE_IPV6
struct in6_addr addr6;
#endif
struct subnet *next;
} *subnet;
struct auth_name_list {
char *name;
int flags;
struct auth_name_list *next;
} *interface_names;
struct addrlist *subnet;
struct auth_zone *next;
};
@@ -311,13 +321,8 @@ struct host_record {
struct interface_name {
char *name; /* domain name */
char *intr; /* interface name */
struct addrlist {
struct all_addr addr;
struct addrlist *next;
} *addr4;
#ifdef HAVE_IPV6
struct addrlist *addr6;
#endif
int family; /* AF_INET, AF_INET6 or zero for both */
struct addrlist *addr;
struct interface_name *next;
};
@@ -454,7 +459,7 @@ struct ipsets {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done;
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
char *name;
struct irec *next;
};
@@ -748,9 +753,8 @@ struct dhcp_context {
#define CONTEXT_RA (1u<<13)
#define CONTEXT_CONF_USED (1u<<14)
#define CONTEXT_USED (1u<<15)
#define CONTEXT_NOAUTH (1u<<16)
#define CONTEXT_OLD (1u<<17)
#define CONTEXT_V6 (1u<<18)
#define CONTEXT_OLD (1u<<16)
#define CONTEXT_V6 (1u<<17)
struct ping_result {
@@ -876,7 +880,7 @@ extern struct daemon {
char *packet; /* packet buffer */
int packet_buff_sz; /* size of above */
char *namebuff; /* MAXDNAME size buffer */
unsigned int local_answer, queries_forwarded;
unsigned int local_answer, queries_forwarded, auth_answer;
struct frec *frec_list;
struct serverfd *sfds;
struct irec *interfaces;
@@ -992,12 +996,15 @@ int private_net(struct in_addr addr, int ban_localhost);
/* auth.c */
#ifdef HAVE_AUTH
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr);
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen,
time_t now, union mysockaddr *peer_addr, int local_query);
int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* util.c */
void rand_init(void);
unsigned short rand16(void);
u64 rand64(void);
int legal_hostname(char *c);
char *canonicalise(char *s, int *nomem);
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
@@ -1070,6 +1077,7 @@ int enumerate_interfaces(int reset);
void create_wildcard_listeners(void);
void create_bound_listeners(int die);
void warn_bound_listeners(void);
void warn_int_names(void);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
@@ -1118,6 +1126,7 @@ u64 lease_find_max_addr6(struct dhcp_context *context);
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
void lease_update_slaac(time_t now);
void lease_set_iaid(struct dhcp_lease *lease, int iaid);
void lease_make_duid(time_t now);
#endif
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
@@ -1218,7 +1227,7 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
#ifdef HAVE_DHCP6
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,
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_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,
+53 -10
View File
@@ -675,8 +675,10 @@ void receive_query(struct listener *listen, time_t now)
struct in_addr netmask, dst_addr_4;
size_t m;
ssize_t n;
int if_index = 0;
int auth_dns = 0;
int if_index = 0, auth_dns = 0;
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmptr;
@@ -695,7 +697,13 @@ void receive_query(struct listener *listen, time_t now)
CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
#ifdef HAVE_IPV6
/* Can always get recvd interface for IPv6 */
int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
#else
int check_dst = !option_bool(OPT_NOWILD);
#endif
/* packet buffer overwritten */
daemon->srv_save = NULL;
@@ -738,7 +746,7 @@ void receive_query(struct listener *listen, time_t now)
source_addr.in6.sin6_flowinfo = 0;
#endif
if (!option_bool(OPT_NOWILD))
if (check_dst)
{
struct ifreq ifr;
@@ -848,6 +856,9 @@ void receive_query(struct listener *listen, time_t now)
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
{
char types[20];
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
querystr(auth_dns ? "auth" : "query", types, type);
@@ -859,15 +870,30 @@ void receive_query(struct listener *listen, time_t now)
log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
(struct all_addr *)&source_addr.in6.sin6_addr, types);
#endif
}
#ifdef HAVE_AUTH
/* find queries for zones we're authoritative for, and answer them directly */
if (!auth_dns)
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (in_zone(zone, daemon->namebuff, NULL))
{
auth_dns = 1;
local_auth = 1;
break;
}
#endif
}
#ifdef HAVE_AUTH
if (auth_dns)
{
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr, local_auth);
if (m >= 1)
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
{
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->auth_answer++;
}
}
else
#endif
@@ -898,6 +924,9 @@ unsigned char *tcp_request(int confd, time_t now,
{
size_t size = 0;
int norebind = 0;
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
int checking_disabled, check_subnet;
size_t m;
unsigned short qtype;
@@ -939,7 +968,9 @@ unsigned char *tcp_request(int confd, time_t now,
if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
{
char types[20];
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
querystr(auth_dns ? "auth" : "query", types, qtype);
if (peer_addr.sa.sa_family == AF_INET)
@@ -950,6 +981,18 @@ unsigned char *tcp_request(int confd, time_t now,
log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
(struct all_addr *)&peer_addr.in6.sin6_addr, types);
#endif
#ifdef HAVE_AUTH
/* find queries for zones we're authoritative for, and answer them directly */
if (!auth_dns)
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (in_zone(zone, daemon->namebuff, NULL))
{
auth_dns = 1;
local_auth = 1;
break;
}
#endif
}
if (local_addr->sa.sa_family == AF_INET)
@@ -959,7 +1002,7 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_AUTH
if (auth_dns)
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
else
#endif
{
+8 -2
View File
@@ -417,15 +417,21 @@ void lease_find_interfaces(time_t now)
iface_enumerate(AF_INET, &now, find_interface_v4);
#ifdef HAVE_DHCP6
iface_enumerate(AF_INET6, &now, find_interface_v6);
#endif
}
#ifdef HAVE_DHCP6
void lease_make_duid(time_t now)
{
/* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
if (!daemon->duid && daemon->dhcp6)
if (!daemon->duid && daemon->doing_dhcp6)
{
file_dirty = 1;
make_duid(now);
}
#endif
}
#endif
+184 -65
View File
@@ -159,7 +159,8 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
if (tmp->name)
{
if (strcmp(tmp->name, name) == 0)
if (strcmp(tmp->name, name) == 0 &&
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
break;
}
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
@@ -239,7 +240,7 @@ struct iface_param {
};
static int iface_allowed(struct iface_param *param, int if_index, char *label,
union mysockaddr *addr, struct in_addr netmask, int dad)
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)
{
struct irec *iface;
int mtu = 0, loopback;
@@ -251,6 +252,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
struct iname *tmp;
#endif
(void)prefixlen;
if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
return 0;
@@ -267,17 +270,71 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
label = ifr.ifr_name;
/* Update addresses from interface_names. These are a set independent
of the set we're listening on. */
#ifdef HAVE_IPV6
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
#endif
{
struct interface_name *int_name;
struct addrlist *al;
#ifdef HAVE_AUTH
struct auth_zone *zone;
struct auth_name_list *name;
/* Find subnets in auth_zones */
for (zone = daemon->auth_zones; zone; zone = zone->next)
for (name = zone->interface_names; name; name = name->next)
if (wildcard_match(name->name, label))
{
if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
{
if (param->spare)
{
al = param->spare;
param->spare = al->next;
}
else
al = whine_malloc(sizeof(struct addrlist));
if (al)
{
al->next = zone->subnet;
zone->subnet = al;
al->prefixlen = prefixlen;
al->addr.addr.addr4 = addr->in.sin_addr;
al->flags = 0;
}
}
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
{
if (param->spare)
{
al = param->spare;
param->spare = al->next;
}
else
al = whine_malloc(sizeof(struct addrlist));
if (al)
{
al->next = zone->subnet;
zone->subnet = al;
al->prefixlen = prefixlen;
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6;
}
}
#endif
}
#endif
/* Update addresses from interface_names. These are a set independent
of the set we're listening on. */
for (int_name = daemon->int_names; int_name; int_name = int_name->next)
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
(addr->sa.sa_family == int_name->family || int_name->family == 0))
{
if (param->spare)
{
@@ -289,18 +346,19 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (al)
{
al->next = int_name->addr;
int_name->addr = al;
if (addr->sa.sa_family == AF_INET)
{
al->addr.addr.addr4 = addr->in.sin_addr;
al->next = int_name->addr4;
int_name->addr4 = al;
al->flags = 0;
}
#ifdef HAVE_IPV6
else
{
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->next = int_name->addr6;
int_name->addr6 = al;
al->flags = ADDRLIST_IPV6;
}
#endif
}
@@ -313,6 +371,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (sockaddr_isequal(&iface->addr, addr))
{
iface->dad = dad;
iface->found = 1; /* for garbage collection */
return 1;
}
@@ -387,6 +446,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->dns_auth = auth_dns;
iface->mtu = mtu;
iface->dad = dad;
iface->found = 1;
iface->done = iface->multicast_done = iface->warned = 0;
iface->index = if_index;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
@@ -413,7 +473,6 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
struct in_addr netmask; /* dummy */
netmask.s_addr = 0;
(void)prefix; /* warning */
(void)scope; /* warning */
(void)preferred;
(void)valid;
@@ -425,9 +484,13 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = if_index;
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
/* FreeBSD insists this is zero for non-linklocal addresses */
if (IN6_IS_ADDR_LINKLOCAL(local))
addr.in6.sin6_scope_id = if_index;
else
addr.in6.sin6_scope_id = 0;
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
}
#endif
@@ -435,6 +498,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
union mysockaddr addr;
int prefix, bit;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -445,7 +509,10 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port);
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, 0);
/* determine prefix length from netmask */
for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
}
int enumerate_interfaces(int reset)
@@ -456,7 +523,11 @@ int enumerate_interfaces(int reset)
int errsave, ret = 1;
struct addrlist *addr, *tmp;
struct interface_name *intname;
struct irec *iface;
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
/* Do this max once per select cycle - also inhibits netlink socket use
in TCP child processes. */
@@ -477,30 +548,45 @@ int enumerate_interfaces(int reset)
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0;
/* Mark interfaces for garbage collection */
for (iface = daemon->interfaces; iface; iface = iface->next)
iface->found = 0;
/* remove addresses stored against interface_names */
for (intname = daemon->int_names; intname; intname = intname->next)
{
for (addr = intname->addr4; addr; addr = tmp)
for (addr = intname->addr; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
intname->addr4 = NULL;
#ifdef HAVE_IPV6
for (addr = intname->addr6; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
intname->addr6 = NULL;
#endif
intname->addr = NULL;
}
#ifdef HAVE_AUTH
/* remove addresses stored against auth_zone subnets, but not
ones configured as address literals */
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (zone->interface_names)
{
struct addrlist **up;
for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
{
tmp = addr->next;
if (addr->flags & ADDRLIST_LITERAL)
up = &addr->next;
else
{
*up = addr->next;
addr->next = spare;
spare = addr;
}
}
}
#endif
param.spare = spare;
#ifdef HAVE_IPV6
@@ -512,11 +598,47 @@ int enumerate_interfaces(int reset)
errsave = errno;
close(param.fd);
if (option_bool(OPT_CLEVERBIND))
{
/* Garbage-collect listeners listening on addresses that no longer exist.
Does nothing when not binding interfaces or for listeners on localhost,
since the ->iface field is NULL. Note that this needs the protections
against re-entrancy, hence it's here. It also means there's a possibility,
in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up;
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
{
tmp = l->next;
if (!l->iface || l->iface->found)
up = &l->next;
else
{
*up = l->next;
/* In case it ever returns */
l->iface->done = 0;
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
}
}
}
errno = errsave;
spare = param.spare;
active = 0;
return ret;
}
@@ -539,7 +661,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if ((fd = socket(family, type, 0)) == -1)
{
int port;
int port, errsav;
char *s;
/* No error if the kernel just doesn't support this IP flavour */
@@ -549,6 +671,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
return -1;
err:
errsav = errno;
port = prettyprint_addr(addr, daemon->addrbuff);
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
sprintf(daemon->addrbuff, "port %d", port);
@@ -556,6 +679,8 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (fd != -1)
close (fd);
errno = errsav;
if (dienow)
{
@@ -586,9 +711,9 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (listen(fd, 5) == -1)
goto err;
}
else if (!option_bool(OPT_NOWILD))
else if (family == AF_INET)
{
if (family == AF_INET)
if (!option_bool(OPT_NOWILD))
{
#if defined(HAVE_LINUX_NETWORK)
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
@@ -599,11 +724,11 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
goto err;
#endif
}
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd))
goto err;
#endif
}
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd))
goto err;
#endif
return fd;
}
@@ -751,7 +876,8 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
l->family = addr->sa.sa_family;
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = tftpfd;
l->tftpfd = tftpfd;
l->iface = NULL;
}
return l;
@@ -798,7 +924,7 @@ void create_bound_listeners(int dienow)
struct iname *if_tmp;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad &&
if (!iface->done && !iface->dad && iface->found &&
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
@@ -822,7 +948,6 @@ void create_bound_listeners(int dienow)
if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
{
new->iface = NULL;
new->next = daemon->listeners;
daemon->listeners = new;
}
@@ -836,6 +961,9 @@ void create_bound_listeners(int dienow)
The fix is to use --bind-dynamic, which actually checks the arrival interface too.
Tough if your platform doesn't support this.
Note that checking the arrival interface is supported in the standard IPv6 API and
always done, so we don't warn about any IPv6 addresses here.
*/
void warn_bound_listeners(void)
@@ -844,43 +972,34 @@ void warn_bound_listeners(void)
int advice = 0;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (option_bool(OPT_NOWILD) && !iface->dns_auth)
if (!iface->dns_auth)
{
int warn = 0;
if (iface->addr.sa.sa_family == AF_INET)
{
if (!private_net(iface->addr.in.sin_addr, 1))
{
inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
daemon->addrbuff, iface->name);
}
}
#ifdef HAVE_IPV6
else
{
if (!IN6_IS_ADDR_LINKLOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_SITELOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_ULA(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&iface->addr.in6.sin6_addr))
{
inet_ntop(AF_INET6, &iface->addr.in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
}
}
#endif
if (warn)
{
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s. "),
daemon->addrbuff, iface->name);
}
}
if (advice)
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)."));
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));
}
void warn_int_names(void)
{
struct interface_name *intname;
for (intname = daemon->int_names; intname; intname = intname->next)
if (!intname->addr)
my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
}
int is_dad_listeners(void)
{
struct irec *iface;
+80 -25
View File
@@ -423,7 +423,7 @@ 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 },
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
@@ -1615,8 +1615,22 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->addr.sa.sa_family = AF_INET6;
#endif
else
new->name = opt_string_alloc(arg);
{
char *fam = split_chr(arg, '/');
new->name = opt_string_alloc(arg);
new->addr.sa.sa_family = 0;
if (fam)
{
if (strcmp(fam, "4") == 0)
new->addr.sa.sa_family = AF_INET;
#ifdef HAVE_IPV6
else if (strcmp(fam, "6") == 0)
new->addr.sa.sa_family = AF_INET6;
#endif
else
ret_err(gen_err);
}
}
new->next = daemon->authinterface;
daemon->authinterface = new;
@@ -1649,6 +1663,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new = opt_malloc(sizeof(struct auth_zone));
new->domain = opt_string_alloc(arg);
new->subnet = NULL;
new->interface_names = NULL;
new->next = daemon->auth_zones;
daemon->auth_zones = new;
@@ -1656,10 +1671,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
int prefixlen = 0;
char *prefix;
struct subnet *subnet = opt_malloc(sizeof(struct subnet));
subnet->next = new->subnet;
new->subnet = subnet;
struct addrlist *subnet = NULL;
struct all_addr addr;
comma = split(arg);
prefix = split_chr(arg, '/');
@@ -1667,24 +1680,50 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (prefix && !atoi_check(prefix, &prefixlen))
ret_err(gen_err);
if (inet_pton(AF_INET, arg, &subnet->addr4))
if (inet_pton(AF_INET, arg, &addr.addr.addr4))
{
subnet = opt_malloc(sizeof(struct addrlist));
subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
subnet->is6 = 0;
subnet->flags = ADDRLIST_LITERAL;
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &subnet->addr6))
else if (inet_pton(AF_INET6, arg, &addr.addr.addr6))
{
subnet = opt_malloc(sizeof(struct addrlist));
subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
subnet->is6 = 1;
subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
}
#endif
else
ret_err(gen_err);
else
{
struct auth_name_list *name = opt_malloc(sizeof(struct auth_name_list));
name->name = opt_string_alloc(arg);
name->flags = AUTH4 | AUTH6;
name->next = new->interface_names;
new->interface_names = name;
if (prefix)
{
if (prefixlen == 4)
name->flags &= ~AUTH6;
#ifdef HAVE_IPV6
else if (prefixlen == 6)
name->flags &= ~AUTH4;
#endif
else
ret_err(gen_err);
}
}
if (subnet)
{
subnet->addr = addr;
subnet->next = new->subnet;
new->subnet = subnet;
}
}
break;
}
case LOPT_AUTHSOA: /* --auth-soa */
comma = split(arg);
daemon->soa_sn = (u32)atoi(arg);
@@ -1860,9 +1899,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else
ret_err(gen_err);
}
else
else
{
char *prefstr;
arg = split(comma);
prefstr = split(arg);
if (inet_pton(AF_INET, comma, &new->start))
{
new->is6 = 0;
@@ -1883,6 +1925,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
#endif
else
ret_err(gen_err);
if (option != 's' && prefstr)
{
if (!(new->prefix = canonicalise_opt(prefstr)) ||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
ret_err(_("bad prefix"));
}
}
new->domain = d;
@@ -2454,11 +2503,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->template_interface = opt_string_alloc(a[leasepos] + 12);
new->flags |= CONTEXT_TEMPLATE;
}
else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
{
new->template_interface = opt_string_alloc(a[leasepos] + 19);
new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
}
else
break;
}
@@ -3325,15 +3369,26 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new = opt_malloc(sizeof(struct interface_name));
new->next = NULL;
new->addr4 = NULL;
#ifdef HAVE_IPV6
new->addr6 = NULL;
#endif
new->addr = NULL;
/* Add to the end of the list, so that first name
of an interface is used for PTR lookups. */
for (up = &daemon->int_names; *up; up = &((*up)->next));
*up = new;
new->name = domain;
new->family = 0;
arg = split_chr(comma, '/');
if (arg)
{
if (strcmp(arg, "4") == 0)
new->family = AF_INET;
#ifdef HAVE_IPV6
else if (strcmp(arg, "6") == 0)
new->family = AF_INET6;
#endif
else
ret_err(gen_err);
}
new->intr = opt_string_alloc(comma);
break;
}
@@ -3427,7 +3482,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_RR: /* dns-rr */
{
struct txt_record *new;
size_t len;
size_t len = len;
char *data;
int val;
+25 -20
View File
@@ -205,7 +205,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
struct dhcp_netid iface_id;
struct dhcp_opt *opt_cfg;
struct ra_interface *ra_param = find_iface_param(iface_name);
int done_dns = 0;
int done_dns = 0, old_prefix = 0;
#ifdef HAVE_LINUX_NETWORK
FILE *f;
#endif
@@ -267,7 +267,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
struct in6_addr local = context->start6;
int do_slaac = 0;
parm.found_context = 1;
old_prefix = 1;
/* zero net part of address */
setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
@@ -300,9 +300,14 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
up = &context->next;
}
if (!parm.found_context)
return;
/* If we're advertising only old prefixes, set router lifetime to zero. */
if (old_prefix && !parm.found_context)
ra->lifetime = htons(0);
/* No prefixes to advertise. */
if (!old_prefix && !parm.found_context)
return;
#ifdef HAVE_LINUX_NETWORK
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
available from SIOCGIFMTU */
@@ -425,7 +430,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_MULTICAST(local))
{
int do_prefix = 0;
int real_prefix = 0;
int do_slaac = 0;
int deprecate = 0;
int constructed = 0;
@@ -434,9 +439,9 @@ static int add_prefixes(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
context->saved_valid = valid;
@@ -491,7 +496,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
if (!param->first)
context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE;
do_prefix = 1;
real_prefix = context->prefix;
}
param->first = 0;
@@ -518,18 +523,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->link_global = *local;
}
if (do_prefix)
if (real_prefix != 0)
{
struct prefix_opt *opt;
if ((opt = expand(sizeof(struct prefix_opt))))
{
/* zero net part of address */
setaddr6part(local, addr6part(local) & ~((prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU));
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
opt->prefix_len = real_prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
opt->valid_lifetime = htonl(valid);
@@ -597,7 +602,7 @@ time_t periodic_ra(time_t now)
if ((context->flags & CONTEXT_OLD) &&
context->if_index != 0 &&
indextoname(daemon->icmp6fd, param.iface, param.name))
indextoname(daemon->icmp6fd, context->if_index, param.name))
{
/* A context for an old address. We'll not find the interface by
looking for addresses, but we know it anyway, since the context is
@@ -640,9 +645,9 @@ static int iface_search(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix) &&
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix) &&
context->ra_time != 0 &&
difftime(context->ra_time, param->now) <= 0.0)
{
@@ -665,9 +670,9 @@ static int iface_search(struct in6_addr *local, int prefix,
/* zero timers for other contexts on the same subnet, so they don't timeout
independently */
for (context = context->next; context; context = context->next)
if (prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
if (prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
context->ra_time = 0;
return 0; /* found, abort */
+31 -25
View File
@@ -637,7 +637,7 @@ struct subnet_opt {
#endif
};
size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
@@ -1221,7 +1221,7 @@ int check_for_local_domain(char *name, time_t now)
struct naptr *naptr;
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME)) &&
(crecp->flags & (F_HOSTS | F_DHCP)))
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
return 1;
for (naptr = daemon->naptr; naptr; naptr = naptr->next)
@@ -1550,8 +1550,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
{
struct addrlist *addrlist;
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
break;
if (addrlist)
@@ -1566,8 +1566,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
{
struct addrlist *addrlist;
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
break;
if (addrlist)
@@ -1725,29 +1725,35 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (intr)
{
struct addrlist *addrlist;
int gotit = 0;
enumerate_interfaces(0);
addrlist = intr->addr4;
#ifdef HAVE_IPV6
if (type == T_AAAA)
addrlist = intr->addr6;
#endif
ans = 1;
if (!dryrun)
{
if (!addrlist)
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
else
for (; addrlist; addrlist = addrlist->next)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
{
ans = 1;
if (!dryrun)
{
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL, type, C_IN,
type == T_A ? "4" : "6", &addrlist->addr))
anscount++;
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
#ifdef HAVE_IPV6
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
#endif
{
gotit = 1;
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL, type, C_IN,
type == T_A ? "4" : "6", &addrlist->addr))
anscount++;
}
}
}
}
if (!dryrun && !gotit)
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
continue;
}
@@ -1851,7 +1857,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (qtype == T_CNAME || qtype == T_ANY)
{
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP))))
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))))
{
ans = 1;
if (!dryrun)
+8 -4
View File
@@ -92,7 +92,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_netid known_id, iface_id, cpewan_id;
struct dhcp_opt *o;
unsigned char pxe_uuid[17];
unsigned char *oui = NULL, *serial = NULL, *class = NULL;
unsigned char *oui = NULL, *serial = NULL;
#ifdef HAVE_SCRIPT
unsigned char *class = NULL;
#endif
subnet_addr.s_addr = override.s_addr = 0;
@@ -156,8 +159,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
unsigned char *y = option_ptr(opt, offset + elen + 5);
oui = option_find1(x, y, 1, 1);
serial = option_find1(x, y, 2, 1);
class = option_find1(x, y, 3, 1);
#ifdef HAVE_SCRIPT
class = option_find1(x, y, 3, 1);
#endif
/* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
the gateway id back. Note that the device class is optional */
if (oui && serial)
@@ -1542,7 +1546,7 @@ static void log_packet(char *type, void *addr, unsigned char *ext_mac,
{
struct in_addr a;
if (!err && (!option_bool(OPT_LOG_OPTS) || option_bool(OPT_QUIET_DHCP)))
if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
return;
/* addr may be misaligned */
+2 -1
View File
@@ -764,7 +764,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
/* Return addresses for all valid contexts which don't yet have one */
while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
+9 -3
View File
@@ -60,7 +60,12 @@ void tftp_request(struct listener *listen, time_t now)
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct all_addr addra;
#ifdef HAVE_IPV6
/* Can always get recvd interface for IPv6 */
int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
#else
int check_dest = !option_bool(OPT_NOWILD);
#endif
union {
struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6
@@ -91,8 +96,9 @@ void tftp_request(struct listener *listen, time_t now)
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
return;
if (option_bool(OPT_NOWILD))
/* Can always get recvd interface for IPv6 */
if (!check_dest)
{
if (listen->iface)
{
+24 -23
View File
@@ -28,24 +28,12 @@
#include <idna.h>
#endif
#ifdef HAVE_ARC4RANDOM
void rand_init(void)
{
return;
}
unsigned short rand16(void)
{
return (unsigned short) (arc4random() >> 15);
}
#else
/* SURF random number generator */
static u32 seed[32];
static u32 in[12];
static u32 out[8];
static int outleft = 0;
void rand_init()
{
@@ -83,18 +71,31 @@ static void surf(void)
unsigned short rand16(void)
{
static int outleft = 0;
if (!outleft) {
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
surf();
outleft = 8;
}
if (!outleft)
{
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
surf();
outleft = 8;
}
return (unsigned short) out[--outleft];
}
#endif
u64 rand64(void)
{
static int outleft = 0;
if (outleft < 2)
{
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
surf();
outleft = 8;
}
outleft -= 2;
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
}
static int check_name(char *in)
{
@@ -457,7 +458,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++)
{
char sav;
char sav = sav;
if (j < bytes - 1)
{
sav = in[(j+1)*2];