mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Handle async notification of address changes using the event system.
This commit is contained in:
@@ -4,6 +4,10 @@ version 2.72
|
|||||||
Add support for "ipsets" in *BSD, using pf. Thanks to
|
Add support for "ipsets" in *BSD, using pf. Thanks to
|
||||||
Sven Falempim for the patch.
|
Sven Falempim for the patch.
|
||||||
|
|
||||||
|
Fix race condition which could lock up dnsmasq when an
|
||||||
|
interface goes down and up rapidly. Thanks to Conrad
|
||||||
|
Kostecki for helping to chase this down.
|
||||||
|
|
||||||
|
|
||||||
version 2.71
|
version 2.71
|
||||||
Subtle change to error handling to help DNSSEC validation
|
Subtle change to error handling to help DNSSEC validation
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ void route_init(void)
|
|||||||
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
|
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void route_sock(time_t now)
|
void route_sock(void)
|
||||||
{
|
{
|
||||||
struct if_msghdr *msg;
|
struct if_msghdr *msg;
|
||||||
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
|
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
|
||||||
@@ -401,7 +401,7 @@ void route_sock(time_t now)
|
|||||||
else if (msg->ifm_type == RTM_NEWADDR)
|
else if (msg->ifm_type == RTM_NEWADDR)
|
||||||
{
|
{
|
||||||
del_family = 0;
|
del_family = 0;
|
||||||
newaddress(now);
|
send_newaddr();
|
||||||
}
|
}
|
||||||
else if (msg->ifm_type == RTM_DELADDR)
|
else if (msg->ifm_type == RTM_DELADDR)
|
||||||
{
|
{
|
||||||
@@ -439,7 +439,7 @@ void route_sock(time_t now)
|
|||||||
of += sizeof(long) - (diff & (sizeof(long) - 1));
|
of += sizeof(long) - (diff & (sizeof(long) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
newaddress(now);
|
send_newaddr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
src/dhcp6.c
10
src/dhcp6.c
@@ -708,20 +708,12 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
void dhcp_construct_contexts(time_t now)
|
void dhcp_construct_contexts(time_t now)
|
||||||
{
|
{
|
||||||
static int active = 0;
|
|
||||||
struct dhcp_context *context, *tmp, **up;
|
struct dhcp_context *context, *tmp, **up;
|
||||||
struct cparam param;
|
struct cparam param;
|
||||||
param.newone = 0;
|
param.newone = 0;
|
||||||
param.newname = 0;
|
param.newname = 0;
|
||||||
param.now = now;
|
param.now = now;
|
||||||
|
|
||||||
/* Various calls that we make may end up calling iface_enumerate(), which can then
|
|
||||||
call us again, We're NOT re-entrant, so ignore a second invokation. */
|
|
||||||
if (active)
|
|
||||||
return;
|
|
||||||
|
|
||||||
active = 1;
|
|
||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (context->flags & CONTEXT_CONSTRUCTED)
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
context->flags |= CONTEXT_GC;
|
context->flags |= CONTEXT_GC;
|
||||||
@@ -779,8 +771,6 @@ void dhcp_construct_contexts(time_t now)
|
|||||||
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
||||||
send_alarm(periodic_ra(now), now);
|
send_alarm(periodic_ra(now), now);
|
||||||
}
|
}
|
||||||
|
|
||||||
active = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -917,10 +917,10 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||||
netlink_multicast(now);
|
netlink_multicast();
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
if (FD_ISSET(daemon->routefd, &rset))
|
if (FD_ISSET(daemon->routefd, &rset))
|
||||||
route_sock(now);
|
route_sock();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for changes to resolv files once per second max. */
|
/* Check for changes to resolv files once per second max. */
|
||||||
@@ -1037,6 +1037,11 @@ void send_alarm(time_t event, time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void send_newaddr(void)
|
||||||
|
{
|
||||||
|
send_event(pipewrite, EVENT_NEWADDR, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void send_event(int fd, int event, int data, char *msg)
|
void send_event(int fd, int event, int data, char *msg)
|
||||||
{
|
{
|
||||||
struct event_desc ev;
|
struct event_desc ev;
|
||||||
@@ -1231,6 +1236,10 @@ static void async_event(int pipe, time_t now)
|
|||||||
log_reopen(daemon->log_file);
|
log_reopen(daemon->log_file);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EVENT_NEWADDR:
|
||||||
|
newaddress(now);
|
||||||
|
break;
|
||||||
|
|
||||||
case EVENT_TERM:
|
case EVENT_TERM:
|
||||||
/* Knock all our children on the head. */
|
/* Knock all our children on the head. */
|
||||||
for (i = 0; i < MAX_PROCS; i++)
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ struct event_desc {
|
|||||||
#define EVENT_LUA_ERR 19
|
#define EVENT_LUA_ERR 19
|
||||||
#define EVENT_TFTP_ERR 20
|
#define EVENT_TFTP_ERR 20
|
||||||
#define EVENT_INIT 21
|
#define EVENT_INIT 21
|
||||||
|
#define EVENT_NEWADDR 22
|
||||||
|
|
||||||
/* Exit codes. */
|
/* Exit codes. */
|
||||||
#define EC_GOOD 0
|
#define EC_GOOD 0
|
||||||
@@ -1288,6 +1289,7 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
|||||||
int make_icmp_sock(void);
|
int make_icmp_sock(void);
|
||||||
int icmp_ping(struct in_addr addr);
|
int icmp_ping(struct in_addr addr);
|
||||||
#endif
|
#endif
|
||||||
|
void send_newaddr(void);
|
||||||
void send_alarm(time_t event, time_t now);
|
void send_alarm(time_t event, time_t now);
|
||||||
void send_event(int fd, int event, int data, char *msg);
|
void send_event(int fd, int event, int data, char *msg);
|
||||||
void clear_cache_and_reload(time_t now);
|
void clear_cache_and_reload(time_t now);
|
||||||
@@ -1296,7 +1298,7 @@ void poll_resolv(int force, int do_reload, time_t now);
|
|||||||
/* netlink.c */
|
/* netlink.c */
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void netlink_init(void);
|
void netlink_init(void);
|
||||||
void netlink_multicast(time_t now);
|
void netlink_multicast(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bpf.c */
|
/* bpf.c */
|
||||||
@@ -1305,7 +1307,7 @@ void init_bpf(void);
|
|||||||
void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||||
struct in_addr iface_addr, struct ifreq *ifr);
|
struct in_addr iface_addr, struct ifreq *ifr);
|
||||||
void route_init(void);
|
void route_init(void);
|
||||||
void route_sock(time_t now);
|
void route_sock(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bpf.c or netlink.c */
|
/* bpf.c or netlink.c */
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
static struct iovec iov;
|
static struct iovec iov;
|
||||||
static u32 netlink_pid;
|
static u32 netlink_pid;
|
||||||
|
|
||||||
static int nl_async(struct nlmsghdr *h);
|
static void nl_async(struct nlmsghdr *h);
|
||||||
|
|
||||||
void netlink_init(void)
|
void netlink_init(void)
|
||||||
{
|
{
|
||||||
@@ -142,7 +142,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
static unsigned int seq = 0;
|
static unsigned int seq = 0;
|
||||||
int callback_ok = 1, newaddr = 0;
|
int callback_ok = 1;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr nlh;
|
struct nlmsghdr nlh;
|
||||||
@@ -191,21 +191,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
/* May be multicast arriving async */
|
/* May be multicast arriving async */
|
||||||
if (nl_async(h))
|
nl_async(h);
|
||||||
{
|
|
||||||
newaddr = 1;
|
|
||||||
enumerate_interfaces(1); /* reset */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == NLMSG_DONE)
|
else if (h->nlmsg_type == NLMSG_DONE)
|
||||||
{
|
|
||||||
/* handle async new interface address arrivals, these have to be done
|
|
||||||
after we complete as we're not re-entrant */
|
|
||||||
if (newaddr)
|
|
||||||
newaddress(dnsmasq_time());
|
|
||||||
|
|
||||||
return callback_ok;
|
return callback_ok;
|
||||||
}
|
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
||||||
{
|
{
|
||||||
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
||||||
@@ -330,11 +319,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void netlink_multicast(time_t now)
|
void netlink_multicast(void)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
int flags, newaddr = 0;
|
int flags;
|
||||||
|
|
||||||
/* don't risk blocking reading netlink messages here. */
|
/* don't risk blocking reading netlink messages here. */
|
||||||
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
||||||
@@ -343,24 +332,19 @@ void netlink_multicast(time_t now)
|
|||||||
|
|
||||||
if ((len = netlink_recv()) != -1)
|
if ((len = netlink_recv()) != -1)
|
||||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||||
if (nl_async(h))
|
nl_async(h);
|
||||||
newaddr = 1;
|
|
||||||
|
|
||||||
/* restore non-blocking status */
|
/* restore non-blocking status */
|
||||||
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
||||||
|
|
||||||
if (newaddr)
|
|
||||||
newaddress(now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl_async(struct nlmsghdr *h)
|
static void nl_async(struct nlmsghdr *h)
|
||||||
{
|
{
|
||||||
if (h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
struct nlmsgerr *err = NLMSG_DATA(h);
|
struct nlmsgerr *err = NLMSG_DATA(h);
|
||||||
if (err->error != 0)
|
if (err->error != 0)
|
||||||
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||||
{
|
{
|
||||||
@@ -385,18 +369,15 @@ static int nl_async(struct nlmsghdr *h)
|
|||||||
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
||||||
fd = daemon->rfd_save->fd;
|
fd = daemon->rfd_save->fd;
|
||||||
else
|
else
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
||||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
return 1; /* clever bind mode - rescan */
|
send_newaddr();
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
|||||||
int enumerate_interfaces(int reset)
|
int enumerate_interfaces(int reset)
|
||||||
{
|
{
|
||||||
static struct addrlist *spare = NULL;
|
static struct addrlist *spare = NULL;
|
||||||
static int done = 0, active = 0;
|
static int done = 0;
|
||||||
struct iface_param param;
|
struct iface_param param;
|
||||||
int errsave, ret = 1;
|
int errsave, ret = 1;
|
||||||
struct addrlist *addr, *tmp;
|
struct addrlist *addr, *tmp;
|
||||||
@@ -570,14 +570,11 @@ int enumerate_interfaces(int reset)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done || active)
|
if (done)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
/* protect against recusive calls from iface_enumerate(); */
|
|
||||||
active = 1;
|
|
||||||
|
|
||||||
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -677,9 +674,7 @@ int enumerate_interfaces(int reset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
errno = errsave;
|
errno = errsave;
|
||||||
|
|
||||||
spare = param.spare;
|
spare = param.spare;
|
||||||
active = 0;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user