sks-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Sks-devel] Patch (partial): IPv6 support (in progress)


From: Kim Minh Kaplan
Subject: Re: [Sks-devel] Patch (partial): IPv6 support (in progress)
Date: Mon, 02 Mar 2009 12:55:21 +0000
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)

Phil Pennock:

> Can those with more experience in OCaml please take a look over this and
> tell me if I'm heading down the right path?
>
> This patch theoretically adds support for IPv6 in recon; it adds the
> settings hooks for hkp too, but doesn't add anything that uses that yet.
> It should both listen on IPv6 and connect outbound too.
>
> It compiles.  It runs.  I see both listening sockets with lsof.  It
> doesn't do anything soon enough for me to see tonight how well I've
> done, as I need to go get some sleep.  I'm not sufficiently comfortable
> to leave sks-peer.spodhuis.org running this code overnight, so I've
> reverted to 1.1.0.
>
> It's my first OCaml hacking and my style sucks and I spend more time
> debugging to get it to compile than I care to think about.
>
> A critical eye and constructive comments appreciated.
>
> Oh, and I've no idea how recent support for IPv6 in OCaml is and have
> made no effort to gracefully degrade to either old OCaml environments or
> systems without IPv6 support.  First, I want to get it working for
> anyone, *then* I can worry about making it conditional.

Hello,

it is funny that you send this as I was just doing something very
similar this weekend.  Here is what I did.  I am still experimenting
with what actually works, what does not and trying to find what I broke.
I'll have a look at the way you did it when I have some time, probably
wednesday.

Kim Minh.

--- a/eventloop.ml      Fri May 23 21:16:40 2008 -0400
+++ b/eventloop.ml      Mon Mar 02 12:48:35 2009 +0000
@@ -121,10 +121,7 @@
 
 let create_sock addr = 
   try
-    let domain = 
-      match addr with 
-         ADDR_UNIX _ -> PF_UNIX 
-       | ADDR_INET (_,_) -> PF_INET in
+    let domain = domain_of_sockaddr addr in
     let sock =
       socket ~domain ~kind:SOCK_STREAM ~protocol:0 in
     setsockopt sock SO_REUSEADDR true;
diff -r e30dc5376cbb membership.ml
--- a/membership.ml     Fri May 23 21:16:40 2008 -0400
+++ b/membership.ml     Mon Mar 02 12:48:35 2009 +0000
@@ -34,32 +34,34 @@
 
 let whitespace = Str.regexp "[ \t]+"
 
-let lookup_hostname string = 
-  try (Unix.gethostbyname string).Unix.h_addr_list.(0)
-  with 
-    | Invalid_argument _ | Not_found -> raise (Lookup_failure string)
+let lookup_hostname string port =
+  let addrs = Unix.getaddrinfo string port [Unix.AI_SOCKTYPE(Unix.SOCK_STREAM)]
+  in
+  if List.length addrs = 0 then raise (Lookup_failure string);
+  addrs
 
 let local_recon_addr () = 
-  Unix.ADDR_INET (lookup_hostname !Settings.hostname, recon_port)
+  lookup_hostname !Settings.hostname (string_of_int recon_port)
 
 let local_recon_addr = Utils.unit_memoize local_recon_addr
 
 let remove_self addresses = 
-  List.filter ~f:(fun (addr,str) -> addr <> local_recon_addr ()) addresses
+  List.filter ~f:(fun (addr, str) -> List.mem addr (local_recon_addr()))
+    addresses
 
 let convert_address l =
-  try 
-    sscanf l "%s %d" 
-    (fun addr port -> Unix.ADDR_INET (lookup_hostname addr,port))
-  with 
+  try
+    sscanf l "%s %s" lookup_hostname
+  with
     Scanf.Scan_failure _ | End_of_file | Failure _ -> raise (Malformed_entry l)
 
 let load_membership_file file =
   let rec loop list =
     try
       let line = decomment (input_line file) in
-      let addr = convert_address line in
-      (addr,line) :: loop list
+      let addrs = convert_address line in
+      let pairs = List.map (fun addr -> (addr,line)) addrs in
+      pairs @ loop list
     with
       | End_of_file -> list
       | Lookup_failure addr -> 
@@ -101,7 +103,7 @@
 let membership_string () = 
   let (mshp,_) = !membership in
   let to_string (addr,str) =
-    sprintf "%s(%s)" (sockaddr_to_string addr) str
+    sprintf "%s(%s)" (sockaddr_to_string addr.Unix.ai_addr) str
   in
   let strings = List.map ~f:to_string (Array.to_list mshp) in
   "Membership: " ^ String.concat ~sep:", " strings
@@ -149,7 +151,14 @@
 
 let same_inet_addr addr1 addr2 = 
   match (addr1,addr2) with
