Diff for /embedaddon/dnsmasq/src/util.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2016/11/02 09:57:01 version 1.1.1.4, 2021/03/17 00:56:46
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     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     it under the terms of the GNU General Public License as published by
Line 24 Line 24
 #include <sys/times.h>  #include <sys/times.h>
 #endif  #endif
   
#if defined(LOCALEDIR) || defined(HAVE_IDN)#if defined(HAVE_LIBIDN2)
 #include <idn2.h>
 #elif defined(HAVE_IDN)
 #include <idna.h>  #include <idna.h>
 #endif  #endif
   
   #ifdef HAVE_LINUX_NETWORK
   #include <sys/utsname.h>
   #endif
   
 /* SURF random number generator */  /* SURF random number generator */
   
 static u32 seed[32];  static u32 seed[32];
Line 109  u64 rand64(void) Line 115  u64 rand64(void)
   return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);    return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
 }  }
   
   /* returns 2 if names is OK but contains one or more underscores */
 static int check_name(char *in)  static int check_name(char *in)
 {  {
   /* remove trailing .     /* remove trailing . 
Line 116  static int check_name(char *in) Line 123  static int check_name(char *in)
   size_t dotgap = 0, l = strlen(in);    size_t dotgap = 0, l = strlen(in);
   char c;    char c;
   int nowhite = 0;    int nowhite = 0;
     int hasuscore = 0;
       
   if (l == 0 || l > MAXDNAME) return 0;    if (l == 0 || l > MAXDNAME) return 0;
       
Line 134  static int check_name(char *in) Line 142  static int check_name(char *in)
       else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))         else if (isascii((unsigned char)c) && iscntrl((unsigned char)c)) 
         /* iscntrl only gives expected results for ascii */          /* iscntrl only gives expected results for ascii */
         return 0;          return 0;
#if !defined(LOCALEDIR) && !defined(HAVE_IDN)#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
       else if (!isascii((unsigned char)c))        else if (!isascii((unsigned char)c))
         return 0;          return 0;
 #endif  #endif
       else if (c != ' ')        else if (c != ' ')
        nowhite = 1;        {
           nowhite = 1;
           if (c == '_')
             hasuscore = 1;
         }
     }      }
   
   if (!nowhite)    if (!nowhite)
     return 0;      return 0;
   
  return 1;  return hasuscore ? 2 : 1;
 }  }
   
 /* Hostnames have a more limited valid charset than domain names  /* Hostnames have a more limited valid charset than domain names
Line 184  int legal_hostname(char *name) Line 196  int legal_hostname(char *name)
 char *canonicalise(char *in, int *nomem)  char *canonicalise(char *in, int *nomem)
 {  {
   char *ret = NULL;    char *ret = NULL;
 #if defined(LOCALEDIR) || defined(HAVE_IDN)  
   int rc;    int rc;
#endif  
 
   if (nomem)    if (nomem)
     *nomem = 0;      *nomem = 0;
       
  if (!check_name(in))  if (!(rc = check_name(in)))
     return NULL;      return NULL;
       
#if defined(LOCALEDIR) || defined(HAVE_IDN)#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
  if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)  /* 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 (ret)#  ifdef HAVE_LIBIDN2
        free(ret);      rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
      if (rc == IDN2_DISALLOWED)
      if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))        rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
 #  else
       rc = idna_to_ascii_lz(in, &ret, 0);
 #  endif
       if (rc != IDNA_SUCCESS)
         {          {
          my_syslog(LOG_ERR, _("failed to allocate memory"));          if (ret)
          *nomem = 1;            free(ret);
           
           if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
             {
               my_syslog(LOG_ERR, _("failed to allocate memory"));
               *nomem = 1;
             }
           
           return NULL;
         }          }
          
      return NULL;      return ret;
     }      }
#else#endif
   
   if ((ret = whine_malloc(strlen(in)+1)))    if ((ret = whine_malloc(strlen(in)+1)))
     strcpy(ret, in);      strcpy(ret, in);
   else if (nomem)    else if (nomem)
     *nomem = 1;          *nomem = 1;    
 #endif  
   
   return ret;    return ret;
 }  }
   
unsigned char *do_rfc1035_name(unsigned char *p, char *sval)unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
 {  {
   int j;    int j;
       
   while (sval && *sval)    while (sval && *sval)
     {      {
       unsigned char *cp = p++;        unsigned char *cp = p++;
   
         if (limit && p > (unsigned char*)limit)
           return NULL;
   
       for (j = 0; *sval && (*sval != '.'); sval++, j++)        for (j = 0; *sval && (*sval != '.'); sval++, j++)
         {          {
             if (limit && p + 1 > (unsigned char*)limit)
               return NULL;
   
 #ifdef HAVE_DNSSEC  #ifdef HAVE_DNSSEC
           if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)            if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
             *p++ = (*(++sval))-1;              *p++ = (*(++sval))-1;
Line 234  unsigned char *do_rfc1035_name(unsigned char *p, char  Line 267  unsigned char *do_rfc1035_name(unsigned char *p, char 
 #endif            #endif          
             *p++ = *sval;              *p++ = *sval;
         }          }
         
       *cp  = j;        *cp  = j;
       if (*sval)        if (*sval)
         sval++;          sval++;
     }      }
     
   return p;    return p;
 }  }
   
 /* for use during startup */  /* for use during startup */
 void *safe_malloc(size_t size)  void *safe_malloc(size_t size)
 {  {
  void *ret = malloc(size);  void *ret = calloc(1, size);
       
   if (!ret)    if (!ret)
     die(_("could not get memory"), NULL, EC_NOMEM);      die(_("could not get memory"), NULL, EC_NOMEM);
           
   return ret;    return ret;
}    }
   
   /* Ensure limited size string is always terminated.
    * Can be replaced by (void)strlcpy() on some platforms */
   void safe_strncpy(char *dest, const char *src, size_t size)
   {
     if (size != 0)
       {
         dest[size-1] = '\0';
         strncpy(dest, src, size-1);
       }
   }
   
 void safe_pipe(int *fd, int read_noblock)  void safe_pipe(int *fd, int read_noblock)
 {  {
   if (pipe(fd) == -1 ||     if (pipe(fd) == -1 || 
Line 262  void safe_pipe(int *fd, int read_noblock) Line 308  void safe_pipe(int *fd, int read_noblock)
   
 void *whine_malloc(size_t size)  void *whine_malloc(size_t size)
 {  {
  void *ret = malloc(size);  void *ret = calloc(1, size);
   
   if (!ret)    if (!ret)
     my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);      my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
  
   return ret;    return ret;
 }  }
   
Line 278  int sockaddr_isequal(union mysockaddr *s1, union mysoc Line 324  int sockaddr_isequal(union mysockaddr *s1, union mysoc
           s1->in.sin_port == s2->in.sin_port &&            s1->in.sin_port == s2->in.sin_port &&
           s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)            s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
         return 1;          return 1;
#ifdef HAVE_IPV6            
       if (s1->sa.sa_family == AF_INET6 &&        if (s1->sa.sa_family == AF_INET6 &&
           s1->in6.sin6_port == s2->in6.sin6_port &&            s1->in6.sin6_port == s2->in6.sin6_port &&
           s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&            s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
           IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))            IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
         return 1;          return 1;
 #endif  
     }      }
   return 0;    return 0;
 }  }
