]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/network.c
1 /* dnsmasq is Copyright (c) 2000 - 2003 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.
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.
13 /* Author's email: simon@thekelleys.org.uk */
17 static struct irec
*add_iface(struct daemon
*daemon
, struct irec
*list
, char *name
, union mysockaddr
*addr
)
23 if (daemon
->if_except
)
24 for (tmp
= daemon
->if_except
; tmp
; tmp
= tmp
->next
)
25 if (tmp
->name
&& strcmp(tmp
->name
, name
) == 0)
27 /* record address of named interfaces, for TCP access control */
32 /* we may need to check the whitelist */
33 if (daemon
->if_names
|| daemon
->if_addrs
)
37 for (tmp
= daemon
->if_names
; tmp
; tmp
= tmp
->next
)
38 if (tmp
->name
&& (strcmp(tmp
->name
, name
) == 0))
41 found
= tmp
->used
= 1;
44 for (tmp
= daemon
->if_addrs
; tmp
; tmp
= tmp
->next
)
45 if (sockaddr_isequal(&tmp
->addr
, addr
))
46 found
= tmp
->used
= 1;
52 /* check whether the interface IP has been added already
53 it is possible to have multiple interfaces with the same address */
54 for (iface
= list
; iface
; iface
= iface
->next
)
55 if (sockaddr_isequal(&iface
->addr
, addr
))
60 /* If OK, add it to the head of the list */
61 iface
= safe_malloc(sizeof(struct irec
));
68 struct irec
*enumerate_interfaces(struct daemon
*daemon
)
70 struct irec
*iface
= NULL
;
72 struct ifreq
*ifr
= NULL
;
75 int len
= 20 * sizeof(struct ifreq
);
76 int fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
79 die ("cannot create socket to enumerate interfaces: %s", NULL
);
83 buf
= safe_malloc(len
);
87 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) < 0)
89 if (errno
!= EINVAL
|| lastlen
!= 0)
90 die ("ioctl error while enumerating interfaces: %s", NULL
);
94 if (ifc
.ifc_len
== lastlen
)
95 break; /* got a big enough buffer now */
96 lastlen
= ifc
.ifc_len
;
98 len
+= 10*sizeof(struct ifreq
);
102 for (ptr
= buf
; ptr
< buf
+ len
; )
104 union mysockaddr addr
;
105 #ifdef HAVE_SOCKADDR_SA_LEN
106 /* subsequent entries may not be aligned, so copy into
107 an aligned buffer to avoid nasty complaints about
108 unaligned accesses. */
109 int ifr_len
= ((struct ifreq
*)ptr
)->ifr_addr
.sa_len
+ IF_NAMESIZE
;
110 if (!(ifr
= realloc(ifr
, ifr_len
)))
111 die("cannot allocate buffer", NULL
);
113 memcpy(ifr
, ptr
, ifr_len
);
116 ifr
= (struct ifreq
*)ptr
;
117 ptr
+= sizeof(struct ifreq
);
120 /* copy address since getting flags overwrites */
121 if (ifr
->ifr_addr
.sa_family
== AF_INET
)
123 addr
.in
= *((struct sockaddr_in
*) &ifr
->ifr_addr
);
124 addr
.in
.sin_port
= htons(daemon
->port
);
127 else if (ifr
->ifr_addr
.sa_family
== AF_INET6
)
129 #ifdef HAVE_BROKEN_SOCKADDR_IN6
130 addr
.in6
= *((struct my_sockaddr_in6
*) &ifr
->ifr_addr
);
132 addr
.in6
= *((struct sockaddr_in6
*) &ifr
->ifr_addr
);
134 addr
.in6
.sin6_port
= htons(daemon
->port
);
135 addr
.in6
.sin6_flowinfo
= htonl(0);
139 continue; /* unknown address family */
141 if (ioctl(fd
, SIOCGIFFLAGS
, ifr
) < 0)
142 die("ioctl error getting interface flags: %m", NULL
);
144 /* If we are restricting the set of interfaces to use, make
145 sure that loopback interfaces are in that set. */
146 if (daemon
->if_names
&& (ifr
->ifr_flags
& IFF_LOOPBACK
))
149 for (lo
= daemon
->if_names
; lo
; lo
= lo
->next
)
150 if (lo
->name
&& strcmp(lo
->name
, ifr
->ifr_name
) == 0)
157 lo
= safe_malloc(sizeof(struct iname
));
158 lo
->name
= safe_string_alloc(ifr
->ifr_name
);
159 lo
->isloop
= lo
->used
= 1;
160 lo
->next
= daemon
->if_names
;
161 daemon
->if_names
= lo
;
165 iface
= add_iface(daemon
, iface
, ifr
->ifr_name
, &addr
);
167 #if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
168 /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
169 /* This code snarfed from net-tools 1.60 and certainly linux specific, though
170 it shouldn't break on other Unices, and their SIOGIFCONF might work. */
172 FILE *f
= fopen(IP6INTERFACES
, "r");
174 union mysockaddr addr6
;
178 unsigned int plen
, scope
, flags
, if_idx
;
179 char devname
[20], addrstring
[32];
181 while (fscanf(f
, "%32s %02x %02x %02x %02x %20s\n",
182 addrstring
, &if_idx
, &plen
, &scope
, &flags
, devname
) != EOF
)
184 if (strcmp(devname
, ifr
->ifr_name
) == 0)
187 unsigned char *addr6p
= (unsigned char *) &addr6
.in6
.sin6_addr
;
188 memset(&addr6
, 0, sizeof(addr6
));
189 addr6
.sa
.sa_family
= AF_INET6
;
193 sscanf(addrstring
+i
+i
, "%02x", &byte
);
196 addr6
.in6
.sin6_port
= htons(daemon
->port
);
197 addr6
.in6
.sin6_flowinfo
= htonl(0);
198 addr6
.in6
.sin6_scope_id
= htonl(scope
);
209 iface
= add_iface(daemon
, iface
, ifr
->ifr_name
, &addr6
);
216 #ifdef HAVE_SOCKADDR_SA_LEN
226 static int create_ipv6_listener(struct listener
**link
, int port
)
228 union mysockaddr addr
;
229 int tcpfd
, fd
, flags
, save
;
233 addr
.in6
.sin6_family
= AF_INET6
;
234 addr
.in6
.sin6_addr
= in6addr_any
;
235 addr
.in6
.sin6_port
= htons(port
);
236 addr
.in6
.sin6_flowinfo
= htonl(0);
237 #ifdef HAVE_SOCKADDR_SA_LEN
238 addr
.in6
.sin6_len
= sizeof(struct sockaddr_in6
);
241 /* No error of the kernel doesn't support IPv6 */
242 if ((fd
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
243 return (errno
== EPROTONOSUPPORT
||
244 errno
== EAFNOSUPPORT
||
247 if ((tcpfd
= socket(AF_INET6
, SOCK_STREAM
, 0)) == -1)
255 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
)) == -1 ||
256 setsockopt(tcpfd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
)) == -1 ||
257 setsockopt(fd
, IPV6_LEVEL
, IPV6_V6ONLY
, &opt
, sizeof(opt
)) == -1 ||
258 setsockopt(tcpfd
, IPV6_LEVEL
, IPV6_V6ONLY
, &opt
, sizeof(opt
)) == -1 ||
259 (flags
= fcntl(tcpfd
, F_GETFL
, 0)) == -1 ||
260 fcntl(tcpfd
, F_SETFL
, flags
| O_NONBLOCK
) == -1 ||
261 #ifdef IPV6_RECVPKTINFO
262 setsockopt(fd
, IPV6_LEVEL
, IPV6_RECVPKTINFO
, &opt
, sizeof(opt
)) == -1 ||
264 setsockopt(fd
, IPV6_LEVEL
, IPV6_PKTINFO
, &opt
, sizeof(opt
)) == -1 ||
266 bind(tcpfd
, (struct sockaddr
*)&addr
, sa_len(&addr
)) == -1 ||
267 listen(tcpfd
, 5) == -1 ||
268 bind(fd
, (struct sockaddr
*)&addr
, sa_len(&addr
)) == -1)
277 l
= safe_malloc(sizeof(struct listener
));
280 l
->family
= AF_INET6
;
288 struct listener
*create_wildcard_listeners(int port
)
290 #if !(defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
293 union mysockaddr addr
;
295 struct listener
*l
, *l6
= NULL
;
299 addr
.in
.sin_family
= AF_INET
;
300 addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
301 addr
.in
.sin_port
= htons(port
);
302 #ifdef HAVE_SOCKADDR_SA_LEN
303 addr
.in
.sin_len
= sizeof(struct sockaddr_in
);
306 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
309 if ((tcpfd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
315 if (setsockopt(tcpfd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
)) == -1 ||
316 bind(tcpfd
, (struct sockaddr
*)&addr
, sa_len(&addr
)) == -1 ||
317 listen(tcpfd
, 5) == -1 ||
318 (flags
= fcntl(tcpfd
, F_GETFL
, 0)) == -1 ||
319 fcntl(tcpfd
, F_SETFL
, flags
| O_NONBLOCK
) == -1 ||
321 !create_ipv6_listener(&l6
, port
) ||
323 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
)) == -1 ||
324 #if defined(IP_PKTINFO)
325 setsockopt(fd
, SOL_IP
, IP_PKTINFO
, &opt
, sizeof(opt
)) == -1 ||
326 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
327 setsockopt(fd
, IPPROTO_IP
, IP_RECVDSTADDR
, &opt
, sizeof(opt
)) == -1 ||
328 setsockopt(fd
, IPPROTO_IP
, IP_RECVIF
, &opt
, sizeof(opt
)) == -1 ||
330 bind(fd
, (struct sockaddr
*)&addr
, sa_len(&addr
)) == -1)
337 l
= safe_malloc(sizeof(struct listener
));
348 struct listener
*create_bound_listeners(struct irec
*interfaces
, int port
)
351 struct listener
*listeners
= NULL
;
353 int flags
= port
, opt
= 1;
355 /* Create bound listeners only for IPv4, IPv6 always binds the wildcard */
358 if (!create_ipv6_listener(&listeners
, port
))
359 die("failed to to create listening socket: %s", NULL
);
362 for (iface
= interfaces
;iface
; iface
= iface
->next
)
363 if (iface
->addr
.sa
.sa_family
== AF_INET
)
365 struct listener
*new = safe_malloc(sizeof(struct listener
));
366 new->family
= iface
->addr
.sa
.sa_family
;
367 new->next
= listeners
;
369 if ((new->tcpfd
= socket(iface
->addr
.sa
.sa_family
, SOCK_STREAM
, 0)) == -1 ||
370 (new->fd
= socket(iface
->addr
.sa
.sa_family
, SOCK_DGRAM
, 0)) == -1 ||
371 setsockopt(new->fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
)) == -1 ||
372 setsockopt(new->tcpfd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
)) == -1 ||
373 /* See Stevens 16.6 */
374 (flags
= fcntl(new->tcpfd
, F_GETFL
, 0)) == -1 ||
375 fcntl(new->tcpfd
, F_SETFL
, flags
| O_NONBLOCK
) == -1 ||
376 bind(new->tcpfd
, &iface
->addr
.sa
, sa_len(&iface
->addr
)) == -1 ||
377 bind(new->fd
, &iface
->addr
.sa
, sa_len(&iface
->addr
)) == -1 ||
378 listen(new->tcpfd
, 5) == -1)
379 die("failed to to create listening socket: %s", NULL
);
385 struct serverfd
*allocate_sfd(union mysockaddr
*addr
, struct serverfd
**sfds
)
387 struct serverfd
*sfd
;
389 /* may have a suitable one already */
390 for (sfd
= *sfds
; sfd
; sfd
= sfd
->next
)
391 if (sockaddr_isequal(&sfd
->source_addr
, addr
))
394 /* need to make a new one. */
395 errno
= ENOMEM
; /* in case malloc fails. */
396 if (!(sfd
= malloc(sizeof(struct serverfd
))))
399 if ((sfd
->fd
= socket(addr
->sa
.sa_family
, SOCK_DGRAM
, 0)) == -1)
405 if (bind(sfd
->fd
, (struct sockaddr
*)addr
, sa_len(addr
)) == -1)
407 int errsave
= errno
; /* save error from bind. */
414 sfd
->source_addr
= *addr
;
421 void check_servers(struct daemon
*daemon
, struct irec
*interfaces
)
423 char addrbuff
[ADDRSTRLEN
];
425 struct server
*new, *tmp
, *ret
= NULL
;
428 /* forward table rules reference servers, so have to blow them away */
431 daemon
->last_server
= NULL
;
433 for (new = daemon
->servers
; new; new = tmp
)
437 if (!(new->flags
& (SERV_LITERAL_ADDRESS
| SERV_NO_ADDR
)))
440 if (new->addr
.sa
.sa_family
== AF_INET
)
442 inet_ntop(AF_INET
, &new->addr
.in
.sin_addr
, addrbuff
, ADDRSTRLEN
);
443 port
= ntohs(new->addr
.in
.sin_port
);
445 else if (new->addr
.sa
.sa_family
== AF_INET6
)
447 inet_ntop(AF_INET6
, &new->addr
.in6
.sin6_addr
, addrbuff
, ADDRSTRLEN
);
448 port
= ntohs(new->addr
.in6
.sin6_port
);
451 strcpy(addrbuff
, inet_ntoa(new->addr
.in
.sin_addr
));
452 port
= ntohs(new->addr
.in
.sin_port
);
454 for (iface
= interfaces
; iface
; iface
= iface
->next
)
455 if (sockaddr_isequal(&new->addr
, &iface
->addr
))
459 syslog(LOG_WARNING
, "ignoring nameserver %s - local interface", addrbuff
);
464 /* Do we need a socket set? */
465 if (!new->sfd
&& !(new->sfd
= allocate_sfd(&new->source_addr
, &daemon
->sfds
)))
468 "ignoring nameserver %s - cannot make/bind socket: %m", addrbuff
);
474 /* reverse order - gets it right. */
478 if (new->flags
& (SERV_HAS_DOMAIN
| SERV_FOR_NODOTS
))
481 if (new->flags
& SERV_HAS_DOMAIN
)
482 s1
= "domain", s2
= new->domain
;
484 s1
= "unqualified", s2
= "domains";
486 if (new->flags
& SERV_NO_ADDR
)
487 syslog(LOG_INFO
, "using local addresses only for %s %s", s1
, s2
);
488 else if (!(new->flags
& SERV_LITERAL_ADDRESS
))
489 syslog(LOG_INFO
, "using nameserver %s#%d for %s %s", addrbuff
, port
, s1
, s2
);
492 syslog(LOG_INFO
, "using nameserver %s#%d", addrbuff
, port
);
495 daemon
->servers
= ret
;
498 void reload_servers(char *fname
, struct daemon
*daemon
)
502 struct server
*old_servers
= NULL
;
503 struct server
*new_servers
= NULL
;
504 struct server
*serv
= daemon
->servers
;
506 /* move old servers to free list - we can reuse the memory
507 and not risk malloc if there are the same or fewer new servers.
508 Servers which were specced on the command line go to the new list. */
511 struct server
*tmp
= serv
->next
;
512 if (serv
->flags
& SERV_FROM_RESOLV
)
514 serv
->next
= old_servers
;
519 serv
->next
= new_servers
;
525 /* buff happens to be NAXDNAME long... */
526 f
= fopen(fname
, "r");
529 syslog(LOG_ERR
, "failed to read %s: %m", fname
);
533 syslog(LOG_INFO
, "reading %s", fname
);
534 while ((line
= fgets(daemon
->namebuff
, MAXDNAME
, f
)))
536 union mysockaddr addr
, source_addr
;
537 char *token
= strtok(line
, " \t\n\r");
540 if (!token
|| strcmp(token
, "nameserver") != 0)
542 if (!(token
= strtok(NULL
, " \t\n\r")))
546 if (inet_pton(AF_INET
, token
, &addr
.in
.sin_addr
))
548 if ((addr
.in
.sin_addr
.s_addr
= inet_addr(token
)) != (in_addr_t
) -1)
551 #ifdef HAVE_SOCKADDR_SA_LEN
552 source_addr
.in
.sin_len
= addr
.in
.sin_len
= sizeof(struct sockaddr_in
);
554 source_addr
.in
.sin_family
= addr
.in
.sin_family
= AF_INET
;
555 addr
.in
.sin_port
= htons(NAMESERVER_PORT
);
556 source_addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
557 source_addr
.in
.sin_port
= htons(daemon
->query_port
);
560 else if (inet_pton(AF_INET6
, token
, &addr
.in6
.sin6_addr
))
562 #ifdef HAVE_SOCKADDR_SA_LEN
563 source_addr
.in6
.sin6_len
= addr
.in6
.sin6_len
= sizeof(struct sockaddr_in6
);
565 source_addr
.in6
.sin6_family
= addr
.in6
.sin6_family
= AF_INET6
;
566 addr
.in6
.sin6_port
= htons(NAMESERVER_PORT
);
567 source_addr
.in6
.sin6_flowinfo
= addr
.in6
.sin6_flowinfo
= htonl(0);
568 source_addr
.in6
.sin6_addr
= in6addr_any
;
569 source_addr
.in6
.sin6_port
= htons(daemon
->query_port
);
578 old_servers
= old_servers
->next
;
580 else if (!(serv
= malloc(sizeof (struct server
))))
583 /* this list is reverse ordered:
584 it gets reversed again in check_servers */
585 serv
->next
= new_servers
;
588 serv
->source_addr
= source_addr
;
591 serv
->flags
= SERV_FROM_RESOLV
;
597 /* Free any memory not used. */
600 struct server
*tmp
= old_servers
->next
;
605 daemon
->servers
= new_servers
;