How to determine whether a 802.11 raw packet has FCS (4bytes) in a NDIS 6 filter driver? - c

I have a NDIS 6 filter driver working on Windows Vista and later systems.
I have bound it below NativeWiFi Filter so I can see 802.11 packets instead of fake Ethernet packets.
And I have set the NDIS_PACKET_TYPE_802_11_RAW_DATA and NDIS_PACKET_TYPE_802_11_RAW_MGMT in the packet filter based on: https://msdn.microsoft.com/en-us/library/windows/hardware/ff554833(v=vs.85).aspx, so I can receive the Raw 802.11 Packets indications from the miniport.
Then I switched my wireless adapter to Monitor Mode.
By now my filter driver can receive all the 802.11 control and management packets.
My question is how to determine whether a 802.11 raw packet has FCS (frame check sequence, 4bytes) in my driver?
I'm asking this because i'm adding Radiotap header (http://radiotap.org/) to the packets and radiotap has a field called Flags that specified whether the 802.11 packet has a FCS or not.
My experiment with my laptop with a wireless adapter Qualcomm Atheros AR9485WB-EG Wireless Network Adapter shows that Beacon and Reassociation Response packets have FCS and all other 802.11 packets don't have one. And the wrong Flags in the radiotap header will cause Wireshark to show Malformed Packet for those packets. This is why I need to determine the availability of FCS in my driver.
My code is like below, and I want to know how to write the if condition.
// [Radiotap] "Flags" field.
if (TRUE) // The packet doesn't have FCS. We always have no FCS for all packets currently.
{
pRadiotapHeader->it_present |= BIT(IEEE80211_RADIOTAP_FLAGS);
*((UCHAR*)Dot11RadiotapHeader + cur) = 0x0; // 0x0: none
cur += sizeof(UCHAR) / sizeof(UCHAR);
}
else // The packet has FCS.
{
pRadiotapHeader->it_present |= BIT(IEEE80211_RADIOTAP_FLAGS);
*((UCHAR*)Dot11RadiotapHeader + cur) = IEEE80211_RADIOTAP_F_FCS; // 0x10: frame includes FCS
// FCS check fails.
if ((pwInfo->uReceiveFlags & DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE) == DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE)
{
*((UCHAR*)Dot11RadiotapHeader + cur) |= IEEE80211_RADIOTAP_F_BADFCS; // 0x40: frame failed FCS check
}
cur += sizeof(UCHAR) / sizeof(UCHAR);
}
Any methods? Thanks!

My experiment with my laptop with a wireless adapter Qualcomm Atheros AR9485WB-EG Wireless Network Adapter shows that Beacon and Reassociation Response packets have FCS and all other 802.11 packets don't have one.
No, it doesn't. When I looked at the same capture, and forced the "FCS at end" flag on, I found that a LOT of frames other than those frames had an FCS that Wireshark reported as valid. Do NOT assume that, just because a frame didn't show a "Malformed frame" error, it didn't have an FCS; the "Malformed frame" errors are due to Wireshark thinking the FCS is frame data, and trying to dissect items larger than the 4 bytes of the FCS. For data frames, the 802.11 dissector doesn't dissect the payload, and if the payload has a length field of its own, as IPv4 and IPv6 frames do, that length will be used, and the FCS will be treated as extra data after the payload and not cause a "Malformed frame" error.
What you should try is to check whether uReceiveFlags has DOT11_RECV_FLAG_RAW_PACKET set and, if so, assume the frame has an FCS, otherwise assume it doesn't.
And remember that, in monitor mode, frames that couldn't be completely received may still be provided to the host, so some "Malformed frame" errors in monitor mode may be due to, for example, the frame being cut short by the radio, so don't assume that a "Malformed frame" error means that the frame shouldn't have had the "FCS at end" flag set.

Related

How is Forward Error Correction implemented in Unet audio?

How is Forward Error Correction implemented in Unet audio, and what approach should be used to work on the existing algorithm or to add a new FEC technique to the Unetstack?
The Unet audio community version implements a ½ rate convolution FEC, which can be enabled or disabled using phy[1].fec or phy[2].fec parameters. If you disable the FEC and there are any errors in the received frame, the CRC check will likely fail, and you'll get a BadFrameNtf instead of a RxFrameNtf. The BadFrameNtf message will have the erroneous bits available as data. If you want to implement your own FEC, you can use these as hard decisions from the PHY layer and do your decoding.
So, to implement your own FEC:
Disable the default FEC on transmit and receive modems (phy[2].fec = 0).
Create your own uncoded frame by including source address, destination address, and protocol number along with your data bits. Compute a CRC and include it in the frame.
FEC encode your uncoded frame and send the encoded bits using a TxRawFrameReq from the transmitter. The "raw" frame request tells UnetStack not to add its default headers.
Receive the corresponding BadFrameNtf on the receiver and extract the received bits from data field.
FEC decode the received bits to yield the uncoded received frame.
Check CRC on the uncoded receive frame. If that passes, then extract the source address, destination address, protocol number and your data from the uncoded received frame.
If you want the rest of the stack to process this as if it came from PHY, you can send a RxFrameNtf with relevant fields filled in and send it on the topic(phy).

Who take care tcp message order

I listen to tcp socket in linux with recv or recvfrom.
Who taking care that I will get the tcp packets on the right order?
Is that the kernel taking care so if packet 1 came after packet 2 the kernel will drop out both/save packet 2 until packet 1 will come?
Or maybe I need to take care on user-space to the order of tcp packet?
On Linux based systems in any normal scenario, this is handled by the kernel.
You can find the source code here, and here's an abridged version:
/* Queue data for delivery to the user.
* Packets in sequence go to the receive queue.
* Out of sequence packets to the out_of_order_queue.
*/
if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
/* packet is in order */
}
if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
/* already received */
}
if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt + tcp_receive_window(tp)))
goto out_of_window;
if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
/* Partial packet, seq < rcv_next < end_seq */
}
/* append to out-of-order queue */
tcp_data_queue_ofo(sk, skb);
along with the actual implementation that does the reordering using RB trees:
To quote Wikipedia,
At the lower levels of the protocol stack, due to network congestion, traffic load balancing, or unpredictable network behaviour, IP packets may be lost, duplicated, or delivered out of order. TCP detects these problems, requests re-transmission of lost data, rearranges out-of-order data, [...]
It's an inherent property of the protocol that you will receive the data in the correct order (or not at all).
Note that TCP is a stream protocol, so you can't even detect packet boundaries. A call to recv/recvfrom may return a portion of a packet, and it may return bytes that came from more than one packet.

