1 /* $OpenBSD: kqueue-tun.c,v 1.5 2016/09/20 23:05:27 bluhm 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 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <sys/uio.h> 33 34 #include <netinet/in.h> 35 #include <net/if.h> 36 #include <net/if_tun.h> 37 38 #include <err.h> 39 #include <errno.h> 40 #include <event.h> 41 #include <fcntl.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 46 #include "main.h" 47 48 #define TUN0 "tun98" 49 #define TUN1 "tun99" 50 #define TUN0_ADDR "192.0.2.1" 51 #define TUN1_ADDR "192.0.2.2" 52 #define TUN_MAXWAIT 5 53 #define TUN_PINGDEL 1 54 55 struct buffer { 56 u_char *buf; 57 size_t len; 58 size_t a; 59 }; 60 61 int state; 62 int tunfd[2]; 63 struct buffer tpkt; 64 u_char pktbuf[TUNMTU]; 65 struct event tunwev[2]; 66 struct timeval exittv = {TUN_MAXWAIT, 0}; 67 68 void 69 tunnel_write(int fd, short which, void *arg) 70 { 71 uint32_t type = htonl(AF_INET); 72 struct iovec iv[2]; 73 int rlen; 74 int fdkey = (fd == tunfd[0]) ? 0 : 1; 75 76 iv[0].iov_base = &type; 77 iv[0].iov_len = sizeof(type); 78 iv[1].iov_base = tpkt.buf; 79 iv[1].iov_len = tpkt.len; 80 81 state++; 82 if ((rlen = writev(fd, iv, 2)) > 0) 83 fprintf(stderr, "Tunnel %d wrote %ld bytes\n", 84 fdkey, (long)(rlen - sizeof(type))); 85 else 86 errx(1, "Write to tunnel %d failed", fdkey); 87 } 88 89 void 90 tunnel_read(int fd, short which, void *arg) 91 { 92 struct iovec iv[2]; 93 uint32_t type; 94 int rlen; 95 int fdkey = (fd == tunfd[0]) ? 0 : 1; 96 int oppfdkey = (fd == tunfd[0]) ? 1 : 0; 97 98 iv[0].iov_base = &type; 99 iv[0].iov_len = sizeof(type); 100 iv[1].iov_base = tpkt.buf; 101 iv[1].iov_len = tpkt.a; 102 103 state++; 104 if ((rlen = readv(fd, iv, 2)) > 0) { 105 fprintf(stderr, "Tunnel %d read %ld bytes\n", 106 fdkey, (long)(rlen - sizeof(type))); 107 tpkt.len = rlen - sizeof(type); 108 109 /* add write event on opposite tunnel */ 110 event_add(&tunwev[oppfdkey], &exittv); 111 } else 112 errx(1, "Read from tunnel %d failed", fdkey); 113 } 114 115 void 116 tunnel_ping(int fd, short which, void *arg) 117 { 118 system("ping -c 1 -I " TUN0_ADDR " " TUN1_ADDR " >/dev/null &"); 119 } 120 121 /* 122 * +------------+ +------------+ 123 * | TUN0 | | TUN1 | 124 * | TUN0_ADDR | | TUN1_ADDR | 125 * +------------+ +------------+ 126 * 127 * Set up both tunnel devices (TUN0, TUN1) 128 * This works because the routing table prefers the opposing end of the ptp 129 * interfaces. 130 * Set up one read and one write event per tunnel. 131 * The read events add the write event. 132 */ 133 int 134 do_tun(void) 135 { 136 struct event tunrev[2]; 137 struct event pingev; 138 struct timeval pingtv = {TUN_PINGDEL, 0}; 139 140 /* read buffer */ 141 tpkt.buf = (u_char *)&pktbuf; 142 tpkt.len = 0; 143 tpkt.a = sizeof(pktbuf); 144 145 event_init(); 146 147 /* tun0 */ 148 if ((tunfd[0] = open("/dev/" TUN0, O_RDWR)) < 0) 149 errx(1, "Cannot open /dev/" TUN0); 150 event_set(&tunrev[0], tunfd[0], EV_READ, tunnel_read, NULL); 151 event_set(&tunwev[0], tunfd[0], EV_WRITE, tunnel_write, NULL); 152 event_add(&tunrev[0], &exittv); 153 154 /* tun1 */ 155 if ((tunfd[1] = open("/dev/" TUN1, O_RDWR)) < 0) 156 errx(1, "Cannot open /dev/" TUN1); 157 event_set(&tunrev[1], tunfd[1], EV_READ, tunnel_read, NULL); 158 event_set(&tunwev[1], tunfd[1], EV_WRITE, tunnel_write, NULL); 159 event_add(&tunrev[1], &exittv); 160 161 /* ping */ 162 evtimer_set(&pingev, tunnel_ping, NULL); 163 event_add(&pingev, &pingtv); 164 165 /* configure the interfaces */ 166 system("ifconfig " TUN0 " " TUN0_ADDR 167 " netmask 255.255.255.255 " TUN1_ADDR); 168 system("ifconfig " TUN1 " " TUN1_ADDR 169 " netmask 255.255.255.255 " TUN0_ADDR); 170 171 state = 0; 172 if (event_dispatch() < 0) 173 errx(errno, "Event handler failed"); 174 175 return (state != 4); 176 } 177