netsukuku/src/dns_wrapper.c

175 lines
4.5 KiB
C
Raw Normal View History

2013-09-16 09:53:25 +00:00
/* This file is part of Netsukuku
* (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* Please refer to the GNU Public License for more details.
*
* You should have received a copy of the GNU Public License along with
* this source code; if not, write to:
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* --
* dns_wrapper.c:
*
* The DNS wrapper listens to the port 53 for DNS hostname resolution queries,
* it then resolves the hostname by using the ANDNA system and sends back the
* resolved ip. In this way, every program can use ANDNA: just set
* "nameserver localhost"
* in /etc/resolv.conf ;)
*/
#include "includes.h"
#include "inet.h"
#include "endianness.h"
#include "map.h"
#include "gmap.h"
#include "bmap.h"
#include "route.h"
#include "request.h"
#include "pkts.h"
#include "tracer.h"
#include "qspn.h"
#include "radar.h"
#include "netsukuku.h"
#include "daemon.h"
#include "crypto.h"
#include "andna_cache.h"
#include "andna.h"
#include "andns.h"
#include "dns_wrapper.h"
#include "common.h"
/*
* dns_exec_pkt: resolve the hostname contained in the DNS query and sends
* the reply to from.
* `passed_argv' is a pointer to a dns_exec_pkt_argv struct.
*/
void *dns_exec_pkt(void *passed_argv)
{
struct dns_exec_pkt_argv argv;
char buf[MAX_DNS_PKT_SZ];
char answer_buffer[ANDNS_MAX_SZ];
int answer_length;
int bytes_sent;
memcpy(&argv, passed_argv, sizeof(struct dns_exec_pkt_argv));
memcpy(&buf, argv.rpkt, argv.rpkt_sz);
pthread_mutex_unlock(&dns_exec_lock);
if (argv.rpkt_sz < MIN_PKT_SZ) {
debug(DBG_NORMAL, "Received malformed DNS packet");
return 0;
}
/* Unpack the DNS query and resolve the hostname */
if(!andns_rslv(buf, argv.rpkt_sz, answer_buffer, &answer_length))
return 0;
/* Send the DNS reply */
bytes_sent=inet_sendto(argv.sk, answer_buffer, answer_length, 0,
&argv.from, argv.from_len);
if(bytes_sent != answer_length)
debug(DBG_SOFT, ERROR_MSG "inet_sendto error: %s", ERROR_POS,
strerror(errno));
return 0;
}
/*
* dns_wrapper_daemon: It receives DNS query pkts, resolves them in ANDNA and
* replies with a DNS reply.
* It listens to `port'.
*/
void dns_wrapper_daemon(u_short port)
{
struct dns_exec_pkt_argv exec_pkt_argv;
char buf[MAX_DNS_PKT_SZ];
fd_set fdset;
int ret, sk;
pthread_t thread;
pthread_attr_t t_attr;
ssize_t err=-1;
#ifdef DEBUG
int select_errors=0;
#endif
pthread_attr_init(&t_attr);
pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
pthread_mutex_init(&dns_exec_lock, 0);
debug(DBG_SOFT, "Preparing the dns_udp listening socket on port %d", port);
sk=prepare_listen_socket(my_family, SOCK_DGRAM, port, 0);
if(sk == -1)
return;
debug(DBG_NORMAL, "DNS wrapper daemon on port %d up & running", port);
for(;;) {
if(!sk)
fatal("The dns_wrapper_daemon socket got corrupted");
FD_ZERO(&fdset);
FD_SET(sk, &fdset);
ret = select(sk+1, &fdset, NULL, NULL, NULL);
if(sigterm_timestamp)
/* NetsukukuD has been closed */
break;
if (ret < 0) {
#ifdef DEBUG
if(select_errors > 20)
break;
select_errors++;
#endif
error("dns_wrapper_daemonp: select error: %s",
strerror(errno));
continue;
}
if(!FD_ISSET(sk, &fdset))
continue;
setzero(&buf, MAX_DNS_PKT_SZ);
setzero(&exec_pkt_argv.from, sizeof(struct sockaddr));
setzero(&exec_pkt_argv, sizeof(struct dns_exec_pkt_argv));
exec_pkt_argv.from_len = my_family == AF_INET ?
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
/* we get the DNS query */
err=inet_recvfrom(sk, buf, MAX_DNS_PKT_SZ, MSG_WAITALL,
&exec_pkt_argv.from, &exec_pkt_argv.from_len);
if(err < 0) {
debug(DBG_NOISE, "dns_wrapper_daemonp: recv of the dns"
" query pkt aborted!");
continue;
}
/* Exec the pkt in another thread */
exec_pkt_argv.sk=sk;
exec_pkt_argv.rpkt_sz=err;
exec_pkt_argv.rpkt=buf;
pthread_mutex_lock(&dns_exec_lock);
pthread_create(&thread, &t_attr, dns_exec_pkt,
(void *)&exec_pkt_argv);
pthread_mutex_lock(&dns_exec_lock);
pthread_mutex_unlock(&dns_exec_lock);
}
}
void *dns_wrapper_thread(void *null)
{
dns_wrapper_daemon(DNS_WRAPPER_PORT);
return 0;
}