import of dnsmasq-2.48.tar.gz

This commit is contained in:
Simon Kelley
2009-06-04 20:32:05 +01:00
parent 73a08a248d
commit 7622fc06ab
37 changed files with 7873 additions and 6709 deletions

2917
CHANGELOG

File diff suppressed because it is too large Load Diff

2509
CHANGELOG.archive Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -23,24 +23,19 @@ PO = po
MAN = man
PKG_CONFIG = pkg-config
AWK = nawk
INSTALL = install
DBUS_MINOR=" `echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --modversion dbus-1 | $(AWK) -F . -- '{ if ($$(NF-1)) print \"-DDBUS_MINOR=\"$$(NF-1) }'`"
DBUS_CFLAGS="`echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --cflags dbus-1`"
DBUS_LIBS=" `echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --libs dbus-1`"
SUNOS_VER=" `if uname | grep SunOS 2>&1 >/dev/null; then uname -r | $(AWK) -F . -- '{ print \"-DSUNOS_VER=\"$$2 }'; fi`"
SUNOS_LIBS=" `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi `"
all : dnsmasq
dnsmasq :
cd $(SRC) && $(MAKE) \
DBUS_MINOR=$(DBUS_MINOR) \
DBUS_CFLAGS=$(DBUS_CFLAGS) \
DBUS_LIBS=$(DBUS_LIBS) \
SUNOS_LIBS=$(SUNOS_LIBS) \
SUNOS_VER=$(SUNOS_VER) \
-f ../bld/Makefile dnsmasq
clean :
@@ -57,11 +52,9 @@ install-common :
all-i18n :
cd $(SRC) && $(MAKE) \
I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \
DBUS_MINOR=$(DBUS_MINOR) \
DBUS_CFLAGS=$(DBUS_CFLAGS) \
DBUS_LIBS=$(DBUS_LIBS) \
SUNOS_LIBS=$(SUNOS_LIBS) \
SUNOS_VER=$(SUNOS_VER) \
-f ../bld/Makefile dnsmasq
cd $(PO); for f in *.po; do \
cd ../$(SRC) && $(MAKE) -f ../bld/Makefile $${f%.po}.mo; \

View File

@@ -0,0 +1,11 @@
A remake of patch Bob Carroll had posted to dnsmasq,
now compatible with version 2.47. Hopefully he doesn't
mind (sending a copy of this mail to him too).
Maybe the patch in question is not acceptible
as it doesn't add new switch, rather it binds itself to "strict-order".
What it does is: if you have strict-order in the
dnsmasq config file and query a domain that would result
in NXDOMAIN, it iterates the whole given nameserver list
until the last one says NXDOMAIN.

View File

