[dns-operations] "dnscap -x" ?
Paul Vixie
paul at vix.com
Tue May 15 17:57:00 UTC 2007
several folks from the DNSBL community wanted to be able to select packets
by regex. this patch adds the following command line option:
-x pat If one or more -x options are provided, then DNS messages
will only be selected if their presentation format represen-
tation matches at least one of the provided pat patterns.
See regex(3) and re_format(7) for more information about
extended regular expression syntax.
should i fold this relatively small thing in before releasing V1.0? note,
it requires libbind (so it's disabled, like "-g", if you don't have libbind.)
-------------- next part --------------
? diffs
Index: dnscap.1
===================================================================
RCS file: /proj/cvsroot/dnscap/dnscap.1,v
retrieving revision 1.3
diff -u -r1.3 dnscap.1
--- dnscap.1 10 May 2007 18:46:53 -0000 1.3
+++ dnscap.1 15 May 2007 16:13:43 -0000
@@ -28,6 +28,7 @@
.Oc
.Op Fl t Ar lim
.Op Fl c Ar lim
+.Op Fl x Ar pat ...
.Sh DESCRIPTION
.Nm
is a network capture utility designed specifically for DNS traffic. It
@@ -151,6 +152,17 @@
.Nm
exits. This option is inclusive with
.Fl t .
+.It Fl x Ar pat
+If one or more
+.Fl x
+options are provided, then DNS messages will only be selected if their
+presentation format representation matches at least one of the provided
+.Ar pat
+patterns. See
+.Xr regex 3
+and
+.Xr re_format 7
+for more information about extended regular expression syntax.
.El
.Pp
If started up with no options,
Index: dnscap.c
===================================================================
RCS file: /proj/cvsroot/dnscap/dnscap.c,v
retrieving revision 1.8
diff -u -r1.8 dnscap.c
--- dnscap.c 14 May 2007 22:09:29 -0000 1.8
+++ dnscap.c 15 May 2007 16:13:43 -0000
@@ -57,6 +57,7 @@
#include <errno.h>
#include <netdb.h>
#include <pcap.h>
+#include <regex.h>
#include <resolv.h>
#include <signal.h>
#include <stdarg.h>
@@ -122,6 +123,7 @@
#define SNAPLEN 65536
#define TRUE 1
#define FALSE 0
+#define REGEX_CFLAGS (REG_EXTENDED|REG_ICASE|REG_NOSUB|REG_NEWLINE)
/* Data structures. */
@@ -166,6 +168,13 @@
typedef ISC_LIST(struct text) text_list;
#define text_size(len) (sizeof(struct text) + len)
+struct myregex {
+ ISC_LINK(struct myregex) link;
+ regex_t reg;
+};
+typedef struct myregex *myregex_ptr;
+typedef ISC_LIST(struct myregex) myregex_list;
+
/* Forward. */
static void setsig(int, int);
@@ -199,6 +208,7 @@
static unsigned end_hide = 0U;
static endpoint_list initiators;
static endpoint_list responders;
+static myregex_list myregexes;
static mypcap_list mypcaps;
static mypcap_ptr pcap_offline = NULL;
static const char *dump_base = NULL;
@@ -279,7 +289,7 @@
"usage: %s\n"
"\t[-avfg6] [-i <if>]+ [-o <file>] [-l <vlan>]+ [-p <port>]\n"
"\t[-m [quire]] [-h [ir]] [-q <host>]+ [-r <host>]+\n"
- "\t[-d <base> [-k <cmd>]] [-t <lim>] [-c <lim>]\n",
+ "\t[-d <base> [-k <cmd>]] [-t <lim>] [-c <lim>] [-x <pat>]+\n",
ProgramName);
}
@@ -304,11 +314,15 @@
"\t-d <base> dump to <base>.<timesec>.<timeusec>\n"
"\t-k <cmd> kick off <cmd> when each dump closes\n"
"\t-t <lim> close dump or exit every <lim> secs\n"
- "\t-c <lim> close dump or exit every <lim> pkts\n");
+ "\t-c <lim> close dump or exit every <lim> pkts\n"
+ "\t-x <pat> display messages matching regex <pat>\n");
}
static void
parse_args(int argc, char *argv[]) {
+#ifdef HAVE_BINDLIB
+ myregex_ptr myregex;
+#endif
mypcap_ptr mypcap;
vlan_ptr vlan;
int i, ch;
@@ -323,7 +337,7 @@
ISC_LIST_INIT(initiators);
ISC_LIST_INIT(responders);
while ((ch = getopt(argc, argv,
- "avfg6?i:o:l:p:m:h:q:r:d:k:t:c:")
+ "avfg6?i:o:l:p:m:h:q:r:d:k:t:c:x:")
) != EOF)
{
switch (ch) {
@@ -442,6 +456,22 @@
usage("-c argument is out of range");
limit_packets = i;
break;
+ case 'x':
+#if HAVE_BINDLIB
+ myregex = malloc(sizeof *myregex);
+ assert(myregex != NULL);
+ ISC_LINK_INIT(myregex, link);
+ i = regcomp(&myregex->reg, optarg, REGEX_CFLAGS);
+ if (i != 0) {
+ regerror(i, &myregex->reg,
+ errbuf, sizeof errbuf);
+ usage(errbuf);
+ }
+ ISC_LIST_APPEND(myregexes, myregex, link);
+ break;
+#else
+ usage("-x option is disabled due to lack of libbind");
+#endif
default:
usage("unrecognized command line option");
}
@@ -746,7 +776,7 @@
do {
readfds = mypcap_fdset;
n = select(pcap_maxfd+1, &readfds, NULL, NULL, NULL);
- } while (n < 0 && errno == EINTR);
+ } while (n < 0 && errno == EINTR && !main_exit);
if (n < 0) {
perror("select");
main_exit = TRUE;
@@ -1036,6 +1066,38 @@
if ((msg_wanted & MSG_ERROR) == 0 &&
(dns.tc != 0 || dns.rcode != ns_r_noerror))
return;
+ if (!ISC_LIST_EMPTY(myregexes)) {
+ char output[SNAPLEN*4];
+ ns_msg msg;
+ ns_sect s;
+ int ok;
+
+ ok = FALSE;
+ if (ns_initparse(pkt, len, &msg) < 0)
+ return;
+ for (s = ns_s_an; s < ns_s_max && !ok; s++) {
+ int count, n;
+ ns_rr rr;
+
+ count = ns_msg_count(msg, s);
+ for (n = 0; n < count && !ok; n++) {
+ myregex_ptr myregex;
+
+ if (ns_parserr(&msg, s, n, &rr) < 0 ||
+ ns_sprintrr(&msg, &rr, NULL, ".",
+ output, sizeof output) < 0)
+ return;
+ for (myregex = ISC_LIST_HEAD(myregexes);
+ myregex != NULL && !ok;
+ myregex = ISC_LIST_NEXT(myregex, link))
+ if (regexec(&myregex->reg, output,
+ 0, NULL, 0) == 0)
+ ok = TRUE;
+ }
+ }
+ if (!ok)
+ return;
+ }
/* Policy hiding. */
if (end_hide != 0) {
More information about the dns-operations
mailing list