Skip to content
Snippets Groups Projects
Commit 96911acb authored by Pierre Alain's avatar Pierre Alain
Browse files

functorise the write and listen callbacks

parent d7a788e0
No related branches found
No related tags found
1 merge request!1functorise the write and listen callbacks
This commit is part of merge request !1. Comments created here will be created in the context of that merge request.
(* mirage >= 4.7.0 & < 4.8.0 *)
(* mirage >= 4.8.1 & < 4.9.0 *)
open Mirage
(* we need two network interfaces: a public side and a private side *)
......@@ -19,7 +19,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public5" "public5")
(netif ~group:"public5" "0"))
let private_netif5 =
Key.(if_impl is_solo5
(netif ~group:"private5" "private5")
......@@ -29,17 +28,14 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public6" "public6")
(netif ~group:"public6" "0"))
let private_netif6 =
Key.(if_impl is_solo5
(netif ~group:"private6" "private6")
(netif ~group:"private6" "1"))
let public_netif7 =
Key.(if_impl is_solo5
(netif ~group:"public7" "public7")
(netif ~group:"public7" "0"))
let private_netif7 =
Key.(if_impl is_solo5
(netif ~group:"private7" "private7")
......@@ -49,7 +45,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public8" "public8")
(netif ~group:"public8" "0"))
let private_netif8 =
Key.(if_impl is_solo5
(netif ~group:"private8" "private8")
......@@ -59,7 +54,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public9" "public9")
(netif ~group:"public9" "0"))
let private_netif9 =
Key.(if_impl is_solo5
(netif ~group:"private9" "private9")
......@@ -69,7 +63,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public10" "public10")
(netif ~group:"public10" "0"))
let private_netif10 =
Key.(if_impl is_solo5
(netif ~group:"private10" "private10")
......@@ -79,7 +72,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public11" "public11")
(netif ~group:"public11" "0"))
let private_netif11 =
Key.(if_impl is_solo5
(netif ~group:"private11" "private11")
......@@ -89,7 +81,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public12" "public12")
(netif ~group:"public12" "0"))
let private_netif12 =
Key.(if_impl is_solo5
(netif ~group:"private12" "private12")
......@@ -99,7 +90,6 @@ let public_netif5 =
Key.(if_impl is_solo5
(netif ~group:"public13" "public13")
(netif ~group:"public13" "0"))
let private_netif13 =
Key.(if_impl is_solo5
(netif ~group:"private13" "private13")
......
let log = Logs.Src.create "ids" ~doc:"IDS rules"
module Log = (val Logs.src_log log : Logs.LOG)
(* Creates a set of rules (empty) and a default action (claim a packet is not an attack) *)
let ids_rules =
Rules.init false
let attacker_ip_lst = ref []
(* Takes an IPv4 [packet], unmarshal it, examine to detect attackers' IPs in TCP packets*)
let detect_and_output_private packet header frame output_cb output_ether_cb =
(* Handle IPv4 only... *)
match Ipv4_packet.Unmarshal.of_cstruct packet with
| Result.Error s ->
Logs.err (fun m -> m "Can't parse IPv4 packet: %s" s);
Lwt.return_unit
(* Otherwise unmarshal it, match rules with IPs, ports, proto *)
| Result.Ok (ipv4_hdr, payload) ->
(match Rules.is_match_rule ids_rules (ipv4_hdr, payload) with
| false ->
()
| true ->
attacker_ip_lst := ipv4_hdr.src :: !attacker_ip_lst;
());
let options = ipv4_hdr.options in
match List.exists (fun attacker_ip -> Ipaddr.V4.compare ipv4_hdr.dst attacker_ip = 0) !attacker_ip_lst with
| false ->
Custom_option.read_custom_opt ipv4_hdr.src options;
output_cb frame
| true ->
let new_options_cs = Custom_option.read_and_append_custom_opt ipv4_hdr.src ipv4_hdr.dst options in
let new_ipv4_hdr = {ipv4_hdr with options= new_options_cs} in
let len_payload = Cstruct.length payload in
let new_ipv4_hdr_cs = Ipv4_packet.Marshal.make_cstruct ~payload_len:len_payload new_ipv4_hdr in
let new_packet = Cstruct.append new_ipv4_hdr_cs payload in
output_ether_cb header.Ethernet.Packet.source header.Ethernet.Packet.destination new_packet
open Lwt.Infix
module Make
(Public_net: Mirage_net.S) (Private_net: Mirage_net.S)
(Public_ethernet : Ethernet.S) (Private_ethernet : Ethernet.S)
= struct
(* configure logs, so we can use them later *)
let log = Logs.Src.create "listener" ~doc:"Listener for public and private interfaces"
module Log = (val Logs.src_log log : Logs.LOG)
(* output callbacks we need *)
let output_public public_netif packet =
let len = Cstruct.length packet in
Public_net.write public_netif ~size:len (fun b -> Cstruct.blit packet 0 b 0 len ; len) >|= function
| Ok () -> ()
| Error e ->
Log.warn (fun f -> f "netif write errored %a" Public_net.pp_error e)
let output_private private_netif packet =
let len = Cstruct.length packet in
Private_net.write private_netif ~size:len (fun b -> Cstruct.blit packet 0 b 0 len ; len) >|= function
| Ok () -> ()
| Error e ->
Log.warn (fun f -> f "netif write errored %a" Private_net.pp_error e)
let output_ether_private private_ethernet mac_src mac_dst packet =
Private_ethernet.write private_ethernet ~src:mac_src mac_dst `IPv4 (fun b ->
let len = Cstruct.length packet in
Cstruct.blit packet 0 b 0 len ;len) >>= function
| Error e ->
Log.err (fun f -> f "Failed to send packet from private interface: %a" Private_ethernet.pp_error e);
Lwt.return_unit
| Ok () -> Lwt.return_unit
(* we need to establish listeners for the and public interfaces *)
(* we're interested in all traffic to the physical interface; we'd like to
send ARP traffic to the normal ARP listener and responder,
handle ipv4 traffic with the functions we've defined above for detection,
and ignore all ipv6 traffic. *)
let listen_public public_netif private_netif private_ethernet =
let header_size = Ethernet.Packet.sizeof_ethernet
and input frame = (* Takes an ethernet packet and send it to the relevant callback *)
match Ethernet.Packet.of_cstruct frame with
| Ok (header, payload) ->
begin
match header.Ethernet.Packet.ethertype with
| `ARP -> output_private private_netif frame
| `IPv4 -> Ids.detect_and_output_private payload header frame (output_private private_netif) (output_ether_private private_ethernet)
| _ -> Lwt.return_unit
end
| Error s ->
Log.debug (fun f -> f "Forward Ethernet frame if I cannot parse %s" s);
output_private private_netif frame;
in
Public_net.listen ~header_size public_netif input >>= function
| Error e -> Log.debug (fun f -> f "public4 interface stopped: %a" Public_net.pp_error e); Lwt.return_unit
| Ok () -> Log.debug (fun f -> f "public4 interface terminated normally");
Lwt.return_unit
let listen_private public_netif private_netif =
let header_size = Ethernet.Packet.sizeof_ethernet
and input frame =
output_public public_netif frame
in
Private_net.listen ~header_size private_netif input >>= function
| Error e -> Log.debug (fun f -> f "private10 interface stopped: %a" Private_net.pp_error e); Lwt.return_unit
| Ok () -> Log.debug (fun f -> f "private10 interface terminated normally"); Lwt.return_unit
end
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment