rpcb_svc_com.c revision 1.19 1 /* $NetBSD: rpcb_svc_com.c,v 1.19 2017/05/03 21:28:00 christos Exp $ */
2
3 /*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
10 *
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 *
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
18 *
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
22 *
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
26 *
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California 94043
30 */
31 /*
32 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
33 */
34
35 /* #ident "@(#)rpcb_svc_com.c 1.18 94/05/02 SMI" */
36
37 /*
38 * rpcb_svc_com.c
39 * The commom server procedure for the rpcbind.
40 */
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <rpc/rpc.h>
47 #include <rpc/rpcb_prot.h>
48 #include <rpc/rpc_com.h>
49 #include <netconfig.h>
50 #include <errno.h>
51 #include <syslog.h>
52 #include <unistd.h>
53 #include <stdio.h>
54 #include <poll.h>
55 #ifdef PORTMAP
56 #include <netinet/in.h>
57 #include <rpc/pmap_prot.h>
58 #endif /* PORTMAP */
59 #include <string.h>
60 #include <stdlib.h>
61
62 #ifdef RPCBIND_RUMP
63 #include <rump/rump.h>
64 #include <rump/rump_syscalls.h>
65 #endif
66
67 #include "rpcbind.h"
68 #include "svc_dg.h"
69 #ifdef RPCBIND_RUMP
70 #include "svc_fdset.h"
71 #endif
72
73 #define RPC_BUF_MAX 65536 /* can be raised if required */
74
75 static char emptystring[] = "";
76 static int rpcb_rmtcalls;
77
78 struct rmtcallfd_list {
79 int fd;
80 SVCXPRT *xprt;
81 char *netid;
82 struct rmtcallfd_list *next;
83 };
84
85 #define NFORWARD 64
86 #define MAXTIME_OFF 300 /* 5 minutes */
87
88 struct finfo {
89 int flag;
90 #define FINFO_ACTIVE 0x1
91 u_int32_t caller_xid;
92 struct netbuf *caller_addr;
93 u_int32_t forward_xid;
94 int forward_fd;
95 char *uaddr;
96 rpcproc_t reply_type;
97 rpcvers_t versnum;
98 time_t time;
99 };
100 static struct finfo FINFO[NFORWARD];
101
102
103 static bool_t xdr_encap_parms(XDR *, struct encap_parms *);
104 static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *);
105 static bool_t xdr_rmtcall_result(XDR *, struct r_rmtcall_args *);
106 static bool_t xdr_opaque_parms(XDR *, struct r_rmtcall_args *);
107 static int find_rmtcallfd_by_netid(char *);
108 static SVCXPRT *find_rmtcallxprt_by_fd(int);
109 static u_int32_t forward_register(u_int32_t, struct netbuf *, int, char *,
110 rpcproc_t, rpcvers_t);
111 static struct finfo *forward_find(u_int32_t);
112 static int free_slot_by_xid(u_int32_t);
113 static int free_slot_by_index(int);
114 static int netbufcmp(struct netbuf *, struct netbuf *);
115 static struct netbuf *netbufdup(struct netbuf *);
116 static void netbuffree(struct netbuf *);
117 static int check_rmtcalls(struct pollfd *, int);
118 static void xprt_set_caller(SVCXPRT *, struct finfo *);
119 static void send_svcsyserr(SVCXPRT *, struct finfo *);
120 static void handle_reply(int, SVCXPRT *);
121 static void find_versions(rpcprog_t, char *, rpcvers_t *, rpcvers_t *);
122 static rpcblist_ptr find_service(rpcprog_t, rpcvers_t, char *);
123 static char *getowner(SVCXPRT *, char *, size_t);
124 static int add_pmaplist(RPCB *);
125 static int del_pmaplist(RPCB *);
126
127 /*
128 * Set a mapping of program, version, netid
129 */
130 /* ARGSUSED */
131 void *
132 rpcbproc_set_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
133 rpcvers_t rpcbversnum)
134 {
135 RPCB *regp = (RPCB *)arg;
136 static bool_t ans;
137 char owner[64];
138
139 #ifdef RPCBIND_DEBUG
140 if (debugging)
141 fprintf(stderr, "RPCB_SET request for (%lu, %lu, %s, %s) : ",
142 (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
143 regp->r_netid, regp->r_addr);
144 #endif
145 ans = map_set(regp, getowner(transp, owner, sizeof owner));
146 #ifdef RPCBIND_DEBUG
147 if (debugging)
148 fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
149 #endif
150 /* XXX: should have used some defined constant here */
151 rpcbs_set(rpcbversnum - 2, ans);
152 return (void *)&ans;
153 }
154
155 bool_t
156 map_set(RPCB *regp, char *owner)
157 {
158 RPCB reg, *a;
159 rpcblist_ptr rbl, fnd;
160
161 reg = *regp;
162 /*
163 * check to see if already used
164 * find_service returns a hit even if
165 * the versions don't match, so check for it
166 */
167 fnd = find_service(reg.r_prog, reg.r_vers, reg.r_netid);
168 if (fnd && (fnd->rpcb_map.r_vers == reg.r_vers)) {
169 if (!strcmp(fnd->rpcb_map.r_addr, reg.r_addr))
170 /*
171 * if these match then it is already
172 * registered so just say "OK".
173 */
174 return (TRUE);
175 else
176 return (FALSE);
177 }
178 /*
179 * add to the end of the list
180 */
181 rbl = (rpcblist_ptr) malloc((u_int)sizeof (RPCBLIST));
182 if (rbl == NULL) {
183 return (FALSE);
184 }
185 a = &(rbl->rpcb_map);
186 a->r_prog = reg.r_prog;
187 a->r_vers = reg.r_vers;
188 a->r_netid = strdup(reg.r_netid);
189 a->r_addr = strdup(reg.r_addr);
190 a->r_owner = strdup(owner);
191 if (!a->r_addr || !a->r_netid || !a->r_owner) {
192 if (a->r_netid)
193 free((void *) a->r_netid);
194 if (a->r_addr)
195 free((void *) a->r_addr);
196 if (a->r_owner)
197 free((void *) a->r_owner);
198 free((void *)rbl);
199 return (FALSE);
200 }
201 rbl->rpcb_next = NULL;
202 if (list_rbl == NULL) {
203 list_rbl = rbl;
204 } else {
205 for (fnd = list_rbl; fnd->rpcb_next;
206 fnd = fnd->rpcb_next)
207 ;
208 fnd->rpcb_next = rbl;
209 }
210 #ifdef PORTMAP
211 (void) add_pmaplist(regp);
212 #endif
213 return (TRUE);
214 }
215
216 /*
217 * Unset a mapping of program, version, netid
218 */
219 /* ARGSUSED */
220 void *
221 rpcbproc_unset_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
222 rpcvers_t rpcbversnum)
223 {
224 RPCB *regp = (RPCB *)arg;
225 static bool_t ans;
226 char owner[64];
227
228 #ifdef RPCBIND_DEBUG
229 if (debugging)
230 fprintf(stderr, "RPCB_UNSET request for (%lu, %lu, %s) : ",
231 (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
232 regp->r_netid);
233 #endif
234 ans = map_unset(regp, getowner(transp, owner, sizeof owner));
235 #ifdef RPCBIND_DEBUG
236 if (debugging)
237 fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
238 #endif
239 /* XXX: should have used some defined constant here */
240 rpcbs_unset(rpcbversnum - 2, ans);
241 return (void *)&ans;
242 }
243
244 bool_t
245 map_unset(RPCB *regp, const char *owner)
246 {
247 int ans = 0;
248 rpcblist_ptr rbl, prev, tmp;
249
250 if (owner == NULL)
251 return (0);
252
253 for (prev = NULL, rbl = list_rbl; rbl; /* cstyle */) {
254 if ((rbl->rpcb_map.r_prog != regp->r_prog) ||
255 (rbl->rpcb_map.r_vers != regp->r_vers) ||
256 (regp->r_netid[0] && strcasecmp(regp->r_netid,
257 rbl->rpcb_map.r_netid))) {
258 /* both rbl & prev move forwards */
259 prev = rbl;
260 rbl = rbl->rpcb_next;
261 continue;
262 }
263 /*
264 * Check whether appropriate uid. Unset only
265 * if superuser or the owner itself.
266 */
267 if (strcmp(owner, rpcbind_superuser) &&
268 strcmp(rbl->rpcb_map.r_owner, owner))
269 return (0);
270 /* found it; rbl moves forward, prev stays */
271 ans = 1;
272 tmp = rbl;
273 rbl = rbl->rpcb_next;
274 if (prev == NULL)
275 list_rbl = rbl;
276 else
277 prev->rpcb_next = rbl;
278 free((void *) tmp->rpcb_map.r_addr);
279 free((void *) tmp->rpcb_map.r_netid);
280 free((void *) tmp->rpcb_map.r_owner);
281 free((void *) tmp);
282 }
283 #ifdef PORTMAP
284 if (ans)
285 (void) del_pmaplist(regp);
286 #endif
287 /*
288 * We return 1 either when the entry was not there or it
289 * was able to unset it. It can come to this point only if
290 * atleast one of the conditions is true.
291 */
292 return (1);
293 }
294
295 void
296 delete_prog(rpcprog_t prog)
297 {
298 RPCB reg;
299 rpcblist_ptr rbl;
300
301 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
302 if ((rbl->rpcb_map.r_prog != prog))
303 continue;
304 if (is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr))
305 continue;
306 reg.r_prog = rbl->rpcb_map.r_prog;
307 reg.r_vers = rbl->rpcb_map.r_vers;
308 reg.r_netid = strdup(rbl->rpcb_map.r_netid);
309 (void)map_unset(®, rpcbind_superuser);
310 free(reg.r_netid);
311 }
312 }
313
314 void *
315 rpcbproc_getaddr_com(RPCB *regp, struct svc_req *rqstp, SVCXPRT *transp,
316 rpcvers_t rpcbversnum, rpcvers_t verstype)
317 {
318 static char *uaddr;
319 char *saddr = NULL;
320 rpcblist_ptr fnd;
321
322 if (uaddr && uaddr[0])
323 free((void *) uaddr);
324 fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid);
325 if (fnd && ((verstype == RPCB_ALLVERS) ||
326 (regp->r_vers == fnd->rpcb_map.r_vers))) {
327 if (*(regp->r_addr) != '\0') { /* may contain a hint about */
328 saddr = regp->r_addr; /* the interface that we */
329 } /* should use */
330 if (!(uaddr = mergeaddr(transp, transp->xp_netid,
331 fnd->rpcb_map.r_addr, saddr))) {
332 /* Try whatever we have */
333 uaddr = strdup(fnd->rpcb_map.r_addr);
334 } else if (!uaddr[0]) {
335 /*
336 * The server died. Unset all versions of this prog.
337 */
338 delete_prog(regp->r_prog);
339 uaddr = emptystring;
340 }
341 } else {
342 uaddr = emptystring;
343 }
344 #ifdef RPCBIND_DEBUG
345 if (debugging)
346 fprintf(stderr, "getaddr: %s\n", uaddr);
347 #endif
348 /* XXX: should have used some defined constant here */
349 rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers,
350 transp->xp_netid, uaddr);
351 return (void *)&uaddr;
352 }
353
354 /* ARGSUSED */
355 void *
356 rpcbproc_gettime_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
357 rpcvers_t rpcbversnum)
358 {
359 static time_t curtime;
360
361 (void) time(&curtime);
362 return (void *)&curtime;
363 }
364
365 /*
366 * Convert uaddr to taddr. Should be used only by
367 * local servers/clients. (kernel level stuff only)
368 */
369 /* ARGSUSED */
370 void *
371 rpcbproc_uaddr2taddr_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
372 rpcvers_t rpcbversnum)
373 {
374 char **uaddrp = (char **)arg;
375 struct netconfig *nconf;
376 static struct netbuf nbuf;
377 static struct netbuf *taddr;
378
379 if (taddr) {
380 free((void *) taddr->buf);
381 free((void *) taddr);
382 }
383 if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
384 ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) {
385 (void) memset((char *)&nbuf, 0, sizeof (struct netbuf));
386 return (void *)&nbuf;
387 }
388 return (void *)taddr;
389 }
390
391 /*
392 * Convert taddr to uaddr. Should be used only by
393 * local servers/clients. (kernel level stuff only)
394 */
395 /* ARGSUSED */
396 void *
397 rpcbproc_taddr2uaddr_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
398 rpcvers_t rpcbversnum)
399 {
400 struct netbuf *taddr = (struct netbuf *)arg;
401 static char *uaddr;
402 struct netconfig *nconf;
403
404 #ifdef CHEW_FDS
405 int fd;
406
407 if ((fd = open("/dev/null", O_RDONLY)) == -1) {
408 uaddr = strerror(errno);
409 return (&uaddr);
410 }
411 #endif /* CHEW_FDS */
412 if (uaddr && !uaddr[0])
413 free((void *) uaddr);
414 if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
415 ((uaddr = taddr2uaddr(nconf, taddr)) == NULL)) {
416 uaddr = emptystring;
417 }
418 return (void *)&uaddr;
419 }
420
421
422 static bool_t
423 xdr_encap_parms(XDR *xdrs, struct encap_parms *epp)
424 {
425 return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen),
426 RPC_MAXDATASIZE));
427 }
428
429 /*
430 * XDR remote call arguments. It ignores the address part.
431 * written for XDR_DECODE direction only
432 */
433 static bool_t
434 xdr_rmtcall_args(XDR *xdrs, struct r_rmtcall_args *cap)
435 {
436 /* does not get the address or the arguments */
437 if (xdr_u_int32_t(xdrs, &(cap->rmt_prog)) &&
438 xdr_u_int32_t(xdrs, &(cap->rmt_vers)) &&
439 xdr_u_int32_t(xdrs, &(cap->rmt_proc))) {
440 return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
441 }
442 return (FALSE);
443 }
444
445 /*
446 * XDR remote call results along with the address. Ignore
447 * program number, version number and proc number.
448 * Written for XDR_ENCODE direction only.
449 */
450 static bool_t
451 xdr_rmtcall_result(XDR *xdrs, struct r_rmtcall_args *cap)
452 {
453 bool_t result;
454
455 #ifdef PORTMAP
456 if (cap->rmt_localvers == PMAPVERS) {
457 int h1, h2, h3, h4, p1, p2;
458 u_long port;
459
460 /* interpret the universal address for TCP/IP */
461 if (sscanf(cap->rmt_uaddr, "%d.%d.%d.%d.%d.%d",
462 &h1, &h2, &h3, &h4, &p1, &p2) != 6)
463 return (FALSE);
464 port = ((p1 & 0xff) << 8) + (p2 & 0xff);
465 result = xdr_u_long(xdrs, &port);
466 } else
467 #endif
468 if ((cap->rmt_localvers == RPCBVERS) ||
469 (cap->rmt_localvers == RPCBVERS4)) {
470 result = xdr_wrapstring(xdrs, &(cap->rmt_uaddr));
471 } else {
472 return (FALSE);
473 }
474 if (result == TRUE)
475 return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
476 return (FALSE);
477 }
478
479 /*
480 * only worries about the struct encap_parms part of struct r_rmtcall_args.
481 * The arglen must already be set!!
482 */
483 static bool_t
484 xdr_opaque_parms(XDR *xdrs, struct r_rmtcall_args *cap)
485 {
486 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
487 }
488
489 static struct rmtcallfd_list *rmthead;
490 static struct rmtcallfd_list *rmttail;
491
492 int
493 create_rmtcall_fd(struct netconfig *nconf)
494 {
495 int fd;
496 struct rmtcallfd_list *rmt;
497 SVCXPRT *xprt;
498
499 if ((fd = __rpc_nconf2fd(nconf)) == -1) {
500 if (debugging)
501 fprintf(stderr,
502 "create_rmtcall_fd: couldn't open \"%s\" (errno %d)\n",
503 nconf->nc_device, errno);
504 return (-1);
505 }
506 xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0);
507 if (xprt == NULL) {
508 if (debugging)
509 fprintf(stderr,
510 "create_rmtcall_fd: svc_tli_create failed\n");
511 return (-1);
512 }
513 rmt = (struct rmtcallfd_list *)malloc((u_int)
514 sizeof (struct rmtcallfd_list));
515 if (rmt == NULL) {
516 syslog(LOG_ERR, "create_rmtcall_fd: no memory!");
517 return (-1);
518 }
519 rmt->xprt = xprt;
520 rmt->netid = strdup(nconf->nc_netid);
521 xprt->xp_netid = rmt->netid;
522 rmt->fd = fd;
523 rmt->next = NULL;
524 if (rmthead == NULL) {
525 rmthead = rmt;
526 rmttail = rmt;
527 } else {
528 rmttail->next = rmt;
529 rmttail = rmt;
530 }
531 svc_fdset_set(fd);
532 return (fd);
533 }
534
535 static int
536 find_rmtcallfd_by_netid(char *netid)
537 {
538 struct rmtcallfd_list *rmt;
539
540 for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
541 if (strcmp(netid, rmt->netid) == 0) {
542 return (rmt->fd);
543 }
544 }
545 return (-1);
546 }
547
548 static SVCXPRT *
549 find_rmtcallxprt_by_fd(int fd)
550 {
551 struct rmtcallfd_list *rmt;
552
553 for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
554 if (fd == rmt->fd) {
555 return (rmt->xprt);
556 }
557 }
558 return (NULL);
559 }
560
561
562 /*
563 * Call a remote procedure service. This procedure is very quiet when things
564 * go wrong. The proc is written to support broadcast rpc. In the broadcast
565 * case, a machine should shut-up instead of complain, lest the requestor be
566 * overrun with complaints at the expense of not hearing a valid reply.
567 * When receiving a request and verifying that the service exists, we
568 *
569 * receive the request
570 *
571 * open a new TLI endpoint on the same transport on which we received
572 * the original request
573 *
574 * remember the original request's XID (which requires knowing the format
575 * of the svc_dg_data structure)
576 *
577 * forward the request, with a new XID, to the requested service,
578 * remembering the XID used to send this request (for later use in
579 * reassociating the answer with the original request), the requestor's
580 * address, the file descriptor on which the forwarded request is
581 * made and the service's address.
582 *
583 * mark the file descriptor on which we anticipate receiving a reply from
584 * the service and one to select for in our private svc_run procedure
585 *
586 * At some time in the future, a reply will be received from the service to
587 * which we forwarded the request. At that time, we detect that the socket
588 * used was for forwarding (by looking through the finfo structures to see
589 * whether the fd corresponds to one of those) and call handle_reply() to
590 *
591 * receive the reply
592 *
593 * bundle the reply, along with the service's universal address
594 *
595 * create a SVCXPRT structure and use a version of svc_sendreply
596 * that allows us to specify the reply XID and destination, send the reply
597 * to the original requestor.
598 */
599
600 void
601 rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp,
602 rpcproc_t reply_type, rpcvers_t versnum)
603 {
604 rpcblist_ptr rbl;
605 struct netconfig *nconf;
606 struct netbuf *caller;
607 struct r_rmtcall_args a;
608 char *buf_alloc = NULL, *outbufp;
609 char *outbuf_alloc = NULL;
610 char buf[RPC_BUF_MAX], outbuf[RPC_BUF_MAX];
611 struct netbuf *na = NULL;
612 struct rpc_msg call_msg;
613 int outlen;
614 u_int sendsz;
615 XDR outxdr;
616 AUTH *auth;
617 int fd = -1;
618 char *uaddr, *m_uaddr, *local_uaddr = NULL;
619 u_int32_t *xidp;
620 struct __rpc_sockinfo si;
621 struct sockaddr *localsa;
622 struct netbuf tbuf;
623
624 if (!__rpc_fd2sockinfo(transp->xp_fd, &si)) {
625 if (reply_type == RPCBPROC_INDIRECT)
626 svcerr_systemerr(transp);
627 return;
628 }
629 if (si.si_socktype != SOCK_DGRAM)
630 return; /* Only datagram type accepted */
631 sendsz = __rpc_get_t_size(si.si_af, si.si_proto, UDPMSGSIZE);
632 if (sendsz == 0) { /* data transfer not supported */
633 if (reply_type == RPCBPROC_INDIRECT)
634 svcerr_systemerr(transp);
635 return;
636 }
637 /*
638 * Should be multiple of 4 for XDR.
639 */
640 sendsz = ((sendsz + 3) / 4) * 4;
641 if (sendsz > RPC_BUF_MAX) {
642 #ifdef notyet
643 buf_alloc = alloca(sendsz); /* not in IDR2? */
644 #else
645 buf_alloc = malloc(sendsz);
646 #endif /* notyet */
647 if (buf_alloc == NULL) {
648 if (debugging)
649 fprintf(stderr,
650 "rpcbproc_callit_com: No Memory!\n");
651 if (reply_type == RPCBPROC_INDIRECT)
652 svcerr_systemerr(transp);
653 return;
654 }
655 a.rmt_args.args = buf_alloc;
656 } else {
657 a.rmt_args.args = buf;
658 }
659
660 call_msg.rm_xid = 0; /* For error checking purposes */
661 if (!svc_getargs(transp, (xdrproc_t) xdr_rmtcall_args, (char *) &a)) {
662 if (reply_type == RPCBPROC_INDIRECT)
663 svcerr_decode(transp);
664 if (debugging)
665 fprintf(stderr,
666 "rpcbproc_callit_com: svc_getargs failed\n");
667 goto error;
668 }
669
670 if (!check_callit(transp, &a, versnum)) {
671 svcerr_weakauth(transp);
672 goto error;
673 }
674
675 caller = svc_getrpccaller(transp);
676 #ifdef RPCBIND_DEBUG
677 if (debugging) {
678 uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller);
679 fprintf(stderr, "%s %s req for (%lu, %lu, %lu, %s) from %s : ",
680 versnum == PMAPVERS ? "pmap_rmtcall" :
681 versnum == RPCBVERS ? "rpcb_rmtcall" :
682 versnum == RPCBVERS4 ? "rpcb_indirect" :
683 rpcbind_unknown,
684 reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit",
685 (unsigned long)a.rmt_prog, (unsigned long)a.rmt_vers,
686 (unsigned long)a.rmt_proc, transp->xp_netid,
687 uaddr ? uaddr : rpcbind_unknown);
688 if (uaddr)
689 free((void *) uaddr);
690 }
691 #endif
692
693 rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid);
694
695 rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers,
696 a.rmt_proc, transp->xp_netid, rbl);
697
698 if (rbl == NULL) {
699 #ifdef RPCBIND_DEBUG
700 if (debugging)
701 fprintf(stderr, "not found\n");
702 #endif
703 if (reply_type == RPCBPROC_INDIRECT)
704 svcerr_noprog(transp);
705 goto error;
706 }
707 if (rbl->rpcb_map.r_vers != a.rmt_vers) {
708 if (reply_type == RPCBPROC_INDIRECT) {
709 rpcvers_t vers_low, vers_high;
710
711 find_versions(a.rmt_prog, transp->xp_netid,
712 &vers_low, &vers_high);
713 svcerr_progvers(transp, vers_low, vers_high);
714 }
715 goto error;
716 }
717
718 #ifdef RPCBIND_DEBUG
719 if (debugging)
720 fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr);
721 #endif
722 /*
723 * Check whether this entry is valid and a server is present
724 * Mergeaddr() returns NULL if no such entry is present, and
725 * returns "" if the entry was present but the server is not
726 * present (i.e., it crashed).
727 */
728 if (reply_type == RPCBPROC_INDIRECT) {
729 uaddr = mergeaddr(transp, transp->xp_netid,
730 rbl->rpcb_map.r_addr, NULL);
731 if ((uaddr == NULL) || uaddr[0] == '\0') {
732 svcerr_noprog(transp);
733 if (uaddr != NULL) {
734 free((void *) uaddr);
735 }
736 goto error;
737 }
738 if (uaddr != NULL) {
739 free((void *) uaddr);
740 }
741 }
742 nconf = rpcbind_get_conf(transp->xp_netid);
743 if (nconf == NULL) {
744 if (reply_type == RPCBPROC_INDIRECT)
745 svcerr_systemerr(transp);
746 if (debugging)
747 fprintf(stderr,
748 "rpcbproc_callit_com: rpcbind_get_conf failed\n");
749 goto error;
750 }
751 localsa = local_sa(((struct sockaddr *)caller->buf)->sa_family);
752 if (localsa == NULL) {
753 if (debugging)
754 fprintf(stderr,
755 "rpcbproc_callit_com: no local address\n");
756 goto error;
757 }
758 tbuf.len = tbuf.maxlen = localsa->sa_len;
759 tbuf.buf = localsa;
760 local_uaddr =
761 addrmerge(&tbuf, rbl->rpcb_map.r_addr, NULL, nconf->nc_netid);
762 m_uaddr = addrmerge(caller, rbl->rpcb_map.r_addr, NULL,
763 nconf->nc_netid);
764 #ifdef RPCBIND_DEBUG
765 if (debugging)
766 fprintf(stderr, "merged uaddr %s\n", m_uaddr);
767 #endif
768 if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) {
769 if (reply_type == RPCBPROC_INDIRECT)
770 svcerr_systemerr(transp);
771 free((void *) m_uaddr);
772 goto error;
773 }
774 xidp = __rpcb_get_dg_xidp(transp);
775 call_msg.rm_xid = forward_register(*xidp,
776 caller, fd, m_uaddr, reply_type, versnum);
777 if (call_msg.rm_xid == 0) {
778 /*
779 * A duplicate request for the slow server. Let's not
780 * beat on it any more.
781 */
782 if (debugging)
783 fprintf(stderr,
784 "rpcbproc_callit_com: duplicate request\n");
785 free((void *) m_uaddr);
786 goto error;
787 } else if (call_msg.rm_xid == (uint32_t)-1) {
788 /* forward_register failed. Perhaps no memory. */
789 if (debugging)
790 fprintf(stderr,
791 "rpcbproc_callit_com: forward_register failed\n");
792 free((void *) m_uaddr);
793 goto error;
794 }
795
796 #ifdef DEBUG_RMTCALL
797 if (debugging)
798 fprintf(stderr,
799 "rpcbproc_callit_com: original XID %x, new XID %x\n",
800 *xidp, call_msg.rm_xid);
801 #endif
802 call_msg.rm_direction = CALL;
803 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
804 call_msg.rm_call.cb_prog = a.rmt_prog;
805 call_msg.rm_call.cb_vers = a.rmt_vers;
806 if (sendsz > RPC_BUF_MAX) {
807 #ifdef notyet
808 outbuf_alloc = alloca(sendsz); /* not in IDR2? */
809 #else
810 outbuf_alloc = malloc(sendsz);
811 #endif /* notyet */
812 if (outbuf_alloc == NULL) {
813 if (reply_type == RPCBPROC_INDIRECT)
814 svcerr_systemerr(transp);
815 if (debugging)
816 fprintf(stderr,
817 "rpcbproc_callit_com: No memory!\n");
818 goto error;
819 }
820 xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE);
821 } else {
822 xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE);
823 }
824 if (!xdr_callhdr(&outxdr, &call_msg)) {
825 if (reply_type == RPCBPROC_INDIRECT)
826 svcerr_systemerr(transp);
827 if (debugging)
828 fprintf(stderr,
829 "rpcbproc_callit_com: xdr_callhdr failed\n");
830 goto error;
831 }
832 if (!xdr_u_int32_t(&outxdr, &(a.rmt_proc))) {
833 if (reply_type == RPCBPROC_INDIRECT)
834 svcerr_systemerr(transp);
835 if (debugging)
836 fprintf(stderr,
837 "rpcbproc_callit_com: xdr_u_long failed\n");
838 goto error;
839 }
840
841 if (rqstp->rq_cred.oa_flavor == AUTH_NULL) {
842 auth = authnone_create();
843 } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
844 struct authunix_parms *au;
845
846 au = (struct authunix_parms *)rqstp->rq_clntcred;
847 auth = authunix_create(au->aup_machname,
848 au->aup_uid, au->aup_gid,
849 au->aup_len, au->aup_gids);
850 if (auth == NULL) /* fall back */
851 auth = authnone_create();
852 } else {
853 /* we do not support any other authentication scheme */
854 if (debugging)
855 fprintf(stderr,
856 "rpcbproc_callit_com: oa_flavor != AUTH_NONE and oa_flavor != AUTH_SYS\n");
857 if (reply_type == RPCBPROC_INDIRECT)
858 svcerr_weakauth(transp); /* XXX too strong.. */
859 goto error;
860 }
861 if (auth == NULL) {
862 if (reply_type == RPCBPROC_INDIRECT)
863 svcerr_systemerr(transp);
864 if (debugging)
865 fprintf(stderr,
866 "rpcbproc_callit_com: authwhatever_create returned NULL\n");
867 goto error;
868 }
869 if (!AUTH_MARSHALL(auth, &outxdr)) {
870 if (reply_type == RPCBPROC_INDIRECT)
871 svcerr_systemerr(transp);
872 AUTH_DESTROY(auth);
873 if (debugging)
874 fprintf(stderr,
875 "rpcbproc_callit_com: AUTH_MARSHALL failed\n");
876 goto error;
877 }
878 AUTH_DESTROY(auth);
879 if (!xdr_opaque_parms(&outxdr, &a)) {
880 if (reply_type == RPCBPROC_INDIRECT)
881 svcerr_systemerr(transp);
882 if (debugging)
883 fprintf(stderr,
884 "rpcbproc_callit_com: xdr_opaque_parms failed\n");
885 goto error;
886 }
887 outlen = (int) XDR_GETPOS(&outxdr);
888 if (outbuf_alloc)
889 outbufp = outbuf_alloc;
890 else
891 outbufp = outbuf;
892
893 na = uaddr2taddr(nconf, local_uaddr);
894 if (!na) {
895 if (reply_type == RPCBPROC_INDIRECT)
896 svcerr_systemerr(transp);
897 goto error;
898 }
899
900 if (sendto(fd, outbufp, outlen, 0, (struct sockaddr *)na->buf, na->len)
901 != outlen) {
902 if (debugging)
903 fprintf(stderr,
904 "rpcbproc_callit_com: sendto failed: errno %d\n", errno);
905 if (reply_type == RPCBPROC_INDIRECT)
906 svcerr_systemerr(transp);
907 goto error;
908 }
909 goto out;
910
911 error:
912 if (call_msg.rm_xid != 0)
913 (void) free_slot_by_xid(call_msg.rm_xid);
914 out:
915 if (local_uaddr)
916 free(local_uaddr);
917 if (buf_alloc)
918 free((void *) buf_alloc);
919 if (outbuf_alloc)
920 free((void *) outbuf_alloc);
921 if (na) {
922 free(na->buf);
923 free(na);
924 }
925 }
926
927 /*
928 * Makes an entry into the FIFO for the given request.
929 * If duplicate request, returns a 0, else returns the xid of its call.
930 */
931 static u_int32_t
932 forward_register(u_int32_t caller_xid, struct netbuf *caller_addr,
933 int forward_fd, char *uaddr, rpcproc_t reply_type,
934 rpcvers_t versnum)
935 {
936 int i;
937 int j = 0;
938 time_t min_time, time_now;
939 static u_int32_t lastxid;
940 int entry = -1;
941
942 min_time = FINFO[0].time;
943 time_now = time((time_t *)0);
944 /* initialization */
945 if (lastxid == 0)
946 lastxid = time_now * NFORWARD;
947
948 /*
949 * Check if it is an duplicate entry. Then,
950 * try to find an empty slot. If not available, then
951 * use the slot with the earliest time.
952 */
953 for (i = 0; i < NFORWARD; i++) {
954 if (FINFO[i].flag & FINFO_ACTIVE) {
955 if ((FINFO[i].caller_xid == caller_xid) &&
956 (FINFO[i].reply_type == reply_type) &&
957 (FINFO[i].versnum == versnum) &&
958 (!netbufcmp(FINFO[i].caller_addr,
959 caller_addr))) {
960 FINFO[i].time = time((time_t *)0);
961 return (0); /* Duplicate entry */
962 } else {
963 /* Should we wait any longer */
964 if ((time_now - FINFO[i].time) > MAXTIME_OFF)
965 (void) free_slot_by_index(i);
966 }
967 }
968 if (entry == -1) {
969 if ((FINFO[i].flag & FINFO_ACTIVE) == 0) {
970 entry = i;
971 } else if (FINFO[i].time < min_time) {
972 j = i;
973 min_time = FINFO[i].time;
974 }
975 }
976 }
977 if (entry != -1) {
978 /* use this empty slot */
979 j = entry;
980 } else {
981 (void) free_slot_by_index(j);
982 }
983 if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) {
984 return (-1);
985 }
986 rpcb_rmtcalls++; /* no of pending calls */
987 FINFO[j].flag = FINFO_ACTIVE;
988 FINFO[j].reply_type = reply_type;
989 FINFO[j].versnum = versnum;
990 FINFO[j].time = time_now;
991 FINFO[j].caller_xid = caller_xid;
992 FINFO[j].forward_fd = forward_fd;
993 /*
994 * Though uaddr is not allocated here, it will still be freed
995 * from free_slot_*().
996 */
997 FINFO[j].uaddr = uaddr;
998 lastxid = lastxid + NFORWARD;
999 FINFO[j].forward_xid = lastxid + j; /* encode slot */
1000 return (FINFO[j].forward_xid); /* forward on this xid */
1001 }
1002
1003 static struct finfo *
1004 forward_find(u_int32_t reply_xid)
1005 {
1006 int i;
1007
1008 i = reply_xid % NFORWARD;
1009 if (i < 0)
1010 i += NFORWARD;
1011 if ((FINFO[i].flag & FINFO_ACTIVE) &&
1012 (FINFO[i].forward_xid == reply_xid)) {
1013 return (&FINFO[i]);
1014 }
1015 return (NULL);
1016 }
1017
1018 static int
1019 free_slot_by_xid(u_int32_t xid)
1020 {
1021 int entry;
1022
1023 entry = xid % NFORWARD;
1024 if (entry < 0)
1025 entry += NFORWARD;
1026 return (free_slot_by_index(entry));
1027 }
1028
1029 static int
1030 free_slot_by_index(int idx)
1031 {
1032 struct finfo *fi;
1033
1034 fi = &FINFO[idx];
1035 if (fi->flag & FINFO_ACTIVE) {
1036 netbuffree(fi->caller_addr);
1037 /* XXX may be too big, but can't access xprt array here */
1038 if (fi->forward_fd >= *svc_fdset_getmax())
1039 (*svc_fdset_getmax())--;
1040 free((void *) fi->uaddr);
1041 fi->flag &= ~FINFO_ACTIVE;
1042 rpcb_rmtcalls--;
1043 return (1);
1044 }
1045 return (0);
1046 }
1047
1048 static int
1049 netbufcmp(struct netbuf *n1, struct netbuf *n2)
1050 {
1051 return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len));
1052 }
1053
1054 static struct netbuf *
1055 netbufdup(struct netbuf *ap)
1056 {
1057 struct netbuf *np;
1058
1059 np = (struct netbuf *) malloc(sizeof (struct netbuf) + ap->len);
1060 if (np) {
1061 np->maxlen = np->len = ap->len;
1062 np->buf = ((char *) np) + sizeof (struct netbuf);
1063 (void) memcpy(np->buf, ap->buf, ap->len);
1064 }
1065 return (np);
1066 }
1067
1068 static void
1069 netbuffree(struct netbuf *ap)
1070 {
1071 free((void *) ap);
1072 }
1073
1074
1075 #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)
1076 extern bool_t __svc_clean_idle(fd_set *, int, bool_t);
1077
1078 void
1079 my_svc_run(void)
1080 {
1081 size_t nfds;
1082 struct pollfd *pollfds;
1083 int npollfds;
1084 int poll_ret, check_ret;
1085 int n, *m;
1086 #ifdef SVC_RUN_DEBUG
1087 int i;
1088 #endif
1089 struct pollfd *p;
1090
1091 pollfds = NULL;
1092 npollfds = 0;
1093
1094 for (;;) {
1095 if (svc_fdset_getsize(0) != npollfds) {
1096 npollfds = svc_fdset_getsize(0);
1097 pollfds = realloc(pollfds, npollfds * sizeof(*pollfds));
1098 }
1099 p = pollfds;
1100 if (p == NULL) {
1101 out:
1102 syslog(LOG_ERR, "Cannot allocate pollfds");
1103 sleep(1);
1104 continue;
1105 }
1106 if ((m = svc_fdset_getmax()) == NULL)
1107 goto out;
1108 for (n = 0; n <= *m; n++) {
1109 if (svc_fdset_isset(n)) {
1110 p->fd = n;
1111 p->events = MASKVAL;
1112 p++;
1113 }
1114 }
1115 nfds = p - pollfds;
1116 poll_ret = 0;
1117 #ifdef SVC_RUN_DEBUG
1118 if (debugging) {
1119 fprintf(stderr, "polling for read on fd < ");
1120 for (i = 0, p = pollfds; i < nfds; i++, p++)
1121 if (p->events)
1122 fprintf(stderr, "%d ", p->fd);
1123 fprintf(stderr, ">\n");
1124 }
1125 #endif
1126 #ifdef RPCBIND_RUMP
1127 poll_ret = rump_sys_poll(pollfds, nfds, 30 * 1000);
1128 #else
1129 poll_ret = poll(pollfds, nfds, 30 * 1000);
1130 #endif
1131 switch (poll_ret) {
1132 case -1:
1133 /*
1134 * We ignore all errors, continuing with the assumption
1135 * that it was set by the signal handlers (or any
1136 * other outside event) and not caused by poll().
1137 */
1138 #ifdef SVC_RUN_DEBUG
1139 if (debugging) {
1140 fprintf(stderr, "poll returned %d (%s)\n",
1141 poll_ret, strerror(errno));
1142 }
1143 #endif
1144 case 0:
1145 __svc_clean_idle(NULL, 30, FALSE);
1146 continue;
1147 default:
1148 #ifdef SVC_RUN_DEBUG
1149 if (debugging) {
1150 fprintf(stderr, "poll returned read fds < ");
1151 for (i = 0, p = pollfds; i < nfds; i++, p++)
1152 if (p->revents)
1153 fprintf(stderr, "%d (0x%x)",
1154 p->fd, p->revents);
1155 fprintf(stderr, ">\n");
1156 }
1157 #endif
1158 /*
1159 * If we found as many replies on callback fds
1160 * as the number of descriptors selectable which
1161 * poll() returned, there can be no more so we
1162 * don't call svc_getreq_poll. Otherwise, there
1163 * must be another so we must call svc_getreq_poll.
1164 */
1165 if ((check_ret = check_rmtcalls(pollfds, nfds)) ==
1166 poll_ret)
1167 continue;
1168 svc_getreq_poll(pollfds, poll_ret-check_ret);
1169 }
1170 #ifdef SVC_RUN_DEBUG
1171 if (debugging) {
1172 fprintf(stderr, "svc_maxfd now %u\n",
1173 *svc_fdset_getmax());
1174 }
1175 #endif
1176 }
1177 }
1178
1179 static int
1180 check_rmtcalls(struct pollfd *pfds, int nfds)
1181 {
1182 int j, ncallbacks_found = 0, rmtcalls_pending;
1183 SVCXPRT *xprt;
1184
1185 if (rpcb_rmtcalls == 0)
1186 return (0);
1187
1188 rmtcalls_pending = rpcb_rmtcalls;
1189 for (j = 0; j < nfds; j++) {
1190 if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) {
1191 if (pfds[j].revents) {
1192 ncallbacks_found++;
1193 #ifdef DEBUG_RMTCALL
1194 if (debugging)
1195 fprintf(stderr,
1196 "my_svc_run: polled on forwarding fd %d, netid %s - calling handle_reply\n",
1197 pfds[j].fd, xprt->xp_netid);
1198 #endif
1199 handle_reply(pfds[j].fd, xprt);
1200 pfds[j].revents = 0;
1201 if (ncallbacks_found >= rmtcalls_pending) {
1202 break;
1203 }
1204 }
1205 }
1206 }
1207 return (ncallbacks_found);
1208 }
1209
1210 static void
1211 xprt_set_caller(SVCXPRT *xprt, struct finfo *fi)
1212 {
1213 u_int32_t *xidp;
1214
1215 *(svc_getrpccaller(xprt)) = *(fi->caller_addr);
1216 xidp = __rpcb_get_dg_xidp(xprt);
1217 *xidp = fi->caller_xid;
1218 }
1219
1220 /*
1221 * Call svcerr_systemerr() only if RPCBVERS4
1222 */
1223 static void
1224 send_svcsyserr(SVCXPRT *xprt, struct finfo *fi)
1225 {
1226 if (fi->reply_type == RPCBPROC_INDIRECT) {
1227 xprt_set_caller(xprt, fi);
1228 svcerr_systemerr(xprt);
1229 }
1230 return;
1231 }
1232
1233 static void
1234 handle_reply(int fd, SVCXPRT *xprt)
1235 {
1236 XDR reply_xdrs;
1237 struct rpc_msg reply_msg;
1238 struct rpc_err reply_error;
1239 char *buffer;
1240 struct finfo *fi;
1241 int inlen, pos, len;
1242 struct r_rmtcall_args a;
1243 struct sockaddr_storage ss;
1244 socklen_t fromlen;
1245 #ifdef SVC_RUN_DEBUG
1246 char *uaddr;
1247 #endif
1248
1249 buffer = malloc(RPC_BUF_MAX);
1250 if (buffer == NULL)
1251 goto done;
1252
1253 do {
1254 fromlen = sizeof ss;
1255 inlen = recvfrom(fd, buffer, RPC_BUF_MAX, 0,
1256 (struct sockaddr *)&ss, &fromlen);
1257 } while (inlen < 0 && errno == EINTR);
1258 if (inlen < 0) {
1259 if (debugging)
1260 fprintf(stderr,
1261 "handle_reply: recvfrom returned %d, errno %d\n", inlen, errno);
1262 goto done;
1263 }
1264
1265 reply_msg.acpted_rply.ar_verf = _null_auth;
1266 reply_msg.acpted_rply.ar_results.where = 0;
1267 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
1268
1269 xdrmem_create(&reply_xdrs, buffer, (u_int)inlen, XDR_DECODE);
1270 if (!xdr_replymsg(&reply_xdrs, &reply_msg)) {
1271 if (debugging)
1272 (void) fprintf(stderr,
1273 "handle_reply: xdr_replymsg failed\n");
1274 goto done;
1275 }
1276 fi = forward_find(reply_msg.rm_xid);
1277 #ifdef SVC_RUN_DEBUG
1278 if (debugging) {
1279 fprintf(stderr, "handle_reply: reply xid: %d fi addr: %p\n",
1280 reply_msg.rm_xid, fi);
1281 }
1282 #endif
1283 if (fi == NULL) {
1284 goto done;
1285 }
1286 _seterr_reply(&reply_msg, &reply_error);
1287 if (reply_error.re_status != RPC_SUCCESS) {
1288 if (debugging)
1289 (void) fprintf(stderr, "handle_reply: %s\n",
1290 clnt_sperrno(reply_error.re_status));
1291 send_svcsyserr(xprt, fi);
1292 goto done;
1293 }
1294 pos = XDR_GETPOS(&reply_xdrs);
1295 len = inlen - pos;
1296 a.rmt_args.args = &buffer[pos];
1297 a.rmt_args.arglen = len;
1298 a.rmt_uaddr = fi->uaddr;
1299 a.rmt_localvers = fi->versnum;
1300
1301 xprt_set_caller(xprt, fi);
1302 #ifdef SVC_RUN_DEBUG
1303 uaddr = taddr2uaddr(rpcbind_get_conf("udp"),
1304 svc_getrpccaller(xprt));
1305 if (debugging) {
1306 fprintf(stderr, "handle_reply: forwarding address %s to %s\n",
1307 a.rmt_uaddr, uaddr ? uaddr : rpcbind_unknown);
1308 }
1309 if (uaddr)
1310 free((void *) uaddr);
1311 #endif
1312 svc_sendreply(xprt, (xdrproc_t) xdr_rmtcall_result, (char *) &a);
1313 done:
1314 if (buffer)
1315 free(buffer);
1316
1317 if (reply_msg.rm_xid == 0) {
1318 #ifdef SVC_RUN_DEBUG
1319 if (debugging) {
1320 fprintf(stderr, "handle_reply: NULL xid on exit!\n");
1321 }
1322 #endif
1323 } else
1324 (void) free_slot_by_xid(reply_msg.rm_xid);
1325 return;
1326 }
1327
1328 static void
1329 find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp)
1330 {
1331 rpcblist_ptr rbl;
1332 rpcvers_t lowv = 0;
1333 rpcvers_t highv = 0;
1334
1335 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
1336 if ((rbl->rpcb_map.r_prog != prog) ||
1337 ((rbl->rpcb_map.r_netid != NULL) &&
1338 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
1339 continue;
1340 if (lowv == 0) {
1341 highv = rbl->rpcb_map.r_vers;
1342 lowv = highv;
1343 } else if (rbl->rpcb_map.r_vers < lowv) {
1344 lowv = rbl->rpcb_map.r_vers;
1345 } else if (rbl->rpcb_map.r_vers > highv) {
1346 highv = rbl->rpcb_map.r_vers;
1347 }
1348 }
1349 *lowvp = lowv;
1350 *highvp = highv;
1351 return;
1352 }
1353
1354 /*
1355 * returns the item with the given program, version number and netid.
1356 * If that version number is not found, it returns the item with that
1357 * program number, so that address is now returned to the caller. The
1358 * caller when makes a call to this program, version number, the call
1359 * will fail and it will return with PROGVERS_MISMATCH. The user can
1360 * then determine the highest and the lowest version number for this
1361 * program using clnt_geterr() and use those program version numbers.
1362 *
1363 * Returns the RPCBLIST for the given prog, vers and netid
1364 */
1365 static rpcblist_ptr
1366 find_service(rpcprog_t prog, rpcvers_t vers, char *netid)
1367 {
1368 rpcblist_ptr hit = NULL;
1369 rpcblist_ptr rbl;
1370
1371 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
1372 if ((rbl->rpcb_map.r_prog != prog) ||
1373 ((rbl->rpcb_map.r_netid != NULL) &&
1374 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
1375 continue;
1376 hit = rbl;
1377 if (rbl->rpcb_map.r_vers == vers)
1378 break;
1379 }
1380 return (hit);
1381 }
1382
1383 /*
1384 * Copies the name associated with the uid of the caller and returns
1385 * a pointer to it. Similar to getwd().
1386 */
1387 static char *
1388 getowner(SVCXPRT *transp, char *owner, size_t ownersize)
1389 {
1390 struct sockcred *sc;
1391
1392 sc = __svc_getcallercreds(transp);
1393 if (sc == NULL)
1394 strlcpy(owner, rpcbind_unknown, ownersize);
1395 else if (sc->sc_uid == 0)
1396 strlcpy(owner, rpcbind_superuser, ownersize);
1397 else
1398 snprintf(owner, ownersize, "%d", sc->sc_uid);
1399
1400 return owner;
1401 }
1402
1403 #ifdef PORTMAP
1404 /*
1405 * Add this to the pmap list only if it is UDP or TCP.
1406 */
1407 static int
1408 add_pmaplist(RPCB *arg)
1409 {
1410 struct pmap pmap;
1411 struct pmaplist *pml;
1412 int h1, h2, h3, h4, p1, p2;
1413
1414 if (strcmp(arg->r_netid, udptrans) == 0) {
1415 /* It is UDP! */
1416 pmap.pm_prot = IPPROTO_UDP;
1417 } else if (strcmp(arg->r_netid, tcptrans) == 0) {
1418 /* It is TCP */
1419 pmap.pm_prot = IPPROTO_TCP;
1420 } else
1421 /* Not a IP protocol */
1422 return (0);
1423
1424 /* interpret the universal address for TCP/IP */
1425 if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d",
1426 &h1, &h2, &h3, &h4, &p1, &p2) != 6)
1427 return (0);
1428 pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff);
1429 pmap.pm_prog = arg->r_prog;
1430 pmap.pm_vers = arg->r_vers;
1431 /*
1432 * add to END of list
1433 */
1434 pml = (struct pmaplist *) malloc((u_int)sizeof (struct pmaplist));
1435 if (pml == NULL) {
1436 (void) syslog(LOG_ERR, "rpcbind: no memory!\n");
1437 return (1);
1438 }
1439 pml->pml_map = pmap;
1440 pml->pml_next = NULL;
1441 if (list_pml == NULL) {
1442 list_pml = pml;
1443 } else {
1444 struct pmaplist *fnd;
1445
1446 /* Attach to the end of the list */
1447 for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next)
1448 ;
1449 fnd->pml_next = pml;
1450 }
1451 return (0);
1452 }
1453
1454 /*
1455 * Delete this from the pmap list only if it is UDP or TCP.
1456 */
1457 static int
1458 del_pmaplist(RPCB *arg)
1459 {
1460 struct pmaplist *pml;
1461 struct pmaplist *prevpml, *fnd;
1462 unsigned long prot;
1463
1464 if (strcmp(arg->r_netid, udptrans) == 0) {
1465 /* It is UDP! */
1466 prot = IPPROTO_UDP;
1467 } else if (strcmp(arg->r_netid, tcptrans) == 0) {
1468 /* It is TCP */
1469 prot = IPPROTO_TCP;
1470 } else if (arg->r_netid[0] == 0) {
1471 prot = 0; /* Remove all occurrences */
1472 } else {
1473 /* Not a IP protocol */
1474 return (0);
1475 }
1476 for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) {
1477 if ((pml->pml_map.pm_prog != arg->r_prog) ||
1478 (pml->pml_map.pm_vers != arg->r_vers) ||
1479 (prot && (pml->pml_map.pm_prot != prot))) {
1480 /* both pml & prevpml move forwards */
1481 prevpml = pml;
1482 pml = pml->pml_next;
1483 continue;
1484 }
1485 /* found it; pml moves forward, prevpml stays */
1486 fnd = pml;
1487 pml = pml->pml_next;
1488 if (prevpml == NULL)
1489 list_pml = pml;
1490 else
1491 prevpml->pml_next = pml;
1492 free((void *) fnd);
1493 }
1494 return (0);
1495 }
1496 #endif /* PORTMAP */
1497