Module Name: src Committed By: pooka Date: Wed Aug 18 21:22:34 UTC 2010
Modified Files: src/tests/net/icmp: t_ping.c Log Message: Add a test for the "ping of death". Declare the test a success when the receiver increases the "ip toolong" stat counter. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/tests/net/icmp/t_ping.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/net/icmp/t_ping.c diff -u src/tests/net/icmp/t_ping.c:1.4 src/tests/net/icmp/t_ping.c:1.5 --- src/tests/net/icmp/t_ping.c:1.4 Wed Aug 18 17:49:03 2010 +++ src/tests/net/icmp/t_ping.c Wed Aug 18 21:22:34 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: t_ping.c,v 1.4 2010/08/18 17:49:03 pooka Exp $ */ +/* $NetBSD: t_ping.c,v 1.5 2010/08/18 21:22:34 pooka Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -29,20 +29,27 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: t_ping.c,v 1.4 2010/08/18 17:49:03 pooka Exp $"); +__RCSID("$NetBSD: t_ping.c,v 1.5 2010/08/18 21:22:34 pooka 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 <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" @@ -293,6 +300,120 @@ 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, "use.fs", "true"); +} + +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(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) { @@ -300,6 +421,7 @@ 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(); }