I'm trying to verify the validity of a checksum value of a UDP packet by checking the packet with Wireshark.
In this specific packet I'm looking at, the values of the UDP headers are as follows:
Source port: 53 (0000 0000 0011 0101)
Destination port: 64992 (1111 1101 1110 0000)
Length: 64 (0000 0000 0100 0000)
Now if these values are added, the sum is 65109 (1111 1110 0101 0101)
So I expect the checksum value to be 426 (0001 1010 1010) which is 1's complement of the sum.
But in Wireshark, the checksum value is 0x63c7, and it says that this checksum is correct.
I'd like to know where I'm mistaken.
Any help or push in the right direction would be greatly appreciated.
Thanks in advance.
If you reference RFC 768, you will find the details you need to properly compute the checksum:
Checksum is the 16-bit one's complement of the one's complement sum of a
pseudo header of information from the IP header, the UDP header, and the
data, padded with zero octets at the end (if necessary) to make a
multiple of two octets.
The pseudo header conceptually prefixed to the UDP header contains the
source address, the destination address, the protocol, and the UDP
length. This information gives protection against misrouted datagrams.
This checksum procedure is the same as is used in TCP.
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| source address |
+--------+--------+--------+--------+
| destination address |
+--------+--------+--------+--------+
| zero |protocol| UDP length |
+--------+--------+--------+--------+
If the computed checksum is zero, it is transmitted as all ones (the
equivalent in one's complement arithmetic). An all zero transmitted
checksum value means that the transmitter generated no checksum (for
debugging or for higher level protocols that don't care).
If you want to see how Wireshark's UDP dissector handles it, you can look at the source code for packet-udp.c. Basically, after setting up the data inputs properly, it essentially just calls the in_cksum() function in the in_cksum.c file to compute it.
You might also want to take a look at RFC 1071, "Computing the Internet Checksum".
Related
I'm parsing a Wireshark PCAP file in C++, not using any external libraries.
The Wireshark app shows that most packets in that file are UDP but some are ARP, STP, or other.
I'm only interested in the UDP. Where in the packet (or packet header) does it denote the protocol?
When it is UDP, byte 23 in the packet is set to 17, however in non-UDP, byte 23 doesn't have the same meaning - thus one can't rely on that byte.
Didn't find any docs on that, including PCAP format docs.
When it is UDP, byte 23 in the packet is set to 17, however in non-UDP, byte 23 doesn't have the same meaning
It's more complicated than that.
A pcap file has, in the file header, a field that indicates the type of link-layer header that the packets in the file have. The list of link-layer header types shows what different values in that field mean.
If the field has the value 1, then the packet begins with an Ethernet header, which begins with a 6-byte Ethernet destination address, followed by a 6-byte Ethernet source address, followed by a 2-byte type/length field.
If the type/length field has the value 0x0800, then the packet is an IPv4 packet. IPv4 is described by RFC 791; the header of an IPv4 packet has a 1- byte protocol field, which contains an Internet Protocol Number value. A value of 6 means TCP; a value of 17 means UDP.
In a packet with an Ethernet header that has a type/length field value of 0x0800, the first 14 bytes are an Ethernet header, and the next 20 bytes are the fixed portion of an IPv4 header. The Protocol field in the IPv4 header is an an offset of 9 from the beginning of the IPv4 header, so, in an IPv4-over-Ethernet packet, the Protocol field is an an offset of 14+9 = 23 bytes from the beginning of the packet.
If the packet does not begin with an Ethernet header, then, unless the link-layer header is also 14 bytes long and is immediately followed by the payload, byte 23 is not the IPv4 Protocol field.
Furthermore, if the packet is not an IPv4 packet, even if the packet does begin with an Ethernet header, byte 23 is not the IPv4 Protocol field.
UDP - and TCP, and so on - can also run on top of IPv6. IPv6 is described by RFC 8200. The IPv6 header has a Next Header field, which contains an Internet Protocol Number field. However, there's no guarantee that this will be a value for a protocol such as TCP or UDP; it might be a value for an "extension header". The "extension header" will contain its own Next Header field, which could be for a protocol such as TCP or UDP or for another "extension header". Eventually, there will be a last "extension header", the Next Header field of which will contain a value specifying a protocol such as TCP or UDP.
If the packet has an Ethernet header, and the type/length field has the value 0x86dd, then an IPv6 header, not an IPv4 header, comes after the Ethernet header.
If your network is an Ethernet network with VLANs, then the type/length field may have the value 0x8100, in which case the Ethernet header will be followed by a 2-byte VLAN tag, which is followed by another 2-byte type/length field.
The tcpdump source file with the Ethernet dissector has ~600 lines of source code; the tcpdump source files with the IPv4 dissector and with the IPv6 dissector both have ~500 lines of source code. Wireshark's dissection is even more complicated than that. Writing code to properly analyze raw network packets from a capture file - whether pcap, pcapng, Sniffer, snoop, Microsoft Network Monitor, or another packet analyzer - isn't a simple process.
Didn't find any docs on that, including PCAP format docs.
The pcap format does not by itself include the information about the transport protocol (UDP, TCP, ...). This information is instead part of the packet data contained in the pcap, specifically in the IPv4/IPv6 header. With IPv4 the transport protocol is contained in the Protocol field of the IPv4 header. With IPv6 it is defined by the Next Header field of the IPv6 header.
I want to put filters on inner packets encapsulated by geneve.
If I put a filter like
tcpdump -vnn udp -i eth0
It filters all geneve packets as the header above geneve is udp.
How to filter the packets which are inside geneve which has proto field set to udp?
I managed to find a sample capture file online that contains Geneve traffic. It's the geneve.pcap file available at Cloudshark.
I download this file and modified one of the packets so the inner encapsulated protocol was UDP instead of ICMP. I was then able to come up with a capture filter to isolate that packet while testing with tcpdump. Here's the command with capture filter that I used to test this:
tcpdump -r geneve_udp.pcap "(udp port 6081) and (udp[10:2] = 0x6558) and (udp[(8 + (4 * (2 + (udp[8:1] & 0x3f))) + 12):2] = 0x0800) and (udp[8 + (4 * (2 + (udp[8:1] & 0x3f))) + 14 + 9:1] = 17)"
Explanation of the capture filter:
udp port 6081: This part just filters for Geneve packets, as identified by the UDP port number.
udp[10:2] = 0x6558: This part filters for Geneve packets with a Protocol Type of "Transparent Ethernet bridging".
udp[(8 + (4 * (2 + (udp[8:1] & 0x3f))) + 12):2] = 0x0800: This somewhat complicated part filters for encapsulated Ethernet frames having an Ethertype of 0x0800 (IPv4). It does this by:
Skipping the 8 bytes of the UDP header itself.
Skipping the Geneve Header, which is 8 bytes plus 4 times the Opt Len, which we must isolate from the byte because this field is only contained within the lower 6 bits.
Skipping to the Ethertype field of the encapsulated Ethernet header.
And finally comparing the 2-byte value found there to the IPv4-assigned Ethertype of 0x0800.
udp[8 + (4 * (2 + (udp[8:1] & 0x3f))) + 14 + 9:1] = 17: This somewhat complicated part filters for encapsulated IPv4 headers having a Protocol field as 17 (UDP). It does this by:
Skipping the 8 bytes of the UDP header itself.
Skipping the Geneve Header, which is 8 bytes plus 4 times the Opt Len, which we must isolate from the byte because this field is only contained within the lower 6 bits.
Skipping the 14 bytes of the encapsulated Ethernet header.
Skipping the 1st 9 bytes of the encapsulated IP header to get to the proper offset of the IPv4 Protocol field.
And finally comparing the value of that field with the UDP-assigned protocol value of 17.
If the Geneve protocol encapsulates UDP within IPv6 instead of IPv4, then you'll have to modify the capture filter accordingly.
NOTE: I'm not sure if I should just delete my original answer or not? For now, I'll just leave it below ...
I'm not familiar with this Geneve protocol, nor do I have any capture files to test with, but you should be able to use the slice operator (i.e., []) if you know the offset to the field containing the desired value indicating that the inner protocol is UDP.
For illustrative purposes, I'll assume that if the Protocol Type field of the Geneve Header contains the value 17, then this indicates an encapsulated UDP packet. Assuming this is correct, then a filters such as follows may help:
"udp[10:2] = 17"
This filter compares the 2 bytes at offset 10 of the UDP data to the value of 17, which as I understand it, is the location of the Protocol Type field of the Geneve Header. You'll obviously need to adjust the offset if this assumption or my understanding of the protocol isn't correct.
Refer to the pcap-filter man page for more help on the capture filter syntax.
I am trying to extract video file from h.265 encoded & unencrypted rtsp/rtp pcap capture. I tried extracting rtp stream raw data and tried play it using vlc but not working. Is there any way can i get h.265 video file from pcap capture.
Actually, it is a tricky thing. A similar concept was implemented by http://ucsniff.sourceforge.net/videosnarf.html for h264, but they don't support h265 so I adopted the method. The main idea is that you have to add some parts that are missing.
As it is mentioned in https://www.rfc-editor.org/rfc/rfc7798 the header is like this:
+---------------+---------------+
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F| Type | LayerId | TID |
+-------------+-----------------+
You have to add the removed header for every elementary stream packet, which is 4 Bytes (00 00 00 01).
But we all know the h265 packets are too long and most of them are fragmented, and as I understand the players like VLC don't support fragmentation. So you have to reassemble them.
This process is only for fragmented packets types (like 49). You have an additional header which is like this:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E| FuType |
+---------------+
the bits S and E tells you how to reassemble the packets. The first packet in the sequence has S,E = 1,0 and others continue with S,E = 0,0 (maybe multiple packets) and the final one has S,E = 0,1. All the payload bytes are concatenated then a new header is created by replacing the type in the main header with the FuType mentioned here like this (and don't forget the 4Byte header):
+---------------+---------------+--------------
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
|F| FuType | LayerId | TID | all the concatenated payloads
+-------------+-----------------+---------------
Just remember you have to keep both the fragmented and nonfragmented payload since most of the unfragmented packets have crucial information like picture size which cannot be omitted. The elementary stream can be played by SMplayer or you can use VLC.
For VLC you have to set the demuxer to h265.
With reference to this question and to ASIO libary, I would like to know what is the maximum size of ICMP v6 reply packet. I'm using ASIO library to listen for and receive ICMPv6 packets, but I don't know what size of buffer to use in order to prevent buffer over flow. I'm confused by IPv6 supporting extension headers.
Ex code:
asio::streambuf replyBuffer;
replyBuffer.consume(replyBuffer.size());
size_t length = icmpV6Socket->receive(replyBuffer.prepare(65536) );
One of the great features of Boost.Asio's buffers is that they provide protection against buffer overruns. Boost.Asio's buffers pair together a handle to the actual memory and the size. Thus, as long as the size is properly set or deduced, then Boost.Asio operations will not produce buffer overruns.
Nevertheless, the details for ICMPv6 sizes are as follows. IPv6 Header is 40 bytes, and reserves 2 bytes to represent the Payload Length. Thus, the max payload for IPv6, including extension headers, is 65,535. This differs from IPv4, where the Total Length included the header itself. The ICMPv6 Echo Reply header is 8 bytes.
Therefore:
The maximum IPv6 packet is 65,575 bytes (max payload of 65,535 + header of 40).
The maximum IPv6 payload is 65,535 bytes.
The maximum ICMPv6 Echo Reply body is 65,527 bytes. (max payload of 65,535 - ICMPv6 Echo Reply Header of 8).
I just learned about the udp checksum calculation.
But I am confused does the algorithm detect all errors.
Of course not. No checksum can detect all errors.
The UDP checksum cannot detect all errors, but it does detect many. It will detect any single bit flip, but if the packet is altered such that the sum of all the data as 16 bit values remains constant, the checksum will not detect the error.
Usually checksums can detect only the most common errors, but not all of them. Actually, the UDP checksum is optional in combination with IPv4 as UDP is designed as an unreliable service.
No, It can not detect all errors.
Suppose we have two 16-bit numbers
A = 0101 1001 1010 0010 and
B = 1010 0100 0110 0101 then Their sum is :
S = 1111 1110 0000 0111 and 1's(Ones) Complement of this checksum is
C = 0000 0001 1111 1000
and this checksum will be filled in the checksum field of UDP Segment.
So Sender will send these 3 16-bit numbers and at receiver sum of A and B will again be calculated at receiver and added to UDP Checksum received .
If we have Sum 1111 1111 1111 1111 then we will think there is no error in recieved segment.
But here is the catch that if
Last two bits in A i.e 10 Get flipped to 01 and similarly
Last two bits in B i.e 01 Get flipped to 10 . Then again S will remain same and S + C will be again 1111 1111 1111 1111. Which is definately a problem as this will not catch error if More than one bit gets flipped.
So, UDP Checksum cannot detect errors of all kinds.