-      (Unix.ADDR_INET (ip1,_), Unix.ADDR_INET (ip2,_)) -> ip1 = ip2
+      (Unix.ADDR_INET (ip1,_), Unix.ADDR_INET (ip2,_)) ->
+       let ipv6_addr addr =
+         let addr_str = Unix.string_of_inet_addr addr in
+         if String.contains addr_str ':'
+         then addr_str
+         else "::ffff:" ^ addr_str
+       in
+       ipv6_addr(ip1) = ipv6_addr(ip2)
     | _ -> false
 
 let test addr = 
@@ -159,7 +168,7 @@
   let found = ref false in
   let i = ref 0 in
   while !i < Array.length m && not !found do 
-    if same_inet_addr addr (fst m.(!i)) then
+    if same_inet_addr addr (fst m.(!i)).Unix.ai_addr then
       found := true;
     incr i
   done;
diff -r e30dc5376cbb reconCS.ml
--- a/reconCS.ml        Fri May 23 21:16:40 2008 -0400
+++ b/reconCS.ml        Mon Mar 02 12:48:35 2009 +0000
@@ -132,21 +132,21 @@
 let connect tree ~filters ~partner ~self = 
   (* TODO: change the following to depend on the address type *)
   let s = Unix.socket 
-           ~domain:Unix.PF_INET 
-           ~kind:Unix.SOCK_STREAM 
-           ~protocol:0 
+           ~domain:partner.Unix.ai_family
+           ~kind:partner.Unix.ai_socktype
+           ~protocol:partner.Unix.ai_protocol
   in
   let run () =
     Unix.bind s ~addr:(get_client_recon_addr ());
-    Unix.connect s ~addr:partner;
+    Unix.connect s ~addr:partner.Unix.ai_addr;
     let cin = Channel.sys_in_from_fd s
     and cout = Channel.sys_out_from_fd s in
     plerror 4 "Initiating reconciliation";
-    let remote_config = handle_config cin cout filters partner in
+    let remote_config = handle_config cin cout filters partner.Unix.ai_addr in
     ignore (Unix.alarm !Settings.reconciliation_timeout);
 
     let http_port = config_get_http_port remote_config in
-    let remote_http_address = change_port partner http_port in
+    let remote_http_address = change_port partner.Unix.ai_addr http_port in
 
     let data = Server.handle tree cin cout in
     (data,remote_http_address)
diff -r e30dc5376cbb reconComm.ml
--- a/reconComm.ml      Fri May 23 21:16:40 2008 -0400
+++ b/reconComm.ml      Mon Mar 02 12:48:35 2009 +0000
@@ -65,13 +65,42 @@
   with
       Not_found -> false
 
+(** Get the protocol family needed for the use of an address *)
+let get_addr_pf addr =
+  match addr with
+    Unix.ADDR_INET(ip, _) ->
+      if String.contains (Unix.string_of_inet_addr ip) ':'
+      then Unix.PF_INET6
+      else Unix.PF_INET
+  | Unix.ADDR_UNIX(_) -> Unix.PF_UNIX
+
+(** Given two protocol families, guess a minimal compatible family *)
+let get_compat_pf addr1 addr2 =
+  match (get_addr_pf addr1, get_addr_pf addr2) with
+    (Unix.PF_INET6, _) | (_, Unix.PF_INET6) -> Unix.PF_INET6
+  | (pf, _) -> pf
+
+(** Map an IP address to IPv6 if protocol family is PF_INET6 *)
+let map_addr pf addr =
+  match (pf, addr) with
+    (Unix.PF_INET6, Unix.ADDR_INET(ip, port)) ->
+      let addr_str = Unix.string_of_inet_addr ip in
+      if String.contains addr_str ':'
+      then addr
+      else Unix.ADDR_INET(Unix.inet_addr_of_string ("::ffff:" ^ addr_str), 
port)
+  | _ -> addr
+
 let get_keystrings_via_http addr hashes = 
+  let recon_addr = get_client_recon_addr() in
+  let pf = get_compat_pf addr recon_addr in
+  let addr = map_addr pf addr in
+  let recon_addr = map_addr pf recon_addr in
   let s = Unix.socket 
-           ~domain:Unix.PF_INET 
+           ~domain:pf
            ~kind:Unix.SOCK_STREAM 
            ~protocol:0  in
   protect ~f:(fun () -> 
-               Unix.bind s ~addr:(get_client_recon_addr ());
+               Unix.bind s ~addr:recon_addr;
                Unix.connect s ~addr;
                let cin = Channel.sys_in_from_fd s 
                and cout = Channel.sys_out_from_fd s in
diff -r e30dc5376cbb reconserver.ml
--- a/reconserver.ml    Fri May 23 21:16:40 2008 -0400
+++ b/reconserver.ml    Mon Mar 02 12:48:35 2009 +0000
@@ -211,7 +211,7 @@
     else
       begin
        let partner = choose_partner () in
-       plerror 4 "Recon partner: %s" (sockaddr_to_string partner);
+       plerror 4 "Recon partner: %s" (sockaddr_to_string partner.Unix.ai_addr);
        let filters = get_filters () in
        let (results,http_addr) = 
          ReconCS.connect (get_ptree ()) ~filters ~partner 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]