dnsproxy.c revision 54fe561ef34bc91e6d39efe592aa5fc2d31a0cbd
/* $Id$ */
/*
* Copyright (c) 2003,2004,2005 Armin Wolfermann
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef VBOX
#include <config.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#else
#include "slirp.h"
#endif
#ifndef VBOX
#define GLOBALS 1
#include "dnsproxy.h"
#define MAX_BUFSPACE 512
static unsigned short queryid = 0;
static struct sockaddr_in authoritative_addr;
static struct sockaddr_in recursive_addr;
static int sock_query;
static int sock_answer;
static int dnsproxy_sig;
extern int event_gotsig;
extern int (*event_sigcb)(void);
#ifdef DEBUG
char *malloc_options = "AGZ";
#endif
/* signal_handler -- Native signal handler. Set external flag for libevent
* and store type of signal. Real signal handling is done in signal_event.
*/
signal_handler(int sig)
{
event_gotsig = 1;
dnsproxy_sig = sig;
}
/* signal_event -- Called by libevent to deliver a signal.
*/
int
signal_event(void)
{
return 0;
}
#else
# define MAX_BUFSPACE 512
#endif
/* timeout -- Called by the event loop when a query times out. Removes the
* query from the queue.
*/
/* ARGSUSED */
#ifndef VBOX
static void
{
/* here we should check if we reached the end of the DNS server list */
}
#else
static void
{
/* here we should check if we reached the end of the DNS server list */
{
}
else
{
int iphlen;
char *data;
{
LogRel(("NAT: can't create DNS socket \n"));
return;
}
{
LogRel(("NAT: can't attach udp socket\n"));
return;
}
if (m == NULL)
{
LogRel(("NAT: Can't allocate mbuf\n"));
return;
}
/* mbuf initialization */
m->m_data += if_maxlinkhdr;
}
}
#endif
/* do_query -- Called by the event loop when a packet arrives at our
* listening socket. Read the packet, create a new query, append it to the
* queue and send it to the correct server.
*
* Slirp: this routine should be called from udp_input
* socket is Slirp's construction (here we should set expiration time for socket)
* mbuf points on ip header to easy fetch information about source and destination.
* iphlen - len of ip header
*/
/* ARGSUSED */
#ifndef VBOX
static void
#else
void
#endif
{
#ifndef VBOX
char buf[MAX_BUFSPACE];
#else
char *buf;
int retransmit;
#endif
struct sockaddr_in addr;
#ifndef VBOX
struct sockaddr_in fromaddr;
#else
struct sockaddr_in fromaddr = { 0, };
#endif
int byte = 0;
++all_queries;
#ifndef VBOX
/* Reschedule event */
/* read packet from socket */
return;
}
#else
/* the validness of ip and udp header has been already checked so we shouldn't care if */
#endif
/* check for minimum dns packet length */
if (byte < 12) {
LogRel(("query too short from %s",
return;
}
#ifndef VBOX
/* allocate new request */
return;
}
#else
/* allocate new request */
{
return;
}
}
/* fill the request structure */
{
{
static int fail_counter = 0;
if (fail_counter == 0)
else
return;
}
retransmit = 0;
}
else
{
retransmit = 1;
}
#endif
#ifndef VBOX
/* where is this query coming from? */
} else {
/* no recursion for foreigners */
}
/* insert it into the hash table */
#else
if (retransmit == 0)
#endif
/* overwrite the original query id */
#ifndef VBOX
/* recursive queries timeout in 90s */
/* send it to our recursive server */
(struct sockaddr *)&recursive_addr,
sizeof(struct sockaddr_in))) == -1) {
return;
}
} else {
/* authoritative queries timeout in 10s */
/* send it to our authoritative server */
(struct sockaddr *)&authoritative_addr,
sizeof(struct sockaddr_in))) == -1) {
return;
}
#else
/* send it to our authoritative server */
sizeof(struct sockaddr_in))) == -1) {
return;
}
#endif
#ifndef VBOX
}
#endif
}
/* do_answer -- Process a packet coming from our authoritative or recursive
* server. Find the corresponding query and send answer back to querying
* host.
*
* Slirp: we call this from the routine from socrecvfrom routine handling UDP responses.
* So at the moment of call response already has been readed and packed into the mbuf
*/
/* ARGSUSED */
#ifndef VBOX
static void
#else
void
#endif
{
#ifndef VBOX
char buf[MAX_BUFSPACE];
int byte = 0;
/* Reschedule event */
/* read packet from socket */
return;
}
#else
char *buf;
int byte;
#endif
/* check for minimum dns packet length */
if (byte < 12) {
LogRel(("answer too short"));
return;
}
/* find corresponding query */
#ifdef VBOX
++late_answers;
/* Probably, this request wasn't serviced by
* dnsproxy so we won't care about it here*/
Log2(("NAT: query wasn't found\n"));
return;
}
#else
++late_answers;
return;
}
#endif
/* restore original query id */
#ifndef VBOX
/* Slirp: will send mbuf to guest by itself */
/* send answer back to querying host */
sizeof(struct sockaddr_in)) == -1) {
} else
#else
#endif
}
/* main -- dnsproxy main function
*/
#ifndef VBOX
int
{
int ch;
struct sockaddr_in addr;
const char *config = "/etc/dnsproxy.conf";
int daemonize = 0;
/* Process commandline arguments */
switch (ch) {
case 'c':
break;
case 'd':
daemonize = 1;
break;
case 'V':
exit(0);
/* FALLTHROUGH */
case 'h':
default:
"usage: dnsproxy [-c file] [-dhV]\n" \
"\t-c file Read configuration from file\n" \
"\t-d Detach and run as a daemon\n" \
"\t-h This help text\n" \
"\t-V Show version information\n");
exit(1);
}
}
/* Parse configuration and check required parameters */
fatal("unable to parse configuration");
if (!authoritative || !recursive)
fatal("No authoritative or recursive server defined");
if (!listenat)
/* Create and bind query socket */
/* Create and bind answer socket */
/* Fill sockaddr_in structs for both servers */
/* Daemonize if requested and switch to syslog */
if (daemonize) {
if (daemon(0, 0) == -1)
fatal("unable to daemonize");
log_syslog("dnsproxy");
}
/* Find less privileged user */
if (user) {
if (!pw)
}
/* Do a chroot if requested */
if (chrootdir) {
chdir("/");
}
/* Drop privileges */
if (user) {
#if defined(HAVE_SETRESGID)
#elif defined(HAVE_SETREGID)
#else
#endif
#if defined(HAVE_SETRESUID)
#elif defined(HAVE_SETREUID)
#else
#endif
}
/* Init event handling */
event_init();
/* Zero counters and start statistics timer */
/* Take care of signals */
/* Start libevent main loop */
return 0;
}
#else
int
{
/* globals initialization */
authoritative_port = 53;
authoritative_timeout = 10;
recursive_port = 53;
recursive_timeout = 2;
stats_timeout = 3600;
dns_port = 53;
return 0;
}
#endif