summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2008-07-18 14:44:51 +0000
committerdwmalone <dwmalone@FreeBSD.org>2008-07-18 14:44:51 +0000
commitf7cc3b4928dba59c3eead3afb623459bc1d4c80a (patch)
tree887336a69c3082404b65301ea919425f27456092 /sys
parent4efb6d2a37b496ded581b12ed193e4ebe091076a (diff)
downloadFreeBSD-src-f7cc3b4928dba59c3eead3afb623459bc1d4c80a.zip
FreeBSD-src-f7cc3b4928dba59c3eead3afb623459bc1d4c80a.tar.gz
Add an accept filter for TCP based DNS requests. It waits until the
whole first request is present before returning from accept.
Diffstat (limited to 'sys')
-rw-r--r--sys/boot/forth/loader.conf1
-rw-r--r--sys/conf/NOTES1
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/options1
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/accf_dns/Makefile8
-rw-r--r--sys/netinet/accf_dns.c135
7 files changed, 148 insertions, 0 deletions
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 2a34dbe..4584a13 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -391,6 +391,7 @@ bktr_load="NO" # Brooktree Bt848/Bt878 TV/Video Capture Card
ispfw_load="NO" # Qlogic ISP Firmware
agp_load="NO" # agp module
accf_data_load="NO" # Wait for data accept filter
+accf_dns_load="NO" # Wait for data accept filter
accf_http_load="NO" # Wait for full HTTP request accept filter
random_load="NO" # Random device
speaker_load="NO" # AT speaker module
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 3f61a67..e71fbcc 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -887,6 +887,7 @@ options MBUF_PROFILING
# Statically Link in accept filters
options ACCEPT_FILTER_DATA
+options ACCEPT_FILTER_DNS
options ACCEPT_FILTER_HTTP
# TCP_SIGNATURE adds support for RFC 2385 (TCP-MD5) digests. These are
diff --git a/sys/conf/files b/sys/conf/files
index a5c7356..4ca36e1 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1902,6 +1902,7 @@ netgraph/ng_tee.c optional netgraph_tee
netgraph/ng_tty.c optional netgraph_tty
netgraph/ng_vjc.c optional netgraph_vjc
netinet/accf_data.c optional accept_filter_data
+netinet/accf_dns.c optional accept_filter_dns
netinet/accf_http.c optional accept_filter_http
netinet/if_atm.c optional atm
netinet/if_ether.c optional ether
diff --git a/sys/conf/options b/sys/conf/options
index 7e5c9c5..b58ba7e 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -342,6 +342,7 @@ ATA_NOPCI opt_ata.h
# Net stuff.
ACCEPT_FILTER_DATA
+ACCEPT_FILTER_DNS
ACCEPT_FILTER_HTTP
ALTQ opt_global.h
ALTQ_CBQ opt_altq.h
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 9ffd1d1..6a5a7b1 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -6,6 +6,7 @@ SUBDIR= ${_3dfx} \
${_3dfx_linux} \
${_aac} \
accf_data \
+ accf_dns \
accf_http \
${_acpi} \
age \
diff --git a/sys/modules/accf_dns/Makefile b/sys/modules/accf_dns/Makefile
new file mode 100644
index 0000000..49012e2
--- /dev/null
+++ b/sys/modules/accf_dns/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../netinet
+
+KMOD= accf_dns
+SRCS= accf_dns.c
+
+.include <bsd.kmod.mk>
diff --git a/sys/netinet/accf_dns.c b/sys/netinet/accf_dns.c
new file mode 100644
index 0000000..1db9076
--- /dev/null
+++ b/sys/netinet/accf_dns.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2007 David Malone <dwmalone@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define ACCEPT_FILTER_MOD
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+#include <sys/socketvar.h>
+
+/* check for full DNS request */
+static void sohasdns(struct socket *so, void *arg, int waitflag);
+
+struct packet {
+ struct mbuf *m; /* Current mbuf. */
+ struct mbuf *n; /* nextpkt mbuf. */
+ unsigned long moff; /* Offset of the beginning of m. */
+ unsigned long offset; /* Which offset we are working at. */
+ unsigned long len; /* The number of bytes we have to play with. */
+};
+
+#define DNS_OK 0
+#define DNS_WAIT -1
+#define DNS_RUN -2
+
+/* check we can skip over various parts of DNS request */
+static int skippacket(struct sockbuf *sb);
+
+static struct accept_filter accf_dns_filter = {
+ "dnsready",
+ sohasdns,
+ NULL,
+ NULL
+};
+
+static moduledata_t accf_dns_mod = {
+ "accf_dns",
+ accept_filt_generic_mod_event,
+ &accf_dns_filter
+};
+
+DECLARE_MODULE(accf_dns, accf_dns_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+
+static void
+sohasdns(struct socket *so, void *arg, int waitflag)
+{
+ struct sockbuf *sb = &so->so_rcv;
+
+ /* If the socket is full, we're ready. */
+ if (sb->sb_cc >= sb->sb_hiwat || sb->sb_mbcnt >= sb->sb_mbmax)
+ goto ready;
+
+ /* Check and see if we have a request. */
+ if (skippacket(sb) == DNS_WAIT)
+ return;
+
+ready:
+ so->so_upcall = NULL;
+ so->so_rcv.sb_flags &= ~SB_UPCALL;
+ soisconnected(so);
+ return;
+}
+
+#define GET8(p, val) do { \
+ if (p->offset < p->moff) \
+ return DNS_RUN; \
+ while (p->offset >= p->moff + p->m->m_len) { \
+ p->moff += p->m->m_len; \
+ p->m = p->m->m_next; \
+ if (p->m == NULL) { \
+ p->m = p->n; \
+ p->n = p->m->m_nextpkt; \
+ } \
+ if (p->m == NULL) \
+ return DNS_WAIT; \
+ } \
+ val = *(mtod(p->m, unsigned char *) + (p->offset - p->moff)); \
+ p->offset++; \
+ } while (0)
+
+#define GET16(p, val) do { \
+ unsigned int v0, v1; \
+ GET8(p, v0); \
+ GET8(p, v1); \
+ val = v0 * 0x100 + v1; \
+ } while (0)
+
+static int
+skippacket(struct sockbuf *sb) {
+ unsigned long packlen;
+ struct packet q, *p = &q;
+
+ if (sb->sb_cc < 2)
+ return DNS_WAIT;
+
+ q.m = sb->sb_mb;
+ q.n = q.m->m_nextpkt;
+ q.moff = 0;
+ q.offset = 0;
+ q.len = sb->sb_cc;
+
+ GET16(p, packlen);
+ if (packlen + 2 < q.len)
+ return DNS_WAIT;
+
+ return DNS_OK;
+}
OpenPOWER on IntegriCloud