Annotation of embedaddon/dnsmasq/src/util.c, revision 1.1.1.3
1.1.1.3 ! misho 1: /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
1.1 misho 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];
1.1.1.2 misho 36: static int outleft = 0;
1.1 misho 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: {
1.1.1.2 misho 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:
1.1.1.3 ! misho 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:
1.1.1.2 misho 96: u64 rand64(void)
97: {
1.1 misho 98: static int outleft = 0;
99:
1.1.1.2 misho 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;
1.1 misho 108:
1.1.1.2 misho 109: return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
1.1 misho 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;
1.1.1.2 misho 125: nowhite = 1;
1.1 misho 126: }
1.1.1.2 misho 127:
1.1 misho 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;
1.1.1.2 misho 158: int first;
1.1 misho 159:
160: if (!check_name(name))
161: return 0;
162:
1.1.1.2 misho 163: for (first = 1; (c = *name); name++, first = 0)
1.1 misho 164: /* check for legal char a-z A-Z 0-9 - _ . */
165: {
166: if ((c >= 'A' && c <= 'Z') ||
167: (c >= 'a' && c <= 'z') ||
1.1.1.2 misho 168: (c >= '0' && c <= '9'))
169: continue;
170:
171: if (!first && (c == '-' || c == '_'))
1.1 misho 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++)
1.1.1.3 ! misho 229: {
! 230: #ifdef HAVE_DNSSEC
! 231: if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
! 232: *p++ = (*(++sval))-1;
! 233: else
! 234: #endif
! 235: *p++ = *sval;
! 236: }
1.1 misho 237: *cp = j;
238: if (*sval)
239: sval++;
240: }
241: return p;
242: }
243:
244: /* for use during startup */
245: void *safe_malloc(size_t size)
246: {
247: void *ret = malloc(size);
248:
249: if (!ret)
250: die(_("could not get memory"), NULL, EC_NOMEM);
251:
252: return ret;
253: }
254:
255: void safe_pipe(int *fd, int read_noblock)
256: {
257: if (pipe(fd) == -1 ||
258: !fix_fd(fd[1]) ||
259: (read_noblock && !fix_fd(fd[0])))
260: die(_("cannot create pipe: %s"), NULL, EC_MISC);
261: }
262:
263: void *whine_malloc(size_t size)
264: {
265: void *ret = malloc(size);
266:
267: if (!ret)
268: my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
269:
270: return ret;
271: }
272:
273: int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
274: {
275: if (s1->sa.sa_family == s2->sa.sa_family)
276: {
277: if (s1->sa.sa_family == AF_INET &&
278: s1->in.sin_port == s2->in.sin_port &&
279: s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
280: return 1;
281: #ifdef HAVE_IPV6
282: if (s1->sa.sa_family == AF_INET6 &&
283: s1->in6.sin6_port == s2->in6.sin6_port &&
1.1.1.3 ! misho 284: s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
1.1 misho 285: IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
286: return 1;
287: #endif
288: }
289: return 0;
290: }
291:
292: int sa_len(union mysockaddr *addr)
293: {
294: #ifdef HAVE_SOCKADDR_SA_LEN
295: return addr->sa.sa_len;
296: #else
297: #ifdef HAVE_IPV6
298: if (addr->sa.sa_family == AF_INET6)
299: return sizeof(addr->in6);
300: else
301: #endif
302: return sizeof(addr->in);
303: #endif
304: }
305:
306: /* don't use strcasecmp and friends here - they may be messed up by LOCALE */
307: int hostname_isequal(const char *a, const char *b)
308: {
309: unsigned int c1, c2;
310:
311: do {
312: c1 = (unsigned char) *a++;
313: c2 = (unsigned char) *b++;
314:
315: if (c1 >= 'A' && c1 <= 'Z')
316: c1 += 'a' - 'A';
317: if (c2 >= 'A' && c2 <= 'Z')
318: c2 += 'a' - 'A';
319:
320: if (c1 != c2)
321: return 0;
322: } while (c1);
323:
324: return 1;
325: }
326:
327: time_t dnsmasq_time(void)
328: {
329: #ifdef HAVE_BROKEN_RTC
330: struct tms dummy;
331: static long tps = 0;
332:
333: if (tps == 0)
334: tps = sysconf(_SC_CLK_TCK);
335:
336: return (time_t)(times(&dummy)/tps);
337: #else
338: return time(NULL);
339: #endif
340: }
341:
1.1.1.3 ! misho 342: int netmask_length(struct in_addr mask)
! 343: {
! 344: int zero_count = 0;
! 345:
! 346: while (0x0 == (mask.s_addr & 0x1) && zero_count < 32)
! 347: {
! 348: mask.s_addr >>= 1;
! 349: zero_count++;
! 350: }
! 351:
! 352: return 32 - zero_count;
! 353: }
! 354:
1.1 misho 355: int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
356: {
357: return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
358: }
359:
360: #ifdef HAVE_IPV6
361: int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
362: {
363: int pfbytes = prefixlen >> 3;
364: int pfbits = prefixlen & 7;
365:
366: if (memcmp(&a->s6_addr, &b->s6_addr, pfbytes) != 0)
367: return 0;
368:
369: if (pfbits == 0 ||
370: (a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
371: return 1;
372:
373: return 0;
374: }
375:
376: /* return least signigicant 64 bits if IPv6 address */
377: u64 addr6part(struct in6_addr *addr)
378: {
379: int i;
380: u64 ret = 0;
381:
382: for (i = 8; i < 16; i++)
383: ret = (ret << 8) + addr->s6_addr[i];
384:
385: return ret;
386: }
387:
388: void setaddr6part(struct in6_addr *addr, u64 host)
389: {
390: int i;
391:
392: for (i = 15; i >= 8; i--)
393: {
394: addr->s6_addr[i] = host;
395: host = host >> 8;
396: }
397: }
398:
399: #endif
400:
401:
402: /* returns port number from address */
403: int prettyprint_addr(union mysockaddr *addr, char *buf)
404: {
405: int port = 0;
406:
407: #ifdef HAVE_IPV6
408: if (addr->sa.sa_family == AF_INET)
409: {
410: inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
411: port = ntohs(addr->in.sin_port);
412: }
413: else if (addr->sa.sa_family == AF_INET6)
414: {
415: char name[IF_NAMESIZE];
416: inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
417: if (addr->in6.sin6_scope_id != 0 &&
418: if_indextoname(addr->in6.sin6_scope_id, name) &&
419: strlen(buf) + strlen(name) + 2 <= ADDRSTRLEN)
420: {
421: strcat(buf, "%");
422: strcat(buf, name);
423: }
424: port = ntohs(addr->in6.sin6_port);
425: }
426: #else
427: strcpy(buf, inet_ntoa(addr->in.sin_addr));
428: port = ntohs(addr->in.sin_port);
429: #endif
430:
431: return port;
432: }
433:
434: void prettyprint_time(char *buf, unsigned int t)
435: {
436: if (t == 0xffffffff)
437: sprintf(buf, _("infinite"));
438: else
439: {
440: unsigned int x, p = 0;
441: if ((x = t/86400))
442: p += sprintf(&buf[p], "%dd", x);
443: if ((x = (t/3600)%24))
444: p += sprintf(&buf[p], "%dh", x);
445: if ((x = (t/60)%60))
446: p += sprintf(&buf[p], "%dm", x);
447: if ((x = t%60))
448: p += sprintf(&buf[p], "%ds", x);
449: }
450: }
451:
452:
453: /* in may equal out, when maxlen may be -1 (No max len).
454: Return -1 for extraneous no-hex chars found. */
455: int parse_hex(char *in, unsigned char *out, int maxlen,
456: unsigned int *wildcard_mask, int *mac_type)
457: {
458: int mask = 0, i = 0;
459: char *r;
460:
461: if (mac_type)
462: *mac_type = 0;
463:
464: while (maxlen == -1 || i < maxlen)
465: {
466: for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
467: if (*r != '*' && !isxdigit((unsigned char)*r))
468: return -1;
469:
470: if (*r == 0)
471: maxlen = i;
472:
473: if (r != in )
474: {
475: if (*r == '-' && i == 0 && mac_type)
476: {
477: *r = 0;
478: *mac_type = strtol(in, NULL, 16);
479: mac_type = NULL;
480: }
481: else
482: {
483: *r = 0;
484: if (strcmp(in, "*") == 0)
485: {
486: mask = (mask << 1) | 1;
487: i++;
488: }
489: else
490: {
491: int j, bytes = (1 + (r - in))/2;
492: for (j = 0; j < bytes; j++)
493: {
1.1.1.2 misho 494: char sav = sav;
1.1 misho 495: if (j < bytes - 1)
496: {
497: sav = in[(j+1)*2];
498: in[(j+1)*2] = 0;
499: }
500: out[i] = strtol(&in[j*2], NULL, 16);
501: mask = mask << 1;
502: i++;
503: if (j < bytes - 1)
504: in[(j+1)*2] = sav;
505: }
506: }
507: }
508: }
509: in = r+1;
510: }
511:
512: if (wildcard_mask)
513: *wildcard_mask = mask;
514:
515: return i;
516: }
517:
518: /* return 0 for no match, or (no matched octets) + 1 */
519: int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
520: {
521: int i, count;
522: for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
523: if (!(mask & 1))
524: {
525: if (a[i] == b[i])
526: count++;
527: else
528: return 0;
529: }
530: return count;
531: }
532:
533: /* _note_ may copy buffer */
534: int expand_buf(struct iovec *iov, size_t size)
535: {
536: void *new;
537:
538: if (size <= (size_t)iov->iov_len)
539: return 1;
540:
541: if (!(new = whine_malloc(size)))
542: {
543: errno = ENOMEM;
544: return 0;
545: }
546:
547: if (iov->iov_base)
548: {
549: memcpy(new, iov->iov_base, iov->iov_len);
550: free(iov->iov_base);
551: }
552:
553: iov->iov_base = new;
554: iov->iov_len = size;
555:
556: return 1;
557: }
558:
559: char *print_mac(char *buff, unsigned char *mac, int len)
560: {
561: char *p = buff;
562: int i;
563:
564: if (len == 0)
565: sprintf(p, "<null>");
566: else
567: for (i = 0; i < len; i++)
568: p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
569:
570: return buff;
571: }
572:
1.1.1.3 ! misho 573: /* rc is return from sendto and friends.
! 574: Return 1 if we should retry.
! 575: Set errno to zero if we succeeded. */
! 576: int retry_send(ssize_t rc)
1.1 misho 577: {
1.1.1.3 ! misho 578: static int retries = 0;
! 579: struct timespec waiter;
! 580:
! 581: if (rc != -1)
! 582: {
! 583: retries = 0;
! 584: errno = 0;
! 585: return 0;
! 586: }
! 587:
! 588: /* Linux kernels can return EAGAIN in perpetuity when calling
! 589: sendmsg() and the relevant interface has gone. Here we loop
! 590: retrying in EAGAIN for 1 second max, to avoid this hanging
! 591: dnsmasq. */
1.1 misho 592:
1.1.1.3 ! misho 593: if (errno == EAGAIN || errno == EWOULDBLOCK)
1.1 misho 594: {
595: waiter.tv_sec = 0;
596: waiter.tv_nsec = 10000;
597: nanosleep(&waiter, NULL);
1.1.1.3 ! misho 598: if (retries++ < 1000)
! 599: return 1;
1.1 misho 600: }
1.1.1.3 ! misho 601:
! 602: retries = 0;
! 603:
! 604: if (errno == EINTR)
! 605: return 1;
! 606:
! 607: return 0;
1.1 misho 608: }
609:
610: int read_write(int fd, unsigned char *packet, int size, int rw)
611: {
612: ssize_t n, done;
613:
614: for (done = 0; done < size; done += n)
615: {
1.1.1.3 ! misho 616: do {
! 617: if (rw)
! 618: n = read(fd, &packet[done], (size_t)(size - done));
! 619: else
! 620: n = write(fd, &packet[done], (size_t)(size - done));
! 621:
! 622: if (n == 0)
! 623: return 0;
! 624:
! 625: } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
! 626:
! 627: if (errno != 0)
! 628: return 0;
1.1 misho 629: }
1.1.1.3 ! misho 630:
1.1 misho 631: return 1;
632: }
633:
634: /* Basically match a string value against a wildcard pattern. */
635: int wildcard_match(const char* wildcard, const char* match)
636: {
637: while (*wildcard && *match)
638: {
639: if (*wildcard == '*')
640: return 1;
641:
642: if (*wildcard != *match)
643: return 0;
644:
645: ++wildcard;
646: ++match;
647: }
648:
649: return *wildcard == *match;
1.1.1.3 ! misho 650: }
! 651:
! 652: /* The same but comparing a maximum of NUM characters, like strncmp. */
! 653: int wildcard_matchn(const char* wildcard, const char* match, int num)
! 654: {
! 655: while (*wildcard && *match && num)
! 656: {
! 657: if (*wildcard == '*')
! 658: return 1;
! 659:
! 660: if (*wildcard != *match)
! 661: return 0;
! 662:
! 663: ++wildcard;
! 664: ++match;
! 665: --num;
! 666: }
! 667:
! 668: return (!num) || (*wildcard == *match);
1.1 misho 669: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>