xref: /freebsd/tests/sys/net/if_ovpn/if_ovpn_c.c (revision 69361b8785468fe15bb2b169a0b72af5bc108cfa)
1248da794SKristof Provost //#include <sys/param.h>
2248da794SKristof Provost #include <stdio.h>
3248da794SKristof Provost 
4248da794SKristof Provost #include <net/if.h>
5248da794SKristof Provost #include <netinet/in.h>
6248da794SKristof Provost #include <sys/param.h>
7248da794SKristof Provost #include <sys/errno.h>
8248da794SKristof Provost #include <sys/linker.h>
9248da794SKristof Provost #include <sys/ioctl.h>
10248da794SKristof Provost #include <sys/nv.h>
11248da794SKristof Provost #include <sys/socket.h>
12248da794SKristof Provost #include <sys/sockio.h>
13248da794SKristof Provost 
14248da794SKristof Provost #include <atf-c.h>
15248da794SKristof Provost 
16248da794SKristof Provost #define OVPN_NEW_PEER		_IO  ('D', 1)
17248da794SKristof Provost 
18248da794SKristof Provost static nvlist_t *
fake_sockaddr(void)19ab28cc35SDimitry Andric fake_sockaddr(void)
20248da794SKristof Provost {
21248da794SKristof Provost 	uint32_t addr = htonl(INADDR_LOOPBACK);
22248da794SKristof Provost 	nvlist_t *nvl;
23248da794SKristof Provost 
24248da794SKristof Provost 	nvl = nvlist_create(0);
25248da794SKristof Provost 
26248da794SKristof Provost 	nvlist_add_number(nvl, "af", AF_INET);
27248da794SKristof Provost 	nvlist_add_binary(nvl, "address", &addr, 4);
28248da794SKristof Provost 	nvlist_add_number(nvl, "port", 1024);
29248da794SKristof Provost 
30248da794SKristof Provost 	return (nvl);
31248da794SKristof Provost }
32248da794SKristof Provost 
33248da794SKristof Provost static char ovpn_ifname[IFNAMSIZ];
34248da794SKristof Provost static int ovpn_fd;
35248da794SKristof Provost 
36248da794SKristof Provost static int
create_interface(int fd)37248da794SKristof Provost create_interface(int fd)
38248da794SKristof Provost {
39248da794SKristof Provost 	int ret;
40248da794SKristof Provost 	struct ifreq ifr;
41248da794SKristof Provost 
42248da794SKristof Provost 	bzero(&ifr, sizeof(ifr));
43248da794SKristof Provost 
44248da794SKristof Provost 	/* Create ovpnx first, then rename it. */
45248da794SKristof Provost 	snprintf(ifr.ifr_name, IFNAMSIZ, "ovpn");
46248da794SKristof Provost 	ret = ioctl(fd, SIOCIFCREATE2, &ifr);
47248da794SKristof Provost 	if (ret)
48248da794SKristof Provost 		return (ret);
49248da794SKristof Provost 
50248da794SKristof Provost 	snprintf(ovpn_ifname, IFNAMSIZ, "%s", ifr.ifr_name);
51248da794SKristof Provost 	printf("Created %s\n", ovpn_ifname);
52248da794SKristof Provost 
53248da794SKristof Provost 	return (0);
54248da794SKristof Provost }
55248da794SKristof Provost 
56248da794SKristof Provost static void
destroy_interface(int fd)57248da794SKristof Provost destroy_interface(int fd)
58248da794SKristof Provost {
59248da794SKristof Provost 	int ret;
60248da794SKristof Provost 	struct ifreq ifr;
61248da794SKristof Provost 
62248da794SKristof Provost 	if (ovpn_ifname[0] == 0)
63248da794SKristof Provost 		return;
64248da794SKristof Provost 
65248da794SKristof Provost 	printf("Destroy %s\n", ovpn_ifname);
66248da794SKristof Provost 
67248da794SKristof Provost 	bzero(&ifr, sizeof(ifr));
68248da794SKristof Provost 	snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ovpn_ifname);
69248da794SKristof Provost 
70248da794SKristof Provost 	ret = ioctl(fd, SIOCIFDESTROY, &ifr);
71248da794SKristof Provost 	if (ret)
72248da794SKristof Provost 		atf_tc_fail("Failed to destroy interface");
73248da794SKristof Provost 
74248da794SKristof Provost 	ovpn_ifname[0] = 0;
75248da794SKristof Provost }
76248da794SKristof Provost 
77248da794SKristof Provost ATF_TC_WITH_CLEANUP(tcp);
ATF_TC_HEAD(tcp,tc)78248da794SKristof Provost ATF_TC_HEAD(tcp, tc)
79248da794SKristof Provost {
80248da794SKristof Provost 	atf_tc_set_md_var(tc, "require.user", "root");
81248da794SKristof Provost }
82248da794SKristof Provost 
ATF_TC_BODY(tcp,tc)83248da794SKristof Provost ATF_TC_BODY(tcp, tc)
84248da794SKristof Provost {
85248da794SKristof Provost 	struct ifdrv drv;
86248da794SKristof Provost 	struct sockaddr_in sock_in;
87248da794SKristof Provost 	int ret;
88248da794SKristof Provost 	nvlist_t *nvl;
89248da794SKristof Provost 
90248da794SKristof Provost 	/* Ensure the module is loaded. */
91*69361b87SKristof Provost 	if (kldfind("if_ovpn") == -1 && errno == ENOENT)
92*69361b87SKristof Provost 		atf_tc_skip("if_ovpn not loaded");
93248da794SKristof Provost 
94248da794SKristof Provost 	ovpn_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
95248da794SKristof Provost 
96248da794SKristof Provost 	/* Kick off a connect so there's a local address set, which we need for
97248da794SKristof Provost 	 * ovpn_new_peer() to get to the critical point. */
98248da794SKristof Provost 	bzero(&sock_in, sizeof(sock_in));
99248da794SKristof Provost 	sock_in.sin_family = AF_INET;
100248da794SKristof Provost 	sock_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
101248da794SKristof Provost 	sock_in.sin_port = htons(1024);
102248da794SKristof Provost 	connect(ovpn_fd, (struct sockaddr *)&sock_in, sizeof(sock_in));
103248da794SKristof Provost 
104248da794SKristof Provost 	ret = create_interface(ovpn_fd);
105248da794SKristof Provost 	if (ret)
106248da794SKristof Provost 		atf_tc_fail("Failed to create interface");
107248da794SKristof Provost 
108248da794SKristof Provost 	nvl = nvlist_create(0);
109248da794SKristof Provost 
110248da794SKristof Provost 	nvlist_add_number(nvl, "peerid", 0);
111248da794SKristof Provost 	nvlist_add_number(nvl, "fd", ovpn_fd);
112248da794SKristof Provost 	nvlist_add_nvlist(nvl, "remote", fake_sockaddr());
113248da794SKristof Provost 
114248da794SKristof Provost 	bzero(&drv, sizeof(drv));
115248da794SKristof Provost 	snprintf(drv.ifd_name, IFNAMSIZ, "%s", ovpn_ifname);
116248da794SKristof Provost 	drv.ifd_cmd = OVPN_NEW_PEER;
117248da794SKristof Provost 	drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
118248da794SKristof Provost 
119248da794SKristof Provost 	ret = ioctl(ovpn_fd, SIOCSDRVSPEC, &drv);
120248da794SKristof Provost 	ATF_CHECK_EQ(ret, -1);
121248da794SKristof Provost 	ATF_CHECK_EQ(errno, EPROTOTYPE);
122248da794SKristof Provost }
123248da794SKristof Provost 
ATF_TC_CLEANUP(tcp,tc)124248da794SKristof Provost ATF_TC_CLEANUP(tcp, tc)
125248da794SKristof Provost {
126248da794SKristof Provost 	destroy_interface(ovpn_fd);
127248da794SKristof Provost 	close(ovpn_fd);
128248da794SKristof Provost }
129248da794SKristof Provost 
ATF_TP_ADD_TCS(tp)130248da794SKristof Provost ATF_TP_ADD_TCS(tp)
131248da794SKristof Provost {
132248da794SKristof Provost 	ATF_TP_ADD_TC(tp, tcp);
133248da794SKristof Provost 
134248da794SKristof Provost 	return (atf_no_error());
135248da794SKristof Provost }
136