why does libpcap/tcpdump add/pad '0x00' bytes at the end of IP/TCP packets? - libpcap

I use both Tcpdump and libpcap(a program which uses libpcap) to capture TCP packets. And I notice there are some packets which are padded/added with additional 0x00 bytes at the end. For example, while the IP length indicated in the IP header says that the length is 40 bytes, tcpdump captures 46 bytes. and I notice there are 6 0x00 bytes at the end of the TCP packets.

They don't add those bytes.
The machine sending the packets does, because that's required on Ethernet.
A 40-byte IP packet, when sent on Ethernet, would be 54 bytes long, because there's a 14-byte Ethernet header before the IP header and payload.
However, the minimum packet length on Ethernet is 60 bytes (not including the 4-byte FCS at the end). That means that the packet has to be padded to 60 bytes, which means adding 6 bytes of padding at the end.
(That's one reason why the IP header has a length field - so that the receiver of the packet knows how much is IP and how much is padding.)

Related

Reverse engineer of APC UPS serial protocol

I have a APC SMC1000-2UC UPS device that has a serial port to connection. The serial port protocol seems that is based on microlink protocol which has not documented. I monitored the communication of the UPC and PC witch UPS deriver has been initialed. I want to detect command of UPS such as shutdown command by a microcontroller-based device. Some information of "https://sites.google.com/site/klaasdc/apc-smartups-decode" site is compatible with things I observed. but calculation of frame checksum and Challenge string calculation don't pass.
Data length of protocol has been set to 32 bytes, So each frame has 35 bytes.
[Msg ID | 32 byte data | 2 byte checksum]
Regarding calculation of challenge frame, the UPS send 0x65 frame ID then 0x68 frame ID, after that the PC response with 0x65 frame ID and UPS send confirmed frame by 0x65 frame ID. based on presented calculation, I think format or Position of Password_1, Header data and two bytes of that has been changed as the protocol has been configured to 32 bytes data. The following frame are a sample of this challenge:
Header frame: 0x00 0a206903fa27090001004000f802fe04fe0940fc1042fc1044fc20f80416fc10 32a6
UPS : 0x65 ffff00010000a0e80000 c0bbb4e1 000001040000001000000004000000000020 7350
UPS : 0x68 000000000000000000000008004c2943000000000966039a063b675601f30000 864f
PC : 0x65 0a 04 8afb65f1 bdf0
UPS : 0x65 ffff000100000eaf62d8 8afb65f1 000001040000001000000004000000000020 6227
How can I satisfy the challenge and checksum type? I try many type of checksum for that data but they not correct.
It may be a bit late, but have you looked at this:
https://github.com/klaasdc/apcups-serial-test
This looks like somebody got pretty far reverse engineering the MicroLink protocol, including the checksum part. The GitHub repo also contains a link to a web page with a protocol description.

Tcpdump dynamic filter based on length

I'm trying to capture all DHCP Discover packets that don't end with ff that should be the last byte of a correct BOOTP request.
I can filter all DHCP Discover by using the correct offset ether[284:1] because it is at the beginning of the packet but what changes is obviously the length of the entire request.
Is there a way to dynamically calculate the length of the packet and use it as a proper offset?
Thanks

In the MySQL client/server protocol, how are compressed packets split?

The MySQL client/server protocol docs say:
Note
sending a MySQL Packet of the size 224-5 to 224-1 via compression leads to at least one extra compressed packet. If the uncompressed MySQL Packet is like
fe ff ff 03 ... -- length = 2^24-2, sequence id = 3
compressing it would result in the length of payload before compression in the Compressed Packet Header being:
length of mysql packet payload: 2^24-2
length of mysql packet header: 4
length of payload before compression: 2^24+2
which can not be represented in one compressed packet. Instead two or more packets have to be sent.
What I don't understand is how the packet is split.
Is the entire MySQL compressed, and then separated? If so, how is it split, and what should the length of payload before compression field be set to?
Or is the MySQL packet split into chunks of max size 224-1, and then sent in individual compressed packets with length of payload before compression set to ff ff ff in all but the last? This seems to be the more likely of the two, but I can't find any documentation for this detail.
Finally, if it is the latter, should the max packet size pre-compression be set to 224-5, to prevent a scenario like the following:
Payload size: 0x100fffe (0xffffff + 0xffff)
MySQL Packets:
#1: length of payload = ff ff ff (size = 0x1000003)
#2: length of payload = ff ff 00 (size = 0x10003)
Compressed packets:
MySQL Packet #1:
#1: length of payload before compression = ff ff ff
#2: length of payload before compression = 04 00 00
MySQL Packet #2:
#1: length of payload before compression = ff ff 00
Here 3 packets are compressed and sent, instead of just 2 if packets were split with max size 224-5 at the MySQL Packet layer.

how to calculate number of bytes going through network with tcpdump?

I have tcpdump like this
sudo tcpdmp tcp -n -i eth0 -w test.dmp
I want to calculate the number of tcp bytes going through eth0. I capture all the package using tcpdump as above. Is the file size equal the number of bytes or tcpdump add additional information into the dump file?
Yes, tcpdump adds additional information to the file.
It (currently) writes only in pcap format, which means there's a 24-byte header at the beginning of the file, giving information such as the link-layer header type for packets in the file, so the first thing you'd need to do would be to subtract 24 from the size of the file.
In addition, each packet has a 16-byte header giving an arrival time stamp for the packet, the length of the packet, and the number of bytes of packet data that was captured. This means that you would need to subtract 16*{number of packets} from the length - but the only way to get the number of packets is to read the file, so you can't get the number of bytes just by looking at the file size!
Note also that some versions of tcpdump did not default to a "snapshot length" of 0, so the number of bytes of packet data that is captured may be less than the number of packet bytes on the network.
Therefore, what you should do is write a program (use libpcap, as it already knows pcap format and you don't have to write your own code to understand it) that reads all the packets and adds up the "length of the packet" field (it's the len field in the struct pcap_pkthdr structure; do not use caplen, as that's the number of bytes of packet data that was captured) values for all the packets.
You say eth0, so the link-layer header type is probably Ethernet, and there is, for example, no radio meta-data, as might be the case if you were capturing in monitor mode on a Wi-Fi adapter. In the cases where there's extra meta-data in the link-layer header, you'd need to subtract that.

Size for storing IPv4, IPv6 addresses as a string

what should be the ideal size for storing IPv4, IPv6 addresses as a string in the MySQL database. should varchar(32) be sufficient?
Assuming textual representation in a string :
15 characters for IPv4 (xxx.xxx.xxx.xxx format, 12+3
separators)
45 characters for IPv6
Those are the maximum length of the string.
Alternatives to storing as string:
IPv4 is 32-bits, so a MySQL data type that can hold 4 bytes will do, using INT UNSIGNED is common along with INET_ATON and INET_NTOA to handle the conversion from address to number, and from number to address
SELECT INET_ATON('209.207.224.40');
-> 3520061480
SELECT INET_NTOA(3520061480);
-> '209.207.224.40'
For IPv6, unfortunately MySQL does not have a data type that is 16 bytes, however one can put the IPv6 into a canonical form, then separate them into 2 BIGINT (8 bytes), this however will use two fields.
If you're storing them as strings rather than bit patterns:
IPv4 addresses consist of four 3-digit decimal characters with three . separators, so that only takes 15 characters such as 255.255.255.255.
IPv6 addresses consist of eight 4-digit hex characters with seven : separators, so that takes 39 characters such as 0123:4567:89ab:cdef:0123:4567:89ab:cdef.
Numerically, an IPv4 address is 32-bit long and IPv6 address is 128-bit long. So you need a storage of at least 16 bytes.
If the "string" you store is an encoding of the address in byte form, then 16 is enough.
You can use a VARBINARY(16) to store an IPv6 address in a binary format.
The applications that need to use this data can then use their inet_pton/ntop implementations to manipulate this data, or you can install a UDF like the one at http://labs.watchmouse.com/2009/10/extending-mysql-5-with-ipv6-functions/
the ipv6 address maybe 46 characters.
reference:
IPv4-mapped IPv6 addresses
Hybrid dual-stack IPv6/IPv4 implementations recognize a special class of addresses, the IPv4-mapped IPv6 addresses. In these addresses, the first 80 bits are zero, the next 16 bits are one, and the remaining 32 bits are the IPv4 address. One may see these addresses with the first 96 bits written in the standard IPv6 format, and the remaining 32 bits written in the customary dot-decimal notation of IPv4. For example, ::ffff:192.0.2.128 represents the IPv4 address 192.0.2.128. A deprecated format for IPv4-compatible IPv6 addresses was ::192.0.2.128.[61]
Assuming you don't have any network information (such as LL identifier, class, or CIDR mask) attached, an IPv4 address is up to fifteen characters (4x3 numbers+3 periods) and an IPv6 address may be up to 39 characters.
Besides what was already said there is Link-Local IPv6 address. If you want to keep the address so that you can use the string to create connections you will need also to keep scope id.
On Windows it is a 16-bits number, on Linux it can be a string - interface name, I did not find the maximum length of an interface name.