Compare commits
11 Commits
v2.63test2
...
v2.63test3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
611ebc5f1e | ||
|
|
be0f45cdbc | ||
|
|
9b40cbf587 | ||
|
|
c4a7f90ebb | ||
|
|
9609baee41 | ||
|
|
395eb71931 | ||
|
|
8bc4cecee6 | ||
|
|
6b617c0d15 | ||
|
|
55d290a3bf | ||
|
|
e17b4b3871 | ||
|
|
236e072cab |
18
CHANGELOG
18
CHANGELOG
@@ -10,6 +10,24 @@ version 2.63
|
||||
Add --bind-dynamic. A hybrid mode between the default and
|
||||
--bind-interfaces which copes with dynamically created
|
||||
interfaces.
|
||||
|
||||
A couple of fixes to the build system for Android. Thanks
|
||||
to Metin Kaya for the patches.
|
||||
|
||||
Remove the interface:<interface> argument in --dhcp-range, and
|
||||
the interface argument to --enable-tftp. These were a
|
||||
still-born attempt to allow automatic isolated
|
||||
configuration by libvirt, but have never (to my knowledge)
|
||||
been used, had very strange semantics, and have been
|
||||
superceded by other mechanisms.
|
||||
|
||||
Fixed bug logging filenames when duplicate dhcp-host
|
||||
addresses are found. Thanks to John Hanks for the patch.
|
||||
|
||||
Fix regression in 2.61 which broke caching of CNAME
|
||||
chains. Thanks to Atul Gupta for the bug report.
|
||||
|
||||
Allow the target of a --cname flag to be anothe --cname.
|
||||
|
||||
|
||||
version 2.62
|
||||
|
||||
@@ -17,4 +17,6 @@ LOCAL_C_INCLUDES := external/dnsmasq/src
|
||||
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
|
||||
|
||||
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -522,7 +522,7 @@
|
||||
# If you want to disable negative caching, uncomment this.
|
||||
#no-negcache
|
||||
|
||||
# Normally responses which come form /etc/hosts and the DHCP lease
|
||||
# Normally responses which come from /etc/hosts and the DHCP lease
|
||||
# file have Time-To-Live set as zero, which conventionally means
|
||||
# do not cache further. If you are happy to trade lower load on the
|
||||
# server for potentially stale date, you can set a time-to-live (in
|
||||
|
||||
@@ -461,7 +461,9 @@ Return an NAPTR DNS record, as specified in RFC3403.
|
||||
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
|
||||
hosts files), from DHCP or from another
|
||||
.B --cname.
|
||||
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
|
||||
@@ -529,9 +531,9 @@ compiled in and the kernel must have conntrack support
|
||||
included and configured. This option cannot be combined with
|
||||
--query-port.
|
||||
.TP
|
||||
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
|
||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
|
||||
.TP
|
||||
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-IPv6addr>[,<end-IPv6addr>][,<mode>][,<prefix-len>][,<lease time>]
|
||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag],]<start-IPv6addr>[,<end-IPv6addr>][,<mode>][,<prefix-len>][,<lease time>]
|
||||
|
||||
Enable the DHCP server. Addresses will be given out from the range
|
||||
<start-addr> to <end-addr> and from statically defined addresses given
|
||||
@@ -624,8 +626,6 @@ can be combined with
|
||||
and
|
||||
.B slaac.
|
||||
|
||||
The interface:<interface name> section is not normally used. See the
|
||||
NOTES section for details of this.
|
||||
.TP
|
||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||
Specify per host parameters for the DHCP server. This allows a machine
|
||||
@@ -1369,12 +1369,11 @@ the relevant link-local address of the machine running dnsmasq is sent
|
||||
as recursive DNS server. If provided, the DHCPv6 options dns-server and
|
||||
domain-search are used for RDNSS and DNSSL.
|
||||
.TP
|
||||
.B --enable-tftp[=<interface>]
|
||||
.B --enable-tftp
|
||||
Enable the TFTP server function. This is deliberately limited to that
|
||||
needed to net-boot a client. Only reading is allowed; the tsize and
|
||||
blksize extensions are supported (tsize is only supported in octet
|
||||
mode). See NOTES section for use of the interface argument.
|
||||
|
||||
mode).
|
||||
.TP
|
||||
.B --tftp-root=<directory>[,<interface>]
|
||||
Look for files to transfer using TFTP relative to the given
|
||||
@@ -1638,52 +1637,6 @@ parameter in a BOOTP request is used as a tag,
|
||||
as is the tag "bootp", allowing some control over the options returned to
|
||||
different classes of hosts.
|
||||
|
||||
.B dhcp-range
|
||||
may have an interface name supplied as
|
||||
"interface:<interface-name>". The semantics if this are as follows:
|
||||
For DHCP, if any other dhcp-range exists _without_ an interface name,
|
||||
then the interface name is ignored and and dnsmasq behaves as if the
|
||||
interface parts did not exist, otherwise DHCP is only provided to
|
||||
interfaces mentioned in dhcp-range
|
||||
declarations. For DNS, if there are no
|
||||
.B --interface
|
||||
or
|
||||
.B --listen-address
|
||||
flags, behaviour is unchanged by the interface part. If either of
|
||||
these flags are present, the interfaces mentioned in
|
||||
dhcp-ranges are added to the set which get DNS service.
|
||||
|
||||
Similarly,
|
||||
.B enable-tftp
|
||||
may take an interface name, which enables TFTP only for a particular
|
||||
interface, ignoring
|
||||
.B --interface
|
||||
or
|
||||
.B --listen-address
|
||||
flags. In addition
|
||||
.B --tftp-secure
|
||||
and
|
||||
.B --tftp-unique-root
|
||||
and
|
||||
.B --tftp-no-blocksize
|
||||
are ignored for requests from such interfaces. (A
|
||||
.B --tftp-root
|
||||
directive giving a root path and an interface should be
|
||||
provided too.)
|
||||
|
||||
These rules may seem odd at first sight, but they
|
||||
allow a single line of the form "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200"
|
||||
to be added to dnsmasq configuration which then supplies
|
||||
DHCP and DNS services to that interface, without affecting
|
||||
what services are supplied to other interfaces and irrespective of
|
||||
the existance or lack of "interface=<interface>"
|
||||
lines elsewhere in the dnsmasq configuration.
|
||||
"enable-tftp=virt0" and "tftp-root=<root>,virt0" do the same job for TFTP.
|
||||
The idea is
|
||||
that such a line can be added automatically by libvirt
|
||||
or equivalent systems, without disturbing any manual
|
||||
configuration.
|
||||
|
||||
.SH EXIT CODES
|
||||
.PP
|
||||
0 - Dnsmasq successfully forked into the background, or terminated
|
||||
|
||||
88
src/cache.c
88
src/cache.c
@@ -243,7 +243,7 @@ static int is_outdated_cname_pointer(struct crec *crecp)
|
||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||
overloaded for something completely different */
|
||||
if (crecp->addr.cname.cache &&
|
||||
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6)) &&
|
||||
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
|
||||
return 0;
|
||||
|
||||
@@ -645,13 +645,29 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void add_hosts_cname(struct crec *target)
|
||||
{
|
||||
struct crec *crec;
|
||||
struct cname *a;
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(cache_get_name(target), a->target) &&
|
||||
(crec = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
||||
crec->name.namep = a->alias;
|
||||
crec->addr.cname.cache = target;
|
||||
crec->addr.cname.uid = target->uid;
|
||||
cache_hash(crec);
|
||||
add_hosts_cname(crec); /* handle chains */
|
||||
}
|
||||
}
|
||||
|
||||
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
||||
int index, struct crec **rhash, int hashsz)
|
||||
{
|
||||
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
||||
int i, nameexists = 0;
|
||||
struct cname *a;
|
||||
unsigned int j;
|
||||
|
||||
/* Remove duplicates in hosts files. */
|
||||
@@ -702,16 +718,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
||||
|
||||
/* 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_get_name(cache), a->target) &&
|
||||
(lookup = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
||||
lookup->name.namep = a->alias;
|
||||
lookup->addr.cname.cache = cache;
|
||||
lookup->addr.cname.uid = index;
|
||||
cache_hash(lookup);
|
||||
}
|
||||
add_hosts_cname(cache);
|
||||
}
|
||||
|
||||
static int eatspace(FILE *f)
|
||||
@@ -1003,13 +1010,41 @@ void cache_unhash_dhcp(void)
|
||||
up = &cache->hash_next;
|
||||
}
|
||||
|
||||
static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||
{
|
||||
struct crec *aliasc;
|
||||
struct cname *a;
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(cache_get_name(target), 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_NAMEP | F_DHCP | F_CNAME;
|
||||
if (ttd == 0)
|
||||
aliasc->flags |= F_IMMORTAL;
|
||||
else
|
||||
aliasc->ttd = ttd;
|
||||
aliasc->name.namep = a->alias;
|
||||
aliasc->addr.cname.cache = target;
|
||||
aliasc->addr.cname.uid = target->uid;
|
||||
cache_hash(aliasc);
|
||||
add_dhcp_cname(aliasc, ttd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
struct all_addr *host_address, time_t ttd)
|
||||
{
|
||||
struct crec *crec = NULL, *aliasc;
|
||||
struct crec *crec = NULL;
|
||||
unsigned short flags = F_IPV4;
|
||||
int in_hosts = 0;
|
||||
struct cname *a;
|
||||
size_t addrlen = sizeof(struct in_addr);
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -1030,7 +1065,6 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
|
||||
inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
|
||||
if (crec->flags & F_CNAME)
|
||||
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
|
||||
host_name, daemon->addrbuff);
|
||||
@@ -1083,27 +1117,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
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_NAMEP | 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);
|
||||
}
|
||||
}
|
||||
add_dhcp_cname(crec, ttd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
||||
#define HOSTSFILE "/etc/hosts"
|
||||
#define ETHERSFILE "/etc/ethers"
|
||||
#define RUNFILE "/var/run/dnsmasq.pid"
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
#define CHGRP "dip"
|
||||
@@ -158,7 +157,13 @@ RESOLVFILE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef RUNFILE
|
||||
# if defined(__ANDROID__)
|
||||
# define RUNFILE "/data/dnsmasq.pid"
|
||||
# else
|
||||
# define RUNFILE "/var/run/dnsmasq.pid"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* platform dependent options: these are determined automatically below
|
||||
|
||||
|
||||
@@ -246,40 +246,6 @@ int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check_dhcp_hosts(int fatal)
|
||||
{
|
||||
/* If the same IP appears in more than one host config, then DISCOVER
|
||||
for one of the hosts will get the address, but REQUEST will be NAKed,
|
||||
since the address is reserved by the other one -> protocol loop.
|
||||
Also check that FQDNs match the domain we are using. */
|
||||
|
||||
struct dhcp_config *configs, *cp;
|
||||
|
||||
for (configs = daemon->dhcp_conf; configs; configs = configs->next)
|
||||
{
|
||||
char *domain;
|
||||
|
||||
if ((configs->flags & DHOPT_BANK) || fatal)
|
||||
{
|
||||
for (cp = configs->next; cp; cp = cp->next)
|
||||
if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
|
||||
{
|
||||
if (fatal)
|
||||
die(_("duplicate IP address %s in dhcp-config directive."),
|
||||
inet_ntoa(cp->addr), EC_BADCONF);
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
|
||||
inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
|
||||
configs->flags &= ~CONFIG_ADDR;
|
||||
}
|
||||
|
||||
/* split off domain part */
|
||||
if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
|
||||
configs->domain = domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dhcp_update_configs(struct dhcp_config *configs)
|
||||
{
|
||||
/* Some people like to keep all static IP addresses in /etc/hosts.
|
||||
@@ -372,7 +338,6 @@ static int join_multicast_worker(struct in6_addr *local, int prefix,
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
struct ipv6_mreq mreq;
|
||||
int fd, i, max = *((int *)vparam);
|
||||
struct dhcp_context *context;
|
||||
struct iname *tmp;
|
||||
|
||||
(void)prefix;
|
||||
@@ -406,15 +371,6 @@ static int join_multicast_worker(struct in6_addr *local, int prefix,
|
||||
if (tmp->name && (strcmp(tmp->name, ifrn_name) == 0))
|
||||
return 1;
|
||||
|
||||
/* weird libvirt-inspired access control */
|
||||
for (context = daemon->ra_contexts ? daemon->ra_contexts : daemon->dhcp6;
|
||||
context; context = context->next)
|
||||
if (!context->interface || strcmp(context->interface, ifrn_name) == 0)
|
||||
break;
|
||||
|
||||
if (!context)
|
||||
return 1;
|
||||
|
||||
mreq.ipv6mr_interface = if_index;
|
||||
|
||||
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
|
||||
|
||||
14
src/dhcp.c
14
src/dhcp.c
@@ -116,9 +116,7 @@ void dhcp_init(void)
|
||||
|
||||
/* Make BPF raw send socket */
|
||||
init_bpf();
|
||||
#endif
|
||||
|
||||
check_dhcp_hosts(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dhcp_packet(time_t now, int pxe_fd)
|
||||
@@ -257,14 +255,6 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||
return;
|
||||
|
||||
/* weird libvirt-inspired access control */
|
||||
for (context = daemon->dhcp; context; context = context->next)
|
||||
if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
|
||||
break;
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
/* unlinked contexts are marked by context->current == context */
|
||||
for (context = daemon->dhcp; context; context = context->next)
|
||||
context->current = context;
|
||||
@@ -277,7 +267,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
||||
for a secondary */
|
||||
struct match_param match;
|
||||
|
||||
|
||||
match.matched = 0;
|
||||
match.ind = iface_index;
|
||||
|
||||
|
||||
@@ -111,14 +111,6 @@ void dhcp6_packet(time_t now)
|
||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||
return;
|
||||
|
||||
/* weird libvirt-inspired access control */
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
|
||||
break;
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
/* unlinked contexts are marked by context->current == context */
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
{
|
||||
|
||||
@@ -120,12 +120,12 @@ int main (int argc, char **argv)
|
||||
{
|
||||
bind_fallback = 1;
|
||||
set_option_bool(OPT_NOWILD);
|
||||
reset_option_bool(OPT_CLVERBIND);
|
||||
reset_option_bool(OPT_CLEVERBIND);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_TFTP
|
||||
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
|
||||
if (option_bool(OPT_TFTP))
|
||||
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
@@ -512,7 +512,7 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
|
||||
if (option_bool(OPT_TFTP))
|
||||
{
|
||||
DIR *dir;
|
||||
struct tftp_prefix *p;
|
||||
@@ -668,7 +668,7 @@ int main (int argc, char **argv)
|
||||
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
|
||||
if (option_bool(OPT_TFTP))
|
||||
{
|
||||
#ifdef FD_SETSIZE
|
||||
if (FD_SETSIZE < (unsigned)max_fd)
|
||||
@@ -1243,7 +1243,6 @@ void clear_cache_and_reload(time_t now)
|
||||
dhcp_read_ethers();
|
||||
reread_dhcp();
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
check_dhcp_hosts(0);
|
||||
lease_update_from_configs();
|
||||
lease_update_file(now);
|
||||
lease_update_dns(1);
|
||||
|
||||
@@ -220,7 +220,8 @@ struct event_desc {
|
||||
#define OPT_RA 37
|
||||
#define OPT_TFTP_LC 38
|
||||
#define OPT_CLEVERBIND 39
|
||||
#define OPT_LAST 40
|
||||
#define OPT_TFTP 40
|
||||
#define OPT_LAST 41
|
||||
|
||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||
@@ -664,7 +665,6 @@ struct dhcp_context {
|
||||
time_t ra_time;
|
||||
#endif
|
||||
int flags;
|
||||
char *interface;
|
||||
struct dhcp_netid netid, *filter;
|
||||
struct dhcp_context *next, *current;
|
||||
};
|
||||
@@ -712,11 +712,6 @@ struct addr_list {
|
||||
struct addr_list *next;
|
||||
};
|
||||
|
||||
struct interface_list {
|
||||
char *interface;
|
||||
struct interface_list *next;
|
||||
};
|
||||
|
||||
struct tftp_prefix {
|
||||
char *interface;
|
||||
char *prefix;
|
||||
@@ -780,8 +775,6 @@ extern struct daemon {
|
||||
unsigned short edns_pktsz;
|
||||
char *tftp_prefix;
|
||||
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
|
||||
struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
|
||||
int tftp_unlimited;
|
||||
unsigned int duid_enterprise, duid_config_len;
|
||||
unsigned char *duid_config;
|
||||
|
||||
@@ -1130,7 +1123,6 @@ char *strip_hostname(char *hostname);
|
||||
void log_tags(struct dhcp_netid *netid, u32 xid);
|
||||
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
||||
void dhcp_update_configs(struct dhcp_config *configs);
|
||||
void check_dhcp_hosts(int fatal);
|
||||
void display_opts(void);
|
||||
u16 lookup_dhcp_opt(int prot, char *name);
|
||||
u16 lookup_dhcp_len(int prot, u16 val);
|
||||
|
||||
@@ -39,7 +39,6 @@ static struct iovec iov;
|
||||
static u32 netlink_pid;
|
||||
|
||||
static int nl_async(struct nlmsghdr *h);
|
||||
static void nl_routechange(struct nlmsghdr *h);
|
||||
|
||||
void netlink_init(void)
|
||||
{
|
||||
@@ -342,59 +341,54 @@ static int nl_async(struct nlmsghdr *h)
|
||||
}
|
||||
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||
{
|
||||
nl_routechange(h);
|
||||
/* We arrange to receive netlink multicast messages whenever the network route is added.
|
||||
If this happens and we still have a DNS packet in the buffer, we re-send it.
|
||||
This helps on DoD links, where frequently the packet which triggers dialling is
|
||||
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
|
||||
failing. */
|
||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||
|
||||
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK)
|
||||
{
|
||||
/* Force re-reading resolv file right now, for luck. */
|
||||
daemon->last_resolv = 0;
|
||||
|
||||
if (daemon->srv_save)
|
||||
{
|
||||
int fd;
|
||||
|
||||
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 0;
|
||||
|
||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (h->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
/* force RAs to sync new network and pick up new interfaces. */
|
||||
if (daemon->ra_contexts)
|
||||
{
|
||||
schedule_subnet_map();
|
||||
ra_start_unsolicted(dnsmasq_time(), NULL);
|
||||
/* cause lease_update_file to run after we return, in case we were called from
|
||||
iface_enumerate and can't re-enter it now */
|
||||
send_alarm(0, 0);
|
||||
}
|
||||
return 1; /* clever bind mode - rescan */
|
||||
else if (h->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
/* force RAs to sync new network and pick up new interfaces. */
|
||||
if (daemon->ra_contexts)
|
||||
{
|
||||
schedule_subnet_map();
|
||||
ra_start_unsolicted(dnsmasq_time(), NULL);
|
||||
/* cause lease_update_file to run after we return, in case we were called from
|
||||
iface_enumerate and can't re-enter it now */
|
||||
send_alarm(0, 0);
|
||||
}
|
||||
return 1; /* clever bind mode - rescan */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We arrange to receive netlink multicast messages whenever the network route is added.
|
||||
If this happens and we still have a DNS packet in the buffer, we re-send it.
|
||||
This helps on DoD links, where frequently the packet which triggers dialling is
|
||||
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
|
||||
failing. */
|
||||
static void nl_routechange(struct nlmsghdr *h)
|
||||
{
|
||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||
int fd;
|
||||
|
||||
if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK)
|
||||
return;
|
||||
|
||||
/* Force re-reading resolv file right now, for luck. */
|
||||
daemon->last_resolv = 0;
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -117,18 +117,8 @@ int iface_check(int family, struct all_addr *addr, char *name)
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
#ifdef HAVE_DHCP
|
||||
struct dhcp_context *range;
|
||||
#endif
|
||||
|
||||
ret = 0;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
for (range = daemon->dhcp; range; range = range->next)
|
||||
if (range->interface && strcmp(range->interface, name) == 0)
|
||||
ret = 1;
|
||||
#endif
|
||||
|
||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
ret = tmp->used = 1;
|
||||
@@ -161,12 +151,11 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
struct irec *iface;
|
||||
int fd, mtu = 0, loopback;
|
||||
struct ifreq ifr;
|
||||
int tftp_ok = daemon->tftp_unlimited;
|
||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||
int dhcp_ok = 1;
|
||||
#ifdef HAVE_DHCP
|
||||
struct iname *tmp;
|
||||
#endif
|
||||
struct interface_list *ir = NULL;
|
||||
|
||||
/* check whether the interface IP has been added already
|
||||
we call this routine multiple times. */
|
||||
@@ -220,37 +209,25 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
/* implement wierd TFTP service rules */
|
||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
||||
if (strcmp(ir->interface, ifr.ifr_name) == 0)
|
||||
if (addr->sa.sa_family == AF_INET &&
|
||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||
{
|
||||
tftp_ok = 1;
|
||||
break;
|
||||
tftp_ok = 0;
|
||||
dhcp_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ir)
|
||||
{
|
||||
if (addr->sa.sa_family == AF_INET &&
|
||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||
{
|
||||
tftp_ok = 0;
|
||||
dhcp_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (addr->sa.sa_family == AF_INET6 &&
|
||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
|
||||
return 1;
|
||||
if (addr->sa.sa_family == AF_INET6 &&
|
||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* add to list */
|
||||
if ((iface = whine_malloc(sizeof(struct irec))))
|
||||
@@ -485,8 +462,7 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
|
||||
void create_wildcard_listeners(void)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
struct listener *l;
|
||||
int tftp_enabled = daemon->tftp_unlimited || daemon->tftp_interfaces;
|
||||
struct listener *l, *l6;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
@@ -496,7 +472,7 @@ void create_wildcard_listeners(void)
|
||||
addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.in.sin_port = htons(daemon->port);
|
||||
|
||||
l = create_listeners(&addr, tftp_enabled, 1);
|
||||
l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
@@ -506,11 +482,12 @@ void create_wildcard_listeners(void)
|
||||
addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_addr = in6addr_any;
|
||||
addr.in6.sin6_port = htons(daemon->port);
|
||||
|
||||
|
||||
l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
|
||||
if (l)
|
||||
l->next = create_listeners(&addr, tftp_enabled, 1);
|
||||
l->next = l6;
|
||||
else
|
||||
l = create_listeners(&addr, tftp_enabled, 1);
|
||||
l = l6;
|
||||
#endif
|
||||
|
||||
daemon->listeners = l;
|
||||
@@ -544,7 +521,7 @@ void create_bound_listeners(int dienow)
|
||||
|
||||
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
||||
if (!if_tmp->used &&
|
||||
(new = create_listeners(&if_tmp->addr, daemon->tftp_unlimited, dienow)))
|
||||
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
|
||||
{
|
||||
new->iface = NULL;
|
||||
new->next = daemon->listeners;
|
||||
|
||||
651
src/option.c
651
src/option.c
File diff suppressed because it is too large
Load Diff
11
src/radv.c
11
src/radv.c
@@ -119,7 +119,6 @@ void icmp6_packet(void)
|
||||
struct sockaddr_in6 from;
|
||||
unsigned char *packet;
|
||||
struct iname *tmp;
|
||||
struct dhcp_context *context;
|
||||
|
||||
/* Note: use outpacket for input buffer */
|
||||
msg.msg_control = control_u.control6;
|
||||
@@ -157,15 +156,9 @@ void icmp6_packet(void)
|
||||
if (tmp->name && (strcmp(tmp->name, interface) == 0))
|
||||
return;
|
||||
|
||||
/* weird libvirt-inspired access control */
|
||||
for (context = daemon->ra_contexts ? daemon->ra_contexts : daemon->dhcp6;
|
||||
context; context = context->next)
|
||||
if (!context->interface || strcmp(context->interface, interface) == 0)
|
||||
break;
|
||||
|
||||
if (!context || packet[1] != 0)
|
||||
if (packet[1] != 0)
|
||||
return;
|
||||
|
||||
|
||||
if (packet[0] == ICMP6_ECHO_REPLY)
|
||||
lease_ping_reply(&from.sin6_addr, packet, interface);
|
||||
else if (packet[0] == ND_ROUTER_SOLICIT)
|
||||
|
||||
45
src/tftp.c
45
src/tftp.c
@@ -18,7 +18,7 @@
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special);
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||
static void free_transfer(struct tftp_transfer *transfer);
|
||||
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
|
||||
static ssize_t tftp_err_oops(char *packet, char *file);
|
||||
@@ -48,7 +48,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
struct ifreq ifr;
|
||||
int is_err = 1, if_index = 0, mtu = 0, special = 0;
|
||||
int is_err = 1, if_index = 0, mtu = 0;
|
||||
#ifdef HAVE_DHCP
|
||||
struct iname *tmp;
|
||||
#endif
|
||||
@@ -61,7 +61,6 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
char *name = NULL;
|
||||
char *prefix = daemon->tftp_prefix;
|
||||
struct tftp_prefix *pref;
|
||||
struct interface_list *ir;
|
||||
|
||||
union {
|
||||
struct cmsghdr align; /* this ensures alignment */
|
||||
@@ -115,7 +114,6 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
{
|
||||
struct cmsghdr *cmptr;
|
||||
int check;
|
||||
struct interface_list *ir;
|
||||
|
||||
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
||||
return;
|
||||
@@ -200,24 +198,13 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
#endif
|
||||
check = iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name);
|
||||
|
||||
/* wierd TFTP service override */
|
||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
||||
if (strcmp(ir->interface, name) == 0)
|
||||
break;
|
||||
|
||||
if (!ir)
|
||||
{
|
||||
if (!daemon->tftp_unlimited || !check)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
/* allowed interfaces are the same as for DHCP */
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
return;
|
||||
/* allowed interfaces are the same as for DHCP */
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||
mtu = ifr.ifr_mtu;
|
||||
@@ -228,12 +215,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
/* check for per-interface prefix */
|
||||
for (pref = daemon->if_prefix; pref; pref = pref->next)
|
||||
if (strcmp(pref->interface, name) == 0)
|
||||
prefix = pref->prefix;
|
||||
|
||||
/* wierd TFTP interfaces disable special options. */
|
||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
||||
if (strcmp(ir->interface, name) == 0)
|
||||
special = 1;
|
||||
prefix = pref->prefix;
|
||||
}
|
||||
|
||||
if (listen->family == AF_INET)
|
||||
@@ -325,8 +307,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
{
|
||||
if (strcasecmp(opt, "blksize") == 0)
|
||||
{
|
||||
if ((opt = next(&p, end)) &&
|
||||
(special || !option_bool(OPT_TFTP_NOBLOCK)))
|
||||
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
|
||||
{
|
||||
transfer->blocksize = atoi(opt);
|
||||
if (transfer->blocksize < 1)
|
||||
@@ -363,7 +344,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
if (prefix[strlen(prefix)-1] != '/')
|
||||
strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||
|
||||
if (!special && option_bool(OPT_TFTP_APREF))
|
||||
if (option_bool(OPT_TFTP_APREF))
|
||||
{
|
||||
size_t oldlen = strlen(daemon->namebuff);
|
||||
struct stat statbuf;
|
||||
@@ -390,7 +371,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||
|
||||
/* check permissions and open file */
|
||||
if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
|
||||
if ((transfer->file = check_tftp_fileperm(&len, prefix)))
|
||||
{
|
||||
if ((len = get_block(packet, transfer)) == -1)
|
||||
len = tftp_err_oops(packet, daemon->namebuff);
|
||||
@@ -411,7 +392,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special)
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||
{
|
||||
char *packet = daemon->packet, *namebuff = daemon->namebuff;
|
||||
struct tftp_file *file;
|
||||
@@ -448,7 +429,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int spe
|
||||
goto perm;
|
||||
}
|
||||
/* in secure mode, must be owned by user running dnsmasq */
|
||||
else if (!special && option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
|
||||
else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
|
||||
goto perm;
|
||||
|
||||
/* If we're doing many tranfers from the same file, only
|
||||
|
||||
Reference in New Issue
Block a user