diff options
author | adrian <adrian@FreeBSD.org> | 2012-01-11 17:41:14 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2012-01-11 17:41:14 +0000 |
commit | c3065d356b034414ae01ae3c1061af5d9895ce26 (patch) | |
tree | 7f7c7c0180b398b10772df243c0b194d815d8f51 | |
parent | 9088749a26906bbb9945b15be4961ceaa97cbda7 (diff) | |
download | FreeBSD-src-c3065d356b034414ae01ae3c1061af5d9895ce26.zip FreeBSD-src-c3065d356b034414ae01ae3c1061af5d9895ce26.tar.gz |
Introduce wtap, the beginnings of a net80211 wlan simulator.
This introduces:
* a basic wtap interface
* a HAL, which implements an abstraction layer for implementing
different device behavious;
* A visibility plugin, which allows for control over which nodes
see other nodes (useful for mesh work.)
It doesn't yet implement sta/adhoc/hostap modes but these are quite
feasible to implement.
Monthadar uses it to do 802.11s mesh verification.
The userland tools will be committed in a follow-up commit.
Submitted by: Monthadar Al Jaberi <monthadar@gmail.com>
-rw-r--r-- | sys/dev/wtap/if_medium.c | 120 | ||||
-rw-r--r-- | sys/dev/wtap/if_medium.h | 72 | ||||
-rw-r--r-- | sys/dev/wtap/if_wtap.c | 904 | ||||
-rw-r--r-- | sys/dev/wtap/if_wtap_module.c | 186 | ||||
-rw-r--r-- | sys/dev/wtap/if_wtapioctl.h | 180 | ||||
-rw-r--r-- | sys/dev/wtap/if_wtapvar.h | 163 | ||||
-rw-r--r-- | sys/dev/wtap/plugins/visibility.c | 241 | ||||
-rw-r--r-- | sys/dev/wtap/plugins/visibility.h | 56 | ||||
-rw-r--r-- | sys/dev/wtap/plugins/visibility_ioctl.h | 51 | ||||
-rw-r--r-- | sys/dev/wtap/plugins/wtap_plugin.h | 48 | ||||
-rw-r--r-- | sys/dev/wtap/wtap_hal/hal.c | 213 | ||||
-rw-r--r-- | sys/dev/wtap/wtap_hal/hal.h | 55 | ||||
-rw-r--r-- | sys/dev/wtap/wtap_hal/handler.h | 50 | ||||
-rw-r--r-- | sys/modules/wtap/Makefile | 30 |
14 files changed, 2369 insertions, 0 deletions
diff --git a/sys/dev/wtap/if_medium.c b/sys/dev/wtap/if_medium.c new file mode 100644 index 0000000..74faa5b1 --- /dev/null +++ b/sys/dev/wtap/if_medium.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#include "if_wtapvar.h" +#include "if_medium.h" + +void +init_medium(struct wtap_medium *md) +{ + + DWTAP_PRINTF("%s\n", __func__); + STAILQ_INIT(&md->md_pktbuf); + mtx_init(&md->md_mtx, "wtap_medium mtx", NULL, MTX_DEF | MTX_RECURSE); + + /* Event handler for sending packets between wtaps */ + struct eventhandler *eh = (struct eventhandler *) + malloc(sizeof(struct eventhandler), M_WTAP, M_NOWAIT | M_ZERO); + eh->tq = taskqueue_create("wtap_tx_taskq", M_NOWAIT | M_ZERO, + taskqueue_thread_enqueue, &eh->tq); + taskqueue_start_threads(&eh->tq, 1, PI_NET, "%s taskq", "wtap_medium"); + md->tx_handler = eh; + /* Mark medium closed by default */ + md->open = 0; +} + +void +deinit_medium(struct wtap_medium *md) +{ + + DWTAP_PRINTF("%s\n", __func__); + taskqueue_free(md->tx_handler->tq); + free(md->tx_handler, M_WTAP); +} + +int +medium_transmit(struct wtap_medium *md, int id, struct mbuf*m) +{ + + mtx_lock(&md->md_mtx); + if (md->open == 0){ + DWTAP_PRINTF("[%d] dropping m=%p\n", id, m); + m_free(m); + mtx_unlock(&md->md_mtx); + return 0; + } + + DWTAP_PRINTF("[%d] transmiting m=%p\n", id, m); + struct packet *p = (struct packet *)malloc(sizeof(struct packet), + M_WTAP_PACKET, M_ZERO | M_NOWAIT); + p->id = id; + p->m = m; + + STAILQ_INSERT_TAIL(&md->md_pktbuf, p, pf_list); + taskqueue_enqueue(md->tx_handler->tq, &md->tx_handler->proc); + mtx_unlock(&md->md_mtx); + + return 0; +} + +struct packet * +medium_get_next_packet(struct wtap_medium *md) +{ + struct packet *p; + + mtx_lock(&md->md_mtx); + p = STAILQ_FIRST(&md->md_pktbuf); + if (p == NULL){ + mtx_unlock(&md->md_mtx); + return NULL; + } + + STAILQ_REMOVE_HEAD(&md->md_pktbuf, pf_list); + mtx_unlock(&md->md_mtx); + return p; +} + +void +medium_open(struct wtap_medium *md) +{ + + mtx_lock(&md->md_mtx); + md->open = 1; + mtx_unlock(&md->md_mtx); +} + +void +medium_close(struct wtap_medium *md) +{ + + mtx_lock(&md->md_mtx); + md->open = 0; + mtx_unlock(&md->md_mtx); +} diff --git a/sys/dev/wtap/if_medium.h b/sys/dev/wtap/if_medium.h new file mode 100644 index 0000000..0650a5e --- /dev/null +++ b/sys/dev/wtap/if_medium.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef __DEV_WTAP_MEDIUM_H__ +#define __DEV_WTAP_MEDIUM_H__ + +#include "if_wtapvar.h" +#include "wtap_hal/handler.h" + +struct packet { + STAILQ_ENTRY(packet) pf_list; + struct mbuf * m; + int id; +}; +typedef STAILQ_HEAD(, packet) md_pkthead; + +struct wtap_medium { + struct mtx md_mtx; +#if 0 + int visibility[MAX_NBR_WTAP]; + struct stailhead *headp; + packet_head pktbuf; + STAILQ_HEAD(stailhead, packet) pktbuf; + STAILQ_HEAD(stailhead, packet) pktbuf; + /* = STAILQ_HEAD_INITIALIZER(head); */ +#endif + /* 0 means we drop packets, 1 we queue them */ + int open; + md_pkthead md_pktbuf; /* master queue */ + struct eventhandler *tx_handler; + struct timehandler *bc_handler; +}; + +extern void init_medium(struct wtap_medium *); +extern void deinit_medium(struct wtap_medium *); +extern void medium_open(struct wtap_medium *); +extern void medium_close(struct wtap_medium *); +extern int medium_transmit(struct wtap_medium *, int id, struct mbuf*); +extern struct packet *medium_get_next_packet(struct wtap_medium *); + +#endif /* __DEV_WTAP_MEDIUM_H__ */ diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c new file mode 100644 index 0000000..c257517 --- /dev/null +++ b/sys/dev/wtap/if_wtap.c @@ -0,0 +1,904 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#include "if_wtapvar.h" +#include <sys/uio.h> /* uio struct */ +#include <sys/jail.h> +#include <net/if_var.h> +#include <net/vnet.h> + +#include <net80211/ieee80211_ratectl.h> +#include "if_medium.h" + +/* device for IOCTL and read/write for debuggin purposes */ +/* Function prototypes */ +static d_open_t wtap_node_open; +static d_close_t wtap_node_close; +static d_write_t wtap_node_write; +static d_ioctl_t wtap_node_ioctl; + +static struct cdevsw wtap_cdevsw = { + .d_version = D_VERSION, + .d_flags = 0, + .d_open = wtap_node_open, + .d_close = wtap_node_close, + .d_write = wtap_node_write, + .d_ioctl = wtap_node_ioctl, + .d_name = "wtapnode", +}; + +static int +wtap_node_open(struct cdev *dev, int oflags, int devtype, struct thread *p) +{ + + int err = 0; + uprintf("Opened device \"echo\" successfully.\n"); + return(err); +} + +static int +wtap_node_close(struct cdev *dev, int fflag, int devtype, struct thread *p) +{ + + uprintf("Closing device \"echo.\"\n"); + return(0); +} + +static int +wtap_node_write(struct cdev *dev, struct uio *uio, int ioflag) +{ + int err = 0; + struct mbuf *m; + struct ifnet *ifp; + struct wtap_softc *sc; + uint8_t buf[1024]; + int buf_len; + + uprintf("write device %s \"echo.\"\n", dev->si_name); + buf_len = MIN(uio->uio_iov->iov_len, 1024); + err = copyin(uio->uio_iov->iov_base, buf, buf_len); + + if (err != 0) { + uprintf("Write failed: bad address!\n"); + return (err); + } + + MGETHDR(m, M_DONTWAIT, MT_DATA); + m_copyback(m, 0, buf_len, buf); + + CURVNET_SET(TD_TO_VNET(curthread)); + IFNET_RLOCK_NOSLEEP(); + + TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + printf("ifp->if_xname = %s\n", ifp->if_xname); + if(strcmp(dev->si_name, ifp->if_xname) == 0){ + printf("found match, correspoding wtap = %s\n", + ifp->if_xname); + sc = (struct wtap_softc *)ifp->if_softc; + printf("wtap id = %d\n", sc->id); + wtap_inject(sc, m); + } + } + + IFNET_RUNLOCK_NOSLEEP(); + CURVNET_RESTORE(); + + return(err); +} + +int +wtap_node_ioctl(struct cdev *dev, u_long cmd, caddr_t data, + int fflag, struct thread *td) +{ + int error = 0; + + switch(cmd) { + default: + DWTAP_PRINTF("Unkown WTAP IOCTL\n"); + error = EINVAL; + } + return error; +} + +static int wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params); + +static int +wtap_medium_enqueue(struct wtap_vap *avp, struct mbuf *m) +{ + + return medium_transmit(avp->av_md, avp->id, m); +} + +static int +wtap_media_change(struct ifnet *ifp) +{ + + DWTAP_PRINTF("%s\n", __func__); + int error = ieee80211_media_change(ifp); + /* NB: only the fixed rate can change and that doesn't need a reset */ + return (error == ENETRESET ? 0 : error); +} + +/* + * Intercept management frames to collect beacon rssi data + * and to do ibss merges. + */ +static void +wtap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, + int subtype, int rssi, int nf) +{ + struct ieee80211vap *vap = ni->ni_vap; +#if 0 + DWTAP_PRINTF("[%d] %s\n", myath_id(ni), __func__); +#endif + WTAP_VAP(vap)->av_recv_mgmt(ni, m, subtype, rssi, nf); +} + +static int +wtap_reset_vap(struct ieee80211vap *vap, u_long cmd) +{ + + DWTAP_PRINTF("%s\n", __func__); + return 0; +} + +static void +wtap_beacon_update(struct ieee80211vap *vap, int item) +{ + struct ieee80211_beacon_offsets *bo = &WTAP_VAP(vap)->av_boff; + + DWTAP_PRINTF("%s\n", __func__); + setbit(bo->bo_flags, item); +} + +/* + * Allocate and setup an initial beacon frame. + */ +static int +wtap_beacon_alloc(struct wtap_softc *sc, struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct wtap_vap *avp = WTAP_VAP(vap); + + DWTAP_PRINTF("[%s] %s\n", ether_sprintf(ni->ni_macaddr), __func__); + + /* + * NB: the beacon data buffer must be 32-bit aligned; + * we assume the mbuf routines will return us something + * with this alignment (perhaps should assert). + */ + avp->beacon = ieee80211_beacon_alloc(ni, &avp->av_boff); + if (avp->beacon == NULL) { + printf("%s: cannot get mbuf\n", __func__); + return ENOMEM; + } + callout_init(&avp->av_swba, 0); + avp->bf_node = ieee80211_ref_node(ni); + + return 0; +} + +static void +wtap_beacon_config(struct wtap_softc *sc, struct ieee80211vap *vap) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +static void +wtap_beacon_intrp(void *arg) +{ + struct wtap_vap *avp = arg; + struct ieee80211vap *vap = arg; + struct mbuf *m; + + KASSERT(vap->iv_state >= IEEE80211_S_RUN, + ("not running, state %d", vap->iv_state)); + DWTAP_PRINTF("[%d] beacon intrp\n", avp->id); //burst mode + /* + * Update dynamic beacon contents. If this returns + * non-zero then we need to remap the memory because + * the beacon frame changed size (probably because + * of the TIM bitmap). + */ + m = m_dup(avp->beacon, M_DONTWAIT); + if (ieee80211_beacon_update(avp->bf_node, &avp->av_boff, m, 0)) { + printf("%s, need to remap the memory because the beacon frame" + " changed size.\n",__func__); + } + + if (ieee80211_radiotap_active_vap(vap)) + ieee80211_radiotap_tx(vap, m); + +#if 0 + medium_transmit(avp->av_md, avp->id, m); +#endif + wtap_medium_enqueue(avp, m); + callout_schedule(&avp->av_swba, avp->av_bcinterval); +} + +static int +wtap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) +{ + struct ieee80211com *ic = vap->iv_ic; + struct wtap_softc *sc = ic->ic_ifp->if_softc; + struct wtap_vap *avp = WTAP_VAP(vap); + struct ieee80211_node *ni = NULL; + int error; + + DWTAP_PRINTF("%s\n", __func__); + + ni = vap->iv_bss; + /* + * Invoke the parent method to do net80211 work. + */ + error = avp->av_newstate(vap, nstate, arg); + if (error != 0) + goto bad; + + if (nstate == IEEE80211_S_RUN) { + /* NB: collect bss node again, it may have changed */ + ni = vap->iv_bss; + switch (vap->iv_opmode) { + case IEEE80211_M_MBSS: + error = wtap_beacon_alloc(sc, ni); + if (error != 0) + goto bad; + wtap_beacon_config(sc, vap); + callout_reset(&avp->av_swba, avp->av_bcinterval, + wtap_beacon_intrp, vap); + break; + default: + goto bad; + } + } + return 0; +bad: + printf("%s: bad\n", __func__); + return error; +} + +static void +wtap_bmiss(struct ieee80211vap *vap) +{ + struct wtap_vap *avp = (struct wtap_vap *)vap; + + DWTAP_PRINTF("%s\n", __func__); + avp->av_bmiss(vap); +} + +static struct ieee80211vap * +wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], + int unit, enum ieee80211_opmode opmode, int flags, + const uint8_t bssid[IEEE80211_ADDR_LEN], + const uint8_t mac[IEEE80211_ADDR_LEN]) +{ + struct wtap_softc *sc = ic->ic_ifp->if_softc; + struct ieee80211vap *vap; + struct wtap_vap *avp; + int error; + + DWTAP_PRINTF("%s\n", __func__); + + avp = (struct wtap_vap *) malloc(sizeof(struct wtap_vap), + M_80211_VAP, M_NOWAIT | M_ZERO); + avp->id = sc->id; + avp->av_md = sc->sc_md; + avp->av_bcinterval = BEACON_INTRERVAL + 100*sc->id; + vap = (struct ieee80211vap *) avp; + error = ieee80211_vap_setup(ic, vap, name, unit, IEEE80211_M_MBSS, + flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); + + /* override various methods */ + avp->av_recv_mgmt = vap->iv_recv_mgmt; + vap->iv_recv_mgmt = wtap_recv_mgmt; + vap->iv_reset = wtap_reset_vap; + vap->iv_update_beacon = wtap_beacon_update; + avp->av_newstate = vap->iv_newstate; + vap->iv_newstate = wtap_newstate; + avp->av_bmiss = vap->iv_bmiss; + vap->iv_bmiss = wtap_bmiss; + + /* complete setup */ + ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status); + avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, + (const char *)ic->ic_ifp->if_xname); + + /* TODO this is a hack to force it to choose the rate we want */ + vap->iv_bss->ni_txrate = 130; + return vap; +} + +static void +wtap_vap_delete(struct ieee80211vap *vap) +{ + struct wtap_vap *avp = WTAP_VAP(vap); + + DWTAP_PRINTF("%s\n", __func__); + destroy_dev(avp->av_dev); + callout_stop(&avp->av_swba); + ieee80211_vap_detach(vap); + free((struct wtap_vap*) vap, M_80211_VAP); +} + +/* NB: This function is not used. + * I had the problem of the queue + * being empty all the time. + * Maybe I am setting the queue wrong? + */ +static void +wtap_start(struct ifnet *ifp) +{ + struct ieee80211com *ic = ifp->if_l2com; + struct ifnet *icifp = ic->ic_ifp; + struct wtap_softc *sc = icifp->if_softc; + struct ieee80211_node *ni; + struct mbuf *m; + + DWTAP_PRINTF("my_start, with id=%u\n", sc->id); + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->up == 0) + return; + for (;;) { + if(IFQ_IS_EMPTY(&ifp->if_snd)){ + printf("queue empty, just trying to see " + "if the other queue is empty\n"); +#if 0 + printf("queue for id=1, %u\n", + IFQ_IS_EMPTY(&global_mscs[1]->ifp->if_snd)); + printf("queue for id=0, %u\n", + IFQ_IS_EMPTY(&global_mscs[0]->ifp->if_snd)); +#endif + break; + } + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) { + printf("error dequeueing from ifp->snd\n"); + break; + } + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + /* + * Check for fragmentation. If this frame + * has been broken up verify we have enough + * buffers to send all the fragments so all + * go out or none... + */ +#if 0 + STAILQ_INIT(&frags); +#endif + if ((m->m_flags & M_FRAG)){ + printf("dont support frags\n"); + ifp->if_oerrors++; + return; + } + ifp->if_opackets++; + if(wtap_raw_xmit(ni, m, NULL) < 0){ + printf("error raw_xmiting\n"); + ifp->if_oerrors++; + return; + } + } +} + +static int +wtap_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ +#if 0 + DWTAP_PRINTF("%s\n", __func__); + uprintf("%s, command %lu\n", __func__, cmd); +#endif +#define IS_RUNNING(ifp) \ + ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) + struct ieee80211com *ic = ifp->if_l2com; + struct wtap_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + int error = 0; + + switch (cmd) { + case SIOCSIFFLAGS: + //printf("%s: %s\n", __func__, "SIOCSIFFLAGS"); + if (IS_RUNNING(ifp)) { + DWTAP_PRINTF("running\n"); +#if 0 + /* + * To avoid rescanning another access point, + * do not call ath_init() here. Instead, + * only reflect promisc mode settings. + */ + //ath_mode_init(sc); +#endif + } else if (ifp->if_flags & IFF_UP) { + DWTAP_PRINTF("up\n"); + sc->up = 1; +#if 0 + /* + * Beware of being called during attach/detach + * to reset promiscuous mode. In that case we + * will still be marked UP but not RUNNING. + * However trying to re-init the interface + * is the wrong thing to do as we've already + * torn down much of our state. There's + * probably a better way to deal with this. + */ + //if (!sc->sc_invalid) + // ath_init(sc); /* XXX lose error */ +#endif + ifp->if_drv_flags |= IFF_DRV_RUNNING; + ieee80211_start_all(ic); + } else { + DWTAP_PRINTF("stoping\n"); +#if 0 + ath_stop_locked(ifp); +#ifdef notyet + /* XXX must wakeup in places like ath_vap_delete */ + if (!sc->sc_invalid) + ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); +#endif +#endif + } + break; + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: +#if 0 + DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFMEDIA|SIOCSIFMEDIA"); +#endif + error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); + break; + case SIOCGIFADDR: +#if 0 + DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFADDR"); +#endif + error = ether_ioctl(ifp, cmd, data); + break; + default: + DWTAP_PRINTF("%s: %s [%lu]\n", __func__, "EINVAL", cmd); + error = EINVAL; + break; + } + return error; +#undef IS_RUNNING +} + +static void +wtap_init(void *arg){ + + DWTAP_PRINTF("%s\n", __func__); +} + +static void +wtap_scan_start(struct ieee80211com *ic) +{ + +#if 0 + DWTAP_PRINTF("%s\n", __func__); +#endif +} + +static void +wtap_scan_end(struct ieee80211com *ic) +{ + +#if 0 + DWTAP_PRINTF("%s\n", __func__); +#endif +} + +static void +wtap_set_channel(struct ieee80211com *ic) +{ + +#if 0 + DWTAP_PRINTF("%s\n", __func__); +#endif +} + +static int +wtap_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params) +{ +#if 0 + DWTAP_PRINTF("%s, %p\n", __func__, m); +#endif + struct ieee80211vap *vap = ni->ni_vap; + struct wtap_vap *avp = WTAP_VAP(vap); + + if (ieee80211_radiotap_active_vap(vap)) { + ieee80211_radiotap_tx(vap, m); + } + if (m->m_flags & M_TXCB) + ieee80211_process_callback(ni, m, 0); + ieee80211_free_node(ni); + return wtap_medium_enqueue(avp, m); +} + +void +wtap_inject(struct wtap_softc *sc, struct mbuf *m) +{ + struct wtap_buf *bf = (struct wtap_buf *)malloc(sizeof(struct wtap_buf), + M_WTAP_RXBUF, M_NOWAIT | M_ZERO); + KASSERT(bf != NULL, ("could not allocated a new wtap_buf\n")); + bf->m = m; + + mtx_lock(&sc->sc_mtx); + STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); + mtx_unlock(&sc->sc_mtx); +} + +void +wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211_node *ni; + int type; +#if 0 + DWTAP_PRINTF("%s\n", __func__); +#endif + + DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, m); + if (m == NULL) { /* NB: shouldn't happen */ + if_printf(ifp, "%s: no mbuf!\n", __func__); + } + + ifp->if_ipackets++; + + ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0); + + /* + * Locate the node for sender, track state, and then + * pass the (referenced) node up to the 802.11 layer + * for its use. + */ + ni = ieee80211_find_rxnode_withkey(ic, + mtod(m, const struct ieee80211_frame_min *),IEEE80211_KEYIX_NONE); + if (ni != NULL) { + /* + * Sending station is known, dispatch directly. + */ + type = ieee80211_input(ni, m, 1<<7, 10); + ieee80211_free_node(ni); + } else { + type = ieee80211_input_all(ic, m, 1<<7, 10); + } +} + +static void +wtap_rx_proc(void *arg, int npending) +{ + struct wtap_softc *sc = (struct wtap_softc *)arg; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct mbuf *m; + struct ieee80211_node *ni; + int type; + struct wtap_buf *bf; + +#if 0 + DWTAP_PRINTF("%s\n", __func__); +#endif + + for(;;) { + mtx_lock(&sc->sc_mtx); + bf = STAILQ_FIRST(&sc->sc_rxbuf); + if (bf == NULL) { + mtx_unlock(&sc->sc_mtx); + return; + } + STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list); + mtx_unlock(&sc->sc_mtx); + KASSERT(bf != NULL, ("wtap_buf is NULL\n")); + m = bf->m; + DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, bf->m); + if (m == NULL) { /* NB: shouldn't happen */ + if_printf(ifp, "%s: no mbuf!\n", __func__); + free(bf, M_WTAP_RXBUF); + return; + } + + ifp->if_ipackets++; +#if 0 + ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0); +#endif + + /* + * Locate the node for sender, track state, and then + * pass the (referenced) node up to the 802.11 layer + * for its use. + */ + ni = ieee80211_find_rxnode_withkey(ic, + mtod(m, const struct ieee80211_frame_min *), + IEEE80211_KEYIX_NONE); + if (ni != NULL) { + /* + * Sending station is known, dispatch directly. + */ +#if 0 + ieee80211_radiotap_rx(ni->ni_vap, m); +#endif + type = ieee80211_input(ni, m, 1<<7, 10); + ieee80211_free_node(ni); + } else { +#if 0 + ieee80211_radiotap_rx_all(ic, m); +#endif + type = ieee80211_input_all(ic, m, 1<<7, 10); + } + + /* The mbufs are freed by the Net80211 stack */ + free(bf, M_WTAP_RXBUF); + } +} + +static void +wtap_newassoc(struct ieee80211_node *ni, int isnew) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +/* + * Callback from the 802.11 layer to update WME parameters. + */ +static int +wtap_wme_update(struct ieee80211com *ic) +{ + + DWTAP_PRINTF("%s\n", __func__); + return 0; +} + +static void +wtap_update_mcast(struct ifnet *ifp) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +static void +wtap_update_promisc(struct ifnet *ifp) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +static int +wtap_if_transmit(struct ifnet *ifp, struct mbuf *m) +{ + struct ieee80211_node *ni = + (struct ieee80211_node *) m->m_pkthdr.rcvif; + struct ieee80211vap *vap = ni->ni_vap; + struct wtap_vap *avp = WTAP_VAP(vap); + + if(ni == NULL){ + printf("m->m_pkthdr.rcvif is NULL we cant radiotap_tx\n"); + }else{ + if (ieee80211_radiotap_active_vap(vap)) + ieee80211_radiotap_tx(vap, m); + } + if (m->m_flags & M_TXCB) + ieee80211_process_callback(ni, m, 0); + ieee80211_free_node(ni); + return wtap_medium_enqueue(avp, m); +} + +static struct ieee80211_node * +wtap_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) +{ + struct ieee80211_node *ni; + + DWTAP_PRINTF("%s\n", __func__); + + ni = malloc(sizeof(struct ieee80211_node), M_80211_NODE, + M_NOWAIT|M_ZERO); + + ni->ni_txrate = 130; + return ni; +} + +static void +wtap_node_free(struct ieee80211_node *ni) +{ + struct ieee80211com *ic = ni->ni_ic; + struct wtap_softc *sc = ic->ic_ifp->if_softc; + + DWTAP_PRINTF("%s\n", __func__); + sc->sc_node_free(ni); +} + +int32_t +wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr) +{ + struct ifnet *ifp; + struct ieee80211com *ic; + char wtap_name[] = {'w','T','a','p',sc->id, + '_','t','a','s','k','q','\0'}; + + DWTAP_PRINTF("%s\n", __func__); + + ifp = if_alloc(IFT_IEEE80211); + if (ifp == NULL) { + printf("can not if_alloc()\n"); + return -1; + } + ic = ifp->if_l2com; + if_initname(ifp, "wtap", sc->id); + + sc->sc_ifp = ifp; + sc->up = 0; + + STAILQ_INIT(&sc->sc_rxbuf); + sc->sc_tq = taskqueue_create(wtap_name, M_NOWAIT | M_ZERO, + taskqueue_thread_enqueue, &sc->sc_tq); + taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ", + ifp->if_xname); + TASK_INIT(&sc->sc_rxtask, 0, wtap_rx_proc, sc); + + ifp->if_softc = sc; + ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; + ifp->if_start = wtap_start; + ifp->if_ioctl = wtap_ioctl; + ifp->if_init = wtap_init; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; + IFQ_SET_READY(&ifp->if_snd); + + ic->ic_ifp = ifp; + ic->ic_phytype = IEEE80211_T_DS; + ic->ic_opmode = IEEE80211_M_MBSS; + ic->ic_caps = IEEE80211_C_MBSS; + + ic->ic_max_keyix = 128; /* A value read from Atheros ATH_KEYMAX */ + + ic->ic_regdomain.regdomain = SKU_ETSI; + ic->ic_regdomain.country = CTRY_SWEDEN; + ic->ic_regdomain.location = 1; /* Indoors */ + ic->ic_regdomain.isocc[0] = 'S'; + ic->ic_regdomain.isocc[1] = 'E'; + /* + * Indicate we need the 802.11 header padded to a + * 32-bit boundary for 4-address and QoS frames. + */ + ic->ic_flags |= IEEE80211_F_DATAPAD; + ic->ic_nchans = 1; + ic->ic_channels[0].ic_flags = IEEE80211_CHAN_B; + ic->ic_channels[0].ic_freq = 2412; + + ieee80211_ifattach(ic, macaddr); + +#if 0 + /* new prototype hook-ups */ + msc->if_input = ifp->if_input; + ifp->if_input = myath_if_input; + msc->if_output = ifp->if_output; + ifp->if_output = myath_if_output; +#endif + sc->if_transmit = ifp->if_transmit; + ifp->if_transmit = wtap_if_transmit; + + /* override default methods */ + ic->ic_newassoc = wtap_newassoc; +#if 0 + ic->ic_updateslot = myath_updateslot; +#endif + ic->ic_wme.wme_update = wtap_wme_update; + ic->ic_vap_create = wtap_vap_create; + ic->ic_vap_delete = wtap_vap_delete; + ic->ic_raw_xmit = wtap_raw_xmit; + ic->ic_update_mcast = wtap_update_mcast; + ic->ic_update_promisc = wtap_update_promisc; + + sc->sc_node_alloc = ic->ic_node_alloc; + ic->ic_node_alloc = wtap_node_alloc; + sc->sc_node_free = ic->ic_node_free; + ic->ic_node_free = wtap_node_free; + +#if 0 + ic->ic_node_getsignal = myath_node_getsignal; +#endif + ic->ic_scan_start = wtap_scan_start; + ic->ic_scan_end = wtap_scan_end; + ic->ic_set_channel = wtap_set_channel; + + ieee80211_radiotap_attach(ic, + &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), + WTAP_TX_RADIOTAP_PRESENT, + &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), + WTAP_RX_RADIOTAP_PRESENT); + + /* Work here, we must find a way to populate the rate table */ +#if 0 + if(ic->ic_rt == NULL){ + printf("no table for ic_curchan\n"); + ic->ic_rt = ieee80211_get_ratetable(&ic->ic_channels[0]); + } + printf("ic->ic_rt =%p\n", ic->ic_rt); + printf("rate count %d\n", ic->ic_rt->rateCount); + + uint8_t code = ic->ic_rt->info[0].dot11Rate; + uint8_t cix = ic->ic_rt->info[0].ctlRateIndex; + uint8_t ctl_rate = ic->ic_rt->info[cix].dot11Rate; + printf("code=%d, cix=%d, ctl_rate=%d\n", code, cix, ctl_rate); + + uint8_t rix0 = ic->ic_rt->rateCodeToIndex[130]; + uint8_t rix1 = ic->ic_rt->rateCodeToIndex[132]; + uint8_t rix2 = ic->ic_rt->rateCodeToIndex[139]; + uint8_t rix3 = ic->ic_rt->rateCodeToIndex[150]; + printf("rix0 %u,rix1 %u,rix2 %u,rix3 %u\n", rix0,rix1,rix2,rix3); + printf("lpAckDuration=%u\n", ic->ic_rt->info[0].lpAckDuration); + printf("rate=%d\n", ic->ic_rt->info[0].rateKbps); +#endif + return 0; +} + +int32_t +wtap_detach(struct wtap_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + + DWTAP_PRINTF("%s\n", __func__); + ieee80211_ageq_drain(&ic->ic_stageq); + ieee80211_ifdetach(ic); + if_free(ifp); + return 0; +} + +void +wtap_resume(struct wtap_softc *sc) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +void +wtap_suspend(struct wtap_softc *sc) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +void +wtap_shutdown(struct wtap_softc *sc) +{ + + DWTAP_PRINTF("%s\n", __func__); +} + +void +wtap_intr(struct wtap_softc *sc) +{ + + DWTAP_PRINTF("%s\n", __func__); +} diff --git a/sys/dev/wtap/if_wtap_module.c b/sys/dev/wtap/if_wtap_module.c new file mode 100644 index 0000000..d0108af --- /dev/null +++ b/sys/dev/wtap/if_wtap_module.c @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#include <sys/param.h> +#include <sys/module.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/ucred.h> +#include <sys/jail.h> + +#include <sys/types.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#include <sys/callout.h> +#include <sys/endian.h> +#include <sys/kthread.h> +#include <sys/taskqueue.h> +#include <sys/priv.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_types.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_llc.h> +#include <net/vnet.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_regdomain.h> + +#include <net/bpf.h> + + +#include <sys/errno.h> +#include <sys/conf.h> /* cdevsw struct */ +#include <sys/uio.h> /* uio struct */ + + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#include "if_wtapvar.h" +#include "if_wtapioctl.h" +#include "if_medium.h" +#include "wtap_hal/hal.h" + +/* WTAP PLUGINS */ +#include "plugins/visibility.h" + +MALLOC_DEFINE(M_WTAP, "wtap", "wtap wireless simulator"); +MALLOC_DEFINE(M_WTAP_PACKET, "wtap packet", "wtap wireless simulator packet"); +MALLOC_DEFINE(M_WTAP_RXBUF, "wtap rxbuf", + "wtap wireless simulator recieve buffer"); +MALLOC_DEFINE(M_WTAP_PLUGIN, "wtap plugin", "wtap wireless simulator plugin"); + +static struct wtap_hal *hal; + +/* Function prototypes */ +static d_ioctl_t wtap_ioctl; + +static struct cdev *sdev; +static struct cdevsw wtap_cdevsw = { + .d_version = D_VERSION, + .d_flags = 0, + .d_ioctl = wtap_ioctl, + .d_name = "wtapctl", +}; + +int +wtap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, + int fflag, struct thread *td) +{ + int error = 0; + + CURVNET_SET(CRED_TO_VNET(curthread->td_ucred)); + + switch(cmd) { + case WTAPIOCTLCRT: + if(new_wtap(hal, *(int *)data)) + error = EINVAL; + break; + case WTAPIOCTLDEL: + if(free_wtap(hal, *(int *)data)) + error = EINVAL; + break; + default: + DWTAP_PRINTF("Unkown WTAP IOCTL\n"); + error = EINVAL; + } + + CURVNET_RESTORE(); + return error; +} + + +/* The function called at load/unload. */ +static int +event_handler(module_t module, int event, void *arg) +{ + struct visibility_plugin *plugin; + int e = 0; /* Error, 0 for normal return status */ + + switch (event) { + case MOD_LOAD: + sdev = make_dev(&wtap_cdevsw,0,UID_ROOT, + GID_WHEEL,0600,(const char *)"wtapctl"); + hal = (struct wtap_hal *)malloc(sizeof(struct wtap_hal), + M_WTAP, M_NOWAIT | M_ZERO); + bzero(hal, sizeof(struct wtap_hal)); + + init_hal(hal); + + /* Setting up a simple plugin */ + plugin = (struct visibility_plugin *)malloc + (sizeof(struct visibility_plugin), M_WTAP_PLUGIN, + M_NOWAIT | M_ZERO); + plugin->base.wp_hal = hal; + plugin->base.init = visibility_init; + plugin->base.deinit = visibility_deinit; + plugin->base.work = visibility_work; + register_plugin(hal, (struct wtap_plugin *)plugin); + + printf("Loaded wtap wireless simulator\n"); + break; + case MOD_UNLOAD: + destroy_dev(sdev); + deregister_plugin(hal); + deinit_hal(hal); + free(hal, M_WTAP); + printf("Unloading wtap wireless simulator\n"); + break; + default: + e = EOPNOTSUPP; /* Error, Operation Not Supported */ + break; + } + + return(e); +} + +/* The second argument of DECLARE_MODULE. */ +static moduledata_t wtap_conf = { + "wtap", /* module name */ + event_handler, /* event handler */ + NULL /* extra data */ +}; + +DECLARE_MODULE(wtap, wtap_conf, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); diff --git a/sys/dev/wtap/if_wtapioctl.h b/sys/dev/wtap/if_wtapioctl.h new file mode 100644 index 0000000..23d0f17 --- /dev/null +++ b/sys/dev/wtap/if_wtapioctl.h @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +/* + * Ioctl-related defintions for the Wireless TAP + * based on Atheros Wireless LAN controller driver. + */ + +#ifndef _DEV_WTAP_WTAPIOCTL_H +#define _DEV_WTAP_WTAPIOCTL_H + +#include <sys/param.h> +#include <net80211/ieee80211_radiotap.h> + +#define SIOCGATHSTATS _IOWR('i', 137, struct ifreq) +#define SIOCZATHSTATS _IOWR('i', 139, struct ifreq) + +#define WTAPIOCTLCRT _IOW('W', 1, int) +#define WTAPIOCTLDEL _IOW('W', 2, int) + +struct wtap_stats { + u_int32_t ast_watchdog; /* device reset by watchdog */ + u_int32_t ast_hardware; /* fatal hardware error interrupts */ + u_int32_t ast_bmiss; /* beacon miss interrupts */ + u_int32_t ast_bmiss_phantom;/* beacon miss interrupts */ + u_int32_t ast_bstuck; /* beacon stuck interrupts */ + u_int32_t ast_rxorn; /* rx overrun interrupts */ + u_int32_t ast_rxeol; /* rx eol interrupts */ + u_int32_t ast_txurn; /* tx underrun interrupts */ + u_int32_t ast_mib; /* mib interrupts */ + u_int32_t ast_intrcoal; /* interrupts coalesced */ + u_int32_t ast_tx_packets; /* packet sent on the interface */ + u_int32_t ast_tx_mgmt; /* management frames transmitted */ + u_int32_t ast_tx_discard; /* frames discarded prior to assoc */ + u_int32_t ast_tx_qstop; /* output stopped 'cuz no buffer */ + u_int32_t ast_tx_encap; /* tx encapsulation failed */ + u_int32_t ast_tx_nonode; /* tx failed 'cuz no node */ + u_int32_t ast_tx_nombuf; /* tx failed 'cuz no mbuf */ + u_int32_t ast_tx_nomcl; /* tx failed 'cuz no cluster */ + u_int32_t ast_tx_linear; /* tx linearized to cluster */ + u_int32_t ast_tx_nodata; /* tx discarded empty frame */ + u_int32_t ast_tx_busdma; /* tx failed for dma resrcs */ + u_int32_t ast_tx_xretries;/* tx failed 'cuz too many retries */ + u_int32_t ast_tx_fifoerr; /* tx failed 'cuz FIFO underrun */ + u_int32_t ast_tx_filtered;/* tx failed 'cuz xmit filtered */ + u_int32_t ast_tx_shortretry;/* tx on-chip retries (short) */ + u_int32_t ast_tx_longretry;/* tx on-chip retries (long) */ + u_int32_t ast_tx_badrate; /* tx failed 'cuz bogus xmit rate */ + u_int32_t ast_tx_noack; /* tx frames with no ack marked */ + u_int32_t ast_tx_rts; /* tx frames with rts enabled */ + u_int32_t ast_tx_cts; /* tx frames with cts enabled */ + u_int32_t ast_tx_shortpre;/* tx frames with short preamble */ + u_int32_t ast_tx_altrate; /* tx frames with alternate rate */ + u_int32_t ast_tx_protect; /* tx frames with protection */ + u_int32_t ast_tx_ctsburst;/* tx frames with cts and bursting */ + u_int32_t ast_tx_ctsext; /* tx frames with cts extension */ + u_int32_t ast_rx_nombuf; /* rx setup failed 'cuz no mbuf */ + u_int32_t ast_rx_busdma; /* rx setup failed for dma resrcs */ + u_int32_t ast_rx_orn; /* rx failed 'cuz of desc overrun */ + u_int32_t ast_rx_crcerr; /* rx failed 'cuz of bad CRC */ + u_int32_t ast_rx_fifoerr; /* rx failed 'cuz of FIFO overrun */ + u_int32_t ast_rx_badcrypt;/* rx failed 'cuz decryption */ + u_int32_t ast_rx_badmic; /* rx failed 'cuz MIC failure */ + u_int32_t ast_rx_phyerr; /* rx failed 'cuz of PHY err */ + u_int32_t ast_rx_phy[32]; /* rx PHY error per-code counts */ + u_int32_t ast_rx_tooshort;/* rx discarded 'cuz frame too short */ + u_int32_t ast_rx_toobig; /* rx discarded 'cuz frame too large */ + u_int32_t ast_rx_packets; /* packet recv on the interface */ + u_int32_t ast_rx_mgt; /* management frames received */ + u_int32_t ast_rx_ctl; /* rx discarded 'cuz ctl frame */ + int8_t ast_tx_rssi; /* tx rssi of last ack */ + int8_t ast_rx_rssi; /* rx rssi from histogram */ + u_int8_t ast_tx_rate; /* IEEE rate of last unicast tx */ + u_int32_t ast_be_xmit; /* beacons transmitted */ + u_int32_t ast_be_nombuf; /* beacon setup failed 'cuz no mbuf */ + u_int32_t ast_per_cal; /* periodic calibration calls */ + u_int32_t ast_per_calfail;/* periodic calibration failed */ + u_int32_t ast_per_rfgain; /* periodic calibration rfgain reset */ + u_int32_t ast_rate_calls; /* rate control checks */ + u_int32_t ast_rate_raise; /* rate control raised xmit rate */ + u_int32_t ast_rate_drop; /* rate control dropped xmit rate */ + u_int32_t ast_ant_defswitch;/* rx/default antenna switches */ + u_int32_t ast_ant_txswitch;/* tx antenna switches */ + u_int32_t ast_ant_rx[8]; /* rx frames with antenna */ + u_int32_t ast_ant_tx[8]; /* tx frames with antenna */ + u_int32_t ast_cabq_xmit; /* cabq frames transmitted */ + u_int32_t ast_cabq_busy; /* cabq found busy */ + u_int32_t ast_tx_raw; /* tx frames through raw api */ + u_int32_t ast_ff_txok; /* fast frames tx'd successfully */ + u_int32_t ast_ff_txerr; /* fast frames tx'd w/ error */ + u_int32_t ast_ff_rx; /* fast frames rx'd */ + u_int32_t ast_ff_flush; /* fast frames flushed from staging q */ + u_int32_t ast_tx_qfull; /* tx dropped 'cuz of queue limit */ + int8_t ast_rx_noise; /* rx noise floor */ + u_int32_t ast_tx_nobuf; /* tx dropped 'cuz no ath buffer */ + u_int32_t ast_tdma_update;/* TDMA slot timing updates */ + u_int32_t ast_tdma_timers;/* TDMA slot update set beacon timers */ + u_int32_t ast_tdma_tsf; /* TDMA slot update set TSF */ + u_int16_t ast_tdma_tsfadjp;/* TDMA slot adjust+ (usec, smoothed)*/ + u_int16_t ast_tdma_tsfadjm;/* TDMA slot adjust- (usec, smoothed)*/ + u_int32_t ast_tdma_ack; /* TDMA tx failed 'cuz ACK required */ + u_int32_t ast_tx_raw_fail;/* raw tx failed 'cuz h/w down */ + u_int32_t ast_tx_nofrag; /* tx dropped 'cuz no ath frag buffer */ + u_int32_t ast_be_missed; /* missed beacons */ + u_int32_t ast_pad[13]; +}; + +/* + * Radio capture format. + */ +#define WTAP_RX_RADIOTAP_PRESENT ( \ + 0) + +struct wtap_rx_radiotap_header { + struct ieee80211_radiotap_header wr_ihdr; +#if 0 + u_int64_t wr_tsf; + u_int8_t wr_flags; + u_int8_t wr_rate; + int8_t wr_antsignal; + int8_t wr_antnoise; + u_int8_t wr_antenna; + u_int8_t wr_pad[3]; + u_int32_t wr_chan_flags; + u_int16_t wr_chan_freq; + u_int8_t wr_chan_ieee; + int8_t wr_chan_maxpow; +#endif +} __packed; + +#define WTAP_TX_RADIOTAP_PRESENT ( \ + 0) + +struct wtap_tx_radiotap_header { + struct ieee80211_radiotap_header wt_ihdr; +#if 0 + u_int64_t wt_tsf; + u_int8_t wt_flags; + u_int8_t wt_rate; + u_int8_t wt_txpower; + u_int8_t wt_antenna; + u_int32_t wt_chan_flags; + u_int16_t wt_chan_freq; + u_int8_t wt_chan_ieee; + int8_t wt_chan_maxpow; +#endif +} __packed; + +#endif diff --git a/sys/dev/wtap/if_wtapvar.h b/sys/dev/wtap/if_wtapvar.h new file mode 100644 index 0000000..bb165b4 --- /dev/null +++ b/sys/dev/wtap/if_wtapvar.h @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _DEV_WTAP_WTAPVAR_H +#define _DEV_WTAP_WTAPVAR_H + +#include <sys/cdefs.h> +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/module.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <sys/types.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#include <sys/callout.h> +#include <sys/endian.h> +#include <sys/kthread.h> +#include <sys/taskqueue.h> +#include <sys/priv.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_types.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_llc.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_regdomain.h> + +#include <net/bpf.h> + +#include <net/vnet.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#if 0 +#define DWTAP_PRINTF(...) printf(__VA_ARGS__) +#else +#define DWTAP_PRINTF(...) +#endif + +#include "if_wtapioctl.h" + +#define MAX_NBR_WTAP (64) +#define BEACON_INTRERVAL (1000) + +MALLOC_DECLARE(M_WTAP); +MALLOC_DECLARE(M_WTAP_PACKET); +MALLOC_DECLARE(M_WTAP_BEACON); +MALLOC_DECLARE(M_WTAP_RXBUF); +MALLOC_DECLARE(M_WTAP_PLUGIN); + +/* driver-specific node state */ +struct wtap_node { + struct ieee80211_node an_node; /* base class */ + /* future addons */ +}; +#define WTAP_NODE(ni) ((struct ath_node *)(ni)) +#define WTAP_NODE_CONST(ni) ((const struct ath_node *)(ni)) + +struct wtap_buf { + STAILQ_ENTRY(wtap_buf) bf_list; + struct mbuf *m; /* mbuf for buf */ +}; +typedef STAILQ_HEAD(, wtap_buf) wtap_bufhead; + +#define WTAP_BUF_BUSY 0x00000002 /* (tx) desc owned by h/w */ + +struct wtap_vap { + struct ieee80211vap av_vap; /* base class */ + int32_t id; /* wtap id */ + struct cdev *av_dev; /* userspace injecting frames */ + struct wtap_medium *av_md; /* back pointer */ + struct mbuf *beacon; /* beacon */ + struct ieee80211_node *bf_node; /* pointer to the node */ + struct ieee80211_beacon_offsets av_boff;/* dynamic update state */ + struct callout av_swba; /* software beacon alert */ + uint32_t av_bcinterval; /* beacon interval */ + void (*av_recv_mgmt)(struct ieee80211_node *, + struct mbuf *, int, int, int); + int (*av_newstate)(struct ieee80211vap *, + enum ieee80211_state, int); + void (*av_bmiss)(struct ieee80211vap *); +}; +#define WTAP_VAP(vap) ((struct wtap_vap *)(vap)) + +struct taskqueue; + +struct wtap_softc { + int32_t id; + int32_t up; + struct ifnet *sc_ifp; /* interface common */ + struct wtap_medium *sc_md; /* interface medium */ + struct ieee80211_node* (* sc_node_alloc) + (struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]); + void (*sc_node_free)(struct ieee80211_node *); + int (*if_output) /* output routine (enqueue) */ + (struct ifnet *, struct mbuf *, struct sockaddr *, struct route *); + void (*if_input) (struct ifnet *, struct mbuf *);/* from h/w driver */ + int (*if_transmit)(struct ifnet *, struct mbuf *);/* output routine */ + struct mtx sc_mtx; /* master lock (recursive) */ + struct taskqueue *sc_tq; /* private task queue */ + wtap_bufhead sc_rxbuf; /* receive buffer */ + struct task sc_rxtask; /* rx int processing */ + struct wtap_tx_radiotap_header sc_tx_th; + int sc_tx_th_len; + struct wtap_rx_radiotap_header sc_rx_th; + int sc_rx_th_len; +}; + +int32_t wtap_attach(struct wtap_softc *, const uint8_t *macaddr); +int32_t wtap_detach(struct wtap_softc *); +void wtap_resume(struct wtap_softc *); +void wtap_suspend(struct wtap_softc *); +void wtap_shutdown(struct wtap_softc *); +void wtap_intr(struct wtap_softc *); +void wtap_inject(struct wtap_softc *, struct mbuf *); +void wtap_rx_deliver(struct wtap_softc *, struct mbuf *); + +#endif diff --git a/sys/dev/wtap/plugins/visibility.c b/sys/dev/wtap/plugins/visibility.c new file mode 100644 index 0000000..9d2624c --- /dev/null +++ b/sys/dev/wtap/plugins/visibility.c @@ -0,0 +1,241 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#include <sys/param.h> +#include <sys/module.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/ucred.h> +#include <sys/jail.h> + +#include <sys/types.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#include <sys/callout.h> +#include <sys/endian.h> +#include <sys/kthread.h> +#include <sys/taskqueue.h> +#include <sys/priv.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_types.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_llc.h> +#include <net/vnet.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_regdomain.h> + +#include <net/bpf.h> + + +#include <sys/errno.h> +#include <sys/conf.h> /* cdevsw struct */ +#include <sys/uio.h> /* uio struct */ + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#include "visibility.h" + +/* Function prototypes */ +static d_ioctl_t vis_ioctl; + +static struct cdevsw vis_cdevsw = { + .d_version = D_VERSION, + .d_flags = 0, + .d_ioctl = vis_ioctl, + .d_name = "visctl", +}; + +void +visibility_init(struct wtap_plugin *plugin) +{ + struct visibility_plugin *vis_plugin; + + vis_plugin = (struct visibility_plugin *) plugin; + plugin->wp_sdev = make_dev(&vis_cdevsw,0,UID_ROOT,GID_WHEEL,0600, + (const char *)"visctl"); + plugin->wp_sdev->si_drv1 = vis_plugin; + mtx_init(&vis_plugin->pl_mtx, "visibility_plugin mtx", + NULL, MTX_DEF | MTX_RECURSE); + printf("Using visibility wtap plugin...\n"); +} + +void +visibility_deinit(struct wtap_plugin *plugin) +{ + struct visibility_plugin *vis_plugin; + + vis_plugin = (struct visibility_plugin *) plugin; + destroy_dev(plugin->wp_sdev); + mtx_destroy(&vis_plugin->pl_mtx); + free(vis_plugin, M_WTAP_PLUGIN); + printf("Removing visibility wtap plugin...\n"); +} + +/* We need to use a mutex lock when we read out a visibility map + * and when we change visibility map from user space through IOCTL + */ +void +visibility_work(struct wtap_plugin *plugin, struct packet *p) +{ + struct visibility_plugin *vis_plugin = + (struct visibility_plugin *) plugin; + struct wtap_hal *hal = (struct wtap_hal *)vis_plugin->base.wp_hal; + struct vis_map *map; + + KASSERT(mtod(p->m, const char *) != (const char *) 0xdeadc0de || + mtod(p->m, const char *) != NULL, + ("[%s] got a corrupt packet from master queue, p->m=%p, p->id=%d\n", + __func__, p->m, p->id)); + DWTAP_PRINTF("[%d] BROADCASTING m=%p\n", p->id, p->m); + mtx_lock(&vis_plugin->pl_mtx); + map = &vis_plugin->pl_node[p->id]; + mtx_unlock(&vis_plugin->pl_mtx); + + /* This is O(n*n) which is not optimal for large + * number of nodes. Another way of doing it is + * creating groups of nodes that hear each other. + * Atleast for this simple static node plugin. + */ + for(int i=0; i<ARRAY_SIZE; ++i){ + uint32_t index = map->map[i]; + for(int j=0; j<32; ++j){ + int vis = index & 0x01; + if(vis){ + int k = i*ARRAY_SIZE + j; + if(hal->hal_devs[k] != NULL + && hal->hal_devs[k]->up == 1){ + struct wtap_softc *sc = + hal->hal_devs[k]; + struct mbuf *m = + m_dup(p->m, M_DONTWAIT); + DWTAP_PRINTF("[%d] duplicated old_m=%p" + "to new_m=%p\n", p->id, p->m, m); +#if 0 + printf("[%d] sending to %d\n", + p->id, k); +#endif + wtap_inject(sc, m); + } + } + index = index >> 1; + } + } +} + +static void +add_link(struct visibility_plugin *vis_plugin, struct link *l) +{ + + mtx_lock(&vis_plugin->pl_mtx); + struct vis_map *map = &vis_plugin->pl_node[l->id1]; + int index = l->id2/ARRAY_SIZE; + int bit = l->id2 % ARRAY_SIZE; + uint32_t value = 1 << bit; + map->map[index] = map->map[index] | value; + mtx_unlock(&vis_plugin->pl_mtx); +#if 0 + printf("l->id1=%d, l->id2=%d, map->map[%d] = %u, bit=%d\n", + l->id1, l->id2, index, map->map[index], bit); +#endif +} + +static void +del_link(struct visibility_plugin *vis_plugin, struct link *l) +{ + + mtx_lock(&vis_plugin->pl_mtx); + struct vis_map *map = &vis_plugin->pl_node[l->id1]; + int index = l->id2/ARRAY_SIZE; + int bit = l->id2 % ARRAY_SIZE; + uint32_t value = 1 << bit; + map->map[index] = map->map[index] & ~value; + mtx_unlock(&vis_plugin->pl_mtx); +#if 0 + printf("map->map[index] = %u\n", map->map[index]); +#endif +} + + +int +vis_ioctl(struct cdev *sdev, u_long cmd, caddr_t data, + int fflag, struct thread *td) +{ + struct visibility_plugin *vis_plugin = + (struct visibility_plugin *) sdev->si_drv1; + struct wtap_hal *hal = vis_plugin->base.wp_hal; + struct link l; + int op; + int error = 0; + + CURVNET_SET(CRED_TO_VNET(curthread->td_ucred)); + switch(cmd) { + case VISIOCTLOPEN: + op = *(int *)data; + if(op == 0) + medium_close(hal->hal_md); + else + medium_open(hal->hal_md); + break; + case VISIOCTLLINK: + l = *(struct link *)data; + if(l.op == 0) + del_link(vis_plugin, &l); + else + add_link(vis_plugin, &l); +#if 0 + printf("op=%d, id1=%d, id2=%d\n", l.op, l.id1, l.id2); +#endif + break; + default: + DWTAP_PRINTF("Unkown WTAP IOCTL\n"); + error = EINVAL; + } + + CURVNET_RESTORE(); + return error; +} + diff --git a/sys/dev/wtap/plugins/visibility.h b/sys/dev/wtap/plugins/visibility.h new file mode 100644 index 0000000..a5e84b0 --- /dev/null +++ b/sys/dev/wtap/plugins/visibility.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#ifndef _VISIBILITY_H_ +#define _VISIBILITY_H_ + +#include "wtap_plugin.h" +#include "visibility_ioctl.h" + +#define CDEV_GET_SOFTC(x) (x)->si_drv1 + +#define ARRAY_SIZE (32) //We support a maximum of 1024 nodes for now + +struct vis_map { + uint32_t map[ARRAY_SIZE]; +}; + +struct visibility_plugin { + struct wtap_plugin base; + struct mtx pl_mtx; + struct vis_map pl_node[MAX_NBR_WTAP]; +}; + +void visibility_init(struct wtap_plugin *); +void visibility_deinit(struct wtap_plugin *); +void visibility_work(struct wtap_plugin *, struct packet *); + +#endif + diff --git a/sys/dev/wtap/plugins/visibility_ioctl.h b/sys/dev/wtap/plugins/visibility_ioctl.h new file mode 100644 index 0000000..08760c6 --- /dev/null +++ b/sys/dev/wtap/plugins/visibility_ioctl.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +/* + * Ioctl-related defintions for the Wireless TAP plugins. + */ + +#ifndef _VISIBILITY_IOCTL_H +#define _VISIBILITY_IOCTL_H + +#include <sys/param.h> + +struct link { + int op; //0 remove, 1 link + int id1; + int id2; +}; + +#define VISIOCTLOPEN _IOW('W', 3, int) // 0 close, 1 open +#define VISIOCTLLINK _IOW('W', 4, struct link) // + +#endif + diff --git a/sys/dev/wtap/plugins/wtap_plugin.h b/sys/dev/wtap/plugins/wtap_plugin.h new file mode 100644 index 0000000..3ced37f --- /dev/null +++ b/sys/dev/wtap/plugins/wtap_plugin.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#ifndef _WTAP_PLUGIN_H_ +#define _WTAP_PLUGIN_H_ + +#include "../if_wtapvar.h" +#include "../if_medium.h" +#include "../wtap_hal/hal.h" + + +struct wtap_plugin { + struct cdev *wp_sdev; + struct wtap_hal *wp_hal; + void (*init)(struct wtap_plugin *); + void (*deinit)(struct wtap_plugin *); + void (*work)(struct wtap_plugin *, struct packet *p); +}; + +#endif + diff --git a/sys/dev/wtap/wtap_hal/hal.c b/sys/dev/wtap/wtap_hal/hal.c new file mode 100644 index 0000000..9ec1ca8 --- /dev/null +++ b/sys/dev/wtap/wtap_hal/hal.c @@ -0,0 +1,213 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ +#include "hal.h" +#include "../if_medium.h" +#include "handler.h" + +static void +hal_tx_proc(void *arg, int npending) +{ + struct wtap_hal *hal = (struct wtap_hal *)arg; + struct packet *p; + +#if 0 + DWTAP_PRINTF("%s\n", __func__); +#endif + + hal = (struct wtap_hal *)arg; + for(;;){ + p = medium_get_next_packet(hal->hal_md); + if(p == NULL) + return; + + hal->plugin->work(hal->plugin, p); + +#if 0 + DWTAP_PRINTF("[%d] freeing m=%p\n", p->id, p->m); +#endif + m_free(p->m); + free(p, M_WTAP_PACKET); + } +} + +void +init_hal(struct wtap_hal *hal) +{ + + DWTAP_PRINTF("%s\n", __func__); + mtx_init(&hal->hal_mtx, "wtap_hal mtx", NULL, MTX_DEF | MTX_RECURSE); + + hal->hal_md = (struct wtap_medium *)malloc(sizeof(struct wtap_medium), + M_WTAP, M_NOWAIT | M_ZERO); + bzero(hal->hal_md, sizeof(struct wtap_medium)); + + init_medium(hal->hal_md); + /* register event handler for packets */ + TASK_INIT(&hal->hal_md->tx_handler->proc, 0, hal_tx_proc, hal); +} + +void +register_plugin(struct wtap_hal *hal, struct wtap_plugin *plugin) +{ + + plugin->init(plugin); + hal->plugin = plugin; +} + +void +deregister_plugin(struct wtap_hal *hal) +{ + + hal->plugin->deinit(hal->plugin); + hal->plugin = NULL; /* catch illegal usages */ +} + +void +deinit_hal(struct wtap_hal *hal) +{ + + DWTAP_PRINTF("%s\n", __func__); + deinit_medium(hal->hal_md); + free(hal->hal_md, M_WTAP); + mtx_destroy(&hal->hal_mtx); +} + +int32_t +new_wtap(struct wtap_hal *hal, int32_t id) +{ + static const uint8_t mac_pool[64][IEEE80211_ADDR_LEN] = { + {0,152,154,152,150,151}, + {0,152,154,152,150,152}, + {0,152,154,152,150,153}, + {0,152,154,152,150,154}, + {0,152,154,152,150,155}, + {0,152,154,152,150,156}, + {0,152,154,152,150,157}, + {0,152,154,152,150,158}, + {0,152,154,152,151,151}, + {0,152,154,152,151,152}, + {0,152,154,152,151,153}, + {0,152,154,152,151,154}, + {0,152,154,152,151,155}, + {0,152,154,152,151,156}, + {0,152,154,152,151,157}, + {0,152,154,152,151,158}, + {0,152,154,152,152,151}, + {0,152,154,152,152,152}, + {0,152,154,152,152,153}, + {0,152,154,152,152,154}, + {0,152,154,152,152,155}, + {0,152,154,152,152,156}, + {0,152,154,152,152,157}, + {0,152,154,152,152,158}, + {0,152,154,152,153,151}, + {0,152,154,152,153,152}, + {0,152,154,152,153,153}, + {0,152,154,152,153,154}, + {0,152,154,152,153,155}, + {0,152,154,152,153,156}, + {0,152,154,152,153,157}, + {0,152,154,152,153,158}, + {0,152,154,152,154,151}, + {0,152,154,152,154,152}, + {0,152,154,152,154,153}, + {0,152,154,152,154,154}, + {0,152,154,152,154,155}, + {0,152,154,152,154,156}, + {0,152,154,152,154,157}, + {0,152,154,152,154,158}, + {0,152,154,152,155,151}, + {0,152,154,152,155,152}, + {0,152,154,152,155,153}, + {0,152,154,152,155,154}, + {0,152,154,152,155,155}, + {0,152,154,152,155,156}, + {0,152,154,152,155,157}, + {0,152,154,152,155,158}, + {0,152,154,152,156,151}, + {0,152,154,152,156,152}, + {0,152,154,152,156,153}, + {0,152,154,152,156,154}, + {0,152,154,152,156,155}, + {0,152,154,152,156,156}, + {0,152,154,152,156,157}, + {0,152,154,152,156,158}, + {0,152,154,152,157,151}, + {0,152,154,152,157,152}, + {0,152,154,152,157,153}, + {0,152,154,152,157,154}, + {0,152,154,152,157,155}, + {0,152,154,152,157,156}, + {0,152,154,152,157,157}, + {0,152,154,152,157,158} + }; + + DWTAP_PRINTF("%s\n", __func__); + uint8_t const *macaddr = mac_pool[id]; + if(hal->hal_devs[id] != NULL){ + printf("error, wtap_id=%d already created\n", id); + return -1; + } + + hal->hal_devs[id] = (struct wtap_softc *)malloc( + sizeof(struct wtap_softc), M_WTAP, M_NOWAIT | M_ZERO); + bzero(hal->hal_devs[id], sizeof(struct wtap_softc)); + hal->hal_devs[id]->sc_md = hal->hal_md; + hal->hal_devs[id]->id = id; + mtx_init(&hal->hal_devs[id]->sc_mtx, "wtap_softc mtx", NULL, + MTX_DEF | MTX_RECURSE); + + if(wtap_attach(hal->hal_devs[id], macaddr)){ + printf("%s, cant alloc new wtap\n", __func__); + return -1; + } + + return 0; +} + +int32_t +free_wtap(struct wtap_hal *hal, int32_t id) +{ + + DWTAP_PRINTF("%s\n", __func__); + if(hal->hal_devs[id] == NULL){ + printf("error, wtap_id=%d never created\n", id); + return -1; + } + + if(wtap_detach(hal->hal_devs[id])) + printf("%s, cant alloc new wtap\n", __func__); + mtx_destroy(&hal->hal_devs[id]->sc_mtx); + free(hal->hal_devs[id], M_WTAP); + hal->hal_devs[id] = NULL; + return 0; +} + diff --git a/sys/dev/wtap/wtap_hal/hal.h b/sys/dev/wtap/wtap_hal/hal.h new file mode 100644 index 0000000..f41aed9 --- /dev/null +++ b/sys/dev/wtap/wtap_hal/hal.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _WTAP_HAL_H_ +#define _WTAP_HAL_H_ + +#include "../if_wtapvar.h" +#include "../plugins/wtap_plugin.h" +#include "handler.h" + +struct wtap_hal { + struct wtap_medium *hal_md; + struct mtx hal_mtx; + struct wtap_plugin *plugin; + struct wtap_softc *hal_devs[MAX_NBR_WTAP]; +}; + +void init_hal(struct wtap_hal *); +void deinit_hal(struct wtap_hal *); +void register_plugin(struct wtap_hal *, struct wtap_plugin *); +void deregister_plugin(struct wtap_hal *); +int32_t new_wtap(struct wtap_hal *, int32_t id); +int32_t free_wtap(struct wtap_hal *, int32_t id); + + +#endif + diff --git a/sys/dev/wtap/wtap_hal/handler.h b/sys/dev/wtap/wtap_hal/handler.h new file mode 100644 index 0000000..ef645fe --- /dev/null +++ b/sys/dev/wtap/wtap_hal/handler.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2010-2011 Monthadar Al Jaberi, TerraNet AB + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _WTAP_HANDLER_H_ +#define _WTAP_HANDLER_H_ + +#include "../if_wtapvar.h" + +struct timehandler { + struct callout cb; + void (*proc)(void *); +}; + +struct taskqueue; + +struct eventhandler { + struct taskqueue *tq; + struct task proc; +}; + +#endif + diff --git a/sys/modules/wtap/Makefile b/sys/modules/wtap/Makefile new file mode 100644 index 0000000..b9e8827 --- /dev/null +++ b/sys/modules/wtap/Makefile @@ -0,0 +1,30 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/wtap + +# Declare Name of kernel module +KMOD = wtap + +# Enumerate Source files for kernel module +SRCS = if_wtap_module.c if_wtap.c if_medium.c + +.PATH: ${.CURDIR}/../../dev/wtap/wtap_hal +SRCS += hal.c + +.PATH: ${.CURDIR}/../../dev/wtap/plugins +SRCS += visibility.c + +SRCS += opt_global.h + +.if defined(KERNBUILDDIR) +MKDEP= -include ${KERNBUILDDIR}/opt_global.h +.else +CFLAGS+= -include opt_global.h +MKDEP= -include opt_global.h + +opt_global.h: + echo "#define VIMAGE 1" > ${.TARGET} +.endif + +# Include kernel module makefile +.include <bsd.kmod.mk> |