135 lines
3.4 KiB
C
135 lines
3.4 KiB
C
|
#include <dnswire/reader.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <uv.h>
|
||
|
#include <arpa/inet.h>
|
||
|
#include <time.h>
|
||
|
#include <errno.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
#include "print_dnstap.c"
|
||
|
|
||
|
#define BUF_SIZE 4096
|
||
|
|
||
|
uv_loop_t* loop;
|
||
|
uv_tcp_t sock;
|
||
|
uv_connect_t conn;
|
||
|
char rbuf[BUF_SIZE];
|
||
|
|
||
|
struct dnswire_reader reader;
|
||
|
|
||
|
void client_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
|
||
|
{
|
||
|
buf->base = rbuf;
|
||
|
buf->len = sizeof(rbuf);
|
||
|
}
|
||
|
|
||
|
void client_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
|
||
|
{
|
||
|
if (nread > 0) {
|
||
|
/*
|
||
|
* We now push all the data we got to the reader.
|
||
|
*/
|
||
|
size_t pushed = 0;
|
||
|
|
||
|
while (pushed < nread) {
|
||
|
enum dnswire_result res = dnswire_reader_push(&reader, (uint8_t*)&buf->base[pushed], nread - pushed, 0, 0);
|
||
|
|
||
|
pushed += dnswire_reader_pushed(reader);
|
||
|
|
||
|
switch (res) {
|
||
|
case dnswire_have_dnstap:
|
||
|
/*
|
||
|
* We got a DNSTAP message, lets print it!
|
||
|
*/
|
||
|
print_dnstap(dnswire_reader_dnstap(reader));
|
||
|
break;
|
||
|
case dnswire_again:
|
||
|
case dnswire_need_more:
|
||
|
break;
|
||
|
case dnswire_endofdata:
|
||
|
/*
|
||
|
* The remote end sent a control stop or finish.
|
||
|
*/
|
||
|
uv_close((uv_handle_t*)handle, 0);
|
||
|
return;
|
||
|
default:
|
||
|
fprintf(stderr, "dnswire_reader_fread() error\n");
|
||
|
uv_close((uv_handle_t*)handle, 0);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (nread < 0) {
|
||
|
if (nread != UV_EOF) {
|
||
|
fprintf(stderr, "client_read() error: %s\n", uv_err_name(nread));
|
||
|
} else {
|
||
|
printf("disconnected\n");
|
||
|
}
|
||
|
uv_close((uv_handle_t*)handle, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void on_connect(uv_connect_t* req, int status)
|
||
|
{
|
||
|
/*
|
||
|
* We have connected to the sender, check that there was no errors
|
||
|
* and start receiving incoming frames.
|
||
|
*/
|
||
|
|
||
|
if (status < 0) {
|
||
|
fprintf(stderr, "on_connect() error: %s\n", uv_strerror(status));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
uv_read_start((uv_stream_t*)&sock, client_alloc_buffer, client_read);
|
||
|
}
|
||
|
|
||
|
int main(int argc, const char* argv[])
|
||
|
{
|
||
|
if (argc < 3) {
|
||
|
fprintf(stderr, "usage: client_receiver_uv <IP> <port>\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* We first initialize the reader and check that it can allocate the
|
||
|
* buffers it needs.
|
||
|
*/
|
||
|
|
||
|
if (dnswire_reader_init(&reader) != dnswire_ok) {
|
||
|
fprintf(stderr, "Unable to initialize dnswire reader\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* We set this reader to reject bidirectional communication.
|
||
|
*/
|
||
|
if (dnswire_reader_allow_bidirectional(&reader, false) != dnswire_ok) {
|
||
|
fprintf(stderr, "Unable to deny bidirectional communication\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* We setup a TCP client using libuv and connect to the given server.
|
||
|
*/
|
||
|
|
||
|
struct sockaddr_storage addr;
|
||
|
int port = atoi(argv[2]);
|
||
|
|
||
|
if (strchr(argv[1], ':')) {
|
||
|
uv_ip6_addr(argv[1], port, (struct sockaddr_in6*)&addr);
|
||
|
} else {
|
||
|
uv_ip4_addr(argv[1], port, (struct sockaddr_in*)&addr);
|
||
|
}
|
||
|
|
||
|
loop = uv_default_loop();
|
||
|
|
||
|
uv_tcp_init(loop, &sock);
|
||
|
uv_tcp_connect(&conn, &sock, (const struct sockaddr*)&addr, on_connect);
|
||
|
|
||
|
return uv_run(loop, UV_RUN_DEFAULT);
|
||
|
}
|