Commit 115ac3e4 authored by Simon Kelley's avatar Simon Kelley

Generalise --interface-name to cope with IPv6 addresses.

parent cfcad42f
...@@ -37,6 +37,9 @@ version 2.67 ...@@ -37,6 +37,9 @@ version 2.67
and do RA but _not_ DHCPv6. Thanks to Trever Adams for the and do RA but _not_ DHCPv6. Thanks to Trever Adams for the
bug report. 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
......
...@@ -153,30 +153,53 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -153,30 +153,53 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
continue; continue;
} }
intr = NULL;
if (flag == F_IPV4) 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) 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->addr6; addrlist; addrlist = addrlist->next)
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
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;
} }
#endif
if (intr) if (intr)
{ {
if (in_zone(zone, intr->name, NULL)) if (in_zone(zone, intr->name, NULL))
{ {
found = 1; found = 1;
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL); log_query(flag| 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->auth_ttl, NULL, daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", intr->name)) T_PTR, C_IN, "d", intr->name))
anscount++; anscount++;
} }
} }
}
if ((crecp = cache_find_by_addr(NULL, &addr, now, flag))) if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
do { do {
...@@ -322,17 +345,34 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -322,17 +345,34 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} }
} }
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)
if (filter_constructed_dhcp(zone, flag, &addrlist->addr))
{ {
found = 1; found = 1;
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL); log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", &addr)) daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &addrlist->addr))
anscount++; anscount++;
} }
} }
...@@ -356,14 +396,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -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,15 +666,27 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -634,15 +666,27 @@ 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) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
anscount++; 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 = '.';
......
...@@ -225,7 +225,7 @@ int main (int argc, char **argv) ...@@ -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))
...@@ -821,11 +821,14 @@ int main (int argc, char **argv) ...@@ -821,11 +821,14 @@ int main (int argc, char **argv)
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) ...@@ -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 &&
......
...@@ -307,6 +307,13 @@ struct host_record { ...@@ -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); ...@@ -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); ...@@ -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
......
...@@ -788,7 +788,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -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) ...@@ -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 &&
......
...@@ -193,7 +193,10 @@ int iface_enumerate(int family, void *parm, int (*callback)()) ...@@ -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) ...@@ -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);
......
...@@ -99,6 +99,8 @@ int indextoname(int fd, int index, char *name) ...@@ -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) ...@@ -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,37 +244,70 @@ static int iface_allowed(struct irec **irecp, int if_index, char *label, ...@@ -237,37 +244,70 @@ 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)
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; 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;
/* 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 /* 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. */
...@@ -292,9 +332,6 @@ static int iface_allowed(struct irec **irecp, int if_index, char *label, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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)
{ {
#ifdef HAVE_IPV6 static struct addrlist *spare = NULL;
if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6)) 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; 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
for (addr = intname->addr6; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
intname->addr6 = NULL;
#endif #endif
}
param.spare = spare;
#ifdef HAVE_IPV6
ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
#endif
if (ret)
ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
return iface_enumerate(AF_INET, &daemon->interfaces, 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) ...@@ -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) ...@@ -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 ...@@ -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));
......
...@@ -1450,19 +1450,42 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -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;
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; 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;
} }
#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,6 +1569,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1546,6 +1569,7 @@ 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
...@@ -1595,9 +1619,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1595,9 +1619,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
} }
/* interface name stuff */ /* interface name stuff */
if (qtype == T_A)
{
struct interface_name *intr;
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))
...@@ -1605,22 +1626,32 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1605,22 +1626,32 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (intr) if (intr)
{ {
struct addrlist *addrlist;
enumerate_interfaces(0);
addrlist = intr->addr4;
#ifdef HAVE_IPV6
if (type == T_AAAA)
addrlist = intr->addr6;
#endif
ans = 1; ans = 1;
if (!dryrun) if (!dryrun)
{ {
if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1) if (!addrlist)
log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL); log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
else else
for (; addrlist; addrlist = addrlist->next)
{ {
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL); log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL, type, C_IN, "4", &addr)) daemon->local_ttl, NULL, type, C_IN,
type == T_A ? "4" : "6", &addrlist->addr))
anscount++; anscount++;
} }
} }
continue; continue;
} }
}
cname_restart: cname_restart:
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME))) if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME)))
......
...@@ -1072,7 +1072,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, ...@@ -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 &&
......
...@@ -201,7 +201,7 @@ void tftp_request(struct listener *listen, time_t now) ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment