33
44#![ allow( non_camel_case_types) ]
55
6+ use log:: * ;
7+
68use std:: ffi:: OsString ;
79use std:: net:: TcpListener ;
810
@@ -15,13 +17,8 @@ use super::rpcbind::procedures::*;
1517pub fn main ( ) {
1618 let service_list = default_service_list ( ) ;
1719
18- let procedures: Vec < Option < RpcProcedure < rpcbind:: RpcbindList > > > = vec ! [
19- None ,
20- None , // set()
21- None , // unset()
22- Some ( getaddr) ,
23- Some ( dump) ,
24- ] ;
20+ let procedures: Vec < Option < RpcProcedure < rpcbind:: RpcbindList > > > =
21+ vec ! [ None , Some ( set) , Some ( unset) , Some ( getaddr) , Some ( dump) ] ;
2522 let mut server = RpcService :: new ( RPCBPROG , RPCBVERS :: VERSION , procedures, service_list) ;
2623
2724 let listener = TcpListener :: bind ( "0.0.0.0:111" ) . unwrap ( ) ;
@@ -34,26 +31,14 @@ pub fn main() {
3431fn getaddr ( _call : & CallBody , mut arg : & [ u8 ] , service_list : & mut rpcbind:: RpcbindList ) -> RpcResult {
3532 let mut requested = rpcbind:: RpcService :: default ( ) ;
3633 rpcbind:: RpcService :: deserialize ( & mut requested, & mut arg) . unwrap ( ) ;
37- eprintln ! ( "{:?}" , requested) ;
38-
39- for service in service_list. items . iter ( ) {
40- let service = & service. rpcb_map ;
41-
42- if requested. prog != service. prog {
43- continue ;
44- }
45-
46- if requested. vers != service. vers {
47- continue ;
48- }
34+ debug ! ( "GETADDR Call: {requested:?}" ) ;
4935
36+ if let Some ( service) = get_service ( requested. prog , requested. vers , service_list) {
5037 let address = rpcbind:: RpcbString {
5138 contents : service. addr . clone ( ) ,
5239 } ;
5340
54- let bytes = rpcbind:: RpcbString :: serialize_alloc ( & address) ;
55-
56- return RpcResult :: Success ( bytes) ;
41+ return RpcResult :: Success ( rpcbind:: RpcbString :: serialize_alloc ( & address) ) ;
5742 }
5843
5944 let empty = rpcbind:: RpcbString {
@@ -63,6 +48,37 @@ fn getaddr(_call: &CallBody, mut arg: &[u8], service_list: &mut rpcbind::Rpcbind
6348 RpcResult :: Success ( empty. serialize_alloc ( ) )
6449}
6550
51+ /// Implementation of the set RPC. This adds a service to the list.
52+ fn set ( _call : & CallBody , arg : & [ u8 ] , service_list : & mut rpcbind:: RpcbindList ) -> RpcResult {
53+ let mut new_service = rpcbind:: RpcService :: default ( ) ;
54+ let mut arg = arg;
55+ if let Err ( _) = new_service. deserialize ( & mut arg) {
56+ return RpcResult :: GarbageArgs ;
57+ }
58+
59+ // Make sure that this service is not already registered:
60+ if get_service ( new_service. prog , new_service. vers , service_list) . is_some ( ) {
61+ // If it is, return False to the caller:
62+ return RpcResult :: Success ( vec ! [ 0 , 0 , 0 , 0 ] ) ;
63+ }
64+
65+ if new_service. netid . is_empty ( ) || new_service. addr . is_empty ( ) {
66+ // According to the RFC, empty netid and address are not allowed.
67+ return RpcResult :: Success ( vec ! [ 0 , 0 , 0 , 0 ] ) ;
68+ }
69+
70+ service_list. items . push ( rpcbind:: RpcbindItem {
71+ rpcb_map : new_service,
72+ } ) ;
73+
74+ RpcResult :: Success ( vec ! [ 0 , 0 , 0 , 1 ] )
75+ }
76+
77+ /// Implementation of the unset RPC. This removes a service from the list.
78+ fn unset ( _call : & CallBody , _arg : & [ u8 ] , service_list : & mut rpcbind:: RpcbindList ) -> RpcResult {
79+ todo ! ( )
80+ }
81+
6682/// Implementation of the dump RPC. This returns the entire known `service_list`.
6783fn dump ( _call : & CallBody , _arg : & [ u8 ] , service_list : & mut rpcbind:: RpcbindList ) -> RpcResult {
6884 let data = service_list. serialize_alloc ( ) ;
@@ -83,3 +99,27 @@ fn default_service_list() -> rpcbind::RpcbindList {
8399
84100 rpcbind:: RpcbindList { items : vec ! [ item] }
85101}
102+
103+ /// Returns the service specified by `program` and `version` from the `service_list`, or none if
104+ /// there is no match.
105+ fn get_service (
106+ program : u32 ,
107+ version : u32 ,
108+ service_list : & rpcbind:: RpcbindList ,
109+ ) -> Option < & rpcbind:: RpcService > {
110+ for service in & service_list. items {
111+ let service = & service. rpcb_map ;
112+
113+ if program != service. prog {
114+ continue ;
115+ }
116+
117+ if version != service. vers {
118+ continue ;
119+ }
120+
121+ return Some ( service) ;
122+ }
123+
124+ return None ;
125+ }
0 commit comments