bos / pcap

Haskell bindings for the pcap library, which provides a low level interface to packet capture systems.
http://bitbucket.org/bos/pcap
Other
26 stars 11 forks source link

Addresses shifted/truncated #1

Open eamsden opened 11 years ago

eamsden commented 11 years ago

I make use of the following incantation to get the bytestring addresses nicely formatted as octets (my eth0 interface is the first one in the list returned from findAllDevs).

ghci> import Network.Pcap ghci> import qualified Data.ByteString as B ghci> import Data.List ghci> import Numeric ghci> fmap (ifAddresses . head) findAllDevs >>= mapM_ putStrLn . map (concat . intersperse "::" . map (flip showHex "") . B.unpack . saAddr . addrSA)

I receive the following output: 0::0::2::0::0::0::1::0::0::6::6c::62::6d::3c 0::0::81::4f::f6::4::0::0::0::0::0::0::0::0 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::20::1::18::e8::0::2::10::f4 0::0::0::0::0::0::fe::80::0::0::0::0::0::0

ifconfig eth0 provides: eth0 Link encap:Ethernet HWaddr 6c:62:6d:3c:a2:28 inet addr:129.79.246.4 Bcast:129.79.247.255 Mask:255.255.252.0 inet6 addr: 2001:18e8:2:10f4:e13e:8551:affc:f40c/64 Scope:Global inet6 addr: 2001:18e8:2:10f4:1527:979f:af7a:1be/64 Scope:Global inet6 addr: 2001:18e8:2:10f4:f46a:95dc:8675:b949/64 Scope:Global inet6 addr: 2001:18e8:2:10f4:d447:8f20:cd1:f766/64 Scope:Global inet6 addr: 2001:18e8:2:10f4:cca:e165:5ba5:e357/64 Scope:Global inet6 addr: 2001:18e8:2:10f4:6e62:6dff:fe3c:a228/64 Scope:Global inet6 addr: fe80::6e62:6dff:fe3c:a228/64 Scope:Link inet6 addr: 2001:18e8:2:10f4:2829:ca11:aa53:3e87/64 Scope:Global inet6 addr: 2001:18e8:2:10f4:945e:90f3:204f:2b3c/64 Scope:Global etc. etc.

I am wondering in particular where the last two octets of my hardware address have gotten to in the pcap output, as well as the last several octets of each of my various autoconfigured IPv6 addresses. Is there some sort of memory offset error in the code reading these addresses from the pcap structs (which I've only looked at briefly)? Am I doing something wrong?

System information: Ubuntu Linux 12.04 x86_64, Haskell Platform 2012.1

eamsden commented 11 years ago

After further investigation, this appears to be a bug in the wrapped pcap library.

eamsden commented 11 years ago

It turns out that the issue is in treating the definition of struct sockaddr literally. struct sockaddr is just something to cast individual types of addresses, such as struct sockaddr_in for IPv4, struct sockaddr_in6 for IPv6, and struct sockaddr_ll for AF_PACKET ethernet addresses.

bos commented 11 years ago

Thanks for digging into this. When you say "the issue is in treating the definition of struct sockaddr literally", what do you mean? Is that happening in the native pcap library, the bindings, or your code?

eamsden commented 11 years ago

The structure that the pcap library presents as a sockaddr structure isn't really a sockaddr structure, but a sockaddr_in structure, or a sockaddr_in6 structure, or a sockaddrll structure. So its a sort of extensible union implemented by casting. All sockaddr* structures have the short for the family identifier at the beginning, but then differing fields after that. For instance, 14 bytes of data can't hold a 16-octet IPv6 address. They could hold an 6-octet MAC address, but there are lots of other fields before those in struct sockaddr_ll. This is the struct that's actually returned as the first address in a pcap interface's list of addresses, and it contains the hardware address of the interface. Just loading the 14-byte data field picks up those extra fields and then part of the hardware address or ipv6 address, but not all of it.