@@ -0,0 +1,17 @@
diff -ur dnsmasq-2.47/src/forward.c dnsmasq-2.47-patched/src/forward.c
--- dnsmasq-2.47/src/forward.c 2009-02-01 17:59:48.000000000 +0200
+++ dnsmasq-2.47-patched/src/forward.c 2009-03-18 19:10:22.000000000 +0200
@@ -488,9 +488,12 @@
return;
server = forward->sentto;
+
+ if ( (header->rcode == NXDOMAIN) && ((daemon->options & OPT_ORDER) != 0) && (server->next != NULL) )
+ header->rcode = SERVFAIL;
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
- !(daemon->options & OPT_ORDER) &&
+ ((daemon->options & OPT_ORDER) != 0) &&
forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
{

View File

@@ -329,7 +329,7 @@
# Reboot time. (Note 'i' to send 32-bit value)
#dhcp-option-force=211,30i
# Set the boot filename for BOOTP. You will only need
# Set the boot filename for netboot/PXE. You will only need
# this is you want to boot machines over the network and you will need
# a TFTP server; either dnsmasq's built in TFTP server or an
# external one. (See below for how to enable the TFTP server.)
@@ -358,6 +358,34 @@
#dhcp-match=hammers, option:client-arch, 6 #x86-64
#dhcp-match=mactels, option:client-arch, 7 #EFI x86-64
# Do real PXE, rather than just booting a single file, this is an
# alternative to dhcp-boot.
#pxe-prompt="What system shall I netboot?"
# or with timeout before first available action is taken:
#pxe-prompt="Press F8 for menu.", 60
# Available boot services. for PXE.
#pxe-service=x86PC, "Boot from local disk", 0
# Loads <tftp-root>/pxelinux.0 from dnsmasq TFTP server.
#pxe-service=x86PC, "Install Linux", pxelinux
# Loads <tftp-root>/pxelinux.0 from TFTP server at 1.2.3.4.
# Beware this fails on old PXE ROMS.
#pxe-service=x86PC, "Install Linux", pxelinux, 1.2.3.4
# Use bootserver on network, found my multicast or broadcast.
#pxe-service=x86PC, "Install windows from RIS server", 1
# Use bootserver at a known IP address.
#pxe-service=x86PC, "Install windows from RIS server", 1, 1.2.3.4
# If you have multicast-FTP available,
# information for that can be passed in a similar way using options 1
# to 5. See page 19 of
# http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf
# Enable dnsmasq's built-in TFTP server
#enable-tftp
@@ -371,8 +399,9 @@
# Set the boot file name only when the "red" tag is set.
#dhcp-boot=net:red,pxelinux.red-net
# An example of dhcp-boot with an external server: the name and IP
# An example of dhcp-boot with an external TFTP server: the name and IP
# address of the server are given after the filename.
# Can fail with old PXE ROMS. Overridden by --pxe-service.
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3
# Set the limit on DHCP leases, the default is 150

View File

@@ -11,7 +11,7 @@ Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP
server and allows machines with DHCP-allocated addresses
to appear in the DNS with names configured either in each host or
in a central configuration file. Dnsmasq supports static and dynamic
DHCP leases and BOOTP/TFTP for network booting of diskless machines.
DHCP leases and BOOTP/TFTP/PXE for network booting of diskless machines.
<P>
Dnsmasq is targeted at home networks using NAT and
connected to the internet via a modem, cable-modem or ADSL
@@ -94,7 +94,10 @@ There is a good article about dnsmasq at <A
HREF="http://www.enterprisenetworkingplanet.com/netos/article.php/3377351">http://www.enterprisenetworkingplanet.com/netos/article.php/3377351</A>
and another at <A
HREF="http://www.linux.com/articles/149040">http://www.linux.com/articles/149040</A>
and Ilya Evseev has an article in Russian about dnsmasq to be found at <A HREF="http://ilya-evseev.narod.ru/articles/dnsmasq"> http://ilya-evseev.narod.ru/articles/dnsmasq</A>
and Ilya Evseev has an article in Russian about dnsmasq to be found at
<A HREF="http://ilya-evseev.narod.ru/articles/dnsmasq">
http://ilya-evseev.narod.ru/articles/dnsmasq</A>. Ismael Ull has an
article about dnsmasq in Spanish at <A HREF="http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq">http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq</A>
<H2>License.</H2>
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution
for details.

View File

@@ -31,13 +31,17 @@ BSD, unless the GNU getopt library is linked, the long form of the
options does not work on the command line; it is still recognised in
the configuration file.
.TP
.B --test
Read and syntax check configuration file(s). Exit with code 0 if all
is OK, or a non-zero code otherwise. Do not start up dnsmasq.
.TP
.B \-h, --no-hosts
Don't read the hostnames in /etc/hosts.
.TP
.B \-H, --addn-hosts=<file>
Additional hosts file. Read the specified file as well as /etc/hosts. If -h is given, read
only the specified file. This option may be repeated for more than one
additional hosts file.
additional hosts file. If a directory is given, then read all the files contained in that directory.
.TP
.B \-E, --expand-hosts
Add the domain to simple names (without a period) in /etc/hosts
@@ -422,25 +426,22 @@ Set the maximum number of concurrent DNS queries. The default value is
where this needs to be increased is when using web-server log file
resolvers, which can generate large numbers of concurrent queries.
.TP
.B \-F, --dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[[,<netmask>],<broadcast>][,<default lease time>]
.B \-F, --dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[[,<netmask>],<broadcast>][,<lease time>]
Enable the DHCP server. Addresses will be given out from the range
<start-addr> to <end-addr> and from statically defined addresses given
in
.B dhcp-host
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
or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given,
the default lease time is one hour. The
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
netmask is optional. It is, however, required for networks which
receive DHCP service via a relay agent. The broadcast address is
always optional. On some broken systems, dnsmasq can listen on only
one interface when using DHCP, and the name of that interface must be
given using the
.B interface
option. This limitation currently affects OpenBSD before version 4.0. It is always
always optional. It is always
allowed to have more than one dhcp-range in a single subnet. The optional
network-id is a alphanumeric label which marks this network so that
dhcp options may be specified on a per-network basis.
@@ -449,10 +450,18 @@ a tag to matching it. Only one tag may be set, but more than one tag may be matc
The end address may be replaced by the keyword
.B static
which tells dnsmasq to enable DHCP for the network specified, but not
to dynamically allocate IP addresses. Only hosts which have static
to dynamically allocate IP addresses: only hosts which have static
addresses given via
.B dhcp-host
or from /etc/ethers will be served.
or from /etc/ethers will be served. The end address may be replaced by
the keyword
.B proxy
in which case dnsmasq will provide proxy-DHCP on the specified
subnet. (See
.B pxe-prompt
and
.B pxe-service
for details.)
.TP
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
Specify per host parameters for the DHCP server. This allows a machine
@@ -720,6 +729,57 @@ is providing a TFTP service (see
If the optional network-id(s) are given,
they must match for this configuration to be sent. Note that
network-ids are prefixed by "net:" to distinguish them.
.TP
.B --pxe-service=[net:<network-id>,]<CSA>,<menu text>,<basename>|<bootservicetype>[,<server address>]
Most uses of PXE boot-ROMS simply allow the PXE
system to obtain an IP address and then download the file specified by
.B dhcp-boot
and execute it. However the PXE system is capable of more complex
functions when supported by a suitable DHCP server.
This specifies a boot option which may appear in a PXE boot menu. <CSA> is
client system type, only services of the correct type will appear in a
menu. The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86,
Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI; an
integer may be used for other types. The
parameter after the menu text may be a file name, in which case dnsmasq acts as a
boot server and directs the PXE client to download the file by TFTP,
either from itself (
.B enable-tftp
must be set for this to work) or another TFTP server if the final IP
address is given.
Note that the "layer"
suffix (normally ".0") is supplied by PXE, and should not be added to
the basename. If an integer boot service type, rather than a basename
is given, then the PXE client will search for a
suitable boot service for that type on the network. This search may be done
by multicast or broadcast, or direct to a server if its IP address is provided. A boot service
type of 0 is special, and will abort the net boot procedure and
continue booting from local media.
.TP
.B --pxe-prompt=[net:<network-id>,]<prompt>[,<timeout>]
Setting this provides a prompt to be displayed after PXE boot. If the
timeout is given then after the
timeout has elapsed with no keyboard input, the first available menu
option will be automatically executed. If the timeout is zero then the first available menu
item will be executed immediately. If
.B pxe-prompt
is ommitted the system will wait for user input if there are multiple
items in the menu, but boot immediately if
there is only one. See
.B pxe-service
for details of menu items.
Dnsmasq supports PXE "proxy-DHCP", in this case another DHCP server on
the network is responsible for allocating IP addresses, and dnsmasq
simply provides the information given in
.B pxe-prompt
and
.B pxe-service
to allow netbooting. This mode is enabled using the
.B proxy
keyword in
.B dhcp-range.
.TP
.B \-X, --dhcp-lease-max=<number>
Limits dnsmasq to the specified maximum number of DHCP leases. The
@@ -829,8 +889,8 @@ to the client-id and lease length and expiry time.
.TP
.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 BSD platforms, and is necessary when using "old style" bridging, since
as if they had arrived at <interface>. This option is necessary when
using "old style" bridging on BSD platforms, since
packets arrive at tap interfaces which don't have an IP address.
.TP
.B \-s, --domain=<domain>[,<address range>]

View File

@@ -16,9 +16,8 @@ fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
globaux soient tout de même résolus, et assure également la résolution de nom
pour les hôtes présents dans le service DHCP.
.PP
Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques, les
réseaux multiples, le relai DHCP et les spécifications de sous-réseaux conformes
à la RFC3011. Il envoie par défaut un jeu raisonnable de paramètres DHCP, et
Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les
réseaux multiples. Il envoie par défaut un jeu raisonnable de paramètres DHCP, et
peut être configuré pour envoyer n'importe quel option DHCP.
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP.
@@ -33,6 +32,11 @@ Sur BSD, à moins que le logiciel ne soit compilé avec la bibliothèque GNU
getopt, la forme longue des options ne fonctionne pas en ligne de commande; Elle
est toujours supportée dans le fichier de configuration.
.TP
.B --test
Vérifie la syntaxe du ou des fichiers de configurations. Se termine avec le
code de retour 0 si tout est OK, ou un code différent de 0 dans le cas
contraire. Ne démarre pas Dnsmasq.
.TP
.B \-h, --no-hosts
Ne pas charger les noms du fichier /etc/hosts.
.TP
@@ -41,7 +45,8 @@ Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts
Si
.B -h
est spécifié, lire uniquement le fichier spécifié. Cette option peut être
répétée afin d'ajouter d'autres fichiers.
répétée afin d'ajouter d'autres fichiers. Si un répertoire est donné, lis les
fichiers contenus dans ce répertoire.
.TP
.B \-E, --expand-hosts
Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
@@ -497,7 +502,7 @@ lorsqu'un serveur web a la résolution de nom activée pour l'enregistrement de
son journal des requêtes, ce qui peut générer un nombre important de requêtes
simultanées.
.TP
.B \-F, --dhcp-range=[[net:]identifiant de réseau,]<adresse de début>,<adresse de fin>[[,<masque de réseau>],<broadcast>][,<durée de bail par défaut>]
.B \-F, --dhcp-range=[[net:]identifiant de réseau,]<adresse de début>,<adresse de fin>[[,<masque de réseau>],<broadcast>][,<durée de bail>]
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
<adresse de début> et <adresse de fin> et à partir des adresses définies
statiquement dans l'option
@@ -505,7 +510,9 @@ 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. La valeur minimum pour un bail DHCP est de 2 minutes.
durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par défaut
de une heure est appliqué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
@@ -513,11 +520,8 @@ Dnsmasq possède une interface), le masque de réseau est optionnel. Il est par
contre requis pour les réseaux pour lesquels le service DHCP se fait via un
relais DHCP ("relay agent"). L'adresse de broadcast est toujours optionnelle.
Sur certains systèmes, Dnsmasq ne peut écouter que sur une interface lorsqu'il
utilise DHCP, et le nom de l'interface doit être spécifié par l'option
.B interface.
Cette limitation affecte tous les systèmes OpenBSD avant la version 4.0. Il
est toujours possible d'avoir plus d'une plage DHCP pour un même sous-réseau.
Il est toujours possible d'avoir plus d'une plage DHCP pour un même
sous-réseau.
L'identifiant de réseau optionnel est un label alphanumérique qui permet de
marquer ce réseau afin de fournir des options DHCP spécifiques à chaque réseau.
@@ -528,10 +532,19 @@ label, il définit le label pour laquelle la règle s'applique. Un seul label pe
L'adresse de fin peut être remplacée par le mot-clef
.B static
("statique") qui indique à Dnsmasq d'activer le service DHCP pour le réseau
spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP. Seuls les
hôtes possédant des adresses IP statiques fournies via
spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls
les hôtes possédant des adresses IP statiques fournies via
.B dhcp-host
ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP.
L'adresse de fin peut-être remplacée par le mot-clef
.B proxy
, auquel cas Dnsmasq fournira un service de DHCP proxy pour le sous-réseau
spécifié. (voir
.B pxe-prompt
et
.B pxe-service
pour plus de détails).
.TP
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,net:<identifiant de réseau>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
@@ -828,7 +841,59 @@ le réseau.
Si d'éventuels identifiants de réseau sont fournis, ils doivent coïncider avec
ceux du client pour que cet élement de configuration lui soit envoyé. Il est à
noter que les identifiants de réseau doivent-être préfixés par "net:".
.TP
.TP
.B --pxe-service=[net:<identifiant de réseau>,]<CSA>,<entrée de menu>,<nom de fichier>|<type de service de démarrage>[,<adresse de serveur>]
La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple
obtention d'une adresse IP, le téléchargement du fichier spécifié dans
.B dhcp-boot
et son exécution. Cependant, le système PXE est capable de fonctions bien plus
complexes pour peu que le serveur DHCP soit adapté.
Ceci spécifie l'option de démarrage qui apparaitra dans un menu de démarrage
PXE. <CSA> est le type du système client. Seuls des types de services valides
apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha,
Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI;
D'autres types peuvent-être spécifiés sous la forme d'une valeur entière. Le
paramètre après le texte correspondant à l'entrée dans le menu peut être un nom
de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au
client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur
(l'option
.B enable-tftp
doit être spécifiée pour que cela marche), soit depuis un autre serveur TFTP
si une adresse de serveur est fournie.
Veuillez noter que le suffixe de "couche" (en principe ".0") est fourni par PXE
et ne doit pas être rajouté au nom de fichier. Si une valeur numérique entière
est fournir pour le type de démarrage, en remplacement du nom de fichier, le
client PXE devra chercher un service de démarrage de ce type sur le réseau.
Cette recherche peut être faite via multicast ou broadcast, ou directement
auprès d'un serveur si son adresse IP est fournie dans l'option. Un service de
démarrage de type 0 est spécial et provoquera une interruption du démarrage par
le réseau ainsi que la poursuite du démarrage sur un média local.
.TP
.B --pxe-prompt=[net:<identifiant de réseau>,]<invite>[,<délai>]
Cette option permet d'afficher une invite à la suite du démarrage PXE. Si un
délai est fourni, alors la première entrée du menu de démarrage sera
automatiquement exécutée après ce délai. Si le délai vaut 0, alors la première
entrée disponible sera exécutée immédiatement. Si
.B pxe-prompt
est omis, le système attendra un choix de l'utilisateur s'il existe plusieurs
entrées dans le menu, ou démarrera immédiatement dans le cas où il n'y a qu'une
seule entrée. Voir
.B pxe-service
pour plus de détails sur les entrées de menu.
Dnsmasq peut servir de "proxy-DHCP" PXE, dans le cas où un autre serveur DHCP
sur le réseau est responsable de l'allocation des adresses IP, auquel cas
Dnsmasq se contente de fournir les informations données dans les options
.B pxe-prompt
et
.B pxe-service
pour permettre le démarrage par le réseau. Ce mode est activé en utilisant le
mot-clef
.B proxy
dans
.B dhcp-range.
.TP
.B \-X, --dhcp-lease-max=<nombre>
Limite Dnsmasq à un maximum de <nombre> baux DHCP. Le défaut est de 150. Cette
limite permet d'éviter des attaques de déni de service ("DoS") par des hôtes
@@ -951,9 +1016,9 @@ 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 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.
nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
pas d'adresse IP.
.TP
.B \-s, --domain=<domaine>[,<gamme d'adresses>]
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière

690
po/de.po

File diff suppressed because it is too large Load Diff

679
po/es.po

File diff suppressed because it is too large Load Diff

690
po/fi.po

File diff suppressed because it is too large Load Diff

688
po/fr.po

File diff suppressed because it is too large Load Diff

697
po/id.po

File diff suppressed because it is too large Load Diff

690
po/it.po

File diff suppressed because it is too large Load Diff

692
po/no.po

File diff suppressed because it is too large Load Diff

679
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

693
po/ro.po

File diff suppressed because it is too large Load Diff

View File

@@ -130,7 +130,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
#endif
#if defined(HAVE_BSD_NETWORK)
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
#include <net/bpf.h>
void init_bpf(void)
@@ -175,7 +175,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
/* Only know how to do ethernet on *BSD */
if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN)
{
my_syslog(LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"),
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"),
mess->htype, ifr->ifr_name);
return;
}

View File

@@ -17,7 +17,10 @@
#include "dnsmasq.h"
static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
static struct crec *dhcp_spare = NULL, *new_chain = NULL;
#ifdef HAVE_DHCP
static struct crec *dhcp_spare = NULL;
#endif
static struct crec *new_chain = NULL;
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
static union bigname *big_free = NULL;
static int bignames_left, hash_size;
@@ -859,10 +862,11 @@ static int read_hostsfile(char *filename, int index, int cache_size)
return name_count;
}
void cache_reload(struct hostsfile *addn_hosts)
void cache_reload(void)
{
struct crec *cache, **up, *tmp;
int i, total_size = daemon->cachesize;
struct hostsfile *ah;
cache_inserted = cache_live_freed = 0;
@@ -889,7 +893,7 @@ void cache_reload(struct hostsfile *addn_hosts)
up = &cache->hash_next;
}
if ((daemon->options & OPT_NO_HOSTS) && !addn_hosts)
if ((daemon->options & OPT_NO_HOSTS) && !daemon->addn_hosts)
{
if (daemon->cachesize > 0)
my_syslog(LOG_INFO, _("cleared cache"));
@@ -898,13 +902,116 @@ void cache_reload(struct hostsfile *addn_hosts)
if (!(daemon->options & OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, 0, total_size);
while (addn_hosts)
for (i = 0, ah = daemon->addn_hosts; ah; ah = ah->next)
{
total_size = read_hostsfile(addn_hosts->fname, addn_hosts->index, total_size);
addn_hosts = addn_hosts->next;
}
if (i <= ah->index)
i = ah->index + 1;
if (ah->flags & AH_DIR)
ah->flags |= AH_INACTIVE;
else
ah->flags &= ~AH_INACTIVE;
}
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (!(ah->flags & AH_INACTIVE))
{
struct stat buf;
if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
{
DIR *dir_stream;
struct dirent *ent;
/* don't read this as a file */
ah->flags |= AH_INACTIVE;
if (!(dir_stream = opendir(ah->fname)))
my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
ah->fname, strerror(errno));
else
{
while ((ent = readdir(dir_stream)))
{
size_t lendir = strlen(ah->fname);
size_t lenfile = strlen(ent->d_name);
struct hostsfile *ah1;
char *path;
/* ignore emacs backups and dotfiles */
if (lenfile == 0 ||
ent->d_name[lenfile - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
ent->d_name[0] == '.')
continue;
/* see if we have an existing record.
dir is ah->fname
file is ent->d_name
path to match is ah1->fname */
for (ah1 = daemon->addn_hosts; ah1; ah1 = ah1->next)
{
if (lendir < strlen(ah1->fname) &&
strstr(ah1->fname, ah->fname) == ah1->fname &&
ah1->fname[lendir] == '/' &&
strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
{
ah1->flags &= ~AH_INACTIVE;
break;
}
}
/* make new record */
if (!ah1)
{
if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
continue;
if (!(path = whine_malloc(lendir + lenfile + 2)))
{
free(ah1);
continue;
}
strcpy(path, ah->fname);
strcat(path, "/");
strcat(path, ent->d_name);
ah1->fname = path;
ah1->index = i++;
ah1->flags = AH_DIR;
ah1->next = daemon->addn_hosts;
daemon->addn_hosts = ah1;
}
/* inactivate record if not regular file */
if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
ah1->flags |= AH_INACTIVE;
}
closedir(dir_stream);
}
}
}
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (!(ah->flags & AH_INACTIVE))
total_size = read_hostsfile(ah->fname, ah->index, total_size);
}
char *get_domain(struct in_addr addr)
{
struct cond_domain *c;
for (c = daemon->cond_domain; c; c = c->next)
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return c->domain;
return daemon->domain_suffix;
}
#ifdef HAVE_DHCP
void cache_unhash_dhcp(void)
{
struct crec *cache, **up;
@@ -942,7 +1049,7 @@ void cache_add_dhcp_entry(char *host_name,
_("not giving name %s to the DHCP lease of %s because "
"the name exists in %s with address %s"),
host_name, inet_ntoa(*host_address),
record_source(daemon->addn_hosts, crec->uid), daemon->namebuff);
record_source(crec->uid), daemon->namebuff);
return;
}
else
@@ -1009,6 +1116,7 @@ void cache_add_dhcp_entry(char *host_name,
}
}
}
#endif
void dump_cache(time_t now)
@@ -1099,20 +1207,18 @@ void dump_cache(time_t now)
}
}
char *record_source(struct hostsfile *addn_hosts, int index)
char *record_source(int index)
{
char *source = HOSTSFILE;
while (addn_hosts)
{
if (addn_hosts->index == index)
{
source = addn_hosts->fname;
break;
}
addn_hosts = addn_hosts->next;
}
struct hostsfile *ah;
return source;
if (index == 0)
return HOSTSFILE;
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (ah->index == index)
return ah->fname;
return "<unknown>";
}
void querystr(char *str, unsigned short type)