Packet capture using PCAP library

I have a scenario where a laptop is connected to an external hardware via ethernet.
The laptop can peek and poke the hardware, i.e. send a request packet to the hardware which generates a response packet from the hardware which the laptop receives and interprets.
This is all happening at the LLC layer, i.e. quite low level. I assemble the bytes constituting the request packet manually and likewise, I read the response packet bytes manually.
My problem is that I don't always 'see' the response packet. Running wireshark in parallel I can always see the request/response packets on the wire, but sometimes my code 'gets' the response packet and sometimes it doesn't - it seems non-deterministic as to whether the receive is success or failure.
This is the relevant code snippet outlining what I am doing:
/* send packet */
if (pcap_sendpacket(pdw_io->pcap, buf, LEN_ETH_REQ_PKT)==-1) {
pcap_perror(pdw_io->pcap, 0);
print_err_log(ERR_LOG, "Error: pcap_sendpacket failed", __FILE__, __LINE__);
ret = 0;
}
free(buf);
/* logic here is that the next pkt after a request pkt is sent is *always*
* the corresponding response pkt */
ret = pcap_next_ex(pdw_io->pcap, &hdr, &response_buf);
The send always works, i.e. I always see the packet in wireshark. I always see the response packet generated by the external hardware, its timestamp is approx 10us after the request. But pcap_next_ex() only return success (and fills response_buf with bytes) about half the time.
I am totally perplexed as to why this is. Note that there are no other LLC packets on the wire during this test, only the request response pair (as observed via wireshark)

