summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac2
-rw-r--r--falgproto/falgproto-match-hostname.c30
-rw-r--r--falgproto/falgproto-protocol-dns.c119
-rw-r--r--falgproto/falgproto.c22
-rw-r--r--falgproto/falgproto.h20
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 */