xref: /openbsd/regress/sys/kern/kqueue/kqueue-tun.c (revision 898184e3)
1 /* $OpenBSD: kqueue-tun.c,v 1.4 2010/06/26 22:54:04 blambert Exp $ */
2 /* $Gateweaver: tunkq.c,v 1.2 2003/11/27 22:47:41 cmaxwell Exp $ */
3 /*
4  * Copyright 2003 Christopher J. Maxwell <cmaxwell@themanor.net>
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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/uio.h>
32 #include <netinet/in.h>
33 #include <net/if.h>
34 #include <net/if_tun.h>
35 #include <errno.h>
36 #include <err.h>
37 #include <event.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 
43 #define TUN0		"tun98"
44 #define TUN1		"tun99"
45 #define TUN0_ADDR	"192.0.2.1"
46 #define TUN1_ADDR	"192.0.2.2"
47 #define TUN_MAXWAIT	5
48 #define TUN_PINGDEL	1
49 
50 struct buffer {
51 	u_char *buf;
52 	size_t len;
53 	size_t a;
54 };
55 
56 int state;
57 int tunfd[2];
58 struct buffer tpkt;
59 u_char pktbuf[TUNMTU];
60 struct event tunwev[2];
61 struct timeval exittv = {TUN_MAXWAIT, 0};
62 
63 void
64 tunnel_write(int fd, short which, void *arg)
65 {
66 	uint32_t type = htonl(AF_INET);
67 	struct iovec iv[2];
68 	int rlen;
69 	int fdkey = (fd == tunfd[0]) ? 0 : 1;
70 
71 	iv[0].iov_base = &type;
72 	iv[0].iov_len = sizeof(type);
73 	iv[1].iov_base = tpkt.buf;
74 	iv[1].iov_len = tpkt.len;
75 
76 	state++;
77 	if ((rlen = writev(fd, iv, 2)) > 0)
78 		fprintf(stderr, "Tunnel %d wrote %ld bytes\n",
79 		    fdkey, (long)(rlen - sizeof(type)));
80 	else
81 		errx(1, "Write to tunnel %d failed", fdkey);
82 }
83 
84 void
85 tunnel_read(int fd, short which, void *arg)
86 {
87 	struct iovec iv[2];
88 	uint32_t type;
89 	int rlen;
90 	int fdkey = (fd == tunfd[0]) ? 0 : 1;
91 	int oppfdkey = (fd == tunfd[0]) ? 1 : 0;
92 
93 	iv[0].iov_base = &type;
94 	iv[0].iov_len = sizeof(type);
95 	iv[1].iov_base = tpkt.buf;
96 	iv[1].iov_len = tpkt.a;
97 
98 	state++;
99 	if ((rlen = readv(fd, iv, 2)) > 0) {
100 		fprintf(stderr, "Tunnel %d read %ld bytes\n",
101 		    fdkey, (long)(rlen - sizeof(type)));
102 		tpkt.len = rlen - sizeof(type);
103 
104 		/* add write event on opposite tunnel */
105 		event_add(&tunwev[oppfdkey], &exittv);
106 	} else
107 		errx(1, "Read from tunnel %d failed", fdkey);
108 }
109 
110 void
111 tunnel_ping(int fd, short which, void *arg)
112 {
113 	system("ping -c 1 -I " TUN0_ADDR " " TUN1_ADDR " >/dev/null &");
114 }
115 
116 /*
117  * +------------+     +------------+
118  * |    TUN0    |     |    TUN1    |
119  * | TUN0_ADDR  |     | TUN1_ADDR  |
120  * +------------+     +------------+
121  *
122  * Set up both tunnel devices (TUN0, TUN1)
123  * This works because the routing table prefers the opposing end of the ptp
124  * interfaces.
125  * Set up one read and one write event per tunnel.
126  * The read events add the write event.
127  */
128 int
129 do_tun(void)
130 {
131 	struct event tunrev[2];
132 	struct event pingev;
133 	struct timeval pingtv = {TUN_PINGDEL, 0};
134 
135 	/* read buffer */
136 	tpkt.buf = (u_char *)&pktbuf;
137 	tpkt.len = 0;
138 	tpkt.a = sizeof(pktbuf);
139 
140 	event_init();
141 
142 	/* tun0 */
143 	if ((tunfd[0] = open("/dev/" TUN0, O_RDWR)) < 0)
144 		errx(1, "Cannot open /dev/" TUN0);
145 	event_set(&tunrev[0], tunfd[0], EV_READ, tunnel_read, NULL);
146 	event_set(&tunwev[0], tunfd[0], EV_WRITE, tunnel_write, NULL);
147 	event_add(&tunrev[0], &exittv);
148 
149 	/* tun1 */
150 	if ((tunfd[1] = open("/dev/" TUN1, O_RDWR)) < 0)
151 		errx(1, "Cannot open /dev/" TUN1);
152 	event_set(&tunrev[1], tunfd[1], EV_READ, tunnel_read, NULL);
153 	event_set(&tunwev[1], tunfd[1], EV_WRITE, tunnel_write, NULL);
154 	event_add(&tunrev[1], &exittv);
155 
156 	/* ping */
157 	evtimer_set(&pingev, tunnel_ping, NULL);
158 	event_add(&pingev, &pingtv);
159 
160 	/* configure the interfaces */
161 	system("ifconfig " TUN0 " " TUN0_ADDR
162 	    " netmask 255.255.255.255 " TUN1_ADDR);
163 	system("ifconfig " TUN1 " " TUN1_ADDR
164 	    " netmask 255.255.255.255 " TUN0_ADDR);
165 
166 	state = 0;
167 	if (event_dispatch() < 0)
168 		errx(errno, "Event handler failed");
169 
170 	return (state != 4);
171 }
172