summaryrefslogtreecommitdiff
path: root/src/packet/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/packet/header.c')
-rw-r--r--src/packet/header.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/packet/header.c b/src/packet/header.c
new file mode 100644
index 0000000..b74ebb1
--- /dev/null
+++ b/src/packet/header.c
@@ -0,0 +1,108 @@
+#include "header.h"
+#include "buffer.h"
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+uint8_t rescode_to_id(ResultCode code) {
+ switch(code) {
+ case NOERROR:
+ return 0;
+ case FORMERR:
+ return 1;
+ case SERVFAIL:
+ return 2;
+ case NXDOMAIN:
+ return 3;
+ case NOTIMP:
+ return 4;
+ case REFUSED:
+ return 5;
+ default:
+ return 2;
+ }
+}
+
+ResultCode rescode_from_id(uint8_t id) {
+ switch(id) {
+ case 0:
+ return NOERROR;
+ case 1:
+ return FORMERR;
+ case 2:
+ return SERVFAIL;
+ case 3:
+ return NXDOMAIN;
+ case 4:
+ return NOTIMP;
+ case 5:
+ return REFUSED;
+ default:
+ return FORMERR;
+ }
+}
+
+const char* str_from_code(ResultCode code) {
+ switch(code) {
+ case NOERROR: return "NOERROR";
+ case FORMERR: return "FORMERR";
+ case SERVFAIL: return "SERVFAIL";
+ case NXDOMAIN: return "NXDOMAIN";
+ case NOTIMP: return "NOTIMP";
+ case REFUSED: return "REFUSED";
+ default: return "????";
+ }
+}
+
+#define MAX(var, max) var = var > max ? max : var;
+
+void read_header(PacketBuffer* buffer, Header* header) {
+ // memset(header, 0, sizeof(Header));
+ header->id = buffer_read_short(buffer);
+
+ uint8_t a = buffer_read(buffer);
+ header->recursion_desired = (a & (1 << 0)) > 0;
+ header->truncated_message = (a & (1 << 1)) > 0;
+ header->authorative_answer = (a & (1 << 2)) > 0;
+ header->opcode = (a >> 3) & 0x0F;
+ header->response = (a & (1 << 7)) > 0;
+
+ uint8_t b = buffer_read(buffer);
+ header->rescode = rescode_from_id(b & 0x0F);
+ header->checking_disabled = (b & (1 << 4)) > 0;
+ header->authed_data = (b& (1 << 4)) > 0;
+ header->z = (b & (1 << 6)) > 0;
+ header->recursion_available = (b & (1 << 7)) > 0;
+ header->questions = buffer_read_short(buffer);
+ header->answers = buffer_read_short(buffer);
+ header->authoritative_entries = buffer_read_short(buffer);
+ header->resource_entries = buffer_read_short(buffer);
+}
+
+void write_header(PacketBuffer* buffer, Header* header) {
+ buffer_write_short(buffer, header->id);
+
+ buffer_write(buffer,
+ ((uint8_t) header->recursion_desired) |
+ ((uint8_t) header->truncated_message << 1) |
+ ((uint8_t) header->authorative_answer << 2) |
+ (header->opcode << 3) |
+ ((uint8_t) header->response << 7)
+ );
+
+ buffer_write(buffer,
+ (rescode_to_id(header->rescode)) |
+ ((uint8_t) header->checking_disabled << 4) |
+ ((uint8_t) header->authed_data << 5) |
+ ((uint8_t) header->z << 6) |
+ ((uint8_t) header->recursion_available << 7)
+ );
+
+ buffer_write_short(buffer, header->questions);
+ buffer_write_short(buffer, header->answers);
+ buffer_write_short(buffer, header->authoritative_entries);
+ buffer_write_short(buffer, header->resource_entries);
+}