blob: 2fc2db2a2da2953f0b3e0307a6adaa54b769a916 [file] [log] [blame]
Simon Kelley824af852008-02-12 20:43:05 +00001/* dnsmasq is Copyright (c) 2000-2007 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 Kelley824af852008-02-12 20:43:05 +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 Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley5aabfc72007-08-29 11:24:47 +010019int iface_check(int family, struct all_addr *addr,
Simon Kelley832af0b2007-01-21 20:01:28 +000020 struct ifreq *ifr, int *indexp)
Simon Kelley9e4abcb2004-01-22 19:47:41 +000021{
Simon Kelley9e4abcb2004-01-22 19:47:41 +000022 struct iname *tmp;
Simon Kelley309331f2006-04-22 15:05:01 +010023 int ret = 1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010024
Simon Kelley309331f2006-04-22 15:05:01 +010025 /* Note: have to check all and not bail out early, so that we set the
26 "used" flags. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010027
Simon Kelley832af0b2007-01-21 20:01:28 +000028 if (indexp)
29 {
Simon Kelley9e038942008-05-30 20:06:34 +010030#ifdef HAVE_BSD_BRIDGE
31 /* One form of bridging on BSD has the property that packets
Simon Kelley832af0b2007-01-21 20:01:28 +000032 can be recieved on bridge interfaces which do not have an IP address.
33 We allow these to be treated as aliases of another interface which does have
34 an IP address with --dhcp-bridge=interface,alias,alias */
35 struct dhcp_bridge *bridge, *alias;
36 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
37 {
38 for (alias = bridge->alias; alias; alias = alias->next)
39 if (strncmp(ifr->ifr_name, alias->iface, IF_NAMESIZE) == 0)
40 {
41 int newindex;
42
43 if (!(newindex = if_nametoindex(bridge->iface)))
44 {
Simon Kelleyf2621c72007-04-29 19:47:21 +010045 my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr->ifr_name);
Simon Kelley832af0b2007-01-21 20:01:28 +000046 return 0;
47 }
48 else
49 {
50 *indexp = newindex;
51 strncpy(ifr->ifr_name, bridge->iface, IF_NAMESIZE);
52 break;
53 }
54 }
55 if (alias)
56 break;
57 }
58#endif
59 }
60
61 if (daemon->if_names || (addr && daemon->if_addrs))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010062 {
Simon Kelley309331f2006-04-22 15:05:01 +010063 ret = 0;
64
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010065 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley832af0b2007-01-21 20:01:28 +000066 if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
Simon Kelley309331f2006-04-22 15:05:01 +010067 ret = tmp->used = 1;
68
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010069 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
Simon Kelley832af0b2007-01-21 20:01:28 +000070 if (addr && tmp->addr.sa.sa_family == family)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010071 {
72 if (family == AF_INET &&
73 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelley309331f2006-04-22 15:05:01 +010074 ret = tmp->used = 1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010075#ifdef HAVE_IPV6
76 else if (family == AF_INET6 &&
77 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
78 &addr->addr.addr6))
Simon Kelley309331f2006-04-22 15:05:01 +010079 ret = tmp->used = 1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010080#endif
81 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010082 }
83
Simon Kelley309331f2006-04-22 15:05:01 +010084 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
Simon Kelley832af0b2007-01-21 20:01:28 +000085 if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
Simon Kelley309331f2006-04-22 15:05:01 +010086 ret = 0;
87
88 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010089}
90
Simon Kelley5aabfc72007-08-29 11:24:47 +010091static int iface_allowed(struct irec **irecp, int if_index,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010092 union mysockaddr *addr, struct in_addr netmask)
93{
94 struct irec *iface;
95 int fd;
96 struct ifreq ifr;
Simon Kelley832af0b2007-01-21 20:01:28 +000097 int dhcp_ok = 1;
98 struct iname *tmp;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010099
100 /* check whether the interface IP has been added already
101 we call this routine multiple times. */
102 for (iface = *irecp; iface; iface = iface->next)
103 if (sockaddr_isequal(&iface->addr, addr))
104 return 1;
105
106#ifdef HAVE_LINUX_NETWORK
107 ifr.ifr_ifindex = if_index;
108#endif
109
110 if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
111#ifdef HAVE_LINUX_NETWORK
112 ioctl(fd, SIOCGIFNAME, &ifr) == -1 ||
113#else
114 !if_indextoname(if_index, ifr.ifr_name) ||
115#endif
116 ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
117 {
118 if (fd != -1)
119 {
120 int errsave = errno;
121 close(fd);
122 errno = errsave;
123 }
124 return 0;
125 }
126
127 close(fd);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000128
Simon Kelley59353a62004-11-21 19:34:28 +0000129 /* If we are restricting the set of interfaces to use, make
130 sure that loopback interfaces are in that set. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100131 if (daemon->if_names && (ifr.ifr_flags & IFF_LOOPBACK))
Simon Kelley59353a62004-11-21 19:34:28 +0000132 {
133 struct iname *lo;
134 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100135 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley59353a62004-11-21 19:34:28 +0000136 {
137 lo->isloop = 1;
138 break;
139 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100140
Simon Kelley5aabfc72007-08-29 11:24:47 +0100141 if (!lo &&
142 (lo = whine_malloc(sizeof(struct iname))) &&
143 (lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley59353a62004-11-21 19:34:28 +0000144 {
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100145 strcpy(lo->name, ifr.ifr_name);
Simon Kelley59353a62004-11-21 19:34:28 +0000146 lo->isloop = lo->used = 1;
147 lo->next = daemon->if_names;
148 daemon->if_names = lo;
149 }
150 }
151
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100152 if (addr->sa.sa_family == AF_INET &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100153 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, &ifr, NULL))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100154 return 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000155
156 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
157 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
158 dhcp_ok = 0;
159
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100160#ifdef HAVE_IPV6
161 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100162 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, &ifr, NULL))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100163 return 1;
164#endif
165
166 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100167 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100168 {
169 iface->addr = *addr;
170 iface->netmask = netmask;
Simon Kelley832af0b2007-01-21 20:01:28 +0000171 iface->dhcp_ok = dhcp_ok;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100172 iface->next = *irecp;
Simon Kelley832af0b2007-01-21 20:01:28 +0000173 *irecp = iface;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100174 return 1;
Simon Kelley44a2a312004-03-10 20:04:35 +0000175 }
176
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100177 errno = ENOMEM;
178 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000179}
180
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100181#ifdef HAVE_IPV6
Simon Kelley5aabfc72007-08-29 11:24:47 +0100182static int iface_allowed_v6(struct in6_addr *local,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100183 int scope, int if_index, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000184{
Simon Kelley59353a62004-11-21 19:34:28 +0000185 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100186 struct in_addr netmask; /* dummy */
Simon Kelley3d8df262005-08-29 12:19:27 +0100187
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100188 netmask.s_addr = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +0000189
Simon Kelley849a8352006-06-09 21:02:31 +0100190 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000191#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100192 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000193#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100194 addr.in6.sin6_family = AF_INET6;
195 addr.in6.sin6_addr = *local;
196 addr.in6.sin6_port = htons(daemon->port);
197 addr.in6.sin6_scope_id = scope;
Simon Kelley849a8352006-06-09 21:02:31 +0100198
Simon Kelley5aabfc72007-08-29 11:24:47 +0100199 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100200}
201#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000202
Simon Kelley5aabfc72007-08-29 11:24:47 +0100203static int iface_allowed_v4(struct in_addr local, int if_index,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100204 struct in_addr netmask, struct in_addr broadcast, void *vparam)
205{
206 union mysockaddr addr;
Simon Kelley849a8352006-06-09 21:02:31 +0100207
208 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000209#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100210 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000211#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100212 addr.in.sin_family = AF_INET;
213 addr.in.sin_addr = broadcast; /* warning */
214 addr.in.sin_addr = local;
215 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000216
Simon Kelley5aabfc72007-08-29 11:24:47 +0100217 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100218}
219
220
Simon Kelley5aabfc72007-08-29 11:24:47 +0100221int enumerate_interfaces(void)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100222{
223#ifdef HAVE_IPV6
Simon Kelley5aabfc72007-08-29 11:24:47 +0100224 return iface_enumerate(&daemon->interfaces, iface_allowed_v4, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100225#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100226 return iface_enumerate(&daemon->interfaces, iface_allowed_v4, NULL);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100227#endif
Simon Kelley44a2a312004-03-10 20:04:35 +0000228}
229
Simon Kelley5aabfc72007-08-29 11:24:47 +0100230/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100231int fix_fd(int fd)
232{
233 int flags;
234
235 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100236 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100237 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100238
Simon Kelley7cebd202006-05-06 14:13:33 +0100239 return 1;
240}
241
Simon Kelley309331f2006-04-22 15:05:01 +0100242#if defined(HAVE_IPV6)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100243static int create_ipv6_listener(struct listener **link, int port)
Simon Kelley44a2a312004-03-10 20:04:35 +0000244{
245 union mysockaddr addr;
Simon Kelley7cebd202006-05-06 14:13:33 +0100246 int tcpfd, fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100247 struct listener *l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000248 int opt = 1;
Simon Kelley44a2a312004-03-10 20:04:35 +0000249
Simon Kelley849a8352006-06-09 21:02:31 +0100250 memset(&addr, 0, sizeof(addr));
Simon Kelley44a2a312004-03-10 20:04:35 +0000251 addr.in6.sin6_family = AF_INET6;
252 addr.in6.sin6_addr = in6addr_any;
253 addr.in6.sin6_port = htons(port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000254#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100255 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley44a2a312004-03-10 20:04:35 +0000256#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100257
258 /* No error of the kernel doesn't support IPv6 */
Simon Kelley44a2a312004-03-10 20:04:35 +0000259 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100260 return (errno == EPROTONOSUPPORT ||
261 errno == EAFNOSUPPORT ||
262 errno == EINVAL);
263
264 if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
Simon Kelley26d0dba2006-04-23 20:00:42 +0100265 return 0;
266
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100267 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
268 setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
269 setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
270 setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
Simon Kelley7cebd202006-05-06 14:13:33 +0100271 !fix_fd(fd) ||
272 !fix_fd(tcpfd) ||
Simon Kelleydfa666f2004-08-02 18:27:27 +0100273#ifdef IPV6_RECVPKTINFO
274 setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
275#else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100276 setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
Simon Kelleydfa666f2004-08-02 18:27:27 +0100277#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100278 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
279 listen(tcpfd, 5) == -1 ||
280 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
Simon Kelley26d0dba2006-04-23 20:00:42 +0100281 return 0;
282
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100283 l = safe_malloc(sizeof(struct listener));
284 l->fd = fd;
285 l->tcpfd = tcpfd;
Simon Kelley832af0b2007-01-21 20:01:28 +0000286 l->tftpfd = -1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100287 l->family = AF_INET6;
288 l->next = NULL;
289 *link = l;
290
291 return 1;
292}
Simon Kelley44a2a312004-03-10 20:04:35 +0000293#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100294
Simon Kelley5aabfc72007-08-29 11:24:47 +0100295struct listener *create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100296{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100297 union mysockaddr addr;
298 int opt = 1;
299 struct listener *l, *l6 = NULL;
Simon Kelley824af852008-02-12 20:43:05 +0000300 int tcpfd = -1, fd = -1, tftpfd = -1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100301
Simon Kelley849a8352006-06-09 21:02:31 +0100302 memset(&addr, 0, sizeof(addr));
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100303 addr.in.sin_family = AF_INET;
304 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100305 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100306#ifdef HAVE_SOCKADDR_SA_LEN
307 addr.in.sin_len = sizeof(struct sockaddr_in);
308#endif
309
Simon Kelley824af852008-02-12 20:43:05 +0000310 if (daemon->port != 0)
311 {
312
313 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
314 (tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
315 return NULL;
316
317 if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
318 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
319 listen(tcpfd, 5) == -1 ||
320 !fix_fd(tcpfd) ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100321#ifdef HAVE_IPV6
Simon Kelley824af852008-02-12 20:43:05 +0000322 !create_ipv6_listener(&l6, daemon->port) ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100323#endif
Simon Kelley824af852008-02-12 20:43:05 +0000324 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
325 !fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100326#if defined(HAVE_LINUX_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000327 setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100328#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
Simon Kelley824af852008-02-12 20:43:05 +0000329 setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
330 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100331#endif
Simon Kelley824af852008-02-12 20:43:05 +0000332 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
333 return NULL;
334 }
335
Simon Kelley832af0b2007-01-21 20:01:28 +0000336#ifdef HAVE_TFTP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100337 if (daemon->options & OPT_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000338 {
339 addr.in.sin_port = htons(TFTP_PORT);
340 if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
341 return NULL;
Simon Kelley26d0dba2006-04-23 20:00:42 +0100342
Simon Kelley5aabfc72007-08-29 11:24:47 +0100343 if (!fix_fd(tftpfd) ||
Simon Kelley832af0b2007-01-21 20:01:28 +0000344#if defined(HAVE_LINUX_NETWORK)
345 setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
346#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
347 setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
348 setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
349#endif
350 bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
351 return NULL;
352 }
353#endif
354
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100355 l = safe_malloc(sizeof(struct listener));
356 l->family = AF_INET;
357 l->fd = fd;
358 l->tcpfd = tcpfd;
Simon Kelley832af0b2007-01-21 20:01:28 +0000359 l->tftpfd = tftpfd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100360 l->next = l6;
361
362 return l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000363}
364
Simon Kelley5aabfc72007-08-29 11:24:47 +0100365struct listener *create_bound_listeners(void)
Simon Kelley44a2a312004-03-10 20:04:35 +0000366{
Simon Kelley44a2a312004-03-10 20:04:35 +0000367 struct listener *listeners = NULL;
368 struct irec *iface;
Simon Kelley7cebd202006-05-06 14:13:33 +0100369 int opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100370
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100371 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley26128d22004-11-14 16:43:54 +0000372 {
373 struct listener *new = safe_malloc(sizeof(struct listener));
374 new->family = iface->addr.sa.sa_family;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000375 new->iface = iface;
Simon Kelley26128d22004-11-14 16:43:54 +0000376 new->next = listeners;
Simon Kelley832af0b2007-01-21 20:01:28 +0000377 new->tftpfd = -1;
Simon Kelley824af852008-02-12 20:43:05 +0000378 new->tcpfd = -1;
379 new->fd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000380
Simon Kelley824af852008-02-12 20:43:05 +0000381 if (daemon->port != 0)
Simon Kelley26128d22004-11-14 16:43:54 +0000382 {
Simon Kelley824af852008-02-12 20:43:05 +0000383 if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
384 (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
385 setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
386 setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
387 !fix_fd(new->tcpfd) ||
388 !fix_fd(new->fd))
389 die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
390
Simon Kelley59353a62004-11-21 19:34:28 +0000391#ifdef HAVE_IPV6
Simon Kelley824af852008-02-12 20:43:05 +0000392 if (iface->addr.sa.sa_family == AF_INET6)
Simon Kelley59353a62004-11-21 19:34:28 +0000393 {
Simon Kelley824af852008-02-12 20:43:05 +0000394 if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
395 setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
396 die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);
Simon Kelley59353a62004-11-21 19:34:28 +0000397 }
Simon Kelley59353a62004-11-21 19:34:28 +0000398#endif
Simon Kelley824af852008-02-12 20:43:05 +0000399
400 if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
401 bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
Simon Kelley3d8df262005-08-29 12:19:27 +0100402 {
Simon Kelley824af852008-02-12 20:43:05 +0000403#ifdef HAVE_IPV6
404 if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL))
405 {
406 close(new->tcpfd);
407 close(new->fd);
408 free(new);
409 new = NULL;
410 }
411 else
412#endif
413 {
414 prettyprint_addr(&iface->addr, daemon->namebuff);
415 die(_("failed to bind listening socket for %s: %s"),
416 daemon->namebuff, EC_BADNET);
417 }
Simon Kelley3d8df262005-08-29 12:19:27 +0100418 }
Simon Kelley824af852008-02-12 20:43:05 +0000419 else if (listen(new->tcpfd, 5) == -1)
420 die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
Simon Kelley59353a62004-11-21 19:34:28 +0000421 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000422
Simon Kelley824af852008-02-12 20:43:05 +0000423#ifdef HAVE_TFTP
Simon Kelley832af0b2007-01-21 20:01:28 +0000424 if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
425 {
426 short save = iface->addr.in.sin_port;
427 iface->addr.in.sin_port = htons(TFTP_PORT);
428 if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
429 setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
430 !fix_fd(new->tftpfd) ||
431 bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
Simon Kelley5aabfc72007-08-29 11:24:47 +0100432 die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
Simon Kelley832af0b2007-01-21 20:01:28 +0000433 iface->addr.in.sin_port = save;
434 }
Simon Kelley824af852008-02-12 20:43:05 +0000435#endif
436
437 if (new)
438 listeners = new;
Simon Kelley26128d22004-11-14 16:43:54 +0000439 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000440
Simon Kelley44a2a312004-03-10 20:04:35 +0000441 return listeners;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000442}
443
Simon Kelley1a6bca82008-07-11 11:11:42 +0100444
445/* return a UDP socket bound to a random port, have to coper with straying into
446 occupied port nos and reserved ones. */
447int random_sock(int family)
448{
449 int fd;
450
451 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
452 {
Simon Kelley3927da42008-07-20 15:10:39 +0100453 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100454 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
455 int i, tries = 3 * ports_avail;
456
457 if (tries > 100)
458 tries = 100;
Simon Kelley3927da42008-07-20 15:10:39 +0100459
Simon Kelley1a6bca82008-07-11 11:11:42 +0100460 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +0100461 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100462
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100463 /* don't loop forever if all ports in use. */
464
Simon Kelley1a6bca82008-07-11 11:11:42 +0100465 if (fix_fd(fd))
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100466 for (i = tries; i != 0; i--)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100467 {
468 unsigned short port = rand16();
469
Simon Kelley3927da42008-07-20 15:10:39 +0100470 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100471 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100472
473 if (family == AF_INET)
474 {
475 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +0100476 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100477#ifdef HAVE_SOCKADDR_SA_LEN
478 addr.in.sin_len = sizeof(struct sockaddr_in);
479#endif
480 }
481#ifdef HAVE_IPV6
482 else
483 {
484 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +0100485 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100486#ifdef HAVE_SOCKADDR_SA_LEN
487 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
488#endif
489 }
490#endif
491
492 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
493 return fd;
494
495 if (errno != EADDRINUSE && errno != EACCES)
496 break;
497 }
498
499 close(fd);
500 }
501
502 return -1;
503}
504
505
Simon Kelley824af852008-02-12 20:43:05 +0000506int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
507{
508 union mysockaddr addr_copy = *addr;
509
510 /* cannot set source _port_ for TCP connections. */
511 if (is_tcp)
512 {
513 if (addr_copy.sa.sa_family == AF_INET)
514 addr_copy.in.sin_port = 0;
515#ifdef HAVE_IPV6
516 else
517 addr_copy.in6.sin6_port = 0;
518#endif
519 }
520
521 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
522 return 0;
523
524#if defined(SO_BINDTODEVICE)
525 if (strlen(intname) != 0 &&
526 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, sizeof(intname)) == -1)
527 return 0;
528#endif
529
530 return 1;
531}
532
533static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000534{
535 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +0000536 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100537
Simon Kelley1a6bca82008-07-11 11:11:42 +0100538 /* when using random ports, servers which would otherwise use
539 the INADDR_ANY/port0 socket have sfd set to NULL */
540 if (!daemon->osport)
541 {
542 errno = 0;
543
544 if (addr->sa.sa_family == AF_INET &&
545 addr->in.sin_addr.s_addr == INADDR_ANY &&
546 addr->in.sin_port == htons(0))
547 return NULL;
548
549#ifdef HAVE_IPV6
550 if (addr->sa.sa_family == AF_INET6 &&
551 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
552 addr->in6.sin6_port == htons(0))
553 return NULL;
554#endif
555 }
556
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000557 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +0000558 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
559 if (sockaddr_isequal(&sfd->source_addr, addr) &&
560 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000561 return sfd;
562
563 /* need to make a new one. */
564 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100565 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000566 return NULL;
567
568 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
569 {
570 free(sfd);
571 return NULL;
572 }
573
Simon Kelley824af852008-02-12 20:43:05 +0000574 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
575 {
576 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000577 close(sfd->fd);
578 free(sfd);
579 errno = errsave;
580 return NULL;
581 }
Simon Kelley824af852008-02-12 20:43:05 +0000582
583 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000584 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +0000585 sfd->next = daemon->sfds;
586 daemon->sfds = sfd;
587 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000588}
589
Simon Kelley824af852008-02-12 20:43:05 +0000590/* create upstream sockets during startup, before root is dropped which may be needed
591 this allows query_port to be a low port and interface binding */
592void pre_allocate_sfds(void)
593{
594 struct server *srv;
595
596 if (daemon->query_port != 0)
597 {
598 union mysockaddr addr;
599 memset(&addr, 0, sizeof(addr));
600 addr.in.sin_family = AF_INET;
601 addr.in.sin_addr.s_addr = INADDR_ANY;
602 addr.in.sin_port = htons(daemon->query_port);
603#ifdef HAVE_SOCKADDR_SA_LEN
604 addr.in.sin_len = sizeof(struct sockaddr_in);
605#endif
606 allocate_sfd(&addr, "");
607#ifdef HAVE_IPV6
608 memset(&addr, 0, sizeof(addr));
609 addr.in6.sin6_family = AF_INET6;
610 addr.in6.sin6_addr = in6addr_any;
611 addr.in6.sin6_port = htons(daemon->query_port);
612#ifdef HAVE_SOCKADDR_SA_LEN
613 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
614#endif
615 allocate_sfd(&addr, "");
616#endif
617 }
618
619 for (srv = daemon->servers; srv; srv = srv->next)
620 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
621 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +0100622 errno != 0 &&
Simon Kelley824af852008-02-12 20:43:05 +0000623 (daemon->options & OPT_NOWILD))
624 {
625 prettyprint_addr(&srv->addr, daemon->namebuff);
626 if (strlen(srv->interface) != 0)
627 {
628 strcat(daemon->namebuff, " ");
629 strcat(daemon->namebuff, srv->interface);
630 }
631 die(_("failed to bind server socket for %s: %s"),
632 daemon->namebuff, EC_BADNET);
633 }
634}
635
636
Simon Kelley5aabfc72007-08-29 11:24:47 +0100637void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000638{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000639 struct irec *iface;
Simon Kelley3be34542004-09-11 19:12:13 +0100640 struct server *new, *tmp, *ret = NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000641 int port = 0;
642
Simon Kelley3be34542004-09-11 19:12:13 +0100643 for (new = daemon->servers; new; new = tmp)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000644 {
645 tmp = new->next;
646
647 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
648 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100649 port = prettyprint_addr(&new->addr, daemon->namebuff);
650
Simon Kelley16972692006-10-16 20:04:18 +0100651 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
652 if (new->addr.sa.sa_family == AF_INET &&
653 new->addr.in.sin_addr.s_addr == 0)
654 {
655 free(new);
656 continue;
657 }
658
Simon Kelley3d8df262005-08-29 12:19:27 +0100659 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000660 if (sockaddr_isequal(&new->addr, &iface->addr))
661 break;
662 if (iface)
663 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100664 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000665 free(new);
666 continue;
667 }
668
669 /* Do we need a socket set? */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100670 if (!new->sfd &&
671 !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
672 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000673 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100674 my_syslog(LOG_WARNING,
675 _("ignoring nameserver %s - cannot make/bind socket: %s"),
676 daemon->namebuff, strerror(errno));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000677 free(new);
678 continue;
679 }
680 }
681
682 /* reverse order - gets it right. */
683 new->next = ret;
684 ret = new;
685
686 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
687 {
688 char *s1, *s2;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100689 if (!(new->flags & SERV_HAS_DOMAIN))
690 s1 = _("unqualified"), s2 = _("names");
691 else if (strlen(new->domain) == 0)
692 s1 = _("default"), s2 = "";
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000693 else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100694 s1 = _("domain"), s2 = new->domain;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000695
696 if (new->flags & SERV_NO_ADDR)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100697 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000698 else if (!(new->flags & SERV_LITERAL_ADDRESS))
Simon Kelleyf2621c72007-04-29 19:47:21 +0100699 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000700 }
Simon Kelley824af852008-02-12 20:43:05 +0000701 else if (strlen(new->interface) != 0)
702 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000703 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100704 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000705 }
706
Simon Kelley3be34542004-09-11 19:12:13 +0100707 daemon->servers = ret;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000708}
Simon Kelley849a8352006-06-09 21:02:31 +0100709
710/* Return zero if no servers found, in that case we keep polling.
711 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100712int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000713{
714 FILE *f;
715 char *line;
716 struct server *old_servers = NULL;
717 struct server *new_servers = NULL;
Simon Kelley849a8352006-06-09 21:02:31 +0100718 struct server *serv;
719 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000720
Simon Kelley849a8352006-06-09 21:02:31 +0100721 /* buff happens to be MAXDNAME long... */
722 if (!(f = fopen(fname, "r")))
723 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100724 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +0100725 return 0;
726 }
727
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000728 /* move old servers to free list - we can reuse the memory
729 and not risk malloc if there are the same or fewer new servers.
730 Servers which were specced on the command line go to the new list. */
Simon Kelley849a8352006-06-09 21:02:31 +0100731 for (serv = daemon->servers; serv;)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000732 {
733 struct server *tmp = serv->next;
734 if (serv->flags & SERV_FROM_RESOLV)
735 {
736 serv->next = old_servers;
Simon Kelley849a8352006-06-09 21:02:31 +0100737 old_servers = serv;
738 /* forward table rules reference servers, so have to blow them away */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100739 server_gone(serv);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000740 }
741 else
742 {
743 serv->next = new_servers;
744 new_servers = serv;
745 }
746 serv = tmp;
747 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000748
Simon Kelley849a8352006-06-09 21:02:31 +0100749 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
750 {
751 union mysockaddr addr, source_addr;
752 char *token = strtok(line, " \t\n\r");
753
Simon Kelley5aabfc72007-08-29 11:24:47 +0100754 if (!token)
755 continue;
756 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +0100757 continue;
758 if (!(token = strtok(NULL, " \t\n\r")))
759 continue;
760
761 memset(&addr, 0, sizeof(addr));
762 memset(&source_addr, 0, sizeof(source_addr));
763
764 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
765 {
766#ifdef HAVE_SOCKADDR_SA_LEN
767 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
768#endif
769 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
770 addr.in.sin_port = htons(NAMESERVER_PORT);
771 source_addr.in.sin_addr.s_addr = INADDR_ANY;
772 source_addr.in.sin_port = htons(daemon->query_port);
773 }
774#ifdef HAVE_IPV6
775 else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
776 {
777#ifdef HAVE_SOCKADDR_SA_LEN
778 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
779#endif
780 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
781 addr.in6.sin6_port = htons(NAMESERVER_PORT);
782 source_addr.in6.sin6_addr = in6addr_any;
783 source_addr.in6.sin6_port = htons(daemon->query_port);
784 }
785#endif /* IPV6 */
786 else
787 continue;
788
789 if (old_servers)
790 {
791 serv = old_servers;
792 old_servers = old_servers->next;
793 }
Simon Kelley5aabfc72007-08-29 11:24:47 +0100794 else if (!(serv = whine_malloc(sizeof (struct server))))
Simon Kelley849a8352006-06-09 21:02:31 +0100795 continue;
796
797 /* this list is reverse ordered:
798 it gets reversed again in check_servers */
799 serv->next = new_servers;
800 new_servers = serv;
801 serv->addr = addr;
802 serv->source_addr = source_addr;
803 serv->domain = NULL;
Simon Kelley824af852008-02-12 20:43:05 +0000804 serv->interface[0] = 0;
Simon Kelley849a8352006-06-09 21:02:31 +0100805 serv->sfd = NULL;
806 serv->flags = SERV_FROM_RESOLV;
Simon Kelley824af852008-02-12 20:43:05 +0000807 serv->queries = serv->failed_queries = 0;
Simon Kelley849a8352006-06-09 21:02:31 +0100808 gotone = 1;
809 }
810
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000811 /* Free any memory not used. */
Simon Kelley849a8352006-06-09 21:02:31 +0100812 while (old_servers)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000813 {
814 struct server *tmp = old_servers->next;
815 free(old_servers);
816 old_servers = tmp;
817 }
818
Simon Kelley3be34542004-09-11 19:12:13 +0100819 daemon->servers = new_servers;
Simon Kelley849a8352006-06-09 21:02:31 +0100820 fclose(f);
821
822 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000823}
824
825
Simon Kelleyf2621c72007-04-29 19:47:21 +0100826/* Use an IPv4 listener socket for ioctling */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100827struct in_addr get_ifaddr(char *intr)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100828{
829 struct listener *l;
830 struct ifreq ifr;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000831
Simon Kelleyf2621c72007-04-29 19:47:21 +0100832 for (l = daemon->listeners; l && l->family != AF_INET; l = l->next);
833
834 strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
835 ifr.ifr_addr.sa_family = AF_INET;
836
837 if (!l || ioctl(l->fd, SIOCGIFADDR, &ifr) == -1)
838 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1;
839
840 return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
841}
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000842
843
844