[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