/**
 *  @brief Get number of aggregated packets
 *
 *  @param data			A pointer to packet data
 *  @param total_pkt_len	Total packet length
 *
 *  @return			Number of packets
 */
static int
wlan_11n_get_num_aggrpkts(t_u8 * data, int total_pkt_len)
{
	int pkt_count = 0, pkt_len, pad;
	t_u8 hdr_len = sizeof(Eth803Hdr_t);

	ENTER();
	while (total_pkt_len >= hdr_len) {
		/* Length will be in network format, change it to host */
		pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 *
							  MLAN_MAC_ADDR_LENGTH))));
		if (pkt_len > total_pkt_len) {
			PRINTM(MERROR, "Error in packet length.\n");
			break;
		}

		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
		data += pkt_len + pad + sizeof(Eth803Hdr_t);
		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
		++pkt_count;
	}
	LEAVE();
	return pkt_count;
}
Beispiel #2
0
/**
 *  @brief Function to send packet
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *
 *  @return			MLAN_STATUS_PENDING
 */
mlan_status
mlan_send_packet(IN t_void * pmlan_adapter, IN pmlan_buffer pmbuf)
{
    mlan_status ret = MLAN_STATUS_PENDING;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;

    ENTER();
    MASSERT(pmlan_adapter && pmbuf);

    MASSERT(pmbuf->bss_num < MLAN_MAX_BSS_NUM);
    pmbuf->flags = MLAN_BUF_FLAG_MOAL_TX_BUF;
    if ((pmadapter->priv[pmbuf->bss_num]->port_ctrl_mode == MTRUE) &&
        (mlan_ntohs(*(t_u16 *) & pmbuf->pbuf[pmbuf->data_offset +
                                             MLAN_ETHER_PKT_TYPE_OFFSET]) ==
         MLAN_ETHER_PKT_TYPE_EAPOL)) {
        PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
        wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
    } else {
        /* Transmit the packet */
        wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
    }

    LEAVE();
    return ret;
}
/**
 *  @brief Function to send packet
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *
 *  @return			MLAN_STATUS_PENDING
 */
mlan_status
mlan_send_packet(IN t_void * pmlan_adapter, IN pmlan_buffer pmbuf)
{
	mlan_status ret = MLAN_STATUS_PENDING;
	mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
	mlan_private *pmpriv;
	t_u16 eth_type = 0;
	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
	tdlsStatus_e tdls_status;

	ENTER();
	MASSERT(pmlan_adapter && pmbuf);

	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
	pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
	pmpriv = pmadapter->priv[pmbuf->bss_index];

	eth_type =
		mlan_ntohs(*(t_u16 *) & pmbuf->
			   pbuf[pmbuf->data_offset +
				MLAN_ETHER_PKT_TYPE_OFFSET]);
	if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
	     ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL)
	      || (eth_type == MLAN_ETHER_PKT_TYPE_WAPI)
	     ))
	    || (eth_type == MLAN_ETHER_PKT_TYPE_TDLS_ACTION)
	    || (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)

		) {
		if (eth_type == MLAN_ETHER_PKT_TYPE_TDLS_ACTION) {
			memcpy(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
			       MLAN_MAC_ADDR_LENGTH);
			tdls_status = wlan_get_tdls_link_status(pmpriv, ra);
			if (MTRUE == wlan_is_tdls_link_setup(tdls_status) ||
			    !pmpriv->media_connected)
				pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
		}
		PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
		wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
	} else {
		/* Transmit the packet */
		wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
	}

	LEAVE();
	return ret;
}
Beispiel #4
0
/**
 *  @brief Get number of aggregated packets
 *
 *  @param data			A pointer to packet data
 *  @param total_pkt_len	Total packet length
 *
 *  @return			Number of packets
 */
