Importing NetBSD "Kyua" test framework
To do so, a few dependencies have been imported: * external/bsd/lutok * external/mit/lua * external/public-domain/sqlite * external/public-domain/xz The Kyua framework is the new generation of ATF (Automated Test Framework), it is composed of: * external/bsd/atf * external/bsd/kyua-atf-compat * external/bsd/kyua-cli * external/bsd/kyua-tester * tests Kyua/ATF being written in C++, it depends on libstdc++ which is provided by GCC. As this is not part of the sources, Kyua is only compiled when the native GCC utils are installed. To install Kyua do the following: * In a cross-build enviromnent, add the following to the build.sh commandline: -V MKBINUTILS=yes -V MKGCCCMDS=yes WARNING: At this point the import is still experimental, and not supported on native builds (a.k.a make build). Change-Id: I26aee23c5bbd2d64adcb7c1beb98fe0d479d7ada
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
# $NetBSD: Makefile,v 1.14 2013/07/03 14:01:29 nakayama Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net
|
||||
|
||||
TESTS_SUBDIRS= fdpass net route sys
|
||||
.if (${MKRUMP} != "no")
|
||||
TESTS_SUBDIRS+= bpf bpfilter carp icmp if if_loop npf
|
||||
.endif
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1 @@
|
||||
.include "../Makefile.inc"
|
||||
@@ -0,0 +1,15 @@
|
||||
# $NetBSD: Makefile,v 1.3 2011/01/03 02:53:15 christos Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/bpf
|
||||
|
||||
TESTS_C= t_bpf
|
||||
TESTS_C+= t_div-by-zero
|
||||
|
||||
LDADD+= -lrumpnet_shmif
|
||||
LDADD+= -lrumpdev_bpf -lrumpdev -lrumpnet_netinet -lrumpnet_net
|
||||
LDADD+= -lrumpnet -lrumpvfs -lrump -lrumpuser -lpthread
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,177 @@
|
||||
/* $NetBSD: t_bpf.c,v 1.5 2012/08/14 19:40:30 alnsn Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
|
||||
*
|
||||
* 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_bpf.c,v 1.5 2012/08/14 19:40:30 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/bpf.h>
|
||||
|
||||
#include <fcntl.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"
|
||||
|
||||
ATF_TC(bpfwriteleak);
|
||||
ATF_TC_HEAD(bpfwriteleak, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Checks that writing to /dev/bpf "
|
||||
"does not leak mbufs");
|
||||
}
|
||||
|
||||
static int
|
||||
getmtdata(void)
|
||||
{
|
||||
struct mbstat mbstat;
|
||||
size_t mbstatlen = sizeof(mbstat);
|
||||
const int mbstat_mib[] = { CTL_KERN, KERN_MBUF, MBUF_STATS };
|
||||
|
||||
RL(rump_sys___sysctl(mbstat_mib, __arraycount(mbstat_mib),
|
||||
&mbstat, &mbstatlen, NULL, 0));
|
||||
return mbstat.m_mtypes[MT_DATA];
|
||||
}
|
||||
|
||||
ATF_TC_BODY(bpfwriteleak, tc)
|
||||
{
|
||||
char buf[28]; /* sizeof(garbage) > etherhdrlen */
|
||||
struct ifreq ifr;
|
||||
int ifnum, bpfd;
|
||||
|
||||
RZ(rump_init());
|
||||
RZ(rump_pub_shmif_create(NULL, &ifnum));
|
||||
sprintf(ifr.ifr_name, "shmif%d", ifnum);
|
||||
|
||||
RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
|
||||
RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
|
||||
RL(rump_sys_ioctl(bpfd, BIOCSFEEDBACK, &ifr));
|
||||
|
||||
if (getmtdata() != 0)
|
||||
atf_tc_fail("test precondition failed: MT_DATA mbufs != 0");
|
||||
|
||||
ATF_REQUIRE_ERRNO(ENETDOWN, rump_sys_write(bpfd, buf, sizeof(buf))==-1);
|
||||
|
||||
ATF_REQUIRE_EQ(getmtdata(), 0);
|
||||
}
|
||||
|
||||
#if (SIZE_MAX > UINT_MAX)
|
||||
ATF_TC(bpfwritetrunc);
|
||||
ATF_TC_HEAD(bpfwritetrunc, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Checks that write to /dev/bpf "
|
||||
"does not truncate size_t to int");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(bpfwritetrunc, tc)
|
||||
{
|
||||
int bpfd;
|
||||
struct ifreq ifr;
|
||||
struct iovec *iov;
|
||||
size_t iovlen, sz;
|
||||
const size_t extra_bytes = 28;
|
||||
const size_t total = extra_bytes + UINT_MAX + 1;
|
||||
long iov_max, vm_page_size; /* round_page wants vm_page_size variable */
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
iov_max = sysconf(_SC_IOV_MAX);
|
||||
vm_page_size = sysconf(_SC_PAGE_SIZE);
|
||||
ATF_REQUIRE(iov_max > 1 && vm_page_size > 1);
|
||||
|
||||
/*
|
||||
* Minimize memory consumption by using many iovecs
|
||||
* all pointing to one memory region.
|
||||
*/
|
||||
iov = calloc(iov_max, sizeof(struct iovec));
|
||||
ATF_REQUIRE(iov != NULL);
|
||||
|
||||
sz = round_page((total + (iov_max - 1)) / iov_max);
|
||||
|
||||
iov[0].iov_len = sz;
|
||||
iov[0].iov_base = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0);
|
||||
ATF_REQUIRE(iov[0].iov_base != MAP_FAILED);
|
||||
|
||||
iovlen = 1;
|
||||
while (sz + iov[0].iov_len <= total)
|
||||
{
|
||||
iov[iovlen].iov_len = iov[0].iov_len;
|
||||
iov[iovlen].iov_base = iov[0].iov_base;
|
||||
sz += iov[0].iov_len;
|
||||
iovlen++;
|
||||
}
|
||||
|
||||
if (sz < total)
|
||||
{
|
||||
iov[iovlen].iov_len = total - sz;
|
||||
iov[iovlen].iov_base = iov[0].iov_base;
|
||||
iovlen++;
|
||||
}
|
||||
|
||||
/* Sanity checks */
|
||||
ATF_REQUIRE(iovlen >= 1 && iovlen <= (size_t)iov_max);
|
||||
ATF_REQUIRE_EQ(iov[iovlen-1].iov_len, total % iov[0].iov_len);
|
||||
|
||||
RZ(rump_init());
|
||||
netcfg_rump_makeshmif("bpfwritetrunc", ifr.ifr_name);
|
||||
netcfg_rump_if(ifr.ifr_name, "10.1.1.1", "255.0.0.0");
|
||||
|
||||
RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
|
||||
RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
|
||||
|
||||
ATF_CHECK_ERRNO(EMSGSIZE, rump_sys_writev(bpfd, iov, iovlen) == -1);
|
||||
|
||||
munmap(iov[0].iov_base, iov[0].iov_len);
|
||||
free(iov);
|
||||
}
|
||||
#endif /* #if (SIZE_MAX > UINT_MAX) */
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, bpfwriteleak);
|
||||
#if (SIZE_MAX > UINT_MAX)
|
||||
ATF_TP_ADD_TC(tp, bpfwritetrunc);
|
||||
#endif
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
ATF_TC(div_by_zero);
|
||||
ATF_TC_HEAD(div_by_zero, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Check that BPF rejects a filter "
|
||||
"which divides by 0");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(div_by_zero, tc)
|
||||
{
|
||||
struct bpf_program bp;
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Source code for following program:
|
||||
* link[0:4]/0 = 2
|
||||
*/
|
||||
struct bpf_insn bins[] = {
|
||||
{ 0x20, 0, 0, 0x00000000 },
|
||||
{ 0x34, 0, 0, 0x00000000 },
|
||||
{ 0x15, 0, 1, 0x00000002 },
|
||||
{ 0x6, 0, 0, 0x00000060 },
|
||||
{ 0x6, 0, 0, 0x00000000 },
|
||||
};
|
||||
|
||||
bp.bf_len = __arraycount(bins);
|
||||
bp.bf_insns = bins;
|
||||
|
||||
rump_init();
|
||||
fd = rump_sys_open("/dev/bpf", O_RDWR);
|
||||
ATF_CHECK(fd != -1);
|
||||
ATF_REQUIRE_EQ_MSG(rump_sys_ioctl(fd, BIOCSETF, &bp), -1,
|
||||
"bpf accepted program with division by zero");
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, div_by_zero);
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,308 @@
|
||||
/* $NetBSD: t_bpfilter.c,v 1.6 2012/09/03 21:27:14 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.6 2012/09/03 21:27:14 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 <sys/wait.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;
|
||||
}
|
||||
|
||||
static void
|
||||
magic_ping_test(const char *name, unsigned int wirelen)
|
||||
{
|
||||
struct bpf_program prog;
|
||||
struct bpf_stat bstat;
|
||||
struct ifreq ifr;
|
||||
struct timeval tv;
|
||||
unsigned int bufsize;
|
||||
bool pinged;
|
||||
ssize_t n;
|
||||
char *buf;
|
||||
pid_t child;
|
||||
int bpfd;
|
||||
char token;
|
||||
int channel[2];
|
||||
|
||||
struct bpf_hdr *hdr;
|
||||
|
||||
RL(pipe(channel));
|
||||
|
||||
prog.bf_len = __arraycount(magic_echo_reply_prog);
|
||||
prog.bf_insns = magic_echo_reply_prog;
|
||||
|
||||
child = fork();
|
||||
RZ(rump_init());
|
||||
netcfg_rump_makeshmif(name, 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");
|
||||
close(channel[0]);
|
||||
ATF_CHECK(write(channel[1], "U", 1) == 1);
|
||||
close(channel[1]);
|
||||
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 = 0;
|
||||
tv.tv_usec = 500;
|
||||
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));
|
||||
|
||||
close(channel[1]);
|
||||
ATF_CHECK(read(channel[0], &token, 1) == 1 && token == 'U');
|
||||
|
||||
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);
|
||||
ATF_REQUIRE(bufsize > sizeof(struct bpf_hdr));
|
||||
|
||||
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);
|
||||
|
||||
close(channel[0]);
|
||||
|
||||
kill(child, SIGKILL);
|
||||
}
|
||||
|
||||
ATF_TC(bpfiltercontig);
|
||||
ATF_TC_HEAD(bpfiltercontig, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Checks that bpf program "
|
||||
"can read bytes from contiguous buffer.");
|
||||
atf_tc_set_md_var(tc, "timeout", "30");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(bpfiltercontig, tc)
|
||||
{
|
||||
|
||||
magic_ping_test("bpfiltercontig", 128);
|
||||
}
|
||||
|
||||
|
||||
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_set_md_var(tc, "timeout", "30");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(bpfiltermchain, tc)
|
||||
{
|
||||
|
||||
magic_ping_test("bpfiltermchain", MINCLSIZE + 1);
|
||||
}
|
||||
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, bpfiltercontig);
|
||||
ATF_TP_ADD_TC(tp, bpfiltermchain);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# $NetBSD: Makefile,v 1.1 2010/08/10 21:55:28 pooka Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/carp
|
||||
|
||||
TESTS_C= t_basic
|
||||
|
||||
LDADD+= -lrumpnet_shmif -lrumpnet_netinet -lrumpnet_net
|
||||
LDADD+= -lrumpnet -lrump -lrumpuser -lpthread
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,221 @@
|
||||
/* $NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip_carp.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "../config/netconfig.c"
|
||||
#include "../../h_macros.h"
|
||||
|
||||
static bool oknow = false;
|
||||
|
||||
static void
|
||||
sighnd(int sig)
|
||||
{
|
||||
|
||||
ATF_REQUIRE_EQ(sig, SIGCHLD);
|
||||
if (oknow)
|
||||
return;
|
||||
|
||||
atf_tc_fail("child died unexpectedly");
|
||||
}
|
||||
|
||||
ATF_TC(handover);
|
||||
ATF_TC_HEAD(handover, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "check that carp handover works if "
|
||||
"the master dies");
|
||||
}
|
||||
|
||||
#define THEBUS "buuuuuuus,etherbus"
|
||||
|
||||
static void
|
||||
child(bool master)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
struct carpreq cr;
|
||||
struct ifreq ifr;
|
||||
const char *carpif;
|
||||
int s;
|
||||
|
||||
/* helps reading carp debug output */
|
||||
if (master)
|
||||
carpif = "carp0";
|
||||
else
|
||||
carpif = "carp1";
|
||||
|
||||
/*
|
||||
* Should use sysctl, bug debug is dabug.
|
||||
*/
|
||||
{
|
||||
//extern int rumpns_carp_opts[]; /* XXX */
|
||||
//rumpns_carp_opts[CARPCTL_LOG] = 1;
|
||||
}
|
||||
|
||||
|
||||
rump_init();
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, carpif, sizeof(ifr.ifr_name));
|
||||
|
||||
RL(s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0));
|
||||
RL(rump_sys_ioctl(s, SIOCIFCREATE, &ifr));
|
||||
|
||||
netcfg_rump_makeshmif(THEBUS, ifname);
|
||||
|
||||
if (master)
|
||||
netcfg_rump_if(ifname, "10.1.1.1", "255.255.255.0");
|
||||
else
|
||||
netcfg_rump_if(ifname, "10.1.1.2", "255.255.255.0");
|
||||
|
||||
/* configure the carp interface */
|
||||
ifr.ifr_data = &cr;
|
||||
RL(rump_sys_ioctl(s, SIOCGVH, &ifr));
|
||||
|
||||
strlcpy(cr.carpr_carpdev, ifname, sizeof(cr.carpr_carpdev));
|
||||
cr.carpr_vhid = 175;
|
||||
if (master)
|
||||
cr.carpr_advskew = 0;
|
||||
else
|
||||
cr.carpr_advskew = 200;
|
||||
cr.carpr_advbase = 1;
|
||||
strcpy((char *)cr.carpr_key, "s3cret");
|
||||
|
||||
RL(rump_sys_ioctl(s, SIOCSVH, &ifr));
|
||||
netcfg_rump_if(carpif, "10.1.1.100", "255.255.255.0");
|
||||
|
||||
/* tassa pause()en enka muuta voi */
|
||||
pause();
|
||||
}
|
||||
|
||||
ATF_TC_BODY(handover, tc)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
pid_t mpid, cpid;
|
||||
int i, status;
|
||||
|
||||
signal(SIGCHLD, sighnd);
|
||||
|
||||
/* fork master */
|
||||
switch (mpid = fork()) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
/*NOTREACHED*/
|
||||
case 0:
|
||||
child(true);
|
||||
/*NOTREACHED*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(500000);
|
||||
|
||||
/* fork backup */
|
||||
switch (cpid = fork()) {
|
||||
case -1:
|
||||
kill(mpid, SIGKILL);
|
||||
atf_tc_fail_errno("fork failed");
|
||||
/*NOTREACHED*/
|
||||
case 0:
|
||||
child(false);
|
||||
/*NOTREACHED*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(500000);
|
||||
|
||||
rump_init();
|
||||
netcfg_rump_makeshmif(THEBUS, ifname);
|
||||
netcfg_rump_if(ifname, "10.1.1.240", "255.255.255.0");
|
||||
|
||||
/* check that the primary addresses are up */
|
||||
ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 1000), true);
|
||||
ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.2", 1000), true);
|
||||
|
||||
/* give carp a while to croak */
|
||||
sleep(4);
|
||||
|
||||
/* check that the shared IP works */
|
||||
ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.100", 500), true);
|
||||
|
||||
/* KILLING SPREE */
|
||||
oknow = true;
|
||||
kill(mpid, SIGKILL);
|
||||
wait(&status);
|
||||
usleep(10000); /* just in case */
|
||||
oknow = false;
|
||||
|
||||
/* check that primary is now dead */
|
||||
ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 100), false);
|
||||
|
||||
/* do it in installments. carp will cluck meanwhile */
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (netcfg_rump_pingtest("10.1.1.100", 1000) == true)
|
||||
break;
|
||||
}
|
||||
if (i == 5)
|
||||
atf_tc_fail("failed to failover");
|
||||
|
||||
/* to kill the child */
|
||||
oknow = true;
|
||||
kill(cpid, SIGKILL);
|
||||
|
||||
/* clean & done */
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, handover);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/* $NetBSD: netconfig.c,v 1.8 2013/07/03 19:13:33 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: netconfig.c,v 1.8 2013/07/03 19:13:33 pooka Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include "../../h_macros.h"
|
||||
|
||||
int noatf;
|
||||
|
||||
static void __unused
|
||||
netcfg_rump_makeshmif(const char *busname, char *ifname)
|
||||
{
|
||||
int rv, ifnum;
|
||||
|
||||
if ((rv = rump_pub_shmif_create(busname, &ifnum)) != 0) {
|
||||
if (noatf)
|
||||
err(1, "makeshmif: rump_pub_shmif_create %d", rv);
|
||||
else
|
||||
atf_tc_fail("makeshmif: rump_pub_shmif_create %d", rv);
|
||||
}
|
||||
sprintf(ifname, "shmif%d", ifnum);
|
||||
}
|
||||
|
||||
static void __unused
|
||||
netcfg_rump_if(const char *ifname, const char *addr, const char *mask)
|
||||
{
|
||||
struct ifaliasreq ia;
|
||||
struct sockaddr_in *sin;
|
||||
in_addr_t inaddr, inmask;
|
||||
int s, rv;
|
||||
|
||||
s = -1;
|
||||
if ((s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
if (noatf)
|
||||
err(1, "if config socket");
|
||||
else
|
||||
atf_tc_fail_errno("if config socket");
|
||||
}
|
||||
|
||||
inaddr = inet_addr(addr);
|
||||
inmask = inet_addr(mask);
|
||||
|
||||
/* Address */
|
||||
memset(&ia, 0, sizeof(ia));
|
||||
strcpy(ia.ifra_name, ifname);
|
||||
sin = (struct sockaddr_in *)&ia.ifra_addr;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_addr.s_addr = inaddr;
|
||||
|
||||
/* Netmask */
|
||||
sin = (struct sockaddr_in *)&ia.ifra_mask;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_addr.s_addr = inmask;
|
||||
|
||||
/* Broadcast address */
|
||||
sin = (struct sockaddr_in *)&ia.ifra_broadaddr;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_addr.s_addr = inaddr | ~inmask;
|
||||
|
||||
rv = rump_sys_ioctl(s, SIOCAIFADDR, &ia);
|
||||
if (rv == -1) {
|
||||
if (noatf)
|
||||
err(1, "SIOCAIFADDR");
|
||||
else
|
||||
atf_tc_fail_errno("SIOCAIFADDR");
|
||||
}
|
||||
rump_sys_close(s);
|
||||
}
|
||||
|
||||
static void __unused
|
||||
netcfg_rump_route(const char *dst, const char *mask, const char *gw)
|
||||
{
|
||||
size_t len;
|
||||
struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
uint8_t m_space[512];
|
||||
} m_rtmsg;
|
||||
#define rtm m_rtmsg.m_rtm
|
||||
uint8_t *bp = m_rtmsg.m_space;
|
||||
struct sockaddr_in sinstore;
|
||||
int s, rv;
|
||||
|
||||
s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (s == -1) {
|
||||
if (noatf)
|
||||
err(1, "routing socket");
|
||||
else
|
||||
atf_tc_fail_errno("routing socket");
|
||||
}
|
||||
|
||||
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
||||
rtm.rtm_type = RTM_ADD;
|
||||
rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
|
||||
rtm.rtm_version = RTM_VERSION;
|
||||
rtm.rtm_seq = 2;
|
||||
rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
|
||||
|
||||
/* dst */
|
||||
memset(&sinstore, 0, sizeof(sinstore));
|
||||
sinstore.sin_family = AF_INET;
|
||||
sinstore.sin_len = sizeof(sinstore);
|
||||
sinstore.sin_addr.s_addr = inet_addr(dst);
|
||||
memcpy(bp, &sinstore, sizeof(sinstore));
|
||||
bp += sizeof(sinstore);
|
||||
|
||||
/* gw */
|
||||
memset(&sinstore, 0, sizeof(sinstore));
|
||||
sinstore.sin_family = AF_INET;
|
||||
sinstore.sin_len = sizeof(sinstore);
|
||||
sinstore.sin_addr.s_addr = inet_addr(gw);
|
||||
memcpy(bp, &sinstore, sizeof(sinstore));
|
||||
bp += sizeof(sinstore);
|
||||
|
||||
/* netmask */
|
||||
memset(&sinstore, 0, sizeof(sinstore));
|
||||
sinstore.sin_family = AF_INET;
|
||||
sinstore.sin_len = sizeof(sinstore);
|
||||
sinstore.sin_addr.s_addr = inet_addr(mask);
|
||||
memcpy(bp, &sinstore, sizeof(sinstore));
|
||||
bp += sizeof(sinstore);
|
||||
|
||||
len = bp - (uint8_t *)&m_rtmsg;
|
||||
rtm.rtm_msglen = len;
|
||||
|
||||
rv = rump_sys_write(s, &m_rtmsg, len);
|
||||
if (rv != (int)len) {
|
||||
if (noatf)
|
||||
err(1, "write routing message");
|
||||
else
|
||||
atf_tc_fail_errno("write routing message");
|
||||
}
|
||||
rump_sys_close(s);
|
||||
}
|
||||
|
||||
static bool __unused
|
||||
netcfg_rump_pingtest(const char *dst, int ms_timo)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct sockaddr_in sin;
|
||||
struct icmp icmp;
|
||||
socklen_t slen;
|
||||
int s;
|
||||
bool rv = false;
|
||||
|
||||
s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (s == -1)
|
||||
return false;
|
||||
tv.tv_sec = ms_timo / 1000;
|
||||
tv.tv_usec = 1000 * (ms_timo % 1000);
|
||||
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);
|
||||
|
||||
memset(&icmp, 0, sizeof(icmp));
|
||||
icmp.icmp_type = ICMP_ECHO;
|
||||
icmp.icmp_id = htons(37);
|
||||
icmp.icmp_cksum = htons(0xf7da); /* precalc */
|
||||
|
||||
slen = sizeof(sin);
|
||||
if (rump_sys_sendto(s, &icmp, sizeof(icmp), 0,
|
||||
(struct sockaddr *)&sin, slen) == -1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rump_sys_recvfrom(s, &icmp, sizeof(icmp), 0,
|
||||
(struct sockaddr *)&sin, &slen) == -1)
|
||||
goto out;
|
||||
|
||||
rv = true;
|
||||
out:
|
||||
rump_sys_close(s);
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# $NetBSD: Makefile,v 1.4 2012/09/13 21:13:34 joerg Exp $
|
||||
#
|
||||
|
||||
SHLIBDIR= /usr/lib
|
||||
SHLIBINSTALLDIR= /usr/lib
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/fdpass
|
||||
|
||||
TESTS_SH= t_fdpass
|
||||
|
||||
PROGS= fdpass64 fdpass32
|
||||
MAN.fdpass64= # empty
|
||||
BINDIR.fdpass64= ${TESTSDIR}
|
||||
|
||||
.if (${MACHINE} == "sparc64" || ${MACHINE} == "amd64") && ${MKCOMPAT} != "no"
|
||||
COPTS.fdpass32.c += -m32
|
||||
LDFLAGS.fdpass32 += -m32
|
||||
.endif
|
||||
MAN.fdpass32= # empty
|
||||
BINDIR.fdpass32= ${TESTSDIR}
|
||||
|
||||
|
||||
fdpass64.c fdpass32.c: fdpass.c
|
||||
ln -s ${.CURDIR}/fdpass.c ${.TARGET}
|
||||
|
||||
CLEANFILES += fdpass64.c fdpass32.c
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,231 @@
|
||||
/* $NetBSD: fdpass.c,v 1.1 2012/08/13 11:15:05 christos Exp $ */
|
||||
/* $OpenBSD: monitor_fdpass.c,v 1.19 2010/01/12 00:58:25 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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: fdpass.c,v 1.1 2012/08/13 11:15:05 christos Exp $");
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
static int
|
||||
send_fd(int sock, int fd)
|
||||
{
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
char buf[1024];
|
||||
} cmsgbuf;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec vec;
|
||||
char ch = '\0';
|
||||
ssize_t n;
|
||||
struct pollfd pfd;
|
||||
|
||||
if (sizeof(cmsgbuf.buf) < CMSG_SPACE(sizeof(int)))
|
||||
errx(1, "%s: %zu < %zu, recompile", __func__,
|
||||
sizeof(cmsgbuf.buf), CMSG_SPACE(sizeof(int)));
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_control = &cmsgbuf.buf;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
*(int *)CMSG_DATA(cmsg) = fd;
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
|
||||
vec.iov_base = &ch;
|
||||
vec.iov_len = 1;
|
||||
msg.msg_iov = &vec;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
pfd.fd = sock;
|
||||
pfd.events = POLLOUT;
|
||||
while ((n = sendmsg(sock, &msg, 0)) == -1 &&
|
||||
(errno == EAGAIN || errno == EINTR)) {
|
||||
(void)poll(&pfd, 1, -1);
|
||||
}
|
||||
switch (n) {
|
||||
case -1:
|
||||
err(1, "%s: sendmsg(%d)", __func__, fd);
|
||||
case 1:
|
||||
if (debug)
|
||||
fprintf(stderr, "%d: send fd %d\n", getpid(), fd);
|
||||
return 0;
|
||||
default:
|
||||
errx(1, "%s: sendmsg: expected sent 1 got %ld",
|
||||
__func__, (long)n);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
recv_fd(int sock)
|
||||
{
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
char buf[1024];
|
||||
} cmsgbuf;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec vec;
|
||||
ssize_t n;
|
||||
char ch;
|
||||
int fd;
|
||||
struct pollfd pfd;
|
||||
|
||||
if (sizeof(cmsgbuf.buf) < CMSG_SPACE(sizeof(int)))
|
||||
errx(1, "%s: %zu < %zu, recompile", __func__,
|
||||
sizeof(cmsgbuf.buf), CMSG_SPACE(sizeof(int)));
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
vec.iov_base = &ch;
|
||||
vec.iov_len = 1;
|
||||
msg.msg_iov = &vec;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = &cmsgbuf.buf;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
|
||||
pfd.fd = sock;
|
||||
pfd.events = POLLIN;
|
||||
while ((n = recvmsg(sock, &msg, 0)) == -1 &&
|
||||
(errno == EAGAIN || errno == EINTR)) {
|
||||
(void)poll(&pfd, 1, -1);
|
||||
}
|
||||
switch (n) {
|
||||
case -1:
|
||||
err(1, "%s: recvmsg", __func__);
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
errx(1, "%s: recvmsg: expected received 1 got %ld",
|
||||
__func__, (long)n);
|
||||
}
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (cmsg == NULL)
|
||||
errx(1, "%s: no message header", __func__);
|
||||
|
||||
if (cmsg->cmsg_type != SCM_RIGHTS)
|
||||
err(1, "%s: expected type %d got %d", __func__,
|
||||
SCM_RIGHTS, cmsg->cmsg_type);
|
||||
fd = (*(int *)CMSG_DATA(cmsg));
|
||||
if (debug)
|
||||
fprintf(stderr, "%d: recv fd %d\n", getpid(), fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void usage(void) __attribute__((__noreturn__));
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-vd] -i <input> -o <output>\n"
|
||||
"\t %s [-v] -p <progname>\n", getprogname(), getprogname());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int s[2], fd, status, c, verbose;
|
||||
char buf[1024], *prog;
|
||||
|
||||
prog = NULL;
|
||||
s[0] = s[1] = -1;
|
||||
verbose = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "di:o:p:")) != -1)
|
||||
switch (c) {
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
case 'i':
|
||||
s[0] = atoi(optarg);
|
||||
break;
|
||||
case 'o':
|
||||
s[1] = atoi(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
prog = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if ((s[0] == -1 && s[1] != -1) || (s[0] != -1 && s[1] == -1))
|
||||
usage();
|
||||
|
||||
if (s[0] == -1) {
|
||||
if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, s) == -1)
|
||||
err(1, "socketpair");
|
||||
} else
|
||||
goto recv;
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
err(1, "fork");
|
||||
default:
|
||||
fd = open("foo", O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd == -1)
|
||||
err(1, "open");
|
||||
send_fd(s[0], fd);
|
||||
wait(&status);
|
||||
return 0;
|
||||
case 0:
|
||||
if (prog != NULL) {
|
||||
char i[64], o[64];
|
||||
snprintf(i, sizeof(i), "%d", s[0]);
|
||||
snprintf(o, sizeof(o), "%d", s[1]);
|
||||
execlp(prog, prog, "-i", i, "-o", o, NULL);
|
||||
err(1, "execlp");
|
||||
}
|
||||
recv:
|
||||
fd = recv_fd(s[1]);
|
||||
if (verbose) {
|
||||
snprintf(buf, sizeof(buf), "ls -l /proc/%d/fd",
|
||||
getpid());
|
||||
system(buf);
|
||||
}
|
||||
if (write(fd, "foo\n", 4) == -1)
|
||||
err(1, "write");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
# $NetBSD: t_fdpass.sh,v 1.2 2012/08/16 08:39:43 martin 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.
|
||||
#
|
||||
|
||||
have32() {
|
||||
local src="$(atf_get_srcdir)"
|
||||
if cmp "${src}/fdpass64" "${src}/fdpass32" > /dev/null
|
||||
then
|
||||
# echo "no -m32 support"
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
atf_test_case fdpass_normal
|
||||
|
||||
fdpass_normal_head() {
|
||||
atf_set "descr" "Test file descriptor passing (default)"
|
||||
}
|
||||
|
||||
fdpass_normal_body() {
|
||||
local src="$(atf_get_srcdir)"
|
||||
atf_check "${src}/fdpass64"
|
||||
}
|
||||
|
||||
|
||||
atf_test_case fdpass_compat
|
||||
|
||||
fdpass_compat_head() {
|
||||
atf_set "descr" "Test file descriptor passing (compat)"
|
||||
}
|
||||
|
||||
fdpass_compat_body() {
|
||||
local src="$(atf_get_srcdir)"
|
||||
have32 && atf_check "${src}/fdpass32"
|
||||
}
|
||||
|
||||
|
||||
atf_test_case fdpass_normal_compat
|
||||
|
||||
fdpass_normal_compat_head() {
|
||||
atf_set "descr" "Test file descriptor passing (normal->compat)"
|
||||
}
|
||||
|
||||
fdpass_normal_compat_body() {
|
||||
local src="$(atf_get_srcdir)"
|
||||
have32 && atf_check "${src}/fdpass64" -p "${src}/fdpass32"
|
||||
}
|
||||
|
||||
|
||||
atf_test_case fdpass_compat_normal
|
||||
|
||||
fdpass_compat_normal_head() {
|
||||
atf_set "descr" "Test file descriptor passing (normal->compat)"
|
||||
}
|
||||
|
||||
fdpass_compat_normal_body() {
|
||||
local src="$(atf_get_srcdir)"
|
||||
have32 && atf_check "${src}/fdpass32" -p "${src}/fdpass64"
|
||||
}
|
||||
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case fdpass_normal
|
||||
if have32
|
||||
then
|
||||
atf_add_test_case fdpass_compat
|
||||
atf_add_test_case fdpass_compat_normal
|
||||
atf_add_test_case fdpass_normal_compat
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# $NetBSD: Makefile,v 1.3 2010/12/14 11:03:17 pooka Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/icmp
|
||||
|
||||
TESTS_C= t_forward
|
||||
TESTS_C+= t_ping
|
||||
|
||||
TESTS_SH= t_ping2
|
||||
|
||||
LDADD+= -lrumpnet_shmif -lrumpnet_netinet -lrumpnet_net -lrumpnet
|
||||
LDADD+= -lrump -lrumpuser -lpthread
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,169 @@
|
||||
/* $NetBSD: t_forward.c,v 1.8 2012/03/18 09:46:50 jruoho Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: t_forward.c,v 1.8 2012/03/18 09:46:50 jruoho Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../h_macros.h"
|
||||
#include "../config/netconfig.c"
|
||||
|
||||
/*
|
||||
* Since our maxttl is in our private namespace, we don't need raw packet
|
||||
* construction like traceroute(8) -- we can just use the global maxttl.
|
||||
*/
|
||||
static void
|
||||
sendttl(void)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
char payload[1024];
|
||||
char ifname[IFNAMSIZ];
|
||||
int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
|
||||
int nv;
|
||||
int s;
|
||||
|
||||
netcfg_rump_makeshmif("bus1", ifname);
|
||||
netcfg_rump_if(ifname, "1.0.0.1", "255.255.255.0");
|
||||
netcfg_rump_route("0.0.0.0", "0.0.0.0", "1.0.0.2"); /* default router */
|
||||
|
||||
/* set global ttl to 1 */
|
||||
nv = 1;
|
||||
if (rump_sys___sysctl(mib, 4, NULL, NULL, &nv, sizeof(nv)) == -1)
|
||||
atf_tc_fail_errno("set ttl");
|
||||
|
||||
s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1)
|
||||
atf_tc_fail_errno("create send socket");
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(33434);
|
||||
sin.sin_addr.s_addr = inet_addr("9.9.9.9");
|
||||
|
||||
/* send udp datagram with ttl == 1 */
|
||||
if (rump_sys_sendto(s, payload, sizeof(payload), 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin)) == -1)
|
||||
atf_tc_fail_errno("sendto");
|
||||
}
|
||||
|
||||
static void
|
||||
router(void)
|
||||
{
|
||||
int mib[4] = { CTL_NET, PF_INET, IPPROTO_ICMP,
|
||||
ICMPCTL_RETURNDATABYTES };
|
||||
char ifname[IFNAMSIZ];
|
||||
int nv;
|
||||
|
||||
/* set returndatabytes to 200 */
|
||||
nv = 200;
|
||||
if (rump_sys___sysctl(mib, 4, NULL, NULL, &nv, sizeof(nv)) == -1)
|
||||
atf_tc_fail_errno("sysctl returndatabytes");
|
||||
|
||||
netcfg_rump_makeshmif("bus1", ifname);
|
||||
netcfg_rump_if(ifname, "1.0.0.2", "255.255.255.0");
|
||||
|
||||
/*
|
||||
* Wait for parent to send us the data and for us to have
|
||||
* a chance to process it.
|
||||
*/
|
||||
sleep(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ATF_TC(returndatabytes);
|
||||
ATF_TC_HEAD(returndatabytes, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "icmp.returndatabytes with certain "
|
||||
"packets can cause kernel panic (PR kern/43548)");
|
||||
atf_tc_set_md_var(tc, "timeout", "4"); /* just in case */
|
||||
}
|
||||
|
||||
ATF_TC_BODY(returndatabytes, tc)
|
||||
{
|
||||
pid_t cpid;
|
||||
int status;
|
||||
|
||||
cpid = fork();
|
||||
rump_init();
|
||||
|
||||
switch (cpid) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
case 0:
|
||||
router();
|
||||
break;
|
||||
default:
|
||||
sendttl();
|
||||
if (wait(&status) == -1)
|
||||
atf_tc_fail_errno("wait");
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status))
|
||||
atf_tc_fail("child exited with status %d",
|
||||
WEXITSTATUS(status));
|
||||
} else {
|
||||
atf_tc_fail("child died");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, returndatabytes);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,438 @@
|
||||
/* $NetBSD: t_ping.c,v 1.15 2012/09/04 22:31:58 alnsn Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: t_ping.c,v 1.15 2012/09/04 22:31:58 alnsn Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip_var.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include "../../h_macros.h"
|
||||
#include "../config/netconfig.c"
|
||||
|
||||
ATF_TC(simpleping);
|
||||
ATF_TC_HEAD(simpleping, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "check that kernel responds to ping");
|
||||
atf_tc_set_md_var(tc, "timeout", "2");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(simpleping, tc)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
pid_t cpid;
|
||||
bool win, win2;
|
||||
char token;
|
||||
int channel[2];
|
||||
|
||||
RL(pipe(channel));
|
||||
|
||||
cpid = fork();
|
||||
rump_init();
|
||||
netcfg_rump_makeshmif("but-can-i-buy-your-ether-bus", ifname);
|
||||
|
||||
switch (cpid) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
case 0:
|
||||
netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
|
||||
close(channel[0]);
|
||||
ATF_CHECK(write(channel[1], "U", 1) == 1);
|
||||
close(channel[1]);
|
||||
pause();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
close(channel[1]);
|
||||
ATF_CHECK(read(channel[0], &token, 1) == 1 && token == 'U');
|
||||
close(channel[0]);
|
||||
|
||||
netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
|
||||
|
||||
/*
|
||||
* The beauty of shmif is that we don't have races here.
|
||||
*/
|
||||
win = netcfg_rump_pingtest("1.1.1.10", 500);
|
||||
win2 = netcfg_rump_pingtest("1.1.1.30", 500);
|
||||
|
||||
kill(cpid, SIGKILL);
|
||||
|
||||
if (!win)
|
||||
atf_tc_fail("ping failed");
|
||||
if (win2)
|
||||
atf_tc_fail("non-existent host responded");
|
||||
}
|
||||
|
||||
ATF_TC(floodping);
|
||||
ATF_TC_HEAD(floodping, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "see how kernel responds to floodping");
|
||||
}
|
||||
|
||||
/* why the hell isn't this available in userspace??? */
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
doping(const char *target, int loops, u_int pktsize)
|
||||
{
|
||||
union {
|
||||
char buf[IP_MAXPACKET - sizeof(struct ip)];
|
||||
struct icmp i; /* ensure proper alignment */
|
||||
} sndbuf;
|
||||
char recvbuf[IP_MAXPACKET];
|
||||
struct sockaddr_in dst, pingee;
|
||||
struct icmp *icmp;
|
||||
socklen_t slen;
|
||||
ssize_t n;
|
||||
int loop, succ;
|
||||
int x, xnon, s;
|
||||
|
||||
RL(s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP));
|
||||
RL(x = rump_sys_fcntl(s, F_GETFL, 0));
|
||||
xnon = x | O_NONBLOCK;
|
||||
|
||||
memset(&dst, 0, sizeof(dst));
|
||||
dst.sin_len = sizeof(dst);
|
||||
dst.sin_family = AF_INET;
|
||||
dst.sin_addr.s_addr = inet_addr(target);
|
||||
|
||||
icmp = (struct icmp *)&sndbuf;
|
||||
memset(icmp, 0, sizeof(*icmp));
|
||||
icmp->icmp_type = ICMP_ECHO;
|
||||
icmp->icmp_id = htons(37);
|
||||
|
||||
if (pktsize < sizeof(*icmp))
|
||||
pktsize = sizeof(*icmp);
|
||||
if (pktsize > sizeof(sndbuf.buf))
|
||||
pktsize = sizeof(sndbuf.buf);
|
||||
|
||||
RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_SNDBUF,
|
||||
&pktsize, sizeof(pktsize)));
|
||||
RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVBUF,
|
||||
&pktsize, sizeof(pktsize)));
|
||||
|
||||
slen = sizeof(pingee);
|
||||
succ = 0;
|
||||
for (loop = 0; loop < loops; loop++) {
|
||||
RL(rump_sys_fcntl(s, F_SETFL, x));
|
||||
icmp->icmp_seq = htons(loop);
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = in_cksum(icmp, pktsize);
|
||||
RL(rump_sys_sendto(s, icmp, pktsize, 0,
|
||||
(struct sockaddr *)&dst, sizeof(dst)));
|
||||
|
||||
RL(rump_sys_fcntl(s, F_SETFL, xnon));
|
||||
while ((n = rump_sys_recvfrom(s, recvbuf, sizeof(recvbuf), 0,
|
||||
(struct sockaddr *)&pingee, &slen)) > 0) {
|
||||
succ++;
|
||||
}
|
||||
if (n == -1 && errno == EAGAIN)
|
||||
continue;
|
||||
atf_tc_fail_errno("recv failed");
|
||||
}
|
||||
|
||||
rump_sys_close(s);
|
||||
return succ;
|
||||
}
|
||||
|
||||
#define LOOPS 10000
|
||||
|
||||
ATF_TC_BODY(floodping, tc)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
pid_t cpid;
|
||||
int succ;
|
||||
|
||||
cpid = fork();
|
||||
rump_init();
|
||||
netcfg_rump_makeshmif("thank-you-driver-for-getting-me-here", ifname);
|
||||
|
||||
switch (cpid) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
case 0:
|
||||
netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
|
||||
pause();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
|
||||
|
||||
succ = doping("1.1.1.10", LOOPS, 56);
|
||||
printf("got %d/%d\n", succ, LOOPS);
|
||||
|
||||
kill(cpid, SIGKILL);
|
||||
}
|
||||
|
||||
ATF_TC(floodping2);
|
||||
ATF_TC_HEAD(floodping2, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "two hosts floodpinging each other");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(floodping2, tc)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
pid_t cpid;
|
||||
int succ;
|
||||
|
||||
cpid = fork();
|
||||
rump_init();
|
||||
netcfg_rump_makeshmif("floodping2", ifname);
|
||||
|
||||
switch (cpid) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
case 0:
|
||||
netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
|
||||
succ = doping("1.1.1.20", LOOPS, 56);
|
||||
break;
|
||||
default:
|
||||
netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
|
||||
succ = doping("1.1.1.10", LOOPS, 56);
|
||||
break;
|
||||
}
|
||||
|
||||
printf("got %d/%d\n", succ, LOOPS);
|
||||
}
|
||||
|
||||
ATF_TC(pingsize);
|
||||
ATF_TC_HEAD(pingsize, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "ping with packets min <= size <= max");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(pingsize, tc)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
pid_t cpid;
|
||||
int succ, i;
|
||||
|
||||
cpid = fork();
|
||||
rump_init();
|
||||
netcfg_rump_makeshmif("jippikaiee", ifname);
|
||||
|
||||
switch (cpid) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
case 0:
|
||||
netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
|
||||
pause();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
|
||||
|
||||
succ = 0;
|
||||
|
||||
/* small sizes */
|
||||
for (i = 0 ; i < IP_MAXPACKET - 60000; i++)
|
||||
succ += doping("1.1.1.10", 1, i);
|
||||
|
||||
/* medium sizes */
|
||||
for (i = IP_MAXPACKET - 60000; i < IP_MAXPACKET - 100; i += 1000)
|
||||
succ += doping("1.1.1.10", 1, i);
|
||||
|
||||
/* big sizes */
|
||||
for (i = IP_MAXPACKET - 100; i < IP_MAXPACKET; i += 10)
|
||||
succ += doping("1.1.1.10", 1, i);
|
||||
|
||||
printf("got %d/%d\n", succ, IP_MAXPACKET);
|
||||
kill(cpid, SIGKILL);
|
||||
}
|
||||
|
||||
ATF_TC(ping_of_death);
|
||||
ATF_TC_HEAD(ping_of_death, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "send a \"ping of death\"");
|
||||
atf_tc_set_md_var(tc, "timeout", "2");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(ping_of_death, tc)
|
||||
{
|
||||
char data[1500];
|
||||
struct sockaddr_in dst;
|
||||
struct ip *ip;
|
||||
struct icmp *icmp;
|
||||
char ifname[IFNAMSIZ];
|
||||
pid_t cpid;
|
||||
size_t tot, frag;
|
||||
int s, x, loop;
|
||||
|
||||
cpid = fork();
|
||||
rump_init();
|
||||
netcfg_rump_makeshmif("jippikaiee", ifname);
|
||||
|
||||
switch (cpid) {
|
||||
case -1:
|
||||
atf_tc_fail_errno("fork failed");
|
||||
case 0:
|
||||
/* wait until we receive a too long IP packet */
|
||||
for (loop = 0;; loop++) {
|
||||
uint64_t ipstat[IP_NSTATS];
|
||||
size_t arglen;
|
||||
int mib[4];
|
||||
|
||||
if (loop == 1)
|
||||
netcfg_rump_if(ifname,
|
||||
"1.1.1.10", "255.255.255.0");
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_INET;
|
||||
mib[2] = IPPROTO_IP;
|
||||
mib[3] = IPCTL_STATS;
|
||||
|
||||
arglen = sizeof(ipstat);
|
||||
RL(rump_sys___sysctl(mib, 4, &ipstat, &arglen,
|
||||
NULL, 0));
|
||||
if (loop == 0 && ipstat[IP_STAT_TOOLONG] != 0)
|
||||
_exit(1);
|
||||
if (ipstat[IP_STAT_TOOLONG])
|
||||
break;
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
|
||||
|
||||
RL(s = rump_sys_socket(PF_INET, SOCK_RAW, 0));
|
||||
x = 1;
|
||||
RL(rump_sys_setsockopt(s, IPPROTO_IP, IP_HDRINCL, &x, sizeof(x)));
|
||||
|
||||
memset(&dst, 0, sizeof(dst));
|
||||
dst.sin_len = sizeof(dst);
|
||||
dst.sin_family = AF_INET;
|
||||
dst.sin_addr.s_addr = inet_addr("1.1.1.10");
|
||||
|
||||
/* construct packet */
|
||||
memset(data, 0, sizeof(data));
|
||||
ip = (struct ip *)data;
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = sizeof(*ip) >> 2;
|
||||
ip->ip_p = IPPROTO_ICMP;
|
||||
ip->ip_ttl = IPDEFTTL;
|
||||
ip->ip_dst = dst.sin_addr;
|
||||
ip->ip_id = 1234;
|
||||
|
||||
icmp = (struct icmp *)(ip + 1);
|
||||
icmp->icmp_type = ICMP_ECHO;
|
||||
icmp->icmp_cksum = in_cksum(icmp, sizeof(*icmp));
|
||||
|
||||
for (;;) {
|
||||
int status;
|
||||
|
||||
/* resolve arp before sending raw stuff */
|
||||
netcfg_rump_pingtest("1.1.1.10", 1);
|
||||
|
||||
for (tot = 0;
|
||||
tot < 65538 - sizeof(*ip);
|
||||
tot += (frag - sizeof(*ip))) {
|
||||
frag = MIN(65538 - tot, sizeof(data));
|
||||
ip->ip_off = tot >> 3;
|
||||
assert((size_t)ip->ip_off << 3 == tot);
|
||||
ip->ip_len = frag;
|
||||
|
||||
if (frag == sizeof(data)) {
|
||||
ip->ip_off |= IP_MF;
|
||||
}
|
||||
|
||||
RL(rump_sys_sendto(s, data, frag, 0,
|
||||
(struct sockaddr *)&dst, sizeof(dst)));
|
||||
}
|
||||
if (waitpid(-1, &status, WNOHANG) > 0) {
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||
break;
|
||||
atf_tc_fail("child did not exit clean");
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, simpleping);
|
||||
ATF_TP_ADD_TC(tp, floodping);
|
||||
ATF_TP_ADD_TC(tp, floodping2);
|
||||
ATF_TP_ADD_TC(tp, pingsize);
|
||||
ATF_TP_ADD_TC(tp, ping_of_death);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
# $NetBSD: t_ping2.sh,v 1.4 2010/12/30 16:58:07 pooka Exp $
|
||||
#
|
||||
# Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
netserver=\
|
||||
"rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif"
|
||||
|
||||
atf_test_case basic cleanup
|
||||
basic_head()
|
||||
{
|
||||
|
||||
atf_set "descr" "Checks that a simple ping works"
|
||||
}
|
||||
|
||||
docfg ()
|
||||
{
|
||||
|
||||
sock=${1}
|
||||
addr=${2}
|
||||
|
||||
atf_check -s exit:0 \
|
||||
env RUMP_SERVER=${sock} rump.ifconfig shmif0 create
|
||||
atf_check -s exit:0 \
|
||||
env RUMP_SERVER=${sock} rump.ifconfig shmif0 linkstr bus
|
||||
atf_check -s exit:0 \
|
||||
env RUMP_SERVER=${sock} rump.ifconfig shmif0 inet ${addr}
|
||||
}
|
||||
|
||||
basic_body()
|
||||
{
|
||||
|
||||
atf_check -s exit:0 ${netserver} unix://commsock1
|
||||
atf_check -s exit:0 ${netserver} unix://commsock2
|
||||
|
||||
docfg unix://commsock1 1.2.3.4
|
||||
docfg unix://commsock2 1.2.3.5
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
env RUMP_SERVER=unix://commsock1 rump.ping -n -c 1 1.2.3.5
|
||||
atf_check -s exit:0 -o ignore \
|
||||
env RUMP_SERVER=unix://commsock2 rump.ping -n -c 1 1.2.3.5
|
||||
}
|
||||
|
||||
basic_cleanup()
|
||||
{
|
||||
|
||||
env RUMP_SERVER=unix://commsock1 rump.halt
|
||||
env RUMP_SERVER=unix://commsock2 rump.halt
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
|
||||
atf_add_test_case basic
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# $NetBSD: Makefile,v 1.1 2010/11/07 19:53:42 pooka Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/if
|
||||
|
||||
TESTS_C= t_compat
|
||||
|
||||
LDADD+= -lrumpnet_shmif -lrumpnet_netinet -lrumpnet_net -lrumpnet -lrump
|
||||
LDADD+= -lrumpuser -lpthread
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,83 @@
|
||||
/* $NetBSD: t_compat.c,v 1.1 2010/11/07 19:53:42 pooka Exp $ */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include "../config/netconfig.c"
|
||||
|
||||
/*
|
||||
* Test for stack smashing in compat ioctl handling. Adapted as an
|
||||
* atf test from code provided by Onno van der Linden in PR kern/44054
|
||||
*/
|
||||
|
||||
struct oifreq {
|
||||
char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
|
||||
union {
|
||||
struct sockaddr ifru_addr;
|
||||
struct sockaddr ifru_dstaddr;
|
||||
struct sockaddr ifru_broadaddr;
|
||||
short ifru_flags;
|
||||
int ifru_metric;
|
||||
int ifru_mtu;
|
||||
int ifru_dlt;
|
||||
u_int ifru_value;
|
||||
void * ifru_data;
|
||||
struct {
|
||||
uint32_t b_buflen;
|
||||
void *b_buf;
|
||||
} ifru_b;
|
||||
} ifr_ifru;
|
||||
};
|
||||
#define OOSIOCGIFBRDADDR _IOWR('i', 18, struct oifreq)
|
||||
|
||||
ATF_TC(OOSIOCGIFBRDADDR);
|
||||
ATF_TC_HEAD(OOSIOCGIFBRDADDR, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Checks that OOSIOCGIFBRDADDR works "
|
||||
"(PR kern/44054)");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(OOSIOCGIFBRDADDR, tc)
|
||||
{
|
||||
int fd, ifnum;
|
||||
struct oifreq ifreq;
|
||||
struct sockaddr_in *sin;
|
||||
int rv;
|
||||
|
||||
memset(&ifreq,'\0',sizeof ifreq);
|
||||
|
||||
rump_init();
|
||||
|
||||
/* create an interface and give it netmask 0xffff0000 */
|
||||
rv = rump_pub_shmif_create("bus", &ifnum);
|
||||
if (rv)
|
||||
atf_tc_fail("failed to create shmif: %s", strerror(rv));
|
||||
sprintf(ifreq.ifr_name, "shmif%d", ifnum);
|
||||
netcfg_rump_if(ifreq.ifr_name, "1.7.64.10", "255.255.0.0");
|
||||
|
||||
/* query kernel for iface bcast */
|
||||
RL(fd = rump_sys_socket(AF_INET, SOCK_DGRAM, 0));
|
||||
RL(rump_sys_ioctl(fd, OOSIOCGIFBRDADDR, &ifreq));
|
||||
|
||||
/* make sure we got what we deserve */
|
||||
sin = (struct sockaddr_in *)&ifreq.ifr_broadaddr;
|
||||
ATF_REQUIRE_EQ(sin->sin_addr.s_addr, htonl(0x0107ffff));
|
||||
rump_sys_close(fd);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, OOSIOCGIFBRDADDR);
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# $NetBSD: Makefile,v 1.1 2010/07/25 21:42:08 pooka Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/if_loop
|
||||
|
||||
TESTS_C= t_pr
|
||||
|
||||
LDADD+= -lrumpnet_netinet -lrumpnet_net -lrumpnet
|
||||
LDADD+= -lrump -lrumpuser -lpthread
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,229 @@
|
||||
/* $NetBSD: t_pr.c,v 1.7 2012/03/18 09:46:50 jruoho Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: t_pr.c,v 1.7 2012/03/18 09:46:50 jruoho Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../config/netconfig.c"
|
||||
#include "../../h_macros.h"
|
||||
|
||||
/*
|
||||
* Prepare rump, configure interface and route to cause fragmentation
|
||||
*/
|
||||
static void
|
||||
setup(void)
|
||||
{
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
struct sockaddr_in m_sin;
|
||||
} m_rtmsg;
|
||||
#define rtm m_rtmsg.m_rtm
|
||||
#define rsin m_rtmsg.m_sin
|
||||
struct ifreq ifr;
|
||||
int s;
|
||||
|
||||
rump_init();
|
||||
|
||||
/* first, config lo0 & route */
|
||||
strcpy(ifname, "lo0");
|
||||
netcfg_rump_if(ifname, "127.0.0.1", "255.0.0.0");
|
||||
netcfg_rump_route("127.0.0.1", "255.0.0.0", "127.0.0.1");
|
||||
|
||||
if ((s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
|
||||
atf_tc_fail_errno("routing socket");
|
||||
|
||||
/*
|
||||
* set MTU for interface so that route MTU doesn't
|
||||
* get overridden by it.
|
||||
*/
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, "lo0");
|
||||
ifr.ifr_mtu = 1300;
|
||||
if (rump_sys_ioctl(s, SIOCSIFMTU, &ifr) == -1)
|
||||
atf_tc_fail_errno("set mtu");
|
||||
|
||||
/* change route MTU to 100 */
|
||||
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
||||
rtm.rtm_type = RTM_CHANGE;
|
||||
rtm.rtm_flags = RTF_STATIC;
|
||||
rtm.rtm_version = RTM_VERSION;
|
||||
rtm.rtm_seq = 3;
|
||||
rtm.rtm_inits = RTV_MTU;
|
||||
rtm.rtm_addrs = RTA_DST;
|
||||
rtm.rtm_rmx.rmx_mtu = 100;
|
||||
rtm.rtm_msglen = sizeof(m_rtmsg);
|
||||
|
||||
memset(&rsin, 0, sizeof(rsin));
|
||||
rsin.sin_family = AF_INET;
|
||||
rsin.sin_len = sizeof(rsin);
|
||||
rsin.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if (rump_sys_write(s, &m_rtmsg, sizeof(m_rtmsg)) != sizeof(m_rtmsg))
|
||||
atf_tc_fail_errno("set route mtu");
|
||||
rump_sys_close(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn on checksums on loopback interfaces
|
||||
*/
|
||||
static int
|
||||
enable_locsums(void)
|
||||
{
|
||||
struct sysctlnode q, ans[256];
|
||||
int mib[5], enable;
|
||||
size_t alen;
|
||||
unsigned i;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_INET;
|
||||
mib[2] = IPPROTO_IP;
|
||||
mib[3] = CTL_QUERY;
|
||||
alen = sizeof(ans);
|
||||
|
||||
memset(&q, 0, sizeof(q));
|
||||
q.sysctl_flags = SYSCTL_VERSION;
|
||||
|
||||
if (rump_sys___sysctl(mib, 4, ans, &alen, &q, sizeof(q)) == -1)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < __arraycount(ans); i++)
|
||||
if (strcmp("do_loopback_cksum", ans[i].sysctl_name) == 0)
|
||||
break;
|
||||
if (i == __arraycount(ans)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mib[3] = ans[i].sysctl_num;
|
||||
|
||||
enable = 1;
|
||||
if (rump_sys___sysctl(mib, 4, NULL, NULL, &enable,
|
||||
sizeof(enable)) == -1)
|
||||
return errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ATF_TC(loopmtu);
|
||||
ATF_TC_HEAD(loopmtu, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr",
|
||||
"test lo0 fragmentation (PR kern/43664)");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(loopmtu, tc)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
char data[2000];
|
||||
int s;
|
||||
|
||||
setup();
|
||||
|
||||
/* open raw socket */
|
||||
s = rump_sys_socket(PF_INET, SOCK_RAW, 0);
|
||||
if (s == -1)
|
||||
atf_tc_fail_errno("raw socket");
|
||||
|
||||
/* then, send data */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_port = htons(12345);
|
||||
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if (rump_sys_sendto(s, data, sizeof(data), 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin)) == -1)
|
||||
atf_tc_fail_errno("sendto failed");
|
||||
}
|
||||
|
||||
ATF_TC(loopmtu_csum);
|
||||
ATF_TC_HEAD(loopmtu_csum, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr",
|
||||
"test lo0 fragmentation with checksums (PR kern/43664)");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(loopmtu_csum, tc)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
char data[2000];
|
||||
int s;
|
||||
|
||||
setup();
|
||||
|
||||
ATF_CHECK(enable_locsums() == 0);
|
||||
|
||||
/* open raw socket */
|
||||
s = rump_sys_socket(PF_INET, SOCK_RAW, 0);
|
||||
if (s == -1)
|
||||
atf_tc_fail_errno("raw socket");
|
||||
|
||||
/* then, send data */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_port = htons(12345);
|
||||
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if (rump_sys_sendto(s, data, sizeof(data), 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin)) == -1)
|
||||
atf_tc_fail_errno("sendto failed");
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, loopmtu);
|
||||
ATF_TP_ADD_TC(tp, loopmtu_csum);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# $NetBSD: Makefile,v 1.6 2013/07/03 14:01:29 nakayama Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/net
|
||||
|
||||
TESTS_C= t_unix
|
||||
TESTS_C+= t_udp
|
||||
TESTS_C+= t_pktinfo
|
||||
.if (${MKRUMP} != "no")
|
||||
TESTS_C+= t_raw
|
||||
.endif
|
||||
|
||||
LDADD.t_raw+= -lrumpnet_local -lrumpnet_netinet -lrumpnet_net
|
||||
LDADD.t_raw+= -lrumpnet -lrumpvfs -lrump -lrumpuser -lpthread
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,193 @@
|
||||
/* $NetBSD: t_pktinfo.c,v 1.1 2013/06/27 20:01:24 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2013 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: t_pktinfo.c,v 1.1 2013/06/27 20:01:24 christos Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
static const char traffic[] = "foo";
|
||||
|
||||
#ifdef TEST
|
||||
#include <err.h>
|
||||
#define ERR(msg) err(EXIT_FAILURE, msg)
|
||||
#define ERRX(msg, a) errx(EXIT_FAILURE, msg, a)
|
||||
#define ERRX2(msg, a1, a2) errx(EXIT_FAILURE, msg, a1, a2)
|
||||
#else
|
||||
#include <atf-c.h>
|
||||
#define ERR(msg) ATF_REQUIRE_MSG(0, "%s: %s", msg, strerror(errno))
|
||||
#define ERRX(msg, a) ATF_REQUIRE_MSG(0, msg, a)
|
||||
#define ERRX2(msg, a1, a2) ATF_REQUIRE_MSG(0, msg, a1, a2)
|
||||
#endif
|
||||
|
||||
static int
|
||||
server(struct sockaddr_in *sin) {
|
||||
int s, one;
|
||||
socklen_t len = sizeof(*sin);
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
ERR("socket");
|
||||
|
||||
memset(sin, 0, len);
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = len;
|
||||
sin->sin_port = 0;
|
||||
sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
if (bind(s, (const struct sockaddr *)sin, len) == -1)
|
||||
ERR("bind");
|
||||
|
||||
if (getsockname(s, (struct sockaddr *)sin, &len) == -1)
|
||||
ERR("getsockname");
|
||||
|
||||
one = 1;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)) == -1)
|
||||
ERR("setsockopt");
|
||||
if (setsockopt(s, IPPROTO_IP, IP_RECVPKTINFO, &one, sizeof(one)) == -1)
|
||||
ERR("setsockopt");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static int
|
||||
client(struct sockaddr_in *sin) {
|
||||
int s;
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
ERR("socket");
|
||||
if (sendto(s, traffic, sizeof(traffic), 0,
|
||||
(const struct sockaddr *)sin, sizeof(*sin)) == -1)
|
||||
ERR("sendto");
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
receive(int s) {
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iov;
|
||||
char buf[sizeof(traffic)];
|
||||
struct in_pktinfo *ipi;
|
||||
char control[CMSG_SPACE(sizeof(*ipi)) * 2];
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = &iov;
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof(control);
|
||||
msg.msg_flags = 0;
|
||||
|
||||
if (recvmsg(s, &msg, 0) == -1)
|
||||
ERR("recvmsg");
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != IPPROTO_IP)
|
||||
ERRX("bad level %d", cmsg->cmsg_level);
|
||||
const char *m;
|
||||
switch (cmsg->cmsg_type) {
|
||||
case IP_PKTINFO:
|
||||
m = "pktinfo";
|
||||
break;
|
||||
case IP_RECVPKTINFO:
|
||||
m = "recvpktinfo";
|
||||
break;
|
||||
default:
|
||||
m = NULL;
|
||||
ERRX("bad type %d", cmsg->cmsg_type);
|
||||
}
|
||||
ipi = (void *)CMSG_DATA(cmsg);
|
||||
#ifdef TEST
|
||||
printf("%s message received on address %s at interface %d\n",
|
||||
m, inet_ntoa(ipi->ipi_addr), ipi->ipi_ifindex);
|
||||
#else
|
||||
ATF_REQUIRE_MSG(ipi->ipi_addr.s_addr == htonl(INADDR_LOOPBACK),
|
||||
"address 0x%x != 0x%x", ipi->ipi_addr.s_addr,
|
||||
htonl(INADDR_LOOPBACK));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (strcmp(traffic, buf) != 0)
|
||||
ERRX2("Bad message '%s' != '%s'", buf, traffic);
|
||||
}
|
||||
|
||||
static void
|
||||
doit(void)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int s, c;
|
||||
s = server(&sin);
|
||||
c = client(&sin);
|
||||
receive(s);
|
||||
close(s);
|
||||
close(c);
|
||||
}
|
||||
|
||||
#ifndef TEST
|
||||
ATF_TC(pktinfo);
|
||||
ATF_TC_HEAD(pktinfo, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Check that IP_PKTINFO and "
|
||||
"IP_RECVPKTINFO work");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(pktinfo, tc)
|
||||
{
|
||||
doit();
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, pktinfo);
|
||||
return atf_no_error();
|
||||
}
|
||||
#else
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
doit();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/* $NetBSD: t_raw.c,v 1.1 2011/01/11 10:51:45 pooka Exp $ */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include "../../h_macros.h"
|
||||
|
||||
ATF_TC(PRU_SENSE);
|
||||
ATF_TC_HEAD(PRU_SENSE, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Biglock leak with PRU_SENSE on "
|
||||
"raw sockets (PR kern/44369)");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(PRU_SENSE, tc)
|
||||
{
|
||||
struct stat sb;
|
||||
int s;
|
||||
|
||||
rump_init();
|
||||
RL(s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0));
|
||||
/* call PRU_SENSE. unfixed bug causes panic in rump_unschedule() */
|
||||
RL(rump_sys_fstat(s, &sb));
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, PRU_SENSE);
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: t_udp.c,v 1.2 2013/01/06 02:22:50 christos Exp $");
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
static const char msg[] = "sendto test";
|
||||
|
||||
static void
|
||||
sendit(int family)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res;
|
||||
int S, s;
|
||||
int e;
|
||||
|
||||
/* lookup localhost addr, depending on argv[1] */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
hints.ai_flags = 0;
|
||||
|
||||
e = getaddrinfo("localhost", "9999", &hints, &res);
|
||||
ATF_REQUIRE_MSG(e == 0, "getaddrinfo AF=%d: %s", family,
|
||||
gai_strerror(e));
|
||||
|
||||
/* server socket */
|
||||
S = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
ATF_REQUIRE_MSG(S >= 0, "server-socket AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
e = bind(S, res->ai_addr, res->ai_addrlen);
|
||||
ATF_REQUIRE_MSG(e == 0, "bind AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
/* client socket */
|
||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
ATF_REQUIRE_MSG(s >= 0, "client-socket AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
/* sendto */
|
||||
e = sendto(s, msg, sizeof(msg), 0, res->ai_addr, res->ai_addrlen);
|
||||
ATF_REQUIRE_MSG(e == sizeof(msg), "sendto(1) AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
e = sendto(s, msg, sizeof(msg), 0, res->ai_addr, res->ai_addrlen);
|
||||
ATF_REQUIRE_MSG(e == sizeof(msg), "sendto(2) AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
/* connect + send */
|
||||
e = connect(s, res->ai_addr, res->ai_addrlen);
|
||||
ATF_REQUIRE_MSG(e == 0, "connect(1) AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
e = send(s, msg, sizeof(msg), 0);
|
||||
ATF_REQUIRE_MSG(e == sizeof(msg), "send(1) AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
e = connect(s, res->ai_addr, res->ai_addrlen);
|
||||
ATF_REQUIRE_MSG(e == 0, "connect(2) AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
e = send(s, msg, sizeof(msg), 0);
|
||||
ATF_REQUIRE_MSG(e == sizeof(msg), "send(2) AF=%d: %s", family,
|
||||
strerror(errno));
|
||||
|
||||
close(s);
|
||||
}
|
||||
|
||||
ATF_TC(udp4_send);
|
||||
ATF_TC_HEAD(udp4_send, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Check that inet4 udp send works both"
|
||||
" for connected and unconnected sockets");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(udp4_send, tc)
|
||||
{
|
||||
sendit(AF_INET);
|
||||
}
|
||||
|
||||
ATF_TC(udp6_send);
|
||||
ATF_TC_HEAD(udp6_send, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Check that inet6 udp send works both"
|
||||
" for connected and unconnected sockets");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(udp6_send, tc)
|
||||
{
|
||||
sendit(AF_INET6);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, udp4_send);
|
||||
ATF_TP_ADD_TC(tp, udp6_send);
|
||||
return atf_no_error();
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/* $NetBSD: t_unix.c,v 1.6 2011/10/04 16:28:26 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 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("$Id: t_unix.c,v 1.6 2011/10/04 16:28:26 christos Exp $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifdef TEST
|
||||
#define FAIL(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__)
|
||||
#else
|
||||
|
||||
#include <atf-c.h>
|
||||
#define FAIL(msg, ...) ATF_CHECK_MSG(0, msg, ## __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
static __dead int
|
||||
acc(int s)
|
||||
{
|
||||
char guard1;
|
||||
struct sockaddr_un sun;
|
||||
char guard2;
|
||||
socklen_t len;
|
||||
|
||||
guard1 = guard2 = 's';
|
||||
|
||||
len = sizeof(sun);
|
||||
if (accept(s, (struct sockaddr *)&sun, &len) == -1)
|
||||
FAIL("accept");
|
||||
if (guard1 != 's')
|
||||
errx(EXIT_FAILURE, "guard1 = '%c'", guard1);
|
||||
if (guard2 != 's')
|
||||
errx(EXIT_FAILURE, "guard2 = '%c'", guard2);
|
||||
close(s);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int
|
||||
test(size_t len)
|
||||
{
|
||||
struct sockaddr_un *sun;
|
||||
int s, s2;
|
||||
size_t slen;
|
||||
socklen_t sl;
|
||||
|
||||
slen = len + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||
|
||||
if ((sun = calloc(1, slen)) == NULL)
|
||||
FAIL("calloc");
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s == -1)
|
||||
FAIL("socket");
|
||||
|
||||
memset(sun->sun_path, 'a', len);
|
||||
sun->sun_path[len] = '\0';
|
||||
(void)unlink(sun->sun_path);
|
||||
|
||||
sl = SUN_LEN(sun);
|
||||
sun->sun_len = sl;
|
||||
sun->sun_family = AF_UNIX;
|
||||
|
||||
if (bind(s, (struct sockaddr *)sun, sl) == -1) {
|
||||
if (errno == EINVAL && sl >= 256)
|
||||
return -1;
|
||||
FAIL("bind");
|
||||
}
|
||||
|
||||
if (listen(s, 5) == -1)
|
||||
FAIL("listen");
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
FAIL("fork");
|
||||
case 0:
|
||||
acc(s);
|
||||
/*NOTREACHED*/
|
||||
default:
|
||||
sleep(1);
|
||||
s2 = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s2 == -1)
|
||||
FAIL("socket");
|
||||
if (connect(s2, (struct sockaddr *)sun, sl) == -1)
|
||||
FAIL("connect");
|
||||
close(s2);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef TEST
|
||||
|
||||
ATF_TC(sockaddr_un_len_exceed);
|
||||
ATF_TC_HEAD(sockaddr_un_len_exceed, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Check that exceeding the size of "
|
||||
"unix domain sockets does not trash memory or kernel when "
|
||||
"exceeding the size of the fixed sun_path");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(sockaddr_un_len_exceed, tc)
|
||||
{
|
||||
ATF_REQUIRE_MSG(test(254) == -1, "test(254): %s", strerror(errno));
|
||||
}
|
||||
|
||||
ATF_TC(sockaddr_un_len_max);
|
||||
ATF_TC_HEAD(sockaddr_un_len_max, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Check that we can use the maximum "
|
||||
"unix domain socket pathlen (253): 255 - sizeof(sun_len) - "
|
||||
"sizeof(sun_family)");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(sockaddr_un_len_max, tc)
|
||||
{
|
||||
ATF_REQUIRE_MSG(test(253) == 0, "test(253): %s", strerror(errno));
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, sockaddr_un_len_exceed);
|
||||
ATF_TP_ADD_TC(tp, sockaddr_un_len_max);
|
||||
return atf_no_error();
|
||||
}
|
||||
#else
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (argc == 1) {
|
||||
fprintf(stderr, "Usage: %s <len>\n", getprogname());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
test(atoi(argv[1]));
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
# $NetBSD: Makefile,v 1.1 2012/09/12 14:06:31 martin Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/npf
|
||||
FILESDIR= ${TESTSDIR}
|
||||
|
||||
TESTS_SH= t_npf
|
||||
FILES= ../../../usr.sbin/npf/npftest/npftest.conf
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,63 @@
|
||||
# $NetBSD: t_npf.sh,v 1.2 2012/09/18 08:28:15 martin Exp $
|
||||
#
|
||||
# Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
run_test()
|
||||
{
|
||||
local name="${1}"
|
||||
|
||||
atf_check -o ignore -e ignore npfctl debug "$(atf_get_srcdir)/npftest.conf" ./npf.plist
|
||||
atf_check -o ignore npftest -c npf.plist -T "${name}"
|
||||
}
|
||||
|
||||
add_test()
|
||||
{
|
||||
local name="${1}"; shift
|
||||
local desc="${*}";
|
||||
|
||||
atf_test_case "npf_${name}"
|
||||
eval "npf_${name}_head() { \
|
||||
atf_set \"descr\" \"${desc}\"; \
|
||||
atf_set \"require.progs\" \"npfctl npftest\"; \
|
||||
}; \
|
||||
npf_${name}_body() { \
|
||||
run_test \"${name}\"; \
|
||||
}"
|
||||
atf_add_test_case "npf_${name}"
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
LIST=/tmp/t_npf.$$
|
||||
trap "rm -f $LIST" EXIT
|
||||
|
||||
sh -ec 'npftest -L || printf "dummy\tnone\n"' > $LIST 2>/dev/null
|
||||
|
||||
while read tag desc
|
||||
do
|
||||
add_test "${tag}" "${desc}"
|
||||
done < $LIST
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# $NetBSD: Makefile,v 1.1 2011/02/08 10:11:29 pooka Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/route
|
||||
|
||||
TESTS_SH= t_change
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,65 @@
|
||||
# $NetBSD: t_change.sh,v 1.4 2013/02/19 21:08:25 joerg Exp $
|
||||
#
|
||||
# Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
netserver=\
|
||||
"rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet"
|
||||
export RUMP_SERVER=unix://commsock
|
||||
|
||||
atf_test_case reject2blackhole cleanup
|
||||
reject2blackhole_head()
|
||||
{
|
||||
|
||||
atf_set "descr" "Change a reject route to blackhole"
|
||||
atf_set "require.progs" "rump_server"
|
||||
}
|
||||
|
||||
reject2blackhole_body()
|
||||
{
|
||||
|
||||
atf_check -s exit:0 ${netserver} ${RUMP_SERVER}
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
rump.route add 207.46.197.32 127.0.0.1 -reject
|
||||
atf_check -s exit:0 -o match:UGHR -x \
|
||||
"rump.route -n show -inet | grep ^207.46"
|
||||
atf_check -s exit:0 -o ignore \
|
||||
rump.route change 207.46.197.32 127.0.0.1 -blackhole
|
||||
atf_check -s exit:0 -o match:' UGHBS ' -e ignore -x \
|
||||
"rump.netstat -rn -f inet | grep ^207.46| grep ^207.46"
|
||||
}
|
||||
|
||||
reject2blackhole_cleanup()
|
||||
{
|
||||
|
||||
env RUMP_SERVER=unix://commsock rump.halt
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
|
||||
atf_add_test_case reject2blackhole
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# $NetBSD: Makefile,v 1.5 2011/11/05 18:19:02 jruoho Exp $
|
||||
|
||||
# NOTE: please add all syscall-tests to tests/lib/libc/sys.
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/net/sys
|
||||
|
||||
TESTS_C+= t_rfc6056
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,152 @@
|
||||
/* $NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 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: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include <err.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
static void
|
||||
test(const char *hostname, const char *service, int family, int al)
|
||||
{
|
||||
static const char hello[] = "hello\n";
|
||||
int s, error, proto, option;
|
||||
struct sockaddr_storage ss;
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
proto = IPPROTO_IP;
|
||||
option = IP_PORTALGO;
|
||||
break;
|
||||
case AF_INET6:
|
||||
proto = IPPROTO_IPV6;
|
||||
option = IPV6_PORTALGO;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
error = getaddrinfo(hostname, service, &hints, &res);
|
||||
if (error)
|
||||
errx(EXIT_FAILURE, "Cannot get address for %s (%s)",
|
||||
hostname, gai_strerror(error));
|
||||
|
||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (s == -1)
|
||||
err(EXIT_FAILURE, "socket");
|
||||
|
||||
if (setsockopt(s, proto, option, &al, sizeof(al)) == -1)
|
||||
err(EXIT_FAILURE, "setsockopt");
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_len = res->ai_addrlen;
|
||||
ss.ss_family = res->ai_family;
|
||||
|
||||
if (bind(s, (struct sockaddr *)&ss, ss.ss_len) == -1)
|
||||
err(EXIT_FAILURE, "bind");
|
||||
|
||||
if (sendto(s, hello, sizeof(hello) - 1, 0,
|
||||
res->ai_addr, res->ai_addrlen) == -1)
|
||||
err(EXIT_FAILURE, "sendto");
|
||||
|
||||
if (close(s) == -1)
|
||||
err(EXIT_FAILURE, "close");
|
||||
|
||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (s == -1)
|
||||
err(EXIT_FAILURE, "socket");
|
||||
|
||||
if (setsockopt(s, proto, option, &al, sizeof(al)) == -1)
|
||||
err(EXIT_FAILURE, "setsockopt");
|
||||
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) == -1)
|
||||
err(EXIT_FAILURE, "connect");
|
||||
|
||||
if (send(s, hello, sizeof(hello) - 1, 0) == -1)
|
||||
err(EXIT_FAILURE, "send");
|
||||
|
||||
if (close(s) == -1)
|
||||
err(EXIT_FAILURE, "close");
|
||||
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
ATF_TC(inet4);
|
||||
ATF_TC_HEAD(inet4, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Checks random port allocation "
|
||||
"for ipv4");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(inet4, tc)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
test("localhost", "http", AF_INET, i);
|
||||
}
|
||||
|
||||
ATF_TC(inet6);
|
||||
ATF_TC_HEAD(inet6, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Checks random port allocation "
|
||||
"for ipv6");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(inet6, tc)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
test("localhost", "http", AF_INET6, i);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
ATF_TP_ADD_TC(tp, inet4);
|
||||
ATF_TP_ADD_TC(tp, inet6);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
Reference in New Issue
Block a user