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

1.1       misho       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>