--- embedaddon/dnsmasq/src/util.c 2014/06/15 16:31:38 1.1.1.2 +++ embedaddon/dnsmasq/src/util.c 2016/11/02 09:57:01 1.1.1.3 @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,6 +81,18 @@ unsigned short rand16(void) return (unsigned short) out[--outleft]; } +u32 rand32(void) +{ + if (!outleft) + { + if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3]; + surf(); + outleft = 8; + } + + return out[--outleft]; +} + u64 rand64(void) { static int outleft = 0; @@ -214,7 +226,14 @@ unsigned char *do_rfc1035_name(unsigned char *p, char { unsigned char *cp = p++; for (j = 0; *sval && (*sval != '.'); sval++, j++) - *p++ = *sval; + { +#ifdef HAVE_DNSSEC + if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE) + *p++ = (*(++sval))-1; + else +#endif + *p++ = *sval; + } *cp = j; if (*sval) sval++; @@ -262,6 +281,7 @@ int sockaddr_isequal(union mysockaddr *s1, union mysoc #ifdef HAVE_IPV6 if (s1->sa.sa_family == AF_INET6 && s1->in6.sin6_port == s2->in6.sin6_port && + s1->in6.sin6_scope_id == s2->in6.sin6_scope_id && IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr)) return 1; #endif @@ -319,6 +339,19 @@ time_t dnsmasq_time(void) #endif } +int netmask_length(struct in_addr mask) +{ + int zero_count = 0; + + while (0x0 == (mask.s_addr & 0x1) && zero_count < 32) + { + mask.s_addr >>= 1; + zero_count++; + } + + return 32 - zero_count; +} + int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) { return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); @@ -537,27 +570,41 @@ char *print_mac(char *buff, unsigned char *mac, int le return buff; } -void bump_maxfd(int fd, int *max) +/* rc is return from sendto and friends. + Return 1 if we should retry. + Set errno to zero if we succeeded. */ +int retry_send(ssize_t rc) { - if (fd > *max) - *max = fd; -} + static int retries = 0; + struct timespec waiter; + + if (rc != -1) + { + retries = 0; + errno = 0; + return 0; + } + + /* Linux kernels can return EAGAIN in perpetuity when calling + sendmsg() and the relevant interface has gone. Here we loop + retrying in EAGAIN for 1 second max, to avoid this hanging + dnsmasq. */ -int retry_send(void) -{ - struct timespec waiter; - if (errno == EAGAIN || errno == EWOULDBLOCK) + if (errno == EAGAIN || errno == EWOULDBLOCK) { waiter.tv_sec = 0; waiter.tv_nsec = 10000; nanosleep(&waiter, NULL); - return 1; + if (retries++ < 1000) + return 1; } - - if (errno == EINTR) - return 1; - - return 0; + + retries = 0; + + if (errno == EINTR) + return 1; + + return 0; } int read_write(int fd, unsigned char *packet, int size, int rw) @@ -566,22 +613,21 @@ int read_write(int fd, unsigned char *packet, int size for (done = 0; done < size; done += n) { - retry: - if (rw) - n = read(fd, &packet[done], (size_t)(size - done)); - else - n = write(fd, &packet[done], (size_t)(size - done)); + do { + if (rw) + n = read(fd, &packet[done], (size_t)(size - done)); + else + n = write(fd, &packet[done], (size_t)(size - done)); + + if (n == 0) + return 0; + + } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS); - if (n == 0) - return 0; - else if (n == -1) - { - if (retry_send() || errno == ENOMEM || errno == ENOBUFS) - goto retry; - else - return 0; - } + if (errno != 0) + return 0; } + return 1; } @@ -601,4 +647,23 @@ int wildcard_match(const char* wildcard, const char* m } return *wildcard == *match; +} + +/* The same but comparing a maximum of NUM characters, like strncmp. */ +int wildcard_matchn(const char* wildcard, const char* match, int num) +{ + while (*wildcard && *match && num) + { + if (*wildcard == '*') + return 1; + + if (*wildcard != *match) + return 0; + + ++wildcard; + ++match; + --num; + } + + return (!num) || (*wildcard == *match); }