1 From a0358e5ddbc1ef3dec791f11f95f5dbe56087a5e Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Sat, 7 Jun 2014 13:38:48 +0100
4 Subject: [PATCH] Handle async notification of address changes using the event
10 src/dhcp6.c | 10 ----------
11 src/dnsmasq.c | 13 +++++++++++--
12 src/dnsmasq.h | 6 ++++--
13 src/netlink.c | 39 ++++++++++-----------------------------
14 src/network.c | 11 +++--------
15 7 files changed, 35 insertions(+), 54 deletions(-)
19 @@ -15,6 +15,10 @@ version 2.71
20 regression introduced in 2.69. Thanks to James Hunt and
21 the Ubuntu crowd for assistance in fixing this.
23 + Fix race condition which could lock up dnsmasq when an
24 + interface goes down and up rapidly. Thanks to Conrad
25 + Kostecki for helping to chase this down.
29 Fix crash, introduced in 2.69, on TCP request when dnsmasq
32 @@ -376,7 +376,7 @@ void route_init(void)
33 die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
36 -void route_sock(time_t now)
37 +void route_sock(void)
39 struct if_msghdr *msg;
40 int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
41 @@ -401,7 +401,7 @@ void route_sock(time_t now)
42 else if (msg->ifm_type == RTM_NEWADDR)
48 else if (msg->ifm_type == RTM_DELADDR)
50 @@ -439,7 +439,7 @@ void route_sock(time_t now)
51 of += sizeof(long) - (diff & (sizeof(long) - 1));
61 @@ -917,10 +917,10 @@ int main (int argc, char **argv)
63 #if defined(HAVE_LINUX_NETWORK)
64 if (FD_ISSET(daemon->netlinkfd, &rset))
65 - netlink_multicast(now);
66 + netlink_multicast();
67 #elif defined(HAVE_BSD_NETWORK)
68 if (FD_ISSET(daemon->routefd, &rset))
73 /* Check for changes to resolv files once per second max. */
74 @@ -1037,6 +1037,11 @@ void send_alarm(time_t event, time_t now
78 +void send_newaddr(void)
80 + send_event(pipewrite, EVENT_NEWADDR, 0, NULL);
83 void send_event(int fd, int event, int data, char *msg)
86 @@ -1230,6 +1235,10 @@ static void async_event(int pipe, time_t
87 if (daemon->log_file != NULL)
88 log_reopen(daemon->log_file);
96 /* Knock all our children on the head. */
99 @@ -165,6 +165,7 @@ struct event_desc {
100 #define EVENT_LUA_ERR 19
101 #define EVENT_TFTP_ERR 20
102 #define EVENT_INIT 21
103 +#define EVENT_NEWADDR 22
107 @@ -1289,6 +1290,7 @@ unsigned char *extended_hwaddr(int hwtyp
108 int make_icmp_sock(void);
109 int icmp_ping(struct in_addr addr);
111 +void send_newaddr(void);
112 void send_alarm(time_t event, time_t now);
113 void send_event(int fd, int event, int data, char *msg);
114 void clear_cache_and_reload(time_t now);
115 @@ -1297,7 +1299,7 @@ void poll_resolv(int force, int do_reloa
117 #ifdef HAVE_LINUX_NETWORK
118 void netlink_init(void);
119 -void netlink_multicast(time_t now);
120 +void netlink_multicast(void);
124 @@ -1306,7 +1308,7 @@ void init_bpf(void);
125 void send_via_bpf(struct dhcp_packet *mess, size_t len,
126 struct in_addr iface_addr, struct ifreq *ifr);
127 void route_init(void);
128 -void route_sock(time_t now);
129 +void route_sock(void);
132 /* bpf.c or netlink.c */
136 static struct iovec iov;
137 static u32 netlink_pid;
139 -static int nl_async(struct nlmsghdr *h);
140 +static void nl_async(struct nlmsghdr *h);
142 void netlink_init(void)
144 @@ -142,7 +142,7 @@ int iface_enumerate(int family, void *pa
147 static unsigned int seq = 0;
148 - int callback_ok = 1, newaddr = 0;
149 + int callback_ok = 1;
153 @@ -191,21 +191,10 @@ int iface_enumerate(int family, void *pa
154 if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
156 /* May be multicast arriving async */
160 - enumerate_interfaces(1); /* reset */
164 else if (h->nlmsg_type == NLMSG_DONE)
166 - /* handle async new interface address arrivals, these have to be done
167 - after we complete as we're not re-entrant */
169 - newaddress(dnsmasq_time());
171 - return callback_ok;
173 + return callback_ok;
174 else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
176 struct ifaddrmsg *ifa = NLMSG_DATA(h);
177 @@ -330,11 +319,11 @@ int iface_enumerate(int family, void *pa
181 -void netlink_multicast(time_t now)
182 +void netlink_multicast(void)
186 - int flags, newaddr = 0;
189 /* don't risk blocking reading netlink messages here. */
190 if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
191 @@ -343,24 +332,19 @@ void netlink_multicast(time_t now)
193 if ((len = netlink_recv()) != -1)
194 for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
199 /* restore non-blocking status */
200 fcntl(daemon->netlinkfd, F_SETFL, flags);
206 -static int nl_async(struct nlmsghdr *h)
207 +static void nl_async(struct nlmsghdr *h)
209 if (h->nlmsg_type == NLMSG_ERROR)
211 struct nlmsgerr *err = NLMSG_DATA(h);
213 my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
216 else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
218 @@ -385,18 +369,15 @@ static int nl_async(struct nlmsghdr *h)
219 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
220 fd = daemon->rfd_save->fd;
225 while(sendto(fd, daemon->packet, daemon->packet_len, 0,
226 &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
231 else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
232 - return 1; /* clever bind mode - rescan */
241 @@ -551,7 +551,7 @@ static int iface_allowed_v4(struct in_ad
242 int enumerate_interfaces(int reset)
244 static struct addrlist *spare = NULL;
245 - static int done = 0, active = 0;
246 + static int done = 0;
247 struct iface_param param;
248 int errsave, ret = 1;
249 struct addrlist *addr, *tmp;
250 @@ -570,14 +570,11 @@ int enumerate_interfaces(int reset)
254 - if (done || active)
260 - /* protect against recusive calls from iface_enumerate(); */
263 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
266 @@ -677,10 +674,8 @@ int enumerate_interfaces(int reset)