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