Compare commits

...

1 Commits
v2.50 ... v2.51

Author SHA1 Message Date
Simon Kelley
1f15b81d61 import of dnsmasq-2.51.tar.gz 2012-01-05 17:31:14 +00:00
34 changed files with 2729 additions and 2194 deletions

View File

@@ -1,5 +1,78 @@
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
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
@@ -358,3 +431,8 @@ version 2.43
ports. Thanks to Patrick McLean for spotting this.
Updated French translation. Thanks to Gildas Le Nadan.
version 2.42
The changelog for version 2.42 and earlier is
available in CHANGELOG.archive.

View File

@@ -24,18 +24,22 @@ MAN = man
PKG_CONFIG = pkg-config
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
dnsmasq :
cd $(SRC) && $(MAKE) \
DBUS_CFLAGS=$(DBUS_CFLAGS) \
DBUS_LIBS=$(DBUS_LIBS) \
SUNOS_LIBS=$(SUNOS_LIBS) \
@cd $(SRC) && $(MAKE) \
DNSMASQ_CFLAGS="$(DNSMASQ_CFLAGS)" \
DNSMASQ_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS)" \
-f ../bld/Makefile dnsmasq
clean :
@@ -50,24 +54,25 @@ install-common :
$(INSTALL) -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR)
all-i18n :
cd $(SRC) && $(MAKE) \
@cd $(SRC) && $(MAKE) \
I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \
DBUS_CFLAGS=$(DBUS_CFLAGS) \
DBUS_LIBS=$(DBUS_LIBS) \
SUNOS_LIBS=$(SUNOS_LIBS) \
DNSMASQ_CFLAGS="$(DNSMASQ_CFLAGS) `$(PKG_CONFIG) --cflags libidn`" \
DNSMASQ_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS) `$(PKG_CONFIG) --libs libidn`" \
-f ../bld/Makefile dnsmasq
cd $(PO); for f in *.po; do \
cd ../$(SRC) && $(MAKE) -f ../bld/Makefile $${f%.po}.mo; \
@cd $(PO); for f in *.po; do \
cd ../$(SRC) && $(MAKE) \
MSGMERGE=$(MSGMERGE) MSGFMT=$(MSGFMT) XGETTEXT=$(XGETTEXT) \
-f ../bld/Makefile $${f%.po}.mo; \
done
install-i18n : all-i18n install-common
cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR)
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR)
cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
merge :
$(MAKE) I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' -f ../bld/Makefile -C $(SRC) dnsmasq.pot
cd $(PO); for f in *.po; do \
msgmerge --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
@cd $(SRC) && $(MAKE) XGETTEXT=$(XGETTEXT) -f ../bld/Makefile dnsmasq.pot
@cd $(PO); for f in *.po; do \
echo -n msgmerge $$f && $(MSGMERGE) --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
done

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
.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)
$(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
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
msgmerge -o - ../po/$*.po dnsmasq.pot | msgfmt -o $*.mo -
$(MSGMERGE) -o - ../po/$*.po dnsmasq.pot | $(MSGFMT) -o $*.mo -

View File

@@ -2,8 +2,8 @@
for f in *; do
if [ -d $f ]; then
install -m 755 -d $1/$f/man8
install -m 644 $f/dnsmasq.8 $1/$f/man8
$2 -m 755 -d $1/$f/man8
$2 -m 644 $f/dnsmasq.8 $1/$f/man8
echo installing $1/$f/man8/dnsmasq.8
fi
done

View File

@@ -1,8 +1,8 @@
#!/bin/sh
for f in *.mo; do
install -m 755 -d $1/${f%.mo}/LC_MESSAGES
install -m 644 $f $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
$2 -m 755 -d $1/${f%.mo}/LC_MESSAGES
$2 -m 644 $f $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
echo installing $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
done

View File

@@ -1,7 +1,10 @@
#!/bin/sh
if grep "^\#.*define.*HAVE_DBUS" config.h 2>&1 >/dev/null || \
grep HAVE_DBUS 2>&1 >/dev/null ; then
search=$1
shift
if grep "^\#.*define.*$search" config.h 2>&1 >/dev/null || \
grep $search 2>&1 >/dev/null ; then
exec $*
fi

View File

@@ -396,6 +396,11 @@
# the user dnsmasq is running as will be send over the net.
#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.
#dhcp-boot=net:red,pxelinux.red-net

View File

@@ -45,7 +45,8 @@ additional hosts file. If a directory is given, then read all the files containe
.TP
.B \-E, --expand-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
.B \-T, --local-ttl=<time>
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>
Read DHCP option information from the specified file. The advantage of
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
.B \-Z, --read-ethers
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
DNSMASQ_CLIENT_ID. If the fully-qualified domain name of the host is
known, the domain part is stored in DNSMASQ_DOMAIN.
If the client provides vendor-class or user-class
information, these are provided in DNSMASQ_VENDOR_CLASS and
If the client provides vendor-class, hostname or user-class,
these are provided in DNSMASQ_VENDOR_CLASS
DNSMASQ_SUPPLIED_HOSTNAME and
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
"add" actions or "old" actions when a host resumes an existing 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
variable DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE stores the name of
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
closed except stdin, stdout and stderr which are open to /dev/null
(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
configuration files, to include multiple configuration files.
.TP
.B \-7, --conf-dir=<directory>
.B \-7, --conf-dir=<directory>[,<file-extension>......]
Read all the files in the given directory as configuration
files. Files whose names end in ~ or start with . or start and end
with # are skipped. This flag may be given on the command
files. If extension(s) are given, any files which end in those
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.
.SH CONFIG FILE
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
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
.IR /etc/dnsmasq.conf

View File

@@ -51,7 +51,8 @@ fichiers contenus dans ce répertoire.
.B \-E, --expand-hosts
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
DHCP.
DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les
enregistrements PTR, TXT, etc...
.TP
.B \-T, --local-ttl=<durée>
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>
Lis les informations relatives aux options DHCP dans le fichier spécifié.
L'intérêt d'utiliser cette option est le même que pour --dhcp-hostsfile : le
fichier spécifié ser rechargé à la réception par dnsmasq d'un signal SIGHUP.
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
.B \-Z, --read-ethers
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
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
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
DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 à DNSMASQ_USER_CLASSn
respectivement, mais seulement pour les actions "add" et "old" lorsqu'un hôte
reprend un bail existant, ces variables n'étant pas stockées dans la base de
baux de Dnsmasq. Si Dnsmasq a été compilé avec l'option HAVE_BROKEN_RTC
("horloge RTC défectueuse"), alors la durée du bail (en secondes) est stockée
dans la variable DNSMASQ_LEASE_LENGTH, sinon la date d'expiration du bail est
toujours stocké dans la variable d'environnement DNSMASQ_LEASE_EXPIRES. Le
nombre de secondes avant expiration est toujours stocké dans
DNSMASQ_TIME_REMAINING. Si un bail était associé à un nom d'hôte et que celui-ci
est supprimé, un évênement de type "old" est généré avec le nouveau statut du
bail, c-à-d sans nom d'hôte, et le nom initial est fourni dans la variable
d'environnement DNSMASQ_OLD_HOSTNAME. La variable DNSMASQ_INTERFACE contient le nom de
l'interface sur laquelle la requête est arrivée; ceci n'est pas renseigné
dans le cas des actions "old" ayant lieu après un redémarrage de dnsmasq.
dans DNSMASQ_DOMAIN. Si le client fournit une information de classe de vendeur,
de classe d'utilisateur ou un nom d'hôte, celles-ci sont positionnées dans les
variables DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 à DNSMASQ_USER_CLASSn
et DNSMASQ_SUPPLIED_HOSTNAME respectivement, mais seulement pour les actions
"add" et "old" lorsqu'un hôte reprend un bail existant, ces variables n'étant
pas stockées dans la base de baux de Dnsmasq. Si Dnsmasq a été compilé avec
l'option HAVE_BROKEN_RTC ("horloge RTC défectueuse"), alors la durée du bail
(en secondes) est stockée dans la variable DNSMASQ_LEASE_LENGTH, sinon la date
d'expiration du bail est toujours stocké dans la variable d'environnement
DNSMASQ_LEASE_EXPIRES. Le nombre de secondes avant expiration est toujours
stocké dans DNSMASQ_TIME_REMAINING. Si un bail était associé à un nom d'hôte et
que celui-ci est supprimé, un évênement de type "old" est généré avec le
nouveau statut du bail, c-à-d sans nom d'hôte, et le nom initial est fourni
dans la variable d'environnement DNSMASQ_OLD_HOSTNAME. La variable
DNSMASQ_INTERFACE contient le nom de l'interface sur laquelle la requête est
arrivée; ceci n'est pas renseigné dans le cas des actions "old" ayant lieu
après un redémarrage de dnsmasq. 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
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
@@ -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
l'inclusion de multiples fichiers de configuration.
.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
configuration. Les fichiers dont les noms se terminent en ~ ou commençant par .,
ainsi que ceux commençant ou se terminant par # ne sont pas pris en compte.
configuration. Si des extensions sont données, tout fichier finissant par ces
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
configuration.
.SH FICHIER DE CONFIGURATION

391
po/de.po

File diff suppressed because it is too large Load Diff

392
po/es.po

File diff suppressed because it is too large Load Diff

391
po/fi.po

File diff suppressed because it is too large Load Diff

395
po/fr.po

File diff suppressed because it is too large Load Diff

395
po/id.po

File diff suppressed because it is too large Load Diff

391
po/it.po

File diff suppressed because it is too large Load Diff

392
po/no.po

File diff suppressed because it is too large Load Diff

463
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

392
po/ro.po

File diff suppressed because it is too large Load Diff

View File

@@ -226,7 +226,7 @@ char *cache_get_name(struct crec *crecp)
{
if (crecp->flags & F_BIGNAME)
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.sname;
@@ -366,7 +366,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
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;
/* 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)
for (a = daemon->cnames; a; a = a->next)
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;
strcpy(lookup->name.sname, a->alias);
lookup->flags = F_FORWARD | F_IMMORTAL | F_CONFIG | F_HOSTS | F_CNAME;
lookup->name.namep = a->alias;
lookup->addr.cname.cache = cache;
lookup->addr.cname.uid = index;
cache_hash(lookup);
@@ -821,35 +821,38 @@ static int read_hostsfile(char *filename, int index, int cache_size)
while (atnl == 0)
{
struct crec *cache;
int fqdn;
int fqdn, nomem;
char *canon;
if ((atnl = gettok(f, token)) == EOF)
break;
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 ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn &&
(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, domain_suffix);
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
addr_dup = 1;
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);
name_count++;
}
free(canon);
}
else
else if (!nomem)
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)
{
aliasc->flags = F_FORWARD | F_DHCP | F_CNAME;
aliasc->flags = F_FORWARD | F_CONFIG | F_DHCP | F_CNAME;
if (ttd == 0)
aliasc->flags |= F_IMMORTAL;
else
@@ -1285,12 +1288,12 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr, char *ar
dest = "<CNAME>";
}
if (flags & F_DHCP)
if (flags & F_CONFIG)
source = "config";
else if (flags & F_DHCP)
source = "DHCP";
else if (flags & F_HOSTS)
source = arg;
else if (flags & F_CONFIG)
source = "config";
else if (flags & F_UPSTREAM)
source = "reply";
else if (flags & F_SERVER)

View File

@@ -14,13 +14,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define VERSION "2.50"
#define VERSION "2.51"
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define EDNS_PKTSZ 1280 /* default max EDNS.0 UDP packet from RFC2671 */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define 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 LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
@@ -126,6 +128,9 @@ HAVE_TFTP
HAVE_DHCP
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
define this if you have GNU libc or GNU getopt.
@@ -162,6 +167,7 @@ NOTES:
/* platform independent options- uncomment to enable */
#define HAVE_DHCP
#define HAVE_TFTP
#define HAVE_SCRIPT
/* #define HAVE_BROKEN_RTC */
/* #define HAVE_DBUS */
@@ -175,6 +181,13 @@ NOTES:
#undef HAVE_DHCP
#endif
/* Allow scripts to be disabled with COPTS=-DNO_SCRIPT */
#ifdef NO_SCRIPT
#undef HAVE_SCRIPT
#endif
/* platform dependent options. */
/* Must preceed __linux__ since uClinux defines __linux__ too. */
@@ -273,3 +286,8 @@ NOTES:
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
#endif
/* Can't do scripts without fork */
#ifdef NOFORK
# undef HAVE_SCRIPT
#endif

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;
DBusMessage* message = NULL;
DBusMessageIter args;
const char *action_str;
char *action_str, *addr, *mac = daemon->namebuff;
unsigned char *p;
int i;
if (!connection)
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)
action_str = "DhcpLeaseDeleted";
else if (action == ACTION_ADD)
@@ -409,6 +418,8 @@ void emit_dbus_signal(int action, char *mac, char *hostname, char *addr)
else
return;
addr = inet_ntoa(lease->addr);
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
return;

View File

@@ -754,6 +754,8 @@ void dhcp_read_ethers(void)
while (fgets(buff, MAXDNAME, f))
{
char *host = NULL;
lineno++;
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
@@ -792,19 +794,28 @@ void dhcp_read_ethers(void)
}
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;
}
flags = CONFIG_NAME;
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;
}
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)
{
for (config = daemon->dhcp_conf; config; config = config->next)
@@ -834,10 +845,8 @@ void dhcp_read_ethers(void)
if (flags & CONFIG_NAME)
{
if ((config->hostname = whine_malloc(strlen(ip)+1)))
strcpy(config->hostname, ip);
else
config->flags &= ~CONFIG_NAME;
config->hostname = host;
host = NULL;
}
if (flags & CONFIG_ADDR)
@@ -856,6 +865,9 @@ void dhcp_read_ethers(void)
config->hwaddr->next = NULL;
}
count++;
free(host);
}
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
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)
{
struct crec *lookup;
@@ -963,7 +976,7 @@ char *host_from_dns(struct in_addr addr)
hostname[255] = 0;
d1 = strip_hostname(hostname);
d2 = get_domain(addr);
if (d1 && (!d2 || hostname_isequal(d1, d2)))
if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
hostname = NULL;
}

