Annotation of embedaddon/dnsmasq/src/util.c, revision 1.1.1.2

1.1.1.2 ! misho       1: /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
1.1       misho       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];
1.1.1.2 ! misho      36: static int outleft = 0;
1.1       misho      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: {
1.1.1.2 ! misho      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: {
1.1       misho      86:   static int outleft = 0;
                     87: 
1.1.1.2 ! misho      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;
1.1       misho      96: 
1.1.1.2 ! misho      97:   return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
1.1       misho      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;
1.1.1.2 ! misho     113:       nowhite = 1;
1.1       misho     114:     }
1.1.1.2 ! misho     115: 
1.1       misho     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;
1.1.1.2 ! misho     146:   int first;
1.1       misho     147: 
                    148:   if (!check_name(name))
                    149:     return 0;
                    150: 
1.1.1.2 ! misho     151:   for (first = 1; (c = *name); name++, first = 0)
1.1       misho     152:     /* check for legal char a-z A-Z 0-9 - _ . */
                    153:     {
                    154:       if ((c >= 'A' && c <= 'Z') ||
                    155:          (c >= 'a' && c <= 'z') ||
1.1.1.2 ! misho     156:          (c >= '0' && c <= '9'))
        !           157:        continue;
        !           158: 
        !           159:       if (!first && (c == '-' || c == '_'))
1.1       misho     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:                    { 
1.1.1.2 ! misho     461:                      char sav = sav;
1.1       misho     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>