Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73a08a248d | ||
|
|
9009d74652 | ||
|
|
1ad24ae15c |
183
CHANGELOG
183
CHANGELOG
@@ -2595,7 +2595,188 @@ version 2.44
|
||||
Jean Wolter for finding this.
|
||||
|
||||
Change implementation of min_port to work even if min-port
|
||||
as large.
|
||||
is large.
|
||||
|
||||
Patch to enable compilation of latest Mac OS X. Thanks to
|
||||
David Gilman.
|
||||
|
||||
Update Spanish translation. Thanks to Christopher Chatham.
|
||||
|
||||
version 2.45
|
||||
Fix total DNS failure in release 2.44 unless --min-port
|
||||
specified. Thanks to Steven Barth and Grant Coady for
|
||||
bugreport. Also reject out-of-range port spec, which could
|
||||
break things too: suggestion from Gilles Espinasse.
|
||||
|
||||
version 2.46
|
||||
Allow --bootp-dynamic to take a netid tag, so that it may
|
||||
be selectively enabled. Thanks to Olaf Westrik for the
|
||||
suggestion.
|
||||
|
||||
Remove ISC-leasefile reading code. This has been
|
||||
deprecated for a long time, and last time I removed it, it
|
||||
ended up going back by request of one user. This time,
|
||||
it's gone for good; otherwise it would need to be
|
||||
re-worked to support multiple domains (see below).
|
||||
|
||||
Support DHCP clients in multiple DNS domains. This is a
|
||||
long-standing request. Clients are assigned to a domain
|
||||
based in their IP address.
|
||||
|
||||
Add --dhcp-fqdn flag, which changes behaviour if DNS names
|
||||
assigned to DHCP clients. When this is set, there must be
|
||||
a domain associated with each client, and only
|
||||
fully-qualified domain names are added to the DNS. The
|
||||
advantage is that the only the FQDN needs to be unique,
|
||||
so that two or more DHCP clients can share a hostname, as
|
||||
long as they are in different domains.
|
||||
|
||||
Set environment variable DNSMASQ_DOMAIN when invoking
|
||||
lease-change script. This may be useful information to
|
||||
have now that it's variable.
|
||||
|
||||
Tighten up data-checking code for DNS packet
|
||||
handling. Thanks to Steve Dodd who found certain illegal
|
||||
packets which could crash dnsmasq. No memory overwrite was
|
||||
possible, so this is not a security issue beyond the DoS
|
||||
potential.
|
||||
|
||||
Update example config dhcp option 47, the previous
|
||||
suggestion generated an illegal, zero-length,
|
||||
option. Thanks to Matthias Andree for finding this.
|
||||
|
||||
Rewrite hosts-file reading code to remove the limit of
|
||||
1024 characters per line. John C Meuser found this.
|
||||
|
||||
Create a net-id tag with the name of the interface on
|
||||
which the DHCP request was received.
|
||||
|
||||
Fixed minor memory leak in DBus code, thanks to Jeremy
|
||||
Laine for the patch.
|
||||
|
||||
Emit DBus signals as the DHCP lease database
|
||||
changes. Thanks to Jeremy Laine for the patch.
|
||||
|
||||
Allow for more that one MAC address in a dhcp-host
|
||||
line. This configuration tells dnsmasq that it's OK to
|
||||
abandon a DHCP lease of the fixed address to one MAC
|
||||
address, if another MAC address in the dhcp-host statement
|
||||
asks for an address. This is useful to give a fixed
|
||||
address to a host which has two network interfaces
|
||||
(say, a laptop with wired and wireless interfaces.)
|
||||
It's very important to ensure that only one interface
|
||||
at a time is up, since dnsmasq abandons the first lease
|
||||
and re-uses the address before the leased time has
|
||||
elapsed. John Gray suggested this.
|
||||
|
||||
Tweak the response to a DHCP request packet with a wrong
|
||||
server-id when --dhcp-authoritative is set; dnsmasq now
|
||||
returns a DHCPNAK, rather than silently ignoring the
|
||||
packet. Thanks to Chris Marget for spotting this
|
||||
improvement.
|
||||
|
||||
Add --cname option. This provides a limited alias
|
||||
function, usable for DHCP names. Thanks to AJ Weber for
|
||||
suggestions on this.
|
||||
|
||||
Updated contrib/webmin with latest version from Neil
|
||||
Fisher.
|
||||
|
||||
Updated Polish translation. Thanks to Jan Psota.
|
||||
|
||||
Correct the text names for DHCP options 64 and 65 to be
|
||||
"nis+-domain" and "nis+-servers".
|
||||
|
||||
Updated Spanish translation. Thanks to Chris Chatham.
|
||||
|
||||
Force re-reading of /etc/resolv.conf when an "interface
|
||||
up" event occurs.
|
||||
|
||||
|
||||
version 2.47
|
||||
Updated French translation. Thanks to Gildas Le Nadan.
|
||||
|
||||
Fixed interface enumeration code to work on NetBSD
|
||||
5.0. Thanks to Roy Marples for the patch.
|
||||
|
||||
Updated config.h to use the same location for the lease
|
||||
file on NetBSD as the other *BSD variants. Also allow
|
||||
LEASEFILE and CONFFILE symbols to be overriden in CFLAGS.
|
||||
|
||||
Handle duplicate address detection on IPv6 more
|
||||
intelligently. In IPv6, an interface can have an address
|
||||
which is not usable, because it is still undergoing DAD
|
||||
(such addresses are marked "tentative"). Attempting to
|
||||
bind to an address in this state returns an error,
|
||||
EADDRNOTAVAIL. Previously, on getting such an error,
|
||||
dnsmasq would silently abandon the address, and never
|
||||
listen on it. Now, it retries once per second for 20
|
||||
seconds before generating a fatal error. 20 seconds should
|
||||
be long enough for any DAD process to complete, but can be
|
||||
adjusted in src/config.h if necessary. Thanks to Martin
|
||||
Krafft for the bug report.
|
||||
|
||||
Add DBus introspection. Patch from Jeremy Laine.
|
||||
|
||||
Update Dbus configuration file. Patch from Colin Walters.
|
||||
Fix for this bug:
|
||||
http://bugs.freedesktop.org/show_bug.cgi?id=18961
|
||||
|
||||
Support arbitrarily encapsulated DHCP options, suggestion
|
||||
and initial patch from Samium Gromoff. This is useful for
|
||||
(eg) gPXE, which expect all its private options to be
|
||||
encapsulated inside a single option 175. So, eg,
|
||||
|
||||
dhcp-option = encap:175, 190, "iscsi-client0"
|
||||
dhcp-option = encap:175, 191, "iscsi-client0-secret"
|
||||
|
||||
will provide iSCSI parameters to gPXE.
|
||||
|
||||
Enhance --dhcp-match to allow testing of the contents of a
|
||||
client-sent option, as well as its presence. This
|
||||
application in mind for this is RFC 4578
|
||||
client-architecture specifiers, but it's generally useful.
|
||||
Joey Korkames suggested the enhancement.
|
||||
|
||||
Move from using the IP_XMIT_IF ioctl to IP_BOUND_IF on
|
||||
OpenSolaris. Thanks to Bastian Machek for the heads-up.
|
||||
|
||||
No longer complain about blank lines in
|
||||
/etc/ethers. Thanks to Jon Nelson for the patch.
|
||||
|
||||
Fix binding of servers to physical devices, eg
|
||||
--server=/domain/1.2.3.4@eth0 which was broken from 2.43
|
||||
onwards unless --query-port=0 set. Thanks to Peter Naulls
|
||||
for the bug report.
|
||||
|
||||
Reply to DHCPINFORM requests even when the supplied ciaddr
|
||||
doesn't fall in any dhcp-range. In this case it's not
|
||||
possible to supply a complete configuration, but
|
||||
individually-configured options (eg PAC) may be useful.
|
||||
|
||||
Allow the source address of an alias to be a range:
|
||||
--alias=192.168.0.0,10.0.0.0,255.255.255.0 maps the whole
|
||||
subnet 192.168.0.0->192.168.0.255 to 10.0.0.0->10.0.0.255,
|
||||
as before.
|
||||
--alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
|
||||
maps only the 192.168.0.10->192.168.0.40 region. Thanks to
|
||||
Ib Uhrskov for the suggestion.
|
||||
|
||||
Don't dynamically allocate DHCP addresses which may break
|
||||
Windows. Addresses which end in .255 or .0 are broken in
|
||||
Windows even when using supernetting.
|
||||
--dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 means
|
||||
192.168.0.255 is a valid IP address, but not for Windows.
|
||||
See Microsoft KB281579. We therefore no longer allocate
|
||||
these addresses to avoid hard-to-diagnose problems.
|
||||
|
||||
Update Polish translation. Thanks to Jan Psota.
|
||||
|
||||
Delete the PID-file when dnsmasq shuts down. Note that by
|
||||
this time, dnsmasq is normally not running as root, so
|
||||
this will fail if the PID-file is stored in a root-owned
|
||||
directory; such failure is silently ignored. To take
|
||||
advantage of this feature, the PID-file must be stored in a
|
||||
directory owned and write-able by the user running
|
||||
dnsmasq.
|
||||
|
||||
|
||||
19
FAQ
19
FAQ
@@ -16,6 +16,14 @@ A: The high ports that dnsmasq opens are for replies from the upstream
|
||||
you to specify the UDP port to be used for this purpose. If not
|
||||
specified, the operating system will select an available port number
|
||||
just as it did before.
|
||||
|
||||
Second addendum: following the discovery of a security flaw in the
|
||||
DNS protocol, dnsmasq from version 2.43 has changed behavior. It
|
||||
now uses a new, randomly selected, port for each query. The old
|
||||
default behaviour (use one port allocated by the OS) is available by
|
||||
setting --query-port=0, and setting the query port to a positive
|
||||
value is still works. You should think hard and know what you are
|
||||
doing before using either of these options.
|
||||
|
||||
Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify
|
||||
that?
|
||||
@@ -324,6 +332,17 @@ A: By default, the identity of a machine is determined by using the
|
||||
method for setting the client-id varies with DHCP client software,
|
||||
dhcpcd uses the "-I" flag. Windows uses a registry setting,
|
||||
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
|
||||
Addendum:
|
||||
From version 2.46, dnsmasq has a solution to this which doesn't
|
||||
involve setting client-IDs. It's possible to put more than one MAC
|
||||
address in a --dhcp-host configuration. This tells dnsmasq that it
|
||||
should use the specified IP for any of the specified MAC addresses,
|
||||
and furthermore it gives dnsmasq permission to sumarily abandon a
|
||||
lease to one of the MAC addresses if another one comes along. Note
|
||||
that this will work fine only as longer as only one interface is
|
||||
up at any time. There is no way for dnsmasq to enforce this
|
||||
constraint: if you configure multiple MAC addresses and violate
|
||||
this rule, bad things will happen.
|
||||
|
||||
Q: Can dnsmasq do DHCP on IP-alias interfaces?
|
||||
|
||||
|
||||
6
Makefile
6
Makefile
@@ -1,4 +1,4 @@
|
||||
# dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
# dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
PREFIX = /usr/local
|
||||
BINDIR = ${PREFIX}/sbin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CFLAGS = -Wall -W -O2
|
||||
|
||||
OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \
|
||||
OBJS = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||
helper.o tftp.o log.o
|
||||
|
||||
|
||||
20
contrib/lease-access/README
Normal file
20
contrib/lease-access/README
Normal file
@@ -0,0 +1,20 @@
|
||||
Hello,
|
||||
|
||||
For some specific application I needed to deny access to a MAC address
|
||||
to a lease. For this reason I modified the dhcp-script behavior and is
|
||||
called with an extra parameter "access" once a dhcp request or discover
|
||||
is received. In that case if the exit code of the script is zero,
|
||||
dnsmasq continues normally, and if non-zero the packet is ignored.
|
||||
|
||||
This was not added as a security feature but as a mean to handle
|
||||
differently some addresses. It is also quite intrusive since it requires
|
||||
changes in several other subsystems.
|
||||
|
||||
It attach the patch in case someone is interested.
|
||||
|
||||
regards,
|
||||
Nikos
|
||||
|
||||
nmav@gennetsa.com
|
||||
|
||||
|
||||
578
contrib/lease-access/lease.access.patch
Normal file
578
contrib/lease-access/lease.access.patch
Normal file
@@ -0,0 +1,578 @@
|
||||
Index: src/dnsmasq.c
|
||||
===================================================================
|
||||
--- src/dnsmasq.c (revision 696)
|
||||
+++ src/dnsmasq.c (revision 821)
|
||||
@@ -59,7 +59,6 @@
|
||||
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
|
||||
static void check_dns_listeners(fd_set *set, time_t now);
|
||||
static void sig_handler(int sig);
|
||||
-static void async_event(int pipe, time_t now);
|
||||
static void fatal_event(struct event_desc *ev);
|
||||
static void poll_resolv(void);
|
||||
|
||||
@@ -275,7 +274,7 @@
|
||||
piperead = pipefd[0];
|
||||
pipewrite = pipefd[1];
|
||||
/* prime the pipe to load stuff first time. */
|
||||
- send_event(pipewrite, EVENT_RELOAD, 0);
|
||||
+ send_event(pipewrite, EVENT_RELOAD, 0, 0);
|
||||
|
||||
err_pipe[1] = -1;
|
||||
|
||||
@@ -340,7 +339,7 @@
|
||||
}
|
||||
else if (getuid() == 0)
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_PIDFILE, errno);
|
||||
+ send_event(err_pipe[1], EVENT_PIDFILE, errno, 0);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
@@ -372,7 +371,7 @@
|
||||
(setgroups(0, &dummy) == -1 ||
|
||||
setgid(gp->gr_gid) == -1))
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
|
||||
+ send_event(err_pipe[1], EVENT_GROUP_ERR, errno, 0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
@@ -415,14 +414,14 @@
|
||||
|
||||
if (bad_capabilities != 0)
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
|
||||
+ send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, 0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/* finally drop root */
|
||||
if (setuid(ent_pw->pw_uid) == -1)
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_USER_ERR, errno);
|
||||
+ send_event(err_pipe[1], EVENT_USER_ERR, errno, 0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
@@ -434,7 +433,7 @@
|
||||
/* lose the setuid and setgid capbilities */
|
||||
if (capset(hdr, data) == -1)
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_CAP_ERR, errno);
|
||||
+ send_event(err_pipe[1], EVENT_CAP_ERR, errno, 0);
|
||||
_exit(0);
|
||||
}
|
||||
#endif
|
||||
@@ -647,7 +646,7 @@
|
||||
}
|
||||
|
||||
if (FD_ISSET(piperead, &rset))
|
||||
- async_event(piperead, now);
|
||||
+ async_event(piperead, now, NULL, 0);
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||
@@ -674,7 +673,7 @@
|
||||
#endif
|
||||
|
||||
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
|
||||
- dhcp_packet(now);
|
||||
+ dhcp_packet(piperead, now);
|
||||
|
||||
#ifndef NO_FORK
|
||||
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
|
||||
@@ -719,17 +718,18 @@
|
||||
else
|
||||
return;
|
||||
|
||||
- send_event(pipewrite, event, 0);
|
||||
+ send_event(pipewrite, event, 0, 0);
|
||||
errno = errsave;
|
||||
}
|
||||
}
|
||||
|
||||
-void send_event(int fd, int event, int data)
|
||||
+void send_event(int fd, int event, int data, int priv)
|
||||
{
|
||||
struct event_desc ev;
|
||||
|
||||
ev.event = event;
|
||||
ev.data = data;
|
||||
+ ev.priv = priv;
|
||||
|
||||
/* error pipe, debug mode. */
|
||||
if (fd == -1)
|
||||
@@ -771,14 +771,17 @@
|
||||
die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
|
||||
}
|
||||
}
|
||||
-
|
||||
-static void async_event(int pipe, time_t now)
|
||||
+
|
||||
+/* returns the private data of the event
|
||||
+ */
|
||||
+int async_event(int pipe, time_t now, struct event_desc* event, unsigned int secs)
|
||||
{
|
||||
pid_t p;
|
||||
struct event_desc ev;
|
||||
int i;
|
||||
|
||||
- if (read_write(pipe, (unsigned char *)&ev, sizeof(ev), 1))
|
||||
+ if (read_timeout(pipe, (unsigned char *)&ev, sizeof(ev), now, secs) > 0)
|
||||
+ {
|
||||
switch (ev.event)
|
||||
{
|
||||
case EVENT_RELOAD:
|
||||
@@ -872,6 +875,14 @@
|
||||
flush_log();
|
||||
exit(EC_GOOD);
|
||||
}
|
||||
+ }
|
||||
+ else
|
||||
+ return -1; /* timeout */
|
||||
+
|
||||
+ if (event)
|
||||
+ memcpy( event, &ev, sizeof(ev));
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void poll_resolv()
|
||||
Index: src/config.h
|
||||
===================================================================
|
||||
--- src/config.h (revision 696)
|
||||
+++ src/config.h (revision 821)
|
||||
@@ -51,6 +51,8 @@
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
#define RANDFILE "/dev/urandom"
|
||||
+#define SCRIPT_TIMEOUT 6
|
||||
+#define LEASE_CHECK_TIMEOUT 10
|
||||
|
||||
/* DBUS interface specifics */
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
|
||||
Index: src/dnsmasq.h
|
||||
===================================================================
|
||||
--- src/dnsmasq.h (revision 696)
|
||||
+++ src/dnsmasq.h (revision 821)
|
||||
@@ -116,6 +116,7 @@
|
||||
/* Async event queue */
|
||||
struct event_desc {
|
||||
int event, data;
|
||||
+ unsigned int priv;
|
||||
};
|
||||
|
||||
#define EVENT_RELOAD 1
|
||||
@@ -390,6 +391,7 @@
|
||||
#define ACTION_OLD_HOSTNAME 2
|
||||
#define ACTION_OLD 3
|
||||
#define ACTION_ADD 4
|
||||
+#define ACTION_ACCESS 5
|
||||
|
||||
#define DHCP_CHADDR_MAX 16
|
||||
|
||||
@@ -709,6 +711,7 @@
|
||||
char *print_mac(char *buff, unsigned char *mac, int len);
|
||||
void bump_maxfd(int fd, int *max);
|
||||
int read_write(int fd, unsigned char *packet, int size, int rw);
|
||||
+int read_timeout(int fd, unsigned char *packet, int size, time_t now, int secs);
|
||||
|
||||
/* log.c */
|
||||
void die(char *message, char *arg1, int exit_code);
|
||||
@@ -748,7 +751,7 @@
|
||||
|
||||
/* dhcp.c */
|
||||
void dhcp_init(void);
|
||||
-void dhcp_packet(time_t now);
|
||||
+void dhcp_packet(int piperead, time_t now);
|
||||
|
||||
struct dhcp_context *address_available(struct dhcp_context *context,
|
||||
struct in_addr addr,
|
||||
@@ -792,14 +795,16 @@
|
||||
void rerun_scripts(void);
|
||||
|
||||
/* rfc2131.c */
|
||||
-size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
+size_t dhcp_reply(int pipefd, struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform);
|
||||
|
||||
/* dnsmasq.c */
|
||||
int make_icmp_sock(void);
|
||||
int icmp_ping(struct in_addr addr);
|
||||
-void send_event(int fd, int event, int data);
|
||||
+void send_event(int fd, int event, int data, int priv);
|
||||
void clear_cache_and_reload(time_t now);
|
||||
+int wait_for_child(int pipe);
|
||||
+int async_event(int pipe, time_t now, struct event_desc*, unsigned int timeout);
|
||||
|
||||
/* isc.c */
|
||||
#ifdef HAVE_ISC_READER
|
||||
@@ -832,9 +837,9 @@
|
||||
/* helper.c */
|
||||
#ifndef NO_FORK
|
||||
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
|
||||
-void helper_write(void);
|
||||
+int helper_write(void);
|
||||
void queue_script(int action, struct dhcp_lease *lease,
|
||||
- char *hostname, time_t now);
|
||||
+ char *hostname, time_t now, unsigned int uid);
|
||||
int helper_buf_empty(void);
|
||||
#endif
|
||||
|
||||
Index: src/util.c
|
||||
===================================================================
|
||||
--- src/util.c (revision 696)
|
||||
+++ src/util.c (revision 821)
|
||||
@@ -444,3 +444,38 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
+int read_timeout(int fd, unsigned char *packet, int size, time_t now, int secs)
|
||||
+{
|
||||
+ ssize_t n, done;
|
||||
+ time_t expire;
|
||||
+
|
||||
+ expire = now + secs;
|
||||
+
|
||||
+ for (done = 0; done < size; done += n)
|
||||
+ {
|
||||
+ retry:
|
||||
+ if (secs > 0) alarm(secs);
|
||||
+ n = read(fd, &packet[done], (size_t)(size - done));
|
||||
+
|
||||
+ if (n == 0)
|
||||
+ return 0;
|
||||
+ else if (n == -1)
|
||||
+ {
|
||||
+ if (errno == EINTR) {
|
||||
+ my_syslog(LOG_INFO, _("read timed out (errno %d)"), errno);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (retry_send() || errno == ENOMEM || errno == ENOBUFS || errno == EAGAIN)
|
||||
+ {
|
||||
+ if (secs == 0 || (secs > 0 && dnsmasq_time() < expire))
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ my_syslog(LOG_INFO, _("error in read (timeout %d, errno %d)"), secs, errno);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
Index: src/dhcp.c
|
||||
===================================================================
|
||||
--- src/dhcp.c (revision 696)
|
||||
+++ src/dhcp.c (revision 821)
|
||||
@@ -103,7 +103,7 @@
|
||||
daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
|
||||
}
|
||||
|
||||
-void dhcp_packet(time_t now)
|
||||
+void dhcp_packet(int piperead, time_t now)
|
||||
{
|
||||
struct dhcp_packet *mess;
|
||||
struct dhcp_context *context;
|
||||
@@ -239,7 +239,8 @@
|
||||
if (!iface_enumerate(&parm, complete_context, NULL))
|
||||
return;
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
- iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
|
||||
+
|
||||
+ iov.iov_len = dhcp_reply(piperead, parm.current, ifr.ifr_name, iface_index, (size_t)sz,
|
||||
now, unicast_dest, &is_inform);
|
||||
lease_update_file(now);
|
||||
lease_update_dns();
|
||||
Index: src/helper.c
|
||||
===================================================================
|
||||
--- src/helper.c (revision 696)
|
||||
+++ src/helper.c (revision 821)
|
||||
@@ -45,6 +45,7 @@
|
||||
#endif
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
char interface[IF_NAMESIZE];
|
||||
+ unsigned int uid;
|
||||
};
|
||||
|
||||
static struct script_data *buf = NULL;
|
||||
@@ -60,7 +61,7 @@
|
||||
then fork our process. */
|
||||
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
|
||||
{
|
||||
- send_event(err_fd, EVENT_PIPE_ERR, errno);
|
||||
+ send_event(err_fd, EVENT_PIPE_ERR, errno, 0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
@@ -87,13 +88,13 @@
|
||||
{
|
||||
if (daemon->options & OPT_NO_FORK)
|
||||
/* send error to daemon process if no-fork */
|
||||
- send_event(event_fd, EVENT_HUSER_ERR, errno);
|
||||
+ send_event(event_fd, EVENT_HUSER_ERR, errno, 0);
|
||||
else
|
||||
{
|
||||
/* kill daemon */
|
||||
- send_event(event_fd, EVENT_DIE, 0);
|
||||
+ send_event(event_fd, EVENT_DIE, 0, 0);
|
||||
/* return error */
|
||||
- send_event(err_fd, EVENT_HUSER_ERR, errno);;
|
||||
+ send_event(err_fd, EVENT_HUSER_ERR, errno, 0);
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
@@ -122,6 +123,8 @@
|
||||
action_str = "del";
|
||||
else if (data.action == ACTION_ADD)
|
||||
action_str = "add";
|
||||
+ else if (data.action == ACTION_ACCESS)
|
||||
+ action_str = "access";
|
||||
else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME)
|
||||
action_str = "old";
|
||||
else
|
||||
@@ -178,9 +181,11 @@
|
||||
{
|
||||
/* On error send event back to main process for logging */
|
||||
if (WIFSIGNALED(status))
|
||||
- send_event(event_fd, EVENT_KILLED, WTERMSIG(status));
|
||||
- else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
|
||||
- send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status));
|
||||
+ send_event(event_fd, EVENT_KILLED, WTERMSIG(status), data.uid);
|
||||
+ else if (WIFEXITED(status))
|
||||
+ send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status), data.uid);
|
||||
+ else
|
||||
+ send_event(event_fd, EVENT_EXITED, -1, data.uid);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -263,7 +268,7 @@
|
||||
err = errno;
|
||||
}
|
||||
/* failed, send event so the main process logs the problem */
|
||||
- send_event(event_fd, EVENT_EXEC_ERR, err);
|
||||
+ send_event(event_fd, EVENT_EXEC_ERR, err, data.uid);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
@@ -295,7 +300,7 @@
|
||||
}
|
||||
|
||||
/* pack up lease data into a buffer */
|
||||
-void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
|
||||
+void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now, unsigned int uid)
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t size;
|
||||
@@ -332,6 +337,7 @@
|
||||
buf_size = size;
|
||||
}
|
||||
|
||||
+ buf->uid = uid;
|
||||
buf->action = action;
|
||||
buf->hwaddr_len = lease->hwaddr_len;
|
||||
buf->hwaddr_type = lease->hwaddr_type;
|
||||
@@ -393,12 +399,15 @@
|
||||
return bytes_in_buf == 0;
|
||||
}
|
||||
|
||||
-void helper_write(void)
|
||||
+/* returns -1 if write failed for a reason, 1 if no data exist
|
||||
+ * and 0 if everything was ok.
|
||||
+ */
|
||||
+int helper_write(void)
|
||||
{
|
||||
ssize_t rc;
|
||||
|
||||
if (bytes_in_buf == 0)
|
||||
- return;
|
||||
+ return 1;
|
||||
|
||||
if ((rc = write(daemon->helperfd, buf, bytes_in_buf)) != -1)
|
||||
{
|
||||
@@ -409,9 +418,11 @@
|
||||
else
|
||||
{
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
- return;
|
||||
+ return -1;
|
||||
bytes_in_buf = 0;
|
||||
}
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Index: src/rfc2131.c
|
||||
===================================================================
|
||||
--- src/rfc2131.c (revision 696)
|
||||
+++ src/rfc2131.c (revision 821)
|
||||
@@ -100,8 +100,49 @@
|
||||
int clid_len, unsigned char *clid, int *len_out);
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||
|
||||
+static int check_access_script( int piperead, struct dhcp_lease *lease, struct dhcp_packet *mess, time_t now)
|
||||
+{
|
||||
+#ifndef NO_FORK
|
||||
+unsigned int uid;
|
||||
+struct event_desc ev;
|
||||
+int ret;
|
||||
+struct dhcp_lease _lease;
|
||||
+
|
||||
+ if (daemon->lease_change_command == NULL) return 0; /* ok */
|
||||
+
|
||||
+ if (!lease) { /* if host has not been seen before lease is NULL */
|
||||
+ memset(&_lease, 0, sizeof(_lease));
|
||||
+ lease = &_lease;
|
||||
+ lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
|
||||
+ }
|
||||
+
|
||||
+ uid = rand16();
|
||||
+ queue_script(ACTION_ACCESS, lease, NULL, now, uid);
|
||||
+
|
||||
+ /* send all data to helper process */
|
||||
+ do
|
||||
+ {
|
||||
+ helper_write();
|
||||
+ } while (helper_buf_empty() == 0);
|
||||
+
|
||||
+ /* wait for our event */
|
||||
+ ret = 0;
|
||||
+ do
|
||||
+ {
|
||||
+ ret = async_event( piperead, now, &ev, SCRIPT_TIMEOUT);
|
||||
+ }
|
||||
+ while(ev.priv != uid && ret >= 0);
|
||||
+
|
||||
+ if (ret < 0 || ev.data != 0) /* timeout or error */
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+#endif
|
||||
+ return 0; /* ok */
|
||||
+}
|
||||
|
||||
-size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
+size_t dhcp_reply(int piperead, struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform)
|
||||
{
|
||||
unsigned char *opt, *clid = NULL;
|
||||
@@ -252,7 +293,7 @@
|
||||
mac->netid.next = netid;
|
||||
netid = &mac->netid;
|
||||
}
|
||||
-
|
||||
+
|
||||
/* Determine network for this packet. Our caller will have already linked all the
|
||||
contexts which match the addresses of the receiving interface but if the
|
||||
machine has an address already, or came via a relay, or we have a subnet selector,
|
||||
@@ -329,7 +370,7 @@
|
||||
my_syslog(LOG_INFO, _("Available DHCP range: %s -- %s"), daemon->namebuff, inet_ntoa(context_tmp->end));
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
mess->op = BOOTREPLY;
|
||||
|
||||
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
|
||||
@@ -418,7 +459,7 @@
|
||||
else
|
||||
mess->yiaddr = lease->addr;
|
||||
}
|
||||
-
|
||||
+
|
||||
if (!message &&
|
||||
!lease &&
|
||||
(!(lease = lease_allocate(mess->yiaddr))))
|
||||
@@ -641,7 +682,14 @@
|
||||
memcpy(req_options, option_ptr(opt, 0), option_len(opt));
|
||||
req_options[option_len(opt)] = OPTION_END;
|
||||
}
|
||||
-
|
||||
+
|
||||
+ if (mess_type == DHCPREQUEST || mess_type == DHCPDISCOVER)
|
||||
+ if (check_access_script(piperead, lease, mess, now) < 0)
|
||||
+ {
|
||||
+ my_syslog(LOG_INFO, _("Ignoring client due to access script"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
switch (mess_type)
|
||||
{
|
||||
case DHCPDECLINE:
|
||||
Index: src/log.c
|
||||
===================================================================
|
||||
--- src/log.c (revision 696)
|
||||
+++ src/log.c (revision 821)
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
if (!log_reopen(daemon->log_file))
|
||||
{
|
||||
- send_event(errfd, EVENT_LOG_ERR, errno);
|
||||
+ send_event(errfd, EVENT_LOG_ERR, errno, 0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
Index: src/lease.c
|
||||
===================================================================
|
||||
--- src/lease.c (revision 696)
|
||||
+++ src/lease.c (revision 821)
|
||||
@@ -511,7 +511,7 @@
|
||||
if (lease->old_hostname)
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
- queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
|
||||
+ queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now, 0);
|
||||
#endif
|
||||
free(lease->old_hostname);
|
||||
lease->old_hostname = NULL;
|
||||
@@ -520,7 +520,7 @@
|
||||
else
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
- queue_script(ACTION_DEL, lease, lease->hostname, now);
|
||||
+ queue_script(ACTION_DEL, lease, lease->hostname, now, 0);
|
||||
#endif
|
||||
old_leases = lease->next;
|
||||
|
||||
@@ -540,7 +540,7 @@
|
||||
if (lease->old_hostname)
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
- queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
|
||||
+ queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now, 0);
|
||||
#endif
|
||||
free(lease->old_hostname);
|
||||
lease->old_hostname = NULL;
|
||||
@@ -552,7 +552,7 @@
|
||||
(lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
- queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now);
|
||||
+ queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now, 0);
|
||||
#endif
|
||||
lease->new = lease->changed = lease->aux_changed = 0;
|
||||
|
||||
Index: man/dnsmasq.8
|
||||
===================================================================
|
||||
--- man/dnsmasq.8 (revision 696)
|
||||
+++ man/dnsmasq.8 (revision 821)
|
||||
@@ -724,12 +724,15 @@
|
||||
.B \-6 --dhcp-script=<path>
|
||||
Whenever a new DHCP lease is created, or an old one destroyed, the
|
||||
binary specified by this option is run. The arguments to the process
|
||||
-are "add", "old" or "del", the MAC
|
||||
+are "add", "old", "access" or "del", the MAC
|
||||
address of the host (or "<null>"), the IP address, and the hostname,
|
||||
if known. "add" means a lease has been created, "del" means it has
|
||||
been destroyed, "old" is a notification of an existing lease when
|
||||
dnsmasq starts or a change to MAC address or hostname of an existing
|
||||
lease (also, lease length or expiry and client-id, if leasefile-ro is set).
|
||||
+The "access" keyword means that a request was just received and depending
|
||||
+on the script exit status request for address will be granted, if exit status
|
||||
+is zero or not if it is non-zero.
|
||||
The process is run as root (assuming that dnsmasq was originally run as
|
||||
root) even if dnsmasq is configured to change UID to an unprivileged user.
|
||||
The environment is inherited from the invoker of dnsmasq, and if the
|
||||
Binary file not shown.
@@ -21,6 +21,9 @@ and avoids startup races with the provider of nameserver information.
|
||||
Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
|
||||
and a single object: /uk/org/thekelleys/dnsmasq
|
||||
|
||||
1. METHODS
|
||||
----------
|
||||
|
||||
Methods are of the form
|
||||
|
||||
uk.org.thekelleys.<method>
|
||||
@@ -91,4 +94,38 @@ Each call to SetServers completely replaces the set of servers
|
||||
specified by via the DBus, but it leaves any servers specified via the
|
||||
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
|
||||
|
||||
2. SIGNALS
|
||||
----------
|
||||
|
||||
If dnsmasq's DHCP server is active, it will send signals over DBUS whenever
|
||||
the DHCP lease database changes. Think of these signals as transactions on
|
||||
a database with the IP address acting as the primary key.
|
||||
|
||||
Signals are of the form:
|
||||
|
||||
uk.org.thekelleys.<signal>
|
||||
|
||||
and their parameters are:
|
||||
|
||||
STRING "192.168.1.115"
|
||||
STRING "01:23:45:67:89:ab"
|
||||
STRING "hostname.or.fqdn"
|
||||
|
||||
|
||||
Available signals are:
|
||||
|
||||
DhcpLeaseAdded
|
||||
---------------
|
||||
|
||||
This signal is emitted when a DHCP lease for a given IP address is created.
|
||||
|
||||
DhcpLeaseDeleted
|
||||
----------------
|
||||
|
||||
This signal is emitted when a DHCP lease for a given IP address is deleted.
|
||||
|
||||
DhcpLeaseUpdated
|
||||
----------------
|
||||
|
||||
This signal is emitted when a DHCP lease for a given IP address is updated.
|
||||
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
<policy user="root">
|
||||
<allow own="uk.org.thekelleys.dnsmasq"/>
|
||||
<allow send_destination="uk.org.thekelleys.dnsmasq"/>
|
||||
<allow send_interface="uk.org.thekelleys.dnsmasq"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<deny own="uk.org.thekelleys.dnsmasq"/>
|
||||
<deny send_destination="uk.org.thekelleys.dnsmasq"/>
|
||||
<deny send_interface="uk.org.thekelleys.dnsmasq"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
|
||||
|
||||
@@ -122,6 +122,12 @@
|
||||
# 3) Provides the domain part for "expand-hosts"
|
||||
#domain=thekelleys.org.uk
|
||||
|
||||
# Set a different domain for a particular subnet
|
||||
#domain=wireless.thekelleys.org.uk,192.168.2.0/24
|
||||
|
||||
# Same idea, but range rather then subnet
|
||||
#domain=reserved.thekelleys.org.uk,192.68.3.100,192.168.3.200
|
||||
|
||||
# Uncomment this to enable the integrated DHCP server, you need
|
||||
# to supply the range of addresses available for lease and optionally
|
||||
# a lease time. If you have more than one network, you will need to
|
||||
@@ -157,6 +163,14 @@
|
||||
# the name fred and IP address 192.168.0.60 and lease time 45 minutes
|
||||
#dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m
|
||||
|
||||
# Give a host with ethernet address 11:22:33:44:55:66 or
|
||||
# 12:34:56:78:90:12 the IP address 192.168.0.60. Dnsmasq will assume
|
||||
# that these two ethernet interfaces will never be in use at the same
|
||||
# time, and give the IP address to the second, even if it is already
|
||||
# in use by the first. Useful for laptops with wired and wireless
|
||||
# addresses.
|
||||
#dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.60
|
||||
|
||||
# Give the machine which says its name is "bert" IP address
|
||||
# 192.168.0.70 and an infinite lease
|
||||
#dhcp-host=bert,192.168.0.70,infinite
|
||||
@@ -270,12 +284,12 @@
|
||||
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
|
||||
# adapted for a typical dnsmasq installation where the host running
|
||||
# dnsmasq is also the host running samba.
|
||||
# you may want to uncomment them if you use Windows clients and Samba.
|
||||
# you may want to uncomment some or all of them if you use
|
||||
# Windows clients and Samba.
|
||||
#dhcp-option=19,0 # option ip-forwarding off
|
||||
#dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s)
|
||||
#dhcp-option=45,0.0.0.0 # netbios datagram distribution server
|
||||
#dhcp-option=46,8 # netbios node type
|
||||
#dhcp-option=47 # empty netbios scope.
|
||||
|
||||
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
|
||||
# probably doesn't support this......
|
||||
@@ -328,6 +342,22 @@
|
||||
#dhcp-boot=net:#gpxe,undionly.kpxe
|
||||
#dhcp-boot=mybootimage
|
||||
|
||||
# Encapsulated options for Etherboot gPXE. All the options are
|
||||
# encapsulated within option 175
|
||||
#dhcp-option=encap:175, 1, 5b # priority code
|
||||
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
|
||||
#dhcp-option=encap:175, 177, string # bus-id
|
||||
#dhcp-option=encap:175, 189, 1b # BIOS drive code
|
||||
#dhcp-option=encap:175, 190, user # iSCSI username
|
||||
#dhcp-option=encap:175, 191, pass # iSCSI password
|
||||
|
||||
# Test for the architecture of a netboot client. PXE clients are
|
||||
# supposed to send their architecture as option 93. (See RFC 4578)
|
||||
#dhcp-match=peecees, option:client-arch, 0 #x86-32
|
||||
#dhcp-match=itanics, option:client-arch, 2 #IA64
|
||||
#dhcp-match=hammers, option:client-arch, 6 #x86-64
|
||||
#dhcp-match=mactels, option:client-arch, 7 #EFI x86-64
|
||||
|
||||
# Enable dnsmasq's built-in TFTP server
|
||||
#enable-tftp
|
||||
|
||||
@@ -395,7 +425,8 @@
|
||||
#alias=1.2.3.4,5.6.7.8
|
||||
# and this maps 1.2.3.x to 5.6.7.x
|
||||
#alias=1.2.3.0,5.6.7.0,255.255.255.0
|
||||
|
||||
# and this maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40
|
||||
#alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
|
||||
|
||||
# Change these lines if you want dnsmasq to serve MX records.
|
||||
|
||||
@@ -458,6 +489,10 @@
|
||||
#Example zeroconf
|
||||
#txt-record=_http._tcp.example.com,name=value,paper=A4
|
||||
|
||||
# Provide an alias for a "local" DNS name. Note that this _only_ works
|
||||
# for targets which are names from DHCP or /etc/hosts. Give host
|
||||
# "bert" another name, bertrand
|
||||
#cname=bertand,bert
|
||||
|
||||
# For debugging purposes, log each DNS query as it passes through
|
||||
# dnsmasq.
|
||||
|
||||
6
doc.html
6
doc.html
@@ -89,11 +89,11 @@ Dnsmasq is part of the Debian distribution, it can be downloaded from
|
||||
<A HREF="http://ftp.debian.org/debian/pool/main/d/dnsmasq/"> here</A> or installed using <TT>apt</TT>.
|
||||
|
||||
<H2>Links.</H2>
|
||||
There is an article in German on dnsmasq at <A
|
||||
HREF="http://www.linuxnetmag.com/de/issue7/m7dnsmasq1.html">http://www.linuxnetmag.com/de/issue7/m7dnsmasq1.html</A>
|
||||
and Damien Raude-Morvan has one in French at <A HREF="http://www.drazzib.com/docs-dnsmasq.html">http://www.drazzib.com/docs-dnsmasq.html</A>
|
||||
Damien Raude-Morvan has an article in French at <A HREF="http://www.drazzib.com/docs-dnsmasq.html">http://www.drazzib.com/docs-dnsmasq.html</A>
|
||||
There is a good article about dnsmasq at <A
|
||||
HREF="http://www.enterprisenetworkingplanet.com/netos/article.php/3377351">http://www.enterprisenetworkingplanet.com/netos/article.php/3377351</A>
|
||||
and another at <A
|
||||
HREF="http://www.linux.com/articles/149040">http://www.linux.com/articles/149040</A>
|
||||
and Ilya Evseev has an article in Russian about dnsmasq to be found at <A HREF="http://ilya-evseev.narod.ru/articles/dnsmasq"> http://ilya-evseev.narod.ru/articles/dnsmasq</A>
|
||||
<H2>License.</H2>
|
||||
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution
|
||||
|
||||
139
man/dnsmasq.8
139
man/dnsmasq.8
@@ -15,8 +15,8 @@ contents of /etc/hosts so that local hostnames
|
||||
which do not appear in the global DNS can be resolved and also answers
|
||||
DNS queries for DHCP configured hosts.
|
||||
.PP
|
||||
The dnsmasq DHCP server supports static address assignments, multiple
|
||||
networks, DHCP-relay and RFC3011 subnet specifiers. It automatically
|
||||
The dnsmasq DHCP server supports static address assignments and multiple
|
||||
networks. It automatically
|
||||
sends a sensible default set of DHCP options, and can be configured to
|
||||
send any desired set of DHCP options, including vendor-encapsulated
|
||||
options. It includes a secure, read-only,
|
||||
@@ -208,13 +208,17 @@ Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192
|
||||
which are not found in /etc/hosts or the DHCP leases file are answered
|
||||
with "no such domain" rather than being forwarded upstream.
|
||||
.TP
|
||||
.B \-V, --alias=<old-ip>,<new-ip>[,<mask>]
|
||||
.B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>]
|
||||
Modify IPv4 addresses returned from upstream nameservers; old-ip is
|
||||
replaced by new-ip. If the optional mask is given then any address
|
||||
which matches the masked old-ip will be re-written. So, for instance
|
||||
.B --alias=1.2.3.0,6.7.8.0,255.255.255.0
|
||||
will map 1.2.3.56 to 6.7.8.56 and 1.2.3.67 to 6.7.8.67. This is what
|
||||
Cisco PIX routers call "DNS doctoring".
|
||||
Cisco PIX routers call "DNS doctoring". If the old IP is given as
|
||||
range, then only addresses in the range, rather than a whole subnet,
|
||||
are re-written. So
|
||||
.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
|
||||
maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40
|
||||
.TP
|
||||
.B \-B, --bogus-nxdomain=<ipaddr>
|
||||
Transform replies which contain the IP address given into "No such
|
||||
@@ -385,6 +389,14 @@ Return a PTR DNS record.
|
||||
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
|
||||
Return an NAPTR DNS record, as specified in RFC3403.
|
||||
.TP
|
||||
.B --cname=<cname>,<target>
|
||||
Return a CNAME record which indicates that <cname> is really
|
||||
<target>. There are significant limitations on the target; it must be a
|
||||
DNS name which is known to dnsmasq from /etc/hosts (or additional
|
||||
hosts files) or from DHCP. If the target does not satisfy this
|
||||
criteria, the whole cname is ignored. The cname must be unique, but it
|
||||
is permissable to have more than one cname pointing to the same target.
|
||||
.TP
|
||||
.B --interface-name=<name>,<interface>
|
||||
Return a DNS record associating the name with the primary address on
|
||||
the given interface. This flag specifies an A record for the given
|
||||
@@ -465,9 +477,11 @@ hardware addresses to identify hosts by prefixing with 'id:'. Thus:
|
||||
refers to the host with client identifier 01:02:03:04. It is also
|
||||
allowed to specify the client ID as text, like this:
|
||||
.B --dhcp-host=id:clientidastext,.....
|
||||
|
||||
The special option id:* means "ignore any client-id
|
||||
and use MAC addresses only." This is useful when a client presents a client-id sometimes
|
||||
but not others.
|
||||
|
||||
If a name appears in /etc/hosts, the associated address can be
|
||||
allocated to a DHCP lease, but only if a
|
||||
.B --dhcp-host
|
||||
@@ -478,8 +492,10 @@ instance
|
||||
.B --dhcp-host=00:20:e0:3b:13:af,ignore
|
||||
This is
|
||||
useful when there is another DHCP server on the network which should
|
||||
be used by some machines. The net:<network-id> sets the network-id tag
|
||||
whenever this dhcp-host directive is in use.This can be used to
|
||||
be used by some machines.
|
||||
|
||||
The net:<network-id> sets the network-id tag
|
||||
whenever this dhcp-host directive is in use. This can be used to
|
||||
selectively send DHCP options just for this host. When a host matches any
|
||||
dhcp-host directive (or one implied by /etc/ethers) then the special
|
||||
network-id tag "known" is set. This allows dnsmasq to be configured to
|
||||
@@ -490,13 +506,27 @@ wildcard bytes, so for example
|
||||
.B --dhcp-host=00:20:e0:3b:13:*,ignore
|
||||
will cause dnsmasq to ignore a range of hardware addresses. Note that
|
||||
the "*" will need to be escaped or quoted on a command line, but not
|
||||
in the configuration file. Hardware addresses normally match any
|
||||
in the configuration file.
|
||||
|
||||
Hardware addresses normally match any
|
||||
network (ARP) type, but it is possible to restrict them to a single
|
||||
ARP type by preceding them with the ARP-type (in HEX) and "-". so
|
||||
.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4
|
||||
will only match a
|
||||
Token-Ring hardware address, since the ARP-address type for token ring
|
||||
is 6.
|
||||
is 6.
|
||||
|
||||
As a special case, it is possible to include more than one
|
||||
hardware address. eg:
|
||||
.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2
|
||||
This allows an IP address to be associated with
|
||||
multiple hardware addresses, and gives dnsmasq permission to abandon a
|
||||
DHCP lease to one of the hardware addresses when another one asks for
|
||||
a lease. Beware that this is a dangerous thing to do, it will only
|
||||
work reliably if only one of the hardware addresses is active at any
|
||||
time and there is no way for dnsmasq to enforce this. It is, for instance,
|
||||
useful to allocate a stable IP address to a laptop which
|
||||
has both wired and wireless interfaces.
|
||||
.TP
|
||||
.B --dhcp-hostsfile=<file>
|
||||
Read DHCP host information from the specified file. The file contains
|
||||
@@ -519,7 +549,7 @@ have exactly the same effect as
|
||||
options containing the same information. /etc/ethers is re-read when
|
||||
dnsmasq receives SIGHUP.
|
||||
.TP
|
||||
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
|
||||
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][encap:<opt>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
|
||||
Specify different or extra options to DHCP clients. By default,
|
||||
dnsmasq sends some standard options to DHCP clients, the netmask and
|
||||
broadcast address are set to the same as the host running dnsmasq, and
|
||||
@@ -579,10 +609,18 @@ client. It is
|
||||
possible to omit the vendorclass completely;
|
||||
.B --dhcp-option=vendor:,1,0.0.0.0
|
||||
in which case the encapsulated option is always sent.
|
||||
|
||||
Options may be encapsulated within other options: for instance
|
||||
.B --dhcp-option=encap:175, 190, "iscsi-client0"
|
||||
will send option 175, within which is the option 190. If multiple
|
||||
options are given which are encapsulated with the same option number
|
||||
then they will be correctly combined into one encapsulated option.
|
||||
encap: and vendor: are may not both be set in the same dhcp-option.
|
||||
|
||||
The address 0.0.0.0 is not treated specially in
|
||||
encapsulated vendor class options.
|
||||
encapsulated options.
|
||||
.TP
|
||||
.B --dhcp-option-force=[<network-id>,[<network-id>,]][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
|
||||
.B --dhcp-option-force=[<network-id>,[<network-id>,]][encap:<opt>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
|
||||
This works in exactly the same way as
|
||||
.B --dhcp-option
|
||||
except that the option will always be sent, even if the client does
|
||||
@@ -634,10 +672,22 @@ agent ID and one provided by a relay agent, the network-id tag is set.
|
||||
.B --dhcp-subscrid=<network-id>,<subscriber-id>
|
||||
Map from RFC3993 subscriber-id relay agent options to network-id tags.
|
||||
.TP
|
||||
.B --dhcp-match=<network-id>,<option number>
|
||||
Set the network-id tag if the client sends a DHCP option of the given
|
||||
number. This can be used to identify particular clients which send
|
||||
information using private option numbers.
|
||||
.B --dhcp-match=<network-id>,<option number>|option:<option name>[,<value>]
|
||||
Without a value, set the network-id tag if the client sends a DHCP
|
||||
option of the given number or name. When a value is given, set the tag only if
|
||||
the option is sent and matches the value. The value may be of the form
|
||||
"01:ff:*:02" in which case the value must match (apart from widcards)
|
||||
but the option sent may have unmatched data past the end of the
|
||||
value. The value may also be of the same form as in
|
||||
.B dhcp-option
|
||||
in which case the option sent is treated as an array, and one element
|
||||
must match, so
|
||||
|
||||
--dhcp-match=efi-ia32,option:client-arch,6
|
||||
|
||||
will set the tag "efi-ia32" if the the number 6 appears in the list of
|
||||
architectures sent by the client in option 93. (See RFC 4578 for
|
||||
details.) If the value is a string, substring matching is used.
|
||||
.TP
|
||||
.B \-J, --dhcp-ignore=<network-id>[,<network-id>]
|
||||
When all the given network-ids match the set of network-ids derived
|
||||
@@ -693,11 +743,13 @@ port number is used for the server and the port number plus one used
|
||||
for the client. Finally, two port numbers allows arbitrary
|
||||
specification of both server and client ports for DHCP.
|
||||
.TP
|
||||
.B \-3, --bootp-dynamic
|
||||
.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
|
||||
Enable dynamic allocation of IP addresses to BOOTP clients. Use this
|
||||
with care, since each address allocated to a BOOTP client is leased
|
||||
forever, and therefore becomes permanently unavailable for re-use by
|
||||
other hosts.
|
||||
other hosts. if this is given without tags, then it unconditionally
|
||||
enables dynamic allocation. With tags, only when the tags are all
|
||||
set. It may be repeated with different tag sets.
|
||||
.TP
|
||||
.B \-5, --no-ping
|
||||
By default, the DHCP server will attempt to ensure that an address in
|
||||
@@ -711,30 +763,26 @@ Extra logging for DHCP: log all the options sent to DHCP clients and
|
||||
the netid tags used to determine them.
|
||||
.TP
|
||||
.B \-l, --dhcp-leasefile=<path>
|
||||
Use the specified file to store DHCP lease information. If this option
|
||||
is given but no dhcp-range option is given then dnsmasq version 1
|
||||
behaviour is activated. The file given is assumed to be an ISC dhcpd
|
||||
lease file and parsed for leases which are then added to the DNS
|
||||
system if they have a hostname. This functionality may have been
|
||||
excluded from dnsmasq at compile time, in which case an error will
|
||||
occur. In any case note that ISC leasefile integration is a deprecated
|
||||
feature. It should not be used in new installations, and will be
|
||||
removed in a future release.
|
||||
Use the specified file to store DHCP lease information.
|
||||
.TP
|
||||
.B \-6 --dhcp-script=<path>
|
||||
Whenever a new DHCP lease is created, or an old one destroyed, the
|
||||
binary specified by this option is run. The arguments to the process
|
||||
executable specified by this option is run. The arguments to the process
|
||||
are "add", "old" or "del", the MAC
|
||||
address of the host (or "<null>"), the IP address, and the hostname,
|
||||
address of the host, the IP address, and the hostname,
|
||||
if known. "add" means a lease has been created, "del" means it has
|
||||
been destroyed, "old" is a notification of an existing lease when
|
||||
dnsmasq starts or a change to MAC address or hostname of an existing
|
||||
lease (also, lease length or expiry and client-id, if leasefile-ro is set).
|
||||
The process is run as root (assuming that dnsmasq was originally run as
|
||||
If the MAC address is from a network type other than ethernet,
|
||||
it will have the network type prepended, eg "06-01:23:45:67:89:ab" for
|
||||
token ring. The process is run as root (assuming that dnsmasq was originally run as
|
||||
root) even if dnsmasq is configured to change UID to an unprivileged user.
|
||||
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 client provides vendor-class or user-class
|
||||
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
|
||||
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
|
||||
"add" actions or "old" actions when a host resumes an existing lease,
|
||||
@@ -785,8 +833,9 @@ as if they had arrived at <interface>. This option is only available
|
||||
on BSD platforms, and is necessary when using "old style" bridging, since
|
||||
packets arrive at tap interfaces which don't have an IP address.
|
||||
.TP
|
||||
.B \-s, --domain=<domain>
|
||||
Specifies the domain for the DHCP server. This has two effects;
|
||||
.B \-s, --domain=<domain>[,<address range>]
|
||||
Specifies DNS domains for the DHCP server. Domains may be be given
|
||||
unconditionally (without the IP range) or for limited IP ranges. This has two effects;
|
||||
firstly it causes the DHCP server to return the domain to any hosts
|
||||
which request it, and secondly it sets the domain which it is legal
|
||||
for DHCP-configured hosts to claim. The intention is to constrain
|
||||
@@ -803,7 +852,28 @@ and have a machine whose DHCP hostname is "laptop". The IP address for that mach
|
||||
.B dnsmasq
|
||||
both as "laptop" and "laptop.thekelleys.org.uk". If the domain is
|
||||
given as "#" then the domain is read from the first "search" directive
|
||||
in /etc/resolv.conf (or equivalent).
|
||||
in /etc/resolv.conf (or equivalent). The address range can be of the form
|
||||
<ip address>,<ip address> or <ip address>/<netmask> or just a single
|
||||
<ip address>. See
|
||||
.B --dhcp-fqdn
|
||||
which can change the behaviour of dnsmasq with domains.
|
||||
.TP
|
||||
.B --dhcp-fqdn
|
||||
In the default mode, dnsmasq inserts the unqualified names of
|
||||
DHCP clients into the DNS. For this reason, the names must be unique,
|
||||
even if two clients which have the same name are in different
|
||||
domains. If a second DHCP client appears which has the same name as an
|
||||
existing client, the name is transfered to the new client. If
|
||||
.B --dhcp-fqdn
|
||||
is set, this behaviour changes: the unqualified name is no longer
|
||||
put in the DNS, only the qualified name. Two DHCP clients with the
|
||||
same name may both keep the name, provided that the domain part is
|
||||
different (ie the fully qualified names differ.) To ensure that all
|
||||
names have a domain part, there must be at least
|
||||
.B --domain
|
||||
without an address specified when
|
||||
.B --dhcp-fqdn
|
||||
is set.
|
||||
.TP
|
||||
.B --enable-tftp
|
||||
Enable the TFTP server function. This is deliberately limited to that
|
||||
@@ -1006,6 +1076,9 @@ collects a set of valid network-id tags, one from the
|
||||
.B dhcp-range
|
||||
used to allocate the address, one from any matching
|
||||
.B dhcp-host
|
||||
(and "known" if a dhcp-host matches)
|
||||
the tag "bootp" for BOOTP requests, a tag whose name is the
|
||||
name if the interface on which the request arrived,
|
||||
and possibly many from matching vendor classes and user
|
||||
classes sent by the DHCP client. Any
|
||||
.B dhcp-option
|
||||
|
||||
107
man/es/dnsmasq.8
107
man/es/dnsmasq.8
@@ -414,8 +414,15 @@ Retornar un r
|
||||
.B --naptr-record=<nombre>,<orden>,<preferencia>,<opciones>,<servicio>,<regexp>[,<remplazo>]
|
||||
Retornar un récord DNS NAPTR, como especificado en RFC3403.
|
||||
.TP
|
||||
.B --cname=<cname>,<target>
|
||||
Retornar un expediente CNAME que indica que <cname> es realmente <target>. Hay
|
||||
limitaciones significativas en el target. Debe ser un nombre DNS que le es conocido
|
||||
a dnsmasq desde /etc/hosts (o archivos hosts adicionales) o de DHCP. Si el target
|
||||
no satisface este criterio, el cname entero es ignorado. El cname debe ser único,
|
||||
pero es permisible tener más de un cname indicando el mismo target.
|
||||
.TP
|
||||
.B --interface-name=<nombre>,<interface>
|
||||
Retornar un récord DNS, asociando el nombre con la dirección primaria
|
||||
Retornar un expediente DNS, asociando el nombre con la dirección primaria
|
||||
en la interface brindada. Esta opción especifica un expediente tipo A
|
||||
para el nombre brindado de la misma forma que una línea de /etc/hosts,
|
||||
excepto que la dirección no es constante y es en vez tomada de la
|
||||
@@ -500,9 +507,11 @@ hardware para identificar hosts prefijando 'id:'. O sea que:
|
||||
se refiere al host con identificador de cliente 01:02:03:04.
|
||||
También se permite especificar el ID de cliente como texto, así:
|
||||
.B --dhcp-host=id:iddeclientecomotexto,.....
|
||||
|
||||
La opción especial id:* significa "ignorar cualquier ID de cliente
|
||||
y usar solamente direcciones MAC." Esto es útil cuando un cliente
|
||||
presenta un ID de cliente algunas veces pero otras no.
|
||||
|
||||
Si un nombre aparece en /etc/hosts, la dirección asociada puede
|
||||
ser alocada a un arriendo DHCP, pero solo si existe una opción
|
||||
.B --dhcp-host
|
||||
@@ -511,14 +520,16 @@ le dice a dnsmasq que no debe ofrecer jam
|
||||
una máquina. La máquina puede ser especificada por dirección de
|
||||
hardware, ID de cliente, o nombre de host, por ejemplo:
|
||||
.B --dhcp-host=00:20:e0:3b:13:af,ignore
|
||||
Esto es útil cuando hay otro servidor DHCP en la red para ser
|
||||
usado por algúnas máquinas. El net:<network-id> fija la etiqueta
|
||||
network-id cuando sea que esta directiva dhcp-host está en uso.
|
||||
Esto puede ser usado para enviar selectivamente opciones DHCP
|
||||
a este host. Cuando un host coincide con cualquier directiva
|
||||
dhcp-host (o una implicada por /etc/ethers) entonces la etiqueta
|
||||
network-id especial "known" es fijada. Esto permite que dnsmasq sea
|
||||
configurado para ignorar pedidos desde máquinas desconocidas usando
|
||||
Esto es útil cuando hay otro servidor DHCP en la red que debe ser
|
||||
usado por algúnas máquinas.
|
||||
|
||||
El net:<network-id> fija la etiqueta network-id cuando sea que
|
||||
esta directiva dhcp-host está en uso. Esto puede ser usado para
|
||||
enviar selectivamente opciones DHCP a este host. Cuando un host
|
||||
coincide con cualquier directiva dhcp-host (o una implicada por
|
||||
/etc/ethers) entonces la etiqueta network-id especial "known" es
|
||||
fijada. Esto permite que dnsmasq sea configurado para ignorar
|
||||
pedidos desde máquinas desconocidas usando
|
||||
.B --dhcp-ignore=#known
|
||||
Direcciones ethernet (pero no client-ids) pueden tener bytes
|
||||
comodínes, así que por ejemplo
|
||||
@@ -526,12 +537,23 @@ comod
|
||||
causará que dnsmasq ignore un rango de direcciones ethernet. Nótese
|
||||
que el "*" necesitará ser escapado o escrito entre comillas en la
|
||||
línea de comandos, pero no en el archivo de configuración.
|
||||
|
||||
Direcciones de hardware normalmente coinciden con cualquier
|
||||
tipo de red (ARP), pero es posible restringirlas a un tipo ARP
|
||||
singular precediendolo con el tipo ARP (en HEX) y "-". Así que
|
||||
.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4
|
||||
solo coincidiría con una dirección de hardware Token-Ring, dado que
|
||||
el tipo ARP para Token-Ring es 6.
|
||||
|
||||
Como caso especial, es posible incluir más de una dirección de
|
||||
hardware. Esto permite que una dirección IP sea asociada con
|
||||
direcciones de hardware múltiples, y le brinda a dnsmasq permiso
|
||||
para abandonar un arriendo DHCP a una de las direcciones de hardware
|
||||
cuando otra pide un arriendo. Nótese que esto es algo peligroso,
|
||||
sólo funcionará dependiblemente si una de las direcciones de hardware
|
||||
está activa en cualquier momento y dnsmasq no tiene forma de enforzar
|
||||
esto. Pero es útil, por ejemplo, para alocar una dirección IP estable
|
||||
a una laptop que tiene interfaces alámbricas e inalámbricas.
|
||||
.TP
|
||||
.B --dhcp-hostsfile=<archivo>
|
||||
Leer información host DHCP desde el archivo especificado. El archivo contiene información de un host por línea. El formato de una línea es igual que texto hacia la derecha de '=' en --dhcp-host. La ventaja de almacenar información host DHCP en este archivo es que puede ser cambiada sin tener que reiniciar dnsmasq. El archivo será re-leído cuando dnsmasq recibe un SIGHUP.
|
||||
@@ -731,11 +753,14 @@ es usado para el servidor y el n
|
||||
para el cliente. Finalmente, dos números permiten que se especifiquen
|
||||
ambos los puertos de servidor y cliente para DHCP.
|
||||
.TP
|
||||
.B \-3, --bootp-dynamic
|
||||
.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
|
||||
Habilitar alocación dinámica de direcciones IP a clientes BOOTP. Usar
|
||||
esto con cuidado, ya que cada dirección alocada a un cliente BOOTP
|
||||
es arrendada para siempre, y consecuentemente queda no-disponible
|
||||
para re-uso por otros hosts.
|
||||
para re-uso por otros hosts. Si esto es brindado sin etiquetas,
|
||||
entonces incondicionalmente habilita alocación dinámica. Con
|
||||
etiquetas, solo cuando todas las etiquetas están fijadas. Puede
|
||||
ser repetido con diferentes juegos de etiquetas.
|
||||
.TP
|
||||
.B \-5, --no-ping
|
||||
Por predetermindado, el servidor DHCP tratará de asegurarse que una
|
||||
@@ -763,20 +788,24 @@ en instalaciones nuevas, y ser
|
||||
.TP
|
||||
.B \-6 --dhcp-script=<path>
|
||||
Cuando un arriendo DHCP nuevo es creado, o uno viejo es
|
||||
destruido, el binario especificado por esta opción es ejecutado.
|
||||
destruido, el ejecutable especificado por esta opción es ejecutado.
|
||||
Los argumentos para el binario son "add", "old", o "del", la dirección
|
||||
MAC del host (o "<null>"), la dirección IP, y el hostname, si es
|
||||
MAC del host, la dirección IP, y el hostname, si es
|
||||
conocido. "add" significa que un arriendo ha sido creado, "del" que
|
||||
ha sido destruido, y "old" es una notificación de un arriendo existente
|
||||
cuando dnsmasq inicia o un cambio a una MAC o nombre host de un arriendo
|
||||
existente (también, tiempo de arriendo o vencimiento y client-id, si
|
||||
leasefile-ro está fijado). El proceso es ejecutado como root (asumiendo
|
||||
que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq está
|
||||
configurado para cambiar su UID a un usuario sin privilegios.
|
||||
leasefile-ro está fijado). Si la dirección MAC es de un tipo de red
|
||||
que no es ethernet, tendrá el tipo de red precolocado, por ejemplo
|
||||
"06-01:23:45:67:89:ab" para token ring. El proceso es ejecutado como root
|
||||
(asumiendo que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq
|
||||
está configurado para cambiar su UID a un usuario sin privilegios.
|
||||
El ambiente es heredado del usuario que ha invocado a dnsmasq, y si el
|
||||
host brindó un client-id, es almacenado en la variable de ambiente
|
||||
DNSMASQ_CLIENT_ID. Si el cliente brinda información de clase de vendedor
|
||||
o usuario, estos son brindados en las variables DNSMASQ_VENDOR_CLASS y
|
||||
DNSMASQ_CLIENT_ID. Si el dominio completamente calificado del host
|
||||
es conocido, la parte de dominio es almacenada en DNSMASQ_DOMAIN. Si
|
||||
el cliente brinda información de clase de vendedoro usuario,
|
||||
estos son brindados en las variables DNSMASQ_VENDOR_CLASS y
|
||||
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add"
|
||||
y "old" cuando un host resume un arriendo existente, dado a que estos
|
||||
datos no son almacenados en la base de datos de arriendos de dnsmasq.
|
||||
@@ -829,11 +858,12 @@ est
|
||||
puentes "estilo viejo", ya que los paquetes llegan a interfaces tap que no
|
||||
tienen una dirección IP.
|
||||
.TP
|
||||
.B \-s, --domain=<dominio>
|
||||
Especifica el dominio para el servidor DHCP. Esto tiene dos efectos:
|
||||
Primeramente, causa que el servidor DHCP le devuelva el dominio a
|
||||
cualquier host que lo pida. Segundamente, fija el dominio para el cual
|
||||
es legal para hosts configurados mediante DHCP reclamar. La intención es
|
||||
.B \-s, --domain=<dominio>[,<rango de IPs>]
|
||||
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
|
||||
brindados incondicionalmente (sin el rango de IPs) o para rangos limitados. Esto
|
||||
tiene dos efectos: Primeramente, causa que el servidor DHCP le devuelva el
|
||||
dominio a cualquier host que lo pida. Segundamente, fija el dominio para el
|
||||
cual es legal para hosts configurados mediante DHCP reclamar. La intención es
|
||||
restringir nombres de host para que un host no-confiado en la LAN no
|
||||
pueda proclamar su nombre vía DHCP, como por ejemplo "microsoft.com" y
|
||||
capturar tráfico no destinado a ella. Si ningún sufijo de dominio es
|
||||
@@ -850,7 +880,28 @@ de esa m
|
||||
.B dnsmasq
|
||||
como "laptop" y "laptop.thekelleys.org.uk". Si el dominio es brindado
|
||||
como "#" entonces el dominio es leido desde la primera directiva search
|
||||
en /etc/resolv.conf (o equivalente).
|
||||
en /etc/resolv.conf (o equivalente). El rango de direcciones puede ser
|
||||
<dirección IP>,<dirección IP> or <dirección IP>/<máscara de subred>. Ver
|
||||
.B --dhcp-fqdn el cual puede cambiar el comportamiento de dnsmasq con
|
||||
dominios.
|
||||
.TP
|
||||
.B --dhcp-fqdn
|
||||
En el modo predeterminado, dnsmasq pone los nombres no-calificados
|
||||
de clientes DHCP en el DNS. Por esta razón, los nombres deben ser únicos,
|
||||
aún si dos clientes que tienen el mismo nombre están en dominios
|
||||
diferentes. Si un segundo cliente DHCP aparece el cual tiene el mismo
|
||||
nombre que un cliente existente, el nombre es transferido al cliente nuevo. Si
|
||||
.B --dhcp-fqdn
|
||||
está fijado, este comportamiento cambia: El nombre no-calificado
|
||||
no es puesto en el DNS, solo el nombre calificado. Dos clientes DHCP con
|
||||
el mismo nombre pueden ambos quedarse con el nombre, con tal que la parte
|
||||
de dominio sea diferente (o sea que los nombres completamente calificados
|
||||
difieran). Para asegurar que todos los nombres tengan una parte de dominio,
|
||||
debe haber al menos
|
||||
.B --domain
|
||||
sin una dirección especificada cuando
|
||||
.B --dhcp-fqdn
|
||||
está fijado.
|
||||
.TP
|
||||
.B --enable-tftp
|
||||
Habilitar la función de servidor TFTP. Esto está deliberadamente limitado
|
||||
@@ -1056,9 +1107,11 @@ una del
|
||||
.B dhcp-range
|
||||
usado para alocar la dirección, una de cualquier
|
||||
.B dhcp-host
|
||||
que coincida, y posiblemente muchas de clases de vendedor y usuario
|
||||
que coinicdan que hayan sido enviadas por el cliente DHCP.
|
||||
Cualquier opción
|
||||
que coincida (y "known" si un dhcp-host coincide), la etiqueta "bootp"
|
||||
para pedidos BOOTP, una etiqueta cuyo nombre es el nombre de la
|
||||
interface donde llegó el pedido, y posiblemente muchas de clases
|
||||
de vendedor y usuario que coincidan que hayan sido enviadas por
|
||||
el cliente DHCP. Cualquier opción
|
||||
.B dhcp-option
|
||||
que tenga etiquetas network-id será usada en preferencia de una opción
|
||||
.B dhcp-option,
|
||||
|
||||
149
man/fr/dnsmasq.8
149
man/fr/dnsmasq.8
@@ -236,7 +236,7 @@ trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées
|
||||
une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises
|
||||
aux serveurs de nom amont ("upstream server").
|
||||
.TP
|
||||
.B \-V, --alias=<ancienne IP>,<nouvelle IP>[,<masque>]
|
||||
.B \-V, --alias=[<ancienne IP>]|[<IP de début>-<IP de fin>],<nouvelle IP>[,<masque>]
|
||||
Modifie les adresses IPv4 retournées par les serveurs de nom amont;
|
||||
<ancienne IP> est remplacée par <nouvelle IP>. Si le <masque> optionnel est
|
||||
fourni, alors toute adresse correspondant à l'adresse <ancienne IP>/<masque>
|
||||
@@ -244,7 +244,11 @@ sera réécrite. Ainsi par exemple
|
||||
.B --alias=1.2.3.0,6.7.8.0,255.255.255.0
|
||||
modifiera 1.2.3.56 en 6.7.8.56 et 1.2.3.67 en 6.7.8.67.
|
||||
Cette fonctionnalité correspond à ce que les routeurs Cisco PIX appellent
|
||||
"bidouillage DNS" ("DNS doctoring").
|
||||
"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme
|
||||
d'une gamme d'adresses, alors seules les adresses dans cette gamme seront
|
||||
réecrites, et non le sous-réseau dans son ensemble. Ainsi,
|
||||
.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
|
||||
fait correspondre 192.168.0.10->192.168.0.40 à 10.0.0.10->10.0.0.40
|
||||
.TP
|
||||
.B \-B, --bogus-nxdomain=<adresse IP>
|
||||
Transforme les réponses contenant l'adresse IP fournie en réponses "pas de tel
|
||||
@@ -455,6 +459,14 @@ Définit un enregistrement DNS de type PTR.
|
||||
.B --naptr-record=<nom>,<ordre>,<préférence>,<drapeaux>,<service>,<expr. régulière>[,<remplacement>]
|
||||
Retourne un enregistrement de type NAPTR, tel que spécifié dans le RFC3403.
|
||||
.TP
|
||||
.B --cname=<cname>,<cible>
|
||||
Retourne un enregistrement de type CNAME qui indique que <cname> est en
|
||||
réalité <cible>. Il existe des contraintes significatives sur la valeur
|
||||
de cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts
|
||||
(ou un fichier hôtes additionnel) ou via DHCP. Si une cible ne satisfait
|
||||
pas ces critères, le CNAME est ignoré. Le CNAME doit être unique, mais
|
||||
il est autorisé d'avoir plus d'un CNAME pointant vers la même cible.
|
||||
.TP
|
||||
.B --interface-name=<nom>,<interface>
|
||||
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
|
||||
l'interface donnée en argument. Cette option spécifie un enregistrement de type
|
||||
@@ -545,6 +557,7 @@ réfère à l'hôte d'identifiant 01:02:03:04. Il est également possible de
|
||||
spécifier l'identifiant client sous la forme d'une chaîne de caractères, comme
|
||||
ceci :
|
||||
.B --dhcp-host=id:identifiantclientsousformedechaine,.....
|
||||
|
||||
L'option spéciale id:* signifie : "ignorer tout identifiant client et n'utiliser
|
||||
que l'adresse matérielle". Cela est utile lorsqu'un client présente un
|
||||
identifiant client mais pas les autres.
|
||||
@@ -558,7 +571,9 @@ spécifiée par son adresse matérielle, son identifiant client ou son nom d'hô
|
||||
Par exemple
|
||||
.B --dhcp-host=00:20:e0:3b:13:af,ignore
|
||||
Cela est utile lorsqu'un autre serveur DHCP sur le réseau doit être utilisé par
|
||||
certaines machines. Le paramètre net:<identifiant réseau> permet de définir un
|
||||
certaines machines.
|
||||
|
||||
Le paramètre net:<identifiant réseau> permet de définir un
|
||||
identifiant de réseau lorsque l'option dhcp-host est utilisée. Cela peut servir
|
||||
à sélectionner des options DHCP juste pour cet hôte. Lorsqu'une machine coïncide
|
||||
avec une directive dhcp-host (ou une impliquée par /etc/ethers), alors
|
||||
@@ -573,12 +588,26 @@ avec des octets joker, ainsi par exemple
|
||||
demande à Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est à noter
|
||||
que "*" doit-être précédé d'un caractère d'échappement ou mis entre guillemets
|
||||
lorsque spécifié en option de ligne de commande, mais pas dans le fichier de
|
||||
configuration. Les adresses matérielles coïncident en principe avec n'importe
|
||||
configuration.
|
||||
|
||||
Les adresses matérielles coïncident en principe avec n'importe
|
||||
quel type de réseau (ARP), mais il est possible de les limiter à un seul type
|
||||
ARP en les précédant du type ARP (en Hexadécimal) et de "-". Ainsi
|
||||
.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4
|
||||
coïncidera uniquement avec des adresses matérielles Token-Ring, puisque le type
|
||||
ARP pour une adresse Token-Ring est 6.
|
||||
|
||||
Un cas spécial correspond à l'inclusion d'une ou plusieurs adresses
|
||||
matérielles, c-à-d :
|
||||
.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2.
|
||||
Cela permet à une adresse IP d'être associé à plusieurs adresses
|
||||
matérielles, et donne à dnsmasq la permission d'abandonner un bail DHCP
|
||||
attribué à l'une de ces adresses lorsqu'une autre adresse dans la liste
|
||||
demande un bail. Ceci est une opération dangereuse qui ne fonctionnera
|
||||
de manière fiable que si une adresse matérielle est active à un moment
|
||||
donné et dnsmasq n'a aucun moyen de s'assurer de cela. Cela est utile,
|
||||
par exemple, pour allouer une adresse IP stable à un laptop qui
|
||||
aurait à la fois une connexion filaire et sans-fil.
|
||||
.TP
|
||||
.B --dhcp-hostsfile=<fichier>
|
||||
Lis les informations d'hôtes DHCP dans le fichier spécifié. Le fichier contient
|
||||
@@ -603,7 +632,7 @@ par Dnsmasq, ces lignes ont exactement le même effet que l'option
|
||||
contenant les mêmes informations. /etc/ethers est relu à la réception d'un
|
||||
signal SIGHUP par Dnsmasq.
|
||||
.TP
|
||||
.B \-O, --dhcp-option=[<identifiant_de_réseau>,[<identifiant_de_réseau>,]][vendor:[<classe_vendeur>],][<opt>|option:<nom d'option>],[<valeur>[,<valeur>]]
|
||||
.B \-O, --dhcp-option=[<identifiant_de_réseau>,[<identifiant_de_réseau>,]][encap:<option>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]]
|
||||
Spécifie des options différentes ou supplémentaires pour des clients DHCP. Par
|
||||
défaut, Dnsmasq envoie un ensemble standard d'options aux clients DHCP : le
|
||||
masque de réseau et l'adresse de broadcast sont les mêmes que pour l'hôte
|
||||
@@ -673,10 +702,19 @@ pour sélectionner les options encapsulées, de préférence à toute option env
|
||||
par le client. Il est possible d'omettre complètement une classe de vendeur :
|
||||
.B --dhcp-option=vendor:,1,0.0.0.0
|
||||
Dans ce cas l'option encapsulée est toujours envoyée.
|
||||
|
||||
Les options peuvent-être encapsulées au sein d'autres options :
|
||||
par exemple
|
||||
.B --dhcp-option=encap:175, 190, "iscsi-client0"
|
||||
enverra l'option 175, au sein de laquelle se trouve l'option 190.
|
||||
Plusieurs options encapsulées avec le même numéro d'option seront correctement
|
||||
combinées au sein d'une seule option encapsulée. Il n'est pas possible de
|
||||
spécifier encap: et vendor: au sein d'une même option dhcp.
|
||||
|
||||
L'adresse 0.0.0.0 n'est pas traitée de manière particulière lorsque fournie dans
|
||||
une option encapsulée de classe de vendeur.
|
||||
une option encapsulée.
|
||||
.TP
|
||||
.B --dhcp-option-force=[<identifiant de réseau>,[<identifiant de réseau>,]][vendor:[<classe de vendeur>],]<opt>,[<valeur>[,<valeur>]]
|
||||
.B --dhcp-option-force=[<identifiant de réseau>,[<identifiant de réseau>,]][encap:<option>,][vendor:[<classe de vendeur>],]<option>,[<valeur>[,<valeur>]]
|
||||
Cela fonctionne exactement de la même façon que
|
||||
.B --dhcp-option
|
||||
sauf que cette option sera toujours envoyée, même si le client ne la demande pas
|
||||
@@ -738,11 +776,23 @@ relais DHCP, alors l'identifiant de réseau est positionné.
|
||||
Associe des options de relais DHCP issues de la RFC3993 à des identifiants de
|
||||
réseau.
|
||||
.TP
|
||||
.B --dhcp-match=<identifiant de réseau>,<numéro d'option>
|
||||
Associe l'identifiant de réseau si le client envoie une option DHCP
|
||||
avec le numéro spécifié. Cela peut-être utilisé pour identifier des
|
||||
clients spécifiques qui envoient des informations par le biais de
|
||||
numéros privés d'option.
|
||||
.B --dhcp-match=<identifiant de réseau>,<numéro d'option>|option:<nom d'option>[,<valeur>]
|
||||
Si aucune valeur n'est spécifiée, associe l'identifiant de réseau si le client
|
||||
envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
|
||||
fournie, positionne le label seulement dans le cas où l'option est fournie et
|
||||
correspond à la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel
|
||||
cas le début de l'option doit correspondre (en respectant les jokers). La
|
||||
valeur peut aussi être de la même forme que dans
|
||||
.B dhcp-option
|
||||
, auquel cas l'option est traitée comme un tableau de valeur, et un des
|
||||
éléments doit correspondre, ainsi
|
||||
|
||||
--dhcp-match=efi-ia32,option:client-arch,6
|
||||
|
||||
spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
|
||||
d'architectures envoyé par le client au sein de l'option 93. (se réferer
|
||||
au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères,
|
||||
celle-ci est recherchée (correspondance en temps que sous-chaîne).
|
||||
.TP
|
||||
.B \-J, --dhcp-ignore=<identifiant de réseau>[,<identifiant de réseau>]
|
||||
Lorsque tous les identifiants de réseau fournis coïncident avec la liste
|
||||
@@ -802,10 +852,14 @@ numéro est utilisé pour le port serveur et ce numéro plus 1 est utilisé pour
|
||||
port client. Enfin, en fournissant deux numéros de ports, il est possible de
|
||||
spécifier arbitrairement 2 ports à la fois pour le serveur et pour le client DHCP.
|
||||
.TP
|
||||
.B \-3, --bootp-dynamic
|
||||
.B \-3, --bootp-dynamic[=<identifiant de réseau>[,<identifiant de réseau>]]
|
||||
Permet l'allocation dynamique d'adresses IP à des clients BOOTP. Utiliser cette
|
||||
option avec précaution, une adresse allouée à un client BOOTP étant perpétuelle,
|
||||
et de fait n'est plus disponibles pour d'autres hôtes.
|
||||
et de fait n'est plus disponibles pour d'autres hôtes. Si aucun argument n'est
|
||||
donné, alors cette option permet une allocation dynamique dans tous les cas. Si
|
||||
des arguments sont spécifiés, alors l'allocation ne se fait que lorsque tous
|
||||
les identifiants coïncident. Il est possible de répeter cette option avec
|
||||
plusieurs jeux d'arguments.
|
||||
.TP
|
||||
.B \-5, --no-ping
|
||||
Par défaut, le serveur DHCP tente de s'assurer qu'une adresse n'est pas utilisée
|
||||
@@ -822,32 +876,28 @@ détermination de celles-ci.
|
||||
.TP
|
||||
.B \-l, --dhcp-leasefile=<chemin de fichier>
|
||||
Utilise le fichier dont le chemin est fourni pour stocker les informations de
|
||||
baux DHCP. Si cette option est fournie mais qu'aucune option de type dhcp-range
|
||||
n'est donnée, alors un comportement de type Dnsmasq version 1 est activé. Le
|
||||
fichier fourni est supposé être un fichier de baux DHCP de type ISC DHCPD et est
|
||||
parcouru à la recherche de baux contenant des noms d'hôtes. Les noms trouvés
|
||||
sont rajoutés au DNS. Cette fonctionalité peut être exclue de Dnsmasq à la
|
||||
compilation, auquel cas une erreur sera produite. Il est à noter que
|
||||
l'intégration avec un fichier de baux au format ISC est une fonctionalité
|
||||
obsolète. Elle ne devrait pas être utilisée dans les nouvelles installations et
|
||||
sera retirée dans une future version.
|
||||
baux DHCP.
|
||||
.TP
|
||||
.B \-6 --dhcp-script=<chemin de fichier>
|
||||
Lorsqu'un bail DHCP est créé, ou qu'un ancien est supprimé, le fichier dont le
|
||||
chemin est spécifié est exécuté. Les arguments fournis à celui-ci sont soit
|
||||
"add" ("ajouter"), "old" ("ancien") ou "del" ("supprimer"), suivi de l'adresse
|
||||
MAC de l'hôte (ou "<null>") puis l'adresse IP et le nom d'hôte si celui-ci est
|
||||
MAC de l'hôte puis l'adresse IP et le nom d'hôte si celui-ci est
|
||||
connu."add" signifie qu'un bail a été créé, "del" signifie qu'il a été supprimé,
|
||||
"old" notifie que le bail existait au lancement de Dnsmasq, ou un changement
|
||||
d'adresse MAC ou de nom d'hôte pour un bail existant (ou, dans le cas où
|
||||
leasefile-ro est spécifié, un changement de durée de bail ou d'identifiant
|
||||
d'hôte). Le processus est exécuté en temps que super-utilisateur (si Dnsmasq a
|
||||
été lancé en temps que "root"), même si Dnsmasq est configuré pour changer son
|
||||
UID pour celle d'un utilisateur non-privilégié. 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 le client fournit une information de classe de vendeur ou
|
||||
de classe d'utilisateur, celles-ci sont positionnées dans les variables
|
||||
d'hôte). Si l'adresse Mac est d'un type de réseau autre qu'ethernet, il est
|
||||
nécessaire de la préceder du type de réseau, par exemple "06-01:23:45:67:89:ab"
|
||||
pour du token ring. Le processus est exécuté en temps que super-utilisateur
|
||||
(si Dnsmasq a été lancé en temps que "root"), même si Dnsmasq est configuré
|
||||
pour changer son UID pour celle d'un utilisateur non-privilégié.
|
||||
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
|
||||
@@ -905,8 +955,10 @@ uniquement disponible sur les plateformes BSD, et est uniquement nécessaire
|
||||
lors de l'utilisation de pont ethernet "ancien mode", puisque dans ce cas les
|
||||
paquets arrivent sur des interfaces "tap" n'ayant pas d'adresse IP.
|
||||
.TP
|
||||
.B \-s, --domain=<domaine>
|
||||
Spécifie le domaine du serveur DHCP. Cela a deux effets; tout d'abord, le
|
||||
.B \-s, --domain=<domaine>[,<gamme d'adresses>]
|
||||
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
|
||||
inconditionnelle (sans spécifier de gamme d'adresses IP) ou pour des gammes
|
||||
d'adresses IP limitées. Cela a deux effets; tout d'abord, le
|
||||
serveur DHCP retourne le domaine à tous les hôtes le demandant, deuxièmement,
|
||||
cela spécifie le domaine valide pour les hôtes DHCP configurés. Le but de cela
|
||||
est de contraindre les noms d'hôte afin qu'aucun hôte sur le LAN ne puisse
|
||||
@@ -925,7 +977,29 @@ et avoir une machine dont le nom DHCP serait "laptop". L'adresse IP de cette
|
||||
machine sera disponible à la fois pour "laptop" et "laptop.thekelleys.org.uk".
|
||||
Si la valeur fournie pour <domaine> est "#", alors le nom de domaine est
|
||||
positionné à la première valeur de la directive "search" du fichier
|
||||
/etc/resolv.conf (ou équivalent).
|
||||
/etc/resolv.conf (ou équivalent). La gamme d'adresses peut être de la forme
|
||||
<adresse ip>,<adresse ip> ou <adresse ip>/<masque de réseau> voire une simple
|
||||
<adresse ip>. Voir
|
||||
.B --dhcp-fqdn
|
||||
qui peut changer le comportement de dnsmasq relatif aux domaines.
|
||||
.TP
|
||||
.B --dhcp-fqdn
|
||||
Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients
|
||||
DHCP dans le DNS. Pour cette raison, les noms doivent être uniques, même si
|
||||
deux clients ayant le même nom sont dans deux domaines différents. Si un
|
||||
deuxième client DHCP apparaît ayant le même nom qu'un client déjà existant,
|
||||
ce nom est transféré au nouveau client. Si
|
||||
.B --dhcp-fqdn
|
||||
est spécifié, ce comportement change : les noms non qualifiés ne sont plus
|
||||
rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP
|
||||
avec le même nom peuvent tous les deux garder le nom, pour peu que la partie
|
||||
relative au domaine soit différente (c-à-d que les noms pleinements qualifiés
|
||||
diffèrent). Pour d'assurer que tous les noms ont une partie domaine, il doit-y
|
||||
avoir au moins un
|
||||
.B --domain
|
||||
sans gamme d'adresses de spécifié lorsque l'option
|
||||
.B --dhcp-fqdn
|
||||
est configurée.
|
||||
.TP
|
||||
.B --enable-tftp
|
||||
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
|
||||
@@ -1164,9 +1238,12 @@ les identifiants de réseau fonctionnent comme suit : Dnsmasq associe à chaque
|
||||
requête DHCP un ensemble d'identifiants de réseau; un pour la plage d'adresse
|
||||
DHCP (
|
||||
.B dhcp-range
|
||||
) utilisée pour allouer l'adresse, une pour chaque entrée
|
||||
) utilisée pour allouer l'adresse, un identifiant pour chaque entrée
|
||||
.B dhcp-host
|
||||
associée et éventuellement une pour chaque classe de vendeur ou d'utilisateur
|
||||
associée (il ajoute "known" lorsqu'une entrée dhcp-host coïncide), l'étiquette
|
||||
"bootp" pour les requêtes BOOTP, un identifiant dont le nom est le nom de
|
||||
l'interface sur laquelle la requête est arrivée, et éventuellement un
|
||||
identifiant pour chaque classe de vendeur ou d'utilisateur
|
||||
fournie par le client DHCP dans sa requête. Les options DHCP (
|
||||
.B dhcp-option
|
||||
) ayant un identifiant de réseau seront utilisés de préférence à celles
|
||||
|
||||
688
po/pt_BR.po
688
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
18
src/bpf.c
18
src/bpf.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -63,16 +63,20 @@ int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
}
|
||||
}
|
||||
|
||||
for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len )
|
||||
for (ptr = ifc.ifc_buf; ptr < (char *)(ifc.ifc_buf + ifc.ifc_len); ptr += len)
|
||||
{
|
||||
/* subsequent entries may not be aligned, so copy into
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
len = ((struct ifreq *)ptr)->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#else
|
||||
|
||||
len = sizeof(struct ifreq);
|
||||
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
ifr = (struct ifreq *)ptr;
|
||||
if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru))
|
||||
len = ifr->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#endif
|
||||
|
||||
if (!expand_buf(&ifreq, len))
|
||||
goto err;
|
||||
|
||||
|
||||
318
src/cache.c
318
src/cache.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -642,150 +642,224 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
||||
unsigned short flags, int index, int addr_dup)
|
||||
{
|
||||
struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6));
|
||||
int i;
|
||||
|
||||
int i, nameexists = 0;
|
||||
struct cname *a;
|
||||
|
||||
/* Remove duplicates in hosts files. */
|
||||
if (lookup && (lookup->flags & F_HOSTS) &&
|
||||
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
||||
free(cache);
|
||||
else
|
||||
if (lookup && (lookup->flags & F_HOSTS))
|
||||
{
|
||||
/* Ensure there is only one address -> name mapping (first one trumps)
|
||||
We do this by steam here, first we see if the address is the same as
|
||||
the last one we saw, which eliminates most in the case of an ad-block
|
||||
file with thousands of entries for the same address.
|
||||
Then we search and bail at the first matching address that came from
|
||||
a HOSTS file. Since the first host entry gets reverse, we know
|
||||
then that it must exist without searching exhaustively for it. */
|
||||
|
||||
if (addr_dup)
|
||||
flags &= ~F_REVERSE;
|
||||
else
|
||||
for (i=0; i<hash_size; i++)
|
||||
{
|
||||
for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next)
|
||||
if ((lookup->flags & F_HOSTS) &&
|
||||
(lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
|
||||
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
||||
{
|
||||
flags &= ~F_REVERSE;
|
||||
break;
|
||||
}
|
||||
if (lookup)
|
||||
nameexists = 1;
|
||||
if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
||||
{
|
||||
free(cache);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure there is only one address -> name mapping (first one trumps)
|
||||
We do this by steam here, first we see if the address is the same as
|
||||
the last one we saw, which eliminates most in the case of an ad-block
|
||||
file with thousands of entries for the same address.
|
||||
Then we search and bail at the first matching address that came from
|
||||
a HOSTS file. Since the first host entry gets reverse, we know
|
||||
then that it must exist without searching exhaustively for it. */
|
||||
|
||||
if (addr_dup)
|
||||
flags &= ~F_REVERSE;
|
||||
else
|
||||
for (i=0; i<hash_size; i++)
|
||||
{
|
||||
for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next)
|
||||
if ((lookup->flags & F_HOSTS) &&
|
||||
(lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
|
||||
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
||||
{
|
||||
flags &= ~F_REVERSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lookup)
|
||||
break;
|
||||
}
|
||||
|
||||
cache->flags = flags;
|
||||
cache->uid = index;
|
||||
memcpy(&cache->addr.addr, addr, addrlen);
|
||||
cache_hash(cache);
|
||||
|
||||
/* don't need to do alias stuff for second and subsequent addresses. */
|
||||
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->flags = F_FORWARD | F_IMMORTAL | F_HOSTS | F_CNAME;
|
||||
strcpy(lookup->name.sname, a->alias);
|
||||
lookup->addr.cname.cache = cache;
|
||||
lookup->addr.cname.uid = index;
|
||||
cache_hash(lookup);
|
||||
}
|
||||
}
|
||||
|
||||
static int eatspace(FILE *f)
|
||||
{
|
||||
int c, nl = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((c = getc(f)) == '#')
|
||||
while (c != '\n' && c != EOF)
|
||||
c = getc(f);
|
||||
|
||||
cache->flags = flags;
|
||||
cache->uid = index;
|
||||
memcpy(&cache->addr.addr, addr, addrlen);
|
||||
cache_hash(cache);
|
||||
if (c == EOF)
|
||||
return 1;
|
||||
|
||||
if (!isspace(c))
|
||||
{
|
||||
ungetc(c, f);
|
||||
return nl;
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
nl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int gettok(FILE *f, char *token)
|
||||
{
|
||||
int c, count = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((c = getc(f)) == EOF)
|
||||
return (count == 0) ? EOF : 1;
|
||||
|
||||
if (isspace(c) || c == '#')
|
||||
{
|
||||
ungetc(c, f);
|
||||
return eatspace(f);
|
||||
}
|
||||
|
||||
if (count < (MAXDNAME - 1))
|
||||
{
|
||||
token[count++] = c;
|
||||
token[count] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int read_hostsfile(char *filename, int opts, char *buff, char *domain_suffix, int index, int cache_size)
|
||||
static int read_hostsfile(char *filename, int index, int cache_size)
|
||||
{
|
||||
FILE *f = fopen(filename, "r");
|
||||
char *line;
|
||||
char *token = daemon->namebuff, *domain_suffix = NULL;
|
||||
int addr_count = 0, name_count = cache_size, lineno = 0;
|
||||
unsigned short flags, saved_flags = 0;
|
||||
unsigned short flags = 0, saved_flags = 0;
|
||||
struct all_addr addr, saved_addr;
|
||||
int atnl, addrlen = 0, addr_dup;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((line = fgets(buff, MAXDNAME, f)))
|
||||
|
||||
eatspace(f);
|
||||
|
||||
while ((atnl = gettok(f, token)) != EOF)
|
||||
{
|
||||
char *token = strtok(line, " \t\n\r");
|
||||
int addrlen, addr_dup = 0;
|
||||
|
||||
addr_dup = 0;
|
||||
lineno++;
|
||||
|
||||
if (!token || (*token == '#'))
|
||||
continue;
|
||||
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (inet_pton(AF_INET, token, &addr) > 0)
|
||||
{
|
||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
|
||||
addrlen = INADDRSZ;
|
||||
domain_suffix = get_domain(addr.addr.addr4);
|
||||
}
|
||||
else if (inet_pton(AF_INET6, token, &addr) > 0)
|
||||
{
|
||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
|
||||
addrlen = IN6ADDRSZ;
|
||||
domain_suffix = daemon->domain_suffix;
|
||||
}
|
||||
#else
|
||||
if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
||||
{
|
||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
|
||||
addrlen = INADDRSZ;
|
||||
if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
||||
{
|
||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
|
||||
addrlen = INADDRSZ;
|
||||
domain_suffix = get_domain(addr.addr.addr4);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
|
||||
while (atnl == 0)
|
||||
atnl = gettok(f, token);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
|
||||
addr_dup = 1;
|
||||
else
|
||||
{
|
||||
saved_flags = flags;
|
||||
saved_addr = addr;
|
||||
}
|
||||
|
||||
addr_count++;
|
||||
|
||||
/* rehash every 1000 names. */
|
||||
if ((name_count - cache_size) > 1000)
|
||||
{
|
||||
rehash(name_count);
|
||||
cache_size = name_count;
|
||||
}
|
||||
|
||||
while (atnl == 0)
|
||||
{
|
||||
struct crec *cache;
|
||||
int fqdn;
|
||||
|
||||
if ((atnl = gettok(f, token)) == EOF)
|
||||
break;
|
||||
|
||||
fqdn = !!strchr(token, '.');
|
||||
|
||||
if (canonicalise(token))
|
||||
{
|
||||
/* 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)))
|
||||
{
|
||||
strcpy(cache->name.sname, token);
|
||||
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)))
|
||||
{
|
||||
strcpy(cache->name.sname, token);
|
||||
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
|
||||
name_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
|
||||
}
|
||||
}
|
||||
|
||||
if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
|
||||
addr_dup = 1;
|
||||
else
|
||||
{
|
||||
saved_flags = flags;
|
||||
saved_addr = addr;
|
||||
}
|
||||
|
||||
addr_count++;
|
||||
|
||||
/* rehash every 1000 names. */
|
||||
if ((name_count - cache_size) > 1000)
|
||||
{
|
||||
rehash(name_count);
|
||||
cache_size = name_count;
|
||||
}
|
||||
|
||||
while ((token = strtok(NULL, " \t\n\r")) && (*token != '#'))
|
||||
{
|
||||
struct crec *cache;
|
||||
int fqdn = !!strchr(token, '.');
|
||||
if (canonicalise(token))
|
||||
{
|
||||
/* If set, add a version of the name with a default domain appended */
|
||||
if ((opts & OPT_EXPAND) && domain_suffix && !fqdn &&
|
||||
(cache = whine_malloc(sizeof(struct crec) +
|
||||
strlen(token)+2+strlen(domain_suffix)-SMALLDNAME)))
|
||||
{
|
||||
strcpy(cache->name.sname, token);
|
||||
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)))
|
||||
{
|
||||
strcpy(cache->name.sname, token);
|
||||
add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
|
||||
name_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
rehash(name_count);
|
||||
|
||||
|
||||
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
|
||||
|
||||
|
||||
return name_count;
|
||||
}
|
||||
|
||||
void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *addn_hosts)
|
||||
void cache_reload(struct hostsfile *addn_hosts)
|
||||
{
|
||||
struct crec *cache, **up, *tmp;
|
||||
int i, total_size = daemon->cachesize;
|
||||
@@ -815,18 +889,18 @@ void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *a
|
||||
up = &cache->hash_next;
|
||||
}
|
||||
|
||||
if ((opts & OPT_NO_HOSTS) && !addn_hosts)
|
||||
if ((daemon->options & OPT_NO_HOSTS) && !addn_hosts)
|
||||
{
|
||||
if (daemon->cachesize > 0)
|
||||
my_syslog(LOG_INFO, _("cleared cache"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(opts & OPT_NO_HOSTS))
|
||||
total_size = read_hostsfile(HOSTSFILE, opts, buff, domain_suffix, 0, total_size);
|
||||
if (!(daemon->options & OPT_NO_HOSTS))
|
||||
total_size = read_hostsfile(HOSTSFILE, 0, total_size);
|
||||
while (addn_hosts)
|
||||
{
|
||||
total_size = read_hostsfile(addn_hosts->fname, opts, buff, domain_suffix, addn_hosts->index, total_size);
|
||||
total_size = read_hostsfile(addn_hosts->fname, addn_hosts->index, total_size);
|
||||
addn_hosts = addn_hosts->next;
|
||||
}
|
||||
}
|
||||
@@ -851,13 +925,11 @@ void cache_unhash_dhcp(void)
|
||||
void cache_add_dhcp_entry(char *host_name,
|
||||
struct in_addr *host_address, time_t ttd)
|
||||
{
|
||||
struct crec *crec = NULL;
|
||||
struct crec *crec = NULL, *aliasc;
|
||||
unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
|
||||
int in_hosts = 0;
|
||||
|
||||
if (!host_name)
|
||||
return;
|
||||
|
||||
struct cname *a;
|
||||
|
||||
while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME)))
|
||||
{
|
||||
/* check all addresses associated with name */
|
||||
@@ -911,10 +983,34 @@ void cache_add_dhcp_entry(char *host_name,
|
||||
crec->ttd = ttd;
|
||||
crec->addr.addr.addr.addr4 = *host_address;
|
||||
crec->name.namep = host_name;
|
||||
crec->uid = uid++;
|
||||
cache_hash(crec);
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(host_name, a->target))
|
||||
{
|
||||
if ((aliasc = dhcp_spare))
|
||||
dhcp_spare = dhcp_spare->next;
|
||||
else /* need new one */
|
||||
aliasc = whine_malloc(sizeof(struct crec));
|
||||
|
||||
if (aliasc)
|
||||
{
|
||||
aliasc->flags = F_FORWARD | F_DHCP | F_CNAME;
|
||||
if (ttd == 0)
|
||||
aliasc->flags |= F_IMMORTAL;
|
||||
else
|
||||
aliasc->ttd = ttd;
|
||||
aliasc->name.namep = a->alias;
|
||||
aliasc->addr.cname.cache = crec;
|
||||
aliasc->addr.cname.uid = crec->uid;
|
||||
cache_hash(aliasc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dump_cache(time_t now)
|
||||
{
|
||||
struct server *serv, *serv1;
|
||||
|
||||
48
src/config.h
48
src/config.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,11 +10,11 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.44"
|
||||
#define VERSION "2.47"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -38,18 +38,25 @@
|
||||
# define RESOLVFILE "/etc/resolv.conf"
|
||||
#endif
|
||||
#define RUNFILE "/var/run/dnsmasq.pid"
|
||||
#if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__)
|
||||
# define LEASEFILE "/var/db/dnsmasq.leases"
|
||||
#elif defined(__sun__) || defined (__sun)
|
||||
# define LEASEFILE "/var/cache/dnsmasq.leases"
|
||||
#else
|
||||
# define LEASEFILE "/var/lib/misc/dnsmasq.leases"
|
||||
|
||||
#ifndef LEASEFILE
|
||||
# if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
||||
# define LEASEFILE "/var/db/dnsmasq.leases"
|
||||
# elif defined(__sun__) || defined (__sun)
|
||||
# define LEASEFILE "/var/cache/dnsmasq.leases"
|
||||
# else
|
||||
# define LEASEFILE "/var/lib/misc/dnsmasq.leases"
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# define CONFFILE "/usr/local/etc/dnsmasq.conf"
|
||||
#else
|
||||
# define CONFFILE "/etc/dnsmasq.conf"
|
||||
|
||||
#ifndef CONFFILE
|
||||
# if defined(__FreeBSD__)
|
||||
# define CONFFILE "/usr/local/etc/dnsmasq.conf"
|
||||
# else
|
||||
# define CONFFILE "/etc/dnsmasq.conf"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
#define CHGRP "dip"
|
||||
@@ -61,6 +68,7 @@
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
#define RANDFILE "/dev/urandom"
|
||||
#define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */
|
||||
|
||||
/* DBUS interface specifics */
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
|
||||
@@ -115,10 +123,6 @@ HAVE_BROKEN_RTC
|
||||
NOTE: when enabling or disabling this, be sure to delete any old
|
||||
leases file, otherwise dnsmasq may get very confused.
|
||||
|
||||
HAVE_ISC_READER
|
||||
define this to include the old ISC dhcpcd integration. Note that you cannot
|
||||
set both HAVE_ISC_READER and HAVE_BROKEN_RTC.
|
||||
|
||||
HAVE_TFTP
|
||||
define this to get dnsmasq's built-in TFTP server.
|
||||
|
||||
@@ -141,9 +145,6 @@ HAVE_BSD_BRIDGE
|
||||
Define this to enable the --bridge-interface option, useful on some
|
||||
BSD systems.
|
||||
|
||||
HAVE_LARGFILE
|
||||
Define this if the C library supports large (>2GB) files probably true everywhere
|
||||
except some builds of uclibc
|
||||
|
||||
NOTES:
|
||||
For Linux you should define
|
||||
@@ -166,13 +167,8 @@ NOTES:
|
||||
/* platform independent options- uncomment to enable */
|
||||
#define HAVE_TFTP
|
||||
/* #define HAVE_BROKEN_RTC */
|
||||
/* #define HAVE_ISC_READER */
|
||||
/* #define HAVE_DBUS */
|
||||
|
||||
#if defined(HAVE_BROKEN_RTC) && defined(HAVE_ISC_READER)
|
||||
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
|
||||
#endif
|
||||
|
||||
/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
|
||||
#ifdef NO_TFTP
|
||||
#undef HAVE_TFTP
|
||||
|
||||
89
src/dbus.c
89
src/dbus.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -21,6 +21,42 @@
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
const char* introspection_xml =
|
||||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
||||
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||
"<node name=\"" DNSMASQ_PATH "\">\n"
|
||||
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
|
||||
" <method name=\"Introspect\">\n"
|
||||
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
" <interface name=\"" DNSMASQ_SERVICE "\">\n"
|
||||
" <method name=\"ClearCache\">\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetVersion\">\n"
|
||||
" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetServers\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"DhcpLeaseDeleted\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"DhcpLeaseUpdated\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
struct watch {
|
||||
DBusWatch *watch;
|
||||
struct watch *next;
|
||||
@@ -229,7 +265,15 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
{
|
||||
char *method = (char *)dbus_message_get_member(message);
|
||||
|
||||
if (strcmp(method, "GetVersion") == 0)
|
||||
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
else if (strcmp(method, "GetVersion") == 0)
|
||||
{
|
||||
char *v = VERSION;
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
@@ -283,7 +327,10 @@ char *dbus_init(void)
|
||||
daemon->dbus = connection;
|
||||
|
||||
if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
|
||||
dbus_connection_send(connection, message, NULL);
|
||||
{
|
||||
dbus_connection_send(connection, message, NULL);
|
||||
dbus_message_unref(message);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -352,4 +399,36 @@ 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)
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
DBusMessage* message = NULL;
|
||||
DBusMessageIter args;
|
||||
const char *action_str;
|
||||
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
if (action == ACTION_DEL)
|
||||
action_str = "DhcpLeaseDeleted";
|
||||
else if (action == ACTION_ADD)
|
||||
action_str = "DhcpLeaseAdded";
|
||||
else if (action == ACTION_OLD)
|
||||
action_str = "DhcpLeaseUpdated";
|
||||
else
|
||||
return;
|
||||
|
||||
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
|
||||
return;
|
||||
|
||||
dbus_message_iter_init_append(message, &args);
|
||||
|
||||
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &addr) &&
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) &&
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname))
|
||||
dbus_connection_send(connection, message, NULL);
|
||||
|
||||
dbus_message_unref(message);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
129
src/dhcp.c
129
src/dhcp.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -345,7 +345,12 @@ void dhcp_packet(time_t now)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
/* OpenSolaris eliminates IP_XMIT_IF */
|
||||
# ifdef IP_XMIT_IF
|
||||
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_XMIT_IF, &iface_index, sizeof(iface_index));
|
||||
# else
|
||||
setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
|
||||
@@ -560,9 +565,16 @@ int address_allocate(struct dhcp_context *context,
|
||||
if (addr.s_addr == d->router.s_addr)
|
||||
break;
|
||||
|
||||
/* Addresses which end in .255 and .0 are broken in Windows even when using
|
||||
supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
|
||||
then 192.168.0.255 is a valid IP address, but not for Windows as it's
|
||||
in the class C range. See KB281579. We therefore don't allocate these
|
||||
addresses to avoid hard-to-diagnose problems. Thanks Bill. */
|
||||
if (!d &&
|
||||
!lease_find_by_addr(addr) &&
|
||||
!config_find_by_address(daemon->dhcp_conf, addr))
|
||||
!config_find_by_address(daemon->dhcp_conf, addr) &&
|
||||
(!IN_CLASSC(ntohl(addr.s_addr)) ||
|
||||
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
|
||||
{
|
||||
struct ping_result *r, *victim = NULL;
|
||||
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
|
||||
@@ -635,6 +647,19 @@ static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
|
||||
{
|
||||
struct hwaddr_config *conf_addr;
|
||||
|
||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||
if (conf_addr->wildcard_mask == 0 &&
|
||||
conf_addr->hwaddr_len == len &&
|
||||
(conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
|
||||
memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
struct dhcp_context *context,
|
||||
@@ -643,7 +668,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
int hw_type, char *hostname)
|
||||
{
|
||||
struct dhcp_config *config;
|
||||
|
||||
struct hwaddr_config *conf_addr;
|
||||
|
||||
if (clid)
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->flags & CONFIG_CLID)
|
||||
@@ -663,11 +689,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if ((config->flags & CONFIG_HWADDR) &&
|
||||
config->wildcard_mask == 0 &&
|
||||
config->hwaddr_len == hw_len &&
|
||||
(config->hwaddr_type == hw_type || config->hwaddr_type == 0) &&
|
||||
memcmp(config->hwaddr, hwaddr, hw_len) == 0 &&
|
||||
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
|
||||
@@ -679,14 +701,14 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
return config;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if ((config->flags & CONFIG_HWADDR) &&
|
||||
config->wildcard_mask != 0 &&
|
||||
config->hwaddr_len == hw_len &&
|
||||
(config->hwaddr_type == hw_type || config->hwaddr_type == 0) &&
|
||||
is_addr_in_context(context, config) &&
|
||||
memcmp_masked(config->hwaddr, hwaddr, hw_len, config->wildcard_mask))
|
||||
return config;
|
||||
|
||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||
if (conf_addr->wildcard_mask != 0 &&
|
||||
conf_addr->hwaddr_len == hw_len &&
|
||||
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
|
||||
is_addr_in_context(context, config) &&
|
||||
memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask))
|
||||
return config;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -720,6 +742,7 @@ void dhcp_read_ethers(void)
|
||||
/* cannot have a clid */
|
||||
if (config->flags & CONFIG_NAME)
|
||||
free(config->hostname);
|
||||
free(config->hwaddr);
|
||||
free(config);
|
||||
}
|
||||
else
|
||||
@@ -733,7 +756,7 @@ void dhcp_read_ethers(void)
|
||||
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
|
||||
buff[strlen(buff)-1] = 0;
|
||||
|
||||
if ((*buff == '#') || (*buff == '+'))
|
||||
if ((*buff == '#') || (*buff == '+') || (*buff == 0))
|
||||
continue;
|
||||
|
||||
for (ip = buff; *ip && !isspace((int)*ip); ip++);
|
||||
@@ -766,7 +789,7 @@ void dhcp_read_ethers(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!canonicalise(ip) || strip_hostname(ip))
|
||||
if (!canonicalise(ip))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
|
||||
continue;
|
||||
@@ -782,19 +805,24 @@ void dhcp_read_ethers(void)
|
||||
if (!config)
|
||||
{
|
||||
for (config = daemon->dhcp_conf; config; config = config->next)
|
||||
if ((config->flags & CONFIG_HWADDR) &&
|
||||
config->wildcard_mask == 0 &&
|
||||
config->hwaddr_len == ETHER_ADDR_LEN &&
|
||||
(config->hwaddr_type == ARPHRD_ETHER || config->hwaddr_type == 0) &&
|
||||
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
|
||||
break;
|
||||
{
|
||||
struct hwaddr_config *conf_addr = config->hwaddr;
|
||||
if (conf_addr &&
|
||||
conf_addr->next == NULL &&
|
||||
conf_addr->wildcard_mask == 0 &&
|
||||
conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
|
||||
(conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
|
||||
memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!config)
|
||||
{
|
||||
if (!(config = whine_malloc(sizeof(struct dhcp_config))))
|
||||
continue;
|
||||
config->flags = CONFIG_FROM_ETHERS;
|
||||
config->wildcard_mask = 0;
|
||||
config->hwaddr = NULL;
|
||||
config->domain = NULL;
|
||||
config->next = daemon->dhcp_conf;
|
||||
daemon->dhcp_conf = config;
|
||||
}
|
||||
@@ -813,10 +841,17 @@ void dhcp_read_ethers(void)
|
||||
config->addr = addr;
|
||||
}
|
||||
|
||||
config->flags |= CONFIG_HWADDR | CONFIG_NOCLID;
|
||||
memcpy(config->hwaddr, hwaddr, ETHER_ADDR_LEN);
|
||||
config->hwaddr_len = ETHER_ADDR_LEN;
|
||||
config->hwaddr_type = ARPHRD_ETHER;
|
||||
config->flags |= CONFIG_NOCLID;
|
||||
if (!config->hwaddr)
|
||||
config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
|
||||
if (config->hwaddr)
|
||||
{
|
||||
memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
|
||||
config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
|
||||
config->hwaddr->hwaddr_type = ARPHRD_ETHER;
|
||||
config->hwaddr->wildcard_mask = 0;
|
||||
config->hwaddr->next = NULL;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -852,15 +887,9 @@ void check_dhcp_hosts(int fatal)
|
||||
configs->flags &= ~CONFIG_ADDR;
|
||||
}
|
||||
|
||||
/* split off domain part */
|
||||
if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
|
||||
{
|
||||
if (fatal)
|
||||
die(_("illegal domain %s in dhcp-config directive."), domain, EC_BADCONF);
|
||||
else
|
||||
my_syslog(LOG_ERR, _("illegal domain %s in %s."), domain, daemon->dhcp_hosts_file);
|
||||
free(configs->hostname);
|
||||
configs->flags &= ~CONFIG_NAME;
|
||||
}
|
||||
configs->domain = domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -918,6 +947,7 @@ char *host_from_dns(struct in_addr addr)
|
||||
{
|
||||
struct crec *lookup;
|
||||
char *hostname = NULL;
|
||||
char *d1, *d2;
|
||||
|
||||
if (daemon->port == 0)
|
||||
return NULL; /* DNS disabled. */
|
||||
@@ -928,14 +958,16 @@ char *host_from_dns(struct in_addr addr)
|
||||
hostname = daemon->dhcp_buff;
|
||||
strncpy(hostname, cache_get_name(lookup), 256);
|
||||
hostname[255] = 0;
|
||||
if (strip_hostname(hostname))
|
||||
d1 = strip_hostname(hostname);
|
||||
d2 = get_domain(addr);
|
||||
if (d1 && (!d2 || hostname_isequal(d1, d2)))
|
||||
hostname = NULL;
|
||||
}
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
/* return illegal domain or NULL if OK */
|
||||
/* return domain or NULL if none. */
|
||||
char *strip_hostname(char *hostname)
|
||||
{
|
||||
char *dot = strchr(hostname, '.');
|
||||
@@ -944,9 +976,20 @@ char *strip_hostname(char *hostname)
|
||||
return NULL;
|
||||
|
||||
*dot = 0; /* truncate */
|
||||
|
||||
if (*(dot+1) && (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix)))
|
||||
if (strlen(dot+1) != 0)
|
||||
return dot+1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *get_domain(struct in_addr addr)
|
||||
{
|
||||
struct cond_domain *c;
|
||||
|
||||
for (c = daemon->cond_domain; c; c = c->next)
|
||||
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
return c->domain;
|
||||
|
||||
return daemon->domain_suffix;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -36,10 +36,6 @@ static char *compile_opts =
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
"BSD-bridge "
|
||||
#endif
|
||||
#ifndef HAVE_ISC_READER
|
||||
"no-"
|
||||
#endif
|
||||
"ISC-leasefile "
|
||||
#ifndef HAVE_DBUS
|
||||
"no-"
|
||||
#endif
|
||||
@@ -66,7 +62,7 @@ static void poll_resolv(void);
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int bind_fallback = 0;
|
||||
time_t now, last = 0;
|
||||
time_t now;
|
||||
struct sigaction sigact;
|
||||
struct iname *if_tmp;
|
||||
int piperead, pipefd[2], err_pipe[2];
|
||||
@@ -117,10 +113,6 @@ int main (int argc, char **argv)
|
||||
if (daemon->dhcp)
|
||||
daemon->lease_file = LEASEFILE;
|
||||
}
|
||||
#ifndef HAVE_ISC_READER
|
||||
else if (!daemon->dhcp)
|
||||
die(_("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
/* Close any file descriptors we inherited apart from std{in|out|err} */
|
||||
for (i = 0; i < max_fd; i++)
|
||||
@@ -633,14 +625,11 @@ int main (int argc, char **argv)
|
||||
|
||||
/* Check for changes to resolv files once per second max. */
|
||||
/* Don't go silent for long periods if the clock goes backwards. */
|
||||
if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < -1.0)
|
||||
if (daemon->last_resolv == 0 ||
|
||||
difftime(now, daemon->last_resolv) > 1.0 ||
|
||||
difftime(now, daemon->last_resolv) < -1.0)
|
||||
{
|
||||
last = now;
|
||||
|
||||
#ifdef HAVE_ISC_READER
|
||||
if (daemon->lease_file && !daemon->dhcp)
|
||||
load_dhcp(now);
|
||||
#endif
|
||||
daemon->last_resolv = now;
|
||||
|
||||
if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
|
||||
poll_resolv();
|
||||
@@ -867,6 +856,9 @@ static void async_event(int pipe, time_t now)
|
||||
|
||||
if (daemon->lease_stream)
|
||||
fclose(daemon->lease_stream);
|
||||
|
||||
if (daemon->runfile)
|
||||
unlink(daemon->runfile);
|
||||
|
||||
my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
|
||||
flush_log();
|
||||
@@ -912,7 +904,7 @@ static void poll_resolv()
|
||||
warned = 0;
|
||||
check_servers();
|
||||
if (daemon->options & OPT_RELOAD)
|
||||
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
|
||||
cache_reload(daemon->addn_hosts);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -929,7 +921,7 @@ static void poll_resolv()
|
||||
void clear_cache_and_reload(time_t now)
|
||||
{
|
||||
if (daemon->port != 0)
|
||||
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
|
||||
cache_reload(daemon->addn_hosts);
|
||||
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2008 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,11 +10,11 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define COPYRIGHT "Copyright (C) 2000-2008 Simon Kelley"
|
||||
#define COPYRIGHT "Copyright (C) 2000-2009 Simon Kelley"
|
||||
|
||||
#ifndef NO_LARGEFILE
|
||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||
@@ -172,7 +172,7 @@ struct event_desc {
|
||||
#define OPT_AUTHORITATIVE (1u<<17)
|
||||
#define OPT_LOCALISE (1u<<18)
|
||||
#define OPT_DBUS (1u<<19)
|
||||
#define OPT_BOOTP_DYNAMIC (1u<<20)
|
||||
#define OPT_DHCP_FQDN (1u<<20)
|
||||
#define OPT_NO_PING (1u<<21)
|
||||
#define OPT_LEASE_RO (1u<<22)
|
||||
#define OPT_ALL_SERVERS (1u<<23)
|
||||
@@ -201,7 +201,7 @@ struct bogus_addr {
|
||||
|
||||
/* dns doctor param */
|
||||
struct doctor {
|
||||
struct in_addr in, out, mask;
|
||||
struct in_addr in, end, out, mask;
|
||||
struct doctor *next;
|
||||
};
|
||||
|
||||
@@ -229,6 +229,11 @@ struct ptr_record {
|
||||
struct ptr_record *next;
|
||||
};
|
||||
|
||||
struct cname {
|
||||
char *alias, *target;
|
||||
struct cname *next;
|
||||
};
|
||||
|
||||
struct interface_name {
|
||||
char *name; /* domain name */
|
||||
char *intr; /* interface name */
|
||||
@@ -425,23 +430,28 @@ struct dhcp_netid_list {
|
||||
struct dhcp_netid_list *next;
|
||||
};
|
||||
|
||||
struct hwaddr_config {
|
||||
int hwaddr_len, hwaddr_type;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
unsigned int wildcard_mask;
|
||||
struct hwaddr_config *next;
|
||||
};
|
||||
|
||||
struct dhcp_config {
|
||||
unsigned int flags;
|
||||
int clid_len; /* length of client identifier */
|
||||
unsigned char *clid; /* clientid */
|
||||
int hwaddr_len, hwaddr_type;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
char *hostname;
|
||||
char *hostname, *domain;
|
||||
struct dhcp_netid netid;
|
||||
struct in_addr addr;
|
||||
time_t decline_time;
|
||||
unsigned int lease_time, wildcard_mask;
|
||||
unsigned int lease_time;
|
||||
struct hwaddr_config *hwaddr;
|
||||
struct dhcp_config *next;
|
||||
};
|
||||
|
||||
#define CONFIG_DISABLE 1
|
||||
#define CONFIG_CLID 2
|
||||
#define CONFIG_HWADDR 4
|
||||
#define CONFIG_TIME 8
|
||||
#define CONFIG_NAME 16
|
||||
#define CONFIG_ADDR 32
|
||||
@@ -454,7 +464,12 @@ struct dhcp_config {
|
||||
|
||||
struct dhcp_opt {
|
||||
int opt, len, flags;
|
||||
unsigned char *val, *vendor_class;
|
||||
union {
|
||||
int encap;
|
||||
unsigned int wildcard_mask;
|
||||
unsigned char *vendor_class;
|
||||
} u;
|
||||
unsigned char *val;
|
||||
struct dhcp_netid *netid;
|
||||
struct dhcp_opt *next;
|
||||
};
|
||||
@@ -462,9 +477,13 @@ struct dhcp_opt {
|
||||
#define DHOPT_ADDR 1
|
||||
#define DHOPT_STRING 2
|
||||
#define DHOPT_ENCAPSULATE 4
|
||||
#define DHOPT_VENDOR_MATCH 8
|
||||
#define DHOPT_ENCAP_MATCH 8
|
||||
#define DHOPT_FORCE 16
|
||||
#define DHOPT_BANK 32
|
||||
#define DHOPT_ENCAP_DONE 64
|
||||
#define DHOPT_MATCH 128
|
||||
#define DHOPT_VENDOR 256
|
||||
#define DHOPT_HEX 512
|
||||
|
||||
struct dhcp_boot {
|
||||
char *file, *sname;
|
||||
@@ -478,7 +497,6 @@ struct dhcp_boot {
|
||||
#define MATCH_CIRCUIT 3
|
||||
#define MATCH_REMOTE 4
|
||||
#define MATCH_SUBSCRIBER 5
|
||||
#define MATCH_OPTION 6
|
||||
|
||||
/* vendorclass, userclass, remote-id or cicuit-id */
|
||||
struct dhcp_vendor {
|
||||
@@ -503,6 +521,12 @@ struct dhcp_bridge {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct cond_domain {
|
||||
char *domain;
|
||||
struct in_addr start, end;
|
||||
struct cond_domain *next;
|
||||
};
|
||||
|
||||
struct dhcp_context {
|
||||
unsigned int lease_time, addr_epoch;
|
||||
struct in_addr netmask, broadcast;
|
||||
@@ -565,16 +589,19 @@ extern struct daemon {
|
||||
|
||||
unsigned int options;
|
||||
struct resolvc default_resolv, *resolv_files;
|
||||
time_t last_resolv;
|
||||
struct mx_srv_record *mxnames;
|
||||
struct naptr *naptr;
|
||||
struct txt_record *txt;
|
||||
struct ptr_record *ptr;
|
||||
struct cname *cnames;
|
||||
struct interface_name *int_names;
|
||||
char *mxtarget;
|
||||
char *lease_file;
|
||||
char *username, *groupname, *scriptuser;
|
||||
int group_set, osport;
|
||||
char *domain_suffix;
|
||||
struct cond_domain *cond_domain;
|
||||
char *runfile;
|
||||
char *lease_change_command;
|
||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
|
||||
@@ -589,11 +616,11 @@ extern struct daemon {
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp;
|
||||
struct dhcp_config *dhcp_conf;
|
||||
struct dhcp_opt *dhcp_opts;
|
||||
struct dhcp_opt *dhcp_opts, *dhcp_match;
|
||||
struct dhcp_vendor *dhcp_vendors;
|
||||
struct dhcp_mac *dhcp_macs;
|
||||
struct dhcp_boot *boot_config;
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast;
|
||||
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;
|
||||
int dhcp_server_port, dhcp_client_port;
|
||||
@@ -660,7 +687,7 @@ void cache_end_insert(void);
|
||||
void cache_start_insert(void);
|
||||
struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
time_t now, unsigned long ttl, unsigned short flags);
|
||||
void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *addn_hosts);
|
||||
void cache_reload(struct hostsfile *addn_hosts);
|
||||
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd);
|
||||
void cache_unhash_dhcp(void);
|
||||
void dump_cache(time_t now);
|
||||
@@ -749,17 +776,17 @@ struct in_addr get_ifaddr(char *intr);
|
||||
/* dhcp.c */
|
||||
void dhcp_init(void);
|
||||
void dhcp_packet(time_t now);
|
||||
|
||||
char *get_domain(struct in_addr addr);
|
||||
struct dhcp_context *address_available(struct dhcp_context *context,
|
||||
struct in_addr addr,
|
||||
struct dhcp_netid *netids);
|
||||
struct dhcp_context *narrow_context(struct dhcp_context *context,
|
||||
struct in_addr taddr,
|
||||
struct dhcp_netid *netids);
|
||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
|
||||
int address_allocate(struct dhcp_context *context,
|
||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);int address_allocate(struct dhcp_context *context,
|
||||
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
|
||||
struct dhcp_netid *netids, time_t now);
|
||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
|
||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
struct dhcp_context *context,
|
||||
unsigned char *clid, int clid_len,
|
||||
@@ -771,6 +798,7 @@ void check_dhcp_hosts(int fatal);
|
||||
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
|
||||
char *strip_hostname(char *hostname);
|
||||
char *host_from_dns(struct in_addr addr);
|
||||
char *get_domain(struct in_addr addr);
|
||||
|
||||
/* lease.c */
|
||||
void lease_update_file(time_t now);
|
||||
@@ -779,8 +807,7 @@ void lease_init(time_t now);
|
||||
struct dhcp_lease *lease_allocate(struct in_addr addr);
|
||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
unsigned char *clid, int hw_len, int hw_type, int clid_len);
|
||||
void lease_set_hostname(struct dhcp_lease *lease, char *name,
|
||||
char *suffix, int auth);
|
||||
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth);
|
||||
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
|
||||
void lease_set_interface(struct dhcp_lease *lease, int interface);
|
||||
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
|
||||
@@ -794,6 +821,8 @@ void rerun_scripts(void);
|
||||
/* rfc2131.c */
|
||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform);
|
||||
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out);
|
||||
|
||||
/* dnsmasq.c */
|
||||
int make_icmp_sock(void);
|
||||
@@ -801,11 +830,6 @@ int icmp_ping(struct in_addr addr);
|
||||
void send_event(int fd, int event, int data);
|
||||
void clear_cache_and_reload(time_t now);
|
||||
|
||||
/* isc.c */
|
||||
#ifdef HAVE_ISC_READER
|
||||
void load_dhcp(time_t now);
|
||||
#endif
|
||||
|
||||
/* netlink.c */
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
void netlink_init(void);
|
||||
@@ -827,6 +851,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);
|
||||
#endif
|
||||
|
||||
/* helper.c */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -381,8 +381,8 @@ static size_t process_reply(HEADER *header, time_t now,
|
||||
size_t plen;
|
||||
|
||||
/* If upstream is advertising a larger UDP packet size
|
||||
than we allow, trim it so that we don't get overlarge
|
||||
requests for the client. We can't do this for signed packets. */
|
||||
than we allow, trim it so that we don't get overlarge
|
||||
requests for the client. We can't do this for signed packets. */
|
||||
|
||||
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
|
||||
{
|
||||
@@ -918,19 +918,23 @@ static struct randfd *allocate_rfd(int family)
|
||||
(eg) TFTP. Once we have a reasonable number, randomness should be OK */
|
||||
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
if (daemon->randomsocks[i].refcount == 0 &&
|
||||
(daemon->randomsocks[i].fd = random_sock(family)) != -1)
|
||||
if (daemon->randomsocks[i].refcount == 0)
|
||||
{
|
||||
if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
|
||||
break;
|
||||
|
||||
daemon->randomsocks[i].refcount = 1;
|
||||
daemon->randomsocks[i].family = family;
|
||||
return &daemon->randomsocks[i];
|
||||
}
|
||||
|
||||
/* No free ones, grab an existing one */
|
||||
/* No free ones or cannot get new socket, grab an existing one */
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
{
|
||||
int j = (i+finger) % RANDOM_SOCKS;
|
||||
if (daemon->randomsocks[j].family == family && daemon->randomsocks[j].refcount != 0xffff)
|
||||
if (daemon->randomsocks[j].refcount != 0 &&
|
||||
daemon->randomsocks[j].family == family &&
|
||||
daemon->randomsocks[j].refcount != 0xffff)
|
||||
{
|
||||
finger = j;
|
||||
daemon->randomsocks[j].refcount++;
|
||||
|
||||
45
src/helper.c
45
src/helper.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -31,7 +31,7 @@
|
||||
#ifndef NO_FORK
|
||||
|
||||
static void my_setenv(const char *name, const char *value, int *error);
|
||||
|
||||
|
||||
struct script_data
|
||||
{
|
||||
unsigned char action, hwaddr_len, hwaddr_type;
|
||||
@@ -93,7 +93,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
/* kill daemon */
|
||||
send_event(event_fd, EVENT_DIE, 0);
|
||||
/* return error */
|
||||
send_event(err_fd, EVENT_HUSER_ERR, errno);;
|
||||
send_event(err_fd, EVENT_HUSER_ERR, errno);
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
@@ -130,13 +130,13 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
/* stringify MAC into dhcp_buff */
|
||||
p = daemon->dhcp_buff;
|
||||
if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0)
|
||||
p += sprintf(p, "%.2x-", data.hwaddr_type);
|
||||
p += sprintf(p, "%.2x-", data.hwaddr_type);
|
||||
for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++)
|
||||
{
|
||||
p += sprintf(p, "%.2x", data.hwaddr[i]);
|
||||
if (i != data.hwaddr_len - 1)
|
||||
p += sprintf(p, ":");
|
||||
}
|
||||
{
|
||||
p += sprintf(p, "%.2x", data.hwaddr[i]);
|
||||
if (i != data.hwaddr_len - 1)
|
||||
p += sprintf(p, ":");
|
||||
}
|
||||
|
||||
/* and CLID into packet */
|
||||
if (!read_write(pipefd[0], buf, data.clid_len, 1))
|
||||
@@ -237,10 +237,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
if (data.hostname_len != 0)
|
||||
{
|
||||
char *dot;
|
||||
hostname = (char *)buf;
|
||||
hostname[data.hostname_len - 1] = 0;
|
||||
if (!canonicalise(hostname))
|
||||
hostname = NULL;
|
||||
else if ((dot = strchr(hostname, '.')))
|
||||
{
|
||||
my_setenv("DNSMASQ_DOMAIN", dot+1, &err);
|
||||
*dot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.action == ACTION_OLD_HOSTNAME && hostname)
|
||||
@@ -299,7 +305,15 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t size;
|
||||
unsigned int i, hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_len = 0;
|
||||
int i;
|
||||
unsigned int hostname_len = 0, clid_len = 0, vclass_len = 0, uclass_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)
|
||||
@@ -320,7 +334,7 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
{
|
||||
struct script_data *new;
|
||||
|
||||
/* start with resonable size, will almost never need extending. */
|
||||
/* start with reasonable size, will almost never need extending. */
|
||||
if (size < sizeof(struct script_data) + 200)
|
||||
size = sizeof(struct script_data) + 200;
|
||||
|
||||
@@ -378,8 +392,9 @@ 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 */
|
||||
for (i = 0; i < hostname_len; i++)
|
||||
/* 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
|
||||
|
||||
252
src/isc.c
252
src/isc.c
@@ -1,252 +0,0 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/* Code in this file is based on contributions by John Volpe. */
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_ISC_READER
|
||||
|
||||
#define MAXTOK 50
|
||||
|
||||
struct isc_lease {
|
||||
char *name, *fqdn;
|
||||
time_t expires;
|
||||
struct in_addr addr;
|
||||
struct isc_lease *next;
|
||||
};
|
||||
|
||||
static struct isc_lease *leases = NULL;
|
||||
static off_t lease_file_size = (off_t)0;
|
||||
static ino_t lease_file_inode = (ino_t)0;
|
||||
static int logged_lease = 0;
|
||||
|
||||
static int next_token (char *token, int buffsize, FILE * fp)
|
||||
{
|
||||
int c, count = 0;
|
||||
char *cp = token;
|
||||
|
||||
while((c = getc(fp)) != EOF)
|
||||
{
|
||||
if (c == '#')
|
||||
do { c = getc(fp); } while (c != '\n' && c != EOF);
|
||||
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == ';')
|
||||
{
|
||||
if (count)
|
||||
break;
|
||||
}
|
||||
else if ((c != '"') && (count<buffsize-1))
|
||||
{
|
||||
*cp++ = c;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*cp = 0;
|
||||
return count ? 1 : 0;
|
||||
}
|
||||
|
||||
void load_dhcp(time_t now)
|
||||
{
|
||||
char *hostname = daemon->namebuff;
|
||||
char token[MAXTOK], *dot;
|
||||
struct in_addr host_address;
|
||||
time_t ttd, tts;
|
||||
FILE *fp;
|
||||
struct isc_lease *lease, *tmp, **up;
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat(daemon->lease_file, &statbuf) == -1)
|
||||
{
|
||||
if (!logged_lease)
|
||||
my_syslog(LOG_WARNING, _("failed to access %s: %s"), daemon->lease_file, strerror(errno));
|
||||
logged_lease = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
logged_lease = 0;
|
||||
|
||||
if ((statbuf.st_size <= lease_file_size) &&
|
||||
(statbuf.st_ino == lease_file_inode))
|
||||
return;
|
||||
|
||||
lease_file_size = statbuf.st_size;
|
||||
lease_file_inode = statbuf.st_ino;
|
||||
|
||||
if (!(fp = fopen (daemon->lease_file, "r")))
|
||||
{
|
||||
my_syslog (LOG_ERR, _("failed to load %s: %s"), daemon->lease_file, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
my_syslog (LOG_INFO, _("reading %s"), daemon->lease_file);
|
||||
|
||||
while ((next_token(token, MAXTOK, fp)))
|
||||
{
|
||||
if (strcmp(token, "lease") == 0)
|
||||
{
|
||||
hostname[0] = '\0';
|
||||
ttd = tts = (time_t)(-1);
|
||||
if (next_token(token, MAXTOK, fp) &&
|
||||
(host_address.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
||||
{
|
||||
if (next_token(token, MAXTOK, fp) && *token == '{')
|
||||
{
|
||||
while (next_token(token, MAXTOK, fp) && *token != '}')
|
||||
{
|
||||
if ((strcmp(token, "client-hostname") == 0) ||
|
||||
(strcmp(token, "hostname") == 0))
|
||||
{
|
||||
if (next_token(hostname, MAXDNAME, fp))
|
||||
if (!canonicalise(hostname))
|
||||
{
|
||||
*hostname = 0;
|
||||
my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
|
||||
}
|
||||
}
|
||||
else if ((strcmp(token, "ends") == 0) ||
|
||||
(strcmp(token, "starts") == 0))
|
||||
{
|
||||
struct tm lease_time;
|
||||
int is_ends = (strcmp(token, "ends") == 0);
|
||||
if (next_token(token, MAXTOK, fp) && /* skip weekday */
|
||||
next_token(token, MAXTOK, fp) && /* Get date from lease file */
|
||||
sscanf (token, "%d/%d/%d",
|
||||
&lease_time.tm_year,
|
||||
&lease_time.tm_mon,
|
||||
&lease_time.tm_mday) == 3 &&
|
||||
next_token(token, MAXTOK, fp) &&
|
||||
sscanf (token, "%d:%d:%d:",
|
||||
&lease_time.tm_hour,
|
||||
&lease_time.tm_min,
|
||||
&lease_time.tm_sec) == 3)
|
||||
{
|
||||
/* There doesn't seem to be a universally available library function
|
||||
which converts broken-down _GMT_ time to seconds-in-epoch.
|
||||
The following was borrowed from ISC dhcpd sources, where
|
||||
it is noted that it might not be entirely accurate for odd seconds.
|
||||
Since we're trying to get the same answer as dhcpd, that's just
|
||||
fine here. */
|
||||
static const int months [11] = { 31, 59, 90, 120, 151, 181,
|
||||
212, 243, 273, 304, 334 };
|
||||
time_t time = ((((((365 * (lease_time.tm_year - 1970) + /* Days in years since '70 */
|
||||
(lease_time.tm_year - 1969) / 4 + /* Leap days since '70 */
|
||||
(lease_time.tm_mon > 1 /* Days in months this year */
|
||||
? months [lease_time.tm_mon - 2]
|
||||
: 0) +
|
||||
(lease_time.tm_mon > 2 && /* Leap day this year */
|
||||
!((lease_time.tm_year - 1972) & 3)) +
|
||||
lease_time.tm_mday - 1) * 24) + /* Day of month */
|
||||
lease_time.tm_hour) * 60) +
|
||||
lease_time.tm_min) * 60) + lease_time.tm_sec;
|
||||
if (is_ends)
|
||||
ttd = time;
|
||||
else
|
||||
tts = time; }
|
||||
}
|
||||
}
|
||||
|
||||
/* missing info? */
|
||||
if (!*hostname)
|
||||
continue;
|
||||
if (ttd == (time_t)(-1))
|
||||
continue;
|
||||
|
||||
/* We use 0 as infinite in ttd */
|
||||
if ((tts != -1) && (ttd == tts - 1))
|
||||
ttd = (time_t)0;
|
||||
else if (difftime(now, ttd) > 0)
|
||||
continue;
|
||||
|
||||
if ((dot = strchr(hostname, '.')))
|
||||
{
|
||||
if (!daemon->domain_suffix || hostname_isequal(dot+1, daemon->domain_suffix))
|
||||
{
|
||||
my_syslog(LOG_WARNING,
|
||||
_("Ignoring DHCP lease for %s because it has an illegal domain part"),
|
||||
hostname);
|
||||
continue;
|
||||
}
|
||||
*dot = 0;
|
||||
}
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
if (hostname_isequal(lease->name, hostname))
|
||||
{
|
||||
lease->expires = ttd;
|
||||
lease->addr = host_address;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lease && (lease = whine_malloc(sizeof(struct isc_lease))))
|
||||
{
|
||||
lease->expires = ttd;
|
||||
lease->addr = host_address;
|
||||
lease->fqdn = NULL;
|
||||
lease->next = leases;
|
||||
if (!(lease->name = whine_malloc(strlen(hostname)+1)))
|
||||
free(lease);
|
||||
else
|
||||
{
|
||||
leases = lease;
|
||||
strcpy(lease->name, hostname);
|
||||
if (daemon->domain_suffix &&
|
||||
(lease->fqdn = whine_malloc(strlen(hostname) + strlen(daemon->domain_suffix) + 2)))
|
||||
{
|
||||
strcpy(lease->fqdn, hostname);
|
||||
strcat(lease->fqdn, ".");
|
||||
strcat(lease->fqdn, daemon->domain_suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
/* prune expired leases */
|
||||
for (lease = leases, up = &leases; lease; lease = tmp)
|
||||
{
|
||||
tmp = lease->next;
|
||||
if (lease->expires != (time_t)0 && difftime(now, lease->expires) > 0)
|
||||
{
|
||||
*up = lease->next; /* unlink */
|
||||
free(lease->name);
|
||||
if (lease->fqdn)
|
||||
free(lease->fqdn);
|
||||
free(lease);
|
||||
}
|
||||
else
|
||||
up = &lease->next;
|
||||
}
|
||||
|
||||
|
||||
/* remove all existing DHCP cache entries */
|
||||
cache_unhash_dhcp();
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
{
|
||||
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
|
||||
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
128
src/lease.c
128
src/lease.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -103,7 +103,7 @@ void lease_init(time_t now)
|
||||
/* unprotect spaces */
|
||||
for (p = strchr(daemon->dhcp_buff, '*'); p; p = strchr(p, '*'))
|
||||
*p = ' ';
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0);
|
||||
}
|
||||
|
||||
/* set these correctly: the "old" events are generated later from
|
||||
@@ -151,9 +151,9 @@ void lease_update_from_configs(void)
|
||||
lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
|
||||
(config->flags & CONFIG_NAME) &&
|
||||
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
|
||||
lease_set_hostname(lease, config->hostname, daemon->domain_suffix, 1);
|
||||
lease_set_hostname(lease, config->hostname, 1);
|
||||
else if ((name = host_from_dns(lease->addr)))
|
||||
lease_set_hostname(lease, name, daemon->domain_suffix, 1); /* updates auth flag only */
|
||||
lease_set_hostname(lease, name, 1); /* updates auth flag only */
|
||||
}
|
||||
|
||||
static void ourprintf(int *errp, char *format, ...)
|
||||
@@ -254,8 +254,11 @@ void lease_update_dns(void)
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
{
|
||||
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
|
||||
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
|
||||
if (lease->fqdn)
|
||||
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
|
||||
|
||||
if (!(daemon->options & OPT_DHCP_FQDN) && lease->hostname)
|
||||
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
|
||||
}
|
||||
|
||||
dns_dirty = 0;
|
||||
@@ -412,11 +415,33 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
|
||||
}
|
||||
|
||||
void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int auth)
|
||||
static void kill_name(struct dhcp_lease *lease)
|
||||
{
|
||||
/* run script to say we lost our old name */
|
||||
|
||||
/* this shouldn't happen unless updates are very quick and the
|
||||
script very slow, we just avoid a memory leak if it does. */
|
||||
free(lease->old_hostname);
|
||||
|
||||
/* If we know the fqdn, pass that. The helper will derive the
|
||||
unqualified name from it, free the unqulaified name here. */
|
||||
|
||||
if (lease->fqdn)
|
||||
{
|
||||
lease->old_hostname = lease->fqdn;
|
||||
free(lease->hostname);
|
||||
}
|
||||
else
|
||||
lease->old_hostname = lease->hostname;
|
||||
|
||||
lease->hostname = lease->fqdn = NULL;
|
||||
}
|
||||
|
||||
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth)
|
||||
{
|
||||
struct dhcp_lease *lease_tmp;
|
||||
char *new_name = NULL, *new_fqdn = NULL;
|
||||
|
||||
|
||||
if (lease->hostname && name && hostname_isequal(lease->hostname, name))
|
||||
{
|
||||
lease->auth_name = auth;
|
||||
@@ -433,44 +458,47 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int
|
||||
|
||||
if (name)
|
||||
{
|
||||
for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
|
||||
if (lease_tmp->hostname && hostname_isequal(lease_tmp->hostname, name))
|
||||
{
|
||||
if (lease_tmp->auth_name && !auth)
|
||||
return;
|
||||
/* this shouldn't happen unless updates are very quick and the
|
||||
script very slow, we just avoid a memory leak if it does. */
|
||||
free(lease_tmp->old_hostname);
|
||||
lease_tmp->old_hostname = lease_tmp->hostname;
|
||||
lease_tmp->hostname = NULL;
|
||||
if (lease_tmp->fqdn)
|
||||
{
|
||||
new_fqdn = lease_tmp->fqdn;
|
||||
lease_tmp->fqdn = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!new_name && (new_name = whine_malloc(strlen(name) + 1)))
|
||||
strcpy(new_name, name);
|
||||
|
||||
if (suffix && !new_fqdn && (new_fqdn = whine_malloc(strlen(name) + strlen(suffix) + 2)))
|
||||
if ((new_name = whine_malloc(strlen(name) + 1)))
|
||||
{
|
||||
strcpy(new_fqdn, name);
|
||||
strcat(new_fqdn, ".");
|
||||
strcat(new_fqdn, suffix);
|
||||
char *suffix = get_domain(lease->addr);
|
||||
strcpy(new_name, name);
|
||||
if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2)))
|
||||
{
|
||||
strcpy(new_fqdn, name);
|
||||
strcat(new_fqdn, ".");
|
||||
strcat(new_fqdn, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
/* Depending on mode, we check either unqualified name or FQDN. */
|
||||
for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
|
||||
{
|
||||
if (daemon->options & OPT_DHCP_FQDN)
|
||||
{
|
||||
if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lease_tmp->auth_name && !auth)
|
||||
{
|
||||
free(new_name);
|
||||
free(new_fqdn);
|
||||
return;
|
||||
}
|
||||
|
||||
kill_name(lease_tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lease->hostname)
|
||||
{
|
||||
/* run script to say we lost our old name */
|
||||
free(lease->old_hostname);
|
||||
lease->old_hostname = lease->hostname;
|
||||
}
|
||||
kill_name(lease);
|
||||
|
||||
free(lease->fqdn);
|
||||
|
||||
lease->hostname = new_name;
|
||||
lease->fqdn = new_fqdn;
|
||||
lease->auth_name = auth;
|
||||
@@ -506,6 +534,13 @@ int do_script_run(time_t now)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
/* If we're going to be sending DBus signals, but the connection is not yet up,
|
||||
delay everything until it is. */
|
||||
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (old_leases)
|
||||
{
|
||||
lease = old_leases;
|
||||
@@ -522,13 +557,13 @@ int do_script_run(time_t now)
|
||||
}
|
||||
else
|
||||
{
|
||||
kill_name(lease);
|
||||
#ifndef NO_FORK
|
||||
queue_script(ACTION_DEL, lease, lease->hostname, now);
|
||||
queue_script(ACTION_DEL, lease, lease->old_hostname, now);
|
||||
#endif
|
||||
old_leases = lease->next;
|
||||
|
||||
free(lease->hostname);
|
||||
free(lease->fqdn);
|
||||
free(lease->old_hostname);
|
||||
free(lease->clid);
|
||||
free(lease->vendorclass);
|
||||
free(lease->userclass);
|
||||
@@ -555,7 +590,8 @@ int do_script_run(time_t now)
|
||||
(lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
|
||||
{
|
||||
#ifndef NO_FORK
|
||||
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now);
|
||||
queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease,
|
||||
lease->fqdn ? lease->fqdn : lease->hostname, now);
|
||||
#endif
|
||||
lease->new = lease->changed = lease->aux_changed = 0;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -237,7 +237,7 @@ static void nl_err(struct nlmsghdr *h)
|
||||
failing. */
|
||||
static void nl_routechange(struct nlmsghdr *h)
|
||||
{
|
||||
if (h->nlmsg_type == RTM_NEWROUTE && daemon->srv_save)
|
||||
if (h->nlmsg_type == RTM_NEWROUTE)
|
||||
{
|
||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||
int fd;
|
||||
@@ -245,17 +245,24 @@ static void nl_routechange(struct nlmsghdr *h)
|
||||
if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK)
|
||||
return;
|
||||
|
||||
if (daemon->srv_save->sfd)
|
||||
fd = daemon->srv_save->sfd->fd;
|
||||
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
||||
fd = daemon->rfd_save->fd;
|
||||
else
|
||||
return;
|
||||
/* Force re-reading resolv file right now, for luck. */
|
||||
daemon->last_resolv = 0;
|
||||
|
||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
||||
if (daemon->srv_save)
|
||||
{
|
||||
if (daemon->srv_save->sfd)
|
||||
fd = daemon->srv_save->sfd->fd;
|
||||
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
||||
fd = daemon->rfd_save->fd;
|
||||
else
|
||||
return;
|
||||
|
||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -366,8 +366,11 @@ struct listener *create_bound_listeners(void)
|
||||
{
|
||||
struct listener *listeners = NULL;
|
||||
struct irec *iface;
|
||||
int opt = 1;
|
||||
|
||||
int rc, opt = 1;
|
||||
#ifdef HAVE_IPV6
|
||||
static int dad_count = 0;
|
||||
#endif
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
{
|
||||
struct listener *new = safe_malloc(sizeof(struct listener));
|
||||
@@ -377,6 +380,7 @@ struct listener *create_bound_listeners(void)
|
||||
new->tftpfd = -1;
|
||||
new->tcpfd = -1;
|
||||
new->fd = -1;
|
||||
listeners = new;
|
||||
|
||||
if (daemon->port != 0)
|
||||
{
|
||||
@@ -396,27 +400,34 @@ struct listener *create_bound_listeners(void)
|
||||
die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
|
||||
bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
|
||||
|
||||
while(1)
|
||||
{
|
||||
if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1)
|
||||
break;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL))
|
||||
/* An interface may have an IPv6 address which is still undergoing DAD.
|
||||
If so, the bind will fail until the DAD completes, so we try over 20 seconds
|
||||
before failing. */
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) &&
|
||||
dad_count++ < DAD_WAIT)
|
||||
{
|
||||
close(new->tcpfd);
|
||||
close(new->fd);
|
||||
free(new);
|
||||
new = NULL;
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
prettyprint_addr(&iface->addr, daemon->namebuff);
|
||||
die(_("failed to bind listening socket for %s: %s"),
|
||||
daemon->namebuff, EC_BADNET);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (listen(new->tcpfd, 5) == -1)
|
||||
|
||||
if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
|
||||
{
|
||||
prettyprint_addr(&iface->addr, daemon->namebuff);
|
||||
die(_("failed to bind listening socket for %s: %s"),
|
||||
daemon->namebuff, EC_BADNET);
|
||||
}
|
||||
|
||||
if (listen(new->tcpfd, 5) == -1)
|
||||
die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
|
||||
@@ -434,15 +445,13 @@ struct listener *create_bound_listeners(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (new)
|
||||
listeners = new;
|
||||
}
|
||||
|
||||
return listeners;
|
||||
}
|
||||
|
||||
|
||||
/* return a UDP socket bound to a random port, have to coper with straying into
|
||||
/* return a UDP socket bound to a random port, have to cope with straying into
|
||||
occupied port nos and reserved ones. */
|
||||
int random_sock(int family)
|
||||
{
|
||||
@@ -451,19 +460,21 @@ int random_sock(int family)
|
||||
if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
unsigned short ports_avail = 65536u - (unsigned short)daemon->min_port;
|
||||
int i;
|
||||
unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
|
||||
int tries = ports_avail < 30 ? 3 * ports_avail : 100;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sa.sa_family = family;
|
||||
|
||||
/* don't loop forever if all ports in use. */
|
||||
|
||||
if (fix_fd(fd))
|
||||
for (i = ports_avail; i != 0; i--)
|
||||
while(tries--)
|
||||
{
|
||||
unsigned short port = rand16();
|
||||
|
||||
if (daemon->min_port != 0)
|
||||
port = htons(daemon->min_port + (port % ports_avail));
|
||||
port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
|
||||
|
||||
if (family == AF_INET)
|
||||
{
|
||||
@@ -517,7 +528,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
||||
return 0;
|
||||
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
if (strlen(intname) != 0 &&
|
||||
if (intname[0] != 0 &&
|
||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, sizeof(intname)) == -1)
|
||||
return 0;
|
||||
#endif
|
||||
@@ -532,7 +543,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
|
||||
/* when using random ports, servers which would otherwise use
|
||||
the INADDR_ANY/port0 socket have sfd set to NULL */
|
||||
if (!daemon->osport)
|
||||
if (!daemon->osport && intname[0] == 0)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
@@ -618,7 +629,7 @@ void pre_allocate_sfds(void)
|
||||
(daemon->options & OPT_NOWILD))
|
||||
{
|
||||
prettyprint_addr(&srv->addr, daemon->namebuff);
|
||||
if (strlen(srv->interface) != 0)
|
||||
if (srv->interface[0] != 0)
|
||||
{
|
||||
strcat(daemon->namebuff, " ");
|
||||
strcat(daemon->namebuff, srv->interface);
|
||||
@@ -693,7 +704,7 @@ void check_servers(void)
|
||||
else if (!(new->flags & SERV_LITERAL_ADDRESS))
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
|
||||
}
|
||||
else if (strlen(new->interface) != 0)
|
||||
else if (new->interface[0] != 0)
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
|
||||
|
||||
325
src/option.c
325
src/option.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* define this to get facilitynames */
|
||||
@@ -60,7 +60,7 @@ struct myoption {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define OPTSTRING "9531yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:"
|
||||
#define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
|
||||
|
||||
/* options which don't have a one-char version */
|
||||
#define LOPT_RELOAD 256
|
||||
@@ -96,6 +96,8 @@ struct myoption {
|
||||
#define LOPT_LOCAL 286
|
||||
#define LOPT_NAPTR 287
|
||||
#define LOPT_MINPORT 288
|
||||
#define LOPT_DHCP_FQDN 289
|
||||
#define LOPT_CNAME 290
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -160,7 +162,7 @@ static const struct myoption opts[] =
|
||||
{"localise-queries", 0, 0, 'y'},
|
||||
{"txt-record", 1, 0, 'Y'},
|
||||
{"enable-dbus", 0, 0, '1'},
|
||||
{"bootp-dynamic", 0, 0, '3'},
|
||||
{"bootp-dynamic", 2, 0, '3'},
|
||||
{"dhcp-mac", 1, 0, '4'},
|
||||
{"no-ping", 0, 0, '5'},
|
||||
{"dhcp-script", 1, 0, '6'},
|
||||
@@ -200,6 +202,8 @@ static const struct myoption opts[] =
|
||||
{"dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
|
||||
{"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
|
||||
{"min-port", 1, 0, LOPT_MINPORT },
|
||||
{"dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
|
||||
{"cname", 1, 0, LOPT_CNAME },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -240,8 +244,8 @@ static struct {
|
||||
{ LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
|
||||
{ LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
|
||||
{ LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
|
||||
{ 'J', ARG_DUP, "<tag>", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
|
||||
{ LOPT_BROADCAST, ARG_DUP, "<tag>", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
|
||||
{ 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
|
||||
{ LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
|
||||
{ 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
|
||||
{ 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
|
||||
{ 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
|
||||
@@ -261,7 +265,7 @@ static struct {
|
||||
{ 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
|
||||
{ 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
|
||||
{ LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
|
||||
{ 's', ARG_ONE, "<domain>", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
|
||||
{ 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
|
||||
{ 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
|
||||
{ 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
|
||||
{ LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
|
||||
@@ -281,7 +285,7 @@ static struct {
|
||||
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
|
||||
{ '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
|
||||
{ '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ '3', OPT_BOOTP_DYNAMIC, NULL, gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
#ifdef HAVE_BSD_BRIDGE
|
||||
{ LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
|
||||
@@ -293,7 +297,7 @@ static struct {
|
||||
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
|
||||
{ '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
|
||||
{ LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
|
||||
{ LOPT_NO_NAMES, ARG_DUP, "[=<id>]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
|
||||
{ LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
|
||||
{ LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
|
||||
{ LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
|
||||
{ LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
|
||||
@@ -306,11 +310,13 @@ static struct {
|
||||
{ LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
|
||||
{ LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
|
||||
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
|
||||
{ LOPT_MATCH, ARG_DUP, "<netid>,<opt-no>", gettext_noop("Set tag if client includes option in request."), NULL },
|
||||
{ LOPT_MATCH, ARG_DUP, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
|
||||
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
|
||||
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
|
||||
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
|
||||
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
|
||||
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
|
||||
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -373,8 +379,8 @@ static const struct {
|
||||
{ "T2", 59, OT_INTERNAL },
|
||||
{ "vendor-class", 60, 0 },
|
||||
{ "client-id", 61,OT_INTERNAL },
|
||||
{ "nis-domain", 64, 0 },
|
||||
{ "nis-server", 65, OT_ADDR_LIST },
|
||||
{ "nis+-domain", 64, 0 },
|
||||
{ "nis+-server", 65, OT_ADDR_LIST },
|
||||
{ "tftp-server", 66, 0 },
|
||||
{ "bootfile-name", 67, 0 },
|
||||
{ "mobile-ip-home", 68, OT_ADDR_LIST },
|
||||
@@ -385,6 +391,9 @@ static const struct {
|
||||
{ "user-class", 77, 0 },
|
||||
{ "FQDN", 81, OT_INTERNAL },
|
||||
{ "agent-id", 82, OT_INTERNAL },
|
||||
{ "client-arch", 93, 2 },
|
||||
{ "client-interface-id", 94, 0 },
|
||||
{ "client-machine-id", 97, 0 },
|
||||
{ "subnet-select", 118, OT_INTERNAL },
|
||||
{ "domain-search", 119, 0 },
|
||||
{ "sip-server", 120, 0 },
|
||||
@@ -485,11 +494,12 @@ static char *opt_string_alloc(char *cp)
|
||||
|
||||
/* find next comma, split string with zero and eliminate spaces.
|
||||
return start of string following comma */
|
||||
static char *split(char *s)
|
||||
|
||||
static char *split_chr(char *s, char c)
|
||||
{
|
||||
char *comma, *p;
|
||||
|
||||
if (!s || !(comma = strchr(s, ',')))
|
||||
if (!s || !(comma = strchr(s, c)))
|
||||
return NULL;
|
||||
|
||||
p = comma;
|
||||
@@ -503,6 +513,11 @@ static char *split(char *s)
|
||||
return comma;
|
||||
}
|
||||
|
||||
static char *split(char *s)
|
||||
{
|
||||
return split_chr(s, ',');
|
||||
}
|
||||
|
||||
static int canonicalise_opt(char *s)
|
||||
{
|
||||
if (!s)
|
||||
@@ -529,6 +544,16 @@ static int atoi_check(char *a, int *res)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int atoi_check16(char *a, int *res)
|
||||
{
|
||||
if (!(atoi_check(a, res)) ||
|
||||
*res < 0 ||
|
||||
*res > 0xffff)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void add_txt(char *name, char *txt)
|
||||
{
|
||||
size_t len = strlen(txt);
|
||||
@@ -626,7 +651,6 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
new->flags = flags;
|
||||
new->netid = NULL;
|
||||
new->val = NULL;
|
||||
new->vendor_class = NULL;
|
||||
new->opt = 0;
|
||||
|
||||
while (arg)
|
||||
@@ -659,7 +683,12 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
}
|
||||
else if (strstr(arg, "vendor:") == arg)
|
||||
{
|
||||
new->vendor_class = (unsigned char *)opt_string_alloc(arg+7);
|
||||
new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
|
||||
new->flags |= DHOPT_VENDOR;
|
||||
}
|
||||
else if (strstr(arg, "encap:") == arg)
|
||||
{
|
||||
new->u.encap = atoi(arg+6);
|
||||
new->flags |= DHOPT_ENCAPSULATE;
|
||||
}
|
||||
else
|
||||
@@ -724,7 +753,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
else
|
||||
is_dec = 0;
|
||||
if (!((c >='A' && c <= 'F') ||
|
||||
(c >='a' && c <= 'f')))
|
||||
(c >='a' && c <= 'f') ||
|
||||
(c == '*' && (flags & DHOPT_MATCH))))
|
||||
is_hex = 0;
|
||||
}
|
||||
|
||||
@@ -741,7 +771,8 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
{
|
||||
new->len = digs;
|
||||
new->val = opt_malloc(new->len);
|
||||
parse_hex(comma, new->val, digs, NULL, NULL);
|
||||
parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
|
||||
new->flags |= DHOPT_HEX;
|
||||
}
|
||||
else if (is_dec)
|
||||
{
|
||||
@@ -788,8 +819,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
{
|
||||
cp = comma;
|
||||
comma = split(cp);
|
||||
if ((slash = strchr(cp, '/')))
|
||||
*slash++ = 0;
|
||||
slash = split_chr(cp, '/');
|
||||
in.s_addr = inet_addr(cp);
|
||||
if (!slash)
|
||||
{
|
||||
@@ -894,8 +924,23 @@ static char *parse_dhcp_opt(char *arg, int flags)
|
||||
|
||||
if (!problem)
|
||||
{
|
||||
new->next = daemon->dhcp_opts;
|
||||
daemon->dhcp_opts = new;
|
||||
if (flags == DHOPT_MATCH)
|
||||
{
|
||||
if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
|
||||
!new->netid ||
|
||||
new->netid->next)
|
||||
problem = _("illegal dhcp-match");
|
||||
else
|
||||
{
|
||||
new->next = daemon->dhcp_match;
|
||||
daemon->dhcp_match = new;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new->next = daemon->dhcp_opts;
|
||||
daemon->dhcp_opts = new;
|
||||
}
|
||||
}
|
||||
|
||||
return problem;
|
||||
@@ -947,7 +992,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
char *file = opt_string_alloc(arg);
|
||||
if (file)
|
||||
one_file(file, nest, 0);
|
||||
{
|
||||
one_file(file, nest, 0);
|
||||
free(file);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -991,6 +1039,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
}
|
||||
|
||||
closedir(dir_stream);
|
||||
free(directory);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1067,7 +1116,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if ((comma = split(arg)))
|
||||
{
|
||||
char *prefstr;
|
||||
if ((prefstr=split(comma)) && !atoi_check(prefstr, &pref))
|
||||
if ((prefstr=split(comma)) && !atoi_check16(prefstr, &pref))
|
||||
problem = _("bad MX preference");
|
||||
}
|
||||
|
||||
@@ -1117,10 +1166,48 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case 's': /* --domain */
|
||||
if (strcmp (arg, "#") == 0)
|
||||
daemon->options |= OPT_RESOLV_DOMAIN;
|
||||
else if (!canonicalise_opt(arg))
|
||||
option = '?';
|
||||
else
|
||||
daemon->domain_suffix = opt_string_alloc(arg);
|
||||
{
|
||||
comma = split(arg);
|
||||
if (!canonicalise_opt(arg))
|
||||
option = '?';
|
||||
else
|
||||
{
|
||||
char *d = opt_string_alloc(arg);
|
||||
if (comma)
|
||||
{
|
||||
struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
|
||||
unhide_metas(comma);
|
||||
if ((arg = split_chr(comma, '/')))
|
||||
{
|
||||
int mask;
|
||||
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
|
||||
!atoi_check(arg, &mask))
|
||||
option = '?';
|
||||
else
|
||||
{
|
||||
mask = (1 << (32 - mask)) - 1;
|
||||
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
|
||||
new->end.s_addr = new->start.s_addr | htonl(mask);
|
||||
}
|
||||
}
|
||||
else if ((arg = split(comma)))
|
||||
{
|
||||
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
|
||||
(new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
}
|
||||
else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
|
||||
new->domain = d;
|
||||
new->next = daemon->cond_domain;
|
||||
daemon->cond_domain = new;
|
||||
}
|
||||
else
|
||||
daemon->domain_suffix = d;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u': /* --user */
|
||||
@@ -1233,10 +1320,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
char *end;
|
||||
arg++;
|
||||
while ((end = strchr(arg, '/')))
|
||||
while ((end = split_chr(arg, '/')))
|
||||
{
|
||||
char *domain = NULL;
|
||||
*end = 0;
|
||||
/* # matches everything and becomes a zero length domain string */
|
||||
if (strcmp(arg, "#") == 0)
|
||||
domain = "";
|
||||
@@ -1250,7 +1336,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
newlist = serv;
|
||||
serv->domain = domain;
|
||||
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
|
||||
arg = end+1;
|
||||
arg = end;
|
||||
}
|
||||
if (!newlist)
|
||||
{
|
||||
@@ -1283,23 +1369,14 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||
char *portno, *source;
|
||||
|
||||
if ((source = strchr(arg, '@'))) /* is there a source. */
|
||||
{
|
||||
*source = 0;
|
||||
if ((portno = strchr(source+1, '#')))
|
||||
{
|
||||
*portno = 0;
|
||||
if (!atoi_check(portno+1, &source_port))
|
||||
problem = _("bad port");
|
||||
}
|
||||
}
|
||||
|
||||
if ((portno = strchr(arg, '#'))) /* is there a port no. */
|
||||
{
|
||||
*portno = 0;
|
||||
if (!atoi_check(portno+1, &serv_port))
|
||||
problem = _("bad port");
|
||||
}
|
||||
if ((source = split_chr(arg, '@')) && /* is there a source. */
|
||||
(portno = split_chr(source, '#')) &&
|
||||
!atoi_check16(portno, &source_port))
|
||||
problem = _("bad port");
|
||||
|
||||
if ((portno = split_chr(arg, '#')) && /* is there a port no. */
|
||||
!atoi_check16(portno, &serv_port))
|
||||
problem = _("bad port");
|
||||
|
||||
if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
|
||||
{
|
||||
@@ -1312,11 +1389,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if (source)
|
||||
{
|
||||
newlist->flags |= SERV_HAS_SOURCE;
|
||||
if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source+1)) == (in_addr_t) -1)
|
||||
if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
strncpy(newlist->interface, source+1, IF_NAMESIZE);
|
||||
strncpy(newlist->interface, source, IF_NAMESIZE);
|
||||
#else
|
||||
problem = _("interface binding not supported");
|
||||
#endif
|
||||
@@ -1337,11 +1414,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
if (source)
|
||||
{
|
||||
newlist->flags |= SERV_HAS_SOURCE;
|
||||
if (inet_pton(AF_INET6, source+1, &newlist->source_addr.in6.sin6_addr) == 0)
|
||||
if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE) || defined(HAVE_SOLARIS_NETWORK)
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
newlist->source_addr.in6.sin6_addr = in6addr_any;
|
||||
strncpy(newlist->interface, source+1, IF_NAMESIZE);
|
||||
strncpy(newlist->interface, source, IF_NAMESIZE);
|
||||
#else
|
||||
problem = _("interface binding not supported");
|
||||
#endif
|
||||
@@ -1390,12 +1467,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
}
|
||||
|
||||
case 'p': /* --port */
|
||||
if (!atoi_check(arg, &daemon->port))
|
||||
if (!atoi_check16(arg, &daemon->port))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
case LOPT_MINPORT: /* --min-port */
|
||||
if (!atoi_check(arg, &daemon->min_port))
|
||||
if (!atoi_check16(arg, &daemon->min_port))
|
||||
option = '?';
|
||||
break;
|
||||
|
||||
@@ -1422,7 +1499,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
}
|
||||
|
||||
case 'Q': /* --query-port */
|
||||
if (!atoi_check(arg, &daemon->query_port))
|
||||
if (!atoi_check16(arg, &daemon->query_port))
|
||||
option = '?';
|
||||
/* if explicitly set to zero, use single OS ephemeral port
|
||||
and disable random ports */
|
||||
@@ -1459,8 +1536,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
case LOPT_TFTPPORTS: /* --tftp-port-range */
|
||||
if (!(comma = split(arg)) ||
|
||||
!atoi_check(arg, &daemon->start_tftp_port) ||
|
||||
!atoi_check(comma, &daemon->end_tftp_port))
|
||||
!atoi_check16(arg, &daemon->start_tftp_port) ||
|
||||
!atoi_check16(comma, &daemon->end_tftp_port))
|
||||
problem = _("bad port range");
|
||||
|
||||
if (daemon->start_tftp_port > daemon->end_tftp_port)
|
||||
@@ -1646,7 +1723,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new = opt_malloc(sizeof(struct dhcp_config));
|
||||
|
||||
new->next = daemon->dhcp_conf;
|
||||
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
|
||||
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
|
||||
new->hwaddr = NULL;
|
||||
|
||||
if ((a[0] = arg))
|
||||
for (k = 1; k < 6; k++)
|
||||
@@ -1696,8 +1774,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
}
|
||||
else
|
||||
{
|
||||
new->hwaddr_len = parse_hex(a[j], new->hwaddr, DHCP_CHADDR_MAX, &new->wildcard_mask, &new->hwaddr_type);
|
||||
new->flags |= CONFIG_HWADDR;
|
||||
struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
|
||||
newhw->next = new->hwaddr;
|
||||
new->hwaddr = newhw;
|
||||
newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
|
||||
&newhw->wildcard_mask, &newhw->hwaddr_type);
|
||||
}
|
||||
}
|
||||
else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
|
||||
@@ -1758,6 +1839,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
new->flags |= CONFIG_NAME;
|
||||
strcpy(new->hostname, a[j]);
|
||||
new->domain = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1776,12 +1858,14 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O':
|
||||
case LOPT_FORCE:
|
||||
case 'O': /* --dhcp-option */
|
||||
case LOPT_FORCE: /* --dhcp-option-force */
|
||||
case LOPT_OPTS:
|
||||
case LOPT_MATCH: /* --dhcp-match */
|
||||
problem = parse_dhcp_opt(arg,
|
||||
option == LOPT_FORCE ? DHOPT_FORCE :
|
||||
(option == LOPT_OPTS ? DHOPT_BANK : 0));
|
||||
(option == LOPT_MATCH ? DHOPT_MATCH :
|
||||
(option == LOPT_OPTS ? DHOPT_BANK : 0)));
|
||||
break;
|
||||
|
||||
case 'M': /* --dhcp-boot */
|
||||
@@ -1840,7 +1924,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
else
|
||||
{
|
||||
struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
|
||||
new->netid.net = opt_string_alloc(arg);
|
||||
if (strstr(arg, "net:") == arg)
|
||||
new->netid.net = opt_string_alloc(arg+4);
|
||||
else
|
||||
new->netid.net = opt_string_alloc(arg);
|
||||
unhide_metas(comma);
|
||||
new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
|
||||
new->next = daemon->dhcp_macs;
|
||||
@@ -1854,7 +1941,6 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case LOPT_CIRCUIT: /* --dhcp-circuitid */
|
||||
case LOPT_REMOTE: /* --dhcp-remoteid */
|
||||
case LOPT_SUBSCR: /* --dhcp-subscrid */
|
||||
case LOPT_MATCH: /* --dhcp-match */
|
||||
{
|
||||
if (!(comma = split(arg)))
|
||||
option = '?';
|
||||
@@ -1863,7 +1949,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
char *p;
|
||||
int dig = 0;
|
||||
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
|
||||
new->netid.net = opt_string_alloc(arg);
|
||||
if (strstr(arg, "net:") == arg)
|
||||
new->netid.net = opt_string_alloc(arg+4);
|
||||
else
|
||||
new->netid.net = opt_string_alloc(arg);
|
||||
/* check for hex string - must digits may include : must not have nothing else,
|
||||
only allowed for agent-options. */
|
||||
for (p = comma; *p; p++)
|
||||
@@ -1872,9 +1961,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
else if (*p != ':')
|
||||
break;
|
||||
unhide_metas(comma);
|
||||
if (option == LOPT_MATCH)
|
||||
new->option = atoi(comma);
|
||||
else if (option == 'U' || option == 'j' || *p || !dig)
|
||||
if (option == 'U' || option == 'j' || *p || !dig)
|
||||
{
|
||||
new->len = strlen(comma);
|
||||
new->data = opt_malloc(new->len);
|
||||
@@ -1904,9 +1991,6 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case LOPT_SUBSCR:
|
||||
new->match_type = MATCH_SUBSCRIBER;
|
||||
break;
|
||||
case LOPT_MATCH:
|
||||
new->match_type = MATCH_OPTION;
|
||||
break;
|
||||
}
|
||||
new->next = daemon->dhcp_vendors;
|
||||
daemon->dhcp_vendors = new;
|
||||
@@ -1923,8 +2007,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
else
|
||||
{
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &daemon->dhcp_server_port) ||
|
||||
(comma && !atoi_check(comma, &daemon->dhcp_client_port)))
|
||||
if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
|
||||
(comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
|
||||
problem = _("invalid port number");
|
||||
if (!comma)
|
||||
daemon->dhcp_client_port = daemon->dhcp_server_port+1;
|
||||
@@ -1934,6 +2018,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
case 'J': /* --dhcp-ignore */
|
||||
case LOPT_NO_NAMES: /* --dhcp-ignore-names */
|
||||
case LOPT_BROADCAST: /* --dhcp-broadcast */
|
||||
case '3': /* --bootp-dynamic */
|
||||
{
|
||||
struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
|
||||
struct dhcp_netid *list = NULL;
|
||||
@@ -1947,6 +2032,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new->next = daemon->force_broadcast;
|
||||
daemon->force_broadcast = new;
|
||||
}
|
||||
else if (option == '3')
|
||||
{
|
||||
new->next = daemon->bootp_dynamic;
|
||||
daemon->bootp_dynamic = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
new->next = daemon->dhcp_ignore_names;
|
||||
@@ -1958,7 +2048,10 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
comma = split(arg);
|
||||
member->next = list;
|
||||
list = member;
|
||||
member->net = opt_string_alloc(arg);
|
||||
if (strstr(arg, "net:") == arg)
|
||||
member->net = opt_string_alloc(arg+4);
|
||||
else
|
||||
member->net = opt_string_alloc(arg);
|
||||
arg = comma;
|
||||
}
|
||||
|
||||
@@ -1968,13 +2061,14 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
case 'V': /* --alias */
|
||||
{
|
||||
char *a[3] = { NULL, NULL, NULL };
|
||||
char *dash, *a[3] = { NULL, NULL, NULL };
|
||||
int k = 0;
|
||||
struct in_addr in, out, mask;
|
||||
struct doctor *new;
|
||||
|
||||
mask.s_addr = 0xffffffff;
|
||||
|
||||
struct doctor *new = opt_malloc(sizeof(struct doctor));
|
||||
new->next = daemon->doctors;
|
||||
daemon->doctors = new;
|
||||
new->mask.s_addr = 0xffffffff;
|
||||
new->end.s_addr = 0;
|
||||
|
||||
if ((a[0] = arg))
|
||||
for (k = 1; k < 3; k++)
|
||||
{
|
||||
@@ -1983,23 +2077,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
unhide_metas(a[k]);
|
||||
}
|
||||
|
||||
dash = split_chr(a[0], '-');
|
||||
|
||||
if ((k < 2) ||
|
||||
((in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
||||
((out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
||||
{
|
||||
option = '?';
|
||||
break;
|
||||
}
|
||||
((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
||||
((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
||||
option = '?';
|
||||
|
||||
if (k == 3)
|
||||
mask.s_addr = inet_addr(a[2]);
|
||||
new->mask.s_addr = inet_addr(a[2]);
|
||||
|
||||
new = opt_malloc(sizeof(struct doctor));
|
||||
new->in = in;
|
||||
new->out = out;
|
||||
new->mask = mask;
|
||||
new->next = daemon->doctors;
|
||||
daemon->doctors = new;
|
||||
if (dash &&
|
||||
((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
|
||||
!is_same_net(new->in, new->end, new->mask) ||
|
||||
ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
|
||||
problem = _("invalid alias range");
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2023,6 +2115,26 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
new->intr = opt_string_alloc(comma);
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_CNAME: /* --cname */
|
||||
{
|
||||
struct cname *new;
|
||||
|
||||
if (!(comma = split(arg)))
|
||||
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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_PTR: /* --ptr-record */
|
||||
{
|
||||
@@ -2058,8 +2170,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
|
||||
if (k < 6 ||
|
||||
!canonicalise_opt(a[0]) ||
|
||||
!atoi_check(a[1], &order) ||
|
||||
!atoi_check(a[2], &pref) ||
|
||||
!atoi_check16(a[1], &order) ||
|
||||
!atoi_check16(a[2], &pref) ||
|
||||
(k == 7 && !canonicalise_opt(a[6])))
|
||||
problem = _("bad NAPTR record");
|
||||
else
|
||||
@@ -2167,21 +2279,21 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &port))
|
||||
if (!atoi_check16(arg, &port))
|
||||
problem = _("invalid port number");
|
||||
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &priority))
|
||||
if (!atoi_check16(arg, &priority))
|
||||
problem = _("invalid priority");
|
||||
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &weight))
|
||||
if (!atoi_check16(arg, &weight))
|
||||
problem = _("invalid weight");
|
||||
}
|
||||
}
|
||||
@@ -2377,6 +2489,13 @@ void reread_dhcp(void)
|
||||
|
||||
if (configs->flags & CONFIG_BANK)
|
||||
{
|
||||
struct hwaddr_config *mac, *tmp;
|
||||
|
||||
for (mac = configs->hwaddr; mac; mac = tmp)
|
||||
{
|
||||
tmp = mac->next;
|
||||
free(mac);
|
||||
}
|
||||
if (configs->flags & CONFIG_CLID)
|
||||
free(configs->clid);
|
||||
if (configs->flags & CONFIG_NETID)
|
||||
@@ -2384,6 +2503,7 @@ void reread_dhcp(void)
|
||||
if (configs->flags & CONFIG_NAME)
|
||||
free(configs->hostname);
|
||||
|
||||
|
||||
*up = configs->next;
|
||||
free(configs);
|
||||
}
|
||||
@@ -2406,7 +2526,8 @@ void reread_dhcp(void)
|
||||
|
||||
if (opts->flags & DHOPT_BANK)
|
||||
{
|
||||
free(opts->vendor_class);
|
||||
if ((opts->flags & DHOPT_VENDOR))
|
||||
free(opts->u.vendor_class);
|
||||
free(opts->val);
|
||||
for (id = opts->netid; id; id = next)
|
||||
{
|
||||
@@ -2629,4 +2750,6 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
srv->name = opt_string_alloc(buff);
|
||||
}
|
||||
}
|
||||
else if (daemon->options & OPT_DHCP_FQDN)
|
||||
die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
|
||||
}
|
||||
|
||||
275
src/rfc1035.c
275
src/rfc1035.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -21,8 +21,14 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp,
|
||||
unsigned long ttl, unsigned int *offset, unsigned short type,
|
||||
unsigned short class, char *format, ...);
|
||||
|
||||
#define CHECK_LEN(header, pp, plen, len) \
|
||||
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
||||
|
||||
#define ADD_RDLEN(header, pp, plen, len) \
|
||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1)
|
||||
|
||||
static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
char *name, int isExtract)
|
||||
char *name, int isExtract, int extrabytes)
|
||||
{
|
||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||
unsigned int j, l, hops = 0;
|
||||
@@ -31,19 +37,47 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
if (isExtract)
|
||||
*cp = 0;
|
||||
|
||||
while ((l = *p++))
|
||||
{
|
||||
unsigned int label_type = l & 0xc0;
|
||||
while (1)
|
||||
{
|
||||
unsigned int label_type;
|
||||
|
||||
if (!CHECK_LEN(header, p, plen, 1))
|
||||
return 0;
|
||||
|
||||
if ((l = *p++) == 0)
|
||||
/* end marker */
|
||||
{
|
||||
/* check that there are the correct no of bytes after the name */
|
||||
if (!CHECK_LEN(header, p, plen, extrabytes))
|
||||
return 0;
|
||||
|
||||
if (isExtract)
|
||||
{
|
||||
if (cp != (unsigned char *)name)
|
||||
cp--;
|
||||
*cp = 0; /* terminate: lose final period */
|
||||
}
|
||||
else if (*cp != 0)
|
||||
retvalue = 2;
|
||||
|
||||
if (p1) /* we jumped via compression */
|
||||
*pp = p1;
|
||||
else
|
||||
*pp = p;
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
label_type = l & 0xc0;
|
||||
|
||||
if (label_type == 0xc0) /* pointer */
|
||||
{
|
||||
if ((size_t)(p - (unsigned char *)header) >= plen)
|
||||
if (!CHECK_LEN(header, p, plen, 1))
|
||||
return 0;
|
||||
|
||||
/* get offset */
|
||||
l = (l&0x3f) << 8;
|
||||
l |= *p++;
|
||||
if (l >= plen)
|
||||
return 0;
|
||||
|
||||
if (!p1) /* first jump, save location to go back to */
|
||||
p1 = p;
|
||||
@@ -74,7 +108,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
/* output is \[x<hex>/siz]. which is digs+9 chars */
|
||||
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
|
||||
return 0;
|
||||
if ((size_t)(p - (unsigned char *)header + ((count-1)>>3)) >= plen)
|
||||
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
|
||||
return 0;
|
||||
|
||||
*cp++ = '\\';
|
||||
@@ -98,8 +132,9 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
{ /* label_type = 0 -> label. */
|
||||
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
|
||||
return 0;
|
||||
if ((size_t)(p - (unsigned char *)header) >= plen)
|
||||
if (!CHECK_LEN(header, p, plen, l))
|
||||
return 0;
|
||||
|
||||
for(j=0; j<l; j++, p++)
|
||||
if (isExtract)
|
||||
{
|
||||
@@ -132,26 +167,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
else if (*cp != 0 && *cp++ != '.')
|
||||
retvalue = 2;
|
||||
}
|
||||
|
||||
if ((unsigned int)(p - (unsigned char *)header) >= plen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isExtract)
|
||||
{
|
||||
if (cp != (unsigned char *)name)
|
||||
cp--;
|
||||
*cp = 0; /* terminate: lose final period */
|
||||
}
|
||||
else if (*cp != 0)
|
||||
retvalue = 2;
|
||||
|
||||
if (p1) /* we jumped via compression */
|
||||
*pp = p1;
|
||||
else
|
||||
*pp = p;
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
/* Max size of input string (for IPv6) is 75 chars.) */
|
||||
@@ -261,15 +277,17 @@ static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen)
|
||||
static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen, int extrabytes)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
unsigned int label_type = (*ansp) & 0xc0;
|
||||
unsigned int label_type;
|
||||
|
||||
if ((unsigned int)(ansp - (unsigned char *)header) >= plen)
|
||||
if (!CHECK_LEN(header, ansp, plen, 1))
|
||||
return NULL;
|
||||
|
||||
label_type = (*ansp) & 0xc0;
|
||||
|
||||
if (label_type == 0xc0)
|
||||
{
|
||||
/* pointer for compression. */
|
||||
@@ -283,6 +301,9 @@ static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen
|
||||
/* Extended label type */
|
||||
unsigned int count;
|
||||
|
||||
if (!CHECK_LEN(header, ansp, plen, 2))
|
||||
return NULL;
|
||||
|
||||
if (((*ansp++) & 0x3f) != 1)
|
||||
return NULL; /* we only understand bitstrings */
|
||||
|
||||
@@ -296,12 +317,17 @@ static unsigned char *skip_name(unsigned char *ansp, HEADER *header, size_t plen
|
||||
else
|
||||
{ /* label type == 0 Bottom six bits is length */
|
||||
unsigned int len = (*ansp++) & 0x3f;
|
||||
|
||||
if (!ADD_RDLEN(header, ansp, plen, len))
|
||||
return NULL;
|
||||
|
||||
if (len == 0)
|
||||
break; /* zero length label marks the end. */
|
||||
|
||||
ansp += len;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CHECK_LEN(header, ansp, plen, extrabytes))
|
||||
return NULL;
|
||||
|
||||
return ansp;
|
||||
}
|
||||
@@ -313,12 +339,10 @@ static unsigned char *skip_questions(HEADER *header, size_t plen)
|
||||
|
||||
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
{
|
||||
if (!(ansp = skip_name(ansp, header, plen)))
|
||||
if (!(ansp = skip_name(ansp, header, plen, 4)))
|
||||
return NULL;
|
||||
ansp += 4; /* class and type */
|
||||
}
|
||||
if ((unsigned int)(ansp - (unsigned char *)header) > plen)
|
||||
return NULL;
|
||||
|
||||
return ansp;
|
||||
}
|
||||
@@ -329,13 +353,12 @@ static unsigned char *skip_section(unsigned char *ansp, int count, HEADER *heade
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (!(ansp = skip_name(ansp, header, plen)))
|
||||
if (!(ansp = skip_name(ansp, header, plen, 10)))
|
||||
return NULL;
|
||||
ansp += 8; /* type, class, TTL */
|
||||
GETSHORT(rdlen, ansp);
|
||||
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
|
||||
if (!ADD_RDLEN(header, ansp, plen, rdlen))
|
||||
return NULL;
|
||||
ansp += rdlen;
|
||||
}
|
||||
|
||||
return ansp;
|
||||
@@ -355,7 +378,7 @@ unsigned int questions_crc(HEADER *header, size_t plen, char *name)
|
||||
|
||||
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
{
|
||||
if (!extract_name(header, plen, &p, name, 1))
|
||||
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
return crc; /* bad packet */
|
||||
|
||||
for (p1 = (unsigned char *)name; *p1; p1++)
|
||||
@@ -381,7 +404,7 @@ unsigned int questions_crc(HEADER *header, size_t plen, char *name)
|
||||
}
|
||||
|
||||
p += 4;
|
||||
if ((unsigned int)(p - (unsigned char *)header) > plen)
|
||||
if (!CHECK_LEN(header, p, plen, 0))
|
||||
return crc; /* bad packet */
|
||||
}
|
||||
|
||||
@@ -393,12 +416,13 @@ size_t resize_packet(HEADER *header, size_t plen, unsigned char *pheader, size_t
|
||||
{
|
||||
unsigned char *ansp = skip_questions(header, plen);
|
||||
|
||||
/* if packet is malformed, just return as-is. */
|
||||
if (!ansp)
|
||||
return 0;
|
||||
return plen;
|
||||
|
||||
if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||
header, plen)))
|
||||
return 0;
|
||||
return plen;
|
||||
|
||||
/* restore pseudoheader */
|
||||
if (pheader && ntohs(header->arcount) == 0)
|
||||
@@ -432,7 +456,7 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
|
||||
{
|
||||
for (i = ntohs(header->qdcount); i != 0; i--)
|
||||
{
|
||||
if (!(ansp = skip_name(ansp, header, plen)))
|
||||
if (!(ansp = skip_name(ansp, header, plen, 4)))
|
||||
return NULL;
|
||||
|
||||
GETSHORT(type, ansp);
|
||||
@@ -458,7 +482,7 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
|
||||
for (i = 0; i < arcount; i++)
|
||||
{
|
||||
unsigned char *save, *start = ansp;
|
||||
if (!(ansp = skip_name(ansp, header, plen)))
|
||||
if (!(ansp = skip_name(ansp, header, plen, 10)))
|
||||
return NULL;
|
||||
|
||||
GETSHORT(type, ansp);
|
||||
@@ -466,9 +490,8 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
|
||||
GETSHORT(class, ansp);
|
||||
ansp += 4; /* TTL */
|
||||
GETSHORT(rdlen, ansp);
|
||||
if ((size_t)(ansp + rdlen - (unsigned char *)header) > plen)
|
||||
if (!ADD_RDLEN(header, ansp, plen, rdlen))
|
||||
return NULL;
|
||||
ansp += rdlen;
|
||||
if (type == T_OPT)
|
||||
{
|
||||
if (len)
|
||||
@@ -508,7 +531,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
|
||||
|
||||
for (i = count; i != 0; i--)
|
||||
{
|
||||
if (!(p = skip_name(p, header, qlen)))
|
||||
if (!(p = skip_name(p, header, qlen, 10)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
@@ -521,25 +544,34 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
|
||||
struct doctor *doctor;
|
||||
struct in_addr addr;
|
||||
|
||||
/* alignment */
|
||||
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
|
||||
return 0;
|
||||
|
||||
/* alignment */
|
||||
memcpy(&addr, p, INADDRSZ);
|
||||
|
||||
for (doctor = daemon->doctors; doctor; doctor = doctor->next)
|
||||
if (is_same_net(doctor->in, addr, doctor->mask))
|
||||
{
|
||||
addr.s_addr &= ~doctor->mask.s_addr;
|
||||
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
||||
/* Since we munged the data, the server it came from is no longer authoritative */
|
||||
header->aa = 0;
|
||||
memcpy(p, &addr, INADDRSZ);
|
||||
break;
|
||||
}
|
||||
{
|
||||
if (doctor->end.s_addr == 0)
|
||||
{
|
||||
if (!is_same_net(doctor->in, addr, doctor->mask))
|
||||
continue;
|
||||
}
|
||||
else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
|
||||
ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
|
||||
continue;
|
||||
|
||||
addr.s_addr &= ~doctor->mask.s_addr;
|
||||
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
||||
/* Since we munged the data, the server it came from is no longer authoritative */
|
||||
header->aa = 0;
|
||||
memcpy(p, &addr, INADDRSZ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p += rdlen;
|
||||
|
||||
if ((size_t)(p - (unsigned char *)header) > qlen)
|
||||
return 0; /* bad packet */
|
||||
if (!ADD_RDLEN(header, p, qlen, rdlen))
|
||||
return 0; /* bad packet */
|
||||
}
|
||||
|
||||
return p;
|
||||
@@ -559,7 +591,7 @@ static int find_soa(HEADER *header, size_t qlen)
|
||||
|
||||
for (i = ntohs(header->nscount); i != 0; i--)
|
||||
{
|
||||
if (!(p = skip_name(p, header, qlen)))
|
||||
if (!(p = skip_name(p, header, qlen, 10)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
@@ -574,10 +606,10 @@ static int find_soa(HEADER *header, size_t qlen)
|
||||
minttl = ttl;
|
||||
|
||||
/* MNAME */
|
||||
if (!(p = skip_name(p, header, qlen)))
|
||||
if (!(p = skip_name(p, header, qlen, 0)))
|
||||
return 0;
|
||||
/* RNAME */
|
||||
if (!(p = skip_name(p, header, qlen)))
|
||||
if (!(p = skip_name(p, header, qlen, 20)))
|
||||
return 0;
|
||||
p += 16; /* SERIAL REFRESH RETRY EXPIRE */
|
||||
|
||||
@@ -585,13 +617,10 @@ static int find_soa(HEADER *header, size_t qlen)
|
||||
if (ttl < minttl)
|
||||
minttl = ttl;
|
||||
}
|
||||
else
|
||||
p += rdlen;
|
||||
|
||||
if ((size_t)(p - (unsigned char *)header) > qlen)
|
||||
else if (!ADD_RDLEN(header, p, qlen, rdlen))
|
||||
return 0; /* bad packet */
|
||||
}
|
||||
|
||||
|
||||
/* rewrite addresses in additioal section too */
|
||||
if (!do_doctor(p, ntohs(header->arcount), header, qlen))
|
||||
return 0;
|
||||
@@ -633,7 +662,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
unsigned long cttl = ULONG_MAX, attl;
|
||||
|
||||
namep = p;
|
||||
if (!extract_name(header, qlen, &p, name, 1))
|
||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
@@ -661,8 +690,8 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
{
|
||||
unsigned char *tmp = namep;
|
||||
/* the loop body overwrites the original name, so get it back here. */
|
||||
if (!extract_name(header, qlen, &tmp, name, 1) ||
|
||||
!(res = extract_name(header, qlen, &p1, name, 0)))
|
||||
if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
|
||||
!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(aqtype, p1);
|
||||
@@ -677,7 +706,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
|
||||
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
|
||||
{
|
||||
if (!extract_name(header, qlen, &p1, name, 1))
|
||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||
return 0;
|
||||
|
||||
if (aqtype == T_CNAME)
|
||||
@@ -692,7 +721,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
}
|
||||
|
||||
p1 = endrr;
|
||||
if ((size_t)(p1 - (unsigned char *)header) > qlen)
|
||||
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||
return 0; /* bad packet */
|
||||
}
|
||||
}
|
||||
@@ -737,7 +766,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
|
||||
for (j = ntohs(header->ancount); j != 0; j--)
|
||||
{
|
||||
if (!(res = extract_name(header, qlen, &p1, name, 0)))
|
||||
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(aqtype, p1);
|
||||
@@ -763,14 +792,17 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
if (attl < cttl)
|
||||
cttl = attl;
|
||||
|
||||
if (!extract_name(header, qlen, &p1, name, 1))
|
||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||
return 0;
|
||||
goto cname_loop1;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = 1;
|
||||
|
||||
/* copy address into aligned storage */
|
||||
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
||||
return 0; /* bad packet */
|
||||
memcpy(&addr, p1, addrlen);
|
||||
|
||||
/* check for returned address in private space */
|
||||
@@ -790,7 +822,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
|
||||
}
|
||||
|
||||
p1 = endrr;
|
||||
if ((size_t)(p1 - (unsigned char *)header) > qlen)
|
||||
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||
return 0; /* bad packet */
|
||||
}
|
||||
}
|
||||
@@ -839,7 +871,7 @@ unsigned short extract_request(HEADER *header, size_t qlen, char *name, unsigned
|
||||
if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
|
||||
return 0; /* must be exactly one query. */
|
||||
|
||||
if (!extract_name(header, qlen, &p, name, 1))
|
||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
@@ -953,7 +985,7 @@ int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
|
||||
|
||||
for (i = ntohs(header->ancount); i != 0; i--)
|
||||
{
|
||||
if (!extract_name(header, qlen, &p, name, 1))
|
||||
if (!extract_name(header, qlen, &p, name, 1, 10))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
@@ -962,19 +994,25 @@ int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
|
||||
GETSHORT(rdlen, p);
|
||||
|
||||
if (qclass == C_IN && qtype == T_A)
|
||||
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
|
||||
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
|
||||
{
|
||||
/* Found a bogus address. Insert that info here, since there no SOA record
|
||||
to get the ttl from in the normal processing */
|
||||
cache_start_insert();
|
||||
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
|
||||
cache_end_insert();
|
||||
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
|
||||
return 0;
|
||||
|
||||
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
|
||||
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
|
||||
{
|
||||
/* Found a bogus address. Insert that info here, since there no SOA record
|
||||
to get the ttl from in the normal processing */
|
||||
cache_start_insert();
|
||||
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
|
||||
cache_end_insert();
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
p += rdlen;
|
||||
if (!ADD_RDLEN(header, p, qlen, rdlen))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1073,6 +1111,18 @@ static int add_resource_record(HEADER *header, char *limit, int *truncp, unsigne
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned long crec_ttl(struct crec *crecp, time_t now)
|
||||
{
|
||||
/* Return 0 ttl for DHCP entries, which might change
|
||||
before the lease expires. */
|
||||
|
||||
if (crecp->flags & (F_IMMORTAL | F_DHCP))
|
||||
return daemon->local_ttl;
|
||||
|
||||
return crecp->ttd - now;
|
||||
}
|
||||
|
||||
|
||||
/* return zero if we can't answer from cache, or packet size if we can */
|
||||
size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
struct in_addr local_addr, struct in_addr local_netmask, time_t now)
|
||||
@@ -1137,7 +1187,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
nameoffset = p - (unsigned char *)header;
|
||||
|
||||
/* now extract name as .-concatenated string into name */
|
||||
if (!extract_name(header, qlen, &p, name, 1))
|
||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
@@ -1239,18 +1289,11 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
auth = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
unsigned long ttl;
|
||||
/* Return 0 ttl for DHCP entries, which might change
|
||||
before the lease expires. */
|
||||
if (crecp->flags & (F_IMMORTAL | F_DHCP))
|
||||
ttl = daemon->local_ttl;
|
||||
else
|
||||
ttl = crecp->ttd - now;
|
||||
|
||||
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
|
||||
record_source(daemon->addn_hosts, crecp->uid));
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL,
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL,
|
||||
T_PTR, C_IN, "d", cache_get_name(crecp)))
|
||||
anscount++;
|
||||
}
|
||||
@@ -1358,7 +1401,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(crecp->flags, name, NULL, record_source(daemon->addn_hosts, crecp->uid));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, crecp->ttd - now, &nameoffset,
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), &nameoffset,
|
||||
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
|
||||
anscount++;
|
||||
}
|
||||
@@ -1391,17 +1435,11 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
unsigned long ttl;
|
||||
|
||||
if (crecp->flags & (F_IMMORTAL | F_DHCP))
|
||||
ttl = daemon->local_ttl;
|
||||
else
|
||||
ttl = crecp->ttd - now;
|
||||
|
||||
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
|
||||
record_source(daemon->addn_hosts, crecp->uid));
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, type, C_IN,
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &crecp->addr))
|
||||
anscount++;
|
||||
}
|
||||
@@ -1529,7 +1567,6 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
crecp = NULL;
|
||||
while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
|
||||
{
|
||||
unsigned long ttl;
|
||||
#ifdef HAVE_IPV6
|
||||
int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
|
||||
#else
|
||||
@@ -1538,12 +1575,8 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
|
||||
if (crecp->flags & F_NEG)
|
||||
continue;
|
||||
|
||||
if (crecp->flags & (F_IMMORTAL | F_DHCP))
|
||||
ttl = daemon->local_ttl;
|
||||
else
|
||||
ttl = crecp->ttd - now;
|
||||
|
||||
if (add_resource_record(header, limit, NULL, rec->offset, &ansp, ttl, NULL, type, C_IN,
|
||||
if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, type, C_IN,
|
||||
crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
|
||||
addncount++;
|
||||
}
|
||||
|
||||
459
src/rfc2131.c
459
src/rfc2131.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -72,7 +72,7 @@
|
||||
#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
|
||||
|
||||
static int sanitise(unsigned char *opt, char *buf);
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override);
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
|
||||
static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
|
||||
static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
|
||||
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||
@@ -90,16 +90,16 @@ static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
unsigned char *req_options,
|
||||
char *hostname,
|
||||
char *hostname,
|
||||
char *domain, char *config_domain,
|
||||
struct dhcp_netid *netid,
|
||||
struct in_addr subnet_addr,
|
||||
unsigned char fqdn_flags,
|
||||
int null_term,
|
||||
unsigned char *agent_id);
|
||||
static unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out);
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||
static void do_encap_opts(int encap, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
||||
|
||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform)
|
||||
@@ -112,13 +112,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0;
|
||||
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
|
||||
unsigned char *end = (unsigned char *)(mess + 1);
|
||||
char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL;
|
||||
char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
|
||||
int hostname_auth = 0, borken_opt = 0;
|
||||
unsigned char *req_options = NULL;
|
||||
char *message = NULL;
|
||||
unsigned int time;
|
||||
struct dhcp_config *config;
|
||||
struct dhcp_netid *netid = NULL;
|
||||
struct dhcp_netid *netid;
|
||||
struct in_addr subnet_addr, fallback, override;
|
||||
unsigned short fuzz = 0;
|
||||
unsigned int mess_type = 0;
|
||||
@@ -126,9 +126,15 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
unsigned char *agent_id = NULL;
|
||||
unsigned char *emac = NULL;
|
||||
int emac_len = 0;
|
||||
struct dhcp_netid known_id;
|
||||
struct dhcp_netid known_id, iface_id;
|
||||
struct dhcp_opt *o;
|
||||
|
||||
subnet_addr.s_addr = override.s_addr = 0;
|
||||
|
||||
/* set tag with name == interface */
|
||||
iface_id.net = iface_name;
|
||||
iface_id.next = NULL;
|
||||
netid = &iface_id;
|
||||
|
||||
if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
|
||||
return 0;
|
||||
@@ -359,8 +365,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
|
||||
|
||||
if (have_config(config, CONFIG_NAME))
|
||||
hostname = config->hostname;
|
||||
|
||||
{
|
||||
hostname = config->hostname;
|
||||
domain = config->domain;
|
||||
}
|
||||
|
||||
if (have_config(config, CONFIG_NETID))
|
||||
{
|
||||
config->netid.next = netid;
|
||||
@@ -389,8 +398,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
if (!message)
|
||||
{
|
||||
int nailed = 0;
|
||||
|
||||
if (have_config(config, CONFIG_ADDR))
|
||||
{
|
||||
nailed = 1;
|
||||
logaddr = &config->addr;
|
||||
mess->yiaddr = config->addr;
|
||||
if ((lease = lease_find_by_addr(config->addr)) &&
|
||||
@@ -399,8 +411,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
|
||||
message = _("address in use");
|
||||
}
|
||||
else if (!(daemon->options & OPT_BOOTP_DYNAMIC))
|
||||
message = _("no address configured");
|
||||
else
|
||||
{
|
||||
if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
|
||||
@@ -419,27 +429,35 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mess->yiaddr = lease->addr;
|
||||
}
|
||||
|
||||
if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
|
||||
message = _("wrong network");
|
||||
else if (context->netid.net)
|
||||
{
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
if (!message && !nailed)
|
||||
{
|
||||
for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
|
||||
if ((!id_list->list) || match_netid(id_list->list, netid, 0))
|
||||
break;
|
||||
if (!id_list)
|
||||
message = _("no address configured");
|
||||
}
|
||||
|
||||
if (!message &&
|
||||
!lease &&
|
||||
(!(lease = lease_allocate(mess->yiaddr))))
|
||||
message = _("no leases left");
|
||||
|
||||
if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
|
||||
message = _("wrong network");
|
||||
|
||||
|
||||
if (!message)
|
||||
{
|
||||
logaddr = &mess->yiaddr;
|
||||
|
||||
if (context->netid.net)
|
||||
{
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
}
|
||||
|
||||
lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
|
||||
if (hostname)
|
||||
lease_set_hostname(lease, hostname, daemon->domain_suffix, 1);
|
||||
lease_set_hostname(lease, hostname, 1);
|
||||
/* infinite lease unless nailed in dhcp-host line. */
|
||||
lease_set_expires(lease,
|
||||
have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
|
||||
@@ -447,8 +465,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
lease_set_interface(lease, int_index);
|
||||
|
||||
clear_packet(mess, end, NULL);
|
||||
do_options(context, mess, end, NULL,
|
||||
hostname, netid, subnet_addr, 0, 0, NULL);
|
||||
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
||||
domain, netid, subnet_addr, 0, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,6 +536,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (have_config(config, CONFIG_NAME))
|
||||
{
|
||||
hostname = config->hostname;
|
||||
domain = config->domain;
|
||||
hostname_auth = 1;
|
||||
/* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
|
||||
if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
|
||||
@@ -525,9 +544,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
else if (client_hostname)
|
||||
{
|
||||
char *d = strip_hostname(client_hostname);
|
||||
if (d)
|
||||
my_syslog(LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), d, client_hostname);
|
||||
domain = strip_hostname(client_hostname);
|
||||
|
||||
if (strlen(client_hostname) != 0)
|
||||
{
|
||||
@@ -540,7 +557,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
|
||||
mess->chaddr, mess->hlen,
|
||||
mess->htype, hostname);
|
||||
if (new && !have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
|
||||
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
|
||||
{
|
||||
config = new;
|
||||
/* set "known" tag for known hosts */
|
||||
@@ -558,6 +575,46 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
netid = &config->netid;
|
||||
}
|
||||
|
||||
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
|
||||
Otherwise assume the option is an array, and look for a matching element.
|
||||
If no data given, existance of the option is enough. */
|
||||
for (o = daemon->dhcp_match; o; o = o->next)
|
||||
{
|
||||
int i, matched = 0;
|
||||
|
||||
if (!(opt = option_find(mess, sz, o->opt, 1)) ||
|
||||
o->len > option_len(opt))
|
||||
continue;
|
||||
|
||||
if (o->len == 0)
|
||||
matched = 1;
|
||||
else if (o->flags & DHOPT_HEX)
|
||||
{
|
||||
if (memcmp_masked(o->val, option_ptr(opt, 0), o->len, o->u.wildcard_mask))
|
||||
matched = 1;
|
||||
}
|
||||
else
|
||||
for (i = 0; i <= (option_len(opt) - o->len); )
|
||||
{
|
||||
if (memcmp(o->val, option_ptr(opt, i), o->len) == 0)
|
||||
{
|
||||
matched = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (o->flags & DHOPT_STRING)
|
||||
i++;
|
||||
else
|
||||
i += o->len;
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
o->netid->next = netid;
|
||||
netid = o->netid;
|
||||
}
|
||||
}
|
||||
|
||||
/* user-class options are, according to RFC3004, supposed to contain
|
||||
a set of counted strings. Here we check that this is so (by seeing
|
||||
if the counts are consistent with the overall option length) and if
|
||||
@@ -581,7 +638,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
ucp[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||
{
|
||||
int mopt;
|
||||
@@ -590,15 +647,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mopt = OPTION_VENDOR_ID;
|
||||
else if (vendor->match_type == MATCH_USER)
|
||||
mopt = OPTION_USER_CLASS;
|
||||
else if (vendor->match_type == MATCH_OPTION)
|
||||
{
|
||||
if (option_find(mess, sz, vendor->option, 1))
|
||||
{
|
||||
vendor->netid.next = netid;
|
||||
netid = &vendor->netid;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
@@ -646,7 +694,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
case DHCPDECLINE:
|
||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||
option_addr(opt).s_addr != server_id(context, override).s_addr)
|
||||
option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
|
||||
return 0;
|
||||
|
||||
/* sanitise any message. Paranoid? Moi? */
|
||||
@@ -679,7 +727,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
case DHCPRELEASE:
|
||||
if (!(context = narrow_context(context, mess->ciaddr, netid)) ||
|
||||
!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||
option_addr(opt).s_addr != server_id(context, override).s_addr)
|
||||
option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
|
||||
return 0;
|
||||
|
||||
if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
|
||||
@@ -710,7 +758,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
char *addrs = inet_ntoa(config->addr);
|
||||
|
||||
if ((ltmp = lease_find_by_addr(config->addr)) && ltmp != lease)
|
||||
if ((ltmp = lease_find_by_addr(config->addr)) &&
|
||||
ltmp != lease &&
|
||||
!config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
|
||||
{
|
||||
int len;
|
||||
unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
|
||||
@@ -763,7 +813,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||
if (time != 0xffffffff)
|
||||
@@ -771,8 +821,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
option_put(mess, end, OPTION_T1, 4, (time/2));
|
||||
option_put(mess, end, OPTION_T2, 4, (time*7)/8);
|
||||
}
|
||||
do_options(context, mess, end, req_options, offer_hostname,
|
||||
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
|
||||
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
|
||||
domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
|
||||
|
||||
return dhcp_packet_size(mess, netid);
|
||||
|
||||
@@ -797,14 +847,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (option_addr(opt).s_addr != override.s_addr)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
for (; context; context = context->current)
|
||||
if (context->local.s_addr == option_addr(opt).s_addr)
|
||||
break;
|
||||
|
||||
if (!context)
|
||||
return 0;
|
||||
{
|
||||
/* In auth mode, a REQUEST sent to the wrong server
|
||||
should be faulted, so that the client establishes
|
||||
communication with us, otherwise, silently ignore. */
|
||||
if (!(daemon->options & OPT_AUTHORITATIVE))
|
||||
return 0;
|
||||
message = _("wrong server-ID");
|
||||
}
|
||||
}
|
||||
|
||||
/* If a lease exists for this host and another address, squash it. */
|
||||
@@ -888,18 +945,33 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
|
||||
message = _("address reserved");
|
||||
|
||||
else if ((ltmp = lease_find_by_addr(mess->yiaddr)) && ltmp != lease)
|
||||
message = _("address in use");
|
||||
|
||||
else if (emac_len == 0)
|
||||
message = _("no unique-id");
|
||||
|
||||
else if (!lease)
|
||||
{
|
||||
if ((lease = lease_allocate(mess->yiaddr)))
|
||||
do_classes = 1;
|
||||
else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
|
||||
{
|
||||
/* If a host is configured with more than one MAC address, it's OK to 'nix
|
||||
a lease from one of it's MACs to give the address to another. */
|
||||
if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
|
||||
{
|
||||
my_syslog(LOG_INFO, _("abandoning lease to %s of %s"),
|
||||
print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
|
||||
inet_ntoa(ltmp->addr));
|
||||
lease = ltmp;
|
||||
}
|
||||
else
|
||||
message = _("no leases left");
|
||||
message = _("address in use");
|
||||
}
|
||||
|
||||
if (!message)
|
||||
{
|
||||
if (emac_len == 0)
|
||||
message = _("no unique-id");
|
||||
|
||||
else if (!lease)
|
||||
{
|
||||
if ((lease = lease_allocate(mess->yiaddr)))
|
||||
do_classes = 1;
|
||||
else
|
||||
message = _("no leases left");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -910,8 +982,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mess->yiaddr.s_addr = 0;
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ,
|
||||
ntohl(server_id(context, override).s_addr ? server_id(context, override).s_addr : fallback.s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
|
||||
/* DHCPNAK gets agent-id too */
|
||||
restore_agent_id(agent_id, mess, end);
|
||||
@@ -984,7 +1055,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
hostname = NULL;
|
||||
}
|
||||
if (hostname)
|
||||
lease_set_hostname(lease, hostname, daemon->domain_suffix, hostname_auth);
|
||||
lease_set_hostname(lease, hostname, hostname_auth);
|
||||
|
||||
lease_set_expires(lease, time, now);
|
||||
lease_set_interface(lease, int_index);
|
||||
@@ -998,7 +1069,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
if (time != 0xffffffff)
|
||||
{
|
||||
@@ -1007,8 +1078,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
|
||||
option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
|
||||
}
|
||||
do_options(context, mess, end, req_options, hostname,
|
||||
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
|
||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
|
||||
domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
|
||||
}
|
||||
|
||||
return dhcp_packet_size(mess, netid);
|
||||
@@ -1019,9 +1090,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_packet("INFORM", &mess->ciaddr, emac, emac_len, iface_name, message);
|
||||
|
||||
if (message || mess->ciaddr.s_addr == 0 ||
|
||||
!(context = narrow_context(context, mess->ciaddr, netid)))
|
||||
if (message || mess->ciaddr.s_addr == 0)
|
||||
return 0;
|
||||
|
||||
/* For DHCPINFORM only, cope without a valid context */
|
||||
context = narrow_context(context, mess->ciaddr, netid);
|
||||
|
||||
/* Find a least based on IP address if we didn't
|
||||
get one from MAC address/client-d */
|
||||
@@ -1035,7 +1108,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_packet("ACK", &mess->ciaddr, emac, emac_len, iface_name, hostname);
|
||||
|
||||
if (context->netid.net)
|
||||
if (context && context->netid.net)
|
||||
{
|
||||
context->netid.next = netid;
|
||||
netid = &context->netid;
|
||||
@@ -1051,8 +1124,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
clear_packet(mess, end, agent_id);
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override).s_addr));
|
||||
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
|
||||
if (lease)
|
||||
{
|
||||
if (lease->expires == 0)
|
||||
@@ -1063,8 +1136,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
lease_set_interface(lease, int_index);
|
||||
}
|
||||
|
||||
do_options(context, mess, end, req_options, hostname,
|
||||
netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
|
||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
||||
domain, netid, subnet_addr, fqdn_flags, borken_opt, agent_id);
|
||||
|
||||
*is_inform = 1; /* handle reply differently */
|
||||
return dhcp_packet_size(mess, netid);
|
||||
@@ -1081,7 +1154,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
then the client-id is using the usual encoding and use the rest of the
|
||||
client-id: if not we can use the whole client-id. This should give
|
||||
sane MAC address logs. */
|
||||
static unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out)
|
||||
{
|
||||
if (hwlen == 0 && clid && clid_len > 3)
|
||||
@@ -1124,12 +1197,14 @@ static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *
|
||||
return time;
|
||||
}
|
||||
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override)
|
||||
static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
|
||||
{
|
||||
if (override.s_addr != 0 || !context)
|
||||
if (override.s_addr != 0)
|
||||
return override;
|
||||
else
|
||||
else if (context)
|
||||
return context->local;
|
||||
else
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static int sanitise(unsigned char *opt, char *buf)
|
||||
@@ -1291,6 +1366,7 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
|
||||
unsigned char *overload;
|
||||
size_t ret;
|
||||
struct dhcp_netid_list *id_list;
|
||||
struct dhcp_netid *n;
|
||||
|
||||
/* We do logging too */
|
||||
if (netid && (daemon->options & OPT_LOG_OPTS))
|
||||
@@ -1299,9 +1375,17 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
|
||||
*p = 0;
|
||||
for (; netid; netid = netid->next)
|
||||
{
|
||||
strncat (p, netid->net, MAXDNAME);
|
||||
if (netid->next)
|
||||
strncat (p, ", ", MAXDNAME);
|
||||
/* kill dupes. */
|
||||
for (n = netid->next; n; n = n->next)
|
||||
if (strcmp(netid->net, n->net) == 0)
|
||||
break;
|
||||
|
||||
if (!n)
|
||||
{
|
||||
strncat (p, netid->net, MAXDNAME);
|
||||
if (netid->next)
|
||||
strncat (p, ", ", MAXDNAME);
|
||||
}
|
||||
}
|
||||
p[MAXDNAME - 1] = 0;
|
||||
my_syslog(LOG_INFO, _("tags: %s"), p);
|
||||
@@ -1427,7 +1511,7 @@ static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int
|
||||
}
|
||||
|
||||
/* return length, note this only does the data part */
|
||||
static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local, int null_term)
|
||||
static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
|
||||
{
|
||||
int len = opt->len;
|
||||
|
||||
@@ -1436,7 +1520,7 @@ static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local,
|
||||
|
||||
if (p && len != 0)
|
||||
{
|
||||
if ((opt->flags & DHOPT_ADDR) && !(opt->flags & DHOPT_ENCAPSULATE))
|
||||
if (context && (opt->flags & DHOPT_ADDR))
|
||||
{
|
||||
int j;
|
||||
struct in_addr *a = (struct in_addr *)opt->val;
|
||||
@@ -1444,7 +1528,7 @@ static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct in_addr local,
|
||||
{
|
||||
/* zero means "self" (but not in vendorclass options.) */
|
||||
if (a->s_addr == 0)
|
||||
memcpy(p, &local, INADDRSZ);
|
||||
memcpy(p, &context->local, INADDRSZ);
|
||||
else
|
||||
memcpy(p, a, INADDRSZ);
|
||||
p += INADDRSZ;
|
||||
@@ -1475,7 +1559,7 @@ static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *
|
||||
{
|
||||
struct dhcp_opt *tmp;
|
||||
for (tmp = opts; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt && !(tmp->flags & DHOPT_ENCAPSULATE))
|
||||
if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)))
|
||||
if (match_netid(tmp->netid, netid, 1) || match_netid(tmp->netid, netid, 0))
|
||||
return tmp;
|
||||
|
||||
@@ -1488,22 +1572,66 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
|
||||
{
|
||||
for (; dopt; dopt = dopt->next)
|
||||
{
|
||||
dopt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
if (opt && (dopt->flags & DHOPT_ENCAPSULATE))
|
||||
dopt->flags &= ~(DHOPT_ENCAP_MATCH | DHOPT_ENCAP_DONE);
|
||||
if (opt && (dopt->flags & DHOPT_VENDOR))
|
||||
{
|
||||
int i, len = 0;
|
||||
if (dopt->vendor_class)
|
||||
len = strlen((char *)dopt->vendor_class);
|
||||
if (dopt->u.vendor_class)
|
||||
len = strlen((char *)dopt->u.vendor_class);
|
||||
for (i = 0; i <= (option_len(opt) - len); i++)
|
||||
if (len == 0 || memcmp(dopt->vendor_class, option_ptr(opt, i), len) == 0)
|
||||
if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
|
||||
{
|
||||
dopt->flags |= DHOPT_VENDOR_MATCH;
|
||||
dopt->flags |= DHOPT_ENCAP_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void do_encap_opts(int encap, struct dhcp_packet *mess, unsigned char *end, int null_term)
|
||||
{
|
||||
int len, enc_len;
|
||||
struct dhcp_opt *opt, *start;
|
||||
unsigned char *p;
|
||||
|
||||
/* find size in advance */
|
||||
for (enc_len = 0, start = opt = daemon->dhcp_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_ENCAP_MATCH)
|
||||
{
|
||||
int new = do_opt(opt, NULL, NULL, null_term) + 2;
|
||||
if (enc_len + new <= 255)
|
||||
enc_len += new;
|
||||
else
|
||||
{
|
||||
p = free_space(mess, end, encap, enc_len);
|
||||
for (; start && start != opt; start = start->next)
|
||||
if (p && (start->flags & DHOPT_ENCAP_MATCH))
|
||||
{
|
||||
len = do_opt(start, p + 2, NULL, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
enc_len = new;
|
||||
start = opt;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_len != 0 &&
|
||||
(p = free_space(mess, end, encap, enc_len + 1)))
|
||||
{
|
||||
for (; start; start = start->next)
|
||||
if (start->flags & DHOPT_ENCAP_MATCH)
|
||||
{
|
||||
len = do_opt(start, p + 2, NULL, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
*p = OPTION_END;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end, unsigned char *agent_id)
|
||||
{
|
||||
/* don't clear agent_id */
|
||||
@@ -1531,7 +1659,8 @@ static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
unsigned char *req_options,
|
||||
char *hostname,
|
||||
char *hostname,
|
||||
char *domain, char *config_domain,
|
||||
struct dhcp_netid *netid,
|
||||
struct in_addr subnet_addr,
|
||||
unsigned char fqdn_flags,
|
||||
@@ -1545,6 +1674,9 @@ static void do_options(struct dhcp_context *context,
|
||||
unsigned char f0 = 0, s0 = 0;
|
||||
int done_file = 0, done_server = 0;
|
||||
|
||||
if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
|
||||
my_syslog(LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname);
|
||||
|
||||
/* logging */
|
||||
if ((daemon->options & OPT_LOG_OPTS) && req_options)
|
||||
{
|
||||
@@ -1576,7 +1708,8 @@ static void do_options(struct dhcp_context *context,
|
||||
if (match_netid(boot->netid, netid, 1))
|
||||
break;
|
||||
|
||||
mess->siaddr = context->local;
|
||||
if (context)
|
||||
mess->siaddr = context->local;
|
||||
|
||||
/* See if we can send the boot stuff as options.
|
||||
To do this we need a requested option list, BOOTP
|
||||
@@ -1660,30 +1793,34 @@ static void do_options(struct dhcp_context *context,
|
||||
/* rfc3011 says this doesn't need to be in the requested options list. */
|
||||
if (subnet_addr.s_addr)
|
||||
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
|
||||
|
||||
/* replies to DHCPINFORM may not have a valid context */
|
||||
if (context)
|
||||
{
|
||||
if (!option_find2(netid, config_opts, OPTION_NETMASK))
|
||||
option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
||||
|
||||
/* May not have a "guessed" broadcast address if we got no packets via a relay
|
||||
from this net yet (ie just unicast renewals after a restart */
|
||||
if (context->broadcast.s_addr &&
|
||||
!option_find2(netid, config_opts, OPTION_BROADCAST))
|
||||
option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
|
||||
|
||||
/* Same comments as broadcast apply, and also may not be able to get a sensible
|
||||
default when using subnet select. User must configure by steam in that case. */
|
||||
if (context->router.s_addr &&
|
||||
in_list(req_options, OPTION_ROUTER) &&
|
||||
!option_find2(netid, config_opts, OPTION_ROUTER))
|
||||
option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
|
||||
|
||||
if (in_list(req_options, OPTION_DNSSERVER) &&
|
||||
!option_find2(netid, config_opts, OPTION_DNSSERVER))
|
||||
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
}
|
||||
|
||||
if (!option_find2(netid, config_opts, OPTION_NETMASK))
|
||||
option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
||||
|
||||
/* May not have a "guessed" broadcast address if we got no packets via a relay
|
||||
from this net yet (ie just unicast renewals after a restart */
|
||||
if (context->broadcast.s_addr &&
|
||||
!option_find2(netid, config_opts, OPTION_BROADCAST))
|
||||
option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
|
||||
|
||||
/* Same comments as broadcast apply, and also may not be able to get a sensible
|
||||
default when using subnet select. User must configure by steam in that case. */
|
||||
if (context->router.s_addr &&
|
||||
in_list(req_options, OPTION_ROUTER) &&
|
||||
!option_find2(netid, config_opts, OPTION_ROUTER))
|
||||
option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
|
||||
|
||||
if (in_list(req_options, OPTION_DNSSERVER) &&
|
||||
!option_find2(netid, config_opts, OPTION_DNSSERVER))
|
||||
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
|
||||
|
||||
if (daemon->domain_suffix && in_list(req_options, OPTION_DOMAINNAME) &&
|
||||
if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
|
||||
!option_find2(netid, config_opts, OPTION_DOMAINNAME))
|
||||
option_put_string(mess, end, OPTION_DOMAINNAME, daemon->domain_suffix, null_term);
|
||||
option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
|
||||
|
||||
/* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
|
||||
if (hostname)
|
||||
@@ -1694,14 +1831,15 @@ static void do_options(struct dhcp_context *context,
|
||||
|
||||
if (fqdn_flags != 0)
|
||||
{
|
||||
int len = strlen(hostname) + 3;
|
||||
len = strlen(hostname) + 3;
|
||||
|
||||
if (fqdn_flags & 0x04)
|
||||
len += 2;
|
||||
else if (null_term)
|
||||
len++;
|
||||
|
||||
if (daemon->domain_suffix)
|
||||
len += strlen(daemon->domain_suffix) + 1;
|
||||
if (domain)
|
||||
len += strlen(domain) + 1;
|
||||
|
||||
if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
|
||||
{
|
||||
@@ -1712,19 +1850,19 @@ static void do_options(struct dhcp_context *context,
|
||||
if (fqdn_flags & 0x04)
|
||||
{
|
||||
p = do_rfc1035_name(p, hostname);
|
||||
if (daemon->domain_suffix)
|
||||
p = do_rfc1035_name(p, daemon->domain_suffix);
|
||||
if (domain)
|
||||
p = do_rfc1035_name(p, domain);
|
||||
*p++ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(p, hostname, strlen(hostname));
|
||||
p += strlen(hostname);
|
||||
if (daemon->domain_suffix)
|
||||
if (domain)
|
||||
{
|
||||
*(p++) = '.';
|
||||
memcpy(p, daemon->domain_suffix, strlen(daemon->domain_suffix));
|
||||
p += strlen(daemon->domain_suffix);
|
||||
memcpy(p, domain, strlen(domain));
|
||||
p += strlen(domain);
|
||||
}
|
||||
if (null_term)
|
||||
*(p++) = 0;
|
||||
@@ -1772,12 +1910,12 @@ static void do_options(struct dhcp_context *context,
|
||||
continue;
|
||||
|
||||
/* always force null-term for filename ans servername - buggy PXE again. */
|
||||
len = do_opt(opt, NULL, context->local,
|
||||
len = do_opt(opt, NULL, context,
|
||||
(optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
|
||||
|
||||
if ((p = free_space(mess, end, optno, len)))
|
||||
{
|
||||
do_opt(opt, p, context->local,
|
||||
do_opt(opt, p, context,
|
||||
(optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
|
||||
|
||||
/* If we send a vendor-id, revisit which vendor-ops we consider
|
||||
@@ -1787,59 +1925,48 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
}
|
||||
|
||||
/* prune encapsulated options based on netid, and look if we're forcing them to be sent */
|
||||
/* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
|
||||
for (opt = config_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
if (opt->flags & DHOPT_ENCAP_MATCH)
|
||||
{
|
||||
if (!match_netid(opt->netid, netid, 1) && !match_netid(opt->netid, netid, 0))
|
||||
opt->flags &= ~DHOPT_VENDOR_MATCH;
|
||||
opt->flags &= ~DHOPT_ENCAP_MATCH;
|
||||
else if (opt->flags & DHOPT_FORCE)
|
||||
force_encap = 1;
|
||||
}
|
||||
|
||||
if (force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT))
|
||||
{
|
||||
int enc_len = 0;
|
||||
struct dhcp_opt *start;
|
||||
|
||||
/* find size in advance */
|
||||
for (start = opt = config_opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_VENDOR_MATCH)
|
||||
do_encap_opts(OPTION_VENDOR_CLASS_OPT, mess, end, null_term);
|
||||
|
||||
/* Now send options to be encapsulated in arbitrary options,
|
||||
eg dhcp-option=encap:172,17,.......
|
||||
The may be more that one "outer" to do, so group
|
||||
all the options which match each outer in turn. */
|
||||
for (opt = config_opts; opt; opt = opt->next)
|
||||
if ((opt->flags & (DHOPT_ENCAPSULATE | DHOPT_ENCAP_DONE)) == DHOPT_ENCAPSULATE)
|
||||
{
|
||||
struct dhcp_opt *o;
|
||||
int found = 0;
|
||||
|
||||
for (o = config_opts; o; o = o->next)
|
||||
{
|
||||
int new = do_opt(opt, NULL, context->local, null_term) + 2;
|
||||
if (enc_len + new <= 255)
|
||||
enc_len += new;
|
||||
else
|
||||
o->flags &= ~DHOPT_ENCAP_MATCH;
|
||||
if ((o->flags & DHOPT_ENCAPSULATE) && opt->u.encap == o->u.encap)
|
||||
{
|
||||
p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len);
|
||||
for (; start && start != opt; start = start->next)
|
||||
if (p && (start->flags & DHOPT_VENDOR_MATCH))
|
||||
{
|
||||
len = do_opt(start, p + 2, context->local, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
enc_len = new;
|
||||
start = opt;
|
||||
o->flags |= DHOPT_ENCAP_DONE;
|
||||
if ((match_netid(o->netid, netid, 1) || match_netid(o->netid, netid, 0)) &&
|
||||
(o->flags & DHOPT_FORCE || in_list(req_options, o->u.encap)))
|
||||
{
|
||||
o->flags |= DHOPT_ENCAP_MATCH;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_len != 0 &&
|
||||
(p = free_space(mess, end, OPTION_VENDOR_CLASS_OPT, enc_len + 1)))
|
||||
{
|
||||
for (; start; start = start->next)
|
||||
if (start->flags & DHOPT_VENDOR_MATCH)
|
||||
{
|
||||
len = do_opt(start, p + 2, context->local, null_term);
|
||||
*(p++) = start->opt;
|
||||
*(p++) = len;
|
||||
p += len;
|
||||
}
|
||||
*p = OPTION_END;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (found)
|
||||
do_encap_opts(opt->u.encap, mess, end, null_term);
|
||||
}
|
||||
|
||||
/* move agent_id back down to the end of the packet */
|
||||
restore_agent_id(agent_id, mess, real_end);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -10,8 +10,8 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
10
src/util.c
10
src/util.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -9,13 +9,11 @@
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Some code in this file contributed by Rob Funk. */
|
||||
|
||||
/* The SURF random number generator was taken from djbdns-1.05, by
|
||||
Daniel J Berstein, which is public domain. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user