Can IP header be at different offset across different machines? - linux

I'm writing a tool with libpcap to analyze TCP traffic. The problem I'm facing is that inside a pcap file that was provided to me for testing, I see the IP header starts at offset 0x10 (hence after 16 bytes), while all the documentation + live capture show me that it's always at 0xE (like the documentation claims).
How I try to get a hold of the ip and tcp header:
struct iphdr *ip;
struct tcphdr *tcp;
ip = (struct iphdr *)(packet + sizeof(struct ethhdr));
tcp = (struct tcphdr *)(packet + sizeof(struct ethhdr) + sizeof(struct iphdr)
Some wireshark images:
Live capture -
As you can see it starts after 14 bytes, like it should
offline dump file -
Dump file ip header starts after 16 bytes
What is the correct way to parse the IP and TCP header?
Thanks

Ron Maupin is 100% correct. To give some more details:
The problem I'm facing is that inside a pcap file that was provided to me for testing
The pcap-savefile(5) man page indicates that one of the fields in the pcap file header is the "Link-layer header type" field; as the man page says:
a 4-byte number giving the link-layer header type for packets in the capture; see pcap-linktype(7) for the LINKTYPE_ values that can appear in this field.
If you have opened a capture file with pcap_open_offline() or one of the variants thereof, the pcap_datalink() routine in libpcap will return the link-layer header type.
The link-layer header type is a requirement for interpreting the contents of a packet. For IP packets, for example, the IP header comes after any metadata headers and the link-layer header, and not all metadata headers (if present) and not all link-layer headers have the same length, so you must know what link-layer header is present in order to know where the IP header begins - or, in fact, to even determine whether the packet is an IP packet! For Ethernet packets, for example, you must look at the Ethernet type/length field to see whether it's 0x0800 (for IPv4) or 0x86dd (for IPv6).
The tcpdump.org list of link-layer header types indicates what link-layer types exist. The numerical values given are those that appear in the "Link-layer header type" field of the file (or in the LinkType field of an Interface Description Block in a pcapng file - libpcap can read some pcapng files, all of the Interface Description Blocks of which must have the same LinkType, and will return the link-layer type in a pcap_datalink() call).
The values returned by pcap_datalink() are the DLT_ values from the list of link-layer header types, so an Ethernet file (or Ethernet Interface Description Block) will have a value of 1, or LINKTYPE_ETHERNET, in the header, which will be mapped to DLT_EN10MB in the value returned by pcap_datalink(). (In most cases, the LINKTYPE_ values and the corresponding DLT_ values are numerically the same, but there are some exceptions in cases where different operating systems have different numerical values for the same DLT_ type.) The second capture has LINKTYPE_LINUX_SLL in the capture file, so pcap_datalink() would return DLT_LINUX_SLL.
The link-layer header type page's descriptions of link-layer header types should help you write code to interpret that link-layer header type's header data.
In addition, as Ron Maupin noted, there may also be VLAN headers after the Ethernet header but before the IP header.
(And, as this is a question by somebody writing a program to read capture files, rather than by somebody designing or maintaining a network, it seems more appropriate for Stack Overflow than Network Engineering.)

Related

Can I access the 4 addresses available in the mac header of the Wireless 802.11 packets?

I am writing a module that hooks a function on OUTPUT hook of the kernel netfilter. I want to access the complete information inside the mac header of the packet esp all the 4 addresses or in some cases 3 addresses of the mac header. I am using the struct sk_buff to get the packet's fields but it does not give any fields other than
ethhdr = (struct ethhdr *)skb_mac_header(skb);
eth_hdr(skb)->h_dest;
eth_hdr(skb)->h_source;
eth_hdr(skb)->h_proto;
these fields.
Can anyone give me some code that can extract them at the OUTPUT hook of the netfilter in Linux where this would be added as a hook function? Or if this is possible anyways?

File handling in tinyos or tossim

I need to read data from a text file in a tinyos file (nesc file). I searched lot on Internet but couldn't find a way.
Is there any way?
I don't know about TOSSIM, but using a real sensor board its possible to do so.
What you could do, is to write a program using Java, C#, etc that reads the file and passes the acquired data to the serial/usb port as a SERIAL PACKET. But you are limited to maximum of 255 byte for each packet.
So you should make a simple protocol that takes care of data chunks.
Of course you should know that how you can create a serial packet to be readable by sensor boards.
For that you need to read the TEP#113. But short story, a serial packet is consisted of:
HEADER + CONTENT + FOOTER
header contains protocol byte, destination and source address etc...
content is your message_t struct
footer has CRC and some other stuff
You have to take care of CRC calculation and also escaping start/end delimeters (I believe byte 126 or 127 is the delimiter, I mean indicator of starting and ending a packet).

Is ethernet checksum exposed via AF_PACKET?

As it is implied by this question, it seems that checksum is calculated and verified by ethernet hardware, so it seems highly unlikely that it must be generated by software when sending frames using an AF_PACKET socket, as seem here and here. Also, I don't think it can be received from the socket nor by any simple mean, since even Wireshark doesn't display it.
So, can anyone confirm this? Do I really need to send the checksum myself as shown in the last two links? Will checksum be created and checked automatically by the ethernet adaptor?
No, you do not need to include the CRC.
When using a packet socket in Linux using socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL) ), you must provide the layer 2 header when sending. This is defined by struct ether_header in netinet/if_ether.h and includes the destination host, source host, and type. The frame check sequence is not included, nor is the preamble, start of frame delimiter, or trailer. These are added by the hardware.
On Linux, if you mention socket(AF_PACKET, SOCK_RAW, htobe16(ETH_P_ALL)) similar case, you don't need to calculate ethernet checksum, NIC hardware/driver will do it for you. That means you need to offer whole data link layer frame except checksum before send it to raw socket.

