]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/util.c
1 /* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
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.
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.
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/>.
17 /* The SURF random number generator was taken from djbdns-1.05, by
18 Daniel J Bernstein, which is public domain. */
23 #ifdef HAVE_BROKEN_RTC
24 #include <sys/times.h>
27 #if defined(LOCALEDIR) || defined(HAVE_IDN)
31 /* SURF random number generator */
36 static int outleft
= 0;
40 int fd
= open(RANDFILE
, O_RDONLY
);
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
);
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));
53 static void surf(void)
55 u32 t
[12]; u32 x
; u32 sum
= 0;
56 int r
; int i
; int loop
;
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
];
61 for (loop
= 0;loop
< 2;++loop
) {
62 for (r
= 0;r
< 16;++r
) {
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)
68 for (i
= 0;i
< 8;++i
) out
[i
] ^= t
[i
+ 4];
72 unsigned short rand16(void)
76 if (!++in
[0]) if (!++in
[1]) if (!++in
[2]) ++in
[3];
81 return (unsigned short) out
[--outleft
];
88 if (!++in
[0]) if (!++in
[1]) if (!++in
[2]) ++in
[3];
93 return out
[--outleft
];
98 static int outleft
= 0;
102 if (!++in
[0]) if (!++in
[1]) if (!++in
[2]) ++in
[3];
109 return (u64
)out
[outleft
+1] + (((u64
)out
[outleft
]) << 32);
112 static int check_name(char *in
)
115 also fail empty string and label > 63 chars */
116 size_t dotgap
= 0, l
= strlen(in
);
120 if (l
== 0 || l
> MAXDNAME
) return 0;
128 for (; (c
= *in
); in
++)
132 else if (++dotgap
> MAXLABEL
)
134 else if (isascii((unsigned char)c
) && iscntrl((unsigned char)c
))
135 /* iscntrl only gives expected results for ascii */
137 #if !defined(LOCALEDIR) && !defined(HAVE_IDN)
138 else if (!isascii((unsigned char)c
))
151 /* Hostnames have a more limited valid charset than domain names
152 so check for legal char a-z A-Z 0-9 - _
153 Note that this may receive a FQDN, so only check the first label
154 for the tighter criteria. */
155 int legal_hostname(char *name
)
160 if (!check_name(name
))
163 for (first
= 1; (c
= *name
); name
++, first
= 0)
164 /* check for legal char a-z A-Z 0-9 - _ . */
166 if ((c
>= 'A' && c
<= 'Z') ||
167 (c
>= 'a' && c
<= 'z') ||
168 (c
>= '0' && c
<= '9'))
171 if (!first
&& (c
== '-' || c
== '_'))
174 /* end of hostname part */
184 char *canonicalise(char *in
, int *nomem
)
187 #if defined(LOCALEDIR) || defined(HAVE_IDN)
197 #if defined(LOCALEDIR) || defined(HAVE_IDN)
198 if ((rc
= idna_to_ascii_lz(in
, &ret
, 0)) != IDNA_SUCCESS
)
203 if (nomem
&& (rc
== IDNA_MALLOC_ERROR
|| rc
== IDNA_DLOPEN_ERROR
))
205 my_syslog(LOG_ERR
, _("failed to allocate memory"));
212 if ((ret
= whine_malloc(strlen(in
)+1)))
221 unsigned char *do_rfc1035_name(unsigned char *p
, char *sval
)
225 while (sval
&& *sval
)
227 unsigned char *cp
= p
++;
228 for (j
= 0; *sval
&& (*sval
!= '.'); sval
++, j
++)
237 /* for use during startup */
238 void *safe_malloc(size_t size
)
240 void *ret
= malloc(size
);
243 die(_("could not get memory"), NULL
, EC_NOMEM
);
248 void safe_pipe(int *fd
, int read_noblock
)
250 if (pipe(fd
) == -1 ||
252 (read_noblock
&& !fix_fd(fd
[0])))
253 die(_("cannot create pipe: %s"), NULL
, EC_MISC
);
256 void *whine_malloc(size_t size
)
258 void *ret
= malloc(size
);
261 my_syslog(LOG_ERR
, _("failed to allocate %d bytes"), (int) size
);
266 int sockaddr_isequal(union mysockaddr
*s1
, union mysockaddr
*s2
)
268 if (s1
->sa
.sa_family
== s2
->sa
.sa_family
)
270 if (s1
->sa
.sa_family
== AF_INET
&&
271 s1
->in
.sin_port
== s2
->in
.sin_port
&&
272 s1
->in
.sin_addr
.s_addr
== s2
->in
.sin_addr
.s_addr
)
275 if (s1
->sa
.sa_family
== AF_INET6
&&
276 s1
->in6
.sin6_port
== s2
->in6
.sin6_port
&&
277 s1
->in6
.sin6_scope_id
== s2
->in6
.sin6_scope_id
&&
278 IN6_ARE_ADDR_EQUAL(&s1
->in6
.sin6_addr
, &s2
->in6
.sin6_addr
))
285 int sa_len(union mysockaddr
*addr
)
287 #ifdef HAVE_SOCKADDR_SA_LEN
288 return addr
->sa
.sa_len
;
291 if (addr
->sa
.sa_family
== AF_INET6
)
292 return sizeof(addr
->in6
);
295 return sizeof(addr
->in
);
299 /* don't use strcasecmp and friends here - they may be messed up by LOCALE */
300 int hostname_isequal(const char *a
, const char *b
)
305 c1
= (unsigned char) *a
++;
306 c2
= (unsigned char) *b
++;
308 if (c1
>= 'A' && c1
<= 'Z')
310 if (c2
>= 'A' && c2
<= 'Z')
320 time_t dnsmasq_time(void)
322 #ifdef HAVE_BROKEN_RTC
327 tps
= sysconf(_SC_CLK_TCK
);
329 return (time_t)(times(&dummy
)/tps
);
335 int netmask_length(struct in_addr mask
)
339 while (0x0 == (mask
.s_addr
& 0x1) && zero_count
< 32)
345 return 32 - zero_count
;
348 int is_same_net(struct in_addr a
, struct in_addr b
, struct in_addr mask
)
350 return (a
.s_addr
& mask
.s_addr
) == (b
.s_addr
& mask
.s_addr
);
354 int is_same_net6(struct in6_addr
*a
, struct in6_addr
*b
, int prefixlen
)
356 int pfbytes
= prefixlen
>> 3;
357 int pfbits
= prefixlen
& 7;
359 if (memcmp(&a
->s6_addr
, &b
->s6_addr
, pfbytes
) != 0)
363 (a
->s6_addr
[pfbytes
] >> (8 - pfbits
) == b
->s6_addr
[pfbytes
] >> (8 - pfbits
)))
369 /* return least signigicant 64 bits if IPv6 address */
370 u64
addr6part(struct in6_addr
*addr
)
375 for (i
= 8; i
< 16; i
++)
376 ret
= (ret
<< 8) + addr
->s6_addr
[i
];
381 void setaddr6part(struct in6_addr
*addr
, u64 host
)
385 for (i
= 15; i
>= 8; i
--)
387 addr
->s6_addr
[i
] = host
;
395 /* returns port number from address */
396 int prettyprint_addr(union mysockaddr
*addr
, char *buf
)
401 if (addr
->sa
.sa_family
== AF_INET
)
403 inet_ntop(AF_INET
, &addr
->in
.sin_addr
, buf
, ADDRSTRLEN
);
404 port
= ntohs(addr
->in
.sin_port
);
406 else if (addr
->sa
.sa_family
== AF_INET6
)
408 char name
[IF_NAMESIZE
];
409 inet_ntop(AF_INET6
, &addr
->in6
.sin6_addr
, buf
, ADDRSTRLEN
);
410 if (addr
->in6
.sin6_scope_id
!= 0 &&
411 if_indextoname(addr
->in6
.sin6_scope_id
, name
) &&
412 strlen(buf
) + strlen(name
) + 2 <= ADDRSTRLEN
)
417 port
= ntohs(addr
->in6
.sin6_port
);
420 strcpy(buf
, inet_ntoa(addr
->in
.sin_addr
));
421 port
= ntohs(addr
->in
.sin_port
);
427 void prettyprint_time(char *buf
, unsigned int t
)
430 sprintf(buf
, _("infinite"));
433 unsigned int x
, p
= 0;
435 p
+= sprintf(&buf
[p
], "%dd", x
);
436 if ((x
= (t
/3600)%24))
437 p
+= sprintf(&buf
[p
], "%dh", x
);
439 p
+= sprintf(&buf
[p
], "%dm", x
);
441 p
+= sprintf(&buf
[p
], "%ds", x
);
446 /* in may equal out, when maxlen may be -1 (No max len).
447 Return -1 for extraneous no-hex chars found. */
448 int parse_hex(char *in
, unsigned char *out
, int maxlen
,
449 unsigned int *wildcard_mask
, int *mac_type
)
457 while (maxlen
== -1 || i
< maxlen
)
459 for (r
= in
; *r
!= 0 && *r
!= ':' && *r
!= '-' && *r
!= ' '; r
++)
460 if (*r
!= '*' && !isxdigit((unsigned char)*r
))
468 if (*r
== '-' && i
== 0 && mac_type
)
471 *mac_type
= strtol(in
, NULL
, 16);
477 if (strcmp(in
, "*") == 0)
479 mask
= (mask
<< 1) | 1;
484 int j
, bytes
= (1 + (r
- in
))/2;
485 for (j
= 0; j
< bytes
; j
++)
493 out
[i
] = strtol(&in
[j
*2], NULL
, 16);
506 *wildcard_mask
= mask
;
511 /* return 0 for no match, or (no matched octets) + 1 */
512 int memcmp_masked(unsigned char *a
, unsigned char *b
, int len
, unsigned int mask
)
515 for (count
= 1, i
= len
- 1; i
>= 0; i
--, mask
= mask
>> 1)
526 /* _note_ may copy buffer */
527 int expand_buf(struct iovec
*iov
, size_t size
)
531 if (size
<= (size_t)iov
->iov_len
)
534 if (!(new = whine_malloc(size
)))
542 memcpy(new, iov
->iov_base
, iov
->iov_len
);
552 char *print_mac(char *buff
, unsigned char *mac
, int len
)
558 sprintf(p
, "<null>");
560 for (i
= 0; i
< len
; i
++)
561 p
+= sprintf(p
, "%.2x%s", mac
[i
], (i
== len
- 1) ? "" : ":");
566 void bump_maxfd(int fd
, int *max
)
572 /* rc is return from sendto and friends.
573 Return 1 if we should retry.
574 Set errno to zero if we succeeded. */
575 int retry_send(ssize_t rc
)
577 static int retries
= 0;
578 struct timespec waiter
;
587 /* Linux kernels can return EAGAIN in perpetuity when calling
588 sendmsg() and the relevant interface has gone. Here we loop
589 retrying in EAGAIN for 1 second max, to avoid this hanging
592 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
)
595 waiter
.tv_nsec
= 10000;
596 nanosleep(&waiter
, NULL
);
597 if (retries
++ < 1000)
609 int read_write(int fd
, unsigned char *packet
, int size
, int rw
)
613 for (done
= 0; done
< size
; done
+= n
)
617 n
= read(fd
, &packet
[done
], (size_t)(size
- done
));
619 n
= write(fd
, &packet
[done
], (size_t)(size
- done
));
624 } while (retry_send(n
) || errno
== ENOMEM
|| errno
== ENOBUFS
);
633 /* Basically match a string value against a wildcard pattern. */
634 int wildcard_match(const char* wildcard
, const char* match
)
636 while (*wildcard
&& *match
)
638 if (*wildcard
== '*')
641 if (*wildcard
!= *match
)
648 return *wildcard
== *match
;
651 /* The same but comparing a maximum of NUM characters, like strncmp. */
652 int wildcard_matchn(const char* wildcard
, const char* match
, int num
)
654 while (*wildcard
&& *match
&& num
)
656 if (*wildcard
== '*')
659 if (*wildcard
!= *match
)
667 return (!num
) || (*wildcard
== *match
);