Compare commits

..
10 Commits
21 changed files with 570 additions and 275 deletions

No files matched your search

+22 -1
View File
@@ -18,8 +18,29 @@ version 2.67
Add --synth-domain. Thanks to Vishvananda Ishaya for
suggesting this.
Fix failure to compile ipset.c if old kernel headers are
in use. Thanks to Eugene Rudoy for pointing this out.
Handle IPv4 interface-address labels in Linux. These are
often used to emulate the old IP-alias addresses. Before,
using --interface=eth0 would service all the addresses of
eth0, including ones configured as aliases, which appear
in ifconfig as eth0:0. Now, only addresses with the label
eth0 are active. This is not backwards compatible: if you
want to continue to bind the aliases too, you need to add
eg. --interface=eth0:0 to the config.
Fix "failed to set SO_BINDTODEVICE on DHCP socket: Socket
operation on non-socket" error on startup with
configurations which have exactly one --interface option
and do RA but _not_ DHCPv6. Thanks to Trever Adams for the
bug report.
Generalise --interface-name to cope with IPv6 addresses
and multiple addresses per interface per address family.
version 2.66
Add the ability to act as an authoritative DNS
server. Dnsmasq can now answer queries from the wider 'net
+7 -1
View File
@@ -2,7 +2,13 @@ dnsmasq (2.67-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 19 Apr 2013 10:23:31 +0000
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 20 May 2013 11:50:22 +0000
dnsmasq (2.66-2) unstable; urgency=low
* Fix error on startup with some configs. (closes: #709010)
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 20 May 2013 11:46:11 +0000
dnsmasq (2.66-1) unstable; urgency=low
+7 -6
View File
@@ -519,17 +519,18 @@ the name. More than one name may be associated with an interface
address by repeating the flag; in that case the first instance is used
for the reverse address-to-name mapping.
.TP
.B --synth-domain=<domain>,<address range>
.B --synth-domain=<domain>,<address range>[,<prefix>]
Create artificial A/AAAA and PTR records for an address range. The
records use the address, with periods (or colons for IPv6) replaced
with dashes.
An example should make this clearer.
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24
will result in a query for 192-168-0-56.thekelleys.org.uk returning
192.168.0.56 and a reverse query vice versa. The same applies to IPv6, but IPv6 addresses may start with '::'
but DNS labels may not start with '-' so in this case a zero is added
in front of the label. ::1 becomes 0--1.
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal-
will result in a query for internal-192-168-0-56.thekelleys.org.uk returning
192.168.0.56 and a reverse query vice versa. The same applies to IPv6,
but IPv6 addresses may start with '::'
but DNS labels may not start with '-' so in this case if no prefix is
configured a zero is added in front of the label. ::1 becomes 0--1.
The address range can be of the form
<ip address>,<ip address> or <ip address>/<netmask>
+90 -46
View File
@@ -152,32 +152,55 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
auth = 0;
continue;
}
if (flag == F_IPV4)
{
for (intr = daemon->int_names; intr; intr = intr->next)
{
if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
break;
else
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
intr = NULL;
if (intr)
{
if (in_zone(zone, intr->name, NULL))
{
found = 1;
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", intr->name))
anscount++;
}
if (flag == F_IPV4)
for (intr = daemon->int_names; intr; intr = intr->next)
{
struct addrlist *addrlist;
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
break;
if (addrlist)
break;
else
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
#ifdef HAVE_IPV6
else if (flag == F_IPV6)
for (intr = daemon->int_names; intr; intr = intr->next)
{
struct addrlist *addrlist;
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
break;
if (addrlist)
break;
else
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
#endif
if (intr)
{
if (in_zone(zone, intr->name, NULL))
{
found = 1;
log_query(flag| F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", intr->name))
anscount++;
}
}
if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
do {
strcpy(name, cache_get_name(crecp));
@@ -321,20 +344,37 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
anscount++;
}
}
if (qtype == T_A)
flag = F_IPV4;
#ifdef HAVE_IPV6
if (qtype == T_AAAA)
flag = F_IPV6;
#endif
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
{
struct addrlist *addrlist;
addrlist = intr->addr4;
#ifdef HAVE_IPV6
if (qtype == T_AAAA)
addrlist = intr->addr6;
#endif
nxdomain = 0;
if (qtype == T_A && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
{
found = 1;
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", &addr))
anscount++;
}
for (; addrlist; addrlist = addrlist->next)
if (filter_constructed_dhcp(zone, flag, &addrlist->addr))
{
found = 1;
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &addrlist->addr))
anscount++;
}
}
for (a = daemon->cnames; a; a = a->next)
@@ -356,14 +396,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
goto cname_restart;
}
if (qtype == T_A)
flag = F_IPV4;
#ifdef HAVE_IPV6
if (qtype == T_AAAA)
flag = F_IPV6;
#endif
if (!cut)
{
nxdomain = 0;
@@ -634,20 +666,32 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (intr = daemon->int_names; intr; intr = intr->next)
if (in_zone(zone, intr->name, &cut) && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
if (in_zone(zone, intr->name, &cut))
{
struct addrlist *addrlist;
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addr))
anscount++;
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
if (filter_constructed_dhcp(zone, F_IPV4, &addrlist->addr) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
anscount++;
#ifdef HAVE_IPV6
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
if (filter_constructed_dhcp(zone, F_IPV6, &addrlist->addr) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
anscount++;
#endif
/* restore config data */
if (cut)
*cut = '.';
}
for (a = daemon->cnames; a; a = a->next)
if (in_zone(zone, a->alias, &cut))
{
+1 -1
View File
@@ -123,7 +123,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
else
broadcast.s_addr = 0;
if (!((*callback)(addr, iface_index, netmask, broadcast, parm)))
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
goto err;
}
#ifdef HAVE_IPV6
+4 -4
View File
@@ -279,12 +279,12 @@ HAVE_SOCKADDR_SA_LEN
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY)
# define HAVE_IPV6
# define ADDRSTRLEN INET6_ADDRSTRLEN
#elif defined(INET_ADDRSTRLEN)
#else
# if !defined(INET_ADDRSTRLEN)
# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
# endif
# undef HAVE_IPV6
# define ADDRSTRLEN INET_ADDRSTRLEN
#else
# undef HAVE_IPV6
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
#endif
+9 -5
View File
@@ -28,9 +28,9 @@ struct match_param {
struct in_addr netmask, broadcast, addr;
};
static int complete_context(struct in_addr local, int if_index,
static int complete_context(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam);
static int check_listen_addrs(struct in_addr local, int if_index,
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam);
static int make_fd(int port)
@@ -287,7 +287,7 @@ void dhcp_packet(time_t now, int pxe_fd)
iface_addr = match.addr;
/* make sure secondary address gets priority in case
there is more than one address on the interface in the same subnet */
complete_context(match.addr, iface_index, match.netmask, match.broadcast, &parm);
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
}
if (!iface_enumerate(AF_INET, &parm, complete_context))
@@ -411,12 +411,14 @@ void dhcp_packet(time_t now, int pxe_fd)
}
/* check against secondary interface addresses */
static int check_listen_addrs(struct in_addr local, int if_index,
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
struct match_param *param = vparam;
struct iname *tmp;
(void) label;
if (if_index == param->ind)
{
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
@@ -444,11 +446,13 @@ static int check_listen_addrs(struct in_addr local, int if_index,
Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
static int complete_context(struct in_addr local, int if_index,
static int complete_context(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
struct dhcp_context *context;
struct iface_param *param = vparam;
(void)label;
for (context = daemon->dhcp; context; context = context->next)
{
+8 -5
View File
@@ -225,7 +225,7 @@ int main (int argc, char **argv)
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
#endif
if (!enumerate_interfaces())
if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -248,7 +248,7 @@ int main (int argc, char **argv)
#endif
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
if (daemon->dhcp6)
if (daemon->doing_dhcp6)
bindtodevice(daemon->dhcp6fd);
#endif
}
@@ -820,12 +820,15 @@ int main (int argc, char **argv)
now = dnsmasq_time();
check_log_writer(&wset);
/* prime. */
enumerate_interfaces(1);
/* Check the interfaces to see if any have exited DAD state
and if so, bind the address. */
if (is_dad_listeners())
{
enumerate_interfaces();
enumerate_interfaces(0);
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
create_bound_listeners(0);
}
@@ -1369,7 +1372,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
/* In full wildcard mode, need to refresh interface list.
This happens automagically in CLEVERBIND */
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
enumerate_interfaces(0);
/* if we can find the arrival interface, check it's one that's allowed */
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
+10 -3
View File
@@ -307,6 +307,13 @@ struct host_record {
struct interface_name {
char *name; /* domain name */
char *intr; /* interface name */
struct addrlist {
struct all_addr addr;
struct addrlist *next;
} *addr4;
#ifdef HAVE_IPV6
struct addrlist *addr6;
#endif
struct interface_name *next;
};
@@ -673,7 +680,7 @@ struct dhcp_bridge {
};
struct cond_domain {
char *domain;
char *domain, *prefix;
struct in_addr start, end;
#ifdef HAVE_IPV6
struct in6_addr start6, end6;
@@ -1024,15 +1031,15 @@ int random_sock(int family);
void pre_allocate_sfds(void);
int reload_servers(char *fname);
void check_servers(void);
int enumerate_interfaces();
int enumerate_interfaces(int reset);
void create_wildcard_listeners(void);
void create_bound_listeners(int die);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
int label_exception(int index, int family, struct all_addr *addr);
int fix_fd(int fd);
int tcp_interface(int fd, int af);
struct in_addr get_ifaddr(char *intr);
#ifdef HAVE_IPV6
int set_ipv6pktinfo(int fd);
#endif
+74 -42
View File
@@ -34,48 +34,69 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
prot = AF_INET6;
#endif
/* NB, must not alter name if we return zero */
for (p = name; *p; p++)
for (c = daemon->synth_domains; c; c = c->next)
{
char c = *p;
int found = 0;
char *tail, *pref;
if ((c >='0' && c <= '9') || c == '-')
for (tail = name, pref = c->prefix; *tail != 0 && pref && *pref != 0; tail++, pref++)
{
unsigned int c1 = (unsigned char) *pref;
unsigned int c2 = (unsigned char) *tail;
if (c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
if (c2 >= 'A' && c2 <= 'Z')
c2 += 'a' - 'A';
if (c1 != c2)
break;
}
if (pref && *pref != 0)
continue; /* prefix match fail */
/* NB, must not alter name if we return zero */
for (p = tail; *p; p++)
{
char c = *p;
if ((c >='0' && c <= '9') || c == '-')
continue;
#ifdef HAVE_IPV6
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
continue;
#endif
break;
}
if (*p != '.')
continue;
#ifdef HAVE_IPV6
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
continue;
#endif
*p = 0;
break;
}
if (*p != '.')
return 0;
*p = 0;
for (p = name; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
#ifdef HAVE_IPV6
else
*p = ':';
else
*p = ':';
#endif
}
if (inet_pton(prot, name, addr))
for (c = daemon->synth_domains; c; c = c->next)
if (hostname_isequal(c->domain, p+1))
}
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
{
if (prot == AF_INET)
{
if (!c->is6 &&
ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
break;
found = 1;
}
#ifdef HAVE_IPV6
else
@@ -86,20 +107,23 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
break;
found = 1;
}
#endif
}
/* restore name */
for (p = tail; *p; p++)
if (*p == '.' || *p == ':')
*p = '-';
*p = '.';
if (found)
return 1;
}
/* restore name */
for (p = name; *p; p++)
if (*p == '.' || *p == ':')
*p = '-';
*p = '.';
return (c != NULL);
return 0;
}
@@ -111,7 +135,11 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
{
char *p;
inet_ntop(AF_INET, &addr->addr.addr4, name, ADDRSTRLEN);
*name = 0;
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
for (p = name; *p; p++)
if (*p == '.')
*p = '-';
@@ -127,11 +155,15 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
{
char *p;
inet_ntop(AF_INET6, &addr->addr.addr6, name, ADDRSTRLEN);
*name = 0;
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
/* IPv6 presentation address can start with ":", but valid domain names
cannot start with "-" so prepend a zero in that case. */
if (*name == ':')
if (!c->prefix && *name == ':')
{
*name = '0';
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
+4 -3
View File
@@ -788,8 +788,9 @@ void receive_query(struct listener *listen, time_t now)
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name))
enumerate_interfaces(0);
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
!label_exception(if_index, listen->family, &dst_addr))
return;
}
@@ -807,7 +808,7 @@ void receive_query(struct listener *listen, time_t now)
/* interface may be new */
if (!iface && !option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
enumerate_interfaces(0);
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->addr.sa.sa_family == AF_INET &&
+39 -15
View File
@@ -26,9 +26,12 @@
#include <arpa/inet.h>
#include <linux/version.h>
#include <linux/netlink.h>
#include <linux/netfilter/nfnetlink.h>
#ifndef NFNL_SUBSYS_IPSET
/* We want to be able to compile against old header files
Kernel version is handled at run-time. */
#define NFNL_SUBSYS_IPSET 6
#define IPSET_ATTR_DATA 7
#define IPSET_ATTR_IP 1
#define IPSET_ATTR_IPADDR_IPV4 1
@@ -39,10 +42,31 @@
#define IPSET_CMD_DEL 10
#define IPSET_MAXNAMELEN 32
#define IPSET_PROTOCOL 6
#else
#include <linux/netfilter/ipset/ip_set.h>
#ifndef NFNETLINK_V0
#define NFNETLINK_V0 0
#endif
#ifndef NLA_F_NESTED
#define NLA_F_NESTED (1 << 15)
#endif
#ifndef NLA_F_NET_BYTEORDER
#define NLA_F_NET_BYTEORDER (1 << 14)
#endif
struct my_nlattr {
__u16 nla_len;
__u16 nla_type;
};
struct my_nfgenmsg {
__u8 nfgen_family; /* AF_xxx */
__u8 version; /* nfnetlink version */
__be16 res_id; /* resource id */
};
/* data structure size in here is fixed */
#define BUFF_SZ 256
@@ -53,11 +77,11 @@ static char *buffer;
static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
{
struct nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
uint16_t payload_len = NL_ALIGN(sizeof(struct nlattr)) + len;
struct my_nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
uint16_t payload_len = NL_ALIGN(sizeof(struct my_nlattr)) + len;
attr->nla_type = type;
attr->nla_len = payload_len;
memcpy((void *)attr + NL_ALIGN(sizeof(struct nlattr)), data, len);
memcpy((void *)attr + NL_ALIGN(sizeof(struct my_nlattr)), data, len);
nlh->nlmsg_len += NL_ALIGN(payload_len);
}
@@ -93,8 +117,8 @@ void ipset_init(void)
static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, int remove)
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfg;
struct nlattr *nested[2];
struct my_nfgenmsg *nfg;
struct my_nlattr *nested[2];
uint8_t proto;
int addrsz = INADDRSZ;
ssize_t rc;
@@ -117,8 +141,8 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
nlh->nlmsg_type = (remove ? IPSET_CMD_DEL : IPSET_CMD_ADD) | (NFNL_SUBSYS_IPSET << 8);
nlh->nlmsg_flags = NLM_F_REQUEST;
nfg = (struct nfgenmsg *)(buffer + nlh->nlmsg_len);
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nfgenmsg));
nfg = (struct my_nfgenmsg *)(buffer + nlh->nlmsg_len);
nlh->nlmsg_len += NL_ALIGN(sizeof(struct my_nfgenmsg));
nfg->nfgen_family = af;
nfg->version = NFNETLINK_V0;
nfg->res_id = htons(0);
@@ -126,11 +150,11 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
proto = IPSET_PROTOCOL;
add_attr(nlh, IPSET_ATTR_PROTOCOL, sizeof(proto), &proto);
add_attr(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
nested[0] = (struct nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nlattr));
nested[0] = (struct my_nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
nlh->nlmsg_len += NL_ALIGN(sizeof(struct my_nlattr));
nested[0]->nla_type = NLA_F_NESTED | IPSET_ATTR_DATA;
nested[1] = (struct nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nlattr));
nested[1] = (struct my_nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
nlh->nlmsg_len += NL_ALIGN(sizeof(struct my_nlattr));
nested[1]->nla_type = NLA_F_NESTED | IPSET_ATTR_IP;
add_attr(nlh,
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
+2 -1
View File
@@ -345,11 +345,12 @@ void lease_update_file(time_t now)
}
static int find_interface_v4(struct in_addr local, int if_index,
static int find_interface_v4(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
struct dhcp_lease *lease;
(void) label;
(void) broadcast;
(void) vparam;
+10 -4
View File
@@ -193,7 +193,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
{
/* May be multicast arriving async */
if (nl_async(h))
newaddr = 1;
{
newaddr = 1;
enumerate_interfaces(1); /* reset */
}
}
else if (h->nlmsg_type == NLMSG_DONE)
{
@@ -215,7 +218,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
if (ifa->ifa_family == AF_INET)
{
struct in_addr netmask, addr, broadcast;
char *label = NULL;
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
addr.s_addr = 0;
broadcast.s_addr = 0;
@@ -226,12 +230,14 @@ int iface_enumerate(int family, void *parm, int (*callback)())
addr = *((struct in_addr *)(rta+1));
else if (rta->rta_type == IFA_BROADCAST)
broadcast = *((struct in_addr *)(rta+1));
else if (rta->rta_type == IFA_LABEL)
label = RTA_DATA(rta);
rta = RTA_NEXT(rta, len1);
}
if (addr.s_addr && callback_ok)
if (!((*callback)(addr, ifa->ifa_index, netmask, broadcast, parm)))
if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm)))
callback_ok = 0;
}
#ifdef HAVE_IPV6
@@ -394,7 +400,7 @@ static int nl_async(struct nlmsghdr *h)
static void nl_newaddress(time_t now)
{
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->doing_ra)
enumerate_interfaces();
enumerate_interfaces(0);
if (option_bool(OPT_CLEVERBIND))
create_bound_listeners(0);
+155 -59
View File
@@ -99,6 +99,8 @@ int indextoname(int fd, int index, char *name)
int indextoname(int fd, int index, char *name)
{
(void)fd;
if (index == 0 || !if_indextoname(index, name))
return 0;
@@ -204,11 +206,36 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
return 0;
}
static int iface_allowed(struct irec **irecp, int if_index,
/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
on the relevant address, but the name of the arrival interface, derived from the
index won't match the config. Check that we found an interface address for the arrival
interface: daemon->interfaces must be up-to-date. */
int label_exception(int index, int family, struct all_addr *addr)
{
struct irec *iface;
/* labels only supported on IPv4 addresses. */
if (family != AF_INET)
return 0;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
return 1;
return 0;
}
struct iface_param {
struct addrlist *spare;
int fd;
};
static int iface_allowed(struct iface_param *param, int if_index, char *label,
union mysockaddr *addr, struct in_addr netmask, int dad)
{
struct irec *iface;
int fd, mtu = 0, loopback;
int mtu = 0, loopback;
struct ifreq ifr;
int tftp_ok = !!option_bool(OPT_TFTP);
int dhcp_ok = 1;
@@ -217,39 +244,72 @@ static int iface_allowed(struct irec **irecp, int if_index,
struct iname *tmp;
#endif
if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
return 0;
loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (loopback)
dhcp_ok = 0;
if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
if (!label)
label = ifr.ifr_name;
/* Update addresses from interface_names. These are a set independent
of the set we're listening on. */
#ifdef HAVE_IPV6
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
#endif
{
struct interface_name *int_name;
struct addrlist *al;
for (int_name = daemon->int_names; int_name; int_name = int_name->next)
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
{
if (param->spare)
{
al = param->spare;
param->spare = al->next;
}
else
al = whine_malloc(sizeof(struct addrlist));
if (al)
{
if (addr->sa.sa_family == AF_INET)
{
al->addr.addr.addr4 = addr->in.sin_addr;
al->next = int_name->addr4;
int_name->addr4 = al;
}
#ifdef HAVE_IPV6
else
{
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->next = int_name->addr6;
int_name->addr6 = al;
}
#endif
}
}
}
/* check whether the interface IP has been added already
we call this routine multiple times. */
for (iface = *irecp; iface; iface = iface->next)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr))
{
iface->dad = dad;
return 1;
}
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
!indextoname(fd, if_index, ifr.ifr_name) ||
ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
{
if (fd != -1)
{
int errsave = errno;
close(fd);
errno = errsave;
}
return 0;
}
loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (loopback)
dhcp_ok = 0;
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
close(fd);
/* If we are restricting the set of interfaces to use, make
/* If we are restricting the set of interfaces to use, make
sure that loopback interfaces are in that set. */
if (daemon->if_names && loopback)
{
@@ -273,12 +333,12 @@ static int iface_allowed(struct irec **irecp, int if_index,
}
if (addr->sa.sa_family == AF_INET &&
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
return 1;
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
return 1;
#endif
@@ -313,8 +373,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
{
strcpy(iface->name, ifr.ifr_name);
iface->next = *irecp;
*irecp = iface;
iface->next = daemon->interfaces;
daemon->interfaces = iface;
return 1;
}
free(iface);
@@ -348,11 +408,11 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = if_index;
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, !!(flags & IFACE_TENTATIVE));
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
}
#endif
static int iface_allowed_v4(struct in_addr local, int if_index,
static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
union mysockaddr addr;
@@ -366,17 +426,73 @@ static int iface_allowed_v4(struct in_addr local, int if_index,
addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port);
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, 0);
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, 0);
}
int enumerate_interfaces(void)
int enumerate_interfaces(int reset)
{
static struct addrlist *spare = NULL;
static int done = 0;
struct iface_param param;
int errsave, ret = 1;
struct addrlist *addr, *tmp;
struct interface_name *intname;
/* DO this max once per select cycle */
if (reset)
{
done = 0;
return 1;
}
if (done)
return 1;
done = 1;
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0;
/* remove addresses stored against interface_names */
for (intname = daemon->int_names; intname; intname = intname->next)
{
for (addr = intname->addr4; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
intname->addr4 = NULL;
#ifdef HAVE_IPV6
if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6))
return 0;
for (addr = intname->addr6; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
intname->addr6 = NULL;
#endif
}
param.spare = spare;
#ifdef HAVE_IPV6
ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
#endif
return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4);
if (ret)
ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
errsave = errno;
close(param.fd);
errno = errsave;
spare = param.spare;
return ret;
}
/* set NONBLOCK bit on fd: See Stevens 16.6 */
@@ -948,7 +1064,7 @@ void check_servers(void)
/* interface may be new since startup */
if (!option_bool(OPT_NOWILD))
enumerate_interfaces();
enumerate_interfaces(0);
for (new = daemon->servers; new; new = tmp)
{
@@ -1156,27 +1272,7 @@ int reload_servers(char *fname)
}
/* Use an IPv4 listener socket for ioctling */
struct in_addr get_ifaddr(char *intr)
{
struct listener *l;
struct ifreq ifr;
struct sockaddr_in ret;
ret.sin_addr.s_addr = -1;
for (l = daemon->listeners;
l && (l->family != AF_INET || l->fd == -1);
l = l->next);
strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
ifr.ifr_addr.sa_family = AF_INET;
if (l && ioctl(l->fd, SIOCGIFADDR, &ifr) != -1)
memcpy(&ret, &ifr.ifr_addr, sizeof(ret));
return ret.sin_addr;
}
+59 -46
View File
@@ -408,7 +408,7 @@ static struct {
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
@@ -660,7 +660,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
scope_id = split_chr(arg, '%');
#endif
if ((addr->in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
{
addr->in.sin_port = htons(serv_port);
addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
@@ -675,7 +675,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
if (flags)
*flags |= SERV_HAS_SOURCE;
source_addr->in.sin_port = htons(source_port);
if ((source_addr->in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
{
#if defined(SO_BINDTODEVICE)
source_addr->in.sin_addr.s_addr = INADDR_ANY;
@@ -1031,7 +1031,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
cp = comma;
comma = split(cp);
slash = split_chr(cp, '/');
in.s_addr = inet_addr(cp);
inet_pton(AF_INET, cp, &in);
if (!slash)
{
memcpy(op, &in, INADDRSZ);
@@ -1576,7 +1576,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
comma = split(arg);
new->name = NULL;
unhide_metas(arg);
if ((new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
new->addr.sa.sa_family = AF_INET;
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
@@ -1707,6 +1707,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
char *netpart;
new->prefix = NULL;
unhide_metas(comma);
if ((netpart = split_chr(comma, '/')))
{
@@ -1723,26 +1725,30 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->end.s_addr = new->start.s_addr | htonl(mask);
if (arg)
{
/* generate the equivalent of
local=/<domain>/
local=/xxx.yyy.zzz.in-addr.arpa/ */
if (strcmp(arg, "local") != 0 ||
option != 's' ||
(msize != 8 && msize != 16 && msize != 24))
if (option != 's')
{
if (!(new->prefix = canonicalise_opt(arg)) ||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
ret_err(_("bad prefix"));
}
else if (strcmp(arg, "local") != 0 ||
(msize != 8 && msize != 16 && msize != 24))
ret_err(gen_err);
else
{
/* generate the equivalent of
local=/<domain>/
local=/xxx.yyy.zzz.in-addr.arpa/ */
struct server *serv = opt_malloc(sizeof(struct server));
in_addr_t a = ntohl(new->start.s_addr) >> 8;
char *p;
memset(serv, 0, sizeof(struct server));
serv->domain = d;
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
serv->next = daemon->servers;
daemon->servers = serv;
serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server));
p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
@@ -1754,7 +1760,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
p += sprintf(p, "%d.", a & 0xff);
a = a >> 8;
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
serv->next = daemon->servers;
daemon->servers = serv;
@@ -1767,11 +1773,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
u64 mask = (1LLU << (128 - msize)) - 1LLU;
u64 addrpart = addr6part(&new->start6);
new->is6 = 1;
/* prefix==64 overflows the mask calculation above */
if (msize == 64)
mask = (u64)-1LL;
new->end6 = new->start6;
setaddr6part(&new->start6, addrpart & ~mask);
setaddr6part(&new->end6, addrpart | mask);
@@ -1780,16 +1786,19 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err(gen_err);
else if (arg)
{
/* generate the equivalent of
local=/<domain>/
local=/xxx.yyy.zzz.ip6.arpa/ */
if (strcmp(arg, "local") != 0 ||
option != 's' ||
((msize & 4) != 0))
if (option != 's')
{
if (!(new->prefix = canonicalise_opt(arg)) ||
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
ret_err(_("bad prefix"));
}
else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
ret_err(gen_err);
else
{
/* generate the equivalent of
local=/<domain>/
local=/xxx.yyy.zzz.ip6.arpa/ */
struct server *serv = opt_malloc(sizeof(struct server));
char *p;
@@ -1918,7 +1927,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
struct in_addr addr;
unhide_metas(arg);
if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
{
struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
baddr->next = daemon->bogus_addr;
@@ -1936,7 +1945,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
struct iname *new = opt_malloc(sizeof(struct iname));
comma = split(arg);
unhide_metas(arg);
if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
{
new->addr.sa.sa_family = AF_INET;
new->addr.in.sin_port = 0;
@@ -2360,7 +2369,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
if (k >= 3 && strchr(a[2], '.') &&
((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
(inet_pton(AF_INET, a[2], &new->netmask) > 0))
{
new->flags |= CONTEXT_NETMASK;
leasepos = 3;
@@ -2369,7 +2378,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
if (k >= 4 && strchr(a[3], '.') &&
((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
(inet_pton(AF_INET, a[3], &new->broadcast) > 0))
{
new->flags |= CONTEXT_BRDCAST;
leasepos = 4;
@@ -2599,7 +2608,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
}
}
else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
{
struct dhcp_config *configs;
@@ -2796,17 +2805,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (comma)
{
unhide_metas(comma);
if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) {
/*
* The user may have specified the tftp hostname here.
* save it so that it can be resolved/looked up during
* actual dhcp_reply().
*/
tftp_sname = opt_string_alloc(comma);
dhcp_next_server.s_addr = 0;
}
if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
{
/*
* The user may have specified the tftp hostname here.
* save it so that it can be resolved/looked up during
* actual dhcp_reply().
*/
tftp_sname = opt_string_alloc(comma);
dhcp_next_server.s_addr = 0;
}
}
}
@@ -2819,7 +2828,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->boot_config;
daemon->boot_config = new;
}
break;
}
@@ -3135,7 +3144,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
while (arg) {
struct addr_list *new = opt_malloc(sizeof(struct addr_list));
comma = split(arg);
if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
ret_err(_("bad dhcp-proxy address"));
new->next = daemon->override_relays;
daemon->override_relays = new;
@@ -3178,15 +3187,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
dash = split_chr(a[0], '-');
if ((k < 2) ||
((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
(!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
(!(inet_pton(AF_INET, a[1], &new->out) > 0)))
option = '?';
if (k == 3)
new->mask.s_addr = inet_addr(a[2]);
inet_pton(AF_INET, a[2], &new->mask);
if (dash &&
((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
(!(inet_pton(AF_INET, dash, &new->end) > 0) ||
!is_same_net(new->in, new->end, new->mask) ||
ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
ret_err(_("invalid alias range"));
@@ -3206,6 +3215,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new = opt_malloc(sizeof(struct interface_name));
new->next = NULL;
new->addr4 = NULL;
#ifdef HAVE_IPV6
new->addr6 = NULL;
#endif
/* Add to the end of the list, so that first name
of an interface is used for PTR lookups. */
for (up = &daemon->int_names; *up; up = &((*up)->next));
+2 -2
View File
@@ -300,9 +300,9 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
}
}
if (!done_dns)
if (daemon->port == NAMESERVER_PORT && !done_dns)
{
/* default == us. */
/* default == us, as long as we are supplying DNS service. */
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char(3);
put_opt6_short(0);
+54 -23
View File
@@ -1450,19 +1450,42 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (is_arpa == F_IPV4)
for (intr = daemon->int_names; intr; intr = intr->next)
{
if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
struct addrlist *addrlist;
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
break;
if (addrlist)
break;
else
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
#ifdef HAVE_IPV6
else if (is_arpa == F_IPV6)
for (intr = daemon->int_names; intr; intr = intr->next)
{
struct addrlist *addrlist;
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
break;
if (addrlist)
break;
else
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
#endif
if (intr)
{
ans = 1;
if (!dryrun)
{
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
T_PTR, C_IN, "d", intr->name))
@@ -1546,7 +1569,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
{
unsigned short type = T_A;
struct interface_name *intr;
if (flag == F_IPV6)
#ifdef HAVE_IPV6
type = T_AAAA;
@@ -1595,31 +1619,38 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
}
/* interface name stuff */
if (qtype == T_A)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
break;
if (intr)
{
struct interface_name *intr;
struct addrlist *addrlist;
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
break;
enumerate_interfaces(0);
if (intr)
addrlist = intr->addr4;
#ifdef HAVE_IPV6
if (type == T_AAAA)
addrlist = intr->addr6;
#endif
ans = 1;
if (!dryrun)
{
ans = 1;
if (!dryrun)
{
if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
else
{
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL, type, C_IN, "4", &addr))
anscount++;
}
}
continue;
if (!addrlist)
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
else
for (; addrlist; addrlist = addrlist->next)
{
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL, type, C_IN,
type == T_A ? "4" : "6", &addrlist->addr))
anscount++;
}
}
continue;
}
cname_restart:
+1 -1
View File
@@ -1072,7 +1072,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
Have to set override to make sure we echo back the correct server-id */
struct irec *intr;
enumerate_interfaces();
enumerate_interfaces(0);
for (intr = daemon->interfaces; intr; intr = intr->next)
if (intr->addr.sa.sa_family == AF_INET &&
+3 -2
View File
@@ -201,8 +201,9 @@ void tftp_request(struct listener *listen, time_t now)
if (!iface_check(listen->family, &addra, name, NULL))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name))
enumerate_interfaces(0);
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
!label_exception(if_index, listen->family, &addra) )
return;
}
+9 -5
View File
@@ -142,19 +142,23 @@ static int check_name(char *in)
int legal_hostname(char *name)
{
char c;
int first;
if (!check_name(name))
return 0;
for (; (c = *name); name++)
for (first = 1; (c = *name); name++, first = 0)
/* check for legal char a-z A-Z 0-9 - _ . */
{
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '-' || c == '_')
(c >= 'a' && c <= 'z'))
continue;
if (!first &&
((c >= '0' && c <= '9') ||
c == '-' || c == '_'))
continue;
/* end of hostname part */
if (c == '.')
return 1;