⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_wlp_wavelan_roam.c

📁 WaveLAN无线网卡Linux驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1997 Carnegie Mellon University. All Rights Reserved. *  * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted (including for commercial or for-profit * use), provided that both the copyright notice and this permission notice * appear in all copies of the software, derivative works, or modified * versions, and any portions thereof, and that both notices appear in * supporting documentation, and that credit is given to Carnegie Mellon * University in all publications reporting on direct or indirect use of this * code or its derivatives. *  * THIS IMPLEMENTATION IS EXPERIMENTAL AND MAY HAVE BUGS, SOME OF WHICH MAY HAVE * SERIOUS CONSEQUENCES.  CARNEGIE MELLON PROVIDES THIS SOFTWARE IN ITS "AS * IS" CONDITION, 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 CARNEGIE MELLON * UNIVERSITY 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. *  * Carnegie Mellon encourages (but does not require) users of this software to * return any improvements or extensions that they make, and to grant * Carnegie Mellon the rights to redistribute these changes without * encumbrance. *  *  */#ifdef WAVELAN_ROAMING#include "card.h"#if NCARD > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/syslog.h>#include <sys/time.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#endif#include <i386/isa/ic/i82593.h>#include <i386/isa/if_wlp_wavelan.h>#include <i386/isa/if_wlp.h>#include <i386/isa/if_wlp_wavelan_roam.h>/* * ====================================================================== * Local WaveLAN Routines * ====================================================================== */static voidRoamReset(struct wlp_softc *);static voidSetDOMID(struct wlp_softc*, int val);	   static voidroam_timer(void *);static voidPurgeAccessPointList(struct wlp_softc *);static struct accesspoint *BestAccessPoint1(struct wlp_softc *);static struct accesspoint *BestAccessPoint2(struct accesspoint *, struct accesspoint *);static voidProcessBeacon(struct ether_header *, struct mbuf *, int);static voidProcessSORsp(struct ether_header *, struct mbuf *);static voidSendSOReq(struct wlp_softc *, struct accesspoint *);static voidSendRECReq(struct wlp_softc *);#ifdef WLP_DEBUGstatic void     dump_aplist(struct wlp_softc *);static void     dump_ap(struct accesspoint *);#endif /* WLP_DEBUG *//* * ====================================================================== * External (non-static) WaveLAN Routines * ====================================================================== */intwavelan_roaming_ioctl(ifp, cmd, data)	struct ifnet   *ifp;	int             cmd;	caddr_t         data;{	struct wlp_softc *sc = (struct wlp_softc *) ifp->if_softc;	struct ifreq   *ifr = (struct ifreq *) data;	int             error = 0;	switch (cmd) {        case SIOCSIFNWID:                if (sc->sc_rs.rs_roam_enable == ROAM_OFF)                        SetNWID(sc, (int) ifr->ifr_data ^ sc->sc_rs.rs_beaconkey, 0);                else                        error = EPERM;                break;        case SIOCGIFNWID:                (int) ifr->ifr_data =                        (sc->sc_nwid[0] << 8 | sc->sc_nwid[1]) ^ sc->sc_rs.rs_beaconkey;                break;	case SIOCSIFROAM:		if (sc->sc_rs.rs_roam_enable == (int) ifr->ifr_data) {			error = EALREADY;			break;		}		if ((int) ifr->ifr_data != ROAM_ON &&                    (int) ifr->ifr_data != ROAM_OFF) {			error = EINVAL;			break;		}		RoamOnOff(sc, (int) ifr->ifr_data);		wlpinit(sc);		break;	case SIOCGIFROAM:		(int) ifr->ifr_data = sc->sc_rs.rs_roam_enable;		break;	case SIOCSIFDOMID:		if (sc->sc_rs.rs_roam_enable == ROAM_ON)			SetDOMID(sc, (int) ifr->ifr_data);		else			error = EPERM;		break;	case SIOCGIFDOMID:		(int) ifr->ifr_data = sc->sc_rs.rs_domid;		break;	case SIOCGIFSIGNAL:		if (sc->sc_rs.rs_roam_enable == ROAM_ON && sc->sc_rs.rs_ap) {			(int) ifr->ifr_data =				(sc->sc_rs.rs_ap->ap_siglevel << SIGL_SHIFT) +				(sc->sc_rs.rs_ap->ap_sillevel << SILL_SHIFT) +				(sc->sc_rs.rs_ap->ap_sigqual << SIGQ_SHIFT);		} else			error = EPERM;		break;	case SIOCSIFBEACONKEY:		sc->sc_rs.rs_beaconkey = htons((int) ifr->ifr_data);		break;	case SIOCGIFBEACONKEY:		(int) ifr->ifr_data = ntohs(sc->sc_rs.rs_beaconkey);		break;	case SIOCGIFTHRESH:		if (sc->sc_rs.rs_roam_enable == ROAM_ON && sc->sc_rs.rs_ap)			(int) ifr->ifr_data =				(STOP_CELL(sc->sc_rs.rs_ap) << STOPC_SHIFT) +				(REG_CELL(sc->sc_rs.rs_ap) << REGC_SHIFT) +				(FAST_CELL(sc->sc_rs.rs_ap) << FASTC_SHIFT);		else			error = EPERM;		break;	default:		error = EINVAL;	}	return error;}voidwavelan_input(eh, m, sigstat)	struct ether_header *eh;	struct mbuf    *m;	int             sigstat;{	caddr_t         p = mtod(m, caddr_t);	switch (*p) {	case PDUTYPE_BEACON:		if (m->m_len >= BEACON_MIN_LEN)			ProcessBeacon(eh, m, sigstat);		break;	case PDUTYPE_SOREQ:	/* we will never get these */		break;	case PDUTYPE_SORSP:		if (m->m_len >= SORSP_MIN_LEN)			ProcessSORsp(eh, m);		break;	}}voidRoamOnOff(sc, status)	struct wlp_softc *sc;	int             status;{	struct ifreq    ifr;	struct sockaddr *sa = &ifr.ifr_addr;	RoamReset(sc);	if (status == ROAM_OFF) {		untimeout(roam_timer, (void *) sc);	}	bzero(&ifr, sizeof(ifr));	bcopy(sc->sc_ac.ac_if.if_name, ifr.ifr_name, sizeof(ifr.ifr_name));	sa->sa_family = AF_UNSPEC;	sa->sa_len = sizeof(*sa);	bcopy(ether_beacon_multiaddr, sa->sa_data,	      sizeof(ether_beacon_multiaddr));	if (status == ROAM_OFF)		ether_delmulti(&ifr, &sc->sc_ac);	else		ether_addmulti(&ifr, &sc->sc_ac);	wlpsetrcr(sc);	if (status == ROAM_ON) {		timeout(roam_timer, (void *) sc, hz * 2);	}	sc->sc_rs.rs_roam_enable = status;#ifdef WLP_DEBUG	printf("%s(): roaming status is %s\n",		__FUNCTION__, status == ROAM_ON ? "ON" : "OFF");#endif}/* * ====================================================================== * Management Functions * ====================================================================== */static voidRoamReset(sc)	struct wlp_softc *sc;{	struct accesspoint *a;	if (sc->sc_rs.rs_roam_enable == ROAM_ON) {		/* Clean up the AP list */		for (a = sc->sc_rs.rs_aplist.lh_first; a; ) {			struct accesspoint *an = a->ap_link.le_next;			LIST_REMOVE(a, ap_link);			free(a, M_TEMP);			a = an;		}	}	LIST_INIT(&sc->sc_rs.rs_aplist);	sc->sc_rs.rs_ap = 0;	sc->sc_rs.rs_apreg = 0;	sc->sc_rs.rs_SOReqCnt = 0;	sc->sc_rs.rs_SOReqRetrans = 0;	sc->sc_rs.rs_roam_mode = MODE_FAST_CELL;	sc->sc_rs.rs_SOReqFailed = 0;	sc->sc_rs.rs_BeaconCount = 0;	sc->sc_rs.rs_BeaconKept = 0;}static voidSetDOMID(sc, val)	struct wlp_softc *sc;	int             val;{	sc->sc_rs.rs_domid = (val & 0xFFFF);	if (sc->sc_rs.rs_domid && sc->sc_rs.rs_ap &&            sc->sc_rs.rs_ap->ap_beacon.domid != sc->sc_rs.rs_domid) {		RoamReset(sc);	}}/* * ====================================================================== * Functions that implement Roaming... * ====================================================================== */static voidroam_timer(arg)	void           *arg;{	struct wlp_softc *sc = arg;	struct ifnet   *ifp = &sc->sc_ac.ac_if;	struct accesspoint *a = 0;	int             s;	s = splimp();#ifdef WLP_DEBUG	printf("----------\nbeacons... COUNT: %d, KEPT: %d, DISCARD: %d\n",	       sc->sc_rs.rs_BeaconCount, sc->sc_rs.rs_BeaconKept,	       sc->sc_rs.rs_BeaconCount - sc->sc_rs.rs_BeaconKept);	printf("%s: sc_ap %p sc_apreg %p\n\tmode %s time %ld.%ld\n",               __FUNCTION__, sc->sc_rs.rs_ap, sc->sc_rs.rs_apreg,	       RoamModeString[sc->sc_rs.rs_roam_mode],	       time.tv_sec, time.tv_usec);	dump_ap(sc->sc_rs.rs_ap);#endif /* WLP_DEBUG */	if (sc->sc_rs.rs_roam_enable != ROAM_ON) {		goto quit;	}	if (sc->sc_gone) {		RoamOnOff(sc, ROAM_OFF);		goto quit;	}	if ((ifp->if_flags & IFF_RUNNING) == 0) {		goto done;	}start:	PurgeAccessPointList(sc);	switch (sc->sc_rs.rs_roam_mode) {	case MODE_FAST_CELL:	case MODE_REG_CELL:		/*		 * ===========================================================		 * Necessary to avoid thrashing...		 * ===========================================================		 */		if (sc->sc_rs.rs_ap &&		    SNR(sc->sc_rs.rs_ap) > STOP_CELL(sc->sc_rs.rs_ap)) {			/* ~NWID Promisc Mode */			SetNWID(sc, sc->sc_rs.rs_ap->ap_beacon.snwid, 0);			if (sc->sc_rs.rs_roam_mode == MODE_FAST_CELL)				EnableTX(ifp);			if (sc->sc_rs.rs_apreg) {#ifdef WLP_DEBUG				printf("Aborting Registration!\n");#endif				EnableTX(ifp);	/* Transmission Enabled */				SendRECReq(sc);	/* XXX - Send a Recover REQ */				sc->sc_rs.rs_apreg = 0;	/* Not Registering */			}			sc->sc_rs.rs_roam_mode = MODE_STOP_CELL;			goto done;		}		/*		 * ===========================================================		 * Try to find a better Access Point...		 * ===========================================================		 */		a = BestAccessPoint1(sc);		if ((a == 0) || SNR(a) < FAST_CELL(a)) {			SetNWID(sc, 0, 1);	/* NWID Promisc Mode */			DisableTX(ifp);			sc->sc_rs.rs_roam_mode = MODE_FAST_CELL;			goto done;		}		/*		 * ===========================================================		 * Current Access Point		 * ===========================================================		 */		if (a == sc->sc_rs.rs_ap ||		    (BestAccessPoint2(sc->sc_rs.rs_ap, a) == sc->sc_rs.rs_ap)) {			/* NWID Promisc Mode */			SetNWID(sc, a->ap_beacon.snwid, 1);			if (sc->sc_rs.rs_roam_mode == MODE_FAST_CELL)				EnableTX(ifp);			if (sc->sc_rs.rs_apreg) {#ifdef WLP_DEBUG				printf("Aborting Registration!\n");#endif				EnableTX(ifp);				SendRECReq(a->ap_softc); /* XXX */				sc->sc_rs.rs_apreg = 0;	/* Not Registering */			}			sc->sc_rs.rs_roam_mode = MODE_REG_CELL;			goto done;		}		/*		 * ===========================================================		 * Registering Access Point		 * ===========================================================		 */		if (a == sc->sc_rs.rs_apreg) {			if (sc->sc_rs.rs_SOReqRetrans < MAX_SOREQ_RETRANS) {#ifdef WLP_DEBUG				printf("*** No Sign-on Response Received\n");				printf("\tNWID: %x, SOReqRetrans = %d\n",				       sc->sc_rs.rs_apreg->ap_beacon.snwid,				       sc->sc_rs.rs_SOReqRetrans);#endif			} else {				/*				 * Must fall back to an initial Sign-ON ==>				 * forget about the previous base station.				 */				if (sc->sc_rs.rs_ap) {					LIST_REMOVE(sc->sc_rs.rs_ap, ap_link);					free(sc->sc_rs.rs_ap, M_TEMP);					sc->sc_rs.rs_ap = 0;				} else {#ifdef WLP_DEBUG					panic("Can't Register at all...");#endif				}#ifdef WLP_DEBUG				printf("*** No Sign-on Response Received\n");				printf("\tNWID: %x, SOReqRetrans = %d\n",				       sc->sc_rs.rs_apreg->ap_beacon.snwid,				       sc->sc_rs.rs_SOReqRetrans);#endif				sc->sc_rs.rs_SOReqRetrans = 0;				sc->sc_rs.rs_SOReqFailed = 1;			}			SendSOReq(sc, a);	/* Send a Sign-on Request */			sc->sc_rs.rs_roam_mode = MODE_REG_CELL;		}		/*		 * ===========================================================		 * New Access Point		 * ===========================================================		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -