module Hans.Layer.IP4.Routing (
Rule(..)
, Mtu
, RoutingTable
, emptyRoutingTable
, addRule
, route
, localAddrs
, sourceMask
) where
import Data.PrefixTree as PT
import Hans.Address.IP4
import Hans.Address
import Data.Maybe (mapMaybe)
type Mtu = Int
data Rule mask addr
= Direct mask addr Mtu
| Indirect mask addr
deriving Show
type RoutingTable addr = PrefixTree (Dest addr)
data Dest addr
= NextHop addr
| Via addr Mtu
deriving Show
emptyRoutingTable :: Address addr => RoutingTable addr
emptyRoutingTable = PT.empty
addRule :: Mask mask addr
=> Rule mask addr -> RoutingTable addr -> RoutingTable addr
addRule rule table = case rule of
Direct mask addr mtu -> k mask (Via addr mtu)
Indirect mask addr -> k mask (NextHop addr)
where
k m d = insert ks d table
where
(addr,bits) = getMaskComponents m
ks = take bits (toBits addr)
route :: Address addr => addr -> RoutingTable addr -> Maybe (addr,addr,Mtu)
route addr t = do
r <- match (toBits addr) t
case r of
Via s mtu -> return (s,addr,mtu)
NextHop hop -> do
Via s mtu <- match (toBits hop) t
return (s,hop,mtu)
sourceMask :: Mask mask addr => addr -> RoutingTable addr -> Maybe mask
sourceMask addr table = do
src <- key (toBits addr) table
let bits = fromIntegral (addrSize addr * 8) length src
return (addr `withMask` bits)
localAddrs :: Address addr => RoutingTable addr -> [addr]
localAddrs table = mapMaybe p (PT.elems table)
where
p (Via s _) = Just s
p _ = Nothing