Module Router.Nat

module Nat: sig .. end
Network Address Translation (N.A.T.) is the process of replacing on the fly non routable addresses used within a LAN by a unique routable address, so that hosts from the LAN can communicate with the outside world by sharing the only routable IP address. A Nat.t is a two sided device, with an inside and an outside, and an affected Ip address, that will translate outgoing source addresses with it's own and restore it in incoming packets. To match these incoming packets with the outgoing one it must use the UDP or TCP client port and an internal memory of currently forwarded connections. This memory is of bounded size. Note that any packet that reach it will be forwarded. A Nat.t is a TRX at IP level (it expects Ip packets).


Behavior on incomming packets:
    [Nat] <----------------------------- [Outside host]
              Src: outside_addr,
              Dst: nat_addr
            Ports: outside_port:nat_port
Lookup (outside_addr, outside_port, nat_port, proto) in in_cnxs_h. If the cnx is found then replace the nat_addr:nat_port by cnx.in_addr:cnx.in_port. If nothing is found, just ignore the packet (or forward it to the sink host without changing the dest port).

Behavior on outgoing packets:

    [Inside host] -----------------------------> [Nat]
                      Src: inside_addr,
                      Dst: outside_addr,
                    Ports: inside_port:outside_port
Lookup (inside_addr, inside_port, nat_port, proto) in out_cnxs_h. If the cnx is found then replace the inside_addr:inside_port by nat_addr:cnx.out_port. If nothing is found, create the cnx as:
 { out_port=random_port; in_addr=inside_addr; in_port=inside_port } 
and insert it with the above key in out_cnxs_h. Also, insert this cnx in in_cnxs_h with key (outside_addr, outside_port, random_port, proto).
type socket = {
   proto : Ip.Proto.t; (*
the IP protocol
*)
   nat_port : int; (*
the Nat ports
*)
   remote_addr : Ip.Addr.t; (*
the other peer's address
*)
   remote_port : int;
}
the port used by the other peer
type cnx = {
   in_addr : Ip.Addr.t; (*
the inside lan's host IP
*)
   in_port : int; (*
the origin port used by this host
*)
   out_port : int;
}
the random port used by NAS in the outside
type t = {
   addr : Ip.Addr.t; (*
our IP addr
*)
   cnxs : cnx Tools.OrdArray.t; (*
all the cnxs we remember
*)
   in_cnxs_h : (socket, int) Batteries.Hashtbl.t; (*
the hash to retrieve cnxs of packets coming from the outside
*)
   out_cnxs_h : (socket, int) Batteries.Hashtbl.t; (*
the hash to retrieve cnxs of packets coming from the inside
*)
   mutable emit : Bitstring.bitstring -> unit; (*
the emit function (ie. carry packets to the outside
*)
   mutable recv : Bitstring.bitstring -> unit;
}
the receive functon (ie. forward incoming packets from the outside
val patch_src_port : Ip.Proto.t -> string * int * int -> Tcp.Port.outer_t -> Bitstring.bitstring
val patch_dst_port : Ip.Proto.t -> string * int * int -> Tcp.Port.outer_t -> Bitstring.bitstring
val tx : t -> Bitstring.bitstring -> unit
bits are flowing from LAN to outside world
val rx : t -> Bitstring.bitstring -> unit
val make : Ip.Addr.t -> int -> Tools.trx
make ip n returns a Tools.trx corresponding to a NAT device (tx is for transmitting from the LAN to the outside) that can track n sockets.