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