* 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 <tomh@inxpress.net>)
* January 2016 --kaniini
*/
-#include <ratbox_lib.h>
+#include <rb_lib.h>
#include "setup.h"
#include "res.h"
#include "reslib.h"
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
#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)
* 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_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;
+ 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;
#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_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;
}
/*
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;
/*
* 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;
}
}
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
*/
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));
+ (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",
+ (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),
+ suffix == NULL ? "ip6.arpa" : suffix);
}
#endif
+}
+
+/*
+ * 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);
switch (request->type)
{
- case T_PTR:
- do_query_number(NULL, &request->addr, request);
- break;
- case T_A:
+ case T_PTR:
+ do_query_number(NULL, &request->addr, request);
+ break;
+ case T_A:
#ifdef RB_IPV6
- case T_AAAA:
+ case T_AAAA:
#endif
- do_query_name(NULL, request->name, request, request->type);
- break;
- default:
- break;
+ do_query_name(NULL, request->name, request, request->type);
+ break;
+ default:
+ break;
}
}
*/
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;
+ 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;
+ 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_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;
}
}
* 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