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

📄 wi_hostap.c

📁 一个学习SNMP项目:tmoerlan.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  Copyright (c) 2003, Tijmen Moerland (moerland@yahoo.com)*//* Doxygen comments follow *//*!	\file wi_hostap.c	\brief The source file enabling (Prism based) interfaces to act as an Access Point (HostAP mode)	The additions for the 802.11 MIB project consist of the following:\n	Keeping track of association, disassociation times (in extended cache)\n	Keeping track of number of associations (in extended cache)\n	Setting disassociation timeout also at association (not only after last packet received), so if a station	associates, but never sends any packets, it gets disassociated after timeout (instead of staying in the	station list and (extended) cache forever.	Created two extra ioctl calls (in wihap_ioctl): SIOCHOSTAP_DEL and SIOCHOSTAP_DISASSOC for deleting and	disassociating a station.	The additions dealing with the extended cache are put between WICACHE defines, and can should thus be easily removable	by recompiling without the -DWICACHE option.	*//* * Copyright (c) 2002 *	Thomas Skibo <skibo@pacbell.net>.  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. * 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. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Thomas Skibo. * 4. Neither the name of the author nor the names of any co-contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Thomas Skibo AND CONTRIBUTORS ``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 Thomas Skibo OR HIS DRINKING PALS * 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. * * $FreeBSD: src/sys/dev/wi/wi_hostap.c,v 1.18 2002/10/16 08:48:39 phk Exp $ *//* This is experimental Host AP software for Prism 2 802.11b interfaces. * * Much of this is based upon the "Linux Host AP driver Host AP driver * for Intersil Prism2" by Jouni Malinen <jkm@ssh.com> or <jkmaline@cc.hut.fi>. */#include <sys/param.h>#include <sys/systm.h>#if __FreeBSD_version >= 500033#include <sys/endian.h>#endif#include <sys/sockio.h>#include <sys/mbuf.h>#include <sys/malloc.h>#include <sys/kernel.h>#include <sys/proc.h>#include <sys/ucred.h>#include <sys/socket.h>#include <sys/module.h>#include <sys/queue.h>#include <sys/bus.h>#include <sys/syslog.h>#include <sys/sysctl.h>#include <machine/bus.h>#include <machine/resource.h>#include <machine/clock.h>#include <machine/md_var.h>#include <machine/bus_pio.h>#include <sys/rman.h>#include <net/if.h>#include <net/if_arp.h>#include <net/ethernet.h>#include <net/if_dl.h>#include <net/if_media.h>#include <net/if_types.h>#include <net/if_ieee80211.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#include <dev/wi/if_wavelan_ieee.h>#include <dev/wi/wi_hostap.h>#include <dev/wi/if_wivar.h>#include <dev/wi/if_wireg.h>#include <sys/time.h>#include <sys/timeb.h>MALLOC_DEFINE(M_HAP_STA, "hostap_sta", "if_wi host AP mode station entry");static void wihap_sta_timeout(void *v);static struct wihap_sta_info *wihap_sta_alloc(struct wi_softc *sc,    u_int8_t *addr);static void wihap_sta_delete(struct wihap_sta_info *sta);static struct wihap_sta_info *wihap_sta_find(struct wihap_info *whi,    u_int8_t *addr);static int wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[]);static void wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,    caddr_t pkt, int len);static void wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[],    u_int16_t reason);static void wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm,    caddr_t pkt, int len);static void wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,    caddr_t pkt, int len);static void wihap_sta_disassoc(struct wi_softc *sc, u_int8_t sta_addr[],    u_int16_t reason);static void wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,    caddr_t pkt, int len);#ifdef WICACHEextern int wi_findCacheEntry(struct wi_softc *, char *);extern void wi_removeCacheEntry(struct wi_softc *, int);void saveDisassocTime(struct wi_softc *, char *);void saveAssocTime(struct wi_softc *, char *);/*!	\fn void saveDisassocTime(struct wi_softc *sc, char *addr)	\brief This functions stores the current time in the disassociation variable of the cache for the specified station. Also starts cache timeout counter	\param sc Pointer to the wi_softc structure of the specific interface	\param addr A six byte MAC address specifying which station to store the disassociation time for	\note This code is also also used by non-HostAP interfaces in if_wi.c. It was orinally only available to HostAP interfaces, that's why	this function is in this file.	This functions looks up the extended cache entry for the station as specified by addr. This cache entry must exist, because	the station was associated before (or this function should not be called). It then stores the current time in the disassociation variable	of the extended cache entry.	Because disassociated cache items can time out, we set the timeout counter present in the extended cache to the value	specific for this interface (defined by sc->wi_timeout_time). If this value is zero, the cache entry is removed immediately.	The timeout counter is decremented every second by a function in if_wi.c and there it will be removed when counter reaches one (1).*/void saveDisassocTime(struct wi_softc *sc, char *addr) {	/* save the current time so that we know time since last disassociation */        int cache_slot;        struct timeval tv;        microtime(&tv);        cache_slot = wi_findCacheEntry(sc, addr);        if (cache_slot > -1) {	/* succes (should be there, this station was assoc'ed before) */       		if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)			device_printf(sc->dev, "saving disassoc time for cache item %6D in slot %d\n", (u_char *) addr, ":", cache_slot);	        bcopy(&tv, &sc->wi_sigextcache[cache_slot].disassoctime, sizeof(tv));		if (sc->wi_timeout_time == 0) {	/* if the timeout time is set to 0, this means						   immediate deleteion of cache entry */			if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)				device_printf(sc->dev, "immediate deletion!!\n");			wi_removeCacheEntry(sc, cache_slot);		}		sc->wi_sigextcache[cache_slot].remove_ctr = sc->wi_timeout_time;	}	else 		device_printf(sc->dev, "saveDisassocTime: no cache_slot for station!");}/*!	\fn void saveAssocTime(struct wi_softc *sc, char *addr)	\brief This function stores the current time in the association variable of the cache for the specified station, and also (re-)sets some other variables.	\param sc Pointer to the wi_softc structure of the specific interface	\param addr A six byte MAC address specifying which station to store the disassociation time for	\note This code is also also used by non-HostAP interfaces in if_wi.c. It was orinally only available to HostAP interfaces, that's why	this function is in this file.	This functions looks up the extended cache entry for the station as specified by addr. If this is the first time the station associates,	a new entry is created (if available). Then the current time is stored to the association variable of this cache entry and the number	of associations is incremented by one. Also, counters keeping track of number of received and sent packets/bytes are reset (to zero).	The cache timeout counter is reset to zero, so that this cache entry will not timeout (if a timeout was running). As long as the station	is associated, it's cache will not time out. Only after disassocation (for whatever reason, e.g. disassociation request or inactivity timeout)	the cache timeout is started.*/void saveAssocTime(struct wi_softc *sc, char *addr) {/* station is now associated, save the current time */        int cache_slot;        struct timeval tv;        microtime(&tv);        cache_slot = wi_findCacheEntry(sc, addr);/*      printf("wi_addr2 = %6D", rxfrm->wi_addr2, ":");        printf("saving assoctime to slot %d, time=%ld, %ld\n",                cache_slot, tv.tv_sec, tv.tv_usec);*/        if (cache_slot > -1) {  /* succes (either found or created) *//*this has already been done by wi_findCacheEntry                bcopy(rxfrm->wi_addr2, sc->wi_sigcache[cache_slot].macsrc, 6);                bcopy(rxfrm->wi_addr2, sc->wi_sigextcache[cache_slot].macsrc, 6);*/                bcopy(&tv, &sc->wi_sigextcache[cache_slot].assoctime, sizeof(tv));                sc->wi_sigextcache[cache_slot].rcvpkts = 0;                sc->wi_sigextcache[cache_slot].rcvbytes = 0;                sc->wi_sigextcache[cache_slot].sndpkts = 0;                sc->wi_sigextcache[cache_slot].sndbytes = 0;                sc->wi_sigextcache[cache_slot].remove_ctr = 0;                sc->wi_sigextcache[cache_slot].nr_assocs++;     /* increase total number of associations */                if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)			device_printf(sc->dev, "assoc'ed: storing cache item %6D in slot %d\n", (u_char *) addr, ":", cache_slot);        }	  else 		    device_printf(sc->dev, "saveAssocTime: no cache_slot for station!");}#endif	/* WICACHE *//* * Spl use in this driver. * * splnet is used everywhere here to block timeouts when we need to do * so. *//* * take_hword() * *	Used for parsing management frames.  The pkt pointer and length *	variables are updated after the value is removed. */static __inline u_int16_ttake_hword(caddr_t *ppkt, int *plen){	u_int16_t s = le16toh(* (u_int16_t *) *ppkt);	*ppkt += sizeof(u_int16_t);	*plen -= sizeof(u_int16_t);	return s;}/* take_tlv() * *	Parse out TLV element from a packet, check for underflow of packet *	or overflow of buffer, update pkt/len. */static inttake_tlv(caddr_t *ppkt, int *plen, int id_expect, void *dst, int maxlen){	u_int8_t id, len;	if (*plen < 2)		return -1;	id = ((u_int8_t *)*ppkt)[0];	len = ((u_int8_t *)*ppkt)[1];	if (id != id_expect || *plen < len+2 || maxlen < len)		return -1;	bcopy(*ppkt + 2, dst, len);	*plen -= 2 + len;	*ppkt += 2 + len;	return (len);}/* put_hword() *	Put half-word element into management frames. */static __inline voidput_hword(caddr_t *ppkt, u_int16_t s){	* (u_int16_t *) *ppkt = htole16(s);	*ppkt += sizeof(u_int16_t);}/* put_tlv() *	Put TLV elements into management frames. */static voidput_tlv(caddr_t *ppkt, u_int8_t id, void *src, u_int8_t len){	(*ppkt)[0] = id;	(*ppkt)[1] = len;	bcopy(src, (*ppkt) + 2, len);	*ppkt += 2 + len;}static intput_rates(caddr_t *ppkt, u_int16_t rates){	u_int8_t ratebuf[8];	int len = 0;	if (rates & WI_SUPPRATES_1M)		ratebuf[len++] = 0x82;	if (rates & WI_SUPPRATES_2M)		ratebuf[len++] = 0x84;	if (rates & WI_SUPPRATES_5M)		ratebuf[len++] = 0x8b;	if (rates & WI_SUPPRATES_11M)		ratebuf[len++] = 0x96;	put_tlv(ppkt, IEEE80211_ELEMID_RATES, ratebuf, len);	return len;}/* wihap_init() * *	Initialize host AP data structures.  Called even if port type is *	not AP. */voidwihap_init(struct wi_softc *sc){	int i;	struct wihap_info *whi = &sc->wi_hostap_info;	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)		printf("wihap_init: sc=0x%x whi=0x%x\n", (int)sc, (int)whi);	bzero(whi, sizeof(struct wihap_info));	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)		return;	whi->apflags = WIHAPFL_ACTIVE;	LIST_INIT(&whi->sta_list);	for (i = 0; i < WI_STA_HASH_SIZE; i++)		LIST_INIT(&whi->sta_hash[i]);	whi->inactivity_time = WIHAP_DFLT_INACTIVITY_TIME;}/* wihap_sta_disassoc() * *	Send a disassociation frame to a specified station. */static voidwihap_sta_disassoc(struct wi_softc *sc, u_int8_t sta_addr[], u_int16_t reason){	struct wi_80211_hdr	*resp_hdr;	caddr_t			pkt;	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 		printf("Sending disassoc to sta %6D\n", sta_addr, ":");	/* Send disassoc packet. */	resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf;	bzero(resp_hdr, sizeof(struct wi_80211_hdr));	resp_hdr->frame_ctl = WI_FTYPE_MGMT | WI_STYPE_MGMT_DISAS;	pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr);	bcopy(sta_addr, resp_hdr->addr1, ETHER_ADDR_LEN);	bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN);	bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN);	put_hword(&pkt, reason);	wi_mgmt_xmit(sc, sc->wi_txbuf, 2 + sizeof(struct wi_80211_hdr));}/* wihap_sta_deauth() * *	Send a deauthentication message to a specified station. */static voidwihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[], u_int16_t reason){	struct wi_80211_hdr	*resp_hdr;	caddr_t			pkt;	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)		printf("Sending deauth to sta %6D\n", sta_addr, ":");	/* Send deauth packet. */	resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf;	bzero(resp_hdr, sizeof(struct wi_80211_hdr));	resp_hdr->frame_ctl = htole16(WI_FTYPE_MGMT | WI_STYPE_MGMT_DEAUTH);	pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr);	bcopy(sta_addr, resp_hdr->addr1, ETHER_ADDR_LEN);	bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN);	bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN);	put_hword(&pkt, reason);	wi_mgmt_xmit(sc, sc->wi_txbuf, 2 + sizeof(struct wi_80211_hdr));}/* wihap_shutdown() * *	Disassociate all stations and free up data structures. */voidwihap_shutdown(struct wi_softc *sc){	struct wihap_info	*whi = &sc->wi_hostap_info;	struct wihap_sta_info	*sta, *next;	int s;	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)		printf("wihap_shutdown: sc=0x%x whi=0x%x\n",		    (int)sc, (int)whi);	if (!(whi->apflags & WIHAPFL_ACTIVE))		return;	/* XXX: I read somewhere you can deauth all the stations with	 * a single broadcast.  Maybe try that someday.	 */	s = splnet();	sta = LIST_FIRST(&whi->sta_list);	while (sta) {		untimeout(wihap_sta_timeout, sta, sta->tmo);		if (!sc->wi_gone) {			/* Disassociate station. */			if (sta->flags & WI_SIFLAGS_ASSOC)				wihap_sta_disassoc(sc, sta->addr,				    IEEE80211_REASON_ASSOC_LEAVE);			/* Deauth station. */			if (sta->flags & WI_SIFLAGS_AUTHEN)				wihap_sta_deauth(sc, sta->addr,				    IEEE80211_REASON_AUTH_LEAVE);		}		/* Delete the structure. */		if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)			printf("wihap_shutdown: FREE(sta=0x%x)\n", (int)sta);		next = LIST_NEXT(sta, list);		FREE(sta, M_HAP_STA);		sta = next;	}	whi->apflags = 0;	splx(s);}/* sta_hash_func() * Hash function for finding stations from ethernet address. */static __inline intsta_hash_func(u_int8_t addr[]){	return ((addr[3] + addr[4] + addr[5]) % WI_STA_HASH_SIZE);}/* addr_cmp():  Maybe this is a faster way to compare addresses? */static __inline intaddr_cmp(u_int8_t a[], u_int8_t b[]){	return (*(u_int16_t *)(a + 4) == *(u_int16_t *)(b + 4) &&		*(u_int32_t *)(a    ) == *(u_int32_t *)(b));}/*!	\fn static void wihap_sta_timeout(void *v)	\brief This is the function that performs the timeout after an inactivity timeout expires.	\param v A pointer to a wi_softc structure of the specific interface		Station is first disassociated. Then the inactivity timeout is started again, and if it expires again (without reassociation)	the station is also deauthenticated and it is removed from the station list.	A call to saveDisassocTime is added here (this will also insure cache timeout).*/static voidwihap_sta_timeout(void *v){	struct wihap_sta_info	*sta = v;	struct wi_softc		*sc = sta->sc;	struct wihap_info	*whi = &sc->wi_hostap_info;	int	s;	s = splnet();/*	device_printf(sc->dev, "wihap_sta_timeout for station %6D\n", sta->addr, ":");*/	if (sta->flags & WI_SIFLAGS_ASSOC) {		if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)			device_printf(sc->dev, "inactivity disassoc: %6D\n",			    sta->addr, ":");		/* Disassoc station. */		wihap_sta_disassoc(sc, sta->addr,

⌨️ 快捷键说明

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