xref: /netbsd-src/tests/net/icmp/t_ping.c (revision dd9a37587628c7b66115640171fbbeb53747344a)
1*dd9a3758Sgson /*	$NetBSD: t_ping.c,v 1.24 2019/06/11 08:34:01 gson Exp $	*/
296f76684Spooka 
396f76684Spooka /*-
496f76684Spooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
596f76684Spooka  * All rights reserved.
696f76684Spooka  *
796f76684Spooka  * Redistribution and use in source and binary forms, with or without
896f76684Spooka  * modification, are permitted provided that the following conditions
996f76684Spooka  * are met:
1096f76684Spooka  * 1. Redistributions of source code must retain the above copyright
1196f76684Spooka  *    notice, this list of conditions and the following disclaimer.
1296f76684Spooka  * 2. Redistributions in binary form must reproduce the above copyright
1396f76684Spooka  *    notice, this list of conditions and the following disclaimer in the
1496f76684Spooka  *    documentation and/or other materials provided with the distribution.
1596f76684Spooka  *
1696f76684Spooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1796f76684Spooka  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1896f76684Spooka  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1996f76684Spooka  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2096f76684Spooka  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
2196f76684Spooka  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2296f76684Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2396f76684Spooka  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2496f76684Spooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2596f76684Spooka  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2696f76684Spooka  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2796f76684Spooka  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2896f76684Spooka  */
2996f76684Spooka 
3096f76684Spooka #include <sys/cdefs.h>
3196f76684Spooka #ifndef lint
32*dd9a3758Sgson __RCSID("$NetBSD: t_ping.c,v 1.24 2019/06/11 08:34:01 gson Exp $");
3396f76684Spooka #endif /* not lint */
3496f76684Spooka 
3596f76684Spooka #include <sys/types.h>
3675487b05Spooka #include <sys/resource.h>
37b3495eccSpooka #include <sys/sysctl.h>
38b3495eccSpooka #include <sys/wait.h>
3996f76684Spooka 
4096f76684Spooka #include <atf-c.h>
41b3495eccSpooka #include <assert.h>
4275487b05Spooka #include <fcntl.h>
4396f76684Spooka #include <stdio.h>
4496f76684Spooka #include <stdlib.h>
4596f76684Spooka #include <string.h>
4696f76684Spooka #include <unistd.h>
4760e8629aSchristos #include <signal.h>
4896f76684Spooka 
49b3495eccSpooka #include <netinet/in.h>
50b3495eccSpooka #include <netinet/ip_var.h>
51b3495eccSpooka 
5296f76684Spooka #include <rump/rump.h>
53b3495eccSpooka #include <rump/rump_syscalls.h>
5496f76684Spooka 
55c54cb811Schristos #include "h_macros.h"
5696f76684Spooka #include "../config/netconfig.c"
5796f76684Spooka 
5896f76684Spooka ATF_TC(simpleping);
ATF_TC_HEAD(simpleping,tc)5996f76684Spooka ATF_TC_HEAD(simpleping, tc)
6096f76684Spooka {
6196f76684Spooka 
6296f76684Spooka 	atf_tc_set_md_var(tc, "descr", "check that kernel responds to ping");
6388c71eddSmartin 	atf_tc_set_md_var(tc, "timeout", "20");
6496f76684Spooka }
6596f76684Spooka 
ATF_TC_BODY(simpleping,tc)6696f76684Spooka ATF_TC_BODY(simpleping, tc)
6796f76684Spooka {
6896f76684Spooka 	char ifname[IFNAMSIZ];
6996f76684Spooka 	pid_t cpid;
7096f76684Spooka 	bool win, win2;
71b8a85c69Salnsn 	char token;
72b8a85c69Salnsn 	int channel[2];
73b8a85c69Salnsn 
74b8a85c69Salnsn 	RL(pipe(channel));
7596f76684Spooka 
7696f76684Spooka 	cpid = fork();
7796f76684Spooka 	rump_init();
7896f76684Spooka 	netcfg_rump_makeshmif("but-can-i-buy-your-ether-bus", ifname);
7996f76684Spooka 
8096f76684Spooka 	switch (cpid) {
8196f76684Spooka 	case -1:
8296f76684Spooka 		atf_tc_fail_errno("fork failed");
8396f76684Spooka 	case 0:
8496f76684Spooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
85b8a85c69Salnsn 		close(channel[0]);
86b8a85c69Salnsn 		ATF_CHECK(write(channel[1], "U", 1) == 1);
87b8a85c69Salnsn 		close(channel[1]);
8896f76684Spooka 		pause();
8996f76684Spooka 		break;
9096f76684Spooka 	default:
9196f76684Spooka 		break;
9296f76684Spooka 	}
9396f76684Spooka 
94b8a85c69Salnsn 	close(channel[1]);
95b8a85c69Salnsn 	ATF_CHECK(read(channel[0], &token, 1) == 1 && token == 'U');
96b8a85c69Salnsn 	close(channel[0]);
97b846a386Spooka 
9896f76684Spooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
9996f76684Spooka 
10096f76684Spooka 	/*
10196f76684Spooka 	 * The beauty of shmif is that we don't have races here.
10296f76684Spooka 	 */
10396f76684Spooka 	win = netcfg_rump_pingtest("1.1.1.10", 500);
10496f76684Spooka 	win2 = netcfg_rump_pingtest("1.1.1.30", 500);
10596f76684Spooka 
10696f76684Spooka 	kill(cpid, SIGKILL);
10796f76684Spooka 
10896f76684Spooka 	if (!win)
10996f76684Spooka 		atf_tc_fail("ping failed");
11096f76684Spooka 	if (win2)
11196f76684Spooka 		atf_tc_fail("non-existent host responded");
11296f76684Spooka }
11396f76684Spooka 
11475487b05Spooka ATF_TC(floodping);
ATF_TC_HEAD(floodping,tc)11575487b05Spooka ATF_TC_HEAD(floodping, tc)
11675487b05Spooka {
11775487b05Spooka 
11875487b05Spooka 	atf_tc_set_md_var(tc, "descr", "see how kernel responds to floodping");
11975487b05Spooka }
12075487b05Spooka 
1219a3c295eSpooka /* why the hell isn't this available in userspace??? */
1229a3c295eSpooka static uint16_t
in_cksum(void * data,size_t len)1239a3c295eSpooka in_cksum(void *data, size_t len)
12475487b05Spooka {
1259a3c295eSpooka 	uint16_t *buf = data;
1269a3c295eSpooka 	unsigned sum;
1279a3c295eSpooka 
1289a3c295eSpooka 	for (sum = 0; len > 1; len -= 2)
1299a3c295eSpooka 		sum += *buf++;
1309a3c295eSpooka 	if (len)
1319a3c295eSpooka 		sum += *(uint8_t *)buf;
1329a3c295eSpooka 
1339a3c295eSpooka 	sum = (sum >> 16) + (sum & 0xffff);
1349a3c295eSpooka 	sum += (sum >> 16);
1359a3c295eSpooka 
1369a3c295eSpooka 	return ~sum;
1379a3c295eSpooka }
1389a3c295eSpooka 
1399a3c295eSpooka static int
doping(const char * target,int loops,u_int pktsize)140fb0d4bccSchristos doping(const char *target, int loops, u_int pktsize)
1419a3c295eSpooka {
142db69e273Smartin 	union {
143db69e273Smartin 		char buf[IP_MAXPACKET - sizeof(struct ip)];
144db69e273Smartin 		struct icmp i;	/* ensure proper alignment */
145db69e273Smartin 	} sndbuf;
1469a3c295eSpooka 	char recvbuf[IP_MAXPACKET];
14775487b05Spooka 	struct sockaddr_in dst, pingee;
1489a3c295eSpooka 	struct icmp *icmp;
14975487b05Spooka 	socklen_t slen;
15075487b05Spooka 	ssize_t n;
1510f10aa9dSchristos 	int loop, succ;
15275487b05Spooka 	int x, xnon, s;
15375487b05Spooka 
1549a3c295eSpooka 	RL(s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP));
1559a3c295eSpooka 	RL(x = rump_sys_fcntl(s, F_GETFL, 0));
1569a3c295eSpooka 	xnon = x | O_NONBLOCK;
1579a3c295eSpooka 
1589a3c295eSpooka 	memset(&dst, 0, sizeof(dst));
1599a3c295eSpooka 	dst.sin_len = sizeof(dst);
1609a3c295eSpooka 	dst.sin_family = AF_INET;
1619a3c295eSpooka 	dst.sin_addr.s_addr = inet_addr(target);
1629a3c295eSpooka 
163db69e273Smartin 	icmp = (struct icmp *)&sndbuf;
1649a3c295eSpooka 	memset(icmp, 0, sizeof(*icmp));
1659a3c295eSpooka 	icmp->icmp_type = ICMP_ECHO;
1669a3c295eSpooka 	icmp->icmp_id = htons(37);
1679a3c295eSpooka 
1689a3c295eSpooka 	if (pktsize < sizeof(*icmp))
1699a3c295eSpooka 		pktsize = sizeof(*icmp);
1707e35902cSmartin 	if (pktsize > sizeof(sndbuf.buf))
1717e35902cSmartin 		pktsize = sizeof(sndbuf.buf);
1729a3c295eSpooka 
1739a3c295eSpooka 	RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1749a3c295eSpooka 	    &pktsize, sizeof(pktsize)));
1759a3c295eSpooka 	RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVBUF,
1769a3c295eSpooka 	    &pktsize, sizeof(pktsize)));
1779a3c295eSpooka 
1789a3c295eSpooka 	slen = sizeof(pingee);
1799a3c295eSpooka 	succ = 0;
1809a3c295eSpooka 	for (loop = 0; loop < loops; loop++) {
1819a3c295eSpooka 		RL(rump_sys_fcntl(s, F_SETFL, x));
1829a3c295eSpooka 		icmp->icmp_seq = htons(loop);
1839a3c295eSpooka 		icmp->icmp_cksum = 0;
1849a3c295eSpooka 		icmp->icmp_cksum = in_cksum(icmp, pktsize);
18505ee2584Sroy 
18605ee2584Sroy 		n = rump_sys_sendto(s, icmp, pktsize, 0,
18705ee2584Sroy 		    (struct sockaddr *)&dst, sizeof(dst));
18805ee2584Sroy 		if (n == -1) {
18905ee2584Sroy 			if (errno == ENOBUFS)
19005ee2584Sroy 				continue;
19105ee2584Sroy 			atf_tc_fail_errno("sendto failed");
19205ee2584Sroy 		}
1939a3c295eSpooka 
1949a3c295eSpooka 		RL(rump_sys_fcntl(s, F_SETFL, xnon));
1959a3c295eSpooka 		while ((n = rump_sys_recvfrom(s, recvbuf, sizeof(recvbuf), 0,
1969a3c295eSpooka 		    (struct sockaddr *)&pingee, &slen)) > 0) {
1979a3c295eSpooka 			succ++;
1989a3c295eSpooka 		}
1991875ff6cSroy 		if (n == -1 && (errno == EAGAIN || errno == ENOBUFS))
2009a3c295eSpooka 			continue;
20162ac00a8Skamil 		atf_tc_fail_errno("recv failed (n == %zd)", n);
2029a3c295eSpooka 	}
2039a3c295eSpooka 
2049a3c295eSpooka 	rump_sys_close(s);
2059a3c295eSpooka 	return succ;
2069a3c295eSpooka }
2079a3c295eSpooka 
2089a3c295eSpooka #define LOOPS 10000
2099a3c295eSpooka 
ATF_TC_BODY(floodping,tc)2109a3c295eSpooka ATF_TC_BODY(floodping, tc)
2119a3c295eSpooka {
2129a3c295eSpooka 	char ifname[IFNAMSIZ];
2139a3c295eSpooka 	pid_t cpid;
2149a3c295eSpooka 	int succ;
2159a3c295eSpooka 
21675487b05Spooka 	cpid = fork();
21775487b05Spooka 	rump_init();
21875487b05Spooka 	netcfg_rump_makeshmif("thank-you-driver-for-getting-me-here", ifname);
21975487b05Spooka 
22075487b05Spooka 	switch (cpid) {
22175487b05Spooka 	case -1:
22275487b05Spooka 		atf_tc_fail_errno("fork failed");
22375487b05Spooka 	case 0:
22475487b05Spooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
22575487b05Spooka 		pause();
22675487b05Spooka 		break;
22775487b05Spooka 	default:
22875487b05Spooka 		break;
22975487b05Spooka 	}
23075487b05Spooka 
23175487b05Spooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
23275487b05Spooka 
2339a3c295eSpooka 	succ = doping("1.1.1.10", LOOPS, 56);
2349a3c295eSpooka 	printf("got %d/%d\n", succ, LOOPS);
23575487b05Spooka 
2369a3c295eSpooka 	kill(cpid, SIGKILL);
2379a3c295eSpooka }
23875487b05Spooka 
2399a3c295eSpooka ATF_TC(floodping2);
ATF_TC_HEAD(floodping2,tc)2409a3c295eSpooka ATF_TC_HEAD(floodping2, tc)
2419a3c295eSpooka {
24275487b05Spooka 
2439a3c295eSpooka 	atf_tc_set_md_var(tc, "descr", "two hosts floodpinging each other");
2449a3c295eSpooka }
2459a3c295eSpooka 
ATF_TC_BODY(floodping2,tc)2469a3c295eSpooka ATF_TC_BODY(floodping2, tc)
2479a3c295eSpooka {
2489a3c295eSpooka 	char ifname[IFNAMSIZ];
2499a3c295eSpooka 	pid_t cpid;
2509a3c295eSpooka 	int succ;
2519a3c295eSpooka 
2529a3c295eSpooka 	cpid = fork();
2539a3c295eSpooka 	rump_init();
2549a3c295eSpooka 	netcfg_rump_makeshmif("floodping2", ifname);
2559a3c295eSpooka 
2569a3c295eSpooka 	switch (cpid) {
2579a3c295eSpooka 	case -1:
2589a3c295eSpooka 		atf_tc_fail_errno("fork failed");
2599a3c295eSpooka 	case 0:
2609a3c295eSpooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
2619a3c295eSpooka 		succ = doping("1.1.1.20", LOOPS, 56);
2629a3c295eSpooka 		break;
2639a3c295eSpooka 	default:
2649a3c295eSpooka 		netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
2659a3c295eSpooka 		succ = doping("1.1.1.10", LOOPS, 56);
2669a3c295eSpooka 		break;
2679a3c295eSpooka 	}
2689a3c295eSpooka 
2699a3c295eSpooka 	printf("got %d/%d\n", succ, LOOPS);
2709a3c295eSpooka }
2719a3c295eSpooka 
2729a3c295eSpooka ATF_TC(pingsize);
ATF_TC_HEAD(pingsize,tc)2739a3c295eSpooka ATF_TC_HEAD(pingsize, tc)
2749a3c295eSpooka {
2759a3c295eSpooka 
2769a3c295eSpooka 	atf_tc_set_md_var(tc, "descr", "ping with packets min <= size <= max");
2779a3c295eSpooka }
2789a3c295eSpooka 
ATF_TC_BODY(pingsize,tc)2799a3c295eSpooka ATF_TC_BODY(pingsize, tc)
2809a3c295eSpooka {
2819a3c295eSpooka 	char ifname[IFNAMSIZ];
2829a3c295eSpooka 	pid_t cpid;
283*dd9a3758Sgson 	int sent, succ, i;
2849a3c295eSpooka 
2859a3c295eSpooka 	cpid = fork();
2869a3c295eSpooka 	rump_init();
2879a3c295eSpooka 	netcfg_rump_makeshmif("jippikaiee", ifname);
2889a3c295eSpooka 
2899a3c295eSpooka 	switch (cpid) {
2909a3c295eSpooka 	case -1:
2919a3c295eSpooka 		atf_tc_fail_errno("fork failed");
2929a3c295eSpooka 	case 0:
2939a3c295eSpooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
2949a3c295eSpooka 		pause();
2959a3c295eSpooka 		break;
2969a3c295eSpooka 	default:
2979a3c295eSpooka 		break;
2989a3c295eSpooka 	}
2999a3c295eSpooka 
3009a3c295eSpooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
3019a3c295eSpooka 
302*dd9a3758Sgson 	succ = sent = 0;
30375487b05Spooka 
3049a3c295eSpooka 	/* small sizes */
305*dd9a3758Sgson 	for (i = 0 ; i < IP_MAXPACKET - 60000; i++) {
306*dd9a3758Sgson 		sent++;
3079a3c295eSpooka 		succ += doping("1.1.1.10", 1, i);
308*dd9a3758Sgson 	}
30975487b05Spooka 
3109a3c295eSpooka 	/* medium sizes */
311*dd9a3758Sgson 	for (i = IP_MAXPACKET - 60000; i < IP_MAXPACKET - 100; i += 1000) {
312*dd9a3758Sgson 		sent++;
3139a3c295eSpooka 		succ += doping("1.1.1.10", 1, i);
314*dd9a3758Sgson 	}
3159a3c295eSpooka 
3169a3c295eSpooka 	/* big sizes */
317*dd9a3758Sgson 	for (i = IP_MAXPACKET - 100; i < IP_MAXPACKET; i += 10) {
318*dd9a3758Sgson 		sent++;
3199a3c295eSpooka 		succ += doping("1.1.1.10", 1, i);
320*dd9a3758Sgson 	}
3219a3c295eSpooka 
322*dd9a3758Sgson 	printf("got %d/%d\n", succ, sent);
32375487b05Spooka 	kill(cpid, SIGKILL);
32475487b05Spooka }
32575487b05Spooka 
326b3495eccSpooka ATF_TC(ping_of_death);
ATF_TC_HEAD(ping_of_death,tc)327b3495eccSpooka ATF_TC_HEAD(ping_of_death, tc)
328b3495eccSpooka {
329b3495eccSpooka 
330b3495eccSpooka 	atf_tc_set_md_var(tc, "descr", "send a \"ping of death\"");
33188c71eddSmartin 	atf_tc_set_md_var(tc, "timeout", "20");
332b3495eccSpooka }
333b3495eccSpooka 
ATF_TC_BODY(ping_of_death,tc)334b3495eccSpooka ATF_TC_BODY(ping_of_death, tc)
335b3495eccSpooka {
336b3495eccSpooka 	char data[1500];
337b3495eccSpooka 	struct sockaddr_in dst;
338b3495eccSpooka 	struct ip *ip;
339b3495eccSpooka 	struct icmp *icmp;
340b3495eccSpooka 	char ifname[IFNAMSIZ];
341b3495eccSpooka 	pid_t cpid;
342b3495eccSpooka 	size_t tot, frag;
34364785daaSroy 	int s, x, loop;
34464785daaSroy 	ssize_t error;
345b3495eccSpooka 
346b3495eccSpooka 	cpid = fork();
347b3495eccSpooka 	rump_init();
348b3495eccSpooka 	netcfg_rump_makeshmif("jippikaiee", ifname);
349b3495eccSpooka 
350b3495eccSpooka 	switch (cpid) {
351b3495eccSpooka 	case -1:
352b3495eccSpooka 		atf_tc_fail_errno("fork failed");
353b3495eccSpooka 	case 0:
354b3495eccSpooka 		/* wait until we receive a too long IP packet */
355b3495eccSpooka 		for (loop = 0;; loop++) {
356b3495eccSpooka 			uint64_t ipstat[IP_NSTATS];
357b3495eccSpooka 			size_t arglen;
358b3495eccSpooka 			int mib[4];
359b3495eccSpooka 
360b3495eccSpooka 			if (loop == 1)
361b3495eccSpooka 				netcfg_rump_if(ifname,
362b3495eccSpooka 				    "1.1.1.10", "255.255.255.0");
363b3495eccSpooka 
364b3495eccSpooka 			mib[0] = CTL_NET;
365b3495eccSpooka 			mib[1] = PF_INET;
366b3495eccSpooka 			mib[2] = IPPROTO_IP;
367b3495eccSpooka 			mib[3] = IPCTL_STATS;
368b3495eccSpooka 
369b3495eccSpooka 			arglen = sizeof(ipstat);
370b3495eccSpooka 			RL(rump_sys___sysctl(mib, 4, &ipstat, &arglen,
371b3495eccSpooka 			    NULL, 0));
372b3495eccSpooka 			if (loop == 0 && ipstat[IP_STAT_TOOLONG] != 0)
373b3495eccSpooka 				_exit(1);
374b3495eccSpooka 			if (ipstat[IP_STAT_TOOLONG])
375b3495eccSpooka 				break;
376b3495eccSpooka 			usleep(10000);
377b3495eccSpooka 		}
378b3495eccSpooka 
379b3495eccSpooka 		_exit(0);
380b3495eccSpooka 		break;
381b3495eccSpooka 	default:
382b3495eccSpooka 		break;
383b3495eccSpooka 	}
384b3495eccSpooka 
385b3495eccSpooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
386b3495eccSpooka 
387b3495eccSpooka 	RL(s = rump_sys_socket(PF_INET, SOCK_RAW, 0));
388b3495eccSpooka 	x = 1;
389b3495eccSpooka 	RL(rump_sys_setsockopt(s, IPPROTO_IP, IP_HDRINCL, &x, sizeof(x)));
390b3495eccSpooka 
391b3495eccSpooka 	memset(&dst, 0, sizeof(dst));
392b3495eccSpooka 	dst.sin_len = sizeof(dst);
393b3495eccSpooka 	dst.sin_family = AF_INET;
394b3495eccSpooka 	dst.sin_addr.s_addr = inet_addr("1.1.1.10");
395b3495eccSpooka 
396b3495eccSpooka 	/* construct packet */
397b3495eccSpooka 	memset(data, 0, sizeof(data));
398b3495eccSpooka 	ip = (struct ip *)data;
399b3495eccSpooka 	ip->ip_v = 4;
400b3495eccSpooka 	ip->ip_hl = sizeof(*ip) >> 2;
401b3495eccSpooka 	ip->ip_p = IPPROTO_ICMP;
402b3495eccSpooka 	ip->ip_ttl = IPDEFTTL;
403b3495eccSpooka 	ip->ip_dst = dst.sin_addr;
404b3495eccSpooka 	ip->ip_id = 1234;
405b3495eccSpooka 
406b3495eccSpooka 	icmp = (struct icmp *)(ip + 1);
407b3495eccSpooka 	icmp->icmp_type = ICMP_ECHO;
408b3495eccSpooka 	icmp->icmp_cksum = in_cksum(icmp, sizeof(*icmp));
409b3495eccSpooka 
410b3495eccSpooka 	for (;;) {
411b3495eccSpooka 		int status;
412b3495eccSpooka 
413b3495eccSpooka 		/* resolve arp before sending raw stuff */
414b3495eccSpooka 		netcfg_rump_pingtest("1.1.1.10", 1);
415b3495eccSpooka 
416b3495eccSpooka 		for (tot = 0;
417b3495eccSpooka 		    tot < 65538 - sizeof(*ip);
418b3495eccSpooka 		    tot += (frag - sizeof(*ip))) {
419b3495eccSpooka 			frag = MIN(65538 - tot, sizeof(data));
420b3495eccSpooka 			ip->ip_off = tot >> 3;
4210f10aa9dSchristos 			assert((size_t)ip->ip_off << 3 == tot);
422b3495eccSpooka 			ip->ip_len = frag;
423b3495eccSpooka 
424b3495eccSpooka 			if (frag == sizeof(data)) {
425b3495eccSpooka 				ip->ip_off |= IP_MF;
426b3495eccSpooka 			}
427b3495eccSpooka 
42880b75699Sroy 			error = rump_sys_sendto(s, data, frag, 0,
42980b75699Sroy 			    (struct sockaddr *)&dst, sizeof(dst));
43064785daaSroy 			if (error == -1) {
43164785daaSroy 				if (errno == ENOBUFS)
43280b75699Sroy 					continue;
43380b75699Sroy 				atf_tc_fail_errno("sendto failed");
434b3495eccSpooka 			}
43564785daaSroy 			if ((size_t)error != frag)
43664785daaSroy 				atf_tc_fail("sendto did not write all data");
43764785daaSroy 		}
438b3495eccSpooka 		if (waitpid(-1, &status, WNOHANG) > 0) {
439b3495eccSpooka 			if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
440b3495eccSpooka 				break;
441b3495eccSpooka 			atf_tc_fail("child did not exit clean");
442b3495eccSpooka 		}
443b3495eccSpooka 
444b3495eccSpooka 		usleep(10000);
445b3495eccSpooka 	}
446b3495eccSpooka }
447b3495eccSpooka 
ATF_TP_ADD_TCS(tp)44896f76684Spooka ATF_TP_ADD_TCS(tp)
44996f76684Spooka {
45096f76684Spooka 
45196f76684Spooka 	ATF_TP_ADD_TC(tp, simpleping);
45275487b05Spooka 	ATF_TP_ADD_TC(tp, floodping);
4539a3c295eSpooka 	ATF_TP_ADD_TC(tp, floodping2);
4549a3c295eSpooka 	ATF_TP_ADD_TC(tp, pingsize);
455b3495eccSpooka 	ATF_TP_ADD_TC(tp, ping_of_death);
45696f76684Spooka 
45796f76684Spooka 	return atf_no_error();
45896f76684Spooka }
459