--- embedaddon/dnsmasq/src/util.c 2021/03/17 00:56:46 1.1.1.4 +++ embedaddon/dnsmasq/src/util.c 2023/09/27 11:02:07 1.1.1.5 @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 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 @@ -115,7 +115,8 @@ u64 rand64(void) return (u64)out[outleft+1] + (((u64)out[outleft]) << 32); } -/* returns 2 if names is OK but contains one or more underscores */ +/* returns 1 if name is OK and ascii printable + * returns 2 if name should be processed by IDN */ static int check_name(char *in) { /* remove trailing . @@ -123,7 +124,9 @@ static int check_name(char *in) size_t dotgap = 0, l = strlen(in); char c; int nowhite = 0; + int idn_encode = 0; int hasuscore = 0; + int hasucase = 0; if (l == 0 || l > MAXDNAME) return 0; @@ -136,28 +139,49 @@ static int check_name(char *in) for (; (c = *in); in++) { if (c == '.') - dotgap = 0; + dotgap = 0; else if (++dotgap > MAXLABEL) - return 0; + return 0; else if (isascii((unsigned char)c) && iscntrl((unsigned char)c)) - /* iscntrl only gives expected results for ascii */ - return 0; -#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2) + /* iscntrl only gives expected results for ascii */ + return 0; else if (!isascii((unsigned char)c)) - return 0; +#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2) + return 0; +#else + idn_encode = 1; #endif else if (c != ' ') - { - nowhite = 1; - if (c == '_') - hasuscore = 1; - } + { + nowhite = 1; +#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003) + if (c == '_') + hasuscore = 1; +#else + (void)hasuscore; +#endif + +#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) + if (c >= 'A' && c <= 'Z') + hasucase = 1; +#else + (void)hasucase; +#endif + } } if (!nowhite) return 0; - return hasuscore ? 2 : 1; +#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003) + /* Older libidn2 strips underscores, so don't do IDN processing + if the name has an underscore unless it also has non-ascii characters. */ + idn_encode = idn_encode || (hasucase && !hasuscore); +#else + idn_encode = idn_encode || hasucase; +#endif + + return (idn_encode) ? 2 : 1; } /* Hostnames have a more limited valid charset than domain names @@ -204,17 +228,11 @@ char *canonicalise(char *in, int *nomem) if (!(rc = check_name(in))) return NULL; -#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003) - /* older libidn2 strips underscores, so don't do IDN processing - if the name has an underscore (check_name() returned 2) */ - if (rc != 2) -#endif #if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) + if (rc == 2) { # ifdef HAVE_LIBIDN2 rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL); - if (rc == IDN2_DISALLOWED) - rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL); # else rc = idna_to_ascii_lz(in, &ret, 0); # endif @@ -234,12 +252,14 @@ char *canonicalise(char *in, int *nomem) return ret; } +#else + (void)rc; #endif if ((ret = whine_malloc(strlen(in)+1))) strcpy(ret, in); else if (nomem) - *nomem = 1; + *nomem = 1; return ret; } @@ -316,8 +336,18 @@ void *whine_malloc(size_t size) return ret; } -int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2) +void *whine_realloc(void *ptr, size_t size) { + void *ret = realloc(ptr, size); + + if (!ret) + my_syslog(LOG_ERR, _("failed to reallocate %d bytes"), (int) size); + + return ret; +} + +int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2) +{ if (s1->sa.sa_family == s2->sa.sa_family) { if (s1->sa.sa_family == AF_INET && @@ -334,6 +364,19 @@ int sockaddr_isequal(union mysockaddr *s1, union mysoc return 0; } +int sockaddr_isnull(const union mysockaddr *s) +{ + if (s->sa.sa_family == AF_INET && + s->in.sin_addr.s_addr == 0) + return 1; + + if (s->sa.sa_family == AF_INET6 && + IN6_IS_ADDR_UNSPECIFIED(&s->in6.sin6_addr)) + return 1; + + return 0; +} + int sa_len(union mysockaddr *addr) { #ifdef HAVE_SOCKADDR_SA_LEN @@ -347,7 +390,7 @@ int sa_len(union mysockaddr *addr) } /* don't use strcasecmp and friends here - they may be messed up by LOCALE */ -int hostname_isequal(const char *a, const char *b) +int hostname_order(const char *a, const char *b) { unsigned int c1, c2; @@ -360,13 +403,21 @@ int hostname_isequal(const char *a, const char *b) if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; - if (c1 != c2) - return 0; + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + } while (c1); - return 1; + return 0; } +int hostname_isequal(const char *a, const char *b) +{ + return hostname_order(a, b) == 0; +} + /* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */ int hostname_issubdomain(char *a, char *b) { @@ -408,18 +459,26 @@ int hostname_issubdomain(char *a, char *b) time_t dnsmasq_time(void) { #ifdef HAVE_BROKEN_RTC - struct tms dummy; - static long tps = 0; + struct timespec ts; - if (tps == 0) - tps = sysconf(_SC_CLK_TCK); + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) + die(_("cannot read monotonic clock: %s"), NULL, EC_MISC); - return (time_t)(times(&dummy)/tps); + return ts.tv_sec; #else return time(NULL); #endif } +u32 dnsmasq_milliseconds(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return (tv.tv_sec) * 1000 + (tv.tv_usec / 1000); +} + int netmask_length(struct in_addr mask) { int zero_count = 0; @@ -436,8 +495,18 @@ int netmask_length(struct in_addr mask) 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); -} +} +int is_same_net_prefix(struct in_addr a, struct in_addr b, int prefix) +{ + struct in_addr mask; + + mask.s_addr = htonl(~((1 << (32 - prefix)) - 1)); + + return is_same_net(a, b, mask); +} + + int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen) { int pfbytes = prefixlen >> 3; @@ -518,7 +587,7 @@ void prettyprint_time(char *buf, unsigned int t) if ((x = (t/60)%60)) p += sprintf(&buf[p], "%um", x); if ((x = t%60)) - p += sprintf(&buf[p], "%us", x); + sprintf(&buf[p], "%us", x); } } @@ -564,7 +633,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen int j, bytes = (1 + (r - in))/2; for (j = 0; j < bytes; j++) { - char sav = sav; + char sav; if (j < bytes - 1) { sav = in[(j+1)*2];