Annotation of embedaddon/dnsmasq/src/util.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* dnsmasq is Copyright (c) 2000-2014 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:
! 84: u64 rand64(void)
! 85: {
1.1 misho 86: static int outleft = 0;
87:
1.1.1.2 ! misho 88: if (outleft < 2)
! 89: {
! 90: if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
! 91: surf();
! 92: outleft = 8;
! 93: }
! 94:
! 95: outleft -= 2;
1.1 misho 96:
1.1.1.2 ! misho 97: return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
1.1 misho 98: }
99:
100: static int check_name(char *in)
101: {
102: /* remove trailing .
103: also fail empty string and label > 63 chars */
104: size_t dotgap = 0, l = strlen(in);
105: char c;
106: int nowhite = 0;
107:
108: if (l == 0 || l > MAXDNAME) return 0;
109:
110: if (in[l-1] == '.')
111: {
112: in[l-1] = 0;
1.1.1.2 ! misho 113: nowhite = 1;
1.1 misho 114: }
1.1.1.2 ! misho 115:
1.1 misho 116: for (; (c = *in); in++)
117: {
118: if (c == '.')
119: dotgap = 0;
120: else if (++dotgap > MAXLABEL)
121: return 0;
122: else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
123: /* iscntrl only gives expected results for ascii */
124: return 0;
125: #if !defined(LOCALEDIR) && !defined(HAVE_IDN)
126: else if (!isascii((unsigned char)c))
127: return 0;
128: #endif
129: else if (c != ' ')
130: nowhite = 1;
131: }
132:
133: if (!nowhite)
134: return 0;
135:
136: return 1;
137: }
138:
139: /* Hostnames have a more limited valid charset than domain names
140: so check for legal char a-z A-Z 0-9 - _
141: Note that this may receive a FQDN, so only check the first label
142: for the tighter criteria. */
143: int legal_hostname(char *name)
144: {
145: char c;
1.1.1.2 ! misho 146: int first;
1.1 misho 147:
148: if (!check_name(name))
149: return 0;
150:
1.1.1.2 ! misho 151: for (first = 1; (c = *name); name++, first = 0)
1.1 misho 152: /* check for legal char a-z A-Z 0-9 - _ . */
153: {
154: if ((c >= 'A' && c <= 'Z') ||
155: (c >= 'a' && c <= 'z') ||
1.1.1.2 ! misho 156: (c >= '0' && c <= '9'))
! 157: continue;
! 158:
! 159: if (!first && (c == '-' || c == '_'))
1.1 misho 160: continue;
161:
162: /* end of hostname part */
163: if (c == '.')
164: return 1;
165:
166: return 0;
167: }
168:
169: return 1;
170: }
171:
172: char *canonicalise(char *in, int *nomem)
173: {
174: char *ret = NULL;
175: #if defined(LOCALEDIR) || defined(HAVE_IDN)
176: int rc;
177: #endif
178:
179: if (nomem)
180: *nomem = 0;
181:
182: if (!check_name(in))
183: return NULL;
184:
185: #if defined(LOCALEDIR) || defined(HAVE_IDN)
186: if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
187: {
188: if (ret)
189: free(ret);
190:
191: if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
192: {
193: my_syslog(LOG_ERR, _("failed to allocate memory"));
194: *nomem = 1;
195: }
196:
197: return NULL;
198: }
199: #else
200: if ((ret = whine_malloc(strlen(in)+1)))
201: strcpy(ret, in);
202: else if (nomem)
203: *nomem = 1;
204: #endif
205:
206: return ret;
207: }
208:
209: unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
210: {
211: int j;
212:
213: while (sval && *sval)
214: {
215: unsigned char *cp = p++;
216: for (j = 0; *sval && (*sval != '.'); sval++, j++)
217: *p++ = *sval;
218: *cp = j;
219: if (*sval)
220: sval++;
221: }
222: return p;
223: }
224:
225: /* for use during startup */
226: void *safe_malloc(size_t size)
227: {
228: void *ret = malloc(size);
229:
230: if (!ret)
231: die(_("could not get memory"), NULL, EC_NOMEM);
232:
233: return ret;
234: }
235:
236: void safe_pipe(int *fd, int read_noblock)
237: {
238: if (pipe(fd) == -1 ||
239: !fix_fd(fd[1]) ||
240: (read_noblock && !fix_fd(fd[0])))
241: die(_("cannot create pipe: %s"), NULL, EC_MISC);
242: }
243:
244: void *whine_malloc(size_t size)
245: {
246: void *ret = malloc(size);
247:
248: if (!ret)
249: my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
250:
251: return ret;
252: }
253:
254: int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
255: {
256: if (s1->sa.sa_family == s2->sa.sa_family)
257: {
258: if (s1->sa.sa_family == AF_INET &&
259: s1->in.sin_port == s2->in.sin_port &&
260: s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
261: return 1;
262: #ifdef HAVE_IPV6
263: if (s1->sa.sa_family == AF_INET6 &&
264: s1->in6.sin6_port == s2->in6.sin6_port &&
265: IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
266: return 1;
267: #endif
268: }
269: return 0;
270: }
271:
272: int sa_len(union mysockaddr *addr)
273: {
274: #ifdef HAVE_SOCKADDR_SA_LEN
275: return addr->sa.sa_len;
276: #else
277: #ifdef HAVE_IPV6
278: if (addr->sa.sa_family == AF_INET6)
279: return sizeof(addr->in6);
280: else
281: #endif
282: return sizeof(addr->in);
283: #endif
284: }
285:
286: /* don't use strcasecmp and friends here - they may be messed up by LOCALE */
287: int hostname_isequal(const char *a, const char *b)
288: {
289: unsigned int c1, c2;
290:
291: do {
292: c1 = (unsigned char) *a++;
293: c2 = (unsigned char) *b++;
294:
295: if (c1 >= 'A' && c1 <= 'Z')
296: c1 += 'a' - 'A';
297: if (c2 >= 'A' && c2 <= 'Z')
298: c2 += 'a' - 'A';
299:
300: if (c1 != c2)
301: return 0;
302: } while (c1);
303:
304: return 1;
305: }
306:
307: time_t dnsmasq_time(void)
308: {
309: #ifdef HAVE_BROKEN_RTC
310: struct tms dummy;
311: static long tps = 0;
312:
313: if (tps == 0)
314: tps = sysconf(_SC_CLK_TCK);
315:
316: return (time_t)(times(&dummy)/tps);
317: #else
318: return time(NULL);
319: #endif
320: }
321:
322: int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
323: {
324: return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
325: }
326:
327: #ifdef HAVE_IPV6
328: int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
329: {
330: int pfbytes = prefixlen >> 3;
331: int pfbits = prefixlen & 7;
332:
333: if (memcmp(&a->s6_addr, &b->s6_addr, pfbytes) != 0)
334: return 0;
335:
336: if (pfbits == 0 ||
337: (a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
338: return 1;
339:
340: return 0;
341: }
342:
343: /* return least signigicant 64 bits if IPv6 address */
344: u64 addr6part(struct in6_addr *addr)
345: {
346: int i;
347: u64 ret = 0;
348:
349: for (i = 8; i < 16; i++)
350: ret = (ret << 8) + addr->s6_addr[i];
351:
352: return ret;
353: }
354:
355: void setaddr6part(struct in6_addr *addr, u64 host)
356: {
357: int i;
358:
359: for (i = 15; i >= 8; i--)
360: {
361: addr->s6_addr[i] = host;
362: host = host >> 8;
363: }
364: }
365:
366: #endif
367:
368:
369: /* returns port number from address */
370: int prettyprint_addr(union mysockaddr *addr, char *buf)
371: {
372: int port = 0;
373:
374: #ifdef HAVE_IPV6
375: if (addr->sa.sa_family == AF_INET)
376: {
377: inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
378: port = ntohs(addr->in.sin_port);
379: }
380: else if (addr->sa.sa_family == AF_INET6)
381: {
382: char name[IF_NAMESIZE];
383: inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
384: if (addr->in6.sin6_scope_id != 0 &&
385: if_indextoname(addr->in6.sin6_scope_id, name) &&
386: strlen(buf) + strlen(name) + 2 <= ADDRSTRLEN)
387: {
388: strcat(buf, "%");
389: strcat(buf, name);
390: }
391: port = ntohs(addr->in6.sin6_port);
392: }
393: #else
394: strcpy(buf, inet_ntoa(addr->in.sin_addr));
395: port = ntohs(addr->in.sin_port);
396: #endif
397:
398: return port;
399: }
400:
401: void prettyprint_time(char *buf, unsigned int t)
402: {
403: if (t == 0xffffffff)
404: sprintf(buf, _("infinite"));
405: else
406: {
407: unsigned int x, p = 0;
408: if ((x = t/86400))
409: p += sprintf(&buf[p], "%dd", x);
410: if ((x = (t/3600)%24))
411: p += sprintf(&buf[p], "%dh", x);
412: if ((x = (t/60)%60))
413: p += sprintf(&buf[p], "%dm", x);
414: if ((x = t%60))
415: p += sprintf(&buf[p], "%ds", x);
416: }
417: }
418:
419:
420: /* in may equal out, when maxlen may be -1 (No max len).
421: Return -1 for extraneous no-hex chars found. */
422: int parse_hex(char *in, unsigned char *out, int maxlen,
423: unsigned int *wildcard_mask, int *mac_type)
424: {
425: int mask = 0, i = 0;
426: char *r;
427:
428: if (mac_type)
429: *mac_type = 0;
430:
431: while (maxlen == -1 || i < maxlen)
432: {
433: for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
434: if (*r != '*' && !isxdigit((unsigned char)*r))
435: return -1;
436:
437: if (*r == 0)
438: maxlen = i;
439:
440: if (r != in )
441: {
442: if (*r == '-' && i == 0 && mac_type)
443: {
444: *r = 0;
445: *mac_type = strtol(in, NULL, 16);
446: mac_type = NULL;
447: }
448: else
449: {
450: *r = 0;
451: if (strcmp(in, "*") == 0)
452: {
453: mask = (mask << 1) | 1;
454: i++;
455: }
456: else
457: {
458: int j, bytes = (1 + (r - in))/2;
459: for (j = 0; j < bytes; j++)
460: {
1.1.1.2 ! misho 461: char sav = sav;
1.1 misho 462: if (j < bytes - 1)
463: {
464: sav = in[(j+1)*2];
465: in[(j+1)*2] = 0;
466: }
467: out[i] = strtol(&in[j*2], NULL, 16);
468: mask = mask << 1;
469: i++;
470: if (j < bytes - 1)
471: in[(j+1)*2] = sav;
472: }
473: }
474: }
475: }
476: in = r+1;
477: }
478:
479: if (wildcard_mask)
480: *wildcard_mask = mask;
481:
482: return i;
483: }
484:
485: /* return 0 for no match, or (no matched octets) + 1 */
486: int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
487: {
488: int i, count;
489: for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
490: if (!(mask & 1))
491: {
492: if (a[i] == b[i])
493: count++;
494: else
495: return 0;
496: }
497: return count;
498: }
499:
500: /* _note_ may copy buffer */
501: int expand_buf(struct iovec *iov, size_t size)
502: {
503: void *new;
504:
505: if (size <= (size_t)iov->iov_len)
506: return 1;
507:
508: if (!(new = whine_malloc(size)))
509: {
510: errno = ENOMEM;
511: return 0;
512: }
513:
514: if (iov->iov_base)
515: {
516: memcpy(new, iov->iov_base, iov->iov_len);
517: free(iov->iov_base);
518: }
519:
520: iov->iov_base = new;
521: iov->iov_len = size;
522:
523: return 1;
524: }
525:
526: char *print_mac(char *buff, unsigned char *mac, int len)
527: {
528: char *p = buff;
529: int i;
530:
531: if (len == 0)
532: sprintf(p, "<null>");
533: else
534: for (i = 0; i < len; i++)
535: p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
536:
537: return buff;
538: }
539:
540: void bump_maxfd(int fd, int *max)
541: {
542: if (fd > *max)
543: *max = fd;
544: }
545:
546: int retry_send(void)
547: {
548: struct timespec waiter;
549: if (errno == EAGAIN || errno == EWOULDBLOCK)
550: {
551: waiter.tv_sec = 0;
552: waiter.tv_nsec = 10000;
553: nanosleep(&waiter, NULL);
554: return 1;
555: }
556:
557: if (errno == EINTR)
558: return 1;
559:
560: return 0;
561: }
562:
563: int read_write(int fd, unsigned char *packet, int size, int rw)
564: {
565: ssize_t n, done;
566:
567: for (done = 0; done < size; done += n)
568: {
569: retry:
570: if (rw)
571: n = read(fd, &packet[done], (size_t)(size - done));
572: else
573: n = write(fd, &packet[done], (size_t)(size - done));
574:
575: if (n == 0)
576: return 0;
577: else if (n == -1)
578: {
579: if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
580: goto retry;
581: else
582: return 0;
583: }
584: }
585: return 1;
586: }
587:
588: /* Basically match a string value against a wildcard pattern. */
589: int wildcard_match(const char* wildcard, const char* match)
590: {
591: while (*wildcard && *match)
592: {
593: if (*wildcard == '*')
594: return 1;
595:
596: if (*wildcard != *match)
597: return 0;
598:
599: ++wildcard;
600: ++match;
601: }
602:
603: return *wildcard == *match;
604: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>