View File

@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define VERSION "2.47"
#define VERSION "2.48"
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
@@ -106,9 +106,6 @@ HAVE_BSD_NETWORK
HAVE_SOLARIS_NETWORK
define exactly one of these to alter interaction with kernel networking.
HAVE_SOLARIS_PRIVS
define for Solaris > 10 which can split privileges.
HAVE_BROKEN_RTC
define this on embedded systems which don't have an RTC
which keeps time over reboots. Causes dnsmasq to use uptime
@@ -126,6 +123,9 @@ HAVE_BROKEN_RTC
HAVE_TFTP
define this to get dnsmasq's built-in TFTP server.
HAVE_DHCP
define this to get dnsmasq's DHCP server.
HAVE_GETOPT_LONG
define this if you have GNU libc or GNU getopt.
@@ -141,11 +141,6 @@ 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.
NOTES:
For Linux you should define
HAVE_LINUX_NETWORK
@@ -165,6 +160,7 @@ NOTES:
*/
/* platform independent options- uncomment to enable */
#define HAVE_DHCP
#define HAVE_TFTP
/* #define HAVE_BROKEN_RTC */
/* #define HAVE_DBUS */
@@ -174,6 +170,11 @@ NOTES:
#undef HAVE_TFTP
#endif
/* Allow DHCP to be disabled with COPTS=-DNO_DHCP */
#ifdef NO_DHCP
#undef HAVE_DHCP
#endif
/* platform dependent options. */
/* Must preceed __linux__ since uClinux defines __linux__ too. */
@@ -211,13 +212,6 @@ NOTES:
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#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 */
#if defined(__GLIBC__) && (__GLIBC__ == 2) && \
defined(__GLIBC_MINOR__) && (__GLIBC_MINOR__ < 2)
typedef unsigned long in_addr_t;
# define HAVE_BROKEN_SOCKADDR_IN6
#endif
#elif defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
@@ -232,7 +226,6 @@ typedef unsigned long in_addr_t;
# define HAVE_ARC4RANDOM
#endif
#define HAVE_SOCKADDR_SA_LEN
#define HAVE_BSD_BRIDGE
#elif defined(__APPLE__)
#define HAVE_BSD_NETWORK
@@ -247,34 +240,16 @@ typedef unsigned long in_addr_t;
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN
#define HAVE_BSD_BRIDGE
#elif defined(__sun) || defined(__sun__)
#define HAVE_SOLARIS_NETWORK
/* only Solaris 10 does split privs. */
#if (SUNOS_VER >= 10)
# define HAVE_SOLARIS_PRIVS
# define HAVE_GETOPT_LONG
#endif
/* some CMSG stuff missing on early solaris */
#ifndef OSSH_ALIGNBYTES
# define OSSH_ALIGNBYTES (sizeof(int) - 1)
#endif
#ifndef __CMSG_ALIGN
# define __CMSG_ALIGN(p) (((u_int)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES)
#endif
#ifndef CMSG_LEN
# define CMSG_LEN(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
#endif
#ifndef CMSG_SPACE
# define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len))
#endif
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#define _XPG4_2
#define __EXTENSIONS__
#define ETHER_ADDR_LEN 6
#define ETHER_ADDR_LEN 6
#endif
/* Decide if we're going to support IPv6 */

View File

