1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   This program is free software; you can redistribute it and/or modify
4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   it under the terms of the GNU General Public License as published by
5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   the Free Software Foundation; version 2 dated June, 1991, or
6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   (at your option) version 3 dated 29 June, 2007.
7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   This program is distributed in the hope that it will be useful,
9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   but WITHOUT ANY WARRANTY; without even the implied warranty of
10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   GNU General Public License for more details.
12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   You should have received a copy of the GNU General Public License
14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   along with this program.  If not, see <http://www.gnu.org/licenses/>.
15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/
16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* The SURF random number generator was taken from djbdns-1.05, by
18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   Daniel J Bernstein, which is public domain. */
19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h"
22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC
24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include <sys/times.h>
25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef LOCALEDIR
28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include <idna.h>
29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_ARC4RANDOM
32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid rand_init(void)
33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return;
35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatunsigned short rand16(void)
38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   return (unsigned short) (arc4random() >> 15);
40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* SURF random number generator */
45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehattypedef unsigned int uint32;
47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic uint32 seed[32];
49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic uint32 in[12];
50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic uint32 out[8];
51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid rand_init()
53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int fd = open(RANDFILE, O_RDONLY);
55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (fd == -1 ||
57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      !read_write(fd, (unsigned char *)&seed, sizeof(seed), 1) ||
58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      !read_write(fd, (unsigned char *)&in, sizeof(in), 1))
59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  close(fd);
62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void surf(void)
68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  uint32 t[12]; uint32 x; uint32 sum = 0;
70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int r; int i; int loop;
71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0;i < 8;++i) out[i] = seed[24 + i];
74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  x = t[11];
75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (loop = 0;loop < 2;++loop) {
76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for (r = 0;r < 16;++r) {
77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      sum += 0x9e3779b9;
78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  }
84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatunsigned short rand16(void)
87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  static int outleft = 0;
89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!outleft) {
91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    surf();
93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    outleft = 8;
94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  }
95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return (unsigned short) out[--outleft];
97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int check_name(char *in)
102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* remove trailing .
104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     also fail empty string and label > 63 chars */
105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  size_t dotgap = 0, l = strlen(in);
106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char c;
107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int nowhite = 0;
108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (l == 0 || l > MAXDNAME) return 0;
110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (in[l-1] == '.')
112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (l == 1) return 0;
114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      in[l-1] = 0;
115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (; (c = *in); in++)
118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (c == '.')
120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	dotgap = 0;
121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (++dotgap > MAXLABEL)
122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return 0;
123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (isascii(c) && iscntrl(c))
124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* iscntrl only gives expected results for ascii */
125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return 0;
126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef LOCALEDIR
127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (!isascii(c))
128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return 0;
129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (c != ' ')
131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	nowhite = 1;
132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!nowhite)
135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 0;
136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Hostnames have a more limited valid charset than domain names
141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   so check for legal char a-z A-Z 0-9 - _
142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   Note that this may receive a FQDN, so only check the first label
143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   for the tighter criteria. */
144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint legal_hostname(char *name)
145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char c;
147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!check_name(name))
149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 0;
150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (; (c = *name); name++)
152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    /* check for legal char a-z A-Z 0-9 - _ . */
153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((c >= 'A' && c <= 'Z') ||
155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  (c >= 'a' && c <= 'z') ||
156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  (c >= '0' && c <= '9') ||
157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  c == '-' || c == '_')
158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	continue;
159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* end of hostname part */
161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (c == '.')
162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return 1;
163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      return 0;
165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatchar *canonicalise(char *in, int *nomem)
171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *ret = NULL;
173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef LOCALEDIR
174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int rc;
175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (nomem)
178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    *nomem = 0;
179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!check_name(in))
181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return NULL;
182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef LOCALEDIR
184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (ret)
187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	free(ret);
188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  my_syslog(LOG_ERR, _("failed to allocate memory"));
192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  *nomem = 1;
193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      return NULL;
196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if ((ret = whine_malloc(strlen(in)+1)))
199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    strcpy(ret, in);
200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (nomem)
201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    *nomem = 1;
202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return ret;
205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatunsigned char *do_rfc1035_name(unsigned char *p, char *sval)
208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int j;
210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (sval && *sval)
212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      unsigned char *cp = p++;
214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (j = 0; *sval && (*sval != '.'); sval++, j++)
215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	*p++ = *sval;
216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      *cp  = j;
217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (*sval)
218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	sval++;
219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return p;
221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* for use during startup */
224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid *safe_malloc(size_t size)
225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  void *ret = malloc(size);
227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!ret)
229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("could not get memory"), NULL, EC_NOMEM);
230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return ret;
232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid safe_pipe(int *fd, int read_noblock)
235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (pipe(fd) == -1 ||
237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      !fix_fd(fd[1]) ||
238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      (read_noblock && !fix_fd(fd[0])))
239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("cannot create pipe: %s"), NULL, EC_MISC);
240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid *whine_malloc(size_t size)
243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  void *ret = malloc(size);
245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!ret)
247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return ret;
250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (s1->sa.sa_family == s2->sa.sa_family)
255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (s1->sa.sa_family == AF_INET &&
257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  s1->in.sin_port == s2->in.sin_port &&
258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return 1;
260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (s1->sa.sa_family == AF_INET6 &&
262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  s1->in6.sin6_port == s2->in6.sin6_port &&
263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return 1;
265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 0;
268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint sa_len(union mysockaddr *addr)
271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN
273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return addr->sa.sa_len;
274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (addr->sa.sa_family == AF_INET6)
277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return sizeof(addr->in6);
278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return sizeof(addr->in);
281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint hostname_isequal(char *a, char *b)
286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned int c1, c2;
288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  do {
290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    c1 = (unsigned char) *a++;
291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    c2 = (unsigned char) *b++;
292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (c1 >= 'A' && c1 <= 'Z')
294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      c1 += 'a' - 'A';
295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (c2 >= 'A' && c2 <= 'Z')
296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      c2 += 'a' - 'A';
297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (c1 != c2)
299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      return 0;
300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  } while (c1);
301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehattime_t dnsmasq_time(void)
306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC
308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct tms dummy;
309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  static long tps = 0;
310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (tps == 0)
312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    tps = sysconf(_SC_CLK_TCK);
313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return (time_t)(times(&dummy)/tps);
315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return time(NULL);
317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* returns port number from address */
326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint prettyprint_addr(union mysockaddr *addr, char *buf)
327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int port = 0;
329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6
331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (addr->sa.sa_family == AF_INET)
332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      port = ntohs(addr->in.sin_port);
335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (addr->sa.sa_family == AF_INET6)
337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      port = ntohs(addr->in6.sin6_port);
340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  strcpy(buf, inet_ntoa(addr->in.sin_addr));
343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  port = ntohs(addr->in.sin_port);
344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return port;
347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid prettyprint_time(char *buf, unsigned int t)
350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (t == 0xffffffff)
352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    sprintf(buf, _("infinite"));
353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      unsigned int x, p = 0;
356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       if ((x = t/86400))
357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	p += sprintf(&buf[p], "%dd", x);
358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       if ((x = (t/3600)%24))
359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	p += sprintf(&buf[p], "%dh", x);
360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((x = (t/60)%60))
361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	p += sprintf(&buf[p], "%dm", x);
362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((x = t%60))
363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	p += sprintf(&buf[p], "%ds", x);
364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* in may equal out, when maxlen may be -1 (No max len). */
369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint parse_hex(char *in, unsigned char *out, int maxlen,
370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      unsigned int *wildcard_mask, int *mac_type)
371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int mask = 0, i = 0;
373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *r;
374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (mac_type)
376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    *mac_type = 0;
377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (maxlen == -1 || i < maxlen)
379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (r = in; *r != 0 && *r != ':' && *r != '-'; r++);
381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (*r == 0)
382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	maxlen = i;
383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (r != in )
385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (*r == '-' && i == 0 && mac_type)
387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   {
388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *r = 0;
389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *mac_type = strtol(in, NULL, 16);
390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      mac_type = NULL;
391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   }
392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      *r = 0;
395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      mask = mask << 1;
396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (strcmp(in, "*") == 0)
397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		mask |= 1;
398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      else
399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		out[i] = strtol(in, NULL, 16);
400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      i++;
401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      in = r+1;
404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (wildcard_mask)
407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    *wildcard_mask = mask;
408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return i;
410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* return 0 for no match, or (no matched octets) + 1 */
413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i, count;
416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (!(mask & 1))
418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (a[i] == b[i])
420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  count++;
421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	else
422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  return 0;
423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return count;
425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* _note_ may copy buffer */
428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint expand_buf(struct iovec *iov, size_t size)
429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  void *new;
431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (size <= (size_t)iov->iov_len)
433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 1;
434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(new = whine_malloc(size)))
436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      errno = ENOMEM;
438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      return 0;
439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (iov->iov_base)
442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      memcpy(new, iov->iov_base, iov->iov_len);
444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      free(iov->iov_base);
445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  iov->iov_base = new;
448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  iov->iov_len = size;
449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatchar *print_mac(char *buff, unsigned char *mac, int len)
454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *p = buff;
456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i;
457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (len == 0)
459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    sprintf(p, "<null>");
460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for (i = 0; i < len; i++)
462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return buff;
465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid bump_maxfd(int fd, int *max)
468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (fd > *max)
470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    *max = fd;
471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint retry_send(void)
474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   struct timespec waiter;
476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   if (errno == EAGAIN)
477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     {
478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       waiter.tv_sec = 0;
479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       waiter.tv_nsec = 10000;
480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       nanosleep(&waiter, NULL);
481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       return 1;
482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     }
483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   if (errno == EINTR)
485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     return 1;
486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   return 0;
488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint read_write(int fd, unsigned char *packet, int size, int rw)
491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  ssize_t n, done;
493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (done = 0; done < size; done += n)
495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    retry:
497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (rw)
498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        n = read(fd, &packet[done], (size_t)(size - done));
499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        n = write(fd, &packet[done], (size_t)(size - done));
501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (n == 0)
503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        return 0;
504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (n == -1)
505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        {
506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat          if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat            goto retry;
508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat          else
509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat            return 0;
510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        }
511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return 1;
513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
515