summaryrefslogtreecommitdiff
path: root/mac-tap/tuntap/src/tuntap.h
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-04 16:56:19 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-04 16:56:19 -0400
commit150850b80012f852521c9935145cf966946334d5 (patch)
treec082369f2fef2515cfa2e4acf1b83250a3963158 /mac-tap/tuntap/src/tuntap.h
downloadinfinitytier-150850b80012f852521c9935145cf966946334d5.tar.gz
infinitytier-150850b80012f852521c9935145cf966946334d5.zip
New git repository for release - version 0.2.0 tagged
Diffstat (limited to 'mac-tap/tuntap/src/tuntap.h')
-rw-r--r--mac-tap/tuntap/src/tuntap.h301
1 files changed, 301 insertions, 0 deletions
diff --git a/mac-tap/tuntap/src/tuntap.h b/mac-tap/tuntap/src/tuntap.h
new file mode 100644
index 00000000..f10d4a06
--- /dev/null
+++ b/mac-tap/tuntap/src/tuntap.h
@@ -0,0 +1,301 @@
+/*
+ * ip tunnel/ethertap device for MacOSX.
+ *
+ * The class tuntaptap_interface contains the common functionality of tuntap_interface and
+ * tap_interface.
+ */
+/*
+ * Copyright (c) 2011 Mattias Nissler <mattias.nissler@gmx.de>
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TUNTAP_H__
+#define __TUNTAP_H__
+
+#include "util.h"
+#include "lock.h"
+
+extern "C" {
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/systm.h>
+#include <sys/kpi_mbuf.h>
+
+#include <kern/locks.h>
+
+#include <net/if.h>
+#include <net/bpf.h>
+#include <net/kpi_interface.h>
+
+}
+
+extern "C" {
+
+errno_t tuntap_if_output(ifnet_t ifp, mbuf_t m);
+errno_t tuntap_if_ioctl(ifnet_t ifp, long unsigned int cmd, void *arg);
+errno_t tuntap_if_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, int (*cb)(ifnet_t, mbuf_t));
+errno_t tuntap_if_demux(ifnet_t ifp, mbuf_t m, char *header, protocol_family_t *proto);
+errno_t tuntap_if_framer(ifnet_t ifp, mbuf_t *m, const struct sockaddr *dest,
+ const char *dest_linkaddr, const char *frame_type);
+errno_t tuntap_if_add_proto(ifnet_t ifp, protocol_family_t proto,
+ const struct ifnet_demux_desc *ddesc, u_int32_t ndesc);
+errno_t tuntap_if_del_proto(ifnet_t ifp, protocol_family_t proto);
+errno_t tuntap_if_check_multi(ifnet_t ifp, const struct sockaddr *maddr);
+void tuntap_if_detached(ifnet_t ifp);
+
+}
+
+/* forward declaration */
+class tuntap_interface;
+
+/* both interface families have their manager object that will create, initialize, shutdown and
+ * delete interfaces. This is (mostly) generic so it can be used both for tun and tap. The only
+ * exception is the interface creation, therefore this class is abstract. tun and tap have their own
+ * versions that simply fill in create_interface().
+ */
+class tuntap_manager {
+
+ protected:
+ /* manager cdev gate */
+ tt_gate cdev_gate;
+ /* interface count */
+ unsigned int count;
+ /* an array holding all the interface instances */
+ tuntap_interface **tuntaps;
+ /* the major device number */
+ int dev_major;
+ /* family name */
+ char *family;
+
+ /* wether static members are initialized */
+ static bool statics_initialized;
+
+ /* major-to-manager-map */
+ static const int MAX_CDEV = 256;
+ static tuntap_manager *mgr_map[MAX_CDEV];
+
+ /* initializes static members */
+ void initialize_statics();
+
+ public:
+ /* sets major device number, allocates the interface table. */
+ bool initialize(unsigned int count, char *family);
+
+ /* tries to shutdown the family. returns true if successful. the manager object may
+ * not be deleted if this wasn't called successfully.
+ */
+ bool shutdown();
+
+ /* the destructor deletes allocated memory and unregisters the character device
+ * switch */
+ virtual ~tuntap_manager();
+
+ /* here are the cdev routines for the class. They will figure out the manager object
+ * and call the service methods declared below.
+ */
+ static int cdev_open(dev_t dev, int flags, int devtype, proc_t p);
+ static int cdev_close(dev_t dev, int flags, int devtype, proc_t p);
+ static int cdev_read(dev_t dev, uio_t uio, int ioflag);
+ static int cdev_write(dev_t dev, uio_t uio, int ioflag);
+ static int cdev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag,
+ proc_t p);
+ static int cdev_select(dev_t dev, int which, void *wql, proc_t p);
+
+ protected:
+ /* Here are the actual service routines that will do the required things (creating
+ * interfaces and such) and forward to the interface's implementation.
+ */
+ int do_cdev_open(dev_t dev, int flags, int devtype, proc_t p);
+ int do_cdev_close(dev_t dev, int flags, int devtype, proc_t p);
+ int do_cdev_read(dev_t dev, uio_t uio, int ioflag);
+ int do_cdev_write(dev_t dev, uio_t uio, int ioflag);
+ int do_cdev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, proc_t p);
+ int do_cdev_select(dev_t dev, int which, void *wql, proc_t p);
+
+ /* abstract method that will create an interface. Implemented by tun and tap */
+ virtual tuntap_interface *create_interface() = 0;
+
+ /* makes sure there is one idle interface available (if nothing fails */
+ void ensure_idle_device();
+
+};
+
+/* a class implementing a mbuf packet queue. On Darwin 7 we had struct ifqueue, but that is now
+ * internal to the kernel for Darwin 8. So lets have our own.
+ */
+class tuntap_mbuf_queue {
+
+ private:
+ /* output end of the queue. dequeueing takes mbufs from here */
+ mbuf_t head;
+ /* input end. new mbufs are appended here. */
+ mbuf_t tail;
+
+ /* size */
+ unsigned int size;
+
+ /* maximum queue size */
+ static const unsigned int QUEUE_SIZE = 128;
+
+ public:
+ /* initialize new empty queue */
+ tuntap_mbuf_queue();
+ ~tuntap_mbuf_queue();
+
+ /* is the queue full? */
+ bool full() { return size == QUEUE_SIZE; }
+ /* is it emtpy? */
+ bool empty() { return size == 0; }
+
+ /* enqueue an mbuf. returns true if there was space left, so the mbuf could be
+ * queued, false otherwise */
+ bool enqueue(mbuf_t mb);
+
+ /* tries to dequeue the next mbuf. If the queue is empty, NULL is returned */
+ mbuf_t dequeue();
+
+ /* makes the queue empty, discarding any queue packets */
+ void clear();
+};
+
+class tuntap_interface {
+
+ protected:
+ /* interface number */
+ unsigned int unit;
+ /* family name */
+ char *family_name;
+ /* family identifier */
+ ifnet_family_t family;
+ /* interface type */
+ u_int32_t type;
+ /* id string */
+ static const unsigned int UIDLEN = 20;
+ char unique_id[UIDLEN];
+
+ /* synchronization */
+ tt_mutex lock;
+ tt_mutex bpf_lock;
+ tt_mutex detach_lock;
+
+ /* the interface structure registered */
+ ifnet_t ifp;
+ /* whether the device has been opened */
+ bool open;
+ /* whether we are doing blocking i/o */
+ bool block_io;
+ /* whether the interface has properly been detached */
+ bool interface_detached;
+ /* handle to the devfs node for the character device */
+ void *dev_handle;
+ /* the pid of the process that opened the cdev, if any */
+ pid_t pid;
+ /* read select info */
+ struct selinfo rsel;
+ /* bpf mode, wether filtering is on or off */
+ bpf_tap_mode bpf_mode;
+ /* bpf callback. called when packet arrives/leaves */
+ int (*bpf_callback)(ifnet_t, mbuf_t);
+ /* pending packets queue (for output), must be accessed with the lock held */
+ tuntap_mbuf_queue send_queue;
+ /* whether an ioctl that we issued is currently being processed */
+ bool in_ioctl;
+
+ /* protected constructor. initializes most of the members */
+ tuntap_interface();
+ virtual ~tuntap_interface();
+
+ /* initialize the device */
+ virtual bool initialize(unsigned short major, unsigned short unit) = 0;
+
+ /* character device management */
+ virtual bool register_chardev(unsigned short major);
+ virtual void unregister_chardev();
+
+ /* network interface management */
+ virtual bool register_interface(const struct sockaddr_dl *lladdr,
+ void *bcaddr, u_int32_t bcaddrlen);
+ virtual void unregister_interface();
+ virtual void cleanup_interface();
+
+ /* called when the character device is opened in order to intialize the network
+ * interface.
+ */
+ virtual int initialize_interface() = 0;
+ /* called when the character device is closed to shutdown the network interface */
+ virtual void shutdown_interface() = 0;
+
+ /* check wether the interface is idle (so it can be brought down) */
+ virtual bool idle();
+
+ /* shut it down */
+ virtual void shutdown() = 0;
+
+ /* notifies BPF of a packet coming through */
+ virtual void notify_bpf(mbuf_t mb, bool out);
+
+ /* executes a socket ioctl through a temporary socket */
+ virtual void do_sock_ioctl(sa_family_t af, unsigned long cmd, void* arg);
+
+ /* character device service methods. Called by the manager */
+ virtual int cdev_open(int flags, int devtype, proc_t p);
+ virtual int cdev_close(int flags, int devtype, proc_t p);
+ virtual int cdev_read(uio_t uio, int ioflag);
+ virtual int cdev_write(uio_t uio, int ioflag);
+ virtual int cdev_ioctl(u_long cmd, caddr_t data, int fflag, proc_t p);
+ virtual int cdev_select(int which, void *wql, proc_t p);
+
+ /* interface functions. friends and implementation methods */
+ friend errno_t tuntap_if_output(ifnet_t ifp, mbuf_t m);
+ friend errno_t tuntap_if_ioctl(ifnet_t ifp, long unsigned int cmd, void *arg);
+ friend errno_t tuntap_if_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode,
+ int (*cb)(ifnet_t, mbuf_t));
+ friend errno_t tuntap_if_demux(ifnet_t ifp, mbuf_t m, char *header,
+ protocol_family_t *proto);
+ friend errno_t tuntap_if_framer(ifnet_t ifp, mbuf_t *m, const struct sockaddr *dest,
+ const char *dest_linkaddr, const char *frame_type);
+ friend errno_t tuntap_if_add_proto(ifnet_t ifp, protocol_family_t proto,
+ const struct ifnet_demux_desc *ddesc, u_int32_t ndesc);
+ friend errno_t tuntap_if_del_proto(ifnet_t ifp, protocol_family_t proto);
+ friend errno_t tuntap_if_check_multi(ifnet_t ifp, const struct sockaddr *maddr);
+ friend void tuntap_if_detached(ifnet_t ifp);
+
+ virtual errno_t if_output(mbuf_t m);
+ virtual errno_t if_ioctl(u_int32_t cmd, void *arg);
+ virtual errno_t if_set_bpf_tap(bpf_tap_mode mode, int (*cb)(ifnet_t, mbuf_t));
+ virtual errno_t if_demux(mbuf_t m, char *header, protocol_family_t *proto) = 0;
+ virtual errno_t if_framer(mbuf_t *m, const struct sockaddr *dest,
+ const char *dest_linkaddr, const char *frame_type) = 0;
+ virtual errno_t if_add_proto(protocol_family_t proto,
+ const struct ifnet_demux_desc *ddesc, u_int32_t ndesc) = 0;
+ virtual errno_t if_del_proto(protocol_family_t proto) = 0;
+ virtual errno_t if_check_multi(const struct sockaddr *maddr);
+ virtual void if_detached();
+
+ /* tuntap_manager feeds us with cdev input, so it is our friend */
+ friend class tuntap_manager;
+};
+
+#endif /* __TUNTAP_H__ */
+