#include "jabberd.h"
#include "srv_resolv.h"
#include <sys/wait.h>
typedef struct __dns_resend_list
{
char* service;
char* host;
struct __dns_resend_list* next;
} *dns_resend_list, _dns_resend_list;
typedef struct
{
int in;
int out;
int pid;
HASHTABLE packet_table;
int packet_timeout;
HASHTABLE cache_table;
int cache_timeout;
pool mempool;
dns_resend_list svclist;
} *dns_io, _dns_io;
typedef int (*RESOLVEFUNC)(dns_io di);
typedef struct __dns_packet_list
{
dpacket packet;
int stamp;
struct __dns_packet_list* next;
} *dns_packet_list, _dns_packet_list;
int debug_flag;
int get_debug_flag() {
return debug_flag;
}
void set_debug_flag(int v) {
debug_flag = v;
}
void dnsrv_child_process_xstream_io(int type, xmlnode x, void* args)
{
dns_io di = (dns_io)args;
char* hostname;
char* service;
char* str = NULL;
dns_resend_list iternode = NULL;
dns_resend_list tmplist = NULL;
if (type == XSTREAM_NODE) {
if (!strcmp(x->name, "resend")) {
service = xmlnode_get_attrib(x, "service");
hostname = xmlnode_get_data(x);
if (hostname != NULL) {
log_debug(NULL, "dnsrv: Recv'd service entry: %s (%s)",
service ? service : "<None>",
hostname);
tmplist = pmalloco(di->mempool, sizeof(_dns_resend_list));
tmplist->service = pstrdup(di->mempool, service);
tmplist->host = pstrdup(di->mempool, hostname);
tmplist->next = di->svclist;
di->svclist = tmplist;
}
} else {
hostname = xmlnode_get_data(x);
log_debug(NULL, "dnsrv: Recv'd lookup request for %s", hostname);
if (hostname != NULL)
{
iternode = di->svclist;
while (iternode != NULL)
{
str = srv_lookup(x->p, iternode->service, hostname);
if (str != NULL)
{
log_debug(NULL, "Resolved %s(%s): %s\tresend to:%s", hostname, iternode->service, str, iternode->host);
xmlnode_put_attrib(x, "ip", str);
xmlnode_put_attrib(x, "to", iternode->host);
break;
}
iternode = iternode->next;
}
str = xmlnode2str(x);
write(di->out, str, strlen(str));
}
}
}
xmlnode_free(x);
}
int dnsrv_child_main(dns_io di)
{
pool p = pool_new();
xstream xs = xstream_new(p, dnsrv_child_process_xstream_io, di);
int len;
char readbuf[1024];
sigset_t sigs;
di->mempool = p;
sigemptyset(&sigs);
sigaddset(&sigs, SIGHUP);
sigprocmask(SIG_BLOCK, &sigs, NULL);
log_debug(NULL,"DNSRV CHILD: starting");
write(di->out, "<stream>", 8);
while (1)
{
len = read(di->in, &readbuf, 1024);
if (len <= 0)
{
log_debug(NULL,"dnsrv: Read error on coprocess(%d): %d %s",getppid(),errno,strerror(errno));
break;
}
log_debug(NULL, "DNSRV CHILD: Read from buffer: %.*s",len,readbuf);
if (xstream_eat(xs, readbuf, len) > XSTREAM_NODE)
{
log_debug(NULL, "DNSRV CHILD: xstream died");
break;
}
}
log_debug(NULL, "DNSRV CHILD: out of loop.. exiting normal");
pool_free(p);
exit(0);
return 0;
}
char *debug_log_timestamp(void)
{
time_t t;
int sz;
char *tmp_str;
t = time(NULL);
if(t == (time_t)-1)
return NULL;
tmp_str = ctime(&t);
sz = strlen(tmp_str);
tmp_str[sz-1]=' ';
return tmp_str;
}
void debug_log(char *zone, const char *msgfmt, ...) {
va_list ap;
char *pos, c = '\0';
if(zone != NULL) {
pos = strchr(zone,'.');
if(pos != NULL) {
c = *pos;
*pos = '\0';
}
if(pos != NULL)
*pos = c;
}
fprintf(stderr, "%s %s ", debug_log_timestamp(), zone);
va_start(ap, msgfmt);
vfprintf(stderr, msgfmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
int main(int argc, char* argv[]) {
_dns_io di;
if (argc < 4) {
fprintf(stderr, "Syntax: jabadns <read handle> <write handle>");
fprintf(stderr, "<debug flag>\n");
exit(1);
}
di.in = atoi(argv[1]);
di.out = atoi(argv[2]);
set_debug_flag(atoi(argv[3]));
di.svclist = NULL;
di.pid = -1;
di.packet_table = NULL;
di.packet_timeout = 0;
di.cache_table = NULL;
di.cache_timeout = 0;
di.mempool = NULL;
dnsrv_child_main(&di);
return 1;
}