View File

@@ -45,11 +45,16 @@ static char *compile_opts =
"no-"
#endif
"DHCP "
#if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
"no-scripts "
#endif
#ifndef HAVE_TFTP
"no-"
#endif
"TFTP";
static volatile pid_t pid = 0;
static volatile int pipewrite;
@@ -68,7 +73,7 @@ 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
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
uid_t script_uid = 0;
gid_t script_gid = 0;
#endif
@@ -202,7 +207,7 @@ int main (int argc, char **argv)
if (daemon->port != 0)
pre_allocate_sfds();
#ifdef HAVE_DHCP
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
/* Note getpwnam returns static storage */
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. */
daemon->helperfd = -1;
#if defined(HAVE_DHCP) && !defined(NO_FORK)
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
if (daemon->dhcp && daemon->lease_change_command)
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
#endif
@@ -603,7 +608,7 @@ int main (int argc, char **argv)
bump_maxfd(piperead, &maxfd);
#ifdef HAVE_DHCP
# ifndef NO_FORK
# ifdef HAVE_SCRIPT
while (helper_buf_empty() && do_script_run(now));
if (!helper_buf_empty())
@@ -674,7 +679,7 @@ int main (int argc, char **argv)
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
dhcp_packet(now);
# ifndef NO_FORK
# ifdef HAVE_SCRIPT
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
helper_write();
# endif
@@ -857,7 +862,7 @@ static void async_event(int pipe, time_t now)
if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGALRM);
#if defined(HAVE_DHCP) && !defined(NO_FORK)
#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
/* handle pending lease transitions */
if (daemon->helperfd != -1)
{

View File

@@ -30,6 +30,7 @@
/* get these before config.h for IPv6 stuff... */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef __APPLE__
@@ -55,7 +56,6 @@
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#if defined(HAVE_SOLARIS_NETWORK)
#include <sys/sockio.h>
@@ -335,7 +335,7 @@ struct server {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int dhcp_ok;
int dhcp_ok, mtu;
struct irec *next;
};
@@ -410,9 +410,9 @@ struct dhcp_lease {
#endif
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
struct in_addr addr, override;
unsigned char *vendorclass, *userclass;
unsigned int vendorclass_len, userclass_len;
struct in_addr addr, override, giaddr;
unsigned char *vendorclass, *userclass, *supplied_hostname;
unsigned int vendorclass_len, userclass_len, supplied_hostname_len;
int last_interface;
struct dhcp_lease *next;
};
@@ -626,6 +626,7 @@ extern struct daemon {
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
struct pxe_service *pxe_services;
int enable_pxe;
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;
@@ -646,6 +647,8 @@ extern struct daemon {
struct irec *interfaces;
struct listener *listeners;
struct server *last_server;
time_t forwardtime;
int forwardcount;
struct server *srv_save; /* Used for resend on DoD */
size_t packet_len; /* " " */
struct randfd *rfd_save; /* " " */
@@ -719,8 +722,8 @@ size_t resize_packet(HEADER *header, size_t plen,
/* util.c */
void rand_init(void);
unsigned short rand16(void);
int legal_char(char c);
int canonicalise(char *s);
int legal_hostname(char *c);
char *canonicalise(char *s, int *nomem);
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
void *safe_malloc(size_t size);
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);
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 emit_dbus_signal(int action, char *mac, char *hostname, char *addr);
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
#endif
/* helper.c */

View File

@@ -262,10 +262,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (type != 0 || (daemon->options & OPT_ORDER))
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;
forward->forwardall = 1;
daemon->forwardcount = 0;
daemon->forwardtime = now;
}
}
}

