mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
3
Commits
v2.67test4
...
v2.67test5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63fd27e35f | ||
|
|
115ac3e4d7 | ||
|
|
cfcad42ff1 |
No files matched your search
@@ -31,7 +31,16 @@ version 2.67
|
|||||||
want to continue to bind the aliases too, you need to add
|
want to continue to bind the aliases too, you need to add
|
||||||
eg. --interface=eth0:0 to the config.
|
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
|
version 2.66
|
||||||
Add the ability to act as an authoritative DNS
|
Add the ability to act as an authoritative DNS
|
||||||
server. Dnsmasq can now answer queries from the wider 'net
|
server. Dnsmasq can now answer queries from the wider 'net
|
||||||
|
|||||||
Vendored
+7
-1
@@ -2,7 +2,13 @@ dnsmasq (2.67-1) unstable; urgency=low
|
|||||||
|
|
||||||
* New upstream.
|
* 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
|
dnsmasq (2.66-1) unstable; urgency=low
|
||||||
|
|
||||||
|
|||||||
+90
-46
@@ -152,32 +152,55 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
auth = 0;
|
auth = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag == F_IPV4)
|
intr = NULL;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intr)
|
if (flag == F_IPV4)
|
||||||
{
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
if (in_zone(zone, intr->name, NULL))
|
{
|
||||||
{
|
struct addrlist *addrlist;
|
||||||
found = 1;
|
|
||||||
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
||||||
daemon->auth_ttl, NULL,
|
break;
|
||||||
T_PTR, C_IN, "d", intr->name))
|
|
||||||
anscount++;
|
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)))
|
if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
|
||||||
do {
|
do {
|
||||||
strcpy(name, cache_get_name(crecp));
|
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++;
|
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)
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
if (hostname_isequal(name, intr->name))
|
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;
|
nxdomain = 0;
|
||||||
if (qtype == T_A && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
|
|
||||||
{
|
for (; addrlist; addrlist = addrlist->next)
|
||||||
found = 1;
|
if (filter_constructed_dhcp(zone, flag, &addrlist->addr))
|
||||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
{
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
found = 1;
|
||||||
daemon->auth_ttl, NULL, T_A, C_IN, "4", &addr))
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||||
anscount++;
|
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)
|
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;
|
goto cname_restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_A)
|
|
||||||
flag = F_IPV4;
|
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (qtype == T_AAAA)
|
|
||||||
flag = F_IPV6;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!cut)
|
if (!cut)
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
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)
|
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)
|
if (cut)
|
||||||
*cut = 0;
|
*cut = 0;
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
|
||||||
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addr))
|
if (filter_constructed_dhcp(zone, F_IPV4, &addrlist->addr) &&
|
||||||
anscount++;
|
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 */
|
/* restore config data */
|
||||||
if (cut)
|
if (cut)
|
||||||
*cut = '.';
|
*cut = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
if (in_zone(zone, a->alias, &cut))
|
if (in_zone(zone, a->alias, &cut))
|
||||||
{
|
{
|
||||||
|
|||||||
+8
-5
@@ -225,7 +225,7 @@ int main (int argc, char **argv)
|
|||||||
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
|
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!enumerate_interfaces())
|
if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
|
||||||
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
||||||
@@ -248,7 +248,7 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
|
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
|
||||||
if (daemon->dhcp6)
|
if (daemon->doing_dhcp6)
|
||||||
bindtodevice(daemon->dhcp6fd);
|
bindtodevice(daemon->dhcp6fd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -820,12 +820,15 @@ int main (int argc, char **argv)
|
|||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
check_log_writer(&wset);
|
check_log_writer(&wset);
|
||||||
|
|
||||||
|
/* prime. */
|
||||||
|
enumerate_interfaces(1);
|
||||||
|
|
||||||
/* Check the interfaces to see if any have exited DAD state
|
/* Check the interfaces to see if any have exited DAD state
|
||||||
and if so, bind the address. */
|
and if so, bind the address. */
|
||||||
if (is_dad_listeners())
|
if (is_dad_listeners())
|
||||||
{
|
{
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
|
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
|
||||||
create_bound_listeners(0);
|
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.
|
/* In full wildcard mode, need to refresh interface list.
|
||||||
This happens automagically in CLEVERBIND */
|
This happens automagically in CLEVERBIND */
|
||||||
if (!option_bool(OPT_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 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 &&
|
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
|
||||||
|
|||||||
+8
-2
@@ -307,6 +307,13 @@ struct host_record {
|
|||||||
struct interface_name {
|
struct interface_name {
|
||||||
char *name; /* domain name */
|
char *name; /* domain name */
|
||||||
char *intr; /* interface 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;
|
struct interface_name *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1024,7 +1031,7 @@ int random_sock(int family);
|
|||||||
void pre_allocate_sfds(void);
|
void pre_allocate_sfds(void);
|
||||||
int reload_servers(char *fname);
|
int reload_servers(char *fname);
|
||||||
void check_servers(void);
|
void check_servers(void);
|
||||||
int enumerate_interfaces();
|
int enumerate_interfaces(int reset);
|
||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
void create_bound_listeners(int die);
|
void create_bound_listeners(int die);
|
||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
@@ -1033,7 +1040,6 @@ 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 label_exception(int index, int family, struct all_addr *addr);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
int tcp_interface(int fd, int af);
|
int tcp_interface(int fd, int af);
|
||||||
struct in_addr get_ifaddr(char *intr);
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
int set_ipv6pktinfo(int fd);
|
int set_ipv6pktinfo(int fd);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-2
@@ -788,7 +788,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
|
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
|
||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
|
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
|
||||||
!label_exception(if_index, listen->family, &dst_addr))
|
!label_exception(if_index, listen->family, &dst_addr))
|
||||||
return;
|
return;
|
||||||
@@ -808,7 +808,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
|
|
||||||
/* interface may be new */
|
/* interface may be new */
|
||||||
if (!iface && !option_bool(OPT_CLEVERBIND))
|
if (!iface && !option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (iface->addr.sa.sa_family == AF_INET &&
|
if (iface->addr.sa.sa_family == AF_INET &&
|
||||||
|
|||||||
+5
-2
@@ -193,7 +193,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
{
|
{
|
||||||
/* May be multicast arriving async */
|
/* May be multicast arriving async */
|
||||||
if (nl_async(h))
|
if (nl_async(h))
|
||||||
newaddr = 1;
|
{
|
||||||
|
newaddr = 1;
|
||||||
|
enumerate_interfaces(1); /* reset */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == NLMSG_DONE)
|
else if (h->nlmsg_type == NLMSG_DONE)
|
||||||
{
|
{
|
||||||
@@ -397,7 +400,7 @@ static int nl_async(struct nlmsghdr *h)
|
|||||||
static void nl_newaddress(time_t now)
|
static void nl_newaddress(time_t now)
|
||||||
{
|
{
|
||||||
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->doing_ra)
|
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
create_bound_listeners(0);
|
create_bound_listeners(0);
|
||||||
|
|||||||
+131
-58
@@ -99,6 +99,8 @@ int indextoname(int fd, int index, char *name)
|
|||||||
|
|
||||||
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))
|
if (index == 0 || !if_indextoname(index, name))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -224,11 +226,16 @@ int label_exception(int index, int family, struct all_addr *addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iface_allowed(struct irec **irecp, int if_index, char *label,
|
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)
|
union mysockaddr *addr, struct in_addr netmask, int dad)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
int fd, mtu = 0, loopback;
|
int mtu = 0, loopback;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||||
int dhcp_ok = 1;
|
int dhcp_ok = 1;
|
||||||
@@ -237,39 +244,72 @@ static int iface_allowed(struct irec **irecp, int if_index, char *label,
|
|||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check whether the interface IP has been added already
|
if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
|
||||||
we call this routine multiple times. */
|
ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
|
||||||
for (iface = *irecp; iface; iface = iface->next)
|
return 0;
|
||||||
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;
|
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
||||||
|
|
||||||
if (loopback)
|
if (loopback)
|
||||||
dhcp_ok = 0;
|
dhcp_ok = 0;
|
||||||
|
|
||||||
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
|
if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
|
|
||||||
close(fd);
|
if (!label)
|
||||||
|
label = ifr.ifr_name;
|
||||||
|
|
||||||
|
|
||||||
/* If we are restricting the set of interfaces to use, make
|
/* 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 = daemon->interfaces; iface; iface = iface->next)
|
||||||
|
if (sockaddr_isequal(&iface->addr, addr))
|
||||||
|
{
|
||||||
|
iface->dad = dad;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are restricting the set of interfaces to use, make
|
||||||
sure that loopback interfaces are in that set. */
|
sure that loopback interfaces are in that set. */
|
||||||
if (daemon->if_names && loopback)
|
if (daemon->if_names && loopback)
|
||||||
{
|
{
|
||||||
@@ -292,9 +332,6 @@ static int iface_allowed(struct irec **irecp, int if_index, char *label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!label)
|
|
||||||
label = ifr.ifr_name;
|
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET &&
|
if (addr->sa.sa_family == AF_INET &&
|
||||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
|
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -336,8 +373,8 @@ static int iface_allowed(struct irec **irecp, int if_index, char *label,
|
|||||||
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
||||||
{
|
{
|
||||||
strcpy(iface->name, ifr.ifr_name);
|
strcpy(iface->name, ifr.ifr_name);
|
||||||
iface->next = *irecp;
|
iface->next = daemon->interfaces;
|
||||||
*irecp = iface;
|
daemon->interfaces = iface;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
free(iface);
|
free(iface);
|
||||||
@@ -371,7 +408,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
addr.in6.sin6_port = htons(daemon->port);
|
addr.in6.sin6_port = htons(daemon->port);
|
||||||
addr.in6.sin6_scope_id = if_index;
|
addr.in6.sin6_scope_id = if_index;
|
||||||
|
|
||||||
return iface_allowed((struct irec **)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -389,17 +426,73 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
|||||||
addr.in.sin_addr = local;
|
addr.in.sin_addr = local;
|
||||||
addr.in.sin_port = htons(daemon->port);
|
addr.in.sin_port = htons(daemon->port);
|
||||||
|
|
||||||
return iface_allowed((struct irec **)vparam, if_index, label, &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
|
#ifdef HAVE_IPV6
|
||||||
if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6))
|
for (addr = intname->addr6; addr; addr = tmp)
|
||||||
return 0;
|
{
|
||||||
|
tmp = addr->next;
|
||||||
|
addr->next = spare;
|
||||||
|
spare = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
intname->addr6 = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
param.spare = spare;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4);
|
if (ret)
|
||||||
|
ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
|
||||||
|
|
||||||
|
errsave = errno;
|
||||||
|
close(param.fd);
|
||||||
|
errno = errsave;
|
||||||
|
|
||||||
|
spare = param.spare;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set NONBLOCK bit on fd: See Stevens 16.6 */
|
/* set NONBLOCK bit on fd: See Stevens 16.6 */
|
||||||
@@ -971,7 +1064,7 @@ void check_servers(void)
|
|||||||
|
|
||||||
/* interface may be new since startup */
|
/* interface may be new since startup */
|
||||||
if (!option_bool(OPT_NOWILD))
|
if (!option_bool(OPT_NOWILD))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
for (new = daemon->servers; new; new = tmp)
|
for (new = daemon->servers; new; new = tmp)
|
||||||
{
|
{
|
||||||
@@ -1179,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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3215,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 = opt_malloc(sizeof(struct interface_name));
|
||||||
new->next = NULL;
|
new->next = NULL;
|
||||||
|
new->addr4 = NULL;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
new->addr6 = NULL;
|
||||||
|
#endif
|
||||||
/* Add to the end of the list, so that first name
|
/* Add to the end of the list, so that first name
|
||||||
of an interface is used for PTR lookups. */
|
of an interface is used for PTR lookups. */
|
||||||
for (up = &daemon->int_names; *up; up = &((*up)->next));
|
for (up = &daemon->int_names; *up; up = &((*up)->next));
|
||||||
|
|||||||
+54
-23
@@ -1450,19 +1450,42 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (is_arpa == F_IPV4)
|
if (is_arpa == F_IPV4)
|
||||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
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;
|
break;
|
||||||
else
|
else
|
||||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||||
intr = intr->next;
|
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)
|
if (intr)
|
||||||
{
|
{
|
||||||
ans = 1;
|
ans = 1;
|
||||||
if (!dryrun)
|
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,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->local_ttl, NULL,
|
daemon->local_ttl, NULL,
|
||||||
T_PTR, C_IN, "d", intr->name))
|
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)
|
for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
|
||||||
{
|
{
|
||||||
unsigned short type = T_A;
|
unsigned short type = T_A;
|
||||||
|
struct interface_name *intr;
|
||||||
|
|
||||||
if (flag == F_IPV6)
|
if (flag == F_IPV6)
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
type = T_AAAA;
|
type = T_AAAA;
|
||||||
@@ -1595,31 +1619,38 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* interface name stuff */
|
/* 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)
|
enumerate_interfaces(0);
|
||||||
if (hostname_isequal(name, intr->name))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (intr)
|
addrlist = intr->addr4;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (type == T_AAAA)
|
||||||
|
addrlist = intr->addr6;
|
||||||
|
#endif
|
||||||
|
ans = 1;
|
||||||
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
ans = 1;
|
if (!addrlist)
|
||||||
if (!dryrun)
|
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
|
||||||
{
|
else
|
||||||
if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
|
for (; addrlist; addrlist = addrlist->next)
|
||||||
log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
|
{
|
||||||
else
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||||
{
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
daemon->local_ttl, NULL, type, C_IN,
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
type == T_A ? "4" : "6", &addrlist->addr))
|
||||||
daemon->local_ttl, NULL, type, C_IN, "4", &addr))
|
anscount++;
|
||||||
anscount++;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cname_restart:
|
cname_restart:
|
||||||
|
|||||||
+1
-1
@@ -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 */
|
Have to set override to make sure we echo back the correct server-id */
|
||||||
struct irec *intr;
|
struct irec *intr;
|
||||||
|
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
for (intr = daemon->interfaces; intr; intr = intr->next)
|
for (intr = daemon->interfaces; intr; intr = intr->next)
|
||||||
if (intr->addr.sa.sa_family == AF_INET &&
|
if (intr->addr.sa.sa_family == AF_INET &&
|
||||||
|
|||||||
+1
-1
@@ -201,7 +201,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if (!iface_check(listen->family, &addra, name, NULL))
|
if (!iface_check(listen->family, &addra, name, NULL))
|
||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces(0);
|
||||||
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
|
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
|
||||||
!label_exception(if_index, listen->family, &addra) )
|
!label_exception(if_index, listen->family, &addra) )
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in new issue
Block a user