tcpdump: capture outgoing packets on virtual interfaces that has an unknown link type to libpcap?

In the system I am testing right now, it has a couple of virtual L2 devices chained together to add our own L2.5 headers between Eth headers and IP headers. Now when I use
tcpdump -xx -i vir_device_1
, it actually shows the SLL header with IP header. How do I capture the full packet that is actually going out of the vir_device_1, i.e. after the ndo_start_xmit() device call?
How do I capture the full packet that is actually going out of the vir_device_1, i.e. after the ndo_start_xmit() device call?
Either by writing your own code to directly use a PF_PACKET/SOCK_RAW socket (you say "SLL header", so this is presumably Linux), or by:
making sure you've assigned a special ARPHRD_ value for your virtual interface;
using one of the DLT_USERn values for your special set of headers, or asking tcpdump-workers#lists.tcpdump.org for an official DLT_ value to be assigned for them;
modifying libpcap to map that ARPHRD_ value to the DLT_ value you're using;
modifying tcpdump to handle that DLT_ value;
if necessary, modifying other programs that would capture on that interface or read capture files as written by tcpdump on that interface to handle that value as well.
Note that the DLT_USERn values are specifically reserved for private use, and no official versions of libpcap, tcpdump, or Wireshark will ever assign them for their own use (i.e., if you use a DLT_USERn value, don't bother contributing patches to assign that value to your type of headers, as they won't be accepted; other people may already be using it for their own special headers, and that must continue to be supported), so you'll have to maintain the modified versions of libpcap, tcpdump, etc. yourself if you use one of those values rather than getting an official value assigned.
Thanks Guy Harris for providing very helpful answers to my original question!
I am adding this as an answer/note to a follow up question I asked in the comments.
Basically my question was what is the status of the packet received by PF_PACKET/SOCK_RAW.
For an software device(no queue), dev_queue_xmit() will call dev_hard_start_xmit(skb, dev) to start transmitting skb buffer. This function calls dev_queue_xmit_nit() before it calls dev->ops->ndo_start_xmit(skb,dev), which means the packet PF_PACKET sees is at the state before any changes made in ndo_start_xmit().

libpcap - capture packets from all interfaces

I need to capture packets from all network interfaces on Linux machine.
In order to do it I'm planning to use pcap_open_live() API and pass "any" as a device argument.
I have different types of ports: Ethernet ports (say eth0) and GRE tunnels (say tun0)
The packets that coming from different types of interfaces has different headers format:
Packets from Ethernet port has MAC header
Packets from tunnel coming with a Linux "cooked" capture encapsulation (16 bytes) header
How can I check into pcap_loop() callback handler what type of packet header I got?
All packets you receive get the same type of packet header; that's the type you get when you call pcap_datalink() on the pcap_t. The values that pcap_datalink() returns are the DLT_ values as shown in the Link-Layer Header Types page on the tcpdump.org site.
If you've opened the any device, pcap_datalink() will return DLT_LINUX_SLL, meaning that ALL packets you capture will have the "cooked" capture header - even the ones from eth0! You'd have to capture on eth0, rather than any, to get Ethernet headers for those packets.

Resources