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