Line 294  int sa_len(union mysockaddr *addr) Line 339  int sa_len(union mysockaddr *addr)
 #ifdef HAVE_SOCKADDR_SA_LEN  #ifdef HAVE_SOCKADDR_SA_LEN
   return addr->sa.sa_len;    return addr->sa.sa_len;
 #else  #else
 #ifdef HAVE_IPV6  
   if (addr->sa.sa_family == AF_INET6)    if (addr->sa.sa_family == AF_INET6)
     return sizeof(addr->in6);      return sizeof(addr->in6);
   else    else
 #endif  
     return sizeof(addr->in);       return sizeof(addr->in); 
 #endif  #endif
 }  }
Line 323  int hostname_isequal(const char *a, const char *b) Line 366  int hostname_isequal(const char *a, const char *b)
       
   return 1;    return 1;
 }  }
    
 /* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
 int hostname_issubdomain(char *a, char *b)
 {
   char *ap, *bp;
   unsigned int c1, c2;
   
   /* move to the end */
   for (ap = a; *ap; ap++); 
   for (bp = b; *bp; bp++);
 
   /* a shorter than b or a empty. */
   if ((bp - b) < (ap - a) || ap == a)
     return 0;
 
   do
     {
       c1 = (unsigned char) *(--ap);
       c2 = (unsigned char) *(--bp);
   
        if (c1 >= 'A' && c1 <= 'Z')
          c1 += 'a' - 'A';
        if (c2 >= 'A' && c2 <= 'Z')
          c2 += 'a' - 'A';
 
        if (c1 != c2)
          return 0;
     } while (ap != a);
 
   if (bp == b)
     return 2;
 
   if (*(--bp) == '.')
     return 1;
 
   return 0;
 }
  
   
 time_t dnsmasq_time(void)  time_t dnsmasq_time(void)
 {  {
 #ifdef HAVE_BROKEN_RTC  #ifdef HAVE_BROKEN_RTC
Line 357  int is_same_net(struct in_addr a, struct in_addr b, st Line 438  int is_same_net(struct in_addr a, struct in_addr b, st
   return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);    return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
 }   } 
   
 #ifdef HAVE_IPV6  
 int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)  int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
 {  {
   int pfbytes = prefixlen >> 3;    int pfbytes = prefixlen >> 3;
Line 373  int is_same_net6(struct in6_addr *a, struct in6_addr * Line 453  int is_same_net6(struct in6_addr *a, struct in6_addr *
   return 0;    return 0;
 }  }
   
/* return least signigicant 64 bits if IPv6 address *//* return least significant 64 bits if IPv6 address */
 u64 addr6part(struct in6_addr *addr)  u64 addr6part(struct in6_addr *addr)
 {  {
   int i;    int i;
Line 396  void setaddr6part(struct in6_addr *addr, u64 host) Line 476  void setaddr6part(struct in6_addr *addr, u64 host)
     }      }
 }  }
   
 #endif  
    
   
 /* returns port number from address */  /* returns port number from address */
 int prettyprint_addr(union mysockaddr *addr, char *buf)  int prettyprint_addr(union mysockaddr *addr, char *buf)
 {  {
   int port = 0;    int port = 0;
       
 #ifdef HAVE_IPV6  
   if (addr->sa.sa_family == AF_INET)    if (addr->sa.sa_family == AF_INET)
     {      {
       inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);        inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
Line 423  int prettyprint_addr(union mysockaddr *addr, char *buf Line 500  int prettyprint_addr(union mysockaddr *addr, char *buf
         }          }
       port = ntohs(addr->in6.sin6_port);        port = ntohs(addr->in6.sin6_port);
     }      }
 #else  
   strcpy(buf, inet_ntoa(addr->in.sin_addr));  
   port = ntohs(addr->in.sin_port);   
 #endif  
       
   return port;    return port;
 }  }
