Module Name:    src
Committed By:   christos
Date:           Sat Mar 10 22:21:50 UTC 2012

Modified Files:
        src/usr.sbin/npf/npfctl: Makefile npf_ncgen.c npfctl.h
Added Files:
        src/usr.sbin/npf/npfctl: npf_disassemble.c

Log Message:
Add a small disassembler.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/npf/npfctl/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.sbin/npf/npfctl/npf_disassemble.c
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/npf/npfctl/npf_ncgen.c
cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/npf/npfctl/npfctl.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/npf/npfctl/Makefile
diff -u src/usr.sbin/npf/npfctl/Makefile:1.5 src/usr.sbin/npf/npfctl/Makefile:1.6
--- src/usr.sbin/npf/npfctl/Makefile:1.5	Sun Jan  8 16:34:21 2012
+++ src/usr.sbin/npf/npfctl/Makefile	Sat Mar 10 17:21:50 2012
@@ -1,16 +1,18 @@
-# $NetBSD: Makefile,v 1.5 2012/01/08 21:34:21 rmind Exp $
+# $NetBSD: Makefile,v 1.6 2012/03/10 22:21:50 christos Exp $
 
 PROG=		npfctl
 MAN=		npfctl.8 npf.conf.5
 
-SRCS=		npfctl.c npf_var.c npf_data.c npf_ncgen.c npf_build.c
+SRCS=		npfctl.c npf_var.c npf_data.c npf_ncgen.c npf_build.c \
+		npf_disassemble.c
 
 CPPFLAGS+=	-I${.CURDIR}
 SRCS+=		npf_scan.l npf_parse.y
 YHEADER=	1
+YFLAGS+=	-v
 
-LDADD+=		-lnpf -lprop -ly
-DPADD+=		${LIBNPF} ${LIBPROP}
+LDADD+=		-lnpf -lprop -lutil -ly
+DPADD+=		${LIBNPF} ${LIBPROP} ${LIBUTIL}
 
 WARNS?=		4
 NOLINT=		# disabled (note: deliberately)

