17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * This file contains the routines that maintain a linked list of known
297c478bd9Sstevel@tonic-gate * program to udp port mappings. There are three static members initialized
307c478bd9Sstevel@tonic-gate * by default, one for the portmapper itself (of course), one for rpcbind,
317c478bd9Sstevel@tonic-gate * and one for nfs. If a program number is not in the list, then routines
327c478bd9Sstevel@tonic-gate * in this file contact the portmapper on the server, and dynamically add
337c478bd9Sstevel@tonic-gate * new members to this list.
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate * This file also contains bpmap_rmtcall() - which lets one get the port
367c478bd9Sstevel@tonic-gate * number AND run the rpc call in one step. Only the server that successfully
377c478bd9Sstevel@tonic-gate * completes the rpc call will return a result.
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate * NOTE: Because we will end up caching the port entries we need
407c478bd9Sstevel@tonic-gate * before the kernel begins running, we can use dynamic allocation here.
417c478bd9Sstevel@tonic-gate * boot_memfree() calls bpmap_memfree() to free up any dynamically
427c478bd9Sstevel@tonic-gate * allocated entries when the boot program has finished its job.
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #include <sys/types.h>
467c478bd9Sstevel@tonic-gate #include <rpc/types.h>
477c478bd9Sstevel@tonic-gate #include <sys/errno.h>
487c478bd9Sstevel@tonic-gate #include <sys/time.h>
497c478bd9Sstevel@tonic-gate #include <sys/socket.h>
507c478bd9Sstevel@tonic-gate #include <net/if.h>
517c478bd9Sstevel@tonic-gate #include <netinet/in.h>
527c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h>
537c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
547c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
557c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
567c478bd9Sstevel@tonic-gate #include "clnt.h"
577c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
587c478bd9Sstevel@tonic-gate #include <rpc/pmap_rmt.h>
597c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
607c478bd9Sstevel@tonic-gate #include "brpc.h"
617c478bd9Sstevel@tonic-gate #include "pmap.h"
627c478bd9Sstevel@tonic-gate #include "nfs_inet.h"
637c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h>
647c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
657c478bd9Sstevel@tonic-gate #include <sys/salib.h>
667c478bd9Sstevel@tonic-gate #include "socket_inet.h"
677c478bd9Sstevel@tonic-gate #include <sys/promif.h>
687c478bd9Sstevel@tonic-gate #include <sys/bootdebug.h>
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate /* portmap structure */
717c478bd9Sstevel@tonic-gate #define PMAP_STATIC (3) /* last statically allocated list entry */
727c478bd9Sstevel@tonic-gate struct pmaplist pre_init[PMAP_STATIC + 1] = {
737c478bd9Sstevel@tonic-gate { {PMAPPROG, PMAPVERS, IPPROTO_UDP, PMAPPORT}, &pre_init[1] },
747c478bd9Sstevel@tonic-gate /* SVR4 rpcbind listens to old portmapper port */
757c478bd9Sstevel@tonic-gate { {RPCBPROG, RPCBVERS, IPPROTO_UDP, PMAPPORT}, &pre_init[2] },
767c478bd9Sstevel@tonic-gate { {NFS_PROGRAM, NFS_VERSION, IPPROTO_UDP, NFS_PORT}, &pre_init[3] },
777c478bd9Sstevel@tonic-gate { {NFS_PROGRAM, NFS_V3, IPPROTO_UDP, NFS_PORT}, NULL }
787c478bd9Sstevel@tonic-gate };
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate struct pmaplist *map_head = &pre_init[0];
817c478bd9Sstevel@tonic-gate struct pmaplist *map_tail = &pre_init[PMAP_STATIC];
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate #define dprintf if (boothowto & RB_DEBUG) printf
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate * bpmap_addport: adds a new entry on to the end of the pmap cache.
877c478bd9Sstevel@tonic-gate * Items are kept in host order.
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate static void
bpmap_addport(rpcprog_t prog,rpcvers_t vers,rpcport_t port)907c478bd9Sstevel@tonic-gate bpmap_addport(rpcprog_t prog, rpcvers_t vers, rpcport_t port)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate struct pmaplist *newp;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /* allocate new pmaplist */
957c478bd9Sstevel@tonic-gate newp = (struct pmaplist *)bkmem_alloc(sizeof (struct pmaplist));
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate if (newp == NULL)
987c478bd9Sstevel@tonic-gate return; /* not fatal here, we'll just throw out the entry */
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate newp->pml_map.pm_prog = prog;
1017c478bd9Sstevel@tonic-gate newp->pml_map.pm_vers = vers;
1027c478bd9Sstevel@tonic-gate newp->pml_map.pm_prot = (rpcprot_t)IPPROTO_UDP;
1037c478bd9Sstevel@tonic-gate newp->pml_map.pm_port = port;
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate map_tail->pml_next = newp;
1067c478bd9Sstevel@tonic-gate newp->pml_next = NULL;
1077c478bd9Sstevel@tonic-gate map_tail = newp;
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate * bpmap_delport: deletes an existing entry from the list. Caution - don't
1127c478bd9Sstevel@tonic-gate * call this function to delete statically allocated entries. Why would
1137c478bd9Sstevel@tonic-gate * you want to, anyway? Only IPPROTO_UDP is supported, of course.
1147c478bd9Sstevel@tonic-gate */
1157c478bd9Sstevel@tonic-gate static void
bpmap_delport(rpcprog_t prog,rpcvers_t vers)1167c478bd9Sstevel@tonic-gate bpmap_delport(rpcprog_t prog, rpcvers_t vers)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate struct pmaplist *tmp, *prev;
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate prev = map_head;
1217c478bd9Sstevel@tonic-gate for (tmp = map_head; tmp != NULL; tmp = tmp->pml_next) {
1227c478bd9Sstevel@tonic-gate if ((tmp->pml_map.pm_prog == prog) &&
1237c478bd9Sstevel@tonic-gate (tmp->pml_map.pm_vers == vers)) {
1247c478bd9Sstevel@tonic-gate if (tmp == map_head)
1257c478bd9Sstevel@tonic-gate map_head = tmp->pml_next; /* new head */
1267c478bd9Sstevel@tonic-gate else if (tmp == map_tail) {
1277c478bd9Sstevel@tonic-gate map_tail = prev; /* new tail */
1287c478bd9Sstevel@tonic-gate map_tail->pml_next = NULL;
1297c478bd9Sstevel@tonic-gate } else {
1307c478bd9Sstevel@tonic-gate /* internal delete */
1317c478bd9Sstevel@tonic-gate prev->pml_next = tmp->pml_next;
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate #ifdef DEBUG
1347c478bd9Sstevel@tonic-gate printf("bpmap_delport: prog: %x, vers: %x\n", prog,
1357c478bd9Sstevel@tonic-gate vers);
1367c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1377c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)tmp, sizeof (struct pmaplist));
1387c478bd9Sstevel@tonic-gate break;
1397c478bd9Sstevel@tonic-gate } else
1407c478bd9Sstevel@tonic-gate prev = tmp;
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate * Modified strtol(3).
1467c478bd9Sstevel@tonic-gate */
1477c478bd9Sstevel@tonic-gate static int
strtoi(char * str,char ** ptr)1487c478bd9Sstevel@tonic-gate strtoi(char *str, char **ptr)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate int c, val;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate for (val = 0, c = *str++; c >= '0' && c <= '9'; c = *str++) {
1537c478bd9Sstevel@tonic-gate val *= 10;
1547c478bd9Sstevel@tonic-gate val += c - '0';
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate *ptr = str;
1577c478bd9Sstevel@tonic-gate return (val);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate * (from dlboot_inet.c) (kernel)
1627c478bd9Sstevel@tonic-gate * Convert a port number from a sockaddr_in expressed
1637c478bd9Sstevel@tonic-gate * in universal address format.
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate static int
uaddr2port(char * addr)1667c478bd9Sstevel@tonic-gate uaddr2port(char *addr)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate int p1, p2;
1697c478bd9Sstevel@tonic-gate char *next;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate * A struct sockaddr_in expressed in universal address
1737c478bd9Sstevel@tonic-gate * format looks like:
1747c478bd9Sstevel@tonic-gate *
1757c478bd9Sstevel@tonic-gate * "IP.IP.IP.IP.PORT[top byte].PORT[bot. byte]"
1767c478bd9Sstevel@tonic-gate *
1777c478bd9Sstevel@tonic-gate * Where each component expresses as a charactor,
1787c478bd9Sstevel@tonic-gate * the corresponding part of the IP address
1797c478bd9Sstevel@tonic-gate * and port number.
1807c478bd9Sstevel@tonic-gate * Thus 127.0.0.1, port 2345 looks like:
1817c478bd9Sstevel@tonic-gate *
1827c478bd9Sstevel@tonic-gate * 49 50 55 46 48 46 48 46 49 46 57 46 52 49
1837c478bd9Sstevel@tonic-gate * 1 2 7 . 0 . 0 . 1 . 9 . 4 1
1847c478bd9Sstevel@tonic-gate *
1857c478bd9Sstevel@tonic-gate * 2345 = 929base16 = 9.32+9 = 9.41
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate (void) strtoi(addr, &next);
1887c478bd9Sstevel@tonic-gate (void) strtoi(next, &next);
1897c478bd9Sstevel@tonic-gate (void) strtoi(next, &next);
1907c478bd9Sstevel@tonic-gate (void) strtoi(next, &next);
1917c478bd9Sstevel@tonic-gate p1 = strtoi(next, &next);
1927c478bd9Sstevel@tonic-gate p2 = strtoi(next, &next);
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate return ((p1 << 8) + p2);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate * Xdr routines used for calling portmapper/rpcbind.
1997c478bd9Sstevel@tonic-gate */
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate bool_t
xdr_pmap(XDR * xdrs,struct pmap * regs)2027c478bd9Sstevel@tonic-gate xdr_pmap(XDR *xdrs, struct pmap *regs)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate if (xdr_rpcprog(xdrs, ®s->pm_prog) &&
2057c478bd9Sstevel@tonic-gate xdr_rpcvers(xdrs, ®s->pm_vers) &&
2067c478bd9Sstevel@tonic-gate xdr_rpcprot(xdrs, ®s->pm_prot))
2077c478bd9Sstevel@tonic-gate return (xdr_rpcprot(xdrs, ®s->pm_port));
2087c478bd9Sstevel@tonic-gate return (FALSE);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate bool_t
xdr_rpcb(XDR * xdrs,RPCB * objp)2127c478bd9Sstevel@tonic-gate xdr_rpcb(XDR *xdrs, RPCB *objp)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate if (!xdr_rpcprog(xdrs, &objp->r_prog))
2157c478bd9Sstevel@tonic-gate return (FALSE);
2167c478bd9Sstevel@tonic-gate if (!xdr_rpcvers(xdrs, &objp->r_vers))
2177c478bd9Sstevel@tonic-gate return (FALSE);
2187c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->r_netid, ~0))
2197c478bd9Sstevel@tonic-gate return (FALSE);
2207c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->r_addr, ~0))
2217c478bd9Sstevel@tonic-gate return (FALSE);
2227c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->r_owner, ~0))
2237c478bd9Sstevel@tonic-gate return (FALSE);
2247c478bd9Sstevel@tonic-gate return (TRUE);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate /*
2287c478bd9Sstevel@tonic-gate * XDR remote call arguments
2297c478bd9Sstevel@tonic-gate * written for XDR_ENCODE direction only
2307c478bd9Sstevel@tonic-gate */
2317c478bd9Sstevel@tonic-gate bool_t
xdr_rmtcall_args(XDR * xdrs,struct rmtcallargs * cap)2327c478bd9Sstevel@tonic-gate xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap)
2337c478bd9Sstevel@tonic-gate {
2347c478bd9Sstevel@tonic-gate uint_t lenposition, argposition, position;
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate if (xdr_rpcprog(xdrs, &(cap->prog)) &&
2377c478bd9Sstevel@tonic-gate xdr_rpcvers(xdrs, &(cap->vers)) &&
2387c478bd9Sstevel@tonic-gate xdr_rpcproc(xdrs, &(cap->proc))) {
2397c478bd9Sstevel@tonic-gate lenposition = XDR_GETPOS(xdrs);
2407c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(cap->arglen)))
2417c478bd9Sstevel@tonic-gate return (FALSE);
2427c478bd9Sstevel@tonic-gate argposition = XDR_GETPOS(xdrs);
2437c478bd9Sstevel@tonic-gate if (!(*(cap->xdr_args))(xdrs, cap->args_ptr))
2447c478bd9Sstevel@tonic-gate return (FALSE);
2457c478bd9Sstevel@tonic-gate position = XDR_GETPOS(xdrs);
2467c478bd9Sstevel@tonic-gate cap->arglen = position - argposition;
247*b531f6d1SToomas Soome (void) XDR_SETPOS(xdrs, lenposition);
2487c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(cap->arglen)))
2497c478bd9Sstevel@tonic-gate return (FALSE);
250*b531f6d1SToomas Soome (void) XDR_SETPOS(xdrs, position);
2517c478bd9Sstevel@tonic-gate return (TRUE);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate return (FALSE);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate /*
2577c478bd9Sstevel@tonic-gate * XDR remote call results
2587c478bd9Sstevel@tonic-gate * written for XDR_DECODE direction only
2597c478bd9Sstevel@tonic-gate */
2607c478bd9Sstevel@tonic-gate bool_t
xdr_rmtcallres(XDR * xdrs,struct rmtcallres * crp)2617c478bd9Sstevel@tonic-gate xdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate caddr_t port_ptr;
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate port_ptr = (caddr_t)crp->port_ptr;
2667c478bd9Sstevel@tonic-gate if (xdr_reference(xdrs, &port_ptr, sizeof (uint_t), xdr_u_int) &&
2677c478bd9Sstevel@tonic-gate xdr_u_int(xdrs, &crp->resultslen)) {
2687c478bd9Sstevel@tonic-gate crp->port_ptr = (rpcport_t *)port_ptr;
2697c478bd9Sstevel@tonic-gate return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate return (FALSE);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate * XDR remote call arguments
2767c478bd9Sstevel@tonic-gate * written for XDR_ENCODE direction only
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate bool_t
xdr_rpcb_rmtcallargs(XDR * xdrs,struct rpcb_rmtcallargs * objp)2797c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallargs(XDR *xdrs, struct rpcb_rmtcallargs *objp)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate uint_t lenposition, argposition, position;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate if (!xdr_rpcprog(xdrs, &objp->prog))
2847c478bd9Sstevel@tonic-gate return (FALSE);
2857c478bd9Sstevel@tonic-gate if (!xdr_rpcvers(xdrs, &objp->vers))
2867c478bd9Sstevel@tonic-gate return (FALSE);
2877c478bd9Sstevel@tonic-gate if (!xdr_rpcproc(xdrs, &objp->proc))
2887c478bd9Sstevel@tonic-gate return (FALSE);
2897c478bd9Sstevel@tonic-gate /*
2907c478bd9Sstevel@tonic-gate * All the jugglery for just getting the size of the arguments
2917c478bd9Sstevel@tonic-gate */
2927c478bd9Sstevel@tonic-gate lenposition = XDR_GETPOS(xdrs);
2937c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(objp->arglen)))
2947c478bd9Sstevel@tonic-gate return (FALSE);
2957c478bd9Sstevel@tonic-gate argposition = XDR_GETPOS(xdrs);
2967c478bd9Sstevel@tonic-gate if (!(*(objp->xdr_args))(xdrs, objp->args_ptr))
2977c478bd9Sstevel@tonic-gate return (FALSE);
2987c478bd9Sstevel@tonic-gate position = XDR_GETPOS(xdrs);
2997c478bd9Sstevel@tonic-gate objp->arglen = position - argposition;
300*b531f6d1SToomas Soome (void) XDR_SETPOS(xdrs, lenposition);
3017c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(objp->arglen)))
3027c478bd9Sstevel@tonic-gate return (FALSE);
303*b531f6d1SToomas Soome (void) XDR_SETPOS(xdrs, position);
3047c478bd9Sstevel@tonic-gate return (TRUE);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * XDR remote call results
3097c478bd9Sstevel@tonic-gate * written for XDR_DECODE direction only
3107c478bd9Sstevel@tonic-gate */
3117c478bd9Sstevel@tonic-gate bool_t
xdr_rpcb_rmtcallres(XDR * xdrs,struct rpcb_rmtcallres * objp)3127c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallres(XDR *xdrs, struct rpcb_rmtcallres *objp)
3137c478bd9Sstevel@tonic-gate {
3147c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->addr_ptr, ~0))
3157c478bd9Sstevel@tonic-gate return (FALSE);
3167c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &objp->resultslen))
3177c478bd9Sstevel@tonic-gate return (FALSE);
3187c478bd9Sstevel@tonic-gate return ((*(objp->xdr_results))(xdrs, objp->results_ptr));
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate * bpmap_rmtcall: does PMAPPROC_CALLIT broadcasts w/ rpc_call requests.
3237c478bd9Sstevel@tonic-gate * Lets one do a PMAPGETPORT/RPC PROC call in one easy step. sockaddr_in args
3247c478bd9Sstevel@tonic-gate * are taken as network order.
3257c478bd9Sstevel@tonic-gate *
3267c478bd9Sstevel@tonic-gate * Code adapted from bpmap_rmtcall() in dlboot_inet.c (kernel)
3277c478bd9Sstevel@tonic-gate */
3287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3297c478bd9Sstevel@tonic-gate enum clnt_stat
bpmap_rmtcall(rpcprog_t prog,rpcvers_t vers,rpcproc_t proc,xdrproc_t in_xdr,caddr_t args,xdrproc_t out_xdr,caddr_t ret,int rexmit,int wait,struct sockaddr_in * to,struct sockaddr_in * from,uint_t auth)3307c478bd9Sstevel@tonic-gate bpmap_rmtcall(
3317c478bd9Sstevel@tonic-gate rpcprog_t prog, /* rpc program number to call. */
3327c478bd9Sstevel@tonic-gate rpcvers_t vers, /* rpc program version */
3337c478bd9Sstevel@tonic-gate rpcproc_t proc, /* rpc procedure to call */
3347c478bd9Sstevel@tonic-gate xdrproc_t in_xdr, /* routine to serialize arguments */
3357c478bd9Sstevel@tonic-gate caddr_t args, /* arg vector for remote call */
3367c478bd9Sstevel@tonic-gate xdrproc_t out_xdr, /* routine to deserialize results */
3377c478bd9Sstevel@tonic-gate caddr_t ret, /* addr of buf to place results in */
3387c478bd9Sstevel@tonic-gate int rexmit, /* retransmission interval (secs) */
3397c478bd9Sstevel@tonic-gate int wait, /* how long (secs) to wait for a resp */
3407c478bd9Sstevel@tonic-gate struct sockaddr_in *to, /* destination */
3417c478bd9Sstevel@tonic-gate struct sockaddr_in *from, /* filled in w/ responder's port/addr */
3427c478bd9Sstevel@tonic-gate uint_t auth) /* type of authentication wanted. */
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate enum clnt_stat status; /* rpc_call status */
3457c478bd9Sstevel@tonic-gate rpcport_t port = 0; /* returned port # */
3467c478bd9Sstevel@tonic-gate struct rmtcallargs pmap_a; /* args for pmap call */
3477c478bd9Sstevel@tonic-gate struct rmtcallres pmap_r; /* results from pmap call */
3487c478bd9Sstevel@tonic-gate struct rpcb_rmtcallargs rpcb_a; /* args for rpcb call */
3497c478bd9Sstevel@tonic-gate struct rpcb_rmtcallres rpcb_r; /* results from rpcb call */
3507c478bd9Sstevel@tonic-gate char ua[UA_SIZE]; /* universal addr buffer */
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /* initialize pmap */
3537c478bd9Sstevel@tonic-gate pmap_a.prog = prog;
3547c478bd9Sstevel@tonic-gate pmap_a.vers = vers;
3557c478bd9Sstevel@tonic-gate pmap_a.proc = proc;
3567c478bd9Sstevel@tonic-gate pmap_a.args_ptr = args;
3577c478bd9Sstevel@tonic-gate pmap_a.xdr_args = in_xdr;
3587c478bd9Sstevel@tonic-gate pmap_r.port_ptr = &port;
3597c478bd9Sstevel@tonic-gate pmap_r.results_ptr = ret;
3607c478bd9Sstevel@tonic-gate pmap_r.xdr_results = out_xdr;
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate status = brpc_call((rpcprog_t)PMAPPROG, (rpcvers_t)PMAPVERS,
3637c478bd9Sstevel@tonic-gate (rpcproc_t)PMAPPROC_CALLIT, xdr_rmtcall_args, (caddr_t)&pmap_a,
3647c478bd9Sstevel@tonic-gate xdr_rmtcallres, (caddr_t)&pmap_r, rexmit, wait, to, from,
3657c478bd9Sstevel@tonic-gate AUTH_NONE);
3667c478bd9Sstevel@tonic-gate if (status != RPC_PROGUNAVAIL) {
3677c478bd9Sstevel@tonic-gate if (status == RPC_SUCCESS) {
3687c478bd9Sstevel@tonic-gate /* delete old port mapping, if it exists */
3697c478bd9Sstevel@tonic-gate bpmap_delport(prog, vers);
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate /* save the new port mapping */
3727c478bd9Sstevel@tonic-gate bpmap_addport(prog, vers, port);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate return (status);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * PMAP is unavailable. Maybe there's a SVR4 machine, with rpcbind.
3797c478bd9Sstevel@tonic-gate */
3807c478bd9Sstevel@tonic-gate bzero(ua, sizeof (ua));
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate /* initialize rpcb */
3837c478bd9Sstevel@tonic-gate rpcb_a.prog = prog;
3847c478bd9Sstevel@tonic-gate rpcb_a.vers = vers;
3857c478bd9Sstevel@tonic-gate rpcb_a.proc = proc;
3867c478bd9Sstevel@tonic-gate rpcb_a.args_ptr = args;
3877c478bd9Sstevel@tonic-gate rpcb_a.xdr_args = in_xdr;
3887c478bd9Sstevel@tonic-gate rpcb_r.addr_ptr = ua;
3897c478bd9Sstevel@tonic-gate rpcb_r.results_ptr = ret;
3907c478bd9Sstevel@tonic-gate rpcb_r.xdr_results = out_xdr;
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate status = brpc_call((rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS,
3937c478bd9Sstevel@tonic-gate (rpcproc_t)RPCBPROC_CALLIT, xdr_rpcb_rmtcallargs, (caddr_t)&rpcb_a,
3947c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallres, (caddr_t)&rpcb_r, rexmit, wait, to, from,
3957c478bd9Sstevel@tonic-gate AUTH_NONE);
3967c478bd9Sstevel@tonic-gate if (status == RPC_SUCCESS) {
3977c478bd9Sstevel@tonic-gate /* delete old port mapping, if it exists */
3987c478bd9Sstevel@tonic-gate bpmap_delport(prog, vers);
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate /* save the new port mapping */
4017c478bd9Sstevel@tonic-gate port = ntohs(uaddr2port(ua));
4027c478bd9Sstevel@tonic-gate bpmap_addport(prog, vers, port);
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate return (status);
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate * bpmap_getport: Queries current list of cached pmap_list entries,
4097c478bd9Sstevel@tonic-gate * returns the port number of the entry found. If the port number
4107c478bd9Sstevel@tonic-gate * is not cached, then getport makes a rpc call first to the portmapper,
4117c478bd9Sstevel@tonic-gate * and then to rpcbind (SVR4) if the portmapper does not respond. The
4127c478bd9Sstevel@tonic-gate * returned port is then added to the cache, and the port number is
4137c478bd9Sstevel@tonic-gate * returned. If both portmapper and rpc bind fail to give us the necessary
4147c478bd9Sstevel@tonic-gate * port, we return 0 to signal we hit an error, and set rpc_stat to
4157c478bd9Sstevel@tonic-gate * the appropriate RPC error code. Only IPPROTO_UDP protocol is supported.
4167c478bd9Sstevel@tonic-gate *
4177c478bd9Sstevel@tonic-gate * Port and sockaddr_in arguments taken in network order. rpcport_t is returned
4187c478bd9Sstevel@tonic-gate * in host order.
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate rpcport_t
bpmap_getport(rpcprog_t prog,rpcvers_t vers,enum clnt_stat * rpc_stat,struct sockaddr_in * to,struct sockaddr_in * from)4217c478bd9Sstevel@tonic-gate bpmap_getport(rpcprog_t prog, rpcvers_t vers, enum clnt_stat *rpc_stat,
4227c478bd9Sstevel@tonic-gate struct sockaddr_in *to, struct sockaddr_in *from)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate struct pmaplist *walk;
4257c478bd9Sstevel@tonic-gate struct pmap pmap_send; /* portmap */
4267c478bd9Sstevel@tonic-gate in_port_t pmap_port;
4277c478bd9Sstevel@tonic-gate rpcport_t dport;
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate #ifdef DEBUG
4307c478bd9Sstevel@tonic-gate printf("bpmap_getport: called with: prog: %d, vers: %d\n", prog, vers);
4317c478bd9Sstevel@tonic-gate #endif /* DEBUG */
4327c478bd9Sstevel@tonic-gate for (walk = map_head; walk != 0; walk = walk->pml_next) {
4337c478bd9Sstevel@tonic-gate if ((walk->pml_map.pm_prog == prog) &&
4347c478bd9Sstevel@tonic-gate (walk->pml_map.pm_vers == vers) &&
4357c478bd9Sstevel@tonic-gate (walk->pml_map.pm_prot == (rpcprot_t)IPPROTO_UDP)) {
4367c478bd9Sstevel@tonic-gate #ifdef DEBUG
4377c478bd9Sstevel@tonic-gate printf("bpmap_getport: Found in cache. returning: %d\n",
4387c478bd9Sstevel@tonic-gate walk->pml_map.pm_port);
4397c478bd9Sstevel@tonic-gate #endif /* DEBUG */
4407c478bd9Sstevel@tonic-gate return (walk->pml_map.pm_port);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * Not in the cache. First try the portmapper (SunOS server?) and
4467c478bd9Sstevel@tonic-gate * if that fails, try rpcbind (SVR4 server).
4477c478bd9Sstevel@tonic-gate */
4487c478bd9Sstevel@tonic-gate pmap_send.pm_prog = prog;
4497c478bd9Sstevel@tonic-gate pmap_send.pm_vers = vers;
4507c478bd9Sstevel@tonic-gate pmap_send.pm_prot = (rpcprot_t)IPPROTO_UDP;
4517c478bd9Sstevel@tonic-gate pmap_send.pm_port = 0; /* what we're after */
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate *rpc_stat = brpc_call(PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
4547c478bd9Sstevel@tonic-gate xdr_pmap, (caddr_t)&pmap_send, xdr_u_short,
4557c478bd9Sstevel@tonic-gate (caddr_t)&pmap_port, 0, 0, to, from, AUTH_NONE);
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate if (*rpc_stat == RPC_PROGUNAVAIL) {
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate * The portmapper isn't available. Try rpcbind.
4607c478bd9Sstevel@tonic-gate * Maybe the server is a SVR4 server.
4617c478bd9Sstevel@tonic-gate */
4627c478bd9Sstevel@tonic-gate char *ua; /* universal address */
4637c478bd9Sstevel@tonic-gate char ua_buf[UA_SIZE]; /* and its buffer */
4647c478bd9Sstevel@tonic-gate RPCB rpcb_send;
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate rpcb_send.r_prog = prog;
4677c478bd9Sstevel@tonic-gate rpcb_send.r_vers = vers;
4687c478bd9Sstevel@tonic-gate rpcb_send.r_netid = NULL;
4697c478bd9Sstevel@tonic-gate rpcb_send.r_addr = NULL;
4707c478bd9Sstevel@tonic-gate rpcb_send.r_owner = NULL;
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate bzero(ua_buf, UA_SIZE);
4737c478bd9Sstevel@tonic-gate ua = ua_buf;
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate * Again, default # of retries. xdr_wrapstring()
4777c478bd9Sstevel@tonic-gate * wants a char **.
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate *rpc_stat = brpc_call(RPCBPROG, RPCBVERS, RPCBPROC_GETADDR,
4807c478bd9Sstevel@tonic-gate xdr_rpcb, (caddr_t)&rpcb_send, xdr_wrapstring,
4817c478bd9Sstevel@tonic-gate (char *)&ua, 0, 0, to, from, AUTH_NONE);
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate if (*rpc_stat == RPC_SUCCESS) {
4847c478bd9Sstevel@tonic-gate if (ua[0] != '\0')
4857c478bd9Sstevel@tonic-gate dport = ntohs(uaddr2port(ua));
4867c478bd9Sstevel@tonic-gate else
4877c478bd9Sstevel@tonic-gate return (0); /* Address unknown */
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate } else {
4907c478bd9Sstevel@tonic-gate /*
4917c478bd9Sstevel@tonic-gate * Why are rpcport_t's uint32_t? port numbers are uint16_t
4927c478bd9Sstevel@tonic-gate * for ipv4 AND ipv6.... XXXX
4937c478bd9Sstevel@tonic-gate */
4947c478bd9Sstevel@tonic-gate dport = (rpcport_t)pmap_port;
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate if (*rpc_stat != RPC_SUCCESS) {
4987c478bd9Sstevel@tonic-gate dprintf("pmap_getport: Failed getting port.\n");
4997c478bd9Sstevel@tonic-gate return (0); /* we failed. */
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate #ifdef DEBUG
5037c478bd9Sstevel@tonic-gate printf("bpmap_getport: prog: %d, vers: %d; returning port: %d.\n",
5047c478bd9Sstevel@tonic-gate prog, vers, dport);
5057c478bd9Sstevel@tonic-gate #endif /* DEBUG */
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate bpmap_addport(prog, vers, dport);
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate return (dport);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate /*
5137c478bd9Sstevel@tonic-gate * bpmap_memfree: frees up any dynamically allocated entries.
5147c478bd9Sstevel@tonic-gate */
5157c478bd9Sstevel@tonic-gate void
bpmap_memfree(void)5167c478bd9Sstevel@tonic-gate bpmap_memfree(void)
5177c478bd9Sstevel@tonic-gate {
5187c478bd9Sstevel@tonic-gate struct pmaplist *current, *tmp;
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate if (map_tail == &pre_init[PMAP_STATIC])
5217c478bd9Sstevel@tonic-gate return; /* no dynamic entries */
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate /* free from head of the list to the tail. */
5247c478bd9Sstevel@tonic-gate current = pre_init[PMAP_STATIC].pml_next;
5257c478bd9Sstevel@tonic-gate while (current != NULL) {
5267c478bd9Sstevel@tonic-gate tmp = current->pml_next;
5277c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)current, sizeof (struct pmaplist));
5287c478bd9Sstevel@tonic-gate current = tmp;
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate }
531