Compare commits

...
2 Commits
Author SHA1 Message Date
Simon Kelley 1f15b81d61 import of dnsmasq-2.51.tar.gz 2012-01-05 17:31:14 +00:00
Simon Kelley 77e94da7bb import of dnsmasq-2.50.tar.gz 2012-01-05 17:31:14 +00:00
34 changed files with 2761 additions and 2211 deletions

No files matched your search

+93
View File
@@ -1,3 +1,91 @@
version 2.51
Add support for internationalised DNS. Non-ASCII characters
in domain names found in /etc/hosts, /etc/ethers and
/etc/dnsmasq.conf will be correctly handled by translation to
punycode, as specified in RFC3490. This function is only
available if dnsmasq is compiled with internationalisation
support, and adds a dependency on GNU libidn. Without i18n
support, dnsmasq continues to be compilable with just
standard tools. Thanks to Yves Dorfsman for the
suggestion.
Add two more environment variables for lease-change scripts:
First, DNSMASQ_SUPPLIED_HOSTNAME; this is set to the hostname
supplied by a client, even if the actual hostname used is
over-ridden by dhcp-host or dhcp-ignore-names directives.
Also DNSMASQ_RELAY_ADDRESS which gives the address of
a DHCP relay, if used.
Suggestions from Michael Rack.
Fix regression which broke echo of relay-agent
options. Thanks to Michael Rack for spotting this.
Don't treat option 67 as being interchangeable with
dhcp-boot parameters if it's specified as
dhcp-option-force.
Make the code to call scripts on lease-change compile-time
optional. It can be switched off by editing src/config.h
or building with "make COPTS=-DNO_SCRIPT".
Make the TFTP server cope with filenames from Windows/DOS
which use '\' as pathname separator. Thanks to Ralf for
the patch.
Updated Polish translation. Thanks to Jan Psota.
Warn if an IP address is duplicated in /etc/ethers. Thanks
to Felix Schwarz for pointing this out.
Teach --conf-dir to take an option list of file suffices
which will be ignored when scanning the directory. Useful
for backup files etc. Thanks to Helmut Hullen for the
suggestion.
Add new DHCP option named tftpserver-address, which
corresponds to the third argument of dhcp-boot. This
allows the complete functionality of dhcp-boot to be
replicated with dhcp-option. Useful when using
dhcp-optsfile.
Test which upstream nameserver to use every 10 seconds
or 50 queries and not just when a query times out and
is retried. This should improve performance when there
is a slow nameserver in the list. Thanks to Joe for the
suggestion.
Don't do any PXE processing, even for clients with the
correct vendorclass, unless at least one pxe-prompt or
pxe-service option is given. This stops dnsmasq
interfering with proxy PXE subsystems when it is just
the DHCP server. Thanks to Spencer Clark for spotting this.
Limit the blocksize used for TFTP transfers to a value
which avoids packet fragmentation, based on the MTU of the
local interface. Many netboot ROMs can't cope with
fragmented packets.
Honour dhcp-ignore configuration for PXE and proxy-PXE
requests. Thanks to Niels Basjes for the bug report.
Updated French translation. Thanks to Gildas Le Nadan.
version 2.50
Fix security problem which allowed any host permitted to
do TFTP to possibly compromise dnsmasq by remote buffer
overflow when TFTP enabled. Thanks to Core Security
Technologies and Iván Arce, Pablo Hernán Jorge, Alejandro
Pablo Rodriguez, Martín Coco, Alberto Soliño Testa and
Pablo Annetta. This problem has Bugtraq id: 36121
and CVE: 2009-2957
Fix a problem which allowed a malicious TFTP client to
crash dnsmasq. Thanks to Steve Grubb at Red Hat for
spotting this. This problem has Bugtraq id: 36120 and
CVE: 2009-2958
version 2.49 version 2.49
Fix regression in 2.48 which disables the lease-change Fix regression in 2.48 which disables the lease-change
script. Thanks to Jose Luis Duran for spotting this. script. Thanks to Jose Luis Duran for spotting this.
@@ -343,3 +431,8 @@ version 2.43
ports. Thanks to Patrick McLean for spotting this. ports. Thanks to Patrick McLean for spotting this.
Updated French translation. Thanks to Gildas Le Nadan. Updated French translation. Thanks to Gildas Le Nadan.
version 2.42
The changelog for version 2.42 and earlier is
available in CHANGELOG.archive.
+23 -18
View File
@@ -24,18 +24,22 @@ MAN = man
PKG_CONFIG = pkg-config PKG_CONFIG = pkg-config
INSTALL = install INSTALL = install
MSGMERGE = msgmerge
MSGFMT = msgfmt
XGETTEXT = xgettext
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_LIBS=" `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi `" DNSMASQ_CFLAGS=`echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
DNSMASQ_LIBS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
SUNOS_LIBS= `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi`
all : dnsmasq all : dnsmasq
dnsmasq : dnsmasq :
cd $(SRC) && $(MAKE) \ @cd $(SRC) && $(MAKE) \
DBUS_CFLAGS=$(DBUS_CFLAGS) \ DNSMASQ_CFLAGS="$(DNSMASQ_CFLAGS)" \
DBUS_LIBS=$(DBUS_LIBS) \ DNSMASQ_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS)" \
SUNOS_LIBS=$(SUNOS_LIBS) \
-f ../bld/Makefile dnsmasq -f ../bld/Makefile dnsmasq
clean : clean :
@@ -50,24 +54,25 @@ install-common :
$(INSTALL) -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR)
all-i18n : all-i18n :
cd $(SRC) && $(MAKE) \ @cd $(SRC) && $(MAKE) \
I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \ I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \
DBUS_CFLAGS=$(DBUS_CFLAGS) \ DNSMASQ_CFLAGS="$(DNSMASQ_CFLAGS) `$(PKG_CONFIG) --cflags libidn`" \
DBUS_LIBS=$(DBUS_LIBS) \ DNSMASQ_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS) `$(PKG_CONFIG) --libs libidn`" \
SUNOS_LIBS=$(SUNOS_LIBS) \
-f ../bld/Makefile dnsmasq -f ../bld/Makefile dnsmasq
cd $(PO); for f in *.po; do \ @cd $(PO); for f in *.po; do \
cd ../$(SRC) && $(MAKE) -f ../bld/Makefile $${f%.po}.mo; \ cd ../$(SRC) && $(MAKE) \
MSGMERGE=$(MSGMERGE) MSGFMT=$(MSGFMT) XGETTEXT=$(XGETTEXT) \
-f ../bld/Makefile $${f%.po}.mo; \
done done
install-i18n : all-i18n install-common install-i18n : all-i18n install-common
cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR) cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
merge : merge :
$(MAKE) I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' -f ../bld/Makefile -C $(SRC) dnsmasq.pot @cd $(SRC) && $(MAKE) XGETTEXT=$(XGETTEXT) -f ../bld/Makefile dnsmasq.pot
cd $(PO); for f in *.po; do \ @cd $(PO); for f in *.po; do \
msgmerge --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \ echo -n msgmerge $$f && $(MSGMERGE) --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
done done
+4 -4
View File
@@ -5,13 +5,13 @@ OBJS = cache.o rfc1035.o util.o option.o forward.o network.o \
helper.o tftp.o log.o helper.o tftp.o log.o
.c.o: .c.o:
$(CC) $(CFLAGS) $(COPTS) $(DBUS_MINOR) $(I18N) $(DBUS_CFLAGS) $(SUNOS_VER) $(RPM_OPT_FLAGS) -c $< $(CC) $(CFLAGS) $(COPTS) $(I18N) $(DNSMASQ_CFLAGS) $(RPM_OPT_FLAGS) -c $<
dnsmasq : $(OBJS) dnsmasq : $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(DBUS_LIBS) $(SUNOS_LIBS) $(LIBS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(DNSMASQ_LIBS) $(LIBS)
dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h
xgettext -d dnsmasq --foreign-user --keyword=_ -o dnsmasq.pot -i $(OBJS:.o=.c) $(XGETTEXT) -d dnsmasq --foreign-user --omit-header --keyword=_ -o $@ -i $(OBJS:.o=.c)
%.mo : ../po/%.po dnsmasq.pot %.mo : ../po/%.po dnsmasq.pot
msgmerge -o - ../po/$*.po dnsmasq.pot | msgfmt -o $*.mo - $(MSGMERGE) -o - ../po/$*.po dnsmasq.pot | $(MSGFMT) -o $*.mo -
+2 -2
View File
@@ -2,8 +2,8 @@
for f in *; do for f in *; do
if [ -d $f ]; then if [ -d $f ]; then
install -m 755 -d $1/$f/man8 $2 -m 755 -d $1/$f/man8
install -m 644 $f/dnsmasq.8 $1/$f/man8 $2 -m 644 $f/dnsmasq.8 $1/$f/man8
echo installing $1/$f/man8/dnsmasq.8 echo installing $1/$f/man8/dnsmasq.8
fi fi
done done
+2 -2
View File
@@ -1,8 +1,8 @@
#!/bin/sh #!/bin/sh
for f in *.mo; do for f in *.mo; do
install -m 755 -d $1/${f%.mo}/LC_MESSAGES $2 -m 755 -d $1/${f%.mo}/LC_MESSAGES
install -m 644 $f $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo $2 -m 644 $f $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
echo installing $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo echo installing $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
done done
+5 -2
View File
@@ -1,7 +1,10 @@
#!/bin/sh #!/bin/sh
if grep "^\#.*define.*HAVE_DBUS" config.h 2>&1 >/dev/null || \ search=$1
grep HAVE_DBUS 2>&1 >/dev/null ; then shift
if grep "^\#.*define.*$search" config.h 2>&1 >/dev/null || \
grep $search 2>&1 >/dev/null ; then
exec $* exec $*
fi fi
+5
View File
@@ -396,6 +396,11 @@
# the user dnsmasq is running as will be send over the net. # the user dnsmasq is running as will be send over the net.
#tftp-secure #tftp-secure
# This option stops dnsmasq from negotiating a larger blocksize for TFTP
# transfers. It will slow things down, but may rescue some broken TFTP
# clients.
#tftp-no-blocksize
# Set the boot file name only when the "red" tag is set. # Set the boot file name only when the "red" tag is set.
#dhcp-boot=net:red,pxelinux.red-net #dhcp-boot=net:red,pxelinux.red-net
+35 -8
View File
@@ -45,7 +45,8 @@ additional hosts file. If a directory is given, then read all the files containe
.TP .TP
.B \-E, --expand-hosts .B \-E, --expand-hosts
Add the domain to simple names (without a period) in /etc/hosts Add the domain to simple names (without a period) in /etc/hosts
in the same way as for DHCP-derived names. in the same way as for DHCP-derived names. Note that this does not
apply to domain names in cnames, PTR records, TXT records etc.
.TP .TP
.B \-T, --local-ttl=<time> .B \-T, --local-ttl=<time>
When replying with information from /etc/hosts or the DHCP leases When replying with information from /etc/hosts or the DHCP leases
@@ -547,7 +548,12 @@ the file will be re-read when dnsmasq receives SIGHUP.
.B --dhcp-optsfile=<file> .B --dhcp-optsfile=<file>
Read DHCP option information from the specified file. The advantage of Read DHCP option information from the specified file. The advantage of
using this option is the same as for --dhcp-hostsfile: the using this option is the same as for --dhcp-hostsfile: the
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
in a dhcp-optsfile.
.TP .TP
.B \-Z, --read-ethers .B \-Z, --read-ethers
Read /etc/ethers for information about hosts for the DHCP server. The Read /etc/ethers for information about hosts for the DHCP server. The
@@ -842,8 +848,9 @@ The environment is inherited from the invoker of dnsmasq, and if the
host provided a client-id, this is stored in the environment variable host provided a client-id, this is stored in the environment variable
DNSMASQ_CLIENT_ID. If the fully-qualified domain name of the host is DNSMASQ_CLIENT_ID. If the fully-qualified domain name of the host is
known, the domain part is stored in DNSMASQ_DOMAIN. known, the domain part is stored in DNSMASQ_DOMAIN.
If the client provides vendor-class or user-class If the client provides vendor-class, hostname or user-class,
information, these are provided in DNSMASQ_VENDOR_CLASS and these are provided in DNSMASQ_VENDOR_CLASS
DNSMASQ_SUPPLIED_HOSTNAME and
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
"add" actions or "old" actions when a host resumes an existing lease, "add" actions or "old" actions when a host resumes an existing lease,
since these data are not held in dnsmasq's lease since these data are not held in dnsmasq's lease
@@ -857,7 +864,8 @@ removed, an "old" event is generated with the new state of the lease,
ie no name, and the former name is provided in the environment ie no name, and the former name is provided in the environment
variable DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE stores the name of variable DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE stores the name of
the interface on which the request arrived; this is not set for "old" the interface on which the request arrived; this is not set for "old"
actions when dnsmasq restarts. actions when dnsmasq restarts. DNSMASQ_RELAY_ADDRESS is set if the client
used a DHCP relay to contact dnsmasq and the IP address of the relay is known.
All file descriptors are All file descriptors are
closed except stdin, stdout and stderr which are open to /dev/null closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode). (except in debug mode).
@@ -995,10 +1003,11 @@ of concurrent TFTP connections is limited by the size of the port range.
Specify a different configuration file. The conf-file option is also allowed in Specify a different configuration file. The conf-file option is also allowed in
configuration files, to include multiple configuration files. configuration files, to include multiple configuration files.
.TP .TP
.B \-7, --conf-dir=<directory> .B \-7, --conf-dir=<directory>[,<file-extension>......]
Read all the files in the given directory as configuration Read all the files in the given directory as configuration
files. Files whose names end in ~ or start with . or start and end files. If extension(s) are given, any files which end in those
with # are skipped. This flag may be given on the command extensions are skipped. Any files whose names end in ~ or start with . or start and end
with # are always skipped. This flag may be given on the command
line or in a configuration file. line or in a configuration file.
.SH CONFIG FILE .SH CONFIG FILE
At startup, dnsmasq reads At startup, dnsmasq reads
@@ -1238,6 +1247,24 @@ or an additional hosts file. The list can be very long,
dnsmasq has been tested successfully with one million names. That size dnsmasq has been tested successfully with one million names. That size
file needs a 1GHz processor and about 60Mb of RAM. file needs a 1GHz processor and about 60Mb of RAM.
.SH INTERNATIONALISATION
Dnsmasq can be compiled to support internationalisation. To do this,
the make targets "all-i18n" and "install-i18n" should be used instead of
the standard targets "all" and "install". When internationalisation
is compiled in, dnsmasq will produce log messages in the local
language and support internationalised domain names (IDN). Domain
names in /etc/hosts, /etc/ethers and /etc/dnsmasq.conf which contain
non-ASCII characters will be translated to the DNS-internal punycode
representation. Note that
dnsmasq determines both the language for messages and the assumed
charset for configuration
files from the LANG environment variable. This should be set to the system
default value by the script which is responsible for starting
dnsmasq. When editing the configuration files, be careful to do so
using only the system-default locale and not user-specific one, since
dnsmasq has no direct way of determining the charset in use, and must
assume that it is the system default.
.SH FILES .SH FILES
.IR /etc/dnsmasq.conf .IR /etc/dnsmasq.conf
+31 -21
View File
@@ -51,7 +51,8 @@ fichiers contenus dans ce répertoire.
.B \-E, --expand-hosts .B \-E, --expand-hosts
Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service
DHCP. DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les
enregistrements PTR, TXT, etc...
.TP .TP
.B \-T, --local-ttl=<durée> .B \-T, --local-ttl=<durée>
Lorsque Dnsmasq répond avec une information provenant du fichier /etc/hosts ou Lorsque Dnsmasq répond avec une information provenant du fichier /etc/hosts ou
@@ -634,7 +635,11 @@ relu lorsque Dnsmasq reçoit un signal SIGHUP.
.B --dhcp-optsfile=<fichier> .B --dhcp-optsfile=<fichier>
Lis les informations relatives aux options DHCP dans le fichier spécifié. Lis les informations relatives aux options DHCP dans le fichier spécifié.
L'intérêt d'utiliser cette option est le même que pour --dhcp-hostsfile : le L'intérêt d'utiliser cette option est le même que pour --dhcp-hostsfile : le
fichier spécifié ser rechargé à la réception par dnsmasq d'un signal SIGHUP. fichier spécifié sera rechargé à la réception par dnsmasq d'un signal SIGHUP.
Notez qu'il est possible d'encoder l'information via
.B --dhcp-boot
en utilisant les noms optionnels bootfile-name, server-ip-address et
tftp-server. Ceci permet d'inclure ces options dans un fichier "dhcp-optsfile".DNSMASQ_SUPPLIED_HOSTNAME
.TP .TP
.B \-Z, --read-ethers .B \-Z, --read-ethers
Lis les informations d'hôtes DHCP dans le fichier /etc/ethers. Le format de Lis les informations d'hôtes DHCP dans le fichier /etc/ethers. Le format de
@@ -961,22 +966,25 @@ L'environnement est hérité de celui de l'invocation du processus Dnsmasq, et
si l'hôte fournit un identifiant de client, celui-ci est stocké dans la si l'hôte fournit un identifiant de client, celui-ci est stocké dans la
variable d'environnement DNSMASQ_CLIENT_ID. Si un nom de domaine pleinement variable d'environnement DNSMASQ_CLIENT_ID. Si un nom de domaine pleinement
qualifié (FQDN) est connu pour l'hôte, la part relative au domaine est stockée qualifié (FQDN) est connu pour l'hôte, la part relative au domaine est stockée
dans DNSMASQ_DOMAIN. Si le client fournit une information de classe de vendeur dans DNSMASQ_DOMAIN. Si le client fournit une information de classe de vendeur,
ou de classe d'utilisateur, celles-ci sont positionnées dans les variables de classe d'utilisateur ou un nom d'hôte, celles-ci sont positionnées dans les
DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 à DNSMASQ_USER_CLASSn variables DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 à DNSMASQ_USER_CLASSn
respectivement, mais seulement pour les actions "add" et "old" lorsqu'un hôte et DNSMASQ_SUPPLIED_HOSTNAME respectivement, mais seulement pour les actions
reprend un bail existant, ces variables n'étant pas stockées dans la base de "add" et "old" lorsqu'un hôte reprend un bail existant, ces variables n'étant
baux de Dnsmasq. Si Dnsmasq a été compilé avec l'option HAVE_BROKEN_RTC pas stockées dans la base de baux de Dnsmasq. Si Dnsmasq a été compilé avec
("horloge RTC défectueuse"), alors la durée du bail (en secondes) est stockée l'option HAVE_BROKEN_RTC ("horloge RTC défectueuse"), alors la durée du bail
dans la variable DNSMASQ_LEASE_LENGTH, sinon la date d'expiration du bail est (en secondes) est stockée dans la variable DNSMASQ_LEASE_LENGTH, sinon la date
toujours stocké dans la variable d'environnement DNSMASQ_LEASE_EXPIRES. Le d'expiration du bail est toujours stocké dans la variable d'environnement
nombre de secondes avant expiration est toujours stocké dans DNSMASQ_LEASE_EXPIRES. Le nombre de secondes avant expiration est toujours
DNSMASQ_TIME_REMAINING. Si un bail était associé à un nom d'hôte et que celui-ci stocké dans DNSMASQ_TIME_REMAINING. Si un bail était associé à un nom d'hôte et
est supprimé, un évênement de type "old" est généré avec le nouveau statut du que celui-ci est supprimé, un évênement de type "old" est généré avec le
bail, c-à-d sans nom d'hôte, et le nom initial est fourni dans la variable nouveau statut du bail, c-à-d sans nom d'hôte, et le nom initial est fourni
d'environnement DNSMASQ_OLD_HOSTNAME. La variable DNSMASQ_INTERFACE contient le nom de dans la variable d'environnement DNSMASQ_OLD_HOSTNAME. La variable
l'interface sur laquelle la requête est arrivée; ceci n'est pas renseigné DNSMASQ_INTERFACE contient le nom de l'interface sur laquelle la requête est
dans le cas des actions "old" ayant lieu après un redémarrage de dnsmasq. arrivée; ceci n'est pas renseigné dans le cas des actions "old" ayant lieu
après un redémarrage de dnsmasq. La variable DNSMASQ_RELAY_ADDRESS est
renseignée si le client a utilisé un relai DHCP pour contacter Dnsmasq, si
l'adresse IP du relai est connue.
Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
sont ouverts sur /dev/null (sauf en mode déverminage). sont ouverts sur /dev/null (sauf en mode déverminage).
Le script n'est pas lancé de manière concurrente : si un autre changement de Le script n'est pas lancé de manière concurrente : si un autre changement de
@@ -1152,10 +1160,12 @@ Spécifie un fichier de configuration différent. L'option "conf-file" est
également autorisée dans des fichiers de configuration, ce qui permet également autorisée dans des fichiers de configuration, ce qui permet
l'inclusion de multiples fichiers de configuration. l'inclusion de multiples fichiers de configuration.
.TP .TP
.B \-7, --conf-dir=<répertoire> .B \-7, --conf-dir=<répertoire>[,<extension de fichier>...]
Lis tous les fichiers du répertoire spécifié et les traite comme des fichiers de Lis tous les fichiers du répertoire spécifié et les traite comme des fichiers de
configuration. Les fichiers dont les noms se terminent en ~ ou commençant par ., configuration. Si des extensions sont données, tout fichier finissant par ces
ainsi que ceux commençant ou se terminant par # ne sont pas pris en compte. extensions seront ignorés. Tout fichier dont le nom se termine en ~ ou commence
par ., ainsi que ceux commençant ou se terminant par # seront systématiquement
ignorés.
Cette option peut être donnée en ligne de commande ou dans un fichier de Cette option peut être donnée en ligne de commande ou dans un fichier de
configuration. configuration.
.SH FICHIER DE CONFIGURATION .SH FICHIER DE CONFIGURATION
+204 -187
View File
File diff suppressed because it is too large. Load diff
+205 -187
View File
File diff suppressed because it is too large. Load diff
+204 -187
View File
File diff suppressed because it is too large. Load diff
+206 -189
View File
File diff suppressed because it is too large. Load diff
+207 -188
View File
File diff suppressed because it is too large. Load diff
+204 -187
View File
File diff suppressed because it is too large. Load diff
+205 -187
View File
File diff suppressed because it is too large. Load diff
+238 -225
View File
File diff suppressed because it is too large. Load diff
+204 -187
View File
File diff suppressed because it is too large. Load diff
+205 -187
View File
File diff suppressed because it is too large. Load diff
+19 -16
View File
@@ -226,7 +226,7 @@ char *cache_get_name(struct crec *crecp)
{ {
if (crecp->flags & F_BIGNAME) if (crecp->flags & F_BIGNAME)
return crecp->name.bname->name; return crecp->name.bname->name;
else if (crecp->flags & F_DHCP) else if (crecp->flags & (F_DHCP | F_CONFIG))
return crecp->name.namep; return crecp->name.namep;
return crecp->name.sname; return crecp->name.sname;
@@ -366,7 +366,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
log_query(flags | F_UPSTREAM, name, addr, NULL); log_query(flags | F_UPSTREAM, name, addr, NULL);
/* CONFIG bit no needed except for logging */ /* CONFIG bit means something else when stored in cache entries */
flags &= ~F_CONFIG; flags &= ~F_CONFIG;
/* if previous insertion failed give up now. */ /* if previous insertion failed give up now. */
@@ -693,10 +693,10 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
if (!nameexists) if (!nameexists)
for (a = daemon->cnames; a; a = a->next) for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(cache->name.sname, a->target) && if (hostname_isequal(cache->name.sname, a->target) &&
(lookup = whine_malloc(sizeof(struct crec) + strlen(a->alias)+1-SMALLDNAME))) (lookup = whine_malloc(sizeof(struct crec))))
{ {
lookup->flags = F_FORWARD | F_IMMORTAL | F_HOSTS | F_CNAME; lookup->flags = F_FORWARD | F_IMMORTAL | F_CONFIG | F_HOSTS | F_CNAME;
strcpy(lookup->name.sname, a->alias); lookup->name.namep = a->alias;
lookup->addr.cname.cache = cache; lookup->addr.cname.cache = cache;
lookup->addr.cname.uid = index; lookup->addr.cname.uid = index;
cache_hash(lookup); cache_hash(lookup);
@@ -821,35 +821,38 @@ static int read_hostsfile(char *filename, int index, int cache_size)
while (atnl == 0) while (atnl == 0)
{ {
struct crec *cache; struct crec *cache;
int fqdn; int fqdn, nomem;
char *canon;
if ((atnl = gettok(f, token)) == EOF) if ((atnl = gettok(f, token)) == EOF)
break; break;
fqdn = !!strchr(token, '.'); fqdn = !!strchr(token, '.');
if (canonicalise(token)) if ((canon = canonicalise(token, &nomem)))
{ {
/* If set, add a version of the name with a default domain appended */ /* If set, add a version of the name with a default domain appended */
if ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn && if ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn &&
(cache = whine_malloc(sizeof(struct crec) + (cache = whine_malloc(sizeof(struct crec) +
strlen(token)+2+strlen(domain_suffix)-SMALLDNAME))) strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
{ {
strcpy(cache->name.sname, token); strcpy(cache->name.sname, canon);
strcat(cache->name.sname, "."); strcat(cache->name.sname, ".");
strcat(cache->name.sname, domain_suffix); strcat(cache->name.sname, domain_suffix);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup); add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
addr_dup = 1; addr_dup = 1;
name_count++; name_count++;
} }
if ((cache = whine_malloc(sizeof(struct crec) + strlen(token)+1-SMALLDNAME))) if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
{ {
strcpy(cache->name.sname, token); strcpy(cache->name.sname, canon);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup); add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
name_count++; name_count++;
} }
free(canon);
} }
else else if (!nomem)
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno); my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
} }
} }
@@ -1103,7 +1106,7 @@ void cache_add_dhcp_entry(char *host_name,
if (aliasc) if (aliasc)
{ {
aliasc->flags = F_FORWARD | F_DHCP | F_CNAME; aliasc->flags = F_FORWARD | F_CONFIG | F_DHCP | F_CNAME;
if (ttd == 0) if (ttd == 0)
aliasc->flags |= F_IMMORTAL; aliasc->flags |= F_IMMORTAL;
else else
@@ -1285,12 +1288,12 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr, char *ar
dest = "<CNAME>"; dest = "<CNAME>";
} }
if (flags & F_DHCP) if (flags & F_CONFIG)
source = "config";
else if (flags & F_DHCP)
source = "DHCP"; source = "DHCP";
else if (flags & F_HOSTS) else if (flags & F_HOSTS)
source = arg; source = arg;
else if (flags & F_CONFIG)
source = "config";
else if (flags & F_UPSTREAM) else if (flags & F_UPSTREAM)
source = "reply"; source = "reply";
else if (flags & F_SERVER) else if (flags & F_SERVER)
+19 -1
View File
@@ -14,13 +14,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define VERSION "2.49" #define VERSION "2.51"
#define FTABSIZ 150 /* max number of outstanding requests (default) */ #define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */ #define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */ #define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define EDNS_PKTSZ 1280 /* default max EDNS.0 UDP packet from RFC2671 */ #define EDNS_PKTSZ 1280 /* default max EDNS.0 UDP packet from RFC2671 */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */ #define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 10 /* or 10 seconds */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */ #define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */ #define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */ #define CACHESIZ 150 /* default cache size */
@@ -126,6 +128,9 @@ HAVE_TFTP
HAVE_DHCP HAVE_DHCP
define this to get dnsmasq's DHCP server. define this to get dnsmasq's DHCP server.
HAVE_SCRIPT
define this to get the ability to call scripts on lease-change
HAVE_GETOPT_LONG HAVE_GETOPT_LONG
define this if you have GNU libc or GNU getopt. define this if you have GNU libc or GNU getopt.
@@ -162,6 +167,7 @@ NOTES:
/* platform independent options- uncomment to enable */ /* platform independent options- uncomment to enable */
#define HAVE_DHCP #define HAVE_DHCP
#define HAVE_TFTP #define HAVE_TFTP
#define HAVE_SCRIPT
/* #define HAVE_BROKEN_RTC */ /* #define HAVE_BROKEN_RTC */
/* #define HAVE_DBUS */ /* #define HAVE_DBUS */
@@ -175,6 +181,13 @@ NOTES:
#undef HAVE_DHCP #undef HAVE_DHCP
#endif #endif
/* Allow scripts to be disabled with COPTS=-DNO_SCRIPT */
#ifdef NO_SCRIPT
#undef HAVE_SCRIPT
#endif
/* platform dependent options. */ /* platform dependent options. */
/* Must preceed __linux__ since uClinux defines __linux__ too. */ /* Must preceed __linux__ since uClinux defines __linux__ too. */
@@ -273,3 +286,8 @@ NOTES:
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */ # define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
#endif #endif
/* Can't do scripts without fork */
#ifdef NOFORK
# undef HAVE_SCRIPT
#endif
+14 -3
View File
@@ -390,16 +390,25 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
} }
} }
void emit_dbus_signal(int action, char *mac, char *hostname, char *addr) void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
{ {
DBusConnection *connection = (DBusConnection *)daemon->dbus; DBusConnection *connection = (DBusConnection *)daemon->dbus;
DBusMessage* message = NULL; DBusMessage* message = NULL;
DBusMessageIter args; DBusMessageIter args;
const char *action_str; char *action_str, *addr, *mac = daemon->namebuff;
unsigned char *p;
int i;
if (!connection) if (!connection)
return; return;
if (!hostname)
hostname = "";
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
lease->hwaddr, lease->clid_len, lease->clid, &i);
print_mac(mac, p, i);
if (action == ACTION_DEL) if (action == ACTION_DEL)
action_str = "DhcpLeaseDeleted"; action_str = "DhcpLeaseDeleted";
else if (action == ACTION_ADD) else if (action == ACTION_ADD)
@@ -409,6 +418,8 @@ void emit_dbus_signal(int action, char *mac, char *hostname, char *addr)
else else
return; return;
addr = inet_ntoa(lease->addr);
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str))) if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
return; return;
+23 -10
View File
@@ -754,6 +754,8 @@ void dhcp_read_ethers(void)
while (fgets(buff, MAXDNAME, f)) while (fgets(buff, MAXDNAME, f))
{ {
char *host = NULL;
lineno++; lineno++;
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1])) while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
@@ -792,19 +794,28 @@ void dhcp_read_ethers(void)
} }
else else
{ {
if (!canonicalise(ip)) int nomem;
if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
{ {
my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno); if (!nomem)
my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
free(host);
continue; continue;
} }
flags = CONFIG_NAME; flags = CONFIG_NAME;
for (config = daemon->dhcp_conf; config; config = config->next) for (config = daemon->dhcp_conf; config; config = config->next)
if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, ip)) if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
break; break;
} }
if (config && (config->flags & CONFIG_FROM_ETHERS))
{
my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno);
continue;
}
if (!config) if (!config)
{ {
for (config = daemon->dhcp_conf; config; config = config->next) for (config = daemon->dhcp_conf; config; config = config->next)
@@ -834,10 +845,8 @@ void dhcp_read_ethers(void)
if (flags & CONFIG_NAME) if (flags & CONFIG_NAME)
{ {
if ((config->hostname = whine_malloc(strlen(ip)+1))) config->hostname = host;
strcpy(config->hostname, ip); host = NULL;
else
config->flags &= ~CONFIG_NAME;
} }
if (flags & CONFIG_ADDR) if (flags & CONFIG_ADDR)
@@ -856,6 +865,9 @@ void dhcp_read_ethers(void)
config->hwaddr->next = NULL; config->hwaddr->next = NULL;
} }
count++; count++;
free(host);
} }
fclose(f); fclose(f);
@@ -945,7 +957,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
for this address. If it has a domain part, that must match the set domain and for this address. If it has a domain part, that must match the set domain and
it gets stripped. */ it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
so check here that the domain name is legal as a hostname. */
char *host_from_dns(struct in_addr addr) char *host_from_dns(struct in_addr addr)
{ {
struct crec *lookup; struct crec *lookup;
@@ -963,7 +976,7 @@ char *host_from_dns(struct in_addr addr)
hostname[255] = 0; hostname[255] = 0;
d1 = strip_hostname(hostname); d1 = strip_hostname(hostname);
d2 = get_domain(addr); d2 = get_domain(addr);
if (d1 && (!d2 || hostname_isequal(d1, d2))) if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
hostname = NULL; hostname = NULL;
} }
+11 -6
View File
@@ -45,11 +45,16 @@ static char *compile_opts =
"no-" "no-"
#endif #endif
"DHCP " "DHCP "
#if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
"no-scripts "
#endif
#ifndef HAVE_TFTP #ifndef HAVE_TFTP
"no-" "no-"
#endif #endif
"TFTP"; "TFTP";
static volatile pid_t pid = 0; static volatile pid_t pid = 0;
static volatile int pipewrite; static volatile int pipewrite;
@@ -68,7 +73,7 @@ int main (int argc, char **argv)
struct iname *if_tmp; struct iname *if_tmp;
int piperead, pipefd[2], err_pipe[2]; int piperead, pipefd[2], err_pipe[2];
struct passwd *ent_pw = NULL; struct passwd *ent_pw = NULL;
#ifdef HAVE_DHCP #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
uid_t script_uid = 0; uid_t script_uid = 0;
gid_t script_gid = 0; gid_t script_gid = 0;
#endif #endif
@@ -202,7 +207,7 @@ int main (int argc, char **argv)
if (daemon->port != 0) if (daemon->port != 0)
pre_allocate_sfds(); pre_allocate_sfds();
#ifdef HAVE_DHCP #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
/* Note getpwnam returns static storage */ /* Note getpwnam returns static storage */
if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser) if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
{ {
@@ -352,7 +357,7 @@ int main (int argc, char **argv)
/* if we are to run scripts, we need to fork a helper before dropping root. */ /* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = -1; daemon->helperfd = -1;
#if defined(HAVE_DHCP) && !defined(NO_FORK) #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
if (daemon->dhcp && daemon->lease_change_command) if (daemon->dhcp && daemon->lease_change_command)
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd); daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
#endif #endif
@@ -603,7 +608,7 @@ int main (int argc, char **argv)
bump_maxfd(piperead, &maxfd); bump_maxfd(piperead, &maxfd);
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
# ifndef NO_FORK # ifdef HAVE_SCRIPT
while (helper_buf_empty() && do_script_run(now)); while (helper_buf_empty() && do_script_run(now));
if (!helper_buf_empty()) if (!helper_buf_empty())
@@ -674,7 +679,7 @@ int main (int argc, char **argv)
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset)) if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
dhcp_packet(now); dhcp_packet(now);
# ifndef NO_FORK # ifdef HAVE_SCRIPT
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset)) if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
helper_write(); helper_write();
# endif # endif
@@ -857,7 +862,7 @@ static void async_event(int pipe, time_t now)
if (daemon->tcp_pids[i] != 0) if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGALRM); kill(daemon->tcp_pids[i], SIGALRM);
#if defined(HAVE_DHCP) && !defined(NO_FORK) #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
/* handle pending lease transitions */ /* handle pending lease transitions */
if (daemon->helperfd != -1) if (daemon->helperfd != -1)
{ {
+11 -8
View File
@@ -30,6 +30,7 @@
/* get these before config.h for IPv6 stuff... */ /* get these before config.h for IPv6 stuff... */
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#ifdef __APPLE__ #ifdef __APPLE__
@@ -55,7 +56,6 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#if defined(HAVE_SOLARIS_NETWORK) #if defined(HAVE_SOLARIS_NETWORK)
#include <sys/sockio.h> #include <sys/sockio.h>
@@ -335,7 +335,7 @@ struct server {
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */ struct in_addr netmask; /* only valid for IPv4 */
int dhcp_ok; int dhcp_ok, mtu;
struct irec *next; struct irec *next;
}; };
@@ -410,9 +410,9 @@ struct dhcp_lease {
#endif #endif
int hwaddr_len, hwaddr_type; int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX]; unsigned char hwaddr[DHCP_CHADDR_MAX];
struct in_addr addr, override; struct in_addr addr, override, giaddr;
unsigned char *vendorclass, *userclass; unsigned char *vendorclass, *userclass, *supplied_hostname;
unsigned int vendorclass_len, userclass_len; unsigned int vendorclass_len, userclass_len, supplied_hostname_len;
int last_interface; int last_interface;
struct dhcp_lease *next; struct dhcp_lease *next;
}; };
@@ -626,6 +626,7 @@ extern struct daemon {
struct dhcp_mac *dhcp_macs; struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config; struct dhcp_boot *boot_config;
struct pxe_service *pxe_services; struct pxe_service *pxe_services;
int enable_pxe;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic; struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
char *dhcp_hosts_file, *dhcp_opts_file; char *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max; int dhcp_max, tftp_max;
@@ -646,6 +647,8 @@ extern struct daemon {
struct irec *interfaces; struct irec *interfaces;
struct listener *listeners; struct listener *listeners;
struct server *last_server; struct server *last_server;
time_t forwardtime;
int forwardcount;
struct server *srv_save; /* Used for resend on DoD */ struct server *srv_save; /* Used for resend on DoD */
size_t packet_len; /* " " */ size_t packet_len; /* " " */
struct randfd *rfd_save; /* " " */ struct randfd *rfd_save; /* " " */
@@ -719,8 +722,8 @@ size_t resize_packet(HEADER *header, size_t plen,
/* util.c */ /* util.c */
void rand_init(void); void rand_init(void);
unsigned short rand16(void); unsigned short rand16(void);
int legal_char(char c); int legal_hostname(char *c);
int canonicalise(char *s); char *canonicalise(char *s, int *nomem);
unsigned char *do_rfc1035_name(unsigned char *p, char *sval); unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
void *safe_malloc(size_t size); void *safe_malloc(size_t size);
void safe_pipe(int *fd, int read_noblock); void safe_pipe(int *fd, int read_noblock);
@@ -863,7 +866,7 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)());
char *dbus_init(void); char *dbus_init(void);
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset); void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset); void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
void emit_dbus_signal(int action, char *mac, char *hostname, char *addr); void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
#endif #endif
/* helper.c */ /* helper.c */
+5 -1
View File
@@ -262,10 +262,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (type != 0 || (daemon->options & OPT_ORDER)) if (type != 0 || (daemon->options & OPT_ORDER))
start = daemon->servers; start = daemon->servers;
else if (!(start = daemon->last_server)) else if (!(start = daemon->last_server) ||
daemon->forwardcount++ > FORWARD_TEST ||
difftime(now, daemon->forwardtime) > FORWARD_TIME)
{ {
start = daemon->servers; start = daemon->servers;
forward->forwardall = 1; forward->forwardall = 1;
daemon->forwardcount = 0;
daemon->forwardtime = now;
} }
} }
} }
+38 -24
View File
@@ -28,15 +28,15 @@
main process. main process.
*/ */
#if defined(HAVE_DHCP) && !defined(NO_FORK) #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
static void my_setenv(const char *name, const char *value, int *error); static void my_setenv(const char *name, const char *value, int *error);
struct script_data struct script_data
{ {
unsigned char action, hwaddr_len, hwaddr_type; unsigned char action, hwaddr_len, hwaddr_type;
unsigned char clid_len, hostname_len, uclass_len, vclass_len; unsigned char clid_len, hostname_len, uclass_len, vclass_len, shost_len;
struct in_addr addr; struct in_addr addr, giaddr;
unsigned int remaining_time; unsigned int remaining_time;
#ifdef HAVE_BROKEN_RTC #ifdef HAVE_BROKEN_RTC
unsigned int length; unsigned int length;
@@ -101,7 +101,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
/* close all the sockets etc, we don't need them here. This closes err_fd, so that /* close all the sockets etc, we don't need them here. This closes err_fd, so that
main process can return. */ main process can return. */
for (max_fd--; max_fd > 0; max_fd--) for (max_fd--; max_fd >= 0; max_fd--)
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO &&
max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_fd) max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_fd)
close(max_fd); close(max_fd);
@@ -155,7 +155,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
sprintf(daemon->dhcp_buff2, "%lu ", (unsigned long)data.expires); sprintf(daemon->dhcp_buff2, "%lu ", (unsigned long)data.expires);
#endif #endif
if (!read_write(pipefd[0], buf, data.hostname_len + data.uclass_len + data.vclass_len, 1)) if (!read_write(pipefd[0], buf,
data.hostname_len + data.uclass_len + data.vclass_len + data.shost_len, 1))
continue; continue;
/* possible fork errors are all temporary resource problems */ /* possible fork errors are all temporary resource problems */
@@ -232,6 +233,19 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
} }
} }
if (data.shost_len != 0)
{
buf[data.shost_len - 1] = 0; /* don't trust zero-term */
/* cannot have = chars in env - truncate if found . */
if ((p = strchr((char *)buf, '=')))
*p = 0;
my_setenv("DNSMASQ_SUPPLIED_HOSTNAME", (char *)buf, &err);
buf += data.shost_len;
}
if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
sprintf(daemon->dhcp_buff2, "%u ", data.remaining_time); sprintf(daemon->dhcp_buff2, "%u ", data.remaining_time);
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
@@ -240,7 +254,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
char *dot; char *dot;
hostname = (char *)buf; hostname = (char *)buf;
hostname[data.hostname_len - 1] = 0; hostname[data.hostname_len - 1] = 0;
if (!canonicalise(hostname)) if (!legal_hostname(hostname))
hostname = NULL; hostname = NULL;
else if ((dot = strchr(hostname, '.'))) else if ((dot = strchr(hostname, '.')))
{ {
@@ -285,16 +299,9 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
{ {
unsigned char *p; unsigned char *p;
size_t size; size_t size;
int i; unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0;
unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0; unsigned int uclass_len = 0, shost_len = 0;
#ifdef HAVE_DBUS
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
lease->hwaddr, lease->clid_len, lease->clid, &i);
print_mac(daemon->namebuff, p, i);
emit_dbus_signal(action, daemon->namebuff, hostname ? hostname : "", inet_ntoa(lease->addr));
#endif
/* no script */ /* no script */
if (daemon->helperfd == -1) if (daemon->helperfd == -1)
return; return;
@@ -303,12 +310,14 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
vclass_len = lease->vendorclass_len; vclass_len = lease->vendorclass_len;
if (lease->userclass) if (lease->userclass)
uclass_len = lease->userclass_len; uclass_len = lease->userclass_len;
if (lease->supplied_hostname)
shost_len = lease->supplied_hostname_len;
if (lease->clid) if (lease->clid)
clid_len = lease->clid_len; clid_len = lease->clid_len;
if (hostname) if (hostname)
hostname_len = strlen(hostname) + 1; hostname_len = strlen(hostname) + 1;
size = sizeof(struct script_data) + clid_len + vclass_len + uclass_len + hostname_len; size = sizeof(struct script_data) + clid_len + vclass_len + uclass_len + shost_len + hostname_len;
if (size > buf_size) if (size > buf_size)
{ {
@@ -332,8 +341,10 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
buf->clid_len = clid_len; buf->clid_len = clid_len;
buf->vclass_len = vclass_len; buf->vclass_len = vclass_len;
buf->uclass_len = uclass_len; buf->uclass_len = uclass_len;
buf->shost_len = shost_len;
buf->hostname_len = hostname_len; buf->hostname_len = hostname_len;
buf->addr = lease->addr; buf->addr = lease->addr;
buf->giaddr = lease->giaddr;
memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len); memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len);
buf->interface[0] = 0; buf->interface[0] = 0;
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
@@ -372,14 +383,17 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
memcpy(p, lease->userclass, uclass_len); memcpy(p, lease->userclass, uclass_len);
p += uclass_len; p += uclass_len;
} }
/* substitute * for space: spaces are allowed in hostnames (for DNS-SD) if (shost_len != 0)
and are likley to be a security hole in most scripts. */ {
for (i = 0; i < (int)hostname_len; i++) memcpy(p, lease->supplied_hostname, shost_len);
if ((daemon->options & OPT_LEASE_RO) && hostname[i] == ' ') p += shost_len;
*(p++) = '*'; }
else if (hostname_len != 0)
*(p++) = hostname[i]; {
memcpy(p, hostname, hostname_len);
p += hostname_len;
}
bytes_in_buf = p - (unsigned char *)buf; bytes_in_buf = p - (unsigned char *)buf;
} }
+33 -28
View File
@@ -42,14 +42,20 @@ void lease_init(time_t now)
initial state of the database. If leasefile-ro is initial state of the database. If leasefile-ro is
set without a script, we just do without any set without a script, we just do without any
lease database. */ lease database. */
if (!daemon->lease_change_command) #ifdef HAVE_SCRIPT
if (daemon->lease_change_command)
{ {
file_dirty = dns_dirty = 0; strcpy(daemon->dhcp_buff, daemon->lease_change_command);
return; strcat(daemon->dhcp_buff, " init");
leasestream = popen(daemon->dhcp_buff, "r");
} }
strcpy(daemon->dhcp_buff, daemon->lease_change_command); else
strcat(daemon->dhcp_buff, " init"); #endif
leasestream = popen(daemon->dhcp_buff, "r"); {
file_dirty = dns_dirty = 0;
return;
}
} }
else else
{ {
@@ -100,19 +106,14 @@ void lease_init(time_t now)
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len); lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
if (strcmp(daemon->dhcp_buff, "*") != 0) if (strcmp(daemon->dhcp_buff, "*") != 0)
{ lease_set_hostname(lease, daemon->dhcp_buff, 0);
char *p;
/* unprotect spaces */
for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*'))
*p = ' ';
lease_set_hostname(lease, daemon->dhcp_buff, 0);
}
/* set these correctly: the "old" events are generated later from /* set these correctly: the "old" events are generated later from
the startup synthesised SIGHUP. */ the startup synthesised SIGHUP. */
lease->new = lease->changed = 0; lease->new = lease->changed = 0;
} }
#ifdef HAVE_SCRIPT
if (!daemon->lease_stream) if (!daemon->lease_stream)
{ {
int rc = 0; int rc = 0;
@@ -133,6 +134,7 @@ void lease_init(time_t now)
die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET); die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
} }
} }
#endif
/* Some leases may have expired */ /* Some leases may have expired */
file_dirty = 0; file_dirty = 0;
@@ -173,7 +175,6 @@ void lease_update_file(time_t now)
struct dhcp_lease *lease; struct dhcp_lease *lease;
time_t next_event; time_t next_event;
int i, err = 0; int i, err = 0;
char *p;
if (file_dirty != 0 && daemon->lease_stream) if (file_dirty != 0 && daemon->lease_stream)
{ {
@@ -199,15 +200,8 @@ void lease_update_file(time_t now)
} }
ourprintf(&err, " %s ", inet_ntoa(lease->addr)); ourprintf(&err, " %s ", inet_ntoa(lease->addr));
ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
/* substitute * for space: "*" is an illegal name, as is " " */
if (lease->hostname)
for (p = lease->hostname; *p; p++)
ourprintf(&err, "%c", *p == ' ' ? '*' : *p);
else
ourprintf(&err, "*");
ourprintf(&err, " ");
if (lease->clid && lease->clid_len != 0) if (lease->clid && lease->clid_len != 0)
{ {
for (i = 0; i < lease->clid_len - 1; i++) for (i = 0; i < lease->clid_len - 1; i++)
@@ -550,7 +544,7 @@ int do_script_run(time_t now)
/* If the lease still has an old_hostname, do the "old" action on that first */ /* If the lease still has an old_hostname, do the "old" action on that first */
if (lease->old_hostname) if (lease->old_hostname)
{ {
#ifndef NO_FORK #ifdef HAVE_SCRIPT
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
#endif #endif
free(lease->old_hostname); free(lease->old_hostname);
@@ -560,8 +554,11 @@ int do_script_run(time_t now)
else else
{ {
kill_name(lease); kill_name(lease);
#ifndef NO_FORK #ifdef HAVE_SCRIPT
queue_script(ACTION_DEL, lease, lease->old_hostname, now); queue_script(ACTION_DEL, lease, lease->old_hostname, now);
#endif
#ifdef HAVE_DBUS
emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
#endif #endif
old_leases = lease->next; old_leases = lease->next;
@@ -569,6 +566,7 @@ int do_script_run(time_t now)
free(lease->clid); free(lease->clid);
free(lease->vendorclass); free(lease->vendorclass);
free(lease->userclass); free(lease->userclass);
free(lease->supplied_hostname);
free(lease); free(lease);
return 1; return 1;
@@ -579,7 +577,7 @@ int do_script_run(time_t now)
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
if (lease->old_hostname) if (lease->old_hostname)
{ {
#ifndef NO_FORK #ifdef HAVE_SCRIPT
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
#endif #endif
free(lease->old_hostname); free(lease->old_hostname);
@@ -591,9 +589,13 @@ int do_script_run(time_t now)
if (lease->new || lease->changed || if (lease->new || lease->changed ||
(lease->aux_changed && (daemon->options & OPT_LEASE_RO))) (lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
{ {
#ifndef NO_FORK #ifdef HAVE_SCRIPT
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease,
lease->fqdn ? lease->fqdn : lease->hostname, now); lease->fqdn ? lease->fqdn : lease->hostname, now);
#endif
#ifdef HAVE_DBUS
emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease,
lease->fqdn ? lease->fqdn : lease->hostname);
#endif #endif
lease->new = lease->changed = lease->aux_changed = 0; lease->new = lease->changed = lease->aux_changed = 0;
@@ -603,7 +605,10 @@ int do_script_run(time_t now)
free(lease->userclass); free(lease->userclass);
lease->userclass = NULL; lease->userclass = NULL;
free(lease->supplied_hostname);
lease->supplied_hostname = NULL;
return 1; return 1;
} }
+8 -2
View File
@@ -119,7 +119,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
union mysockaddr *addr, struct in_addr netmask) union mysockaddr *addr, struct in_addr netmask)
{ {
struct irec *iface; struct irec *iface;
int fd; int fd, mtu = 0, loopback;
struct ifreq ifr; struct ifreq ifr;
int dhcp_ok = 1; int dhcp_ok = 1;
struct iname *tmp; struct iname *tmp;
@@ -142,12 +142,17 @@ static int iface_allowed(struct irec **irecp, int if_index,
} }
return 0; return 0;
} }
loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
close(fd); close(fd);
/* If we are restricting the set of interfaces to use, make /* If we are restricting the set of interfaces to use, make
sure that loopback interfaces are in that set. */ sure that loopback interfaces are in that set. */
if (daemon->if_names && (ifr.ifr_flags & IFF_LOOPBACK)) if (daemon->if_names && loopback)
{ {
struct iname *lo; struct iname *lo;
for (lo = daemon->if_names; lo; lo = lo->next) for (lo = daemon->if_names; lo; lo = lo->next)
@@ -188,6 +193,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
iface->addr = *addr; iface->addr = *addr;
iface->netmask = netmask; iface->netmask = netmask;
iface->dhcp_ok = dhcp_ok; iface->dhcp_ok = dhcp_ok;
iface->mtu = mtu;
iface->next = *irecp; iface->next = *irecp;
*irecp = iface; *irecp = iface;
return 1; return 1;
+130 -77
View File
@@ -406,6 +406,7 @@ static const struct {
{ "domain-search", 119, 0 }, { "domain-search", 119, 0 },
{ "sip-server", 120, 0 }, { "sip-server", 120, 0 },
{ "classless-static-route", 121, 0 }, { "classless-static-route", 121, 0 },
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
@@ -530,13 +531,24 @@ static char *split(char *s)
return split_chr(s, ','); return split_chr(s, ',');
} }
static int canonicalise_opt(char *s) static char *canonicalise_opt(char *s)
{ {
char *ret;
int nomem;
if (!s) if (!s)
return 0; return 0;
unhide_metas(s); unhide_metas(s);
return canonicalise(s); if (!(ret = canonicalise(s, &nomem)) && nomem)
{
if (mem_recover)
longjmp(mem_jmp, 1);
else
die(_("could not get memory"), NULL, EC_NOMEM);
}
return ret;
} }
static int atoi_check(char *a, int *res) static int atoi_check(char *a, int *res)
@@ -646,7 +658,7 @@ static void display_opts(void)
printf(_("Known DHCP options:\n")); printf(_("Known DHCP options:\n"));
for (i = 0; opttab[i].name; i++) for (i = 0; opttab[i].name; i++)
if (opttab[i].size != OT_INTERNAL) if (!(opttab[i].size & OT_INTERNAL))
printf("%3d %s\n", opttab[i].val, opttab[i].name); printf("%3d %s\n", opttab[i].val, opttab[i].name);
} }
@@ -684,7 +696,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
if (strstr(arg, "option:") == arg) if (strstr(arg, "option:") == arg)
{ {
for (i = 0; opttab[i].name; i++) for (i = 0; opttab[i].name; i++)
if (opttab[i].size != OT_INTERNAL && if (!(opttab[i].size & OT_INTERNAL) &&
strcasecmp(opttab[i].name, arg+7) == 0) strcasecmp(opttab[i].name, arg+7) == 0)
{ {
new->opt = opttab[i].val; new->opt = opttab[i].val;
@@ -873,7 +885,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
while (arg && *arg) while (arg && *arg)
{ {
if (!canonicalise_opt(arg)) char *dom;
if (!(dom = arg = canonicalise_opt(arg)))
{ {
problem = _("bad domain in dhcp-option"); problem = _("bad domain in dhcp-option");
break; break;
@@ -898,7 +911,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
arg++; arg++;
} }
*q++ = 0; *q++ = 0;
free(dom);
/* Now tail-compress using earlier names. */ /* Now tail-compress using earlier names. */
newlen = q - p; newlen = q - p;
for (tail = p + len; *tail; tail += (*tail) + 1) for (tail = p + len; *tail; tail += (*tail) + 1)
@@ -1018,25 +1032,51 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
DIR *dir_stream; DIR *dir_stream;
struct dirent *ent; struct dirent *ent;
char *directory, *path; char *directory, *path;
struct list {
char *suffix;
struct list *next;
} *ignore_suffix = NULL, *li;
comma = split(arg);
if (!(directory = opt_string_alloc(arg))) if (!(directory = opt_string_alloc(arg)))
break; break;
for (arg = comma; arg; arg = comma)
{
comma = split(arg);
li = opt_malloc(sizeof(struct list));
li->next = ignore_suffix;
ignore_suffix = li;
/* Have to copy: buffer is overwritten */
li->suffix = opt_string_alloc(arg);
};
if (!(dir_stream = opendir(directory))) if (!(dir_stream = opendir(directory)))
die(_("cannot access directory %s: %s"), directory, EC_FILE); die(_("cannot access directory %s: %s"), directory, EC_FILE);
while ((ent = readdir(dir_stream))) while ((ent = readdir(dir_stream)))
{ {
size_t len = strlen(ent->d_name); size_t len = strlen(ent->d_name);
struct stat buf; struct stat buf;
/* ignore emacs backups and dotfiles */ /* ignore emacs backups and dotfiles */
if (len == 0 || if (len == 0 ||
ent->d_name[len - 1] == '~' || ent->d_name[len - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') || (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
ent->d_name[0] == '.') ent->d_name[0] == '.')
continue; continue;
for (li = ignore_suffix; li; li = li->next)
{
/* check for proscribed suffices */
size_t ls = strlen(li->suffix);
if (len > ls &&
strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
break;
}
if (li)
continue;
path = opt_malloc(strlen(directory) + len + 2); path = opt_malloc(strlen(directory) + len + 2);
strcpy(path, directory); strcpy(path, directory);
strcat(path, "/"); strcat(path, "/");
@@ -1055,6 +1095,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
closedir(dir_stream); closedir(dir_stream);
free(directory); free(directory);
for(; ignore_suffix; ignore_suffix = li)
{
li = ignore_suffix->next;
free(ignore_suffix->suffix);
free(ignore_suffix);
}
break; break;
} }
@@ -1127,32 +1174,32 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{ {
int pref = 1; int pref = 1;
struct mx_srv_record *new; struct mx_srv_record *new;
char *name, *target = NULL;
if ((comma = split(arg))) if ((comma = split(arg)))
{ {
char *prefstr; char *prefstr;
if ((prefstr=split(comma)) && !atoi_check16(prefstr, &pref)) if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
problem = _("bad MX preference"); problem = _("bad MX preference");
} }
if (!canonicalise_opt(arg) || (comma && !canonicalise_opt(comma))) if (!(name = canonicalise_opt(arg)) ||
(comma && !(target = canonicalise_opt(comma))))
problem = _("bad MX name"); problem = _("bad MX name");
new = opt_malloc(sizeof(struct mx_srv_record)); new = opt_malloc(sizeof(struct mx_srv_record));
new->next = daemon->mxnames; new->next = daemon->mxnames;
daemon->mxnames = new; daemon->mxnames = new;
new->issrv = 0; new->issrv = 0;
new->name = opt_string_alloc(arg); new->name = name;
new->target = opt_string_alloc(comma); /* may be NULL */ new->target = target; /* may be NULL */
new->weight = pref; new->weight = pref;
break; break;
} }
case 't': /* --mx-target */ case 't': /* --mx-target */
if (!canonicalise_opt(arg)) if (!(daemon->mxtarget = canonicalise_opt(arg)))
problem = _("bad MX target"); problem = _("bad MX target");
else
daemon->mxtarget = opt_string_alloc(arg);
break; break;
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
@@ -1161,8 +1208,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
break; break;
case '6': /* --dhcp-script */ case '6': /* --dhcp-script */
# ifdef NO_FORK # if defined(NO_FORK)
problem = _("cannot run scripts under uClinux"); problem = _("cannot run scripts under uClinux");
# elif !defined(HAVE_SCRIPT)
problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
# else # else
daemon->lease_change_command = opt_string_alloc(arg); daemon->lease_change_command = opt_string_alloc(arg);
# endif # endif
@@ -1186,12 +1235,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
daemon->options |= OPT_RESOLV_DOMAIN; daemon->options |= OPT_RESOLV_DOMAIN;
else else
{ {
char *d;
comma = split(arg); comma = split(arg);
if (!canonicalise_opt(arg)) if (!(d = canonicalise_opt(arg)))
option = '?'; option = '?';
else else
{ {
char *d = opt_string_alloc(arg);
if (comma) if (comma)
{ {
struct cond_domain *new = safe_malloc(sizeof(struct cond_domain)); struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
@@ -1346,10 +1395,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
/* # matches everything and becomes a zero length domain string */ /* # matches everything and becomes a zero length domain string */
if (strcmp(arg, "#") == 0) if (strcmp(arg, "#") == 0)
domain = ""; domain = "";
else if (!canonicalise_opt(arg) && strlen(arg) != 0) else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?'; option = '?';
else
domain = opt_string_alloc(arg); /* NULL if strlen is zero */
serv = opt_malloc(sizeof(struct server)); serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server)); memset(serv, 0, sizeof(struct server));
serv->next = newlist; serv->next = newlist;
@@ -1662,7 +1709,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if (!(a[k] = split(a[k-1]))) if (!(a[k] = split(a[k-1])))
break; break;
if (option == '?' || (k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1)) if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
option = '?'; option = '?';
else if (strcmp(a[1], "static") == 0) else if (strcmp(a[1], "static") == 0)
{ {
@@ -1860,15 +1907,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->flags |= CONFIG_DISABLE; new->flags |= CONFIG_DISABLE;
else else
{ {
int len = strlen(a[j]) + 1; if (!(new->hostname = canonicalise_opt(a[j])) ||
if (!canonicalise_opt(a[j])) !legal_hostname(new->hostname))
problem = _("bad DHCP host name"); problem = _("bad DHCP host name");
else if ((new->hostname = opt_malloc(len))) else
{ new->flags |= CONFIG_NAME;
new->flags |= CONFIG_NAME; new->domain = NULL;
strcpy(new->hostname, a[j]);
new->domain = NULL;
}
} }
} }
else else
@@ -1983,6 +2027,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->next = daemon->dhcp_opts; new->next = daemon->dhcp_opts;
daemon->dhcp_opts = new; daemon->dhcp_opts = new;
daemon->enable_pxe = 1;
} }
break; break;
@@ -2051,6 +2096,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
s->next = new; s->next = new;
} }
daemon->enable_pxe = 1;
break; break;
} }
} }
@@ -2243,19 +2289,20 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case LOPT_INTNAME: /* --interface-name */ case LOPT_INTNAME: /* --interface-name */
{ {
struct interface_name *new, **up; struct interface_name *new, **up;
char *domain = NULL;
comma = split(arg); comma = split(arg);
if (!comma || !canonicalise_opt(arg)) if (!comma || !(domain = canonicalise_opt(arg)))
problem = _("bad interface name"); problem = _("bad interface name");
new = opt_malloc(sizeof(struct interface_name)); new = opt_malloc(sizeof(struct interface_name));
new->next = NULL; new->next = NULL;
/* Add to the end of the list, so that first name /* Add to the end of the list, so that first name
of an interface is used for PTR lookups. */ of an interface is used for PTR lookups. */
for (up = &daemon->int_names; *up; up = &((*up)->next)); for (up = &daemon->int_names; *up; up = &((*up)->next));
*up = new; *up = new;
new->name = opt_string_alloc(arg); new->name = domain;
new->intr = opt_string_alloc(comma); new->intr = opt_string_alloc(comma);
break; break;
} }
@@ -2268,14 +2315,22 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
option = '?'; option = '?';
else else
{ {
for (new = daemon->cnames; new; new = new->next) char *alias = canonicalise_opt(arg);
if (hostname_isequal(new->alias, arg)) char *target = canonicalise_opt(comma);
problem = _("duplicate CNAME");
new = opt_malloc(sizeof(struct cname)); if (!alias || !target)
new->next = daemon->cnames; problem = _("bad CNAME");
daemon->cnames = new; else
new->alias = opt_string_alloc(arg); {
new->target = opt_string_alloc(comma); for (new = daemon->cnames; new; new = new->next)
if (hostname_isequal(new->alias, arg))
problem = _("duplicate CNAME");
new = opt_malloc(sizeof(struct cname));
new->next = daemon->cnames;
daemon->cnames = new;
new->alias = alias;
new->target = target;
}
} }
break; break;
} }
@@ -2283,19 +2338,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case LOPT_PTR: /* --ptr-record */ case LOPT_PTR: /* --ptr-record */
{ {
struct ptr_record *new; struct ptr_record *new;
char *dom, *target = NULL;
comma = split(arg); comma = split(arg);
if (!canonicalise_opt(arg)) if (!(dom = canonicalise_opt(arg)) ||
(comma && !(target = canonicalise_opt(comma))))
problem = _("bad PTR record"); problem = _("bad PTR record");
else
new = opt_malloc(sizeof(struct ptr_record)); {
new->next = daemon->ptr; new = opt_malloc(sizeof(struct ptr_record));
daemon->ptr = new; new->next = daemon->ptr;
new->name = opt_string_alloc(arg); daemon->ptr = new;
new->ptr = NULL; new->name = dom;
if (comma) new->ptr = target;
new->ptr = opt_string_alloc(comma); }
break; break;
} }
@@ -2305,6 +2362,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
int k = 0; int k = 0;
struct naptr *new; struct naptr *new;
int order, pref; int order, pref;
char *name, *replace = NULL;
if ((a[0] = arg)) if ((a[0] = arg))
for (k = 1; k < 7; k++) for (k = 1; k < 7; k++)
@@ -2313,22 +2371,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if (k < 6 || if (k < 6 ||
!canonicalise_opt(a[0]) || !(name = canonicalise_opt(a[0])) ||
!atoi_check16(a[1], &order) || !atoi_check16(a[1], &order) ||
!atoi_check16(a[2], &pref) || !atoi_check16(a[2], &pref) ||
(k == 7 && !canonicalise_opt(a[6]))) (k == 7 && !(replace = canonicalise_opt(a[6]))))
problem = _("bad NAPTR record"); problem = _("bad NAPTR record");
else else
{ {
new = opt_malloc(sizeof(struct naptr)); new = opt_malloc(sizeof(struct naptr));
new->next = daemon->naptr; new->next = daemon->naptr;
daemon->naptr = new; daemon->naptr = new;
new->name = opt_string_alloc(a[0]); new->name = name;
new->flags = opt_string_alloc(a[3]); new->flags = opt_string_alloc(a[3]);
new->services = opt_string_alloc(a[4]); new->services = opt_string_alloc(a[4]);
new->regexp = opt_string_alloc(a[5]); new->regexp = opt_string_alloc(a[5]);
if (k == 7) new->replace = replace;
new->replace = opt_string_alloc(a[6]);
new->order = order; new->order = order;
new->pref = pref; new->pref = pref;
} }
@@ -2345,12 +2402,6 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
gen_prob = _("TXT record string too long"); gen_prob = _("TXT record string too long");
if (!canonicalise_opt(arg))
{
problem = _("bad TXT record");
break;
}
if ((q = (unsigned char *)comma)) if ((q = (unsigned char *)comma))
while (1) while (1)
{ {
@@ -2394,7 +2445,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
/* ensure arg is terminated */ /* ensure arg is terminated */
if (comma) if (comma)
*comma = 0; *comma = 0;
new->name = opt_string_alloc(arg);
if (!(new->name = canonicalise_opt(arg)))
{
problem = _("bad TXT record");
break;
}
break; break;
} }
@@ -2406,19 +2463,16 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
comma = split(arg); comma = split(arg);
if (!canonicalise_opt(arg)) if (!(name = canonicalise_opt(arg)))
problem = _("bad SRV record"); problem = _("bad SRV record");
name = opt_string_alloc(arg);
if (comma) if (comma)
{ {
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
if (!canonicalise_opt(arg)) if (!(target = canonicalise_opt(arg))
problem = _("bad SRV target"); ) problem = _("bad SRV target");
target = opt_string_alloc(arg);
if (comma) if (comma)
{ {
arg = comma; arg = comma;
@@ -2683,7 +2737,7 @@ void reread_dhcp(void)
} }
one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK); one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
my_syslog(LOG_INFO, _("read %s"), daemon->dhcp_hosts_file); my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
} }
if (daemon->dhcp_opts_file) if (daemon->dhcp_opts_file)
@@ -2714,7 +2768,7 @@ void reread_dhcp(void)
} }
one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS); one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
my_syslog(LOG_INFO, _("read %s"), daemon->dhcp_opts_file); my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
} }
} }
#endif #endif
@@ -2898,8 +2952,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
continue; continue;
if ((token = strtok(NULL, " \t\n\r")) && if ((token = strtok(NULL, " \t\n\r")) &&
canonicalise_opt(token) && (daemon->domain_suffix = canonicalise_opt(token)))
(daemon->domain_suffix = opt_string_alloc(token)))
break; break;
} }
+2 -1
View File
@@ -138,7 +138,8 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
for(j=0; j<l; j++, p++) for(j=0; j<l; j++, p++)
if (isExtract) if (isExtract)
{ {
if (legal_char(*p)) unsigned char c = *p;
if (isascii(c) && !iscntrl(c) && c != '.')
*cp++ = *p; *cp++ = *p;
else else
return 0; return 0;
+38 -17
View File
@@ -415,7 +415,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next) for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
if (match_netid(id_list->list, netid, 0)) if (match_netid(id_list->list, netid, 0))
message = _("disabled"); message = _("ignored");
if (!message) if (!message)
{ {
@@ -536,7 +536,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
*pq = 0; *pq = 0;
if (canonicalise(daemon->dhcp_buff)) if (legal_hostname(daemon->dhcp_buff))
offer_hostname = client_hostname = daemon->dhcp_buff; offer_hostname = client_hostname = daemon->dhcp_buff;
} }
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1))) else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
@@ -550,7 +550,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
borken_opt = 1; borken_opt = 1;
else else
daemon->dhcp_buff[len] = 0; daemon->dhcp_buff[len] = 0;
if (canonicalise(daemon->dhcp_buff)) if (legal_hostname(daemon->dhcp_buff))
client_hostname = daemon->dhcp_buff; client_hostname = daemon->dhcp_buff;
} }
@@ -708,7 +708,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clid = NULL; clid = NULL;
/* Check if client is PXE client. */ /* Check if client is PXE client. */
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) && if (daemon->enable_pxe &&
(opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0) strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
{ {
if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17))) if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
@@ -728,6 +729,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
unsigned char save71[4]; unsigned char save71[4];
struct dhcp_opt opt71; struct dhcp_opt opt71;
if (ignore)
return 0;
if (layer & 0x8000) if (layer & 0x8000)
{ {
my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported")); my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
@@ -807,8 +811,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
prune_vendor_opts(netid); prune_vendor_opts(netid);
do_encap_opts(pxe_opts(pxearch, netid), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0); do_encap_opts(pxe_opts(pxearch, netid), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
log_packet("PXE", NULL, emac, emac_len, iface_name, "proxy", mess->xid); log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy" : "proxy-ignored", mess->xid);
return dhcp_packet_size(mess, netid, agent_id, real_end); return ignore ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
} }
} }
} }
@@ -1133,6 +1137,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{ {
if (do_classes) if (do_classes)
{ {
if (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
lease->changed = 1; lease->changed = 1;
/* copy user-class and vendor class into new lease, for the script */ /* copy user-class and vendor class into new lease, for the script */
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1))) if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
@@ -1162,6 +1169,18 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease->vendorclass_len = len+1; lease->vendorclass_len = len+1;
} }
} }
if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
{
int len = option_len(opt);
unsigned char *ucp = option_ptr(opt, 0);
free(lease->supplied_hostname);
if ((lease->supplied_hostname = whine_malloc(len+1)))
{
memcpy(lease->supplied_hostname, ucp, len);
lease->supplied_hostname[len] = 0;
lease->supplied_hostname_len = len+1;
}
}
} }
if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr))) if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
@@ -1538,7 +1557,6 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
/* move agent_id back down to the end of the packet */ /* move agent_id back down to the end of the packet */
if (agent_id) if (agent_id)
{ {
unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
memmove(p, agent_id, real_end - agent_id); memmove(p, agent_id, real_end - agent_id);
p += real_end - agent_id; p += real_end - agent_id;
memset(p, 0, real_end - p); /* in case of overlap */ memset(p, 0, real_end - p); /* in case of overlap */
@@ -1547,9 +1565,8 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
/* We do logging too */ /* We do logging too */
if (netid && (daemon->options & OPT_LOG_OPTS)) if (netid && (daemon->options & OPT_LOG_OPTS))
{ {
char *p = daemon->namebuff; char *s = daemon->namebuff;
*p = 0; for (*s = 0; netid; netid = netid->next)
for (; netid; netid = netid->next)
{ {
/* kill dupes. */ /* kill dupes. */
for (n = netid->next; n; n = n->next) for (n = netid->next; n; n = n->next)
@@ -1558,13 +1575,12 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
if (!n) if (!n)
{ {
strncat (p, netid->net, MAXDNAME); strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
if (netid->next) if (netid->next)
strncat (p, ", ", MAXDNAME); strncat (s, ", ", (MAXDNAME-1) - strlen(s));
} }
} }
p[MAXDNAME - 1] = 0; my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s);
my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), p);
} }
/* add END options to the regions. */ /* add END options to the regions. */
@@ -2074,21 +2090,26 @@ static void do_options(struct dhcp_context *context,
} }
else else
/* Use the values of the relevant options if no dhcp-boot given and /* Use the values of the relevant options if no dhcp-boot given and
they're not explicitly asked for as options. */ they're not explicitly asked for as options. OPTION_END is used
as an internal way to specify siaddr without using dhcp-boot, for use in
dhcp-optsfile. */
{ {
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) && mess->file[0] == 0 && if ((!req_options || !in_list(req_options, OPTION_FILENAME)) && mess->file[0] == 0 &&
(opt = option_find2(netid, config_opts, OPTION_FILENAME))) (opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
{ {
strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1); strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
done_file = 1; done_file = 1;
} }
if ((!req_options || !in_list(req_options, OPTION_SNAME)) && if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
(opt = option_find2(netid, config_opts, OPTION_SNAME))) (opt = option_find2(netid, config_opts, OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
{ {
strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1); strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
done_server = 1; done_server = 1;
} }
if ((opt = option_find2(netid, config_opts, OPTION_END)))
mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
} }
/* We don't want to do option-overload for BOOTP, so make the file and sname /* We don't want to do option-overload for BOOTP, so make the file and sname
+37 -23
View File
@@ -46,12 +46,13 @@ void tftp_request(struct listener *listen, time_t now)
struct sockaddr_in addr, peer; struct sockaddr_in addr, peer;
struct msghdr msg; struct msghdr msg;
struct iovec iov; struct iovec iov;
int is_err = 1, if_index = 0; struct ifreq ifr;
int is_err = 1, if_index = 0, mtu = 0;
struct iname *tmp; struct iname *tmp;
struct tftp_transfer *transfer; struct tftp_transfer *transfer;
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */ int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
int mtu = IP_PMTUDISC_DONT; int mtuflag = IP_PMTUDISC_DONT;
#endif #endif
union { union {
@@ -83,7 +84,10 @@ void tftp_request(struct listener *listen, time_t now)
return; return;
if (daemon->options & OPT_NOWILD) if (daemon->options & OPT_NOWILD)
addr = listen->iface->addr.in; {
addr = listen->iface->addr.in;
mtu = listen->iface->mtu;
}
else else
{ {
char name[IF_NAMESIZE]; char name[IF_NAMESIZE];
@@ -125,7 +129,10 @@ void tftp_request(struct listener *listen, time_t now)
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0)) if (tmp->name && (strcmp(tmp->name, name) == 0))
return; return;
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
} }
addr.sin_port = htons(port); addr.sin_port = htons(port);
@@ -158,7 +165,7 @@ void tftp_request(struct listener *listen, time_t now)
{ {
if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 || if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 ||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 || setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
#endif #endif
!fix_fd(transfer->sockfd)) !fix_fd(transfer->sockfd))
{ {
@@ -192,42 +199,50 @@ void tftp_request(struct listener *listen, time_t now)
while ((opt = next(&p, end))) while ((opt = next(&p, end)))
{ {
if (strcasecmp(opt, "blksize") == 0 && if (strcasecmp(opt, "blksize") == 0)
(opt = next(&p, end)) &&
!(daemon->options & OPT_TFTP_NOBLOCK))
{ {
transfer->blocksize = atoi(opt); if ((opt = next(&p, end)) &&
if (transfer->blocksize < 1) !(daemon->options & OPT_TFTP_NOBLOCK))
transfer->blocksize = 1; {
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4) transfer->blocksize = atoi(opt);
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4; if (transfer->blocksize < 1)
transfer->opt_blocksize = 1; transfer->blocksize = 1;
transfer->block = 0; if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
/* 32 bytes for IP, UDP and TFTP headers */
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
transfer->blocksize = (unsigned)mtu - 32;
transfer->opt_blocksize = 1;
transfer->block = 0;
}
} }
else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
{ {
transfer->opt_transize = 1; transfer->opt_transize = 1;
transfer->block = 0; transfer->block = 0;
} }
} }
/* cope with backslashes from windows boxen. */
while ((p = strchr(filename, '\\')))
*p = '/';
strcpy(daemon->namebuff, "/"); strcpy(daemon->namebuff, "/");
if (daemon->tftp_prefix) if (daemon->tftp_prefix)
{ {
if (daemon->tftp_prefix[0] == '/') if (daemon->tftp_prefix[0] == '/')
daemon->namebuff[0] = 0; daemon->namebuff[0] = 0;
strncat(daemon->namebuff, daemon->tftp_prefix, MAXDNAME); strncat(daemon->namebuff, daemon->tftp_prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/') if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/')
strncat(daemon->namebuff, "/", MAXDNAME); strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
if (daemon->options & OPT_TFTP_APREF) if (daemon->options & OPT_TFTP_APREF)
{ {
size_t oldlen = strlen(daemon->namebuff); size_t oldlen = strlen(daemon->namebuff);
struct stat statbuf; struct stat statbuf;
strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), MAXDNAME); strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), (MAXDNAME-1) - strlen(daemon->namebuff));
strncat(daemon->namebuff, "/", MAXDNAME); strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
/* remove unique-directory if it doesn't exist */ /* remove unique-directory if it doesn't exist */
if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode)) if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
@@ -245,8 +260,7 @@ void tftp_request(struct listener *listen, time_t now)
} }
else if (filename[0] == '/') else if (filename[0] == '/')
daemon->namebuff[0] = 0; daemon->namebuff[0] = 0;
strncat(daemon->namebuff, filename, MAXDNAME); strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
daemon->namebuff[MAXDNAME-1] = 0;
/* check permissions and open file */ /* check permissions and open file */
if ((transfer->file = check_tftp_fileperm(&len))) if ((transfer->file = check_tftp_fileperm(&len)))
+91 -26
View File
@@ -24,6 +24,9 @@
#include <sys/times.h> #include <sys/times.h>
#endif #endif
#ifdef LOCALEDIR
#include <idna.h>
#endif
#ifdef HAVE_ARC4RANDOM #ifdef HAVE_ARC4RANDOM
void rand_init(void) void rand_init(void)
@@ -95,48 +98,110 @@ unsigned short rand16(void)
#endif #endif
static int check_name(char *in)
int legal_char(char c)
{ {
/* check for legal char a-z A-Z 0-9 - /* remove trailing .
(also / , used for RFC2317 and _ used in windows queries
and space, for DNS-SD stuff) */
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '-' || c == '/' || c == '_' || c == ' ')
return 1;
return 0;
}
int canonicalise(char *s)
{
/* check for legal chars and remove trailing .
also fail empty string and label > 63 chars */ also fail empty string and label > 63 chars */
size_t dotgap = 0, l = strlen(s); size_t dotgap = 0, l = strlen(in);
char c; char c;
int nowhite = 0; int nowhite = 0;
if (l == 0 || l > MAXDNAME) return 0; if (l == 0 || l > MAXDNAME) return 0;
if (s[l-1] == '.') if (in[l-1] == '.')
{ {
if (l == 1) return 0; if (l == 1) return 0;
s[l-1] = 0; in[l-1] = 0;
} }
while ((c = *s)) for (; (c = *in); in++)
{ {
if (c == '.') if (c == '.')
dotgap = 0; dotgap = 0;
else if (!legal_char(c) || (++dotgap > MAXLABEL)) else if (++dotgap > MAXLABEL)
return 0; return 0;
else if (isascii(c) && iscntrl(c))
/* iscntrl only gives expected results for ascii */
return 0;
#ifndef LOCALEDIR
else if (!isascii(c))
return 0;
#endif
else if (c != ' ') else if (c != ' ')
nowhite = 1; nowhite = 1;
s++;
} }
return nowhite;
if (!nowhite)
return 0;
return 1;
}
/* Hostnames have a more limited valid charset than domain names
so check for legal char a-z A-Z 0-9 - _
Note that this may receive a FQDN, so only check the first label
for the tighter criteria. */
int legal_hostname(char *name)
{
char c;
if (!check_name(name))
return 0;
for (; (c = *name); name++)
/* check for legal char a-z A-Z 0-9 - _ . */
{
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '-' || c == '_')
continue;
/* end of hostname part */
if (c == '.')
return 1;
return 0;
}
return 1;
}
char *canonicalise(char *in, int *nomem)
{
char *ret = NULL;
#ifdef LOCALEDIR
int rc;
#endif
if (nomem)
*nomem = 0;
if (!check_name(in))
return NULL;
#ifdef LOCALEDIR
if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
{
if (ret)
free(ret);
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
{
my_syslog(LOG_ERR, _("failed to allocate memory"));
*nomem = 1;
}
return NULL;
}
#else
if ((ret = whine_malloc(strlen(in)+1)))
strcpy(ret, in);
else if (nomem)
*nomem = 1;
#endif
return ret;
} }
unsigned char *do_rfc1035_name(unsigned char *p, char *sval) unsigned char *do_rfc1035_name(unsigned char *p, char *sval)