~cyphermox/ubuntu/precise/dnsmasq/dbus

« back to all changes in this revision

Viewing changes to src/network.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Kelley
  • Date: 2005-05-04 13:25:23 UTC
  • mfrom: (0.2.1 upstream) (1.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050504132523-29x9nzdnkypp62nc
Tags: 2.22-2
Make the resolv.conf polling code resistant to 
backwards-moving system clocks. (closes: #306117) (closes: #300694)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* dnsmasq is Copyright (c) 2000 - 2005 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.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
*/
 
12
 
 
13
/* Author's email: simon@thekelleys.org.uk */
 
14
 
 
15
#include "dnsmasq.h"
 
16
 
 
17
static int iface_allowed(struct daemon *daemon, struct irec *iface, 
 
18
                         char *name, int is_loopback, union mysockaddr *addr) 
 
19
{
 
20
  struct iname *tmp;
 
21
  
 
22
  /* If we are restricting the set of interfaces to use, make
 
23
     sure that loopback interfaces are in that set. */
 
24
  if (daemon->if_names && is_loopback)
 
25
    {
 
26
      struct iname *lo;
 
27
      for (lo = daemon->if_names; lo; lo = lo->next)
 
28
        if (lo->name && strcmp(lo->name, name) == 0)
 
29
          {
 
30
            lo->isloop = 1;
 
31
            break;
 
32
          }
 
33
      if (!lo)
 
34
        {
 
35
          lo = safe_malloc(sizeof(struct iname));
 
36
          lo->name = safe_string_alloc(name);
 
37
          lo->isloop = lo->used = 1;
 
38
          lo->next = daemon->if_names;
 
39
          daemon->if_names = lo;
 
40
        }
 
41
    }
 
42
  
 
43
  /* check blacklist */
 
44
  if (daemon->if_except)
 
45
    for (tmp = daemon->if_except; tmp; tmp = tmp->next)
 
46
      if (tmp->name && strcmp(tmp->name, name) == 0)
 
47
        return 0;
 
48
        
 
49
  /* we may need to check the whitelist */
 
50
  if (daemon->if_names || daemon->if_addrs)
 
51
    { 
 
52
      int found = 0;
 
53
 
 
54
      for (tmp = daemon->if_names; tmp; tmp = tmp->next)
 
55
        if (tmp->name && (strcmp(tmp->name, name) == 0))
 
56
          found = tmp->used = 1;
 
57
          
 
58
      for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
 
59
        if (sockaddr_isequal(&tmp->addr, addr))
 
60
          found = tmp->used = 1;
 
61
      
 
62
      if (!found) 
 
63
        return 0;
 
64
    }
 
65
  
 
66
  /* check whether the interface IP has been added already 
 
67
     it is possible to have multiple interfaces with the same address */
 
68
  for (; iface; iface = iface->next) 
 
69
    if (sockaddr_isequal(&iface->addr, addr))
 
70
      break;
 
71
  if (iface)
 
72
    return 0;
 
73
  
 
74
  return 1;
 
75
}
 
76
 
 
77
/* This does two different jobs: if chainp is non-NULL, it puts
 
78
   a list of all the interfaces allowed by config into *chainp.
 
79
   If chainp is NULL, it returns 1 if addr is  an address of an interface
 
80
   allowed by config and if that address is IPv4, it fills in the
 
81
   netmask of the interface. 
 
82
   
 
83
   If chainp is non-NULL, a zero return indicates a fatal error.
 
84
 
 
85
   If chainp is NULL, errors result in a match failure and zero return.
 
86
*/
 
87
int enumerate_interfaces(struct daemon *daemon, struct irec **chainp,
 
88
                         union mysockaddr *test_addrp, struct in_addr *netmaskp)
 
89
{
 
90
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
 
91
  FILE *f;
 
92
#endif
 
93
  union mysockaddr addr;
 
94
  struct irec *iface = NULL;
 
95
  char *buf, *ptr;
 
96
  struct ifreq *ifr = NULL;
 
97
  struct ifconf ifc;
 
98
  int lastlen = 0;
 
99
  int len = 20 * sizeof(struct ifreq);
 
100
  int fd = socket(PF_INET, SOCK_DGRAM, 0);
 
101
  struct in_addr netmask;
 
102
  int ret = 0;
 
103
 
 
104
  if (fd == -1)
 
105
    return 0;
 
106
 
 
107
#ifdef HAVE_IPV6
 
108
  if (test_addrp && test_addrp->sa.sa_family == AF_INET6)
 
109
    test_addrp->in6.sin6_flowinfo = htonl(0);
 
110
#endif
 
111
        
 
112
  while (1)
 
113
     {
 
114
       buf = safe_malloc(len);
 
115
 
 
116
       ifc.ifc_len = len;
 
117
       ifc.ifc_buf = buf;
 
118
       if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
 
119
         {
 
120
           if (errno != EINVAL || lastlen != 0)
 
121
             goto exit;
 
122
         }
 
123
       else
 
124
         {
 
125
           if (ifc.ifc_len == lastlen)
 
126
             break; /* got a big enough buffer now */
 
127
           lastlen = ifc.ifc_len;
 
128
         }
 
129
       len += 10*sizeof(struct ifreq);
 
130
       free(buf);
 
131
     }
 
132
  
 
133
  for (ptr = buf; ptr < buf + ifc.ifc_len; )
 
134
    {
 
135
#ifdef HAVE_SOCKADDR_SA_LEN
 
136
      /* subsequent entries may not be aligned, so copy into
 
137
         an aligned buffer to avoid nasty complaints about 
 
138
         unaligned accesses. */
 
139
      int ifr_len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
 
140
      if (!(ifr = realloc(ifr, ifr_len)))
 
141
        goto exit;
 
142
      
 
143
      memcpy(ifr, ptr, ifr_len);
 
144
      ptr += ifr_len;
 
145
#else
 
146
      ifr = (struct ifreq *)ptr;
 
147
      ptr += sizeof(struct ifreq);
 
148
#endif
 
149
      
 
150
      /* copy address since getting flags overwrites */
 
151
      if (ifr->ifr_addr.sa_family == AF_INET)
 
152
        {
 
153
          addr.in = *((struct sockaddr_in *) &ifr->ifr_addr);
 
154
          addr.in.sin_port = htons(daemon->port);
 
155
          if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1)
 
156
            goto exit;
 
157
          netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
 
158
        }
 
159
#ifdef HAVE_IPV6
 
160
      else if (ifr->ifr_addr.sa_family == AF_INET6)
 
161
        {
 
162
#ifdef HAVE_BROKEN_SOCKADDR_IN6
 
163
          addr.in6 = *((struct my_sockaddr_in6 *) &ifr->ifr_addr);
 
164
#else
 
165
          addr.in6 = *((struct sockaddr_in6 *) &ifr->ifr_addr);
 
166
#endif
 
167
          addr.in6.sin6_port = htons(daemon->port);
 
168
          addr.in6.sin6_flowinfo = htonl(0);
 
169
        }
 
170
#endif
 
171
      else
 
172
        continue; /* unknown address family */
 
173
      
 
174
      if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
 
175
        goto exit;
 
176
 
 
177
      if (iface_allowed(daemon, iface, ifr->ifr_name, ifr->ifr_flags & IFF_LOOPBACK, &addr))
 
178
        {
 
179
          if (chainp)
 
180
            {
 
181
              struct irec *new = safe_malloc(sizeof(struct irec));
 
182
              new->addr = addr;
 
183
              new->netmask = netmask;
 
184
              new->next = iface;
 
185
              iface = new;
 
186
            }
 
187
          else if (sockaddr_isequal(&addr, test_addrp))
 
188
            {
 
189
              *netmaskp = netmask;
 
190
              ret = 1;
 
191
              goto exit;
 
192
            }
 
193
        }
 
194
    }
 
195
 
 
196
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
 
197
  /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
 
198
  /* This code snarfed from net-tools 1.60 and certainly linux specific, though
 
199
     it shouldn't break on other Unices, and their SIOGIFCONF might work. */
 
200
  if ((f = fopen(IP6INTERFACES, "r")))
 
201
    {
 
202
      unsigned int plen, scope, flags, if_idx;
 
203
      char devname[21], addrstring[33];
 
204
      
 
205
      while (fscanf(f, "%32s %x %x %x %x %20s\n",
 
206
                    addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF) 
 
207
        {
 
208
          int i;
 
209
          struct ifreq sifr;
 
210
          unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
 
211
          memset(&addr, 0, sizeof(addr));
 
212
          addr.sa.sa_family = AF_INET6;
 
213
          for (i=0; i<16; i++)
 
214
            {
 
215
              unsigned int byte;
 
216
              sscanf(addrstring+i+i, "%02x", &byte);
 
217
              addr6p[i] = byte;
 
218
            }
 
219
          addr.in6.sin6_port = htons(daemon->port);
 
220
          addr.in6.sin6_flowinfo = htonl(0);
 
221
          addr.in6.sin6_scope_id = htonl(scope);
 
222
          
 
223
          strncpy(sifr.ifr_name, devname, IF_NAMESIZE);
 
224
          if (ioctl(fd, SIOCGIFFLAGS, &sifr) < 0)
 
225
            goto exit;
 
226
          
 
227
          if (iface_allowed(daemon, iface, sifr.ifr_name, sifr.ifr_flags & IFF_LOOPBACK, &addr))
 
228
            {
 
229
              if (chainp)
 
230
                {
 
231
                  struct irec *new = safe_malloc(sizeof(struct irec));
 
232
                  new->addr = addr;
 
233
                  new->next = iface;
 
234
                  iface = new;
 
235
                }
 
236
              else if (sockaddr_isequal(&addr, test_addrp))
 
237
                {
 
238
                  ret = 1;
 
239
                  goto exit;
 
240
                }
 
241
            }
 
242
        }           
 
243
      fclose(f);
 
244
    }
 
245
#endif /* LINUX */
 
246
  
 
247
  if (chainp)
 
248
    {
 
249
      *chainp = iface;
 
250
      ret = 1;
 
251
    }
 
252
 
 
253
 exit:  
 
254
  if (buf)
 
255
    free(buf);
 
256
#ifdef HAVE_SOCKADDR_SA_LEN
 
257
  if (ifr)
 
258
    free(ifr);
 
259
#endif
 
260
  close(fd);
 
261
 
 
262
  return ret;
 
263
}
 
264
 
 
265
#ifdef HAVE_IPV6
 
266
static int create_ipv6_listener(struct listener **link, int port)
 
267
{
 
268
  union mysockaddr addr;
 
269
  int tcpfd, fd, flags, save;
 
270
  struct listener *l;
 
271
  int opt = 1;
 
272
 
 
273
  addr.in6.sin6_family = AF_INET6;
 
274
  addr.in6.sin6_addr = in6addr_any;
 
275
  addr.in6.sin6_port = htons(port);
 
276
  addr.in6.sin6_flowinfo = htonl(0);
 
277
#ifdef HAVE_SOCKADDR_SA_LEN
 
278
  addr.in6.sin6_len = sizeof(struct sockaddr_in6);
 
279
#endif
 
280
 
 
281
  /* No error of the kernel doesn't support IPv6 */
 
282
  if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
 
283
    return (errno == EPROTONOSUPPORT ||
 
284
            errno == EAFNOSUPPORT ||
 
285
            errno == EINVAL);
 
286
  
 
287
  if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
 
288
    {
 
289
      save = errno;
 
290
      close(fd);
 
291
      errno = save;
 
292
      return 0;
 
293
    }
 
294
  
 
295
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
 
296
      setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
 
297
      setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
 
298
      setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
 
299
      (flags = fcntl(fd, F_GETFL, 0)) == -1 ||
 
300
      fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
 
301
      (flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
 
302
      fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
 
303
#ifdef IPV6_RECVPKTINFO
 
304
      setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
 
305
#else
 
306
      setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
 
307
#endif
 
308
      bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
 
309
      listen(tcpfd, 5) == -1 ||
 
310
      bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1) 
 
311
    {
 
312
      save = errno;
 
313
      close(fd);
 
314
      close(tcpfd);
 
315
      errno = save;
 
316
      return 0;
 
317
    }
 
318
  
 
319
  l = safe_malloc(sizeof(struct listener));
 
320
  l->fd = fd;
 
321
  l->tcpfd = tcpfd;
 
322
  l->family = AF_INET6;
 
323
  l->next = NULL;
 
324
  *link = l;
 
325
  
 
326
  return 1;
 
327
}
 
328
#endif
 
329
 
 
330
struct listener *create_wildcard_listeners(int port)
 
331
{
 
332
#if !(defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
 
333
  return NULL;
 
334
#else
 
335
  union mysockaddr addr;
 
336
  int opt = 1;
 
337
  struct listener *l, *l6 = NULL;
 
338
  int flags;
 
339
  int tcpfd, fd;
 
340
 
 
341
  addr.in.sin_family = AF_INET;
 
342
  addr.in.sin_addr.s_addr = INADDR_ANY;
 
343
  addr.in.sin_port = htons(port);
 
344
#ifdef HAVE_SOCKADDR_SA_LEN
 
345
  addr.in.sin_len = sizeof(struct sockaddr_in);
 
346
#endif
 
347
 
 
348
  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
 
349
    return NULL;
 
350
  
 
351
  if ((tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
 
352
    {
 
353
      close (fd);
 
354
      return NULL;
 
355
    }
 
356
  
 
357
  if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
 
358
      bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
 
359
      listen(tcpfd, 5) == -1 ||
 
360
      (flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
 
361
      fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
 
362
#ifdef HAVE_IPV6
 
363
      !create_ipv6_listener(&l6, port) ||
 
364
#endif
 
365
      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
 
366
      (flags = fcntl(fd, F_GETFL, 0)) == -1 ||
 
367
      fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
 
368
#if defined(IP_PKTINFO) 
 
369
      setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
 
370
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
 
371
      setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
 
372
      setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
 
373
#endif 
 
374
      bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
 
375
    {
 
376
      close(fd);
 
377
      close(tcpfd);
 
378
      return NULL;
 
379
    }
 
380
  
 
381
  l = safe_malloc(sizeof(struct listener));
 
382
  l->family = AF_INET;
 
383
  l->fd = fd;
 
384
  l->tcpfd = tcpfd;
 
385
  l->next = l6;
 
386
 
 
387
  return l;
 
388
 
 
389
#endif
 
390
}
 
391
 
 
392
struct listener *create_bound_listeners(struct irec *interfaces, int port)
 
393
{
 
394
 
 
395
  struct listener *listeners = NULL;
 
396
  struct irec *iface;
 
397
  int flags = port, opt = 1;
 
398
  
 
399
  for (iface = interfaces ;iface; iface = iface->next)
 
400
    {
 
401
      struct listener *new = safe_malloc(sizeof(struct listener));
 
402
      new->family = iface->addr.sa.sa_family;
 
403
      new->iface = iface;
 
404
      new->next = listeners;
 
405
      if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
 
406
          (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
 
407
          setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
 
408
          setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
 
409
          /* See Stevens 16.6 */
 
410
          (flags = fcntl(new->tcpfd, F_GETFL, 0)) == -1 ||
 
411
          fcntl(new->tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
 
412
          (flags = fcntl(new->fd, F_GETFL, 0)) == -1 ||
 
413
          fcntl(new->fd, F_SETFL, flags | O_NONBLOCK) == -1)
 
414
        die("failed to create listening socket: %s", NULL);
 
415
      
 
416
#ifdef HAVE_IPV6
 
417
      if (iface->addr.sa.sa_family == AF_INET6)
 
418
        {
 
419
          if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
 
420
              setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
 
421
            die("failed to set IPV6 options on listening socket: %s", NULL);
 
422
        }
 
423
#endif
 
424
      
 
425
      if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
 
426
          bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
 
427
        {
 
428
#ifdef HAVE_IPV6
 
429
          if (iface->addr.sa.sa_family == AF_INET6 && errno == ENODEV)
 
430
            {
 
431
              close(new->tcpfd);
 
432
              close(new->fd);
 
433
              free(new);
 
434
            }
 
435
          else
 
436
#endif
 
437
            die("failed to bind listening socket: %s", NULL);
 
438
        }
 
439
      else
 
440
         {
 
441
           listeners = new;     
 
442
           if (listen(new->tcpfd, 5) == -1)
 
443
             die("failed to listen on socket: %s", NULL);
 
444
         }
 
445
    }
 
446
  
 
447
  return listeners;
 
448
}
 
449
 
 
450
struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
 
451
{
 
452
  struct serverfd *sfd;
 
453
  int flags;
 
454
 
 
455
  /* may have a suitable one already */
 
456
  for (sfd = *sfds; sfd; sfd = sfd->next )
 
457
    if (sockaddr_isequal(&sfd->source_addr, addr))
 
458
      return sfd;
 
459
  
 
460
  /* need to make a new one. */
 
461
  errno = ENOMEM; /* in case malloc fails. */
 
462
  if (!(sfd = malloc(sizeof(struct serverfd))))
 
463
    return NULL;
 
464
  
 
465
  if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
 
466
    {
 
467
      free(sfd);
 
468
      return NULL;
 
469
    }
 
470
  
 
471
  if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1 ||
 
472
      (flags = fcntl(sfd->fd, F_GETFL, 0)) == -1 ||
 
473
      fcntl(sfd->fd, F_SETFL, flags | O_NONBLOCK) == -1)
 
474
    {
 
475
      int errsave = errno; /* save error from bind. */
 
476
      close(sfd->fd);
 
477
      free(sfd);
 
478
      errno = errsave;
 
479
      return NULL;
 
480
    }
 
481
  
 
482
  sfd->source_addr = *addr;
 
483
  sfd->next = *sfds;
 
484
  *sfds = sfd;
 
485
  
 
486
  return sfd;
 
487
}
 
488
 
 
489
void check_servers(struct daemon *daemon, struct irec *interfaces)
 
490
{
 
491
  char addrbuff[ADDRSTRLEN];
 
492
  struct irec *iface;
 
493
  struct server *new, *tmp, *ret = NULL;
 
494
  int port = 0;
 
495
 
 
496
  /* forward table rules reference servers, so have to blow them away */
 
497
  forward_init(0);
 
498
  
 
499
  daemon->last_server = NULL;
 
500
  
 
501
  for (new = daemon->servers; new; new = tmp)
 
502
    {
 
503
      tmp = new->next;
 
504
      
 
505
      if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
 
506
        {
 
507
#ifdef HAVE_IPV6
 
508
          if (new->addr.sa.sa_family == AF_INET)
 
509
            {
 
510
              inet_ntop(AF_INET, &new->addr.in.sin_addr, addrbuff, ADDRSTRLEN);
 
511
              port = ntohs(new->addr.in.sin_port);
 
512
            }
 
513
          else if (new->addr.sa.sa_family == AF_INET6)
 
514
            {
 
515
              inet_ntop(AF_INET6, &new->addr.in6.sin6_addr, addrbuff, ADDRSTRLEN);
 
516
              port = ntohs(new->addr.in6.sin6_port);
 
517
            }
 
518
#else
 
519
          strcpy(addrbuff, inet_ntoa(new->addr.in.sin_addr));
 
520
          port = ntohs(new->addr.in.sin_port); 
 
521
#endif
 
522
          for (iface = interfaces; iface; iface = iface->next)
 
523
            if (sockaddr_isequal(&new->addr, &iface->addr))
 
524
              break;
 
525
          if (iface)
 
526
            {
 
527
              syslog(LOG_WARNING, "ignoring nameserver %s - local interface", addrbuff);
 
528
              free(new);
 
529
              continue;
 
530
            }
 
531
          
 
532
          /* Do we need a socket set? */
 
533
          if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, &daemon->sfds)))
 
534
            {
 
535
              syslog(LOG_WARNING, 
 
536
                     "ignoring nameserver %s - cannot make/bind socket: %m", addrbuff);
 
537
              free(new);
 
538
              continue;
 
539
            }
 
540
        }
 
541
      
 
542
      /* reverse order - gets it right. */
 
543
      new->next = ret;
 
544
      ret = new;
 
545
      
 
546
      if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
 
547
        {
 
548
          char *s1, *s2;
 
549
          if (new->flags & SERV_HAS_DOMAIN)
 
550
            s1 = "domain", s2 = new->domain;
 
551
          else
 
552
            s1 = "unqualified", s2 = "domains";
 
553
          
 
554
          if (new->flags & SERV_NO_ADDR)
 
555
            syslog(LOG_INFO, "using local addresses only for %s %s", s1, s2);
 
556
          else if (!(new->flags & SERV_LITERAL_ADDRESS))
 
557
            syslog(LOG_INFO, "using nameserver %s#%d for %s %s", addrbuff, port, s1, s2);
 
558
        }
 
559
      else
 
560
        syslog(LOG_INFO, "using nameserver %s#%d", addrbuff, port); 
 
561
    }
 
562
  
 
563
  daemon->servers = ret;
 
564
}
 
565
  
 
566
void reload_servers(char *fname, struct daemon *daemon)
 
567
{
 
568
  FILE *f;
 
569
  char *line;
 
570
  struct server *old_servers = NULL;
 
571
  struct server *new_servers = NULL;
 
572
  struct server *serv = daemon->servers;
 
573
 
 
574
  /* move old servers to free list - we can reuse the memory 
 
575
     and not risk malloc if there are the same or fewer new servers. 
 
576
     Servers which were specced on the command line go to the new list. */
 
577
  while (serv)
 
578
    {
 
579
      struct server *tmp = serv->next;
 
580
      if (serv->flags & SERV_FROM_RESOLV)
 
581
        {
 
582
          serv->next = old_servers;
 
583
          old_servers = serv;
 
584
        }
 
585
      else
 
586
        {
 
587
          serv->next = new_servers;
 
588
          new_servers = serv;
 
589
        }
 
590
      serv = tmp;
 
591
    }
 
592
 
 
593
  /* buff happens to be NAXDNAME long... */
 
594
  f = fopen(fname, "r");
 
595
  if (!f)
 
596
    {
 
597
      syslog(LOG_ERR, "failed to read %s: %m", fname);
 
598
    }
 
599
  else
 
600
    {
 
601
      syslog(LOG_INFO, "reading %s", fname);
 
602
      while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
 
603
        {
 
604
          union  mysockaddr addr, source_addr;
 
605
          char *token = strtok(line, " \t\n\r");
 
606
          struct server *serv;
 
607
          
 
608
          if (!token || strcmp(token, "nameserver") != 0)
 
609
            continue;
 
610
          if (!(token = strtok(NULL, " \t\n\r")))
 
611
            continue;
 
612
          
 
613
#ifdef HAVE_IPV6
 
614
          if (inet_pton(AF_INET, token, &addr.in.sin_addr))
 
615
#else
 
616
          if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
 
617
#endif
 
618
            {
 
619
#ifdef HAVE_SOCKADDR_SA_LEN
 
620
              source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
 
621
#endif
 
622
              source_addr.in.sin_family = addr.in.sin_family = AF_INET;
 
623
              addr.in.sin_port = htons(NAMESERVER_PORT);
 
624
              source_addr.in.sin_addr.s_addr = INADDR_ANY;
 
625
              source_addr.in.sin_port = htons(daemon->query_port);
 
626
            }
 
627
#ifdef HAVE_IPV6
 
628
          else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr))
 
629
            {
 
630
#ifdef HAVE_SOCKADDR_SA_LEN
 
631
              source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
 
632
#endif
 
633
              source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
 
634
              addr.in6.sin6_port = htons(NAMESERVER_PORT);
 
635
              source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = htonl(0);
 
636
              source_addr.in6.sin6_addr = in6addr_any;
 
637
              source_addr.in6.sin6_port = htons(daemon->query_port);
 
638
            }
 
639
#endif /* IPV6 */
 
640
          else
 
641
            continue;
 
642
          
 
643
          if (old_servers)
 
644
            {
 
645
              serv = old_servers;
 
646
              old_servers = old_servers->next;
 
647
            }
 
648
          else if (!(serv = malloc(sizeof (struct server))))
 
649
            continue;
 
650
          
 
651
          /* this list is reverse ordered: 
 
652
             it gets reversed again in check_servers */
 
653
          serv->next = new_servers;
 
654
          new_servers = serv;
 
655
          serv->addr = addr;
 
656
          serv->source_addr = source_addr;
 
657
          serv->domain = NULL;
 
658
          serv->sfd = NULL;
 
659
          serv->flags = SERV_FROM_RESOLV;
 
660
        }
 
661
  
 
662
      fclose(f);
 
663
    }
 
664
 
 
665
  /* Free any memory not used. */
 
666
  while(old_servers)
 
667
    {
 
668
      struct server *tmp = old_servers->next;
 
669
      free(old_servers);
 
670
      old_servers = tmp;
 
671
    }
 
672
 
 
673
  daemon->servers = new_servers;
 
674
}
 
675
 
 
676
 
 
677
 
 
678
 
 
679
 
 
680
 
 
681