mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Handle IPv4 interface-address labels in Linux.
This commit is contained in:
@@ -21,6 +21,15 @@ version 2.67
|
|||||||
|
|
||||||
Fix failure to compile ipset.c if old kernel headers are
|
Fix failure to compile ipset.c if old kernel headers are
|
||||||
in use. Thanks to Eugene Rudoy for pointing this out.
|
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.
|
||||||
|
|
||||||
|
|
||||||
version 2.66
|
version 2.66
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||||||
else
|
else
|
||||||
broadcast.s_addr = 0;
|
broadcast.s_addr = 0;
|
||||||
if (!((*callback)(addr, iface_index, netmask, broadcast, parm)))
|
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
14
src/dhcp.c
14
src/dhcp.c
@@ -28,9 +28,9 @@ struct match_param {
|
|||||||
struct in_addr netmask, broadcast, addr;
|
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);
|
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);
|
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
||||||
|
|
||||||
static int make_fd(int port)
|
static int make_fd(int port)
|
||||||
@@ -287,7 +287,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
iface_addr = match.addr;
|
iface_addr = match.addr;
|
||||||
/* make sure secondary address gets priority in case
|
/* make sure secondary address gets priority in case
|
||||||
there is more than one address on the interface in the same subnet */
|
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))
|
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 */
|
/* 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 in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct match_param *param = vparam;
|
struct match_param *param = vparam;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
|
|
||||||
|
(void) label;
|
||||||
|
|
||||||
if (if_index == param->ind)
|
if (if_index == param->ind)
|
||||||
{
|
{
|
||||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
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. */
|
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 in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct iface_param *param = vparam;
|
struct iface_param *param = vparam;
|
||||||
|
|
||||||
|
(void)label;
|
||||||
|
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1030,6 +1030,7 @@ void create_bound_listeners(int die);
|
|||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
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 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 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);
|
struct in_addr get_ifaddr(char *intr);
|
||||||
|
|||||||
@@ -789,7 +789,8 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces();
|
||||||
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))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
|
(void) label;
|
||||||
(void) broadcast;
|
(void) broadcast;
|
||||||
(void) vparam;
|
(void) vparam;
|
||||||
|
|
||||||
|
|||||||
@@ -215,7 +215,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (ifa->ifa_family == AF_INET)
|
if (ifa->ifa_family == AF_INET)
|
||||||
{
|
{
|
||||||
struct in_addr netmask, addr, broadcast;
|
struct in_addr netmask, addr, broadcast;
|
||||||
|
char *label = NULL;
|
||||||
|
|
||||||
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
|
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
|
||||||
addr.s_addr = 0;
|
addr.s_addr = 0;
|
||||||
broadcast.s_addr = 0;
|
broadcast.s_addr = 0;
|
||||||
@@ -226,12 +227,14 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
addr = *((struct in_addr *)(rta+1));
|
addr = *((struct in_addr *)(rta+1));
|
||||||
else if (rta->rta_type == IFA_BROADCAST)
|
else if (rta->rta_type == IFA_BROADCAST)
|
||||||
broadcast = *((struct in_addr *)(rta+1));
|
broadcast = *((struct in_addr *)(rta+1));
|
||||||
|
else if (rta->rta_type == IFA_LABEL)
|
||||||
|
label = RTA_DATA(rta);
|
||||||
|
|
||||||
rta = RTA_NEXT(rta, len1);
|
rta = RTA_NEXT(rta, len1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr.s_addr && callback_ok)
|
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;
|
callback_ok = 0;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
@@ -204,7 +204,27 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
|||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iface_allowed(struct irec **irecp, 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;
|
||||||
@@ -242,8 +262,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
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(fd, SIOCGIFMTU, &ifr) != -1)
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
|
|
||||||
@@ -272,13 +292,16 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, ifr.ifr_name, &auth_dns))
|
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (addr->sa.sa_family == AF_INET6 &&
|
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;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -348,11 +371,11 @@ 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, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
return iface_allowed((struct irec **)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
@@ -366,7 +389,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index,
|
|||||||
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, &addr, netmask, 0);
|
return iface_allowed((struct irec **)vparam, if_index, label, &addr, netmask, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int enumerate_interfaces(void)
|
int enumerate_interfaces(void)
|
||||||
|
|||||||
@@ -202,7 +202,8 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces();
|
||||||
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) )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user