sks-devel
[Top][All Lists]
Advanced

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

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


From: Phil Pennock
Subject: [Sks-devel] Patch (partial): IPv6 support (in progress)
Date: Mon, 2 Mar 2009 02:52:57 -0800

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.

Thanks,
-Phil
diff -r e30dc5376cbb common.ml
--- a/common.ml Fri May 23 21:16:40 2008 -0400
+++ b/common.ml Mon Mar 02 02:43:24 2009 -0800
@@ -199,6 +199,7 @@
 
 let recon_port = !Settings.recon_port 
 let recon_address = !Settings.recon_address
+let recon6_address = !Settings.recon6_address
 let http_port = !Settings.hkp_port
 let http_address = !Settings.hkp_address
 let db_command_name = Filename.concat !Settings.basedir "db_com_sock"
@@ -212,7 +213,15 @@
   | Unix.ADDR_INET (inet_addr,port) -> Unix.ADDR_INET (inet_addr,port + 1)
 
 
-let get_client_recon_addr () =
-  Unix.ADDR_INET (Unix.inet_addr_of_string recon_address,0)
+let get_client_recon_addr remote_addr = match Unix.domain_of_sockaddr 
remote_addr with
+    Unix.PF_UNIX -> failwith "Can't connect to remote local-domain sockets"
+  | Unix.PF_INET -> Unix.ADDR_INET (Unix.inet_addr_of_string recon_address,0)
+  | Unix.PF_INET6 -> Unix.ADDR_INET (Unix.inet_addr_of_string recon6_address,0)
 let get_client_recon_addr = 
-  Utils.unit_memoize get_client_recon_addr
+  Utils.memoize get_client_recon_addr
+
+let sockaddr_to_string sockaddr = match sockaddr with
+    Unix.ADDR_UNIX s -> sprintf "<ADDR_UNIX %s>" s
+  | Unix.ADDR_INET (addr,p) -> sprintf "<ADDR_INET %s:%d>"
+      (Unix.string_of_inet_addr addr) p
+
diff -r e30dc5376cbb eventloop.ml
--- a/eventloop.ml      Fri May 23 21:16:40 2008 -0400
+++ b/eventloop.ml      Mon Mar 02 02:43:24 2009 -0800
@@ -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 = Unix.domain_of_sockaddr addr in
     let sock =
       socket ~domain ~kind:SOCK_STREAM ~protocol:0 in
     setsockopt sock SO_REUSEADDR true;
@@ -132,8 +129,10 @@
     listen sock ~max:20;
     sock
   with