View File

@@ -28,15 +28,15 @@
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);
struct script_data
{
unsigned char action, hwaddr_len, hwaddr_type;
unsigned char clid_len, hostname_len, uclass_len, vclass_len;
struct in_addr addr;
unsigned char clid_len, hostname_len, uclass_len, vclass_len, shost_len;
struct in_addr addr, giaddr;
unsigned int remaining_time;
#ifdef HAVE_BROKEN_RTC
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
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 &&
max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_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);
#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;
/* 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);
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;
hostname = (char *)buf;
hostname[data.hostname_len - 1] = 0;
if (!canonicalise(hostname))
if (!legal_hostname(hostname))
hostname = NULL;
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;
size_t size;
int i;
unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0;
unsigned int hostname_len = 0, clid_len = 0, vclass_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 */
if (daemon->helperfd == -1)
return;
@@ -303,12 +310,14 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
vclass_len = lease->vendorclass_len;
if (lease->userclass)
uclass_len = lease->userclass_len;
if (lease->supplied_hostname)
shost_len = lease->supplied_hostname_len;
if (lease->clid)
clid_len = lease->clid_len;
if (hostname)
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)
{
@@ -332,8 +341,10 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
buf->clid_len = clid_len;
buf->vclass_len = vclass_len;
buf->uclass_len = uclass_len;
buf->shost_len = shost_len;
buf->hostname_len = hostname_len;
buf->addr = lease->addr;
buf->giaddr = lease->giaddr;
memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len);
buf->interface[0] = 0;
#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);
p += uclass_len;
}
/* substitute * for space: spaces are allowed in hostnames (for DNS-SD)
and are likley to be a security hole in most scripts. */
for (i = 0; i < (int)hostname_len; i++)
if ((daemon->options & OPT_LEASE_RO) && hostname[i] == ' ')
*(p++) = '*';
else
*(p++) = hostname[i];
if (shost_len != 0)
{
memcpy(p, lease->supplied_hostname, shost_len);
p += shost_len;
}
if (hostname_len != 0)
{
memcpy(p, hostname, hostname_len);
p += hostname_len;
}
bytes_in_buf = p - (unsigned char *)buf;
}

