xref: /freebsd/contrib/netbsd-tests/net/bpf/t_bpf.c (revision dd66b5ba)
1*dd66b5baSEnji Cooper /*	$NetBSD: t_bpf.c,v 1.7 2017/02/01 08:04:49 ozaki-r Exp $	*/
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
557718be8SEnji Cooper  *
657718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
757718be8SEnji Cooper  * modification, are permitted provided that the following conditions
857718be8SEnji Cooper  * are met:
957718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1057718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1157718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1257718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1357718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1457718be8SEnji Cooper  *
1557718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1657718be8SEnji Cooper  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1757718be8SEnji Cooper  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1857718be8SEnji Cooper  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1957718be8SEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2057718be8SEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2157718be8SEnji Cooper  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2257718be8SEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2357718be8SEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2457718be8SEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2557718be8SEnji Cooper  * SUCH DAMAGE.
2657718be8SEnji Cooper  */
2757718be8SEnji Cooper #include <sys/cdefs.h>
28*dd66b5baSEnji Cooper __RCSID("$NetBSD: t_bpf.c,v 1.7 2017/02/01 08:04:49 ozaki-r Exp $");
2957718be8SEnji Cooper 
3057718be8SEnji Cooper #include <sys/param.h>
3157718be8SEnji Cooper #include <sys/ioctl.h>
3257718be8SEnji Cooper #include <sys/socket.h>
3357718be8SEnji Cooper #include <sys/mbuf.h>
3457718be8SEnji Cooper #include <sys/sysctl.h>
3557718be8SEnji Cooper #include <sys/mman.h>
3657718be8SEnji Cooper #include <unistd.h>
3757718be8SEnji Cooper 
3857718be8SEnji Cooper #include <net/if.h>
3957718be8SEnji Cooper #include <net/bpf.h>
4057718be8SEnji Cooper 
4157718be8SEnji Cooper #include <fcntl.h>
4257718be8SEnji Cooper #include <stdio.h>
4357718be8SEnji Cooper #include <string.h>
4457718be8SEnji Cooper 
4557718be8SEnji Cooper #include <rump/rump.h>
4657718be8SEnji Cooper #include <rump/rump_syscalls.h>
4757718be8SEnji Cooper 
4857718be8SEnji Cooper /* XXX: atf-c.h has collisions with mbuf */
4957718be8SEnji Cooper #undef m_type
5057718be8SEnji Cooper #undef m_data
5157718be8SEnji Cooper #include <atf-c.h>
5257718be8SEnji Cooper 
5363d1fd59SEnji Cooper #include "h_macros.h"
5457718be8SEnji Cooper #include "../config/netconfig.c"
5557718be8SEnji Cooper 
5657718be8SEnji Cooper ATF_TC(bpfwriteleak);
ATF_TC_HEAD(bpfwriteleak,tc)5757718be8SEnji Cooper ATF_TC_HEAD(bpfwriteleak, tc)
5857718be8SEnji Cooper {
5957718be8SEnji Cooper 
6057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks that writing to /dev/bpf "
6157718be8SEnji Cooper 	    "does not leak mbufs");
6257718be8SEnji Cooper }
6357718be8SEnji Cooper 
6457718be8SEnji Cooper static int
getmtdata(void)6557718be8SEnji Cooper getmtdata(void)
6657718be8SEnji Cooper {
6757718be8SEnji Cooper 	struct mbstat mbstat;
6857718be8SEnji Cooper 	size_t mbstatlen = sizeof(mbstat);
6957718be8SEnji Cooper 	const int mbstat_mib[] = { CTL_KERN, KERN_MBUF, MBUF_STATS };
7057718be8SEnji Cooper 
7157718be8SEnji Cooper 	RL(rump_sys___sysctl(mbstat_mib, __arraycount(mbstat_mib),
7257718be8SEnji Cooper 	    &mbstat, &mbstatlen, NULL, 0));
7357718be8SEnji Cooper 	return mbstat.m_mtypes[MT_DATA];
7457718be8SEnji Cooper }
7557718be8SEnji Cooper 
ATF_TC_BODY(bpfwriteleak,tc)7657718be8SEnji Cooper ATF_TC_BODY(bpfwriteleak, tc)
7757718be8SEnji Cooper {
7857718be8SEnji Cooper 	char buf[28]; /* sizeof(garbage) > etherhdrlen */
7957718be8SEnji Cooper 	struct ifreq ifr;
8057718be8SEnji Cooper 	int ifnum, bpfd;
8157718be8SEnji Cooper 
8257718be8SEnji Cooper 	RZ(rump_init());
8357718be8SEnji Cooper 	RZ(rump_pub_shmif_create(NULL, &ifnum));
8457718be8SEnji Cooper 	sprintf(ifr.ifr_name, "shmif%d", ifnum);
8557718be8SEnji Cooper 
8657718be8SEnji Cooper 	RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
8757718be8SEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
8857718be8SEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCSFEEDBACK, &ifr));
8957718be8SEnji Cooper 
9057718be8SEnji Cooper 	if (getmtdata() != 0)
9157718be8SEnji Cooper 		atf_tc_fail("test precondition failed: MT_DATA mbufs != 0");
9257718be8SEnji Cooper 
9357718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENETDOWN, rump_sys_write(bpfd, buf, sizeof(buf))==-1);
9457718be8SEnji Cooper 
9557718be8SEnji Cooper 	ATF_REQUIRE_EQ(getmtdata(), 0);
9657718be8SEnji Cooper }
9757718be8SEnji Cooper 
9857718be8SEnji Cooper #if (SIZE_MAX > UINT_MAX)
9957718be8SEnji Cooper ATF_TC(bpfwritetrunc);
ATF_TC_HEAD(bpfwritetrunc,tc)10057718be8SEnji Cooper ATF_TC_HEAD(bpfwritetrunc, tc)
10157718be8SEnji Cooper {
10257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks that write to /dev/bpf "
10357718be8SEnji Cooper 	    "does not truncate size_t to int");
10457718be8SEnji Cooper }
10557718be8SEnji Cooper 
ATF_TC_BODY(bpfwritetrunc,tc)10657718be8SEnji Cooper ATF_TC_BODY(bpfwritetrunc, tc)
10757718be8SEnji Cooper {
10857718be8SEnji Cooper 	int bpfd;
10957718be8SEnji Cooper 	struct ifreq ifr;
11057718be8SEnji Cooper 	struct iovec *iov;
11157718be8SEnji Cooper 	size_t iovlen, sz;
11257718be8SEnji Cooper 	const size_t extra_bytes = 28;
11357718be8SEnji Cooper 	const size_t total = extra_bytes + UINT_MAX + 1;
11457718be8SEnji Cooper 	long iov_max, vm_page_size; /* round_page wants vm_page_size variable */
11557718be8SEnji Cooper 
11657718be8SEnji Cooper 	memset(&ifr, 0, sizeof(ifr));
11757718be8SEnji Cooper 
11857718be8SEnji Cooper 	iov_max      = sysconf(_SC_IOV_MAX);
11957718be8SEnji Cooper 	vm_page_size = sysconf(_SC_PAGE_SIZE);
12057718be8SEnji Cooper 	ATF_REQUIRE(iov_max > 1 && vm_page_size > 1);
12157718be8SEnji Cooper 
12257718be8SEnji Cooper 	/*
12357718be8SEnji Cooper 	 * Minimize memory consumption by using many iovecs
12457718be8SEnji Cooper 	 * all pointing to one memory region.
12557718be8SEnji Cooper 	 */
12657718be8SEnji Cooper 	iov = calloc(iov_max, sizeof(struct iovec));
12757718be8SEnji Cooper 	ATF_REQUIRE(iov != NULL);
12857718be8SEnji Cooper 
12957718be8SEnji Cooper 	sz = round_page((total + (iov_max - 1)) / iov_max);
13057718be8SEnji Cooper 
13157718be8SEnji Cooper 	iov[0].iov_len = sz;
13257718be8SEnji Cooper 	iov[0].iov_base = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0);
13357718be8SEnji Cooper 	ATF_REQUIRE(iov[0].iov_base != MAP_FAILED);
13457718be8SEnji Cooper 
13557718be8SEnji Cooper 	iovlen = 1;
13657718be8SEnji Cooper 	while (sz + iov[0].iov_len <= total)
13757718be8SEnji Cooper 	{
13857718be8SEnji Cooper 		iov[iovlen].iov_len  = iov[0].iov_len;
13957718be8SEnji Cooper 		iov[iovlen].iov_base = iov[0].iov_base;
14057718be8SEnji Cooper 		sz += iov[0].iov_len;
14157718be8SEnji Cooper 		iovlen++;
14257718be8SEnji Cooper 	}
14357718be8SEnji Cooper 
14457718be8SEnji Cooper 	if (sz < total)
14557718be8SEnji Cooper 	{
14657718be8SEnji Cooper 		iov[iovlen].iov_len = total - sz;
14757718be8SEnji Cooper 		iov[iovlen].iov_base = iov[0].iov_base;
14857718be8SEnji Cooper 		iovlen++;
14957718be8SEnji Cooper 	}
15057718be8SEnji Cooper 
15157718be8SEnji Cooper 	/* Sanity checks */
15257718be8SEnji Cooper 	ATF_REQUIRE(iovlen >= 1 && iovlen <= (size_t)iov_max);
15357718be8SEnji Cooper 	ATF_REQUIRE_EQ(iov[iovlen-1].iov_len, total % iov[0].iov_len);
15457718be8SEnji Cooper 
15557718be8SEnji Cooper 	RZ(rump_init());
15657718be8SEnji Cooper 	netcfg_rump_makeshmif("bpfwritetrunc", ifr.ifr_name);
15757718be8SEnji Cooper 	netcfg_rump_if(ifr.ifr_name, "10.1.1.1", "255.0.0.0");
15857718be8SEnji Cooper 
15957718be8SEnji Cooper 	RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
16057718be8SEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
16157718be8SEnji Cooper 
16257718be8SEnji Cooper 	ATF_CHECK_ERRNO(EMSGSIZE, rump_sys_writev(bpfd, iov, iovlen) == -1);
16357718be8SEnji Cooper 
16457718be8SEnji Cooper 	munmap(iov[0].iov_base, iov[0].iov_len);
16557718be8SEnji Cooper 	free(iov);
16657718be8SEnji Cooper }
16757718be8SEnji Cooper #endif /* #if (SIZE_MAX > UINT_MAX) */
16857718be8SEnji Cooper 
169*dd66b5baSEnji Cooper ATF_TC(bpf_ioctl_BLEN);
ATF_TC_HEAD(bpf_ioctl_BLEN,tc)170*dd66b5baSEnji Cooper ATF_TC_HEAD(bpf_ioctl_BLEN, tc)
171*dd66b5baSEnji Cooper {
172*dd66b5baSEnji Cooper 
173*dd66b5baSEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks behaviors of BIOCGBLEN and "
174*dd66b5baSEnji Cooper 	    "BIOCSBLEN");
175*dd66b5baSEnji Cooper }
176*dd66b5baSEnji Cooper 
ATF_TC_BODY(bpf_ioctl_BLEN,tc)177*dd66b5baSEnji Cooper ATF_TC_BODY(bpf_ioctl_BLEN, tc)
178*dd66b5baSEnji Cooper {
179*dd66b5baSEnji Cooper 	struct ifreq ifr;
180*dd66b5baSEnji Cooper 	int ifnum, bpfd;
181*dd66b5baSEnji Cooper 	u_int blen = 0;
182*dd66b5baSEnji Cooper 
183*dd66b5baSEnji Cooper 	RZ(rump_init());
184*dd66b5baSEnji Cooper 	RZ(rump_pub_shmif_create(NULL, &ifnum));
185*dd66b5baSEnji Cooper 	sprintf(ifr.ifr_name, "shmif%d", ifnum);
186*dd66b5baSEnji Cooper 
187*dd66b5baSEnji Cooper 	RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
188*dd66b5baSEnji Cooper 
189*dd66b5baSEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCGBLEN, &blen));
190*dd66b5baSEnji Cooper 	ATF_REQUIRE(blen != 0);
191*dd66b5baSEnji Cooper 	blen = 100;
192*dd66b5baSEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCSBLEN, &blen));
193*dd66b5baSEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCGBLEN, &blen));
194*dd66b5baSEnji Cooper 	ATF_REQUIRE_EQ(blen, 100);
195*dd66b5baSEnji Cooper 
196*dd66b5baSEnji Cooper 	RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
197*dd66b5baSEnji Cooper 
198*dd66b5baSEnji Cooper 	ATF_REQUIRE_EQ_MSG(rump_sys_ioctl(bpfd, BIOCSBLEN, &blen), -1,
199*dd66b5baSEnji Cooper 	    "Don't allow to change buflen after binding bpf to an interface");
200*dd66b5baSEnji Cooper }
201*dd66b5baSEnji Cooper 
ATF_TP_ADD_TCS(tp)20257718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
20357718be8SEnji Cooper {
20457718be8SEnji Cooper 
20557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfwriteleak);
20657718be8SEnji Cooper #if (SIZE_MAX > UINT_MAX)
20757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfwritetrunc);
20857718be8SEnji Cooper #endif
209*dd66b5baSEnji Cooper 	ATF_TP_ADD_TC(tp, bpf_ioctl_BLEN);
21057718be8SEnji Cooper 	return atf_no_error();
21157718be8SEnji Cooper }
212