diff --git a/include/client.h b/include/client.h index d2441ec0a..1f3a32f81 100644 --- a/include/client.h +++ b/include/client.h @@ -36,7 +36,7 @@ #include "ircd_defs.h" #include "channel.h" -#include "res.h" +#include "dns.h" #include "snomask.h" #include "match.h" #include "ircd.h" diff --git a/include/ircd_defs.h b/include/ircd_defs.h index 58411530a..6816f9773 100644 --- a/include/ircd_defs.h +++ b/include/ircd_defs.h @@ -66,6 +66,11 @@ #define HOSTLEN 63 /* Length of hostname. Updated to */ /* comply with RFC1123 */ +/* Longest hostname we're willing to work with. + * Due to DNSBLs this is more than HOSTLEN. + */ +#define IRCD_RES_HOSTLEN 255 + #define USERLEN 10 #define REALLEN 50 #define CHANNELLEN 200 diff --git a/include/res.h b/include/res.h deleted file mode 100644 index a67c262a9..000000000 --- a/include/res.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * res.h for referencing functions in res.c, reslib.c - * - * $Id: res.h 2023 2006-09-02 23:47:27Z jilles $ - */ - -#ifndef _CHARYBDIS_RES_H -#define _CHARYBDIS_RES_H - -#include "ircd_defs.h" -#include "common.h" -#include "reslib.h" -#include "match.h" -#include "ircd.h" - -/* Maximum number of nameservers in /etc/resolv.conf we care about - * In hybrid, this was 2 -- but in Charybdis, we want to track - * a few more than that ;) --nenolod - */ -#define IRCD_MAXNS 10 - -struct DNSReply -{ - char *h_name; - struct rb_sockaddr_storage addr; -}; - -struct DNSQuery -{ - void *ptr; /* pointer used by callback to identify request */ - void (*callback)(void* vptr, struct DNSReply *reply); /* callback to call */ -}; - -extern struct rb_sockaddr_storage irc_nsaddr_list[]; -extern int irc_nscount; - -extern void init_resolver(void); -extern void restart_resolver(void); -extern void delete_resolver_queries(const struct DNSQuery *); -extern void gethost_byname_type(const char *, struct DNSQuery *, int); -extern void gethost_byaddr(const struct rb_sockaddr_storage *, struct DNSQuery *); -extern void add_local_domain(char *, size_t); -extern void report_dns_servers(struct Client *); - -#endif diff --git a/include/reslib.h b/include/reslib.h deleted file mode 100644 index 52699b6d9..000000000 --- a/include/reslib.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * include/irc_reslib.h - * - * $Id: reslib.h 446 2006-02-12 02:46:54Z db $ - */ - -#ifndef _CHARYBDIS_RESLIB_H -#define _CHARYBDIS_RESLIB_H - -/* Longest hostname we're willing to work with. - * Due to DNSBLs this is more than HOSTLEN. - */ -#define IRCD_RES_HOSTLEN 255 - -/* Here we define some values lifted from nameser.h */ -#define NS_NOTIFY_OP 4 -#define NS_INT16SZ 2 -#define NS_IN6ADDRSZ 16 -#define NS_INADDRSZ 4 -#define NS_INT32SZ 4 -#define NS_CMPRSFLGS 0xc0 -#define NS_MAXCDNAME 255 -#define QUERY 0 -#define IQUERY 1 -#define NO_ERRORS 0 -#define SERVFAIL 2 -#define NXDOMAIN 3 -#define NOTIMP 4 -#define REFUSED 5 -#define T_A 1 -#define T_AAAA 28 -#define T_PTR 12 -#define T_CNAME 5 -#define T_NULL 10 -#define C_IN 1 -#define QFIXEDSZ 4 -#define RRFIXEDSZ 10 -#define HFIXEDSZ 12 - -typedef struct -{ - unsigned id :16; /* query identification number */ -#ifdef WORDS_BIGENDIAN - /* fields in third byte */ - unsigned qr: 1; /* response flag */ - unsigned opcode: 4; /* purpose of message */ - unsigned aa: 1; /* authoritive answer */ - unsigned tc: 1; /* truncated message */ - unsigned rd: 1; /* recursion desired */ - /* fields in fourth byte */ - unsigned ra: 1; /* recursion available */ - unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ - unsigned ad: 1; /* authentic data from named */ - unsigned cd: 1; /* checking disabled by resolver */ - unsigned rcode :4; /* response code */ -#else - /* fields in third byte */ - unsigned rd :1; /* recursion desired */ - unsigned tc :1; /* truncated message */ - unsigned aa :1; /* authoritive answer */ - unsigned opcode :4; /* purpose of message */ - unsigned qr :1; /* response flag */ - /* fields in fourth byte */ - unsigned rcode :4; /* response code */ - unsigned cd: 1; /* checking disabled by resolver */ - unsigned ad: 1; /* authentic data from named */ - unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ - unsigned ra :1; /* recursion available */ -#endif - /* remaining bytes */ - unsigned qdcount :16; /* number of question entries */ - unsigned ancount :16; /* number of answer entries */ - unsigned nscount :16; /* number of authority entries */ - unsigned arcount :16; /* number of resource entries */ -} HEADER; - -/* - * Inline versions of get/put short/long. Pointer is advanced. - */ -#define IRC_NS_GET16(s, cp) { \ - const unsigned char *t_cp = (const unsigned char *)(cp); \ - (s) = ((u_int16_t)t_cp[0] << 8) \ - | ((u_int16_t)t_cp[1]) \ - ; \ - (cp) += NS_INT16SZ; \ -} - -#define IRC_NS_GET32(l, cp) { \ - const unsigned char *t_cp = (const unsigned char *)(cp); \ - (l) = ((u_int32_t)t_cp[0] << 24) \ - | ((u_int32_t)t_cp[1] << 16) \ - | ((u_int32_t)t_cp[2] << 8) \ - | ((u_int32_t)t_cp[3]) \ - ; \ - (cp) += NS_INT32SZ; \ -} - -#define IRC_NS_PUT16(s, cp) { \ - u_int16_t t_s = (u_int16_t)(s); \ - unsigned char *t_cp = (unsigned char *)(cp); \ - *t_cp++ = t_s >> 8; \ - *t_cp = t_s; \ - (cp) += NS_INT16SZ; \ -} - -#define IRC_NS_PUT32(l, cp) { \ - u_int32_t t_l = (u_int32_t)(l); \ - unsigned char *t_cp = (unsigned char *)(cp); \ - *t_cp++ = t_l >> 24; \ - *t_cp++ = t_l >> 16; \ - *t_cp++ = t_l >> 8; \ - *t_cp = t_l; \ - (cp) += NS_INT32SZ; \ -} - -extern int irc_res_init(void); -extern int irc_dn_expand(const unsigned char *msg, const unsigned char *eom, const unsigned char *src, char *dst, int dstsiz); -extern int irc_dn_skipname(const unsigned char *ptr, const unsigned char *eom); -extern unsigned int irc_ns_get16(const unsigned char *src); -extern unsigned long irc_ns_get32(const unsigned char *src); -extern void irc_ns_put16(unsigned int src, unsigned char *dst); -extern void irc_ns_put32(unsigned long src, unsigned char *dst); -extern int irc_res_mkquery(const char *dname, int class, int type, unsigned char *buf, int buflen); - -extern char irc_domain[IRCD_RES_HOSTLEN + 1]; - -#endif diff --git a/ircd/Makefile.am b/ircd/Makefile.am index 095c79e10..ed06d3bb1 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -47,8 +47,6 @@ libircd_la_SOURCES = \ parse.c \ privilege.c \ ratelimit.c \ - res.c \ - reslib.c \ reject.c \ restart.c \ s_auth.c \ diff --git a/ircd/Makefile.in b/ircd/Makefile.in index b483d3004..5acd86738 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -142,10 +142,10 @@ am_libircd_la_OBJECTS = authd.lo bandbi.lo blacklist.lo cache.lo \ ipv4_from_ipv6.lo irc_dictionary.lo ircd.lo ircd_parser.lo \ ircd_lexer.lo ircd_signal.lo listener.lo logger.lo match.lo \ modules.lo monitor.lo newconf.lo operhash.lo packet.lo \ - parse.lo privilege.lo ratelimit.lo res.lo reslib.lo reject.lo \ - restart.lo s_auth.lo s_conf.lo s_newconf.lo s_serv.lo \ - s_user.lo scache.lo send.lo snomask.lo sslproc.lo \ - substitution.lo supported.lo tgchange.lo version.lo whowas.lo + parse.lo privilege.lo ratelimit.lo reject.lo restart.lo \ + s_auth.lo s_conf.lo s_newconf.lo s_serv.lo s_user.lo scache.lo \ + send.lo snomask.lo sslproc.lo substitution.lo supported.lo \ + tgchange.lo version.lo whowas.lo libircd_la_OBJECTS = $(am_libircd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -460,8 +460,6 @@ libircd_la_SOURCES = \ parse.c \ privilege.c \ ratelimit.c \ - res.c \ - reslib.c \ reject.c \ restart.c \ s_auth.c \ @@ -654,8 +652,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privilege.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ratelimit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reject.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/res.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reslib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/restart.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s_auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s_conf.Plo@am__quote@ diff --git a/ircd/ircd.c b/ircd/ircd.c index 08453c74d..b5995327e 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -41,7 +41,6 @@ #include "hostmask.h" #include "numeric.h" #include "parse.h" -#include "res.h" #include "restart.h" #include "s_auth.h" #include "s_conf.h" @@ -662,7 +661,6 @@ charybdis_main(int argc, char *argv[]) init_auth(); /* Initialise the auth code */ init_authd(); /* Start up authd. */ - init_resolver(); /* Needs to be setup before the io loop */ privilegeset_set_new("default", "", 0); if (testing_conf) diff --git a/ircd/res.c b/ircd/res.c deleted file mode 100644 index 75cdae74b..000000000 --- a/ircd/res.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * A rewrite of Darren Reeds original res.c As there is nothing - * left of Darrens original code, this is now licensed by the hybrid group. - * (Well, some of the function names are the same, and bits of the structs..) - * You can use it where it is useful, free even. Buy us a beer and stuff. - * - * The authors takes no responsibility for any damage or loss - * of property which results from the use of this software. - * - * $Id: res.c 3301 2007-03-28 15:04:06Z jilles $ - * from Hybrid Id: res.c 459 2006-02-12 22:21:37Z db $ - * - * July 1999 - Rewrote a bunch of stuff here. Change hostent builder code, - * added callbacks and reference counting of returned hostents. - * --Bleep (Thomas Helvey ) - * - * This was all needlessly complicated for irc. Simplified. No more hostent - * All we really care about is the IP -> hostname mappings. Thats all. - * - * Apr 28, 2003 --cryogen and Dianora - * - * DNS server flooding lessened, AAAA-or-A lookup removed, ip6.int support - * removed, various robustness fixes - * - * 2006 --jilles and nenolod - * - * Resend queries to other servers if the DNS server replies with an error or - * an invalid response. Also, avoid servers that return errors or invalid - * responses. - * - * October 2012 --mr_flea - */ - -#include "stdinc.h" -#include "ircd_defs.h" -#include "common.h" -#include "ircd.h" -#include "res.h" -#include "reslib.h" -#include "match.h" -#include "numeric.h" -#include "client.h" /* SNO_* */ -#include "s_assert.h" -#include "logger.h" -#include "send.h" - -#if (CHAR_BIT != 8) -#error this code needs to be able to address individual octets -#endif - -static PF res_readreply; - -#define MAXPACKET 1024 /* rfc sez 512 but we expand names so ... */ -#define RES_MAXALIASES 35 /* maximum aliases allowed */ -#define RES_MAXADDRS 35 /* maximum addresses allowed */ -#define AR_TTL 600 /* TTL in seconds for dns cache entries */ - -/* RFC 1104/1105 wasn't very helpful about what these fields - * should be named, so for now, we'll just name them this way. - * we probably should look at what named calls them or something. - */ -#define TYPE_SIZE (size_t)2 -#define CLASS_SIZE (size_t)2 -#define TTL_SIZE (size_t)4 -#define RDLENGTH_SIZE (size_t)2 -#define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE) - -struct reslist -{ - rb_dlink_node node; - int id; - time_t ttl; - char type; - char queryname[IRCD_RES_HOSTLEN + 1]; /* name currently being queried */ - char retries; /* retry counter */ - char sends; /* number of sends (>1 means resent) */ - time_t sentat; - time_t timeout; - int lastns; /* index of last server sent to */ - struct rb_sockaddr_storage addr; - char *name; - struct DNSQuery *query; /* query callback for this request */ -}; - -static rb_fde_t *res_fd; -static rb_dlink_list request_list = { NULL, NULL, 0 }; -static int ns_failure_count[IRCD_MAXNS]; /* timeouts and invalid/failed replies */ - -static void rem_request(struct reslist *request); -static struct reslist *make_request(struct DNSQuery *query); -static void gethost_byname_type_fqdn(const char *name, struct DNSQuery *query, - int type); -static void do_query_name(struct DNSQuery *query, const char *name, struct reslist *request, int); -static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_storage *, - struct reslist *request); -static void query_name(struct reslist *request); -static int send_res_msg(const char *buf, int len, int count); -static void resend_query(struct reslist *request); -static int check_question(struct reslist *request, HEADER * header, char *buf, char *eob); -static int proc_answer(struct reslist *request, HEADER * header, char *, char *); -static struct reslist *find_id(int id); -static struct DNSReply *make_dnsreply(struct reslist *request); - -/* - * int - * res_ourserver(inp) - * looks up "inp" in irc_nsaddr_list[] - * returns: - * server ID or -1 for not found - * author: - * paul vixie, 29may94 - * revised for ircd, cryogen(stu) may03 - * slightly modified for charybdis, mr_flea oct12 - */ -static int res_ourserver(const struct rb_sockaddr_storage *inp) -{ -#ifdef RB_IPV6 - const struct sockaddr_in6 *v6; - const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp; -#endif - const struct sockaddr_in *v4; - const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp; - int ns; - - for (ns = 0; ns < irc_nscount; ns++) - { - const struct rb_sockaddr_storage *srv = &irc_nsaddr_list[ns]; - - if (srv->ss_family != inp->ss_family) - continue; - -#ifdef RB_IPV6 - v6 = (const struct sockaddr_in6 *)srv; -#endif - v4 = (const struct sockaddr_in *)srv; - - /* could probably just memcmp(srv, inp, srv.ss_len) here - * but we'll err on the side of caution - stu - */ - switch (srv->ss_family) - { -#ifdef RB_IPV6 - case AF_INET6: - if (v6->sin6_port == v6in->sin6_port) - if ((memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr, - sizeof(struct in6_addr)) == 0) || - (memcmp(&v6->sin6_addr.s6_addr, &in6addr_any, - sizeof(struct in6_addr)) == 0)) - { - return ns; - } - break; -#endif - case AF_INET: - if (v4->sin_port == v4in->sin_port) - if ((v4->sin_addr.s_addr == INADDR_ANY) - || (v4->sin_addr.s_addr == v4in->sin_addr.s_addr)) - { - return ns; - } - break; - default: - break; - } - } - - return -1; -} - -/* - * timeout_query_list - Remove queries from the list which have been - * there too long without being resolved. - */ -static time_t timeout_query_list(time_t now) -{ - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; - struct reslist *request; - time_t next_time = 0; - time_t timeout = 0; - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head) - { - request = ptr->data; - timeout = request->sentat + request->timeout; - - if (now >= timeout) - { - ns_failure_count[request->lastns]++; - request->sentat = now; - request->timeout += request->timeout; - resend_query(request); - } - - if ((next_time == 0) || timeout < next_time) - { - next_time = timeout; - } - } - - return (next_time > now) ? next_time : (now + AR_TTL); -} - -/* - * timeout_resolver - check request list - */ -static void timeout_resolver(void *notused) -{ - timeout_query_list(rb_current_time()); -} - -static struct ev_entry *timeout_resolver_ev = NULL; - -/* - * start_resolver - do everything we need to read the resolv.conf file - * and initialize the resolver file descriptor if needed - */ -static void start_resolver(void) -{ - int i; - - irc_res_init(); - for (i = 0; i < irc_nscount; i++) - ns_failure_count[i] = 0; - - if (res_fd == NULL) - { - if ((res_fd = rb_socket(irc_nsaddr_list[0].ss_family, SOCK_DGRAM, 0, - "UDP resolver socket")) == NULL) - return; - - /* At the moment, the resolver FD data is global .. */ - rb_setselect(res_fd, RB_SELECT_READ, res_readreply, NULL); - timeout_resolver_ev = rb_event_add("timeout_resolver", timeout_resolver, NULL, 1); - } -} - -/* - * init_resolver - initialize resolver and resolver library - */ -void init_resolver(void) -{ -#ifdef HAVE_SRAND48 - srand48(rb_current_time()); -#endif - start_resolver(); -} - -/* - * restart_resolver - reread resolv.conf, reopen socket - */ -void restart_resolver(void) -{ - rb_close(res_fd); - res_fd = NULL; - rb_event_delete(timeout_resolver_ev); /* -ddosen */ - start_resolver(); -} - -/* - * add_local_domain - Add the domain to hostname, if it is missing - * (as suggested by eps@TOASTER.SFSU.EDU) - */ -void add_local_domain(char *hname, size_t size) -{ - /* try to fix up unqualified names */ - if (strchr(hname, '.') == NULL) - { - if (irc_domain[0]) - { - size_t len = strlen(hname); - - if ((strlen(irc_domain) + len + 2) < size) - { - hname[len++] = '.'; - strcpy(hname + len, irc_domain); - } - } - } -} - -/* - * rem_request - remove a request from the list. - * This must also free any memory that has been allocated for - * temporary storage of DNS results. - */ -static void rem_request(struct reslist *request) -{ - rb_dlinkDelete(&request->node, &request_list); - rb_free(request->name); - rb_free(request); -} - -/* - * make_request - Create a DNS request record for the server. - */ -static struct reslist *make_request(struct DNSQuery *query) -{ - struct reslist *request = rb_malloc(sizeof(struct reslist)); - - request->sentat = rb_current_time(); - request->retries = 3; - request->timeout = 4; /* start at 4 and exponential inc. */ - request->query = query; - - /* - * generate a unique id - * NOTE: we don't have to worry about converting this to and from - * network byte order, the nameserver does not interpret this value - * and returns it unchanged - * - * we generate an id per request now (instead of per send) to allow - * late replies to be used. - */ -#ifdef HAVE_LRAND48 - do - { - request->id = (request->id + lrand48()) & 0xffff; - } while (find_id(request->id)); -#else - int k = 0; - struct timeval tv; - gettimeofday(&tv, NULL); - do - { - request->id = (request->id + k + tv.tv_usec) & 0xffff; - k++; - } while (find_id(request->id)); -#endif /* HAVE_LRAND48 */ - - rb_dlinkAdd(request, &request->node, &request_list); - - return request; -} - -/* - * delete_resolver_queries - cleanup outstanding queries - * for which there no longer exist clients or conf lines. - */ -void delete_resolver_queries(const struct DNSQuery *query) -{ - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; - struct reslist *request; - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head) - { - if ((request = ptr->data) != NULL) - { - if (query == request->query) - rem_request(request); - } - } -} - -/* - * retryfreq - determine how many queries to wait before resending - * if there have been that many consecutive timeouts - */ -static int retryfreq(int timeouts) -{ - switch (timeouts) - { - case 1: - return 3; - case 2: - return 9; - case 3: - return 27; - case 4: - return 81; - default: - return 243; - } -} - -/* - * send_res_msg - sends msg to a nameserver. - * This should reflect /etc/resolv.conf. - * Returns number of nameserver successfully sent to - * or -1 if no successful sends. - */ -static int send_res_msg(const char *msg, int len, int rcount) -{ - int i; - int ns; - static int retrycnt; - - retrycnt++; - /* First try a nameserver that seems to work. - * Every once in a while, try a possibly broken one to check - * if it is working again. - */ - for (i = 0; i < irc_nscount; i++) - { - ns = (i + rcount - 1) % irc_nscount; - if (ns_failure_count[ns] && retrycnt % retryfreq(ns_failure_count[ns])) - continue; - if (sendto(rb_get_fd(res_fd), msg, len, 0, - (struct sockaddr *)&(irc_nsaddr_list[ns]), - GET_SS_LEN(&irc_nsaddr_list[ns])) == len) - return ns; - } - - /* No known working nameservers, try some broken one. */ - for (i = 0; i < irc_nscount; i++) - { - ns = (i + rcount - 1) % irc_nscount; - if (!ns_failure_count[ns]) - continue; - if (sendto(rb_get_fd(res_fd), msg, len, 0, - (struct sockaddr *)&(irc_nsaddr_list[ns]), - GET_SS_LEN(&irc_nsaddr_list[ns])) == len) - return ns; - } - - return -1; -} - -/* - * find_id - find a dns request id (id is determined by dn_mkquery) - */ -static struct reslist *find_id(int id) -{ - rb_dlink_node *ptr; - struct reslist *request; - - RB_DLINK_FOREACH(ptr, request_list.head) - { - request = ptr->data; - - if (request->id == id) - return (request); - } - - return (NULL); -} - -/* - * gethost_byname_type - get host address from name, adding domain if needed - */ -void gethost_byname_type(const char *name, struct DNSQuery *query, int type) -{ - char fqdn[IRCD_RES_HOSTLEN + 1]; - assert(name != 0); - - rb_strlcpy(fqdn, name, sizeof fqdn); - add_local_domain(fqdn, IRCD_RES_HOSTLEN); - gethost_byname_type_fqdn(fqdn, query, type); -} - -/* - * gethost_byname_type_fqdn - get host address from fqdn - */ -static void gethost_byname_type_fqdn(const char *name, struct DNSQuery *query, - int type) -{ - assert(name != 0); - do_query_name(query, name, NULL, type); -} - -/* - * gethost_byaddr - get host name from address - */ -void gethost_byaddr(const struct rb_sockaddr_storage *addr, struct DNSQuery *query) -{ - do_query_number(query, addr, NULL); -} - -/* - * do_query_name - nameserver lookup name - */ -static void do_query_name(struct DNSQuery *query, const char *name, struct reslist *request, - int type) -{ - if (request == NULL) - { - request = make_request(query); - request->name = rb_strdup(name); - } - - rb_strlcpy(request->queryname, name, sizeof(request->queryname)); - request->type = type; - query_name(request); -} - -/* - * do_query_number - Use this to do reverse IP# lookups. - */ -static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_storage *addr, - struct reslist *request) -{ - const unsigned char *cp; - - if (request == NULL) - { - request = make_request(query); - memcpy(&request->addr, addr, sizeof(struct rb_sockaddr_storage)); - request->name = (char *)rb_malloc(IRCD_RES_HOSTLEN + 1); - } - - if (addr->ss_family == AF_INET) - { - const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr; - cp = (const unsigned char *)&v4->sin_addr.s_addr; - - rb_sprintf(request->queryname, "%u.%u.%u.%u.in-addr.arpa", (unsigned int)(cp[3]), - (unsigned int)(cp[2]), (unsigned int)(cp[1]), (unsigned int)(cp[0])); - } -#ifdef RB_IPV6 - else if (addr->ss_family == AF_INET6) - { - const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr; - cp = (const unsigned char *)&v6->sin6_addr.s6_addr; - - (void)sprintf(request->queryname, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." - "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", - (unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4), - (unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4), - (unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4), - (unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4), - (unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4), - (unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4), - (unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4), - (unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4), - (unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4), - (unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4), - (unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4), - (unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4), - (unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4), - (unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4), - (unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4), - (unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4)); - } -#endif - - request->type = T_PTR; - query_name(request); -} - -/* - * query_name - generate a query based on class, type and name. - */ -static void query_name(struct reslist *request) -{ - char buf[MAXPACKET]; - int request_len = 0; - int ns; - - memset(buf, 0, sizeof(buf)); - - if ((request_len = - irc_res_mkquery(request->queryname, C_IN, request->type, (unsigned char *)buf, sizeof(buf))) > 0) - { - HEADER *header = (HEADER *)(void *)buf; - header->id = request->id; - ++request->sends; - - ns = send_res_msg(buf, request_len, request->sends); - if (ns != -1) - request->lastns = ns; - } -} - -static void resend_query(struct reslist *request) -{ - if (--request->retries <= 0) - { - (*request->query->callback) (request->query->ptr, NULL); - rem_request(request); - return; - } - - switch (request->type) - { - case T_PTR: - do_query_number(NULL, &request->addr, request); - break; - case T_A: -#ifdef RB_IPV6 - case T_AAAA: -#endif - do_query_name(NULL, request->name, request, request->type); - break; - default: - break; - } -} - -/* - * check_question - check if the reply really belongs to the - * name we queried (to guard against late replies from previous - * queries with the same id). - */ -static int check_question(struct reslist *request, HEADER * header, char *buf, char *eob) -{ - char hostbuf[IRCD_RES_HOSTLEN + 1]; /* working buffer */ - unsigned char *current; /* current position in buf */ - int n; /* temp count */ - - current = (unsigned char *)buf + sizeof(HEADER); - if (header->qdcount != 1) - return 0; - n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf, - sizeof(hostbuf)); - if (n <= 0) - return 0; - if (strcasecmp(hostbuf, request->queryname)) - return 0; - return 1; -} - -/* - * proc_answer - process name server reply - */ -static int proc_answer(struct reslist *request, HEADER * header, char *buf, char *eob) -{ - char hostbuf[IRCD_RES_HOSTLEN + 100]; /* working buffer */ - unsigned char *current; /* current position in buf */ - int type; /* answer type */ - int n; /* temp count */ - int rd_length; - struct sockaddr_in *v4; /* conversion */ -#ifdef RB_IPV6 - struct sockaddr_in6 *v6; -#endif - current = (unsigned char *)buf + sizeof(HEADER); - - for (; header->qdcount > 0; --header->qdcount) - { - if ((n = irc_dn_skipname(current, (unsigned char *)eob)) < 0) - return 0; - - current += (size_t) n + QFIXEDSZ; - } - - /* - * process each answer sent to us blech. - */ - while (header->ancount > 0 && (char *)current < eob) - { - header->ancount--; - - n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf, - sizeof(hostbuf)); - - if (n < 0) - { - /* - * broken message - */ - return (0); - } - else if (n == 0) - { - /* - * no more answers left - */ - return (0); - } - - hostbuf[IRCD_RES_HOSTLEN] = '\0'; - - /* With Address arithmetic you have to be very anal - * this code was not working on alpha due to that - * (spotted by rodder/jailbird/dianora) - */ - current += (size_t) n; - - if (!(((char *)current + ANSWER_FIXED_SIZE) < eob)) - break; - - type = irc_ns_get16(current); - current += TYPE_SIZE; - - (void) irc_ns_get16(current); - current += CLASS_SIZE; - - request->ttl = irc_ns_get32(current); - current += TTL_SIZE; - - rd_length = irc_ns_get16(current); - current += RDLENGTH_SIZE; - - /* - * Wait to set request->type until we verify this structure - */ - switch (type) - { - case T_A: - if (request->type != T_A) - return (0); - - /* - * check for invalid rd_length or too many addresses - */ - if (rd_length != sizeof(struct in_addr)) - return (0); - v4 = (struct sockaddr_in *)&request->addr; - SET_SS_LEN(&request->addr, sizeof(struct sockaddr_in)); - v4->sin_family = AF_INET; - memcpy(&v4->sin_addr, current, sizeof(struct in_addr)); - return (1); - break; -#ifdef RB_IPV6 - case T_AAAA: - if (request->type != T_AAAA) - return (0); - if (rd_length != sizeof(struct in6_addr)) - return (0); - SET_SS_LEN(&request->addr, sizeof(struct sockaddr_in6)); - v6 = (struct sockaddr_in6 *)&request->addr; - v6->sin6_family = AF_INET6; - memcpy(&v6->sin6_addr, current, sizeof(struct in6_addr)); - return (1); - break; -#endif - case T_PTR: - if (request->type != T_PTR) - return (0); - n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, - hostbuf, sizeof(hostbuf)); - if (n < 0) - return (0); /* broken message */ - else if (n == 0) - return (0); /* no more answers left */ - - rb_strlcpy(request->name, hostbuf, IRCD_RES_HOSTLEN + 1); - - return (1); - break; - case T_CNAME: - /* real answer will follow */ - current += rd_length; - break; - - default: - /* XXX I'd rather just throw away the entire bogus thing - * but its possible its just a broken nameserver with still - * valid answers. But lets do some rudimentary logging for now... - */ - ilog(L_MAIN, "irc_res.c bogus type %d", type); - break; - } - } - - return (1); -} - -/* - * res_read_single_reply - read a dns reply from the nameserver and process it. - * Return value: 1 if a packet was read, 0 otherwise - */ -static int res_read_single_reply(rb_fde_t *F, void *data) -{ - char buf[sizeof(HEADER) + MAXPACKET] - /* Sparc and alpha need 16bit-alignment for accessing header->id - * (which is uint16_t). Because of the header = (HEADER*) buf; - * lateron, this is neeeded. --FaUl - */ -#if defined(__sparc__) || defined(__alpha__) - __attribute__ ((aligned(16))) -#endif - ; - HEADER *header; - struct reslist *request = NULL; - struct DNSReply *reply = NULL; - int rc; - int answer_count; - socklen_t len = sizeof(struct rb_sockaddr_storage); - struct rb_sockaddr_storage lsin; - int ns; - - rc = recvfrom(rb_get_fd(F), buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len); - - /* No packet */ - if (rc == 0 || rc == -1) - return 0; - - /* Too small */ - if (rc <= (int)(sizeof(HEADER))) - return 1; - - /* - * convert DNS reply reader from Network byte order to CPU byte order. - */ - header = (HEADER *)(void *)buf; - header->ancount = ntohs(header->ancount); - header->qdcount = ntohs(header->qdcount); - header->nscount = ntohs(header->nscount); - header->arcount = ntohs(header->arcount); - - /* - * response for an id which we have already received an answer for - * just ignore this response. - */ - if (0 == (request = find_id(header->id))) - return 1; - - /* - * check against possibly fake replies - */ - ns = res_ourserver(&lsin); - if (ns == -1) - return 1; - - if (ns != request->lastns) - { - /* - * We'll accept the late reply, but penalize it a little more to make - * sure a laggy server doesn't end up favored. - */ - ns_failure_count[ns] += 3; - } - - - if (!check_question(request, header, buf, buf + rc)) - return 1; - - if ((header->rcode != NO_ERRORS) || (header->ancount == 0)) - { - /* - * RFC 2136 states that in the event of a server returning SERVFAIL - * or NOTIMP, the request should be resent to the next server. - * Additionally, if the server refuses our query, resend it as well. - * -- mr_flea - */ - if (SERVFAIL == header->rcode || NOTIMP == header->rcode || - REFUSED == header->rcode) - { - ns_failure_count[ns]++; - resend_query(request); - } - else - { - /* - * Either a fatal error was returned or no answer. Cancel the - * request. - */ - if (NXDOMAIN == header->rcode) - { - /* If the rcode is NXDOMAIN, treat it as a good response. */ - ns_failure_count[ns] /= 4; - } - (*request->query->callback) (request->query->ptr, NULL); - rem_request(request); - } - return 1; - } - /* - * If this fails there was an error decoding the received packet. - * -- jilles - */ - answer_count = proc_answer(request, header, buf, buf + rc); - - if (answer_count) - { - if (request->type == T_PTR) - { - if (request->name == NULL) - { - /* - * Got a PTR response with no name, something strange is - * happening. Try another DNS server. - */ - ns_failure_count[ns]++; - resend_query(request); - return 1; - } - - /* - * Lookup the 'authoritative' name that we were given for the - * ip#. - */ -#ifdef RB_IPV6 - if (request->addr.ss_family == AF_INET6) - gethost_byname_type_fqdn(request->name, request->query, T_AAAA); - else -#endif - gethost_byname_type_fqdn(request->name, request->query, T_A); - rem_request(request); - } - else - { - /* - * got a name and address response, client resolved - */ - reply = make_dnsreply(request); - (*request->query->callback) (request->query->ptr, reply); - rb_free(reply); - rem_request(request); - } - - ns_failure_count[ns] /= 4; - } - else - { - /* Invalid or corrupt reply - try another resolver. */ - ns_failure_count[ns]++; - resend_query(request); - } - return 1; -} - -static void res_readreply(rb_fde_t *F, void *data) -{ - while (res_read_single_reply(F, data)) - ; - rb_setselect(F, RB_SELECT_READ, res_readreply, NULL); -} - -static struct DNSReply *make_dnsreply(struct reslist *request) -{ - struct DNSReply *cp; - s_assert(request != 0); - - cp = (struct DNSReply *)rb_malloc(sizeof(struct DNSReply)); - - cp->h_name = request->name; - memcpy(&cp->addr, &request->addr, sizeof(cp->addr)); - return (cp); -} diff --git a/ircd/reslib.c b/ircd/reslib.c deleted file mode 100644 index c24950715..000000000 --- a/ircd/reslib.c +++ /dev/null @@ -1,1181 +0,0 @@ -/* - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* Original copyright ISC as above. - * Code modified specifically for ircd use from the following orginal files - * in bind ... - * - * res_comp.c - * ns_name.c - * ns_netint.c - * res_init.c - * - * - Dianora - */ - -#include "stdinc.h" -#include "ircd_defs.h" -#include "common.h" -#include "ircd.h" -#include "res.h" -#include "reslib.h" -#include "match.h" -#include "logger.h" - -#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ -#define DNS_LABELTYPE_BITSTRING 0x41 -#define DNS_MAXLINE 128 - -/* $Id: reslib.c 1695 2006-06-27 15:11:23Z jilles $ */ -/* from Hybrid Id: reslib.c 177 2005-10-22 09:05:05Z michael $ */ - -struct rb_sockaddr_storage irc_nsaddr_list[IRCD_MAXNS]; -int irc_nscount = 0; -char irc_domain[IRCD_RES_HOSTLEN + 1]; - -static const char digitvalue[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ -}; - -static int parse_resvconf(void); -static void add_nameserver(const char *); - -static const char digits[] = "0123456789"; -static int labellen(const unsigned char *lp); -static int special(int ch); -static int printable(int ch); -static int irc_decode_bitstring(const char **cpp, char *dn, const char *eom); -static int irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz, - const unsigned char **dnptrs, const unsigned char **lastdnptr); -static int irc_dn_find(const unsigned char *, const unsigned char *, const unsigned char * const *, - const unsigned char * const *); -static int irc_encode_bitsring(const char **, const char *, unsigned char **, unsigned char **, - const char *); -static int irc_ns_name_uncompress(const unsigned char *, const unsigned char *, - const unsigned char *, char *, size_t); -static int irc_ns_name_unpack(const unsigned char *, const unsigned char *, - const unsigned char *, unsigned char *, - size_t); -static int irc_ns_name_ntop(const char *, char *, size_t); -static int irc_ns_name_skip(const unsigned char **, const unsigned char *); -static int mklower(int ch); - -int -irc_res_init(void) -{ - irc_nscount = 0; - parse_resvconf(); - if (irc_nscount == 0) - add_nameserver("127.0.0.1"); - return 0; -} - -/* parse_resvconf() - * - * inputs - NONE - * output - -1 if failure 0 if success - * side effects - fills in irc_nsaddr_list - */ -static int -parse_resvconf(void) -{ - char *p; - char *opt; - char *arg; - char input[DNS_MAXLINE]; - FILE *file; - - /* XXX "/etc/resolv.conf" should be from a define in setup.h perhaps - * for cygwin support etc. this hardcodes it to unix for now -db - */ - if ((file = fopen("/etc/resolv.conf", "r")) == NULL) - return -1; - - while (fgets(input, sizeof(input), file) != NULL) - { - /* blow away any newline */ - if ((p = strpbrk(input, "\r\n")) != NULL) - *p = '\0'; - - p = input; - /* skip until something thats not a space is seen */ - while (IsSpace(*p)) - p++; - /* if at this point, have a '\0' then continue */ - if (*p == '\0') - continue; - - /* Ignore comment lines immediately */ - if (*p == '#' || *p == ';') - continue; - - /* skip until a space is found */ - opt = p; - while (!IsSpace(*p) && *p != '\0') - p++; - if (*p == '\0') - continue; /* no arguments?.. ignore this line */ - /* blow away the space character */ - *p++ = '\0'; - - /* skip these spaces that are before the argument */ - while (IsSpace(*p)) - p++; - /* Now arg should be right where p is pointing */ - arg = p; - if ((p = strpbrk(arg, " \t")) != NULL) - *p = '\0'; /* take the first word */ - - if (irccmp(opt, "domain") == 0) - rb_strlcpy(irc_domain, arg, sizeof(irc_domain)); - else if (irccmp(opt, "nameserver") == 0) - add_nameserver(arg); - } - - fclose(file); - return 0; -} - -/* add_nameserver() - * - * input - either an IPV4 address in dotted quad - * or an IPV6 address in : format - * output - NONE - * side effects - entry in irc_nsaddr_list is filled in as needed - */ -static void -add_nameserver(const char *arg) -{ - struct addrinfo hints, *res; - - /* Done max number of nameservers? */ - if (irc_nscount >= IRCD_MAXNS) - { - ilog (L_MAIN, "Too many nameservers, ignoring %s", arg); - return; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - - if (getaddrinfo(arg, "domain", &hints, &res)) - return; - - if (res == NULL) - return; - - memcpy(&irc_nsaddr_list[irc_nscount], res->ai_addr, res->ai_addrlen); - SET_SS_LEN(&irc_nsaddr_list[irc_nscount], res->ai_addrlen); - irc_nscount++; - freeaddrinfo(res); -} - -/* - * Expand compressed domain name 'comp_dn' to full domain name. - * 'msg' is a pointer to the begining of the message, - * 'eomorig' points to the first location after the message, - * 'exp_dn' is a pointer to a buffer of size 'length' for the result. - * Return size of compressed name or -1 if there was an error. - */ -int -irc_dn_expand(const unsigned char *msg, const unsigned char *eom, - const unsigned char *src, char *dst, int dstsiz) -{ - int n = irc_ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); - - if (n > 0 && dst[0] == '.') - dst[0] = '\0'; - return(n); -} - -/* - * irc_ns_name_uncompress(msg, eom, src, dst, dstsiz) - * Expand compressed domain name to presentation format. - * return: - * Number of bytes read out of `src', or -1 (with errno set). - * note: - * Root domain returns as "." not "". - */ -static int -irc_ns_name_uncompress(const unsigned char *msg, const unsigned char *eom, - const unsigned char *src, char *dst, size_t dstsiz) -{ - unsigned char tmp[NS_MAXCDNAME]; - int n; - - if ((n = irc_ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) - return(-1); - if (irc_ns_name_ntop((char*)tmp, dst, dstsiz) == -1) - return(-1); - return(n); -} -/* - * irc_ns_name_unpack(msg, eom, src, dst, dstsiz) - * Unpack a domain name from a message, source may be compressed. - * return: - * -1 if it fails, or consumed octets if it succeeds. - */ -static int -irc_ns_name_unpack(const unsigned char *msg, const unsigned char *eom, - const unsigned char *src, unsigned char *dst, - size_t dstsiz) -{ - const unsigned char *srcp, *dstlim; - unsigned char *dstp; - int n, len, checked, l; - - len = -1; - checked = 0; - dstp = dst; - srcp = src; - dstlim = dst + dstsiz; - if (srcp < msg || srcp >= eom) { - errno = EMSGSIZE; - return (-1); - } - /* Fetch next label in domain name. */ - while ((n = *srcp++) != 0) { - /* Check for indirection. */ - switch (n & NS_CMPRSFLGS) { - case 0: - case NS_TYPE_ELT: - /* Limit checks. */ - if ((l = labellen(srcp - 1)) < 0) { - errno = EMSGSIZE; - return(-1); - } - if (dstp + l + 1 >= dstlim || srcp + l >= eom) { - errno = EMSGSIZE; - return (-1); - } - checked += l + 1; - *dstp++ = n; - memcpy(dstp, srcp, l); - dstp += l; - srcp += l; - break; - - case NS_CMPRSFLGS: - if (srcp >= eom) { - errno = EMSGSIZE; - return (-1); - } - if (len < 0) - len = srcp - src + 1; - srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); - if (srcp < msg || srcp >= eom) { /* Out of range. */ - errno = EMSGSIZE; - return (-1); - } - checked += 2; - /* - * Check for loops in the compressed name; - * if we've looked at the whole message, - * there must be a loop. - */ - if (checked >= eom - msg) { - errno = EMSGSIZE; - return (-1); - } - break; - - default: - errno = EMSGSIZE; - return (-1); /* flag error */ - } - } - *dstp = '\0'; - if (len < 0) - len = srcp - src; - return (len); -} - -/* - * irc_ns_name_ntop(src, dst, dstsiz) - * Convert an encoded domain name to printable ascii as per RFC1035. - * return: - * Number of bytes written to buffer, or -1 (with errno set) - * notes: - * The root is returned as "." - * All other domains are returned in non absolute form - */ -static int -irc_ns_name_ntop(const char *src, char *dst, size_t dstsiz) -{ - const char *cp; - char *dn, *eom; - unsigned char c; - unsigned int n; - int l; - - cp = src; - dn = dst; - eom = dst + dstsiz; - - while ((n = *cp++) != 0) { - if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { - /* Some kind of compression pointer. */ - errno = EMSGSIZE; - return (-1); - } - if (dn != dst) { - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '.'; - } - if ((l = labellen((const unsigned char*)(cp - 1))) < 0) { - errno = EMSGSIZE; /* XXX */ - return(-1); - } - if (dn + l >= eom) { - errno = EMSGSIZE; - return (-1); - } - if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { - int m; - - if (n != DNS_LABELTYPE_BITSTRING) { - /* XXX: labellen should reject this case */ - errno = EINVAL; - return(-1); - } - if ((m = irc_decode_bitstring(&cp, dn, eom)) < 0) - { - errno = EMSGSIZE; - return(-1); - } - dn += m; - continue; - } - for ((void)NULL; l > 0; l--) { - c = *cp++; - if (special(c)) { - if (dn + 1 >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '\\'; - *dn++ = (char)c; - } else if (!printable(c)) { - if (dn + 3 >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '\\'; - *dn++ = digits[c / 100]; - *dn++ = digits[(c % 100) / 10]; - *dn++ = digits[c % 10]; - } else { - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = (char)c; - } - } - } - if (dn == dst) { - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '.'; - } - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '\0'; - return (dn - dst); -} - -/* - * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. - * Return the size of the compressed name or -1. - * 'length' is the size of the array pointed to by 'comp_dn'. - */ -static int -irc_dn_comp(const char *src, unsigned char *dst, int dstsiz, - const unsigned char **dnptrs, const unsigned char **lastdnptr) -{ - return(irc_ns_name_compress(src, dst, (size_t)dstsiz, - (const unsigned char **)dnptrs, - (const unsigned char **)lastdnptr)); -} - -/* - * Skip over a compressed domain name. Return the size or -1. - */ -int -irc_dn_skipname(const unsigned char *ptr, const unsigned char *eom) { - const unsigned char *saveptr = ptr; - - if (irc_ns_name_skip(&ptr, eom) == -1) - return(-1); - return(ptr - saveptr); -} - -/* - * ns_name_skip(ptrptr, eom) - * Advance *ptrptr to skip over the compressed name it points at. - * return: - * 0 on success, -1 (with errno set) on failure. - */ -static int -irc_ns_name_skip(const unsigned char **ptrptr, const unsigned char *eom) -{ - const unsigned char *cp; - unsigned int n; - int l; - - cp = *ptrptr; - - while (cp < eom && (n = *cp++) != 0) - { - /* Check for indirection. */ - switch (n & NS_CMPRSFLGS) - { - case 0: /* normal case, n == len */ - cp += n; - continue; - case NS_TYPE_ELT: /* EDNS0 extended label */ - if ((l = labellen(cp - 1)) < 0) - { - errno = EMSGSIZE; /* XXX */ - return(-1); - } - - cp += l; - continue; - case NS_CMPRSFLGS: /* indirection */ - cp++; - break; - default: /* illegal type */ - errno = EMSGSIZE; - return(-1); - } - - break; - } - - if (cp > eom) - { - errno = EMSGSIZE; - return (-1); - } - - *ptrptr = cp; - return(0); -} - -unsigned int -irc_ns_get16(const unsigned char *src) -{ - unsigned int dst; - - IRC_NS_GET16(dst, src); - return(dst); -} - -unsigned long -irc_ns_get32(const unsigned char *src) -{ - unsigned long dst; - - IRC_NS_GET32(dst, src); - return(dst); -} - -void -irc_ns_put16(unsigned int src, unsigned char *dst) -{ - IRC_NS_PUT16(src, dst); -} - -void -irc_ns_put32(unsigned long src, unsigned char *dst) -{ - IRC_NS_PUT32(src, dst); -} - -/* From ns_name.c */ - -/* - * special(ch) - * Thinking in noninternationalized USASCII (per the DNS spec), - * is this characted special ("in need of quoting") ? - * return: - * boolean. - */ -static int -special(int ch) -{ - switch (ch) - { - case 0x22: /* '"' */ - case 0x2E: /* '.' */ - case 0x3B: /* ';' */ - case 0x5C: /* '\\' */ - case 0x28: /* '(' */ - case 0x29: /* ')' */ - /* Special modifiers in zone files. */ - case 0x40: /* '@' */ - case 0x24: /* '$' */ - return(1); - default: - return(0); - } -} - -static int -labellen(const unsigned char *lp) -{ - int bitlen; - unsigned char l = *lp; - - if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) - { - /* should be avoided by the caller */ - return(-1); - } - - if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) - { - if (l == DNS_LABELTYPE_BITSTRING) - { - if ((bitlen = *(lp + 1)) == 0) - bitlen = 256; - return((bitlen + 7 ) / 8 + 1); - } - - return(-1); /* unknwon ELT */ - } - - return(l); -} - - -/* - * printable(ch) - * Thinking in noninternationalized USASCII (per the DNS spec), - * is this character visible and not a space when printed ? - * return: - * boolean. - */ -static int -printable(int ch) -{ - return(ch > 0x20 && ch < 0x7f); -} - -static int -irc_decode_bitstring(const char **cpp, char *dn, const char *eom) -{ - const char *cp = *cpp; - char *beg = dn, tc; - int b, blen, plen; - - if ((blen = (*cp & 0xff)) == 0) - blen = 256; - plen = (blen + 3) / 4; - plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); - if (dn + plen >= eom) - return(-1); - - cp++; - dn += sprintf(dn, "\\[x"); - for (b = blen; b > 7; b -= 8, cp++) - dn += sprintf(dn, "%02x", *cp & 0xff); - if (b > 4) { - tc = *cp++; - dn += sprintf(dn, "%02x", tc & (0xff << (8 - b))); - } else if (b > 0) { - tc = *cp++; - dn += sprintf(dn, "%1x", - ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); - } - dn += sprintf(dn, "/%d]", blen); - - *cpp = cp; - return(dn - beg); -} - -/* - * irc_ns_name_pton(src, dst, dstsiz) - * Convert a ascii string into an encoded domain name as per RFC1035. - * return: - * -1 if it fails - * 1 if string was fully qualified - * 0 is string was not fully qualified - * notes: - * Enforces label and domain length limits. - */ -static int -irc_ns_name_pton(const char *src, unsigned char *dst, size_t dstsiz) -{ - unsigned char *label, *bp, *eom; - char *cp; - int c, n, escaped, e = 0; - - escaped = 0; - bp = dst; - eom = dst + dstsiz; - label = bp++; - - - while ((c = *src++) != 0) { - if (escaped) { - if (c == '[') { /* start a bit string label */ - if ((cp = strchr(src, ']')) == NULL) { - errno = EINVAL; /* ??? */ - return(-1); - } - if ((e = irc_encode_bitsring(&src, - cp + 2, - &label, - &bp, - (const char *)eom)) - != 0) { - errno = e; - return(-1); - } - escaped = 0; - label = bp++; - if ((c = *src++) == 0) - goto done; - else if (c != '.') { - errno = EINVAL; - return(-1); - } - continue; - } - else if ((cp = strchr(digits, c)) != NULL) { - n = (cp - digits) * 100; - if ((c = *src++) == 0 || - (cp = strchr(digits, c)) == NULL) { - errno = EMSGSIZE; - return (-1); - } - n += (cp - digits) * 10; - if ((c = *src++) == 0 || - (cp = strchr(digits, c)) == NULL) { - errno = EMSGSIZE; - return (-1); - } - n += (cp - digits); - if (n > 255) { - errno = EMSGSIZE; - return (-1); - } - c = n; - } - escaped = 0; - } else if (c == '\\') { - escaped = 1; - continue; - } else if (c == '.') { - c = (bp - label - 1); - if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ - errno = EMSGSIZE; - return (-1); - } - if (label >= eom) { - errno = EMSGSIZE; - return (-1); - } - *label = c; - /* Fully qualified ? */ - if (*src == '\0') { - if (c != 0) { - if (bp >= eom) { - errno = EMSGSIZE; - return (-1); - } - *bp++ = '\0'; - } - if ((bp - dst) > NS_MAXCDNAME) { - errno = EMSGSIZE; - return (-1); - } - return (1); - } - if (c == 0 || *src == '.') { - errno = EMSGSIZE; - return (-1); - } - label = bp++; - continue; - } - if (bp >= eom) { - errno = EMSGSIZE; - return (-1); - } - *bp++ = (unsigned char)c; - } - c = (bp - label - 1); - if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ - errno = EMSGSIZE; - return (-1); - } - done: - if (label >= eom) { - errno = EMSGSIZE; - return (-1); - } - *label = c; - if (c != 0) { - if (bp >= eom) { - errno = EMSGSIZE; - return (-1); - } - *bp++ = 0; - } - - if ((bp - dst) > NS_MAXCDNAME) - { /* src too big */ - errno = EMSGSIZE; - return (-1); - } - - return (0); -} - -/* - * irc_ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) - * Pack domain name 'domain' into 'comp_dn'. - * return: - * Size of the compressed name, or -1. - * notes: - * 'dnptrs' is an array of pointers to previous compressed names. - * dnptrs[0] is a pointer to the beginning of the message. The array - * ends with NULL. - * 'lastdnptr' is a pointer to the end of the array pointed to - * by 'dnptrs'. - * Side effects: - * The list of pointers in dnptrs is updated for labels inserted into - * the message as we compress the name. If 'dnptr' is NULL, we don't - * try to compress names. If 'lastdnptr' is NULL, we don't update the - * list. - */ -static int -irc_ns_name_pack(const unsigned char *src, unsigned char *dst, int dstsiz, - const unsigned char **dnptrs, const unsigned char **lastdnptr) -{ - unsigned char *dstp; - const unsigned char **cpp, **lpp, *eob, *msg; - const unsigned char *srcp; - int n, l, first = 1; - - srcp = src; - dstp = dst; - eob = dstp + dstsiz; - lpp = cpp = NULL; - if (dnptrs != NULL) { - if ((msg = *dnptrs++) != NULL) { - for (cpp = dnptrs; *cpp != NULL; cpp++) - (void)NULL; - lpp = cpp; /* end of list to search */ - } - } else - msg = NULL; - - /* make sure the domain we are about to add is legal */ - l = 0; - do { - int l0; - - n = *srcp; - if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { - errno = EMSGSIZE; - return (-1); - } - if ((l0 = labellen(srcp)) < 0) { - errno = EINVAL; - return(-1); - } - l += l0 + 1; - if (l > NS_MAXCDNAME) { - errno = EMSGSIZE; - return (-1); - } - srcp += l0 + 1; - } while (n != 0); - - /* from here on we need to reset compression pointer array on error */ - srcp = src; - do { - /* Look to see if we can use pointers. */ - n = *srcp; - if (n != 0 && msg != NULL) { - l = irc_dn_find(srcp, msg, (const unsigned char * const *)dnptrs, - (const unsigned char * const *)lpp); - if (l >= 0) { - if (dstp + 1 >= eob) { - goto cleanup; - } - *dstp++ = (l >> 8) | NS_CMPRSFLGS; - *dstp++ = l % 256; - return (dstp - dst); - } - /* Not found, save it. */ - if (lastdnptr != NULL && cpp < lastdnptr - 1 && - (dstp - msg) < 0x4000 && first) { - *cpp++ = dstp; - *cpp = NULL; - first = 0; - } - } - /* copy label to buffer */ - if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { - /* Should not happen. */ - goto cleanup; - } - n = labellen(srcp); - if (dstp + 1 + n >= eob) { - goto cleanup; - } - memcpy(dstp, srcp, n + 1); - srcp += n + 1; - dstp += n + 1; - } while (n != 0); - - if (dstp > eob) { -cleanup: - if (msg != NULL) - *lpp = NULL; - errno = EMSGSIZE; - return (-1); - } - return(dstp - dst); -} - -static int -irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz, - const unsigned char **dnptrs, const unsigned char **lastdnptr) -{ - unsigned char tmp[NS_MAXCDNAME]; - - if (irc_ns_name_pton(src, tmp, sizeof tmp) == -1) - return(-1); - return(irc_ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); -} - -static int -irc_encode_bitsring(const char **bp, const char *end, unsigned char **labelp, - unsigned char **dst, const char *eom) -{ - int afterslash = 0; - const char *cp = *bp; - char *tp, c; - const char *beg_blen; - char *end_blen = NULL; - int value = 0, count = 0, tbcount = 0, blen = 0; - - beg_blen = end_blen = NULL; - - /* a bitstring must contain at least 2 characters */ - if (end - cp < 2) - return(EINVAL); - - /* XXX: currently, only hex strings are supported */ - if (*cp++ != 'x') - return(EINVAL); - if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ - return(EINVAL); - - for (tp = (char*)(dst + 1); cp < end && tp < eom; cp++) { - switch((c = *cp)) { - case ']': /* end of the bitstring */ - if (afterslash) { - if (beg_blen == NULL) - return(EINVAL); - blen = (int)strtol(beg_blen, &end_blen, 10); - if (*end_blen != ']') - return(EINVAL); - } - if (count) - *tp++ = ((value << 4) & 0xff); - cp++; /* skip ']' */ - goto done; - case '/': - afterslash = 1; - break; - default: - if (afterslash) { - if (!isdigit(c&0xff)) - return(EINVAL); - if (beg_blen == NULL) { - - if (c == '0') { - /* blen never begings with 0 */ - return(EINVAL); - } - beg_blen = cp; - } - } else { - if (!isxdigit(c&0xff)) - return(EINVAL); - value <<= 4; - value += digitvalue[(int)c]; - count += 4; - tbcount += 4; - if (tbcount > 256) - return(EINVAL); - if (count == 8) { - *tp++ = value; - count = 0; - } - } - break; - } - } - done: - if (cp >= end || tp >= eom) - return(EMSGSIZE); - - /* - * bit length validation: - * If a is present, the number of digits in the - * MUST be just sufficient to contain the number of bits specified - * by the . If there are insignificant bits in a final - * hexadecimal or octal digit, they MUST be zero. - * RFC 2673, Section 3.2. - */ - if (blen > 0) { - int traillen; - - if (((blen + 3) & ~3) != tbcount) - return(EINVAL); - traillen = tbcount - blen; /* between 0 and 3 */ - if (((value << (8 - traillen)) & 0xff) != 0) - return(EINVAL); - } - else - blen = tbcount; - if (blen == 256) - blen = 0; - - /* encode the type and the significant bit fields */ - **labelp = DNS_LABELTYPE_BITSTRING; - **dst = blen; - - *bp = cp; - *dst = (unsigned char*)tp; - - return(0); -} - -/* - * dn_find(domain, msg, dnptrs, lastdnptr) - * Search for the counted-label name in an array of compressed names. - * return: - * offset from msg if found, or -1. - * notes: - * dnptrs is the pointer to the first name on the list, - * not the pointer to the start of the message. - */ -static int -irc_dn_find(const unsigned char *domain, const unsigned char *msg, - const unsigned char * const *dnptrs, - const unsigned char * const *lastdnptr) -{ - const unsigned char *dn, *cp, *sp; - const unsigned char * const *cpp; - unsigned int n; - - for (cpp = dnptrs; cpp < lastdnptr; cpp++) - { - sp = *cpp; - /* - * terminate search on: - * root label - * compression pointer - * unusable offset - */ - while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && - (sp - msg) < 0x4000) { - dn = domain; - cp = sp; - while ((n = *cp++) != 0) { - /* - * check for indirection - */ - switch (n & NS_CMPRSFLGS) { - case 0: /* normal case, n == len */ - n = labellen(cp - 1); /* XXX */ - - if (n != *dn++) - goto next; - - for ((void)NULL; n > 0; n--) - if (mklower(*dn++) != - mklower(*cp++)) - goto next; - /* Is next root for both ? */ - if (*dn == '\0' && *cp == '\0') - return (sp - msg); - if (*dn) - continue; - goto next; - case NS_CMPRSFLGS: /* indirection */ - cp = msg + (((n & 0x3f) << 8) | *cp); - break; - - default: /* illegal type */ - errno = EMSGSIZE; - return (-1); - } - } - next: ; - sp += *sp + 1; - } - } - errno = ENOENT; - return (-1); -} - -/* - * * Thinking in noninternationalized USASCII (per the DNS spec), - * * convert this character to lower case if it's upper case. - * */ -static int -mklower(int ch) -{ - if (ch >= 0x41 && ch <= 0x5A) - return(ch + 0x20); - - return(ch); -} - -/* From resolv/mkquery.c */ - -/* - * Form all types of queries. - * Returns the size of the result or -1. - */ -int -irc_res_mkquery( - const char *dname, /* domain name */ - int class, int type, /* class and type of query */ - unsigned char *buf, /* buffer to put query */ - int buflen) /* size of buffer */ -{ - HEADER *hp; - unsigned char *cp; - int n; - const unsigned char *dnptrs[20], **dpp, **lastdnptr; - - /* - * Initialize header fields. - */ - if ((buf == NULL) || (buflen < HFIXEDSZ)) - return (-1); - memset(buf, 0, HFIXEDSZ); - hp = (HEADER *)(void *)buf; - - hp->id = 0; - hp->opcode = QUERY; - hp->rd = 1; /* recurse */ - hp->rcode = NO_ERRORS; - cp = buf + HFIXEDSZ; - buflen -= HFIXEDSZ; - dpp = dnptrs; - *dpp++ = buf; - *dpp++ = NULL; - lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; - - if ((buflen -= QFIXEDSZ) < 0) - return (-1); - if ((n = irc_dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) - return (-1); - - cp += n; - buflen -= n; - IRC_NS_PUT16(type, cp); - IRC_NS_PUT16(class, cp); - hp->qdcount = htons(1); - - return (cp - buf); -} diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 5001d1878..0587f3289 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -54,6 +54,7 @@ #include "chmode.h" #include "hook.h" #include "s_assert.h" +#include "authd.h" struct config_server_hide ConfigServerHide; @@ -646,7 +647,7 @@ rehash(int sig) "Got signal SIGHUP, reloading ircd conf. file"); } - restart_resolver(); + restart_authd(); /* don't close listeners until we know we can go ahead with the rehash */ read_conf_files(NO); diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 92e6a6046..20dd4ddd8 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -40,7 +40,6 @@ #include "ircd_defs.h" #include "numeric.h" #include "packet.h" -#include "res.h" #include "s_conf.h" #include "s_newconf.h" #include "logger.h" diff --git a/modules/m_rehash.c b/modules/m_rehash.c index 004bca664..84b542d06 100644 --- a/modules/m_rehash.c +++ b/modules/m_rehash.c @@ -32,7 +32,6 @@ #include "ircd.h" #include "s_serv.h" #include "numeric.h" -#include "res.h" #include "s_conf.h" #include "s_newconf.h" #include "logger.h" @@ -82,7 +81,7 @@ rehash_dns(struct Client *source_p) remote_rehash_oper_p = source_p; /* reread /etc/resolv.conf and reopen res socket */ - restart_resolver(); + restart_authd(); } static void