static int
wlan_11n_get_num_aggrpkts(t_u8 * data, int total_pkt_len)
{
    int pkt_count = 0, pkt_len, pad;

    ENTER();
    while (total_pkt_len > 0) {
        /* Length will be in network format, change it to host */
        pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH))));
        pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
            (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
        data += pkt_len + pad + sizeof(Eth803Hdr_t);
        total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
        ++pkt_count;
    }
    LEAVE();
    return pkt_count;
}
/**
 *  @brief Function to send packet
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *  @param pmbuf		A pointer to mlan_buffer structure
 *
 *  @return			MLAN_STATUS_PENDING
 */
mlan_status
mlan_send_packet(IN t_void * pmlan_adapter, IN pmlan_buffer pmbuf)
{
    mlan_status ret = MLAN_STATUS_PENDING;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    mlan_private *pmpriv;
    t_u16 eth_type = 0;

    ENTER();
    MASSERT(pmlan_adapter && pmbuf);

    MASSERT(pmbuf->bss_index < pmadapter->priv_num);
    pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
    pmpriv = pmadapter->priv[pmbuf->bss_index];

    eth_type =
        mlan_ntohs(*(t_u16 *) & pmbuf->
                   pbuf[pmbuf->data_offset +
                        MLAN_ETHER_PKT_TYPE_OFFSET]);
    if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
            ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL)
             || (eth_type == MLAN_ETHER_PKT_TYPE_WAPI)
            ))
            || (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)

       ) {
        PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
        wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
    } else {
        /* Transmit the packet */
        wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
    }

    LEAVE();
    return ret;
}
/**
 *  @brief Deaggregate the received AMSDU packet
 *
 *  @param priv		A pointer to mlan_private structure
 *  @param pmbuf	A pointer to aggregated data packet
 *
 *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
 */
mlan_status
wlan_11n_deaggregate_pkt(mlan_private * priv, pmlan_buffer pmbuf)
{
	t_u16 pkt_len;
	int total_pkt_len;
	t_u8 *data;
	t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;
	int pad;
	mlan_status ret = MLAN_STATUS_FAILURE;
	RxPacketHdr_t *prx_pkt;
	mlan_buffer *daggr_mbuf = MNULL;
	mlan_adapter *pmadapter = priv->adapter;
	t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03,
		0x00, 0x00, 0x00
	};
	t_u8 hdr_len = sizeof(Eth803Hdr_t);

	ENTER();

	data = (t_u8 *) (pmbuf->pbuf + pmbuf->data_offset);
	total_pkt_len = pmbuf->data_len;

	/* Sanity test */
	if (total_pkt_len > max_rx_data_size) {
		PRINTM(MERROR, "Total packet length greater than tx buffer"
		       " size %d\n", total_pkt_len);
		goto done;
	}

	pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);

	while (total_pkt_len >= hdr_len) {
		prx_pkt = (RxPacketHdr_t *) data;
		/* Length will be in network format, change it to host */
		pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 *
							  MLAN_MAC_ADDR_LENGTH))));
		if (pkt_len > total_pkt_len) {
			PRINTM(MERROR,
			       "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
			       total_pkt_len, pkt_len);
			break;
		}

		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;

		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);

		if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr,
			   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
			memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 *
								       MLAN_MAC_ADDR_LENGTH));
			data += LLC_SNAP_LEN;
			pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
		} else {
			*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH))
				= (t_u16) 0;
			pkt_len += sizeof(Eth803Hdr_t);
		}
		daggr_mbuf =
			wlan_alloc_mlan_buffer(pmadapter, pkt_len, 0,
					       MOAL_ALLOC_MLAN_BUFFER);
		if (daggr_mbuf == MNULL) {
			PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
			LEAVE();
			return MLAN_STATUS_FAILURE;
		}
		daggr_mbuf->bss_index = pmbuf->bss_index;
		daggr_mbuf->buf_type = pmbuf->buf_type;
		daggr_mbuf->data_len = pkt_len;
		daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
		daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
		daggr_mbuf->pparent = pmbuf;
		daggr_mbuf->priority = pmbuf->priority;
		memcpy(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset,
		       data, pkt_len);

