00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include <sys/socket.h>
00012 #include <sys/uio.h>
00013
00014 #include <errno.h>
00015 #include <fcntl.h>
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020
00021 #include "dnet.h"
00022
00023 struct tun {
00024 int fd;
00025 intf_t *intf;
00026 struct intf_entry save;
00027 };
00028
00029 #define MAX_DEVS 16
00030
00031 tun_t *
00032 tun_open(struct addr *src, struct addr *dst, int mtu)
00033 {
00034 struct intf_entry ifent;
00035 tun_t *tun;
00036 char dev[128];
00037 int i;
00038
00039 if (src->addr_type != ADDR_TYPE_IP || dst->addr_type != ADDR_TYPE_IP ||
00040 src->addr_bits != IP_ADDR_BITS || dst->addr_bits != IP_ADDR_BITS) {
00041 errno = EINVAL;
00042 return (NULL);
00043 }
00044 if ((tun = calloc(1, sizeof(*tun))) == NULL)
00045 return (NULL);
00046
00047 if ((tun->intf = intf_open()) == NULL)
00048 return (tun_close(tun));
00049
00050 memset(&ifent, 0, sizeof(ifent));
00051 ifent.intf_len = sizeof(ifent);
00052
00053 for (i = 0; i < MAX_DEVS; i++) {
00054 snprintf(dev, sizeof(dev), "/dev/tun%d", i);
00055 strlcpy(ifent.intf_name, dev + 5, sizeof(ifent.intf_name));
00056 tun->save = ifent;
00057
00058 if ((tun->fd = open(dev, O_RDWR, 0)) != -1 &&
00059 intf_get(tun->intf, &tun->save) == 0) {
00060 route_t *r;
00061 struct route_entry entry;
00062
00063 ifent.intf_flags = INTF_FLAG_UP|INTF_FLAG_POINTOPOINT;
00064 ifent.intf_addr = *src;
00065 ifent.intf_dst_addr = *dst;
00066 ifent.intf_mtu = mtu;
00067
00068 if (intf_set(tun->intf, &ifent) < 0)
00069 tun = tun_close(tun);
00070
00071
00072 if ((r = route_open()) != NULL) {
00073 entry.route_dst = *dst;
00074 entry.route_gw = *src;
00075 route_add(r, &entry);
00076 route_close(r);
00077 }
00078 break;
00079 }
00080 }
00081 if (i == MAX_DEVS)
00082 tun = tun_close(tun);
00083 return (tun);
00084 }
00085
00086 const char *
00087 tun_name(tun_t *tun)
00088 {
00089 return (tun->save.intf_name);
00090 }
00091
00092 int
00093 tun_fileno(tun_t *tun)
00094 {
00095 return (tun->fd);
00096 }
00097
00098 ssize_t
00099 tun_send(tun_t *tun, const void *buf, size_t size)
00100 {
00101 #ifdef __OpenBSD__
00102 struct iovec iov[2];
00103 uint32_t af = htonl(AF_INET);
00104
00105 iov[0].iov_base = ⁡
00106 iov[0].iov_len = sizeof(af);
00107 iov[1].iov_base = (void *)buf;
00108 iov[1].iov_len = size;
00109
00110 return (writev(tun->fd, iov, 2));
00111 #else
00112 return (write(tun->fd, buf, size));
00113 #endif
00114 }
00115
00116 ssize_t
00117 tun_recv(tun_t *tun, void *buf, size_t size)
00118 {
00119 #ifdef __OpenBSD__
00120 struct iovec iov[2];
00121 uint32_t af;
00122
00123 iov[0].iov_base = ⁡
00124 iov[0].iov_len = sizeof(af);
00125 iov[1].iov_base = (void *)buf;
00126 iov[1].iov_len = size;
00127
00128 return (readv(tun->fd, iov, 2) - sizeof(af));
00129 #else
00130 return (read(tun->fd, buf, size));
00131 #endif
00132 }
00133
00134 tun_t *
00135 tun_close(tun_t *tun)
00136 {
00137 if (tun->fd > 0)
00138 close(tun->fd);
00139 if (tun->intf != NULL) {
00140
00141 intf_set(tun->intf, &tun->save);
00142 intf_close(tun->intf);
00143 }
00144 free(tun);
00145 return (NULL);
00146 }