Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a6bca81f6 | ||
|
|
9e038946a1 |
120
CHANGELOG
120
CHANGELOG
@@ -2459,10 +2459,126 @@ version 2.41
|
||||
SIP, XMPP and Google-talk to the example config file.
|
||||
|
||||
Fix va_list abuse in log.c. This fixes crashes on powerpc
|
||||
when debug mode is set. Thanks to cedric Duval for the
|
||||
when debug mode is set. Thanks to Cedric Duval for the
|
||||
patch.
|
||||
|
||||
version 2.42
|
||||
Define _GNU_SOURCE to avoid problems with later glibc
|
||||
headers. Thanks to Jima for spotting the problem.
|
||||
|
||||
|
||||
Add --dhcp-alternate-port option. Thanks to Jan Psota for
|
||||
the suggestion.
|
||||
|
||||
Fix typo in code which is only used on BSD, when Dbus and
|
||||
IPv6 support is enabled. Thanks to Roy Marples.
|
||||
|
||||
Updated Polish translations - thank to Jan Psota.
|
||||
|
||||
Fix OS detection logic to cope with GNU/FreeBSD.
|
||||
|
||||
Fix unitialised variable in DBus code - thanks to Roy
|
||||
Marples.
|
||||
|
||||
Fix network enumeration code to work on later NetBSD -
|
||||
thanks to Roy Marples.
|
||||
|
||||
Provide --dhcp-bridge on all BSD variants.
|
||||
|
||||
Define _LARGEFILE_SOURCE which removes an arbitrary 2GB
|
||||
limit on logfiles. Thanks to Paul Chambers for spotting
|
||||
the problem.
|
||||
|
||||
Fix RFC3046 agent-id echo code, broken for many
|
||||
releases. Thanks to Jeremy Laine for spotting the problem
|
||||
and providing a patch.
|
||||
|
||||
Added Solaris 10 service manifest from David Connelly in
|
||||
contrib/Solaris10
|
||||
|
||||
Add --dhcp-scriptuser option.
|
||||
|
||||
Support new capability interface on suitable Linux
|
||||
kernels, removes "legacy support in use" messages. Thanks
|
||||
to Jorge Bastos for pointing this out.
|
||||
|
||||
Fix subtle bug in cache code which could cause dnsmasq to
|
||||
lock spinning CPU in rare circumstances. Thanks to Alex
|
||||
Chekholko for bug reports and help debugging.
|
||||
|
||||
Support netascii transfer mode for TFTP.
|
||||
|
||||
|
||||
version 2.43
|
||||
Updated Polish translation. Thanks to Jan Psota.
|
||||
|
||||
Flag errors when configuration options are repeated
|
||||
illegally.
|
||||
|
||||
Further tweaks for GNU/kFreeBSD
|
||||
|
||||
Add --no-wrap to msgmerge call - provides nicer .po file
|
||||
format.
|
||||
|
||||
Honour lease-time spec in dhcp-host lines even for
|
||||
BOOTP. The user is assumed to known what they are doing in
|
||||
this case. (Hosts without the time spec still get infinite
|
||||
leases for BOOTP, over-riding the default in the
|
||||
dhcp-range.) Thanks to Peter Katzmann for uncovering this.
|
||||
|
||||
Fix problem matching relay-agent ids. Thanks to Michael
|
||||
Rack for the bug report.
|
||||
|
||||
Add --naptr-record option. Suggestion from Johan
|
||||
Bergquist.
|
||||
|
||||
Implement RFC 5107 server-id-override DHCP relay agent
|
||||
option.
|
||||
|
||||
Apply patches from Stefan Kruger for compilation on
|
||||
Solaris 10 under Sun studio.
|
||||
|
||||
Yet more tweaking of Linux capability code, to suppress
|
||||
pointless wingeing from kernel 2.6.25 and above.
|
||||
|
||||
Improve error checking during startup. Previously, some
|
||||
errors which occurred during startup would be worked
|
||||
around, with dnsmasq still starting up. Some were logged,
|
||||
some silent. Now, they all cause a fatal error and dnsmasq
|
||||
terminates with a non-zero exit code. The errors are those
|
||||
associated with changing uid and gid, setting process
|
||||
capabilities and writing the pidfile. Thanks to Uwe
|
||||
Gansert and the Suse security team for pointing out
|
||||
this improvement, and Bill Reimers for good implementation
|
||||
suggestions.
|
||||
|
||||
Provide NO_LARGEFILE compile option to switch off largefile
|
||||
support when compiling against versions of uclibc which
|
||||
don't support it. Thanks to Stephane Billiart for the patch.
|
||||
|
||||
Implement random source ports for interactions with
|
||||
upstream nameservers. New spoofing attacks have been found
|
||||
against nameservers which do not do this, though it is not
|
||||
clear if dnsmasq is vulnerable, since to doesn't implement
|
||||
recursion. By default dnsmasq will now use a different
|
||||
source port (and socket) for each query it sends
|
||||
upstream. This behaviour can suppressed using the
|
||||
--query-port option, and the old default behaviour
|
||||
restored using --query-port=0. Explicit source-port
|
||||
specifications in --server configs are still honoured.
|
||||
|
||||
Replace the random number generator, for better
|
||||
security. On most BSD systems, dnsmasq uses the
|
||||
arc4random() RNG, which is secure, but on other platforms,
|
||||
it relied on the C-library RNG, which may be
|
||||
guessable and therefore allow spoofing. This release
|
||||
replaces the libc RNG with the SURF RNG, from Daniel
|
||||
J. Berstein's DJBDNS package.
|
||||
|
||||
Don't attempt to change user or group or set capabilities
|
||||
if dnsmasq is run as a non-root user. Without this, the
|
||||
change from soft to hard errors when these fail causes
|
||||
problems for non-root daemons listening on high
|
||||
ports. Thanks to Patrick McLean for spotting this.
|
||||
|
||||
Updated French translation. Thanks to Gildas Le Nadan.
|
||||
|
||||
|
||||
10
FAQ
10
FAQ
@@ -226,7 +226,7 @@ A: What is happening is this: The boot process sends a DHCP
|
||||
Q: What network types are supported by the DHCP server?
|
||||
|
||||
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
|
||||
Linux Token Ring is also supported.
|
||||
Linux all network types (including FireWire) are supported.
|
||||
|
||||
Q: What is this strange "bind-interface" option?
|
||||
|
||||
@@ -387,12 +387,12 @@ A: This a variant on the iptables problem. Explicit details on how to
|
||||
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2007q4/001764.html
|
||||
|
||||
|
||||
Q: Dnsmasq logs "running as root because setting capabilities failed"
|
||||
when it starts up. Why did that happen and what can do to fix it?
|
||||
Q: Dnsmasq fails to start up with a message about capabilities.
|
||||
Why did that happen and what can do to fix it?
|
||||
|
||||
A: Change your kernel configuration: either deselect CONFIG_SECURITY
|
||||
_or_ select CONFIG_SECURITY_CAPABILITIES.
|
||||
|
||||
_or_ select CONFIG_SECURITY_CAPABILITIES. Alternatively, you can
|
||||
remove the need to set capabilities by running dnsmasq as root.
|
||||
|
||||
Q: Where can I get .rpms Suitable for Suse?
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -74,7 +74,7 @@ install-i18n : all-i18n install-common
|
||||
merge :
|
||||
$(MAKE) I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' -f ../bld/Makefile -C $(SRC) dnsmasq.pot
|
||||
cd $(PO); for f in *.po; do \
|
||||
msgmerge -U $$f ../$(SRC)/dnsmasq.pot; \
|
||||
msgmerge --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
|
||||
done
|
||||
|
||||
|
||||
|
||||
28
contrib/Solaris10/README
Normal file
28
contrib/Solaris10/README
Normal file
@@ -0,0 +1,28 @@
|
||||
From: David Connelly <dconnelly@gmail.com>
|
||||
Date: Mon, Apr 7, 2008 at 3:31 AM
|
||||
Subject: Solaris 10 service manifest
|
||||
To: dnsmasq-discuss@lists.thekelleys.org.uk
|
||||
|
||||
|
||||
I've found dnsmasq much easier to set up on my home server running Solaris
|
||||
10 than the stock dhcp/dns server, which is probably overkill anyway for my
|
||||
simple home network needs. Since Solaris now uses SMF (Service Management
|
||||
Facility) to manage services I thought I'd create a simple service manifest
|
||||
for the dnsmasq service. The manifest currently assumes that dnsmasq has
|
||||
been installed in '/usr/local/sbin/dnsmasq' and the configuration file in
|
||||
'/usr/local/etc/dnsmasq.conf', so you may have to adjust these paths for
|
||||
your local installation. Here are the steps I followed to install and enable
|
||||
the dnsmasq service:
|
||||
# svccfg import dnsmasq.xml
|
||||
# svcadm enable dnsmasq
|
||||
|
||||
To confirm that the service is enabled and online:
|
||||
|
||||
# svcs -l dnsmasq
|
||||
|
||||
I've just started learning about SMF so if anyone has any
|
||||
corrections/feedback they are more than welcome.
|
||||
|
||||
Thanks,
|
||||
David
|
||||
|
||||
65
contrib/Solaris10/dnsmasq.xml
Normal file
65
contrib/Solaris10/dnsmasq.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
|
||||
|
||||
<!-- Service manifest for dnsmasq -->
|
||||
|
||||
<service_bundle type='manifest' name='dnsmasq'>
|
||||
<service name='network/dnsmasq' type='service' version='1'>
|
||||
|
||||
<create_default_instance enabled='false'/>
|
||||
<single_instance/>
|
||||
|
||||
<dependency name='multi-user'
|
||||
grouping='require_all'
|
||||
restart_on='refresh'
|
||||
type='service'>
|
||||
<service_fmri value='svc:/milestone/multi-user'/>
|
||||
</dependency>
|
||||
|
||||
<dependency name='config'
|
||||
grouping='require_all'
|
||||
restart_on='restart'
|
||||
type='path'>
|
||||
<service_fmri value='file:///usr/local/etc/dnsmasq.conf'/>
|
||||
</dependency>
|
||||
|
||||
<dependent name='dnsmasq_multi-user-server'
|
||||
grouping='optional_all'
|
||||
restart_on='none'>
|
||||
<service_fmri value='svc:/milestone/multi-user-server' />
|
||||
</dependent>
|
||||
|
||||
<exec_method type='method' name='start'
|
||||
exec='/usr/local/sbin/dnsmasq -C /usr/local/etc/dnsmasq.conf'
|
||||
timeout_seconds='60' >
|
||||
<method_context>
|
||||
<method_credential user='root' group='root' privileges='all'/>
|
||||
</method_context>
|
||||
</exec_method>
|
||||
|
||||
<exec_method type='method'
|
||||
name='stop'
|
||||
exec=':kill'
|
||||
timeout_seconds='60'/>
|
||||
|
||||
<exec_method type='method'
|
||||
name='refresh'
|
||||
exec=':kill -HUP'
|
||||
timeout_seconds='60' />
|
||||
|
||||
<template>
|
||||
<common_name>
|
||||
<loctext xml:lang='C'>dnsmasq server</loctext>
|
||||
</common_name>
|
||||
<description>
|
||||
<loctext xml:lang='C'>
|
||||
dnsmasq - A lightweight DHCP and caching DNS server.
|
||||
</loctext>
|
||||
</description>
|
||||
<documentation>
|
||||
<manpage title='dnsmasq' section='8' manpath='/usr/local/man'/>
|
||||
</documentation>
|
||||
</template>
|
||||
|
||||
</service>
|
||||
</service_bundle>
|
||||
@@ -77,7 +77,7 @@ Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on r
|
||||
.B \-8, --log-facility=<facility>
|
||||
Set the facility to which dnsmasq will send syslog entries, this
|
||||
defaults to DAEMON, and to LOCAL0 when debug mode is in operation. If
|
||||
the facilty given contains at least one '/' character, it is taken to
|
||||
the facility given contains at least one '/' character, it is taken to
|
||||
be a filename, and dnsmasq logs to the given file, instead of
|
||||
syslog. (Errors whilst reading configuration will still go to syslog,
|
||||
but all output from a successful startup, and all output whilst
|
||||
@@ -122,9 +122,18 @@ forwarder. Defaults to 1280, which is the RFC2671-recommended maximum
|
||||
for ethernet.
|
||||
.TP
|
||||
.B \-Q, --query-port=<query_port>
|
||||
Send outbound DNS queries from, and listen for their replies on, the specific UDP port <query_port> instead of using one chosen at runtime. Useful to simplify your
|
||||
firewall rules; without this, your firewall would have to allow connections from outside DNS servers to a range of UDP ports, or dynamically adapt to the
|
||||
port being used by the current dnsmasq instance.
|
||||
Send outbound DNS queries from, and listen for their replies on, the
|
||||
specific UDP port <query_port> instead of using random ports. NOTE
|
||||
that using this option will make dnsmasq less secure against DNS
|
||||
spoofing attacks but it may be faster and use less resources. Setting this option
|
||||
to zero makes dnsmasq use a single port allocated to it by the
|
||||
OS: this was the default behaviour in versions prior to 2.43.
|
||||
.TP
|
||||
.B --min-port=<port>
|
||||
Do not use ports less than that given as source for outbound DNS
|
||||
queries. Dnsmasq picks random ports as source for outbound queries:
|
||||
when this option is given, the ports used will always to larger
|
||||
than that specified. Useful for systems behind firewalls.
|
||||
.TP
|
||||
.B \-i, --interface=<interface name>
|
||||
Listen only on the specified interface(s). Dnsmasq automatically adds
|
||||
@@ -373,12 +382,15 @@ so any number may be included, split by commas.
|
||||
.B --ptr-record=<name>[,<target>]
|
||||
Return a PTR DNS record.
|
||||
.TP
|
||||
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
|
||||
Return an NAPTR DNS record, as specified in RFC3403.
|
||||
.TP
|
||||
.B --interface-name=<name>,<interface>
|
||||
Return a DNS record associating the name with the primary address on
|
||||
the given interface. This flag specifies an A record for the given
|
||||
name in the same way as an /etc/hosts line, except that the address is
|
||||
not constant, but taken from the given interface. If the interface is
|
||||
down, not configured or non-existant, an empty record is returned. The
|
||||
down, not configured or non-existent, an empty record is returned. The
|
||||
matching PTR record is also created, mapping the interface address to
|
||||
the name. More than one name may be associated with an interface
|
||||
address by repeating the flag; in that case the first instance is used
|
||||
@@ -406,7 +418,7 @@ in
|
||||
options. If the lease time is given, then leases
|
||||
will be given for that length of time. The lease time is in seconds,
|
||||
or minutes (eg 45m) or hours (eg 1h) or the literal "infinite". The
|
||||
minimum lease time is two minutres. This
|
||||
minimum lease time is two minutes. This
|
||||
option may be repeated, with different addresses, to enable DHCP
|
||||
service to more than one network. For directly connected networks (ie,
|
||||
networks on which the machine running dnsmasq has an interface) the
|
||||
@@ -635,7 +647,7 @@ not allocate it a DHCP lease.
|
||||
.B --dhcp-ignore-names[=<network-id>[,<network-id>]]
|
||||
When all the given network-ids match the set of network-ids derived
|
||||
from the net, host, vendor and user classes, ignore any hostname
|
||||
provided by the host. Note that, unlike dhcp-ignore, it is permissable
|
||||
provided by the host. Note that, unlike dhcp-ignore, it is permissible
|
||||
to supply no netid tags, in which case DHCP-client supplied hostnames
|
||||
are always ignored, and DHCP hosts are added to the DNS using only
|
||||
dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
|
||||
@@ -671,7 +683,15 @@ It changes the behaviour from strict RFC compliance so that DHCP requests on
|
||||
unknown leases from unknown hosts are not ignored. This allows new hosts
|
||||
to get a lease without a tedious timeout under all circumstances. It also
|
||||
allows dnsmasq to rebuild its lease database without each client needing to
|
||||
reaquire a lease, if the database is lost.
|
||||
reacquire a lease, if the database is lost.
|
||||
.TP
|
||||
.B --dhcp-alternate-port[=<server port>[,<client port>]]
|
||||
Change the ports used for DHCP from the default. If this option is
|
||||
given alone, without arguments, it changes the ports used for DHCP
|
||||
from 67 and 68 to 1067 and 1068. If a single argument is given, that
|
||||
port number is used for the server and the port number plus one used
|
||||
for the client. Finally, two port numbers allows arbitrary
|
||||
specification of both server and client ports for DHCP.
|
||||
.TP
|
||||
.B \-3, --bootp-dynamic
|
||||
Enable dynamic allocation of IP addresses to BOOTP clients. Use this
|
||||
@@ -728,9 +748,9 @@ If a lease used to have a hostname, which is
|
||||
removed, an "old" event is generated with the new state of the lease,
|
||||
ie no name, and the former name is provided in the environment
|
||||
variable DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE stores the name of
|
||||
the interface on which the reuest arrived; this is not set for "old"
|
||||
the interface on which the request arrived; this is not set for "old"
|
||||
actions when dnsmasq restarts.
|
||||
All file decriptors are
|
||||
All file descriptors are
|
||||
closed except stdin, stdout and stderr which are open to /dev/null
|
||||
(except in debug mode).
|
||||
The script is not invoked concurrently: if subsequent lease
|
||||
@@ -740,7 +760,10 @@ all existing leases as they are read from the lease file. Expired
|
||||
leases will be called with "del" and others with "old". <path>
|
||||
must be an absolute pathname, no PATH search occurs. When dnsmasq
|
||||
receives a HUP signal, the script will be invoked for existing leases
|
||||
with an "old " event.
|
||||
with an "old " event.
|
||||
.TP
|
||||
.B --dhcp-scriptuser
|
||||
Specify the user as which to run the lease-change script. This defaults to root, but can be changed to another user using this flag.
|
||||
.TP
|
||||
.B \-9, --leasefile-ro
|
||||
Completely suppress use of the lease database file. The file will not
|
||||
@@ -759,7 +782,7 @@ to the client-id and lease length and expiry time.
|
||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||
Treat DHCP request packets arriving at any of the <alias> interfaces
|
||||
as if they had arrived at <interface>. This option is only available
|
||||
on FreeBSD and Dragonfly BSD, and is necessary when using "old style" bridging, since
|
||||
on BSD platforms, and is necessary when using "old style" bridging, since
|
||||
packets arrive at tap interfaces which don't have an IP address.
|
||||
.TP
|
||||
.B \-s, --domain=<domain>
|
||||
@@ -784,8 +807,8 @@ in /etc/resolv.conf (or equivalent).
|
||||
.TP
|
||||
.B --enable-tftp
|
||||
Enable the TFTP server function. This is deliberately limited to that
|
||||
needed to net-boot a client: Only reading is allowed, and only in
|
||||
binary/octet mode. The tsize and blksize extensions are supported.
|
||||
needed to net-boot a client. Only reading is allowed; the tsize and
|
||||
blksize extensions are supported (tsize is only supported in octet mode).
|
||||
.TP
|
||||
.B --tftp-root=<directory>
|
||||
Look for files to transfer using TFTP relative to the given
|
||||
@@ -902,7 +925,7 @@ will close and reopen the log file. Note that during this operation,
|
||||
dnsmasq will not be running as root. When it first creates the logfile
|
||||
dnsmasq changes the ownership of the file to the non-root user it will run
|
||||
as. Logrotate should be configured to create a new log file with
|
||||
the ownership which matches the exising one before sending SIGUSR2.
|
||||
the ownership which matches the existing one before sending SIGUSR2.
|
||||
If TCP DNS queries are in progress, the old logfile will remain open in
|
||||
child processes which are handling TCP queries and may continue to be
|
||||
written. There is a limit of 150 seconds, after which all existing TCP
|
||||
@@ -1027,7 +1050,7 @@ normally if backgrounding is not enabled.
|
||||
2 - A problem with network access occurred (address in use, attempt
|
||||
to use privileged ports without permission).
|
||||
.PP
|
||||
3 - A problem occured with a filesystem operation (missing
|
||||
3 - A problem occurred with a filesystem operation (missing
|
||||
file/directory, permissions).
|
||||
.PP
|
||||
4 - Memory allocation failure.
|
||||
|
||||
152
man/fr/dnsmasq.8
152
man/fr/dnsmasq.8
@@ -58,6 +58,15 @@ Cette option permet de spécifier la valeur de time-to-live à retourner (en
|
||||
secondes). Cela permet de réduire la charge sur le serveur, mais les clients
|
||||
risquent d'utiliser des données périmées dans certains cas.
|
||||
.TP
|
||||
.B --neg-ttl=<durée>
|
||||
Les réponses négatives provenant des serveurs amonts contiennent normalement
|
||||
une information de durée de vie (time-to-live) dans les enregistrements SOA,
|
||||
information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse
|
||||
du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette
|
||||
option permet de doner une valeur de durée de vie par défaut (en secondes) que
|
||||
dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
|
||||
l'absence d'enregistrement SOA.
|
||||
.TP
|
||||
.B \-k, --keep-in-foreground
|
||||
Ne pas aller en tâche de fond au lancement, mais en dehors de cela, fonctionner
|
||||
normalement. Ce mode est prévu pour les cas où Dnsmasq est lancé par daemontools
|
||||
@@ -119,8 +128,9 @@ n'est en général pas en lecture par tout le monde.
|
||||
Imprime le numéro de version.
|
||||
.TP
|
||||
.B \-p, --port=<port>
|
||||
Ecoute sur le port numéro <port> au lieu du port DNS standard (53). Cette option
|
||||
est essentiellement utile à des fins de déverminage ("debug").
|
||||
Ecoute sur le port numéro <port> au lieu du port DNS standard (53). Paramétrer
|
||||
cette valeur à zéro désactive complètement la fonction DNS pour ne laisser actif
|
||||
que le DHCP ou le TFTP.
|
||||
.TP
|
||||
.B \-P, --edns-packet-max=<taille>
|
||||
Spécifie la taille maximum de paquet UDP EDNS.0 supporté par le relai DNS. Le
|
||||
@@ -129,11 +139,19 @@ recommandée pour ethernet dans la RFC2671.
|
||||
.TP
|
||||
.B \-Q, --query-port=<numéro de port>
|
||||
Envoie et écoute les requêtes DNS sortantes depuis le port UDP spécifié par
|
||||
<numéro de port>, et non sur un port défini lors de l'exécution. Cette option
|
||||
permet de simplifier les règles de garde-barrière ("firewall"). Sans cela en
|
||||
effet, votre garde-barrière serait obligé d'accepter les connexions depuis les
|
||||
serveurs DNS externes sur une plage de ports UDP, ou de s'adapter dynamiquement
|
||||
au port utilisé par l'instance courante de Dnsmasq.
|
||||
<numéro de port>, et non sur un port aléatoire. NOTE : Cette option rends
|
||||
dnsmasq moins sûr contre les attaques par usurpation DNS ("DNS spoofing"), mais
|
||||
cela peut permettre d'utiliser moins de ressources et d'être plus rapide. Donner
|
||||
une valeur de zéro à cette option restaure le comportement par défaut présent dans
|
||||
les versions de dnsmasq inférieures à 2.43 qui consiste à n'allouer qu'un seul port
|
||||
alloué par le système d'exploitation.
|
||||
.TP
|
||||
.B --min-port=<port>
|
||||
Ne pas utiliser de port dont le numéro est inférieur à la valeur donnée en paramètre
|
||||
pour les requêtes DNS sortantes. Dnsmasq choisis un port source aléatoire pour les
|
||||
requêtes sortantes : lorsque cette option est fournie, les ports utilisés seront toujours
|
||||
au dessus de la valeur spécifiée. Utile pour des systèmes derrière des dispositifs
|
||||
garde-barrières ("firewalls").
|
||||
.TP
|
||||
.B \-i, --interface=<nom d'interface>
|
||||
N'écouter que sur l'interface réseau spécifiée. Dnsmasq aujoute automatiquement
|
||||
@@ -277,6 +295,19 @@ fonctionner. Cette option force Dnsmasq à essayer d'interroger, pour chaque
|
||||
requête, les serveurs DNS dans leur ordre d'apparition dans le fichier
|
||||
/etc/resolv.conf.
|
||||
.TP
|
||||
.B --all-servers
|
||||
Par défaut, lorsque dnsmasq a plus d'un serveur amont disponible, il n'envoie
|
||||
les requêtes qu'à un seul serveur. Spécifier cette option force dnsmasq à
|
||||
effectuer ses requêtes à tous les serveurs disponibles. Le résultat renvoyé
|
||||
au client sera celui fournit par le premier serveur ayant répondu.
|
||||
.TP
|
||||
.B --stop-dns-rebind
|
||||
Rejete (et enregistre dans le journal d'activité) les adresses dans la gamme
|
||||
d'adresses IP privée (au sens RFC1918) qui pourraient être renvoyées par les
|
||||
serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherchant
|
||||
à détourner de leur usage les logiciels de navigation web ('browser') en s'en
|
||||
servant pour découvrir les machines situées sur le réseau local.
|
||||
.TP
|
||||
.B \-n, --no-poll
|
||||
Ne pas vérifier régulièrement si le fichier /etc/resolv.conf a été modifié.
|
||||
.TP
|
||||
@@ -291,7 +322,7 @@ simples, ne comprenant donc ni points ni nom de domaine. Si un nom n'est pas
|
||||
dans /etc/hosts ou dans la liste des baux DHCP, alors une réponse de type
|
||||
"non trouvé" est renvoyée.
|
||||
.TP
|
||||
.B \-S, --local, --server=[/[<domaine>]/[domaine/]][<Adresse IP>[#<port>][@<Adresse IP source>[#<port>]]]
|
||||
.B \-S, --local, --server=[/[<domaine>]/[domaine/]][<Adresse IP>[#<port>][@<Adresse IP source>|<interface>[#<port>]]]
|
||||
Spécifie directement l'adresse IP d'un serveur de nom amont. Cette option ne
|
||||
supprime pas la lecture du fichier /etc/resolv.conf : utiliser pour cela
|
||||
l'option
|
||||
@@ -327,14 +358,18 @@ est synonyme de
|
||||
("serveur") afin de rendre plus claire l'utilisation de cette option pour cet
|
||||
usage particulier.
|
||||
|
||||
La deuxième adresse IP optionnelle suivant le caractère @ permet de définir
|
||||
l'adresse source que Dnsmasq doit utiliser comme source pour les réponses à ce
|
||||
serveur de nom. Il doit s'agir d'une des adresses appartenant à la machine sur
|
||||
La chaîne de caractères optionnelle suivant le caractère @ permet de définir
|
||||
la source que Dnsmasq doit utiliser pour les réponses à ce
|
||||
serveur de nom. Il doit s'agir d'une des adresses IP appartenant à la machine sur
|
||||
laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera
|
||||
consignée dans le journal des événements. L'option
|
||||
.B query-port
|
||||
est ignorée pour tous les serveurs ayant une adresse source spécifiée, mais il
|
||||
est possible de la donner directement dans la spécification de l'adresse source.
|
||||
consignée dans le journal des événements, ou alors d'un nom d'interface. Si un nom
|
||||
d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées
|
||||
depuis cette interface; si une adresse ip est donnée, alors l'adresse source de
|
||||
la requête sera l'adresse en question. L'option query-port est ignorée pour tous
|
||||
les serveurs ayant une adresse source spécifiée, mais il est possible de la donner
|
||||
directement dans la spécification de l'adresse source. Forcer les requêtes à être
|
||||
émises depuis une interface spécifique n'est pas possible sur toutes les plateformes
|
||||
supportées par dnsmasq.
|
||||
.TP
|
||||
.B \-A, --address=/<domaine>/[domaine/]<adresse IP>
|
||||
Spécifie une adresse IP à retourner pour toute requête pour les domaines fournis
|
||||
@@ -417,6 +452,9 @@ caractères peuvent être spécifiées, séparées par des virgules.
|
||||
.B --ptr-record=<nom>[,<cible>]
|
||||
Définit un enregistrement DNS de type PTR.
|
||||
.TP
|
||||
.B --naptr-record=<nom>,<ordre>,<préférence>,<drapeaux>,<service>,<expr. régulière>[,<remplacement>]
|
||||
Retourne un enregistrement de type NAPTR, tel que spécifié dans le RFC3403.
|
||||
.TP
|
||||
.B --interface-name=<nom>,<interface>
|
||||
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
|
||||
l'interface donnée en argument. Cette option spécifie un enregistrement de type
|
||||
@@ -455,7 +493,8 @@ statiquement dans l'option
|
||||
Si une durée de bail est donnée, alors les baux seront donnés pour cette
|
||||
durée. La durée de bail est donnée en secondes, en minutes (exemple : 45m),
|
||||
en heures (exemple : 1h) ou être la chaine de caractère "infinite" pour une
|
||||
durée indéterminée. Cette option peut être répétée, avec différentes adresses,
|
||||
durée indéterminée. La valeur minimum pour un bail DHCP est de 2 minutes.
|
||||
Cette option peut être répétée, avec différentes adresses,
|
||||
pour activer le service DHCP sur plus d'un réseau. Pour des réseaux directement
|
||||
connectés (c'est-à-dire des réseaux dans lesquels la machine sur laquelle tourne
|
||||
Dnsmasq possède une interface), le masque de réseau est optionnel. Il est par
|
||||
@@ -549,7 +588,12 @@ que le texte fourni à la droite sur caractère "=" dans l'option
|
||||
L'avantage de stocker les informations sur les hôtes DHCP dans ce fichier est
|
||||
que celles-ci peuvent être modifiées sans recharger Dnsmasq; le fichier sera
|
||||
relu lorsque Dnsmasq reçoit un signal SIGHUP.
|
||||
.TP
|
||||
.TP
|
||||
.B --dhcp-optsfile=<fichier>
|
||||
Lis les informations relatives aux options DHCP dans le fichier spécifié.
|
||||
L'intérêt d'utiliser cette option est le même que pour --dhcp-hostsfile : le
|
||||
fichier spécifié ser rechargé à la réception par dnsmasq d'un signal SIGHUP.
|
||||
.TP
|
||||
.B \-Z, --read-ethers
|
||||
Lis les informations d'hôtes DHCP dans le fichier /etc/ethers. Le format de
|
||||
/etc/ethers est une adresse matérielle suivie, soit par un nom d'hôte, soit par
|
||||
@@ -639,6 +683,17 @@ sauf que cette option sera toujours envoyée, même si le client ne la demande p
|
||||
dans la liste de paramêtres requis. Cela est parfois nécessaire, par exemple lors
|
||||
de la fourniture d'options à PXELinux.
|
||||
.TP
|
||||
.B --dhcp-no-override
|
||||
Désactive la réutilisation des champs DHCP nom de serveur et nom de
|
||||
fichier comme espace supplémentaire pour les options. Si cela est
|
||||
possible, dnsmasq déplace les informations sur le serveur de démarrage
|
||||
et le nom de fichier (fournis par 'dhcp-boot') en dehors des champs
|
||||
dédiés à cet usage dans les options DHCP. Cet espace supplémentaire est
|
||||
alors disponible dans le paquet DHCP pour d'autres options, mais peut, dans
|
||||
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 \-U, --dhcp-vendorclass=<identifiant de réseau>,<classe de vendeur>
|
||||
Associe une chaîne de classe de vendeur à un indentifiant de réseau. La plupart
|
||||
des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
|
||||
@@ -683,6 +738,12 @@ relais DHCP, alors l'identifiant de réseau est positionné.
|
||||
Associe des options de relais DHCP issues de la RFC3993 à des identifiants de
|
||||
réseau.
|
||||
.TP
|
||||
.B --dhcp-match=<identifiant de réseau>,<numéro d'option>
|
||||
Associe l'identifiant de réseau si le client envoie une option DHCP
|
||||
avec le numéro spécifié. Cela peut-être utilisé pour identifier des
|
||||
clients spécifiques qui envoient des informations par le biais de
|
||||
numéros privés d'option.
|
||||
.TP
|
||||
.B \-J, --dhcp-ignore=<identifiant de réseau>[,<identifiant de réseau>]
|
||||
Lorsque tous les identifiants de réseau fournis coïncident avec la liste
|
||||
d'identifiants réseau dérivée des classes de réseau, hôte, vendeur et
|
||||
@@ -698,6 +759,14 @@ ignorés, et les noms d'hôtes seront ajoutés au DNS en utilisant uniquement la
|
||||
configuration dhcp-host de Dnsmasq, ainsi que le contenu des fichiers /etc/hosts
|
||||
et /etc/ethers.
|
||||
.TP
|
||||
.B --dhcp-broadcast=<identifiant de réseau>[,<identifiant de réseau>]
|
||||
Lorsque tous les identifiants de réseaux fournis correspondent à ceux
|
||||
obtenus à partir des classes de réseau, d'hôte ou d'utilisateur, force
|
||||
l'utilisation du broadcast pour communiquer avec l'hôte lorsque celui-ci n'est
|
||||
pas configuré. La plupart des clients DHCP nécessitant une réponse par le biais
|
||||
d'un broadcast activent une option dans leur requête, ce qui fait que cela
|
||||
se fait automatiquement, mais ce n'est pas la cas de certains vieux clients BOOTP.
|
||||
.TP
|
||||
.B \-M, --dhcp-boot=[net:<identifiant de réseau>,]<nom de fichier>,[<nom de serveur>[,<adresse de serveur>]]
|
||||
Spécifie les options BOOTP devant être retournées par le serveur DHCP. Le nom de
|
||||
serveur ainsi que l'adresse sont optionnels : s'ils ne sont pas fournis, le nom
|
||||
@@ -725,6 +794,14 @@ baux sans tenir compte de fastidieuses temporisations ("timeout"). Cela permet
|
||||
également à Dnsmasq de reconstruire sa base de donnée contenant les baux sans
|
||||
que les clients n'aient besoin de redemander un bail, si celle-ci est perdue.
|
||||
.TP
|
||||
.B --dhcp-alternate-port[=<port serveur>[,<port client>]]
|
||||
Change les ports utilisés par défaut pour le DHCP. Si cette option est donnée
|
||||
toute seule sans arguments, alors change les ports utilisés pour le DHCP
|
||||
de 67 et 68 respectivement à 1067 et 1068. Si un seul argument est donné, ce
|
||||
numéro est utilisé pour le port serveur et ce numéro plus 1 est utilisé pour le
|
||||
port client. Enfin, en fournissant deux numéros de ports, il est possible de
|
||||
spécifier arbitrairement 2 ports à la fois pour le serveur et pour le client DHCP.
|
||||
.TP
|
||||
.B \-3, --bootp-dynamic
|
||||
Permet l'allocation dynamique d'adresses IP à des clients BOOTP. Utiliser cette
|
||||
option avec précaution, une adresse allouée à un client BOOTP étant perpétuelle,
|
||||
@@ -782,7 +859,9 @@ nombre de secondes avant expiration est toujours stocké dans
|
||||
DNSMASQ_TIME_REMAINING. Si un bail était associé à un nom d'hôte et que celui-ci
|
||||
est supprimé, un évênement de type "old" est généré avec le nouveau statut du
|
||||
bail, c-à-d sans nom d'hôte, et le nom initial est fourni dans la variable
|
||||
d'environnement DNSMASQ_OLD_HOSTNAME.
|
||||
d'environnement DNSMASQ_OLD_HOSTNAME. La variable DNSMASQ_INTERFACE contient le nom de
|
||||
l'interface sur laquelle la requête est arrivée; ceci n'est pas renseigné
|
||||
dans le cas des actions "old" ayant lieu après un redémarrage de dnsmasq.
|
||||
Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
|
||||
sont ouverts sur /dev/null (sauf en mode déverminage).
|
||||
Le script n'est pas lancé de manière concurrente : si un autre changement de
|
||||
@@ -796,6 +875,11 @@ dans les répertoires de la variable d'environnement PATH. Lorsque Dnsmasq reço
|
||||
un signal HUP, le script sera invoqué avec une action "old" pour tous les baux
|
||||
existants.
|
||||
.TP
|
||||
.B --dhcp-scriptuser
|
||||
Spécifie l'utilisateur sous lequel le script lease-change doit être exécuté. La
|
||||
valeur par défaut correspond à l'utilisateur root mais peut-être changée par le
|
||||
biais de cette option.
|
||||
.TP
|
||||
.B \-9, --leasefile-ro
|
||||
Supprimer complètement l'usage du fichier servant de base de donnée pour les
|
||||
baux DHCP. Le fichier ne sera ni créé, ni lu, ni écrit. Change la façon dont le
|
||||
@@ -817,7 +901,7 @@ longueur de bail ou de date d'expiration.
|
||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||
Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
|
||||
comme si elles arrivaient de l'interface <interface>. Cette option est
|
||||
uniquement disponible sous FreeBSD et DragonflyBSD, et est uniquement nécessaire
|
||||
uniquement disponible sur les plateformes BSD, et est uniquement nécessaire
|
||||
lors de l'utilisation de pont ethernet "ancien mode", puisque dans ce cas les
|
||||
paquets arrivent sur des interfaces "tap" n'ayant pas d'adresse IP.
|
||||
.TP
|
||||
@@ -845,9 +929,9 @@ positionné à la première valeur de la directive "search" du fichier
|
||||
.TP
|
||||
.B --enable-tftp
|
||||
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, et uniquement en mode binaire/octet. Les
|
||||
extensions tsize et blksize sont supportées.
|
||||
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).
|
||||
.TP
|
||||
.B --tftp-root=<répertoire>
|
||||
Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le
|
||||
@@ -892,6 +976,9 @@ descripteur de fichier pour chaque connexion TFTP simultanée et pour chacun des
|
||||
fichiers devant être fournis. De fait, servir le même fichier à n clients ne
|
||||
nécessitera qu'environ n + 10 descripteurs de fichiers, alors que fournir des
|
||||
fichiers tous différents à n clients utilisera environ (2*n) + 10 descripteurs.
|
||||
Si elle est donnée, l'option
|
||||
.B --tftp-port-range
|
||||
peut affecter le nombre maximum de connexions concurrentes.
|
||||
.TP
|
||||
.B --tftp-no-blocksize
|
||||
Empêche le serveur TFTP de négocier l'option "blocksize" (taille de bloc) avec
|
||||
@@ -899,6 +986,18 @@ les clients. Certains clients buggés spécifient cette option mais se comporten
|
||||
ensuite de manière incorrecte si celle-ci est accordée.
|
||||
.TP
|
||||
.B --tftp-port-range=<début>,<fin>
|
||||
Un serveur TFTP écoute sur le port prédéfini 69 ("well-known port") pour
|
||||
l'initiation de la connexion, mais utilise également un port dynamiquement
|
||||
alloué pour chaque connexion. Normalement, ces ports sont alloués par
|
||||
le système d'exploitation, mais cette option permet de spécifier une gamme
|
||||
de ports à utiliser pour les transferts TFTP. Cela peut-être utile si
|
||||
TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur
|
||||
de début pour la plage de port ne peut-être inférieure à 1025 sauf si
|
||||
dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de
|
||||
connexions TFTP concurrentes est limitée par la taille de la gamme de
|
||||
ports ainsi spécifiée.
|
||||
.TP
|
||||
.B --tftp-port-range=<début>,<fin>
|
||||
Un serveur TFTP écoute sur un numéro de port bien connu (69) pour l'initiation
|
||||
de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces
|
||||
numéros de ports sont en principe alloués par le système d'exploitation, mais
|
||||
@@ -936,9 +1035,9 @@ Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du
|
||||
fichier de configuration prends le pas sur celle fournie en ligne de commande.
|
||||
Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et
|
||||
"#" ne soit interprêtés, et il est possible d'utiliser les séquences
|
||||
d'échappement suivantes : \\\\ \\" \\t \\a \\b \\r et \\n. Elles correspondent
|
||||
d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent
|
||||
respectivement à la barre oblique descendante ("anti-slash"), guillemets doubles,
|
||||
tabulation, sonnerie ("bell"), suppression ("backspace"), retour ("return") et
|
||||
tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et
|
||||
nouvelle ligne ("newline").
|
||||
.SH NOTES
|
||||
A la réception d'un signal SIGHUP,
|
||||
@@ -966,8 +1065,9 @@ A la réception d'un signal SIGUSR1,
|
||||
écrit des statistiques dans les traces système. Les informations fournies sont :
|
||||
la taille du cache, le nombre de noms ayant été supprimés du cache avant
|
||||
expiration afin de faire de la place pour les nouveaux noms, ainsi que le nombre
|
||||
total d'entrées ayant été insérées dans le cache.
|
||||
Lorsque Dnsmasq a été lancé via
|
||||
total d'entrées ayant été insérées dans le cache. Pour chaque serveur amont, il fournit
|
||||
le nomnbre de requêtes transmises ainsi que le nombre de requêtes ayant résulté par une
|
||||
erreur. Lorsque Dnsmasq a été lancé via
|
||||
.B --no-daemon
|
||||
ou lorsque la traçabilité maximale a été activée (
|
||||
.B -q
|
||||
|
||||
709
po/pt_BR.po
709
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
|
||||
len = ((struct ifreq *)ptr)->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#else
|
||||
len = sizeof(struct ifreq);
|
||||
#endif
|
||||
@@ -212,8 +212,8 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
udp.uh_sport = htons(DHCP_SERVER_PORT);
|
||||
udp.uh_dport = htons(DHCP_CLIENT_PORT);
|
||||
udp.uh_sport = htons(daemon->dhcp_server_port);
|
||||
udp.uh_dport = htons(daemon->dhcp_client_port);
|
||||
if (len & 1)
|
||||
((char *)mess)[len] = 0; /* for checksum, in case length is odd. */
|
||||
udp.uh_sum = 0;
|
||||
|
||||
74
src/cache.c
74
src/cache.c
@@ -45,6 +45,7 @@ static const struct {
|
||||
{ 25, "KEY" },
|
||||
{ 28, "AAAA" },
|
||||
{ 33, "SRV" },
|
||||
{ 35, "NAPTR" },
|
||||
{ 36, "KX" },
|
||||
{ 37, "CERT" },
|
||||
{ 38, "A6" },
|
||||
@@ -63,7 +64,6 @@ static const struct {
|
||||
static void cache_free(struct crec *crecp);
|
||||
static void cache_unlink(struct crec *crecp);
|
||||
static void cache_link(struct crec *crecp);
|
||||
static char *record_source(struct hostsfile *add_hosts, int index);
|
||||
static void rehash(int size);
|
||||
static void cache_hash(struct crec *crecp);
|
||||
|
||||
@@ -359,8 +359,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
struct crec *new;
|
||||
union bigname *big_name = NULL;
|
||||
int freed_all = flags & F_REVERSE;
|
||||
int free_avail = 0;
|
||||
|
||||
log_query(flags | F_UPSTREAM, name, addr, 0, NULL, 0);
|
||||
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
||||
|
||||
/* CONFIG bit no needed except for logging */
|
||||
flags &= ~F_CONFIG;
|
||||
@@ -392,8 +393,19 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
|
||||
if (new->flags & (F_FORWARD | F_REVERSE))
|
||||
{
|
||||
/* If free_avail set, we believe that an entry has been freed.
|
||||
Bugs have been known to make this not true, resulting in
|
||||
a tight loop here. If that happens, abandon the
|
||||
insert. Once in this state, all inserts will probably fail. */
|
||||
if (free_avail)
|
||||
{
|
||||
insert_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (freed_all)
|
||||
{
|
||||
free_avail = 1; /* Must be free space now. */
|
||||
cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags);
|
||||
cache_live_freed++;
|
||||
}
|
||||
@@ -516,19 +528,22 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
||||
Make sure that re-ordering doesn't break the hash-chain
|
||||
order invariants.
|
||||
*/
|
||||
if (!insert)
|
||||
{
|
||||
insert = up;
|
||||
ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
else if ((crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
|
||||
if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
crecp->hash_next = *insert;
|
||||
*insert = crecp;
|
||||
insert = &crecp->hash_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!insert)
|
||||
{
|
||||
insert = up;
|
||||
ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
|
||||
}
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* case : not expired, incorrect entry. */
|
||||
@@ -988,7 +1003,7 @@ void dump_cache(time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
static char *record_source(struct hostsfile *addn_hosts, int index)
|
||||
char *record_source(struct hostsfile *addn_hosts, int index)
|
||||
{
|
||||
char *source = HOSTSFILE;
|
||||
while (addn_hosts)
|
||||
@@ -1004,12 +1019,20 @@ static char *record_source(struct hostsfile *addn_hosts, int index)
|
||||
return source;
|
||||
}
|
||||
|
||||
void log_query(unsigned short flags, char *name, struct all_addr *addr,
|
||||
unsigned short type, struct hostsfile *addn_hosts, int index)
|
||||
void querystr(char *str, unsigned short type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
sprintf(str, "query[type=%d]", type);
|
||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||
if (typestr[i].type == type)
|
||||
sprintf(str,"query[%s]", typestr[i].name);
|
||||
}
|
||||
|
||||
void log_query(unsigned short flags, char *name, struct all_addr *addr, char *arg)
|
||||
{
|
||||
char *source, *dest = addrbuff;
|
||||
char *verb = "is";
|
||||
char types[20];
|
||||
|
||||
if (!(daemon->options & OPT_LOG))
|
||||
return;
|
||||
@@ -1053,15 +1076,9 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr,
|
||||
}
|
||||
else if (flags & F_CNAME)
|
||||
{
|
||||
/* nasty abuse of IPV4 and IPV6 flags */
|
||||
if (flags & F_IPV4)
|
||||
dest = "<MX>";
|
||||
else if (flags & F_IPV6)
|
||||
dest = "<SRV>";
|
||||
else if (flags & F_NXDOMAIN)
|
||||
dest = "<TXT>";
|
||||
else if (flags & F_BIGNAME)
|
||||
dest = "<PTR>";
|
||||
/* nasty abuse of NXDOMAIN and CNAME flags */
|
||||
if (flags & F_NXDOMAIN)
|
||||
dest = arg;
|
||||
else
|
||||
dest = "<CNAME>";
|
||||
}
|
||||
@@ -1069,7 +1086,7 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr,
|
||||
if (flags & F_DHCP)
|
||||
source = "DHCP";
|
||||
else if (flags & F_HOSTS)
|
||||
source = record_source(addn_hosts, index);
|
||||
source = arg;
|
||||
else if (flags & F_CONFIG)
|
||||
source = "config";
|
||||
else if (flags & F_UPSTREAM)
|
||||
@@ -1081,16 +1098,7 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr,
|
||||
}
|
||||
else if (flags & F_QUERY)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (type != 0)
|
||||
{
|
||||
sprintf(types, "query[type=%d]", type);
|
||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||
if (typestr[i].type == type)
|
||||
sprintf(types,"query[%s]", typestr[i].name);
|
||||
}
|
||||
source = types;
|
||||
source = arg;
|
||||
verb = "from";
|
||||
}
|
||||
else
|
||||
|
||||
80
src/config.h
80
src/config.h
@@ -14,13 +14,14 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.41"
|
||||
#define VERSION "2.43"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define EDNS_PKTSZ 1280 /* default max EDNS.0 UDP packet from RFC2671 */
|
||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
|
||||
#define CACHESIZ 150 /* default cache size */
|
||||
#define MAXLEASES 150 /* maximum number of DHCP leases */
|
||||
@@ -39,7 +40,7 @@
|
||||
#define RUNFILE "/var/run/dnsmasq.pid"
|
||||
#if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__)
|
||||
# define LEASEFILE "/var/db/dnsmasq.leases"
|
||||
#elif defined(__sun__)
|
||||
#elif defined(__sun__) || defined (__sun)
|
||||
# define LEASEFILE "/var/cache/dnsmasq.leases"
|
||||
#else
|
||||
# define LEASEFILE "/var/lib/misc/dnsmasq.leases"
|
||||
@@ -54,9 +55,12 @@
|
||||
#define CHGRP "dip"
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_ALTPORT 1067
|
||||
#define DHCP_CLIENT_ALTPORT 1068
|
||||
#define TFTP_PORT 69
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
#define RANDFILE "/dev/urandom"
|
||||
|
||||
/* DBUS interface specifics */
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
|
||||
@@ -85,13 +89,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Get linux C library versions. */
|
||||
#if defined(__linux__) && !defined(__UCLIBC__) && !defined(__uClinux__)
|
||||
/*# include <libio.h> */
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Follows system specific switches. If you run on a
|
||||
new system, you may want to edit these.
|
||||
May replace this with Autoconf one day.
|
||||
@@ -132,19 +129,6 @@ HAVE_ARC4RANDOM
|
||||
define this if you have arc4random() to get better security from DNS spoofs
|
||||
by using really random ids (OpenBSD)
|
||||
|
||||
HAVE_RANDOM
|
||||
define this if you have the 4.2BSD random() function (and its
|
||||
associated srandom() function), which is at least as good as (if not
|
||||
better than) the rand() function.
|
||||
|
||||
HAVE_DEV_RANDOM
|
||||
define this if you have the /dev/random device, which gives truly
|
||||
random numbers but may run out of random numbers.
|
||||
|
||||
HAVE_DEV_URANDOM
|
||||
define this if you have the /dev/urandom device, which gives
|
||||
semi-random numbers when it runs out of truly random numbers.
|
||||
|
||||
HAVE_SOCKADDR_SA_LEN
|
||||
define this if struct sockaddr has sa_len field (*BSD)
|
||||
|
||||
@@ -153,13 +137,18 @@ HAVE_DBUS
|
||||
define some methods to allow (re)configuration of the upstream DNS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_BSD_BRIDGE
|
||||
Define this to enable the --bridge-interface option, useful on some
|
||||
BSD systems.
|
||||
|
||||
HAVE_LARGFILE
|
||||
Define this if the C library supports large (>2GB) files probably true everywhere
|
||||
except some builds of uclibc
|
||||
|
||||
NOTES:
|
||||
For Linux you should define
|
||||
HAVE_LINUX_NETWORK
|
||||
HAVE_GETOPT_LONG
|
||||
HAVE_RANDOM
|
||||
HAVE_DEV_RANDOM
|
||||
HAVE_DEV_URANDOM
|
||||
you should NOT define
|
||||
HAVE_ARC4RANDOM
|
||||
HAVE_SOCKADDR_SA_LEN
|
||||
@@ -167,12 +156,8 @@ NOTES:
|
||||
For *BSD systems you should define
|
||||
HAVE_BSD_NETWORK
|
||||
HAVE_SOCKADDR_SA_LEN
|
||||
HAVE_RANDOM
|
||||
and you MAY define
|
||||
HAVE_ARC4RANDOM - OpenBSD and FreeBSD and NetBSD version 2.0 or later
|
||||
HAVE_DEV_URANDOM - OpenBSD and FreeBSD and NetBSD
|
||||
HAVE_DEV_RANDOM - FreeBSD and NetBSD
|
||||
(OpenBSD with hardware random number generator)
|
||||
HAVE_GETOPT_LONG - NetBSD, later FreeBSD
|
||||
(FreeBSD and OpenBSD only if you link GNU getopt)
|
||||
|
||||
@@ -188,7 +173,7 @@ NOTES:
|
||||
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
|
||||
#endif
|
||||
|
||||
/* Allow TFTP to be disabled with COPT=-DNO_TFTP */
|
||||
/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
|
||||
#ifdef NO_TFTP
|
||||
#undef HAVE_TFTP
|
||||
#endif
|
||||
@@ -200,9 +185,6 @@ NOTES:
|
||||
#define HAVE_LINUX_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_DEV_RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
/* Never use fork() on uClinux. Note that this is subtly different from the
|
||||
--keep-in-foreground option, since it also suppresses forking new
|
||||
@@ -215,13 +197,8 @@ NOTES:
|
||||
#if defined(__UCLIBC_HAS_GNU_GETOPT__) || \
|
||||
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
|
||||
# define HAVE_GETOPT_LONG
|
||||
#else
|
||||
# undef HAVE_GETOPT_LONG
|
||||
#endif
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_DEV_RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
|
||||
# define NO_FORK
|
||||
@@ -237,9 +214,6 @@ NOTES:
|
||||
#define HAVE_LINUX_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_DEV_RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
/* glibc < 2.2 has broken Sockaddr_in6 so we have to use our own. */
|
||||
/* glibc < 2.2 doesn't define in_addr_t */
|
||||
@@ -249,25 +223,25 @@ typedef unsigned long in_addr_t;
|
||||
# define HAVE_BROKEN_SOCKADDR_IN6
|
||||
#endif
|
||||
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#elif defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined (__FreeBSD_kernel__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
/* Later verions of FreeBSD have getopt_long() */
|
||||
#if defined(optional_argument) && defined(required_argument)
|
||||
# define HAVE_GETOPT_LONG
|
||||
#else
|
||||
# undef HAVE_GETOPT_LONG
|
||||
#endif
|
||||
#define HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#if !defined (__FreeBSD_kernel__)
|
||||
# define HAVE_ARC4RANDOM
|
||||
#endif
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_BRIDGE
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
#undef HAVE_GETOPT_LONG
|
||||
#define HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
/* Define before sys/socket.h is included so we get socklen_t */
|
||||
#define _BSD_SOCKLEN_T_
|
||||
@@ -278,10 +252,8 @@ typedef unsigned long in_addr_t;
|
||||
#define HAVE_BSD_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_DEV_RANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_BRIDGE
|
||||
|
||||
#elif defined(__sun) || defined(__sun__)
|
||||
#define HAVE_SOLARIS_NETWORK
|
||||
@@ -304,10 +276,8 @@ typedef unsigned long in_addr_t;
|
||||
# define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len))
|
||||
#endif
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_RANDOM
|
||||
#undef HAVE_DEV_URANDOM
|
||||
#undef HAVE_DEV_RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
|
||||
#define _XPG4_2
|
||||
#define __EXTENSIONS__
|
||||
#define ETHER_ADDR_LEN 6
|
||||
|
||||
@@ -118,7 +118,7 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
{
|
||||
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(stuct sockaddr_in6);
|
||||
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_port = htons(NAMESERVER_PORT);
|
||||
@@ -167,8 +167,11 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
||||
{
|
||||
/* Not found, create a new one. */
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
if (domain)
|
||||
serv->domain = whine_malloc(strlen(domain)+1);
|
||||
|
||||
if (domain && !serv->domain)
|
||||
{
|
||||
free(serv);
|
||||
@@ -179,7 +182,6 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
serv->flags = SERV_FROM_DBUS;
|
||||
serv->sfd = NULL;
|
||||
if (domain)
|
||||
{
|
||||
strcpy(serv->domain, domain);
|
||||
|
||||
16
src/dhcp.c
16
src/dhcp.c
@@ -71,7 +71,7 @@ void dhcp_init(void)
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(DHCP_SERVER_PORT);
|
||||
saddr.sin_port = htons(daemon->dhcp_server_port);
|
||||
saddr.sin_addr.s_addr = INADDR_ANY;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
saddr.sin_len = sizeof(struct sockaddr_in);
|
||||
@@ -264,7 +264,7 @@ void dhcp_packet(time_t now)
|
||||
if (mess->giaddr.s_addr)
|
||||
{
|
||||
/* Send to BOOTP relay */
|
||||
dest.sin_port = htons(DHCP_SERVER_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_server_port);
|
||||
dest.sin_addr = mess->giaddr;
|
||||
}
|
||||
else if (mess->ciaddr.s_addr)
|
||||
@@ -276,7 +276,7 @@ void dhcp_packet(time_t now)
|
||||
if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
|
||||
dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
|
||||
{
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
dest.sin_addr = mess->ciaddr;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +296,7 @@ void dhcp_packet(time_t now)
|
||||
cmptr->cmsg_level = SOL_IP;
|
||||
cmptr->cmsg_type = IP_PKTINFO;
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -304,7 +304,7 @@ void dhcp_packet(time_t now)
|
||||
struct sockaddr limits size to 14 bytes. */
|
||||
struct arpreq req;
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
*((struct sockaddr_in *)&req.arp_pa) = dest;
|
||||
req.arp_ha.sa_family = mess->htype;
|
||||
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
@@ -317,7 +317,7 @@ void dhcp_packet(time_t now)
|
||||
{
|
||||
/* broadcast to 255.255.255.255 (or mac address invalid) */
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
/* note that we don't specify the interface here: that's done by the
|
||||
IP_XMIT_IF sockopt lower down. */
|
||||
}
|
||||
@@ -329,7 +329,7 @@ void dhcp_packet(time_t now)
|
||||
mysteriously. Bah. Fall back to broadcast for other net types. */
|
||||
struct arpreq req;
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
*((struct sockaddr_in *)&req.arp_pa) = dest;
|
||||
req.arp_ha.sa_family = AF_UNSPEC;
|
||||
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
@@ -896,7 +896,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4);
|
||||
if (!crec)
|
||||
continue; /* should be never */
|
||||
my_syslog(LOG_WARNING, _("%s has more then one address in hostsfile, using %s for DHCP"),
|
||||
my_syslog(LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
|
||||
config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
|
||||
}
|
||||
|
||||
|
||||
319
src/dnsmasq.c
319
src/dnsmasq.c
@@ -33,6 +33,9 @@ static char *compile_opts =
|
||||
#ifdef NO_FORK
|
||||
"no-MMU "
|
||||
#endif
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
"BSD-bridge "
|
||||
#endif
|
||||
#ifndef HAVE_ISC_READER
|
||||
"no-"
|
||||
#endif
|
||||
@@ -57,18 +60,27 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
|
||||
static void check_dns_listeners(fd_set *set, time_t now);
|
||||
static void sig_handler(int sig);
|
||||
static void async_event(int pipe, time_t now);
|
||||
static void fatal_event(struct event_desc *ev);
|
||||
static void poll_resolv(void);
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int bind_fallback = 0;
|
||||
int bad_capabilities = 0;
|
||||
time_t now, last = 0;
|
||||
struct sigaction sigact;
|
||||
struct iname *if_tmp;
|
||||
int piperead, pipefd[2];
|
||||
struct passwd *ent_pw;
|
||||
int piperead, pipefd[2], err_pipe[2];
|
||||
struct passwd *ent_pw = NULL;
|
||||
uid_t script_uid = 0;
|
||||
gid_t script_gid = 0;
|
||||
struct group *gp= NULL;
|
||||
long i, max_fd = sysconf(_SC_OPEN_MAX);
|
||||
char *baduser = NULL;
|
||||
int log_err;
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
cap_user_header_t hdr = NULL;
|
||||
cap_user_data_t data = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef LOCALEDIR
|
||||
setlocale(LC_ALL, "");
|
||||
@@ -99,7 +111,7 @@ int main (int argc, char **argv)
|
||||
daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
|
||||
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
|
||||
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
||||
|
||||
|
||||
if (!daemon->lease_file)
|
||||
{
|
||||
if (daemon->dhcp)
|
||||
@@ -137,6 +149,8 @@ int main (int argc, char **argv)
|
||||
die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
rand_init();
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
if (daemon->dhcp)
|
||||
@@ -181,7 +195,7 @@ int main (int argc, char **argv)
|
||||
|
||||
if (daemon->port != 0)
|
||||
cache_init();
|
||||
|
||||
|
||||
if (daemon->options & OPT_DBUS)
|
||||
#ifdef HAVE_DBUS
|
||||
{
|
||||
@@ -197,35 +211,113 @@ int main (int argc, char **argv)
|
||||
|
||||
if (daemon->port != 0)
|
||||
pre_allocate_sfds();
|
||||
|
||||
/* Note getpwnam returns static storage */
|
||||
if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
|
||||
{
|
||||
if ((ent_pw = getpwnam(daemon->scriptuser)))
|
||||
{
|
||||
script_uid = ent_pw->pw_uid;
|
||||
script_gid = ent_pw->pw_gid;
|
||||
}
|
||||
else
|
||||
baduser = daemon->scriptuser;
|
||||
}
|
||||
|
||||
if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
|
||||
baduser = daemon->username;
|
||||
else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
|
||||
baduser = daemon->groupname;
|
||||
|
||||
if (baduser)
|
||||
die(_("unknown user or group: %s"), baduser, EC_BADCONF);
|
||||
|
||||
/* implement group defaults, "dip" if available, or group associated with uid */
|
||||
if (!daemon->group_set && !gp)
|
||||
{
|
||||
if (!(gp = getgrnam(CHGRP)) && ent_pw)
|
||||
gp = getgrgid(ent_pw->pw_gid);
|
||||
|
||||
/* for error message */
|
||||
if (gp)
|
||||
daemon->groupname = gp->gr_name;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
/* determine capability API version here, while we can still
|
||||
call safe_malloc */
|
||||
if (ent_pw && ent_pw->pw_uid != 0)
|
||||
{
|
||||
hdr = safe_malloc(sizeof(*hdr));
|
||||
int capsize = 1; /* for header version 1 */
|
||||
|
||||
/* find version supported by kernel */
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
capget(hdr, NULL);
|
||||
|
||||
if (hdr->version != LINUX_CAPABILITY_VERSION_1)
|
||||
{
|
||||
/* if unknown version, use largest supported version (3) */
|
||||
if (hdr->version != LINUX_CAPABILITY_VERSION_2)
|
||||
hdr->version = LINUX_CAPABILITY_VERSION_3;
|
||||
capsize = 2;
|
||||
}
|
||||
|
||||
data = safe_malloc(sizeof(*data) * capsize);
|
||||
memset(data, 0, sizeof(*data) * capsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Use a pipe to carry signals and other events back to the event loop
|
||||
in a race-free manner */
|
||||
if (pipe(pipefd) == -1 || !fix_fd(pipefd[0]) || !fix_fd(pipefd[1]))
|
||||
die(_("cannot create pipe: %s"), NULL, EC_MISC);
|
||||
in a race-free manner and another to carry errors to daemon-invoking process */
|
||||
safe_pipe(pipefd, 1);
|
||||
|
||||
piperead = pipefd[0];
|
||||
pipewrite = pipefd[1];
|
||||
/* prime the pipe to load stuff first time. */
|
||||
send_event(pipewrite, EVENT_RELOAD, 0);
|
||||
|
||||
err_pipe[1] = -1;
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG))
|
||||
{
|
||||
FILE *pidfile;
|
||||
int nullfd;
|
||||
|
||||
/* The following code "daemonizes" the process.
|
||||
See Stevens section 12.4 */
|
||||
|
||||
if (chdir("/") != 0)
|
||||
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
|
||||
|
||||
#ifndef NO_FORK
|
||||
if (!(daemon->options & OPT_NO_FORK))
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
/* pipe to carry errors back to original process.
|
||||
When startup is complete we close this and the process terminates. */
|
||||
safe_pipe(err_pipe, 0);
|
||||
|
||||
if ((pid = fork()) == -1 )
|
||||
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
||||
|
||||
|
||||
if (pid != 0)
|
||||
_exit(EC_GOOD);
|
||||
{
|
||||
struct event_desc ev;
|
||||
|
||||
/* close our copy of write-end */
|
||||
close(err_pipe[1]);
|
||||
|
||||
/* check for errors after the fork */
|
||||
if (read_write(err_pipe[0], (unsigned char *)&ev, sizeof(ev), 1))
|
||||
fatal_event(&ev);
|
||||
|
||||
_exit(EC_GOOD);
|
||||
}
|
||||
|
||||
close(err_pipe[0]);
|
||||
|
||||
/* NO calls to die() from here on. */
|
||||
|
||||
setsid();
|
||||
pid = fork();
|
||||
@@ -234,17 +326,25 @@ int main (int argc, char **argv)
|
||||
_exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (chdir("/") != 0)
|
||||
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
|
||||
|
||||
|
||||
/* write pidfile _after_ forking ! */
|
||||
if (daemon->runfile && (pidfile = fopen(daemon->runfile, "w")))
|
||||
{
|
||||
fprintf(pidfile, "%d\n", (int) getpid());
|
||||
fclose(pidfile);
|
||||
if (daemon->runfile)
|
||||
{
|
||||
FILE *pidfile;
|
||||
|
||||
/* only complain if started as root */
|
||||
if ((pidfile = fopen(daemon->runfile, "w")))
|
||||
{
|
||||
fprintf(pidfile, "%d\n", (int) getpid());
|
||||
fclose(pidfile);
|
||||
}
|
||||
else if (getuid() == 0)
|
||||
{
|
||||
send_event(err_pipe[1], EVENT_PIDFILE, errno);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* open stdout etc to /dev/null */
|
||||
nullfd = open("/dev/null", O_RDWR);
|
||||
dup2(nullfd, STDOUT_FILENO);
|
||||
@@ -253,51 +353,41 @@ int main (int argc, char **argv)
|
||||
close(nullfd);
|
||||
}
|
||||
|
||||
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
||||
#ifndef NO_FORK
|
||||
daemon->helperfd = create_helper(pipewrite, max_fd);
|
||||
#endif
|
||||
log_err = log_start(ent_pw, err_pipe[1]);
|
||||
|
||||
ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
|
||||
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
||||
daemon->helperfd = -1;
|
||||
#ifndef NO_FORK
|
||||
if (daemon->dhcp && daemon->lease_change_command)
|
||||
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
||||
#endif
|
||||
|
||||
/* before here, we should only call die(), after here, only call syslog() */
|
||||
log_start(ent_pw);
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG))
|
||||
if (!(daemon->options & OPT_DEBUG) && getuid() == 0)
|
||||
{
|
||||
/* UID changing, etc */
|
||||
if (daemon->groupname || ent_pw)
|
||||
{
|
||||
gid_t dummy;
|
||||
struct group *gp;
|
||||
|
||||
/* change group for /etc/ppp/resolv.conf otherwise get the group for "nobody" */
|
||||
if ((daemon->groupname && (gp = getgrnam(daemon->groupname))) ||
|
||||
(ent_pw && (gp = getgrgid(ent_pw->pw_gid))))
|
||||
{
|
||||
/* remove all supplimentary groups */
|
||||
setgroups(0, &dummy);
|
||||
setgid(gp->gr_gid);
|
||||
}
|
||||
}
|
||||
int bad_capabilities = 0;
|
||||
gid_t dummy;
|
||||
|
||||
/* remove all supplimentary groups */
|
||||
if (gp &&
|
||||
(setgroups(0, &dummy) == -1 ||
|
||||
setgid(gp->gr_gid) == -1))
|
||||
{
|
||||
send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (ent_pw && ent_pw->pw_uid != 0)
|
||||
{
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
|
||||
CAP_NET_RAW (for icmp) if we're doing dhcp */
|
||||
cap_user_header_t hdr = safe_malloc(sizeof(*hdr));
|
||||
cap_user_data_t data = safe_malloc(sizeof(*data));
|
||||
hdr->version = _LINUX_CAPABILITY_VERSION;
|
||||
hdr->pid = 0; /* this process */
|
||||
data->effective = data->permitted = data->inheritable =
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
|
||||
(1 << CAP_SETGID) | (1 << CAP_SETUID);
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
|
||||
|
||||
/* Tell kernel to not clear capabilities when dropping root */
|
||||
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
|
||||
bad_capabilities = errno;
|
||||
|
||||
|
||||
#elif defined(HAVE_SOLARIS_PRIVS)
|
||||
/* http://developers.sun.com/solaris/articles/program_privileges.html */
|
||||
priv_set_t *priv_set;
|
||||
@@ -323,20 +413,32 @@ int main (int argc, char **argv)
|
||||
bad_capabilities = ENOTSUP;
|
||||
#endif
|
||||
|
||||
if (bad_capabilities == 0)
|
||||
if (bad_capabilities != 0)
|
||||
{
|
||||
/* finally drop root */
|
||||
setuid(ent_pw->pw_uid);
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
data->effective = data->permitted =
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
|
||||
data->inheritable = 0;
|
||||
|
||||
/* lose the setuid and setgid capbilities */
|
||||
capset(hdr, data);
|
||||
#endif
|
||||
send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/* finally drop root */
|
||||
if (setuid(ent_pw->pw_uid) == -1)
|
||||
{
|
||||
send_event(err_pipe[1], EVENT_USER_ERR, errno);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
data->effective = data->permitted =
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
|
||||
data->inheritable = 0;
|
||||
|
||||
/* lose the setuid and setgid capbilities */
|
||||
if (capset(hdr, data) == -1)
|
||||
{
|
||||
send_event(err_pipe[1], EVENT_CAP_ERR, errno);
|
||||
_exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,6 +466,10 @@ int main (int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (log_err != 0)
|
||||
my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
|
||||
daemon->log_file, strerror(log_err));
|
||||
|
||||
if (bind_fallback)
|
||||
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
|
||||
|
||||
@@ -443,13 +549,9 @@ int main (int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
|
||||
{
|
||||
if (bad_capabilities)
|
||||
my_syslog(LOG_WARNING, _("warning: setting capabilities failed: %s"), strerror(bad_capabilities));
|
||||
|
||||
my_syslog(LOG_WARNING, _("running as root"));
|
||||
}
|
||||
/* finished start-up - release original process */
|
||||
if (err_pipe[1] != -1)
|
||||
close(err_pipe[1]);
|
||||
|
||||
if (daemon->port != 0)
|
||||
check_servers();
|
||||
@@ -628,11 +730,48 @@ void send_event(int fd, int event, int data)
|
||||
|
||||
ev.event = event;
|
||||
ev.data = data;
|
||||
/* pipe is non-blocking and struct event_desc is smaller than
|
||||
PIPE_BUF, so this either fails or writes everything */
|
||||
while (write(fd, &ev, sizeof(ev)) == -1 && errno == EINTR);
|
||||
|
||||
/* error pipe, debug mode. */
|
||||
if (fd == -1)
|
||||
fatal_event(&ev);
|
||||
else
|
||||
/* pipe is non-blocking and struct event_desc is smaller than
|
||||
PIPE_BUF, so this either fails or writes everything */
|
||||
while (write(fd, &ev, sizeof(ev)) == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
static void fatal_event(struct event_desc *ev)
|
||||
{
|
||||
errno = ev->data;
|
||||
|
||||
switch (ev->event)
|
||||
{
|
||||
case EVENT_DIE:
|
||||
exit(0);
|
||||
|
||||
case EVENT_PIPE_ERR:
|
||||
die(_("failed to create helper: %s"), NULL, EC_MISC);
|
||||
|
||||
case EVENT_CAP_ERR:
|
||||
die(_("setting capabilities failed: %s"), NULL, EC_MISC);
|
||||
|
||||
case EVENT_USER_ERR:
|
||||
case EVENT_HUSER_ERR:
|
||||
die(_("failed to change user-id to %s: %s"),
|
||||
ev->event == EVENT_USER_ERR ? daemon->username : daemon->scriptuser,
|
||||
EC_MISC);
|
||||
|
||||
case EVENT_GROUP_ERR:
|
||||
die(_("failed to change group-id to %s: %s"), daemon->groupname, EC_MISC);
|
||||
|
||||
case EVENT_PIDFILE:
|
||||
die(_("failed to open pidfile %s: %s"), daemon->runfile, EC_FILE);
|
||||
|
||||
case EVENT_LOG_ERR:
|
||||
die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
static void async_event(int pipe, time_t now)
|
||||
{
|
||||
pid_t p;
|
||||
@@ -688,11 +827,14 @@ static void async_event(int pipe, time_t now)
|
||||
break;
|
||||
|
||||
case EVENT_EXEC_ERR:
|
||||
my_syslog(LOG_ERR, _("failed to execute %s: %s"), daemon->lease_change_command, strerror(ev.data));
|
||||
my_syslog(LOG_ERR, _("failed to execute %s: %s"),
|
||||
daemon->lease_change_command, strerror(ev.data));
|
||||
break;
|
||||
|
||||
case EVENT_PIPE_ERR:
|
||||
my_syslog(LOG_ERR, _("failed to create helper: %s"), strerror(ev.data));
|
||||
/* necessary for fatal errors in helper */
|
||||
case EVENT_HUSER_ERR:
|
||||
case EVENT_DIE:
|
||||
fatal_event(&ev);
|
||||
break;
|
||||
|
||||
case EVENT_REOPEN:
|
||||
@@ -828,7 +970,15 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
FD_SET(serverfdp->fd, set);
|
||||
bump_maxfd(serverfdp->fd, maxfdp);
|
||||
}
|
||||
|
||||
|
||||
if (daemon->port != 0 && !daemon->osport)
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
if (daemon->randomsocks[i].refcount != 0)
|
||||
{
|
||||
FD_SET(daemon->randomsocks[i].fd, set);
|
||||
bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
|
||||
}
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
{
|
||||
/* only listen for queries if we have resources */
|
||||
@@ -865,17 +1015,24 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
static void check_dns_listeners(fd_set *set, time_t now)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
|
||||
struct listener *listener;
|
||||
int i;
|
||||
|
||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||
if (FD_ISSET(serverfdp->fd, set))
|
||||
reply_query(serverfdp, now);
|
||||
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
|
||||
|
||||
if (daemon->port != 0 && !daemon->osport)
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
if (daemon->randomsocks[i].refcount != 0 &&
|
||||
FD_ISSET(daemon->randomsocks[i].fd, set))
|
||||
reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
{
|
||||
if (listener->fd != -1 && FD_ISSET(listener->fd, set))
|
||||
receive_query(listener, now);
|
||||
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
|
||||
tftp_request(listener, now);
|
||||
|
||||
144
src/dnsmasq.h
144
src/dnsmasq.h
@@ -16,6 +16,18 @@
|
||||
|
||||
#define COPYRIGHT "Copyright (C) 2000-2008 Simon Kelley"
|
||||
|
||||
#ifndef NO_LARGEFILE
|
||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
/* Get linux C library versions. */
|
||||
#ifdef __linux__
|
||||
# define _GNU_SOURCE
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
/* get these before config.h for IPv6 stuff... */
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -60,12 +72,13 @@
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <stdarg.h>
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) || defined (__sun)
|
||||
# include <netinet/if_ether.h>
|
||||
#else
|
||||
# include <net/ethernet.h>
|
||||
@@ -84,8 +97,13 @@
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
#include <linux/capability.h>
|
||||
/* There doesn't seem to be a universally-available
|
||||
userpace header for this. */
|
||||
userpace header for these. */
|
||||
extern int capset(cap_user_header_t header, cap_user_data_t data);
|
||||
extern int capget(cap_user_header_t header, cap_user_data_t data);
|
||||
#define LINUX_CAPABILITY_VERSION_1 0x19980330
|
||||
#define LINUX_CAPABILITY_VERSION_2 0x20071026
|
||||
#define LINUX_CAPABILITY_VERSION_3 0x20080522
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#elif defined(HAVE_SOLARIS_PRIVS)
|
||||
#include <priv.h>
|
||||
@@ -109,6 +127,13 @@ struct event_desc {
|
||||
#define EVENT_KILLED 8
|
||||
#define EVENT_EXEC_ERR 9
|
||||
#define EVENT_PIPE_ERR 10
|
||||
#define EVENT_USER_ERR 11
|
||||
#define EVENT_CAP_ERR 12
|
||||
#define EVENT_PIDFILE 13
|
||||
#define EVENT_HUSER_ERR 14
|
||||
#define EVENT_GROUP_ERR 15
|
||||
#define EVENT_DIE 16
|
||||
#define EVENT_LOG_ERR 17
|
||||
|
||||
/* Exit codes. */
|
||||
#define EC_GOOD 0
|
||||
@@ -126,38 +151,38 @@ struct event_desc {
|
||||
*/
|
||||
#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
|
||||
|
||||
#define OPT_BOGUSPRIV (1<<0)
|
||||
#define OPT_FILTER (1<<1)
|
||||
#define OPT_LOG (1<<2)
|
||||
#define OPT_SELFMX (1<<3)
|
||||
#define OPT_NO_HOSTS (1<<4)
|
||||
#define OPT_NO_POLL (1<<5)
|
||||
#define OPT_DEBUG (1<<6)
|
||||
#define OPT_ORDER (1<<7)
|
||||
#define OPT_NO_RESOLV (1<<8)
|
||||
#define OPT_EXPAND (1<<9)
|
||||
#define OPT_LOCALMX (1<<10)
|
||||
#define OPT_NO_NEG (1<<11)
|
||||
#define OPT_NODOTS_LOCAL (1<<12)
|
||||
#define OPT_NOWILD (1<<13)
|
||||
#define OPT_ETHERS (1<<14)
|
||||
#define OPT_RESOLV_DOMAIN (1<<15)
|
||||
#define OPT_NO_FORK (1<<16)
|
||||
#define OPT_AUTHORITATIVE (1<<17)
|
||||
#define OPT_LOCALISE (1<<18)
|
||||
#define OPT_DBUS (1<<19)
|
||||
#define OPT_BOOTP_DYNAMIC (1<<20)
|
||||
#define OPT_NO_PING (1<<21)
|
||||
#define OPT_LEASE_RO (1<<22)
|
||||
#define OPT_ALL_SERVERS (1<<23)
|
||||
#define OPT_RELOAD (1<<24)
|
||||
#define OPT_TFTP (1<<25)
|
||||
#define OPT_TFTP_SECURE (1<<26)
|
||||
#define OPT_TFTP_NOBLOCK (1<<27)
|
||||
#define OPT_LOG_OPTS (1<<28)
|
||||
#define OPT_TFTP_APREF (1<<29)
|
||||
#define OPT_NO_OVERRIDE (1<<30)
|
||||
#define OPT_NO_REBIND (1<<31)
|
||||
#define OPT_BOGUSPRIV (1u<<0)
|
||||
#define OPT_FILTER (1u<<1)
|
||||
#define OPT_LOG (1u<<2)
|
||||
#define OPT_SELFMX (1u<<3)
|
||||
#define OPT_NO_HOSTS (1u<<4)
|
||||
#define OPT_NO_POLL (1u<<5)
|
||||
#define OPT_DEBUG (1u<<6)
|
||||
#define OPT_ORDER (1u<<7)
|
||||
#define OPT_NO_RESOLV (1u<<8)
|
||||
#define OPT_EXPAND (1u<<9)
|
||||
#define OPT_LOCALMX (1u<<10)
|
||||
#define OPT_NO_NEG (1u<<11)
|
||||
#define OPT_NODOTS_LOCAL (1u<<12)
|
||||
#define OPT_NOWILD (1u<<13)
|
||||
#define OPT_ETHERS (1u<<14)
|
||||
#define OPT_RESOLV_DOMAIN (1u<<15)
|
||||
#define OPT_NO_FORK (1u<<16)
|
||||
#define OPT_AUTHORITATIVE (1u<<17)
|
||||
#define OPT_LOCALISE (1u<<18)
|
||||
#define OPT_DBUS (1u<<19)
|
||||
#define OPT_BOOTP_DYNAMIC (1u<<20)
|
||||
#define OPT_NO_PING (1u<<21)
|
||||
#define OPT_LEASE_RO (1u<<22)
|
||||
#define OPT_ALL_SERVERS (1u<<23)
|
||||
#define OPT_RELOAD (1u<<24)
|
||||
#define OPT_TFTP (1u<<25)
|
||||
#define OPT_TFTP_SECURE (1u<<26)
|
||||
#define OPT_TFTP_NOBLOCK (1u<<27)
|
||||
#define OPT_LOG_OPTS (1u<<28)
|
||||
#define OPT_TFTP_APREF (1u<<29)
|
||||
#define OPT_NO_OVERRIDE (1u<<30)
|
||||
#define OPT_NO_REBIND (1u<<31)
|
||||
|
||||
struct all_addr {
|
||||
union {
|
||||
@@ -186,6 +211,12 @@ struct mx_srv_record {
|
||||
struct mx_srv_record *next;
|
||||
};
|
||||
|
||||
struct naptr {
|
||||
char *name, *replace, *regexp, *services, *flags;
|
||||
unsigned int order, pref;
|
||||
struct naptr *next;
|
||||
};
|
||||
|
||||
struct txt_record {
|
||||
char *name, *txt;
|
||||
unsigned short class, len;
|
||||
@@ -286,6 +317,11 @@ struct serverfd {
|
||||
struct serverfd *next;
|
||||
};
|
||||
|
||||
struct randfd {
|
||||
int fd;
|
||||
unsigned short refcount, family;
|
||||
};
|
||||
|
||||
struct server {
|
||||
union mysockaddr addr, source_addr;
|
||||
char interface[IF_NAMESIZE+1];
|
||||
@@ -336,6 +372,10 @@ struct frec {
|
||||
union mysockaddr source;
|
||||
struct all_addr dest;
|
||||
struct server *sentto; /* NULL means free */
|
||||
struct randfd *rfd4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct randfd *rfd6;
|
||||
#endif
|
||||
unsigned int iface;
|
||||
unsigned short orig_id, new_id;
|
||||
int fd, forwardall;
|
||||
@@ -367,7 +407,7 @@ struct dhcp_lease {
|
||||
#endif
|
||||
int hwaddr_len, hwaddr_type;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
struct in_addr addr;
|
||||
struct in_addr addr, override;
|
||||
unsigned char *vendorclass, *userclass;
|
||||
unsigned int vendorclass_len, userclass_len;
|
||||
int last_interface;
|
||||
@@ -455,7 +495,7 @@ struct dhcp_mac {
|
||||
struct dhcp_mac *next;
|
||||
};
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
struct dhcp_bridge {
|
||||
char iface[IF_NAMESIZE];
|
||||
struct dhcp_bridge *alias, *next;
|
||||
@@ -509,9 +549,10 @@ struct tftp_transfer {
|
||||
int sockfd;
|
||||
time_t timeout;
|
||||
int backoff;
|
||||
unsigned int block, blocksize;
|
||||
unsigned int block, blocksize, expansion;
|
||||
off_t offset;
|
||||
struct sockaddr_in peer;
|
||||
char opt_blocksize, opt_transize;
|
||||
char opt_blocksize, opt_transize, netascii, carrylf;
|
||||
struct tftp_file *file;
|
||||
struct tftp_transfer *next;
|
||||
};
|
||||
@@ -524,12 +565,14 @@ extern struct daemon {
|
||||
unsigned int options;
|
||||
struct resolvc default_resolv, *resolv_files;
|
||||
struct mx_srv_record *mxnames;
|
||||
struct naptr *naptr;
|
||||
struct txt_record *txt;
|
||||
struct ptr_record *ptr;
|
||||
struct interface_name *int_names;
|
||||
char *mxtarget;
|
||||
char *lease_file;
|
||||
char *username, *groupname;
|
||||
char *username, *groupname, *scriptuser;
|
||||
int group_set, osport;
|
||||
char *domain_suffix;
|
||||
char *runfile;
|
||||
char *lease_change_command;
|
||||
@@ -540,7 +583,7 @@ extern struct daemon {
|
||||
char *log_file; /* optional log file */
|
||||
int max_logs; /* queue limit */
|
||||
int cachesize, ftabsize;
|
||||
int port, query_port;
|
||||
int port, query_port, min_port;
|
||||
unsigned long local_ttl, neg_ttl;
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp;
|
||||
@@ -552,6 +595,7 @@ extern struct daemon {
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast;
|
||||
char *dhcp_hosts_file, *dhcp_opts_file;
|
||||
int dhcp_max, tftp_max;
|
||||
int dhcp_server_port, dhcp_client_port;
|
||||
int start_tftp_port, end_tftp_port;
|
||||
unsigned int min_leasetime;
|
||||
struct doctor *doctors;
|
||||
@@ -563,6 +607,7 @@ extern struct daemon {
|
||||
int packet_buff_sz; /* size of above */
|
||||
char *namebuff; /* MAXDNAME size buffer */
|
||||
unsigned int local_answer, queries_forwarded;
|
||||
struct frec *frec_list;
|
||||
struct serverfd *sfds;
|
||||
struct irec *interfaces;
|
||||
struct listener *listeners;
|
||||
@@ -570,7 +615,8 @@ extern struct daemon {
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
pid_t tcp_pids[MAX_PROCS];
|
||||
|
||||
struct randfd randomsocks[RANDOM_SOCKS];
|
||||
|
||||
/* DHCP state */
|
||||
int dhcpfd, helperfd;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
@@ -582,7 +628,7 @@ extern struct daemon {
|
||||
char *dhcp_buff, *dhcp_buff2;
|
||||
struct ping_result *ping_results;
|
||||
FILE *lease_stream;
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
struct dhcp_bridge *bridges;
|
||||
#endif
|
||||
|
||||
@@ -600,8 +646,9 @@ extern struct daemon {
|
||||
|
||||
/* cache.c */
|
||||
void cache_init(void);
|
||||
void log_query(unsigned short flags, char *name, struct all_addr *addr,
|
||||
unsigned short type, struct hostsfile *addn_hosts, int index);
|
||||
void log_query(unsigned short flags, char *name, struct all_addr *addr, char *arg);
|
||||
char *record_source(struct hostsfile *addn_hosts, int index);
|
||||
void querystr(char *str, unsigned short type);
|
||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||
struct all_addr *addr, time_t now,
|
||||
unsigned short prot);
|
||||
@@ -636,11 +683,13 @@ size_t resize_packet(HEADER *header, size_t plen,
|
||||
unsigned char *pheader, size_t hlen);
|
||||
|
||||
/* util.c */
|
||||
void rand_init(void);
|
||||
unsigned short rand16(void);
|
||||
int legal_char(char c);
|
||||
int canonicalise(char *s);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
||||
void *safe_malloc(size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
void *whine_malloc(size_t size);
|
||||
int sa_len(union mysockaddr *addr);
|
||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||
@@ -661,7 +710,7 @@ int read_write(int fd, unsigned char *packet, int size, int rw);
|
||||
|
||||
/* log.c */
|
||||
void die(char *message, char *arg1, int exit_code);
|
||||
void log_start(struct passwd *ent_pw);
|
||||
int log_start(struct passwd *ent_pw, int errfd);
|
||||
int log_reopen(char *log_file);
|
||||
void my_syslog(int priority, const char *format, ...);
|
||||
void set_log_writer(fd_set *set, int *maxfdp);
|
||||
@@ -674,7 +723,7 @@ char *option_string(unsigned char opt);
|
||||
void reread_dhcp(void);
|
||||
|
||||
/* forward.c */
|
||||
void reply_query(struct serverfd *sfd, time_t now);
|
||||
void reply_query(int fd, int family, time_t now);
|
||||
void receive_query(struct listener *listen, time_t now);
|
||||
unsigned char *tcp_request(int confd, time_t now,
|
||||
struct in_addr local_addr, struct in_addr netmask);
|
||||
@@ -683,6 +732,7 @@ struct frec *get_new_frec(time_t now, int *wait);
|
||||
|
||||
/* network.c */
|
||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
|
||||
int random_sock(int family);
|
||||
void pre_allocate_sfds(void);
|
||||
int reload_servers(char *fname);
|
||||
void check_servers(void);
|
||||
@@ -779,7 +829,7 @@ void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
|
||||
|
||||
/* helper.c */
|
||||
#ifndef NO_FORK
|
||||
int create_helper(int log_fd, long max_fd);
|
||||
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
|
||||
void helper_write(void);
|
||||
void queue_script(int action, struct dhcp_lease *lease,
|
||||
char *hostname, time_t now);
|
||||
|
||||
297
src/forward.c
297
src/forward.c
@@ -16,14 +16,13 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
static struct frec *frec_list = NULL;
|
||||
|
||||
static struct frec *lookup_frec(unsigned short id, unsigned int crc);
|
||||
static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
union mysockaddr *addr,
|
||||
unsigned int crc);
|
||||
static unsigned short get_id(int force, unsigned short force_id, unsigned int crc);
|
||||
|
||||
static void free_frec(struct frec *f);
|
||||
static struct randfd *allocate_rfd(int family);
|
||||
|
||||
/* Send a UDP packet with its source address set as "source"
|
||||
unless nowild is true, when we just send it with the kernel default */
|
||||
@@ -196,7 +195,7 @@ static unsigned short search_servers(time_t now, struct all_addr **addrpp,
|
||||
if (flags == F_NXDOMAIN || flags == F_NOERR)
|
||||
logflags = F_NEG | qtype;
|
||||
|
||||
log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, 0, NULL, 0);
|
||||
log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
|
||||
}
|
||||
|
||||
return flags;
|
||||
@@ -290,7 +289,32 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
(type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
|
||||
!(start->flags & SERV_LITERAL_ADDRESS))
|
||||
{
|
||||
if (sendto(start->sfd->fd, (char *)header, plen, 0,
|
||||
int fd;
|
||||
|
||||
/* find server socket to use, may need to get random one. */
|
||||
if (start->sfd)
|
||||
fd = start->sfd->fd;
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
if (start->addr.sa.sa_family == AF_INET6)
|
||||
{
|
||||
if (!forward->rfd6 &&
|
||||
!(forward->rfd6 = allocate_rfd(AF_INET6)))
|
||||
break;
|
||||
fd = forward->rfd6->fd;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!forward->rfd4 &&
|
||||
!(forward->rfd4 = allocate_rfd(AF_INET)))
|
||||
break;
|
||||
fd = forward->rfd4->fd;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendto(fd, (char *)header, plen, 0,
|
||||
&start->addr.sa,
|
||||
sa_len(&start->addr)) == -1)
|
||||
{
|
||||
@@ -307,13 +331,11 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
strcpy(daemon->namebuff, "query");
|
||||
if (start->addr.sa.sa_family == AF_INET)
|
||||
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&start->addr.in.sin_addr, 0,
|
||||
NULL, 0);
|
||||
(struct all_addr *)&start->addr.in.sin_addr, NULL);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&start->addr.in6.sin6_addr, 0,
|
||||
NULL, 0);
|
||||
(struct all_addr *)&start->addr.in6.sin6_addr, NULL);
|
||||
#endif
|
||||
start->queries++;
|
||||
forwarded = 1;
|
||||
@@ -336,7 +358,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
|
||||
/* could not send on, prepare to return */
|
||||
header->id = htons(forward->orig_id);
|
||||
forward->sentto = NULL; /* cancel */
|
||||
free_frec(forward); /* cancel */
|
||||
}
|
||||
|
||||
/* could not send on, return empty answer or address if known for whole domain */
|
||||
@@ -428,7 +450,7 @@ static size_t process_reply(HEADER *header, time_t now,
|
||||
}
|
||||
|
||||
/* sets new last_server */
|
||||
void reply_query(struct serverfd *sfd, time_t now)
|
||||
void reply_query(int fd, int family, time_t now)
|
||||
{
|
||||
/* packet from peer server, extract data for cache, and send to
|
||||
original requester */
|
||||
@@ -436,91 +458,101 @@ void reply_query(struct serverfd *sfd, time_t now)
|
||||
union mysockaddr serveraddr;
|
||||
struct frec *forward;
|
||||
socklen_t addrlen = sizeof(serveraddr);
|
||||
ssize_t n = recvfrom(sfd->fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
|
||||
ssize_t n = recvfrom(fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
|
||||
size_t nn;
|
||||
|
||||
struct server *server;
|
||||
|
||||
/* packet buffer overwritten */
|
||||
daemon->srv_save = NULL;
|
||||
|
||||
/* Determine the address of the server replying so that we can mark that as good */
|
||||
serveraddr.sa.sa_family = sfd->source_addr.sa.sa_family;
|
||||
serveraddr.sa.sa_family = family;
|
||||
#ifdef HAVE_IPV6
|
||||
if (serveraddr.sa.sa_family == AF_INET6)
|
||||
serveraddr.in6.sin6_flowinfo = 0;
|
||||
#endif
|
||||
|
||||
/* spoof check: answer must come from known server, */
|
||||
for (server = daemon->servers; server; server = server->next)
|
||||
if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
|
||||
sockaddr_isequal(&server->addr, &serveraddr))
|
||||
break;
|
||||
|
||||
header = (HEADER *)daemon->packet;
|
||||
|
||||
if (n >= (int)sizeof(HEADER) && header->qr &&
|
||||
(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
|
||||
if (!server ||
|
||||
n < (int)sizeof(HEADER) || !header->qr ||
|
||||
!(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
|
||||
return;
|
||||
|
||||
server = forward->sentto;
|
||||
|
||||
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
|
||||
!(daemon->options & OPT_ORDER) &&
|
||||
forward->forwardall == 0)
|
||||
/* for broken servers, attempt to send to another one. */
|
||||
{
|
||||
struct server *server = forward->sentto;
|
||||
unsigned char *pheader;
|
||||
size_t plen;
|
||||
int is_sign;
|
||||
|
||||
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
|
||||
!(daemon->options & OPT_ORDER) &&
|
||||
forward->forwardall == 0)
|
||||
/* for broken servers, attempt to send to another one. */
|
||||
/* recreate query from reply */
|
||||
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
|
||||
if (!is_sign)
|
||||
{
|
||||
unsigned char *pheader;
|
||||
size_t plen;
|
||||
int is_sign;
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
|
||||
{
|
||||
header->qr = 0;
|
||||
header->tc = 0;
|
||||
forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((forward->sentto->flags & SERV_TYPE) == 0)
|
||||
{
|
||||
if (header->rcode == SERVFAIL || header->rcode == REFUSED)
|
||||
server = NULL;
|
||||
else
|
||||
{
|
||||
struct server *last_server;
|
||||
|
||||
/* recreate query from reply */
|
||||
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
|
||||
if (!is_sign)
|
||||
{
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
|
||||
{
|
||||
header->qr = 0;
|
||||
header->tc = 0;
|
||||
forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((forward->sentto->flags & SERV_TYPE) == 0)
|
||||
/* find good server by address if possible, otherwise assume the last one we sent to */
|
||||
for (last_server = daemon->servers; last_server; last_server = last_server->next)
|
||||
if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
|
||||
sockaddr_isequal(&last_server->addr, &serveraddr))
|
||||
{
|
||||
server = last_server;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(daemon->options & OPT_ALL_SERVERS))
|
||||
daemon->last_server = server;
|
||||
}
|
||||
|
||||
/* If the answer is an error, keep the forward record in place in case
|
||||
we get a good reply from another server. Kill it when we've
|
||||
had replies from all to avoid filling the forwarding table when
|
||||
everything is broken */
|
||||
if (forward->forwardall == 0 || --forward->forwardall == 1 ||
|
||||
(header->rcode != REFUSED && header->rcode != SERVFAIL))
|
||||
{
|
||||
if ((nn = process_reply(header, now, server, (size_t)n)))
|
||||
{
|
||||
if (header->rcode == SERVFAIL || header->rcode == REFUSED)
|
||||
server = NULL;
|
||||
else
|
||||
{
|
||||
struct server *last_server;
|
||||
/* find good server by address if possible, otherwise assume the last one we sent to */
|
||||
for (last_server = daemon->servers; last_server; last_server = last_server->next)
|
||||
if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
|
||||
sockaddr_isequal(&last_server->addr, &serveraddr))
|
||||
{
|
||||
server = last_server;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(daemon->options & OPT_ALL_SERVERS))
|
||||
daemon->last_server = server;
|
||||
}
|
||||
|
||||
/* If the answer is an error, keep the forward record in place in case
|
||||
we get a good reply from another server. Kill it when we've
|
||||
had replies from all to avoid filling the forwarding table when
|
||||
everything is broken */
|
||||
if (forward->forwardall == 0 || --forward->forwardall == 1 ||
|
||||
(header->rcode != REFUSED && header->rcode != SERVFAIL))
|
||||
{
|
||||
if ((nn = process_reply(header, now, server, (size_t)n)))
|
||||
{
|
||||
header->id = htons(forward->orig_id);
|
||||
header->ra = 1; /* recursion if available */
|
||||
send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn,
|
||||
&forward->source, &forward->dest, forward->iface);
|
||||
}
|
||||
forward->sentto = NULL; /* cancel */
|
||||
header->id = htons(forward->orig_id);
|
||||
header->ra = 1; /* recursion if available */
|
||||
send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn,
|
||||
&forward->source, &forward->dest, forward->iface);
|
||||
}
|
||||
free_frec(forward); /* cancel */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void receive_query(struct listener *listen, time_t now)
|
||||
{
|
||||
HEADER *header = (HEADER *)daemon->packet;
|
||||
@@ -658,13 +690,17 @@ void receive_query(struct listener *listen, time_t now)
|
||||
|
||||
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
|
||||
{
|
||||
char types[20];
|
||||
|
||||
querystr(types, type);
|
||||
|
||||
if (listen->family == AF_INET)
|
||||
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&source_addr.in.sin_addr, type, NULL, 0);
|
||||
(struct all_addr *)&source_addr.in.sin_addr, types);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&source_addr.in6.sin6_addr, type, NULL, 0);
|
||||
(struct all_addr *)&source_addr.in6.sin6_addr, types);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -719,13 +755,17 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
|
||||
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1)
|
||||
{
|
||||
char types[20];
|
||||
|
||||
querystr(types, qtype);
|
||||
|
||||
if (peer_addr.sa.sa_family == AF_INET)
|
||||
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&peer_addr.in.sin_addr, qtype, NULL, 0);
|
||||
(struct all_addr *)&peer_addr.in.sin_addr, types);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&peer_addr.in6.sin6_addr, qtype, NULL, 0);
|
||||
(struct all_addr *)&peer_addr.in6.sin6_addr, types);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -812,11 +852,11 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
strcpy(daemon->namebuff, "query");
|
||||
if (last_server->addr.sa.sa_family == AF_INET)
|
||||
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&last_server->addr.in.sin_addr, 0, NULL, 0);
|
||||
(struct all_addr *)&last_server->addr.in.sin_addr, NULL);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||
(struct all_addr *)&last_server->addr.in6.sin6_addr, 0, NULL, 0);
|
||||
(struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
|
||||
#endif
|
||||
|
||||
/* There's no point in updating the cache, since this process will exit and
|
||||
@@ -854,34 +894,99 @@ static struct frec *allocate_frec(time_t now)
|
||||
|
||||
if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
|
||||
{
|
||||
f->next = frec_list;
|
||||
f->next = daemon->frec_list;
|
||||
f->time = now;
|
||||
f->sentto = NULL;
|
||||
frec_list = f;
|
||||
f->rfd4 = NULL;
|
||||
#ifdef HAVE_IPV6
|
||||
f->rfd6 = NULL;
|
||||
#endif
|
||||
daemon->frec_list = f;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static struct randfd *allocate_rfd(int family)
|
||||
{
|
||||
static int finger = 0;
|
||||
int i;
|
||||
|
||||
/* limit the number of sockets we have open to avoid starvation of
|
||||
(eg) TFTP. Once we have a reasonable number, randomness should be OK */
|
||||
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
if (daemon->randomsocks[i].refcount == 0 &&
|
||||
(daemon->randomsocks[i].fd = random_sock(family)) != -1)
|
||||
{
|
||||
daemon->randomsocks[i].refcount = 1;
|
||||
daemon->randomsocks[i].family = family;
|
||||
return &daemon->randomsocks[i];
|
||||
}
|
||||
|
||||
/* No free ones, grab an existing one */
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
{
|
||||
int j = (i+finger) % RANDOM_SOCKS;
|
||||
if (daemon->randomsocks[j].family == family && daemon->randomsocks[j].refcount != 0xffff)
|
||||
{
|
||||
finger = j;
|
||||
daemon->randomsocks[j].refcount++;
|
||||
return &daemon->randomsocks[j];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* doom */
|
||||
}
|
||||
|
||||
static void free_frec(struct frec *f)
|
||||
{
|
||||
if (f->rfd4 && --(f->rfd4->refcount) == 0)
|
||||
close(f->rfd4->fd);
|
||||
|
||||
f->rfd4 = NULL;
|
||||
f->sentto = NULL;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (f->rfd6 && --(f->rfd6->refcount) == 0)
|
||||
close(f->rfd6->fd);
|
||||
|
||||
f->rfd6 = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* if wait==NULL return a free or older than TIMEOUT record.
|
||||
else return *wait zero if one available, or *wait is delay to
|
||||
when the oldest in-use record will expire. */
|
||||
when the oldest in-use record will expire. Impose an absolute
|
||||
limit of 4*TIMEOUT before we wipe things (for random sockets) */
|
||||
struct frec *get_new_frec(time_t now, int *wait)
|
||||
{
|
||||
struct frec *f, *oldest;
|
||||
struct frec *f, *oldest, *target;
|
||||
int count;
|
||||
|
||||
if (wait)
|
||||
*wait = 0;
|
||||
|
||||
for (f = frec_list, oldest = NULL, count = 0; f; f = f->next, count++)
|
||||
for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
|
||||
if (!f->sentto)
|
||||
target = f;
|
||||
else
|
||||
{
|
||||
f->time = now;
|
||||
return f;
|
||||
if (difftime(now, f->time) >= 4*TIMEOUT)
|
||||
{
|
||||
free_frec(f);
|
||||
target = f;
|
||||
}
|
||||
|
||||
if (!oldest || difftime(f->time, oldest->time) <= 0)
|
||||
oldest = f;
|
||||
}
|
||||
else if (!oldest || difftime(f->time, oldest->time) <= 0)
|
||||
oldest = f;
|
||||
|
||||
if (target)
|
||||
{
|
||||
target->time = now;
|
||||
return target;
|
||||
}
|
||||
|
||||
/* can't find empty one, use oldest if there is one
|
||||
and it's older than timeout */
|
||||
@@ -896,7 +1001,7 @@ struct frec *get_new_frec(time_t now, int *wait)
|
||||
|
||||
if (!wait)
|
||||
{
|
||||
oldest->sentto = 0;
|
||||
free_frec(oldest);
|
||||
oldest->time = now;
|
||||
}
|
||||
return oldest;
|
||||
@@ -922,7 +1027,7 @@ static struct frec *lookup_frec(unsigned short id, unsigned int crc)
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for(f = frec_list; f; f = f->next)
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto && f->new_id == id &&
|
||||
(f->crc == crc || crc == 0xffffffff))
|
||||
return f;
|
||||
@@ -936,7 +1041,7 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for(f = frec_list; f; f = f->next)
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto &&
|
||||
f->orig_id == id &&
|
||||
f->crc == crc &&
|
||||
@@ -951,9 +1056,9 @@ void server_gone(struct server *server)
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for (f = frec_list; f; f = f->next)
|
||||
for (f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto && f->sentto == server)
|
||||
f->sentto = NULL;
|
||||
free_frec(f);
|
||||
|
||||
if (daemon->last_server == server)
|
||||
daemon->last_server = NULL;
|
||||
@@ -974,7 +1079,7 @@ static unsigned short get_id(int force, unsigned short force_id, unsigned int cr
|
||||
{
|
||||
struct frec *f = lookup_frec(force_id, crc);
|
||||
if (f)
|
||||
f->sentto = NULL; /* free */
|
||||
free_frec(f); /* free */
|
||||
ret = force_id;
|
||||
}
|
||||
else do
|
||||
|
||||
36
src/helper.c
36
src/helper.c
@@ -50,22 +50,18 @@ struct script_data
|
||||
static struct script_data *buf = NULL;
|
||||
static size_t bytes_in_buf = 0, buf_size = 0;
|
||||
|
||||
int create_helper(int event_fd, long max_fd)
|
||||
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
{
|
||||
pid_t pid;
|
||||
int i, pipefd[2];
|
||||
struct sigaction sigact;
|
||||
|
||||
if (!daemon->dhcp || !daemon->lease_change_command)
|
||||
return -1;
|
||||
|
||||
/* create the pipe through which the main program sends us commands,
|
||||
then fork our process. By now it's too late to die(), we just log
|
||||
any failure via the main process. */
|
||||
then fork our process. */
|
||||
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
|
||||
{
|
||||
send_event(event_fd, EVENT_PIPE_ERR, errno);
|
||||
return -1;
|
||||
send_event(err_fd, EVENT_PIPE_ERR, errno);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (pid != 0)
|
||||
@@ -82,7 +78,29 @@ int create_helper(int event_fd, long max_fd)
|
||||
sigaction(SIGTERM, &sigact, NULL);
|
||||
sigaction(SIGALRM, &sigact, NULL);
|
||||
|
||||
/* close all the sockets etc, we don't need them here */
|
||||
if (!(daemon->options & OPT_DEBUG) && uid != 0)
|
||||
{
|
||||
gid_t dummy;
|
||||
if (setgroups(0, &dummy) == -1 ||
|
||||
setgid(gid) == -1 ||
|
||||
setuid(uid) == -1)
|
||||
{
|
||||
if (daemon->options & OPT_NO_FORK)
|
||||
/* send error to daemon process if no-fork */
|
||||
send_event(event_fd, EVENT_HUSER_ERR, errno);
|
||||
else
|
||||
{
|
||||
/* kill daemon */
|
||||
send_event(event_fd, EVENT_DIE, 0);
|
||||
/* return error */
|
||||
send_event(err_fd, EVENT_HUSER_ERR, errno);;
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* close all the sockets etc, we don't need them here. This closes err_fd, so that
|
||||
main process can return. */
|
||||
for (max_fd--; max_fd > 0; max_fd--)
|
||||
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO &&
|
||||
max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_fd)
|
||||
|
||||
18
src/log.c
18
src/log.c
@@ -50,8 +50,10 @@ static struct log_entry *entries = NULL;
|
||||
static struct log_entry *free_entries = NULL;
|
||||
|
||||
|
||||
void log_start(struct passwd *ent_pw)
|
||||
int log_start(struct passwd *ent_pw, int errfd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
log_stderr = !!(daemon->options & OPT_DEBUG);
|
||||
|
||||
if (daemon->log_fac != -1)
|
||||
@@ -70,8 +72,11 @@ void log_start(struct passwd *ent_pw)
|
||||
max_logs = daemon->max_logs;
|
||||
|
||||
if (!log_reopen(daemon->log_file))
|
||||
die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
|
||||
|
||||
{
|
||||
send_event(errfd, EVENT_LOG_ERR, errno);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/* if queuing is inhibited, make sure we allocate
|
||||
the one required buffer now. */
|
||||
if (max_logs == 0)
|
||||
@@ -85,8 +90,11 @@ void log_start(struct passwd *ent_pw)
|
||||
change the ownership here so that the file is always owned by
|
||||
the dnsmasq user. Then logrotate can just copy the owner.
|
||||
Failure of the chown call is OK, (for instance when started as non-root) */
|
||||
if (log_to_file && ent_pw && ent_pw->pw_uid != 0 && fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), daemon->log_file, strerror(errno));
|
||||
if (log_to_file && ent_pw && ent_pw->pw_uid != 0 &&
|
||||
fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
ret = errno;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_reopen(char *log_file)
|
||||
|
||||
@@ -27,8 +27,8 @@ int iface_check(int family, struct all_addr *addr,
|
||||
|
||||
if (indexp)
|
||||
{
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
/* One form of bridging on FreeBSD has the property that packets
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
/* One form of bridging on BSD has the property that packets
|
||||
can be recieved on bridge interfaces which do not have an IP address.
|
||||
We allow these to be treated as aliases of another interface which does have
|
||||
an IP address with --dhcp-bridge=interface,alias,alias */
|
||||
@@ -441,6 +441,61 @@ struct listener *create_bound_listeners(void)
|
||||
return listeners;
|
||||
}
|
||||
|
||||
|
||||
/* return a UDP socket bound to a random port, have to coper with straying into
|
||||
occupied port nos and reserved ones. */
|
||||
int random_sock(int family)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.in.sin_family = family;
|
||||
|
||||
if (fix_fd(fd))
|
||||
while (1)
|
||||
{
|
||||
unsigned short port = rand16();
|
||||
|
||||
if (port <= (unsigned short) daemon->min_port)
|
||||
continue;
|
||||
|
||||
if (family == AF_INET)
|
||||
{
|
||||
addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.in.sin_port = htons(port);
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
addr.in6.sin6_addr = in6addr_any;
|
||||
addr.in6.sin6_port = htons(port);
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
|
||||
return fd;
|
||||
|
||||
if (errno != EADDRINUSE && errno != EACCES)
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
||||
{
|
||||
union mysockaddr addr_copy = *addr;
|
||||
@@ -473,6 +528,25 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
struct serverfd *sfd;
|
||||
int errsave;
|
||||
|
||||
/* when using random ports, servers which would otherwise use
|
||||
the INADDR_ANY/port0 socket have sfd set to NULL */
|
||||
if (!daemon->osport)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
if (addr->sa.sa_family == AF_INET &&
|
||||
addr->in.sin_addr.s_addr == INADDR_ANY &&
|
||||
addr->in.sin_port == htons(0))
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (addr->sa.sa_family == AF_INET6 &&
|
||||
memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
|
||||
addr->in6.sin6_port == htons(0))
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* may have a suitable one already */
|
||||
for (sfd = daemon->sfds; sfd; sfd = sfd->next )
|
||||
if (sockaddr_isequal(&sfd->source_addr, addr) &&
|
||||
@@ -538,6 +612,7 @@ void pre_allocate_sfds(void)
|
||||
for (srv = daemon->servers; srv; srv = srv->next)
|
||||
if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
|
||||
!allocate_sfd(&srv->source_addr, srv->interface) &&
|
||||
errno != 0 &&
|
||||
(daemon->options & OPT_NOWILD))
|
||||
{
|
||||
prettyprint_addr(&srv->addr, daemon->namebuff);
|
||||
@@ -585,7 +660,9 @@ void check_servers(void)
|
||||
}
|
||||
|
||||
/* Do we need a socket set? */
|
||||
if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, new->interface)))
|
||||
if (!new->sfd &&
|
||||
!(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
|
||||
errno != 0)
|
||||
{
|
||||
my_syslog(LOG_WARNING,
|
||||
_("ignoring nameserver %s - cannot make/bind socket: %s"),
|
||||
|
||||
397
src/option.c
397
src/option.c
@@ -91,6 +91,11 @@ struct myoption {
|
||||
#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
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -128,7 +133,7 @@ static const struct myoption opts[] =
|
||||
{"pid-file", 2, 0, 'x'},
|
||||
{"strict-order", 0, 0, 'o'},
|
||||
{"server", 1, 0, 'S'},
|
||||
{"local", 1, 0, 'S' },
|
||||
{"local", 1, 0, LOPT_LOCAL },
|
||||
{"address", 1, 0, 'A' },
|
||||
{"conf-file", 2, 0, 'C'},
|
||||
{"no-resolv", 0, 0, 'R'},
|
||||
@@ -171,7 +176,8 @@ static const struct myoption opts[] =
|
||||
{"tftp-root", 1, 0, LOPT_PREFIX },
|
||||
{"tftp-max", 1, 0, LOPT_TFTP_MAX },
|
||||
{"ptr-record", 1, 0, LOPT_PTR },
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
{"naptr-record", 1, 0, LOPT_NAPTR },
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{"bridge-interface", 1, 0 , LOPT_BRIDGE },
|
||||
#endif
|
||||
{"dhcp-option-force", 1, 0, LOPT_FORCE },
|
||||
@@ -191,148 +197,121 @@ static const struct myoption opts[] =
|
||||
{"dhcp-match", 1, 0, LOPT_MATCH },
|
||||
{"dhcp-broadcast", 1, 0, LOPT_BROADCAST },
|
||||
{"neg-ttl", 1, 0, LOPT_NEGTTL },
|
||||
{"dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
|
||||
{"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
|
||||
{"min-port", 1, 0, LOPT_MINPORT },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
struct optflags {
|
||||
int c;
|
||||
unsigned int flag;
|
||||
};
|
||||
/* These must have more the one '1' bit */
|
||||
#define ARG_DUP 3
|
||||
#define ARG_ONE 5
|
||||
#define ARG_USED_CL 7
|
||||
#define ARG_USED_FILE 9
|
||||
|
||||
static const struct optflags optmap[] = {
|
||||
{ 'b', OPT_BOGUSPRIV },
|
||||
{ 'f', OPT_FILTER },
|
||||
{ 'q', OPT_LOG },
|
||||
{ 'e', OPT_SELFMX },
|
||||
{ 'h', OPT_NO_HOSTS },
|
||||
{ 'n', OPT_NO_POLL },
|
||||
{ 'd', OPT_DEBUG },
|
||||
{ 'k', OPT_NO_FORK },
|
||||
{ 'K', OPT_AUTHORITATIVE },
|
||||
{ 'o', OPT_ORDER },
|
||||
{ 'R', OPT_NO_RESOLV },
|
||||
{ 'E', OPT_EXPAND },
|
||||
{ 'L', OPT_LOCALMX },
|
||||
{ 'N', OPT_NO_NEG },
|
||||
{ 'D', OPT_NODOTS_LOCAL },
|
||||
{ 'z', OPT_NOWILD },
|
||||
{ 'Z', OPT_ETHERS },
|
||||
{ 'y', OPT_LOCALISE },
|
||||
{ '1', OPT_DBUS },
|
||||
{ '3', OPT_BOOTP_DYNAMIC },
|
||||
{ '5', OPT_NO_PING },
|
||||
{ '9', OPT_LEASE_RO },
|
||||
{ LOPT_RELOAD, OPT_RELOAD },
|
||||
{ LOPT_TFTP, OPT_TFTP },
|
||||
{ LOPT_SECURE, OPT_TFTP_SECURE },
|
||||
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK },
|
||||
{ LOPT_LOG_OPTS, OPT_LOG_OPTS },
|
||||
{ LOPT_APREF, OPT_TFTP_APREF },
|
||||
{ LOPT_OVERRIDE, OPT_NO_OVERRIDE },
|
||||
{ LOPT_REBIND, OPT_NO_REBIND },
|
||||
{ LOPT_NOLAST, OPT_ALL_SERVERS },
|
||||
{ 'v', 0},
|
||||
{ 'w', 0},
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char * const flag;
|
||||
static struct {
|
||||
int opt;
|
||||
unsigned int rept;
|
||||
char * const flagdesc;
|
||||
char * const desc;
|
||||
char * const arg;
|
||||
} usage[] = {
|
||||
{ "-a, --listen-address=ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL },
|
||||
{ "-A, --address=/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
|
||||
{ "-b, --bogus-priv", gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
|
||||
{ "-B, --bogus-nxdomain=ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
|
||||
{ "-c, --cache-size=cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
|
||||
{ "-C, --conf-file=path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
|
||||
{ "-d, --no-daemon", gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
|
||||
{ "-D, --domain-needed", gettext_noop("Do NOT forward queries with no domain part."), NULL },
|
||||
{ "-e, --selfmx", gettext_noop("Return self-pointing MX records for local hosts."), NULL },
|
||||
{ "-E, --expand-hosts", gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
|
||||
{ "-f, --filterwin2k", gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
|
||||
{ "-F, --dhcp-range=ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
|
||||
{ "-g, --group=groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
|
||||
{ "-G, --dhcp-host=<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
|
||||
{ " --dhcp-hostsfile=<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
|
||||
{ " --dhcp-optsfile=<filename>", gettext_noop("Read DHCP option specs from file"), NULL },
|
||||
{ "-h, --no-hosts", gettext_noop("Do NOT load %s file."), HOSTSFILE },
|
||||
{ "-H, --addn-hosts=path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
|
||||
{ "-i, --interface=interface", gettext_noop("Specify interface(s) to listen on."), NULL },
|
||||
{ "-I, --except-interface=int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
|
||||
{ "-j, --dhcp-userclass=<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
|
||||
{ " --dhcp-circuitid=<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
|
||||
{ " --dhcp-remoteid=<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
|
||||
{ " --dhcp-subscrid=<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
|
||||
{ "-J, --dhcp-ignore=<tag>", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
|
||||
{ " --dhcp-broadcast=<tag>", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
|
||||
{ "-k, --keep-in-foreground", gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
|
||||
{ "-K, --dhcp-authoritative", gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
|
||||
{ "-l, --dhcp-leasefile=path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
|
||||
{ "-L, --localmx", gettext_noop("Return MX records for local hosts."), NULL },
|
||||
{ "-m, --mx-host=host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
|
||||
{ "-M, --dhcp-boot=<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
|
||||
{ "-n, --no-poll", gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
|
||||
{ "-N, --no-negcache", gettext_noop("Do NOT cache failed search results."), NULL },
|
||||
{ "-o, --strict-order", gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
|
||||
{ "-O, --dhcp-option=<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
|
||||
{ " --dhcp-option-force=<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
|
||||
{ "-p, --port=number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
|
||||
{ "-P, --edns-packet-max=<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
|
||||
{ "-q, --log-queries", gettext_noop("Log DNS queries."), NULL },
|
||||
{ "-Q, --query-port=number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
|
||||
{ "-R, --no-resolv", gettext_noop("Do NOT read resolv.conf."), NULL },
|
||||
{ "-r, --resolv-file=path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
|
||||
{ "-S, --server=/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
|
||||
{ " --local=/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
|
||||
{ "-s, --domain=domain", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
|
||||
{ "-t, --mx-target=host_name", gettext_noop("Specify default target in an MX record."), NULL },
|
||||
{ "-T, --local-ttl=time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
|
||||
{ " --neg-ttl=time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
|
||||
{ "-u, --user=username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
|
||||
{ "-U, --dhcp-vendorclass=<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
|
||||
{ "-v, --version", gettext_noop("Display dnsmasq version and copyright information."), NULL },
|
||||
{ "-V, --alias=addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
|
||||
{ "-W, --srv-host=name,target,...", gettext_noop("Specify a SRV record."), NULL },
|
||||
{ "-w, --help", gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
|
||||
{ "-x, --pid-file=path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
|
||||
{ "-X, --dhcp-lease-max=number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
|
||||
{ "-y, --localise-queries", gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
|
||||
{ "-Y --txt-record=name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
|
||||
{ " --ptr-record=name,target", gettext_noop("Specify PTR DNS record."), NULL },
|
||||
{ " --interface-name=name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
|
||||
{ "-z, --bind-interfaces", gettext_noop("Bind only to interfaces in use."), NULL },
|
||||
{ "-Z, --read-ethers", gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
|
||||
{ "-1, --enable-dbus", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
|
||||
{ "-2, --no-dhcp-interface=interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ "-3, --bootp-dynamic", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ "-4, --dhcp-mac=<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
{ " --bridge-interface=iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
|
||||
{ 'a', ARG_DUP, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL },
|
||||
{ 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
|
||||
{ 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
|
||||
{ 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL },
|
||||
{ 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
|
||||
{ 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
|
||||
{ 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
|
||||
{ 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL },
|
||||
{ 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
|
||||
{ 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
|
||||
{ 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
|
||||
{ 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
|
||||
{ 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
|
||||
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
|
||||
{ LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
|
||||
{ LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL },
|
||||
{ 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
|
||||
{ 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
|
||||
{ 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
|
||||
{ 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
|
||||
{ 'j', ARG_DUP, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
|
||||
{ LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
|
||||
{ LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
|
||||
{ LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
|
||||
{ 'J', ARG_DUP, "<tag>", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
|
||||
{ LOPT_BROADCAST, ARG_DUP, "<tag>", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
|
||||
{ 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
|
||||
{ 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
|
||||
{ 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
|
||||
{ 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
|
||||
{ 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
|
||||
{ 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
|
||||
{ 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
|
||||
{ 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
|
||||
{ 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
|
||||
{ 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
|
||||
{ LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
|
||||
{ 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
|
||||
{ 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
|
||||
{ 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
|
||||
{ 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
|
||||
{ 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
|
||||
{ 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
|
||||
{ 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
|
||||
{ LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
|
||||
{ 's', ARG_ONE, "<domain>", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
|
||||
{ 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
|
||||
{ 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
|
||||
{ LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
|
||||
{ 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
|
||||
{ 'U', ARG_DUP, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
|
||||
{ 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
|
||||
{ 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
|
||||
{ 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
|
||||
{ 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
|
||||
{ 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
|
||||
{ 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
|
||||
{ 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
|
||||
{ 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
|
||||
{ LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL },
|
||||
{ LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
|
||||
{ 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
|
||||
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
|
||||
{ '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
|
||||
{ '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ '3', OPT_BOOTP_DYNAMIC, NULL, gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{ LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
|
||||
#endif
|
||||
{ "-5, --no-ping", gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
|
||||
{ "-6, --dhcp-script=path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
|
||||
{ "-7, --conf-dir=path", gettext_noop("Read configuration from all the files in this directory."), NULL },
|
||||
{ "-8, --log-facility=facilty|file", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
|
||||
{ "-9, --leasefile-ro", gettext_noop("Read leases at startup, but never write the lease file."), NULL },
|
||||
{ "-0, --dns-forward-max=<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
|
||||
{ " --clear-on-reload", gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
|
||||
{ " --dhcp-ignore-names[=<id>]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
|
||||
{ " --dhcp-no-override", gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
|
||||
{ " --enable-tftp", gettext_noop("Enable integrated read-only TFTP server."), NULL },
|
||||
{ " --tftp-root=<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
|
||||
{ " --tftp-unique-root", gettext_noop("Add client IP address to tftp-root."), NULL },
|
||||
{ " --tftp-secure", gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
|
||||
{ " --tftp-max=<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
|
||||
{ " --tftp-no-blocksize", gettext_noop("Disable the TFTP blocksize extension."), NULL },
|
||||
{ " --tftp-port-range=<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
|
||||
{ " --log-dhcp", gettext_noop("Extra logging for DHCP."), NULL },
|
||||
{ " --log-async[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
|
||||
{ " --stop-dns-rebind", gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
|
||||
{ " --all-servers", gettext_noop("Always perform DNS queries to all servers."), NULL },
|
||||
{ " --dhcp-match=<netid>,<opt-no>", gettext_noop("Set tag if client includes option in request."), NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
{ '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
|
||||
{ '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
|
||||
{ '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
|
||||
{ '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
|
||||
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
|
||||
{ '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
|
||||
{ LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
|
||||
{ LOPT_NO_NAMES, ARG_DUP, "[=<id>]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
|
||||
{ LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
|
||||
{ LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
|
||||
{ LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
|
||||
{ LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
|
||||
{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
|
||||
{ LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
|
||||
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
|
||||
{ LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
|
||||
{ LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
|
||||
{ LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
|
||||
{ LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
|
||||
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
|
||||
{ LOPT_MATCH, ARG_DUP, "<netid>,<opt-no>", gettext_noop("Set tag if client includes option in request."), NULL },
|
||||
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
|
||||
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
|
||||
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
|
||||
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* makes options which take a list of addresses */
|
||||
@@ -396,8 +375,8 @@ static const struct {
|
||||
{ "client-id", 61,OT_INTERNAL },
|
||||
{ "nis-domain", 64, 0 },
|
||||
{ "nis-server", 65, OT_ADDR_LIST },
|
||||
{ "tftp-server", 66, OT_INTERNAL },
|
||||
{ "bootfile-name", 67, OT_INTERNAL },
|
||||
{ "tftp-server", 66, 0 },
|
||||
{ "bootfile-name", 67, 0 },
|
||||
{ "mobile-ip-home", 68, OT_ADDR_LIST },
|
||||
{ "smtp-server", 69, OT_ADDR_LIST },
|
||||
{ "pop3-server", 70, OT_ADDR_LIST },
|
||||
@@ -586,10 +565,30 @@ static void do_usage(void)
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
printf(_("Use short options only on the command line.\n"));
|
||||
#endif
|
||||
printf(_("Valid options are :\n"));
|
||||
printf(_("Valid options are:\n"));
|
||||
|
||||
for (i = 0; usage[i].flag; i++)
|
||||
for (i = 0; usage[i].opt != 0; i++)
|
||||
{
|
||||
char *desc = usage[i].flagdesc;
|
||||
char *eq = "=";
|
||||
|
||||
if (!desc || *desc == '[')
|
||||
eq = "";
|
||||
|
||||
if (!desc)
|
||||
desc = "";
|
||||
|
||||
for ( j = 0; opts[j].name; j++)
|
||||
if (opts[j].val == usage[i].opt)
|
||||
break;
|
||||
if (usage[i].opt < 256)
|
||||
sprintf(buff, "-%c, ", usage[i].opt);
|
||||
else
|
||||
sprintf(buff, " ");
|
||||
|
||||
sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
|
||||
printf("%-36.36s", buff);
|
||||
|
||||
if (usage[i].arg)
|
||||
{
|
||||
strcpy(buff, usage[i].arg);
|
||||
@@ -597,7 +596,6 @@ static void do_usage(void)
|
||||
if (tab[j].handle == *(usage[i].arg))
|
||||
sprintf(buff, "%d", tab[j].val);
|
||||
}
|
||||
printf("%-36.36s", usage[i].flag);
|
||||
printf(_(usage[i].desc), buff);
|
||||
printf("\n");
|
||||
}
|
||||
@@ -912,13 +910,37 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if (option == '?')
|
||||
return gen_prob;
|
||||
|
||||
for (i=0; optmap[i].c; i++)
|
||||
if (option == optmap[i].c)
|
||||
for (i=0; usage[i].opt != 0; i++)
|
||||
if (usage[i].opt == option)
|
||||
{
|
||||
daemon->options |= optmap[i].flag;
|
||||
return NULL;
|
||||
int rept = usage[i].rept;
|
||||
|
||||
if (nest == 0)
|
||||
{
|
||||
/* command line */
|
||||
if (rept == ARG_USED_CL)
|
||||
return _("illegal repeated flag");
|
||||
if (rept == ARG_ONE)
|
||||
usage[i].rept = ARG_USED_CL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* allow file to override command line */
|
||||
if (rept == ARG_USED_FILE)
|
||||
return _("illegal repeated keyword");
|
||||
if (rept == ARG_USED_CL || rept == ARG_ONE)
|
||||
usage[i].rept = ARG_USED_FILE;
|
||||
}
|
||||
|
||||
if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL)
|
||||
{
|
||||
daemon->options |= rept;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case 'C': /* --conf-file */
|
||||
@@ -1107,6 +1129,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
case 'g': /* --group */
|
||||
daemon->groupname = opt_string_alloc(arg);
|
||||
daemon->group_set = 1;
|
||||
break;
|
||||
|
||||
case LOPT_SCRIPTUSR: /* --scriptuser */
|
||||
daemon->scriptuser = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
case 'i': /* --interface */
|
||||
@@ -1194,8 +1221,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
} while (arg);
|
||||
break;
|
||||
|
||||
case 'S': /* --server */
|
||||
case 'A': /* --address */
|
||||
case 'S': /* --server */
|
||||
case LOPT_LOCAL: /* --local */
|
||||
case 'A': /* --address */
|
||||
{
|
||||
struct server *serv, *newlist = NULL;
|
||||
|
||||
@@ -1366,6 +1394,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case LOPT_MINPORT: /* --min-port */
|
||||
if (!atoi_check(arg, &daemon->min_port))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case '0': /* --dns-forward-max */
|
||||
if (!atoi_check(arg, &daemon->ftabsize))
|
||||
option = '?';
|
||||
@@ -1391,6 +1424,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case 'Q': /* --query-port */
|
||||
if (!atoi_check(arg, &daemon->query_port))
|
||||
option = '?';
|
||||
/* if explicitly set to zero, use single OS ephemeral port
|
||||
and disable random ports */
|
||||
if (daemon->query_port == 0)
|
||||
daemon->osport = 1;
|
||||
break;
|
||||
|
||||
case 'T': /* --local-ttl */
|
||||
@@ -1435,7 +1472,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
break;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
case LOPT_BRIDGE: /* --bridge-interface */
|
||||
{
|
||||
struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
|
||||
@@ -1869,6 +1906,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
case LOPT_MATCH:
|
||||
new->match_type = MATCH_OPTION;
|
||||
break;
|
||||
}
|
||||
new->next = daemon->dhcp_vendors;
|
||||
daemon->dhcp_vendors = new;
|
||||
@@ -1876,6 +1914,23 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_ALTPORT: /* --dhcp-alternate-port */
|
||||
if (!arg)
|
||||
{
|
||||
daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
|
||||
daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &daemon->dhcp_server_port) ||
|
||||
(comma && !atoi_check(comma, &daemon->dhcp_client_port)))
|
||||
problem = _("invalid port number");
|
||||
if (!comma)
|
||||
daemon->dhcp_client_port = daemon->dhcp_server_port+1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'J': /* --dhcp-ignore */
|
||||
case LOPT_NO_NAMES: /* --dhcp-ignore-names */
|
||||
case LOPT_BROADCAST: /* --dhcp-broadcast */
|
||||
@@ -1988,6 +2043,42 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_NAPTR: /* --naptr-record */
|
||||
{
|
||||
char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
int k = 0;
|
||||
struct naptr *new;
|
||||
int order, pref;
|
||||
|
||||
if ((a[0] = arg))
|
||||
for (k = 1; k < 7; k++)
|
||||
if (!(a[k] = split(a[k-1])))
|
||||
break;
|
||||
|
||||
|
||||
if (k < 6 ||
|
||||
!canonicalise_opt(a[0]) ||
|
||||
!atoi_check(a[1], &order) ||
|
||||
!atoi_check(a[2], &pref) ||
|
||||
(k == 7 && !canonicalise_opt(a[6])))
|
||||
problem = _("bad NAPTR record");
|
||||
else
|
||||
{
|
||||
new = opt_malloc(sizeof(struct naptr));
|
||||
new->next = daemon->naptr;
|
||||
daemon->naptr = new;
|
||||
new->name = opt_string_alloc(a[0]);
|
||||
new->flags = opt_string_alloc(a[3]);
|
||||
new->services = opt_string_alloc(a[4]);
|
||||
new->regexp = opt_string_alloc(a[5]);
|
||||
if (k == 7)
|
||||
new->replace = opt_string_alloc(a[6]);
|
||||
new->order = order;
|
||||
new->pref = pref;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Y': /* --txt-record */
|
||||
{
|
||||
struct txt_record *new;
|
||||
@@ -2351,11 +2442,12 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
daemon->cachesize = CACHESIZ;
|
||||
daemon->ftabsize = FTABSIZ;
|
||||
daemon->port = NAMESERVER_PORT;
|
||||
daemon->dhcp_client_port = DHCP_CLIENT_PORT;
|
||||
daemon->dhcp_server_port = DHCP_SERVER_PORT;
|
||||
daemon->default_resolv.is_default = 1;
|
||||
daemon->default_resolv.name = RESOLVFILE;
|
||||
daemon->resolv_files = &daemon->default_resolv;
|
||||
daemon->username = CHUSER;
|
||||
daemon->groupname = CHGRP;
|
||||
daemon->runfile = RUNFILE;
|
||||
daemon->dhcp_max = MAXLEASES;
|
||||
daemon->tftp_max = TFTP_MAX_CONNECTIONS;
|
||||
@@ -2424,7 +2516,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
if (conffile)
|
||||
one_file(conffile, nest, 0);
|
||||
|
||||
/* port might no be known when the address is parsed - fill in here */
|
||||
/* port might not be known when the address is parsed - fill in here */
|
||||
if (daemon->servers)
|
||||
{
|
||||
struct server *tmp;
|
||||
@@ -2538,6 +2630,3 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
||||
if (*name == '\\' && *(name+1) == '[' &&
|
||||
(*(name+2) == 'x' || *(name+2) == 'X'))
|
||||
{
|
||||
for (j = 0, cp1 = name+3; *cp1 && isxdigit(*cp1) && j < 32; cp1++, j++)
|
||||
for (j = 0, cp1 = name+3; *cp1 && isxdigit((int) *cp1) && j < 32; cp1++, j++)
|
||||
{
|
||||
char xdig[2];
|
||||
xdig[0] = *cp1;
|
||||
@@ -1044,6 +1044,16 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp, unsigne
|
||||
memcpy(p, sval, usval);
|
||||
p += usval;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
sval = va_arg(ap, char *);
|
||||
usval = sval ? strlen(sval) : 0;
|
||||
if (usval > 255)
|
||||
usval = 255;
|
||||
*p++ = (unsigned char)usval;
|
||||
memcpy(p, sval, usval);
|
||||
p += usval;
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(ap); /* clean up variable argument pointer */
|
||||
@@ -1145,7 +1155,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, 0, NULL, 0);
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<TXT>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_TXT, t->class, "t", t->len, t->txt))
|
||||
@@ -1184,7 +1194,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, 0, NULL, 0);
|
||||
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", intr->name))
|
||||
@@ -1196,7 +1206,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_BIGNAME, name, NULL, 0, NULL, 0);
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<PTR>");
|
||||
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
|
||||
if (hostname_isequal(name, ptr->name) &&
|
||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
@@ -1220,7 +1230,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (crecp->flags & F_NXDOMAIN)
|
||||
nxdomain = 1;
|
||||
if (!dryrun)
|
||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, 0, NULL, 0);
|
||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
|
||||
}
|
||||
else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
|
||||
{
|
||||
@@ -1237,8 +1247,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
else
|
||||
ttl = crecp->ttd - now;
|
||||
|
||||
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
|
||||
0, daemon->addn_hosts, crecp->uid);
|
||||
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
|
||||
record_source(daemon->addn_hosts, crecp->uid));
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL,
|
||||
T_PTR, C_IN, "d", cache_get_name(crecp)))
|
||||
@@ -1255,7 +1265,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
nxdomain = 1;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN,
|
||||
name, &addr, 0, NULL, 0);
|
||||
name, &addr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1279,7 +1289,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, 0, NULL, 0);
|
||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN, "4", &addr))
|
||||
anscount++;
|
||||
@@ -1302,10 +1312,10 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (!dryrun)
|
||||
{
|
||||
if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
|
||||
log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, 0, NULL, 0);
|
||||
log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
|
||||
else
|
||||
{
|
||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, 0, NULL, 0);
|
||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN, "4", &addr))
|
||||
anscount++;
|
||||
@@ -1347,7 +1357,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
{
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(crecp->flags, name, NULL, 0, daemon->addn_hosts, crecp->uid);
|
||||
log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, crecp->ttd - now, &nameoffset,
|
||||
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
|
||||
anscount++;
|
||||
@@ -1364,7 +1374,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (crecp->flags & F_NXDOMAIN)
|
||||
nxdomain = 1;
|
||||
if (!dryrun)
|
||||
log_query(crecp->flags, name, NULL, 0, NULL, 0);
|
||||
log_query(crecp->flags, name, NULL, NULL);
|
||||
}
|
||||
else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
|
||||
{
|
||||
@@ -1389,7 +1399,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ttl = crecp->ttd - now;
|
||||
|
||||
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
|
||||
0, daemon->addn_hosts, crecp->uid);
|
||||
record_source(daemon->addn_hosts, crecp->uid));
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &crecp->addr))
|
||||
@@ -1410,7 +1420,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (!dryrun)
|
||||
{
|
||||
unsigned int offset;
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_IPV4, name, NULL, 0, NULL, 0);
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||
{
|
||||
@@ -1427,7 +1437,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_IPV4, name, NULL, 0, NULL, 0);
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
|
||||
T_MX, C_IN, "sd", 1,
|
||||
(daemon->options & OPT_SELFMX) ? name : daemon->mxtarget))
|
||||
@@ -1447,7 +1457,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (!dryrun)
|
||||
{
|
||||
unsigned int offset;
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_IPV6, name, NULL, 0, NULL, 0);
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<SRV>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
&offset, T_SRV, C_IN, "sssd",
|
||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||
@@ -1463,9 +1473,27 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
{
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_NEG, name, NULL, 0, NULL, 0);
|
||||
log_query(F_CONFIG | F_NEG, name, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (qtype == T_NAPTR || qtype == T_ANY)
|
||||
{
|
||||
struct naptr *na;
|
||||
for (na = daemon->naptr; na; na = na->next)
|
||||
if (hostname_isequal(name, na->name))
|
||||
{
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<NAPTR>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qtype == T_MAILB)
|
||||
ans = 1, nxdomain = 1;
|
||||
@@ -1474,7 +1502,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
{
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_NEG, name, &addr, 0, NULL, 0);
|
||||
log_query(F_CONFIG | F_NEG, name, &addr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
164
src/rfc2131.c
164
src/rfc2131.c
@@ -56,6 +56,7 @@
|
||||
#define SUBOPT_REMOTE_ID 2
|
||||
#define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */
|
||||
#define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */
|
||||
#define SUBOPT_SERVER_OR 11 /* RFC 5107 */
|
||||
|
||||
#define DHCPDISCOVER 1
|
||||
#define DHCPOFFER 2
|
||||
@@ -68,9 +69,10 @@
|
||||
|
||||
#define have_config(config, mask) ((config) && ((config)->flags & (mask)))
|
||||
#define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
|
||||
#define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2]))
|
||||
#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
|
||||
|
||||
static int sanitise(unsigned char *opt, char *buf);
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override);
|
||||
static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
|
||||
static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
|
||||
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||
@@ -82,7 +84,8 @@ static void log_packet(char *type, void *addr,
|
||||
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, struct dhcp_netid *netid);
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end, unsigned char *agent_id);
|
||||
static void restore_agent_id(unsigned char *agent_id, struct dhcp_packet *mess, unsigned char *real_end);
|
||||
static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
@@ -116,16 +119,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
unsigned int time;
|
||||
struct dhcp_config *config;
|
||||
struct dhcp_netid *netid = NULL;
|
||||
struct in_addr subnet_addr, fallback;
|
||||
struct in_addr subnet_addr, fallback, override;
|
||||
unsigned short fuzz = 0;
|
||||
unsigned int mess_type = 0;
|
||||
unsigned char fqdn_flags = 0;
|
||||
unsigned char *agent_id = NULL;
|
||||
unsigned char *emac = NULL;
|
||||
int emac_len;
|
||||
int emac_len = 0;
|
||||
struct dhcp_netid known_id;
|
||||
|
||||
subnet_addr.s_addr = 0;
|
||||
subnet_addr.s_addr = override.s_addr = 0;
|
||||
|
||||
if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
|
||||
return 0;
|
||||
@@ -183,8 +186,12 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
|
||||
/* look for RFC3527 Link selection sub-option */
|
||||
if ((sopt = option_find1(option_ptr(opt), option_ptr(opt) + option_len(opt), SUBOPT_SUBNET_SELECT, INADDRSZ)))
|
||||
if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
|
||||
subnet_addr = option_addr(sopt);
|
||||
|
||||
/* look for RFC5107 server-identifier-override */
|
||||
if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
|
||||
override = option_addr(sopt);
|
||||
|
||||
/* if a circuit-id or remote-is option is provided, exact-match to options. */
|
||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||
@@ -200,9 +207,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else
|
||||
continue;
|
||||
|
||||
if ((sopt = option_find1(option_ptr(opt), option_ptr(opt) + option_len(opt), search, 1)) &&
|
||||
if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
|
||||
vendor->len == option_len(sopt) &&
|
||||
memcmp(option_ptr(sopt), vendor->data, vendor->len) == 0)
|
||||
memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
|
||||
{
|
||||
vendor->netid.next = netid;
|
||||
netid = &vendor->netid;
|
||||
@@ -219,7 +226,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
|
||||
{
|
||||
clid_len = option_len(opt);
|
||||
clid = option_ptr(opt);
|
||||
clid = option_ptr(opt, 0);
|
||||
}
|
||||
|
||||
/* do we have a lease in store? */
|
||||
@@ -433,10 +440,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
|
||||
if (hostname)
|
||||
lease_set_hostname(lease, hostname, daemon->domain_suffix, 1);
|
||||
lease_set_expires(lease, 0xffffffff, now); /* infinite lease */
|
||||
/* infinite lease unless nailed in dhcp-host line. */
|
||||
lease_set_expires(lease,
|
||||
have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
|
||||
now);
|
||||
lease_set_interface(lease, int_index);
|
||||
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, NULL);
|
||||
do_options(context, mess, end, NULL,
|
||||
hostname, netid, subnet_addr, 0, 0, NULL);
|
||||
}
|
||||
@@ -452,7 +462,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
/* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
|
||||
int len = option_len(opt);
|
||||
char *pq = daemon->dhcp_buff;
|
||||
unsigned char *pp, *op = option_ptr(opt);
|
||||
unsigned char *pp, *op = option_ptr(opt, 0);
|
||||
|
||||
fqdn_flags = *op;
|
||||
len -= 3;
|
||||
@@ -493,7 +503,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
memcpy(daemon->dhcp_buff, option_ptr(opt), len);
|
||||
memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
|
||||
/* Microsoft clients are broken, and need zero-terminated strings
|
||||
in options. We detect this state here, and do the same in
|
||||
any options we send */
|
||||
@@ -561,7 +571,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
|
||||
{
|
||||
unsigned char *ucp = option_ptr(opt);
|
||||
unsigned char *ucp = option_ptr(opt, 0);
|
||||
int tmp, j;
|
||||
for (j = 0; j < option_len(opt); j += ucp[j] + 1);
|
||||
if (j == option_len(opt))
|
||||
@@ -596,7 +606,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= (option_len(opt) - vendor->len); i++)
|
||||
if (memcmp(vendor->data, option_ptr(opt)+i, vendor->len) == 0)
|
||||
if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
|
||||
{
|
||||
vendor->netid.next = netid;
|
||||
netid = &vendor->netid;
|
||||
@@ -628,7 +638,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
|
||||
{
|
||||
req_options = (unsigned char *)daemon->dhcp_buff2;
|
||||
memcpy(req_options, option_ptr(opt), option_len(opt));
|
||||
memcpy(req_options, option_ptr(opt, 0), option_len(opt));
|
||||
req_options[option_len(opt)] = OPTION_END;
|
||||
}
|
||||
|
||||
@@ -636,16 +646,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
case DHCPDECLINE:
|
||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||
(context->local.s_addr != option_addr(opt).s_addr))
|
||||
option_addr(opt).s_addr != server_id(context, override).s_addr)
|
||||
return 0;
|
||||
|
||||
|
||||
/* sanitise any message. Paranoid? Moi? */
|
||||
sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
|
||||
|
||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
return 0;
|
||||
|
||||
log_packet("DECLINE", option_ptr(opt), emac, emac_len, iface_name, daemon->dhcp_buff);
|
||||
log_packet("DECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff);
|
||||
|
||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||
lease_prune(lease, now);
|
||||
@@ -669,7 +679,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
case DHCPRELEASE:
|
||||
if (!(context = narrow_context(context, mess->ciaddr, netid)) ||
|
||||
!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||
(context->local.s_addr != option_addr(opt).s_addr))
|
||||
option_addr(opt).s_addr != server_id(context, override).s_addr)
|
||||
return 0;
|
||||
|
||||
if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
|
||||
@@ -691,10 +701,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
struct in_addr addr, conf;
|
||||
|
||||
addr.s_addr = conf.s_addr = 0;
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
addr = option_addr(opt);
|
||||
|
||||
conf.s_addr = 0;
|
||||
if (have_config(config, CONFIG_ADDR))
|
||||
{
|
||||
char *addrs = inet_ntoa(config->addr);
|
||||
@@ -736,7 +747,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
message = _("no address available");
|
||||
}
|
||||
|
||||
log_packet("DISCOVER", opt ? option_ptr(opt) : NULL, emac, emac_len, iface_name, message);
|
||||
log_packet("DISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message);
|
||||
|
||||
if (message || !(context = narrow_context(context, mess->yiaddr, netid)))
|
||||
return 0;
|
||||
@@ -750,9 +761,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
|
||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||
if (time != 0xffffffff)
|
||||
@@ -781,13 +792,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
/* SELECTING */
|
||||
selecting = 1;
|
||||
|
||||
for (; context; context = context->current)
|
||||
if (context->local.s_addr == option_addr(opt).s_addr)
|
||||
break;
|
||||
if (override.s_addr != 0)
|
||||
{
|
||||
if (option_addr(opt).s_addr != override.s_addr)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; context; context = context->current)
|
||||
if (context->local.s_addr == option_addr(opt).s_addr)
|
||||
break;
|
||||
|
||||
if (!context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!context)
|
||||
return 0;
|
||||
|
||||
/* If a lease exists for this host and another address, squash it. */
|
||||
if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
|
||||
{
|
||||
@@ -889,11 +908,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
log_packet("NAK", &mess->yiaddr, emac, emac_len, iface_name, message);
|
||||
|
||||
mess->yiaddr.s_addr = 0;
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ,
|
||||
ntohl(context ? context->local.s_addr : fallback.s_addr));
|
||||
ntohl(server_id(context, override).s_addr ? server_id(context, override).s_addr : fallback.s_addr));
|
||||
option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
|
||||
/* DHCPNAK gets agent-id too */
|
||||
restore_agent_id(agent_id, mess, end);
|
||||
/* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
|
||||
a distant subnet which unicast a REQ to us won't work. */
|
||||
if (!unicast_dest || mess->giaddr.s_addr != 0 ||
|
||||
@@ -912,7 +933,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
unsigned char *ucp = option_ptr(opt);
|
||||
unsigned char *ucp = option_ptr(opt, 0);
|
||||
/* If the user-class option started as counted strings, the first byte will be zero. */
|
||||
if (len != 0 && ucp[0] == 0)
|
||||
ucp++, len--;
|
||||
@@ -927,7 +948,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
unsigned char *ucp = option_ptr(opt);
|
||||
unsigned char *ucp = option_ptr(opt, 0);
|
||||
free(lease->vendorclass);
|
||||
if ((lease->vendorclass = whine_malloc(len+1)))
|
||||
{
|
||||
@@ -967,12 +988,17 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
lease_set_expires(lease, time, now);
|
||||
lease_set_interface(lease, int_index);
|
||||
|
||||
|
||||
if (override.s_addr != 0)
|
||||
lease->override = override;
|
||||
else
|
||||
override = lease->override;
|
||||
|
||||
log_packet("ACK", &mess->yiaddr, emac, emac_len, iface_name, hostname);
|
||||
|
||||
clear_packet(mess, end);
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
if (time != 0xffffffff)
|
||||
{
|
||||
@@ -1015,9 +1041,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
clear_packet(mess, end);
|
||||
if (lease && override.s_addr != 0)
|
||||
lease->override = override;
|
||||
else
|
||||
override = lease->override;
|
||||
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
|
||||
if (lease)
|
||||
{
|
||||
@@ -1090,6 +1121,14 @@ static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *
|
||||
return time;
|
||||
}
|
||||
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override)
|
||||
{
|
||||
if (override.s_addr != 0)
|
||||
return override;
|
||||
else
|
||||
return context->local;
|
||||
}
|
||||
|
||||
static int sanitise(unsigned char *opt, char *buf)
|
||||
{
|
||||
char *p;
|
||||
@@ -1100,7 +1139,7 @@ static int sanitise(unsigned char *opt, char *buf)
|
||||
if (!opt)
|
||||
return 0;
|
||||
|
||||
p = option_ptr(opt);
|
||||
p = option_ptr(opt, 0);
|
||||
|
||||
for (i = option_len(opt); i > 0; i--)
|
||||
{
|
||||
@@ -1150,27 +1189,27 @@ static void log_options(unsigned char *start)
|
||||
|
||||
static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
|
||||
{
|
||||
while (*p != OPTION_END)
|
||||
while (1)
|
||||
{
|
||||
if (p >= end)
|
||||
return NULL; /* malformed packet */
|
||||
if (p > end)
|
||||
return NULL;
|
||||
else if (*p == OPTION_END)
|
||||
return opt == OPTION_END ? p : NULL;
|
||||
else if (*p == OPTION_PAD)
|
||||
p++;
|
||||
else
|
||||
{
|
||||
int opt_len;
|
||||
if (p >= end - 2)
|
||||
if (p > end - 2)
|
||||
return NULL; /* malformed packet */
|
||||
opt_len = option_len(p);
|
||||
if (p >= end - (2 + opt_len))
|
||||
if (p > end - (2 + opt_len))
|
||||
return NULL; /* malformed packet */
|
||||
if (*p == opt && opt_len >= minsize)
|
||||
return p;
|
||||
p += opt_len + 2;
|
||||
}
|
||||
}
|
||||
|
||||
return opt == OPTION_END ? p : NULL;
|
||||
}
|
||||
|
||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
|
||||
@@ -1204,7 +1243,7 @@ static struct in_addr option_addr(unsigned char *opt)
|
||||
/* struct in_addr is network byte order */
|
||||
struct in_addr ret;
|
||||
|
||||
memcpy(&ret, option_ptr(opt), INADDRSZ);
|
||||
memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1214,7 +1253,7 @@ static unsigned int option_uint(unsigned char *opt, int size)
|
||||
/* this worries about unaligned data and byte order */
|
||||
unsigned int ret = 0;
|
||||
int i;
|
||||
unsigned char *p = option_ptr(opt);
|
||||
unsigned char *p = option_ptr(opt, 0);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
ret = (ret << 8) | *p++;
|
||||
@@ -1453,7 +1492,7 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
|
||||
if (dopt->vendor_class)
|
||||
len = strlen((char *)dopt->vendor_class);
|
||||
for (i = 0; i <= (option_len(opt) - len); i++)
|
||||
if (len == 0 || memcmp(dopt->vendor_class, option_ptr(opt)+i, len) == 0)
|
||||
if (len == 0 || memcmp(dopt->vendor_class, option_ptr(opt, i), len) == 0)
|
||||
{
|
||||
dopt->flags |= DHOPT_VENDOR_MATCH;
|
||||
break;
|
||||
@@ -1462,14 +1501,29 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end, unsigned char *agent_id)
|
||||
{
|
||||
/* don't clear agent_id */
|
||||
if (agent_id)
|
||||
end = agent_id;
|
||||
|
||||
memset(mess->sname, 0, sizeof(mess->sname));
|
||||
memset(mess->file, 0, sizeof(mess->file));
|
||||
memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
|
||||
mess->siaddr.s_addr = 0;
|
||||
}
|
||||
|
||||
static void restore_agent_id(unsigned char *agent_id, struct dhcp_packet *mess, unsigned char *real_end)
|
||||
{
|
||||
if (agent_id)
|
||||
{
|
||||
unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
|
||||
memmove(p, agent_id, real_end - agent_id);
|
||||
p += real_end - agent_id;
|
||||
memset(p, 0, real_end - p); /* in case of overlap */
|
||||
}
|
||||
}
|
||||
|
||||
static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
@@ -1784,13 +1838,7 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
|
||||
/* move agent_id back down to the end of the packet */
|
||||
if (agent_id)
|
||||
{
|
||||
p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
|
||||
memmove(p, agent_id, real_end - agent_id);
|
||||
p += real_end - agent_id;
|
||||
memset(p, 0, real_end - p); /* in case of overlap */
|
||||
}
|
||||
restore_agent_id(agent_id, mess, real_end);
|
||||
|
||||
/* restore BOOTP anti-overload hack */
|
||||
if (!req_options || (daemon->options & OPT_NO_OVERRIDE))
|
||||
|
||||
56
src/tftp.c
56
src/tftp.c
@@ -151,8 +151,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
transfer->backoff = 1;
|
||||
transfer->block = 1;
|
||||
transfer->blocksize = 512;
|
||||
transfer->offset = 0;
|
||||
transfer->file = NULL;
|
||||
transfer->opt_blocksize = transfer->opt_transize = 0;
|
||||
transfer->netascii = transfer->carrylf = 0;
|
||||
|
||||
/* if we have a nailed-down range, iterate until we find a free one. */
|
||||
while (1)
|
||||
@@ -184,10 +186,13 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
|
||||
!(filename = next(&p, end)) ||
|
||||
!(mode = next(&p, end)) ||
|
||||
strcasecmp(mode, "octet") != 0)
|
||||
(strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
|
||||
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), inet_ntoa(peer.sin_addr));
|
||||
else
|
||||
{
|
||||
if (strcasecmp(mode, "netascii") == 0)
|
||||
transfer->netascii = 1;
|
||||
|
||||
while ((opt = next(&p, end)))
|
||||
{
|
||||
if (strcasecmp(opt, "blksize") == 0 &&
|
||||
@@ -203,7 +208,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
transfer->block = 0;
|
||||
}
|
||||
|
||||
if (strcasecmp(opt, "tsize") == 0 && next(&p, end))
|
||||
if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
|
||||
{
|
||||
transfer->opt_transize = 1;
|
||||
transfer->block = 0;
|
||||
@@ -378,7 +383,8 @@ void check_tftp_listeners(fd_set *rset, time_t now)
|
||||
/* Got ack, ensure we take the (re)transmit path */
|
||||
transfer->timeout = now;
|
||||
transfer->backoff = 0;
|
||||
transfer->block++;
|
||||
if (transfer->block++ != 0)
|
||||
transfer->offset += transfer->blocksize - transfer->expansion;
|
||||
}
|
||||
else if (ntohs(mess->op) == OP_ERR)
|
||||
{
|
||||
@@ -532,24 +538,52 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
|
||||
unsigned char data[];
|
||||
} *mess = (struct datamess *)packet;
|
||||
|
||||
off_t offset = transfer->blocksize * (transfer->block - 1);
|
||||
size_t size = transfer->file->size - offset;
|
||||
size_t size = transfer->file->size - transfer->offset;
|
||||
|
||||
if (offset > transfer->file->size)
|
||||
if (transfer->offset > transfer->file->size)
|
||||
return 0; /* finished */
|
||||
|
||||
if (size > transfer->blocksize)
|
||||
size = transfer->blocksize;
|
||||
|
||||
lseek(transfer->file->fd, offset, SEEK_SET);
|
||||
|
||||
mess->op = htons(OP_DATA);
|
||||
mess->block = htons((unsigned short)(transfer->block));
|
||||
|
||||
if (!read_write(transfer->file->fd, mess->data, size, 1))
|
||||
if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
|
||||
!read_write(transfer->file->fd, mess->data, size, 1))
|
||||
return -1;
|
||||
else
|
||||
return size + 4;
|
||||
|
||||
transfer->expansion = 0;
|
||||
|
||||
/* Map '\n' to CR-LF in netascii mode */
|
||||
if (transfer->netascii)
|
||||
{
|
||||
size_t i;
|
||||
int newcarrylf;
|
||||
|
||||
for (i = 0, newcarrylf = 0; i < size; i++)
|
||||
if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
|
||||
{
|
||||
if (size == transfer->blocksize)
|
||||
{
|
||||
transfer->expansion++;
|
||||
if (i == size - 1)
|
||||
newcarrylf = 1; /* don't expand LF again if it moves to the next block */
|
||||
}
|
||||
else
|
||||
size++; /* room in this block */
|
||||
|
||||
/* make space and insert CR */
|
||||
memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
|
||||
mess->data[i] = '\r';
|
||||
|
||||
i++;
|
||||
}
|
||||
transfer->carrylf = newcarrylf;
|
||||
|
||||
}
|
||||
|
||||
return size + 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
143
src/util.c
143
src/util.c
@@ -16,82 +16,88 @@
|
||||
|
||||
/* Some code in this file contributed by Rob Funk. */
|
||||
|
||||
/* The SURF random number generator was taken from djbdns-1.05, by
|
||||
Daniel J Berstein, which is public domain. */
|
||||
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
|
||||
/* Prefer arc4random(3) over random(3) over rand(3) */
|
||||
/* Also prefer /dev/urandom over /dev/random, to preserve the entropy pool */
|
||||
|
||||
#ifdef HAVE_ARC4RANDOM
|
||||
# define rand() arc4random()
|
||||
# define srand(s) (void)0
|
||||
# define RANDFILE (NULL)
|
||||
#else
|
||||
# ifdef HAVE_RANDOM
|
||||
# define rand() random()
|
||||
# define srand(s) srandom(s)
|
||||
# endif
|
||||
# ifdef HAVE_DEV_URANDOM
|
||||
# define RANDFILE "/dev/urandom"
|
||||
# else
|
||||
# ifdef HAVE_DEV_RANDOM
|
||||
# define RANDFILE "/dev/random"
|
||||
# else
|
||||
# define RANDFILE (NULL)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
void rand_init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned short rand16(void)
|
||||
{
|
||||
static int been_seeded = 0;
|
||||
const char *randfile = RANDFILE;
|
||||
|
||||
if (! been_seeded)
|
||||
{
|
||||
int fd, n = 0;
|
||||
unsigned int c = 0, seed = 0, badseed;
|
||||
char sbuf[sizeof(seed)];
|
||||
char *s;
|
||||
struct timeval now;
|
||||
|
||||
/* get the bad seed as a backup */
|
||||
/* (but we'd rather have something more random) */
|
||||
gettimeofday(&now, NULL);
|
||||
badseed = now.tv_sec ^ now.tv_usec ^ (getpid() << 16);
|
||||
|
||||
fd = open(randfile, O_RDONLY);
|
||||
if (fd < 0)
|
||||
seed = badseed;
|
||||
else
|
||||
{
|
||||
s = (char *) &seed;
|
||||
while ((c < sizeof(seed)) &&
|
||||
((n = read(fd, sbuf, sizeof(seed)) > 0)))
|
||||
{
|
||||
memcpy(s, sbuf, n);
|
||||
s += n;
|
||||
c += n;
|
||||
}
|
||||
if (n < 0)
|
||||
seed = badseed;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
srand(seed);
|
||||
been_seeded = 1;
|
||||
}
|
||||
|
||||
/* Some rand() implementations have less randomness in low bits
|
||||
* than in high bits, so we only pay attention to the high ones.
|
||||
* But most implementations don't touch the high bit, so we
|
||||
* ignore that one.
|
||||
*/
|
||||
return( (unsigned short) (rand() >> 15) );
|
||||
return (unsigned short) (arc4random() >> 15);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* SURF random number generator */
|
||||
|
||||
typedef unsigned int uint32;
|
||||
|
||||
static uint32 seed[32];
|
||||
static uint32 in[12];
|
||||
static uint32 out[8];
|
||||
|
||||
void rand_init()
|
||||
{
|
||||
int fd = open(RANDFILE, O_RDONLY);
|
||||
|
||||
if (fd == -1 ||
|
||||
!read_write(fd, (unsigned char *)&seed, sizeof(seed), 1) ||
|
||||
!read_write(fd, (unsigned char *)&in, sizeof(in), 1))
|
||||
die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
|
||||
#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
|
||||
|
||||
static void surf(void)
|
||||
{
|
||||
uint32 t[12]; uint32 x; uint32 sum = 0;
|
||||
int r; int i; int loop;
|
||||
|
||||
for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
|
||||
for (i = 0;i < 8;++i) out[i] = seed[24 + i];
|
||||
x = t[11];
|
||||
for (loop = 0;loop < 2;++loop) {
|
||||
for (r = 0;r < 16;++r) {
|
||||
sum += 0x9e3779b9;
|
||||
MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
|
||||
MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
|
||||
MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
|
||||
}
|
||||
for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short rand16(void)
|
||||
{
|
||||
static int outleft = 0;
|
||||
|
||||
if (!outleft) {
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
|
||||
return (unsigned short) out[--outleft];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int legal_char(char c)
|
||||
{
|
||||
/* check for legal char a-z A-Z 0-9 -
|
||||
@@ -162,6 +168,14 @@ void *safe_malloc(size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void safe_pipe(int *fd, int read_noblock)
|
||||
{
|
||||
if (pipe(fd) == -1 ||
|
||||
!fix_fd(fd[1]) ||
|
||||
(read_noblock && !fix_fd(fd[0])))
|
||||
die(_("cannot create pipe: %s"), NULL, EC_MISC);
|
||||
}
|
||||
|
||||
void *whine_malloc(size_t size)
|
||||
{
|
||||
void *ret = malloc(size);
|
||||
@@ -429,3 +443,4 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user