Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * In-kernel rpcbind client supporting versions 2, 3, and 4 of the rpcbind
4 : : * protocol
5 : : *
6 : : * Based on RFC 1833: "Binding Protocols for ONC RPC Version 2" and
7 : : * RFC 3530: "Network File System (NFS) version 4 Protocol"
8 : : *
9 : : * Original: Gilles Quillard, Bull Open Source, 2005 <gilles.quillard@bull.net>
10 : : * Updated: Chuck Lever, Oracle Corporation, 2007 <chuck.lever@oracle.com>
11 : : *
12 : : * Descended from net/sunrpc/pmap_clnt.c,
13 : : * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
14 : : */
15 : :
16 : : #include <linux/module.h>
17 : :
18 : : #include <linux/types.h>
19 : : #include <linux/socket.h>
20 : : #include <linux/un.h>
21 : : #include <linux/in.h>
22 : : #include <linux/in6.h>
23 : : #include <linux/kernel.h>
24 : : #include <linux/errno.h>
25 : : #include <linux/mutex.h>
26 : : #include <linux/slab.h>
27 : : #include <net/ipv6.h>
28 : :
29 : : #include <linux/sunrpc/clnt.h>
30 : : #include <linux/sunrpc/addr.h>
31 : : #include <linux/sunrpc/sched.h>
32 : : #include <linux/sunrpc/xprtsock.h>
33 : :
34 : : #include "netns.h"
35 : :
36 : : #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
37 : : # define RPCDBG_FACILITY RPCDBG_BIND
38 : : #endif
39 : :
40 : : #define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock"
41 : :
42 : : #define RPCBIND_PROGRAM (100000u)
43 : : #define RPCBIND_PORT (111u)
44 : :
45 : : #define RPCBVERS_2 (2u)
46 : : #define RPCBVERS_3 (3u)
47 : : #define RPCBVERS_4 (4u)
48 : :
49 : : enum {
50 : : RPCBPROC_NULL,
51 : : RPCBPROC_SET,
52 : : RPCBPROC_UNSET,
53 : : RPCBPROC_GETPORT,
54 : : RPCBPROC_GETADDR = 3, /* alias for GETPORT */
55 : : RPCBPROC_DUMP,
56 : : RPCBPROC_CALLIT,
57 : : RPCBPROC_BCAST = 5, /* alias for CALLIT */
58 : : RPCBPROC_GETTIME,
59 : : RPCBPROC_UADDR2TADDR,
60 : : RPCBPROC_TADDR2UADDR,
61 : : RPCBPROC_GETVERSADDR,
62 : : RPCBPROC_INDIRECT,
63 : : RPCBPROC_GETADDRLIST,
64 : : RPCBPROC_GETSTAT,
65 : : };
66 : :
67 : : /*
68 : : * r_owner
69 : : *
70 : : * The "owner" is allowed to unset a service in the rpcbind database.
71 : : *
72 : : * For AF_LOCAL SET/UNSET requests, rpcbind treats this string as a
73 : : * UID which it maps to a local user name via a password lookup.
74 : : * In all other cases it is ignored.
75 : : *
76 : : * For SET/UNSET requests, user space provides a value, even for
77 : : * network requests, and GETADDR uses an empty string. We follow
78 : : * those precedents here.
79 : : */
80 : : #define RPCB_OWNER_STRING "0"
81 : : #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING)
82 : :
83 : : /*
84 : : * XDR data type sizes
85 : : */
86 : : #define RPCB_program_sz (1)
87 : : #define RPCB_version_sz (1)
88 : : #define RPCB_protocol_sz (1)
89 : : #define RPCB_port_sz (1)
90 : : #define RPCB_boolean_sz (1)
91 : :
92 : : #define RPCB_netid_sz (1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN))
93 : : #define RPCB_addr_sz (1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
94 : : #define RPCB_ownerstring_sz (1 + XDR_QUADLEN(RPCB_MAXOWNERLEN))
95 : :
96 : : /*
97 : : * XDR argument and result sizes
98 : : */
99 : : #define RPCB_mappingargs_sz (RPCB_program_sz + RPCB_version_sz + \
100 : : RPCB_protocol_sz + RPCB_port_sz)
101 : : #define RPCB_getaddrargs_sz (RPCB_program_sz + RPCB_version_sz + \
102 : : RPCB_netid_sz + RPCB_addr_sz + \
103 : : RPCB_ownerstring_sz)
104 : :
105 : : #define RPCB_getportres_sz RPCB_port_sz
106 : : #define RPCB_setres_sz RPCB_boolean_sz
107 : :
108 : : /*
109 : : * Note that RFC 1833 does not put any size restrictions on the
110 : : * address string returned by the remote rpcbind database.
111 : : */
112 : : #define RPCB_getaddrres_sz RPCB_addr_sz
113 : :
114 : : static void rpcb_getport_done(struct rpc_task *, void *);
115 : : static void rpcb_map_release(void *data);
116 : : static const struct rpc_program rpcb_program;
117 : :
118 : : struct rpcbind_args {
119 : : struct rpc_xprt * r_xprt;
120 : :
121 : : u32 r_prog;
122 : : u32 r_vers;
123 : : u32 r_prot;
124 : : unsigned short r_port;
125 : : const char * r_netid;
126 : : const char * r_addr;
127 : : const char * r_owner;
128 : :
129 : : int r_status;
130 : : };
131 : :
132 : : static const struct rpc_procinfo rpcb_procedures2[];
133 : : static const struct rpc_procinfo rpcb_procedures3[];
134 : : static const struct rpc_procinfo rpcb_procedures4[];
135 : :
136 : : struct rpcb_info {
137 : : u32 rpc_vers;
138 : : const struct rpc_procinfo *rpc_proc;
139 : : };
140 : :
141 : : static const struct rpcb_info rpcb_next_version[];
142 : : static const struct rpcb_info rpcb_next_version6[];
143 : :
144 : : static const struct rpc_call_ops rpcb_getport_ops = {
145 : : .rpc_call_done = rpcb_getport_done,
146 : : .rpc_release = rpcb_map_release,
147 : : };
148 : :
149 : 0 : static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
150 : : {
151 : : xprt_clear_binding(xprt);
152 : 0 : rpc_wake_up_status(&xprt->binding, status);
153 : 0 : }
154 : :
155 : 0 : static void rpcb_map_release(void *data)
156 : : {
157 : : struct rpcbind_args *map = data;
158 : :
159 : 0 : rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status);
160 : 0 : xprt_put(map->r_xprt);
161 : 0 : kfree(map->r_addr);
162 : 0 : kfree(map);
163 : 0 : }
164 : :
165 : 0 : static int rpcb_get_local(struct net *net)
166 : : {
167 : : int cnt;
168 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
169 : :
170 : : spin_lock(&sn->rpcb_clnt_lock);
171 [ # # ]: 0 : if (sn->rpcb_users)
172 : 0 : sn->rpcb_users++;
173 : 0 : cnt = sn->rpcb_users;
174 : : spin_unlock(&sn->rpcb_clnt_lock);
175 : :
176 : 0 : return cnt;
177 : : }
178 : :
179 : 0 : void rpcb_put_local(struct net *net)
180 : : {
181 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
182 : 0 : struct rpc_clnt *clnt = sn->rpcb_local_clnt;
183 : 0 : struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4;
184 : : int shutdown = 0;
185 : :
186 : : spin_lock(&sn->rpcb_clnt_lock);
187 [ # # ]: 0 : if (sn->rpcb_users) {
188 [ # # ]: 0 : if (--sn->rpcb_users == 0) {
189 : 0 : sn->rpcb_local_clnt = NULL;
190 : 0 : sn->rpcb_local_clnt4 = NULL;
191 : : }
192 : 0 : shutdown = !sn->rpcb_users;
193 : : }
194 : : spin_unlock(&sn->rpcb_clnt_lock);
195 : :
196 [ # # ]: 0 : if (shutdown) {
197 : : /*
198 : : * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
199 : : */
200 [ # # ]: 0 : if (clnt4)
201 : 0 : rpc_shutdown_client(clnt4);
202 [ # # ]: 0 : if (clnt)
203 : 0 : rpc_shutdown_client(clnt);
204 : : }
205 : 0 : }
206 : :
207 : : static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
208 : : struct rpc_clnt *clnt4,
209 : : bool is_af_local)
210 : : {
211 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
212 : :
213 : : /* Protected by rpcb_create_local_mutex */
214 : 0 : sn->rpcb_local_clnt = clnt;
215 : 0 : sn->rpcb_local_clnt4 = clnt4;
216 : 0 : sn->rpcb_is_af_local = is_af_local ? 1 : 0;
217 : 0 : smp_wmb();
218 : 0 : sn->rpcb_users = 1;
219 : : dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: "
220 : : "%p, rpcb_local_clnt4: %p) for net %x%s\n",
221 : : sn->rpcb_local_clnt, sn->rpcb_local_clnt4,
222 : : net->ns.inum, (net == &init_net) ? " (init_net)" : "");
223 : : }
224 : :
225 : : /*
226 : : * Returns zero on success, otherwise a negative errno value
227 : : * is returned.
228 : : */
229 : 0 : static int rpcb_create_local_unix(struct net *net)
230 : : {
231 : : static const struct sockaddr_un rpcb_localaddr_rpcbind = {
232 : : .sun_family = AF_LOCAL,
233 : : .sun_path = RPCBIND_SOCK_PATHNAME,
234 : : };
235 : 0 : struct rpc_create_args args = {
236 : : .net = net,
237 : : .protocol = XPRT_TRANSPORT_LOCAL,
238 : : .address = (struct sockaddr *)&rpcb_localaddr_rpcbind,
239 : : .addrsize = sizeof(rpcb_localaddr_rpcbind),
240 : : .servername = "localhost",
241 : : .program = &rpcb_program,
242 : : .version = RPCBVERS_2,
243 : : .authflavor = RPC_AUTH_NULL,
244 : 0 : .cred = current_cred(),
245 : : /*
246 : : * We turn off the idle timeout to prevent the kernel
247 : : * from automatically disconnecting the socket.
248 : : * Otherwise, we'd have to cache the mount namespace
249 : : * of the caller and somehow pass that to the socket
250 : : * reconnect code.
251 : : */
252 : : .flags = RPC_CLNT_CREATE_NO_IDLE_TIMEOUT,
253 : : };
254 : : struct rpc_clnt *clnt, *clnt4;
255 : : int result = 0;
256 : :
257 : : /*
258 : : * Because we requested an RPC PING at transport creation time,
259 : : * this works only if the user space portmapper is rpcbind, and
260 : : * it's listening on AF_LOCAL on the named socket.
261 : : */
262 : 0 : clnt = rpc_create(&args);
263 [ # # ]: 0 : if (IS_ERR(clnt)) {
264 : : dprintk("RPC: failed to create AF_LOCAL rpcbind "
265 : : "client (errno %ld).\n", PTR_ERR(clnt));
266 : : result = PTR_ERR(clnt);
267 : 0 : goto out;
268 : : }
269 : :
270 : 0 : clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
271 [ # # ]: 0 : if (IS_ERR(clnt4)) {
272 : : dprintk("RPC: failed to bind second program to "
273 : : "rpcbind v4 client (errno %ld).\n",
274 : : PTR_ERR(clnt4));
275 : : clnt4 = NULL;
276 : : }
277 : :
278 : : rpcb_set_local(net, clnt, clnt4, true);
279 : :
280 : : out:
281 : 0 : return result;
282 : : }
283 : :
284 : : /*
285 : : * Returns zero on success, otherwise a negative errno value
286 : : * is returned.
287 : : */
288 : 0 : static int rpcb_create_local_net(struct net *net)
289 : : {
290 : : static const struct sockaddr_in rpcb_inaddr_loopback = {
291 : : .sin_family = AF_INET,
292 : : .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
293 : : .sin_port = htons(RPCBIND_PORT),
294 : : };
295 : 0 : struct rpc_create_args args = {
296 : : .net = net,
297 : : .protocol = XPRT_TRANSPORT_TCP,
298 : : .address = (struct sockaddr *)&rpcb_inaddr_loopback,
299 : : .addrsize = sizeof(rpcb_inaddr_loopback),
300 : : .servername = "localhost",
301 : : .program = &rpcb_program,
302 : : .version = RPCBVERS_2,
303 : : .authflavor = RPC_AUTH_UNIX,
304 : 0 : .cred = current_cred(),
305 : : .flags = RPC_CLNT_CREATE_NOPING,
306 : : };
307 : : struct rpc_clnt *clnt, *clnt4;
308 : : int result = 0;
309 : :
310 : 0 : clnt = rpc_create(&args);
311 [ # # ]: 0 : if (IS_ERR(clnt)) {
312 : : dprintk("RPC: failed to create local rpcbind "
313 : : "client (errno %ld).\n", PTR_ERR(clnt));
314 : : result = PTR_ERR(clnt);
315 : 0 : goto out;
316 : : }
317 : :
318 : : /*
319 : : * This results in an RPC ping. On systems running portmapper,
320 : : * the v4 ping will fail. Proceed anyway, but disallow rpcb
321 : : * v4 upcalls.
322 : : */
323 : 0 : clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
324 [ # # ]: 0 : if (IS_ERR(clnt4)) {
325 : : dprintk("RPC: failed to bind second program to "
326 : : "rpcbind v4 client (errno %ld).\n",
327 : : PTR_ERR(clnt4));
328 : : clnt4 = NULL;
329 : : }
330 : :
331 : : rpcb_set_local(net, clnt, clnt4, false);
332 : :
333 : : out:
334 : 0 : return result;
335 : : }
336 : :
337 : : /*
338 : : * Returns zero on success, otherwise a negative errno value
339 : : * is returned.
340 : : */
341 : 0 : int rpcb_create_local(struct net *net)
342 : : {
343 : : static DEFINE_MUTEX(rpcb_create_local_mutex);
344 : : int result = 0;
345 : :
346 [ # # ]: 0 : if (rpcb_get_local(net))
347 : : return result;
348 : :
349 : 0 : mutex_lock(&rpcb_create_local_mutex);
350 [ # # ]: 0 : if (rpcb_get_local(net))
351 : : goto out;
352 : :
353 [ # # ]: 0 : if (rpcb_create_local_unix(net) != 0)
354 : 0 : result = rpcb_create_local_net(net);
355 : :
356 : : out:
357 : 0 : mutex_unlock(&rpcb_create_local_mutex);
358 : 0 : return result;
359 : : }
360 : :
361 : 0 : static struct rpc_clnt *rpcb_create(struct net *net, const char *nodename,
362 : : const char *hostname,
363 : : struct sockaddr *srvaddr, size_t salen,
364 : : int proto, u32 version,
365 : : const struct cred *cred)
366 : : {
367 : 0 : struct rpc_create_args args = {
368 : : .net = net,
369 : : .protocol = proto,
370 : : .address = srvaddr,
371 : : .addrsize = salen,
372 : : .servername = hostname,
373 : : .nodename = nodename,
374 : : .program = &rpcb_program,
375 : : .version = version,
376 : : .authflavor = RPC_AUTH_UNIX,
377 : : .cred = cred,
378 : : .flags = (RPC_CLNT_CREATE_NOPING |
379 : : RPC_CLNT_CREATE_NONPRIVPORT),
380 : : };
381 : :
382 [ # # # ]: 0 : switch (srvaddr->sa_family) {
383 : : case AF_INET:
384 : 0 : ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
385 : 0 : break;
386 : : case AF_INET6:
387 : 0 : ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT);
388 : 0 : break;
389 : : default:
390 : : return ERR_PTR(-EAFNOSUPPORT);
391 : : }
392 : :
393 : 0 : return rpc_create(&args);
394 : : }
395 : :
396 : 0 : static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set)
397 : : {
398 : : int flags = RPC_TASK_NOCONNECT;
399 : 0 : int error, result = 0;
400 : :
401 [ # # # # ]: 0 : if (is_set || !sn->rpcb_is_af_local)
402 : : flags = RPC_TASK_SOFTCONN;
403 : 0 : msg->rpc_resp = &result;
404 : :
405 : 0 : error = rpc_call_sync(clnt, msg, flags);
406 [ # # ]: 0 : if (error < 0) {
407 : : dprintk("RPC: failed to contact local rpcbind "
408 : : "server (errno %d).\n", -error);
409 : : return error;
410 : : }
411 : :
412 [ # # ]: 0 : if (!result)
413 : : return -EACCES;
414 : 0 : return 0;
415 : : }
416 : :
417 : : /**
418 : : * rpcb_register - set or unset a port registration with the local rpcbind svc
419 : : * @net: target network namespace
420 : : * @prog: RPC program number to bind
421 : : * @vers: RPC version number to bind
422 : : * @prot: transport protocol to register
423 : : * @port: port value to register
424 : : *
425 : : * Returns zero if the registration request was dispatched successfully
426 : : * and the rpcbind daemon returned success. Otherwise, returns an errno
427 : : * value that reflects the nature of the error (request could not be
428 : : * dispatched, timed out, or rpcbind returned an error).
429 : : *
430 : : * RPC services invoke this function to advertise their contact
431 : : * information via the system's rpcbind daemon. RPC services
432 : : * invoke this function once for each [program, version, transport]
433 : : * tuple they wish to advertise.
434 : : *
435 : : * Callers may also unregister RPC services that are no longer
436 : : * available by setting the passed-in port to zero. This removes
437 : : * all registered transports for [program, version] from the local
438 : : * rpcbind database.
439 : : *
440 : : * This function uses rpcbind protocol version 2 to contact the
441 : : * local rpcbind daemon.
442 : : *
443 : : * Registration works over both AF_INET and AF_INET6, and services
444 : : * registered via this function are advertised as available for any
445 : : * address. If the local rpcbind daemon is listening on AF_INET6,
446 : : * services registered via this function will be advertised on
447 : : * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6
448 : : * addresses).
449 : : */
450 : 0 : int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short port)
451 : : {
452 : 0 : struct rpcbind_args map = {
453 : : .r_prog = prog,
454 : : .r_vers = vers,
455 : : .r_prot = prot,
456 : : .r_port = port,
457 : : };
458 : 0 : struct rpc_message msg = {
459 : : .rpc_argp = &map,
460 : : };
461 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
462 : : bool is_set = false;
463 : :
464 : : dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
465 : : "rpcbind\n", (port ? "" : "un"),
466 : : prog, vers, prot, port);
467 : :
468 : 0 : msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
469 [ # # ]: 0 : if (port != 0) {
470 : 0 : msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
471 : : is_set = true;
472 : : }
473 : :
474 : 0 : return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set);
475 : : }
476 : :
477 : : /*
478 : : * Fill in AF_INET family-specific arguments to register
479 : : */
480 : 0 : static int rpcb_register_inet4(struct sunrpc_net *sn,
481 : : const struct sockaddr *sap,
482 : : struct rpc_message *msg)
483 : : {
484 : : const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
485 : 0 : struct rpcbind_args *map = msg->rpc_argp;
486 : 0 : unsigned short port = ntohs(sin->sin_port);
487 : : bool is_set = false;
488 : : int result;
489 : :
490 : 0 : map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
491 : :
492 : : dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
493 : : "local rpcbind\n", (port ? "" : "un"),
494 : : map->r_prog, map->r_vers,
495 : : map->r_addr, map->r_netid);
496 : :
497 : 0 : msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
498 [ # # ]: 0 : if (port != 0) {
499 : 0 : msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
500 : : is_set = true;
501 : : }
502 : :
503 : 0 : result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
504 : 0 : kfree(map->r_addr);
505 : 0 : return result;
506 : : }
507 : :
508 : : /*
509 : : * Fill in AF_INET6 family-specific arguments to register
510 : : */
511 : 0 : static int rpcb_register_inet6(struct sunrpc_net *sn,
512 : : const struct sockaddr *sap,
513 : : struct rpc_message *msg)
514 : : {
515 : : const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
516 : 0 : struct rpcbind_args *map = msg->rpc_argp;
517 : 0 : unsigned short port = ntohs(sin6->sin6_port);
518 : : bool is_set = false;
519 : : int result;
520 : :
521 : 0 : map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
522 : :
523 : : dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
524 : : "local rpcbind\n", (port ? "" : "un"),
525 : : map->r_prog, map->r_vers,
526 : : map->r_addr, map->r_netid);
527 : :
528 : 0 : msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
529 [ # # ]: 0 : if (port != 0) {
530 : 0 : msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
531 : : is_set = true;
532 : : }
533 : :
534 : 0 : result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
535 : 0 : kfree(map->r_addr);
536 : 0 : return result;
537 : : }
538 : :
539 : : static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn,
540 : : struct rpc_message *msg)
541 : : {
542 : 0 : struct rpcbind_args *map = msg->rpc_argp;
543 : :
544 : : dprintk("RPC: unregistering [%u, %u, '%s'] with "
545 : : "local rpcbind\n",
546 : : map->r_prog, map->r_vers, map->r_netid);
547 : :
548 : 0 : map->r_addr = "";
549 : 0 : msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
550 : :
551 : 0 : return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false);
552 : : }
553 : :
554 : : /**
555 : : * rpcb_v4_register - set or unset a port registration with the local rpcbind
556 : : * @net: target network namespace
557 : : * @program: RPC program number of service to (un)register
558 : : * @version: RPC version number of service to (un)register
559 : : * @address: address family, IP address, and port to (un)register
560 : : * @netid: netid of transport protocol to (un)register
561 : : *
562 : : * Returns zero if the registration request was dispatched successfully
563 : : * and the rpcbind daemon returned success. Otherwise, returns an errno
564 : : * value that reflects the nature of the error (request could not be
565 : : * dispatched, timed out, or rpcbind returned an error).
566 : : *
567 : : * RPC services invoke this function to advertise their contact
568 : : * information via the system's rpcbind daemon. RPC services
569 : : * invoke this function once for each [program, version, address,
570 : : * netid] tuple they wish to advertise.
571 : : *
572 : : * Callers may also unregister RPC services that are registered at a
573 : : * specific address by setting the port number in @address to zero.
574 : : * They may unregister all registered protocol families at once for
575 : : * a service by passing a NULL @address argument. If @netid is ""
576 : : * then all netids for [program, version, address] are unregistered.
577 : : *
578 : : * This function uses rpcbind protocol version 4 to contact the
579 : : * local rpcbind daemon. The local rpcbind daemon must support
580 : : * version 4 of the rpcbind protocol in order for these functions
581 : : * to register a service successfully.
582 : : *
583 : : * Supported netids include "udp" and "tcp" for UDP and TCP over
584 : : * IPv4, and "udp6" and "tcp6" for UDP and TCP over IPv6,
585 : : * respectively.
586 : : *
587 : : * The contents of @address determine the address family and the
588 : : * port to be registered. The usual practice is to pass INADDR_ANY
589 : : * as the raw address, but specifying a non-zero address is also
590 : : * supported by this API if the caller wishes to advertise an RPC
591 : : * service on a specific network interface.
592 : : *
593 : : * Note that passing in INADDR_ANY does not create the same service
594 : : * registration as IN6ADDR_ANY. The former advertises an RPC
595 : : * service on any IPv4 address, but not on IPv6. The latter
596 : : * advertises the service on all IPv4 and IPv6 addresses.
597 : : */
598 : 0 : int rpcb_v4_register(struct net *net, const u32 program, const u32 version,
599 : : const struct sockaddr *address, const char *netid)
600 : : {
601 : 0 : struct rpcbind_args map = {
602 : : .r_prog = program,
603 : : .r_vers = version,
604 : : .r_netid = netid,
605 : : .r_owner = RPCB_OWNER_STRING,
606 : : };
607 : 0 : struct rpc_message msg = {
608 : : .rpc_argp = &map,
609 : : };
610 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
611 : :
612 [ # # ]: 0 : if (sn->rpcb_local_clnt4 == NULL)
613 : : return -EPROTONOSUPPORT;
614 : :
615 [ # # ]: 0 : if (address == NULL)
616 : 0 : return rpcb_unregister_all_protofamilies(sn, &msg);
617 : :
618 [ # # # ]: 0 : switch (address->sa_family) {
619 : : case AF_INET:
620 : 0 : return rpcb_register_inet4(sn, address, &msg);
621 : : case AF_INET6:
622 : 0 : return rpcb_register_inet6(sn, address, &msg);
623 : : }
624 : :
625 : : return -EAFNOSUPPORT;
626 : : }
627 : :
628 : 0 : static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt,
629 : : struct rpcbind_args *map, const struct rpc_procinfo *proc)
630 : : {
631 : 0 : struct rpc_message msg = {
632 : : .rpc_proc = proc,
633 : : .rpc_argp = map,
634 : : .rpc_resp = map,
635 : : };
636 : 0 : struct rpc_task_setup task_setup_data = {
637 : : .rpc_client = rpcb_clnt,
638 : : .rpc_message = &msg,
639 : : .callback_ops = &rpcb_getport_ops,
640 : : .callback_data = map,
641 : : .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN,
642 : : };
643 : :
644 : 0 : return rpc_run_task(&task_setup_data);
645 : : }
646 : :
647 : : /*
648 : : * In the case where rpc clients have been cloned, we want to make
649 : : * sure that we use the program number/version etc of the actual
650 : : * owner of the xprt. To do so, we walk back up the tree of parents
651 : : * to find whoever created the transport and/or whoever has the
652 : : * autobind flag set.
653 : : */
654 : : static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
655 : : {
656 : 0 : struct rpc_clnt *parent = clnt->cl_parent;
657 : 0 : struct rpc_xprt_switch *xps = rcu_access_pointer(clnt->cl_xpi.xpi_xpswitch);
658 : :
659 [ # # ]: 0 : while (parent != clnt) {
660 [ # # ]: 0 : if (rcu_access_pointer(parent->cl_xpi.xpi_xpswitch) != xps)
661 : : break;
662 [ # # ]: 0 : if (clnt->cl_autobind)
663 : : break;
664 : : clnt = parent;
665 : 0 : parent = parent->cl_parent;
666 : : }
667 : 0 : return clnt;
668 : : }
669 : :
670 : : /**
671 : : * rpcb_getport_async - obtain the port for a given RPC service on a given host
672 : : * @task: task that is waiting for portmapper request
673 : : *
674 : : * This one can be called for an ongoing RPC request, and can be used in
675 : : * an async (rpciod) context.
676 : : */
677 : 0 : void rpcb_getport_async(struct rpc_task *task)
678 : : {
679 : : struct rpc_clnt *clnt;
680 : : const struct rpc_procinfo *proc;
681 : : u32 bind_version;
682 : : struct rpc_xprt *xprt;
683 : : struct rpc_clnt *rpcb_clnt;
684 : : struct rpcbind_args *map;
685 : : struct rpc_task *child;
686 : : struct sockaddr_storage addr;
687 : : struct sockaddr *sap = (struct sockaddr *)&addr;
688 : : size_t salen;
689 : : int status;
690 : :
691 : : rcu_read_lock();
692 : 0 : clnt = rpcb_find_transport_owner(task->tk_client);
693 : : rcu_read_unlock();
694 : 0 : xprt = xprt_get(task->tk_xprt);
695 : :
696 : : dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
697 : : task->tk_pid, __func__,
698 : : xprt->servername, clnt->cl_prog, clnt->cl_vers, xprt->prot);
699 : :
700 : : /* Put self on the wait queue to ensure we get notified if
701 : : * some other task is already attempting to bind the port */
702 : 0 : rpc_sleep_on_timeout(&xprt->binding, task,
703 : 0 : NULL, jiffies + xprt->bind_timeout);
704 : :
705 [ # # ]: 0 : if (xprt_test_and_set_binding(xprt)) {
706 : : dprintk("RPC: %5u %s: waiting for another binder\n",
707 : : task->tk_pid, __func__);
708 : 0 : xprt_put(xprt);
709 : 0 : return;
710 : : }
711 : :
712 : : /* Someone else may have bound if we slept */
713 [ # # ]: 0 : if (xprt_bound(xprt)) {
714 : : status = 0;
715 : : dprintk("RPC: %5u %s: already bound\n",
716 : : task->tk_pid, __func__);
717 : : goto bailout_nofree;
718 : : }
719 : :
720 : : /* Parent transport's destination address */
721 : 0 : salen = rpc_peeraddr(clnt, sap, sizeof(addr));
722 : :
723 : : /* Don't ever use rpcbind v2 for AF_INET6 requests */
724 [ # # # ]: 0 : switch (sap->sa_family) {
725 : : case AF_INET:
726 : 0 : proc = rpcb_next_version[xprt->bind_index].rpc_proc;
727 : 0 : bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
728 : 0 : break;
729 : : case AF_INET6:
730 : 0 : proc = rpcb_next_version6[xprt->bind_index].rpc_proc;
731 : 0 : bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers;
732 : 0 : break;
733 : : default:
734 : : status = -EAFNOSUPPORT;
735 : : dprintk("RPC: %5u %s: bad address family\n",
736 : : task->tk_pid, __func__);
737 : : goto bailout_nofree;
738 : : }
739 [ # # ]: 0 : if (proc == NULL) {
740 : 0 : xprt->bind_index = 0;
741 : : status = -EPFNOSUPPORT;
742 : : dprintk("RPC: %5u %s: no more getport versions available\n",
743 : : task->tk_pid, __func__);
744 : 0 : goto bailout_nofree;
745 : : }
746 : :
747 : : dprintk("RPC: %5u %s: trying rpcbind version %u\n",
748 : : task->tk_pid, __func__, bind_version);
749 : :
750 : 0 : rpcb_clnt = rpcb_create(xprt->xprt_net,
751 : 0 : clnt->cl_nodename,
752 : : xprt->servername, sap, salen,
753 : : xprt->prot, bind_version,
754 : : clnt->cl_cred);
755 [ # # ]: 0 : if (IS_ERR(rpcb_clnt)) {
756 : : status = PTR_ERR(rpcb_clnt);
757 : : dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
758 : : task->tk_pid, __func__, PTR_ERR(rpcb_clnt));
759 : 0 : goto bailout_nofree;
760 : : }
761 : :
762 : 0 : map = kzalloc(sizeof(struct rpcbind_args), GFP_NOFS);
763 [ # # ]: 0 : if (!map) {
764 : : status = -ENOMEM;
765 : : dprintk("RPC: %5u %s: no memory available\n",
766 : : task->tk_pid, __func__);
767 : : goto bailout_release_client;
768 : : }
769 : 0 : map->r_prog = clnt->cl_prog;
770 : 0 : map->r_vers = clnt->cl_vers;
771 : 0 : map->r_prot = xprt->prot;
772 : 0 : map->r_port = 0;
773 : 0 : map->r_xprt = xprt;
774 : 0 : map->r_status = -EIO;
775 : :
776 [ # # # ]: 0 : switch (bind_version) {
777 : : case RPCBVERS_4:
778 : : case RPCBVERS_3:
779 : 0 : map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID];
780 : 0 : map->r_addr = rpc_sockaddr2uaddr(sap, GFP_NOFS);
781 [ # # ]: 0 : if (!map->r_addr) {
782 : : status = -ENOMEM;
783 : : dprintk("RPC: %5u %s: no memory available\n",
784 : : task->tk_pid, __func__);
785 : : goto bailout_free_args;
786 : : }
787 : 0 : map->r_owner = "";
788 : 0 : break;
789 : : case RPCBVERS_2:
790 : 0 : map->r_addr = NULL;
791 : 0 : break;
792 : : default:
793 : 0 : BUG();
794 : : }
795 : :
796 : 0 : child = rpcb_call_async(rpcb_clnt, map, proc);
797 : 0 : rpc_release_client(rpcb_clnt);
798 [ # # ]: 0 : if (IS_ERR(child)) {
799 : : /* rpcb_map_release() has freed the arguments */
800 : : dprintk("RPC: %5u %s: rpc_run_task failed\n",
801 : : task->tk_pid, __func__);
802 : : return;
803 : : }
804 : :
805 : 0 : xprt->stat.bind_count++;
806 : 0 : rpc_put_task(child);
807 : 0 : return;
808 : :
809 : : bailout_free_args:
810 : 0 : kfree(map);
811 : : bailout_release_client:
812 : 0 : rpc_release_client(rpcb_clnt);
813 : : bailout_nofree:
814 : 0 : rpcb_wake_rpcbind_waiters(xprt, status);
815 : 0 : task->tk_status = status;
816 : 0 : xprt_put(xprt);
817 : : }
818 : : EXPORT_SYMBOL_GPL(rpcb_getport_async);
819 : :
820 : : /*
821 : : * Rpcbind child task calls this callback via tk_exit.
822 : : */
823 : 0 : static void rpcb_getport_done(struct rpc_task *child, void *data)
824 : : {
825 : : struct rpcbind_args *map = data;
826 : 0 : struct rpc_xprt *xprt = map->r_xprt;
827 : 0 : int status = child->tk_status;
828 : :
829 : : /* Garbage reply: retry with a lesser rpcbind version */
830 [ # # ]: 0 : if (status == -EIO)
831 : : status = -EPROTONOSUPPORT;
832 : :
833 : : /* rpcbind server doesn't support this rpcbind protocol version */
834 [ # # ]: 0 : if (status == -EPROTONOSUPPORT)
835 : 0 : xprt->bind_index++;
836 : :
837 [ # # ]: 0 : if (status < 0) {
838 : : /* rpcbind server not available on remote host? */
839 : 0 : xprt->ops->set_port(xprt, 0);
840 [ # # ]: 0 : } else if (map->r_port == 0) {
841 : : /* Requested RPC service wasn't registered on remote host */
842 : 0 : xprt->ops->set_port(xprt, 0);
843 : : status = -EACCES;
844 : : } else {
845 : : /* Succeeded */
846 : 0 : xprt->ops->set_port(xprt, map->r_port);
847 : : xprt_set_bound(xprt);
848 : : status = 0;
849 : : }
850 : :
851 : : dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
852 : : child->tk_pid, status, map->r_port);
853 : :
854 : 0 : map->r_status = status;
855 : 0 : }
856 : :
857 : : /*
858 : : * XDR functions for rpcbind
859 : : */
860 : :
861 : 0 : static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr,
862 : : const void *data)
863 : : {
864 : : const struct rpcbind_args *rpcb = data;
865 : : __be32 *p;
866 : :
867 : : dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n",
868 : : req->rq_task->tk_pid,
869 : : req->rq_task->tk_msg.rpc_proc->p_name,
870 : : rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
871 : :
872 : 0 : p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2);
873 : 0 : *p++ = cpu_to_be32(rpcb->r_prog);
874 : 0 : *p++ = cpu_to_be32(rpcb->r_vers);
875 : 0 : *p++ = cpu_to_be32(rpcb->r_prot);
876 : 0 : *p = cpu_to_be32(rpcb->r_port);
877 : 0 : }
878 : :
879 : 0 : static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr,
880 : : void *data)
881 : : {
882 : : struct rpcbind_args *rpcb = data;
883 : : unsigned long port;
884 : : __be32 *p;
885 : :
886 : 0 : rpcb->r_port = 0;
887 : :
888 : 0 : p = xdr_inline_decode(xdr, 4);
889 [ # # ]: 0 : if (unlikely(p == NULL))
890 : : return -EIO;
891 : :
892 : : port = be32_to_cpup(p);
893 : : dprintk("RPC: %5u PMAP_%s result: %lu\n", req->rq_task->tk_pid,
894 : : req->rq_task->tk_msg.rpc_proc->p_name, port);
895 [ # # ]: 0 : if (unlikely(port > USHRT_MAX))
896 : : return -EIO;
897 : :
898 : 0 : rpcb->r_port = port;
899 : 0 : return 0;
900 : : }
901 : :
902 : 0 : static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr,
903 : : void *data)
904 : : {
905 : : unsigned int *boolp = data;
906 : : __be32 *p;
907 : :
908 : 0 : p = xdr_inline_decode(xdr, 4);
909 [ # # ]: 0 : if (unlikely(p == NULL))
910 : : return -EIO;
911 : :
912 : 0 : *boolp = 0;
913 [ # # ]: 0 : if (*p != xdr_zero)
914 : 0 : *boolp = 1;
915 : :
916 : : dprintk("RPC: %5u RPCB_%s call %s\n",
917 : : req->rq_task->tk_pid,
918 : : req->rq_task->tk_msg.rpc_proc->p_name,
919 : : (*boolp ? "succeeded" : "failed"));
920 : : return 0;
921 : : }
922 : :
923 : 0 : static void encode_rpcb_string(struct xdr_stream *xdr, const char *string,
924 : : const u32 maxstrlen)
925 : : {
926 : : __be32 *p;
927 : : u32 len;
928 : :
929 : 0 : len = strlen(string);
930 [ # # # # ]: 0 : WARN_ON_ONCE(len > maxstrlen);
931 [ # # ]: 0 : if (len > maxstrlen)
932 : : /* truncate and hope for the best */
933 : : len = maxstrlen;
934 : 0 : p = xdr_reserve_space(xdr, 4 + len);
935 : 0 : xdr_encode_opaque(p, string, len);
936 : 0 : }
937 : :
938 : 0 : static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
939 : : const void *data)
940 : : {
941 : : const struct rpcbind_args *rpcb = data;
942 : : __be32 *p;
943 : :
944 : : dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n",
945 : : req->rq_task->tk_pid,
946 : : req->rq_task->tk_msg.rpc_proc->p_name,
947 : : rpcb->r_prog, rpcb->r_vers,
948 : : rpcb->r_netid, rpcb->r_addr);
949 : :
950 : 0 : p = xdr_reserve_space(xdr, (RPCB_program_sz + RPCB_version_sz) << 2);
951 : 0 : *p++ = cpu_to_be32(rpcb->r_prog);
952 : 0 : *p = cpu_to_be32(rpcb->r_vers);
953 : :
954 : 0 : encode_rpcb_string(xdr, rpcb->r_netid, RPCBIND_MAXNETIDLEN);
955 : 0 : encode_rpcb_string(xdr, rpcb->r_addr, RPCBIND_MAXUADDRLEN);
956 : 0 : encode_rpcb_string(xdr, rpcb->r_owner, RPCB_MAXOWNERLEN);
957 : 0 : }
958 : :
959 : 0 : static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
960 : : void *data)
961 : : {
962 : : struct rpcbind_args *rpcb = data;
963 : : struct sockaddr_storage address;
964 : : struct sockaddr *sap = (struct sockaddr *)&address;
965 : : __be32 *p;
966 : : u32 len;
967 : :
968 : 0 : rpcb->r_port = 0;
969 : :
970 : 0 : p = xdr_inline_decode(xdr, 4);
971 [ # # ]: 0 : if (unlikely(p == NULL))
972 : : goto out_fail;
973 : : len = be32_to_cpup(p);
974 : :
975 : : /*
976 : : * If the returned universal address is a null string,
977 : : * the requested RPC service was not registered.
978 : : */
979 [ # # ]: 0 : if (len == 0) {
980 : : dprintk("RPC: %5u RPCB reply: program not registered\n",
981 : : req->rq_task->tk_pid);
982 : : return 0;
983 : : }
984 : :
985 [ # # ]: 0 : if (unlikely(len > RPCBIND_MAXUADDRLEN))
986 : : goto out_fail;
987 : :
988 : 0 : p = xdr_inline_decode(xdr, len);
989 [ # # ]: 0 : if (unlikely(p == NULL))
990 : : goto out_fail;
991 : : dprintk("RPC: %5u RPCB_%s reply: %s\n", req->rq_task->tk_pid,
992 : : req->rq_task->tk_msg.rpc_proc->p_name, (char *)p);
993 : :
994 [ # # ]: 0 : if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len,
995 : : sap, sizeof(address)) == 0)
996 : : goto out_fail;
997 : 0 : rpcb->r_port = rpc_get_port(sap);
998 : :
999 : 0 : return 0;
1000 : :
1001 : : out_fail:
1002 : : dprintk("RPC: %5u malformed RPCB_%s reply\n",
1003 : : req->rq_task->tk_pid,
1004 : : req->rq_task->tk_msg.rpc_proc->p_name);
1005 : : return -EIO;
1006 : : }
1007 : :
1008 : : /*
1009 : : * Not all rpcbind procedures described in RFC 1833 are implemented
1010 : : * since the Linux kernel RPC code requires only these.
1011 : : */
1012 : :
1013 : : static const struct rpc_procinfo rpcb_procedures2[] = {
1014 : : [RPCBPROC_SET] = {
1015 : : .p_proc = RPCBPROC_SET,
1016 : : .p_encode = rpcb_enc_mapping,
1017 : : .p_decode = rpcb_dec_set,
1018 : : .p_arglen = RPCB_mappingargs_sz,
1019 : : .p_replen = RPCB_setres_sz,
1020 : : .p_statidx = RPCBPROC_SET,
1021 : : .p_timer = 0,
1022 : : .p_name = "SET",
1023 : : },
1024 : : [RPCBPROC_UNSET] = {
1025 : : .p_proc = RPCBPROC_UNSET,
1026 : : .p_encode = rpcb_enc_mapping,
1027 : : .p_decode = rpcb_dec_set,
1028 : : .p_arglen = RPCB_mappingargs_sz,
1029 : : .p_replen = RPCB_setres_sz,
1030 : : .p_statidx = RPCBPROC_UNSET,
1031 : : .p_timer = 0,
1032 : : .p_name = "UNSET",
1033 : : },
1034 : : [RPCBPROC_GETPORT] = {
1035 : : .p_proc = RPCBPROC_GETPORT,
1036 : : .p_encode = rpcb_enc_mapping,
1037 : : .p_decode = rpcb_dec_getport,
1038 : : .p_arglen = RPCB_mappingargs_sz,
1039 : : .p_replen = RPCB_getportres_sz,
1040 : : .p_statidx = RPCBPROC_GETPORT,
1041 : : .p_timer = 0,
1042 : : .p_name = "GETPORT",
1043 : : },
1044 : : };
1045 : :
1046 : : static const struct rpc_procinfo rpcb_procedures3[] = {
1047 : : [RPCBPROC_SET] = {
1048 : : .p_proc = RPCBPROC_SET,
1049 : : .p_encode = rpcb_enc_getaddr,
1050 : : .p_decode = rpcb_dec_set,
1051 : : .p_arglen = RPCB_getaddrargs_sz,
1052 : : .p_replen = RPCB_setres_sz,
1053 : : .p_statidx = RPCBPROC_SET,
1054 : : .p_timer = 0,
1055 : : .p_name = "SET",
1056 : : },
1057 : : [RPCBPROC_UNSET] = {
1058 : : .p_proc = RPCBPROC_UNSET,
1059 : : .p_encode = rpcb_enc_getaddr,
1060 : : .p_decode = rpcb_dec_set,
1061 : : .p_arglen = RPCB_getaddrargs_sz,
1062 : : .p_replen = RPCB_setres_sz,
1063 : : .p_statidx = RPCBPROC_UNSET,
1064 : : .p_timer = 0,
1065 : : .p_name = "UNSET",
1066 : : },
1067 : : [RPCBPROC_GETADDR] = {
1068 : : .p_proc = RPCBPROC_GETADDR,
1069 : : .p_encode = rpcb_enc_getaddr,
1070 : : .p_decode = rpcb_dec_getaddr,
1071 : : .p_arglen = RPCB_getaddrargs_sz,
1072 : : .p_replen = RPCB_getaddrres_sz,
1073 : : .p_statidx = RPCBPROC_GETADDR,
1074 : : .p_timer = 0,
1075 : : .p_name = "GETADDR",
1076 : : },
1077 : : };
1078 : :
1079 : : static const struct rpc_procinfo rpcb_procedures4[] = {
1080 : : [RPCBPROC_SET] = {
1081 : : .p_proc = RPCBPROC_SET,
1082 : : .p_encode = rpcb_enc_getaddr,
1083 : : .p_decode = rpcb_dec_set,
1084 : : .p_arglen = RPCB_getaddrargs_sz,
1085 : : .p_replen = RPCB_setres_sz,
1086 : : .p_statidx = RPCBPROC_SET,
1087 : : .p_timer = 0,
1088 : : .p_name = "SET",
1089 : : },
1090 : : [RPCBPROC_UNSET] = {
1091 : : .p_proc = RPCBPROC_UNSET,
1092 : : .p_encode = rpcb_enc_getaddr,
1093 : : .p_decode = rpcb_dec_set,
1094 : : .p_arglen = RPCB_getaddrargs_sz,
1095 : : .p_replen = RPCB_setres_sz,
1096 : : .p_statidx = RPCBPROC_UNSET,
1097 : : .p_timer = 0,
1098 : : .p_name = "UNSET",
1099 : : },
1100 : : [RPCBPROC_GETADDR] = {
1101 : : .p_proc = RPCBPROC_GETADDR,
1102 : : .p_encode = rpcb_enc_getaddr,
1103 : : .p_decode = rpcb_dec_getaddr,
1104 : : .p_arglen = RPCB_getaddrargs_sz,
1105 : : .p_replen = RPCB_getaddrres_sz,
1106 : : .p_statidx = RPCBPROC_GETADDR,
1107 : : .p_timer = 0,
1108 : : .p_name = "GETADDR",
1109 : : },
1110 : : };
1111 : :
1112 : : static const struct rpcb_info rpcb_next_version[] = {
1113 : : {
1114 : : .rpc_vers = RPCBVERS_2,
1115 : : .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
1116 : : },
1117 : : {
1118 : : .rpc_proc = NULL,
1119 : : },
1120 : : };
1121 : :
1122 : : static const struct rpcb_info rpcb_next_version6[] = {
1123 : : {
1124 : : .rpc_vers = RPCBVERS_4,
1125 : : .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR],
1126 : : },
1127 : : {
1128 : : .rpc_vers = RPCBVERS_3,
1129 : : .rpc_proc = &rpcb_procedures3[RPCBPROC_GETADDR],
1130 : : },
1131 : : {
1132 : : .rpc_proc = NULL,
1133 : : },
1134 : : };
1135 : :
1136 : : static unsigned int rpcb_version2_counts[ARRAY_SIZE(rpcb_procedures2)];
1137 : : static const struct rpc_version rpcb_version2 = {
1138 : : .number = RPCBVERS_2,
1139 : : .nrprocs = ARRAY_SIZE(rpcb_procedures2),
1140 : : .procs = rpcb_procedures2,
1141 : : .counts = rpcb_version2_counts,
1142 : : };
1143 : :
1144 : : static unsigned int rpcb_version3_counts[ARRAY_SIZE(rpcb_procedures3)];
1145 : : static const struct rpc_version rpcb_version3 = {
1146 : : .number = RPCBVERS_3,
1147 : : .nrprocs = ARRAY_SIZE(rpcb_procedures3),
1148 : : .procs = rpcb_procedures3,
1149 : : .counts = rpcb_version3_counts,
1150 : : };
1151 : :
1152 : : static unsigned int rpcb_version4_counts[ARRAY_SIZE(rpcb_procedures4)];
1153 : : static const struct rpc_version rpcb_version4 = {
1154 : : .number = RPCBVERS_4,
1155 : : .nrprocs = ARRAY_SIZE(rpcb_procedures4),
1156 : : .procs = rpcb_procedures4,
1157 : : .counts = rpcb_version4_counts,
1158 : : };
1159 : :
1160 : : static const struct rpc_version *rpcb_version[] = {
1161 : : NULL,
1162 : : NULL,
1163 : : &rpcb_version2,
1164 : : &rpcb_version3,
1165 : : &rpcb_version4
1166 : : };
1167 : :
1168 : : static struct rpc_stat rpcb_stats;
1169 : :
1170 : : static const struct rpc_program rpcb_program = {
1171 : : .name = "rpcbind",
1172 : : .number = RPCBIND_PROGRAM,
1173 : : .nrvers = ARRAY_SIZE(rpcb_version),
1174 : : .version = rpcb_version,
1175 : : .stats = &rpcb_stats,
1176 : : };
|