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