Writing

Software, technology, sysadmin war stories, and more. Feed
Friday, June 10, 2011

Learning IP by writing a sniffer in DOS

A friend of mine has been working on migrating his office's network from a relatively old and crufty firewall/NAT/router box to something newer and shinier. This involved a number of small changes to the overall design in order to make it behave sanely. We wound up talking about it at some length, and at some point, a question came up: how did I figure out all of this network and routing stuff? This question comes up enough in my life to where it's probably worth answering here, if only so that I can refer to it the next time someone asks.

This story starts back in the early 90s. Some friends and fellow bulletin board system operators were doing some early DOS-based peer to peer networking over Ethernet to expand their operations. One thing that you could do was read your mail over the network from another machine while a user was dialed in, since you just needed to access the mailbox files remotely.

I wound up following their example and set up a simple two-node Ethernet configuration using some thirdhand 3c501 cards, a bit of coaxial cable, two tee connectors and a pair of terminators. I picked up two copies of Netware Lite from the back of Computer Shopper and I was in business. That got things going and I was happy, but it set the stage for future experiments.

About a year later, I got an account on my school's Unix machine as part of an engineering class project, and started learning about the network. They had a bunch of low-end DOS machines running NCSA telnet scattered throughout campus, and we'd use them to get to the server. I became a TA for their main computer lab and started wondering how all of this stuff worked.

In parallel, I had started playing with IP connectivity on my local network at home. I had been playing with Linux from a boot floppy, since I didn't have anywhere to install it "for real". Most of the time I just experimented with things like NCSA telnet (from school) and another tool called ka9q. Both of these programs ran in DOS on top of these things called packet drivers. Those drivers provided a simple software interrupt API for sending and receiving frames on my Ethernet.

Due to some previous experimenting with background programming in DOS (yep, TSRs), I already owned a book called PC Interrupts. It was a huge listing of all sorts of ways to talk to DOS and Netware and everything else you can imagine. Having that around was fortunate, since it had a section on packet drivers. Using that, I was able to put together something simple which would just put my NIC in promiscuous mode and dump bytes to the screen. Then I could jump into ka9q on my other machine and run ping and ... stuff would scroll by. It was just a bunch of garbage, but it was clearly linked to my pings. I wanted to know more.

Around this time, Boardwatch magazine was getting more and more into Internet stuff, and some BBSes were slowly turning into ISPs. I wanted to learn more about this and paid more attention to this. One month, Boardwatch reviewed a new book: TCP/IP Illustrated, Volume 1: The Protocols. It was said to be a bit expensive but worth every penny for the explanations and diagrams contained within. I found the money and bought a copy.

This new book started explaining the junk I had been seeing with my dumb little sniffer program. All of those bytes flying by had a purpose. I learned about what Ethernet addresses really look like in a frame, and the whole type/len thing, and different protocol numbers, and then noticed that the "08 06" I kept seeing when starting up a ping meant something. It was the other box desperately trying to find the Ethernet address of the host I was trying to ping with ARP!

At this point I was hooked. I wanted to reply to that request and see what would happen next. Turning again to the PC Interrupts book, I figured out how to write a packet and set to actually crafting one, hard-coding everything at first. I started ping, then ran my evil ARP replier, and ... the packets changed! Now I was getting "08 00" stuff I had never seen before, and had to decode that.

The story just goes on like this from here: I had to figure out enough of IP and then ICMP to understand what was being requested, and then turned around and wrote something to emit a halfway plausible reply. After a long time, I got results on the ka9q console, and I was actually starting to understand this stuff.

Some might think that I took this base and went and wrote my own IP stack or something like that. They'd be wrong. I realized what a horrible hack I was making and decided to stop before it got too complicated. By then I had managed to get another drive and had installed Linux, so I started writing network stuff in userspace instead. That let me move on to useful things instead.

While I never wrote an IP stack, I did make a really scary little multitasking print server and client which ran right on top of those packet drivers in DOS for my school. That, however, is a subject for another post at another time.