2 * linux/net/sunrpc/pmap.c
6 * FIXME: In a secure environment, we may want to use an authentication
7 * flavor other than AUTH_NULL.
9 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
12 #include <linux/config.h>
13 #include <linux/types.h>
14 #include <linux/socket.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/uio.h>
19 #include <linux/sunrpc/clnt.h>
20 #include <linux/sunrpc/xprt.h>
21 #include <linux/sunrpc/sched.h>
24 # define RPCDBG_FACILITY RPCDBG_PMAP
29 #define PMAP_GETPORT 3
31 static struct rpc_clnt
* pmap_create(char *, struct sockaddr_in
*, int);
32 static void pmap_getport_done(struct rpc_task
*);
33 extern struct rpc_program pmap_program
;
34 spinlock_t pmap_lock
= SPIN_LOCK_UNLOCKED
;
37 * Obtain the port for a given RPC service on a given host. This one can
38 * be called for an ongoing RPC request.
41 rpc_getport(struct rpc_task
*task
, struct rpc_clnt
*clnt
)
43 struct rpc_portmap
*map
= &clnt
->cl_pmap
;
44 struct sockaddr_in
*sap
= &clnt
->cl_xprt
->addr
;
45 struct rpc_message msg
= { PMAP_GETPORT
, map
, &clnt
->cl_port
, NULL
};
46 struct rpc_clnt
*pmap_clnt
;
47 struct rpc_task
*child
;
49 dprintk("RPC: %4d rpc_getport(%s, %d, %d, %d)\n",
50 task
->tk_pid
, clnt
->cl_server
,
51 map
->pm_prog
, map
->pm_vers
, map
->pm_prot
);
53 spin_lock(&pmap_lock
);
54 if (clnt
->cl_binding
) {
55 rpc_sleep_on(&clnt
->cl_bindwait
, task
, NULL
, 0);
56 spin_unlock(&pmap_lock
);
60 spin_unlock(&pmap_lock
);
62 task
->tk_status
= -EACCES
; /* why set this? returns -EIO below */
63 if (!(pmap_clnt
= pmap_create(clnt
->cl_server
, sap
, map
->pm_prot
)))
68 * Note: rpc_new_child will release client after a failure.
70 if (!(child
= rpc_new_child(pmap_clnt
, task
)))
73 /* Setup the call info struct */
74 rpc_call_setup(child
, &msg
, 0);
76 /* ... and run the child task */
77 rpc_run_child(task
, child
, pmap_getport_done
);
81 spin_lock(&pmap_lock
);
83 rpc_wake_up(&clnt
->cl_bindwait
);
84 spin_unlock(&pmap_lock
);
85 task
->tk_status
= -EIO
;
86 task
->tk_action
= NULL
;
89 #ifdef CONFIG_ROOT_NFS
90 char *in_ntoa(__u32 in
);
93 rpc_getport_external(struct sockaddr_in
*sin
, __u32 prog
, __u32 vers
, int prot
)
95 struct rpc_portmap map
= { prog
, vers
, prot
, 0 };
96 struct rpc_clnt
*pmap_clnt
;
100 dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n",
101 NIPQUAD(sin
->sin_addr
.s_addr
), prog
, vers
, prot
);
103 strcpy(hostname
, in_ntoa(sin
->sin_addr
.s_addr
));
104 if (!(pmap_clnt
= pmap_create(hostname
, sin
, prot
)))
107 /* Setup the call info struct */
108 status
= rpc_call(pmap_clnt
, PMAP_GETPORT
, &map
, &map
.pm_port
, 0);
111 if (map
.pm_port
!= 0)
120 pmap_getport_done(struct rpc_task
*task
)
122 struct rpc_clnt
*clnt
= task
->tk_client
;
124 dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n",
125 task
->tk_pid
, task
->tk_status
, clnt
->cl_port
);
126 if (task
->tk_status
< 0) {
127 /* Make the calling task exit with an error */
128 task
->tk_action
= NULL
;
129 } else if (clnt
->cl_port
== 0) {
130 /* Program not registered */
131 task
->tk_status
= -EACCES
;
132 task
->tk_action
= NULL
;
134 /* byte-swap port number first */
135 clnt
->cl_port
= htons(clnt
->cl_port
);
136 clnt
->cl_xprt
->addr
.sin_port
= clnt
->cl_port
;
138 spin_lock(&pmap_lock
);
139 clnt
->cl_binding
= 0;
140 rpc_wake_up(&clnt
->cl_bindwait
);
141 spin_unlock(&pmap_lock
);
145 * Set or unset a port registration with the local portmapper.
146 * port == 0 means unregister, port != 0 means register.
149 rpc_register(u32 prog
, u32 vers
, int prot
, unsigned short port
, int *okay
)
151 struct sockaddr_in sin
;
152 struct rpc_portmap map
;
153 struct rpc_clnt
*pmap_clnt
;
154 unsigned int error
= 0;
156 dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n",
157 prog
, vers
, prot
, port
);
159 sin
.sin_family
= AF_INET
;
160 sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
161 if (!(pmap_clnt
= pmap_create("localhost", &sin
, IPPROTO_UDP
))) {
162 dprintk("RPC: couldn't create pmap client\n");
171 error
= rpc_call(pmap_clnt
, port
? PMAP_SET
: PMAP_UNSET
,
176 "RPC: failed to contact portmap (errno %d).\n",
179 dprintk("RPC: registration status %d/%d\n", error
, *okay
);
181 /* Client deleted automatically because cl_oneshot == 1 */
185 static struct rpc_clnt
*
186 pmap_create(char *hostname
, struct sockaddr_in
*srvaddr
, int proto
)
188 struct rpc_xprt
*xprt
;
189 struct rpc_clnt
*clnt
;
191 /* printk("pmap: create xprt\n"); */
192 if (!(xprt
= xprt_create_proto(proto
, srvaddr
, NULL
)))
194 xprt
->addr
.sin_port
= htons(RPC_PMAP_PORT
);
196 /* printk("pmap: create clnt\n"); */
197 clnt
= rpc_create_client(xprt
, hostname
,
198 &pmap_program
, RPC_PMAP_VERSION
,
203 clnt
->cl_softrtry
= 1;
205 clnt
->cl_oneshot
= 1;
211 * XDR encode/decode functions for PMAP
214 xdr_error(struct rpc_rqst
*req
, u32
*p
, void *dummy
)
220 xdr_encode_mapping(struct rpc_rqst
*req
, u32
*p
, struct rpc_portmap
*map
)
222 dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n",
223 map
->pm_prog
, map
->pm_vers
, map
->pm_prot
, map
->pm_port
);
224 *p
++ = htonl(map
->pm_prog
);
225 *p
++ = htonl(map
->pm_vers
);
226 *p
++ = htonl(map
->pm_prot
);
227 *p
++ = htonl(map
->pm_port
);
229 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
234 xdr_decode_port(struct rpc_rqst
*req
, u32
*p
, unsigned short *portp
)
236 *portp
= (unsigned short) ntohl(*p
++);
241 xdr_decode_bool(struct rpc_rqst
*req
, u32
*p
, unsigned int *boolp
)
243 *boolp
= (unsigned int) ntohl(*p
++);
247 static struct rpc_procinfo pmap_procedures
[4] = {
249 (kxdrproc_t
) xdr_error
,
250 (kxdrproc_t
) xdr_error
, 0, 0 },
252 (kxdrproc_t
) xdr_encode_mapping
,
253 (kxdrproc_t
) xdr_decode_bool
, 4, 1 },
255 (kxdrproc_t
) xdr_encode_mapping
,
256 (kxdrproc_t
) xdr_decode_bool
, 4, 1 },
258 (kxdrproc_t
) xdr_encode_mapping
,
259 (kxdrproc_t
) xdr_decode_port
, 4, 1 },
262 static struct rpc_version pmap_version2
= {
263 2, 4, pmap_procedures
266 static struct rpc_version
* pmap_version
[] = {
272 static struct rpc_stat pmap_stats
;
274 struct rpc_program pmap_program
= {
277 sizeof(pmap_version
)/sizeof(pmap_version
[0]),