File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / util.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (10 years, 11 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_66p0, v2_66, HEAD
dnsmasq

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

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