]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/0058-Fix-boilerplate-code-for-re-running-system-calls-on-.patch
Merge branch 'next' of ssh://git.ipfire.org/pub/git/ipfire-2.x into next
[ipfire-2.x.git] / src / patches / dnsmasq / 0058-Fix-boilerplate-code-for-re-running-system-calls-on-.patch
CommitLineData
c6ce1e7e
MT
1From ff841ebf5a5d6864ff48571f607c32ce80dbb75a Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Wed, 11 Mar 2015 21:36:30 +0000
697b4f04 4Subject: [PATCH 058/113] Fix boilerplate code for re-running system calls on
c6ce1e7e
MT
5 EINTR and EAGAIN etc.
6
7The nasty code with static variable in retry_send() which
8avoids looping forever needs to be called on success of the syscall,
9to reset the static variable.
10---
11 src/bpf.c | 2 +-
12 src/dhcp.c | 2 +-
13 src/dhcp6.c | 6 +++---
14 src/dnsmasq.c | 35 +++++++++++++++++----------------
15 src/dnsmasq.h | 2 +-
16 src/forward.c | 41 ++++++++++++++++++--------------------
17 src/ipset.c | 8 ++++----
18 src/loop.c | 5 +++--
19 src/netlink.c | 8 ++++----
20 src/radv.c | 5 +++--
21 src/util.c | 63 ++++++++++++++++++++++++++++++++++-------------------------
22 11 files changed, 93 insertions(+), 84 deletions(-)
23
24diff --git a/src/bpf.c b/src/bpf.c
25index 997d87421bed..a066641f969f 100644
26--- a/src/bpf.c
27+++ b/src/bpf.c
28@@ -359,7 +359,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
29 iov[3].iov_base = mess;
30 iov[3].iov_len = len;
31
32- while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
33+ while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
34 }
35
36 #endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
37diff --git a/src/dhcp.c b/src/dhcp.c
38index f29be9b489a7..5c3089ab94ff 100644
39--- a/src/dhcp.c
40+++ b/src/dhcp.c
41@@ -443,7 +443,7 @@ void dhcp_packet(time_t now, int pxe_fd)
42 setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
43 #endif
44
45- while(sendmsg(fd, &msg, 0) == -1 && retry_send());
46+ while(retry_send(sendmsg(fd, &msg, 0)));
47 }
48
49 /* check against secondary interface addresses */
50diff --git a/src/dhcp6.c b/src/dhcp6.c
51index c7144f5fee7c..ee2aa5d3bf3c 100644
52--- a/src/dhcp6.c
53+++ b/src/dhcp6.c
54@@ -225,9 +225,9 @@ void dhcp6_packet(time_t now)
55 if (port != 0)
56 {
57 from.sin6_port = htons(port);
58- while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0),
59- 0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
60- retry_send());
61+ while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
62+ save_counter(0), 0, (struct sockaddr *)&from,
63+ sizeof(from))));
64 }
65 }
66
67diff --git a/src/dnsmasq.c b/src/dnsmasq.c
68index f3e5bcffec4f..b784951950d4 100644
69--- a/src/dnsmasq.c
70+++ b/src/dnsmasq.c
71@@ -444,7 +444,7 @@ int main (int argc, char **argv)
72 char *msg;
73
74 /* close our copy of write-end */
75- close(err_pipe[1]);
76+ while (retry_send(close(err_pipe[1])));
77
78 /* check for errors after the fork */
79 if (read_event(err_pipe[0], &ev, &msg))
80@@ -453,7 +453,7 @@ int main (int argc, char **argv)
81 _exit(EC_GOOD);
82 }
83
84- close(err_pipe[0]);
85+ while (retry_send(close(err_pipe[0])));
86
87 /* NO calls to die() from here on. */
88
89@@ -505,10 +505,12 @@ int main (int argc, char **argv)
90 {
91 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
92 err = 1;
93-
94- while (!err && close(fd) == -1)
95- if (!retry_send())
96- err = 1;
97+ else
98+ {
99+ while (retry_send(close(fd)));
100+ if (errno != 0)
101+ err = 1;
102+ }
103 }
104
105 if (err)
106@@ -813,7 +815,7 @@ int main (int argc, char **argv)
107
108 /* finished start-up - release original process */
109 if (err_pipe[1] != -1)
110- close(err_pipe[1]);
111+ while (retry_send(close(err_pipe[1])));
112
113 if (daemon->port != 0)
114 check_servers();
115@@ -1319,7 +1321,7 @@ static void async_event(int pipe, time_t now)
116 do {
117 helper_write();
118 } while (!helper_buf_empty() || do_script_run(now));
119- close(daemon->helperfd);
120+ while (retry_send(close(daemon->helperfd)));
121 }
122 #endif
123
124@@ -1544,7 +1546,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
125
126 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
127 {
128- close(confd);
129+ while (retry_send(close(confd)));
130 continue;
131 }
132
133@@ -1609,7 +1611,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
134 if (!client_ok)
135 {
136 shutdown(confd, SHUT_RDWR);
137- close(confd);
138+ while (retry_send(close(confd)));
139 }
140 #ifndef NO_FORK
141 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
142@@ -1624,7 +1626,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
143 break;
144 }
145 }
146- close(confd);
147+ while (retry_send(close(confd)));
148
149 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
150 daemon->log_id += TCP_MAX_QUERIES;
151@@ -1669,7 +1671,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
152 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
153
154 shutdown(confd, SHUT_RDWR);
155- close(confd);
156+ while (retry_send(close(confd)));
157
158 if (buff)
159 free(buff);
160@@ -1678,7 +1680,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
161 if (s->tcpfd != -1)
162 {
163 shutdown(s->tcpfd, SHUT_RDWR);
164- close(s->tcpfd);
165+ while (retry_send(close(s->tcpfd)));
166 }
167 #ifndef NO_FORK
168 if (!option_bool(OPT_DEBUG))
169@@ -1756,9 +1758,8 @@ int icmp_ping(struct in_addr addr)
170 j = (j & 0xffff) + (j >> 16);
171 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
172
173- while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
174- (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
175- retry_send());
176+ while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
177+ (struct sockaddr *)&saddr, sizeof(saddr))));
178
179 for (now = start = dnsmasq_time();
180 difftime(now, start) < (float)PING_WAIT;)
181@@ -1820,7 +1821,7 @@ int icmp_ping(struct in_addr addr)
182 }
183
184 #if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
185- close(fd);
186+ while (retry_send(close(fd)));
187 #else
188 opt = 1;
189 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
190diff --git a/src/dnsmasq.h b/src/dnsmasq.h
191index fc7259881358..de95d0e875e3 100644
192--- a/src/dnsmasq.h
193+++ b/src/dnsmasq.h
194@@ -1177,7 +1177,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
195 u64 addr6part(struct in6_addr *addr);
196 void setaddr6part(struct in6_addr *addr, u64 host);
197 #endif
198-int retry_send(void);
199+int retry_send(ssize_t rc);
200 void prettyprint_time(char *buf, unsigned int t);
201 int prettyprint_addr(union mysockaddr *addr, char *buf);
202 int parse_hex(char *in, unsigned char *out, int maxlen,
203diff --git a/src/forward.c b/src/forward.c
204index 438e9fa490b8..7c0fa8da3fdf 100644
205--- a/src/forward.c
206+++ b/src/forward.c
207@@ -103,15 +103,11 @@ int send_from(int fd, int nowild, char *packet, size_t len,
208 #endif
209 }
210
211- while (sendmsg(fd, &msg, 0) == -1)
212+ while (retry_send(sendmsg(fd, &msg, 0)));
213+
214+ /* If interface is still in DAD, EINVAL results - ignore that. */
215+ if (errno != 0 && errno != EINVAL)
216 {
217- if (retry_send())
218- continue;
219-
220- /* If interface is still in DAD, EINVAL results - ignore that. */
221- if (errno == EINVAL)
222- break;
223-
224 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
225 return 0;
226 }
227@@ -297,9 +293,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
228 fd = forward->rfd4->fd;
229 }
230
231- while (sendto(fd, (char *)header, plen, 0,
232- &forward->sentto->addr.sa,
233- sa_len(&forward->sentto->addr)) == -1 && retry_send());
234+ while (retry_send( sendto(fd, (char *)header, plen, 0,
235+ &forward->sentto->addr.sa,
236+ sa_len(&forward->sentto->addr))));
237
238 return 1;
239 }
240@@ -469,14 +465,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
241 #endif
242 }
243
244- if (sendto(fd, (char *)header, plen, 0,
245- &start->addr.sa,
246- sa_len(&start->addr)) == -1)
247- {
248- if (retry_send())
249- continue;
250- }
251- else
252+ if (retry_send(sendto(fd, (char *)header, plen, 0,
253+ &start->addr.sa,
254+ sa_len(&start->addr))))
255+ continue;
256+
257+ if (errno == 0)
258 {
259 /* Keep info in case we want to re-send this packet */
260 daemon->srv_save = start;
261@@ -932,7 +926,9 @@ void reply_query(int fd, int family, time_t now)
262
263 if (fd != -1)
264 {
265- while (sendto(fd, (char *)header, nn, 0, &server->addr.sa, sa_len(&server->addr)) == -1 && retry_send());
266+ while (retry_send(sendto(fd, (char *)header, nn, 0,
267+ &server->addr.sa,
268+ sa_len(&server->addr))));
269 server->queries++;
270 }
271
272@@ -2228,8 +2224,9 @@ void resend_query()
273 else
274 return;
275
276- while(sendto(fd, daemon->packet, daemon->packet_len, 0,
277- &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
278+ while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
279+ &daemon->srv_save->addr.sa,
280+ sa_len(&daemon->srv_save->addr))));
281 }
282 }
283
284diff --git a/src/ipset.c b/src/ipset.c
285index 8c5b72722371..a315e86bc7f4 100644
286--- a/src/ipset.c
287+++ b/src/ipset.c
288@@ -121,7 +121,6 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
289 struct my_nlattr *nested[2];
290 uint8_t proto;
291 int addrsz = INADDRSZ;
292- ssize_t rc;
293
294 #ifdef HAVE_IPV6
295 if (af == AF_INET6)
296@@ -162,9 +161,10 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
297 nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
298 nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
299
300- while ((rc = sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
301- (struct sockaddr *)&snl, sizeof(snl))) == -1 && retry_send());
302- return rc;
303+ while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
304+ (struct sockaddr *)&snl, sizeof(snl))));
305+
306+ return errno == 0 ? 0 : -1;
307 }
308
309
310diff --git a/src/loop.c b/src/loop.c
311index 565f7d8e58e0..c9ed075670de 100644
312--- a/src/loop.c
313+++ b/src/loop.c
314@@ -45,8 +45,9 @@ void loop_send_probes()
315 fd = rfd->fd;
316 }
317
318- while (sendto(fd, daemon->packet, len, 0, &serv->addr.sa, sa_len(&serv->addr)) == -1 && retry_send());
319-
320+ while (retry_send(sendto(fd, daemon->packet, len, 0,
321+ &serv->addr.sa, sa_len(&serv->addr))));
322+
323 free_rfd(rfd);
324 }
325 }
326diff --git a/src/netlink.c b/src/netlink.c
327index 10f94db25a14..753784dc20b4 100644
328--- a/src/netlink.c
329+++ b/src/netlink.c
330@@ -169,10 +169,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
331 req.g.rtgen_family = family;
332
333 /* Don't block in recvfrom if send fails */
334- while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
335- (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
336-
337- if (len == -1)
338+ while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
339+ (struct sockaddr *)&addr, sizeof(addr))));
340+
341+ if (errno != 0)
342 return 0;
343
344 while (1)
345diff --git a/src/radv.c b/src/radv.c
346index 6da125b864ae..d0faddf8684a 100644
347--- a/src/radv.c
348+++ b/src/radv.c
349@@ -479,8 +479,9 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
350 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
351 }
352
353- while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
354- (struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
355+ while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
356+ save_counter(0), 0, (struct sockaddr *)&addr,
357+ sizeof(addr))));
358
359 }
360
361diff --git a/src/util.c b/src/util.c
362index 91d02410b13f..648bc4d4b428 100644
363--- a/src/util.c
364+++ b/src/util.c
365@@ -569,17 +569,27 @@ void bump_maxfd(int fd, int *max)
366 *max = fd;
367 }
368
369-int retry_send(void)
370+/* rc is return from sendto and friends.
371+ Return 1 if we should retry.
372+ Set errno to zero if we succeeded. */
373+int retry_send(ssize_t rc)
374 {
375+ static int retries = 0;
376+ struct timespec waiter;
377+
378+ if (rc != -1)
379+ {
380+ retries = 0;
381+ errno = 0;
382+ return 0;
383+ }
384+
385 /* Linux kernels can return EAGAIN in perpetuity when calling
386 sendmsg() and the relevant interface has gone. Here we loop
387 retrying in EAGAIN for 1 second max, to avoid this hanging
388 dnsmasq. */
389
390- static int retries = 0;
391- struct timespec waiter;
392-
393- if (errno == EAGAIN || errno == EWOULDBLOCK)
394+ if (errno == EAGAIN || errno == EWOULDBLOCK)
395 {
396 waiter.tv_sec = 0;
397 waiter.tv_nsec = 10000;
398@@ -587,13 +597,13 @@ int retry_send(void)
399 if (retries++ < 1000)
400 return 1;
401 }
402-
403- retries = 0;
404-
405- if (errno == EINTR)
406- return 1;
407-
408- return 0;
409+
410+ retries = 0;
411+
412+ if (errno == EINTR)
413+ return 1;
414+
415+ return 0;
416 }
417
418 int read_write(int fd, unsigned char *packet, int size, int rw)
419@@ -602,22 +612,21 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
420
421 for (done = 0; done < size; done += n)
422 {
423- retry:
424- if (rw)
425- n = read(fd, &packet[done], (size_t)(size - done));
426- else
427- n = write(fd, &packet[done], (size_t)(size - done));
428-
429- if (n == 0)
430- return 0;
431- else if (n == -1)
432- {
433- if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
434- goto retry;
435- else
436- return 0;
437- }
438+ do {
439+ if (rw)
440+ n = read(fd, &packet[done], (size_t)(size - done));
441+ else
442+ n = write(fd, &packet[done], (size_t)(size - done));
443+
444+ if (n == 0)
445+ return 0;
446+
447+ } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
448+
449+ if (errno != 0)
450+ return 0;
451 }
452+
453 return 1;
454 }
455
456--
4572.1.0
458