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