/* ----------------------------------------------------------------------------
NSTX -- tunneling network-packets over DNS
(C) 2000 by Julien Oster and Florian Heinz
This program 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 program 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#include <time.h>
#include <sysexits.h>
#include "nstxfun.h"
#include "nstx_dns.h"
#include "nstxdns.h"
#include "nstx_pstack.h"
#define DRQLEN 10
static void nstxc_handle_reply(char *, int);
static int nstxc_send_packet(char *, int);
static int nsid;
int gotpacket = 0;
static void
usage(const char *prog, int code)
{
fprintf(stderr, "Usage: %s [-d tun-device] <domainname> <dns-server>\n"
"Example: %s tun.yomama.com 125.23.53.12\n", prog, prog);
exit(code);
}
int main (int argc, char * argv[]) {
struct nstxmsg *msg;
const char *device = NULL;
int ch;
nsid = time(NULL);
if (argc < 3)
usage(argv[0], EX_USAGE);
while ((ch = getopt(argc, argv, "hd:")) != -1) {
switch (ch) {
case 'd':
device = optarg;
break;
case 'h':
usage(argv[0], 0);
default:
usage(argv[0], EX_USAGE);
}
}
dns_setsuffix(argv[optind]);
qsettimeout(10);
open_tuntap(device);
open_ns(argv[optind + 1]);
for (;;) {
msg = nstx_select(1);
if (msg) {
if (msg->src == FROMNS) {
nstxc_handle_reply (msg->data, msg->len);
} else if (msg->src == FROMTUN) {
nstxc_send_packet (msg->data, msg->len);
}
}
timeoutqueue(NULL);
while (queuelen() < DRQLEN)
nstxc_send_packet (NULL, 0);
}
return 0;
}
static void nstxc_handle_reply (char * reply, int len) {
struct dnspkt *pkt;
const char *data;
int datalen;
pkt = dns_extractpkt ((unsigned char*)reply, len);
if (!pkt)
return;
while ((data = dns_getanswerdata(pkt, &datalen))) {
data = (char*)txt2data((unsigned char*)data, &datalen);
nstx_handlepacket (data, datalen, &sendtun);
}
dequeueitem(pkt->id);
dns_free(pkt);
}
static int nstxc_send_packet (char *data, int datalen) {
static int id = -1;
char *p;
struct nstxhdr nh;
struct dnspkt *pkt;
int l;
if (id < 0)
id = time(NULL);
nh.magic = NSTX_MAGIC;
nh.seq = 0;
nh.id = id++;
nh.flags = 0;
do {
pkt = dns_alloc();
dns_settype(pkt, DNS_QUERY);
dns_setid(pkt, nsid);
l = dns_getfreespace(pkt, DNS_QUERY);
if (l <= 0) {
printf("Fatal: no free space in dns-packet?!\n");
exit(1);
}
p = malloc(l);
l -= sizeof(nh);
if (l > datalen) {
l = datalen;
nh.flags = NSTX_LF;
}
memcpy (p, (char*)&nh, sizeof(nh));
if (data)
memcpy (p + sizeof(nh), data, l);
data += l;
datalen -= l;
dns_addquery(pkt, dns_data2fqdn(nstx_encode((unsigned char*)p, sizeof(nh)+l)));
free(p);
p = (char*)dns_constructpacket(pkt, &l);
sendns(p, l, NULL);
free(p);
queueid(nsid);
nsid++;
nh.seq++;
} while (datalen);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1