• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
rand_init(void)32 void rand_init(void)
33 {
34   return;
35 }
36 
rand16(void)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 
rand_init()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 
surf(void)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 
rand16(void)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 
check_name(char * in)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. */
legal_hostname(char * name)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 
canonicalise(char * in,int * nomem)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 
do_rfc1035_name(unsigned char * p,char * sval)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 */
safe_malloc(size_t size)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 
safe_pipe(int * fd,int read_noblock)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 
whine_malloc(size_t size)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 
sockaddr_isequal(union mysockaddr * s1,union mysockaddr * s2)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 
sa_len(union mysockaddr * addr)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 */
hostname_isequal(char * a,char * b)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 
dnsmasq_time(void)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 
is_same_net(struct in_addr a,struct in_addr b,struct in_addr mask)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 */
prettyprint_addr(union mysockaddr * addr,char * buf)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 
prettyprint_time(char * buf,unsigned int t)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). */
parse_hex(char * in,unsigned char * out,int maxlen,unsigned int * wildcard_mask,int * mac_type)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 */
memcmp_masked(unsigned char * a,unsigned char * b,int len,unsigned int mask)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 */
expand_buf(struct iovec * iov,size_t size)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 
print_mac(char * buff,unsigned char * mac,int len)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 
bump_maxfd(int fd,int * max)467 void bump_maxfd(int fd, int *max)
468 {
469   if (fd > *max)
470     *max = fd;
471 }
472 
retry_send(void)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 
read_write(int fd,unsigned char * packet,int size,int rw)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