00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "config.h"
00013
00014 #include <sys/ioctl.h>
00015 #include <sys/socket.h>
00016 #include <sys/uio.h>
00017
00018 #include <linux/if.h>
00019 #include <linux/if_tun.h>
00020
00021 #include <fcntl.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <unistd.h>
00026
00027 #include "dnet.h"
00028
00029 struct tun {
00030 int fd;
00031 intf_t *intf;
00032 struct ifreq ifr;
00033 };
00034
00035 tun_t *
00036 tun_open(struct addr *src, struct addr *dst, int mtu)
00037 {
00038 tun_t *tun;
00039 struct intf_entry ifent;
00040
00041 if ((tun = calloc(1, sizeof(*tun))) == NULL)
00042 return (NULL);
00043
00044 if ((tun->fd = open("/dev/net/tun", O_RDWR, 0)) < 0 ||
00045 (tun->intf = intf_open()) == NULL)
00046 return (tun_close(tun));
00047
00048 tun->ifr.ifr_flags = IFF_TUN;
00049
00050 if (ioctl(tun->fd, TUNSETIFF, (void *) &tun->ifr) < 0)
00051 return (tun_close(tun));
00052
00053 memset(&ifent, 0, sizeof(ifent));
00054 strlcpy(ifent.intf_name, tun->ifr.ifr_name, sizeof(ifent.intf_name));
00055 ifent.intf_flags = INTF_FLAG_UP|INTF_FLAG_POINTOPOINT;
00056 ifent.intf_addr = *src;
00057 ifent.intf_dst_addr = *dst;
00058 ifent.intf_mtu = mtu;
00059
00060 if (intf_set(tun->intf, &ifent) < 0)
00061 return (tun_close(tun));
00062
00063 return (tun);
00064 }
00065
00066 const char *
00067 tun_name(tun_t *tun)
00068 {
00069 return (tun->ifr.ifr_name);
00070 }
00071
00072 int
00073 tun_fileno(tun_t *tun)
00074 {
00075 return (tun->fd);
00076 }
00077
00078 ssize_t
00079 tun_send(tun_t *tun, const void *buf, size_t size)
00080 {
00081 struct iovec iov[2];
00082 uint32_t type = ETH_TYPE_IP;
00083
00084 iov[0].iov_base = &type;
00085 iov[0].iov_len = sizeof(type);
00086 iov[1].iov_base = (void *)buf;
00087 iov[1].iov_len = size;
00088
00089 return (writev(tun->fd, iov, 2));
00090 }
00091
00092 ssize_t
00093 tun_recv(tun_t *tun, void *buf, size_t size)
00094 {
00095 struct iovec iov[2];
00096 uint32_t type;
00097
00098 iov[0].iov_base = &type;
00099 iov[0].iov_len = sizeof(type);
00100 iov[1].iov_base = (void *)buf;
00101 iov[1].iov_len = size;
00102
00103 return (readv(tun->fd, iov, 2) - sizeof(type));
00104 }
00105
00106 tun_t *
00107 tun_close(tun_t *tun)
00108 {
00109 if (tun->fd > 0)
00110 close(tun->fd);
00111 if (tun->intf != NULL)
00112 intf_close(tun->intf);
00113 free(tun);
00114 return (NULL);
00115 }