Commit Diff
Diff:
d67bdb6273c79e8d6bde41acd4bf0d0fdd3fc664
c0963faf0fd5fc9a3c77ab2336e970d55a801ecc
Commit:
c0963faf0fd5fc9a3c77ab2336e970d55a801ecc
Tree:
6211f0e70a8af690d15127857764e2a08e710692
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Thu May 1 15:26:24 2014 UTC
Message:
* add filtering capability, this is like recurse and will traverse a singly linked list everytime a connect or received packet is made. I'm hoping on revisiting this some day. Thanks to the guys that were abusing/scanning my dns server. * rename some variables around the queue(3) macros that I used for singly linked lists. They should have less confusing reuse of names. I did this in search for a bug that is possibly caused by OpenBSD-current which I currently use as my main developing workstation. * add a sample filter entry in example8.conf Tested to work on OpenBSD 5.5-stable
blob - b3794ce16454ecf42b835ca4e27cd96edf0de39a
blob + e7729fc4d378ffef214e7a10b3c927dcd4677912
--- Makefile.freebsd
+++ Makefile.freebsd
@@ -1,6 +1,6 @@
PROG=wildcarddnsd
-SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c
+SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c filter.c
CFLAGS= -Wall -g -I/usr/local/include/db5/
LDFLAGS= -Wall -g -L/usr/local/lib/db5/
blob - 1b8b85bece208c5b19734c3f3c045149ef4cd6d4
blob + 6b74db682845aaa7aba2f308245635193a908f5a
--- Makefile.linux
+++ Makefile.linux
@@ -20,6 +20,7 @@ build:
$(CC) $(CFLAGS) -c res_random.c
$(CC) $(CFLAGS) -c log.c
$(CC) $(CFLAGS) -c axfr.c
+ $(CC) $(CFLAGS) -c filter.c
$(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o recurse.o bsd-arc4random.o res_random.o log.o axfr.o $(LDADD)
blob - 242ae4c9d55787c68819744a24705e4aff4e6d53
blob + 2a44803c0025c62a5aaffc3855902735fdef8afd
--- Makefile.macosx
+++ Makefile.macosx
@@ -15,6 +15,7 @@ build:
$(CC) $(CFLAGS) -c log.c
$(CC) $(CFLAGS) -c recurse.c
$(CC) $(CFLAGS) -c axfr.c
+ $(CC) $(CFLAGS) -c filter.c
$(CC) $(CFLAGS) -c res_random.c
$(CC) $(CFLAGS) -c bsd-arc4random.c
$(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o log.o recurse.o axfr.o res_random.c bsd-arc4random.o $(LDADD)
blob - 19ac45818b08d37bfcf017563ae7643fcb7d96a3
blob + d66ff587db00ee9d01ee85aed299e6982a61d741
--- Makefile.netbsd
+++ Makefile.netbsd
@@ -1,6 +1,6 @@
PROG=wildcarddnsd
-SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c axfr.c
+SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c axfr.c filter.c
CFLAGS= -Wall -g -I/usr/pkg/include/db46/
LDFLAGS= -Wall -g -L/usr/pkg/lib -R/usr/pkg/lib
blob - 0fffe1cf10f04ef76326010436bd09a6886c3bd6
blob + 0eb70a6de7ddd55f7e1493e211486141de2831ef
--- Makefile.openbsd
+++ Makefile.openbsd
@@ -1,6 +1,6 @@
PROG=wildcarddnsd
-SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c
+SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c filter.c
#CFLAGS= -DDEBUG -g -Wall
CFLAGS= -Wall -g -I/usr/local/include/db4
blob - 0328ce97cd6fdd545a3dddb70f6353cd39decfe4
blob + 86f1db893aea6b46a4a6d5385db547ad8f19f000
--- axfr.c
+++ axfr.c
@@ -53,17 +53,17 @@ extern int debug, verbose;
SLIST_HEAD(listhead, axfrentry) axfrhead;
-struct axfrentry {
+static struct axfrentry {
char name[INET6_ADDRSTRLEN];
int family;
struct sockaddr_storage hostmask;
struct sockaddr_storage netmask;
u_int8_t prefixlen;
- SLIST_ENTRY(axfrentry) entries;
-} *an1, *an2, *anp;
+ SLIST_ENTRY(axfrentry) axfr_entry;
+} *an2, *anp;
-static const char rcsid[] = "$Id: axfr.c,v 1.6 2014/04/13 09:05:42 pjp Exp $";
+static const char rcsid[] = "$Id: axfr.c,v 1.7 2014/05/01 15:26:24 pjp Exp $";
/*
* INIT_AXFR - initialize the axfr singly linked list
@@ -115,7 +115,7 @@ insert_axfr(char *address, char *prefixlen)
}
- SLIST_INSERT_HEAD(&axfrhead, an2, entries);
+ SLIST_INSERT_HEAD(&axfrhead, an2, axfr_entry);
return (0);
}
@@ -139,7 +139,7 @@ find_axfr(struct sockaddr_storage *sst, int family)
u_int32_t *hm[4], *nm[4], *a6[4];
#endif
- SLIST_FOREACH(anp, &axfrhead, entries) {
+ SLIST_FOREACH(anp, &axfrhead, axfr_entry) {
if (anp->family == AF_INET) {
if (family != AF_INET)
continue;
blob - b6d98f01ef13cec9acfc5713f6e2b509f67433c8
blob + 8247dcbe3990f9c0636688477518ee4406054b43
--- db.h
+++ db.h
@@ -194,7 +194,7 @@ struct recurses {
int hascallback; /* some request has callback don't remove */
struct question *question; /* question struct */
- SLIST_ENTRY(recurses) entries;
+ SLIST_ENTRY(recurses) recurses_entry;
struct recurses *callback; /* callback */
} *sr, *sr1, *sr2;
blob - 2f7b998d67e97db45553d07536eb732dcb3aa9d6
blob + 4d286b6369ca40628a97fe85f0308008910c904e
--- example8.conf
+++ example8.conf
@@ -4,7 +4,7 @@ version "6";
options "cool stuff" {
interface "lo0";
- interface "re0";
+ interface "em0";
;bind 127.0.0.1;
;bind 192.168.34.4;
@@ -13,6 +13,10 @@ options "cool stuff" {
;fork 2;
log;
+}
+
+filter "these hosts" {
+ 127.0.0.1;
}
axfrport "10053";
blob - /dev/null
blob + ce56cf7baa9cf22cd832b479690d0be88dd69e8b (mode 644)
--- /dev/null
+++ filter.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2014 Peter J. Philipp
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ */
+#include "include.h"
+#include "dns.h"
+#include "db.h"
+
+/*
+void init_filter(void);
+int find_filter(struct sockaddr_storage *sst, int family);
+int insert_filter(char *address, char *prefixlen);
+*/
+
+extern in_addr_t getmask(int prefixlen);
+extern int getmask6(int prefixlen, struct sockaddr_in6 *sin6);
+extern void dolog(int, char *, ...);
+
+extern int debug, verbose;
+
+SLIST_HEAD(listhead, filterentry) filterhead;
+
+static struct filterentry {
+ char name[INET6_ADDRSTRLEN];
+ int family;
+ struct sockaddr_storage hostmask;
+ struct sockaddr_storage netmask;
+ u_int8_t prefixlen;
+ SLIST_ENTRY(filterentry) filter_entry;
+} *fn2, *fnp;
+
+
+static const char rcsid[] = "$Id: filter.c,v 1.1 2014/05/01 15:26:24 pjp Exp $";
+
+/*
+ * INIT_FILTER - initialize the filter singly linked list
+ */
+
+void
+init_filter(void)
+{
+ SLIST_INIT(&filterhead);
+ return;
+}
+
+/*
+ * INSERT_FILTER - insert an address and prefixlen into the filter slist
+ */
+
+int
+insert_filter(char *address, char *prefixlen)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ int pnum;
+ int ret;
+
+ pnum = atoi(prefixlen);
+ fn2 = malloc(sizeof(struct filterentry)); /* Insert after. */
+
+ if (strchr(address, ':') != NULL) {
+ fn2->family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&fn2->hostmask;
+ if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
+ return (-1);
+ sin6->sin6_family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&fn2->netmask;
+ sin6->sin6_family = AF_INET6;
+ if (getmask6(pnum, sin6) < 0)
+ return(-1);
+ fn2->prefixlen = pnum;
+ } else {
+
+ fn2->family = AF_INET;
+ sin = (struct sockaddr_in *)&fn2->hostmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = inet_addr(address);
+ sin = (struct sockaddr_in *)&fn2->netmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = getmask(pnum);
+ fn2->prefixlen = pnum;
+
+ }
+
+ SLIST_INSERT_HEAD(&filterhead, fn2, filter_entry);
+
+ return (0);
+}
+
+/*
+ * FIND_FILTER - walk the filter list and find the correponding network
+ * if a network matches return 1, if no match is found return
+ * 0.
+ */
+
+int
+find_filter(struct sockaddr_storage *sst, int family)
+{
+ struct sockaddr_in *sin, *sin0;
+ struct sockaddr_in6 *sin6, *sin60, *sin61;
+ u_int32_t hostmask, netmask;
+ u_int32_t a;
+#ifdef __amd64
+ u_int64_t *hm[2], *nm[2], *a6[2];
+#else
+ u_int32_t *hm[4], *nm[4], *a6[4];
+#endif
+
+ SLIST_FOREACH(fnp, &filterhead, filter_entry) {
+ if (fnp->family == AF_INET) {
+ if (family != AF_INET)
+ continue;
+ sin = (struct sockaddr_in *)sst;
+ a = sin->sin_addr.s_addr;
+ sin = (struct sockaddr_in *)&fnp->hostmask;
+ sin0 = (struct sockaddr_in *)&fnp->netmask;
+ hostmask = sin->sin_addr.s_addr;
+ netmask = sin0->sin_addr.s_addr;
+ if ((hostmask & netmask) == (a & netmask)) {
+ return (1);
+ } /* if hostmask */
+ } else if (fnp->family == AF_INET6) {
+ if (family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)sst;
+ sin60 = (struct sockaddr_in6 *)&fnp->hostmask;
+ sin61 = (struct sockaddr_in6 *)&fnp->netmask;
+#ifdef __amd64
+ /*
+ * If this is on a 64 bit machine, we'll benefit
+ * by using 64 bit registers, this should make it
+ * a tad faster...
+ */
+ hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1);
+ nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1);
+ a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1);
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
+#else
+ hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
+ hm[3] = (hm[2] + 1);
+ nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
+ nm[3] = (nm[2] + 1);
+ a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
+ a6[3] = (a6[2] + 1);
+
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
+ ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
+ ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
+#endif
+
+ return (1);
+ } /* if ip6 address */
+
+ } /* if AF_INET6 */
+ } /* SLIST */
+
+ return (0);
+}
blob - 9c997f9558db784fdeebdea4265f2eb0bc067a15
blob + 92cf1b5cb1fd71005019969d9000138c8d3ca679
--- main.c
+++ main.c
@@ -42,6 +42,7 @@ int get_soa(DB *, struct question *, struct domain *,
extern void reply_notimpl(struct sreply *);
extern void reply_nxdomain(struct sreply *);
extern void reply_noerror(struct sreply *);
+extern void reply_refused(struct sreply *);
extern void reply_fmterror(struct sreply *);
extern void reply_a(struct sreply *, DB *);
extern void reply_aaaa(struct sreply *, DB *);
@@ -57,9 +58,11 @@ extern void reply_srv(struct sreply *, DB *);
extern void reply_sshfp(struct sreply *);
extern u_int8_t find_region(struct sockaddr_storage *sst, int family);
extern int find_wildcard(struct sockaddr_storage *sst, int family);
+extern int find_filter(struct sockaddr_storage *sst, int family);
extern void init_wildcard(void);
extern void init_recurse(void);
extern void init_region(void);
+extern void init_filter(void);
extern void collects_init(void);
extern void recurseloop(int sp, int *raw, DB *db);
extern int find_recurse(struct sockaddr_storage *, int);
@@ -140,7 +143,7 @@ char *interface_list[255];
/* singly linked list for tcp operations */
SLIST_HEAD(listhead, tcps) tcpshead;
-struct tcps {
+static struct tcps {
char *input;
char *ident;
char *address;
@@ -152,11 +155,11 @@ struct tcps {
u_int8_t region;
int wildcard;
time_t time;
- SLIST_ENTRY(tcps) entries;
-} *tn1, *tn2, *tnp;
+ SLIST_ENTRY(tcps) tcps_entry;
+} *tn1, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.85 2014/04/21 19:26:15 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.86 2014/05/01 15:26:24 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -412,6 +415,7 @@ main(int argc, char *argv[])
init_wildcard();
init_recurse();
init_region();
+ init_filter();
if (parse_file(db, conffile) < 0) {
dolog(LOG_INFO, "parsing config file failed\n");
@@ -2119,6 +2123,7 @@ mainloop(struct cfg *cfg)
int type0, type1;
int lzerrno;
int wildcard = 0;
+ int filter = 0;
int sp;
int lfd;
@@ -2200,13 +2205,13 @@ mainloop(struct cfg *cfg)
* check for timeouts
*/
- SLIST_FOREACH(tnp, &tcpshead, entries) {
+ SLIST_FOREACH(tnp, &tcpshead, tcps_entry) {
if ((tnp->time + 10) < time(NULL)) {
free(tnp->input);
free(tnp->ident);
free(tnp->address);
close(tnp->so);
- SLIST_REMOVE(&tcpshead, tnp, tcps, entries);
+ SLIST_REMOVE(&tcpshead, tnp, tcps, tcps_entry);
free(tnp);
}
}
@@ -2229,7 +2234,7 @@ mainloop(struct cfg *cfg)
FD_SET(cfg->axfr[i], &rset);
}
- SLIST_FOREACH(tnp, &tcpshead, entries) {
+ SLIST_FOREACH(tnp, &tcpshead, tcps_entry) {
if (maxso < tnp->so)
maxso = tnp->so;
@@ -2253,13 +2258,13 @@ mainloop(struct cfg *cfg)
}
if (sel == 0) {
- SLIST_FOREACH(tnp, &tcpshead, entries) {
+ SLIST_FOREACH(tnp, &tcpshead, tcps_entry) {
if ((tnp->time + 10) < time(NULL)) {
free(tnp->input);
free(tnp->ident);
free(tnp->address);
close(tnp->so);
- SLIST_REMOVE(&tcpshead, tnp, tcps, entries);
+ SLIST_REMOVE(&tcpshead, tnp, tcps, tcps_entry);
free(tnp);
}
}
@@ -2285,6 +2290,8 @@ mainloop(struct cfg *cfg)
inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, (char *)&address, sizeof(address));
aregion = find_region((struct sockaddr_storage *)sin6, AF_INET6);
wildcard = find_wildcard((struct sockaddr_storage *)sin6, AF_INET6);
+ // filter = find_filter((struct sockaddr_storage *)sin6, AF_INET6);
+ filter = 0;
} else if (from->sa_family == AF_INET) {
is_ipv6 = 0;
@@ -2293,12 +2300,21 @@ mainloop(struct cfg *cfg)
inet_ntop(AF_INET, (void *)&sin->sin_addr, (char *)&address, sizeof(address));
wildcard = find_wildcard((struct sockaddr_storage *)sin, AF_INET);
aregion = find_region((struct sockaddr_storage *)sin, AF_INET);
+ filter = find_filter((struct sockaddr_storage *)sin, AF_INET);
} else {
dolog(LOG_INFO, "TCP packet received on descriptor %u interface \"%s\" had weird address family (%u), drop\n", so, cfg->ident[i], from->sa_family);
close(so);
continue;
}
+
+ if (filter) {
+ dolog(LOG_INFO, "TCP connection refused on descriptor %u interface \"%s\" from %s, filter policy\n", so, cfg->ident[i], address);
+ close(so);
+ continue;
+ }
+
+
/*
* make this socket nonblocking
*/
@@ -2339,12 +2355,12 @@ mainloop(struct cfg *cfg)
tn1->wildcard = wildcard;
tn1->time = time(NULL);
- SLIST_INSERT_HEAD(&tcpshead, tn1, entries);
+ SLIST_INSERT_HEAD(&tcpshead, tn1, tcps_entry);
} /* FD_ISSET(); */
} /* if sockcount */
- SLIST_FOREACH(tnp, &tcpshead, entries) {
+ SLIST_FOREACH(tnp, &tcpshead, tcps_entry) {
if (FD_ISSET(tnp->so, &rset)) {
istcp = 1;
@@ -2357,7 +2373,7 @@ mainloop(struct cfg *cfg)
free(tnp->ident);
free(tnp->address);
close(tnp->so);
- SLIST_REMOVE(&tcpshead, tnp, tcps, entries);
+ SLIST_REMOVE(&tcpshead, tnp, tcps, tcps_entry);
free(tnp);
continue;
}
@@ -2368,7 +2384,7 @@ mainloop(struct cfg *cfg)
free(tnp->ident);
free(tnp->address);
close(tnp->so);
- SLIST_REMOVE(&tcpshead, tnp, tcps, entries);
+ SLIST_REMOVE(&tcpshead, tnp, tcps, tcps_entry);
free(tnp);
continue;
}
@@ -2865,6 +2881,7 @@ axfrentry:
inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, (char *)&address, sizeof(address));
aregion = find_region((struct sockaddr_storage *)sin6, AF_INET6);
wildcard = find_wildcard((struct sockaddr_storage *)sin6, AF_INET6);
+ filter = find_filter((struct sockaddr_storage *)sin6, AF_INET6);
if (rflag) {
recursion = find_recurse((struct sockaddr_storage *)sin6, AF_INET6);
recurseheader(&rh, IPPROTO_UDP, (struct sockaddr_storage*)sin6, &sto, AF_INET6);
@@ -2877,6 +2894,7 @@ axfrentry:
inet_ntop(AF_INET, (void *)&sin->sin_addr, (char *)&address, sizeof(address));
aregion = find_region((struct sockaddr_storage *)sin, AF_INET);
wildcard = find_wildcard((struct sockaddr_storage *)sin, AF_INET);
+ filter = find_filter((struct sockaddr_storage *)sin, AF_INET);
if (rflag) {
recursion = find_recurse((struct sockaddr_storage *)sin, AF_INET);
recurseheader(&rh, IPPROTO_UDP, (struct sockaddr_storage*)sin, &sto, AF_INET);
@@ -2914,6 +2932,16 @@ axfrentry:
dolog(LOG_INFO, "question on descriptor %d interface \"%s\" from %s, did not have question of 1 replying format error\n", so, cfg->ident[i], address);
goto drop;
}
+
+ if (filter) {
+
+ build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, wildcard, NULL, replybuf);
+ reply_refused(&sreply);
+
+ dolog(LOG_INFO, "UDP connection refused on descriptor %u interface \"%s\" from %s (ttl=%d, region=%d) replying REFUSED, filter policy\n", so, cfg->ident[i], address, received_ttl, aregion);
+ goto drop;
+ }
+
if (rflag && recursion) {
memcpy(&rh.buf, buf, len);
blob - 0de34bae29bce4b78698b28460a0d5a19231fa4c
blob + 9b80333efd439209ed9f92fcb0d401a8c2c7c3fd
--- parse.y
+++ parse.y
@@ -58,7 +58,7 @@ typedef struct {
int lineno;
} YYSTYPE;
-static const char rcsid[] = "$Id: parse.y,v 1.15 2014/04/22 08:01:47 pjp Exp $";
+static const char rcsid[] = "$Id: parse.y,v 1.16 2014/05/01 15:26:24 pjp Exp $";
static int version = 0;
static int state = 0;
static uint8_t region = 0;
@@ -92,6 +92,7 @@ extern char * dns_label(char *, int *);
extern u_int8_t find_region(struct sockaddr_storage *sst, int family);
extern int insert_region(char *address, char *prefixlen, u_int8_t region);
extern int insert_axfr(char *, char *);
+extern int insert_filter(char *, char *);
extern int insert_recurse(char *, char *);
extern int insert_wildcard(char *, char *);
extern void dolog(int, char *, ...);
@@ -173,7 +174,7 @@ parse_file(DB *db, char *filename)
%token VERSION OBRACE EBRACE REGION AXFRFOR RECURSEFOR
%token DOT COLON TEXT WOF INCLUDE ZONE COMMA CRLF
-%token ERROR AXFRPORT LOGGING OPTIONS
+%token ERROR AXFRPORT LOGGING OPTIONS FILTER
%token <v.string> POUND
%token <v.string> SEMICOLON
@@ -202,6 +203,7 @@ cmd :
| region CRLF
| wof CRLF
| axfr CRLF
+ | filter CRLF
| recurse CRLF
| logging
| comment CRLF
@@ -750,6 +752,57 @@ loggingstatement:
| comment CRLF
;
+/* filter "these hosts" { .. } */
+
+filter:
+ FILTER filterlabel filtercontent
+ {
+ if ((confstatus & CONFIG_VERSION) != CONFIG_VERSION) {
+ dolog(LOG_INFO, "There must be a version at the top of the first configfile\n");
+ return (-1);
+ }
+ }
+ ;
+
+filterlabel:
+ QUOTEDSTRING
+ ;
+
+filtercontent:
+ OBRACE filterstatements EBRACE
+ | OBRACE CRLF filterstatements EBRACE
+ ;
+
+filterstatements :
+ filterstatements filterstatement
+ | filterstatement
+ ;
+
+filterstatement : ipcidr SEMICOLON CRLF
+ {
+ char prefixlength[INET_ADDRSTRLEN];
+ char *dst;
+
+
+ if ((dst = get_prefixlen($1, (char *)&prefixlength, sizeof(prefixlength))) == NULL) {
+ return (-1);
+ }
+
+ if (insert_filter(dst, prefixlength) < 0) {
+ dolog(LOG_ERR, "insert_filter, line %d\n", file->lineno);
+ return (-1);
+ }
+
+ if (debug)
+ printf("recurse inserted %s address\n", $1);
+
+ free (dst);
+ free ($1);
+ }
+ | comment CRLF
+ ;
+
+
/* axfr-for "these hosts" { .. } */
axfr:
@@ -994,6 +1047,7 @@ struct tab * lookup(struct tab *cmdtab, char *keyword)
struct tab cmdtab[] = {
{ "axfrport", AXFRPORT, 0},
{ "axfr-for", AXFRFOR, STATE_IP },
+ { "filter", FILTER, STATE_IP },
{ "include", INCLUDE, 0 },
{ "logging", LOGGING, 0 },
{ "options", OPTIONS, 0 },
blob - af4d92924444829421dc0f00ce83139f37cf8178
blob + fb9a41778e51acf0496d9dbb9ef990e26cab4190
--- recurse.c
+++ recurse.c
@@ -83,17 +83,17 @@ extern int debug, verbose;
SLIST_HEAD(listhead, recurseentry) recursehead;
-struct recurseentry {
+static struct recurseentry {
char name[INET6_ADDRSTRLEN];
int family;
struct sockaddr_storage hostmask;
struct sockaddr_storage netmask;
u_int8_t prefixlen;
- SLIST_ENTRY(recurseentry) entries;
-} *rn1, *rn2, *rnp;
+ SLIST_ENTRY(recurseentry) recurse_entry;
+} *rn2, *rnp;
-static const char rcsid[] = "$Id: recurse.c,v 1.41 2014/04/13 09:05:42 pjp Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.42 2014/05/01 15:26:24 pjp Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -145,7 +145,7 @@ insert_recurse(char *address, char *prefixlen)
}
- SLIST_INSERT_HEAD(&recursehead, rn2, entries);
+ SLIST_INSERT_HEAD(&recursehead, rn2, recurse_entry);
return (0);
}
@@ -169,7 +169,7 @@ find_recurse(struct sockaddr_storage *sst, int family)
u_int32_t *hm[4], *nm[4], *a6[4];
#endif
- SLIST_FOREACH(rnp, &recursehead, entries) {
+ SLIST_FOREACH(rnp, &recursehead, recurse_entry) {
if (rnp->family == AF_INET) {
if (family != AF_INET)
continue;
@@ -255,7 +255,7 @@ recurseloop(int sp, int *raw, DB *db)
/*
* launch all fakesr requests
*/
- SLIST_FOREACH(sr1, &recurseshead, entries) {
+ SLIST_FOREACH(sr1, &recurseshead, recurses_entry) {
if (sr1->isfake && !sr1->launched) {
dolog(LOG_DEBUG, "launching question (fakesr) for %s", sr1->question->hdr->name);
sr1->launched = 1;
@@ -263,7 +263,7 @@ recurseloop(int sp, int *raw, DB *db)
if (type < 0) {
netlookup(db, sr1);
} else {
- SLIST_REMOVE(&recurseshead, sr1, recurses, entries);
+ SLIST_REMOVE(&recurseshead, sr1, recurses, recurses_entry);
sr1->callback->hascallback--;
free_question(sr1->question);
free(sr1);
@@ -281,7 +281,7 @@ recurseloop(int sp, int *raw, DB *db)
*/
if (! sr1->hascallback) {
dolog(LOG_DEBUG, "removing recurses struct");
- SLIST_REMOVE(&recurseshead, sr1, recurses, entries);
+ SLIST_REMOVE(&recurseshead, sr1, recurses, recurses_entry);
if (sr1->so != -1) {
if (close(sr1->so) < 0)
dolog(LOG_ERR, "close: %m");
@@ -302,7 +302,7 @@ recurseloop(int sp, int *raw, DB *db)
FD_SET(sp, &rset);
/* XXX remember recurseshead is for struct recurses */
- SLIST_FOREACH(sr1, &recurseshead, entries) {
+ SLIST_FOREACH(sr1, &recurseshead, recurses_entry) {
if (sr1->so != -1) {
if (maxso < sr1->so)
maxso = sr1->so;
@@ -373,7 +373,7 @@ recurseloop(int sp, int *raw, DB *db)
if (netlookup(db, sr) < 0)
continue;
- SLIST_INSERT_HEAD(&recurseshead, sr, entries);
+ SLIST_INSERT_HEAD(&recurseshead, sr, recurses_entry);
} else {
dolog(LOG_DEBUG, "we had the record in our cache, reply action");
/* check if zone is expired */
@@ -387,7 +387,7 @@ recurseloop(int sp, int *raw, DB *db)
if (netlookup(db, sr) < 0)
continue;
- SLIST_INSERT_HEAD(&recurseshead, sr, entries);
+ SLIST_INSERT_HEAD(&recurseshead, sr, recurses_entry);
continue;
}
@@ -403,7 +403,7 @@ recurseloop(int sp, int *raw, DB *db)
} /* FD_ISSET(sp) */
- SLIST_FOREACH(sr1, &recurseshead, entries) {
+ SLIST_FOREACH(sr1, &recurseshead, recurses_entry) {
if (sr1->so != -1 && FD_ISSET(sr1->so, &rset)) {
/*
* we got a reply from the nameserver we
@@ -535,7 +535,7 @@ remove:
* outstanding...
*/
if (! sr1->hascallback) {
- SLIST_REMOVE(&recurseshead, sr1, recurses, entries);
+ SLIST_REMOVE(&recurseshead, sr1, recurses, recurses_entry);
free_question(sr1->question);
free(sr1);
}
@@ -1740,7 +1740,7 @@ fakerecurse(DB *db, struct recurses *sr, struct ns *ns
/* check if we have already started a fakerecurse on the same name */
- SLIST_FOREACH(sr2, &recurseshead, entries) {
+ SLIST_FOREACH(sr2, &recurseshead, recurses_entry) {
if (memcasecmp((u_char *)ns->nsserver, (u_char *)sr2->question->hdr->name, MIN(ns->nslen, sr2->question->hdr->namelen)) == 0) {
dolog(LOG_INFO, "already have a fakerecurse structure with name %s, drop\n", ns->nsserver);
return (-1);
@@ -1800,7 +1800,7 @@ fakerecurse(DB *db, struct recurses *sr, struct ns *ns
fakesr->len = len;
- SLIST_INSERT_HEAD(&recurseshead, fakesr, entries);
+ SLIST_INSERT_HEAD(&recurseshead, fakesr, recurses_entry);
return (0);
}
blob - 0617754fc3e1919ad07a61af8775a88d8e1890a1
blob + 00b09ed92476c805ee03cd6ba93f961183824db7
--- region.c
+++ region.c
@@ -37,18 +37,18 @@ int getmask6(int prefixlen, struct sockaddr_in6 *sin6)
SLIST_HEAD(listhead, entry) head;
-struct entry {
+static struct entry {
char name[INET6_ADDRSTRLEN];
int family;
struct sockaddr_storage hostmask;
struct sockaddr_storage netmask;
u_int8_t region;
u_int8_t prefixlen;
- SLIST_ENTRY(entry) entries;
-} *n1, *n2, *np;
+ SLIST_ENTRY(entry) region_entry;
+} *n2, *np;
-static const char rcsid[] = "$Id: region.c,v 1.9 2014/04/13 09:05:42 pjp Exp $";
+static const char rcsid[] = "$Id: region.c,v 1.10 2014/05/01 15:26:24 pjp Exp $";
/*
* INIT_REGION - initialize the region singly linked list
@@ -106,7 +106,7 @@ insert_region(char *address, char *prefixlen, u_int8_t
}
- SLIST_INSERT_HEAD(&head, n2, entries);
+ SLIST_INSERT_HEAD(&head, n2, region_entry);
return (0);
}
@@ -133,7 +133,7 @@ find_region(struct sockaddr_storage *sst, int family)
u_int8_t region = 0xff;
u_int8_t prefixlen = 0;
- SLIST_FOREACH(np, &head, entries) {
+ SLIST_FOREACH(np, &head, region_entry) {
if (np->family == AF_INET) {
if (family != AF_INET)
continue;
blob - d1e06d629ec1e98924a2343c5b97793584637496
blob + 8d33325ecd798bcf3286be913c74046fedf80aa3
--- reply.c
+++ reply.c
@@ -44,6 +44,7 @@ void reply_srv(struct sreply *sreply, DB *db);
void reply_sshfp(struct sreply *);
void reply_cname(struct sreply *);
void reply_any(struct sreply *);
+void reply_refused(struct sreply *);
void reply_fmterror(struct sreply *);
void reply_raw2(int so, char *reply, int outlen, struct recurses *sr);
void reply_raw6(int so, char *reply, int outlen, struct recurses *sr);
@@ -80,13 +81,13 @@ struct collects {
u_int16_t namelen;
u_int16_t type;
struct domain *sd;
- SLIST_ENTRY(collects) entries;
+ SLIST_ENTRY(collects) collect_entry;
} *cn1, *cn2, *cnp;
extern int debug, verbose;
-static const char rcsid[] = "$Id: reply.c,v 1.54 2014/04/22 07:21:23 pjp Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.55 2014/05/01 15:26:24 pjp Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -501,7 +502,7 @@ reply_mx(struct sreply *sreply, DB *db)
cn1->sd = sd0;
cn1->type = DNS_TYPE_A;
- SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ SLIST_INSERT_HEAD(&collectshead, cn1, collect_entry);
}
}
}
@@ -516,7 +517,7 @@ reply_mx(struct sreply *sreply, DB *db)
cn1->sd = sd0;
cn1->type = DNS_TYPE_AAAA;
- SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ SLIST_INSERT_HEAD(&collectshead, cn1, collect_entry);
}
}
}
@@ -537,7 +538,7 @@ reply_mx(struct sreply *sreply, DB *db)
/* write additional */
- SLIST_FOREACH(cnp, &collectshead, entries) {
+ SLIST_FOREACH(cnp, &collectshead, collect_entry) {
int addcount;
int tmplen;
@@ -561,7 +562,7 @@ reply_mx(struct sreply *sreply, DB *db)
while (!SLIST_EMPTY(&collectshead)) {
cn1 = SLIST_FIRST(&collectshead);
- SLIST_REMOVE_HEAD(&collectshead, entries);
+ SLIST_REMOVE_HEAD(&collectshead, collect_entry);
free(cn1->name);
free(cn1->sd);
free(cn1);
@@ -722,7 +723,7 @@ reply_ns(struct sreply *sreply, DB *db)
cn1->sd = sd0;
cn1->type = DNS_TYPE_A;
- SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ SLIST_INSERT_HEAD(&collectshead, cn1, collect_entry);
}
}
@@ -738,7 +739,7 @@ reply_ns(struct sreply *sreply, DB *db)
cn1->sd = sd0;
cn1->type = DNS_TYPE_AAAA;
- SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ SLIST_INSERT_HEAD(&collectshead, cn1, collect_entry);
}
}
@@ -771,7 +772,7 @@ reply_ns(struct sreply *sreply, DB *db)
/* shuffle through our linked collect structure and add additional */
- SLIST_FOREACH(cnp, &collectshead, entries) {
+ SLIST_FOREACH(cnp, &collectshead, collect_entry) {
int addcount;
int tmplen;
@@ -795,7 +796,7 @@ reply_ns(struct sreply *sreply, DB *db)
while (!SLIST_EMPTY(&collectshead)) {
cn1 = SLIST_FIRST(&collectshead);
- SLIST_REMOVE_HEAD(&collectshead, entries);
+ SLIST_REMOVE_HEAD(&collectshead, collect_entry);
free(cn1->name);
free(cn1->sd);
free(cn1);
@@ -1878,7 +1879,7 @@ reply_srv(struct sreply *sreply, DB *db)
cn1->sd = sd0;
cn1->type = DNS_TYPE_A;
- SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ SLIST_INSERT_HEAD(&collectshead, cn1, collect_entry);
}
}
}
@@ -1893,7 +1894,7 @@ reply_srv(struct sreply *sreply, DB *db)
cn1->sd = sd0;
cn1->type = DNS_TYPE_AAAA;
- SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ SLIST_INSERT_HEAD(&collectshead, cn1, collect_entry);
}
}
}
@@ -1914,7 +1915,7 @@ reply_srv(struct sreply *sreply, DB *db)
/* write additional */
- SLIST_FOREACH(cnp, &collectshead, entries) {
+ SLIST_FOREACH(cnp, &collectshead, collect_entry) {
int addcount;
int tmplen;
@@ -1938,7 +1939,7 @@ reply_srv(struct sreply *sreply, DB *db)
while (!SLIST_EMPTY(&collectshead)) {
cn1 = SLIST_FIRST(&collectshead);
- SLIST_REMOVE_HEAD(&collectshead, entries);
+ SLIST_REMOVE_HEAD(&collectshead, collect_entry);
free(cn1->name);
free(cn1->sd);
free(cn1);
@@ -2317,6 +2318,74 @@ reply_nxdomain(struct sreply *sreply)
}
}
} /* sreply->sr.. */
+
+ return;
+}
+
+/*
+ * REPLY_REFUSED() - replies a DNS question (*q) on socket (so)
+ *
+ */
+
+void
+reply_refused(struct sreply *sreply)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ u_int16_t outlen;
+
+ int so = sreply->so;
+ int len = sreply->len;
+ char *buf = sreply->buf;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ memset(reply, 0, replysize);
+
+ odh = (struct dns_header *)&reply[0];
+
+ outlen = sizeof(struct dns_header);
+
+ if (len > replysize) {
+ return;
+ }
+
+ memcpy((char *)&odh->id, buf, sizeof(u_int16_t));
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+
+ SET_DNS_REPLY(odh);
+ SET_DNS_RCODE_REFUSED(odh);
+
+ HTONS(odh->query);
+
+ if (istcp) {
+ char *tmpbuf;
+ u_int16_t *plen;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == NULL) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ plen = (u_int16_t *)tmpbuf;
+ *plen = htons(outlen);
+
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if (send(so, tmpbuf, outlen + 2, 0) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if (sendto(so, reply, sizeof(struct dns_header), 0, sa, salen) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
return;
}
blob - 4a0746311bd7e3551aec9c824c5684255b652061
blob + ae7b74188f942674590bb0791a04157f5f689b3f
--- wildcard.c
+++ wildcard.c
@@ -37,17 +37,17 @@ extern int getmask6(int prefixlen, struct sockaddr_in6
SLIST_HEAD(listhead, wildentry) wildhead;
-struct wildentry {
+static struct wildentry {
char name[INET6_ADDRSTRLEN];
int family;
struct sockaddr_storage hostmask;
struct sockaddr_storage netmask;
u_int8_t prefixlen;
- SLIST_ENTRY(wildentry) entries;
-} *wn1, *wn2, *wnp;
+ SLIST_ENTRY(wildentry) wildcard_entry;
+} *wn2, *wnp;
-static const char rcsid[] = "$Id: wildcard.c,v 1.5 2014/04/13 09:05:42 pjp Exp $";
+static const char rcsid[] = "$Id: wildcard.c,v 1.6 2014/05/01 15:26:24 pjp Exp $";
/*
* INIT_WILDCARD - initialize the wildcard singly linked list
@@ -99,7 +99,7 @@ insert_wildcard(char *address, char *prefixlen)
}
- SLIST_INSERT_HEAD(&wildhead, wn2, entries);
+ SLIST_INSERT_HEAD(&wildhead, wn2, wildcard_entry);
return (0);
}
@@ -123,7 +123,7 @@ find_wildcard(struct sockaddr_storage *sst, int family
u_int32_t *hm[4], *nm[4], *a6[4];
#endif
- SLIST_FOREACH(wnp, &wildhead, entries) {
+ SLIST_FOREACH(wnp, &wildhead, wildcard_entry) {
if (wnp->family == AF_INET) {
if (family != AF_INET)
continue;
repomaster@centroid.eu