View File

@@ -42,14 +42,20 @@ void lease_init(time_t now)
initial state of the database. If leasefile-ro is
set without a script, we just do without any
lease database. */
if (!daemon->lease_change_command)
#ifdef HAVE_SCRIPT
if (daemon->lease_change_command)
{
file_dirty = dns_dirty = 0;
return;
strcpy(daemon->dhcp_buff, daemon->lease_change_command);
strcat(daemon->dhcp_buff, " init");
leasestream = popen(daemon->dhcp_buff, "r");
}
strcpy(daemon->dhcp_buff, daemon->lease_change_command);
strcat(daemon->dhcp_buff, " init");
leasestream = popen(daemon->dhcp_buff, "r");
else
#endif
{
file_dirty = dns_dirty = 0;
return;
}
}
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);
if (strcmp(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);
}
lease_set_hostname(lease, daemon->dhcp_buff, 0);
/* set these correctly: the "old" events are generated later from
the startup synthesised SIGHUP. */
lease->new = lease->changed = 0;
}
#ifdef HAVE_SCRIPT
if (!daemon->lease_stream)
{
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);
}
}
#endif
/* Some leases may have expired */
file_dirty = 0;
@@ -173,7 +175,6 @@ void lease_update_file(time_t now)
struct dhcp_lease *lease;
time_t next_event;
int i, err = 0;
char *p;
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));
/* 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, " ");
ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
if (lease->clid && lease->clid_len != 0)
{
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 (lease->old_hostname)
{
#ifndef NO_FORK
#ifdef HAVE_SCRIPT
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
#endif
free(lease->old_hostname);
@@ -560,8 +554,11 @@ int do_script_run(time_t now)
else
{
kill_name(lease);
#ifndef NO_FORK
#ifdef HAVE_SCRIPT
queue_script(ACTION_DEL, lease, lease->old_hostname, now);
#endif
#ifdef HAVE_DBUS
emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
#endif
old_leases = lease->next;
@@ -569,6 +566,7 @@ int do_script_run(time_t now)
free(lease->clid);
free(lease->vendorclass);
free(lease->userclass);
free(lease->supplied_hostname);
free(lease);
return 1;
@@ -579,7 +577,7 @@ int do_script_run(time_t now)
for (lease = leases; lease; lease = lease->next)
if (lease->old_hostname)
{
#ifndef NO_FORK
#ifdef HAVE_SCRIPT
queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
#endif
free(lease->old_hostname);
@@ -591,9 +589,13 @@ int do_script_run(time_t now)
if (lease->new || lease->changed ||
(lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
{
#ifndef NO_FORK
#ifdef HAVE_SCRIPT
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease,
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
lease->new = lease->changed = lease->aux_changed = 0;
@@ -603,7 +605,10 @@ int do_script_run(time_t now)
free(lease->userclass);
lease->userclass = NULL;
free(lease->supplied_hostname);
lease->supplied_hostname = NULL;
return 1;
}

View File

@@ -119,7 +119,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
union mysockaddr *addr, struct in_addr netmask)
{
struct irec *iface;
int fd;
int fd, mtu = 0, loopback;
struct ifreq ifr;
int dhcp_ok = 1;
struct iname *tmp;
@@ -142,12 +142,17 @@ static int iface_allowed(struct irec **irecp, int if_index,
}
return 0;
}
loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
close(fd);
/* If we are restricting the set of interfaces to use, make
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;
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->netmask = netmask;
iface->dhcp_ok = dhcp_ok;
iface->mtu = mtu;
iface->next = *irecp;
*irecp = iface;
return 1;

View File

@@ -406,6 +406,7 @@ static const struct {
{ "domain-search", 119, 0 },
{ "sip-server", 120, 0 },
{ "classless-static-route", 121, 0 },
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
{ NULL, 0, 0 }
};
@@ -530,13 +531,24 @@ static char *split(char *s)
return split_chr(s, ',');
}
static int canonicalise_opt(char *s)
static char *canonicalise_opt(char *s)
{
char *ret;
int nomem;
if (!s)
return 0;
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)
@@ -646,7 +658,7 @@ static void display_opts(void)
printf(_("Known DHCP options:\n"));
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);
}
@@ -684,7 +696,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
if (strstr(arg, "option:") == arg)
{
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)
{
new->opt = opttab[i].val;
@@ -873,7 +885,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
while (arg && *arg)
{
if (!canonicalise_opt(arg))
char *dom;
if (!(dom = arg = canonicalise_opt(arg)))
{
problem = _("bad domain in dhcp-option");
break;
@@ -898,7 +911,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
arg++;
}
*q++ = 0;
free(dom);
/* Now tail-compress using earlier names. */
newlen = q - p;
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;
struct dirent *ent;
char *directory, *path;
struct list {
char *suffix;
struct list *next;
} *ignore_suffix = NULL, *li;
comma = split(arg);
if (!(directory = opt_string_alloc(arg)))
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)))
die(_("cannot access directory %s: %s"), directory, EC_FILE);
while ((ent = readdir(dir_stream)))
{
size_t len = strlen(ent->d_name);
struct stat buf;
/* ignore emacs backups and dotfiles */
/* ignore emacs backups and dotfiles */
if (len == 0 ||
ent->d_name[len - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
ent->d_name[0] == '.')
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);
strcpy(path, directory);
strcat(path, "/");
@@ -1055,6 +1095,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
closedir(dir_stream);
free(directory);
for(; ignore_suffix; ignore_suffix = li)
{
li = ignore_suffix->next;
free(ignore_suffix->suffix);
free(ignore_suffix);
}
break;
}
@@ -1127,32 +1174,32 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
{
int pref = 1;
struct mx_srv_record *new;
char *name, *target = NULL;
if ((comma = split(arg)))
{
char *prefstr;
if ((prefstr=split(comma)) && !atoi_check16(prefstr, &pref))
if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
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");
new = opt_malloc(sizeof(struct mx_srv_record));
new->next = daemon->mxnames;
daemon->mxnames = new;
new->issrv = 0;
new->name = opt_string_alloc(arg);
new->target = opt_string_alloc(comma); /* may be NULL */
new->name = name;
new->target = target; /* may be NULL */
new->weight = pref;
break;
}
case 't': /* --mx-target */
if (!canonicalise_opt(arg))
if (!(daemon->mxtarget = canonicalise_opt(arg)))
problem = _("bad MX target");
else
daemon->mxtarget = opt_string_alloc(arg);
break;
#ifdef HAVE_DHCP
@@ -1161,8 +1208,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
break;
case '6': /* --dhcp-script */
# ifdef NO_FORK
# if defined(NO_FORK)
problem = _("cannot run scripts under uClinux");
# elif !defined(HAVE_SCRIPT)
problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
# else
daemon->lease_change_command = opt_string_alloc(arg);
# endif
@@ -1186,12 +1235,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
daemon->options |= OPT_RESOLV_DOMAIN;
else
{
char *d;
comma = split(arg);
if (!canonicalise_opt(arg))
if (!(d = canonicalise_opt(arg)))
option = '?';
else
{
char *d = opt_string_alloc(arg);
if (comma)
{
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 */
if (strcmp(arg, "#") == 0)
domain = "";
else if (!canonicalise_opt(arg) && strlen(arg) != 0)
else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?';
else
domain = opt_string_alloc(arg); /* NULL if strlen is zero */
serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server));
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])))
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 = '?';
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;
else
{
int len = strlen(a[j]) + 1;
if (!canonicalise_opt(a[j]))
if (!(new->hostname = canonicalise_opt(a[j])) ||
!legal_hostname(new->hostname))
problem = _("bad DHCP host name");
else if ((new->hostname = opt_malloc(len)))
{
new->flags |= CONFIG_NAME;
strcpy(new->hostname, a[j]);
new->domain = NULL;
}
else
new->flags |= CONFIG_NAME;
new->domain = NULL;
}
}
else
@@ -1983,6 +2027,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->next = daemon->dhcp_opts;
daemon->dhcp_opts = new;
daemon->enable_pxe = 1;
}
break;
@@ -2051,6 +2096,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
s->next = new;
}
daemon->enable_pxe = 1;
break;
}
}
@@ -2243,19 +2289,20 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case LOPT_INTNAME: /* --interface-name */
{
struct interface_name *new, **up;
char *domain = NULL;
comma = split(arg);
if (!comma || !canonicalise_opt(arg))
if (!comma || !(domain = canonicalise_opt(arg)))
problem = _("bad interface name");
new = opt_malloc(sizeof(struct interface_name));
new->next = NULL;
/* Add to the end of the list, so that first name
of an interface is used for PTR lookups. */
for (up = &daemon->int_names; *up; up = &((*up)->next));
*up = new;
new->name = opt_string_alloc(arg);
new->name = domain;
new->intr = opt_string_alloc(comma);
break;
}
@@ -2268,14 +2315,22 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
option = '?';
else
{
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 = opt_string_alloc(arg);
new->target = opt_string_alloc(comma);
char *alias = canonicalise_opt(arg);
char *target = canonicalise_opt(comma);
if (!alias || !target)
problem = _("bad CNAME");
else
{
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;
}
@@ -2283,19 +2338,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case LOPT_PTR: /* --ptr-record */
{
struct ptr_record *new;
char *dom, *target = NULL;
comma = split(arg);
if (!canonicalise_opt(arg))
if (!(dom = canonicalise_opt(arg)) ||
(comma && !(target = canonicalise_opt(comma))))
problem = _("bad PTR record");
new = opt_malloc(sizeof(struct ptr_record));
new->next = daemon->ptr;
daemon->ptr = new;
new->name = opt_string_alloc(arg);
new->ptr = NULL;
if (comma)
new->ptr = opt_string_alloc(comma);
else
{
new = opt_malloc(sizeof(struct ptr_record));
new->next = daemon->ptr;
daemon->ptr = new;
new->name = dom;
new->ptr = target;
}
break;
}
@@ -2305,6 +2362,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
int k = 0;
struct naptr *new;
int order, pref;
char *name, *replace = NULL;
if ((a[0] = arg))
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 ||
!canonicalise_opt(a[0]) ||
!(name = canonicalise_opt(a[0])) ||
!atoi_check16(a[1], &order) ||
!atoi_check16(a[2], &pref) ||
(k == 7 && !canonicalise_opt(a[6])))
(k == 7 && !(replace = canonicalise_opt(a[6]))))
problem = _("bad NAPTR record");
else
{
new = opt_malloc(sizeof(struct naptr));
new->next = daemon->naptr;
daemon->naptr = new;
new->name = opt_string_alloc(a[0]);
new->name = name;
new->flags = opt_string_alloc(a[3]);
new->services = opt_string_alloc(a[4]);
new->regexp = opt_string_alloc(a[5]);
if (k == 7)
new->replace = opt_string_alloc(a[6]);
new->replace = replace;
new->order = order;
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");
if (!canonicalise_opt(arg))
{
problem = _("bad TXT record");
break;
}
if ((q = (unsigned char *)comma))
while (1)
{
@@ -2394,7 +2445,13 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
/* ensure arg is terminated */
if (comma)
*comma = 0;
new->name = opt_string_alloc(arg);
if (!(new->name = canonicalise_opt(arg)))
{
problem = _("bad TXT record");
break;
}
break;
}
@@ -2406,19 +2463,16 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
comma = split(arg);
if (!canonicalise_opt(arg))
if (!(name = canonicalise_opt(arg)))
problem = _("bad SRV record");
name = opt_string_alloc(arg);
if (comma)
{
arg = comma;
comma = split(arg);
if (!canonicalise_opt(arg))
problem = _("bad SRV target");
if (!(target = canonicalise_opt(arg))
) problem = _("bad SRV target");
target = opt_string_alloc(arg);
if (comma)
{
arg = comma;
@@ -2683,7 +2737,7 @@ void reread_dhcp(void)
}
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)
@@ -2714,7 +2768,7 @@ void reread_dhcp(void)
}
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
@@ -2898,8 +2952,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
continue;
if ((token = strtok(NULL, " \t\n\r")) &&
canonicalise_opt(token) &&
(daemon->domain_suffix = opt_string_alloc(token)))
(daemon->domain_suffix = canonicalise_opt(token)))
break;
}

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++)
if (isExtract)
{
if (legal_char(*p))
unsigned char c = *p;
if (isascii(c) && !iscntrl(c) && c != '.')
*cp++ = *p;
else
return 0;

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)
if (match_netid(id_list->list, netid, 0))
message = _("disabled");
message = _("ignored");
if (!message)
{
@@ -536,7 +536,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
*pq = 0;
if (canonicalise(daemon->dhcp_buff))
if (legal_hostname(daemon->dhcp_buff))
offer_hostname = client_hostname = daemon->dhcp_buff;
}
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;
else
daemon->dhcp_buff[len] = 0;
if (canonicalise(daemon->dhcp_buff))
if (legal_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;
/* 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)
{
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];
struct dhcp_opt opt71;
if (ignore)
return 0;
if (layer & 0x8000)
{
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);
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);
return dhcp_packet_size(mess, netid, agent_id, real_end);
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy" : "proxy-ignored", mess->xid);
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 (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
lease->changed = 1;
/* copy user-class and vendor class into new lease, for the script */
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;
}
}
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)))
@@ -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 */
if (agent_id)
{
unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
memmove(p, agent_id, real_end - agent_id);
p += real_end - agent_id;
memset(p, 0, real_end - p); /* in case of overlap */
@@ -1547,9 +1565,8 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
/* We do logging too */
if (netid && (daemon->options & OPT_LOG_OPTS))
{
char *p = daemon->namebuff;
*p = 0;
for (; netid; netid = netid->next)
char *s = daemon->namebuff;
for (*s = 0; netid; netid = netid->next)
{
/* kill dupes. */
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)
{
strncat (p, netid->net, MAXDNAME);
strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
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), p);
my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s);
}
/* add END options to the regions. */
@@ -2074,21 +2090,26 @@ static void do_options(struct dhcp_context *context,
}
else
/* 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 &&
(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);
done_file = 1;
}
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);
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

View File

@@ -46,12 +46,13 @@ void tftp_request(struct listener *listen, time_t now)
struct sockaddr_in addr, peer;
struct msghdr msg;
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 tftp_transfer *transfer;
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
int mtu = IP_PMTUDISC_DONT;
int mtuflag = IP_PMTUDISC_DONT;
#endif
union {
@@ -83,7 +84,10 @@ void tftp_request(struct listener *listen, time_t now)
return;
if (daemon->options & OPT_NOWILD)
addr = listen->iface->addr.in;
{
addr = listen->iface->addr.in;
mtu = listen->iface->mtu;
}
else
{
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)
if (tmp->name && (strcmp(tmp->name, name) == 0))
return;
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
}
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 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
!fix_fd(transfer->sockfd))
{
@@ -202,6 +209,9 @@ void tftp_request(struct listener *listen, time_t now)
transfer->blocksize = 1;
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;
}
@@ -213,6 +223,10 @@ void tftp_request(struct listener *listen, time_t now)
}
}
/* cope with backslashes from windows boxen. */
while ((p = strchr(filename, '\\')))
*p = '/';
strcpy(daemon->namebuff, "/");
if (daemon->tftp_prefix)
{

View File

@@ -24,6 +24,9 @@
#include <sys/times.h>
#endif
#ifdef LOCALEDIR
#include <idna.h>
#endif
#ifdef HAVE_ARC4RANDOM
void rand_init(void)
@@ -95,48 +98,110 @@ unsigned short rand16(void)
#endif
int legal_char(char c)
static int check_name(char *in)
{
/* check for legal char a-z A-Z 0-9 -
(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 .
/* remove trailing .
also fail empty string and label > 63 chars */
size_t dotgap = 0, l = strlen(s);
size_t dotgap = 0, l = strlen(in);
char c;
int nowhite = 0;
if (l == 0 || l > MAXDNAME) return 0;
if (s[l-1] == '.')
if (in[l-1] == '.')
{
if (l == 1) return 0;
s[l-1] = 0;
in[l-1] = 0;
}
while ((c = *s))
for (; (c = *in); in++)
{
if (c == '.')
dotgap = 0;
else if (!legal_char(c) || (++dotgap > MAXLABEL))
else if (++dotgap > MAXLABEL)
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 != ' ')
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)