1
/* Copyright (c) 2009 Sam Trenholme
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
15
* This software is provided 'as is' with no guarantees of correctness or
16
* fitness for purpose.
19
/* This is a simple DNS-over-TCP server that reads a DNS packet over
20
* port 53 TCP, then outputs that packet on the standard input. Then
21
* the program reads standard input and outputs the DNS packet on
28
#include <sys/socket.h>
29
#include <arpa/inet.h>
30
#include <netinet/in.h>
33
/* We use a special SOCKET type for easier Windows porting */
36
/* Get port: Get a port locally and return the socket the port is on */
37
SOCKET get_port(uint32_t ip, struct sockaddr_in *dns) {
42
sock = socket(AF_INET,SOCK_STREAM,0);
44
perror("socket error");
47
memset(dns,0,sizeof(struct sockaddr_in));
48
dns->sin_family = AF_INET;
49
dns->sin_port = htons(53);
50
dns->sin_addr.s_addr = ip;
51
if(dns->sin_addr.s_addr == INADDR_NONE) {
52
perror("Problem with bind");
55
len_inet = sizeof(struct sockaddr_in);
56
if(bind(sock,(struct sockaddr *)dns,len_inet) == -1) {
61
/* Linux kernel bug */
62
/* fcntl(sock, F_SETFL, O_NONBLOCK); */
67
#define calc_dns_len(a) ((a[0] & 0xff) << 8) | (a[1] & 0xff)
69
/* Get a single nibble from stdin in hex */
73
while((nib = (getc(stdin)))) {
75
/* We allow pauses to test TCP buffering */
79
/* Hex-ASCII to bin conversion */
80
} else if(nib >= '0' && nib <= '9') {
82
} else if(nib >= 'A' && nib <= 'F') {
83
return nib - 'A' + 10;
84
} else if(nib >= 'a' && nib <= 'f') {
85
return nib - 'a' + 10;
92
/* Get a single byte from stdin in hex */
93
int16_t get_stdin_hex() {
106
return (high << 4) | low;
109
int main(int argc, char **argv) {
114
uint32_t dns_l, place;
115
struct sockaddr_in dns;
116
uint8_t buffer[1512], id1, id2;
121
ip = inet_addr(argv[1]);
123
ip = 0; /* All IP addresses */
125
sock = get_port(ip,&dns);
126
if(listen(sock, 250) == -1) {
127
perror("listen error");
130
len = sizeof(struct sockaddr_in);
131
local = accept(sock,(struct sockaddr *)&dns,(void *)&len);
133
perror("accept error");
136
/* Blocking: Get 2-byte length header */
137
len = recv(local, buffer, 2, MSG_WAITALL);
139
perror("recv error");
141
for(a=0; a < len; a++) {
142
printf("%02X",buffer[a]);
144
dns_l = calc_dns_len(buffer);
145
/* Blocking: Get DNS packet */
146
len = recv(local, buffer, dns_l, MSG_WAITALL);
147
for(a=0; a < len; a++) {
148
printf("%02X ",buffer[a]);
153
/* Now, send a packet back from stdin */
154
buffer[0] = get_stdin_hex();
155
buffer[1] = get_stdin_hex();
156
dns_l = calc_dns_len(buffer);
157
if(send(local, buffer, 2, MSG_WAITALL) == -1) {
158
perror("send error len");
162
for(a=0; a < dns_l; ) {
163
get = get_stdin_hex();
165
if(send(local,buffer + place, a - place, MSG_WAITALL)
167
perror("send error pause");
170
printf("%d bytes sent\n",a - place);
179
if(send(local,buffer + place,dns_l - place, MSG_WAITALL) == -1) {
180
perror("send error");
183
printf("%d bytes sent\n",dns_l - place);