blob: a729f339e219d3e24fd28ab2ac0e5410da2d0f8e [file] [log] [blame]
Simon Kelleyc47e3ba2014-01-08 17:07:54 +00001/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
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
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 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.
Simon Kelley73a08a22009-02-05 20:28:08 +000012
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/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley1a6bca82008-07-11 11:11:42 +010017/* The SURF random number generator was taken from djbdns-1.05, by
Simon Kelley7622fc02009-06-04 20:32:05 +010018 Daniel J Bernstein, which is public domain. */
Simon Kelley1a6bca82008-07-11 11:11:42 +010019
20
Simon Kelley9e4abcb2004-01-22 19:47:41 +000021#include "dnsmasq.h"
22
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010023#ifdef HAVE_BROKEN_RTC
24#include <sys/times.h>
25#endif
26
Simon Kelley572b41e2011-02-18 18:11:18 +000027#if defined(LOCALEDIR) || defined(HAVE_IDN)
Simon Kelley1f15b812009-10-13 17:49:32 +010028#include <idna.h>
29#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +010030
Simon Kelley1a6bca82008-07-11 11:11:42 +010031/* SURF random number generator */
32
Simon Kelley572b41e2011-02-18 18:11:18 +000033static u32 seed[32];
34static u32 in[12];
35static u32 out[8];
Simon Kelley6586e832013-11-07 14:20:13 +000036static int outleft = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010037
38void rand_init()
39{
40 int fd = open(RANDFILE, O_RDONLY);
41
42 if (fd == -1 ||
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);
46
47 close(fd);
48}
49
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));
52
53static void surf(void)
54{
Simon Kelley572b41e2011-02-18 18:11:18 +000055 u32 t[12]; u32 x; u32 sum = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010056 int r; int i; int loop;
57
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];
60 x = t[11];
61 for (loop = 0;loop < 2;++loop) {
62 for (r = 0;r < 16;++r) {
63 sum += 0x9e3779b9;
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)
67 }
68 for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
69 }
70}
71
72unsigned short rand16(void)
73{
Simon Kelley6586e832013-11-07 14:20:13 +000074 if (!outleft)
75 {
76 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
77 surf();
78 outleft = 8;
79 }
80
81 return (unsigned short) out[--outleft];
82}
83
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010084u32 rand32(void)
85{
86 if (!outleft)
87 {
88 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
89 surf();
90 outleft = 8;
91 }
92
93 return out[--outleft];
94}
95
Simon Kelley6586e832013-11-07 14:20:13 +000096u64 rand64(void)
97{
Simon Kelley1a6bca82008-07-11 11:11:42 +010098 static int outleft = 0;
99
Simon Kelley6586e832013-11-07 14:20:13 +0000100 if (outleft < 2)
101 {
102 if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
103 surf();
104 outleft = 8;
105 }
106
107 outleft -= 2;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100108
Simon Kelley6586e832013-11-07 14:20:13 +0000109 return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100110}
111
Simon Kelley1f15b812009-10-13 17:49:32 +0100112static int check_name(char *in)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000113{
Simon Kelley1f15b812009-10-13 17:49:32 +0100114 /* remove trailing .
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000115 also fail empty string and label > 63 chars */
Simon Kelley1f15b812009-10-13 17:49:32 +0100116 size_t dotgap = 0, l = strlen(in);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000117 char c;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100118 int nowhite = 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100119
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000120 if (l == 0 || l > MAXDNAME) return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100121
122 if (in[l-1] == '.')
Simon Kelleya2226412004-05-13 20:27:08 +0100123 {
Simon Kelley1f15b812009-10-13 17:49:32 +0100124 in[l-1] = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000125 nowhite = 1;
Simon Kelleya2226412004-05-13 20:27:08 +0100126 }
Simon Kelley0fc2f312014-01-08 10:26:58 +0000127
Simon Kelley1f15b812009-10-13 17:49:32 +0100128 for (; (c = *in); in++)
Simon Kelley3d8df262005-08-29 12:19:27 +0100129 {
130 if (c == '.')
131 dotgap = 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100132 else if (++dotgap > MAXLABEL)
Simon Kelley3d8df262005-08-29 12:19:27 +0100133 return 0;
Simon Kelley572b41e2011-02-18 18:11:18 +0000134 else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
Simon Kelley1f15b812009-10-13 17:49:32 +0100135 /* iscntrl only gives expected results for ascii */
136 return 0;
Simon Kelley572b41e2011-02-18 18:11:18 +0000137#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
138 else if (!isascii((unsigned char)c))
Simon Kelley1f15b812009-10-13 17:49:32 +0100139 return 0;
140#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100141 else if (c != ' ')
142 nowhite = 1;
Simon Kelley3d8df262005-08-29 12:19:27 +0100143 }
Simon Kelley1f15b812009-10-13 17:49:32 +0100144
145 if (!nowhite)
146 return 0;
147
148 return 1;
149}
150
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. */
155int legal_hostname(char *name)
156{
157 char c;
Simon Kelley7abb69b2013-04-29 10:52:16 +0100158 int first;
Simon Kelley1f15b812009-10-13 17:49:32 +0100159
160 if (!check_name(name))
161 return 0;
162
Simon Kelley7abb69b2013-04-29 10:52:16 +0100163 for (first = 1; (c = *name); name++, first = 0)
Simon Kelley1f15b812009-10-13 17:49:32 +0100164 /* check for legal char a-z A-Z 0-9 - _ . */
165 {
166 if ((c >= 'A' && c <= 'Z') ||
Kyle Mesteryd859ca22013-07-24 13:11:58 +0100167 (c >= 'a' && c <= 'z') ||
168 (c >= '0' && c <= '9'))
Simon Kelley1f15b812009-10-13 17:49:32 +0100169 continue;
Simon Kelley7abb69b2013-04-29 10:52:16 +0100170
Kyle Mesteryd859ca22013-07-24 13:11:58 +0100171 if (!first && (c == '-' || c == '_'))
Simon Kelley7abb69b2013-04-29 10:52:16 +0100172 continue;
Kyle Mesteryd859ca22013-07-24 13:11:58 +0100173
Simon Kelley1f15b812009-10-13 17:49:32 +0100174 /* end of hostname part */
175 if (c == '.')
176 return 1;
177
178 return 0;
179 }
180
181 return 1;
182}
183
184char *canonicalise(char *in, int *nomem)
185{
186 char *ret = NULL;
Simon Kelley572b41e2011-02-18 18:11:18 +0000187#if defined(LOCALEDIR) || defined(HAVE_IDN)
Simon Kelley1f15b812009-10-13 17:49:32 +0100188 int rc;
189#endif
190
191 if (nomem)
192 *nomem = 0;
193
194 if (!check_name(in))
195 return NULL;
196
Simon Kelley572b41e2011-02-18 18:11:18 +0000197#if defined(LOCALEDIR) || defined(HAVE_IDN)
Simon Kelley1f15b812009-10-13 17:49:32 +0100198 if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
199 {
200 if (ret)
201 free(ret);
202
203 if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
204 {
205 my_syslog(LOG_ERR, _("failed to allocate memory"));
206 *nomem = 1;
207 }
208
209 return NULL;
210 }
211#else
212 if ((ret = whine_malloc(strlen(in)+1)))
213 strcpy(ret, in);
214 else if (nomem)
215 *nomem = 1;
216#endif
217
218 return ret;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000219}
220
Simon Kelley3d8df262005-08-29 12:19:27 +0100221unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
222{
223 int j;
224
225 while (sval && *sval)
226 {
227 unsigned char *cp = p++;
228 for (j = 0; *sval && (*sval != '.'); sval++, j++)
229 *p++ = *sval;
230 *cp = j;
231 if (*sval)
232 sval++;
233 }
234 return p;
235}
236
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000237/* for use during startup */
Simon Kelley0a852542005-03-23 20:28:59 +0000238void *safe_malloc(size_t size)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000239{
240 void *ret = malloc(size);
241
242 if (!ret)
Simon Kelley5aabfc72007-08-29 11:24:47 +0100243 die(_("could not get memory"), NULL, EC_NOMEM);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000244
245 return ret;
Simon Kelley3d8df262005-08-29 12:19:27 +0100246}
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000247
Simon Kelley1a6bca82008-07-11 11:11:42 +0100248void safe_pipe(int *fd, int read_noblock)
249{
250 if (pipe(fd) == -1 ||
251 !fix_fd(fd[1]) ||
252 (read_noblock && !fix_fd(fd[0])))
253 die(_("cannot create pipe: %s"), NULL, EC_MISC);
254}
255
Simon Kelley5aabfc72007-08-29 11:24:47 +0100256void *whine_malloc(size_t size)
257{
258 void *ret = malloc(size);
259
260 if (!ret)
261 my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
262
263 return ret;
264}
265
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000266int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
267{
268 if (s1->sa.sa_family == s2->sa.sa_family)
269 {
270 if (s1->sa.sa_family == AF_INET &&
271 s1->in.sin_port == s2->in.sin_port &&
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100272 s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000273 return 1;
274#ifdef HAVE_IPV6
275 if (s1->sa.sa_family == AF_INET6 &&
276 s1->in6.sin6_port == s2->in6.sin6_port &&
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100277 IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000278 return 1;
279#endif
280 }
281 return 0;
282}
283
284int sa_len(union mysockaddr *addr)
285{
286#ifdef HAVE_SOCKADDR_SA_LEN
287 return addr->sa.sa_len;
288#else
289#ifdef HAVE_IPV6
290 if (addr->sa.sa_family == AF_INET6)
291 return sizeof(addr->in6);
292 else
293#endif
294 return sizeof(addr->in);
295#endif
296}
297
298/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
Simon Kelleyc99df932012-10-12 13:39:04 +0100299int hostname_isequal(const char *a, const char *b)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000300{
301 unsigned int c1, c2;
302
303 do {
Simon Kelley3d8df262005-08-29 12:19:27 +0100304 c1 = (unsigned char) *a++;
305 c2 = (unsigned char) *b++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000306
307 if (c1 >= 'A' && c1 <= 'Z')
308 c1 += 'a' - 'A';
309 if (c2 >= 'A' && c2 <= 'Z')
310 c2 += 'a' - 'A';
311
312 if (c1 != c2)
313 return 0;
314 } while (c1);
315
316 return 1;
317}
318
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100319time_t dnsmasq_time(void)
Simon Kelley44a2a312004-03-10 20:04:35 +0000320{
321#ifdef HAVE_BROKEN_RTC
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100322 struct tms dummy;
323 static long tps = 0;
324
325 if (tps == 0)
326 tps = sysconf(_SC_CLK_TCK);
327
328 return (time_t)(times(&dummy)/tps);
Simon Kelley44a2a312004-03-10 20:04:35 +0000329#else
Simon Kelley44a2a312004-03-10 20:04:35 +0000330 return time(NULL);
331#endif
332}
Simon Kelleya84fa1d2004-04-23 22:21:21 +0100333
Lung-Pin Changdc8a1b12014-07-02 10:48:05 +0800334int netmask_length(struct in_addr mask)
335{
336 int zero_count = 0;
337
Simon Kelley6d8e8ac2014-07-13 22:12:45 +0100338 while (0x0 == (mask.s_addr & 0x1) && zero_count < 32)
339 {
340 mask.s_addr >>= 1;
341 zero_count++;
342 }
343
Lung-Pin Changdc8a1b12014-07-02 10:48:05 +0800344 return 32 - zero_count;
345}
346
Simon Kelleya84fa1d2004-04-23 22:21:21 +0100347int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
348{
349 return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
350}
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100351
Simon Kelleyc72daea2012-01-05 21:33:27 +0000352#ifdef HAVE_IPV6
353int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
354{
355 int pfbytes = prefixlen >> 3;
356 int pfbits = prefixlen & 7;
357
358 if (memcmp(&a->s6_addr, &b->s6_addr, pfbytes) != 0)
359 return 0;
360
361 if (pfbits == 0 ||
Simon Kelleyc64b7f62012-05-18 10:19:59 +0100362 (a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
Simon Kelleyc72daea2012-01-05 21:33:27 +0000363 return 1;
364
365 return 0;
366}
367
Simon Kelley52b92f42012-01-22 16:05:15 +0000368/* return least signigicant 64 bits if IPv6 address */
369u64 addr6part(struct in6_addr *addr)
370{
371 int i;
372 u64 ret = 0;
373
374 for (i = 8; i < 16; i++)
375 ret = (ret << 8) + addr->s6_addr[i];
376
377 return ret;
378}
379
380void setaddr6part(struct in6_addr *addr, u64 host)
381{
382 int i;
383
384 for (i = 15; i >= 8; i--)
385 {
386 addr->s6_addr[i] = host;
387 host = host >> 8;
388 }
389}
390
Simon Kelleyc72daea2012-01-05 21:33:27 +0000391#endif
392
393
Simon Kelley3d8df262005-08-29 12:19:27 +0100394/* returns port number from address */
395int prettyprint_addr(union mysockaddr *addr, char *buf)
396{
397 int port = 0;
398
399#ifdef HAVE_IPV6
400 if (addr->sa.sa_family == AF_INET)
401 {
402 inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
403 port = ntohs(addr->in.sin_port);
404 }
405 else if (addr->sa.sa_family == AF_INET6)
406 {
Simon Kelley7de060b2011-08-26 17:24:52 +0100407 char name[IF_NAMESIZE];
Simon Kelley3d8df262005-08-29 12:19:27 +0100408 inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
Simon Kelley7de060b2011-08-26 17:24:52 +0100409 if (addr->in6.sin6_scope_id != 0 &&
410 if_indextoname(addr->in6.sin6_scope_id, name) &&
411 strlen(buf) + strlen(name) + 2 <= ADDRSTRLEN)
412 {
413 strcat(buf, "%");
414 strcat(buf, name);
415 }
Simon Kelley3d8df262005-08-29 12:19:27 +0100416 port = ntohs(addr->in6.sin6_port);
417 }
418#else
419 strcpy(buf, inet_ntoa(addr->in.sin_addr));
420 port = ntohs(addr->in.sin_port);
421#endif
422
423 return port;
424}
425
Simon Kelley0a852542005-03-23 20:28:59 +0000426void prettyprint_time(char *buf, unsigned int t)
427{
428 if (t == 0xffffffff)
Simon Kelleyb8187c82005-11-26 21:46:27 +0000429 sprintf(buf, _("infinite"));
Simon Kelley0a852542005-03-23 20:28:59 +0000430 else
431 {
432 unsigned int x, p = 0;
Simon Kelley3d8df262005-08-29 12:19:27 +0100433 if ((x = t/86400))
434 p += sprintf(&buf[p], "%dd", x);
435 if ((x = (t/3600)%24))
Simon Kelley0a852542005-03-23 20:28:59 +0000436 p += sprintf(&buf[p], "%dh", x);
437 if ((x = (t/60)%60))
438 p += sprintf(&buf[p], "%dm", x);
439 if ((x = t%60))
440 p += sprintf(&buf[p], "%ds", x);
441 }
442}
443
444
Simon Kelley28866e92011-02-14 20:19:14 +0000445/* in may equal out, when maxlen may be -1 (No max len).
446 Return -1 for extraneous no-hex chars found. */
Simon Kelleycdeda282006-03-16 20:16:06 +0000447int parse_hex(char *in, unsigned char *out, int maxlen,
448 unsigned int *wildcard_mask, int *mac_type)
Simon Kelley0a852542005-03-23 20:28:59 +0000449{
450 int mask = 0, i = 0;
451 char *r;
Simon Kelleycdeda282006-03-16 20:16:06 +0000452
453 if (mac_type)
454 *mac_type = 0;
455
Simon Kelley0a852542005-03-23 20:28:59 +0000456 while (maxlen == -1 || i < maxlen)
457 {
Simon Kelley9f7f3b12012-05-28 21:39:57 +0100458 for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
Simon Kelley572b41e2011-02-18 18:11:18 +0000459 if (*r != '*' && !isxdigit((unsigned char)*r))
Simon Kelley28866e92011-02-14 20:19:14 +0000460 return -1;
461
Simon Kelley0a852542005-03-23 20:28:59 +0000462 if (*r == 0)
463 maxlen = i;
Simon Kelleycdeda282006-03-16 20:16:06 +0000464
Simon Kelley0a852542005-03-23 20:28:59 +0000465 if (r != in )
466 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000467 if (*r == '-' && i == 0 && mac_type)
468 {
469 *r = 0;
470 *mac_type = strtol(in, NULL, 16);
471 mac_type = NULL;
472 }
Simon Kelley0a852542005-03-23 20:28:59 +0000473 else
Simon Kelleycdeda282006-03-16 20:16:06 +0000474 {
475 *r = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +0000476 if (strcmp(in, "*") == 0)
Simon Kelley9f7f3b12012-05-28 21:39:57 +0100477 {
478 mask = (mask << 1) | 1;
479 i++;
480 }
Simon Kelleycdeda282006-03-16 20:16:06 +0000481 else
Simon Kelley9f7f3b12012-05-28 21:39:57 +0100482 {
483 int j, bytes = (1 + (r - in))/2;
484 for (j = 0; j < bytes; j++)
485 {
Vladislav Grishenko50db3492013-11-26 11:09:31 +0000486 char sav = sav;
Simon Kelley9f7f3b12012-05-28 21:39:57 +0100487 if (j < bytes - 1)
488 {
489 sav = in[(j+1)*2];
490 in[(j+1)*2] = 0;
491 }
492 out[i] = strtol(&in[j*2], NULL, 16);
493 mask = mask << 1;
494 i++;
495 if (j < bytes - 1)
496 in[(j+1)*2] = sav;
497 }
498 }
Simon Kelleycdeda282006-03-16 20:16:06 +0000499 }
Simon Kelley0a852542005-03-23 20:28:59 +0000500 }
501 in = r+1;
502 }
503
504 if (wildcard_mask)
505 *wildcard_mask = mask;
506
507 return i;
508}
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100509
Simon Kelley7622fc02009-06-04 20:32:05 +0100510/* return 0 for no match, or (no matched octets) + 1 */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100511int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
512{
Simon Kelley7622fc02009-06-04 20:32:05 +0100513 int i, count;
514 for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
515 if (!(mask & 1))
516 {
517 if (a[i] == b[i])
518 count++;
519 else
520 return 0;
521 }
522 return count;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100523}
524
525/* _note_ may copy buffer */
526int expand_buf(struct iovec *iov, size_t size)
527{
528 void *new;
529
Simon Kelley824af852008-02-12 20:43:05 +0000530 if (size <= (size_t)iov->iov_len)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100531 return 1;
532
Simon Kelley5aabfc72007-08-29 11:24:47 +0100533 if (!(new = whine_malloc(size)))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100534 {
535 errno = ENOMEM;
536 return 0;
537 }
538
539 if (iov->iov_base)
540 {
541 memcpy(new, iov->iov_base, iov->iov_len);
542 free(iov->iov_base);
543 }
544
545 iov->iov_base = new;
546 iov->iov_len = size;
547
548 return 1;
549}
Simon Kelley7cebd202006-05-06 14:13:33 +0100550
Simon Kelley5aabfc72007-08-29 11:24:47 +0100551char *print_mac(char *buff, unsigned char *mac, int len)
Simon Kelley7cebd202006-05-06 14:13:33 +0100552{
Simon Kelley5aabfc72007-08-29 11:24:47 +0100553 char *p = buff;
Simon Kelley7cebd202006-05-06 14:13:33 +0100554 int i;
555
556 if (len == 0)
557 sprintf(p, "<null>");
558 else
559 for (i = 0; i < len; i++)
560 p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
561
Simon Kelley5aabfc72007-08-29 11:24:47 +0100562 return buff;
Simon Kelley7cebd202006-05-06 14:13:33 +0100563}
Simon Kelley16972692006-10-16 20:04:18 +0100564
565void bump_maxfd(int fd, int *max)
566{
567 if (fd > *max)
568 *max = fd;
569}
570
Simon Kelley5aabfc72007-08-29 11:24:47 +0100571int retry_send(void)
572{
Simon Kelley57826492014-09-18 22:08:58 +0100573 /* Linux kernels can return EAGAIN in perpetuity when calling
574 sendmsg() and the relevant interface has gone. Here we loop
575 retrying in EAGAIN for 1 second max, to avoid this hanging
576 dnsmasq. */
577
578 static int retries = 0;
579 struct timespec waiter;
580
Simon Kelleyc72daea2012-01-05 21:33:27 +0000581 if (errno == EAGAIN || errno == EWOULDBLOCK)
Simon Kelley5aabfc72007-08-29 11:24:47 +0100582 {
583 waiter.tv_sec = 0;
584 waiter.tv_nsec = 10000;
585 nanosleep(&waiter, NULL);
Simon Kelley57826492014-09-18 22:08:58 +0100586 if (retries++ < 1000)
587 return 1;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100588 }
Simon Kelley57826492014-09-18 22:08:58 +0100589
590 retries = 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100591
592 if (errno == EINTR)
593 return 1;
Simon Kelley57826492014-09-18 22:08:58 +0100594
Simon Kelley5aabfc72007-08-29 11:24:47 +0100595 return 0;
596}
597
Simon Kelley16972692006-10-16 20:04:18 +0100598int read_write(int fd, unsigned char *packet, int size, int rw)
599{
600 ssize_t n, done;
601
602 for (done = 0; done < size; done += n)
603 {
604 retry:
605 if (rw)
606 n = read(fd, &packet[done], (size_t)(size - done));
607 else
608 n = write(fd, &packet[done], (size_t)(size - done));
609
610 if (n == 0)
611 return 0;
612 else if (n == -1)
613 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100614 if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
Simon Kelley16972692006-10-16 20:04:18 +0100615 goto retry;
616 else
617 return 0;
618 }
619 }
620 return 1;
621}
Simon Kelley1a6bca82008-07-11 11:11:42 +0100622
Simon Kelley49333cb2013-03-15 20:30:51 +0000623/* Basically match a string value against a wildcard pattern. */
624int wildcard_match(const char* wildcard, const char* match)
625{
626 while (*wildcard && *match)
627 {
628 if (*wildcard == '*')
629 return 1;
630
631 if (*wildcard != *match)
632 return 0;
633
634 ++wildcard;
635 ++match;
636 }
637
638 return *wildcard == *match;
639}
Neil Jerram70772c92014-06-11 21:22:40 +0100640
641/* The same but comparing a maximum of NUM characters, like strncmp. */
642int wildcard_matchn(const char* wildcard, const char* match, int num)
643{
644 while (*wildcard && *match && num)
645 {
646 if (*wildcard == '*')
647 return 1;
648
649 if (*wildcard != *match)
650 return 0;
651
652 ++wildcard;
653 ++match;
654 --num;
655 }
656
657 return (!num) || (*wildcard == *match);
658}