xref: /netbsd-src/tests/net/if_loop/t_pr.c (revision 1a9a81992d29fa1ebe387b8059e482fa3d394fb8)
1 /*	$NetBSD: t_pr.c,v 1.5 2011/04/10 11:31:48 martin Exp $	*/
2 
3 /*-
4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 #ifndef lint
32 __RCSID("$NetBSD: t_pr.c,v 1.5 2011/04/10 11:31:48 martin Exp $");
33 #endif /* not lint */
34 
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 
39 #include <netinet/in.h>
40 #include <net/route.h>
41 
42 #include <rump/rump.h>
43 #include <rump/rump_syscalls.h>
44 
45 #include <atf-c.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 
52 #include "../config/netconfig.c"
53 #include "../../h_macros.h"
54 
55 /*
56  * Prepare rump server, configure interface and route to cause fragmentation
57  */
58 static void
59 setup(void)
60 {
61 	char ifname[IFNAMSIZ];
62 	struct {
63 		struct rt_msghdr m_rtm;
64 		struct sockaddr_in m_sin;
65 	} m_rtmsg;
66 #define rtm m_rtmsg.m_rtm
67 #define rsin m_rtmsg.m_sin
68 	struct ifreq ifr;
69 	int s;
70 
71 	static bool init_done = false;
72 	if (init_done) return;
73 
74 	strcpy(ifname, "lo0");
75 	rump_init();
76 
77 	/* first, config lo0 & route */
78 	netcfg_rump_if(ifname, "127.0.0.1", "255.0.0.0");
79 	netcfg_rump_route("127.0.0.1", "255.0.0.0", "127.0.0.1");
80 
81 	if ((s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
82 		atf_tc_fail_errno("routing socket");
83 
84 	/*
85 	 * set MTU for interface so that route MTU doesn't
86 	 * get overridden by it.
87 	 */
88 	memset(&ifr, 0, sizeof(ifr));
89 	strcpy(ifr.ifr_name, "lo0");
90 	ifr.ifr_mtu = 1300;
91 	if (rump_sys_ioctl(s, SIOCSIFMTU, &ifr) == -1)
92 		atf_tc_fail_errno("set mtu");
93 
94 	/* change route MTU to 100 */
95 	memset(&m_rtmsg, 0, sizeof(m_rtmsg));
96 	rtm.rtm_type = RTM_CHANGE;
97 	rtm.rtm_flags = RTF_STATIC;
98 	rtm.rtm_version = RTM_VERSION;
99 	rtm.rtm_seq = 3;
100 	rtm.rtm_inits = RTV_MTU;
101 	rtm.rtm_addrs = RTA_DST;
102 	rtm.rtm_rmx.rmx_mtu = 100;
103 	rtm.rtm_msglen = sizeof(m_rtmsg);
104 
105 	memset(&rsin, 0, sizeof(rsin));
106 	rsin.sin_family = AF_INET;
107 	rsin.sin_len = sizeof(rsin);
108 	rsin.sin_addr.s_addr = inet_addr("127.0.0.1");
109 
110 	if (rump_sys_write(s, &m_rtmsg, sizeof(m_rtmsg)) != sizeof(m_rtmsg))
111 		atf_tc_fail_errno("set route mtu");
112 	rump_sys_close(s);
113 
114 	init_done = true;
115 }
116 
117 /*
118  * Turn on checksums on loopback interfaces
119  */
120 static int
121 enable_locsums(void)
122 {
123 	struct sysctlnode q, ans[256];
124 	int mib[5], enable;
125 	size_t alen;
126 	unsigned i;
127 
128 	mib[0] = CTL_NET;
129 	mib[1] = PF_INET;
130 	mib[2] = IPPROTO_IP;
131 	mib[3] = CTL_QUERY;
132 	alen = sizeof(ans);
133 
134 	memset(&q, 0, sizeof(q));
135 	q.sysctl_flags = SYSCTL_VERSION;
136 
137 	if (rump_sys___sysctl(mib, 4, ans, &alen, &q, sizeof(q)) == -1)
138 		return -1;
139 
140 	for (i = 0; i < __arraycount(ans); i++)
141 		if (strcmp("do_loopback_cksum", ans[i].sysctl_name) == 0)
142 			break;
143 	if (i == __arraycount(ans)) {
144 		errno = ENOENT;
145 		return -1;
146 	}
147 
148 	mib[3] = ans[i].sysctl_num;
149 
150 	enable = 1;
151 	if (rump_sys___sysctl(mib, 4, NULL, NULL, &enable,
152 	    sizeof(enable)) == -1)
153 		return errno;
154 
155 	return 0;
156 }
157 
158 ATF_TC(loopmtu);
159 ATF_TC_HEAD(loopmtu, tc)
160 {
161 
162 	atf_tc_set_md_var(tc, "descr", "test lo0 fragmentation");
163 	/* PR kern/43664 */
164 }
165 
166 ATF_TC_BODY(loopmtu, tc)
167 {
168 	struct sockaddr_in sin;
169 	char data[2000];
170 	int s;
171 
172 	setup();
173 
174 	/* open raw socket */
175 	s = rump_sys_socket(PF_INET, SOCK_RAW, 0);
176 	if (s == -1)
177 		atf_tc_fail_errno("raw socket");
178 
179 	/* then, send data */
180 	memset(&sin, 0, sizeof(sin));
181 	sin.sin_family = AF_INET;
182 	sin.sin_len = sizeof(sin);
183 	sin.sin_port = htons(12345);
184 	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
185 
186 	/*
187 	 * Should not fail anymore, PR has been fixed...
188 	 *
189 	 * atf_tc_expect_signal(SIGABRT, "PR kern/43664");
190 	 */
191 	if (rump_sys_sendto(s, data, sizeof(data), 0,
192 	    (struct sockaddr *)&sin, sizeof(sin)) == -1)
193 		atf_tc_fail_errno("sendto failed");
194 }
195 
196 ATF_TC(loopmtu_csum);
197 ATF_TC_HEAD(loopmtu_csum, tc)
198 {
199 
200 	atf_tc_set_md_var(tc, "descr", "test lo0 fragmentation with checksums");
201 	/* PR kern/43664 */
202 }
203 
204 ATF_TC_BODY(loopmtu_csum, tc)
205 {
206 	struct sockaddr_in sin;
207 	char data[2000];
208 	int s;
209 
210 	setup();
211 
212 	ATF_CHECK(enable_locsums() == 0);
213 
214 	/* open raw socket */
215 	s = rump_sys_socket(PF_INET, SOCK_RAW, 0);
216 	if (s == -1)
217 		atf_tc_fail_errno("raw socket");
218 
219 	/* then, send data */
220 	memset(&sin, 0, sizeof(sin));
221 	sin.sin_family = AF_INET;
222 	sin.sin_len = sizeof(sin);
223 	sin.sin_port = htons(12345);
224 	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
225 
226 	/*
227 	 * Should not fail anymore, PR has been fixed...
228 	 *
229 	 * atf_tc_expect_signal(SIGABRT, "PR kern/43664");
230 	 */
231 	if (rump_sys_sendto(s, data, sizeof(data), 0,
232 	    (struct sockaddr *)&sin, sizeof(sin)) == -1)
233 		atf_tc_fail_errno("sendto failed");
234 }
235 
236 ATF_TP_ADD_TCS(tp)
237 {
238 
239 	ATF_TP_ADD_TC(tp, loopmtu);
240 	ATF_TP_ADD_TC(tp, loopmtu_csum);
241 
242 	return atf_no_error();
243 }
244 
245