Initial import
[ratbox-ambernet.git] / src / adns.c
blob3cf44ca22623bd3e0e39423b8218629764e7cc53
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * adns.c: Interfaces to the adns DNS library.
5 * Copyright (C) 2001-2002 Aaron Sethman <androsyn@ratbox.org>
6 * Copyright (C) 2001-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
24 * $Id: adns.c 22395 2006-05-07 10:23:50Z leeh $
27 #include "stdinc.h"
28 #include "setup.h"
30 #include "res.h"
31 #include "send.h"
32 #include "s_conf.h"
33 #include "commio.h"
34 #include "s_log.h"
35 #include "event.h"
36 #include "client.h"
37 #include "ircd_defs.h"
38 #include "numeric.h"
39 #include "../adns/internal.h"
41 adns_state dns_state;
43 /* void report_adns_servers(struct Client *source_p)
44 * Input: A client to send a list of DNS servers to.
45 * Output: None
46 * Side effects: Sends a list of DNS servers to source_p
48 void
49 report_adns_servers(struct Client *source_p)
51 int x;
52 char buf[16]; /* XXX: adns only deals with ipv4 dns servers so this is okay */
53 for (x = 0; x < dns_state->nservers; x++)
55 inetntop(AF_INET, &dns_state->servers[x].addr.s_addr, buf, 16);
56 sendto_one_numeric(source_p, RPL_STATSDEBUG,
57 "A %s", buf);
61 /* void delete_adns_queries(struct DNSQuery *q)
62 * Input: A pointer to the applicable DNSQuery structure.
63 * Output: None
64 * Side effects: Cancels a DNS query.
66 void
67 delete_adns_queries(struct DNSQuery *q)
69 if(q != NULL && q->query != NULL)
71 adns_cancel(q->query);
72 q->callback = NULL;
74 dns_select();
77 /* void restart_resolver(void)
78 * Input: None
79 * Output: None
80 * Side effects: Tears down any old ADNS sockets..reloads the conf
82 void
83 restart_resolver(void)
85 adns__rereadconfig(dns_state);
88 /* void init_resolver(void)
89 * Input: None
90 * Output: None
91 * Side effects: Reads the ADNS configuration and sets up the ADNS server
92 * polling and query timeouts.
94 void
95 init_resolver(void)
97 int r;
99 r = adns_init(&dns_state, adns_if_noautosys, 0);
101 if(dns_state == NULL)
103 ilog(L_MAIN, "Error opening /etc/resolv.conf: %s; r = %d", strerror(errno), r);
104 exit(76);
107 eventAddIsh("timeout_adns", timeout_adns, NULL, 2);
108 dns_select();
111 /* void timeout_adns(void *ptr);
112 * Input: None used.
113 * Output: None
114 * Side effects: Cancel any old(expired) DNS queries.
115 * Note: Called by the event code.
117 void
118 timeout_adns(void *ptr)
120 adns_processtimeouts(dns_state, &SystemTime);
123 /* void dns_writeable(int fd, void *ptr)
124 * Input: An fd which has become writeable, ptr not used.
125 * Output: None.
126 * Side effects: Write any queued buffers out.
127 * Note: Called by the fd system.
129 void
130 dns_writeable(int fd, void *ptr)
132 adns_processwriteable(dns_state, fd, &SystemTime);
133 dns_do_callbacks();
134 dns_select();
138 /* void dns_do_callbacks(void)
139 * Input: None.
140 * Output: None.
141 * Side effects: Call all the callbacks(into the ircd core) for the
142 * results of a DNS resolution.
144 void
145 dns_do_callbacks(void)
147 adns_query q, r;
148 adns_answer *answer;
149 void *xr = &r;
150 struct DNSQuery *query;
151 void *xq = &query;
152 int failure = 0;
153 adns_forallqueries_begin(dns_state);
155 while ((q = adns_forallqueries_next(dns_state, xr)) != NULL)
157 switch (adns_check(dns_state, &q, &answer, xq))
159 case 0:
160 /* Looks like we got a winner */
161 assert(query->callback != NULL);
162 if(query->callback != NULL)
164 query->query = NULL;
165 query->callback(query->ptr, answer);
167 break;
169 case EAGAIN:
170 /* Go into the queue again */
171 continue;
173 default:
174 assert(query->callback != NULL);
175 if(query->callback != NULL)
177 /* Awww we failed, what a shame */
178 query->query = NULL;
179 query->callback(query->ptr, NULL);
181 if(answer != NULL && answer->status == adns_s_systemfail)
182 failure = 1;
184 break;
187 if(failure == 1)
189 sendto_realops_flags(UMODE_ALL, L_ALL, "adns got a global system failure..attempting to restart resolver");
190 init_resolver();
194 /* void dns_readable(int fd, void *ptr)
195 * Input: An fd which has become readable, ptr not used.
196 * Output: None.
197 * Side effects: Read DNS responses from DNS servers.
198 * Note: Called by the fd system.
200 void
201 dns_readable(int fd, void *ptr)
203 adns_processreadable(dns_state, fd, &SystemTime);
204 dns_do_callbacks();
205 dns_select();
208 /* void dns_select(void)
209 * Input: None.
210 * Output: None
211 * Side effects: Re-register ADNS fds with the fd system. Also calls the
212 * callbacks into core ircd.
214 void
215 dns_select(void)
217 struct adns_pollfd pollfds[MAXFD_POLL];
218 int npollfds, i, fd;
219 adns__consistency(dns_state, 0, cc_entex);
220 npollfds = adns__pollfds(dns_state, pollfds);
221 for (i = 0; i < npollfds; i++)
223 fd = pollfds[i].fd;
224 if(pollfds[i].events & ADNS_POLLIN)
225 comm_setselect(fd, FDLIST_SERVER, COMM_SELECT_READ, dns_readable, NULL);
226 if(pollfds[i].events & ADNS_POLLOUT)
227 comm_setselect(fd, FDLIST_SERVICE, COMM_SELECT_WRITE,
228 dns_writeable, NULL);
232 /* int adns_gethost(const char *name, int aftype, struct DNSQuery *req);
233 * Input: A name, an address family, a DNSQuery structure.
234 * Output: None
235 * Side effects: Sets up a query structure and sends off a DNS query to
236 * the DNS server to resolve an "A"(address) entry by name.
239 adns_gethost(const char *name, int aftype, struct DNSQuery *req)
241 int result;
242 assert(dns_state->nservers > 0);
243 #ifdef IPV6
244 if(aftype == AF_INET6)
245 result = adns_submit(dns_state, name, adns_r_addr6, adns_qf_owner, req, &req->query);
246 else
247 #endif
248 result = adns_submit(dns_state, name, adns_r_addr, adns_qf_owner, req, &req->query);
249 dns_select();
250 return result;
253 /* int adns_getaddr(struct irc_inaddr *addr, int aftype,
254 * struct DNSQuery *req, int arpa_type);
255 * Input: An address, an address family, a DNSQuery structure.
256 * Output: None
257 * Side effects: Sets up a query entry and sends it to the DNS server to
258 * resolve an IP address to a domain name.
261 adns_getaddr(struct sockaddr *addr, int aftype, struct DNSQuery *req)
263 int result;
264 int flags = adns_r_ptr;
265 assert(dns_state->nservers > 0);
266 #ifdef IPV6
267 if(addr->sa_family == AF_INET6)
268 flags = adns_r_ptr_ip6;
269 #endif
270 result = adns_submit_reverse(dns_state,
271 (struct sockaddr *) addr,
272 flags,
273 adns_qf_owner | adns_qf_cname_loose |
274 adns_qf_quoteok_anshost, req, &req->query);
275 dns_select();
276 return result;