Annotation of embedaddon/dnsmasq/src/util.c, revision 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>