Compare commits

...

11 Commits

Author SHA1 Message Date
Simon Kelley
611ebc5f1e Fix broken caching of CNAME chains. 2012-07-16 16:23:46 +01:00
Simon Kelley
be0f45cdbc Typo fix. Thanks Wieland Hoffmann. 2012-07-16 13:35:25 +01:00
Simon Kelley
9b40cbf587 Fix FTBFS when TFTP disabled. 2012-07-13 19:58:26 +01:00
Simon Kelley
c4a7f90ebb Config parsing error-handling update. 2012-07-12 20:52:12 +01:00
Simon Kelley
9609baee41 Merge branch 'access_control' 2012-07-10 15:06:34 +01:00
Simon Kelley
395eb71931 Better log message when dhcp hosts|opts file cannot be read. 2012-07-06 22:07:05 +01:00
Simon Kelley
8bc4cecee6 Remove libvirt-inspired but never used access control features. 2012-07-03 21:04:11 +01:00
Simon Kelley
6b617c0d15 Logging library in Android build scaffold. 2012-06-29 22:11:26 +01:00
Simon Kelley
55d290a3bf Handle pid-file location in Android. 2012-06-29 20:58:32 +01:00
Simon Kelley
e17b4b3871 Fix build-failure with -DNO_DHCP6. 2012-06-28 21:44:30 +01:00
Simon Kelley
236e072cab Typo in BSD-only code. 2012-06-26 21:33:01 +01:00
16 changed files with 477 additions and 648 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -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