diff options
author | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-05 23:08:09 -0400 |
---|---|---|
committer | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-05 23:08:09 -0400 |
commit | bb85374b79086cd8efde24d23a1bffeb97cae26b (patch) | |
tree | a36e2df6a89e567822820ac110afec6a13eacbf6 /src/server/resolver.c | |
parent | finish dns and start webserver (diff) | |
download | wrapper-bb85374b79086cd8efde24d23a1bffeb97cae26b.tar.gz wrapper-bb85374b79086cd8efde24d23a1bffeb97cae26b.tar.bz2 wrapper-bb85374b79086cd8efde24d23a1bffeb97cae26b.zip |
new c version
Diffstat (limited to 'src/server/resolver.c')
-rw-r--r-- | src/server/resolver.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/server/resolver.c b/src/server/resolver.c new file mode 100644 index 0000000..e05f365 --- /dev/null +++ b/src/server/resolver.c @@ -0,0 +1,166 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "resolver.h" +#include "addr.h" +#include "binding.h" +#include "../io/log.h" + +static bool lookup( + Question* question, + Packet* response, + BindingType type, + SocketAddr addr +) { + INIT_LOG_BUFFER(log) + LOGONLY(print_socket_addr(&addr, log);) + TRACE("Attempting lookup on fallback dns %s", log); + + Connection request; + if (!create_request(type, &addr, &request)) { + return false; + } + + Packet req; + memset(&req, 0, sizeof(Packet)); + req.header.id = response->header.id; + req.header.opcode = response->header.opcode; + req.header.questions = 1; + req.header.recursion_desired = true; + req.questions = malloc(sizeof(Question)); + req.questions[0] = *question; + + if (!request_packet(&request, &req, response)) { + free_request(&request); + free(req.questions); + ERROR("Failed to request fallback dns: %s", strerror(errno)); + return false; + } + + free_request(&request); + free(req.questions); + return true; +} + +static bool search(Question* question, Packet* result, BindingType type) { + IpAddr addr; + char ip[4] = {1, 1, 1, 1}; + create_ip_addr(ip, &addr); + + uint16_t port = 53; + SocketAddr saddr; + create_socket_addr(port, addr, &saddr); + + while(1) { + if (!lookup(question, result, type, saddr)) { + return false; + } + + if (result->header.answers > 0 && result->header.rescode == NOERROR) { + return true; + } + + if (result->header.rescode == NXDOMAIN) { + return true; + } + + if (get_resolved_ns(result, question->domain, &addr)) { + continue; + } + + Question new_question; + if (!get_unresoled_ns(result, question->domain, &new_question)) { + return true; + } + + Packet recurse; + if (!search(&new_question, &recurse, type)) { + return false; + } + + free_question(&new_question); + + IpAddr random; + if (!get_random_a(&recurse, &random)) { + free_packet(&recurse); + return true; + } else { + free_packet(&recurse); + addr = random; + } + } +} + +static void push_records(Record* from, uint8_t from_len, Record** to, uint8_t to_len) { + if(from_len < 1) return; + *to = realloc(*to, sizeof(Record) * (from_len + to_len)); + memcpy(*to + to_len, from, from_len * sizeof(Record)); +} + +static void push_questions(Question* from, uint8_t from_len, Question** to, uint8_t to_len) { + if(from_len < 1) return; + *to = realloc(*to, sizeof(Question) * (from_len + to_len)); + memcpy(*to + to_len, from, from_len * sizeof(Question)); +} + +void handle_query(Packet* request, Packet* response, BindingType type) { + memset(response, 0, sizeof(Packet)); + response->header.id = request->header.id; + response->header.opcode = request->header.opcode; + response->header.recursion_desired = true; + response->header.recursion_available = true; + response->header.response = true; + + if (request->header.questions < 1) { + response->header.response = FORMERR; + return; + } + + for (uint16_t i = 0; i < request->header.questions; i++) { + Packet result; + memset(&result, 0, sizeof(Packet)); + result.header.id = response->header.id; + if (!search(&request->questions[i], &result, type)) { + response->header.response = SERVFAIL; + break; + } + + push_questions( + result.questions, + result.header.questions, + &response->questions, + response->header.questions + ); + response->header.questions += result.header.questions; + + push_records( + result.answers, + result.header.answers, + &response->answers, + response->header.answers + ); + response->header.answers += result.header.answers; + + push_records( + result.authorities, + result.header.authoritative_entries, + &response->authorities, + response->header.authoritative_entries + ); + response->header.authoritative_entries += result.header.authoritative_entries; + + push_records( + result.resources, + result.header.resource_entries, + &response->resources, + response->header.resource_entries + ); + response->header.resource_entries += result.header.resource_entries; + + free(result.questions); + free(result.answers); + free(result.authorities); + free(result.resources); + } +}
\ No newline at end of file |