diff options
author | Ting-Wei Lan <lantw44@gmail.com> | 2014-06-08 23:46:53 +0800 |
---|---|---|
committer | Ting-Wei Lan <lantw44@gmail.com> | 2014-06-08 23:48:05 +0800 |
commit | 1726f10f65032106a42a409c3275bcd0727ff1d5 (patch) | |
tree | e94bb520eedc104f014a1397cb955d40b72dd11d /falgproto/falgproto-protocol-dns.c | |
parent | 94097c3f7f9587fd66b3bab00096baf1179f335f (diff) | |
download | fastalg-protocol-1726f10f65032106a42a409c3275bcd0727ff1d5.tar.gz fastalg-protocol-1726f10f65032106a42a409c3275bcd0727ff1d5.tar.zst fastalg-protocol-1726f10f65032106a42a409c3275bcd0727ff1d5.zip |
Add DNS protocol support and hostname matcherv0.1.1
Diffstat (limited to 'falgproto/falgproto-protocol-dns.c')
-rw-r--r-- | falgproto/falgproto-protocol-dns.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/falgproto/falgproto-protocol-dns.c b/falgproto/falgproto-protocol-dns.c new file mode 100644 index 0000000..5a67a7b --- /dev/null +++ b/falgproto/falgproto-protocol-dns.c @@ -0,0 +1,119 @@ +/* vim: set sw=4 ts=4 sts=4 et: */ + +#include "config.h" +#include "falgproto.h" + +#include <arpa/inet.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + + +static inline int get_question_count ( + const char *pkt, size_t len, uint16_t *result) { + + if (len < 12) { + return -1; + } + + uint16_t result_ne; + memcpy (&result_ne, pkt + 4, 2); + *result = ntohs (result_ne); + + return 0; +} + +/* XXX: We only inspect the first question in the packet, as we + * don't know which question should we use to decide the + * destination. */ +static inline ssize_t get_question_name ( + const char *pkt_s, size_t len, char *out_s) { + + /* String length are always unsigned. */ + const unsigned char *pkt = pkt_s; + unsigned char *out = out_s; + + /* We assume get_question_count are called before this function, so + * we don't get a malformed or truncated packet */ + ssize_t i = 12, j = 0; + for (; i < len && pkt[i] != 0; j++) { + unsigned int label_len = pkt[i]; + for (i++; i < len && label_len > 0; i++, j++, label_len--) { + if (out != NULL) { + out[j] = pkt[i]; + } + } + if (out != NULL) { + if (pkt[i] != 0) { + out[j] = '.'; + } else { + out[j] = '\0'; + } + } + } + + if (pkt[i] != 0) { + printf ("%hhu %c\n", pkt[i], pkt[i]); + return -1; + } + + return i - 12 - 1; +} + +FALGPROTO_PARAM_GETTER_DECL (dns) { + + uint16_t question_count; + if (get_question_count (pkt, len, &question_count) < 0) { + return (FalgprotoParam) { .result = FALGPROTO_PARAM_RESULT_TRUNCATED }; + } + if (question_count == 0) { + return (FalgprotoParam) { .result = FALGPROTO_PARAM_RESULT_NOT_FOUND }; + } + + ssize_t question_name_len = get_question_name (pkt, len, NULL); + if (question_name_len < 0) { + return (FalgprotoParam) { .result = FALGPROTO_PARAM_RESULT_TRUNCATED }; + } + + char *question_name = malloc (question_name_len + 1); + if (question_name == NULL) { + return (FalgprotoParam) { .result = FALGPROTO_PARAM_RESULT_ERROR }; + } + + get_question_name (pkt, len, question_name); + return (FalgprotoParam) { + .param = question_name, + .len = question_name_len, + .dup = true, + .result = FALGPROTO_PARAM_RESULT_OK }; +} + +FALGPROTO_PRINTER_DECL (dns) { + + uint16_t question_count; + if (get_question_count (pkt, len, &question_count) < 0) { + fputs ("DNS: Cannot get question count\n", fp); + return; + } + + fprintf (fp, "DNS: Question count: %" PRIu16 "\n", question_count); + if (question_count == 0) { + fputs ("DNS: Why the question count is zero?\n", fp); + return; + } + + ssize_t question_name_len = get_question_name (pkt, len, NULL); + if (question_name_len < 0) { + fputs ("DNS: Malformed question name\n", fp); + return; + } + + char question_name[question_name_len + 1]; + get_question_name (pkt, len, question_name); + fputs ("DNS: Question name: ", fp); + fputs (question_name, fp); + fputc ('\n', fp); + fprintf (fp, "DNS: Question name length: %zd\n", question_name_len); +} |