diff options
author | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-17 22:49:49 -0400 |
---|---|---|
committer | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-17 22:49:49 -0400 |
commit | 7d650d5d9bcba940ae312657d51e366e7401fd6b (patch) | |
tree | d7283c146aaa625920cf85582a2e4099df86759d /src/client/client.c | |
download | wig-main.tar.gz wig-main.tar.bz2 wig-main.zip |
Diffstat (limited to '')
-rw-r--r-- | src/client/client.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/src/client/client.c b/src/client/client.c new file mode 100644 index 0000000..31ef589 --- /dev/null +++ b/src/client/client.c @@ -0,0 +1,177 @@ +#include "client.h" +#include "../packet/question.h" +#include "addr.h" +#include "binding.h" + +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <sys/time.h> + +void resolve_default_server(IpAddr* addr) { + res_init(); + addr->data.v4 = _res.nsaddr_list[0].sin_addr; + addr->type = V4; +} + +static void push_question(Question** buf, Question q, uint8_t* amount, uint8_t* capacity) { + if (*amount >= *capacity) { + *capacity *= 2; + *buf = realloc(*buf, sizeof(Question) * *capacity); + } + (*buf)[*amount] = q; + (*amount)++; +} + +void resolve_questions(int argc, char** argv, uint8_t* len, Question** questions) { + assert(argc > 0); + + uint8_t amount = 0; + uint8_t capacity = 1; + Question* buf = malloc(sizeof(Question) * capacity); + + Question q; + RecordType t; + if (argc == 1 && str_to_qtype(argv[0], &t)) { + create_question("", NS, &q); + push_question(&buf, q, &amount, &capacity); + *questions = buf; + *len = 1; + return; + } + + for (int i = 0; i < argc; i++) { + if (str_to_qtype(argv[i], &t)) { + if (i + 1 == argc) break; + create_question(argv[i+1], t, &q); + i++; + } else if (i + 1 < argc && str_to_qtype(argv[i+1], &t)){ + create_question(argv[i], t, &q); + i++; + } else { + create_question(argv[i], A, &q); + } + push_question(&buf, q, &amount, &capacity); + } + + *questions = buf; + *len = amount; +} + +static void print_result(Packet* packet, const char* type, uint32_t ms) { + printf(">> Recieved response\n"); + printf("Id: %hu, Code: %s\n", + packet->header.id, + str_from_code(packet->header.rescode) + ); + printf("Questions: %hu, Answers: %hu, Authorities: %hu, Resources: %hu\n", + packet->header.questions, + packet->header.answers, + packet->header.authoritative_entries, + packet->header.resource_entries + ); + + if (packet->header.questions > 0) { + printf("\n>> Question Section\n"); + for (uint16_t i = 0; i < packet->header.questions; i++) { + print_question(&packet->questions[i]); + } + } + + if (packet->header.answers > 0) { + printf("\n>> Answer Section\n"); + for (uint16_t i = 0; i < packet->header.answers; i++) { + print_record(&packet->answers[i]); + } + } + + if (packet->header.authoritative_entries > 0) { + printf("\n>> Authority Section\n"); + for (uint16_t i = 0; i < packet->header.authoritative_entries; i++) { + print_record(&packet->authorities[i]); + } + } + + if (packet->header.resource_entries > 0) { + printf("\n>> Resource Section\n"); + for (uint16_t i = 0; i < packet->header.resource_entries; i++) { + print_record(&packet->resources[i]); + } + } + + printf("\n>> Query time: %ums (%s)\n", ms, type); +} + +void resolve(IpAddr server, Options options, Question* questions, uint8_t len) { + struct timeval stop, start; + gettimeofday(&start, NULL); + + SocketAddr addr; + create_socket_addr(options.port, server, &addr); + + Packet req; + memset(&req, 0, sizeof(Packet)); + srand(time(NULL)); + req.header.id = rand() % 65536; + req.header.questions = len; + req.header.recursion_desired = true; + req.questions = questions; + + Connection conn; + if (options.force_tcp) goto tcp; + + if (!create_request(UDP, &addr, &conn)) { + printf("error: failed to create udp request: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + Packet res; + if (!request_packet(&conn, &req, &res)) { + free_request(&conn); + free_packet(&req); + printf("error: failed to request udp packet: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + free_request(&conn); + + if (!res.header.truncated_message) { + gettimeofday(&stop, NULL); + uint32_t ms = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec; + + print_result(&res, "UDP", ms / 1000); + free_packet(&req); + free_packet(&res); + return; + } + + free_packet(&res); + printf("Response truncated, retrying in TCP...\n"); + +tcp: + + if (!create_request(TCP, &addr, &conn)) { + printf("error: failed to create tcp request: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + if (!request_packet(&conn, &req, &res)) { + free_request(&conn); + printf("error: failed to request tcp packet: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + gettimeofday(&stop, NULL); + uint32_t ms = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec; + + print_result(&res, "TCP", ms / 1000); + + free_request(&conn); + free_packet(&req); + free_packet(&res); +} + |