File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / util.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:31:38 2014 UTC (10 years, 1 month ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_71, HEAD
dnsmasq 2.71

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

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