diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2008-07-18 14:44:51 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2008-07-18 14:44:51 +0000 |
commit | f7cc3b4928dba59c3eead3afb623459bc1d4c80a (patch) | |
tree | 887336a69c3082404b65301ea919425f27456092 /sys | |
parent | 4efb6d2a37b496ded581b12ed193e4ebe091076a (diff) | |
download | FreeBSD-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.conf | 1 | ||||
-rw-r--r-- | sys/conf/NOTES | 1 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/modules/Makefile | 1 | ||||
-rw-r--r-- | sys/modules/accf_dns/Makefile | 8 | ||||
-rw-r--r-- | sys/netinet/accf_dns.c | 135 |
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; +} |