• 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 #include "dnsmasq.h"
21 
22 #include <netdb.h>
23 
24 #ifdef HAVE_BROKEN_RTC
25 #include <sys/times.h>
26 #endif
27 
28 #ifdef LOCALEDIR
29 #include <idna.h>
30 #endif
31 
32 #ifdef HAVE_ARC4RANDOM
rand_init(void)33 void rand_init(void) {
34     return;
35 }
36 
rand16(void)37 unsigned short rand16(void) {
38     return (unsigned short) (arc4random() >> 15);
39 }
40 
41 #else
42 
43 /* SURF random number generator */
44 
45 typedef unsigned int uint32;
46 
47 static uint32 seed[32];
48 static uint32 in[12];
49 static uint32 out[8];
50 
rand_init()51 void rand_init() {
52     int fd = open(RANDFILE, O_RDONLY);
53 
54     if (fd == -1 || !read_write(fd, (unsigned char*) &seed, sizeof(seed), 1) ||
55         !read_write(fd, (unsigned char*) &in, sizeof(in), 1))
56         die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
57 
58     close(fd);
59 }
60 
61 #define ROTATE(x, b) (((x) << (b)) | ((x) >> (32 - (b))))
62 #define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x, b));
63 
surf(void)64 static void surf(void) {
65     uint32 t[12];
66     uint32 x;
67     uint32 sum = 0;
68     int r;
69     int i;
70     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)
79             MUSH(1, 7) MUSH(2, 9) MUSH(3, 13) 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     static int outleft = 0;
88 
89     if (!outleft) {
90         if (!++in[0])
91             if (!++in[1])
92                 if (!++in[2]) ++in[3];
93         surf();
94         outleft = 8;
95     }
96 
97     return (unsigned short) out[--outleft];
98 }
99 
100 #endif
101 
check_name(char * in)102 static int check_name(char* in) {
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         if (l == 1) return 0;
113         in[l - 1] = 0;
114     }
115 
116     for (; (c = *in); in++) {
117         if (c == '.')
118             dotgap = 0;
119         else if (++dotgap > MAXLABEL)
120             return 0;
121         else if (isascii(c) && iscntrl(c))
122             /* iscntrl only gives expected results for ascii */
123             return 0;
124 #ifndef LOCALEDIR
125         else if (!isascii(c))
126             return 0;
127 #endif
128         else if (c != ' ')
129             nowhite = 1;
130     }
131 
132     if (!nowhite) return 0;
133 
134     return 1;
135 }
136 
137 /* Hostnames have a more limited valid charset than domain names
138    so check for legal char a-z A-Z 0-9 - _
139    Note that this may receive a FQDN, so only check the first label
140    for the tighter criteria. */
legal_hostname(char * name)141 int legal_hostname(char* name) {
142     char c;
143 
144     if (!check_name(name)) return 0;
145 
146     for (; (c = *name); name++)
147     /* check for legal char a-z A-Z 0-9 - _ . */
148     {
149         if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
150             c == '-' || c == '_')
151             continue;
152 
153         /* end of hostname part */
154         if (c == '.') return 1;
155 
156         return 0;
157     }
158 
159     return 1;
160 }
161 
canonicalise(char * in,int * nomem)162 char* canonicalise(char* in, int* nomem) {
163     char* ret = NULL;
164 #ifdef LOCALEDIR
165     int rc;
166 #endif
167 
168     if (nomem) *nomem = 0;
169 
170     if (!check_name(in)) return NULL;
171 
172 #ifdef LOCALEDIR
173     if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS) {
174         if (ret) free(ret);
175 
176         if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR)) {
177             my_syslog(LOG_ERR, _("failed to allocate memory"));
178             *nomem = 1;
179         }
180 
181         return NULL;
182     }
183 #else
184     if ((ret = whine_malloc(strlen(in) + 1)))
185         strcpy(ret, in);
186     else if (nomem)
187         *nomem = 1;
188 #endif
189 
190     return ret;
191 }
192 
do_rfc1035_name(unsigned char * p,char * sval,char * limit)193 unsigned char* do_rfc1035_name(unsigned char* p, char* sval, char *limit) {
194     int j;
195 
196     while (sval && *sval) {
197         if (limit && p + 1 > (unsigned char*)limit)
198             return p;
199 
200         unsigned char* cp = p++;
201         for (j = 0; *sval && (*sval != '.'); sval++, j++) {
202             if (limit && p + 1 > (unsigned char*)limit)
203                 return p;
204             *p++ = *sval;
205         }
206         *cp = j;
207         if (*sval) sval++;
208     }
209     return p;
210 }
211 
212 /* for use during startup */
safe_malloc(size_t size)213 void* safe_malloc(size_t size) {
214     void* ret = malloc(size);
215 
216     if (!ret) die(_("could not get memory"), NULL, EC_NOMEM);
217 
218     return ret;
219 }
220 
safe_pipe(int * fd,int read_noblock)221 void safe_pipe(int* fd, int read_noblock) {
222     if (pipe(fd) == -1 || !fix_fd(fd[1]) || (read_noblock && !fix_fd(fd[0])))
223         die(_("cannot create pipe: %s"), NULL, EC_MISC);
224 }
225 
whine_malloc(size_t size)226 void* whine_malloc(size_t size) {
227     void* ret = malloc(size);
228 
229     if (!ret) my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
230 
231     return ret;
232 }
233 
sockaddr_isequal(union mysockaddr * s1,union mysockaddr * s2)234 int sockaddr_isequal(union mysockaddr* s1, union mysockaddr* s2) {
235     if (s1->sa.sa_family == s2->sa.sa_family) {
236         if (s1->sa.sa_family == AF_INET && s1->in.sin_port == s2->in.sin_port &&
237             s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
238             return 1;
239 #ifdef HAVE_IPV6
240         if (s1->sa.sa_family == AF_INET6 && s1->in6.sin6_port == s2->in6.sin6_port &&
241             IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr) &&
242             (!IN6_IS_ADDR_LINKLOCAL(&s1->in6.sin6_addr) ||
243              (s1->in6.sin6_scope_id == s2->in6.sin6_scope_id)))
244             return 1;
245 #endif
246     }
247     return 0;
248 }
249 
sa_len(union mysockaddr * addr)250 int sa_len(union mysockaddr* addr) {
251     if (addr->sa.sa_family == AF_INET6)
252         return sizeof(addr->in6);
253     else
254         return sizeof(addr->in);
255 }
256 
257 /* don't use strcasecmp and friends here - they may be messed up by LOCALE */
hostname_isequal(char * a,char * b)258 int hostname_isequal(char* a, char* b) {
259     unsigned int c1, c2;
260 
261     do {
262         c1 = (unsigned char) *a++;
263         c2 = (unsigned char) *b++;
264 
265         if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
266         if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
267 
268         if (c1 != c2) return 0;
269     } while (c1);
270 
271     return 1;
272 }
273 
dnsmasq_time(void)274 time_t dnsmasq_time(void) {
275 #ifdef HAVE_BROKEN_RTC
276     struct tms unused;
277     static long tps = 0;
278 
279     if (tps == 0) tps = sysconf(_SC_CLK_TCK);
280 
281     return (time_t)(times(&unused) / tps);
282 #else
283     return time(NULL);
284 #endif
285 }
286 
is_same_net(struct in_addr a,struct in_addr b,struct in_addr mask)287 int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) {
288     return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
289 }
290 
parse_addr(int family,const char * addrstr,union mysockaddr * addr)291 int parse_addr(int family, const char* addrstr, union mysockaddr* addr) {
292     struct addrinfo *res, hints = {
293                               .ai_flags = AI_NUMERICHOST,
294                               .ai_family = family,
295                               .ai_socktype = SOCK_DGRAM,
296                           };
297 
298     int ret = getaddrinfo(addrstr, NULL, &hints, &res);
299     if (ret) {
300         return ret;
301     }
302 
303     switch (res->ai_family) {
304         case AF_INET:
305             addr->in = *((struct sockaddr_in*) res->ai_addr);
306             break;
307 #ifdef HAVE_IPV6
308         case AF_INET6:
309             addr->in6 = *((struct sockaddr_in6*) res->ai_addr);
310             break;
311 #endif
312         default:
313             errno = EAFNOSUPPORT;
314             ret = -1;
315             break;
316     }
317     freeaddrinfo(res);
318     return ret;
319 }
320 
321 /* returns port number from address */
prettyprint_addr(const union mysockaddr * addr,char * buf)322 int prettyprint_addr(const union mysockaddr* addr, char* buf) {
323     int port = 0;
324 
325 #ifdef HAVE_IPV6
326     char portstr[strlen("65535")];
327     getnameinfo((const struct sockaddr*) addr, sizeof(*addr), buf, ADDRSTRLEN, portstr,
328                 sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
329     port = atoi(portstr);
330 #else
331     strcpy(buf, inet_ntoa(addr->in.sin_addr));
332     port = ntohs(addr->in.sin_port);
333 #endif
334 
335     return port;
336 }
337 
prettyprint_time(char * buf,unsigned int t)338 void prettyprint_time(char* buf, unsigned int t) {
339     if (t == 0xffffffff)
340         sprintf(buf, _("infinite"));
341     else {
342         unsigned int x, p = 0;
343         if ((x = t / 86400)) p += sprintf(&buf[p], "%dd", x);
344         if ((x = (t / 3600) % 24)) p += sprintf(&buf[p], "%dh", x);
345         if ((x = (t / 60) % 60)) p += sprintf(&buf[p], "%dm", x);
346         if ((x = t % 60)) p += sprintf(&buf[p], "%ds", x);
347     }
348 }
349 
350 /* 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)351 int parse_hex(char* in, unsigned char* out, int maxlen, unsigned int* wildcard_mask, int* mac_type) {
352     int mask = 0, i = 0;
353     char* r;
354 
355     if (mac_type) *mac_type = 0;
356 
357     while (maxlen == -1 || i < maxlen) {
358         for (r = in; *r != 0 && *r != ':' && *r != '-'; r++)
359             ;
360         if (*r == 0) maxlen = i;
361 
362         if (r != in) {
363             if (*r == '-' && i == 0 && mac_type) {
364                 *r = 0;
365                 *mac_type = strtol(in, NULL, 16);
366                 mac_type = NULL;
367             } else {
368                 *r = 0;
369                 mask = mask << 1;
370                 if (strcmp(in, "*") == 0)
371                     mask |= 1;
372                 else
373                     out[i] = strtol(in, NULL, 16);
374                 i++;
375             }
376         }
377         in = r + 1;
378     }
379 
380     if (wildcard_mask) *wildcard_mask = mask;
381 
382     return i;
383 }
384 
385 /* return 0 for no match, or (no matched octets) + 1 */
memcmp_masked(unsigned char * a,unsigned char * b,int len,unsigned int mask)386 int memcmp_masked(unsigned char* a, unsigned char* b, int len, unsigned int mask) {
387     int i, count;
388     for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
389         if (!(mask & 1)) {
390             if (a[i] == b[i])
391                 count++;
392             else
393                 return 0;
394         }
395     return count;
396 }
397 
398 /* _note_ may copy buffer */
expand_buf(struct iovec * iov,size_t size)399 int expand_buf(struct iovec* iov, size_t size) {
400     void* new;
401 
402     if (size <= (size_t) iov->iov_len) return 1;
403 
404     if (!(new = whine_malloc(size))) {
405         errno = ENOMEM;
406         return 0;
407     }
408 
409     if (iov->iov_base) {
410         memcpy(new, iov->iov_base, iov->iov_len);
411         free(iov->iov_base);
412     }
413 
414     iov->iov_base = new;
415     iov->iov_len = size;
416 
417     return 1;
418 }
419 
print_mac(char * buff,unsigned char * mac,int len)420 char* print_mac(char* buff, unsigned char* mac, int len) {
421     char* p = buff;
422     int i;
423 
424     if (len == 0)
425         sprintf(p, "<null>");
426     else
427         for (i = 0; i < len; i++) p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
428 
429     return buff;
430 }
431 
bump_maxfd(int fd,int * max)432 void bump_maxfd(int fd, int* max) {
433     if (fd > *max) *max = fd;
434 }
435 
retry_send(void)436 int retry_send(void) {
437     struct timespec waiter;
438     if (errno == EAGAIN) {
439         waiter.tv_sec = 0;
440         waiter.tv_nsec = 10000;
441         nanosleep(&waiter, NULL);
442         return 1;
443     }
444 
445     if (errno == EINTR) return 1;
446 
447     return 0;
448 }
449 
read_write(int fd,unsigned char * packet,int size,int rw)450 int read_write(int fd, unsigned char* packet, int size, int rw) {
451     ssize_t n, done;
452 
453     for (done = 0; done < size; done += n) {
454     retry:
455         if (rw)
456             n = read(fd, &packet[done], (size_t)(size - done));
457         else
458             n = write(fd, &packet[done], (size_t)(size - done));
459 
460         if (n == 0)
461             return 0;
462         else if (n == -1) {
463             if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
464                 goto retry;
465             else
466                 return 0;
467         }
468     }
469     return 1;
470 }
471