1140348Srwatson/*-
2140348Srwatson * Copyright (c) 2005 Robert N. M. Watson
3140348Srwatson * All rights reserved.
4140348Srwatson *
5140348Srwatson * Redistribution and use in source and binary forms, with or without
6140348Srwatson * modification, are permitted provided that the following conditions
7140348Srwatson * are met:
8140348Srwatson * 1. Redistributions of source code must retain the above copyright
9140348Srwatson *    notice, this list of conditions and the following disclaimer.
10140348Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11140348Srwatson *    notice, this list of conditions and the following disclaimer in the
12140348Srwatson *    documentation and/or other materials provided with the distribution.
13140348Srwatson *
14140348Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15140348Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16140348Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17140348Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18140348Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19140348Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20140348Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21140348Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22140348Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23140348Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24140348Srwatson * SUCH DAMAGE.
25140348Srwatson *
26140348Srwatson * $FreeBSD$
27140348Srwatson */
28140348Srwatson
29140348Srwatson#include <sys/param.h>
30140348Srwatson#include <sys/jail.h>
31140348Srwatson#include <sys/socket.h>
32140348Srwatson
33140348Srwatson#include <netinet/in.h>
34140348Srwatson
35140348Srwatson#include <arpa/inet.h>
36140348Srwatson
37140348Srwatson#include <err.h>
38140348Srwatson#include <errno.h>
39140348Srwatson#include <stdio.h>
40140348Srwatson#include <stdlib.h>
41140348Srwatson#include <string.h>
42140348Srwatson#include <unistd.h>
43140348Srwatson
44140348Srwatson/*
45140348Srwatson * A bug in the jail(8) code prevented processes in jail from properly
46140348Srwatson * connecting UDP sockets.  This test program attempts to exercise that bug.
47140348Srwatson */
48140348Srwatson
49140348Srwatsonstatic void
50140348Srwatsonusage(void)
51140348Srwatson{
52140348Srwatson
53140348Srwatson	fprintf(stderr, "udpconnectjail: no arguments\n");
54140348Srwatson	exit(-1);
55140348Srwatson}
56140348Srwatson
57140348Srwatsonstatic void
58140348Srwatsontest(const char *context, struct sockaddr_in *sin)
59140348Srwatson{
60140348Srwatson	int sock;
61140348Srwatson
62140348Srwatson	sock = socket(PF_INET, SOCK_DGRAM, 0);
63140348Srwatson	if (sock == -1)
64140348Srwatson		errx(-1, "%s: socket(PF_INET, SOCK_DGRAM, 0): %s", context,
65140348Srwatson		    strerror(errno));
66140348Srwatson
67140352Srwatson	if (connect(sock, (struct sockaddr *)sin, sizeof(*sin)) < 0)
68140348Srwatson		errx(-1, "%s: connect(%s): %s", context,
69140348Srwatson		    inet_ntoa(sin->sin_addr), strerror(errno));
70140348Srwatson
71140348Srwatson	if (close(sock) < 0)
72140348Srwatson		errx(-1, "%s: close(): %s", context, strerror(errno));
73140348Srwatson}
74140348Srwatson
75140348Srwatsonint
76140348Srwatsonmain(int argc, __unused char *argv[])
77140348Srwatson{
78140348Srwatson	struct sockaddr_in sin;
79140348Srwatson	struct jail thejail;
80222487Sbz	struct in_addr ia4;
81140348Srwatson
82140348Srwatson	if (argc != 1)
83140348Srwatson		usage();
84140348Srwatson
85140348Srwatson	bzero(&sin, sizeof(sin));
86140348Srwatson	sin.sin_len = sizeof(sin);
87140348Srwatson	sin.sin_family = AF_INET;
88140348Srwatson	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
89140352Srwatson	sin.sin_port = htons(8080);	/* Arbitrary */
90140348Srwatson
91140348Srwatson	/*
92140348Srwatson	 * First run the system call test outside of a jail.
93140348Srwatson	 */
94140348Srwatson	test("not in jail", &sin);
95140348Srwatson
96140348Srwatson	/*
97140348Srwatson	 * Now re-run in a jail.
98222487Sbz	 * XXX-BZ should switch to jail_set(2).
99140348Srwatson	 */
100222487Sbz	ia4.s_addr = htonl(INADDR_LOOPBACK);
101222487Sbz
102140348Srwatson	bzero(&thejail, sizeof(thejail));
103222487Sbz	thejail.version = JAIL_API_VERSION;
104140348Srwatson	thejail.path = "/";
105140348Srwatson	thejail.hostname = "jail";
106222487Sbz	thejail.jailname = "udpconnectjail";
107222487Sbz	thejail.ip4s = 1;
108222487Sbz	thejail.ip4 = &ia4;
109222487Sbz
110140348Srwatson	if (jail(&thejail) < 0)
111140348Srwatson		errx(-1, "jail: %s", strerror(errno));
112140348Srwatson	test("in jail", &sin);
113140348Srwatson
114140348Srwatson	fprintf(stdout, "PASS\n");
115140348Srwatson
116140348Srwatson	return (0);
117140348Srwatson}
118