Annotation of embedaddon/dnsmasq/src/util.c, revision 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>