{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE CPP #-} module Hans ( -- * Network Stack NetworkStack(), Config(..), defaultConfig, newNetworkStack, processPackets, -- * Devices DeviceName, Device(), DeviceConfig(..), defaultDeviceConfig, addDevice, listDevices, closeDevice, startDevice, -- * Network Layer Addr(), sameFamily, NetworkAddr(..), Network(..), RouteInfo(..), -- ** IP4 IP4.IP4(), IP4.packIP4, IP4.unpackIP4, IP4.IP4Mask(..), IP4.Route(..), IP4.RouteType(Direct,Indirect), addIP4Route, ) where import Hans.Addr (NetworkAddr(..),Addr(),sameFamily) import Hans.Config import Hans.Device import Hans.Device.Loopback import qualified Hans.IP4.State as IP4 import qualified Hans.IP4.Packet as IP4 import qualified Hans.IP4.RoutingTable as IP4 (Route(..),RouteType(..)) import qualified Hans.IP4.Output as IP4 (responder) import Hans.Input import Hans.Network import Hans.Threads (forkNamed) import Hans.Types import qualified Hans.Tcp.Output as Tcp (responder) import qualified Hans.Tcp.Timers as Tcp import qualified Hans.Udp.Output as Udp (responder) import Control.Concurrent.BoundedChan (newBoundedChan) import Data.IORef (newIORef,atomicModifyIORef') #ifdef HANS_TARGET_XEN import Hypervisor.XenStore (XenStore) #endif -- | Create a network stack with no devices registered. newNetworkStack :: Config -> IO NetworkStack newNetworkStack nsConfig = do nsInput <- newBoundedChan (cfgInputQueueSize nsConfig) nsNat <- newNatState nsConfig nsDevices <- newIORef [] nsIP4State <- newIP4State nsConfig nsUdpState <- newUdpState nsConfig nsTcpState <- newTcpState nsConfig nsNameServers4 <- newIORef [] rec nsIP4Responder <- forkNamed "IP4.responder" (IP4.responder ns) nsTcpTimers <- forkNamed "Tcp.tcpTimers" (Tcp.tcpTimers ns) nsTcpResponder <- forkNamed "Tcp.responder" (Tcp.responder ns) nsUdpResponder <- forkNamed "Udp.responder" (Udp.responder ns) let ns = NetworkStack { .. } registerLoopback ns return ns -- | Create and register the loopback device. Additionally, add its routing -- information. registerLoopback :: NetworkStack -> IO () registerLoopback ns = do lo <- newLoopbackDevice ns atomicModifyIORef' (nsDevices ns) (\devs -> (lo : devs, ())) -- add the route for 127.0.0.0/8 addIP4Route ns False IP4.Route { routeNetwork = IP4.IP4Mask (IP4.packIP4 127 0 0 1) 8 , routeType = IP4.Direct , routeDevice = lo } -- | Initialize and register a device with the network stack. -- NOTE: this does not start the device. #ifdef HANS_TARGET_XEN addDevice :: XenStore -> NetworkStack -> DeviceName -> DeviceConfig -> IO Device addDevice xs ns devName devConfig = do dev <- openDevice xs ns devName devConfig atomicModifyIORef' (nsDevices ns) (\devs -> (dev : devs, ())) return dev #else addDevice :: NetworkStack -> DeviceName -> DeviceConfig -> IO Device addDevice ns devName devConfig = do dev <- openDevice ns devName devConfig atomicModifyIORef' (nsDevices ns) (\devs -> (dev : devs, ())) return dev #endif -- | Add a route to the IP4 layer. addIP4Route :: NetworkStack -> Bool -> IP4.Route -> IO () addIP4Route NetworkStack { .. } = IP4.addRoute nsIP4State {-# INLINE addIP4Route #-}