Home | History | Annotate | Line # | Download | only in icmp
      1  1.24      gson /*	$NetBSD: t_ping.c,v 1.24 2019/06/11 08:34:01 gson Exp $	*/
      2   1.1     pooka 
      3   1.1     pooka /*-
      4   1.1     pooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5   1.1     pooka  * All rights reserved.
      6   1.1     pooka  *
      7   1.1     pooka  * Redistribution and use in source and binary forms, with or without
      8   1.1     pooka  * modification, are permitted provided that the following conditions
      9   1.1     pooka  * are met:
     10   1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     11   1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     12   1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     14   1.1     pooka  *    documentation and/or other materials provided with the distribution.
     15   1.1     pooka  *
     16   1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17   1.1     pooka  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18   1.1     pooka  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19   1.1     pooka  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20   1.1     pooka  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21   1.1     pooka  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22   1.1     pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23   1.1     pooka  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24   1.1     pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25   1.1     pooka  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26   1.1     pooka  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27   1.1     pooka  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28   1.1     pooka  */
     29   1.1     pooka 
     30   1.1     pooka #include <sys/cdefs.h>
     31   1.1     pooka #ifndef lint
     32  1.24      gson __RCSID("$NetBSD: t_ping.c,v 1.24 2019/06/11 08:34:01 gson Exp $");
     33   1.1     pooka #endif /* not lint */
     34   1.1     pooka 
     35   1.1     pooka #include <sys/types.h>
     36   1.2     pooka #include <sys/resource.h>
     37   1.5     pooka #include <sys/sysctl.h>
     38   1.5     pooka #include <sys/wait.h>
     39   1.1     pooka 
     40   1.1     pooka #include <atf-c.h>
     41   1.5     pooka #include <assert.h>
     42   1.2     pooka #include <fcntl.h>
     43   1.1     pooka #include <stdio.h>
     44   1.1     pooka #include <stdlib.h>
     45   1.1     pooka #include <string.h>
     46   1.1     pooka #include <unistd.h>
     47  1.14  christos #include <signal.h>
     48   1.1     pooka 
     49   1.5     pooka #include <netinet/in.h>
     50   1.5     pooka #include <netinet/ip_var.h>
     51   1.5     pooka 
     52   1.1     pooka #include <rump/rump.h>
     53   1.5     pooka #include <rump/rump_syscalls.h>
     54   1.1     pooka 
     55  1.17  christos #include "h_macros.h"
     56   1.1     pooka #include "../config/netconfig.c"
     57   1.1     pooka 
     58   1.1     pooka ATF_TC(simpleping);
     59   1.1     pooka ATF_TC_HEAD(simpleping, tc)
     60   1.1     pooka {
     61   1.1     pooka 
     62   1.1     pooka 	atf_tc_set_md_var(tc, "descr", "check that kernel responds to ping");
     63  1.16    martin 	atf_tc_set_md_var(tc, "timeout", "20");
     64   1.1     pooka }
     65   1.1     pooka 
     66   1.1     pooka ATF_TC_BODY(simpleping, tc)
     67   1.1     pooka {
     68   1.1     pooka 	char ifname[IFNAMSIZ];
     69   1.1     pooka 	pid_t cpid;
     70   1.1     pooka 	bool win, win2;
     71  1.15     alnsn 	char token;
     72  1.15     alnsn 	int channel[2];
     73  1.15     alnsn 
     74  1.15     alnsn 	RL(pipe(channel));
     75   1.1     pooka 
     76   1.1     pooka 	cpid = fork();
     77   1.1     pooka 	rump_init();
     78   1.1     pooka 	netcfg_rump_makeshmif("but-can-i-buy-your-ether-bus", ifname);
     79   1.1     pooka 
     80   1.1     pooka 	switch (cpid) {
     81   1.1     pooka 	case -1:
     82   1.1     pooka 		atf_tc_fail_errno("fork failed");
     83   1.1     pooka 	case 0:
     84   1.1     pooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
     85  1.15     alnsn 		close(channel[0]);
     86  1.15     alnsn 		ATF_CHECK(write(channel[1], "U", 1) == 1);
     87  1.15     alnsn 		close(channel[1]);
     88   1.1     pooka 		pause();
     89   1.1     pooka 		break;
     90   1.1     pooka 	default:
     91   1.1     pooka 		break;
     92   1.1     pooka 	}
     93   1.1     pooka 
     94  1.15     alnsn 	close(channel[1]);
     95  1.15     alnsn 	ATF_CHECK(read(channel[0], &token, 1) == 1 && token == 'U');
     96  1.15     alnsn 	close(channel[0]);
     97   1.7     pooka 
     98   1.1     pooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
     99   1.1     pooka 
    100   1.1     pooka 	/*
    101   1.1     pooka 	 * The beauty of shmif is that we don't have races here.
    102   1.1     pooka 	 */
    103   1.1     pooka 	win = netcfg_rump_pingtest("1.1.1.10", 500);
    104   1.1     pooka 	win2 = netcfg_rump_pingtest("1.1.1.30", 500);
    105   1.1     pooka 
    106   1.1     pooka 	kill(cpid, SIGKILL);
    107   1.1     pooka 
    108   1.1     pooka 	if (!win)
    109   1.1     pooka 		atf_tc_fail("ping failed");
    110   1.1     pooka 	if (win2)
    111   1.1     pooka 		atf_tc_fail("non-existent host responded");
    112   1.1     pooka }
    113   1.1     pooka 
    114   1.2     pooka ATF_TC(floodping);
    115   1.2     pooka ATF_TC_HEAD(floodping, tc)
    116   1.2     pooka {
    117   1.2     pooka 
    118   1.2     pooka 	atf_tc_set_md_var(tc, "descr", "see how kernel responds to floodping");
    119   1.2     pooka }
    120   1.2     pooka 
    121   1.3     pooka /* why the hell isn't this available in userspace??? */
    122   1.3     pooka static uint16_t
    123   1.3     pooka in_cksum(void *data, size_t len)
    124   1.3     pooka {
    125   1.3     pooka 	uint16_t *buf = data;
    126   1.3     pooka 	unsigned sum;
    127   1.3     pooka 
    128   1.3     pooka 	for (sum = 0; len > 1; len -= 2)
    129   1.3     pooka 		sum += *buf++;
    130   1.3     pooka 	if (len)
    131   1.3     pooka 		sum += *(uint8_t *)buf;
    132   1.3     pooka 
    133   1.3     pooka 	sum = (sum >> 16) + (sum & 0xffff);
    134   1.3     pooka 	sum += (sum >> 16);
    135   1.3     pooka 
    136   1.3     pooka 	return ~sum;
    137   1.3     pooka }
    138   1.3     pooka 
    139   1.3     pooka static int
    140  1.10  christos doping(const char *target, int loops, u_int pktsize)
    141   1.2     pooka {
    142  1.12    martin 	union {
    143  1.12    martin 		char buf[IP_MAXPACKET - sizeof(struct ip)];
    144  1.12    martin 		struct icmp i;	/* ensure proper alignment */
    145  1.12    martin 	} sndbuf;
    146   1.3     pooka 	char recvbuf[IP_MAXPACKET];
    147   1.2     pooka 	struct sockaddr_in dst, pingee;
    148   1.3     pooka 	struct icmp *icmp;
    149   1.2     pooka 	socklen_t slen;
    150   1.2     pooka 	ssize_t n;
    151   1.9  christos 	int loop, succ;
    152   1.2     pooka 	int x, xnon, s;
    153   1.2     pooka 
    154   1.3     pooka 	RL(s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP));
    155   1.3     pooka 	RL(x = rump_sys_fcntl(s, F_GETFL, 0));
    156   1.3     pooka 	xnon = x | O_NONBLOCK;
    157   1.3     pooka 
    158   1.3     pooka 	memset(&dst, 0, sizeof(dst));
    159   1.3     pooka 	dst.sin_len = sizeof(dst);
    160   1.3     pooka 	dst.sin_family = AF_INET;
    161   1.3     pooka 	dst.sin_addr.s_addr = inet_addr(target);
    162   1.3     pooka 
    163  1.12    martin 	icmp = (struct icmp *)&sndbuf;
    164   1.3     pooka 	memset(icmp, 0, sizeof(*icmp));
    165   1.3     pooka 	icmp->icmp_type = ICMP_ECHO;
    166   1.3     pooka 	icmp->icmp_id = htons(37);
    167   1.3     pooka 
    168   1.3     pooka 	if (pktsize < sizeof(*icmp))
    169   1.3     pooka 		pktsize = sizeof(*icmp);
    170  1.13    martin 	if (pktsize > sizeof(sndbuf.buf))
    171  1.13    martin 		pktsize = sizeof(sndbuf.buf);
    172   1.3     pooka 
    173   1.3     pooka 	RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_SNDBUF,
    174   1.3     pooka 	    &pktsize, sizeof(pktsize)));
    175   1.3     pooka 	RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVBUF,
    176   1.3     pooka 	    &pktsize, sizeof(pktsize)));
    177   1.3     pooka 
    178   1.3     pooka 	slen = sizeof(pingee);
    179   1.3     pooka 	succ = 0;
    180   1.3     pooka 	for (loop = 0; loop < loops; loop++) {
    181   1.3     pooka 		RL(rump_sys_fcntl(s, F_SETFL, x));
    182   1.3     pooka 		icmp->icmp_seq = htons(loop);
    183   1.3     pooka 		icmp->icmp_cksum = 0;
    184   1.3     pooka 		icmp->icmp_cksum = in_cksum(icmp, pktsize);
    185  1.19       roy 
    186  1.19       roy 		n = rump_sys_sendto(s, icmp, pktsize, 0,
    187  1.19       roy 		    (struct sockaddr *)&dst, sizeof(dst));
    188  1.19       roy 		if (n == -1) {
    189  1.19       roy 			if (errno == ENOBUFS)
    190  1.19       roy 				continue;
    191  1.19       roy 			atf_tc_fail_errno("sendto failed");
    192  1.19       roy 		}
    193   1.3     pooka 
    194   1.3     pooka 		RL(rump_sys_fcntl(s, F_SETFL, xnon));
    195   1.3     pooka 		while ((n = rump_sys_recvfrom(s, recvbuf, sizeof(recvbuf), 0,
    196   1.3     pooka 		    (struct sockaddr *)&pingee, &slen)) > 0) {
    197   1.3     pooka 			succ++;
    198   1.3     pooka 		}
    199  1.18       roy 		if (n == -1 && (errno == EAGAIN || errno == ENOBUFS))
    200   1.3     pooka 			continue;
    201  1.21     kamil 		atf_tc_fail_errno("recv failed (n == %zd)", n);
    202   1.3     pooka 	}
    203   1.3     pooka 
    204   1.3     pooka 	rump_sys_close(s);
    205   1.3     pooka 	return succ;
    206   1.3     pooka }
    207   1.3     pooka 
    208   1.3     pooka #define LOOPS 10000
    209   1.3     pooka 
    210   1.3     pooka ATF_TC_BODY(floodping, tc)
    211   1.3     pooka {
    212   1.3     pooka 	char ifname[IFNAMSIZ];
    213   1.3     pooka 	pid_t cpid;
    214   1.3     pooka 	int succ;
    215   1.3     pooka 
    216   1.2     pooka 	cpid = fork();
    217   1.2     pooka 	rump_init();
    218   1.2     pooka 	netcfg_rump_makeshmif("thank-you-driver-for-getting-me-here", ifname);
    219   1.2     pooka 
    220   1.2     pooka 	switch (cpid) {
    221   1.2     pooka 	case -1:
    222   1.2     pooka 		atf_tc_fail_errno("fork failed");
    223   1.2     pooka 	case 0:
    224   1.2     pooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
    225   1.2     pooka 		pause();
    226   1.2     pooka 		break;
    227   1.2     pooka 	default:
    228   1.2     pooka 		break;
    229   1.2     pooka 	}
    230   1.2     pooka 
    231   1.2     pooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
    232   1.2     pooka 
    233   1.3     pooka 	succ = doping("1.1.1.10", LOOPS, 56);
    234   1.3     pooka 	printf("got %d/%d\n", succ, LOOPS);
    235   1.3     pooka 
    236   1.3     pooka 	kill(cpid, SIGKILL);
    237   1.3     pooka }
    238   1.3     pooka 
    239   1.3     pooka ATF_TC(floodping2);
    240   1.3     pooka ATF_TC_HEAD(floodping2, tc)
    241   1.3     pooka {
    242   1.3     pooka 
    243   1.3     pooka 	atf_tc_set_md_var(tc, "descr", "two hosts floodpinging each other");
    244   1.3     pooka }
    245   1.3     pooka 
    246   1.3     pooka ATF_TC_BODY(floodping2, tc)
    247   1.3     pooka {
    248   1.3     pooka 	char ifname[IFNAMSIZ];
    249   1.3     pooka 	pid_t cpid;
    250   1.3     pooka 	int succ;
    251   1.3     pooka 
    252   1.3     pooka 	cpid = fork();
    253   1.3     pooka 	rump_init();
    254   1.3     pooka 	netcfg_rump_makeshmif("floodping2", ifname);
    255   1.3     pooka 
    256   1.3     pooka 	switch (cpid) {
    257   1.3     pooka 	case -1:
    258   1.3     pooka 		atf_tc_fail_errno("fork failed");
    259   1.3     pooka 	case 0:
    260   1.3     pooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
    261   1.3     pooka 		succ = doping("1.1.1.20", LOOPS, 56);
    262   1.3     pooka 		break;
    263   1.3     pooka 	default:
    264   1.3     pooka 		netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
    265   1.3     pooka 		succ = doping("1.1.1.10", LOOPS, 56);
    266   1.3     pooka 		break;
    267   1.3     pooka 	}
    268   1.3     pooka 
    269   1.3     pooka 	printf("got %d/%d\n", succ, LOOPS);
    270   1.3     pooka }
    271   1.3     pooka 
    272   1.3     pooka ATF_TC(pingsize);
    273   1.3     pooka ATF_TC_HEAD(pingsize, tc)
    274   1.3     pooka {
    275   1.3     pooka 
    276   1.3     pooka 	atf_tc_set_md_var(tc, "descr", "ping with packets min <= size <= max");
    277   1.3     pooka }
    278   1.3     pooka 
    279   1.3     pooka ATF_TC_BODY(pingsize, tc)
    280   1.3     pooka {
    281   1.3     pooka 	char ifname[IFNAMSIZ];
    282   1.3     pooka 	pid_t cpid;
    283  1.24      gson 	int sent, succ, i;
    284   1.3     pooka 
    285   1.3     pooka 	cpid = fork();
    286   1.3     pooka 	rump_init();
    287   1.3     pooka 	netcfg_rump_makeshmif("jippikaiee", ifname);
    288   1.2     pooka 
    289   1.3     pooka 	switch (cpid) {
    290   1.3     pooka 	case -1:
    291   1.3     pooka 		atf_tc_fail_errno("fork failed");
    292   1.3     pooka 	case 0:
    293   1.3     pooka 		netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0");
    294   1.3     pooka 		pause();
    295   1.3     pooka 		break;
    296   1.3     pooka 	default:
    297   1.3     pooka 		break;
    298   1.3     pooka 	}
    299   1.2     pooka 
    300   1.3     pooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
    301   1.2     pooka 
    302  1.24      gson 	succ = sent = 0;
    303   1.2     pooka 
    304   1.3     pooka 	/* small sizes */
    305  1.24      gson 	for (i = 0 ; i < IP_MAXPACKET - 60000; i++) {
    306  1.24      gson 		sent++;
    307   1.3     pooka 		succ += doping("1.1.1.10", 1, i);
    308  1.24      gson 	}
    309   1.3     pooka 
    310   1.3     pooka 	/* medium sizes */
    311  1.24      gson 	for (i = IP_MAXPACKET - 60000; i < IP_MAXPACKET - 100; i += 1000) {
    312  1.24      gson 		sent++;
    313   1.3     pooka 		succ += doping("1.1.1.10", 1, i);
    314  1.24      gson 	}
    315   1.3     pooka 
    316   1.3     pooka 	/* big sizes */
    317  1.24      gson 	for (i = IP_MAXPACKET - 100; i < IP_MAXPACKET; i += 10) {
    318  1.24      gson 		sent++;
    319   1.3     pooka 		succ += doping("1.1.1.10", 1, i);
    320  1.24      gson 	}
    321   1.2     pooka 
    322  1.24      gson 	printf("got %d/%d\n", succ, sent);
    323   1.2     pooka 	kill(cpid, SIGKILL);
    324   1.2     pooka }
    325   1.2     pooka 
    326   1.5     pooka ATF_TC(ping_of_death);
    327   1.5     pooka ATF_TC_HEAD(ping_of_death, tc)
    328   1.5     pooka {
    329   1.5     pooka 
    330   1.5     pooka 	atf_tc_set_md_var(tc, "descr", "send a \"ping of death\"");
    331  1.16    martin 	atf_tc_set_md_var(tc, "timeout", "20");
    332   1.5     pooka }
    333   1.5     pooka 
    334   1.5     pooka ATF_TC_BODY(ping_of_death, tc)
    335   1.5     pooka {
    336   1.5     pooka 	char data[1500];
    337   1.5     pooka 	struct sockaddr_in dst;
    338   1.5     pooka 	struct ip *ip;
    339   1.5     pooka 	struct icmp *icmp;
    340   1.5     pooka 	char ifname[IFNAMSIZ];
    341   1.5     pooka 	pid_t cpid;
    342   1.5     pooka 	size_t tot, frag;
    343  1.23       roy 	int s, x, loop;
    344  1.23       roy 	ssize_t error;
    345   1.5     pooka 
    346   1.5     pooka 	cpid = fork();
    347   1.5     pooka 	rump_init();
    348   1.5     pooka 	netcfg_rump_makeshmif("jippikaiee", ifname);
    349   1.5     pooka 
    350   1.5     pooka 	switch (cpid) {
    351   1.5     pooka 	case -1:
    352   1.5     pooka 		atf_tc_fail_errno("fork failed");
    353   1.5     pooka 	case 0:
    354   1.5     pooka 		/* wait until we receive a too long IP packet */
    355   1.5     pooka 		for (loop = 0;; loop++) {
    356   1.5     pooka 			uint64_t ipstat[IP_NSTATS];
    357   1.5     pooka 			size_t arglen;
    358   1.5     pooka 			int mib[4];
    359   1.5     pooka 
    360   1.5     pooka 			if (loop == 1)
    361   1.5     pooka 				netcfg_rump_if(ifname,
    362   1.5     pooka 				    "1.1.1.10", "255.255.255.0");
    363   1.5     pooka 
    364   1.5     pooka 			mib[0] = CTL_NET;
    365   1.5     pooka 			mib[1] = PF_INET;
    366   1.5     pooka 			mib[2] = IPPROTO_IP;
    367   1.5     pooka 			mib[3] = IPCTL_STATS;
    368   1.5     pooka 
    369   1.5     pooka 			arglen = sizeof(ipstat);
    370   1.5     pooka 			RL(rump_sys___sysctl(mib, 4, &ipstat, &arglen,
    371   1.5     pooka 			    NULL, 0));
    372   1.5     pooka 			if (loop == 0 && ipstat[IP_STAT_TOOLONG] != 0)
    373   1.5     pooka 				_exit(1);
    374   1.5     pooka 			if (ipstat[IP_STAT_TOOLONG])
    375   1.5     pooka 				break;
    376   1.5     pooka 			usleep(10000);
    377   1.5     pooka 		}
    378   1.5     pooka 
    379   1.5     pooka 		_exit(0);
    380   1.5     pooka 		break;
    381   1.5     pooka 	default:
    382   1.5     pooka 		break;
    383   1.5     pooka 	}
    384   1.5     pooka 
    385   1.5     pooka 	netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0");
    386   1.5     pooka 
    387   1.5     pooka 	RL(s = rump_sys_socket(PF_INET, SOCK_RAW, 0));
    388   1.5     pooka 	x = 1;
    389   1.5     pooka 	RL(rump_sys_setsockopt(s, IPPROTO_IP, IP_HDRINCL, &x, sizeof(x)));
    390   1.5     pooka 
    391   1.5     pooka 	memset(&dst, 0, sizeof(dst));
    392   1.5     pooka 	dst.sin_len = sizeof(dst);
    393   1.5     pooka 	dst.sin_family = AF_INET;
    394   1.5     pooka 	dst.sin_addr.s_addr = inet_addr("1.1.1.10");
    395   1.5     pooka 
    396   1.5     pooka 	/* construct packet */
    397   1.5     pooka 	memset(data, 0, sizeof(data));
    398   1.5     pooka 	ip = (struct ip *)data;
    399   1.5     pooka 	ip->ip_v = 4;
    400   1.5     pooka 	ip->ip_hl = sizeof(*ip) >> 2;
    401   1.5     pooka 	ip->ip_p = IPPROTO_ICMP;
    402   1.5     pooka 	ip->ip_ttl = IPDEFTTL;
    403   1.5     pooka 	ip->ip_dst = dst.sin_addr;
    404   1.5     pooka 	ip->ip_id = 1234;
    405   1.5     pooka 
    406   1.5     pooka 	icmp = (struct icmp *)(ip + 1);
    407   1.5     pooka 	icmp->icmp_type = ICMP_ECHO;
    408   1.5     pooka 	icmp->icmp_cksum = in_cksum(icmp, sizeof(*icmp));
    409   1.5     pooka 
    410   1.5     pooka 	for (;;) {
    411   1.5     pooka 		int status;
    412   1.5     pooka 
    413   1.5     pooka 		/* resolve arp before sending raw stuff */
    414   1.5     pooka 		netcfg_rump_pingtest("1.1.1.10", 1);
    415   1.5     pooka 
    416   1.5     pooka 		for (tot = 0;
    417   1.5     pooka 		    tot < 65538 - sizeof(*ip);
    418   1.5     pooka 		    tot += (frag - sizeof(*ip))) {
    419   1.5     pooka 			frag = MIN(65538 - tot, sizeof(data));
    420   1.5     pooka 			ip->ip_off = tot >> 3;
    421   1.9  christos 			assert((size_t)ip->ip_off << 3 == tot);
    422   1.5     pooka 			ip->ip_len = frag;
    423   1.5     pooka 
    424   1.5     pooka 			if (frag == sizeof(data)) {
    425   1.5     pooka 				ip->ip_off |= IP_MF;
    426   1.5     pooka 			}
    427   1.5     pooka 
    428  1.20       roy 			error = rump_sys_sendto(s, data, frag, 0,
    429  1.20       roy 			    (struct sockaddr *)&dst, sizeof(dst));
    430  1.23       roy 			if (error == -1) {
    431  1.23       roy 				if (errno == ENOBUFS)
    432  1.23       roy 					continue;
    433  1.23       roy 				atf_tc_fail_errno("sendto failed");
    434  1.23       roy 			}
    435  1.23       roy 			if ((size_t)error != frag)
    436  1.23       roy 				atf_tc_fail("sendto did not write all data");
    437   1.5     pooka 		}
    438   1.5     pooka 		if (waitpid(-1, &status, WNOHANG) > 0) {
    439   1.5     pooka 			if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
    440   1.5     pooka 				break;
    441   1.5     pooka 			atf_tc_fail("child did not exit clean");
    442   1.5     pooka 		}
    443  1.20       roy 
    444   1.5     pooka 		usleep(10000);
    445   1.5     pooka 	}
    446   1.5     pooka }
    447   1.5     pooka 
    448   1.1     pooka ATF_TP_ADD_TCS(tp)
    449   1.1     pooka {
    450   1.1     pooka 
    451   1.1     pooka 	ATF_TP_ADD_TC(tp, simpleping);
    452   1.2     pooka 	ATF_TP_ADD_TC(tp, floodping);
    453   1.3     pooka 	ATF_TP_ADD_TC(tp, floodping2);
    454   1.3     pooka 	ATF_TP_ADD_TC(tp, pingsize);
    455   1.5     pooka 	ATF_TP_ADD_TC(tp, ping_of_death);
    456   1.1     pooka 
    457   1.1     pooka 	return atf_no_error();
    458   1.1     pooka }
    459