Signed-Off-By: Georg Lukas Index: net80211/ieee80211_node.c =================================================================== --- net80211/ieee80211_node.c (revision 2091) +++ net80211/ieee80211_node.c (working copy) @@ -781,9 +781,7 @@ static void node_cleanup(struct ieee80211_node *ni) { -#define N(a) (sizeof(a)/sizeof(a[0])) struct ieee80211vap *vap = ni->ni_vap; - int i; /* NB: preserve ni_table */ if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) { @@ -822,14 +820,13 @@ * * XXX does this leave us open to inheriting old state? */ - for (i = 0; i < N(ni->ni_rxfrag); i++) - if (ni->ni_rxfrag[i] != NULL) { - dev_kfree_skb_any(ni->ni_rxfrag[i]); - ni->ni_rxfrag[i] = NULL; - } + + if (ni->ni_rxfrag != NULL) { + dev_kfree_skb_any(ni->ni_rxfrag); + ni->ni_rxfrag = NULL; + } ieee80211_crypto_delkey(vap, &ni->ni_ucastkey, ni); ni->ni_rxkeyoff = 0; -#undef N } static void @@ -1455,10 +1452,10 @@ * (last fragment older than 1s). * XXX doesn't belong here */ - if (ni->ni_rxfrag[0] != NULL && + if (ni->ni_rxfrag != NULL && jiffies > ni->ni_rxfragstamp + HZ) { - dev_kfree_skb(ni->ni_rxfrag[0]); - ni->ni_rxfrag[0] = NULL; + dev_kfree_skb(ni->ni_rxfrag); + ni->ni_rxfrag = NULL; } /* * Special case ourself; we may be idle for extended periods @@ -1557,15 +1554,23 @@ void ieee80211_iterate_nodes(struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg) { + ieee80211_iterate_dev_nodes(NULL, nt, f, arg); +} +EXPORT_SYMBOL(ieee80211_iterate_nodes); + +void +ieee80211_iterate_dev_nodes(struct net_device *dev, struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg) +{ struct ieee80211_node *tni, *ni; u_int gen; IEEE80211_SCAN_LOCK_IRQ(nt); gen = ++nt->nt_scangen; - restart: IEEE80211_NODE_TABLE_LOCK_IRQ(nt); TAILQ_FOREACH(tni, &nt->nt_node, ni_list) { + if (dev != NULL && tni->ni_vap->iv_dev != dev) + continue; /* skip node not for this vap */ if (tni->ni_scangen != gen) { tni->ni_scangen = gen; @@ -1582,12 +1587,11 @@ IEEE80211_SCAN_UNLOCK_IRQ(nt); } -EXPORT_SYMBOL(ieee80211_iterate_nodes); +EXPORT_SYMBOL(ieee80211_iterate_dev_nodes); void ieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni) { - int i; printf("0x%p: mac %s refcnt %d\n", ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); Index: net80211/ieee80211_node.h =================================================================== --- net80211/ieee80211_node.h (revision 2091) +++ net80211/ieee80211_node.h (working copy) @@ -130,7 +130,7 @@ u_int16_t ni_txseqs[17]; /* tx seq per-tid */ u_int16_t ni_rxseqs[17]; /* rx seq previous per-tid*/ u_int32_t ni_rxfragstamp; /* time stamp of last rx frag */ - struct sk_buff *ni_rxfrag[3]; /* rx frag reassembly */ + struct sk_buff *ni_rxfrag; /* rx frag reassembly */ struct ieee80211_rsnparms ni_rsn; /* RSN/WPA parameters */ struct ieee80211_key ni_ucastkey; /* unicast key */ int ni_rxkeyoff; /* Receive key offset */ @@ -328,6 +328,8 @@ typedef void ieee80211_iter_func(void *, struct ieee80211_node *); void ieee80211_iterate_nodes(struct ieee80211_node_table *, ieee80211_iter_func *, void *); +void ieee80211_iterate_dev_nodes(struct net_device *, + struct ieee80211_node_table *, ieee80211_iter_func *, void *); void ieee80211_dump_node(struct ieee80211_node_table *, struct ieee80211_node *); Index: net80211/ieee80211_wireless.c =================================================================== --- net80211/ieee80211_wireless.c (revision 2091) +++ net80211/ieee80211_wireless.c (working copy) @@ -2152,11 +2152,11 @@ break; case IEEE80211_PARAM_UCASTCIPHERS: /* - * Convert cipher set to equivalent capabilities. * NB: this logic intentionally ignores unknown and * unsupported ciphers so folks can specify 0xff or * similar and get all available ciphers. */ + /* caps are really ciphers */ caps = 0; for (j = 1; j < 32; j++) /* NB: skip WEP */ if ((value & (1 << j)) && @@ -2172,9 +2172,12 @@ retv = ENETRESET; break; case IEEE80211_PARAM_UCASTCIPHER: - if ((rsn->rsn_ucastcipherset & cipher2cap(value)) == 0) + if ((vap->iv_caps & cipher2cap(value)) == 0 && + !ieee80211_crypto_available(value)) return -EINVAL; rsn->rsn_ucastcipher = value; + if (vap->iv_flags & IEEE80211_F_WPA) + retv = ENETRESET; break; case IEEE80211_PARAM_UCASTKEYLEN: if (!(0 < value && value <= IEEE80211_KEYBUF_SIZE)) @@ -2591,6 +2594,7 @@ return -retv; } +#if 0 static int cap2cipher(int flag) { @@ -2603,6 +2607,7 @@ } return -1; } +#endif static int ieee80211_ioctl_getmode(struct net_device *dev, struct iw_request_info *info, @@ -2650,7 +2655,7 @@ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn; int *param = (int *) extra; - u_int m; + switch (param[0]) { case IEEE80211_PARAM_AUTHMODE: if (vap->iv_flags & IEEE80211_F_WPA) @@ -2668,10 +2673,7 @@ param[0] = rsn->rsn_mcastkeylen; break; case IEEE80211_PARAM_UCASTCIPHERS: - param[0] = 0; - for (m = 0x1; m != 0; m <<= 1) - if (rsn->rsn_ucastcipherset & m) - param[0] |= 1<rsn_ucastcipherset; break; case IEEE80211_PARAM_UCASTCIPHER: param[0] = rsn->rsn_ucastcipher; @@ -3020,15 +3022,18 @@ static int ieee80211_ioctl_setappiebuf(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) + struct iw_point *data, char *extra) { struct ieee80211vap *vap = dev->priv; struct ieee80211req_getset_appiebuf *iebuf = (struct ieee80211req_getset_appiebuf *)extra; enum ieee80211_opmode chk_opmode; + int iebuf_len; int rc = 0; - if (iebuf->app_buflen > IEEE80211_APPIE_MAX) + iebuf_len = data->length - sizeof(struct ieee80211req_getset_appiebuf); + if ( iebuf_len < 0 || iebuf_len != iebuf->app_buflen || + iebuf->app_buflen > IEEE80211_APPIE_MAX ) return -EINVAL; switch (iebuf->app_frmtype) { @@ -3059,12 +3064,22 @@ static int ieee80211_ioctl_getappiebuf(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) + struct iw_point *data, char *extra) { struct ieee80211vap *vap = dev->priv; struct ieee80211req_getset_appiebuf *iebuf = (struct ieee80211req_getset_appiebuf *)extra; + int max_iebuf_len; + int rc = 0; + max_iebuf_len = data->length - sizeof(struct ieee80211req_getset_appiebuf); + if (max_iebuf_len < 0) + return -EINVAL; + if (copy_from_user(iebuf, data->pointer, sizeof(struct ieee80211req_getset_appiebuf))) + return -EFAULT; + if (iebuf->app_buflen > max_iebuf_len) + iebuf->app_buflen = max_iebuf_len; + switch (iebuf->app_frmtype) { case IEEE80211_APPIE_FRAME_BEACON: case IEEE80211_APPIE_FRAME_PROBE_RESP: @@ -3081,7 +3096,11 @@ return -EINVAL; } - return get_app_ie(iebuf->app_frmtype, vap, iebuf); + rc = get_app_ie(iebuf->app_frmtype, vap, iebuf); + + data->length = sizeof(struct ieee80211req_getset_appiebuf) + iebuf->app_buflen; + + return rc; } static int @@ -3344,10 +3363,11 @@ mlme->im_macaddr); if (ni == NULL) return -EINVAL; - domlme(mlme, ni); + if (dev == ni->ni_vap->iv_dev) + domlme(mlme, ni); ieee80211_unref_node(&ni); } else - ieee80211_iterate_nodes(&ic->ic_sta, domlme, mlme); + ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme); break; default: return -EINVAL; @@ -4819,7 +4839,7 @@ #define IW_PRIV_TYPE_CHANINFO \ IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_chaninfo) #define IW_PRIV_TYPE_APPIEBUF \ - (IW_PRIV_TYPE_BYTE | IEEE80211_APPIE_MAX) + (IW_PRIV_TYPE_BYTE | (sizeof(struct ieee80211req_getset_appiebuf) + IEEE80211_APPIE_MAX)) #define IW_PRIV_TYPE_FILTER \ IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_set_filter) @@ -5276,7 +5296,7 @@ .num_private = N(ieee80211_priv_handlers), .private_args = (struct iw_priv_args *) ieee80211_priv_args, .num_private_args = N(ieee80211_priv_args), -#if WIRELESS_EXT >= 17 +#if IW_HANDLER_VERSION >= 7 .get_wireless_stats = ieee80211_iw_getstats, #endif #undef N @@ -5374,7 +5394,9 @@ return -EPERM; if (copy_from_user(&cp, ifr->ifr_data, sizeof(cp))) return -EFAULT; - + if (access_ok(VERIFY_WRITE, ifr->ifr_name, IFNAMSIZ)) + return -EFAULT; + unit = ieee80211_new_wlanunit(); if (unit == -1) return -EIO; /* XXX */ @@ -5385,8 +5407,11 @@ ieee80211_delete_wlanunit(unit); return -EIO; } - /* return final device name */ - strncpy(ifr->ifr_name, vap->iv_dev->name, IFNAMSIZ); + + /* return final device name - should not fail, we have already + checked above if we can access this. */ + if (__copy_to_user(ifr->ifr_name, vap->iv_dev->name, IFNAMSIZ)) + return -EFAULT; return 0; } EXPORT_SYMBOL(ieee80211_ioctl_create_vap); Index: net80211/ieee80211_input.c =================================================================== --- net80211/ieee80211_input.c (revision 2091) +++ net80211/ieee80211_input.c (working copy) @@ -957,7 +957,7 @@ fragno = le16_to_cpu(*(__le16 *)wh->i_seq) & IEEE80211_SEQ_FRAG_MASK; /* Quick way out, if there's nothing to defragment */ - if (!more_frag && fragno == 0 && ni->ni_rxfrag[0] == NULL) + if (!more_frag && fragno == 0 && ni->ni_rxfrag == NULL) return skb; /* @@ -980,7 +980,7 @@ /* * Update the time stamp. As a side effect, it * also makes sure that the timer will not change - * ni->ni_rxfrag[0] for at least 1 second, or in + * ni->ni_rxfrag for at least 1 second, or in * other words, for the remaining of this function. * XXX HUGE HORRIFIC HACK */ @@ -990,10 +990,10 @@ * Validate that fragment is in order and * related to the previous ones. */ - if (ni->ni_rxfrag[0]) { + if (ni->ni_rxfrag) { struct ieee80211_frame *lwh; - lwh = (struct ieee80211_frame *) ni->ni_rxfrag[0]->data; + lwh = (struct ieee80211_frame *) ni->ni_rxfrag->data; last_rxseq = le16_to_cpu(*(__le16 *)lwh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; last_fragno = le16_to_cpu(*(__le16 *)lwh->i_seq) & @@ -1002,20 +1002,20 @@ || fragno != last_fragno + 1 || (!IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1)) || (!IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) - || (ni->ni_rxfrag[0]->end - ni->ni_rxfrag[0]->tail < + || (ni->ni_rxfrag->end - ni->ni_rxfrag->tail < skb->len)) { /* * Unrelated fragment or no space for it, * clear current fragments */ - dev_kfree_skb(ni->ni_rxfrag[0]); - ni->ni_rxfrag[0] = NULL; + dev_kfree_skb(ni->ni_rxfrag); + ni->ni_rxfrag = NULL; } } /* If this is the first fragment */ - if (ni->ni_rxfrag[0] == NULL && fragno == 0) { - ni->ni_rxfrag[0] = skb; + if (ni->ni_rxfrag == NULL && fragno == 0) { + ni->ni_rxfrag = skb; /* If more frags are coming */ if (more_frag) { if (skb_is_nonlinear(skb)) { @@ -1023,7 +1023,7 @@ * We need a continous buffer to * assemble fragments */ - ni->ni_rxfrag[0] = skb_copy(skb, GFP_ATOMIC); + ni->ni_rxfrag = skb_copy(skb, GFP_ATOMIC); dev_kfree_skb(skb); } /* @@ -1033,26 +1033,26 @@ */ else if (skb->end - skb->head < ni->ni_vap->iv_dev->mtu + hdrlen) { - ni->ni_rxfrag[0] = skb_copy_expand(skb, 0, + ni->ni_rxfrag = skb_copy_expand(skb, 0, (ni->ni_vap->iv_dev->mtu + hdrlen) - (skb->end - skb->head), GFP_ATOMIC); dev_kfree_skb(skb); } } } else { - if (ni->ni_rxfrag[0]) { + if (ni->ni_rxfrag) { struct ieee80211_frame *lwh = (struct ieee80211_frame *) - ni->ni_rxfrag[0]->data; + ni->ni_rxfrag->data; /* * We know we have enough space to copy, * we've verified that before */ /* Copy current fragment at end of previous one */ - memcpy(ni->ni_rxfrag[0]->tail, + memcpy(ni->ni_rxfrag->tail, skb->data + hdrlen, skb->len - hdrlen); /* Update tail and length */ - skb_put(ni->ni_rxfrag[0], skb->len - hdrlen); + skb_put(ni->ni_rxfrag, skb->len - hdrlen); /* Keep a copy of last sequence and fragno */ *(__le16 *) lwh->i_seq = *(__le16 *) wh->i_seq; } @@ -1065,8 +1065,8 @@ skb = NULL; } else { /* Last fragment received, we're done! */ - skb = ni->ni_rxfrag[0]; - ni->ni_rxfrag[0] = NULL; + skb = ni->ni_rxfrag; + ni->ni_rxfrag = NULL; } return skb; } Index: net80211/ieee80211_output.c =================================================================== --- net80211/ieee80211_output.c (revision 2091) +++ net80211/ieee80211_output.c (working copy) @@ -842,8 +842,8 @@ ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr); break; case IEEE80211_M_HOSTAP: - if (!IEEE80211_ADDR_EQ(eh.ether_dhost, ni->ni_macaddr) && - !IEEE80211_IS_MULTICAST(eh.ether_dhost)) { + if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) && + !IEEE80211_ADDR_EQ(eh.ether_dhost, ni->ni_macaddr)) { hdrsize += IEEE80211_ADDR_LEN; use4addr = 1; ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr); @@ -852,8 +852,8 @@ ismulticast = IEEE80211_IS_MULTICAST(eh.ether_dhost); break; case IEEE80211_M_STA: - if ((!IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) && - (vap->iv_flags_ext & IEEE80211_FEXT_WDS)) { + if ((vap->iv_flags_ext & IEEE80211_FEXT_WDS) && + (!IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr))) { hdrsize += IEEE80211_ADDR_LEN; use4addr = 1; ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr); Index: include/compat.h =================================================================== --- include/compat.h (revision 2091) +++ include/compat.h (working copy) @@ -41,6 +41,7 @@ /* Compatibility with older Linux kernels */ #ifdef __KERNEL__ #include +#endif #ifndef __bitwise #define __le16 u_int16_t #define __le32 u_int32_t @@ -50,10 +51,6 @@ #define __be64 u_int64_t #define __force #endif -#else -#include -#include -#endif #ifndef container_of #define container_of(ptr, type, member) ({ \ Index: THANKS =================================================================== --- THANKS (revision 2091) +++ THANKS (working copy) @@ -109,6 +109,7 @@ Mats Hojlund Michal Wrobel Tim Harvey +Andrew Lunn Apologies to anyone whose name was unintentionally left off. Please let us know if you think your name should be mentioned here! Index: ath_hal/ah_os.h =================================================================== --- ath_hal/ah_os.h (revision 2091) +++ ath_hal/ah_os.h (working copy) @@ -147,19 +147,19 @@ #if (AH_BYTE_ORDER == AH_BIG_ENDIAN) #define _OS_REG_WRITE(_ah, _reg, _val) do { \ (0x4000 <= (_reg) && (_reg) < 0x5000) ? \ - writel((_val), (void __force __iomem *)((_ah)->ah_sh + (_reg))) : \ - __raw_writel((_val), (void __force __iomem *)((_ah)->ah_sh + (_reg))); \ + writel((_val), (_ah)->ah_sh + (_reg)) : \ + __raw_writel((_val), (_ah)->ah_sh + (_reg)); \ } while (0) #define _OS_REG_READ(_ah, _reg) \ ((0x4000 <= (_reg) && (_reg) < 0x5000) ? \ - readl((void __force __iomem *)((_ah)->ah_sh + (_reg))) : \ - __raw_readl((void __force __iomem *)((_ah)->ah_sh + (_reg)))) + readl((_ah)->ah_sh + (_reg)) : \ + __raw_readl((_ah)->ah_sh + (_reg))) #else /* AH_LITTLE_ENDIAN */ #define _OS_REG_WRITE(_ah, _reg, _val) do { \ - writel(_val, (void __force __iomem *)((_ah)->ah_sh + (_reg))); \ + writel(_val, (_ah)->ah_sh + (_reg)); \ } while (0) #define _OS_REG_READ(_ah, _reg) \ - readl((void __force __iomem *)((_ah)->ah_sh + (_reg))) + readl((_ah)->ah_sh + (_reg)) #endif /* AH_BYTE_ORDER */ #if defined(AH_DEBUG) || defined(AH_REGOPS_FUNC) || defined(AH_DEBUG_ALQ) Index: ath_hal/ah_osdep.h =================================================================== --- ath_hal/ah_osdep.h (revision 2091) +++ ath_hal/ah_osdep.h (working copy) @@ -54,4 +54,8 @@ #define __packed __attribute__((__packed__)) #endif +/* Replace non-annotated HAL_BUS_HANDLE from ah.h */ +typedef void __iomem* ath_iomem_t; +#define HAL_BUS_HANDLE ath_iomem_t + #endif /* _ATH_AH_OSDEP_H_ */ Index: ath_hal/ah_os.c =================================================================== --- ath_hal/ah_os.c (revision 2091) +++ ath_hal/ah_os.c (working copy) @@ -41,6 +41,9 @@ #define EXPORT_SYMTAB #endif +/* Don't use virtualized timer in Linux 2.6.20+ */ +#define USE_REAL_TIME_DELAY + #ifndef AUTOCONF_INCLUDED #include #endif Index: tools/athkey.c =================================================================== --- tools/athkey.c (revision 2091) +++ tools/athkey.c (working copy) @@ -52,6 +52,8 @@ #include #include +#include + #include "wireless_copy.h" #include "net80211/ieee80211.h" #include "net80211/ieee80211_crypto.h" Index: tools/wlanconfig.c =================================================================== --- tools/wlanconfig.c (revision 2091) +++ tools/wlanconfig.c (working copy) @@ -55,6 +55,8 @@ #include #include +#include + #include "wireless_copy.h" #include "net80211/ieee80211.h" #include "net80211/ieee80211_crypto.h" @@ -178,7 +180,7 @@ ifr.ifr_data = (void *) &cp; vap_create(&ifr); - printf("%s\n", cp.icp_name); + printf("%s\n", ifr.ifr_name); } else if (streq(cmd, "destroy")) { vap_destroy(ifname); } else if (streq(cmd, "list")) { Index: tools/athchans.c =================================================================== --- tools/athchans.c (revision 2091) +++ tools/athchans.c (working copy) @@ -52,6 +52,8 @@ #include #include +#include + #include "wireless_copy.h" #include "net80211/ieee80211.h" #include "net80211/ieee80211_crypto.h" Index: tools/80211stats.c =================================================================== --- tools/80211stats.c (revision 2091) +++ tools/80211stats.c (working copy) @@ -53,6 +53,8 @@ #include #include +#include + #include "wireless_copy.h" #include "net80211/ieee80211.h" #include "net80211/ieee80211_crypto.h" Index: tools/Makefile =================================================================== --- tools/Makefile (revision 2091) +++ tools/Makefile (working copy) @@ -44,15 +44,13 @@ HAL= $(TOP)/hal endif -INCS= -include $(TOP)/include/compat.h - ALL= athstats 80211stats athkey athchans athctrl \ athdebug 80211debug wlanconfig all: $(ALL) -INCS+= -I. -I$(HAL) -I$(TOP) +INCS= -I. -I$(HAL) -I$(TOP) CFLAGS= -g -O2 -Wall ALL_CFLAGS= $(CFLAGS) $(INCS) LDFLAGS= Index: ath/if_ath.c =================================================================== --- ath/if_ath.c (revision 2091) +++ ath/if_ath.c (working copy) @@ -431,9 +431,7 @@ * built with an ah.h that does not correspond to the HAL * module loaded in the kernel. */ - ah = _ath_hal_attach(devid, sc, tag, - (__force HAL_BUS_HANDLE) sc->sc_iobase, - &status); + ah = _ath_hal_attach(devid, sc, tag, sc->sc_iobase, &status); if (ah == NULL) { printk(KERN_ERR "%s: unable to attach hardware: '%s' (HAL status %u)\n", dev->name, ath_get_hal_status_desc(status), status);