diff options
Diffstat (limited to 'ext/tap-mac/tuntap/src/tuntap.cc')
-rw-r--r-- | ext/tap-mac/tuntap/src/tuntap.cc | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/ext/tap-mac/tuntap/src/tuntap.cc b/ext/tap-mac/tuntap/src/tuntap.cc deleted file mode 100644 index d0f89018..00000000 --- a/ext/tap-mac/tuntap/src/tuntap.cc +++ /dev/null @@ -1,963 +0,0 @@ -/* - * ip tunnel/ethertap device for MacOSX. Common functionality of tap_interface and tun_interface. - * - * tuntap_interface class definition - */ -/* - * 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. - */ - -#include "tuntap.h" - -#if 0 -#define dprintf(...) log(LOG_INFO, __VA_ARGS__) -#else -#define dprintf(...) -#endif - -extern "C" { - -#include <sys/conf.h> -#include <sys/syslog.h> -#include <sys/param.h> -#include <sys/filio.h> -#include <sys/sockio.h> -#include <sys/fcntl.h> -#include <sys/kpi_socket.h> - -#include <vm/vm_kern.h> - -#include <net/if_types.h> -#include <net/if_var.h> -#include <net/if_dl.h> -#include <net/if_arp.h> - -#include <miscfs/devfs/devfs.h> - -} - -extern "C" { - -/* interface service functions that delegate to the appropriate tuntap_interface instance */ -errno_t -tuntap_if_output(ifnet_t ifp, mbuf_t m) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_output(m); - } - - if (m != NULL) - mbuf_freem_list(m); - - return ENODEV; -} - -errno_t -tuntap_if_ioctl(ifnet_t ifp, long unsigned int cmd, void *arg) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_ioctl(cmd, arg); - } - - return ENODEV; -} - -errno_t -tuntap_if_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, int (*cb)(ifnet_t, mbuf_t)) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_set_bpf_tap(mode, cb); - } - - return ENODEV; -} - -errno_t -tuntap_if_demux(ifnet_t ifp, mbuf_t m, char *header, protocol_family_t *proto) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_demux(m, header, proto); - } - - return ENODEV; -} - -errno_t -tuntap_if_framer(ifnet_t ifp, mbuf_t *m, const struct sockaddr *dest, const char *dest_linkaddr, - const char *frame_type) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_framer(m, dest, dest_linkaddr, frame_type); - } - - return ENODEV; -} - -errno_t -tuntap_if_add_proto(ifnet_t ifp, protocol_family_t proto, const struct ifnet_demux_desc *ddesc, - u_int32_t ndesc) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_add_proto(proto, ddesc, ndesc); - } - - return ENODEV; -} - -errno_t -tuntap_if_del_proto(ifnet_t ifp, protocol_family_t proto) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_del_proto(proto); - } - - return ENODEV; -} - -errno_t -tuntap_if_check_multi(ifnet_t ifp, const struct sockaddr* maddr) -{ - if (ifp != NULL) - { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - return ttif->if_check_multi(maddr); - } - - return ENODEV; -} - -void -tuntap_if_detached(ifnet_t ifp) -{ - if (ifp != NULL) { - tuntap_interface *ttif = (tuntap_interface *) ifnet_softc(ifp); - if (ttif != NULL) - ttif->if_detached(); - } -} - -errno_t -tuntap_if_noop_output(ifnet_t, mbuf_t) -{ - return ENODEV; -} - -errno_t -tuntap_if_noop_demux(ifnet_t, mbuf_t, char*, protocol_family_t*) -{ - return ENODEV; -} - -errno_t -tuntap_if_noop_add_proto(ifnet_t, protocol_family_t, const struct ifnet_demux_desc*, u_int32_t) -{ - return ENODEV; -} - -errno_t -tuntap_if_noop_del_proto(ifnet_t, protocol_family_t) -{ - return ENODEV; -} - -} /* extern "C" */ - -/* tuntap_mbuf_queue */ -tuntap_mbuf_queue::tuntap_mbuf_queue() -{ - head = tail = NULL; - size = 0; -} - -tuntap_mbuf_queue::~tuntap_mbuf_queue() -{ - clear(); -} - -bool -tuntap_mbuf_queue::enqueue(mbuf_t mb) -{ - if (size == QUEUE_SIZE) - return false; - - mbuf_setnextpkt(mb, NULL); - - if (head == NULL) - head = tail = mb; - else { - mbuf_setnextpkt(tail, mb); - tail = mb; - } - size++; - - return true; -} - -mbuf_t -tuntap_mbuf_queue::dequeue() -{ - mbuf_t ret; - - /* check wether there is a packet in the queue */ - if (head == NULL) - return NULL; - - /* fetch it */ - ret = head; - head = mbuf_nextpkt(head); - mbuf_setnextpkt(ret, NULL); - size--; - - return ret; -} - -void -tuntap_mbuf_queue::clear() -{ - /* free mbufs that are in the queue */ - if (head != NULL) - mbuf_freem_list(head); - - head = NULL; - tail = NULL; - size = 0; -} - -/* tuntap_interface members */ -tuntap_interface::tuntap_interface() -{ - /* initialize the members */ - ifp = NULL; - open = false; - block_io = true; - dev_handle = NULL; - pid = 0; - selthreadclear(&rsel); - bpf_mode = BPF_MODE_DISABLED; - bpf_callback = NULL; - bzero(unique_id, UIDLEN); - in_ioctl = false; -} - -tuntap_interface::~tuntap_interface() -{ -} - -bool -tuntap_interface::register_chardev(unsigned short major) -{ - /* register character device */ - dev_handle = devfs_make_node(makedev(major, unit), DEVFS_CHAR, 0, 0, 0660, "%s%d", - family_name, (int) unit); - - if (dev_handle == NULL) { - log(LOG_ERR, "tuntap: could not make /dev/%s%d\n", family_name, (int) unit); - return false; - } - - return true; -} - -void -tuntap_interface::unregister_chardev() -{ - dprintf("unregistering character device\n"); - - /* unregister character device */ - if (dev_handle != NULL) - devfs_remove(dev_handle); - dev_handle = NULL; -} - -bool -tuntap_interface::register_interface(const struct sockaddr_dl* lladdr, void *bcaddr, - u_int32_t bcaddrlen) -{ - struct ifnet_init_params ip; - errno_t err; - - dprintf("register_interface\n"); - - /* initialize an initialization info struct */ - ip.uniqueid_len = UIDLEN; - ip.uniqueid = unique_id; - ip.name = family_name; - ip.unit = unit; - ip.family = family; - ip.type = type; - ip.output = tuntap_if_output; - ip.demux = tuntap_if_demux; - ip.add_proto = tuntap_if_add_proto; - ip.del_proto = tuntap_if_del_proto; - ip.check_multi = tuntap_if_check_multi; - ip.framer = tuntap_if_framer; - ip.softc = this; - ip.ioctl = tuntap_if_ioctl; - ip.set_bpf_tap = tuntap_if_set_bpf_tap; - ip.detach = tuntap_if_detached; - ip.event = NULL; - ip.broadcast_addr = bcaddr; - ip.broadcast_len = bcaddrlen; - - dprintf("tuntap: tuntap_if_check_multi is at 0x%08x\n", (void*) tuntap_if_check_multi); - - /* allocate the interface */ - err = ifnet_allocate(&ip, &ifp); - if (err) { - log(LOG_ERR, "tuntap: could not allocate interface for %s%d: %d\n", family_name, - (int) unit, err); - ifp = NULL; - return false; - } - - /* activate the interface */ - err = ifnet_attach(ifp, lladdr); - if (err) { - log(LOG_ERR, "tuntap: could not attach interface %s%d: %d\n", family_name, - (int) unit, err); - ifnet_release(ifp); - ifp = NULL; - return false; - } - - dprintf("setting interface flags\n"); - - /* set interface flags */ - ifnet_set_flags(ifp, IFF_RUNNING | IFF_MULTICAST | IFF_SIMPLEX, (u_int16_t) ~0UL); - - dprintf("flags: %x\n", ifnet_flags(ifp)); - - return true; -} - -void -tuntap_interface::unregister_interface() -{ - errno_t err; - - dprintf("unregistering network interface\n"); - - if (ifp != NULL) { - interface_detached = false; - - /* detach interface */ - err = ifnet_detach(ifp); - if (err) - log(LOG_ERR, "tuntap: error detaching interface %s%d: %d\n", - family_name, unit, err); - - dprintf("interface detaching\n"); - - /* Wait until the interface has completely been detached. */ - thread_sync_lock.lock(); - while (!interface_detached) - thread_sync_lock.sleep(&interface_detached); - thread_sync_lock.unlock(); - - dprintf("interface detached\n"); - - /* release the interface */ - ifnet_release(ifp); - - ifp = NULL; - } - - dprintf("network interface unregistered\n"); -} - -void -tuntap_interface::cleanup_interface() -{ - errno_t err; - ifaddr_t *addrs; - ifaddr_t *a; - struct ifreq ifr; - - /* mark the interface down */ - ifnet_set_flags(ifp, 0, IFF_UP | IFF_RUNNING); - - /* Unregister all interface addresses. This works around a deficiency in the Darwin kernel. - * If we don't remove all IP addresses that are attached to the interface it can happen that - * the IP code fails to clean them up itself. When the interface is recycled, the IP code - * might then think some addresses are still attached to the interface... - */ - - err = ifnet_get_address_list(ifp, &addrs); - if (!err) { - - /* Execute a SIOCDIFADDR ioctl for each address. For technical reasons, we can only - * do that with a socket of the appropriate family. So try to create a dummy socket. - * I know this is a little expensive, but better than crashing... - * - * This really sucks. - */ - for (a = addrs; *a != NULL; a++) { - /* initialize the request parameters */ - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", - ifnet_name(ifp), ifnet_unit(ifp)); - ifaddr_address(*a, &(ifr.ifr_addr), sizeof(ifr.ifr_addr)); - if (ifr.ifr_addr.sa_family != AF_INET) - continue; - - dprintf("trying to delete address of family %d\n", ifr.ifr_addr.sa_family); - - do_sock_ioctl(ifr.ifr_addr.sa_family, SIOCDIFADDR, &ifr); - } - - /* release the address list */ - ifnet_free_address_list(addrs); - } -} - -bool -tuntap_interface::idle() -{ - return !(open); -} - -void -tuntap_interface::notify_bpf(mbuf_t mb, bool out) -{ - auto_lock l(&bpf_lock); - - if ((out && bpf_mode == BPF_MODE_OUTPUT) - || (!out && bpf_mode == BPF_MODE_INPUT) - || (bpf_mode == BPF_MODE_INPUT_OUTPUT)) - (*bpf_callback)(ifp, mb); -} - -void -tuntap_interface::do_sock_ioctl(sa_family_t af, unsigned long cmd, void* arg) { - if (in_ioctl) { - log(LOG_ERR, "tuntap: ioctl recursion detected, aborting.\n"); - return; - } - - socket_t sock; - errno_t err = sock_socket(af, SOCK_RAW, 0, NULL, NULL, &sock); - if (err) { - log(LOG_ERR, "tuntap: failed to create socket: %d\n", err); - return; - } - - in_ioctl = true; - - /* issue the ioctl */ - err = sock_ioctl(sock, cmd, arg); - if (err) - log(LOG_ERR, "tuntap: socket ioctl %d failed: %d\n", cmd, err); - - in_ioctl = false; - - /* get rid of the socket */ - sock_close(sock); -} - -/* character device service methods */ -int -tuntap_interface::cdev_open(int flags, int devtype, proc_t p) -{ - dprintf("tuntap: cdev_open()\n"); - - /* grab the lock so that there can only be one thread inside */ - auto_lock l(&lock); - - /* check wether it is already open */ - if (open) - return EBUSY; - - /* bring the network interface up */ - int error = initialize_interface(); - if (error) - return error; - - open = true; - pid = proc_pid(p); - - return 0; -} - -int -tuntap_interface::cdev_close(int flags, int devtype, proc_t p) -{ - dprintf("tuntap: cdev_close()\n"); - - auto_lock l(&lock); - - if (open) { - open = false; - - /* shut down the network interface */ - shutdown_interface(); - - /* clear the queue */ - send_queue.clear(); - - /* wakeup the cdev thread and notify selects */ - wakeup(this); - selwakeup(&rsel); - - return 0; - } - - return EBADF; -} - -int -tuntap_interface::cdev_read(uio_t uio, int ioflag) -{ - auto_lock l(&lock); - - unsigned int nb = 0; - int error; - - dprintf("tuntap: cdev read\n"); - - if (!open || ifp == NULL || !(ifnet_flags(ifp) & IFF_UP)) - return EIO; - - /* fetch a new mbuf from the queue if necessary */ - mbuf_t cur_mbuf = NULL; - while (cur_mbuf == NULL) { - dprintf("tuntap: fetching new mbuf\n"); - - cur_mbuf = send_queue.dequeue(); - if (cur_mbuf == NULL) { - /* nothing in queue, block or return */ - if (!block_io) { - dprintf("tuntap: aborting (nbio)\n"); - return EWOULDBLOCK; - } else { - /* block */ - dprintf("tuntap: waiting\n"); - /* release the lock while waiting */ - l.unlock(); - error = msleep(this, NULL, PZERO | PCATCH, "tuntap", NULL); - - l.lock(); - - if (error) - return error; - - /* see whether the device was closed in the meantime */ - if (!open || ifp == NULL || !(ifnet_flags(ifp) & IFF_UP)) - return EIO; - - } - } - } - - /* notify bpf */ - notify_bpf(cur_mbuf, true); - - /* output what we have */ - do { - dprintf("tuntap: got new mbuf: %p uio_resid: %d\n", cur_mbuf, uio_resid(uio)); - - /* now we have an mbuf */ - int chunk_len = min(mbuf_len(cur_mbuf), uio_resid(uio)); - error = uiomove((char *) mbuf_data(cur_mbuf), chunk_len, uio); - if (error) { - mbuf_freem(cur_mbuf); - return error; - } - nb += chunk_len; - - dprintf("tuntap: moved %d bytes to userspace uio_resid: %d\n", chunk_len, - uio_resid(uio)); - - /* update cur_mbuf */ - cur_mbuf = mbuf_free(cur_mbuf); - - } while (uio_resid(uio) > 0 && cur_mbuf != NULL); - - /* update statistics */ - ifnet_stat_increment_out(ifp, 1, nb, 0); - - /* still data left? forget about that ;-) */ - if (cur_mbuf != NULL) - mbuf_freem(cur_mbuf); - - dprintf("tuntap: read done\n"); - - return 0; -} - -int -tuntap_interface::cdev_write(uio_t uio, int ioflag) -{ - auto_lock l(&lock); - - if (!open || ifp == NULL || !(ifnet_flags(ifp) & IFF_UP)) - return EIO; - - dprintf("tuntap: cdev write. uio_resid: %d\n", uio_resid(uio)); - - /* pack the data into an mbuf chain */ - mbuf_t first, mb; - - /* first we need an mbuf having a header */ - mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_DATA, &first); - if (first == NULL) { - log(LOG_ERR, "tuntap: could not get mbuf.\n"); - return ENOMEM; - } - mbuf_setlen(first, 0); - - unsigned int mlen = mbuf_maxlen(first); - unsigned int chunk_len; - unsigned int copied = 0; - unsigned int max_data_len = ifnet_mtu(ifp) + ifnet_hdrlen(ifp); - int error; - - /* stuff the data into the mbuf(s) */ - mb = first; - while (uio_resid(uio) > 0) { - /* copy a chunk. enforce mtu (don't know if this is correct behaviour) */ - chunk_len = min(max_data_len - copied, min(uio_resid(uio), mlen)); - error = uiomove((caddr_t) mbuf_data(mb), chunk_len, uio); - if (error) { - log(LOG_ERR, "tuntap: could not copy data from userspace: %d\n", error); - mbuf_freem(first); - return error; - } - - dprintf("tuntap: copied %d bytes, uio_resid %d\n", chunk_len, - uio_resid(uio)); - - mlen -= chunk_len; - mbuf_setlen(mb, mbuf_len(mb) + chunk_len); - copied += chunk_len; - - /* if done, break the loop */ - if (uio_resid(uio) <= 0 || copied >= max_data_len) - break; - - /* allocate a new mbuf if the current is filled */ - if (mlen == 0) { - mbuf_t next; - mbuf_get(MBUF_WAITOK, MBUF_TYPE_DATA, &next); - if (next == NULL) { - log(LOG_ERR, "tuntap: could not get mbuf.\n"); - mbuf_freem(first); - return ENOMEM; - } - mbuf_setnext(mb, next); - mb = next; - mbuf_setlen(mb, 0); - mlen = mbuf_maxlen(mb); - } - } - - /* fill in header info */ - mbuf_pkthdr_setrcvif(first, ifp); - mbuf_pkthdr_setlen(first, copied); - mbuf_pkthdr_setheader(first, mbuf_data(first)); - mbuf_set_csum_performed(first, 0, 0); - - /* update statistics */ - ifnet_stat_increment_in(ifp, 1, copied, 0); - - dprintf("tuntap: mbuf chain constructed. first: %p mb: %p len: %d data: %p\n", - first, mb, mbuf_len(first), mbuf_data(first)); - - /* notify bpf */ - notify_bpf(first, false); - - /* need to adjust the data pointer to point directly behind the linklevel header. The header - * itself is later accessed via m_pkthdr.header. Well, if something is ugly, here is it. - */ - mbuf_adj(first, ifnet_hdrlen(ifp)); - - /* pass the packet over to the network stack */ - error = ifnet_input(ifp, first, NULL); - - if (error) { - log(LOG_ERR, "tuntap: could not input packet into network stack.\n"); - mbuf_freem(first); - return error; - } - - return 0; -} - -int -tuntap_interface::cdev_ioctl(u_long cmd, caddr_t data, int fflag, proc_t p) -{ - auto_lock l(&lock); - - dprintf("tuntap: cdev ioctl: %d\n", (int) (cmd & 0xff)); - - switch (cmd) { - case FIONBIO: - /* set i/o mode */ - block_io = *((int *) data) ? false : true; - return 0; - case FIOASYNC: - /* don't allow switching it on */ - if (*((int *) data)) - return ENOTTY; - return 0; - } - - return ENOTTY; -} - -int -tuntap_interface::cdev_select(int which, void *wql, proc_t p) -{ - auto_lock l(&lock); - - int ret = 0; - - dprintf("tuntap: select. which: %d\n", which); - - switch (which) { - case FREAD: - /* check wether data is available */ - { - if (!send_queue.empty()) - ret = 1; - else { - dprintf("tuntap: select: waiting\n"); - selrecord(p, &rsel, wql); - } - } - break; - case FWRITE: - /* we are always writeable */ - ret = 1; - } - - return ret; -} - -/* interface service methods */ -errno_t -tuntap_interface::if_output(mbuf_t m) -{ - mbuf_t pkt; - - dprintf("tuntap: if output\n"); - - /* just to be sure */ - if (m == NULL) - return 0; - - if (!open || ifp == NULL || !(ifnet_flags(ifp) & IFF_UP)) { - mbuf_freem_list(m); - return EHOSTDOWN; - } - - /* check whether packet has a header */ - if ((mbuf_flags(m) & MBUF_PKTHDR) == 0) { - log(LOG_ERR, "tuntap: packet to be output has no mbuf header.\n"); - mbuf_freem_list(m); - return EINVAL; - } - - /* put the packet(s) into the output queue */ - while (m != NULL) { - /* keep pointer, iterate */ - pkt = m; - m = mbuf_nextpkt(m); - mbuf_setnextpkt(pkt, NULL); - - auto_lock l(&lock); - - if (!send_queue.enqueue(pkt)) { - mbuf_freem(pkt); - mbuf_freem_list(m); - return ENOBUFS; - } - } - - /* protect the wakeup calls with the lock, not sure they are safe. */ - { - auto_lock l(&lock); - - /* wakeup the cdev thread and notify selects */ - wakeup(this); - selwakeup(&rsel); - } - - return 0; -} - -errno_t -tuntap_interface::if_ioctl(u_int32_t cmd, void *arg) -{ - dprintf("tuntap: if ioctl: %d\n", (int) (cmd & 0xff)); - - switch (cmd) { - case SIOCSIFADDR: - { - dprintf("tuntap: if_ioctl: SIOCSIFADDR\n"); - - /* Unfortunately, ifconfig sets the address family field of an INET - * netmask to zero, which makes early mDNSresponder versions ignore - * the interface. Fix that here. This one is of the category "ugly - * workaround". Dumb Darwin... - * - * Meanwhile, Apple has fixed mDNSResponder, and recent versions of - * Leopard don't need this hack anymore. However, Tiger still has a - * broken version so we leave the hack in for now. - * - * TODO: Revisit when dropping Tiger support. - * - * Btw. If you configure other network interfaces using ifconfig, - * you run into the same problem. I still don't know how to make the - * tap devices show up in the network configuration panel... - */ - ifaddr_t ifa = (ifaddr_t) arg; - if (ifa == NULL) - return 0; - - sa_family_t af = ifaddr_address_family(ifa); - if (af != AF_INET) - return 0; - - struct ifaliasreq ifra; - int sa_size = sizeof(struct sockaddr); - if (ifaddr_address(ifa, &ifra.ifra_addr, sa_size) - || ifaddr_dstaddress(ifa, &ifra.ifra_broadaddr, sa_size) - || ifaddr_netmask(ifa, &ifra.ifra_mask, sa_size)) { - log(LOG_WARNING, - "tuntap: failed to parse interface address.\n"); - return 0; - } - - // Check that the address family fields match. If not, issue another - // SIOCAIFADDR to fix the entry. - if (ifra.ifra_addr.sa_family != af - || ifra.ifra_broadaddr.sa_family != af - || ifra.ifra_mask.sa_family != af) { - log(LOG_INFO, "tuntap: Fixing address family for %s%d\n", - family_name, unit); - - snprintf(ifra.ifra_name, sizeof(ifra.ifra_name), "%s%d", - family_name, unit); - ifra.ifra_addr.sa_family = af; - ifra.ifra_broadaddr.sa_family = af; - ifra.ifra_mask.sa_family = af; - - do_sock_ioctl(af, SIOCAIFADDR, &ifra); - } - - return 0; - } - - case SIOCSIFFLAGS: - return 0; - - case SIOCGIFSTATUS: - { - struct ifstat *stat = (struct ifstat *) arg; - int len; - char *p; - - if (stat == NULL) - return EINVAL; - - /* print status */ - len = strlen(stat->ascii); - p = stat->ascii + len; - if (open) { - snprintf(p, IFSTATMAX - len, "\topen (pid %u)\n", pid); - } else { - snprintf(p, IFSTATMAX - len, "\tclosed\n"); - } - - return 0; - } - - case SIOCSIFMTU: - { - struct ifreq *ifr = (struct ifreq *) arg; - - if (ifr == NULL) - return EINVAL; - - ifnet_set_mtu(ifp, ifr->ifr_mtu); - - return 0; - } - - case SIOCDIFADDR: - return 0; - - } - - return EOPNOTSUPP; -} - -errno_t -tuntap_interface::if_set_bpf_tap(bpf_tap_mode mode, int (*cb)(ifnet_t, mbuf_t)) -{ - dprintf("tuntap: mode %d\n", mode); - - auto_lock l(&bpf_lock); - - bpf_callback = cb; - bpf_mode = mode; - - return 0; -} - -errno_t -tuntap_interface::if_check_multi(const struct sockaddr *maddr) -{ - dprintf("tuntap: if_check_multi\n"); - - return EOPNOTSUPP; -} - -void -tuntap_interface::if_detached() -{ - dprintf("tuntap: if_detached\n"); - - /* wake unregister_interface() */ - thread_sync_lock.lock(); - interface_detached = true; - thread_sync_lock.wakeup(&interface_detached); - thread_sync_lock.unlock(); - - dprintf("if_detached done\n"); -} - |