2 * dns.c: An interface to the resolver module in authd
3 * (based somewhat on ircd-ratbox dns.c)
5 * Copyright (C) 2005 Aaron Sethman <androsyn@ratbox.org>
6 * Copyright (C) 2005-2012 ircd-ratbox development team
7 * Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
28 #include "ircd_defs.h"
40 #define DNS_IDTABLE_SIZE 0x2000
41 #define DNS_STATTABLE_SIZE 0x10
43 #define DNS_HOST_IPV4 ((char)'4')
44 #define DNS_HOST_IPV6 ((char)'6')
45 #define DNS_REVERSE_IPV4 ((char)'R')
46 #define DNS_REVERSE_IPV6 ((char)'S')
48 static void submit_dns(uint16_t uid
, char type
, const char *addr
);
49 static void submit_dns_stat(uint16_t uid
);
63 static struct dnsreq querytable
[DNS_IDTABLE_SIZE
];
64 static struct dnsstatreq stattable
[DNS_STATTABLE_SIZE
];
65 rb_dlink_list nameservers
;
71 static uint16_t id
= 1;
75 if(++loopcnt
> DNS_IDTABLE_SIZE
)
77 if(id
< DNS_IDTABLE_SIZE
- 1 || id
== 0)
81 if(querytable
[id
].callback
== NULL
)
88 assign_dns_stat_id(void)
90 static uint8_t id
= 1;
94 if(++loopcnt
> DNS_STATTABLE_SIZE
)
96 if(id
< DNS_STATTABLE_SIZE
- 1 || id
== 0)
100 if(stattable
[id
].callback
== NULL
)
107 handle_dns_failure(uint16_t xid
)
111 req
= &querytable
[xid
];
112 if(req
->callback
== NULL
)
115 req
->callback("FAILED", 0, 0, req
->data
);
116 req
->callback
= NULL
;
121 handle_dns_stat_failure(uint8_t xid
)
123 struct dnsstatreq
*req
;
124 const char *err
[] = { "Unknown failure" };
126 req
= &stattable
[xid
];
127 if(req
->callback
== NULL
)
130 req
->callback(1, err
, 2, req
->data
);
132 req
->callback
= NULL
;
137 cancel_lookup(uint16_t xid
)
139 querytable
[xid
].callback
= NULL
;
140 querytable
[xid
].data
= NULL
;
144 cancel_dns_stats(uint16_t xid
)
146 stattable
[xid
].callback
= NULL
;
147 stattable
[xid
].data
= NULL
;
151 lookup_hostname(const char *hostname
, int aftype
, DNSCB callback
, void *data
)
157 nid
= assign_dns_id();
158 if((nid
= assign_dns_id()) == 0)
161 req
= &querytable
[nid
];
163 req
->callback
= callback
;
167 if(aftype
== AF_INET6
)
173 submit_dns(nid
, aft
== 4 ? DNS_HOST_IPV4
: DNS_HOST_IPV6
, hostname
);
178 lookup_ip(const char *addr
, int aftype
, DNSCB callback
, void *data
)
185 if((nid
= assign_dns_id()) == 0)
188 req
= &querytable
[nid
];
190 req
->callback
= callback
;
194 if(aftype
== AF_INET6
)
200 submit_dns(nid
, aft
== 4 ? DNS_REVERSE_IPV4
: DNS_REVERSE_IPV6
, addr
);
205 get_nameservers(DNSLISTCB callback
, void *data
)
207 struct dnsstatreq
*req
;
211 if((nid
= assign_dns_stat_id()) == 0)
214 req
= &stattable
[nid
];
215 req
->callback
= callback
;
218 submit_dns_stat(nid
);
223 dns_results_callback(const char *callid
, const char *status
, const char *type
, const char *results
)
229 long lnid
= strtol(callid
, NULL
, 16);
231 if(lnid
> DNS_IDTABLE_SIZE
|| lnid
== 0)
233 nid
= (uint16_t)lnid
;
234 req
= &querytable
[nid
];
235 st
= (*status
== 'O');
236 aft
= *type
== '6' || *type
== 'S' ? 6 : 4;
237 if(req
->callback
== NULL
)
239 /* got cancelled..oh well */
250 req
->callback(results
, st
, aft
, req
->data
);
251 req
->callback
= NULL
;
256 dns_stats_results_callback(const char *callid
, const char *status
, int resc
, const char *resv
[])
258 struct dnsstatreq
*req
;
261 long lnid
= strtol(callid
, NULL
, 16);
263 if(lnid
> DNS_STATTABLE_SIZE
|| lnid
== 0)
266 req
= &stattable
[nid
];
268 if(req
->callback
== NULL
)
284 /* Shouldn't happen... */
289 req
->callback(resc
, resv
, st
, stattable
[nid
].data
);
292 req
->callback
= NULL
;
296 get_nameservers_cb(int resc
, const char *resv
[], int status
, void *data
)
300 rb_dlink_node
*n
, *tn
;
302 RB_DLINK_FOREACH_SAFE(n
, tn
, nameservers
.head
)
304 /* Clean up old nameservers */
306 rb_dlinkDestroy(n
, &nameservers
);
309 for(int i
= 0; i
< resc
; i
++)
310 rb_dlinkAddAlloc(rb_strdup(resv
[i
]), &nameservers
);
314 const char *error
= resc
? resv
[resc
] : "Unknown error";
315 iwarn("Error getting DNS servers: %s", error
);
320 init_nameserver_cache(void)
322 (void)get_nameservers(get_nameservers_cb
, NULL
);
326 submit_dns(uint16_t nid
, char type
, const char *addr
)
328 if(authd_helper
== NULL
)
330 handle_dns_failure(nid
);
333 rb_helper_write(authd_helper
, "D %x %c %s", nid
, type
, addr
);
337 submit_dns_stat(uint16_t nid
)
339 if(authd_helper
== NULL
)
341 handle_dns_stat_failure(nid
);
344 rb_helper_write(authd_helper
, "S %x D", nid
);