X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/1b7a47417b303f48217e495e201daee82eeefedf..4abf8eb2e6066c1c1456f5978cd9a613992a468e:/authd/res.c diff --git a/authd/res.c b/authd/res.c index b2313d9d..0336b462 100644 --- a/authd/res.c +++ b/authd/res.c @@ -32,7 +32,7 @@ * January 2016 --kaniini */ -#include +#include #include "setup.h" #include "res.h" #include "reslib.h" @@ -44,8 +44,6 @@ 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 @@ -58,9 +56,7 @@ static PF res_readreply; #define RDLENGTH_SIZE (size_t)2 #define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE) -#ifdef RB_IPV6 struct in6_addr ipv6_addr; -#endif struct in_addr ipv4_addr; struct reslist @@ -98,64 +94,8 @@ static int check_question(struct reslist *request, HEADER * header, char *buf, c 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); -static int generate_random_port(void); static uint16_t generate_random_id(void); -#ifdef RES_MIN -#undef RES_MIN -#endif - -#define RES_MIN(a, b) ((a) < (b) ? (a) : (b)) - -static rb_fde_t * -random_socket(int family) -{ - rb_fde_t *F; - int nport; - int i; - rb_socklen_t len; - struct rb_sockaddr_storage sockaddr; - F = rb_socket(family, SOCK_DGRAM, 0, "UDP resolver socket"); - if(F == NULL) - return NULL; - - memset(&sockaddr, 0, sizeof(sockaddr)); - - SET_SS_FAMILY(&sockaddr, family); - -#ifdef RB_IPV6 - if(family == AF_INET6) - { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&sockaddr; - memcpy(&in6->sin6_addr, &ipv6_addr, sizeof(struct in6_addr)); - len = (rb_socklen_t) sizeof(struct sockaddr_in6); - } - else -#endif - { - struct sockaddr_in *in = (struct sockaddr_in *)&sockaddr; - in->sin_addr.s_addr = ipv4_addr.s_addr; - len = (rb_socklen_t) sizeof(struct sockaddr_in); - } - - for(i = 0; i < 10; i++) - { - nport = htons(generate_random_port()); - - if(family == AF_INET) - ((struct sockaddr_in *)&sockaddr)->sin_port = nport; -#ifdef RB_IPV6 - else - ((struct sockaddr_in6 *)&sockaddr)->sin6_port = nport; - -#endif - if(bind(rb_get_fd(F), (struct sockaddr *)&sockaddr, len) == 0) - return F; - } - rb_close(F); - return NULL; -} - /* * int * res_ourserver(inp) @@ -167,59 +107,48 @@ random_socket(int family) * revised for ircd, cryogen(stu) may03 * slightly modified for charybdis, mr_flea oct12 */ -static int res_ourserver(const struct rb_sockaddr_storage *inp) +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++) + 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 + * but we'll air on the side of caution - stu */ - switch (srv->ss_family) + switch (GET_SS_FAMILY(srv)) { -#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; + case AF_INET6: + if(GET_SS_FAMILY(srv) == GET_SS_FAMILY(inp)) + 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 1; + break; + case AF_INET: + if(GET_SS_FAMILY(srv) == GET_SS_FAMILY(inp)) + 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 1; + break; + default: + break; } } - return -1; + return 0; } /* @@ -280,7 +209,7 @@ static void start_resolver(void) if (res_fd == NULL) { - if ((res_fd = rb_socket(irc_nsaddr_list[0].ss_family, SOCK_DGRAM, 0, + if ((res_fd = rb_socket(GET_SS_FAMILY(&irc_nsaddr_list[0]), SOCK_DGRAM, 0, "UDP resolver socket")) == NULL) return; @@ -316,7 +245,7 @@ void restart_resolver(void) * 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) +static void add_local_domain(char *hname, size_t size) { /* try to fix up unqualified names */ if (strchr(hname, '.') == NULL) @@ -377,21 +306,23 @@ static struct reslist *make_request(struct DNSQuery *query) /* * retryfreq - determine how many queries to wait before resending * if there have been that many consecutive timeouts + * + * This is a cubic backoff btw, if anyone didn't pick up on it. --Elizafox */ 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; + case 1: + return 3; + case 2: + return 9; + case 3: + return 27; + case 4: + return 81; + default: + return 243; } } @@ -472,20 +403,6 @@ generate_random_id(void) return id; } -static int -generate_random_port(void) -{ - uint16_t port; - - while(1) - { - rb_get_random(&port, sizeof(port)); - if(port > 1024) - break; - } - return (int)port; -} - /* * gethost_byname_type - get host address from name, adding domain if needed */ @@ -534,55 +451,70 @@ static void do_query_name(struct DNSQuery *query, const char *name, struct resli 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) +/* Build an rDNS style query - if suffix is NULL, use the appropriate .arpa zone */ +void build_rdns(char *buf, size_t size, const struct rb_sockaddr_storage *addr, const char *suffix) { 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) + if (GET_SS_FAMILY(addr) == AF_INET) { const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr; cp = (const unsigned char *)&v4->sin_addr.s_addr; - 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])); + (void) snprintf(buf, size, "%u.%u.%u.%u.%s", + (unsigned int)(cp[3]), + (unsigned int)(cp[2]), + (unsigned int)(cp[1]), + (unsigned int)(cp[0]), + suffix == NULL ? "in-addr.arpa" : suffix); } -#ifdef RB_IPV6 - else if (addr->ss_family == AF_INET6) + else if (GET_SS_FAMILY(addr) == 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)); +#define HI_NIBBLE(x) (unsigned int)((x) >> 4) +#define LO_NIBBLE(x) (unsigned int)((x) & 0xf) + + (void) snprintf(buf, size, + "%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.%s", + LO_NIBBLE(cp[15]), HI_NIBBLE(cp[15]), + LO_NIBBLE(cp[14]), HI_NIBBLE(cp[14]), + LO_NIBBLE(cp[13]), HI_NIBBLE(cp[13]), + LO_NIBBLE(cp[12]), HI_NIBBLE(cp[12]), + LO_NIBBLE(cp[11]), HI_NIBBLE(cp[11]), + LO_NIBBLE(cp[10]), HI_NIBBLE(cp[10]), + LO_NIBBLE(cp[9]), HI_NIBBLE(cp[9]), + LO_NIBBLE(cp[8]), HI_NIBBLE(cp[8]), + LO_NIBBLE(cp[7]), HI_NIBBLE(cp[7]), + LO_NIBBLE(cp[6]), HI_NIBBLE(cp[6]), + LO_NIBBLE(cp[5]), HI_NIBBLE(cp[5]), + LO_NIBBLE(cp[4]), HI_NIBBLE(cp[4]), + LO_NIBBLE(cp[3]), HI_NIBBLE(cp[3]), + LO_NIBBLE(cp[2]), HI_NIBBLE(cp[2]), + LO_NIBBLE(cp[1]), HI_NIBBLE(cp[1]), + LO_NIBBLE(cp[0]), HI_NIBBLE(cp[0]), + suffix == NULL ? "ip6.arpa" : suffix); } -#endif + +#undef HI_NIBBLE +#undef LO_NIBBLE +} + +/* + * 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) +{ + 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); + } + + build_rdns(request->queryname, IRCD_RES_HOSTLEN + 1, addr, NULL); request->type = T_PTR; query_name(request); @@ -623,17 +555,15 @@ static void resend_query(struct reslist *request) 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; + case T_PTR: + do_query_number(NULL, &request->addr, request); + break; + case T_A: + case T_AAAA: + do_query_name(NULL, request->name, request, request->type); + break; + default: + break; } } @@ -655,7 +585,7 @@ static int check_question(struct reslist *request, HEADER * header, char *buf, c sizeof(hostbuf)); if (n <= 0) return 0; - if (strcasecmp(hostbuf, request->queryname)) + if (rb_strcasecmp(hostbuf, request->queryname)) return 0; return 1; } @@ -671,9 +601,7 @@ static int proc_answer(struct reslist *request, HEADER * header, char *buf, char 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) @@ -737,56 +665,46 @@ static int proc_answer(struct reslist *request, HEADER * header, char *buf, char */ 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: - break; + 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); + 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); + 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); } + /* skip any other record type e.g. CNAME, DNAME; real answer should follow */ + current += rd_length; } return (1); @@ -917,11 +835,9 @@ static int res_read_single_reply(rb_fde_t *F, void *data) * Lookup the 'authoritative' name that we were given for the * ip#. */ -#ifdef RB_IPV6 - if (request->addr.ss_family == AF_INET6) + if (GET_SS_FAMILY(&request->addr) == 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); }