Articles tagged #icmp
So. Serializing IPv4 packets. Easy? Well, not exactly.
IPv4 was annoying to parse, because we had 3-bit integers, and 13-bit integers, and who knows what else. Serializing it is going to be exactly the same.
Right now, we don't have a way to serialize that.
Let's take the version
and ihl
fields, both of which are supposed
to take 4 bits, together making a byte. We could serialize them like this:
In the last part, we've finally parsed some IPv4 packets. We even found a way to filter only IPv4 packets that contain ICMP packets.
There's one thing we haven't done though, and that's verify their checksum. Folks could be sending us invalid IPv4 packets and we'd be parsing them like a fool!
This series is getting quite long, so let's jump right into it.
Hello and welcome to Part 11 of this series, wherein we finally use some of the code I prototyped way back when I was planning this series.
Where are we standing?
Let's review the progress we've made in the first 10 parts: first, we've started thinking about what it takes for computers to communicate. Then, we've followed a rough outline of the various standards and protocols that have emerged since the 1970s.
Let's set aside our sup
project for a while.
Don't get me wrong - it's a perfectly fine project, and, were we simply rewriting "ping" for Windows in Rust, we could (almost) stop there.
We're currently using the operating system's facility to speak ICMP, which is great for a bunch of reasons: we can be sure that whatever flaws there are in the implementation, all "native" Windows programs suffer from it as well.
Our ping API is simple, but it's also very limited:
pub fn ping(dest: ipv4::Addr) -> Result<(), String> // called as: ping(ipv4::Addr([8, 8, 8, 8])).unwrap();
It doesn't allow specifying the TTL (time to live) of packets, it doesn't allow specifying the timeout, it doesn't let one specify the data to send along, and it doesn't give us any kind of information on the reply.
We've just spent a lot of time abstracting over LoadLibrary, but we still have all the gory details of the Win32 ICMP API straight in our main.rs file! That won't do.
This time will be much quicker, since we already learned about carefully designing an API, hiding the low-level bits and so on.
Let's add an icmp
module to our program. Actually, we've been dealing with
an all this time, it also sounds like it could use its own package:
It's time to make sup
, our own take on ping
, use the Win32 APIs to send
an ICMP echo. Earlier we discovered that Windows's ping.exe
used
IcmpSendEcho2Ex
. But for our purposes, the simpler IcmpSendEcho
will do
just fine.
As we mentioned earlier, it's provided by IPHLPAPI.dll
, and its C
declaration is:
IPHLPAPI_DLL_LINKAGE DWORD IcmpSendEcho( , , , , , , , );
So, how does ping.exe
actually send a ping? It seems unrealistic that
ping.exe
itself implements all the protocols involved in sending a ping.
So it must be calling some sort of library. Also, since it ends up
talking to the outside world via a NIC (network interface controller),
the kernel is probably involved at some point.
In reading files the hard way - part 2, we learned about dynamic libraries (like libc), and the Linux kernel, and how syscalls allowed us to ask the Linux kernel to do our bidding. For this series, we're going to have to look at the Windows equivalents.
Go back to the homepage.