summaryrefslogtreecommitdiff
path: root/src/packet/header.c
blob: b74ebb14dd6b53ed08e13c02ca97a35abb95e98e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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);
}