@@ -18,7 +18,6 @@
#ifdef HAVE_DBUS
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
const char* introspection_xml =
@@ -345,11 +344,7 @@ void set_dbus_listeners(int *maxfdp,
if (dbus_watch_get_enabled(w->watch))
{
unsigned int flags = dbus_watch_get_flags(w->watch);
#if (DBUS_MINOR > 0)
int fd = dbus_watch_get_unix_fd(w->watch);
#else
int fd = dbus_watch_get_fd(w->watch);
#endif
bump_maxfd(fd, maxfdp);
@@ -372,11 +367,7 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
if (dbus_watch_get_enabled(w->watch))
{
unsigned int flags = 0;
#if (DBUS_MINOR > 0)
int fd = dbus_watch_get_unix_fd(w->watch);
#else
int fd = dbus_watch_get_fd(w->watch);
#endif
if (FD_ISSET(fd, rset))
flags |= DBUS_WATCH_READABLE;

View File

@@ -16,6 +16,8 @@
#include "dnsmasq.h"
#ifdef HAVE_DHCP
struct iface_param {
struct in_addr relay, primary;
struct dhcp_context *current;
@@ -35,7 +37,7 @@ void dhcp_init(void)
#endif
if (fd == -1)
die (_("cannot create DHCP socket : %s"), NULL, EC_BADNET);
die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
if (!fix_fd(fd) ||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
@@ -43,7 +45,7 @@ void dhcp_init(void)
#endif
#if defined(HAVE_LINUX_NETWORK)
setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
#elif defined(IP_RECVIF)
#else
setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
#endif
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
@@ -51,12 +53,7 @@ void dhcp_init(void)
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 67. That's OK if they serve different networks.
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD.
OpenBSD <= 4.0 screws up IP_RECVIF when SO_REUSEPORT is set, but
OpenBSD <= 3.9 doesn't have IP_RECVIF anyway, so we just have to elide
this for OpenBSD 4.0, if you want more than one instance on oBSD4.0, tough. */
#ifndef OpenBSD4_0
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
if (daemon->options & OPT_NOWILD)
{
#ifdef SO_REUSEPORT
@@ -67,7 +64,6 @@ void dhcp_init(void)
if (rc == -1)
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
}
#endif
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
@@ -124,7 +120,7 @@ void dhcp_packet(time_t now)
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
#elif defined(HAVE_SOLARIS_NETWORK)
char control[CMSG_SPACE(sizeof(unsigned int))];
#elif defined(IP_RECVIF)
#elif defined(HAVE_BSD_NETWORK)
char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
@@ -136,13 +132,30 @@ void dhcp_packet(time_t now)
msg.msg_iov = &daemon->dhcp_packet;
msg.msg_iovlen = 1;
do
while (1)
{
msg.msg_flags = 0;
while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
if (sz == -1)
return;
if (!(msg.msg_flags & MSG_TRUNC))
break;
/* Very new Linux kernels return the actual size needed,
older ones always return truncated size */
if ((size_t)sz == daemon->dhcp_packet.iov_len)
{
if (!expand_buf(&daemon->dhcp_packet, sz + 100))
return;
}
else
{
expand_buf(&daemon->dhcp_packet, sz);
break;
}
}
while (sz != -1 && (msg.msg_flags & MSG_TRUNC) &&
expand_buf(&daemon->dhcp_packet, daemon->dhcp_packet.iov_len + 100));
/* expand_buf may have moved buffer */
mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
@@ -154,7 +167,7 @@ void dhcp_packet(time_t now)
while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) == -1 && errno == EINTR);
if (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
return;
#if defined (HAVE_LINUX_NETWORK)
@@ -166,41 +179,31 @@ void dhcp_packet(time_t now)
if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
unicast_dest = 1;
}
if (!(ifr.ifr_ifindex = iface_index) ||
ioctl(daemon->dhcpfd, SIOCGIFNAME, &ifr) == -1)
return;
#elif defined(IP_RECVIF)
#elif defined(HAVE_BSD_NETWORK)
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
#ifdef HAVE_SOLARIS_NETWORK
iface_index = *((unsigned int *)CMSG_DATA(cmptr));
#else
iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
#endif
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
return;
#elif defined(HAVE_SOLARIS_NETWORK)
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
iface_index = *((unsigned int *)CMSG_DATA(cmptr));
#endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
return;
#ifdef MSG_BCAST
/* OpenBSD tells us when a packet was broadcast */
if (!(msg.msg_flags & MSG_BCAST))
unicast_dest = 1;
#endif
#else
/* fallback for systems without IP_RECVIF - allow only one interface
and assume packets arrive from it - yuk. */
{
struct iname *name;
for (name = daemon->if_names; name->isloop; name = name->next);
strcpy(ifr.ifr_name, name->name);
iface_index = if_nametoindex(name->name);
}
#endif
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
{
@@ -208,7 +211,7 @@ void dhcp_packet(time_t now)
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
if (!iface_check(AF_INET, (struct all_addr *)addrp, &ifr, &iface_index))
if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index))
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
@@ -218,9 +221,9 @@ void dhcp_packet(time_t now)
/* interface may have been changed by alias in iface_check */
if (!addrp)
{
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1)
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
{
my_syslog(LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
else
@@ -319,7 +322,7 @@ void dhcp_packet(time_t now)
dest.sin_addr.s_addr = INADDR_BROADCAST;
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. */
IP_BOUND_IF sockopt lower down. */
}
else
{
@@ -345,12 +348,7 @@ void dhcp_packet(time_t now)
#endif
#ifdef HAVE_SOLARIS_NETWORK
/* OpenSolaris eliminates IP_XMIT_IF */
# ifdef IP_XMIT_IF
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_XMIT_IF, &iface_index, sizeof(iface_index));
# else
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
# endif
#endif
while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
@@ -384,7 +382,7 @@ static int complete_context(struct in_addr local, int if_index,
{
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
my_syslog(LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
}
context->netmask = netmask;
@@ -474,9 +472,9 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
if (!(tmp = address_available(context, taddr, netids)))
{
for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net(taddr, tmp->start, tmp->netmask) &&
(tmp->flags & CONTEXT_STATIC))
break;
if (is_same_net(taddr, tmp->start, tmp->netmask) &&
(tmp->flags & CONTEXT_STATIC))
break;
if (!tmp)
for (tmp = context; tmp; tmp = tmp->current)
@@ -667,7 +665,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
unsigned char *hwaddr, int hw_len,
int hw_type, char *hostname)
{
struct dhcp_config *config;
int count, new;
struct dhcp_config *config, *candidate;
struct hwaddr_config *conf_addr;
if (clid)
@@ -699,17 +698,21 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
hostname_isequal(config->hostname, hostname) &&
is_addr_in_context(context, config))
return config;
for (config = configs; config; config = config->next)
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
if (conf_addr->wildcard_mask != 0 &&
conf_addr->hwaddr_len == hw_len &&
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
is_addr_in_context(context, config) &&
memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask))
return config;
return NULL;
/* use match with fewest wildcast octets */
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
if (is_addr_in_context(context, config))
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
if (conf_addr->wildcard_mask != 0 &&
conf_addr->hwaddr_len == hw_len &&
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
(new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
{
count = new;
candidate = config;
}
return candidate;
}
void dhcp_read_ethers(void)
@@ -728,7 +731,7 @@ void dhcp_read_ethers(void)
if (!f)
{
my_syslog(LOG_ERR, _("failed to read %s:%s"), ETHERSFILE, strerror(errno));
my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
return;
}
@@ -764,7 +767,7 @@ void dhcp_read_ethers(void)
*ip = 0;
if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
{
my_syslog(LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
continue;
}
@@ -777,7 +780,7 @@ void dhcp_read_ethers(void)
{
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
{
my_syslog(LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
continue;
}
@@ -791,7 +794,7 @@ void dhcp_read_ethers(void)
{
if (!canonicalise(ip))
{
my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
continue;
}
@@ -857,7 +860,7 @@ void dhcp_read_ethers(void)
fclose(f);
my_syslog(LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
}
void check_dhcp_hosts(int fatal)
@@ -882,7 +885,7 @@ void check_dhcp_hosts(int fatal)
die(_("duplicate IP address %s in dhcp-config directive."),
inet_ntoa(cp->addr), EC_BADCONF);
else
my_syslog(LOG_ERR, _("duplicate IP address %s in %s."),
my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
configs->flags &= ~CONFIG_ADDR;
}
@@ -925,12 +928,12 @@ 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 than one address in hostsfile, using %s for DHCP"),
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
}
if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
my_syslog(LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
else
{
@@ -982,14 +985,5 @@ char *strip_hostname(char *hostname)
return NULL;
}
char *get_domain(struct in_addr addr)
{
struct cond_domain *c;
#endif
for (c = daemon->cond_domain; c; c = c->next)
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return c->domain;
return daemon->domain_suffix;
}

View File

@@ -33,9 +33,6 @@ static char *compile_opts =
#ifdef NO_FORK
"no-MMU "
#endif
#ifdef HAVE_BSD_BRIDGE
"BSD-bridge "
#endif
#ifndef HAVE_DBUS
"no-"
#endif
@@ -44,6 +41,10 @@ static char *compile_opts =
"no-"
#endif
"I18N "
#ifndef HAVE_DHCP
"no-"
#endif
"DHCP "
#ifndef HAVE_TFTP
"no-"
#endif
@@ -67,9 +68,11 @@ int main (int argc, char **argv)
struct iname *if_tmp;
int piperead, pipefd[2], err_pipe[2];
struct passwd *ent_pw = NULL;
#ifdef HAVE_DHCP
uid_t script_uid = 0;
gid_t script_gid = 0;
struct group *gp= NULL;
#endif
struct group *gp = NULL;
long i, max_fd = sysconf(_SC_OPEN_MAX);
char *baduser = NULL;
int log_err;
@@ -108,11 +111,13 @@ int main (int argc, char **argv)
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
daemon->packet = safe_malloc(daemon->packet_buff_sz);
#ifdef HAVE_DHCP
if (!daemon->lease_file)
{
if (daemon->dhcp)
daemon->lease_file = LEASEFILE;
}
#endif
/* Close any file descriptors we inherited apart from std{in|out|err} */
for (i = 0; i < max_fd; i++)
@@ -145,23 +150,16 @@ int main (int argc, char **argv)
now = dnsmasq_time();
#ifdef HAVE_DHCP
if (daemon->dhcp)
{
#if !defined(HAVE_LINUX_NETWORK) && !defined(IP_RECVIF)
int c;
struct iname *tmp;
for (c = 0, tmp = daemon->if_names; tmp; tmp = tmp->next)
if (!tmp->isloop)
c++;
if (c != 1)
die(_("must set exactly one interface on broken systems without IP_RECVIF"), NULL, EC_BADCONF);
#endif
/* Note that order matters here, we must call lease_init before
creating any file descriptors which shouldn't be leaked
to the lease-script init process. */
lease_init(now);
dhcp_init();
}
#endif
if (!enumerate_interfaces())
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
@@ -204,6 +202,7 @@ int main (int argc, char **argv)
if (daemon->port != 0)
pre_allocate_sfds();
#ifdef HAVE_DHCP
/* Note getpwnam returns static storage */
if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
{
@@ -215,6 +214,7 @@ int main (int argc, char **argv)
else
baduser = daemon->scriptuser;
}
#endif
if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
baduser = daemon->username;
@@ -290,8 +290,9 @@ int main (int argc, char **argv)
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 = fork()) == -1)
/* fd == -1 since we've not forked, never returns. */
send_event(-1, EVENT_FORK_ERR, errno);
if (pid != 0)
{
@@ -312,9 +313,11 @@ int main (int argc, char **argv)
/* NO calls to die() from here on. */
setsid();
pid = fork();
if (pid != 0 && pid != -1)
if ((pid = fork()) == -1)
send_event(err_pipe[1], EVENT_FORK_ERR, errno);
if (pid != 0)
_exit(0);
}
#endif
@@ -349,7 +352,7 @@ int main (int argc, char **argv)
/* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = -1;
#ifndef NO_FORK
#if defined(HAVE_DHCP) && !defined(NO_FORK)
if (daemon->dhcp && daemon->lease_change_command)
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
#endif
@@ -380,7 +383,7 @@ int main (int argc, char **argv)
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
bad_capabilities = errno;
#elif defined(HAVE_SOLARIS_PRIVS)
#elif defined(HAVE_SOLARIS_NETWORK)
/* http://developers.sun.com/solaris/articles/program_privileges.html */
priv_set_t *priv_set;
@@ -400,9 +403,6 @@ int main (int argc, char **argv)
if (priv_set)
priv_freeset(priv_set);
#elif defined(HAVE_SOLARIS_NETWORK)
bad_capabilities = ENOTSUP;
#endif
if (bad_capabilities != 0)
@@ -482,6 +482,7 @@ int main (int argc, char **argv)
if (daemon->max_logs != 0)
my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
#ifdef HAVE_DHCP
if (daemon->dhcp)
{
struct dhcp_context *dhcp_tmp;
@@ -490,13 +491,16 @@ int main (int argc, char **argv)
{
prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
my_syslog(LOG_INFO,
my_syslog(MS_DHCP | LOG_INFO,
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, lease time %s") :
(dhcp_tmp->flags & CONTEXT_PROXY) ?
_("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, IP range %s -- %s, lease time %s"),
daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
}
}
#endif
#ifdef HAVE_TFTP
if (daemon->options & OPT_TFTP)
@@ -506,7 +510,7 @@ int main (int argc, char **argv)
max_fd = FD_SETSIZE;
#endif
my_syslog(LOG_INFO, "TFTP %s%s %s",
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
daemon->tftp_prefix ? _("root is ") : _("enabled"),
daemon->tftp_prefix ? daemon->tftp_prefix: "",
daemon->options & OPT_TFTP_SECURE ? _("secure mode") : "");
@@ -534,7 +538,7 @@ int main (int argc, char **argv)
if (daemon->tftp_max > max_fd)
{
daemon->tftp_max = max_fd;
my_syslog(LOG_WARNING,
my_syslog(MS_TFTP | LOG_WARNING,
_("restricting maximum simultaneous TFTP transfers to %d"),
daemon->tftp_max);
}
@@ -582,11 +586,13 @@ int main (int argc, char **argv)
set_dbus_listeners(&maxfd, &rset, &wset, &eset);
#endif
#ifdef HAVE_DHCP
if (daemon->dhcp)
{
FD_SET(daemon->dhcpfd, &rset);
bump_maxfd(daemon->dhcpfd, &maxfd);
}
#endif
#ifdef HAVE_LINUX_NETWORK
FD_SET(daemon->netlinkfd, &rset);
@@ -596,7 +602,8 @@ int main (int argc, char **argv)
FD_SET(piperead, &rset);
bump_maxfd(piperead, &maxfd);
#ifndef NO_FORK
#ifdef HAVE_DHCP
# ifdef NO_FORK
while (helper_buf_empty() && do_script_run(now));
if (!helper_buf_empty())
@@ -604,11 +611,12 @@ int main (int argc, char **argv)
FD_SET(daemon->helperfd, &wset);
bump_maxfd(daemon->helperfd, &maxfd);
}
#else
# else
/* need this for other side-effects */
while (do_script_run(now));
# endif
#endif
/* must do this just before select(), when we know no
more calls to my_syslog() can occur */
set_log_writer(&wset, &maxfd);
@@ -662,12 +670,14 @@ int main (int argc, char **argv)
check_tftp_listeners(&rset, now);
#endif
#ifdef HAVE_DHCP
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
dhcp_packet(now);
#ifndef NO_FORK
# ifndef NO_FORK
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
helper_write();
# endif
#endif
}
@@ -737,6 +747,9 @@ static void fatal_event(struct event_desc *ev)
{
case EVENT_DIE:
exit(0);
case EVENT_FORK_ERR:
die(_("cannot fork into background: %s"), NULL, EC_MISC);
case EVENT_PIPE_ERR:
die(_("failed to create helper: %s"), NULL, EC_MISC);
@@ -777,7 +790,9 @@ static void async_event(int pipe, time_t now)
reload_servers(daemon->resolv_files->name);
check_servers();
}
#ifdef HAVE_DHCP
rerun_scripts();
#endif
break;
case EVENT_DUMP:
@@ -786,11 +801,13 @@ static void async_event(int pipe, time_t now)
break;
case EVENT_ALARM:
#ifdef HAVE_DHCP
if (daemon->dhcp)
{
lease_prune(NULL, now);
lease_update_file(now);
}
#endif
break;
case EVENT_CHILD:
@@ -840,7 +857,7 @@ static void async_event(int pipe, time_t now)
if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGALRM);
#ifndef NO_FORK
#if defined(HAVE_DHCP) && !defined(NO_FORK)
/* handle pending lease transitions */
if (daemon->helperfd != -1)
{
@@ -904,7 +921,7 @@ static void poll_resolv()
warned = 0;
check_servers();
if (daemon->options & OPT_RELOAD)
cache_reload(daemon->addn_hosts);
cache_reload();
}
else
{
@@ -921,8 +938,9 @@ static void poll_resolv()
void clear_cache_and_reload(time_t now)
{
if (daemon->port != 0)
cache_reload(daemon->addn_hosts);
cache_reload();
#ifdef HAVE_DHCP
if (daemon->dhcp)
{
if (daemon->options & OPT_ETHERS)
@@ -934,6 +952,7 @@ void clear_cache_and_reload(time_t now)
lease_update_file(now);
lease_update_dns();
}
#endif
}
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
@@ -1135,7 +1154,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
}
}
#ifdef HAVE_DHCP
int make_icmp_sock(void)
{
int fd;
@@ -1258,5 +1277,6 @@ int icmp_ping(struct in_addr addr)
return gotreply;
}
#endif

View File

@@ -106,7 +106,7 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
#define LINUX_CAPABILITY_VERSION_3 0x20080522
#include <sys/prctl.h>
#elif defined(HAVE_SOLARIS_PRIVS)
#elif defined(HAVE_SOLARIS_NETWORK)
#include <priv.h>
#endif
@@ -135,6 +135,7 @@ struct event_desc {
#define EVENT_GROUP_ERR 15
#define EVENT_DIE 16
#define EVENT_LOG_ERR 17
#define EVENT_FORK_ERR 18
/* Exit codes. */
#define EC_GOOD 0
@@ -185,6 +186,11 @@ struct event_desc {
#define OPT_NO_OVERRIDE (1u<<30)
#define OPT_NO_REBIND (1u<<31)
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
#define MS_TFTP LOG_USER
#define MS_DHCP LOG_DAEMON
struct all_addr {
union {
struct in_addr addr4;
@@ -287,19 +293,7 @@ struct crec {
union mysockaddr {
struct sockaddr sa;
struct sockaddr_in in;
#ifdef HAVE_BROKEN_SOCKADDR_IN6
/* early versions of glibc don't include sin6_scope_id in sockaddr_in6
but latest kernels _require_ it to be set. The choice is to have
dnsmasq fail to compile on back-level libc or fail to run
on latest kernels with IPv6. Or to do this: sorry that it's so gross. */
struct my_sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 */
uint16_t sin6_port; /* transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* set of interfaces for a scope */
} in6;
#elif defined(HAVE_IPV6)
#if defined(HAVE_IPV6)
struct sockaddr_in6 in6;
#endif
};
@@ -368,8 +362,11 @@ struct resolvc {
};
/* adn-hosts parms from command-line */
#define AH_DIR 1
#define AH_INACTIVE 2
struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
int index; /* matches to cache entries for logging */
};
@@ -484,6 +481,7 @@ struct dhcp_opt {
#define DHOPT_MATCH 128
#define DHOPT_VENDOR 256
#define DHOPT_HEX 512
#define DHOPT_VENDOR_MATCH 1024
struct dhcp_boot {
char *file, *sname;
@@ -492,6 +490,14 @@ struct dhcp_boot {
struct dhcp_boot *next;
};
struct pxe_service {
unsigned short CSA, type;
char *menu, *basename;
struct in_addr server;
struct dhcp_netid *netid;
struct pxe_service *next;
};
#define MATCH_VENDOR 1
#define MATCH_USER 2
#define MATCH_CIRCUIT 3
@@ -514,12 +520,10 @@ struct dhcp_mac {
struct dhcp_mac *next;
};
#ifdef HAVE_BSD_BRIDGE
struct dhcp_bridge {
char iface[IF_NAMESIZE];
struct dhcp_bridge *alias, *next;
};
#endif
struct cond_domain {
char *domain;
@@ -540,6 +544,7 @@ struct dhcp_context {
#define CONTEXT_STATIC 1
#define CONTEXT_NETMASK 2
#define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8
typedef unsigned char u8;
@@ -620,6 +625,7 @@ extern struct daemon {
struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
struct pxe_service *pxe_services;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
char *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max;
@@ -643,23 +649,21 @@ extern struct daemon {
struct server *srv_save; /* Used for resend on DoD */
size_t packet_len; /* " " */
struct randfd *rfd_save; /* " " */
pid_t tcp_pids[MAX_PROCS];
pid_t tcp_pids[MAX_PROCS];
struct randfd randomsocks[RANDOM_SOCKS];
/* DHCP state */
int dhcpfd, helperfd;
#ifdef HAVE_LINUX_NETWORK
#if defined(HAVE_LINUX_NETWORK)
int netlinkfd;
#else
#elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd;
#endif
struct iovec dhcp_packet;
char *dhcp_buff, *dhcp_buff2;
struct ping_result *ping_results;
FILE *lease_stream;
#ifdef HAVE_BSD_BRIDGE
struct dhcp_bridge *bridges;
#endif
/* DBus stuff */
/* void * here to avoid depending on dbus headers outside dbus.c */
@@ -676,7 +680,7 @@ pid_t tcp_pids[MAX_PROCS];
/* cache.c */
void cache_init(void);
void log_query(unsigned short flags, char *name, struct all_addr *addr, char *arg);
char *record_source(struct hostsfile *addn_hosts, int index);
char *record_source(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,
@@ -687,11 +691,12 @@ void cache_end_insert(void);
void cache_start_insert(void);
struct crec *cache_insert(char *name, struct all_addr *addr,
time_t now, unsigned long ttl, unsigned short flags);
void cache_reload(struct hostsfile *addn_hosts);
void cache_reload(void);
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd);
void cache_unhash_dhcp(void);
void dump_cache(time_t now);
char *cache_get_name(struct crec *crecp);
char *get_domain(struct in_addr addr);
/* rfc1035.c */
unsigned short extract_request(HEADER *header, size_t qlen,
@@ -748,7 +753,7 @@ void flush_log(void);
/* option.c */
void read_opts (int argc, char **argv, char *compile_opts);
char *option_string(unsigned char opt);
char *option_string(unsigned char opt, int *is_ip, int *is_name);
void reread_dhcp(void);
/* forward.c */
@@ -760,6 +765,7 @@ void server_gone(struct server *server);
struct frec *get_new_frec(time_t now, int *wait);
/* network.c */
int indextoname(int fd, int index, char *name);
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
int random_sock(int family);
void pre_allocate_sfds(void);
@@ -768,15 +774,14 @@ void check_servers(void);
int enumerate_interfaces();
struct listener *create_wildcard_listeners(void);
struct listener *create_bound_listeners(void);
int iface_check(int family, struct all_addr *addr,
struct ifreq *ifr, int *indexp);
int iface_check(int family, struct all_addr *addr, char *name, int *indexp);
int fix_fd(int fd);
struct in_addr get_ifaddr(char *intr);
/* dhcp.c */
#ifdef HAVE_DHCP
void dhcp_init(void);
void dhcp_packet(time_t now);
char *get_domain(struct in_addr addr);
struct dhcp_context *address_available(struct dhcp_context *context,
struct in_addr addr,
struct dhcp_netid *netids);
@@ -799,8 +804,10 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
char *strip_hostname(char *hostname);
char *host_from_dns(struct in_addr addr);
char *get_domain(struct in_addr addr);
#endif
/* lease.c */
#ifdef HAVE_DHCP
void lease_update_file(time_t now);
void lease_update_dns();
void lease_init(time_t now);
@@ -817,16 +824,21 @@ void lease_prune(struct dhcp_lease *target, time_t now);
void lease_update_from_configs(void);
int do_script_run(time_t now);
void rerun_scripts(void);
#endif
/* rfc2131.c */
#ifdef HAVE_DHCP
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int *is_inform);
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out);
#endif
/* dnsmasq.c */
#ifdef HAVE_DHCP
int make_icmp_sock(void);
int icmp_ping(struct in_addr addr);
#endif
void send_event(int fd, int event, int data);
void clear_cache_and_reload(time_t now);
@@ -855,7 +867,7 @@ void emit_dbus_signal(int action, char *mac, char *hostname, char *addr);
#endif
/* helper.c */
#ifndef NO_FORK
#if defined(HAVE_DHCP) && !defined(NO_FORK)
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,

View File

@@ -667,19 +667,8 @@ void receive_query(struct listener *listen, time_t now)
/* enforce available interface configuration */
if (if_index == 0)
return;
#ifdef SIOCGIFNAME
ifr.ifr_ifindex = if_index;
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
return;
#else
if (!if_indextoname(if_index, ifr.ifr_name))
return;
#endif
if (!iface_check(listen->family, &dst_addr, &ifr, &if_index))
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
!iface_check(listen->family, &dst_addr, ifr.ifr_name, &if_index))
return;
if (listen->family == AF_INET &&

View File

@@ -28,7 +28,7 @@
main process.
*/
#ifndef NO_FORK
#if defined(HAVE_DHCP) && !defined(NO_FORK)
static void my_setenv(const char *name, const char *value, int *error);
@@ -276,28 +276,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
static void my_setenv(const char *name, const char *value, int *error)
{
if (*error == 0)
{
#if defined(HAVE_SOLARIS_NETWORK) && !defined(HAVE_SOLARIS_PRIVS)
/* old Solaris is missing setenv..... */
char *p;
if (!(p = malloc(strlen(name) + strlen(value) + 2)))
*error = ENOMEM;
else
{
strcpy(p, name);
strcat(p, "=");
strcat(p, value);
if (putenv(p) != 0)
*error = errno;
}
#else
if (setenv(name, value, 1) != 0)
*error = errno;
#endif
}
if (*error == 0 && setenv(name, value, 1) != 0)
*error = errno;
}
/* pack up lease data into a buffer */

View File

@@ -16,6 +16,8 @@
#include "dnsmasq.h"
#ifdef HAVE_DHCP
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
static int dns_dirty, file_dirty, leases_left;
@@ -57,7 +59,7 @@ void lease_init(time_t now)
if (!leasestream)
die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
/* a+ mode lease pointer at end. */
/* a+ mode leaves pointer at end. */
rewind(leasestream);
}
@@ -235,7 +237,7 @@ void lease_update_file(time_t now)
if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
next_event = LEASE_RETRY + now;
my_syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"),
my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"),
daemon->lease_file, strerror(err),
(unsigned int)difftime(next_event, now));
}
@@ -607,6 +609,8 @@ int do_script_run(time_t now)
return 0; /* nothing to do */
}
#endif

View File

@@ -248,6 +248,10 @@ static void log_write(void)
}
}
/* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h.
OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between
DNS, DHCP and TFTP services.
*/
void my_syslog(int priority, const char *format, ...)
{
va_list ap;
@@ -256,10 +260,18 @@ void my_syslog(int priority, const char *format, ...)
char *p;
size_t len;
pid_t pid = getpid();
char *func = "";
if ((LOG_FACMASK & priority) == MS_TFTP)
func = "-tftp";
else if ((LOG_FACMASK & priority) == MS_DHCP)
func = "-dhcp";
priority = LOG_PRI(priority);
if (log_stderr)
{
fprintf(stderr, "dnsmasq: ");
fprintf(stderr, "dnsmasq%s: ", func);
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
@@ -305,8 +317,9 @@ void my_syslog(int priority, const char *format, ...)
p = entry->payload;
if (!log_to_file)
p += sprintf(p, "<%d>", priority | log_fac);
p += sprintf(p, "%.15s dnsmasq[%d]: ", ctime(&time_now) + 4, (int)pid);
p += sprintf(p, "%.15s dnsmasq%s[%d]: ", ctime(&time_now) + 4, func, (int)pid);
len = p - entry->payload;
va_start(ap, format);
len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */

View File

@@ -31,6 +31,7 @@
#endif
static struct iovec iov;
static u32 netlink_pid;
static void nl_err(struct nlmsghdr *h);
static void nl_routechange(struct nlmsghdr *h);
@@ -38,6 +39,7 @@ static void nl_routechange(struct nlmsghdr *h);
void netlink_init(void)
{
struct sockaddr_nl addr;
socklen_t slen = sizeof(addr);
addr.nl_family = AF_NETLINK;
addr.nl_pad = 0;
@@ -59,48 +61,63 @@ void netlink_init(void)
}
}
if (daemon->netlinkfd == -1)
if (daemon->netlinkfd == -1 ||
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == 1)
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
/* save pid assigned by bind() and retrieved by getsockname() */
netlink_pid = addr.nl_pid;
iov.iov_len = 200;
iov.iov_len = 100;
iov.iov_base = safe_malloc(iov.iov_len);
}
static ssize_t netlink_recv(void)
{
struct msghdr msg;
struct sockaddr_nl nladdr;
ssize_t rc;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
while (1)
{
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_name = &nladdr;
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
while ((rc = recvmsg(daemon->netlinkfd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
/* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
big buffer and pray in that case. */
if (rc == -1 && errno == EOPNOTSUPP)
while ((rc = recvmsg(daemon->netlinkfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
/* make buffer big enough */
if (rc != -1 && (msg.msg_flags & MSG_TRUNC))
{
if (!expand_buf(&iov, 2000))
return -1;
break;
/* Very new Linux kernels return the actual size needed, older ones always return truncated size */
if ((size_t)rc == iov.iov_len)
{
if (expand_buf(&iov, rc + 100))
continue;
}
else
expand_buf(&iov, rc);
}
if (rc == -1 || !(msg.msg_flags & MSG_TRUNC))
break;
if (!expand_buf(&iov, iov.iov_len + 100))
return -1;
}
/* finally, read it for real */
while ((rc = recvmsg(daemon->netlinkfd, &msg, 0)) == -1 && errno == EINTR);
/* read it for real */
msg.msg_flags = 0;
while ((rc = recvmsg(daemon->netlinkfd, &msg, 0)) == -1 && errno == EINTR);
/* Make sure this is from the kernel */
if (rc == -1 || nladdr.nl_pid == 0)
break;
}
/* discard stuff which is truncated at this point (expand_buf() may fail) */
if (msg.msg_flags & MSG_TRUNC)
{
rc = -1;
errno = ENOMEM;
}
return rc;
}
@@ -141,13 +158,20 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
while (1)
{
if ((len = netlink_recv()) == -1)
return 0;
{
if (errno == ENOBUFS)
{
sleep(1);
goto again;
}
return 0;
}
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
if (h->nlmsg_type == NLMSG_ERROR)
nl_err(h);
else if (h->nlmsg_seq != seq)
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid)
nl_routechange(h); /* May be multicast arriving async */
else if (h->nlmsg_type == NLMSG_ERROR)
nl_err(h);
else if (h->nlmsg_type == NLMSG_DONE)
{
#ifdef HAVE_IPV6
@@ -208,10 +232,17 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
}
}
void netlink_multicast(void)
{
ssize_t len;
struct nlmsghdr *h;
int flags;
/* don't risk blocking reading netlink messages here. */
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
fcntl(daemon->netlinkfd, F_SETFL, flags | O_NONBLOCK) == -1)
return;
if ((len = netlink_recv()) != -1)
{
@@ -221,11 +252,15 @@ void netlink_multicast(void)
else
nl_routechange(h);
}
/* restore non-blocking status */
fcntl(daemon->netlinkfd, F_SETFL, flags);
}
static void nl_err(struct nlmsghdr *h)
{
struct nlmsgerr *err = NLMSG_DATA(h);
if (err->error != 0)
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
}
@@ -234,10 +269,10 @@ static void nl_err(struct nlmsghdr *h)
If this happens and we still have a DNS packet in the buffer, we re-send it.
This helps on DoD links, where frequently the packet which triggers dialling is
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
failing. */
failing. Note that we only accept these messages from the kernel (pid == 0) */
static void nl_routechange(struct nlmsghdr *h)
{
if (h->nlmsg_type == RTM_NEWROUTE)
if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
{
struct rtmsg *rtm = NLMSG_DATA(h);
int fd;

View File

@@ -16,8 +16,37 @@
#include "dnsmasq.h"
int iface_check(int family, struct all_addr *addr,
struct ifreq *ifr, int *indexp)
#ifdef HAVE_LINUX_NETWORK
int indextoname(int fd, int index, char *name)
{
struct ifreq ifr;
if (index == 0)
return 0;
ifr.ifr_ifindex = index;
if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
return 0;
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
return 1;
}
#else
int indextoname(int fd, int index, char *name)
{
if (index == 0 || !if_indextoname(index, name))
return 0;
return 1;
}
#endif
int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
{
struct iname *tmp;
int ret = 1;
@@ -27,7 +56,6 @@ int iface_check(int family, struct all_addr *addr,
if (indexp)
{
#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
@@ -36,26 +64,25 @@ int iface_check(int family, struct all_addr *addr,
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (strncmp(ifr->ifr_name, alias->iface, IF_NAMESIZE) == 0)
if (strncmp(name, alias->iface, IF_NAMESIZE) == 0)
{
int newindex;
if (!(newindex = if_nametoindex(bridge->iface)))
{
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr->ifr_name);
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), name);
return 0;
}
else
{
*indexp = newindex;
strncpy(ifr->ifr_name, bridge->iface, IF_NAMESIZE);
strncpy(name, bridge->iface, IF_NAMESIZE);
break;
}
}
if (alias)
break;
}
#endif
}
if (daemon->if_names || (addr && daemon->if_addrs))
@@ -63,7 +90,7 @@ int iface_check(int family, struct all_addr *addr,
ret = 0;
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = tmp->used = 1;
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
@@ -82,7 +109,7 @@ int iface_check(int family, struct all_addr *addr,
}
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = 0;
return ret;
@@ -103,16 +130,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
if (sockaddr_isequal(&iface->addr, addr))
return 1;
#ifdef HAVE_LINUX_NETWORK
ifr.ifr_ifindex = if_index;
#endif
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
#ifdef HAVE_LINUX_NETWORK
ioctl(fd, SIOCGIFNAME, &ifr) == -1 ||
#else
!if_indextoname(if_index, ifr.ifr_name) ||
#endif
!indextoname(fd, if_index, ifr.ifr_name) ||
ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
{
if (fd != -1)
@@ -150,7 +169,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
}
if (addr->sa.sa_family == AF_INET &&
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, &ifr, NULL))
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
return 1;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
@@ -159,7 +178,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, &ifr, NULL))
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
return 1;
#endif
@@ -217,7 +236,6 @@ static int iface_allowed_v4(struct in_addr local, int if_index,
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
}
int enumerate_interfaces(void)
{
#ifdef HAVE_IPV6
@@ -529,7 +547,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
#if defined(SO_BINDTODEVICE)
if (intname[0] != 0 &&
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, sizeof(intname)) == -1)
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, strlen(intname)) == -1)
return 0;
#endif

View File

@@ -19,6 +19,10 @@
#include "dnsmasq.h"
#include <setjmp.h>
static volatile int mem_recover = 0;
static jmp_buf mem_jmp;
static void one_file(char *file, int nest, int hard_opt);
/* Solaris headers don't have facility names. */
#ifdef HAVE_SOLARIS_NETWORK
static const struct {
@@ -34,10 +38,7 @@ static const struct {
{ "lpr", LOG_LPR },
{ "news", LOG_NEWS },
{ "uucp", LOG_UUCP },
#ifdef LOG_AUDIT
/* Not Solaris < 10 */
{ "audit", LOG_AUDIT },
#endif
{ "cron", LOG_CRON },
{ "local0", LOG_LOCAL0 },
{ "local1", LOG_LOCAL1 },
@@ -98,6 +99,9 @@ struct myoption {
#define LOPT_MINPORT 288
#define LOPT_DHCP_FQDN 289
#define LOPT_CNAME 290
#define LOPT_PXE_PROMT 291
#define LOPT_PXE_SERV 292
#define LOPT_TEST 293
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -105,105 +109,106 @@ static const struct option opts[] =
static const struct myoption opts[] =
#endif
{
{"version", 0, 0, 'v'},
{"no-hosts", 0, 0, 'h'},
{"no-poll", 0, 0, 'n'},
{"help", 0, 0, 'w'},
{"no-daemon", 0, 0, 'd'},
{"log-queries", 0, 0, 'q'},
{"user", 2, 0, 'u'},
{"group", 2, 0, 'g'},
{"resolv-file", 2, 0, 'r'},
{"mx-host", 1, 0, 'm'},
{"mx-target", 1, 0, 't'},
{"cache-size", 2, 0, 'c'},
{"port", 1, 0, 'p'},
{"dhcp-leasefile", 2, 0, 'l'},
{"dhcp-lease", 1, 0, 'l' },
{"dhcp-host", 1, 0, 'G'},
{"dhcp-range", 1, 0, 'F'},
{"dhcp-option", 1, 0, 'O'},
{"dhcp-boot", 1, 0, 'M'},
{"domain", 1, 0, 's'},
{"domain-suffix", 1, 0, 's'},
{"interface", 1, 0, 'i'},
{"listen-address", 1, 0, 'a'},
{"bogus-priv", 0, 0, 'b'},
{"bogus-nxdomain", 1, 0, 'B'},
{"selfmx", 0, 0, 'e'},
{"filterwin2k", 0, 0, 'f'},
{"pid-file", 2, 0, 'x'},
{"strict-order", 0, 0, 'o'},
{"server", 1, 0, 'S'},
{"local", 1, 0, LOPT_LOCAL },
{"address", 1, 0, 'A' },
{"conf-file", 2, 0, 'C'},
{"no-resolv", 0, 0, 'R'},
{"expand-hosts", 0, 0, 'E'},
{"localmx", 0, 0, 'L'},
{"local-ttl", 1, 0, 'T'},
{"no-negcache", 0, 0, 'N'},
{"addn-hosts", 1, 0, 'H'},
{"query-port", 1, 0, 'Q'},
{"except-interface", 1, 0, 'I'},
{"no-dhcp-interface", 1, 0, '2'},
{"domain-needed", 0, 0, 'D'},
{"dhcp-lease-max", 1, 0, 'X' },
{"bind-interfaces", 0, 0, 'z'},
{"read-ethers", 0, 0, 'Z' },
{"alias", 1, 0, 'V' },
{"dhcp-vendorclass", 1, 0, 'U'},
{"dhcp-userclass", 1, 0, 'j'},
{"dhcp-ignore", 1, 0, 'J'},
{"edns-packet-max", 1, 0, 'P'},
{"keep-in-foreground", 0, 0, 'k'},
{"dhcp-authoritative", 0, 0, 'K'},
{"srv-host", 1, 0, 'W'},
{"localise-queries", 0, 0, 'y'},
{"txt-record", 1, 0, 'Y'},
{"enable-dbus", 0, 0, '1'},
{"bootp-dynamic", 2, 0, '3'},
{"dhcp-mac", 1, 0, '4'},
{"no-ping", 0, 0, '5'},
{"dhcp-script", 1, 0, '6'},
{"conf-dir", 1, 0, '7'},
{"log-facility", 1, 0 ,'8'},
{"leasefile-ro", 0, 0, '9'},
{"dns-forward-max", 1, 0, '0'},
{"clear-on-reload", 0, 0, LOPT_RELOAD },
{"dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
{"enable-tftp", 0, 0, LOPT_TFTP },
{"tftp-secure", 0, 0, LOPT_SECURE },
{"tftp-unique-root", 0, 0, LOPT_APREF },
{"tftp-root", 1, 0, LOPT_PREFIX },
{"tftp-max", 1, 0, LOPT_TFTP_MAX },
{"ptr-record", 1, 0, LOPT_PTR },
{"naptr-record", 1, 0, LOPT_NAPTR },
#ifdef HAVE_BSD_BRIDGE
{"bridge-interface", 1, 0 , LOPT_BRIDGE },
#endif
{"dhcp-option-force", 1, 0, LOPT_FORCE },
{"tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
{"log-dhcp", 0, 0, LOPT_LOG_OPTS },
{"log-async", 2, 0, LOPT_MAX_LOGS },
{"dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
{"dhcp-remoteid", 1, 0, LOPT_REMOTE },
{"dhcp-subscrid", 1, 0, LOPT_SUBSCR },
{"interface-name", 1, 0, LOPT_INTNAME },
{"dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{"dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
{"dhcp-no-override", 0, 0, LOPT_OVERRIDE },
{"tftp-port-range", 1, 0, LOPT_TFTPPORTS },
{"stop-dns-rebind", 0, 0, LOPT_REBIND },
{"all-servers", 0, 0, LOPT_NOLAST},
{"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 },
{"dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
{"cname", 1, 0, LOPT_CNAME },
{ "version", 0, 0, 'v' },
{ "no-hosts", 0, 0, 'h' },
{ "no-poll", 0, 0, 'n' },
{ "help", 0, 0, 'w' },
{ "no-daemon", 0, 0, 'd' },
{ "log-queries", 0, 0, 'q' },
{ "user", 2, 0, 'u' },
{ "group", 2, 0, 'g' },
{ "resolv-file", 2, 0, 'r' },
{ "mx-host", 1, 0, 'm' },
{ "mx-target", 1, 0, 't' },
{ "cache-size", 2, 0, 'c' },
{ "port", 1, 0, 'p' },
{ "dhcp-leasefile", 2, 0, 'l' },
{ "dhcp-lease", 1, 0, 'l' },
{ "dhcp-host", 1, 0, 'G' },
{ "dhcp-range", 1, 0, 'F' },
{ "dhcp-option", 1, 0, 'O' },
{ "dhcp-boot", 1, 0, 'M' },
{ "domain", 1, 0, 's' },
{ "domain-suffix", 1, 0, 's' },
{ "interface", 1, 0, 'i' },
{ "listen-address", 1, 0, 'a' },
{ "bogus-priv", 0, 0, 'b' },
{ "bogus-nxdomain", 1, 0, 'B' },
{ "selfmx", 0, 0, 'e' },
{ "filterwin2k", 0, 0, 'f' },
{ "pid-file", 2, 0, 'x' },
{ "strict-order", 0, 0, 'o' },
{ "server", 1, 0, 'S' },
{ "local", 1, 0, LOPT_LOCAL },
{ "address", 1, 0, 'A' },
{ "conf-file", 2, 0, 'C' },
{ "no-resolv", 0, 0, 'R' },
{ "expand-hosts", 0, 0, 'E' },
{ "localmx", 0, 0, 'L' },
{ "local-ttl", 1, 0, 'T' },
{ "no-negcache", 0, 0, 'N' },
{ "addn-hosts", 1, 0, 'H' },
{ "query-port", 1, 0, 'Q' },
{ "except-interface", 1, 0, 'I' },
{ "no-dhcp-interface", 1, 0, '2' },
{ "domain-needed", 0, 0, 'D' },
{ "dhcp-lease-max", 1, 0, 'X' },
{ "bind-interfaces", 0, 0, 'z' },
{ "read-ethers", 0, 0, 'Z' },
{ "alias", 1, 0, 'V' },
{ "dhcp-vendorclass", 1, 0, 'U' },
{ "dhcp-userclass", 1, 0, 'j' },
{ "dhcp-ignore", 1, 0, 'J' },
{ "edns-packet-max", 1, 0, 'P' },
{ "keep-in-foreground", 0, 0, 'k' },
{ "dhcp-authoritative", 0, 0, 'K' },
{ "srv-host", 1, 0, 'W' },
{ "localise-queries", 0, 0, 'y' },
{ "txt-record", 1, 0, 'Y' },
{ "enable-dbus", 0, 0, '1' },
{ "bootp-dynamic", 2, 0, '3' },
{ "dhcp-mac", 1, 0, '4' },
{ "no-ping", 0, 0, '5' },
{ "dhcp-script", 1, 0, '6' },
{ "conf-dir", 1, 0, '7' },
{ "log-facility", 1, 0 ,'8' },
{ "leasefile-ro", 0, 0, '9' },
{ "dns-forward-max", 1, 0, '0' },
{ "clear-on-reload", 0, 0, LOPT_RELOAD },
{ "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
{ "enable-tftp", 0, 0, LOPT_TFTP },
{ "tftp-secure", 0, 0, LOPT_SECURE },
{ "tftp-unique-root", 0, 0, LOPT_APREF },
{ "tftp-root", 1, 0, LOPT_PREFIX },
{ "tftp-max", 1, 0, LOPT_TFTP_MAX },
{ "ptr-record", 1, 0, LOPT_PTR },
{ "naptr-record", 1, 0, LOPT_NAPTR },
{ "bridge-interface", 1, 0 , LOPT_BRIDGE },
{ "dhcp-option-force", 1, 0, LOPT_FORCE },
{ "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
{ "log-dhcp", 0, 0, LOPT_LOG_OPTS },
{ "log-async", 2, 0, LOPT_MAX_LOGS },
{ "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
{ "dhcp-remoteid", 1, 0, LOPT_REMOTE },
{ "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
{ "interface-name", 1, 0, LOPT_INTNAME },
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
{ "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
{ "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
{ "all-servers", 0, 0, LOPT_NOLAST },
{ "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 },
{ "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
{ "cname", 1, 0, LOPT_CNAME },
{ "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
{ "pxe-service", 1, 0, LOPT_PXE_SERV },
{ "test", 0, 0, LOPT_TEST },
{ NULL, 0, 0, 0 }
};
@@ -287,9 +292,7 @@ static struct {
{ '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
{ '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
#ifdef HAVE_BSD_BRIDGE
{ LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
#endif
{ '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 },
@@ -317,13 +320,18 @@ static struct {
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
{ 0, 0, NULL, NULL, NULL }
};
#ifdef HAVE_DHCP
/* makes options which take a list of addresses */
#define OT_ADDR_LIST 255
#define OT_ADDR_LIST 0x80
/* DHCP-internal options, for logging. not valid in config file */
#define OT_INTERNAL 254
#define OT_INTERNAL 0x40
#define OT_NAME 0x20
static const struct {
char *name;
@@ -335,9 +343,9 @@ static const struct {
{ "dns-server", 6, OT_ADDR_LIST },
{ "log-server", 7, OT_ADDR_LIST },
{ "lpr-server", 9, OT_ADDR_LIST },
{ "hostname", 12, OT_INTERNAL },
{ "hostname", 12, OT_INTERNAL | OT_NAME },
{ "boot-file-size", 13, 2 },
{ "domain-name", 15, 0 },
{ "domain-name", 15, OT_NAME },
{ "swap-server", 16, OT_ADDR_LIST },
{ "root-path", 17, 0 },
{ "extension-path", 18, 0 },
@@ -348,7 +356,7 @@ static const struct {
{ "default-ttl", 23, 1 },
{ "mtu", 26, 2 },
{ "all-subnets-local", 27, 1 },
{ "broadcast", 28, OT_INTERNAL },
{ "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
{ "router-discovery", 31, 1 },
{ "router-solicitation", 32, OT_ADDR_LIST },
{ "static-route", 33, OT_ADDR_LIST },
@@ -367,11 +375,11 @@ static const struct {
{ "netbios-scope", 47, 0 },
{ "x-windows-fs", 48, OT_ADDR_LIST },
{ "x-windows-dm", 49, OT_ADDR_LIST },
{ "requested-address", 50, OT_INTERNAL },
{ "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
{ "lease-time", 51, OT_INTERNAL },
{ "option-overload", 52, OT_INTERNAL },
{ "message-type", 53, OT_INTERNAL, },
{ "server-identifier", 54, OT_INTERNAL },
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
{ "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL },
@@ -401,21 +409,25 @@ static const struct {
{ NULL, 0, 0 }
};
static volatile int mem_recover = 0;
static jmp_buf mem_jmp;
static void one_file(char *file, int nest, int hard_opt);
char *option_string(unsigned char opt)
char *option_string(unsigned char opt, int *is_ip, int *is_name)
{
int i;
for (i = 0; opttab[i].name; i++)
if (opttab[i].val == opt)
return opttab[i].name;
{
if (is_ip)
*is_ip = !!(opttab[i].size & OT_ADDR_LIST);
if (is_name)
*is_name = !!(opttab[i].size & OT_NAME);
return opttab[i].name;
}
return NULL;
}
#endif
/* We hide metacharaters in quoted strings by mapping them into the ASCII control
character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
following sequence so that they map to themselves: it is therefore possible to call
@@ -626,6 +638,7 @@ static void do_usage(void)
}
}
#ifdef HAVE_DHCP
static void display_opts(void)
{
int i;
@@ -760,7 +773,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
/* We know that some options take addresses */
if (opt_len == OT_ADDR_LIST)
if (opt_len & OT_ADDR_LIST)
{
is_string = is_dec = is_hex = 0;
if (!is_addr || dots == 0)
@@ -919,7 +932,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
}
}
if (new->len > 255)
if ((new->len > 255) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
problem = _("dhcp-option too long");
if (!problem)
@@ -946,6 +959,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
return problem;
}
#endif
static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{
@@ -1013,20 +1027,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
while ((ent = readdir(dir_stream)))
{
size_t len;
size_t len = strlen(ent->d_name);
struct stat buf;
if ((len = strlen(ent->d_name)) == 0)
continue;
/* ignore emacs backups and dotfiles */
if (ent->d_name[len - 1] == '~' ||
if (len == 0 ||
ent->d_name[len - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
ent->d_name[0] == '.')
continue;
path = opt_malloc(strlen(directory) + len + 2);
strcpy(path, directory);
strcat(path, "/");
strcat(path, ent->d_name);
if (stat(path, &buf) == -1)
die(_("cannot access %s: %s"), path, EC_FILE);
/* only reg files allowed. */
@@ -1139,25 +1154,28 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
else
daemon->mxtarget = opt_string_alloc(arg);
break;
#ifdef HAVE_DHCP
case 'l': /* --dhcp-leasefile */
daemon->lease_file = opt_string_alloc(arg);
break;
case '6': /* --dhcp-script */
#ifdef NO_FORK
# ifdef NO_FORK
problem = _("cannot run scripts under uClinux");
#else
# else
daemon->lease_change_command = opt_string_alloc(arg);
#endif
# endif
break;
#endif
case 'H': /* --addn-hosts */
{
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
static int hosts_index = 1;
new->fname = opt_string_alloc(arg);
new->index = hosts_index++;
new->flags = 0;
new->next = daemon->addn_hosts;
daemon->addn_hosts = new;
break;
@@ -1219,9 +1237,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
daemon->group_set = 1;
break;
#ifdef HAVE_DHCP
case LOPT_SCRIPTUSR: /* --scriptuser */
daemon->scriptuser = opt_string_alloc(arg);
break;
#endif
case 'i': /* --interface */
do {
@@ -1520,11 +1540,14 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
break;
}
#ifdef HAVE_DHCP
case 'X': /* --dhcp-lease-max */
if (!atoi_check(arg, &daemon->dhcp_max))
option = '?';
break;
#endif
#ifdef HAVE_TFTP
case LOPT_TFTP_MAX: /* --tftp-max */
if (!atoi_check(arg, &daemon->tftp_max))
option = '?';
@@ -1548,8 +1571,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
}
break;
#endif
#ifdef HAVE_BSD_BRIDGE
case LOPT_BRIDGE: /* --bridge-interface */
{
struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
@@ -1578,8 +1601,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
break;
}
#endif
#ifdef HAVE_DHCP
case 'F': /* --dhcp-range */
{
int k, leasepos = 2;
@@ -1646,6 +1669,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->end = new->start;
new->flags |= CONTEXT_STATIC;
}
else if (strcmp(a[1], "proxy") == 0)
{
new->end = new->start;
new->flags |= CONTEXT_PROXY;
}
else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
option = '?';
@@ -1916,7 +1944,122 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
break;
}
case LOPT_PXE_PROMT: /* --pxe-prompt */
{
struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
int timeout;
new->netid = NULL;
new->opt = 10; /* PXE_MENU_PROMPT */
while (arg && strstr(arg, "net:") == arg)
{
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
comma = split(arg);
nn->next = new->netid;
new->netid = nn;
nn->net = opt_string_alloc(arg+4);
arg = comma;
}
if (!arg)
option = '?';
else
{
comma = split(arg);
unhide_metas(arg);
new->len = strlen(arg) + 1;
new->val = opt_malloc(new->len);
memcpy(new->val + 1, arg, new->len - 1);
new->u.vendor_class = (unsigned char *)"PXEClient";
new->flags = DHOPT_VENDOR;
if (comma && atoi_check(comma, &timeout))
*(new->val) = timeout;
else
*(new->val) = 255;
new->next = daemon->dhcp_opts;
daemon->dhcp_opts = new;
}
break;
}
case LOPT_PXE_SERV: /* --pxe-service */
{
struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
"IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
static int boottype = 32768;
new->netid = NULL;
new->server.s_addr = 0;
while (arg && strstr(arg, "net:") == arg)
{
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
comma = split(arg);
nn->next = new->netid;
new->netid = nn;
nn->net = opt_string_alloc(arg+4);
arg = comma;
}
if (arg && (comma = split(arg)))
{
for (i = 0; CSA[i]; i++)
if (strcasecmp(CSA[i], arg) == 0)
break;
if (CSA[i] || atoi_check(arg, &i))
{
arg = comma;
comma = split(arg);
new->CSA = i;
new->menu = opt_string_alloc(arg);
if (comma)
{
arg = comma;
comma = split(arg);
if (atoi_check(arg, &i))
{
new->type = i;
new->basename = NULL;
}
else
{
new->type = boottype++;
new->basename = opt_string_alloc(arg);
}
if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
option = '?';
/* Order matters */
new->next = NULL;
if (!daemon->pxe_services)
daemon->pxe_services = new;
else
{
struct pxe_service *s;
for (s = daemon->pxe_services; s->next; s = s->next);
s->next = new;
}
break;
}
}
}
option = '?';
break;
}
case '4': /* --dhcp-mac */
{
if (!(comma = split(arg)))
@@ -2058,6 +2201,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->list = list;
break;
}
#endif
case 'V': /* --alias */
{
@@ -2311,6 +2455,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->weight = weight;
break;
}
default:
return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
}
if (problem)
@@ -2328,10 +2476,32 @@ static void one_file(char *file, int nest, int hard_opt)
int i, option;
FILE *f;
char *p, *arg, *start, *buff = daemon->namebuff;
static struct fileread {
dev_t dev;
ino_t ino;
struct fileread *next;
} *filesread = NULL;
struct stat statbuf;
/* ignore repeated files. */
if (hard_opt == 0 && stat(file, &statbuf) == 0)
{
struct fileread *r;
for (r = filesread; r; r = r->next)
if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
return;
r = safe_malloc(sizeof(struct fileread));
r->next = filesread;
filesread = r;
r->dev = statbuf.st_dev;
r->ino = statbuf.st_ino;
}
if (nest > 20)
die(_("files nested too deep in %s"), file, EC_BADCONF);
if (!(f = fopen(file, "r")))
{
if (errno == ENOENT && nest == 0)
@@ -2476,6 +2646,7 @@ static void one_file(char *file, int nest, int hard_opt)
fclose(f);
}
#ifdef HAVE_DHCP
void reread_dhcp(void)
{
if (daemon->dhcp_hosts_file)
@@ -2546,11 +2717,12 @@ void reread_dhcp(void)
my_syslog(LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
}
}
#endif
void read_opts(int argc, char **argv, char *compile_opts)
{
char *buff = opt_malloc(MAXDNAME);
int option, nest = 0;
int option, nest = 0, testmode = 0;
char *errmess, *arg, *conffile = CONFFILE;
opterr = 0;
@@ -2600,12 +2772,16 @@ void read_opts(int argc, char **argv, char *compile_opts)
arg = NULL;
/* command-line only stuff */
if (option == 'w')
if (option == LOPT_TEST)
testmode = 1;
else if (option == 'w')
{
if (argc == 3 && strcmp(argv[2], "dhcp") == 0)
display_opts();
else
if (argc != 3 || strcmp(argv[2], "dhcp") != 0)
do_usage();
#ifdef HAVE_DHCP
else
display_opts();
#endif
exit(0);
}
else if (option == 'v')
@@ -2752,4 +2928,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
}
else if (daemon->options & OPT_DHCP_FQDN)
die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
if (testmode)
{
fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
exit(0);
}
}

View File

@@ -1290,7 +1290,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
if (!dryrun)
{
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
record_source(daemon->addn_hosts, crecp->uid));
record_source(crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), NULL,
@@ -1400,7 +1400,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
{
if (!dryrun)
{
log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid));
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), &nameoffset,
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
@@ -1436,7 +1436,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
if (!dryrun)
{
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
record_source(daemon->addn_hosts, crecp->uid));
record_source(crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), NULL, type, C_IN,

File diff suppressed because it is too large Load Diff

View File

@@ -45,9 +45,7 @@ void tftp_request(struct listener *listen, time_t now)
char *filename, *mode, *p, *end, *opt;
struct sockaddr_in addr, peer;
struct msghdr msg;
struct cmsghdr *cmptr;
struct iovec iov;
struct ifreq ifr;
int is_err = 1, if_index = 0;
struct iname *tmp;
struct tftp_transfer *transfer;
@@ -62,7 +60,7 @@ void tftp_request(struct listener *listen, time_t now)
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
#elif defined(HAVE_SOLARIS_NETWORK)
char control[CMSG_SPACE(sizeof(unsigned int))];
#else
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
@@ -88,6 +86,9 @@ void tftp_request(struct listener *listen, time_t now)
addr = listen->iface->addr.in;
else
{
char name[IF_NAMESIZE];
struct cmsghdr *cmptr;
addr.sin_addr.s_addr = 0;
#if defined(HAVE_LINUX_NETWORK)
@@ -97,36 +98,32 @@ void tftp_request(struct listener *listen, time_t now)
addr.sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
}
if (!(ifr.ifr_ifindex = if_index) ||
ioctl(listen->tftpfd, SIOCGIFNAME, &ifr) == -1)
return;
#elif defined(HAVE_SOLARIS_NETWORK)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_index = *((unsigned int *)CMSG_DATA(cmptr));
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
#ifdef HAVE_SOLARIS_NETWORK
if_index = *((unsigned int *)CMSG_DATA(cmptr));
#else
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
#endif
if (if_index == 0 || !if_indextoname(if_index, ifr.ifr_name))
return;
#endif
if (addr.sin_addr.s_addr == 0)
return;
if (!iface_check(AF_INET, (struct all_addr *)&addr.sin_addr,
&ifr, &if_index))
if (!indextoname(listen->tftpfd, if_index, name) ||
addr.sin_addr.s_addr == 0 ||
!iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index))
return;
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
if (tmp->name && (strcmp(tmp->name, name) == 0))
return;
}
@@ -172,7 +169,7 @@ void tftp_request(struct listener *listen, time_t now)
addr.sin_port = htons(port);
continue;
}
my_syslog(LOG_ERR, _("unable to get free port for TFTP"));
my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
}
free_transfer(transfer);
return;
@@ -268,7 +265,7 @@ void tftp_request(struct listener *listen, time_t now)
free_transfer(transfer);
else
{
my_syslog(LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
my_syslog(MS_TFTP | LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
transfer->next = daemon->tftp_trans;
daemon->tftp_trans = transfer;
}
@@ -402,7 +399,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
*(q++) = *r;
*q = 0;
}
my_syslog(LOG_ERR, _("TFTP error %d %s received from %s"),
my_syslog(MS_TFTP | LOG_ERR, _("TFTP error %d %s received from %s"),
(int)ntohs(mess->block), err,
inet_ntoa(transfer->peer.sin_addr));
@@ -433,7 +430,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
/* don't complain about timeout when we're awaiting the last
ACK, some clients never send it */
if (len != 0)
my_syslog(LOG_ERR, _("TFTP failed sending %s to %s"),
my_syslog(MS_TFTP | LOG_ERR, _("TFTP failed sending %s to %s"),
transfer->file->filename, inet_ntoa(transfer->peer.sin_addr));
len = 0;
}
@@ -493,7 +490,7 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
mess->err = htons(err);
ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
if (err != ERR_FNF)
my_syslog(LOG_ERR, "TFTP %s", mess->message);
my_syslog(MS_TFTP | LOG_ERR, "TFTP %s", mess->message);
return ret;
}

View File

@@ -15,7 +15,7 @@
*/
/* The SURF random number generator was taken from djbdns-1.05, by
Daniel J Berstein, which is public domain. */
Daniel J Bernstein, which is public domain. */
#include "dnsmasq.h"
@@ -344,14 +344,19 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
return i;
}
/* return 0 for no match, or (no matched octets) + 1 */
int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
{
int i;
for (i = len - 1; i >= 0; i--, mask = mask >> 1)
if (!(mask & 1) && a[i] != b[i])
return 0;
return 1;
int i, count;
for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
if (!(mask & 1))
{
if (a[i] == b[i])
count++;
else
return 0;
}
return count;
}
/* _note_ may copy buffer */