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

tun-bsd.c

Go to the documentation of this file.
00001 /*
00002  * tun-bsd.c
00003  *
00004  * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
00005  *
00006  * $Id: tun-bsd.c,v 1.3 2005/02/10 23:50:04 dugsong Exp $
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      /* XXX - max number of tunnel devices */
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                         /* XXX - try to ensure our route got set */
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 = &af;
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 = &af;
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                 /* Restore interface configuration on close. */
00141                 intf_set(tun->intf, &tun->save);
00142                 intf_close(tun->intf);
00143         }
00144         free(tun);
00145         return (NULL);
00146 }

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