File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / util.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 09:57:01 2016 UTC (7 years, 8 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_76p1, HEAD
dnsmasq 2.76

    1: /* dnsmasq is Copyright (c) 2000-2016 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: /* SURF random number generator */
   32: 
   33: static u32 seed[32];
   34: static u32 in[12];
   35: static u32 out[8];
   36: static int outleft = 0;
   37: 
   38: void rand_init()
   39: {
   40:   int fd = open(RANDFILE, O_RDONLY);
   41:   
   42:   if (fd == -1 ||
   43:       !read_write(fd, (unsigned char *)&seed, sizeof(seed), 1) ||
   44:       !read_write(fd, (unsigned char *)&in, sizeof(in), 1))
   45:     die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
   46:   
   47:   close(fd);
   48: }
   49: 
   50: #define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
   51: #define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
   52: 
   53: static void surf(void)
   54: {
   55:   u32 t[12]; u32 x; u32 sum = 0;
   56:   int r; int i; int loop;
   57: 
   58:   for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
   59:   for (i = 0;i < 8;++i) out[i] = seed[24 + i];
   60:   x = t[11];
   61:   for (loop = 0;loop < 2;++loop) {
   62:     for (r = 0;r < 16;++r) {
   63:       sum += 0x9e3779b9;
   64:       MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
   65:       MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
   66:       MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
   67:     }
   68:     for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
   69:   }
   70: }
   71: 
   72: unsigned short rand16(void)
   73: {
   74:   if (!outleft) 
   75:     {
   76:       if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
   77:       surf();
   78:       outleft = 8;
   79:     }
   80:   
   81:   return (unsigned short) out[--outleft];
   82: }
   83: 
   84: u32 rand32(void)
   85: {
   86:  if (!outleft) 
   87:     {
   88:       if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
   89:       surf();
   90:       outleft = 8;
   91:     }
   92:   
   93:   return out[--outleft]; 
   94: }
   95: 
   96: u64 rand64(void)
   97: {
   98:   static int outleft = 0;
   99: 
  100:   if (outleft < 2)
  101:     {
  102:       if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
  103:       surf();
  104:       outleft = 8;
  105:     }
  106:   
  107:   outleft -= 2;
  108: 
  109:   return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
  110: }
  111: 
  112: static int check_name(char *in)
  113: {
  114:   /* remove trailing . 
  115:      also fail empty string and label > 63 chars */
  116:   size_t dotgap = 0, l = strlen(in);
  117:   char c;
  118:   int nowhite = 0;
  119:   
  120:   if (l == 0 || l > MAXDNAME) return 0;
  121:   
  122:   if (in[l-1] == '.')
  123:     {
  124:       in[l-1] = 0;
  125:       nowhite = 1;
  126:     }
  127: 
  128:   for (; (c = *in); in++)
  129:     {
  130:       if (c == '.')
  131: 	dotgap = 0;
  132:       else if (++dotgap > MAXLABEL)
  133: 	return 0;
  134:       else if (isascii((unsigned char)c) && iscntrl((unsigned char)c)) 
  135: 	/* iscntrl only gives expected results for ascii */
  136: 	return 0;
  137: #if !defined(LOCALEDIR) && !defined(HAVE_IDN)
  138:       else if (!isascii((unsigned char)c))
  139: 	return 0;
  140: #endif
  141:       else if (c != ' ')
  142: 	nowhite = 1;
  143:     }
  144: 
  145:   if (!nowhite)
  146:     return 0;
  147: 
  148:   return 1;
  149: }
  150: 
  151: /* Hostnames have a more limited valid charset than domain names
  152:    so check for legal char a-z A-Z 0-9 - _ 
  153:    Note that this may receive a FQDN, so only check the first label 
  154:    for the tighter criteria. */
  155: int legal_hostname(char *name)
  156: {
  157:   char c;
  158:   int first;
  159: 
  160:   if (!check_name(name))
  161:     return 0;
  162: 
  163:   for (first = 1; (c = *name); name++, first = 0)
  164:     /* check for legal char a-z A-Z 0-9 - _ . */
  165:     {
  166:       if ((c >= 'A' && c <= 'Z') ||
  167: 	  (c >= 'a' && c <= 'z') ||
  168: 	  (c >= '0' && c <= '9'))
  169: 	continue;
  170: 
  171:       if (!first && (c == '-' || c == '_'))
  172: 	continue;
  173:       
  174:       /* end of hostname part */
  175:       if (c == '.')
  176: 	return 1;
  177:       
  178:       return 0;
  179:     }
  180:   
  181:   return 1;
  182: }
  183:   
  184: char *canonicalise(char *in, int *nomem)
  185: {
  186:   char *ret = NULL;
  187: #if defined(LOCALEDIR) || defined(HAVE_IDN)
  188:   int rc;
  189: #endif
  190: 
  191:   if (nomem)
  192:     *nomem = 0;
  193:   
  194:   if (!check_name(in))
  195:     return NULL;
  196:   
  197: #if defined(LOCALEDIR) || defined(HAVE_IDN)
  198:   if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
  199:     {
  200:       if (ret)
  201: 	free(ret);
  202: 
  203:       if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
  204: 	{
  205: 	  my_syslog(LOG_ERR, _("failed to allocate memory"));
  206: 	  *nomem = 1;
  207: 	}
  208:     
  209:       return NULL;
  210:     }
  211: #else
  212:   if ((ret = whine_malloc(strlen(in)+1)))
  213:     strcpy(ret, in);
  214:   else if (nomem)
  215:     *nomem = 1;    
  216: #endif
  217: 
  218:   return ret;
  219: }
  220: 
  221: unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
  222: {
  223:   int j;
  224:   
  225:   while (sval && *sval)
  226:     {
  227:       unsigned char *cp = p++;
  228:       for (j = 0; *sval && (*sval != '.'); sval++, j++)
  229: 	{
  230: #ifdef HAVE_DNSSEC
  231: 	  if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
  232: 	    *p++ = (*(++sval))-1;
  233: 	  else
  234: #endif		
  235: 	    *p++ = *sval;
  236: 	}
  237:       *cp  = j;
  238:       if (*sval)
  239: 	sval++;
  240:     }
  241:   return p;
  242: }
  243: 
  244: /* for use during startup */
  245: void *safe_malloc(size_t size)
  246: {
  247:   void *ret = malloc(size);
  248:   
  249:   if (!ret)
  250:     die(_("could not get memory"), NULL, EC_NOMEM);
  251:      
  252:   return ret;
  253: }    
  254: 
  255: void safe_pipe(int *fd, int read_noblock)
  256: {
  257:   if (pipe(fd) == -1 || 
  258:       !fix_fd(fd[1]) ||
  259:       (read_noblock && !fix_fd(fd[0])))
  260:     die(_("cannot create pipe: %s"), NULL, EC_MISC);
  261: }
  262: 
  263: void *whine_malloc(size_t size)
  264: {
  265:   void *ret = malloc(size);
  266: 
  267:   if (!ret)
  268:     my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
  269: 
  270:   return ret;
  271: }
  272: 
  273: int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
  274: {
  275:   if (s1->sa.sa_family == s2->sa.sa_family)
  276:     { 
  277:       if (s1->sa.sa_family == AF_INET &&
  278: 	  s1->in.sin_port == s2->in.sin_port &&
  279: 	  s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
  280: 	return 1;
  281: #ifdef HAVE_IPV6      
  282:       if (s1->sa.sa_family == AF_INET6 &&
  283: 	  s1->in6.sin6_port == s2->in6.sin6_port &&
  284: 	  s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
  285: 	  IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
  286: 	return 1;
  287: #endif
  288:     }
  289:   return 0;
  290: }
  291: 
  292: int sa_len(union mysockaddr *addr)
  293: {
  294: #ifdef HAVE_SOCKADDR_SA_LEN
  295:   return addr->sa.sa_len;
  296: #else
  297: #ifdef HAVE_IPV6
  298:   if (addr->sa.sa_family == AF_INET6)
  299:     return sizeof(addr->in6);
  300:   else
  301: #endif
  302:     return sizeof(addr->in); 
  303: #endif
  304: }
  305: 
  306: /* don't use strcasecmp and friends here - they may be messed up by LOCALE */
  307: int hostname_isequal(const char *a, const char *b)
  308: {
  309:   unsigned int c1, c2;
  310:   
  311:   do {
  312:     c1 = (unsigned char) *a++;
  313:     c2 = (unsigned char) *b++;
  314:     
  315:     if (c1 >= 'A' && c1 <= 'Z')
  316:       c1 += 'a' - 'A';
  317:     if (c2 >= 'A' && c2 <= 'Z')
  318:       c2 += 'a' - 'A';
  319:     
  320:     if (c1 != c2)
  321:       return 0;
  322:   } while (c1);
  323:   
  324:   return 1;
  325: }
  326:     
  327: time_t dnsmasq_time(void)
  328: {
  329: #ifdef HAVE_BROKEN_RTC
  330:   struct tms dummy;
  331:   static long tps = 0;
  332: 
  333:   if (tps == 0)
  334:     tps = sysconf(_SC_CLK_TCK);
  335: 
  336:   return (time_t)(times(&dummy)/tps);
  337: #else
  338:   return time(NULL);
  339: #endif
  340: }
  341: 
  342: int netmask_length(struct in_addr mask)
  343: {
  344:   int zero_count = 0;
  345: 
  346:   while (0x0 == (mask.s_addr & 0x1) && zero_count < 32) 
  347:     {
  348:       mask.s_addr >>= 1;
  349:       zero_count++;
  350:     }
  351:   
  352:   return 32 - zero_count;
  353: }
  354: 
  355: int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
  356: {
  357:   return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
  358: } 
  359: 
  360: #ifdef HAVE_IPV6
  361: int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
  362: {
  363:   int pfbytes = prefixlen >> 3;
  364:   int pfbits = prefixlen & 7;
  365: 
  366:   if (memcmp(&a->s6_addr, &b->s6_addr, pfbytes) != 0)
  367:     return 0;
  368: 
  369:   if (pfbits == 0 ||
  370:       (a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
  371:     return 1;
  372: 
  373:   return 0;
  374: }
  375: 
  376: /* return least signigicant 64 bits if IPv6 address */
  377: u64 addr6part(struct in6_addr *addr)
  378: {
  379:   int i;
  380:   u64 ret = 0;
  381: 
  382:   for (i = 8; i < 16; i++)
  383:     ret = (ret << 8) + addr->s6_addr[i];
  384: 
  385:   return ret;
  386: }
  387: 
  388: void setaddr6part(struct in6_addr *addr, u64 host)
  389: {
  390:   int i;
  391: 
  392:   for (i = 15; i >= 8; i--)
  393:     {
  394:       addr->s6_addr[i] = host;
  395:       host = host >> 8;
  396:     }
  397: }
  398: 
  399: #endif
  400:  
  401: 
  402: /* returns port number from address */
  403: int prettyprint_addr(union mysockaddr *addr, char *buf)
  404: {
  405:   int port = 0;
  406:   
  407: #ifdef HAVE_IPV6
  408:   if (addr->sa.sa_family == AF_INET)
  409:     {
  410:       inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
  411:       port = ntohs(addr->in.sin_port);
  412:     }
  413:   else if (addr->sa.sa_family == AF_INET6)
  414:     {
  415:       char name[IF_NAMESIZE];
  416:       inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
  417:       if (addr->in6.sin6_scope_id != 0 &&
  418: 	  if_indextoname(addr->in6.sin6_scope_id, name) &&
  419: 	  strlen(buf) + strlen(name) + 2 <= ADDRSTRLEN)
  420: 	{
  421: 	  strcat(buf, "%");
  422: 	  strcat(buf, name);
  423: 	}
  424:       port = ntohs(addr->in6.sin6_port);
  425:     }
  426: #else
  427:   strcpy(buf, inet_ntoa(addr->in.sin_addr));
  428:   port = ntohs(addr->in.sin_port); 
  429: #endif
  430:   
  431:   return port;
  432: }
  433: 
  434: void prettyprint_time(char *buf, unsigned int t)
  435: {
  436:   if (t == 0xffffffff)
  437:     sprintf(buf, _("infinite"));
  438:   else
  439:     {
  440:       unsigned int x, p = 0;
  441:        if ((x = t/86400))
  442: 	p += sprintf(&buf[p], "%dd", x);
  443:        if ((x = (t/3600)%24))
  444: 	p += sprintf(&buf[p], "%dh", x);
  445:       if ((x = (t/60)%60))
  446: 	p += sprintf(&buf[p], "%dm", x);
  447:       if ((x = t%60))
  448: 	p += sprintf(&buf[p], "%ds", x);
  449:     }
  450: }
  451: 
  452: 
  453: /* in may equal out, when maxlen may be -1 (No max len). 
  454:    Return -1 for extraneous no-hex chars found. */
  455: int parse_hex(char *in, unsigned char *out, int maxlen, 
  456: 	      unsigned int *wildcard_mask, int *mac_type)
  457: {
  458:   int mask = 0, i = 0;
  459:   char *r;
  460:     
  461:   if (mac_type)
  462:     *mac_type = 0;
  463:   
  464:   while (maxlen == -1 || i < maxlen)
  465:     {
  466:       for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
  467: 	if (*r != '*' && !isxdigit((unsigned char)*r))
  468: 	  return -1;
  469:       
  470:       if (*r == 0)
  471: 	maxlen = i;
  472:       
  473:       if (r != in )
  474: 	{
  475: 	  if (*r == '-' && i == 0 && mac_type)
  476: 	   {
  477: 	      *r = 0;
  478: 	      *mac_type = strtol(in, NULL, 16);
  479: 	      mac_type = NULL;
  480: 	   }
  481: 	  else
  482: 	    {
  483: 	      *r = 0;
  484: 	      if (strcmp(in, "*") == 0)
  485: 		{
  486: 		  mask = (mask << 1) | 1;
  487: 		  i++;
  488: 		}
  489: 	      else
  490: 		{
  491: 		  int j, bytes = (1 + (r - in))/2;
  492: 		  for (j = 0; j < bytes; j++)
  493: 		    { 
  494: 		      char sav = sav;
  495: 		      if (j < bytes - 1)
  496: 			{
  497: 			  sav = in[(j+1)*2];
  498: 			  in[(j+1)*2] = 0;
  499: 			}
  500: 		      out[i] = strtol(&in[j*2], NULL, 16);
  501: 		      mask = mask << 1;
  502: 		      i++;
  503: 		      if (j < bytes - 1)
  504: 			in[(j+1)*2] = sav;
  505: 		    }
  506: 		}
  507: 	    }
  508: 	}
  509:       in = r+1;
  510:     }
  511:   
  512:   if (wildcard_mask)
  513:     *wildcard_mask = mask;
  514: 
  515:   return i;
  516: }
  517: 
  518: /* return 0 for no match, or (no matched octets) + 1 */
  519: int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
  520: {
  521:   int i, count;
  522:   for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
  523:     if (!(mask & 1))
  524:       {
  525: 	if (a[i] == b[i])
  526: 	  count++;
  527: 	else
  528: 	  return 0;
  529:       }
  530:   return count;
  531: }
  532: 
  533: /* _note_ may copy buffer */
  534: int expand_buf(struct iovec *iov, size_t size)
  535: {
  536:   void *new;
  537: 
  538:   if (size <= (size_t)iov->iov_len)
  539:     return 1;
  540: 
  541:   if (!(new = whine_malloc(size)))
  542:     {
  543:       errno = ENOMEM;
  544:       return 0;
  545:     }
  546: 
  547:   if (iov->iov_base)
  548:     {
  549:       memcpy(new, iov->iov_base, iov->iov_len);
  550:       free(iov->iov_base);
  551:     }
  552: 
  553:   iov->iov_base = new;
  554:   iov->iov_len = size;
  555: 
  556:   return 1;
  557: }
  558: 
  559: char *print_mac(char *buff, unsigned char *mac, int len)
  560: {
  561:   char *p = buff;
  562:   int i;
  563:    
  564:   if (len == 0)
  565:     sprintf(p, "<null>");
  566:   else
  567:     for (i = 0; i < len; i++)
  568:       p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
  569:   
  570:   return buff;
  571: }
  572: 
  573: /* rc is return from sendto and friends.
  574:    Return 1 if we should retry.
  575:    Set errno to zero if we succeeded. */
  576: int retry_send(ssize_t rc)
  577: {
  578:   static int retries = 0;
  579:   struct timespec waiter;
  580:   
  581:   if (rc != -1)
  582:     {
  583:       retries = 0;
  584:       errno = 0;
  585:       return 0;
  586:     }
  587:   
  588:   /* Linux kernels can return EAGAIN in perpetuity when calling
  589:      sendmsg() and the relevant interface has gone. Here we loop
  590:      retrying in EAGAIN for 1 second max, to avoid this hanging 
  591:      dnsmasq. */
  592: 
  593:   if (errno == EAGAIN || errno == EWOULDBLOCK)
  594:      {
  595:        waiter.tv_sec = 0;
  596:        waiter.tv_nsec = 10000;
  597:        nanosleep(&waiter, NULL);
  598:        if (retries++ < 1000)
  599: 	 return 1;
  600:      }
  601:   
  602:   retries = 0;
  603:   
  604:   if (errno == EINTR)
  605:     return 1;
  606:   
  607:   return 0;
  608: }
  609: 
  610: int read_write(int fd, unsigned char *packet, int size, int rw)
  611: {
  612:   ssize_t n, done;
  613:   
  614:   for (done = 0; done < size; done += n)
  615:     {
  616:       do { 
  617: 	if (rw)
  618: 	  n = read(fd, &packet[done], (size_t)(size - done));
  619: 	else
  620: 	  n = write(fd, &packet[done], (size_t)(size - done));
  621: 	
  622: 	if (n == 0)
  623: 	  return 0;
  624: 	
  625:       } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
  626: 
  627:       if (errno != 0)
  628: 	return 0;
  629:     }
  630:      
  631:   return 1;
  632: }
  633: 
  634: /* Basically match a string value against a wildcard pattern.  */
  635: int wildcard_match(const char* wildcard, const char* match)
  636: {
  637:   while (*wildcard && *match)
  638:     {
  639:       if (*wildcard == '*')
  640:         return 1;
  641: 
  642:       if (*wildcard != *match)
  643:         return 0; 
  644: 
  645:       ++wildcard;
  646:       ++match;
  647:     }
  648: 
  649:   return *wildcard == *match;
  650: }
  651: 
  652: /* The same but comparing a maximum of NUM characters, like strncmp.  */
  653: int wildcard_matchn(const char* wildcard, const char* match, int num)
  654: {
  655:   while (*wildcard && *match && num)
  656:     {
  657:       if (*wildcard == '*')
  658:         return 1;
  659: 
  660:       if (*wildcard != *match)
  661:         return 0; 
  662: 
  663:       ++wildcard;
  664:       ++match;
  665:       --num;
  666:     }
  667: 
  668:   return (!num) || (*wildcard == *match);
  669: }

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