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