diff -rup sys/net80211/ieee80211_ioctl.c.orig sys/net80211/ieee80211_ioctl.c --- sys/net80211/ieee80211_ioctl.c.orig Fri Mar 31 08:54:55 2006 +++ sys/net80211/ieee80211_ioctl.c Thu Jul 27 09:43:23 2006 @@ -1829,7 +1829,8 @@ ieee80211_ioctl_setmlme(struct ieee80211 return error; switch (mlme.im_op) { case IEEE80211_MLME_ASSOC: - if (ic->ic_opmode != IEEE80211_M_STA) + if (ic->ic_opmode != IEEE80211_M_STA && + ic->ic_opmode != IEEE80211_M_IBSS) return EINVAL; /* XXX must be in S_SCAN state? */ @@ -1847,8 +1848,12 @@ ieee80211_ioctl_setmlme(struct ieee80211 */ ni = ieee80211_find_node(&ic->ic_scan, mlme.im_macaddr); } - if (ni == NULL) - return EINVAL; + if (ni == NULL) { + if (ic->ic_opmode != IEEE80211_M_IBSS) + return EINVAL; + ieee80211_create_ibss2(ic); + break; + } if (!ieee80211_sta_join(ic, ni)) { ieee80211_free_node(ni); return EINVAL; diff -rup sys/net80211/ieee80211_node.c.orig sys/net80211/ieee80211_node.c --- sys/net80211/ieee80211_node.c.orig Sat Jun 3 13:18:51 2006 +++ sys/net80211/ieee80211_node.c Thu Jul 27 09:45:08 2006 @@ -470,6 +470,71 @@ ieee80211_create_ibss(struct ieee80211co } void +ieee80211_create_ibss2(struct ieee80211com *ic) +{ + struct ieee80211_node_table *nt = &ic->ic_scan; + struct ieee80211_node *ni; + + if (ic->ic_opmode != IEEE80211_M_IBSS && + ic->ic_opmode != IEEE80211_M_AHDEMO) + return; + + if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) { + ieee80211_create_ibss(ic, ic->ic_des_chan); + } else { + u_int8_t maxrssi[IEEE80211_CHAN_MAX]; /* XXX off stack? */ + int i, bestchan; + u_int8_t rssi; + + /* + * The passive scan to look for existing AP's completed, + * select a channel to camp on. Identify the channels + * that already have one or more AP's and try to locate + * an unoccupied one. If that fails, pick a channel that + * looks to be quietest. + */ + memset(maxrssi, 0, sizeof(maxrssi)); + IEEE80211_NODE_LOCK(nt); + TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { + rssi = ic->ic_node_getrssi(ni); + if (ni->ni_chan == IEEE80211_CHAN_ANYC) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, + "invalid channel on %p\n", ni); + continue; + } + i = ieee80211_chan2ieee(ic, ni->ni_chan); + if (rssi > maxrssi[i]) + maxrssi[i] = rssi; + } + IEEE80211_NODE_UNLOCK(nt); + /* XXX select channel more intelligently */ + bestchan = -1; + for (i = 0; i < IEEE80211_CHAN_MAX; i++) + if (isset(ic->ic_chan_active, i)) { + /* + * If the channel is unoccupied the max rssi + * should be zero; just take it. Otherwise + * track the channel with the lowest rssi and + * use that when all channels appear occupied. + */ + if (maxrssi[i] == 0) { + bestchan = i; + break; + } + if (bestchan == -1 || + maxrssi[i] < maxrssi[bestchan]) + bestchan = i; + } + + if (bestchan != -1) { + ieee80211_create_ibss(ic, &ic->ic_channels[bestchan]); + return; + } + /* no suitable channel, should not happen */ + } +} + +void ieee80211_reset_bss(struct ieee80211com *ic) { struct ieee80211_node *ni, *obss; diff -rup sys/net80211/ieee80211_node.h.orig sys/net80211/ieee80211_node.h --- sys/net80211/ieee80211_node.h.orig Fri Mar 31 08:54:55 2006 +++ sys/net80211/ieee80211_node.h Thu Jul 27 09:46:44 2006 @@ -189,6 +189,7 @@ void ieee80211_begin_scan(struct ieee802 int ieee80211_next_scan(struct ieee80211com *); void ieee80211_probe_curchan(struct ieee80211com *, int); void ieee80211_create_ibss(struct ieee80211com*, struct ieee80211_channel *); +void ieee80211_create_ibss2(struct ieee80211com*); void ieee80211_reset_bss(struct ieee80211com *); void ieee80211_cancel_scan(struct ieee80211com *); void ieee80211_end_scan(struct ieee80211com *); diff -rup sys/net80211/ieee80211_output.c.orig sys/net80211/ieee80211_output.c --- sys/net80211/ieee80211_output.c.orig Fri Mar 31 08:54:55 2006 +++ sys/net80211/ieee80211_output.c Mon Jul 24 09:31:24 2006 @@ -742,9 +742,12 @@ ieee80211_setup_wpa_ie(struct ieee80211c { WPA_OUI_BYTES, WPA_CSE_CCMP }, { 0x00, 0x00, 0x00, 0x00 }, /* XXX CKIP */ { WPA_OUI_BYTES, WPA_CSE_NULL }, + { WPA_OUI_BYTES, WPA_CSE_NULL }, }; static const u_int8_t wep104_suite[4] = { WPA_OUI_BYTES, WPA_CSE_WEP104 }; + static const u_int8_t key_mgt_none[4] = + { WPA_OUI_BYTES, WPA_ASE_NONE }; static const u_int8_t key_mgt_unspec[4] = { WPA_OUI_BYTES, WPA_ASE_8021X_UNSPEC }; static const u_int8_t key_mgt_psk[4] = @@ -779,10 +782,18 @@ ieee80211_setup_wpa_ie(struct ieee80211c selcnt[0]++; ADDSELECTOR(frm, cipher_suite[IEEE80211_CIPHER_TKIP]); } + if (rsn->rsn_ucastcipherset & (1<rsn_keymgmtset == WPA_ASE_NONE) { + selcnt[0]++; + ADDSELECTOR(frm, key_mgt_none); + } if (rsn->rsn_keymgmtset & WPA_ASE_8021X_UNSPEC) { selcnt[0]++; ADDSELECTOR(frm, key_mgt_unspec); @@ -1178,11 +1189,11 @@ ieee80211_send_mgmt(struct ieee80211com *frm++ = 2; *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ } - if (ic->ic_flags & IEEE80211_F_WPA) - frm = ieee80211_add_wpa(frm, ic); if (ic->ic_curmode == IEEE80211_MODE_11G) frm = ieee80211_add_erp(frm, ic); frm = ieee80211_add_xrates(frm, &ni->ni_rates); + if (ic->ic_flags & IEEE80211_F_WPA) + frm = ieee80211_add_wpa(frm, ic); if (ic->ic_flags & IEEE80211_F_WME) frm = ieee80211_add_wme_param(frm, &ic->ic_wme); m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); @@ -1497,18 +1508,18 @@ ieee80211_beacon_alloc(struct ieee80211c bo->bo_tim_len = 1; } bo->bo_trailer = frm; - if (ic->ic_flags & IEEE80211_F_WME) { - bo->bo_wme = frm; - frm = ieee80211_add_wme_param(frm, &ic->ic_wme); - ic->ic_flags &= ~IEEE80211_F_WMEUPDATE; - } - if (ic->ic_flags & IEEE80211_F_WPA) - frm = ieee80211_add_wpa(frm, ic); if (ic->ic_curmode == IEEE80211_MODE_11G) { bo->bo_erp = frm; frm = ieee80211_add_erp(frm, ic); } efrm = ieee80211_add_xrates(frm, rs); + if (ic->ic_flags & IEEE80211_F_WME) { + bo->bo_wme = efrm; + efrm = ieee80211_add_wme_param(efrm, &ic->ic_wme); + ic->ic_flags &= ~IEEE80211_F_WMEUPDATE; + } + if (ic->ic_flags & IEEE80211_F_WPA) + efrm = ieee80211_add_wpa(efrm, ic); bo->bo_trailer_len = efrm - bo->bo_trailer; m->m_pkthdr.len = m->m_len = efrm - mtod(m, u_int8_t *); diff -rup sys/net80211/ieee80211_proto.c.orig sys/net80211/ieee80211_proto.c --- sys/net80211/ieee80211_proto.c.orig Fri Mar 31 08:54:55 2006 +++ sys/net80211/ieee80211_proto.c Thu Jul 27 09:05:01 2006 @@ -972,6 +972,8 @@ ieee80211_newstate(struct ieee80211com * * bypass the scan and startup immediately. */ ieee80211_create_ibss(ic, ic->ic_des_chan); + ieee80211_cancel_scan(ic); + ieee80211_notify_scan_done(ic); } else { ieee80211_begin_scan(ic, arg); }