Compare commits
No commits in common. "packet-parsing" and "main" have entirely different histories.
packet-par
...
main
8 changed files with 78 additions and 129 deletions
|
|
@ -1,7 +1,6 @@
|
|||
cmake_minimum_required(VERSION 4.0)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
project(pupdns VERSION 0.1)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
#define PB_SIZE 512
|
||||
#define PB_OUT_OF_BOUNDS 9999;
|
||||
#define PACKET_BUFFER_SIZE 512
|
||||
|
||||
struct DNSPacketBuffer {
|
||||
unsigned char buf[PB_SIZE];
|
||||
char buf[PACKET_BUFFER_SIZE];
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
struct DNSPacketBuffer *new_dns_packet_buffer();
|
||||
|
||||
unsigned char pb_read_byte(struct DNSPacketBuffer *);
|
||||
struct DNSPacketHeader *dns_header(struct DNSPacketBuffer);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
#define DNS_HEADER_BYTES 12
|
||||
|
||||
struct DNSPacketHeader {
|
||||
/*
|
||||
|
|
@ -9,34 +8,14 @@ struct DNSPacketHeader {
|
|||
* a random ID is assigned to query packets.
|
||||
* Response packets must contain the same ID as the query.
|
||||
*/
|
||||
unsigned int packet_id : 16;
|
||||
|
||||
/*
|
||||
* RD (Recursion Desired)
|
||||
* if set by the client, the server should
|
||||
* attempt to resolve the query recursively
|
||||
*
|
||||
* the server may not allow recursive resolution.
|
||||
* (see RA / Recursion Available)
|
||||
*/
|
||||
unsigned int recursion_desired : 1;
|
||||
size_t packet_id : 16;
|
||||
|
||||
/*
|
||||
* TC (Truncated)
|
||||
* if true, this message was truncated.
|
||||
* usually happens when the response payload
|
||||
* is larger than the max UDP packet size
|
||||
*
|
||||
* if set, the query may be re-issued over TCP for the full payload.
|
||||
* QR (Query/Response)
|
||||
* 0 if the packet is a query
|
||||
* 1 if the packet is a response
|
||||
*/
|
||||
unsigned int is_truncated : 1;
|
||||
|
||||
/*
|
||||
* AA (Authoritative Answer)
|
||||
*
|
||||
* 1 if the responding server is authoritative for the queried domain
|
||||
*/
|
||||
unsigned int is_authoritative : 1;
|
||||
size_t is_response : 1;
|
||||
|
||||
/*
|
||||
* OPCODE (Operation Code)
|
||||
|
|
@ -48,14 +27,51 @@ struct DNSPacketHeader {
|
|||
*
|
||||
* almost always will be 0
|
||||
*/
|
||||
unsigned int opcode : 4;
|
||||
size_t opcode : 4;
|
||||
|
||||
/*
|
||||
* QR (Query/Response)
|
||||
* 0 if the packet is a query
|
||||
* 1 if the packet is a response
|
||||
* AA (Authoritative Answer)
|
||||
*
|
||||
* 1 if the responding server is authoritative for the queried domain
|
||||
*/
|
||||
unsigned int is_response : 1;
|
||||
size_t is_authoritative : 1;
|
||||
|
||||
/*
|
||||
* TC (Truncated)
|
||||
* if true, this message was truncated.
|
||||
* usually happens when the response payload
|
||||
* is larger than the max UDP packet size
|
||||
*
|
||||
* if set, the query may be re-issued over TCP for the full payload.
|
||||
*/
|
||||
size_t is_truncated : 1;
|
||||
|
||||
/*
|
||||
* RD (Recursion Desired)
|
||||
* if set by the client, the server should
|
||||
* attempt to resolve the query recursively
|
||||
*
|
||||
* the server may not allow recursive resolution.
|
||||
* (see RA / Recursion Available)
|
||||
*/
|
||||
size_t recursion_desired : 1;
|
||||
|
||||
|
||||
/*
|
||||
* RA (Recursion Available)
|
||||
* if set by the server, incicates that the server allows
|
||||
* recursive queries.
|
||||
*/
|
||||
size_t recursion_available : 1;
|
||||
|
||||
/*
|
||||
* Z (Reserved)
|
||||
* in the original spec, this is reserved for future use.
|
||||
*
|
||||
* in later RFCs, it is used for DNSSEC queries.
|
||||
* (to be implemented)
|
||||
*/
|
||||
size_t z : 3;
|
||||
|
||||
/*
|
||||
* RCODE (Response Code)
|
||||
|
|
@ -70,47 +86,31 @@ struct DNSPacketHeader {
|
|||
* 5 - Refused - the nameserver refuses to perform the requested operation. for example, it may refuse a zone transfer.
|
||||
* 6-15 - Reserved for future use
|
||||
*/
|
||||
unsigned int response_code : 4;
|
||||
|
||||
/*
|
||||
* Z (Reserved)
|
||||
* in the original spec, this is reserved for future use.
|
||||
*
|
||||
* in later RFCs, it is used for DNSSEC queries.
|
||||
* (to be implemented)
|
||||
*/
|
||||
unsigned int z : 3;
|
||||
|
||||
/*
|
||||
* RA (Recursion Available)
|
||||
* if set by the server, incicates that the server allows
|
||||
* recursive queries.
|
||||
*/
|
||||
unsigned int recursion_available : 1;
|
||||
size_t response_code : 4;
|
||||
|
||||
/*
|
||||
* QDCOUNT (Question Count)
|
||||
* the number of entries in the question section
|
||||
*/
|
||||
unsigned int question_count : 16;
|
||||
size_t question_count : 16;
|
||||
|
||||
/*
|
||||
* ANCOUNT (Answer Count)
|
||||
* the number of entries in the answer section
|
||||
*/
|
||||
unsigned int answer_count : 16;
|
||||
size_t answer_count : 16;
|
||||
|
||||
/*
|
||||
* NSCOUNT (Nameserver Count)
|
||||
* the number of entries in the authority records section
|
||||
*/
|
||||
unsigned int ns_count : 16;
|
||||
size_t ns_count : 16;
|
||||
|
||||
/*
|
||||
* ARCOUNT (Additional Records Count)
|
||||
* the number of entries in the additional records section
|
||||
*/
|
||||
unsigned int ar_count : 16;
|
||||
size_t ar_count : 16;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -125,26 +125,26 @@ struct RecordPreamble {
|
|||
* TYPE
|
||||
* the record type
|
||||
*/
|
||||
unsigned int type : 16;
|
||||
size_t type : 16;
|
||||
|
||||
/*
|
||||
* CLASS
|
||||
* specifies the class of the data in the RDATA field.
|
||||
* in practice, always set to 1
|
||||
*/
|
||||
unsigned int class : 16;
|
||||
size_t class : 16;
|
||||
|
||||
/*
|
||||
* TTL (Time-To-Live)
|
||||
* how long a record can be cached before it should be requeried.
|
||||
*/
|
||||
unsigned int ttl : 32;
|
||||
size_t ttl : 32;
|
||||
|
||||
/*
|
||||
* RDLENGTH (Record Data Length)
|
||||
* length of the record-type-specific data.
|
||||
*/
|
||||
unsigned int rd_data_length: 16;
|
||||
size_t rd_data_length: 16;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -153,5 +153,5 @@ struct RecordPreamble {
|
|||
*/
|
||||
struct ARecord {
|
||||
struct RecordPreamble preamble;
|
||||
unsigned int ip : 32;
|
||||
size_t ip : 32;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "dns_packets.h"
|
||||
#include "dns_packet_buffer.h"
|
||||
|
||||
struct DNSRequest {
|
||||
struct DNSPacketHeader *header;
|
||||
struct DNSPacketHeader header;
|
||||
};
|
||||
|
||||
struct DNSRequest *parse_dns_query(struct DNSPacketBuffer *pb);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#define UDP_PORT 1053
|
||||
#define UDP_PORT 53
|
||||
|
||||
int start_server();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include "dns_packet_buffer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct DNSPacketBuffer *new_dns_packet_buffer()
|
||||
|
|
@ -8,3 +7,8 @@ struct DNSPacketBuffer *new_dns_packet_buffer()
|
|||
buf = malloc(sizeof(struct DNSPacketBuffer));
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct DNSPacketHeader *dns_header(struct DNSPacketBuffer)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,3 @@
|
|||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "dns_request.h"
|
||||
|
||||
struct DNSRequest *parse_dns_query(struct DNSPacketBuffer *pb)
|
||||
{
|
||||
struct DNSRequest *req;
|
||||
req = malloc(sizeof(struct DNSRequest));
|
||||
req->header = (struct DNSPacketHeader *) pb->buf;
|
||||
|
||||
/*
|
||||
* casting the buffer directly into the packet header struct like this
|
||||
* works okay, but because of the nature of the DNS protocol, it needs
|
||||
* a lot of manual tweaking.
|
||||
*
|
||||
* the struct fields are defined in a weird order (compared to the spec)
|
||||
* because C wants to read each byte from right to left,
|
||||
* but DNS fields go left to right.
|
||||
*
|
||||
* so for each set of fields adding up to 8 bits of data, i reversed the
|
||||
* order of the fields in the struct definition so that the fields end up
|
||||
* with the correct bits off the wire.
|
||||
*
|
||||
* DNS also has multi-bit (but less than a byte) fields such as
|
||||
* opcode and response code. fortunately we can skip these for now,
|
||||
* since opcode is practically always zero for our purposes,
|
||||
* and response_code only makes sense in the server response.
|
||||
*
|
||||
* but we do need to take care of all the network-order 16-bit fields.
|
||||
*/
|
||||
req->header->packet_id = ntohs(req->header->packet_id);
|
||||
req->header->question_count = ntohs(req->header->question_count);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
#include "dns_packet_buffer.h"
|
||||
#include "dns_request.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
|
@ -37,37 +37,20 @@ int start_server()
|
|||
return -1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
socklen_t len = 0;
|
||||
socklen_t len = 0;
|
||||
|
||||
int n = recvfrom(sockfd, (char *)pb->buf, sizeof(pb->buf), MSG_WAITALL, 0, &len);
|
||||
int n = recvfrom(sockfd, (char *)pb->buf, sizeof(pb->buf), MSG_WAITALL, 0, &len);
|
||||
|
||||
printf("===== NEW REQUEST =====\n");
|
||||
printf("received %d bytes\n", n);
|
||||
printf("received %d bytes\n", n);
|
||||
|
||||
struct DNSRequest *req = parse_dns_query(pb);
|
||||
struct DNSRequest *req = new_dns_request(pb);
|
||||
|
||||
printf("packet_id: %x\n", req->header->packet_id);
|
||||
printf("is_response: %d\n", req->header->is_response);
|
||||
printf("opcode: %d\n", req->header->opcode);
|
||||
printf("is_authoritative: %d\n", req->header->is_authoritative);
|
||||
printf("is_truncated: %d\n", req->header->is_truncated);
|
||||
printf("recursion_desired: %d\n", req->header->recursion_desired);
|
||||
printf("recursion_available: %d\n", req->header->recursion_available);
|
||||
printf("reserved: %d\n", req->header->z);
|
||||
printf("response_code: %d\n", req->header->response_code);
|
||||
printf("question_count: %d\n", req->header->question_count);
|
||||
printf("answer_count: %d\n", req->header->answer_count);
|
||||
printf("ns_count: %d\n", req->header->ns_count);
|
||||
printf("ar_count: %d\n", req->header->ar_count);
|
||||
|
||||
// for (int i=0; i<n; i++) {
|
||||
// printf("%d = %02X\n", i, (unsigned char)pb->buf[i]);
|
||||
// }
|
||||
|
||||
free(pb);
|
||||
free(req);
|
||||
}
|
||||
printf("packet_id: %x\n", req->header->packet_id);
|
||||
printf("is_response: %d\n", req->header->is_response);
|
||||
printf("opcode: %d\n", req->header->opcode);
|
||||
printf("is_authoritative: %d\n", req->header->is_authoritative);
|
||||
printf("is_truncated: %d\n", req->header->is_truncated);
|
||||
printf("recursion_desired: %d\n", req->header->recursion_desired);
|
||||
|
||||
close(sockfd);
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue