#include "ircd_alloc.h"
#include "ircd_log.h"
#include "ircd_osdep.h"
+#include "ircd_reply.h"
#include "ircd_string.h"
+#include "msg.h"
#include "numeric.h"
#include "s_bsd.h"
#include "s_debug.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
+#include <regex.h>
#include <arpa/nameser.h>
#include <resolv.h>
* Nov. 17, 1997 --Bleep
*/
-typedef struct Hostent {
+struct Hostent {
struct hostent h; /* the hostent struct we are passing around */
char* buf; /* buffer for data pointed to from hostent */
-} aHostent;
+};
struct ResRequest {
struct ResRequest* next;
struct in_addr addr;
char* name;
struct DNSQuery query; /* query callback for this request */
- aHostent he;
+ struct Hostent he;
};
struct CacheEntry {
const char* addr);
static struct ResRequest* find_id(int);
-static struct cacheinfo {
+static struct cacheinfo {
int ca_adds;
int ca_dels;
int ca_expires;
* paul vixie, 29may94
*/
static int
-res_ourserver(const struct __res_state* statp, const struct sockaddr_in *inp)
+res_ourserver(const struct __res_state* statp, const struct sockaddr_in* inp)
{
struct sockaddr_in ina;
int ns;
memset(hashtable, 0, sizeof(hashtable));
memset(&reinfo, 0, sizeof(reinfo));
- requestListHead = requestListTail = NULL;
+ requestListHead = requestListTail = 0;
errno = h_errno = 0;
+
start_resolver();
Debug((DEBUG_DNS, "Resolver: fd %d errno: %d h_errno: %d: %s",
- ResolverFileDescriptor, errno, h_errno, strerror(errno)));
+ ResolverFileDescriptor, errno, h_errno,
+ (strerror(errno)) ? strerror(errno) : "Unknown"));
return ResolverFileDescriptor;
}
start_resolver();
}
+static int validate_hostent(const struct hostent* hp)
+{
+ const char* name;
+ int i = 0;
+ assert(0 != hp);
+ for (name = hp->h_name; name; name = hp->h_aliases[i++]) {
+ if (!string_is_hostname(name))
+ return 0;
+ }
+ return 1;
+}
+
/*
* add_request - place a new request in the request list
*/
++sent;
}
else
- ircd_log(L_ERROR, "Resolver: send failed %s", strerror(errno));
+ ircd_log(L_ERROR, "Resolver: send failed %s",
+ (strerror(errno)) ? strerror(errno) : "Unknown");
}
return sent;
}
Debug((DEBUG_DNS, "Resolver: query_name: %s %d %d", name, query_class, type));
memset(buf, 0, sizeof(buf));
if ((request_len = res_mkquery(QUERY, name, query_class, type,
- NULL, 0, NULL, buf, sizeof(buf))) > 0) {
+ 0, 0, 0, (unsigned char*) buf, sizeof(buf))) > 0) {
HEADER* header = (HEADER*) buf;
#ifndef LRAND48
int k = 0;
++request->sends;
Debug((DEBUG_DNS, "Resolver: query_name %d: %s %d %d", request->id,
name, query_class, type));
- request->sent += send_res_msg(buf, request_len, request->sends);
+ request->sent += send_res_msg((const unsigned char*) buf, request_len, request->sends);
}
}
Debug((DEBUG_DNS, "Resolver: read"));
if (IO_SUCCESS != os_recvfrom_nonb(ResolverFileDescriptor,
- buf, sizeof(buf), &rc, &sin)) {
+ (char*) buf, sizeof(buf), &rc, &sin)) {
return 0;
}
if (rc < sizeof(HEADER)) {
- Debug((DEBUG_DNS, "Resolver: short reply %d: %s", rc, strerror(errno)));
+ Debug((DEBUG_DNS, "Resolver: short reply %d: %s", rc,
+ (strerror(errno)) ? strerror(errno) : "Unknown"));
return 0;
}
/*
* check against possibly fake replies
*/
if (!res_ourserver(&_res, &sin)) {
- Debug((DEBUG_DNS, "Resolver: fake reply from: %s",
- (const char*) &sin.sin_addr));
+ Debug((DEBUG_DNS, "Resolver: fake reply from: %s", (const char*) &sin.sin_addr));
++reinfo.re_unkrep;
return 1;
}
answer_count = proc_answer(request, header, buf, buf + rc);
if (answer_count) {
if (T_PTR == request->type) {
- struct DNSReply* reply = NULL;
+ struct DNSReply* reply = 0;
if (0 == request->he.h.h_name) {
/*
* got a PTR response with no name, something bogus is happening
* extra kludges.
*/
reply = gethost_byname(request->he.h.h_name, &request->query);
- if (0 == reply) {
+ if (reply) {
+ (*request->query.callback)(request->query.vptr, reply);
+ }
+ else {
/*
* If name wasn't found, a request has been queued and it will
* be the last one queued. This is rather nasty way to keep
request->he.buf = 0;
memcpy(&requestListTail->he.h, &request->he.h, sizeof(struct hostent));
}
- else
- (*request->query.callback)(request->query.vptr, reply);
rem_request(request);
}
else {
* PTR returned a CNAME, cp was not checked before so the
* callback was being called with a value of 0x2C != NULL.
*/
- cp = make_cache(request);
- (*request->query.callback)(request->query.vptr,
- (cp) ? &cp->reply : 0);
+ struct DNSReply* reply = 0;
+ if (validate_hostent(&request->he.h)) {
+ if ((cp = make_cache(request)))
+ reply = &cp->reply;
+ }
+ (*request->query.callback)(request->query.vptr, reply);
rem_request(request);
}
}
* dup_hostent - Duplicate a hostent struct, allocate only enough memory for
* the data we're putting in it.
*/
-static void dup_hostent(aHostent* new_hp, struct hostent* hp)
+static void dup_hostent(struct Hostent* new_hp, struct hostent* hp)
{
char* p;
char** ap;
/*
* update_hostent - Add records to a Hostent struct in place.
*/
-static void update_hostent(aHostent* hp, char** addr, char** alias)
+static void update_hostent(struct Hostent* hp, char** addr, char** alias)
{
char* p;
char** ap;
ocp->hname_next = hashtable[hashv].name_list;
hashtable[hashv].name_list = ocp;
- hashv = hash_number(ocp->he.h.h_addr);
+ hashv = hash_number((const unsigned char*) ocp->he.h.h_addr);
ocp->hnum_next = hashtable[hashv].num_list;
hashtable[hashv].num_list = ocp;
int i;
assert(0 != addr);
- hashv = hash_number(addr);
+ hashv = hash_number((const unsigned char*) addr);
cp = hashtable[hashv].num_list;
for (; cp; cp = cp->hnum_next) {
* are looking for, its been done already.
*/
if (!cp->he.h.h_addr_list[1] ||
- hashv == hash_number(cp->he.h.h_addr_list[0]))
+ hashv == hash_number((const unsigned char*) cp->he.h.h_addr_list[0]))
continue;
for (i = 1; cp->he.h.h_addr_list[i]; ++i) {
if (!memcmp(cp->he.h.h_addr_list[i], addr, sizeof(struct in_addr))) {
/*
* remove cache entry from hashed number list
*/
- hashv = hash_number(hp->h_addr);
+ hashv = hash_number((const unsigned char*) hp->h_addr);
assert(-1 < hashv);
for (cp = &hashtable[hashv].num_list; *cp; cp = &((*cp)->hnum_next)) {
if (parv[1] && *parv[1] == 'l') {
for(cp = cacheTop; cp; cp = cp->list_next) {
hp = &cp->he.h;
- sendto_one(sptr, "NOTICE %s :Ex %d ttl %d host %s(%s)",
- parv[0], cp->expireat - CurrentTime, cp->ttl,
- hp->h_name, ircd_ntoa(hp->h_addr));
+ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Ex %d ttl %d host %s(%s)",
+ sptr, cp->expireat - CurrentTime, cp->ttl,
+ hp->h_name, ircd_ntoa(hp->h_addr));
for (i = 0; hp->h_aliases[i]; i++)
- sendto_one(sptr,"NOTICE %s : %s = %s (CN)",
- parv[0], hp->h_name, hp->h_aliases[i]);
+ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C : %s = %s (CN)", sptr,
+ hp->h_name, hp->h_aliases[i]);
for (i = 1; hp->h_addr_list[i]; i++)
- sendto_one(sptr,"NOTICE %s : %s = %s (IP)",
- parv[0], hp->h_name, ircd_ntoa(hp->h_addr_list[i]));
+ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C : %s = %s (IP)", sptr,
+ hp->h_name, ircd_ntoa(hp->h_addr_list[i]));
}
return 0;
}
if (parv[1] && *parv[1] == 'd') {
- sendto_one(sptr, "NOTICE %s :ResolverFileDescriptor = %d",
- parv[0], ResolverFileDescriptor);
+ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :ResolverFileDescriptor = %d",
+ sptr, ResolverFileDescriptor);
return 0;
}
- sendto_one(sptr,"NOTICE %s :Ca %d Cd %d Ce %d Cl %d Ch %d:%d Cu %d",
- sptr->name,
- cainfo.ca_adds, cainfo.ca_dels, cainfo.ca_expires,
- cainfo.ca_lookups, cainfo.ca_na_hits, cainfo.ca_nu_hits,
- cainfo.ca_updates);
+ sendcmdto_one(&me, CMD_NOTICE, sptr,"%C :Ca %d Cd %d Ce %d Cl %d Ch %d:%d "
+ "Cu %d", sptr,
+ cainfo.ca_adds, cainfo.ca_dels, cainfo.ca_expires,
+ cainfo.ca_lookups, cainfo.ca_na_hits, cainfo.ca_nu_hits,
+ cainfo.ca_updates);
- sendto_one(sptr,"NOTICE %s :Re %d Rl %d/%d Rp %d Rq %d",
- sptr->name, reinfo.re_errors, reinfo.re_nu_look,
- reinfo.re_na_look, reinfo.re_replies, reinfo.re_requests);
- sendto_one(sptr,"NOTICE %s :Ru %d Rsh %d Rs %d(%d) Rt %d", sptr->name,
- reinfo.re_unkrep, reinfo.re_shortttl, reinfo.re_sent,
- reinfo.re_resends, reinfo.re_timeouts);
+ sendcmdto_one(&me, CMD_NOTICE, sptr,"%C :Re %d Rl %d/%d Rp %d Rq %d",
+ sptr, reinfo.re_errors, reinfo.re_nu_look,
+ reinfo.re_na_look, reinfo.re_replies, reinfo.re_requests);
+ sendcmdto_one(&me, CMD_NOTICE, sptr,"%C :Ru %d Rsh %d Rs %d(%d) Rt %d", sptr,
+ reinfo.re_unkrep, reinfo.re_shortttl, reinfo.re_sent,
+ reinfo.re_resends, reinfo.re_timeouts);
#endif
return 0;
}
request_mem += MAXGETHOSTLEN + 1;
++request_count;
}
+
if (cachedCount != cache_count) {
- sendto_one(sptr,
- ":%s %d %s :Resolver: cache count mismatch: %d != %d",
- me.name, RPL_STATSDEBUG, sptr->name, cachedCount, cache_count);
+ send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG,
+ ":Resolver: cache count mismatch: %d != %d", cachedCount,
+ cache_count);
assert(cachedCount == cache_count);
}
- sendto_one(sptr, ":%s %d %s :Resolver: cache %d(%d) requests %d(%d)",
- me.name, RPL_STATSDEBUG, sptr->name, cache_count, cache_mem,
- request_count, request_mem);
+ send_reply(sptr, SND_EXPLICIT | RPL_STATSDEBUG,
+ ":Resolver: cache %d(%d) requests %d(%d)", cache_count,
+ cache_mem, request_count, request_mem);
return cache_mem + request_mem;
}