171 lines
4.7 KiB
C
171 lines
4.7 KiB
C
|
#include "packet.h"
|
||
|
#include "buffer.h"
|
||
|
#include "header.h"
|
||
|
#include "question.h"
|
||
|
#include "record.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
void read_packet(PacketBuffer* buffer, Packet* packet) {
|
||
|
read_header(buffer, &packet->header);
|
||
|
|
||
|
packet->questions = malloc(sizeof(Question) * packet->header.questions);
|
||
|
for(uint16_t i = 0; i < packet->header.questions; i++) {
|
||
|
read_question(buffer, &packet->questions[i]);
|
||
|
}
|
||
|
|
||
|
packet->answers = malloc(sizeof(Record) * packet->header.answers);
|
||
|
for(uint16_t i = 0; i < packet->header.answers; i++) {
|
||
|
read_record(buffer, &packet->answers[i]);
|
||
|
}
|
||
|
|
||
|
packet->authorities = malloc(sizeof(Record) * packet->header.authoritative_entries);
|
||
|
for(uint16_t i = 0; i < packet->header.authoritative_entries; i++) {
|
||
|
read_record(buffer, &packet->authorities[i]);
|
||
|
}
|
||
|
|
||
|
packet->resources = malloc(sizeof(Record) * packet->header.resource_entries);
|
||
|
for(uint16_t i = 0; i < packet->header.resource_entries; i++) {
|
||
|
read_record(buffer, &packet->resources[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void write_packet(PacketBuffer* buffer, Packet* packet) {
|
||
|
write_header(buffer, &packet->header);
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.questions; i++) {
|
||
|
write_question(buffer, &packet->questions[i]);
|
||
|
}
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.answers; i++) {
|
||
|
write_record(buffer, &packet->answers[i]);
|
||
|
}
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.authoritative_entries; i++) {
|
||
|
write_record(buffer, &packet->authorities[i]);
|
||
|
}
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.resource_entries; i++) {
|
||
|
write_record(buffer, &packet->resources[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void free_packet(Packet* packet) {
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.questions; i++) {
|
||
|
free_question(&packet->questions[i]);
|
||
|
}
|
||
|
free(packet->questions);
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.answers; i++) {
|
||
|
free_record(&packet->answers[i]);
|
||
|
}
|
||
|
free(packet->answers);
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.authoritative_entries; i++) {
|
||
|
free_record(&packet->authorities[i]);
|
||
|
}
|
||
|
free(packet->authorities);
|
||
|
|
||
|
for(uint16_t i = 0; i < packet->header.resource_entries; i++) {
|
||
|
free_record(&packet->resources[i]);
|
||
|
}
|
||
|
free(packet->resources);
|
||
|
}
|
||
|
|
||
|
bool get_random_a(Packet* packet, IpAddr* addr) {
|
||
|
for (uint16_t i = 0; i < packet->header.answers; i++) {
|
||
|
Record record = packet->answers[i];
|
||
|
if (record.type == A) {
|
||
|
create_ip_addr((char*) &record.data.a.addr, addr);
|
||
|
return true;
|
||
|
} else if (record.type == AAAA) {
|
||
|
create_ip_addr6((char*) &record.data.aaaa.addr, addr);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static bool ends_with(uint8_t* full, uint8_t* end) {
|
||
|
uint8_t check = end[0];
|
||
|
uint8_t len = full[0];
|
||
|
|
||
|
if (check > len) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for(uint8_t i = 0; i < check; i++) {
|
||
|
if (end[check - 1 - i] != full[len - 1 - i]) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool equals(uint8_t* a, uint8_t* b) {
|
||
|
if (a[0] != b[0]) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for(uint8_t i = 1; i < a[0] + 1; i++) {
|
||
|
if(a[i] != b[i]) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool get_resolved_ns(Packet* packet, uint8_t* qname, IpAddr* addr) {
|
||
|
for (uint16_t i = 0; i < packet->header.authoritative_entries; i++) {
|
||
|
Record record = packet->authorities[i];
|
||
|
if (record.type != NS) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(!ends_with(qname, record.domain)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
for (uint16_t i = 0; i < packet->header.resource_entries; i++) {
|
||
|
Record resource = packet->resources[i];
|
||
|
if (!equals(record.data.ns.host, resource.domain)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (resource.type == A) {
|
||
|
create_ip_addr((char*) &record.data.a.addr, addr);
|
||
|
return true;
|
||
|
} else if (resource.type == AAAA) {
|
||
|
create_ip_addr6((char*) &record.data.aaaa.addr, addr);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool get_unresoled_ns(Packet* packet, uint8_t* qname, Question* question) {
|
||
|
for (uint16_t i = 0; i < packet->header.authoritative_entries; i++) {
|
||
|
Record record = packet->authorities[i];
|
||
|
if (record.type != NS) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(!ends_with(qname, record.domain)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
uint8_t* host = record.data.ns.host;
|
||
|
|
||
|
question->qtype = NS;
|
||
|
question->domain = malloc(host[0] + 1);
|
||
|
memcpy(question->domain, host, host[0] + 1);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|