-    | Unix_error (_,"bind",_) -> 
-       failwith "Failure while binding socket.  Probably another socket bound 
to this address"
+    | Unix_error (error, "bind",_) -> 
+        let msg = error_message error in
+        let addrstr = sockaddr_to_string addr in
+       failwith (sprintf "Failure binding %s: %s" addrstr msg)
     | e -> raise e
 let add_events heap evlist =
   List.iter ~f:(fun (Event (time, callback)) -> 
diff -r e30dc5376cbb membership.ml
--- a/membership.ml     Fri May 23 21:16:40 2008 -0400
+++ b/membership.ml     Mon Mar 02 02:43:24 2009 -0800
@@ -29,28 +29,80 @@
 exception Bug of string
 exception Lookup_failure of string
 exception Malformed_entry of string
+exception Empty_line
 
 let membership = ref ([| |],-1.)
 
 let whitespace = Str.regexp "[ \t]+"
 
-let lookup_hostname string = 
-  try (Unix.gethostbyname string).Unix.h_addr_list.(0)
-  with 
+(* Although the OCaml standard Unix library does not include AF_UNSPEC, the
+ * underlying C implementation uses AF_UNSPEC unless overriden (ie, there's
+ * no way to specify a value which matches the default behaviour).
+ * So for IPv4/IPv6 functionality, use getaddrinfo without an AI_FAMILY
+ * parameter.
+ * This does mean that we need a separate function to filter though.
+ *)
+
+let inet_addr_of_sockaddr sock = match sock with
+    Unix.ADDR_UNIX _ -> raise (Bug "asking for inet addr of local domain 
socket")
+  | Unix.ADDR_INET (addr, port) -> addr
+
+let inet_addr_of_addr_info ai = match ai.Unix.ai_addr with
+    Unix.ADDR_UNIX _ -> raise (Bug "converting getaddrinfo result which is 
local domain?")
+  | Unix.ADDR_INET (addr, port) -> addr
+
+let lookup_hostname_list ?(port = recon_port) string =
+  let portstr = string_of_int port in
+  try begin
+    let reslist = Unix.getaddrinfo string portstr [Unix.AI_SOCKTYPE 
Unix.SOCK_STREAM] in
+    if List.length reslist == 0 then raise (Lookup_failure string)
+    else List.map inet_addr_of_addr_info reslist
+  end
+  with
     | Invalid_argument _ | Not_found -> raise (Lookup_failure string)
 
-let local_recon_addr () = 
-  Unix.ADDR_INET (lookup_hostname !Settings.hostname, recon_port)
+let lookup_hostname_list_filtered ~family ?(port = recon_port) string =
+  let portstr = string_of_int port in
+  let filter = (fun ai -> if ai.Unix.ai_family == family then true else false) 
in
+  try begin
+    let reslist = Unix.getaddrinfo string portstr [Unix.AI_SOCKTYPE 
Unix.SOCK_STREAM] in
+    if List.length reslist == 0 then raise (Lookup_failure string)
+    else List.map inet_addr_of_addr_info (List.filter filter reslist)
+  end
+  with
+    | Invalid_argument _ | Not_found -> raise (Lookup_failure string)
 
-let local_recon_addr = Utils.unit_memoize local_recon_addr
+let my_ipv4_recon_addresses () =
+  let r = Unix.inet_addr_of_string !Settings.recon_address in
+  if r = Unix.inet_addr_any
+  then lookup_hostname_list_filtered ~family:Unix.PF_INET !Settings.hostname
+  else [r]
+let my_ipv4_recon_addresses = Utils.unit_memoize my_ipv4_recon_addresses
+
+let my_ipv6_recon_addresses () =
+  let r = Unix.inet_addr_of_string !Settings.recon6_address in
+  if r = Unix.inet6_addr_any
+  then lookup_hostname_list_filtered ~family:Unix.PF_INET6 !Settings.hostname
+  else [r]
+let my_ipv6_recon_addresses = Utils.unit_memoize my_ipv6_recon_addresses
+
+let is_local_recon_addr peer = match Unix.domain_of_sockaddr peer with
+    Unix.PF_UNIX -> raise (Bug "trying to find local address of remote local 
domain socket")
+  | Unix.PF_INET -> List.exists (fun a -> (inet_addr_of_sockaddr peer) = a) 
(my_ipv4_recon_addresses ())
+  | Unix.PF_INET6 -> List.exists (fun a -> (inet_addr_of_sockaddr peer) = a) 
(my_ipv6_recon_addresses ())
+ 
+let is_local_recon_addr = Utils.memoize is_local_recon_addr
 
 let remove_self addresses = 
-  List.filter ~f:(fun (addr,str) -> addr <> local_recon_addr ()) addresses
+  List.filter ~f:(fun (addr,str) -> not (is_local_recon_addr addr)) addresses
 
+(* For now, leave this single-address *)
 let convert_address l =
   try 
-    sscanf l "%s %d" 
-    (fun addr port -> Unix.ADDR_INET (lookup_hostname addr,port))
+    if String.length l == 0 then raise Empty_line
+    else
+      sscanf l "%s %d" 
+      (fun addr port -> Unix.ADDR_INET (List.hd (lookup_hostname_list 
addr),port))
   with 
     Scanf.Scan_failure _ | End_of_file | Failure _ -> raise (Malformed_entry l)
 
@@ -61,6 +113,7 @@
       let addr = convert_address line in
       (addr,line) :: loop list
     with
+      | Empty_line -> loop list
       | End_of_file -> list
       | Lookup_failure addr -> 
          perror "Lookup failure on address %s" addr;
@@ -93,11 +146,6 @@
             )
     ~finally:(fun () -> close_in file)
 
-let sockaddr_to_string sockaddr = match sockaddr with
-    Unix.ADDR_UNIX s -> sprintf "<ADDR_UNIX %s>" s
-  | Unix.ADDR_INET (addr,p) -> sprintf "<ADDR_INET %s:%d>" 
-      (Unix.string_of_inet_addr addr) p
-
 let membership_string () = 
   let (mshp,_) = !membership in
   let to_string (addr,str) =
diff -r e30dc5376cbb reconCS.ml
--- a/reconCS.ml        Fri May 23 21:16:40 2008 -0400
+++ b/reconCS.ml        Mon Mar 02 02:43:24 2009 -0800
@@ -129,7 +129,7 @@
 
 
 (** function to connect to remote host to initate reconciliation *)
-let connect tree ~filters ~partner ~self = 
+let connect tree ~filters ~partner = 
   (* TODO: change the following to depend on the address type *)
   let s = Unix.socket 
            ~domain:Unix.PF_INET 
@@ -137,7 +137,7 @@
            ~protocol:0 
   in
   let run () =
-    Unix.bind s ~addr:(get_client_recon_addr ());
+    Unix.bind s ~addr:(get_client_recon_addr partner);
     Unix.connect s ~addr:partner;
     let cin = Channel.sys_in_from_fd s
     and cout = Channel.sys_out_from_fd s in
diff -r e30dc5376cbb reconComm.ml
--- a/reconComm.ml      Fri May 23 21:16:40 2008 -0400
+++ b/reconComm.ml      Mon Mar 02 02:43:24 2009 -0800
@@ -67,11 +67,11 @@
 
 let get_keystrings_via_http addr hashes = 
   let s = Unix.socket 
-           ~domain:Unix.PF_INET 
+           ~domain:(Unix.domain_of_sockaddr addr)
            ~kind:Unix.SOCK_STREAM 
            ~protocol:0  in
   protect ~f:(fun () -> 
-               Unix.bind s ~addr:(get_client_recon_addr ());
+               Unix.bind s ~addr:(get_client_recon_addr 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 02:43:24 2009 -0800
@@ -50,7 +50,9 @@
   (******************************************************************)
 
   let recon_addr = Unix.ADDR_INET (Unix.inet_addr_of_string 
recon_address,recon_port)
+  let recon6_addr = Unix.ADDR_INET (Unix.inet_addr_of_string 
recon6_address,recon_port)
   let reconsock = Eventloop.create_sock recon_addr
+  let recon6sock = Eventloop.create_sock recon6_addr
 
   let () = 
     if Sys.file_exists recon_command_name
@@ -215,7 +217,6 @@
        let filters = get_filters () in
        let (results,http_addr) = 
          ReconCS.connect (get_ptree ()) ~filters ~partner 
-           ~self:Membership.local_recon_addr
        in
        let results = ZSet.elements results in
        plerror 4 "Reconciliation complete";
@@ -360,7 +361,12 @@
           ~timeout:!Settings.command_timeout
        ); 
        (reconsock, Eventloop.make_th 
-          ~name:"reconciliation handler"
+          ~name:"reconciliation handler (IPv4)"
+          ~cb:recon_handler 
+          ~timeout:!Settings.reconciliation_config_timeout
+       ); 
+       (recon6sock, Eventloop.make_th 
+          ~name:"reconciliation handler (IPv6)"
           ~cb:recon_handler 
           ~timeout:!Settings.reconciliation_config_timeout
        ); 
diff -r e30dc5376cbb settings.ml
--- a/settings.ml       Fri May 23 21:16:40 2008 -0400
+++ b/settings.ml       Mon Mar 02 02:43:24 2009 -0800
@@ -56,12 +56,16 @@
   seed := value
 
 let recon_port = ref 11370
-let recon_address = ref "0.0.0.0"
+let recon_address = ref (Unix.string_of_inet_addr Unix.inet_addr_any)
 let set_recon_address value = recon_address := value
+let recon6_address = ref (Unix.string_of_inet_addr Unix.inet6_addr_any)
+let set_recon6_address value = recon6_address := value
 
 let hkp_port = ref 11371
-let hkp_address = ref "0.0.0.0"
+let hkp_address = ref (Unix.string_of_inet_addr Unix.inet_addr_any)
 let set_hkp_address value = hkp_address := value
+let hkp6_address = ref (Unix.string_of_inet_addr Unix.inet6_addr_any)
+let set_hkp6_address value = hkp6_address := value
 
 let use_port_80 = ref false
 
@@ -247,9 +251,11 @@
     ("-baseport",Arg.Int set_base_port, " Set base port number");
     ("-logfile",Arg.String (fun _ -> ()), " DEPRECATED.  Now ignored.");
     ("-recon_port",Arg.Int set_recon_port, " Set recon port number");
-    ("-recon_address",Arg.String set_recon_address, " Set recon binding 
address"); 
+    ("-recon_address",Arg.String set_recon_address, " Set recon binding 
address (IPv4)"); 
+    ("-recon6_address",Arg.String set_recon6_address, " Set recon binding 
address (IPv6)"); 
     ("-hkp_port",Arg.Int set_hkp_port, " Set hkp port number");
-    ("-hkp_address",Arg.String set_hkp_address, " Set hkp binding address"); 
+    ("-hkp_address",Arg.String set_hkp_address, " Set hkp binding address 
(IPv4)"); 
+    ("-hkp6_address",Arg.String set_hkp6_address, " Set hkp binding address 
(IPv6)"); 
     ("-use_port_80",Arg.Set use_port_80, 
      " Have the HKP interface listen on port 80, as well as the hkp_port"); 
     ("-basedir", Arg.Set_string basedir, " Base directory");
diff -r e30dc5376cbb sks.pod
--- a/sks.pod   Fri May 23 21:16:40 2008 -0400
+++ b/sks.pod   Mon Mar 02 02:43:24 2009 -0800
@@ -152,7 +152,11 @@
 
 =item -recon_address
 
-Set recon binding address.
+Set recon binding IPv4 address.  Also used for outbound connections.
+
+=item -recon6_address
+
+Set recon binding IPv6 address.  Also used for outbound connections.
 
 =item -hkp_port
 
@@ -160,7 +164,11 @@
 
 =item -hkp_address
 
-Set hkp binding address.
+Set hkp binding IPv4 address.
+
+=item -hkp6_address
+
+Set hkp binding IPv6 address.
 
 =item -use_port_80
 

Attachment: pgp8nRb6K_0YY.pgp
Description: PGP signature


reply via email to

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