RTP packet drop issue(?)

I have a client and a server, where server sends the audio data by RTP packets encapsulated inside UDP. Client receives the packets. As UDP has no flow control, client checks for the sequence number of the packet and rearranges them if they come out of order.
My question here is, I see client never receives packet with some sequence number, as show below in the wireshark -
If this is the case, when i play the audio at client side, it is distorted(obvious). How do i avoid it? What factors effect these? Should i set the socket buffer size to a large value?
Appreciate reply in advance.
EDIT 1: This issue is on QNX platform and not on Linux.
I observed the output of "netstat -p udp" to see if that gives any hint about why packets are getting dropped on QNX and not on Linux.
QNX:
SOCK=/dev/d_usb3/ netstat -p udp
udp:
8673 datagrams received
0 with incomplete header
 60 with bad data length field
0 with bad checksum
0 dropped due to no socket
2 broadcast/multicast datagrams dropped due to no socket
0 dropped due to full socket buffers
8611 delivered
8592 PCB hash misses
On Linux I see netstat shows no packet drops with the same server and same audio!
Any leads? Why this might be? Driver issue? Networking stack?
You need to specify how you are handling lost packets in your client.
If you lose packets, that means you have missing data in your audio stream. So your client has to "do something" where it is missing data. Some options are
- play silence (makes a cracking noise due to sharp envelop to 0)
- fade to silence
- estimate waveform by examining adjacent data
- play noise
You play cannot misalign packets or play them with missing packets. For example, suppose you you get packet 1,2,3,4 and 6. You are missing packet 5. You cannot play packet 4 then play packet 6. Something has to happen to fill the space of packet 5.
See this post for more info.

how to capture packets in pcap, and skip ethernet header

I am using
fp = pcap_open_dead(DLT_EN10MB,65535);
to capture frames in pcap format. But what fp = pcap_open_dead(**DLT_XXX** )
should I use if I want to skip the ethernet header. My module is working on layer 3 , so I want to capture packets starting from layer 3.
fp = pcap_open_dead(DLT_EN10MB,65535);
if (NULL == fp)
{
FPA_ERROR_PRINT("unable to open the dead interface \n");
return 1;
Any help will on this will be highly appreciated.
Thanks in advance.
I don't think you can. You need to manually skip the Ethernet header part when parsing the packet buffer.
I am using fp = pcap_open_dead(DLT_EN10MB,65535); to capture frames in pcap format.
Presumably you mean "to write frames to a file in pcap format"; the "dead" in "pcap_open_dead" means "not live", as in "you can't capture packets from this".
(It's necessary because the pcap_dump_open() call doesn't take a DLT_ value and a snapshot length as a type, it takes a pcap_t * and gets the DLT_ value and snapshot length from there. That's convenient if you're saving packets from a live capture you opened with pcap_open_live() or pcap_create()/pcap_activate(), or another capture file you opened with pcap_open_offline(), but it's not very convenient if the packets aren't coming from libpcap/WinPcap.)
But what fp = pcap_open_dead(DLT_XXX ) should I use if I want to skip the ethernet header. My module is working on layer 3 , so I want to capture packets starting from layer 3.
If "layer 3" means "IP", so that all your packets are IPv4 or IPv6 packets, you want DLT_RAW.
Skipping the Ethernet header, however, is your job. If whatever mechanism is supplying the captured frames is supplying frames with Ethernet headers, then you have to skip the Ethernet header - and discard frames where the type/length field in the Ethernet header is anything other than 0x0800 for IPv4 or 0x86dd for IPv6 - and calculate the appropriate captured length and on-the-wire length (14 bytes fewer than the captured and on-the-wire lengths of the frames with Ethernet headers; if either of those are less than or equal to 14, discard the frame), and hand those, along with a pointer to the data after the Ethernet header to pcap_dump().

Resources