1314818Sngie/* $NetBSD: t_pr.c,v 1.8 2017/01/13 21:30:42 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17272343Sngie * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18272343Sngie * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19272343Sngie * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20272343Sngie * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21272343Sngie * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23272343Sngie * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25272343Sngie * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26272343Sngie * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27272343Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28272343Sngie */ 29272343Sngie 30272343Sngie#include <sys/cdefs.h> 31272343Sngie#ifndef lint 32314818Sngie__RCSID("$NetBSD: t_pr.c,v 1.8 2017/01/13 21:30:42 christos Exp $"); 33272343Sngie#endif /* not lint */ 34272343Sngie 35272343Sngie#include <sys/types.h> 36272343Sngie#include <sys/socket.h> 37272343Sngie#include <sys/sysctl.h> 38272343Sngie 39272343Sngie#include <netinet/in.h> 40272343Sngie#include <net/route.h> 41272343Sngie 42272343Sngie#include <rump/rump.h> 43272343Sngie#include <rump/rump_syscalls.h> 44272343Sngie 45272343Sngie#include <atf-c.h> 46272343Sngie#include <errno.h> 47272343Sngie#include <stdio.h> 48272343Sngie#include <stdlib.h> 49272343Sngie#include <string.h> 50272343Sngie#include <unistd.h> 51272343Sngie 52272343Sngie#include "../config/netconfig.c" 53314818Sngie#include "h_macros.h" 54272343Sngie 55272343Sngie/* 56272343Sngie * Prepare rump, configure interface and route to cause fragmentation 57272343Sngie */ 58272343Sngiestatic void 59272343Sngiesetup(void) 60272343Sngie{ 61272343Sngie char ifname[IFNAMSIZ]; 62272343Sngie struct { 63272343Sngie struct rt_msghdr m_rtm; 64272343Sngie struct sockaddr_in m_sin; 65272343Sngie } m_rtmsg; 66272343Sngie#define rtm m_rtmsg.m_rtm 67272343Sngie#define rsin m_rtmsg.m_sin 68272343Sngie struct ifreq ifr; 69272343Sngie int s; 70272343Sngie 71272343Sngie rump_init(); 72272343Sngie 73272343Sngie /* first, config lo0 & route */ 74272343Sngie strcpy(ifname, "lo0"); 75272343Sngie netcfg_rump_if(ifname, "127.0.0.1", "255.0.0.0"); 76272343Sngie netcfg_rump_route("127.0.0.1", "255.0.0.0", "127.0.0.1"); 77272343Sngie 78272343Sngie if ((s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 79272343Sngie atf_tc_fail_errno("routing socket"); 80272343Sngie 81272343Sngie /* 82272343Sngie * set MTU for interface so that route MTU doesn't 83272343Sngie * get overridden by it. 84272343Sngie */ 85272343Sngie memset(&ifr, 0, sizeof(ifr)); 86272343Sngie strcpy(ifr.ifr_name, "lo0"); 87272343Sngie ifr.ifr_mtu = 1300; 88272343Sngie if (rump_sys_ioctl(s, SIOCSIFMTU, &ifr) == -1) 89272343Sngie atf_tc_fail_errno("set mtu"); 90272343Sngie 91272343Sngie /* change route MTU to 100 */ 92272343Sngie memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 93272343Sngie rtm.rtm_type = RTM_CHANGE; 94272343Sngie rtm.rtm_flags = RTF_STATIC; 95272343Sngie rtm.rtm_version = RTM_VERSION; 96272343Sngie rtm.rtm_seq = 3; 97272343Sngie rtm.rtm_inits = RTV_MTU; 98272343Sngie rtm.rtm_addrs = RTA_DST; 99272343Sngie rtm.rtm_rmx.rmx_mtu = 100; 100272343Sngie rtm.rtm_msglen = sizeof(m_rtmsg); 101272343Sngie 102272343Sngie memset(&rsin, 0, sizeof(rsin)); 103272343Sngie rsin.sin_family = AF_INET; 104272343Sngie rsin.sin_len = sizeof(rsin); 105272343Sngie rsin.sin_addr.s_addr = inet_addr("127.0.0.1"); 106272343Sngie 107272343Sngie if (rump_sys_write(s, &m_rtmsg, sizeof(m_rtmsg)) != sizeof(m_rtmsg)) 108272343Sngie atf_tc_fail_errno("set route mtu"); 109272343Sngie rump_sys_close(s); 110272343Sngie} 111272343Sngie 112272343Sngie/* 113272343Sngie * Turn on checksums on loopback interfaces 114272343Sngie */ 115272343Sngiestatic int 116272343Sngieenable_locsums(void) 117272343Sngie{ 118272343Sngie struct sysctlnode q, ans[256]; 119272343Sngie int mib[5], enable; 120272343Sngie size_t alen; 121272343Sngie unsigned i; 122272343Sngie 123272343Sngie mib[0] = CTL_NET; 124272343Sngie mib[1] = PF_INET; 125272343Sngie mib[2] = IPPROTO_IP; 126272343Sngie mib[3] = CTL_QUERY; 127272343Sngie alen = sizeof(ans); 128272343Sngie 129272343Sngie memset(&q, 0, sizeof(q)); 130272343Sngie q.sysctl_flags = SYSCTL_VERSION; 131272343Sngie 132272343Sngie if (rump_sys___sysctl(mib, 4, ans, &alen, &q, sizeof(q)) == -1) 133272343Sngie return -1; 134272343Sngie 135272343Sngie for (i = 0; i < __arraycount(ans); i++) 136272343Sngie if (strcmp("do_loopback_cksum", ans[i].sysctl_name) == 0) 137272343Sngie break; 138272343Sngie if (i == __arraycount(ans)) { 139272343Sngie errno = ENOENT; 140272343Sngie return -1; 141272343Sngie } 142272343Sngie 143272343Sngie mib[3] = ans[i].sysctl_num; 144272343Sngie 145272343Sngie enable = 1; 146272343Sngie if (rump_sys___sysctl(mib, 4, NULL, NULL, &enable, 147272343Sngie sizeof(enable)) == -1) 148272343Sngie return errno; 149272343Sngie 150272343Sngie return 0; 151272343Sngie} 152272343Sngie 153272343SngieATF_TC(loopmtu); 154272343SngieATF_TC_HEAD(loopmtu, tc) 155272343Sngie{ 156272343Sngie 157272343Sngie atf_tc_set_md_var(tc, "descr", 158272343Sngie "test lo0 fragmentation (PR kern/43664)"); 159272343Sngie} 160272343Sngie 161272343SngieATF_TC_BODY(loopmtu, tc) 162272343Sngie{ 163272343Sngie struct sockaddr_in sin; 164272343Sngie char data[2000]; 165272343Sngie int s; 166272343Sngie 167272343Sngie setup(); 168272343Sngie 169272343Sngie /* open raw socket */ 170272343Sngie s = rump_sys_socket(PF_INET, SOCK_RAW, 0); 171272343Sngie if (s == -1) 172272343Sngie atf_tc_fail_errno("raw socket"); 173272343Sngie 174272343Sngie /* then, send data */ 175272343Sngie memset(&sin, 0, sizeof(sin)); 176272343Sngie sin.sin_family = AF_INET; 177272343Sngie sin.sin_len = sizeof(sin); 178272343Sngie sin.sin_port = htons(12345); 179272343Sngie sin.sin_addr.s_addr = inet_addr("127.0.0.1"); 180272343Sngie 181272343Sngie if (rump_sys_sendto(s, data, sizeof(data), 0, 182272343Sngie (struct sockaddr *)&sin, sizeof(sin)) == -1) 183272343Sngie atf_tc_fail_errno("sendto failed"); 184272343Sngie} 185272343Sngie 186272343SngieATF_TC(loopmtu_csum); 187272343SngieATF_TC_HEAD(loopmtu_csum, tc) 188272343Sngie{ 189272343Sngie 190272343Sngie atf_tc_set_md_var(tc, "descr", 191272343Sngie "test lo0 fragmentation with checksums (PR kern/43664)"); 192272343Sngie} 193272343Sngie 194272343SngieATF_TC_BODY(loopmtu_csum, tc) 195272343Sngie{ 196272343Sngie struct sockaddr_in sin; 197272343Sngie char data[2000]; 198272343Sngie int s; 199272343Sngie 200272343Sngie setup(); 201272343Sngie 202272343Sngie ATF_CHECK(enable_locsums() == 0); 203272343Sngie 204272343Sngie /* open raw socket */ 205272343Sngie s = rump_sys_socket(PF_INET, SOCK_RAW, 0); 206272343Sngie if (s == -1) 207272343Sngie atf_tc_fail_errno("raw socket"); 208272343Sngie 209272343Sngie /* then, send data */ 210272343Sngie memset(&sin, 0, sizeof(sin)); 211272343Sngie sin.sin_family = AF_INET; 212272343Sngie sin.sin_len = sizeof(sin); 213272343Sngie sin.sin_port = htons(12345); 214272343Sngie sin.sin_addr.s_addr = inet_addr("127.0.0.1"); 215272343Sngie 216272343Sngie if (rump_sys_sendto(s, data, sizeof(data), 0, 217272343Sngie (struct sockaddr *)&sin, sizeof(sin)) == -1) 218272343Sngie atf_tc_fail_errno("sendto failed"); 219272343Sngie} 220272343Sngie 221272343SngieATF_TP_ADD_TCS(tp) 222272343Sngie{ 223272343Sngie 224272343Sngie ATF_TP_ADD_TC(tp, loopmtu); 225272343Sngie ATF_TP_ADD_TC(tp, loopmtu_csum); 226272343Sngie 227272343Sngie return atf_no_error(); 228272343Sngie} 229272343Sngie 230