Line 439  void prettyprint_time(char *buf, unsigned int t) Line 512  void prettyprint_time(char *buf, unsigned int t)
     {      {
       unsigned int x, p = 0;        unsigned int x, p = 0;
        if ((x = t/86400))         if ((x = t/86400))
        p += sprintf(&buf[p], "%dd", x);        p += sprintf(&buf[p], "%ud", x);
        if ((x = (t/3600)%24))         if ((x = (t/3600)%24))
        p += sprintf(&buf[p], "%dh", x);        p += sprintf(&buf[p], "%uh", x);
       if ((x = (t/60)%60))        if ((x = (t/60)%60))
        p += sprintf(&buf[p], "%dm", x);        p += sprintf(&buf[p], "%um", x);
       if ((x = t%60))        if ((x = t%60))
        p += sprintf(&buf[p], "%ds", x);        p += sprintf(&buf[p], "%us", x);
     }      }
 }  }
   
Line 455  void prettyprint_time(char *buf, unsigned int t) Line 528  void prettyprint_time(char *buf, unsigned int t)
 int parse_hex(char *in, unsigned char *out, int maxlen,   int parse_hex(char *in, unsigned char *out, int maxlen, 
               unsigned int *wildcard_mask, int *mac_type)                unsigned int *wildcard_mask, int *mac_type)
 {  {
  int mask = 0, i = 0;  int done = 0, mask = 0, i = 0;
   char *r;    char *r;
           
   if (mac_type)    if (mac_type)
     *mac_type = 0;      *mac_type = 0;
       
  while (maxlen == -1 || i < maxlen)  while (!done && (maxlen == -1 || i < maxlen))
     {      {
       for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)        for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
         if (*r != '*' && !isxdigit((unsigned char)*r))          if (*r != '*' && !isxdigit((unsigned char)*r))
           return -1;            return -1;
               
       if (*r == 0)        if (*r == 0)
        maxlen = i;        done = 1;
               
       if (r != in )        if (r != in )
         {          {
Line 497  int parse_hex(char *in, unsigned char *out, int maxlen Line 570  int parse_hex(char *in, unsigned char *out, int maxlen
                           sav = in[(j+1)*2];                            sav = in[(j+1)*2];
                           in[(j+1)*2] = 0;                            in[(j+1)*2] = 0;
                         }                          }
                         /* checks above allow mix of hexdigit and *, which
                            is illegal. */
                         if (strchr(&in[j*2], '*'))
                           return -1;
                       out[i] = strtol(&in[j*2], NULL, 16);                        out[i] = strtol(&in[j*2], NULL, 16);
                       mask = mask << 1;                        mask = mask << 1;
                      i++;                      if (++i == maxlen)
                         break; 
                       if (j < bytes - 1)                        if (j < bytes - 1)
                         in[(j+1)*2] = sav;                          in[(j+1)*2] = sav;
                     }                      }
Line 631  int read_write(int fd, unsigned char *packet, int size Line 709  int read_write(int fd, unsigned char *packet, int size
   return 1;    return 1;
 }  }
   
   /* close all fds except STDIN, STDOUT and STDERR, spare1, spare2 and spare3 */
   void close_fds(long max_fd, int spare1, int spare2, int spare3) 
   {
     /* On Linux, use the /proc/ filesystem to find which files
        are actually open, rather than iterate over the whole space,
        for efficiency reasons. If this fails we drop back to the dumb code. */
   #ifdef HAVE_LINUX_NETWORK 
     DIR *d;
     
     if ((d = opendir("/proc/self/fd")))
       {
         struct dirent *de;
   
         while ((de = readdir(d)))
           {
             long fd;
             char *e = NULL;
             
             errno = 0;
             fd = strtol(de->d_name, &e, 10);
                     
             if (errno != 0 || !e || *e || fd == dirfd(d) ||
                 fd == STDOUT_FILENO || fd == STDERR_FILENO || fd == STDIN_FILENO ||
                 fd == spare1 || fd == spare2 || fd == spare3)
               continue;
             
             close(fd);
           }
         
         closedir(d);
         return;
     }
   #endif
   
     /* fallback, dumb code. */
     for (max_fd--; max_fd >= 0; max_fd--)
       if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && max_fd != STDIN_FILENO &&
           max_fd != spare1 && max_fd != spare2 && max_fd != spare3)
         close(max_fd);
   }
   
 /* Basically match a string value against a wildcard pattern.  */  /* Basically match a string value against a wildcard pattern.  */
 int wildcard_match(const char* wildcard, const char* match)  int wildcard_match(const char* wildcard, const char* match)
 {  {
Line 667  int wildcard_matchn(const char* wildcard, const char*  Line 786  int wildcard_matchn(const char* wildcard, const char* 
   
   return (!num) || (*wildcard == *match);    return (!num) || (*wildcard == *match);
 }  }
   
   #ifdef HAVE_LINUX_NETWORK
   int kernel_version(void)
   {
     struct utsname utsname;
     int version;
     char *split;
     
     if (uname(&utsname) < 0)
       die(_("failed to find kernel version: %s"), NULL, EC_MISC);
     
     split = strtok(utsname.release, ".");
     version = (split ? atoi(split) : 0);
     split = strtok(NULL, ".");
     version = version * 256 + (split ? atoi(split) : 0);
     split = strtok(NULL, ".");
     return version * 256 + (split ? atoi(split) : 0);
   }
   #endif

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>