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 sends a DNS packet from
20
* stdin over port 53 TCP (the first two bytes of the packet are the
21
* length header), then outputs on stdout the received packet */
27
#include <sys/socket.h>
28
#include <arpa/inet.h>
29
#include <netinet/in.h>
32
/* We use a special SOCKET type for easier Windows porting */
35
/* Get port: Connect to a remote machine via TCP */
36
SOCKET get_port(uint32_t ip, struct sockaddr_in *dns) {
41
sock = socket(AF_INET,SOCK_STREAM,0);
43
perror("socket error");
46
memset(dns,0,sizeof(struct sockaddr_in));
47
dns->sin_family = AF_INET;
48
dns->sin_port = htons(53);
49
dns->sin_addr.s_addr = ip;
50
if(dns->sin_addr.s_addr == INADDR_NONE) {
51
perror("Problem with s_addr");
54
len_inet = sizeof(struct sockaddr_in);
55
if(connect(sock,(struct sockaddr *)dns,len_inet) == -1) {
56
perror("connect error");
60
/* Linux kernel bug */
61
/* fcntl(sock, F_SETFL, O_NONBLOCK); */
66
#define calc_dns_len(a) ((a[0] & 0xff) << 8) | (a[1] & 0xff)
68
/* Get a single nibble from stdin in hex */
72
while((nib = (getc(stdin)))) {
74
/* We allow pauses to test TCP buffering */
77
return -2; /* Time to send() the packet */
78
/* Hex-ASCII to bin conversion */
79
} else if(nib >= '0' && nib <= '9') {
81
} else if(nib >= 'A' && nib <= 'F') {
82
return nib - 'A' + 10;
83
} else if(nib >= 'a' && nib <= 'f') {
84
return nib - 'a' + 10;
91
/* Get a single byte from stdin in hex */
92
int16_t get_stdin_hex() {
105
return (high << 4) | low;
108
int main(int argc, char **argv) {
112
uint32_t dns_l, place;
113
struct sockaddr_in dns;
114
uint8_t buffer[1512];
119
ip = inet_addr(argv[1]);
121
ip = 0x0100007f; /* Localhost (127.0.0.1) */
123
sock = get_port(ip,&dns);
125
/* Send hex bytes from stdin upstream */
126
buffer[0] = get_stdin_hex();
127
buffer[1] = get_stdin_hex();
128
dns_l = calc_dns_len(buffer);
129
if(send(sock, buffer, 2, MSG_WAITALL) == -1) {
130
perror("send error len");
134
for(a=0; a < dns_l; ) {
135
get = get_stdin_hex();
137
if(send(sock,buffer + place, a - place, MSG_WAITALL)
139
perror("send error pause");
142
printf("%d bytes sent\n",a - place);
149
if(send(sock,buffer + place,dns_l - place, MSG_WAITALL) == -1) {
150
perror("send error");
153
printf("%d bytes sent\n",dns_l - place);
154
/* Get reply from upstream, show on stdout */
155
/* Blocking: Get 2-byte length header */
156
len = recv(sock, buffer, 2, MSG_WAITALL);
158
perror("recv error len");
161
for(a=0; a < len; a++) {
162
printf("%02X ",buffer[a]);
164
dns_l = calc_dns_len(buffer);
165
/* Blocking: Get DNS packet */
166
len = recv(sock, buffer, dns_l, MSG_WAITALL);
168
perror("recv error");
171
for(a=0; a < len; a++) {
172
printf("%02X ",buffer[a]);