]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/util.c
Fix boilerplate code for re-running system calls on EINTR and EAGAIN etc.
[people/ms/dnsmasq.git] / src / util.c
1 /* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 /* The SURF random number generator was taken from djbdns-1.05, by
18 Daniel J Bernstein, which is public domain. */
19
20
21 #include "dnsmasq.h"
22
23 #ifdef HAVE_BROKEN_RTC
24 #include <sys/times.h>
25 #endif
26
27 #if defined(LOCALEDIR) || defined(HAVE_IDN)
28 #include <idna.h>
29 #endif
30
31 /* SURF random number generator */
32
33 static u32 seed[32];
34 static u32 in[12];
35 static u32 out[8];
36 static int outleft = 0;
37
38 void rand_init()
39 {
40 int fd = open(RANDFILE, O_RDONLY);
41
42 if (fd == -1 ||
43 !read_write(fd, (unsigned char *)&seed, sizeof(seed), 1) ||
44 !read_write(fd, (unsigned char *)&in, sizeof(in), 1))
45 die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
46
47 close(fd);
48 }
49
50 #define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
51 #define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
52
53 static void surf(void)
54 {
55 u32 t[12]; u32 x; u32 sum = 0;
56 int r; int i; int loop;
57
58 for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
59 for (i = 0;i < 8;++i) out[i] = seed[24 + i];
60 x = t[11];
61 for (loop = 0;loop < 2;++loop) {
62 for (r = 0;r < 16;++r) {
63 sum += 0x9e3779b9;
64 MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
65 MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
66 MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
67 }
68 for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
69 }
70 }
71
72 unsigned short rand16(void)
73 {
74 if (!outleft)
75 {
76 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
77 surf();
78 outleft = 8;
79 }
80
81 return (unsigned short) out[--outleft];
82 }
83
84 u32 rand32(void)
85 {
86 if (!outleft)
87 {
88 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
89 surf();
90 outleft = 8;
91 }
92
93 return out[--outleft];
94 }
95
96 u64 rand64(void)
97 {
98 static int outleft = 0;
99
100 if (outleft < 2)
101 {
102 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
103 surf();
104 outleft = 8;
105 }
106
107 outleft -= 2;
108
109 return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
110 }
111
112 static int check_name(char *in)
113 {
114 /* remove trailing .
115 also fail empty string and label > 63 chars */
116 size_t dotgap = 0, l = strlen(in);
117 char c;
118 int nowhite = 0;
119
120 if (l == 0 || l > MAXDNAME) return 0;
121
122 if (in[l-1] == '.')
123 {
124 in[l-1] = 0;
125 nowhite = 1;
126 }
127
128 for (; (c = *in); in++)
129 {
130 if (c == '.')
131 dotgap = 0;
132 else if (++dotgap > MAXLABEL)
133 return 0;
134 else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
135 /* iscntrl only gives expected results for ascii */
136 return 0;
137 #if !defined(LOCALEDIR) && !defined(HAVE_IDN)
138 else if (!isascii((unsigned char)c))
139 return 0;
140 #endif
141 else if (c != ' ')
142 nowhite = 1;
143 }
144
145 if (!nowhite)
146 return 0;
147
148 return 1;
149 }
150
151 /* Hostnames have a more limited valid charset than domain names
152 so check for legal char a-z A-Z 0-9 - _
153 Note that this may receive a FQDN, so only check the first label
154 for the tighter criteria. */
155 int legal_hostname(char *name)
156 {
157 char c;
158 int first;
159
160 if (!check_name(name))
161 return 0;
162
163 for (first = 1; (c = *name); name++, first = 0)
164 /* check for legal char a-z A-Z 0-9 - _ . */
165 {
166 if ((c >= 'A' && c <= 'Z') ||
167 (c >= 'a' && c <= 'z') ||
168 (c >= '0' && c <= '9'))
169 continue;
170
171 if (!first && (c == '-' || c == '_'))
172 continue;
173
174 /* end of hostname part */
175 if (c == '.')
176 return 1;
177
178 return 0;
179 }
180
181 return 1;
182 }
183
184 char *canonicalise(char *in, int *nomem)
185 {
186 char *ret = NULL;
187 #if defined(LOCALEDIR) || defined(HAVE_IDN)
188 int rc;
189 #endif
190
191 if (nomem)
192 *nomem = 0;
193
194 if (!check_name(in))
195 return NULL;
196
197 #if defined(LOCALEDIR) || defined(HAVE_IDN)
198 if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
199 {
200 if (ret)
201 free(ret);
202
203 if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
204 {
205 my_syslog(LOG_ERR, _("failed to allocate memory"));
206 *nomem = 1;
207 }
208
209 return NULL;
210 }
211 #else
212 if ((ret = whine_malloc(strlen(in)+1)))
213 strcpy(ret, in);
214 else if (nomem)
215 *nomem = 1;
216 #endif
217
218 return ret;
219 }
220
221 unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
222 {
223 int j;
224
225 while (sval && *sval)
226 {
227 unsigned char *cp = p++;
228 for (j = 0; *sval && (*sval != '.'); sval++, j++)
229 *p++ = *sval;
230 *cp = j;
231 if (*sval)
232 sval++;
233 }
234 return p;
235 }
236
237 /* for use during startup */
238 void *safe_malloc(size_t size)
239 {
240 void *ret = malloc(size);
241
242 if (!ret)
243 die(_("could not get memory"), NULL, EC_NOMEM);
244
245 return ret;
246 }
247
248 void safe_pipe(int *fd, int read_noblock)
249 {
250 if (pipe(fd) == -1 ||
251 !fix_fd(fd[1]) ||
252 (read_noblock && !fix_fd(fd[0])))
253 die(_("cannot create pipe: %s"), NULL, EC_MISC);
254 }
255
256 void *whine_malloc(size_t size)
257 {
258 void *ret = malloc(size);
259
260 if (!ret)
261 my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
262
263 return ret;
264 }
265
266 int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
267 {
268 if (s1->sa.sa_family == s2->sa.sa_family)
269 {
270 if (s1->sa.sa_family == AF_INET &&
271 s1->in.sin_port == s2->in.sin_port &&
272 s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
273 return 1;
274 #ifdef HAVE_IPV6
275 if (s1->sa.sa_family == AF_INET6 &&
276 s1->in6.sin6_port == s2->in6.sin6_port &&
277 s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
278 IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
279 return 1;
280 #endif
281 }
282 return 0;
283 }
284
285 int sa_len(union mysockaddr *addr)
286 {
287 #ifdef HAVE_SOCKADDR_SA_LEN
288 return addr->sa.sa_len;
289 #else
290 #ifdef HAVE_IPV6
291 if (addr->sa.sa_family == AF_INET6)
292 return sizeof(addr->in6);
293 else
294 #endif
295 return sizeof(addr->in);
296 #endif
297 }
298
299 /* don't use strcasecmp and friends here - they may be messed up by LOCALE */
300 int hostname_isequal(const char *a, const char *b)
301 {
302 unsigned int c1, c2;
303
304 do {
305 c1 = (unsigned char) *a++;
306 c2 = (unsigned char) *b++;
307
308 if (c1 >= 'A' && c1 <= 'Z')
309 c1 += 'a' - 'A';
310 if (c2 >= 'A' && c2 <= 'Z')
311 c2 += 'a' - 'A';
312
313 if (c1 != c2)
314 return 0;
315 } while (c1);
316
317 return 1;
318 }
319
320 time_t dnsmasq_time(void)
321 {
322 #ifdef HAVE_BROKEN_RTC
323 struct tms dummy;
324 static long tps = 0;
325
326 if (tps == 0)
327 tps = sysconf(_SC_CLK_TCK);
328
329 return (time_t)(times(&dummy)/tps);
330 #else
331 return time(NULL);
332 #endif
333 }
334
335 int netmask_length(struct in_addr mask)
336 {
337 int zero_count = 0;
338
339 while (0x0 == (mask.s_addr & 0x1) && zero_count < 32)
340 {
341 mask.s_addr >>= 1;
342 zero_count++;
343 }
344
345 return 32 - zero_count;
346 }
347
348 int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
349 {
350 return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
351 }
352
353 #ifdef HAVE_IPV6
354 int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
355 {
356 int pfbytes = prefixlen >> 3;
357 int pfbits = prefixlen & 7;
358
359 if (memcmp(&a->s6_addr, &b->s6_addr, pfbytes) != 0)
360 return 0;
361
362 if (pfbits == 0 ||
363 (a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
364 return 1;
365
366 return 0;
367 }
368
369 /* return least signigicant 64 bits if IPv6 address */
370 u64 addr6part(struct in6_addr *addr)
371 {
372 int i;
373 u64 ret = 0;
374
375 for (i = 8; i < 16; i++)
376 ret = (ret << 8) + addr->s6_addr[i];
377
378 return ret;
379 }
380
381 void setaddr6part(struct in6_addr *addr, u64 host)
382 {
383 int i;
384
385 for (i = 15; i >= 8; i--)
386 {
387 addr->s6_addr[i] = host;
388 host = host >> 8;
389 }
390 }
391
392 #endif
393
394
395 /* returns port number from address */
396 int prettyprint_addr(union mysockaddr *addr, char *buf)
397 {
398 int port = 0;
399
400 #ifdef HAVE_IPV6
401 if (addr->sa.sa_family == AF_INET)
402 {
403 inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
404 port = ntohs(addr->in.sin_port);
405 }
406 else if (addr->sa.sa_family == AF_INET6)
407 {
408 char name[IF_NAMESIZE];
409 inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
410 if (addr->in6.sin6_scope_id != 0 &&
411 if_indextoname(addr->in6.sin6_scope_id, name) &&
412 strlen(buf) + strlen(name) + 2 <= ADDRSTRLEN)
413 {
414 strcat(buf, "%");
415 strcat(buf, name);
416 }
417 port = ntohs(addr->in6.sin6_port);
418 }
419 #else
420 strcpy(buf, inet_ntoa(addr->in.sin_addr));
421 port = ntohs(addr->in.sin_port);
422 #endif
423
424 return port;
425 }
426
427 void prettyprint_time(char *buf, unsigned int t)
428 {
429 if (t == 0xffffffff)
430 sprintf(buf, _("infinite"));
431 else
432 {
433 unsigned int x, p = 0;
434 if ((x = t/86400))
435 p += sprintf(&buf[p], "%dd", x);
436 if ((x = (t/3600)%24))
437 p += sprintf(&buf[p], "%dh", x);
438 if ((x = (t/60)%60))
439 p += sprintf(&buf[p], "%dm", x);
440 if ((x = t%60))
441 p += sprintf(&buf[p], "%ds", x);
442 }
443 }
444
445
446 /* in may equal out, when maxlen may be -1 (No max len).
447 Return -1 for extraneous no-hex chars found. */
448 int parse_hex(char *in, unsigned char *out, int maxlen,
449 unsigned int *wildcard_mask, int *mac_type)
450 {
451 int mask = 0, i = 0;
452 char *r;
453
454 if (mac_type)
455 *mac_type = 0;
456
457 while (maxlen == -1 || i < maxlen)
458 {
459 for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
460 if (*r != '*' && !isxdigit((unsigned char)*r))
461 return -1;
462
463 if (*r == 0)
464 maxlen = i;
465
466 if (r != in )
467 {
468 if (*r == '-' && i == 0 && mac_type)
469 {
470 *r = 0;
471 *mac_type = strtol(in, NULL, 16);
472 mac_type = NULL;
473 }
474 else
475 {
476 *r = 0;
477 if (strcmp(in, "*") == 0)
478 {
479 mask = (mask << 1) | 1;
480 i++;
481 }
482 else
483 {
484 int j, bytes = (1 + (r - in))/2;
485 for (j = 0; j < bytes; j++)
486 {
487 char sav = sav;
488 if (j < bytes - 1)
489 {
490 sav = in[(j+1)*2];
491 in[(j+1)*2] = 0;
492 }
493 out[i] = strtol(&in[j*2], NULL, 16);
494 mask = mask << 1;
495 i++;
496 if (j < bytes - 1)
497 in[(j+1)*2] = sav;
498 }
499 }
500 }
501 }
502 in = r+1;
503 }
504
505 if (wildcard_mask)
506 *wildcard_mask = mask;
507
508 return i;
509 }
510
511 /* return 0 for no match, or (no matched octets) + 1 */
512 int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
513 {
514 int i, count;
515 for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
516 if (!(mask & 1))
517 {
518 if (a[i] == b[i])
519 count++;
520 else
521 return 0;
522 }
523 return count;
524 }
525
526 /* _note_ may copy buffer */
527 int expand_buf(struct iovec *iov, size_t size)
528 {
529 void *new;
530
531 if (size <= (size_t)iov->iov_len)
532 return 1;
533
534 if (!(new = whine_malloc(size)))
535 {
536 errno = ENOMEM;
537 return 0;
538 }
539
540 if (iov->iov_base)
541 {
542 memcpy(new, iov->iov_base, iov->iov_len);
543 free(iov->iov_base);
544 }
545
546 iov->iov_base = new;
547 iov->iov_len = size;
548
549 return 1;
550 }
551
552 char *print_mac(char *buff, unsigned char *mac, int len)
553 {
554 char *p = buff;
555 int i;
556
557 if (len == 0)
558 sprintf(p, "<null>");
559 else
560 for (i = 0; i < len; i++)
561 p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
562
563 return buff;
564 }
565
566 void bump_maxfd(int fd, int *max)
567 {
568 if (fd > *max)
569 *max = fd;
570 }
571
572 /* rc is return from sendto and friends.
573 Return 1 if we should retry.
574 Set errno to zero if we succeeded. */
575 int retry_send(ssize_t rc)
576 {
577 static int retries = 0;
578 struct timespec waiter;
579
580 if (rc != -1)
581 {
582 retries = 0;
583 errno = 0;
584 return 0;
585 }
586
587 /* Linux kernels can return EAGAIN in perpetuity when calling
588 sendmsg() and the relevant interface has gone. Here we loop
589 retrying in EAGAIN for 1 second max, to avoid this hanging
590 dnsmasq. */
591
592 if (errno == EAGAIN || errno == EWOULDBLOCK)
593 {
594 waiter.tv_sec = 0;
595 waiter.tv_nsec = 10000;
596 nanosleep(&waiter, NULL);
597 if (retries++ < 1000)
598 return 1;
599 }
600
601 retries = 0;
602
603 if (errno == EINTR)
604 return 1;
605
606 return 0;
607 }
608
609 int read_write(int fd, unsigned char *packet, int size, int rw)
610 {
611 ssize_t n, done;
612
613 for (done = 0; done < size; done += n)
614 {
615 do {
616 if (rw)
617 n = read(fd, &packet[done], (size_t)(size - done));
618 else
619 n = write(fd, &packet[done], (size_t)(size - done));
620
621 if (n == 0)
622 return 0;
623
624 } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
625
626 if (errno != 0)
627 return 0;
628 }
629
630 return 1;
631 }
632
633 /* Basically match a string value against a wildcard pattern. */
634 int wildcard_match(const char* wildcard, const char* match)
635 {
636 while (*wildcard && *match)
637 {
638 if (*wildcard == '*')
639 return 1;
640
641 if (*wildcard != *match)
642 return 0;
643
644 ++wildcard;
645 ++match;
646 }
647
648 return *wildcard == *match;
649 }
650
651 /* The same but comparing a maximum of NUM characters, like strncmp. */
652 int wildcard_matchn(const char* wildcard, const char* match, int num)
653 {
654 while (*wildcard && *match && num)
655 {
656 if (*wildcard == '*')
657 return 1;
658
659 if (*wildcard != *match)
660 return 0;
661
662 ++wildcard;
663 ++match;
664 --num;
665 }
666
667 return (!num) || (*wildcard == *match);
668 }