Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

tun-linux.c

Go to the documentation of this file.
00001 /*
00002  * tun-linux.c
00003  *
00004  * Universal TUN/TAP driver, in Linux 2.4+
00005  * /usr/src/linux/Documentation/networking/tuntap.txt
00006  *
00007  * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
00008  *
00009  * $Id: tun-linux.c,v 1.4 2005/09/12 02:18:06 dugsong Exp $
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 }

Generated on Sun May 14 14:51:12 2006 by  doxygen 1.4.2