Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnsmasq / src / util.c
blobaf4031c89f6f7ef9e37036a25cca1bb9f7b15f07
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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.
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.
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/>.
17 /* The SURF random number generator was taken from djbdns-1.05, by
18 Daniel J Bernstein, which is public domain. */
21 #include "dnsmasq.h"
23 #ifdef HAVE_BROKEN_RTC
24 #include <sys/times.h>
25 #endif
27 #if defined(LOCALEDIR) || defined(HAVE_IDN)
28 #include <idna.h>
29 #endif
31 #ifdef HAVE_ARC4RANDOM
32 void rand_init(void)
34 return;
37 unsigned short rand16(void)
39 return (unsigned short) (arc4random() >> 15);
42 #else
44 /* SURF random number generator */
46 static u32 seed[32];
47 static u32 in[12];
48 static u32 out[8];
50 void rand_init()
52 int fd = open(RANDFILE, O_RDONLY);
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);
59 close(fd);
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));
65 static void surf(void)
67 u32 t[12]; u32 x; u32 sum = 0;
68 int r; int i; int loop;
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)
80 for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
84 unsigned short rand16(void)
86 static int outleft = 0;
88 if (!outleft) {
89 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
90 surf();
91 outleft = 8;
94 return (unsigned short) out[--outleft];
97 #endif
99 static int check_name(char *in)
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;
107 if (l == 0 || l > MAXDNAME) return 0;
109 if (in[l-1] == '.')
111 if (l == 1) return 0;
112 in[l-1] = 0;
115 for (; (c = *in); in++)
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;
132 if (!nowhite)
133 return 0;
135 return 1;
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)
144 char c;
145 int first;
147 if (!check_name(name))
148 return 0;
150 for (first = 1; (c = *name); name++, first = 0)
151 /* check for legal char a-z A-Z 0-9 - _ . */
153 if ((c >= 'A' && c <= 'Z') ||
154 (c >= 'a' && c <= 'z'))
155 continue;
157 if (!first &&
158 ((c >= '0' && c <= '9') ||
159 c == '-' || c == '_'))
160 continue;
162 /* end of hostname part */
163 if (c == '.')
164 return 1;
166 return 0;
169 return 1;
172 char *canonicalise(char *in, int *nomem)
174 char *ret = NULL;
175 #if defined(LOCALEDIR) || defined(HAVE_IDN)
176 int rc;
177 #endif
179 if (nomem)
180 *nomem = 0;
182 if (!check_name(in))
183 return NULL;
185 #if defined(LOCALEDIR) || defined(HAVE_IDN)
186 if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
188 if (ret)
189 free(ret);
191 if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
193 my_syslog(LOG_ERR, _("failed to allocate memory"));
194 *nomem = 1;
197 return NULL;
199 #else
200 if ((ret = whine_malloc(strlen(in)+1)))
201 strcpy(ret, in);
202 else if (nomem)
203 *nomem = 1;
204 #endif
206 return ret;
209 unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
211 int j;
213 while (sval && *sval)
215 unsigned char *cp = p++;
216 for (j = 0; *sval && (*sval != '.'); sval++, j++)
217 *p++ = *sval;
218 *cp = j;
219 if (*sval)
220 sval++;
222 return p;
225 /* for use during startup */
226 void *safe_malloc(size_t size)
228 void *ret = malloc(size);
230 if (!ret)
231 die(_("could not get memory"), NULL, EC_NOMEM);
233 return ret;
236 void safe_pipe(int *fd, int read_noblock)
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);
244 void *whine_malloc(size_t size)
246 void *ret = malloc(size);
248 if (!ret)
249 my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
251 return ret;
254 int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
256 if (s1->sa.sa_family == s2->sa.sa_family)
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
269 return 0;
272 int sa_len(union mysockaddr *addr)
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
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)
289 unsigned int c1, c2;
291 do {
292 c1 = (unsigned char) *a++;
293 c2 = (unsigned char) *b++;
295 if (c1 >= 'A' && c1 <= 'Z')
296 c1 += 'a' - 'A';
297 if (c2 >= 'A' && c2 <= 'Z')
298 c2 += 'a' - 'A';
300 if (c1 != c2)
301 return 0;
302 } while (c1);
304 return 1;
307 time_t dnsmasq_time(void)
309 #ifdef HAVE_BROKEN_RTC
310 struct tms dummy;
311 static long tps = 0;
313 if (tps == 0)
314 tps = sysconf(_SC_CLK_TCK);
316 return (time_t)(times(&dummy)/tps);
317 #else
318 return time(NULL);
319 #endif
322 int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
324 return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
327 #ifdef HAVE_IPV6
328 int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
330 int pfbytes = prefixlen >> 3;
331 int pfbits = prefixlen & 7;
333 if (memcmp(&a->s6_addr, &b->s6_addr, pfbytes) != 0)
334 return 0;
336 if (pfbits == 0 ||
337 (a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
338 return 1;
340 return 0;
343 /* return least signigicant 64 bits if IPv6 address */
344 u64 addr6part(struct in6_addr *addr)
346 int i;
347 u64 ret = 0;
349 for (i = 8; i < 16; i++)
350 ret = (ret << 8) + addr->s6_addr[i];
352 return ret;
355 void setaddr6part(struct in6_addr *addr, u64 host)
357 int i;
359 for (i = 15; i >= 8; i--)
361 addr->s6_addr[i] = host;
362 host = host >> 8;
366 #endif
369 /* returns port number from address */
370 int prettyprint_addr(union mysockaddr *addr, char *buf)
372 int port = 0;
374 #ifdef HAVE_IPV6
375 if (addr->sa.sa_family == AF_INET)
377 inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
378 port = ntohs(addr->in.sin_port);
380 else if (addr->sa.sa_family == AF_INET6)
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)
388 strcat(buf, "%");
389 strcat(buf, name);
391 port = ntohs(addr->in6.sin6_port);
393 #else
394 strcpy(buf, inet_ntoa(addr->in.sin_addr));
395 port = ntohs(addr->in.sin_port);
396 #endif
398 return port;
401 void prettyprint_time(char *buf, unsigned int t)
403 if (t == 0xffffffff)
404 sprintf(buf, _("infinite"));
405 else
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);
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)
425 int mask = 0, i = 0;
426 char *r;
428 if (mac_type)
429 *mac_type = 0;
431 while (maxlen == -1 || i < maxlen)
433 for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
434 if (*r != '*' && !isxdigit((unsigned char)*r))
435 return -1;
437 if (*r == 0)
438 maxlen = i;
440 if (r != in )
442 if (*r == '-' && i == 0 && mac_type)
444 *r = 0;
445 *mac_type = strtol(in, NULL, 16);
446 mac_type = NULL;
448 else
450 *r = 0;
451 if (strcmp(in, "*") == 0)
453 mask = (mask << 1) | 1;
454 i++;
456 else
458 int j, bytes = (1 + (r - in))/2;
459 for (j = 0; j < bytes; j++)
461 char sav;
462 if (j < bytes - 1)
464 sav = in[(j+1)*2];
465 in[(j+1)*2] = 0;
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;
476 in = r+1;
479 if (wildcard_mask)
480 *wildcard_mask = mask;
482 return i;
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)
488 int i, count;
489 for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
490 if (!(mask & 1))
492 if (a[i] == b[i])
493 count++;
494 else
495 return 0;
497 return count;
500 /* _note_ may copy buffer */
501 int expand_buf(struct iovec *iov, size_t size)
503 void *new;
505 if (size <= (size_t)iov->iov_len)
506 return 1;
508 if (!(new = whine_malloc(size)))
510 errno = ENOMEM;
511 return 0;
514 if (iov->iov_base)
516 memcpy(new, iov->iov_base, iov->iov_len);
517 free(iov->iov_base);
520 iov->iov_base = new;
521 iov->iov_len = size;
523 return 1;
526 char *print_mac(char *buff, unsigned char *mac, int len)
528 char *p = buff;
529 int i;
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) ? "" : ":");
537 return buff;
540 void bump_maxfd(int fd, int *max)
542 if (fd > *max)
543 *max = fd;
546 int retry_send(void)
548 struct timespec waiter;
549 if (errno == EAGAIN || errno == EWOULDBLOCK)
551 waiter.tv_sec = 0;
552 waiter.tv_nsec = 10000;
553 nanosleep(&waiter, NULL);
554 return 1;
557 if (errno == EINTR)
558 return 1;
560 return 0;
563 int read_write(int fd, unsigned char *packet, int size, int rw)
565 ssize_t n, done;
567 for (done = 0; done < size; done += n)
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));
575 if (n == 0)
576 return 0;
577 else if (n == -1)
579 if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
580 goto retry;
581 else
582 return 0;
585 return 1;
588 /* Basically match a string value against a wildcard pattern. */
589 int wildcard_match(const char* wildcard, const char* match)
591 while (*wildcard && *match)
593 if (*wildcard == '*')
594 return 1;
596 if (*wildcard != *match)
597 return 0;
599 ++wildcard;
600 ++match;
603 return *wildcard == *match;