Module Name:    src
Committed By:   alnsn
Date:           Tue Aug 14 19:09:16 UTC 2012

Added Files:
        src/tests/net/bpfilter: Makefile t_bpfilter.c

Log Message:
Add t_bpfilter test. At the moment, it only checks
that bpf program can read bytes from mbuf chain.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/tests/net/bpfilter/Makefile \
    src/tests/net/bpfilter/t_bpfilter.c

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

Added files:

Index: src/tests/net/bpfilter/Makefile
diff -u /dev/null src/tests/net/bpfilter/Makefile:1.1
--- /dev/null	Tue Aug 14 19:09:16 2012
+++ src/tests/net/bpfilter/Makefile	Tue Aug 14 19:09:15 2012
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile,v 1.1 2012/08/14 19:09:15 alnsn Exp $
+#
+
+.include <bsd.own.mk>
+
+TESTSDIR=	${TESTSBASE}/net/bpfilter
+
+TESTS_C=	t_bpfilter
+
+LDADD+=		-lrumpnet_shmif
+LDADD+=		-lrumpdev_bpf -lrumpdev -lrumpnet_netinet -lrumpnet_net
+LDADD+=		-lrumpnet -lrumpvfs -lrump -lrumpuser -lpthread
+
+.include <bsd.test.mk>
Index: src/tests/net/bpfilter/t_bpfilter.c
diff -u /dev/null src/tests/net/bpfilter/t_bpfilter.c:1.1
--- /dev/null	Tue Aug 14 19:09:16 2012
+++ src/tests/net/bpfilter/t_bpfilter.c	Tue Aug 14 19:09:15 2012
@@ -0,0 +1,269 @@
+/*	$NetBSD: t_bpfilter.c,v 1.1 2012/08/14 19:09:15 alnsn Exp $	*/
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ *
+ * 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 ``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.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_bpfilter.c,v 1.1 2012/08/14 19:09:15 alnsn Exp $");
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/mbuf.h>
+#include <sys/sysctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/bpf.h>
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rump/rump.h>
+#include <rump/rump_syscalls.h>
+
+/* XXX: atf-c.h has collisions with mbuf */
+#undef m_type
+#undef m_data
+#include <atf-c.h>
+
+#include "../../h_macros.h"
+#include "../config/netconfig.c"
+
+
+#define SNAPLEN UINT32_MAX
+
+#define BMAGIC UINT32_C(0x37)
+#define HMAGIC UINT32_C(0xc2c2)
+#define WMAGIC UINT32_C(0x7d7d7d7d)
+
+static const char magic_echo_reply_tail[7] = {
+	BMAGIC,
+	HMAGIC & 0xff,
+	HMAGIC & 0xff,
+	WMAGIC & 0xff,
+	WMAGIC & 0xff,
+	WMAGIC & 0xff,
+	WMAGIC & 0xff
+};
+
+/*
+ * Match ICMP_ECHOREPLY packet with 7 magic bytes at the end.
+ */
+static struct bpf_insn magic_echo_reply_prog[] = {
+	BPF_STMT(BPF_LD+BPF_ABS+BPF_B,
+	    sizeof(struct ip) + offsetof(struct icmp, icmp_type)),
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ICMP_ECHOREPLY, 1, 0),
+	BPF_STMT(BPF_RET+BPF_K, 0),
+
+	BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),  /* A <- len   */
+	BPF_STMT(BPF_ALU+BPF_SUB+BPF_K, 7), /* A <- A - 7 */
+	BPF_STMT(BPF_MISC+BPF_TAX, 0),      /* X <- A     */
+
+	BPF_STMT(BPF_LD+BPF_IND+BPF_B, 0),
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, BMAGIC, 1, 0),
+	BPF_STMT(BPF_RET+BPF_K, 0),
+
+	BPF_STMT(BPF_LD+BPF_IND+BPF_H, 1),
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, HMAGIC, 1, 0),
+	BPF_STMT(BPF_RET+BPF_K, 0),
+
+	BPF_STMT(BPF_LD+BPF_IND+BPF_W, 3),
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, WMAGIC, 1, 0),
+	BPF_STMT(BPF_RET+BPF_K, 0),
+
+	BPF_STMT(BPF_RET+BPF_K, SNAPLEN)
+};
+
+static uint16_t
+in_cksum(void *data, size_t len)
+{
+	uint16_t *buf = data;
+	unsigned sum;
+
+	for (sum = 0; len > 1; len -= 2)
+		sum += *buf++;
+	if (len)
+		sum += *(uint8_t *)buf;
+
+	sum = (sum >> 16) + (sum & 0xffff);
+	sum += (sum >> 16);
+
+	return ~sum;
+}
+
+/*
+ * Based on netcfg_rump_pingtest().
+ */
+static bool __unused
+pingtest(const char *dst, unsigned int wirelen, const char tail[7])
+{
+	struct timeval tv;
+	struct sockaddr_in sin;
+	struct icmp *icmp;
+	char *pkt;
+	unsigned int pktsize;
+	socklen_t slen;
+	int s;
+	bool rv = false;
+
+	if (wirelen < ETHER_HDR_LEN + sizeof(struct ip))
+		return false;
+
+	pktsize = wirelen - ETHER_HDR_LEN - sizeof(struct ip);
+	if (pktsize < sizeof(struct icmp) + 7)
+		return false;
+
+	s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
+	if (s == -1)
+		return false;
+
+	pkt = NULL;
+
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	if (rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
+	    &tv, sizeof(tv)) == -1)
+		goto out;
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_len = sizeof(sin);
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = inet_addr(dst);
+
+	pkt = calloc(1, pktsize);
+	icmp = (struct icmp *)pkt;
+	if (pkt == NULL)
+		goto out;
+
+	memcpy(pkt + pktsize - 7, tail, 7);
+	icmp->icmp_type = ICMP_ECHO;
+	icmp->icmp_id = htons(37); 
+	icmp->icmp_seq = htons(1); 
+	icmp->icmp_cksum = in_cksum(pkt, pktsize);
+
+	slen = sizeof(sin);
+	if (rump_sys_sendto(s, pkt, pktsize, 0,
+	    (struct sockaddr *)&sin, slen) == -1) {
+		goto out;
+	}
+
+	if (rump_sys_recvfrom(s, pkt, pktsize, 0,
+	    (struct sockaddr *)&sin, &slen) == -1)
+		goto out;
+
+	rv = true;
+ out:
+	if (pkt != NULL)
+		free(pkt);
+	rump_sys_close(s);
+	return rv;
+}
+
+ATF_TC(bpfiltermchain);
+ATF_TC_HEAD(bpfiltermchain, tc)
+{
+
+	atf_tc_set_md_var(tc, "descr", "Checks that bpf program "
+	    "can read bytes from mbuf chain.");
+}
+
+ATF_TC_BODY(bpfiltermchain, tc)
+{
+	struct bpf_program prog;
+	struct bpf_stat bstat;
+	struct ifreq ifr;
+	struct timeval tv;
+	unsigned int bufsize, wirelen;
+	bool pinged;
+	ssize_t n;
+	char *buf;
+	pid_t child;
+	int bpfd;
+
+	struct bpf_hdr *hdr;
+
+	prog.bf_len = __arraycount(magic_echo_reply_prog);
+	prog.bf_insns = magic_echo_reply_prog;
+
+	child = fork();
+	RZ(rump_init());
+	netcfg_rump_makeshmif("bpfiltermchain", ifr.ifr_name);
+
+	switch (child) {
+	case -1:
+		atf_tc_fail_errno("fork failed");
+	case 0:
+		netcfg_rump_if(ifr.ifr_name, "10.1.1.10", "255.0.0.0");
+		pause();
+		return;
+	default:
+		break;
+	}
+
+	netcfg_rump_if(ifr.ifr_name, "10.1.1.20", "255.0.0.0");
+
+	RL(bpfd = rump_sys_open("/dev/bpf", O_RDONLY));
+
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	RL(rump_sys_ioctl(bpfd, BIOCSRTIMEOUT, &tv));
+
+	RL(rump_sys_ioctl(bpfd, BIOCGBLEN, &bufsize));
+	RL(rump_sys_ioctl(bpfd, BIOCSETF, &prog));
+	RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
+
+	wirelen = MINCLSIZE + 1;
+	pinged = pingtest("10.1.1.10", wirelen, magic_echo_reply_tail);
+	ATF_CHECK(pinged);
+
+	buf = malloc(bufsize);
+	hdr = (struct bpf_hdr *)buf;
+	ATF_REQUIRE(buf != NULL);
+
+	n = rump_sys_read(bpfd, buf, bufsize);
+
+	ATF_CHECK(n > (int)sizeof(struct bpf_hdr *));
+	ATF_CHECK(hdr->bh_caplen == MIN(SNAPLEN, wirelen));
+
+	RL(rump_sys_ioctl(bpfd, BIOCGSTATS, &bstat));
+	ATF_CHECK(bstat.bs_capt > 1); /* XXX == 1 */
+
+	rump_sys_close(bpfd);
+	free(buf);
+	kill(child, SIGKILL);
+}
+
+
+ATF_TP_ADD_TCS(tp)
+{
+
+	ATF_TP_ADD_TC(tp, bpfiltermchain);
+
+	return atf_no_error();
+}

Reply via email to