1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/module.h>
16
17#include <linux/types.h>
18#include <linux/socket.h>
19#include <linux/in.h>
20#include <linux/in6.h>
21#include <linux/kernel.h>
22#include <linux/errno.h>
23#include <net/ipv6.h>
24
25#include <linux/sunrpc/clnt.h>
26#include <linux/sunrpc/sched.h>
27#include <linux/sunrpc/xprtsock.h>
28
29#ifdef RPC_DEBUG
30# define RPCDBG_FACILITY RPCDBG_BIND
31#endif
32
33#define RPCBIND_PROGRAM (100000u)
34#define RPCBIND_PORT (111u)
35
36#define RPCBVERS_2 (2u)
37#define RPCBVERS_3 (3u)
38#define RPCBVERS_4 (4u)
39
40enum {
41 RPCBPROC_NULL,
42 RPCBPROC_SET,
43 RPCBPROC_UNSET,
44 RPCBPROC_GETPORT,
45 RPCBPROC_GETADDR = 3,
46 RPCBPROC_DUMP,
47 RPCBPROC_CALLIT,
48 RPCBPROC_BCAST = 5,
49 RPCBPROC_GETTIME,
50 RPCBPROC_UADDR2TADDR,
51 RPCBPROC_TADDR2UADDR,
52 RPCBPROC_GETVERSADDR,
53 RPCBPROC_INDIRECT,
54 RPCBPROC_GETADDRLIST,
55 RPCBPROC_GETSTAT,
56};
57
58#define RPCB_HIGHPROC_2 RPCBPROC_CALLIT
59#define RPCB_HIGHPROC_3 RPCBPROC_TADDR2UADDR
60#define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT
61
62
63
64
65
66
67
68#define RPCB_OWNER_STRING "rpcb"
69#define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING)
70
71static void rpcb_getport_done(struct rpc_task *, void *);
72static void rpcb_map_release(void *data);
73static struct rpc_program rpcb_program;
74
75struct rpcbind_args {
76 struct rpc_xprt * r_xprt;
77
78 u32 r_prog;
79 u32 r_vers;
80 u32 r_prot;
81 unsigned short r_port;
82 const char * r_netid;
83 const char * r_addr;
84 const char * r_owner;
85
86 int r_status;
87};
88
89static struct rpc_procinfo rpcb_procedures2[];
90static struct rpc_procinfo rpcb_procedures3[];
91static struct rpc_procinfo rpcb_procedures4[];
92
93struct rpcb_info {
94 u32 rpc_vers;
95 struct rpc_procinfo * rpc_proc;
96};
97
98static struct rpcb_info rpcb_next_version[];
99static struct rpcb_info rpcb_next_version6[];
100
101static const struct rpc_call_ops rpcb_getport_ops = {
102 .rpc_call_done = rpcb_getport_done,
103 .rpc_release = rpcb_map_release,
104};
105
106static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
107{
108 xprt_clear_binding(xprt);
109 rpc_wake_up_status(&xprt->binding, status);
110}
111
112static void rpcb_map_release(void *data)
113{
114 struct rpcbind_args *map = data;
115
116 rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status);
117 xprt_put(map->r_xprt);
118 kfree(map);
119}
120
121static const struct sockaddr_in rpcb_inaddr_loopback = {
122 .sin_family = AF_INET,
123 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
124 .sin_port = htons(RPCBIND_PORT),
125};
126
127static const struct sockaddr_in6 rpcb_in6addr_loopback = {
128 .sin6_family = AF_INET6,
129 .sin6_addr = IN6ADDR_LOOPBACK_INIT,
130 .sin6_port = htons(RPCBIND_PORT),
131};
132
133static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr,
134 size_t addrlen, u32 version)
135{
136 struct rpc_create_args args = {
137 .protocol = XPRT_TRANSPORT_UDP,
138 .address = addr,
139 .addrsize = addrlen,
140 .servername = "localhost",
141 .program = &rpcb_program,
142 .version = version,
143 .authflavor = RPC_AUTH_UNIX,
144 .flags = RPC_CLNT_CREATE_NOPING,
145 };
146
147 return rpc_create(&args);
148}
149
150static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
151 size_t salen, int proto, u32 version)
152{
153 struct rpc_create_args args = {
154 .protocol = proto,
155 .address = srvaddr,
156 .addrsize = salen,
157 .servername = hostname,
158 .program = &rpcb_program,
159 .version = version,
160 .authflavor = RPC_AUTH_UNIX,
161 .flags = (RPC_CLNT_CREATE_NOPING |
162 RPC_CLNT_CREATE_NONPRIVPORT),
163 };
164
165 switch (srvaddr->sa_family) {
166 case AF_INET:
167 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
168 break;
169 case AF_INET6:
170 ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT);
171 break;
172 default:
173 return NULL;
174 }
175
176 return rpc_create(&args);
177}
178
179static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
180 u32 version, struct rpc_message *msg)
181{
182 struct rpc_clnt *rpcb_clnt;
183 int result, error = 0;
184
185 msg->rpc_resp = &result;
186
187 rpcb_clnt = rpcb_create_local(addr, addrlen, version);
188 if (!IS_ERR(rpcb_clnt)) {
189 error = rpc_call_sync(rpcb_clnt, msg, 0);
190 rpc_shutdown_client(rpcb_clnt);
191 } else
192 error = PTR_ERR(rpcb_clnt);
193
194 if (error < 0) {
195 printk(KERN_WARNING "RPC: failed to contact local rpcbind "
196 "server (errno %d).\n", -error);
197 return error;
198 }
199
200 if (!result)
201 return -EACCES;
202 return 0;
203}
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
238{
239 struct rpcbind_args map = {
240 .r_prog = prog,
241 .r_vers = vers,
242 .r_prot = prot,
243 .r_port = port,
244 };
245 struct rpc_message msg = {
246 .rpc_argp = &map,
247 };
248
249 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
250 "rpcbind\n", (port ? "" : "un"),
251 prog, vers, prot, port);
252
253 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
254 if (port)
255 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
256
257 return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback,
258 sizeof(rpcb_inaddr_loopback),
259 RPCBVERS_2, &msg);
260}
261
262
263
264
265static int rpcb_register_netid4(struct sockaddr_in *address_to_register,
266 struct rpc_message *msg)
267{
268 struct rpcbind_args *map = msg->rpc_argp;
269 unsigned short port = ntohs(address_to_register->sin_port);
270 char buf[32];
271
272
273 snprintf(buf, sizeof(buf),
274 NIPQUAD_FMT".%u.%u",
275 NIPQUAD(address_to_register->sin_addr.s_addr),
276 port >> 8, port & 0xff);
277 map->r_addr = buf;
278
279 dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
280 "local rpcbind\n", (port ? "" : "un"),
281 map->r_prog, map->r_vers,
282 map->r_addr, map->r_netid);
283
284 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
285 if (port)
286 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
287
288 return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback,
289 sizeof(rpcb_inaddr_loopback),
290 RPCBVERS_4, msg);
291}
292
293
294
295
296static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
297 struct rpc_message *msg)
298{
299 struct rpcbind_args *map = msg->rpc_argp;
300 unsigned short port = ntohs(address_to_register->sin6_port);
301 char buf[64];
302
303
304 if (ipv6_addr_any(&address_to_register->sin6_addr))
305 snprintf(buf, sizeof(buf), "::.%u.%u",
306 port >> 8, port & 0xff);
307 else
308 snprintf(buf, sizeof(buf), NIP6_FMT".%u.%u",
309 NIP6(address_to_register->sin6_addr),
310 port >> 8, port & 0xff);
311 map->r_addr = buf;
312
313 dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
314 "local rpcbind\n", (port ? "" : "un"),
315 map->r_prog, map->r_vers,
316 map->r_addr, map->r_netid);
317
318 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
319 if (port)
320 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
321
322 return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback,
323 sizeof(rpcb_in6addr_loopback),
324 RPCBVERS_4, msg);
325}
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369int rpcb_v4_register(const u32 program, const u32 version,
370 const struct sockaddr *address, const char *netid)
371{
372 struct rpcbind_args map = {
373 .r_prog = program,
374 .r_vers = version,
375 .r_netid = netid,
376 .r_owner = RPCB_OWNER_STRING,
377 };
378 struct rpc_message msg = {
379 .rpc_argp = &map,
380 };
381
382 switch (address->sa_family) {
383 case AF_INET:
384 return rpcb_register_netid4((struct sockaddr_in *)address,
385 &msg);
386 case AF_INET6:
387 return rpcb_register_netid6((struct sockaddr_in6 *)address,
388 &msg);
389 }
390
391 return -EAFNOSUPPORT;
392}
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
410{
411 struct rpcbind_args map = {
412 .r_prog = prog,
413 .r_vers = vers,
414 .r_prot = prot,
415 .r_port = 0,
416 };
417 struct rpc_message msg = {
418 .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
419 .rpc_argp = &map,
420 .rpc_resp = &map.r_port,
421 };
422 struct rpc_clnt *rpcb_clnt;
423 int status;
424
425 dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
426 __func__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
427
428 rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
429 sizeof(*sin), prot, RPCBVERS_2);
430 if (IS_ERR(rpcb_clnt))
431 return PTR_ERR(rpcb_clnt);
432
433 status = rpc_call_sync(rpcb_clnt, &msg, 0);
434 rpc_shutdown_client(rpcb_clnt);
435
436 if (status >= 0) {
437 if (map.r_port != 0)
438 return map.r_port;
439 status = -EACCES;
440 }
441 return status;
442}
443EXPORT_SYMBOL_GPL(rpcb_getport_sync);
444
445static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
446{
447 struct rpc_message msg = {
448 .rpc_proc = proc,
449 .rpc_argp = map,
450 .rpc_resp = &map->r_port,
451 };
452 struct rpc_task_setup task_setup_data = {
453 .rpc_client = rpcb_clnt,
454 .rpc_message = &msg,
455 .callback_ops = &rpcb_getport_ops,
456 .callback_data = map,
457 .flags = RPC_TASK_ASYNC,
458 };
459
460 return rpc_run_task(&task_setup_data);
461}
462
463
464
465
466
467
468
469
470static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
471{
472 struct rpc_clnt *parent = clnt->cl_parent;
473
474 while (parent != clnt) {
475 if (parent->cl_xprt != clnt->cl_xprt)
476 break;
477 if (clnt->cl_autobind)
478 break;
479 clnt = parent;
480 parent = parent->cl_parent;
481 }
482 return clnt;
483}
484
485
486
487
488
489
490
491
492void rpcb_getport_async(struct rpc_task *task)
493{
494 struct rpc_clnt *clnt;
495 struct rpc_procinfo *proc;
496 u32 bind_version;
497 struct rpc_xprt *xprt;
498 struct rpc_clnt *rpcb_clnt;
499 static struct rpcbind_args *map;
500 struct rpc_task *child;
501 struct sockaddr_storage addr;
502 struct sockaddr *sap = (struct sockaddr *)&addr;
503 size_t salen;
504 int status;
505
506 clnt = rpcb_find_transport_owner(task->tk_client);
507 xprt = clnt->cl_xprt;
508
509 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
510 task->tk_pid, __func__,
511 clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
512
513
514
515 rpc_sleep_on(&xprt->binding, task, NULL);
516
517 if (xprt_test_and_set_binding(xprt)) {
518 dprintk("RPC: %5u %s: waiting for another binder\n",
519 task->tk_pid, __func__);
520 return;
521 }
522
523
524 if (xprt_bound(xprt)) {
525 status = 0;
526 dprintk("RPC: %5u %s: already bound\n",
527 task->tk_pid, __func__);
528 goto bailout_nofree;
529 }
530
531 salen = rpc_peeraddr(clnt, sap, sizeof(addr));
532
533
534 switch (sap->sa_family) {
535 case AF_INET:
536 proc = rpcb_next_version[xprt->bind_index].rpc_proc;
537 bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
538 break;
539 case AF_INET6:
540 proc = rpcb_next_version6[xprt->bind_index].rpc_proc;
541 bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers;
542 break;
543 default:
544 status = -EAFNOSUPPORT;
545 dprintk("RPC: %5u %s: bad address family\n",
546 task->tk_pid, __func__);
547 goto bailout_nofree;
548 }
549 if (proc == NULL) {
550 xprt->bind_index = 0;
551 status = -EPFNOSUPPORT;
552 dprintk("RPC: %5u %s: no more getport versions available\n",
553 task->tk_pid, __func__);
554 goto bailout_nofree;
555 }
556
557 dprintk("RPC: %5u %s: trying rpcbind version %u\n",
558 task->tk_pid, __func__, bind_version);
559
560 rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot,
561 bind_version);
562 if (IS_ERR(rpcb_clnt)) {
563 status = PTR_ERR(rpcb_clnt);
564 dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
565 task->tk_pid, __func__, PTR_ERR(rpcb_clnt));
566 goto bailout_nofree;
567 }
568
569 map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
570 if (!map) {
571 status = -ENOMEM;
572 dprintk("RPC: %5u %s: no memory available\n",
573 task->tk_pid, __func__);
574 goto bailout_release_client;
575 }
576 map->r_prog = clnt->cl_prog;
577 map->r_vers = clnt->cl_vers;
578 map->r_prot = xprt->prot;
579 map->r_port = 0;
580 map->r_xprt = xprt_get(xprt);
581 map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID);
582 map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
583 map->r_owner = RPCB_OWNER_STRING;
584 map->r_status = -EIO;
585
586 child = rpcb_call_async(rpcb_clnt, map, proc);
587 rpc_release_client(rpcb_clnt);
588 if (IS_ERR(child)) {
589
590 dprintk("RPC: %5u %s: rpc_run_task failed\n",
591 task->tk_pid, __func__);
592 return;
593 }
594
595 xprt->stat.bind_count++;
596 rpc_put_task(child);
597 return;
598
599bailout_release_client:
600 rpc_release_client(rpcb_clnt);
601bailout_nofree:
602 rpcb_wake_rpcbind_waiters(xprt, status);
603 task->tk_status = status;
604}
605EXPORT_SYMBOL_GPL(rpcb_getport_async);
606
607
608
609
610static void rpcb_getport_done(struct rpc_task *child, void *data)
611{
612 struct rpcbind_args *map = data;
613 struct rpc_xprt *xprt = map->r_xprt;
614 int status = child->tk_status;
615
616
617 if (status == -EIO)
618 status = -EPROTONOSUPPORT;
619
620
621 if (status == -EPROTONOSUPPORT)
622 xprt->bind_index++;
623
624 if (status < 0) {
625
626 xprt->ops->set_port(xprt, 0);
627 } else if (map->r_port == 0) {
628
629 xprt->ops->set_port(xprt, 0);
630 status = -EACCES;
631 } else {
632
633 xprt->ops->set_port(xprt, map->r_port);
634 xprt_set_bound(xprt);
635 status = 0;
636 }
637
638 dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
639 child->tk_pid, status, map->r_port);
640
641 map->r_status = status;
642}
643
644
645
646
647
648static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
649 struct rpcbind_args *rpcb)
650{
651 dprintk("RPC: encoding rpcb request (%u, %u, %d, %u)\n",
652 rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
653 *p++ = htonl(rpcb->r_prog);
654 *p++ = htonl(rpcb->r_vers);
655 *p++ = htonl(rpcb->r_prot);
656 *p++ = htonl(rpcb->r_port);
657
658 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
659 return 0;
660}
661
662static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
663 unsigned short *portp)
664{
665 *portp = (unsigned short) ntohl(*p++);
666 dprintk("RPC: rpcb getport result: %u\n",
667 *portp);
668 return 0;
669}
670
671static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
672 unsigned int *boolp)
673{
674 *boolp = (unsigned int) ntohl(*p++);
675 dprintk("RPC: rpcb set/unset call %s\n",
676 (*boolp ? "succeeded" : "failed"));
677 return 0;
678}
679
680static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p,
681 struct rpcbind_args *rpcb)
682{
683 dprintk("RPC: encoding rpcb request (%u, %u, %s)\n",
684 rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
685 *p++ = htonl(rpcb->r_prog);
686 *p++ = htonl(rpcb->r_vers);
687
688 p = xdr_encode_string(p, rpcb->r_netid);
689 p = xdr_encode_string(p, rpcb->r_addr);
690 p = xdr_encode_string(p, rpcb->r_owner);
691
692 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
693
694 return 0;
695}
696
697static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
698 unsigned short *portp)
699{
700 char *addr;
701 u32 addr_len;
702 int c, i, f, first, val;
703
704 *portp = 0;
705 addr_len = ntohl(*p++);
706
707
708
709
710
711 if (addr_len < 11 || addr_len > RPCBIND_MAXUADDRLEN)
712 goto out_err;
713
714
715
716
717
718
719 addr = (char *)p;
720 val = 0;
721 first = 1;
722 f = 1;
723 for (i = addr_len - 1; i > 0; i--) {
724 c = addr[i];
725 if (c >= '0' && c <= '9') {
726 val += (c - '0') * f;
727 f *= 10;
728 } else if (c == '.') {
729 if (first) {
730 *portp = val;
731 val = first = 0;
732 f = 1;
733 } else {
734 *portp |= (val << 8);
735 break;
736 }
737 }
738 }
739
740
741
742
743
744 if (first)
745 goto out_err;
746
747 dprintk("RPC: rpcb_decode_getaddr port=%u\n", *portp);
748 return 0;
749
750out_err:
751 dprintk("RPC: rpcbind server returned malformed reply\n");
752 return -EIO;
753}
754
755#define RPCB_program_sz (1u)
756#define RPCB_version_sz (1u)
757#define RPCB_protocol_sz (1u)
758#define RPCB_port_sz (1u)
759#define RPCB_boolean_sz (1u)
760
761#define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN))
762#define RPCB_addr_sz (1+XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
763#define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN))
764
765#define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \
766 RPCB_protocol_sz+RPCB_port_sz
767#define RPCB_getaddrargs_sz RPCB_program_sz+RPCB_version_sz+ \
768 RPCB_netid_sz+RPCB_addr_sz+ \
769 RPCB_ownerstring_sz
770
771#define RPCB_setres_sz RPCB_boolean_sz
772#define RPCB_getportres_sz RPCB_port_sz
773
774
775
776
777
778#define RPCB_getaddrres_sz RPCB_addr_sz
779
780#define PROC(proc, argtype, restype) \
781 [RPCBPROC_##proc] = { \
782 .p_proc = RPCBPROC_##proc, \
783 .p_encode = (kxdrproc_t) rpcb_encode_##argtype, \
784 .p_decode = (kxdrproc_t) rpcb_decode_##restype, \
785 .p_arglen = RPCB_##argtype##args_sz, \
786 .p_replen = RPCB_##restype##res_sz, \
787 .p_statidx = RPCBPROC_##proc, \
788 .p_timer = 0, \
789 .p_name = #proc, \
790 }
791
792
793
794
795
796static struct rpc_procinfo rpcb_procedures2[] = {
797 PROC(SET, mapping, set),
798 PROC(UNSET, mapping, set),
799 PROC(GETPORT, mapping, getport),
800};
801
802static struct rpc_procinfo rpcb_procedures3[] = {
803 PROC(SET, getaddr, set),
804 PROC(UNSET, getaddr, set),
805 PROC(GETADDR, getaddr, getaddr),
806};
807
808static struct rpc_procinfo rpcb_procedures4[] = {
809 PROC(SET, getaddr, set),
810 PROC(UNSET, getaddr, set),
811 PROC(GETADDR, getaddr, getaddr),
812 PROC(GETVERSADDR, getaddr, getaddr),
813};
814
815static struct rpcb_info rpcb_next_version[] = {
816 {
817 .rpc_vers = RPCBVERS_2,
818 .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
819 },
820 {
821 .rpc_proc = NULL,
822 },
823};
824
825static struct rpcb_info rpcb_next_version6[] = {
826 {
827 .rpc_vers = RPCBVERS_4,
828 .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR],
829 },
830 {
831 .rpc_vers = RPCBVERS_3,
832 .rpc_proc = &rpcb_procedures3[RPCBPROC_GETADDR],
833 },
834 {
835 .rpc_proc = NULL,
836 },
837};
838
839static struct rpc_version rpcb_version2 = {
840 .number = RPCBVERS_2,
841 .nrprocs = RPCB_HIGHPROC_2,
842 .procs = rpcb_procedures2
843};
844
845static struct rpc_version rpcb_version3 = {
846 .number = RPCBVERS_3,
847 .nrprocs = RPCB_HIGHPROC_3,
848 .procs = rpcb_procedures3
849};
850
851static struct rpc_version rpcb_version4 = {
852 .number = RPCBVERS_4,
853 .nrprocs = RPCB_HIGHPROC_4,
854 .procs = rpcb_procedures4
855};
856
857static struct rpc_version *rpcb_version[] = {
858 NULL,
859 NULL,
860 &rpcb_version2,
861 &rpcb_version3,
862 &rpcb_version4
863};
864
865static struct rpc_stat rpcb_stats;
866
867static struct rpc_program rpcb_program = {
868 .name = "rpcbind",
869 .number = RPCBIND_PROGRAM,
870 .nrvers = ARRAY_SIZE(rpcb_version),
871 .version = rpcb_version,
872 .stats = &rpcb_stats,
873};
874