(* $Id: rpc_portmapper.ml 258 2004-05-25 16:49:11Z gerd $ * ---------------------------------------------------------------------- * *) (* Call the portmapper version 2. Note that version 2 is an older version * (version 3 and 4 are called 'rpcbind'), but it is normally available. *) open Rtypes open Xdr open Rpc type t = { client : Rpc_simple_client.t } ;; let pm2_ts = [ "mapping", X_struct [ "prog", X_uint; "vers", X_uint; "prot", X_uint; "port", X_uint ]; "pmaplist", X_rec("pmaplist", (x_optional (X_struct [ "map", X_type "mapping"; "next", X_refer "pmaplist" ]))); "call_args", X_struct [ "prog", X_uint; "vers", X_uint; "proc", X_uint; "args", x_opaque_max ]; "call_results", X_struct [ "port", X_uint; "res", x_opaque_max ] ] ;; let pm2_spec() = begin Rpc_program.create (uint4_of_int 100000) (uint4_of_int 2) (validate_xdr_type_system pm2_ts) [ "NULL", ((uint4_of_int 0), X_void, X_void); "SET", ((uint4_of_int 1), X_type "mapping", x_bool); "UNSET", ((uint4_of_int 2), X_type "mapping", x_bool); "GETPORT", ((uint4_of_int 3), X_type "mapping", X_uint); "DUMP", ((uint4_of_int 4), X_void, X_type "pmaplist"); "CALLIT", ((uint4_of_int 5), X_type "call_args", X_type "call_results") ] end ;; let mk_mapping prog vers prot port = XV_struct_fast [| (* prog *) XV_uint prog; (* vers *) XV_uint vers; (* prot *) XV_uint (if prot = Tcp then uint4_of_int 6 else uint4_of_int 17); (* port *) XV_uint (uint4_of_int port) |] ;; let rec dest_pmaplist l = try begin match l with XV_union_over_enum_fast (1, s) -> begin match s with XV_struct_fast [| (* map *) XV_struct_fast [| (* prog *) XV_uint prog; (* vers *) XV_uint vers; (* prot *) XV_uint prot; (* port *) XV_uint port |]; (* next *) l' |] -> let prot' = match int_of_uint4 prot with 6 -> Tcp | 17 -> Udp | _ -> failwith "illegal protocol specifier found" in (prog, vers, prot', int_of_uint4 port) :: dest_pmaplist l' end | XV_union_over_enum_fast (0, _) -> [] end with Match_failure _ -> failwith "dest_pmaplist" ;; let create connector = let spec = pm2_spec() in let client = Rpc_simple_client.create connector Tcp spec in { client = client } ;; let create_inet s = create (Rpc_client.Inet(s,111)) ;; let shut_down pm = Rpc_simple_client.shut_down pm.client ;; let null pm = ignore(Rpc_simple_client.call pm.client "NULL" XV_void) ;; let set pm prog vers prot port = let reply = Rpc_simple_client.call pm.client "SET" (mk_mapping prog vers prot port) in reply = xv_true ;; let unset pm prog vers prot port = let reply = Rpc_simple_client.call pm.client "UNSET" (mk_mapping prog vers prot port) in reply = xv_true ;; let getport pm prog vers prot = let reply = Rpc_simple_client.call pm.client "GETPORT" (mk_mapping prog vers prot 0) in match reply with XV_uint n -> int_of_uint4 n | _ -> failwith "Rpc_portmapper.getport" ;; let dump pm = let reply = Rpc_simple_client.call pm.client "DUMP" XV_void in dest_pmaplist reply ;; let callit pm spec proc arg = let (proc_nr, in_t, out_t) = Rpc_program.signature spec proc in let prog_nr = Rpc_program.program_number spec in let vers_nr = Rpc_program.version_number spec in let arg_value = Xdr.pack_xdr_value_as_string arg in_t [] in let reply = Rpc_simple_client.call pm.client "CALLIT" (XV_struct_fast [| (* prog *) XV_uint prog_nr; (* vers *) XV_uint vers_nr; (* proc *) XV_uint proc_nr; (* args *) XV_opaque arg_value |] ) in let XV_struct_fast [| (* port *) XV_uint port; (* res *) XV_opaque result |] = reply in int_of_uint4 port, unpack_xdr_value result out_t [] ;; let port_of_program program serverhost prot = let pm = create_inet serverhost in let p = getport pm (Rpc_program.program_number program) (Rpc_program.version_number program) prot in shut_down pm; if p = 0 then failwith "portmapper does not know the program"; p ;;