Skip to content

Commit 4f14aef

Browse files
committed
debug: add a vpnkit.exe curl <url> command
This will allow testing of the I/O system. Signed-off-by: David Scott <dave@recoil.org>
1 parent 6039eac commit 4f14aef

File tree

3 files changed

+101
-3
lines changed

3 files changed

+101
-3
lines changed

src/bin/curl.ml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
(* A debug tool, intended to check the I/O subsystem is working correctly. *)
2+
3+
open Lwt.Infix
4+
5+
let lookup host =
6+
Host.Dns.getaddrinfo host `INET
7+
>>= function
8+
| [] ->
9+
Lwt.fail_with (Printf.sprintf "unable to lookup %s" host)
10+
| Ipaddr.V6 _ :: _ ->
11+
Lwt.fail_with "IPv6 not currently supported."
12+
| Ipaddr.V4 ipv4 :: _ ->
13+
Lwt.return (Ipaddr.V4 ipv4)
14+
15+
module Client(FLOW: Mirage_flow.S) = struct
16+
module C = Mirage_channel.Make(FLOW)
17+
let get flow host path =
18+
let request = "GET " ^ path ^ " HTTP/1.0\r\nHost: " ^ host ^ "\r\nConnection: close\r\n\r\n" in
19+
let c = C.create flow in
20+
Printf.printf "writing\n%s\n" request;
21+
C.write_string c request 0 (String.length request);
22+
C.flush c
23+
>>= function
24+
| Error e ->
25+
Printf.printf "error sending request: %s\n" (Fmt.str "%a" C.pp_write_error e);
26+
Lwt.return_unit
27+
| Ok () ->
28+
let rec loop () =
29+
C.read_some c >>= function
30+
| Ok `Eof -> Lwt.return_unit
31+
| Error e ->
32+
Printf.printf "error reading response: %s\n" (Fmt.str "%a" C.pp_error e);
33+
Lwt.return_unit
34+
| Ok (`Data buf) ->
35+
print_string (Cstruct.to_string buf);
36+
loop () in
37+
loop ()
38+
end
39+
40+
let curl _verbose urls =
41+
let module HTTP = Client(Host.Sockets.Stream.Tcp) in
42+
let fetch host port path =
43+
let path = if path = "" then "/" else path in
44+
lookup host
45+
>>= fun ipv4 ->
46+
Printf.printf "connecting to %s:%d\n" (Ipaddr.to_string ipv4) port;
47+
Host.Sockets.Stream.Tcp.connect (ipv4, port)
48+
>>= function
49+
| Error (`Msg m) ->
50+
Printf.printf "unable to connect: %s\n" m;
51+
Lwt.return_unit
52+
| Ok socket ->
53+
Printf.printf "connected\n";
54+
Lwt.finalize
55+
(fun () ->
56+
HTTP.get socket host path
57+
) (fun () -> Host.Sockets.Stream.Tcp.close socket) in
58+
try
59+
Host.Main.run begin
60+
Lwt_list.iter_s (fun url ->
61+
let uri = Uri.of_string url in
62+
if Uri.scheme uri <> Some "http" then begin
63+
Printf.printf "only http:// URLs are currently supported by this debug tool\n";
64+
Lwt.return_unit
65+
end else begin
66+
Printf.printf "trying URL %s\n" url;
67+
let path = Uri.path uri in
68+
match Uri.host uri, Uri.port uri with
69+
| Some host, Some port ->
70+
fetch host port path
71+
| Some host, None ->
72+
fetch host 80 path
73+
| _, _ ->
74+
Printf.printf "unable to parse host and port from URL\n";
75+
Lwt.return_unit
76+
end
77+
) urls
78+
end
79+
with e ->
80+
Printf.printf "Host.Main.run caught exception %s: %s\n" (Printexc.to_string e) (Printexc.get_backtrace ())

src/bin/main.ml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ let gc_compact =
824824
in
825825
Arg.(value & opt (some int) None doc)
826826

827-
let command =
827+
let ethernet_cmd =
828828
let doc = "proxy TCP/IP connections from an ethernet link via sockets" in
829829
let man =
830830
[`S "DESCRIPTION";
@@ -838,7 +838,23 @@ let command =
838838
$ server_macaddr $ domain $ allowed_bind_addresses $ gateway_ip $ host_ip
839839
$ lowest_ip $ highest_ip $ dhcp_json_path $ mtu $ udpv4_forwards $ tcpv4_forwards
840840
$ gateway_forwards_path $ gc_compact),
841-
Term.info (Filename.basename Sys.argv.(0)) ~version:Version.git ~doc ~man
841+
Term.info "ethernet" ~version:Version.git ~doc ~man
842+
843+
844+
let verbose =
845+
let doc = "Extra verbose logging"in
846+
Arg.(value & flag & info ["v"; "verbose"] ~doc)
847+
848+
let urls = Arg.(value & pos_all string [] & info [] ~docv:"URL")
849+
850+
let curl_cmd =
851+
let doc = "A debug command which fetches a resource over HTTP" in
852+
let man =
853+
[`S "DESCRIPTION";
854+
`P "Fetch a resource over HTTP to help diagnose local firewall or anti-virus problems."]
855+
in
856+
Term.(const Curl.curl $ verbose $ urls),
857+
Term.info "curl" ~version:Version.git ~doc ~man
842858

843859
let () =
844860
Printexc.record_backtrace true;
@@ -847,4 +863,4 @@ let () =
847863
Log.err (fun f ->
848864
f "Lwt.async failure %a: %s" Fmt.exn exn (Printexc.get_backtrace ()))
849865
);
850-
Term.exit @@ Term.eval command
866+
Term.exit @@ Term.eval_choice ethernet_cmd [ethernet_cmd; curl_cmd]

src/hostnet/sig.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ module type FILES = sig
130130
end
131131

132132
module type DNS = sig
133+
val getaddrinfo: string -> Luv.Sockaddr.Address_family.t -> Ipaddr.t list Lwt.t
134+
133135
val resolve: Dns.Packet.question -> Dns.Packet.rr list Lwt.t
134136
(** Given a question, find associated resource records *)
135137
end

0 commit comments

Comments
 (0)