diff options
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | falgproto/falgproto-match-hostname.c | 30 | ||||
-rw-r--r-- | falgproto/falgproto-protocol-dns.c | 119 | ||||
-rw-r--r-- | falgproto/falgproto.c | 22 | ||||
-rw-r--r-- | falgproto/falgproto.h | 20 |
6 files changed, 191 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am index 754c312..57eba78 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,8 +9,10 @@ EXTRA_DIST = \ $(NULL) falgproto_libfalgproto_0_1_la_SOURCES = \ - falgproto/falgproto.h \ - falgproto/falgproto.c \ + falgproto/falgproto.h \ + falgproto/falgproto.c \ + falgproto/falgproto-protocol-dns.c \ + falgproto/falgproto-match-hostname.c \ $(NULL) falgprotoincludedir = $(includedir)/falgproto-0.1 diff --git a/configure.ac b/configure.ac index ae3f5d1..de5e469 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. # vim: set sw=4 ts=4 sts=4 et: -AC_INIT([fastalg-protocol], [0.1], [BUG-REPORT-ADDRESS]) +AC_INIT([fastalg-protocol], [0.1.1], [BUG-REPORT-ADDRESS]) AC_CONFIG_SRCDIR([falgproto/falgproto.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/falgproto/falgproto-match-hostname.c b/falgproto/falgproto-match-hostname.c new file mode 100644 index 0000000..b093c6a --- /dev/null +++ b/falgproto/falgproto-match-hostname.c @@ -0,0 +1,30 @@ +/* vim: set sw=4 ts=4 sts=4 et: */ + +#include "config.h" +#include "falgproto.h" + +#include <stdbool.h> + + +FALGPROTO_MATCHER_DECL (hostname) { + + const char *big_end = big + big_len; + const char *little_end = little + little_len; + + for (; big_end >= big && little_end >= little && *big_end == *little_end; + big_end--, little_end--); + + if (little_end < little) { + if (big_end >= big) { + if (*big_end == '.') { + return true; + } else { + return false; + } + } else { + return true; + } + } + + return false; +} 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); +} diff --git a/falgproto/falgproto.c b/falgproto/falgproto.c index b66f7ef..58a611f 100644 --- a/falgproto/falgproto.c +++ b/falgproto/falgproto.c @@ -14,32 +14,46 @@ struct proto_info { char* description; FalgprotoParamGetter param_getter; FalgprotoPrinter printer; + FalgprotoMatcher matcher; }; +/* protocol implementation declaraion */ +FALGPROTO_PARAM_GETTER_DECL (dns); +FALGPROTO_PRINTER_DECL (dns); + +/* matcher implementation declaraion */ +FALGPROTO_MATCHER_DECL (hostname); + static struct proto_info info[] = { { FALGPROTO_TYPE_HTTP, FALGPROTO_TRANSPORT_TCP, "http", "HTTP", NULL, + NULL, NULL }, { FALGPROTO_TYPE_HTTPS, FALGPROTO_TRANSPORT_TCP, "https", "HTTPS", NULL, + NULL, NULL }, { FALGPROTO_TYPE_DNS, FALGPROTO_TRANSPORT_UDP, "dns", "DNS", - NULL, - NULL }, + FALGPROTO_PARAM_GETTER_NAME (dns), + FALGPROTO_PRINTER_NAME (dns), + FALGPROTO_MATCHER_NAME (hostname) }, { FALGPROTO_TYPE_FTP, FALGPROTO_TRANSPORT_TCP, "ftp", "FTP", NULL, + NULL, NULL }, { FALGPROTO_TYPE_SSH, FALGPROTO_TRANSPORT_TCP, "ssh", "SSH", NULL, + NULL, NULL }, { FALGPROTO_TYPE_LDAP, FALGPROTO_TRANSPORT_TCP, "ldap", "LDAP", NULL, + NULL, NULL }, { FALGPROTO_TYPE_MAX, 0, NULL, NULL, NULL, NULL } }; @@ -76,3 +90,7 @@ FalgprotoParamGetter falgproto_get_param_getter (FalgprotoType protocol) { FalgprotoPrinter falgproto_get_printer (FalgprotoType protocol) { return info[protocol].printer; } + +FalgprotoMatcher falgproto_get_matcher (FalgprotoType protocol) { + return info[protocol].matcher; +} diff --git a/falgproto/falgproto.h b/falgproto/falgproto.h index 0f66fe8..adf8fee 100644 --- a/falgproto/falgproto.h +++ b/falgproto/falgproto.h @@ -30,10 +30,23 @@ typedef struct falgproto_param { #define FALGPROTO_PARAM_RESULT_ERROR -1 #define FALGPROTO_PARAM_RESULT_OK 0 #define FALGPROTO_PARAM_RESULT_NOT_FOUND 1 -#define FALGPROTO_PARAM_RESULT_INCOMPLETE 2 +#define FALGPROTO_PARAM_RESULT_TRUNCATED 2 -typedef FalgprotoParam (*FalgprotoParamGetter) (const char *pkt); -typedef void (*FalgprotoPrinter) (const char *pkt, FILE *fp); +typedef FalgprotoParam (*FalgprotoParamGetter) (const char *pkt, size_t len); +typedef void (*FalgprotoPrinter) (FILE *fp, const char *pkt, size_t len); +typedef bool (*FalgprotoMatcher) ( + const char *big, size_t big_len, const char *little, size_t little_len); + +#define FALGPROTO_PARAM_GETTER_NAME(type) falgproto_##type##_param_getter +#define FALGPROTO_PARAM_GETTER_DECL(type) \ + FalgprotoParam FALGPROTO_PARAM_GETTER_NAME(type)(const char *pkt, size_t len) +#define FALGPROTO_PRINTER_NAME(type) falgproto_##type##_printer +#define FALGPROTO_PRINTER_DECL(type) \ + void FALGPROTO_PRINTER_NAME(type)(FILE *fp, const char *pkt, size_t len) +#define FALGPROTO_MATCHER_NAME(type) falgproto_##type##_matcher +#define FALGPROTO_MATCHER_DECL(type) \ + bool FALGPROTO_MATCHER_NAME(type) \ + (const char *big, size_t big_len, const char *little, size_t little_len) unsigned falgproto_get_count (void); @@ -43,6 +56,7 @@ const char* falgproto_get_description (FalgprotoType protocol); FalgprotoTransport falgproto_get_transport (FalgprotoType protocol); FalgprotoParamGetter falgproto_get_param_getter (FalgprotoType protocol); FalgprotoPrinter falgproto_get_printer (FalgprotoType protocol); +FalgprotoMatcher falgproto_get_matcher (FalgprotoType protocol); #endif /* FALGPROTO_H */ |