Index: src/usr.sbin/npf/npfctl/npf_ncgen.c
diff -u src/usr.sbin/npf/npfctl/npf_ncgen.c:1.7 src/usr.sbin/npf/npfctl/npf_ncgen.c:1.8
--- src/usr.sbin/npf/npfctl/npf_ncgen.c:1.7	Sun Jan  8 20:47:09 2012
+++ src/usr.sbin/npf/npfctl/npf_ncgen.c	Sat Mar 10 17:21:50 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ncgen.c,v 1.7 2012/01/09 01:47:09 rmind Exp $	*/
+/*	$NetBSD: npf_ncgen.c,v 1.8 2012/03/10 22:21:50 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_ncgen.c,v 1.7 2012/01/09 01:47:09 rmind Exp $");
+__RCSID("$NetBSD: npf_ncgen.c,v 1.8 2012/03/10 22:21:50 christos Exp $");
 
 #include <stdlib.h>
 #include <stddef.h>
@@ -388,10 +388,14 @@ npfctl_gennc_tcpfl(nc_ctx_t *ctx, uint8_
 void
 npfctl_ncgen_print(const void *code, size_t len)
 {
+#if 0
 	const uint32_t *op = code;
 
 	while (len) {
 		printf("\t> |0x%02x|\n", (u_int)*op++);
 		len -= sizeof(*op);
 	}
+#else
+	npfctl_ncode_disassemble(stdout, code, len);
+#endif
 }

Index: src/usr.sbin/npf/npfctl/npfctl.h
diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.12 src/usr.sbin/npf/npfctl/npfctl.h:1.13
--- src/usr.sbin/npf/npfctl/npfctl.h:1.12	Sun Feb 26 16:50:05 2012
+++ src/usr.sbin/npf/npfctl/npfctl.h	Sat Mar 10 17:21:50 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfctl.h,v 1.12 2012/02/26 21:50:05 christos Exp $	*/
+/*	$NetBSD: npfctl.h,v 1.13 2012/03/10 22:21:50 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -154,5 +154,6 @@ void		npfctl_build_rule(int, u_int, sa_f
 void		npfctl_build_nat(int, u_int, const filt_opts_t *,
 		    npfvar_t *, npfvar_t *);
 void		npfctl_build_table(const char *, u_int, const char *);
+int		npfctl_ncode_disassemble(FILE *, const void *, size_t);
 
 #endif

Added files:

Index: src/usr.sbin/npf/npfctl/npf_disassemble.c
diff -u /dev/null src/usr.sbin/npf/npfctl/npf_disassemble.c:1.1
--- /dev/null	Sat Mar 10 17:21:50 2012
+++ src/usr.sbin/npf/npfctl/npf_disassemble.c	Sat Mar 10 17:21:50 2012
@@ -0,0 +1,246 @@
+/*	$NetBSD: npf_disassemble.c,v 1.1 2012/03/10 22:21:50 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: npf_disassemble.c,v 1.1 2012/03/10 22:21:50 christos Exp $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <util.h>
+
+#define NPF_OPCODES_STRINGS
+#include <net/npf_ncode.h>
+
+#include "npfctl.h"
+
+#define ADVANCE(n, rv) \
+	do { \
+		if (len < sizeof(*pc) * (n)) { \
+			warnx("ran out of bytes"); \
+			return rv; \
+		} \
+		pc += (n); \
+		len -= sizeof(*pc) * (n); \
+	} while (/*CONSTCOND*/0)
+
+static size_t
+npfctl_ncode_get_target(const uint32_t *pc, const uint32_t **t, size_t l)
+{
+	for (size_t i = 0; i < l; i++)
+		if (t[i] == pc)
+			return i;
+	return ~0;
+}
+
+static size_t
+npfctl_ncode_add_target(const uint32_t *pc, const uint32_t ***t, size_t *l,
+    size_t *m)
+{
+	size_t q = npfctl_ncode_get_target(pc, *t, *l);
+
+	if (q != (size_t)~0)
+		return q;
+
+	if (*l <= *m) {
+		*m += 10;
+		*t = xrealloc(*t, *m * sizeof(**t));
+	}
+	q = *l;
+	(*t)[(*l)++] = pc;
+	return q;
+}
+
+static const char *
+npfctl_ncode_operand(char *buf, size_t bufsiz, uint8_t op, const uint32_t *st,
+    const uint32_t **pcv, size_t *lenv, const uint32_t ***t, size_t *l,
+    size_t *m)
+{
+	const uint32_t *pc = *pcv;
+	size_t len = *lenv;
+	struct sockaddr_storage ss;
+
+	switch (op) {
+	case NPF_OPERAND_NONE:
+		abort();
+
+	case NPF_OPERAND_REGISTER:
+		if (*pc & ~0x3) {
+			warnx("Bad register operand 0x%x at offset %td",
+			    *pc, pc - st);
+			return NULL;
+		}
+		snprintf(buf, bufsiz, "R%d", *pc);
+		ADVANCE(1, NULL);
+		break;
+				
+	case NPF_OPERAND_KEY:
+		snprintf(buf, bufsiz, "key=<0x%x>", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_VALUE:
+		snprintf(buf, bufsiz, "value=<0x%x>", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_SD:
+		if (*pc & ~0x1) {
+			warnx("Bad src/dst operand 0x%x at offset %td",
+			    *pc, pc - st);
+			return NULL;
+		}
+		snprintf(buf, bufsiz, "%s", *pc == NPF_OPERAND_SD_SRC ?
+		    "SRC" : "DST");
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_REL_ADDRESS:
+		snprintf(buf, bufsiz, "+%zu",
+		    npfctl_ncode_add_target(pc + *pc - 1, t, l, m));
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_NET_ADDRESS4: {
+		struct sockaddr_in *sin = (void *)&ss;
+		sin->sin_len = sizeof(*sin);
+		sin->sin_family = AF_INET;
+		sin->sin_port = 0;
+		memcpy(&sin->sin_addr, pc, sizeof(sin->sin_addr));
+		sockaddr_snprintf(buf, bufsiz, "%a", (struct sockaddr *)(void *)
+		    sin);
+		ADVANCE(sizeof(sin->sin_addr) / sizeof(*pc), NULL);
+		break;
+	}
+	case NPF_OPERAND_NET_ADDRESS6: {
+		struct sockaddr_in6 *sin6 = (void *)&ss;
+		sin6->sin6_len = sizeof(*sin6);
+		sin6->sin6_family = AF_INET6;
+		sin6->sin6_port = 0;
+		memcpy(&sin6->sin6_addr, pc, sizeof(sin6->sin6_addr));
+		sockaddr_snprintf(buf, bufsiz, "%a", (struct sockaddr *)(void *)
+		    sin6);
+		ADVANCE(sizeof(sin6->sin6_addr) / sizeof(*pc), NULL);
+		break;
+	}
+	case NPF_OPERAND_ETHER_TYPE:
+		snprintf(buf, bufsiz, "ether=0x%x", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_SUBNET:
+		snprintf(buf, bufsiz, "/%d", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_LENGTH:
+		snprintf(buf, bufsiz, "length=%d", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_TABLE_ID:
+		snprintf(buf, bufsiz, "id=%d", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_ICMP4_TYPE_CODE:
+		snprintf(buf, bufsiz, "icmp=0x%x", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_TCP_FLAGS_MASK:
+		snprintf(buf, bufsiz, "flmask=0x%x", *pc);
+		ADVANCE(1, NULL);
+		break;
+
+	case NPF_OPERAND_PORT_RANGE:
+		snprintf(buf, bufsiz, "%d-%d", (*pc >> 16), *pc & 0xffff);
+		ADVANCE(1, NULL);
+		break;
+	default:
+		warnx("invalid operand %d at offset %td", op, pc - st);
+		return NULL;
+	}
+
+	*pcv = pc;
+	*lenv = len;
+	return buf;
+}
+
+int
+npfctl_ncode_disassemble(FILE *fp, const void *v, size_t len)
+{
+	const uint32_t *pc = v;
+	const uint32_t *st = v;
+	const struct npf_instruction *ni;
+	char buf[256];
+	const uint32_t **targ;
+	size_t tlen, mlen, target;
+
+	targ = NULL;
+	mlen = tlen = 0;
+	while (len) {
+		/* Get the opcode */
+		if (*pc & ~0xff) {
+			warnx("bad opcode 0x%x at offset (%td)", *pc,
+			    pc - st);
+			return -1;
+		}
+		ni = &npf_instructions[*pc];
+		if (ni->name == NULL) {
+			warnx("invalid opcode 0x%x at offset (%td)", *pc,
+			    pc - st);
+			return -1;
+		}
+		target = npfctl_ncode_get_target(pc, targ, tlen);
+		if (target != (size_t)~0)
+			printf("%zu:", target);
+		fprintf(fp, "\t%s", ni->name);
+		ADVANCE(1, -1);
+		for (size_t i = 0; i < __arraycount(ni->op); i++) {
+			const char *op;
+			if (ni->op[i] == NPF_OPERAND_NONE)
+				break;
+			op = npfctl_ncode_operand(buf, sizeof(buf), ni->op[i],
+			    st, &pc, &len, &targ, &tlen, &mlen);
+			if (op == NULL)
+				return -1;
+			fprintf(fp, "%s%s", i == 0 ? " " : ", ", op);
+		}
+		fprintf(fp, "\n");
+	}
+	return 0;
+}

Reply via email to