#ifdef UAP_SUPPORT
		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
			ret = wlan_uap_recv_packet(priv, daggr_mbuf);
		} else {
#endif /* UAP_SUPPORT */
			ret = pmadapter->callbacks.moal_recv_packet(pmadapter->
								    pmoal_handle,
								    daggr_mbuf);
#ifdef UAP_SUPPORT
		}
#endif /* UAP_SUPPORT */
		switch (ret) {
		case MLAN_STATUS_PENDING:
			break;
		case MLAN_STATUS_FAILURE:
			PRINTM(MERROR, "Deaggr, send to moal failed\n");
			daggr_mbuf->status_code = MLAN_ERROR_PKT_INVALID;
		case MLAN_STATUS_SUCCESS:
			wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
			break;
		default:
			break;
		}

		data += pkt_len + pad;
	}

done:
	LEAVE();
	return ret;
}
Beispiel #7
0
/**
 *  @brief This function process tdls action frame
 *
 *  @param priv        A pointer to mlan_private structure
 *  @param pbuf        A pointer to tdls action frame buffer
 *  @param len         len of tdls action frame buffer
 *  @return            N/A
 */
void
wlan_process_tdls_action_frame(pmlan_private priv, t_u8 *pbuf, t_u32 len)
{
	sta_node *sta_ptr = MNULL;
	t_u8 *peer;
	t_u8 *pos, *end;
	t_u8 action;
	int ie_len = 0;
	t_u8 i;

#define TDLS_PAYLOAD_TYPE     2
#define TDLS_CATEGORY         0x0c
#define TDLS_REQ_FIX_LEN      6
#define TDLS_RESP_FIX_LEN     8
#define TDLS_CONFIRM_FIX_LEN  6
	if (len < (sizeof(EthII_Hdr_t) + 3))
		return;
	if (*(t_u8 *)(pbuf + sizeof(EthII_Hdr_t)) != TDLS_PAYLOAD_TYPE)
		/* TDLS payload type = 2 */
		return;
	if (*(t_u8 *)(pbuf + sizeof(EthII_Hdr_t) + 1) != TDLS_CATEGORY)
		/* TDLS category = 0xc */
		return;
	peer = pbuf + MLAN_MAC_ADDR_LENGTH;

	action = *(t_u8 *)(pbuf + sizeof(EthII_Hdr_t) + 2);
	/* 2= payload type + category */

	if (action > TDLS_SETUP_CONFIRM) {
		/* just handle TDLS setup request/response/confirm */
		PRINTM(MMSG, "Recv TDLS Action: peer=" MACSTR ", action=%d\n",
		       MAC2STR(peer), action);
		return;
	}

	sta_ptr = wlan_add_station_entry(priv, peer);
	if (!sta_ptr)
		return;
	if (action == TDLS_SETUP_REQUEST) {	/* setup request */
		sta_ptr->status = TDLS_NOT_SETUP;
		PRINTM(MMSG, "Recv TDLS SETUP Request: peer=" MACSTR "\n",
		       MAC2STR(peer));
		wlan_hold_tdls_packets(priv, peer);
		if (len < (sizeof(EthII_Hdr_t) + TDLS_REQ_FIX_LEN))
			return;
		pos = pbuf + sizeof(EthII_Hdr_t) + 4;
		/* payload 1+ category 1 + action 1 +dialog 1 */
		sta_ptr->capability = mlan_ntohs(*(t_u16 *)pos);
		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_REQ_FIX_LEN;
		pos += 2;
	} else if (action == 1) {	/* setup respons */
		PRINTM(MMSG, "Recv TDLS SETUP Response: peer=" MACSTR "\n",
		       MAC2STR(peer));
		if (len < (sizeof(EthII_Hdr_t) + TDLS_RESP_FIX_LEN))
			return;
		pos = pbuf + sizeof(EthII_Hdr_t) + 6;
		/* payload 1+ category 1 + action 1 +dialog 1 +status 2 */
		sta_ptr->capability = mlan_ntohs(*(t_u16 *)pos);
		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_RESP_FIX_LEN;
		pos += 2;
	} else {		/* setup confirm */
		PRINTM(MMSG, "Recv TDLS SETUP Confirm: peer=" MACSTR "\n",
		       MAC2STR(peer));
		if (len < (sizeof(EthII_Hdr_t) + TDLS_CONFIRM_FIX_LEN))
			return;
		pos = pbuf + sizeof(EthII_Hdr_t) + TDLS_CONFIRM_FIX_LEN;
		/* payload 1+ category 1 + action 1 +dialog 1 + status 2 */
		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_CONFIRM_FIX_LEN;
	}
	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
		if (pos + 2 + pos[1] > end)
			break;
		switch (*pos) {
		case SUPPORTED_RATES:
			sta_ptr->rate_len = pos[1];
			for (i = 0; i < pos[1]; i++)
				sta_ptr->support_rate[i] = pos[2 + i];
			break;
		case EXTENDED_SUPPORTED_RATES:
			for (i = 0; i < pos[1]; i++)
				sta_ptr->support_rate[sta_ptr->rate_len + i] =
					pos[2 + i];
			sta_ptr->rate_len += pos[1];
			break;
		case HT_CAPABILITY:
			memcpy(priv->adapter, (t_u8 *)&sta_ptr->HTcap, pos,
			       sizeof(IEEEtypes_HTCap_t));
			sta_ptr->is_11n_enabled = 1;
			DBG_HEXDUMP(MDAT_D, "TDLS HT capability",
				    (t_u8 *)(&sta_ptr->HTcap),
				    MIN(sizeof(IEEEtypes_HTCap_t),
					MAX_DATA_DUMP_LEN));
			break;
		case HT_OPERATION:
			memcpy(priv->adapter, &sta_ptr->HTInfo, pos,
			       sizeof(IEEEtypes_HTInfo_t));
			DBG_HEXDUMP(MDAT_D, "TDLS HT info",
				    (t_u8 *)(&sta_ptr->HTInfo),
				    MIN(sizeof(IEEEtypes_HTInfo_t),
					MAX_DATA_DUMP_LEN));
			break;
		case BSSCO_2040:
			memcpy(priv->adapter, (t_u8 *)&sta_ptr->BSSCO_20_40,
			       pos, sizeof(IEEEtypes_2040BSSCo_t));
			break;
		case EXT_CAPABILITY:
			memcpy(priv->adapter, (t_u8 *)&sta_ptr->ExtCap, pos,
			       pos[1] + sizeof(IEEEtypes_Header_t));
			DBG_HEXDUMP(MDAT_D, "TDLS Extended capability",
				    (t_u8 *)(&sta_ptr->ExtCap),
				    sta_ptr->ExtCap.ieee_hdr.len + 2);
			break;
		case RSN_IE:
			memcpy(priv->adapter, (t_u8 *)&sta_ptr->rsn_ie, pos,
			       pos[1] + sizeof(IEEEtypes_Header_t));
			DBG_HEXDUMP(MDAT_D, "TDLS Rsn ie ",
				    (t_u8 *)(&sta_ptr->rsn_ie),
				    pos[1] + sizeof(IEEEtypes_Header_t));
			break;
		case QOS_INFO:
			sta_ptr->qos_info = pos[2];
			PRINTM(MDAT_D, "TDLS qos info %x\n", sta_ptr->qos_info);
			break;
		case LINK_ID:
			memcpy(priv->adapter, (t_u8 *)&sta_ptr->link_ie, pos,
			       sizeof(IEEEtypes_LinkIDElement_t));
			break;

		default:
			break;
		}
	}
	return;
}