Writing a router

A router is a very basic component for all networks. It reads frames from its network interfaces, looks up the destination in its routing table, and forwards the frame to the according interface. Let’s start to write a very simple router without a GUI. To do so, create a new command line application and add the eEx Network Library to the references. We will only work in the main-method for this basic example.
The first step for building a router is to query all interfaces from the local host. We will use EthernetInterfaces, so WinPcap or LibPcap must be installed on the computer to run the program. At first, we will get all available EthernetInterfaces and save them into an array:


WinPcapInterface[] arWpc = EthernetInterface.GetAllPcapInterfaces();
The next step is to instantiate some Traffic Handlers we well need: The router and a traffic splitter which can be used to add analyzers.


Router rRouter = new Router(); 
TrafficSplitter tsSplitter = new TrafficSplitter();
The next step is to start this classes so that their worker threads are running and they become ready for handling traffic. Also the handlers must be linked together.


//Start handlers
rRouter.Start();
tsSplitter.Start();

//Let the router forward traffic from the interfaces to the traffic splitter
rRouter.OutputHandler = tsSplitter;
//Let the traffic splitter forward received traffic back to the router
tsSplitter.OutputHandler = rRouter;

This code segment starts all handlers and them together in the right way. The linking of handlers does affect the whole behavior of this program. In this scenario, the graph which is created is not very complicated: The router sends all traffic from the interfaces to the traffic splitter, and the traffic splitter sends it back to the router which will forward it to the interfaces.

The next task we have to do is to add a default route, if we need one. To do so, let’s create a new routing entry and simply add it to the router.


//Create the properties of the routing entry
IPAddress ipaDestination = IPAddress.Parse("0.0.0.0");
IPAddress ipaGateway = IPAddress.Parse("192.168.1.1");
Subnetmask smMask = Subnetmask.Parse("0.0.0.0");
int iMetric = 10;

//Create the routing entry
RoutingEntry rEntry = new RoutingEntry(ipaDestination, ipaGateway, 
iMetric, smMask, RoutingEntryOwner.UserStatic);

This code segment creates the IP addresses and the subnet mask for the routing entry and then creates the routing entry with the given metric. Setting the owner of self added entries to UserStatic is important when working with routing protocols, since it tells the router that this route is a static route from the user and should not be overwritten by routes from routing protocols.

Before we add the network interfaces to the router, there is still one task to go: Let’s register some event handlers to see what the router is doing.

//Add some event handlers
rRouter.FrameDropped += new EventHandler(rRouter_FrameDropped);
rRouter.FrameForwarded += new EventHandler(rRouter_FrameForwarded);
rRouter.FrameReceived += new EventHandler(rRouter_FrameReceived);
rRouter.ExceptionThrown += new TrafficHandler.ExceptionEventHandler(rRouter_ExceptionThrown);


Here are some default event handlers you can paste below your main-method:
static void rRouter_FrameForwarded(object sender, EventArgs e)
{
    Console.WriteLine("Frame forwarded!");
}

static void rRouter_FrameDropped(object sender, EventArgs e)
{
    Console.WriteLine("Frame dropped!");
}

static void rRouter_ExceptionThrown(object sender, ExceptionEventArgs args)
{
    Console.WriteLine("Router error: " + args.Exception.Message);
} 

static void rRouter_FrameReceived(object sender, EventArgs e)
{
    Console.WriteLine("Frame received!");
}

Now we will receive a little bit output every time something happens. The next step is to add the interfaces. Here we have to create an EthernetInterface for each WinPcapInterface we queried in the beginning, start it, and add it to the router. We also have to save the interfaces in a list because we need to close them when we shut down the program.


//Create a list for the interfaces
List wpcInterfaces = new List();

//Foreach WinPcapInterface of this host
foreach (WinPcapInterface wpc in arWpc)
{
    //Create a new interface handler and start it
    EthernetInterface ipInterface = new EthernetInterface(wpc);
    ipInterface.Start();

    //Then add it to the router and to our list
    wpcInterfaces.Add(ipInterface);
    rRouter.AddInterface(ipInterface);
}
Here we create a new interface handler for each WinPcapInterface and add all known interfaces to the router. The router now inserts routes for the interfaces subnets automatically in its routing table.

If you would start this programm now, it would do routing and it would also generate some output. But if you would close it now, there could be errors because none of the interfaces would be closed and none of the threads would be stopped. Stopping graphs is sometimes complicated. You have to keep one rule in mind. Traffic handlers should be stopped in the same order as they were started and interfaces should be stopped last. Also you have to call the cleanup method in the same order as described above before initiating the shutdown process. A call to the cleanup method will stop, for example, the interfaces from receiving traffic or lets attacks restore conditions as they were before the attack happened. So let’s implement that our programm will shut down cleanly when we press the ‘x’ key.


//Run until 'x' is pressed
while (Console.ReadKey().Key != ConsoleKey.X) ;

//Start the cleanup process for all handlers
rRouter.Cleanup();
tsSplitter.Cleanup();

//Start the cleanup process for all interfaces
foreach (EthernetInterface ipInterface in wpcInterfaces)
{
    ipInterface.Cleanup();
}

//Stop all handlers
rRouter.Stop();
tsSplitter.Stop(); 

//Stop all interfaces
foreach (EthernetInterface ipInterface in wpcInterfaces)
{
    ipInterface.Stop();
}

Congratulations! Your router is now finished.

Summary

Writing a small program with the network library can be split up into the following steps:
  1. Create, link and configure all Traffic Handlers
  2. Create, link and configure all Interfaces
  3. Let the program run and handle events from event handlers
  4. Cleanup all Traffic Handlers
  5. Cleanup all Interfaces
  6. Stop all Traffic Handlers
  7. Stop all Interfaces

Continue with Extending the Router.

Last edited Apr 24, 2011 at 1:18 PM by emiswelt, version 4

Comments

No comments yet.