1(* This program monitors the traffic going through your loopback
2 interface, once this program is run, check your trace pipe with
3 `sudo cat /sys/kernel/debug/tracing/trace_pipe` and run `ping
4 127.0.0.1` to see the output *)
5open Ctypes
6open Libbpf
7
8let obj_path = "tc.bpf.o"
9let program_name = "tc_ingress"
10
11let () =
12 (* Set signal handlers *)
13 let exitting = ref true in
14 let sig_handler = Sys.Signal_handle (fun _ -> exitting := false) in
15 Sys.(set_signal sigint sig_handler);
16 Sys.(set_signal sigterm sig_handler);
17
18 let hook_created = ref false in
19
20 let tc_hook = make C.Types.Bpf_tc.hook in
21 setf tc_hook C.Types.Bpf_tc.ifindex 1;
22 setf tc_hook C.Types.Bpf_tc.attach_point `INGRESS;
23 let sz = Ctypes.sizeof C.Types.Bpf_tc.hook in
24 setf tc_hook C.Types.Bpf_tc.sz (Unsigned.Size_t.of_int sz);
25
26 let tc_opts = make C.Types.Bpf_tc.Opts.t in
27 setf tc_opts C.Types.Bpf_tc.Opts.handle (Unsigned.UInt32.of_int 1);
28 setf tc_opts C.Types.Bpf_tc.Opts.priority (Unsigned.UInt32.of_int 1);
29 let sz = Ctypes.sizeof C.Types.Bpf_tc.Opts.t in
30 setf tc_opts C.Types.Bpf_tc.Opts.sz (Unsigned.Size_t.of_int sz);
31
32 (* Open and load bpf object *)
33 let obj = bpf_object_open obj_path in
34 bpf_object_load obj;
35 let prog = bpf_object_find_program_by_name obj program_name in
36
37 (* Try to create hook *)
38 (* The hook (i.e. qdisc) may already exists because: *)
39 (* 1. it is created by other processes or users *)
40 (* 2. or since we are attaching to the TC ingress ONLY, *)
41 (* bpf_tc_hook_destroy does NOT really remove the qdisc, *)
42 (* there may be an egress filter on the qdisc *)
43 let err = C.Functions.bpf_tc_hook_create (addr tc_hook) in
44 if err = 0 then hook_created := true;
45
46 if err <> 0 && err <> -17 (*EEXIST*) then (
47 Printf.eprintf "Failed to create tc hook: %d\n" err;
48 exit 1);
49
50 setf tc_opts C.Types.Bpf_tc.Opts.prog_fd prog.fd;
51 let err = C.Functions.bpf_tc_attach (addr tc_hook) (addr tc_opts) in
52 if err = 1 then (
53 Printf.eprintf "Failed to attach TC: %d\n" err;
54 C.Functions.bpf_tc_hook_destroy (addr tc_hook) |> ignore;
55 exit 1);
56
57 Printf.printf
58 "Successfully started! Please run `sudo cat \
59 /sys/kernel/debug/tracing/trace_pipe` to see output of the BPF program.\n\
60 %!";
61
62 while !exitting do
63 Printf.eprintf ".%!";
64 Unix.sleepf 1.0
65 done;
66
67 let err = C.Functions.bpf_tc_detach (addr tc_hook) (addr tc_opts) in
68 if err = 1 then Printf.eprintf "Failed to detach TC: %d\n" err;
69 C.Functions.bpf_tc_hook_destroy (addr tc_hook) |> ignore;
70 bpf_object_close obj