if (ni != ic->ic_bss)		 ieee80211_free_node(ic, ni);
ieee80211_release_node(ic, ni);
ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,	int type, int arg){#define	senderr(_x, _v)	do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)	struct ifnet *ifp = &ic->ic_if;	struct mbuf *m;	u_int8_t *frm;	enum ieee80211_phymode mode;	u_int16_t capinfo;	int has_challenge, is_shared_key, ret, timer;	IASSERT(ni != NULL, ("null node"));	/*	 * Hold a reference on the node so it doesn't go away until after	 * the xmit is complete all the way in the driver.  On error we	 * will remove our reference.	 */	if (ni != ic->ic_bss)		ieee80211_ref_node(ni);	timer = 0;	switch (type) {	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:		/*		 * prreq frame format		 *	[tlv] ssid		 *	[tlv] supported rates		 *	[tlv] extended supported rates		 */		m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,			 2 + ic->ic_des_esslen		       + 2 + IEEE80211_RATE_SIZE		       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		m->m_data += sizeof(struct ieee80211_frame);		frm = mtod(m, u_int8_t *);		frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);		mode = ieee80211_chan2mode(ic, ni->ni_chan);		frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);		frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);		m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);		timer = IEEE80211_TRANS_WAIT;		break;	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:		/*		 * probe response frame format		 *	[8] time stamp		 *	[2] beacon interval		 *	[2] cabability information		 *	[tlv] ssid		 *	[tlv] supported rates		 *	[tlv] parameter set (FH/DS)		 *	[tlv] parameter set (IBSS)		 *	[tlv] extended supported rates		 */		m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,			 8 + 2 + 2 + 2		       + 2 + ni->ni_esslen		       + 2 + IEEE80211_RATE_SIZE		       + (ic->ic_phytype == IEEE80211_T_FH ? 7 : 3)		       + 6		       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		m->m_data += sizeof(struct ieee80211_frame);		frm = mtod(m, u_int8_t *);		memset(frm, 0, 8);	/* timestamp should be filled later */		frm += 8;		*(u_int16_t *)frm = htole16(ic->ic_bss->ni_intval);		frm += 2;		if (ic->ic_opmode == IEEE80211_M_IBSS)			capinfo = IEEE80211_CAPINFO_IBSS;		else			capinfo = IEEE80211_CAPINFO_ESS;		if (ic->ic_flags & IEEE80211_F_WEPON)			capinfo |= IEEE80211_CAPINFO_PRIVACY;		if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&		    IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))			capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;		*(u_int16_t *)frm = htole16(capinfo);		frm += 2;		frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,				ic->ic_bss->ni_esslen);		frm = ieee80211_add_rates(frm, &ic->ic_bss->ni_rates);		if (ic->ic_phytype == IEEE80211_T_FH) {                        *frm++ = IEEE80211_ELEMID_FHPARMS;                        *frm++ = 5;                        *frm++ = ni->ni_fhdwell & 0x00ff;                        *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff;                        *frm++ = IEEE80211_FH_CHANSET(			    ieee80211_chan2ieee(ic, ni->ni_chan));                        *frm++ = IEEE80211_FH_CHANPAT(			    ieee80211_chan2ieee(ic, ni->ni_chan));                        *frm++ = ni->ni_fhindex;		} else {			*frm++ = IEEE80211_ELEMID_DSPARMS;			*frm++ = 1;			*frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);		}		if (ic->ic_opmode == IEEE80211_M_IBSS) {			*frm++ = IEEE80211_ELEMID_IBSSPARMS;			*frm++ = 2;			*frm++ = 0; *frm++ = 0;		/* TODO: ATIM window */		} else {	/* IEEE80211_M_HOSTAP */			/* TODO: TIM */			*frm++ = IEEE80211_ELEMID_TIM;			*frm++ = 4;	/* length */			*frm++ = 0;	/* DTIM count */			*frm++ = 1;	/* DTIM period */			*frm++ = 0;	/* bitmap control */			*frm++ = 0;	/* Partial Virtual Bitmap (variable length) */		}		frm = ieee80211_add_xrates(frm, &ic->ic_bss->ni_rates);		m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);		break;	case IEEE80211_FC0_SUBTYPE_AUTH:		MGETHDR(m, M_DONTWAIT, MT_DATA);		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE ||		    arg == IEEE80211_AUTH_SHARED_RESPONSE) &&		    ni->ni_challenge != NULL);		is_shared_key = has_challenge || (ni->ni_challenge != NULL &&		    arg == IEEE80211_AUTH_SHARED_PASS);		if (has_challenge) {			MH_ALIGN(m, 2 * 3 + 2 + IEEE80211_CHALLENGE_LEN);			m->m_pkthdr.len = m->m_len =			    2 * 3 + 2 + IEEE80211_CHALLENGE_LEN;		} else {			MH_ALIGN(m, 2 * 3);			m->m_pkthdr.len = m->m_len = 2 * 3;		}		frm = mtod(m, u_int8_t *);		((u_int16_t *)frm)[0] =		    (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED)		                    : htole16(IEEE80211_AUTH_ALG_OPEN);		((u_int16_t *)frm)[1] = htole16(arg);	/* sequence number */		((u_int16_t *)frm)[2] = 0;		/* status */		if (has_challenge) {			((u_int16_t *)frm)[3] =			    htole16((IEEE80211_CHALLENGE_LEN << 8) |			    IEEE80211_ELEMID_CHALLENGE);			memcpy(&((u_int16_t *)frm)[4], ni->ni_challenge,			    IEEE80211_CHALLENGE_LEN);			if (arg == IEEE80211_AUTH_SHARED_RESPONSE) {				IEEE80211_DPRINTF((				    "%s: request encrypt frame\n", __func__));				m->m_flags |= M_LINK0; /* WEP-encrypt, please */			}		}		if (ic->ic_opmode == IEEE80211_M_STA)			timer = IEEE80211_TRANS_WAIT;		break;	case IEEE80211_FC0_SUBTYPE_DEAUTH:		if (ifp->if_flags & IFF_DEBUG)			if_printf(ifp, "station %s deauthenticate (reason %d)\n",			    ether_sprintf(ni->ni_macaddr), arg);		MGETHDR(m, M_DONTWAIT, MT_DATA);		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		MH_ALIGN(m, 2);		m->m_pkthdr.len = m->m_len = 2;		*mtod(m, u_int16_t *) = htole16(arg);	/* reason */		break;	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:	case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:		/*		 * asreq frame format		 *	[2] capability information		 *	[2] listen interval		 *	[6*] current AP address (reassoc only)		 *	[tlv] ssid		 *	[tlv] supported rates		 *	[tlv] extended supported rates		 */		m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,			 sizeof(capinfo)		       + sizeof(u_int16_t)		       + IEEE80211_ADDR_LEN		       + 2 + ni->ni_esslen		       + 2 + IEEE80211_RATE_SIZE		       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		m->m_data += sizeof(struct ieee80211_frame);		frm = mtod(m, u_int8_t *);		capinfo = 0;		if (ic->ic_opmode == IEEE80211_M_IBSS)			capinfo |= IEEE80211_CAPINFO_IBSS;		else		/* IEEE80211_M_STA */			capinfo |= IEEE80211_CAPINFO_ESS;		if (ic->ic_flags & IEEE80211_F_WEPON)			capinfo |= IEEE80211_CAPINFO_PRIVACY;		/*		 * NB: Some 11a AP's reject the request when		 *     short premable is set.		 */		if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&		    IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))			capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;		if (ic->ic_flags & IEEE80211_F_SHSLOT)			capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;		*(u_int16_t *)frm = htole16(capinfo);		frm += 2;		*(u_int16_t *)frm = htole16(ic->ic_lintval);		frm += 2;		if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {			IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);			frm += IEEE80211_ADDR_LEN;		}		frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);		frm = ieee80211_add_rates(frm, &ni->ni_rates);		frm = ieee80211_add_xrates(frm, &ni->ni_rates);		m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);		timer = IEEE80211_TRANS_WAIT;		break;	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:		/*		 * asreq frame format		 *	[2] capability information		 *	[2] status		 *	[2] association ID		 *	[tlv] supported rates		 *	[tlv] extended supported rates		 */		m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,			 sizeof(capinfo)		       + sizeof(u_int16_t)		       + sizeof(u_int16_t)		       + 2 + IEEE80211_RATE_SIZE		       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		m->m_data += sizeof(struct ieee80211_frame);		frm = mtod(m, u_int8_t *);		capinfo = IEEE80211_CAPINFO_ESS;		if (ic->ic_flags & IEEE80211_F_WEPON)			capinfo |= IEEE80211_CAPINFO_PRIVACY;		if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&		    IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))			capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;		*(u_int16_t *)frm = htole16(capinfo);		frm += 2;		*(u_int16_t *)frm = htole16(arg);	/* status */		frm += 2;		if (arg == IEEE80211_STATUS_SUCCESS)			*(u_int16_t *)frm = htole16(ni->ni_associd);		frm += 2;		frm = ieee80211_add_rates(frm, &ni->ni_rates);		frm = ieee80211_add_xrates(frm, &ni->ni_rates);		m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);		break;	case IEEE80211_FC0_SUBTYPE_DISASSOC:		if (ifp->if_flags & IFF_DEBUG)			if_printf(ifp, "station %s disassociate (reason %d)\n",			    ether_sprintf(ni->ni_macaddr), arg);		MGETHDR(m, M_DONTWAIT, MT_DATA);		if (m == NULL)			senderr(ENOMEM, is_tx_nombuf);		MH_ALIGN(m, 2);		m->m_pkthdr.len = m->m_len = 2;		*mtod(m, u_int16_t *) = htole16(arg);	/* reason */		break;	default:		IEEE80211_DPRINTF(("%s: invalid mgmt frame type %u\n",			__func__, type));		senderr(EINVAL, is_tx_unknownmgt);		/* NOTREACHED */	}	ret = ieee80211_mgmt_output(ifp, ni, m, type);	if (ret == 0) {		if (timer)			ic->ic_mgt_timer = timer;	} else {bad:		if (ni != ic->ic_bss)		/* remove ref we added */			ieee80211_free_node(ic, ni);	}	return ret;#undef senderr}