Compare commits
38 Commits
v2.67test1
...
v2.68test2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd9d9ce54c | ||
|
|
32b4e4cb7c | ||
|
|
376d48c7f1 | ||
|
|
6586e8352a | ||
|
|
3511a92869 | ||
|
|
44de649e5c | ||
|
|
29c122af83 | ||
|
|
6dbdc972c4 | ||
|
|
7b174c250d | ||
|
|
50d7f721ee | ||
|
|
eec5c1e21c | ||
|
|
1f776a4aa2 | ||
|
|
227ddad9b5 | ||
|
|
a9bf81ad91 | ||
|
|
6008bdbbc1 | ||
|
|
93bafe619d | ||
|
|
8ab91e9f7f | ||
|
|
5731050062 | ||
|
|
fb63dd1345 | ||
|
|
5f8002fcd7 | ||
|
|
19b1689161 | ||
|
|
b485ed97aa | ||
|
|
53c4c5c859 | ||
|
|
dc27e148a1 | ||
|
|
45cca58592 | ||
|
|
e136725c5b | ||
|
|
486479e943 | ||
|
|
3bb51da835 | ||
|
|
806cf78797 | ||
|
|
3b3f441189 | ||
|
|
24b5a5d50b | ||
|
|
d56a604a96 | ||
|
|
8c0b73d3a8 | ||
|
|
6bd3a09fb8 | ||
|
|
f65b0e546b | ||
|
|
8584c502d3 | ||
|
|
c3edf383ff | ||
|
|
c4cd95df68 |
59
CHANGELOG
59
CHANGELOG
@@ -1,3 +1,39 @@
|
||||
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.
|
||||
|
||||
|
||||
version 2.67
|
||||
Fix crash if upstream server returns SERVFAIL when
|
||||
--conntrack in use. Thanks to Giacomo Tazzari for finding
|
||||
@@ -90,8 +126,6 @@ version 2.67
|
||||
smallest valid dhcp-range is sent. Thanks to Uwe Schindler
|
||||
for suggesting this.
|
||||
|
||||
Add --force-fast-ra option. Another thanks to Uwe Schindler.
|
||||
|
||||
Make --listen-address higher priority than --except-interface
|
||||
in all circumstances. Thanks to Thomas Hood for the bugreport.
|
||||
|
||||
@@ -132,8 +166,27 @@ version 2.67
|
||||
|
||||
Update Spanish transalation. Thanks to Vicente Soriano.
|
||||
|
||||
Add --ra-param option. Thanks to Vladislav Grishenko for
|
||||
inspiration on this.
|
||||
|
||||
Add --add-subnet configuration, to tell upstream DNS
|
||||
servers where the original client is.
|
||||
servers where the original client is. Thanks to DNSthingy
|
||||
for sponsoring this feature.
|
||||
|
||||
Add --quiet-dhcp, --quiet-dhcp6 and --quiet-ra. Thanks to
|
||||
Kevin Darbyshire-Bryant for the initial patch.
|
||||
|
||||
Allow A/AAAA records created by --interface-name to be the
|
||||
target of --cname. Thanks to Hadmut Danisch for the
|
||||
suggestion.
|
||||
|
||||
Avoid treating a --dhcp-host which has an IPv6 address
|
||||
as eligable for use with DHCPv4 on the grounds that it has
|
||||
no address, and vice-versa. Thanks to Yury Konovalov for
|
||||
spotting the problem.
|
||||
|
||||
Do a better job caching dangling CNAMEs. Thanks to Yves
|
||||
Dorfsman for spotting the problem.
|
||||
|
||||
|
||||
version 2.66
|
||||
|
||||
@@ -497,7 +497,7 @@ Return an NAPTR DNS record, as specified in RFC3403.
|
||||
Return a CNAME record which indicates that <cname> is really
|
||||
<target>. There are significant limitations on the target; it must be a
|
||||
DNS name which is known to dnsmasq from /etc/hosts (or additional
|
||||
hosts files), from DHCP or from another
|
||||
hosts files), from DHCP, from --interface-name or from another
|
||||
.B --cname.
|
||||
If the target does not satisfy this
|
||||
criteria, the whole cname is ignored. The cname must be unique, but it
|
||||
@@ -589,10 +589,19 @@ needed for a client to do validation itself.
|
||||
.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
|
||||
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
|
||||
@@ -680,12 +689,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
|
||||
@@ -1260,6 +1263,11 @@ tried. This flag disables this check. Use with caution.
|
||||
Extra logging for DHCP: log all the options sent to DHCP clients and
|
||||
the tags used to determine them.
|
||||
.TP
|
||||
.B --quiet-dhcp, --quiet-dhcp6, --quiet-ra
|
||||
Suppress logging of the routine operation of these protocols. Errors and
|
||||
problems will still be logged. --quiet-dhcp and quiet-dhcp6 are
|
||||
over-ridden by --log-dhcp.
|
||||
.TP
|
||||
.B \-l, --dhcp-leasefile=<path>
|
||||
Use the specified file to store DHCP lease information.
|
||||
.TP
|
||||
@@ -1538,11 +1546,19 @@ the relevant link-local address of the machine running dnsmasq is sent
|
||||
as recursive DNS server. If provided, the DHCPv6 options dns-server and
|
||||
domain-search are used for RDNSS and DNSSL.
|
||||
.TP
|
||||
.B --force-fast-ra
|
||||
Normally, dnsmasq advertises a new IPv6 prefix frequently (every 10 seconds or so) for the first minute, and then
|
||||
drops back to sending "maintenance" advertisements every 10 minutes or so. This option forces dnsmasq to be always in
|
||||
frequent RA mode. It's a bug workaround for mobile devices which go deaf to RAs during sleep and therefore
|
||||
lose conectivity; with frequent RAs they recover in a reasonable time after wakeup.
|
||||
.B --ra-param=<interface>,[high|low],[[<ra-interval>],<router lifetime>]
|
||||
Set non-default values for router advertisements sent via an
|
||||
interface. The priority field for the router may be altered from the
|
||||
default of medium with eg
|
||||
.B --ra-param=eth0,high.
|
||||
The interval between router advertisements may be set (in seconds) with
|
||||
.B --ra-param=eth0,60.
|
||||
The lifetime of the route may be changed or set to zero, which allows
|
||||
a router to advertise prefixes but not a route via itself.
|
||||
.B --ra-parm=eth0,0,0
|
||||
(A value of zero for the interval means the default value.) All three parameters may be set at once.
|
||||
.B --ra-param=low,60,1200
|
||||
The interface field may include a wildcard.
|
||||
.TP
|
||||
.B --enable-tftp[=<interface>[,<interface>]]
|
||||
Enable the TFTP server function. This is deliberately limited to that
|
||||
@@ -1886,9 +1902,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
|
||||
@@ -1946,18 +1966,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
|
||||
|
||||
164
man/fr/dnsmasq.8
164
man/fr/dnsmasq.8
@@ -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
|
||||
|
||||
37
po/fr.po
37
po/fr.po
@@ -4,10 +4,10 @@
|
||||
# Translation completed by Gildas Le Nadan <3ntr0p13@gmail.com>
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: dnsmasq 2.66\n"
|
||||
"Project-Id-Version: dnsmasq 2.67\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-06-18 12:24+0100\n"
|
||||
"PO-Revision-Date: 2013-03-26 21:12+1100\n"
|
||||
"PO-Revision-Date: 2013-10-24 19:24+1100\n"
|
||||
"Last-Translator: Gildas Le Nadan <3ntr0p13@gmail.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=ISO-8859-1\n"
|
||||
@@ -541,7 +541,7 @@ msgstr "Utilise ces relais DHCP en temps que proxy complets."
|
||||
|
||||
#: option.c:394
|
||||
msgid "Relay DHCP requests to a remote server"
|
||||
msgstr ""
|
||||
msgstr "Requêtes de relais DHCP à un serveur distant"
|
||||
|
||||
#: option.c:395
|
||||
msgid "Specify alias name for LOCAL DNS name."
|
||||
@@ -582,11 +582,11 @@ msgstr "Autoriser les clients DHCP
|
||||
|
||||
#: option.c:404
|
||||
msgid "Send router-advertisements for interfaces doing DHCPv6"
|
||||
msgstr "envoyer des annonces de routeurs pour toutes les interfaces faisant du DHCPv6"
|
||||
msgstr "Envoyer des annonces de routeurs pour toutes les interfaces faisant du DHCPv6"
|
||||
|
||||
#: option.c:405
|
||||
msgid "Always send frequent router-advertisements"
|
||||
msgstr ""
|
||||
msgstr "Envoyer des annonces de routeurs fréquentes"
|
||||
|
||||
#: option.c:406
|
||||
msgid "Specify DUID_EN-type DHCPv6 server DUID"
|
||||
@@ -634,7 +634,7 @@ msgstr "Sp
|
||||
|
||||
#: option.c:417
|
||||
msgid "Specify a domain and address range for sythesised names"
|
||||
msgstr ""
|
||||
msgstr "Spécifie un domaine et une plage d'adresses pour les noms auto-générés"
|
||||
|
||||
#: option.c:419
|
||||
msgid "Specify DHCPv6 prefix class"
|
||||
@@ -787,17 +787,14 @@ msgid "inconsistent DHCP range"
|
||||
msgstr "plage d'adresses DHCP incohérente"
|
||||
|
||||
#: option.c:2459
|
||||
#, fuzzy
|
||||
msgid "prefix length must be exactly 64 for RA subnets"
|
||||
msgstr "la taille du préfixe doit être exactement 64 pour les sous-réseaux d'annonces de routeurs (RA)"
|
||||
|
||||
#: option.c:2461
|
||||
#, fuzzy
|
||||
msgid "prefix length must be exactly 64 for subnet constructors"
|
||||
msgstr "la taille du préfixe doit être exactement 64 pour le constructeur de sous-réseaux"
|
||||
|
||||
#: option.c:2465
|
||||
#, fuzzy
|
||||
msgid "prefix length must be at least 64"
|
||||
msgstr "la taille de préfixe doit être au minimum 64"
|
||||
|
||||
@@ -806,9 +803,8 @@ msgid "inconsistent DHCPv6 range"
|
||||
msgstr "plage d'adresses DHCPv6 incohérente"
|
||||
|
||||
#: option.c:2479
|
||||
#, fuzzy
|
||||
msgid "prefix must be zero with \"constructor:\" argument"
|
||||
msgstr "la taille du préfixe doit être exactement 64 pour le constructeur de sous-réseaux"
|
||||
msgstr "le préfixe doit avoir une taille de 0 lorsque l'argument \"constructor:\" est utilisé"
|
||||
|
||||
#: option.c:2590 option.c:2638
|
||||
msgid "bad hex constant"
|
||||
@@ -842,9 +838,8 @@ msgid "bad dhcp-proxy address"
|
||||
msgstr "adresse dhcp-proxy incorrecte"
|
||||
|
||||
#: option.c:3210
|
||||
#, fuzzy
|
||||
msgid "Bad dhcp-relay"
|
||||
msgstr "plage d'adresses DHCP (dhcp-range) incorrecte"
|
||||
msgstr "valeur incorrecte pour le relais DHCP (dhcp-relay)"
|
||||
|
||||
#: option.c:3220
|
||||
msgid "bad DUID"
|
||||
@@ -1039,9 +1034,9 @@ msgid "possible DNS-rebind attack detected: %s"
|
||||
msgstr "détection d'une possible attaque de type DNS-rebind: %s"
|
||||
|
||||
#: forward.c:1216
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "Maximum number of concurrent DNS queries reached (max: %d)"
|
||||
msgstr "Spécifie le nombre maximum de requêtes DHCP concurrentes (par défaut : %s)."
|
||||
msgstr "Nombre maximum de requêtes DNS concurrentes atteint (maximum : %d)."
|
||||
|
||||
#: network.c:551
|
||||
#, c-format
|
||||
@@ -1391,7 +1386,7 @@ msgstr "ignore %s
|
||||
#: dhcp.c:993 rfc3315.c:2047
|
||||
#, c-format
|
||||
msgid "DHCP relay %s -> %s"
|
||||
msgstr ""
|
||||
msgstr "Relais DHCP %s -> %s"
|
||||
|
||||
#: lease.c:61
|
||||
#, c-format
|
||||
@@ -1709,9 +1704,9 @@ msgid "%u vendor class: %u"
|
||||
msgstr "%u Classe de vendeur ('Vendor Class') : %u"
|
||||
|
||||
#: rfc3315.c:418
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "%u client MAC address: %s"
|
||||
msgstr "le client %u fourni le nom : %s"
|
||||
msgstr "%u MAC adresse du client : %s"
|
||||
|
||||
#: rfc3315.c:650
|
||||
#, c-format
|
||||
@@ -1760,7 +1755,7 @@ msgstr "lib
|
||||
|
||||
#: rfc3315.c:2038
|
||||
msgid "Cannot multicast to DHCPv6 server without correct interface"
|
||||
msgstr ""
|
||||
msgstr "Impossible de faire du multicast au server DHCPv6 sans interface valide"
|
||||
|
||||
#: dhcp-common.c:145
|
||||
#, c-format
|
||||
@@ -1839,12 +1834,12 @@ msgstr "annonces de routeurs sur %s%s"
|
||||
#: dhcp-common.c:875
|
||||
#, c-format
|
||||
msgid "DHCP relay from %s to %s via %s"
|
||||
msgstr ""
|
||||
msgstr "Relais DHCP de %s à %s via %s"
|
||||
|
||||
#: dhcp-common.c:877
|
||||
#, c-format
|
||||
msgid "DHCP relay from %s to %s"
|
||||
msgstr ""
|
||||
msgstr "Relais DHCP de %s à %s"
|
||||
|
||||
#: radv.c:93
|
||||
#, c-format
|
||||
|
||||
156
src/auth.c
156
src/auth.c
@@ -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 *filter_zone(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,7 @@ 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)
|
||||
{
|
||||
#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
|
||||
|
||||
return filter_zone(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 +72,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 +80,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 +93,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 +127,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 = filter_zone(zone, flag, &addr)))
|
||||
break;
|
||||
|
||||
if (!zone)
|
||||
{
|
||||
auth = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
intr = NULL;
|
||||
|
||||
if (flag == F_IPV4)
|
||||
@@ -161,8 +147,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 +163,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 +180,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 +344,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 +373,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 +386,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 +419,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 +429,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 +447,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 +470,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 +501,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 +523,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 +659,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 (!(subnet->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 ((subnet->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 +709,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 +727,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 +763,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 +783,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 */
|
||||
|
||||
@@ -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));
|
||||
|
||||
58
src/cache.c
58
src/cache.c
@@ -24,7 +24,7 @@ static struct crec *new_chain = NULL;
|
||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||
static union bigname *big_free = NULL;
|
||||
static int bignames_left, hash_size;
|
||||
static int uid = 0;
|
||||
static int uid = 1;
|
||||
#ifdef HAVE_DNSSEC
|
||||
static struct keydata *keyblock_free = NULL;
|
||||
#endif
|
||||
@@ -76,7 +76,7 @@ void cache_init(void)
|
||||
{
|
||||
struct crec *crecp;
|
||||
int i;
|
||||
|
||||
|
||||
bignames_left = daemon->cachesize/10;
|
||||
|
||||
if (daemon->cachesize > 0)
|
||||
@@ -177,7 +177,10 @@ static void cache_free(struct crec *crecp)
|
||||
crecp->flags &= ~F_FORWARD;
|
||||
crecp->flags &= ~F_REVERSE;
|
||||
crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
|
||||
|
||||
|
||||
if (uid == -1)
|
||||
uid++;
|
||||
|
||||
if (cache_tail)
|
||||
cache_tail->next = crecp;
|
||||
else
|
||||
@@ -235,6 +238,16 @@ char *cache_get_name(struct crec *crecp)
|
||||
return crecp->name.sname;
|
||||
}
|
||||
|
||||
char *cache_get_cname_target(struct crec *crecp)
|
||||
{
|
||||
if (crecp->addr.cname.uid != -1)
|
||||
return cache_get_name(crecp->addr.cname.target.cache);
|
||||
|
||||
return crecp->addr.cname.target.int_name->name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct crec *cache_enumerate(int init)
|
||||
{
|
||||
static int bucket;
|
||||
@@ -260,14 +273,14 @@ struct crec *cache_enumerate(int init)
|
||||
|
||||
static int is_outdated_cname_pointer(struct crec *crecp)
|
||||
{
|
||||
if (!(crecp->flags & F_CNAME))
|
||||
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == -1)
|
||||
return 0;
|
||||
|
||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||
overloaded for something completely different */
|
||||
if (crecp->addr.cname.cache &&
|
||||
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
|
||||
if (crecp->addr.cname.target.cache &&
|
||||
(crecp->addr.cname.target.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||
crecp->addr.cname.uid == crecp->addr.cname.target.cache->uid)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -317,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);
|
||||
@@ -680,9 +693,9 @@ static void add_hosts_cname(struct crec *target)
|
||||
if (hostname_isequal(cache_get_name(target), a->target) &&
|
||||
(crec = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
|
||||
crec->name.namep = a->alias;
|
||||
crec->addr.cname.cache = target;
|
||||
crec->addr.cname.target.cache = target;
|
||||
crec->addr.cname.uid = target->uid;
|
||||
cache_hash(crec);
|
||||
add_hosts_cname(crec); /* handle chains */
|
||||
@@ -901,6 +914,8 @@ void cache_reload(void)
|
||||
struct hostsfile *ah;
|
||||
struct host_record *hr;
|
||||
struct name_list *nl;
|
||||
struct cname *a;
|
||||
struct interface_name *intr;
|
||||
|
||||
cache_inserted = cache_live_freed = 0;
|
||||
|
||||
@@ -927,6 +942,20 @@ void cache_reload(void)
|
||||
up = &cache->hash_next;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
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 */
|
||||
}
|
||||
|
||||
/* borrow the packet buffer for a temporary by-address hash */
|
||||
memset(daemon->packet, 0, daemon->packet_buff_sz);
|
||||
revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
|
||||
@@ -1019,13 +1048,13 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||
|
||||
if (aliasc)
|
||||
{
|
||||
aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
|
||||
aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
|
||||
if (ttd == 0)
|
||||
aliasc->flags |= F_IMMORTAL;
|
||||
else
|
||||
aliasc->ttd = ttd;
|
||||
aliasc->name.namep = a->alias;
|
||||
aliasc->addr.cname.cache = target;
|
||||
aliasc->addr.cname.target.cache = target;
|
||||
aliasc->addr.cname.uid = target->uid;
|
||||
cache_hash(aliasc);
|
||||
add_dhcp_cname(aliasc, ttd);
|
||||
@@ -1132,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)
|
||||
@@ -1173,7 +1205,7 @@ void dump_cache(time_t now)
|
||||
{
|
||||
a = "";
|
||||
if (!is_outdated_cname_pointer(cache))
|
||||
a = cache_get_name(cache->addr.cname.cache);
|
||||
a = cache_get_cname_target(cache);
|
||||
}
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DNSKEY)
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#define SOA_REFRESH 1200 /* SOA refresh default */
|
||||
#define SOA_RETRY 180 /* SOA retry default */
|
||||
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
||||
#define RA_INTERVAL 600 /* Send unsolicited RA's this often when not provoked. */
|
||||
|
||||
/* compile-time options: uncomment below to enable or do eg.
|
||||
make COPTS=-DHAVE_BROKEN_RTC
|
||||
@@ -255,7 +254,10 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#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
|
||||
|
||||
@@ -272,27 +272,26 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
|
||||
if (!context) /* called via find_config() from lease_update_from_configs() */
|
||||
return 1;
|
||||
|
||||
if (!(context->flags & CONTEXT_V6))
|
||||
{
|
||||
if (!(config->flags & CONFIG_ADDR))
|
||||
if (!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6)))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if ((context->flags & CONTEXT_V6) && (config->flags & CONFIG_WILDCARD))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
for (; context; context = context->current)
|
||||
#ifdef HAVE_DHCP6
|
||||
if (context->flags & CONTEXT_V6)
|
||||
{
|
||||
if ((config->flags & CONFIG_ADDR6) && is_same_net6(&config->addr6, &context->start6, context->prefix))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
|
||||
return 1;
|
||||
|
||||
for (; context; context = context->current)
|
||||
if (is_same_net(config->addr, context->start, context->netmask))
|
||||
return 1;
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -316,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;
|
||||
@@ -445,7 +445,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
void bindtodevice(int fd)
|
||||
char *whichdevice(void)
|
||||
{
|
||||
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
|
||||
to that device. This is for the use case of (eg) OpenStack, which runs a new
|
||||
@@ -453,17 +453,20 @@ void bindtodevice(int fd)
|
||||
individual processes don't always see the packets they should.
|
||||
SO_BINDTODEVICE is only available Linux.
|
||||
|
||||
Note that if wildcards are used in --interface, or a configured interface doesn't
|
||||
yet exist, then more interfaces may arrive later, so we can't safely assert there
|
||||
is only one interface and proceed.
|
||||
Note that if wildcards are used in --interface, or --interface is not used at all,
|
||||
or a configured interface doesn't yet exist, then more interfaces may arrive later,
|
||||
so we can't safely assert there is only one interface and proceed.
|
||||
*/
|
||||
|
||||
struct irec *iface, *found;
|
||||
struct iname *if_tmp;
|
||||
|
||||
|
||||
if (!daemon->if_names)
|
||||
return NULL;
|
||||
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*')))
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->dhcp_ok)
|
||||
@@ -471,18 +474,24 @@ void bindtodevice(int fd)
|
||||
if (!found)
|
||||
found = iface;
|
||||
else if (strcmp(found->name, iface->name) != 0)
|
||||
return; /* more than one. */
|
||||
return NULL; /* more than one. */
|
||||
}
|
||||
|
||||
|
||||
if (found)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
strcpy(ifr.ifr_name, found->name);
|
||||
/* only allowed by root. */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
|
||||
errno != EPERM)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
return found->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bindtodevice(char *device, int fd)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
strcpy(ifr.ifr_name, device);
|
||||
/* only allowed by root. */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
|
||||
errno != EPERM)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
59
src/dhcp6.c
59
src/dhcp6.c
@@ -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;
|
||||
@@ -624,7 +640,8 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
||||
}
|
||||
|
||||
}
|
||||
else if (wildcard_match(template->template_interface, ifrn_name))
|
||||
else if (wildcard_match(template->template_interface, ifrn_name) &&
|
||||
template->prefix == prefix)
|
||||
{
|
||||
start6 = *local;
|
||||
setaddr6part(&start6, addr6part(&template->start6));
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#define T_ANY 255
|
||||
|
||||
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
|
||||
#define EDNS0_OPTION_CLIENT_SUBNET 5 /* IANA */
|
||||
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
|
||||
|
||||
|
||||
struct dns_header {
|
||||
|
||||
@@ -50,6 +50,8 @@ int main (int argc, char **argv)
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
cap_user_header_t hdr = NULL;
|
||||
cap_user_data_t data = NULL;
|
||||
char *bound_device = NULL;
|
||||
int did_bind = 0;
|
||||
#endif
|
||||
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
|
||||
struct dhcp_context *context;
|
||||
@@ -239,18 +241,29 @@ int main (int argc, char **argv)
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
|
||||
/* after enumerate_interfaces() */
|
||||
bound_device = whichdevice();
|
||||
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
if (!daemon->relay4)
|
||||
bindtodevice(daemon->dhcpfd);
|
||||
if (daemon->enable_pxe)
|
||||
bindtodevice(daemon->pxefd);
|
||||
if (!daemon->relay4 && bound_device)
|
||||
{
|
||||
bindtodevice(bound_device, daemon->dhcpfd);
|
||||
did_bind = 1;
|
||||
}
|
||||
if (daemon->enable_pxe && bound_device)
|
||||
{
|
||||
bindtodevice(bound_device, daemon->pxefd);
|
||||
did_bind = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
|
||||
if (daemon->doing_dhcp6 && !daemon->relay6)
|
||||
bindtodevice(daemon->dhcp6fd);
|
||||
if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
|
||||
{
|
||||
bindtodevice(bound_device, daemon->dhcp6fd);
|
||||
did_bind = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -260,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)
|
||||
@@ -619,6 +635,8 @@ 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))
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
@@ -659,6 +677,11 @@ int main (int argc, char **argv)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_LINUX_NETWORK
|
||||
if (did_bind)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
|
||||
# endif
|
||||
|
||||
/* after dhcp_contruct_contexts */
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
lease_find_interfaces(now);
|
||||
@@ -838,6 +861,7 @@ int main (int argc, char **argv)
|
||||
enumerate_interfaces(0);
|
||||
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
|
||||
create_bound_listeners(0);
|
||||
warn_bound_listeners();
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
|
||||
@@ -221,9 +221,11 @@ struct event_desc {
|
||||
#define OPT_TFTP_LC 38
|
||||
#define OPT_CLEVERBIND 39
|
||||
#define OPT_TFTP 40
|
||||
#define OPT_FAST_RA 41
|
||||
#define OPT_CLIENT_SUBNET 42
|
||||
#define OPT_LAST 43
|
||||
#define OPT_CLIENT_SUBNET 41
|
||||
#define OPT_QUIET_DHCP 42
|
||||
#define OPT_QUIET_DHCP6 43
|
||||
#define OPT_QUIET_RA 44
|
||||
#define OPT_LAST 45
|
||||
|
||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||
@@ -278,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;
|
||||
};
|
||||
|
||||
@@ -309,13 +321,7 @@ 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
|
||||
struct addrlist *addr;
|
||||
struct interface_name *next;
|
||||
};
|
||||
|
||||
@@ -335,8 +341,11 @@ struct crec {
|
||||
union {
|
||||
struct all_addr addr;
|
||||
struct {
|
||||
struct crec *cache;
|
||||
int uid;
|
||||
union {
|
||||
struct crec *cache;
|
||||
struct interface_name *int_name;
|
||||
} target;
|
||||
int uid; /* -1 if union is interface-name */
|
||||
} cname;
|
||||
struct {
|
||||
struct keydata *keydata;
|
||||
@@ -449,7 +458,7 @@ struct ipsets {
|
||||
struct irec {
|
||||
union mysockaddr addr;
|
||||
struct in_addr netmask; /* only valid for IPv4 */
|
||||
int tftp_ok, dhcp_ok, mtu, done, dad, dns_auth, index, multicast_done;
|
||||
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done;
|
||||
char *name;
|
||||
struct irec *next;
|
||||
};
|
||||
@@ -703,6 +712,12 @@ struct prefix_class {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ra_interface {
|
||||
char *name;
|
||||
int interval, lifetime, prio;
|
||||
struct ra_interface *next;
|
||||
};
|
||||
|
||||
struct dhcp_context {
|
||||
unsigned int lease_time, addr_epoch;
|
||||
struct in_addr netmask, broadcast;
|
||||
@@ -737,9 +752,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 {
|
||||
@@ -829,6 +843,7 @@ extern struct daemon {
|
||||
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp, *dhcp6;
|
||||
struct ra_interface *ra_interfaces;
|
||||
struct dhcp_config *dhcp_conf;
|
||||
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
||||
struct dhcp_vendor *dhcp_vendors;
|
||||
@@ -864,7 +879,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;
|
||||
@@ -932,6 +947,7 @@ struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||
void cache_unhash_dhcp(void);
|
||||
void dump_cache(time_t now);
|
||||
char *cache_get_name(struct crec *crecp);
|
||||
char *cache_get_cname_target(struct crec *crecp);
|
||||
struct crec *cache_enumerate(int init);
|
||||
#ifdef HAVE_DNSSEC
|
||||
struct keydata *keydata_alloc(char *data, size_t len);
|
||||
@@ -975,15 +991,19 @@ unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
char *name, int isExtract, int extrabytes);
|
||||
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
||||
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);
|
||||
@@ -1055,6 +1075,7 @@ void check_servers(void);
|
||||
int enumerate_interfaces(int reset);
|
||||
void create_wildcard_listeners(void);
|
||||
void create_bound_listeners(int die);
|
||||
void warn_bound_listeners(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);
|
||||
@@ -1103,6 +1124,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);
|
||||
@@ -1203,7 +1225,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,
|
||||
@@ -1255,7 +1277,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
int hw_type, char *hostname);
|
||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
void bindtodevice(int fd);
|
||||
char *whichdevice(void);
|
||||
void bindtodevice(char *device, int fd);
|
||||
#endif
|
||||
# ifdef HAVE_DHCP6
|
||||
void display_opts6(void);
|
||||
|
||||
@@ -676,7 +676,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
size_t m;
|
||||
ssize_t n;
|
||||
int if_index = 0;
|
||||
int auth_dns = 0;
|
||||
int local_auth = 0, auth_dns = 0;
|
||||
struct iovec iov[1];
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmptr;
|
||||
@@ -848,6 +848,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 +862,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 +916,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
{
|
||||
size_t size = 0;
|
||||
int norebind = 0;
|
||||
int local_auth = 0;
|
||||
int checking_disabled, check_subnet;
|
||||
size_t m;
|
||||
unsigned short qtype;
|
||||
@@ -939,7 +958,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 +971,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 +992,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
|
||||
{
|
||||
|
||||
10
src/lease.c
10
src/lease.c
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
179
src/network.c
179
src/network.c
@@ -16,6 +16,10 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifndef IN6_IS_ADDR_ULA
|
||||
#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
|
||||
int indextoname(int fd, int index, char *name)
|
||||
@@ -235,7 +239,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;
|
||||
@@ -263,15 +267,67 @@ 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)
|
||||
{
|
||||
@@ -285,18 +341,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
|
||||
}
|
||||
@@ -383,7 +440,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->done = iface->multicast_done = 0;
|
||||
iface->done = iface->multicast_done = iface->warned = 0;
|
||||
iface->index = if_index;
|
||||
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
||||
{
|
||||
@@ -409,7 +466,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;
|
||||
@@ -423,7 +479,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
||||
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));
|
||||
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -431,6 +487,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
|
||||
@@ -441,7 +498,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)
|
||||
@@ -452,7 +512,10 @@ int enumerate_interfaces(int reset)
|
||||
int errsave, ret = 1;
|
||||
struct addrlist *addr, *tmp;
|
||||
struct interface_name *intname;
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
struct auth_zone *zone;
|
||||
#endif
|
||||
|
||||
/* Do this max once per select cycle - also inhibits netlink socket use
|
||||
in TCP child processes. */
|
||||
|
||||
@@ -476,27 +539,38 @@ int enumerate_interfaces(int reset)
|
||||
/* 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
|
||||
@@ -824,6 +898,59 @@ void create_bound_listeners(int dienow)
|
||||
}
|
||||
}
|
||||
|
||||
/* In --bind-interfaces, the only access control is the addresses we're listening on.
|
||||
There's nothing to avoid a query to the address of an internal interface arriving via
|
||||
an external interface where we don't want to accept queries, except that in the usual
|
||||
case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
|
||||
and we listen on an address that looks like it's probably globally routeable, shout.
|
||||
|
||||
The fix is to use --bind-dynamic, which actually checks the arrival interface too.
|
||||
Tough if your platform doesn't support this.
|
||||
*/
|
||||
|
||||
void warn_bound_listeners(void)
|
||||
{
|
||||
struct irec *iface;
|
||||
int advice = 0;
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (option_bool(OPT_NOWILD) && !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;
|
||||
}
|
||||
}
|
||||
#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)."));
|
||||
}
|
||||
|
||||
int is_dad_listeners(void)
|
||||
{
|
||||
struct irec *iface;
|
||||
|
||||
249
src/option.c
249
src/option.c
@@ -64,77 +64,81 @@ struct myoption {
|
||||
#define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
|
||||
|
||||
/* options which don't have a one-char version */
|
||||
#define LOPT_RELOAD 256
|
||||
#define LOPT_NO_NAMES 257
|
||||
#define LOPT_TFTP 258
|
||||
#define LOPT_SECURE 259
|
||||
#define LOPT_PREFIX 260
|
||||
#define LOPT_PTR 261
|
||||
#define LOPT_BRIDGE 262
|
||||
#define LOPT_TFTP_MAX 263
|
||||
#define LOPT_FORCE 264
|
||||
#define LOPT_NOBLOCK 265
|
||||
#define LOPT_LOG_OPTS 266
|
||||
#define LOPT_MAX_LOGS 267
|
||||
#define LOPT_CIRCUIT 268
|
||||
#define LOPT_REMOTE 269
|
||||
#define LOPT_SUBSCR 270
|
||||
#define LOPT_INTNAME 271
|
||||
#define LOPT_BANK 272
|
||||
#define LOPT_DHCP_HOST 273
|
||||
#define LOPT_APREF 274
|
||||
#define LOPT_OVERRIDE 275
|
||||
#define LOPT_TFTPPORTS 276
|
||||
#define LOPT_REBIND 277
|
||||
#define LOPT_NOLAST 278
|
||||
#define LOPT_OPTS 279
|
||||
#define LOPT_DHCP_OPTS 280
|
||||
#define LOPT_MATCH 281
|
||||
#define LOPT_BROADCAST 282
|
||||
#define LOPT_NEGTTL 283
|
||||
#define LOPT_ALTPORT 284
|
||||
#define LOPT_SCRIPTUSR 285
|
||||
#define LOPT_LOCAL 286
|
||||
#define LOPT_NAPTR 287
|
||||
#define LOPT_MINPORT 288
|
||||
#define LOPT_DHCP_FQDN 289
|
||||
#define LOPT_CNAME 290
|
||||
#define LOPT_PXE_PROMT 291
|
||||
#define LOPT_PXE_SERV 292
|
||||
#define LOPT_TEST 293
|
||||
#define LOPT_TAG_IF 294
|
||||
#define LOPT_PROXY 295
|
||||
#define LOPT_GEN_NAMES 296
|
||||
#define LOPT_MAXTTL 297
|
||||
#define LOPT_NO_REBIND 298
|
||||
#define LOPT_LOC_REBND 299
|
||||
#define LOPT_ADD_MAC 300
|
||||
#define LOPT_DNSSEC 301
|
||||
#define LOPT_INCR_ADDR 302
|
||||
#define LOPT_CONNTRACK 303
|
||||
#define LOPT_FQDN 304
|
||||
#define LOPT_LUASCRIPT 305
|
||||
#define LOPT_RA 306
|
||||
#define LOPT_DUID 307
|
||||
#define LOPT_HOST_REC 308
|
||||
#define LOPT_TFTP_LC 309
|
||||
#define LOPT_RR 310
|
||||
#define LOPT_CLVERBIND 311
|
||||
#define LOPT_MAXCTTL 312
|
||||
#define LOPT_AUTHZONE 313
|
||||
#define LOPT_AUTHSERV 314
|
||||
#define LOPT_AUTHTTL 315
|
||||
#define LOPT_AUTHSOA 316
|
||||
#define LOPT_AUTHSFS 317
|
||||
#define LOPT_AUTHPEER 318
|
||||
#define LOPT_IPSET 319
|
||||
#define LOPT_SYNTH 320
|
||||
#define LOPT_RELOAD 256
|
||||
#define LOPT_NO_NAMES 257
|
||||
#define LOPT_TFTP 258
|
||||
#define LOPT_SECURE 259
|
||||
#define LOPT_PREFIX 260
|
||||
#define LOPT_PTR 261
|
||||
#define LOPT_BRIDGE 262
|
||||
#define LOPT_TFTP_MAX 263
|
||||
#define LOPT_FORCE 264
|
||||
#define LOPT_NOBLOCK 265
|
||||
#define LOPT_LOG_OPTS 266
|
||||
#define LOPT_MAX_LOGS 267
|
||||
#define LOPT_CIRCUIT 268
|
||||
#define LOPT_REMOTE 269
|
||||
#define LOPT_SUBSCR 270
|
||||
#define LOPT_INTNAME 271
|
||||
#define LOPT_BANK 272
|
||||
#define LOPT_DHCP_HOST 273
|
||||
#define LOPT_APREF 274
|
||||
#define LOPT_OVERRIDE 275
|
||||
#define LOPT_TFTPPORTS 276
|
||||
#define LOPT_REBIND 277
|
||||
#define LOPT_NOLAST 278
|
||||
#define LOPT_OPTS 279
|
||||
#define LOPT_DHCP_OPTS 280
|
||||
#define LOPT_MATCH 281
|
||||
#define LOPT_BROADCAST 282
|
||||
#define LOPT_NEGTTL 283
|
||||
#define LOPT_ALTPORT 284
|
||||
#define LOPT_SCRIPTUSR 285
|
||||
#define LOPT_LOCAL 286
|
||||
#define LOPT_NAPTR 287
|
||||
#define LOPT_MINPORT 288
|
||||
#define LOPT_DHCP_FQDN 289
|
||||
#define LOPT_CNAME 290
|
||||
#define LOPT_PXE_PROMT 291
|
||||
#define LOPT_PXE_SERV 292
|
||||
#define LOPT_TEST 293
|
||||
#define LOPT_TAG_IF 294
|
||||
#define LOPT_PROXY 295
|
||||
#define LOPT_GEN_NAMES 296
|
||||
#define LOPT_MAXTTL 297
|
||||
#define LOPT_NO_REBIND 298
|
||||
#define LOPT_LOC_REBND 299
|
||||
#define LOPT_ADD_MAC 300
|
||||
#define LOPT_DNSSEC 301
|
||||
#define LOPT_INCR_ADDR 302
|
||||
#define LOPT_CONNTRACK 303
|
||||
#define LOPT_FQDN 304
|
||||
#define LOPT_LUASCRIPT 305
|
||||
#define LOPT_RA 306
|
||||
#define LOPT_DUID 307
|
||||
#define LOPT_HOST_REC 308
|
||||
#define LOPT_TFTP_LC 309
|
||||
#define LOPT_RR 310
|
||||
#define LOPT_CLVERBIND 311
|
||||
#define LOPT_MAXCTTL 312
|
||||
#define LOPT_AUTHZONE 313
|
||||
#define LOPT_AUTHSERV 314
|
||||
#define LOPT_AUTHTTL 315
|
||||
#define LOPT_AUTHSOA 316
|
||||
#define LOPT_AUTHSFS 317
|
||||
#define LOPT_AUTHPEER 318
|
||||
#define LOPT_IPSET 319
|
||||
#define LOPT_SYNTH 320
|
||||
#ifdef OPTION6_PREFIX_CLASS
|
||||
#define LOPT_PREF_CLSS 321
|
||||
#define LOPT_PREF_CLSS 321
|
||||
#endif
|
||||
#define LOPT_FAST_RA 322
|
||||
#define LOPT_RELAY 323
|
||||
#define LOPT_ADD_SBNET 324
|
||||
#define LOPT_RELAY 323
|
||||
#define LOPT_RA_PARAM 324
|
||||
#define LOPT_ADD_SBNET 325
|
||||
#define LOPT_QUIET_DHCP 326
|
||||
#define LOPT_QUIET_DHCP6 327
|
||||
#define LOPT_QUIET_RA 328
|
||||
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -273,8 +277,11 @@ static const struct myoption opts[] =
|
||||
#ifdef OPTION6_PREFIX_CLASS
|
||||
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
|
||||
#endif
|
||||
{ "force-fast-ra", 0, 0, LOPT_FAST_RA },
|
||||
{ "dhcp-relay", 1, 0, LOPT_RELAY },
|
||||
{ "ra-param", 1, 0, LOPT_RA_PARAM },
|
||||
{ "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
|
||||
{ "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
|
||||
{ "quiet-ra", 0, 0, LOPT_QUIET_RA },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -405,7 +412,6 @@ static struct {
|
||||
{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
|
||||
{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
|
||||
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
|
||||
{ LOPT_FAST_RA, OPT_FAST_RA, NULL, gettext_noop("Always send frequent router-advertisements"), NULL },
|
||||
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
|
||||
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
|
||||
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
|
||||
@@ -417,10 +423,14 @@ 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
|
||||
{ LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
|
||||
{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
|
||||
{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
|
||||
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -1639,6 +1649,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;
|
||||
|
||||
@@ -1646,10 +1657,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, '/');
|
||||
@@ -1657,24 +1666,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);
|
||||
@@ -1850,9 +1885,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;
|
||||
@@ -1873,6 +1911,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;
|
||||
@@ -2444,11 +2489,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;
|
||||
}
|
||||
@@ -3229,6 +3269,31 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
case LOPT_RA_PARAM: /* --ra-param */
|
||||
if ((comma = split(arg)))
|
||||
{
|
||||
struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
|
||||
new->lifetime = -1;
|
||||
new->prio = 0;
|
||||
new->name = opt_string_alloc(arg);
|
||||
if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
|
||||
{
|
||||
if (*comma == 'l' || *comma == 'L')
|
||||
new->prio = 0x18;
|
||||
else
|
||||
new->prio = 0x08;
|
||||
comma = split(comma);
|
||||
}
|
||||
arg = split(comma);
|
||||
if (!atoi_check(comma, &new->interval) ||
|
||||
(arg && !atoi_check(arg, &new->lifetime)))
|
||||
ret_err(_("bad RA-params"));
|
||||
|
||||
new->next = daemon->ra_interfaces;
|
||||
daemon->ra_interfaces = new;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOPT_DUID: /* --dhcp-duid */
|
||||
if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterprise))
|
||||
ret_err(_("bad DUID"));
|
||||
@@ -3290,10 +3355,8 @@ 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));
|
||||
|
||||
139
src/radv.c
139
src/radv.c
@@ -32,11 +32,12 @@ struct ra_param {
|
||||
char *if_name;
|
||||
struct dhcp_netid *tags;
|
||||
struct in6_addr link_local, link_global;
|
||||
unsigned int pref_time;
|
||||
unsigned int pref_time, adv_interval;
|
||||
};
|
||||
|
||||
struct search_param {
|
||||
time_t now; int iface;
|
||||
char name[IF_NAMESIZE+1];
|
||||
};
|
||||
|
||||
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
|
||||
@@ -47,7 +48,11 @@ static int iface_search(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
int prefered, int valid, void *vparam);
|
||||
static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||
static void new_timeout(struct dhcp_context *context, time_t now);
|
||||
static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now);
|
||||
static unsigned int calc_lifetime(struct ra_interface *ra);
|
||||
static unsigned int calc_interval(struct ra_interface *ra);
|
||||
static unsigned int calc_prio(struct ra_interface *ra);
|
||||
static struct ra_interface *find_iface_param(char *iface);
|
||||
|
||||
static int hop_limit;
|
||||
|
||||
@@ -184,7 +189,8 @@ void icmp6_packet(time_t now)
|
||||
mac = daemon->namebuff;
|
||||
}
|
||||
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||
if (!option_bool(OPT_QUIET_RA))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||
/* source address may not be valid in solicit request. */
|
||||
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
||||
}
|
||||
@@ -198,19 +204,20 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
struct dhcp_context *context, *tmp, **up;
|
||||
struct dhcp_netid iface_id;
|
||||
struct dhcp_opt *opt_cfg;
|
||||
struct ra_interface *ra_param = find_iface_param(iface_name);
|
||||
int done_dns = 0;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
FILE *f;
|
||||
#endif
|
||||
|
||||
|
||||
save_counter(0);
|
||||
ra = expand(sizeof(struct ra_packet));
|
||||
|
||||
ra->type = ND_ROUTER_ADVERT;
|
||||
ra->code = 0;
|
||||
ra->hop_limit = hop_limit;
|
||||
ra->flags = 0x00;
|
||||
ra->lifetime = htons(RA_INTERVAL * 3); /* AdvDefaultLifetime * 3 */
|
||||
ra->flags = calc_prio(ra_param);
|
||||
ra->lifetime = htons(calc_lifetime(ra_param));
|
||||
ra->reachable_time = 0;
|
||||
ra->retrans_time = 0;
|
||||
|
||||
@@ -222,6 +229,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
parm.first = 1;
|
||||
parm.now = now;
|
||||
parm.pref_time = 0;
|
||||
parm.adv_interval = calc_interval(ra_param);
|
||||
|
||||
/* set tag with name == interface */
|
||||
iface_id.net = iface_name;
|
||||
@@ -281,7 +289,8 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
opt->prefix = local;
|
||||
|
||||
inet_ntop(AF_INET6, &local, daemon->addrbuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s old prefix", iface_name, daemon->addrbuff);
|
||||
if (!option_bool(OPT_QUIET_RA))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s old prefix", iface_name, daemon->addrbuff);
|
||||
}
|
||||
|
||||
up = &context->next;
|
||||
@@ -327,15 +336,15 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
if (opt_cfg->opt == OPTION6_DNS_SERVER)
|
||||
{
|
||||
struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
|
||||
|
||||
|
||||
done_dns = 1;
|
||||
if (opt_cfg->len == 0)
|
||||
continue;
|
||||
if (opt_cfg->len == 0 || (IN6_IS_ADDR_UNSPECIFIED(a) && parm.pref_time != 0))
|
||||
continue;
|
||||
|
||||
put_opt6_char(ICMP6_OPT_RDNSS);
|
||||
put_opt6_char((opt_cfg->len/8) + 1);
|
||||
put_opt6_short(0);
|
||||
put_opt6_long(RA_INTERVAL * 2); /* lifetime - twice RA retransmit */
|
||||
put_opt6_long(parm.pref_time);
|
||||
/* zero means "self" */
|
||||
for (i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(a))
|
||||
@@ -351,7 +360,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
put_opt6_char(ICMP6_OPT_DNSSL);
|
||||
put_opt6_char(len + 1);
|
||||
put_opt6_short(0);
|
||||
put_opt6_long(RA_INTERVAL * 2); /* lifetime - twice RA retransmit */
|
||||
put_opt6_long(parm.pref_time);
|
||||
put_opt6(opt_cfg->val, opt_cfg->len);
|
||||
|
||||
/* pad */
|
||||
@@ -360,14 +369,14 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
}
|
||||
}
|
||||
|
||||
if (daemon->port == NAMESERVER_PORT && !done_dns)
|
||||
if (daemon->port == NAMESERVER_PORT && !done_dns && parm.pref_time != 0)
|
||||
{
|
||||
/* default == us, as long as we are supplying DNS service. */
|
||||
put_opt6_char(ICMP6_OPT_RDNSS);
|
||||
put_opt6_char(3);
|
||||
put_opt6_short(0);
|
||||
put_opt6_long(RA_INTERVAL * 2); /* lifetime - twice RA retransmit */
|
||||
put_opt6(&parm.link_global, IN6ADDRSZ);
|
||||
put_opt6_long(parm.pref_time);
|
||||
put_opt6(&parm.link_local, IN6ADDRSZ);
|
||||
}
|
||||
|
||||
/* set managed bits unless we're providing only RA on this link */
|
||||
@@ -455,8 +464,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
if (time > context->lease_time)
|
||||
{
|
||||
time = context->lease_time;
|
||||
if (time < ((unsigned int)(3 * RA_INTERVAL)))
|
||||
time = 3 * RA_INTERVAL;
|
||||
if (time < ((unsigned int)(3 * param->adv_interval)))
|
||||
time = 3 * param->adv_interval;
|
||||
}
|
||||
|
||||
if (context->flags & CONTEXT_DEPRECATE)
|
||||
@@ -529,7 +538,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
opt->prefix = *local;
|
||||
|
||||
inet_ntop(AF_INET6, local, daemon->addrbuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
|
||||
if (!option_bool(OPT_QUIET_RA))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -564,8 +574,7 @@ time_t periodic_ra(time_t now)
|
||||
struct search_param param;
|
||||
struct dhcp_context *context;
|
||||
time_t next_event;
|
||||
char interface[IF_NAMESIZE+1];
|
||||
|
||||
|
||||
param.now = now;
|
||||
param.iface = 0;
|
||||
|
||||
@@ -586,13 +595,15 @@ time_t periodic_ra(time_t now)
|
||||
if (!context)
|
||||
break;
|
||||
|
||||
if ((context->flags & CONTEXT_OLD) && context->if_index != 0)
|
||||
if ((context->flags & CONTEXT_OLD) &&
|
||||
context->if_index != 0 &&
|
||||
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, as long as we
|
||||
sent at least one RA whilst the address was current. */
|
||||
looking for addresses, but we know it anyway, since the context is
|
||||
constructed */
|
||||
param.iface = context->if_index;
|
||||
new_timeout(context, now);
|
||||
new_timeout(context, param.name, now);
|
||||
}
|
||||
else if (iface_enumerate(AF_INET6, ¶m, iface_search))
|
||||
/* There's a context overdue, but we can't find an interface
|
||||
@@ -603,15 +614,14 @@ time_t periodic_ra(time_t now)
|
||||
context->ra_time = 0;
|
||||
|
||||
if (param.iface != 0 &&
|
||||
indextoname(daemon->icmp6fd, param.iface, interface) &&
|
||||
iface_check(AF_LOCAL, NULL, interface, NULL))
|
||||
iface_check(AF_LOCAL, NULL, param.name, NULL))
|
||||
{
|
||||
struct iname *tmp;
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, interface))
|
||||
if (tmp->name && wildcard_match(tmp->name, param.name))
|
||||
break;
|
||||
if (!tmp)
|
||||
send_ra(now, param.iface, interface, NULL);
|
||||
send_ra(now, param.iface, param.name, NULL);
|
||||
}
|
||||
}
|
||||
return next_event;
|
||||
@@ -643,7 +653,14 @@ static int iface_search(struct in6_addr *local, int prefix,
|
||||
if (!(flags & IFACE_TENTATIVE))
|
||||
param->iface = if_index;
|
||||
|
||||
new_timeout(context, param->now);
|
||||
/* should never fail */
|
||||
if (!indextoname(daemon->icmp6fd, if_index, param->name))
|
||||
{
|
||||
param->iface = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_timeout(context, param->name, param->now);
|
||||
|
||||
/* zero timers for other contexts on the same subnet, so they don't timeout
|
||||
independently */
|
||||
@@ -659,14 +676,70 @@ static int iface_search(struct in6_addr *local, int prefix,
|
||||
return 1; /* keep searching */
|
||||
}
|
||||
|
||||
static void new_timeout(struct dhcp_context *context, time_t now)
|
||||
static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now)
|
||||
{
|
||||
if (difftime(now, context->ra_short_period_start) < 60.0 || option_bool(OPT_FAST_RA))
|
||||
if (difftime(now, context->ra_short_period_start) < 60.0)
|
||||
/* range 5 - 20 */
|
||||
context->ra_time = now + 5 + (rand16()/4400);
|
||||
else
|
||||
/* range 3/4 - 1 times RA_INTERVAL */
|
||||
context->ra_time = now + (3 * RA_INTERVAL)/4 + ((RA_INTERVAL * (unsigned int)rand16()) >> 18);
|
||||
{
|
||||
/* range 3/4 - 1 times MaxRtrAdvInterval */
|
||||
unsigned int adv_interval = calc_interval(find_iface_param(iface_name));
|
||||
context->ra_time = now + (3 * adv_interval)/4 + ((adv_interval * (unsigned int)rand16()) >> 18);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ra_interface *find_iface_param(char *iface)
|
||||
{
|
||||
struct ra_interface *ra;
|
||||
|
||||
for (ra = daemon->ra_interfaces; ra; ra = ra->next)
|
||||
if (wildcard_match(ra->name, iface))
|
||||
return ra;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int calc_interval(struct ra_interface *ra)
|
||||
{
|
||||
int interval = 600;
|
||||
|
||||
if (ra && ra->interval != 0)
|
||||
{
|
||||
interval = ra->interval;
|
||||
if (interval > 1800)
|
||||
interval = 1800;
|
||||
else if (interval < 4)
|
||||
interval = 4;
|
||||
}
|
||||
|
||||
return (unsigned int)interval;
|
||||
}
|
||||
|
||||
static unsigned int calc_lifetime(struct ra_interface *ra)
|
||||
{
|
||||
int lifetime, interval = (int)calc_interval(ra);
|
||||
|
||||
if (!ra || ra->lifetime == -1) /* not specified */
|
||||
lifetime = 3 * interval;
|
||||
else
|
||||
{
|
||||
lifetime = ra->lifetime;
|
||||
if (lifetime < interval && lifetime != 0)
|
||||
lifetime = interval;
|
||||
else if (lifetime > 9000)
|
||||
lifetime = 9000;
|
||||
}
|
||||
|
||||
return (unsigned int)lifetime;
|
||||
}
|
||||
|
||||
static unsigned int calc_prio(struct ra_interface *ra)
|
||||
{
|
||||
if (ra)
|
||||
return ra->prio;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
239
src/rfc1035.c
239
src/rfc1035.c
@@ -637,27 +637,27 @@ 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 */
|
||||
|
||||
int len;
|
||||
void *addrp;
|
||||
|
||||
if (source->sa.sa_family == AF_INET)
|
||||
{
|
||||
opt->family = htons(1);
|
||||
opt->source_netmask = daemon->addr4_netmask;
|
||||
addrp = &source->in.sin_addr;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
if (source->sa.sa_family == AF_INET6)
|
||||
{
|
||||
opt->family = htons(2);
|
||||
opt->source_netmask = daemon->addr6_netmask;
|
||||
addrp = &source->in6.sin6_addr;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
opt->family = htons(1);
|
||||
opt->source_netmask = daemon->addr4_netmask;
|
||||
addrp = &source->in.sin_addr;
|
||||
}
|
||||
|
||||
opt->scope_netmask = 0;
|
||||
len = 0;
|
||||
@@ -724,7 +724,7 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
|
||||
}
|
||||
|
||||
/* is addr in the non-globally-routed IP space? */
|
||||
static int private_net(struct in_addr addr, int ban_localhost)
|
||||
int private_net(struct in_addr addr, int ban_localhost)
|
||||
{
|
||||
in_addr_t ip_addr = ntohl(addr.s_addr);
|
||||
|
||||
@@ -1011,91 +1011,88 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
else
|
||||
continue;
|
||||
|
||||
if (!(flags & F_NXDOMAIN))
|
||||
cname_loop1:
|
||||
if (!(p1 = skip_questions(header, qlen)))
|
||||
return 0;
|
||||
|
||||
for (j = ntohs(header->ancount); j != 0; j--)
|
||||
{
|
||||
cname_loop1:
|
||||
if (!(p1 = skip_questions(header, qlen)))
|
||||
return 0;
|
||||
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
for (j = ntohs(header->ancount); j != 0; j--)
|
||||
GETSHORT(aqtype, p1);
|
||||
GETSHORT(aqclass, p1);
|
||||
GETLONG(attl, p1);
|
||||
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
|
||||
{
|
||||
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(aqtype, p1);
|
||||
GETSHORT(aqclass, p1);
|
||||
GETLONG(attl, p1);
|
||||
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
|
||||
(p1) -= 4;
|
||||
PUTLONG(daemon->max_ttl, p1);
|
||||
}
|
||||
GETSHORT(ardlen, p1);
|
||||
endrr = p1+ardlen;
|
||||
|
||||
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
|
||||
{
|
||||
if (aqtype == T_CNAME)
|
||||
{
|
||||
(p1) -= 4;
|
||||
PUTLONG(daemon->max_ttl, p1);
|
||||
}
|
||||
GETSHORT(ardlen, p1);
|
||||
endrr = p1+ardlen;
|
||||
|
||||
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
|
||||
{
|
||||
if (aqtype == T_CNAME)
|
||||
if (!cname_count--)
|
||||
return 0; /* looped CNAMES */
|
||||
newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
|
||||
if (newc)
|
||||
{
|
||||
if (!cname_count--)
|
||||
return 0; /* looped CNAMES */
|
||||
newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
|
||||
if (newc)
|
||||
newc->addr.cname.target.cache = NULL;
|
||||
if (cpp)
|
||||
{
|
||||
newc->addr.cname.cache = NULL;
|
||||
if (cpp)
|
||||
{
|
||||
cpp->addr.cname.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
}
|
||||
|
||||
cpp = newc;
|
||||
if (attl < cttl)
|
||||
cttl = attl;
|
||||
|
||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||
return 0;
|
||||
goto cname_loop1;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = 1;
|
||||
|
||||
/* copy address into aligned storage */
|
||||
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
||||
return 0; /* bad packet */
|
||||
memcpy(&addr, p1, addrlen);
|
||||
|
||||
/* check for returned address in private space */
|
||||
if (check_rebind &&
|
||||
(flags & F_IPV4) &&
|
||||
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_IPSET
|
||||
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
||||
{
|
||||
ipsets_cur = ipsets;
|
||||
while (*ipsets_cur)
|
||||
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
|
||||
if (newc && cpp)
|
||||
{
|
||||
cpp->addr.cname.cache = newc;
|
||||
cpp->addr.cname.target.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
cpp = NULL;
|
||||
}
|
||||
|
||||
cpp = newc;
|
||||
if (attl < cttl)
|
||||
cttl = attl;
|
||||
|
||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||
return 0;
|
||||
goto cname_loop1;
|
||||
}
|
||||
else if (!(flags & F_NXDOMAIN))
|
||||
{
|
||||
found = 1;
|
||||
|
||||
/* copy address into aligned storage */
|
||||
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
||||
return 0; /* bad packet */
|
||||
memcpy(&addr, p1, addrlen);
|
||||
|
||||
/* check for returned address in private space */
|
||||
if (check_rebind &&
|
||||
(flags & F_IPV4) &&
|
||||
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_IPSET
|
||||
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
||||
{
|
||||
ipsets_cur = ipsets;
|
||||
while (*ipsets_cur)
|
||||
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
|
||||
if (newc && cpp)
|
||||
{
|
||||
cpp->addr.cname.target.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
cpp = NULL;
|
||||
}
|
||||
|
||||
p1 = endrr;
|
||||
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||
return 0; /* bad packet */
|
||||
}
|
||||
|
||||
p1 = endrr;
|
||||
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||
return 0; /* bad packet */
|
||||
}
|
||||
|
||||
if (!found && !option_bool(OPT_NO_NEG))
|
||||
@@ -1112,7 +1109,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags);
|
||||
if (newc && cpp)
|
||||
{
|
||||
cpp->addr.cname.cache = newc;
|
||||
cpp->addr.cname.target.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
}
|
||||
@@ -1224,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)
|
||||
@@ -1553,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)
|
||||
@@ -1569,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)
|
||||
@@ -1720,7 +1717,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
}
|
||||
|
||||
/* interface name stuff */
|
||||
|
||||
intname_restart:
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(name, intr->name))
|
||||
break;
|
||||
@@ -1728,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;
|
||||
}
|
||||
|
||||
@@ -1779,22 +1782,28 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
{
|
||||
/* don't answer wildcard queries with data not from /etc/hosts
|
||||
or DHCP leases */
|
||||
if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
|
||||
if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
||||
break;
|
||||
|
||||
if (crecp->flags & F_CNAME)
|
||||
{
|
||||
char *cname_target = cache_get_cname_target(crecp);
|
||||
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), &nameoffset,
|
||||
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
|
||||
T_CNAME, C_IN, "d", cname_target))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
strcpy(name, cache_get_name(crecp->addr.cname.cache));
|
||||
goto cname_restart;
|
||||
strcpy(name, cname_target);
|
||||
/* check if target interface_name */
|
||||
if (crecp->addr.cname.uid == -1)
|
||||
goto intname_restart;
|
||||
else
|
||||
goto cname_restart;
|
||||
}
|
||||
|
||||
if (crecp->flags & F_NEG)
|
||||
@@ -1848,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)
|
||||
@@ -1856,7 +1865,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), &nameoffset,
|
||||
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
|
||||
T_CNAME, C_IN, "d", cache_get_cname_target(crecp)))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
@@ -2029,7 +2038,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
if (trunc)
|
||||
header->hb3 |= HB3_TC;
|
||||
|
||||
if (anscount == 0 && nxdomain)
|
||||
if (nxdomain)
|
||||
SET_RCODE(header, NXDOMAIN);
|
||||
else
|
||||
SET_RCODE(header, NOERROR); /* no error */
|
||||
|
||||
@@ -34,7 +34,7 @@ static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||
static struct in_addr option_addr(unsigned char *opt);
|
||||
static unsigned int option_uint(unsigned char *opt, int i, int size);
|
||||
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||
int mac_len, char *interface, char *string, u32 xid);
|
||||
int mac_len, char *interface, char *string, char *err, u32 xid);
|
||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
||||
static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
|
||||
static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
|
||||
@@ -610,7 +610,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
}
|
||||
|
||||
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
|
||||
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
|
||||
|
||||
return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
|
||||
}
|
||||
@@ -827,7 +827,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
opt71.next = daemon->dhcp_opts;
|
||||
do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
|
||||
log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);
|
||||
log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
return dhcp_packet_size(mess, agent_id, real_end);
|
||||
}
|
||||
@@ -887,7 +887,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
prune_vendor_opts(tagif_netid);
|
||||
do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid);
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
|
||||
}
|
||||
@@ -919,7 +919,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
return 0;
|
||||
|
||||
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid);
|
||||
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
|
||||
|
||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||
lease_prune(lease, now);
|
||||
@@ -951,7 +951,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else
|
||||
message = _("unknown lease");
|
||||
|
||||
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
|
||||
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1015,7 +1015,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
message = _("no address available");
|
||||
}
|
||||
|
||||
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid);
|
||||
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
|
||||
return 0;
|
||||
@@ -1028,7 +1028,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
|
||||
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
|
||||
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||
|
||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||
clear_packet(mess, end);
|
||||
@@ -1144,7 +1144,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mess->yiaddr = mess->ciaddr;
|
||||
}
|
||||
|
||||
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
|
||||
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||
|
||||
if (!message)
|
||||
{
|
||||
@@ -1216,7 +1216,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
if (message)
|
||||
{
|
||||
log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid);
|
||||
log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
mess->yiaddr.s_addr = 0;
|
||||
clear_packet(mess, end);
|
||||
@@ -1355,7 +1355,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else
|
||||
override = lease->override;
|
||||
|
||||
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid);
|
||||
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
||||
|
||||
clear_packet(mess, end);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
@@ -1378,7 +1378,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||
message = _("ignored");
|
||||
|
||||
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
|
||||
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
|
||||
|
||||
if (message || mess->ciaddr.s_addr == 0)
|
||||
return 0;
|
||||
@@ -1404,7 +1404,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
|
||||
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);
|
||||
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
||||
|
||||
if (lease)
|
||||
{
|
||||
@@ -1538,10 +1538,13 @@ static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
|
||||
#endif
|
||||
|
||||
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||
int mac_len, char *interface, char *string, u32 xid)
|
||||
int mac_len, char *interface, char *string, char *err, u32 xid)
|
||||
{
|
||||
struct in_addr a;
|
||||
|
||||
if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
|
||||
return;
|
||||
|
||||
/* addr may be misaligned */
|
||||
if (addr)
|
||||
memcpy(&a, addr, sizeof(a));
|
||||
@@ -1549,22 +1552,24 @@ static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||
print_mac(daemon->namebuff, ext_mac, mac_len);
|
||||
|
||||
if(option_bool(OPT_LOG_OPTS))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s",
|
||||
my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
|
||||
ntohl(xid),
|
||||
type,
|
||||
interface,
|
||||
addr ? inet_ntoa(a) : "",
|
||||
addr ? " " : "",
|
||||
daemon->namebuff,
|
||||
string ? string : "");
|
||||
string ? string : "",
|
||||
err ? err : "");
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s",
|
||||
my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
|
||||
type,
|
||||
interface,
|
||||
addr ? inet_ntoa(a) : "",
|
||||
addr ? " " : "",
|
||||
daemon->namebuff,
|
||||
string ? string : "");
|
||||
string ? string : "",
|
||||
err ? err : "");
|
||||
}
|
||||
|
||||
static void log_options(unsigned char *start, u32 xid)
|
||||
|
||||
@@ -41,6 +41,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now);
|
||||
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
|
||||
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||
static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize);
|
||||
static void *opt6_next(void *opts, void *end);
|
||||
static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
|
||||
@@ -595,7 +596,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
end_opt6(o);
|
||||
}
|
||||
|
||||
log6_packet(state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
|
||||
log6_quiet(state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
|
||||
|
||||
request_no_address:
|
||||
solicit_tags = tagif;
|
||||
@@ -763,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)
|
||||
@@ -815,7 +817,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
state->lease_allocate = 1;
|
||||
|
||||
log6_packet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
|
||||
log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
|
||||
|
||||
if (ignore)
|
||||
return 0;
|
||||
@@ -928,7 +930,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
|
||||
log6_packet(state, "DHCPRENEW", NULL, NULL);
|
||||
log6_quiet(state, "DHCPRENEW", NULL, NULL);
|
||||
|
||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
||||
{
|
||||
@@ -1011,8 +1013,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
message = _("address invalid");
|
||||
}
|
||||
|
||||
log6_packet(state, "DHCPREPLY", req_addr, message);
|
||||
|
||||
if (message)
|
||||
log6_packet(state, "DHCPREPLY", req_addr, message);
|
||||
else
|
||||
log6_quiet(state, "DHCPREPLY", req_addr, message);
|
||||
|
||||
o1 = new_opt6(OPTION6_IAADDR);
|
||||
put_opt6(req_addr, sizeof(*req_addr));
|
||||
put_opt6_long(preferred_time);
|
||||
@@ -1034,7 +1039,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
|
||||
log6_packet(state, "DHCPCONFIRM", NULL, NULL);
|
||||
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
|
||||
|
||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
||||
{
|
||||
@@ -1055,7 +1060,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
return 1;
|
||||
}
|
||||
|
||||
log6_packet(state, "DHCPREPLY", req_addr, state->hostname);
|
||||
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1084,7 +1089,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
else
|
||||
state->send_domain = get_domain6(NULL);
|
||||
|
||||
log6_packet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
|
||||
log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
|
||||
if (ignore)
|
||||
return 0;
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
@@ -1098,7 +1103,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
|
||||
log6_packet(state, "DHCPRELEASE", NULL, NULL);
|
||||
log6_quiet(state, "DHCPRELEASE", NULL, NULL);
|
||||
|
||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
||||
{
|
||||
@@ -1160,7 +1165,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
|
||||
log6_packet(state, "DHCPDECLINE", NULL, NULL);
|
||||
log6_quiet(state, "DHCPDECLINE", NULL, NULL);
|
||||
|
||||
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
|
||||
{
|
||||
@@ -1610,7 +1615,7 @@ static void add_address(struct state *state, struct dhcp_context *context, unsig
|
||||
}
|
||||
}
|
||||
|
||||
log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
|
||||
log6_quiet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
|
||||
|
||||
}
|
||||
|
||||
@@ -1880,6 +1885,12 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
|
||||
}
|
||||
}
|
||||
|
||||
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string)
|
||||
{
|
||||
if (option_bool(OPT_LOG_OPTS) || !option_bool(OPT_QUIET_DHCP6))
|
||||
log6_packet(state, type, addr, string);
|
||||
}
|
||||
|
||||
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string)
|
||||
{
|
||||
int clid_len = state->clid_len;
|
||||
|
||||
@@ -200,7 +200,8 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
||||
slaac->backoff = 0;
|
||||
gotone = 1;
|
||||
inet_ntop(AF_INET6, sender, daemon->addrbuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_INFO, "SLAAC-CONFIRM(%s) %s %s", interface, daemon->addrbuff, lease->hostname);
|
||||
if (!option_bool(OPT_QUIET_DHCP6))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "SLAAC-CONFIRM(%s) %s %s", interface, daemon->addrbuff, lease->hostname);
|
||||
}
|
||||
|
||||
lease_update_dns(gotone);
|
||||
|
||||
37
src/util.c
37
src/util.c
@@ -39,6 +39,15 @@ unsigned short rand16(void)
|
||||
return (unsigned short) (arc4random() >> 15);
|
||||
}
|
||||
|
||||
u64 rand64(void)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
arc4random_buf(&ret, sizeof(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* SURF random number generator */
|
||||
@@ -46,6 +55,7 @@ unsigned short rand16(void)
|
||||
static u32 seed[32];
|
||||
static u32 in[12];
|
||||
static u32 out[8];
|
||||
static int outleft = 0;
|
||||
|
||||
void rand_init()
|
||||
{
|
||||
@@ -82,16 +92,31 @@ static void surf(void)
|
||||
}
|
||||
|
||||
unsigned short rand16(void)
|
||||
{
|
||||
if (!outleft)
|
||||
{
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
|
||||
return (unsigned short) out[--outleft];
|
||||
}
|
||||
|
||||
u64 rand64(void)
|
||||
{
|
||||
static int outleft = 0;
|
||||
|
||||
if (!outleft) {
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
if (outleft < 2)
|
||||
{
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
|
||||
outleft -= 2;
|
||||
|
||||
return (unsigned short) out[--outleft];
|
||||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user