1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file contains the routines that maintain a linked list of known 31*7c478bd9Sstevel@tonic-gate * program to udp port mappings. There are three static members initialized 32*7c478bd9Sstevel@tonic-gate * by default, one for the portmapper itself (of course), one for rpcbind, 33*7c478bd9Sstevel@tonic-gate * and one for nfs. If a program number is not in the list, then routines 34*7c478bd9Sstevel@tonic-gate * in this file contact the portmapper on the server, and dynamically add 35*7c478bd9Sstevel@tonic-gate * new members to this list. 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * This file also contains bpmap_rmtcall() - which lets one get the port 38*7c478bd9Sstevel@tonic-gate * number AND run the rpc call in one step. Only the server that successfully 39*7c478bd9Sstevel@tonic-gate * completes the rpc call will return a result. 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * NOTE: Because we will end up caching the port entries we need 42*7c478bd9Sstevel@tonic-gate * before the kernel begins running, we can use dynamic allocation here. 43*7c478bd9Sstevel@tonic-gate * boot_memfree() calls bpmap_memfree() to free up any dynamically 44*7c478bd9Sstevel@tonic-gate * allocated entries when the boot program has finished its job. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 48*7c478bd9Sstevel@tonic-gate #include <rpc/types.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 52*7c478bd9Sstevel@tonic-gate #include <net/if.h> 53*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 54*7c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h> 55*7c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 56*7c478bd9Sstevel@tonic-gate #include <rpc/auth.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 58*7c478bd9Sstevel@tonic-gate #include "clnt.h" 59*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h> 60*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_rmt.h> 61*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 62*7c478bd9Sstevel@tonic-gate #include "brpc.h" 63*7c478bd9Sstevel@tonic-gate #include "pmap.h" 64*7c478bd9Sstevel@tonic-gate #include "nfs_inet.h" 65*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 66*7c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/salib.h> 68*7c478bd9Sstevel@tonic-gate #include "socket_inet.h" 69*7c478bd9Sstevel@tonic-gate #include <sys/promif.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/bootdebug.h> 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* portmap structure */ 73*7c478bd9Sstevel@tonic-gate #define PMAP_STATIC (3) /* last statically allocated list entry */ 74*7c478bd9Sstevel@tonic-gate struct pmaplist pre_init[PMAP_STATIC + 1] = { 75*7c478bd9Sstevel@tonic-gate { {PMAPPROG, PMAPVERS, IPPROTO_UDP, PMAPPORT}, &pre_init[1] }, 76*7c478bd9Sstevel@tonic-gate /* SVR4 rpcbind listens to old portmapper port */ 77*7c478bd9Sstevel@tonic-gate { {RPCBPROG, RPCBVERS, IPPROTO_UDP, PMAPPORT}, &pre_init[2] }, 78*7c478bd9Sstevel@tonic-gate { {NFS_PROGRAM, NFS_VERSION, IPPROTO_UDP, NFS_PORT}, &pre_init[3] }, 79*7c478bd9Sstevel@tonic-gate { {NFS_PROGRAM, NFS_V3, IPPROTO_UDP, NFS_PORT}, NULL } 80*7c478bd9Sstevel@tonic-gate }; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate struct pmaplist *map_head = &pre_init[0]; 83*7c478bd9Sstevel@tonic-gate struct pmaplist *map_tail = &pre_init[PMAP_STATIC]; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #define dprintf if (boothowto & RB_DEBUG) printf 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * bpmap_addport: adds a new entry on to the end of the pmap cache. 89*7c478bd9Sstevel@tonic-gate * Items are kept in host order. 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate static void 92*7c478bd9Sstevel@tonic-gate bpmap_addport(rpcprog_t prog, rpcvers_t vers, rpcport_t port) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate struct pmaplist *newp; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* allocate new pmaplist */ 97*7c478bd9Sstevel@tonic-gate newp = (struct pmaplist *)bkmem_alloc(sizeof (struct pmaplist)); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate if (newp == NULL) 100*7c478bd9Sstevel@tonic-gate return; /* not fatal here, we'll just throw out the entry */ 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate newp->pml_map.pm_prog = prog; 103*7c478bd9Sstevel@tonic-gate newp->pml_map.pm_vers = vers; 104*7c478bd9Sstevel@tonic-gate newp->pml_map.pm_prot = (rpcprot_t)IPPROTO_UDP; 105*7c478bd9Sstevel@tonic-gate newp->pml_map.pm_port = port; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate map_tail->pml_next = newp; 108*7c478bd9Sstevel@tonic-gate newp->pml_next = NULL; 109*7c478bd9Sstevel@tonic-gate map_tail = newp; 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * bpmap_delport: deletes an existing entry from the list. Caution - don't 114*7c478bd9Sstevel@tonic-gate * call this function to delete statically allocated entries. Why would 115*7c478bd9Sstevel@tonic-gate * you want to, anyway? Only IPPROTO_UDP is supported, of course. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate static void 118*7c478bd9Sstevel@tonic-gate bpmap_delport(rpcprog_t prog, rpcvers_t vers) 119*7c478bd9Sstevel@tonic-gate { 120*7c478bd9Sstevel@tonic-gate struct pmaplist *tmp, *prev; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate prev = map_head; 123*7c478bd9Sstevel@tonic-gate for (tmp = map_head; tmp != NULL; tmp = tmp->pml_next) { 124*7c478bd9Sstevel@tonic-gate if ((tmp->pml_map.pm_prog == prog) && 125*7c478bd9Sstevel@tonic-gate (tmp->pml_map.pm_vers == vers)) { 126*7c478bd9Sstevel@tonic-gate if (tmp == map_head) 127*7c478bd9Sstevel@tonic-gate map_head = tmp->pml_next; /* new head */ 128*7c478bd9Sstevel@tonic-gate else if (tmp == map_tail) { 129*7c478bd9Sstevel@tonic-gate map_tail = prev; /* new tail */ 130*7c478bd9Sstevel@tonic-gate map_tail->pml_next = NULL; 131*7c478bd9Sstevel@tonic-gate } else { 132*7c478bd9Sstevel@tonic-gate /* internal delete */ 133*7c478bd9Sstevel@tonic-gate prev->pml_next = tmp->pml_next; 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 136*7c478bd9Sstevel@tonic-gate printf("bpmap_delport: prog: %x, vers: %x\n", prog, 137*7c478bd9Sstevel@tonic-gate vers); 138*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 139*7c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)tmp, sizeof (struct pmaplist)); 140*7c478bd9Sstevel@tonic-gate break; 141*7c478bd9Sstevel@tonic-gate } else 142*7c478bd9Sstevel@tonic-gate prev = tmp; 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* 147*7c478bd9Sstevel@tonic-gate * Modified strtol(3). 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate static int 150*7c478bd9Sstevel@tonic-gate strtoi(char *str, char **ptr) 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate int c, val; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate for (val = 0, c = *str++; c >= '0' && c <= '9'; c = *str++) { 155*7c478bd9Sstevel@tonic-gate val *= 10; 156*7c478bd9Sstevel@tonic-gate val += c - '0'; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate *ptr = str; 159*7c478bd9Sstevel@tonic-gate return (val); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate /* 163*7c478bd9Sstevel@tonic-gate * (from dlboot_inet.c) (kernel) 164*7c478bd9Sstevel@tonic-gate * Convert a port number from a sockaddr_in expressed 165*7c478bd9Sstevel@tonic-gate * in universal address format. 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate static int 168*7c478bd9Sstevel@tonic-gate uaddr2port(char *addr) 169*7c478bd9Sstevel@tonic-gate { 170*7c478bd9Sstevel@tonic-gate int p1, p2; 171*7c478bd9Sstevel@tonic-gate char *next; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * A struct sockaddr_in expressed in universal address 175*7c478bd9Sstevel@tonic-gate * format looks like: 176*7c478bd9Sstevel@tonic-gate * 177*7c478bd9Sstevel@tonic-gate * "IP.IP.IP.IP.PORT[top byte].PORT[bot. byte]" 178*7c478bd9Sstevel@tonic-gate * 179*7c478bd9Sstevel@tonic-gate * Where each component expresses as a charactor, 180*7c478bd9Sstevel@tonic-gate * the corresponding part of the IP address 181*7c478bd9Sstevel@tonic-gate * and port number. 182*7c478bd9Sstevel@tonic-gate * Thus 127.0.0.1, port 2345 looks like: 183*7c478bd9Sstevel@tonic-gate * 184*7c478bd9Sstevel@tonic-gate * 49 50 55 46 48 46 48 46 49 46 57 46 52 49 185*7c478bd9Sstevel@tonic-gate * 1 2 7 . 0 . 0 . 1 . 9 . 4 1 186*7c478bd9Sstevel@tonic-gate * 187*7c478bd9Sstevel@tonic-gate * 2345 = 929base16 = 9.32+9 = 9.41 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate (void) strtoi(addr, &next); 190*7c478bd9Sstevel@tonic-gate (void) strtoi(next, &next); 191*7c478bd9Sstevel@tonic-gate (void) strtoi(next, &next); 192*7c478bd9Sstevel@tonic-gate (void) strtoi(next, &next); 193*7c478bd9Sstevel@tonic-gate p1 = strtoi(next, &next); 194*7c478bd9Sstevel@tonic-gate p2 = strtoi(next, &next); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate return ((p1 << 8) + p2); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* 200*7c478bd9Sstevel@tonic-gate * Xdr routines used for calling portmapper/rpcbind. 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate bool_t 204*7c478bd9Sstevel@tonic-gate xdr_pmap(XDR *xdrs, struct pmap *regs) 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate if (xdr_rpcprog(xdrs, ®s->pm_prog) && 207*7c478bd9Sstevel@tonic-gate xdr_rpcvers(xdrs, ®s->pm_vers) && 208*7c478bd9Sstevel@tonic-gate xdr_rpcprot(xdrs, ®s->pm_prot)) 209*7c478bd9Sstevel@tonic-gate return (xdr_rpcprot(xdrs, ®s->pm_port)); 210*7c478bd9Sstevel@tonic-gate return (FALSE); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate bool_t 214*7c478bd9Sstevel@tonic-gate xdr_rpcb(XDR *xdrs, RPCB *objp) 215*7c478bd9Sstevel@tonic-gate { 216*7c478bd9Sstevel@tonic-gate if (!xdr_rpcprog(xdrs, &objp->r_prog)) 217*7c478bd9Sstevel@tonic-gate return (FALSE); 218*7c478bd9Sstevel@tonic-gate if (!xdr_rpcvers(xdrs, &objp->r_vers)) 219*7c478bd9Sstevel@tonic-gate return (FALSE); 220*7c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->r_netid, ~0)) 221*7c478bd9Sstevel@tonic-gate return (FALSE); 222*7c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->r_addr, ~0)) 223*7c478bd9Sstevel@tonic-gate return (FALSE); 224*7c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->r_owner, ~0)) 225*7c478bd9Sstevel@tonic-gate return (FALSE); 226*7c478bd9Sstevel@tonic-gate return (TRUE); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * XDR remote call arguments 231*7c478bd9Sstevel@tonic-gate * written for XDR_ENCODE direction only 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate bool_t 234*7c478bd9Sstevel@tonic-gate xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 235*7c478bd9Sstevel@tonic-gate { 236*7c478bd9Sstevel@tonic-gate uint_t lenposition, argposition, position; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate if (xdr_rpcprog(xdrs, &(cap->prog)) && 239*7c478bd9Sstevel@tonic-gate xdr_rpcvers(xdrs, &(cap->vers)) && 240*7c478bd9Sstevel@tonic-gate xdr_rpcproc(xdrs, &(cap->proc))) { 241*7c478bd9Sstevel@tonic-gate lenposition = XDR_GETPOS(xdrs); 242*7c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(cap->arglen))) 243*7c478bd9Sstevel@tonic-gate return (FALSE); 244*7c478bd9Sstevel@tonic-gate argposition = XDR_GETPOS(xdrs); 245*7c478bd9Sstevel@tonic-gate if (!(*(cap->xdr_args))(xdrs, cap->args_ptr)) 246*7c478bd9Sstevel@tonic-gate return (FALSE); 247*7c478bd9Sstevel@tonic-gate position = XDR_GETPOS(xdrs); 248*7c478bd9Sstevel@tonic-gate cap->arglen = position - argposition; 249*7c478bd9Sstevel@tonic-gate XDR_SETPOS(xdrs, lenposition); 250*7c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(cap->arglen))) 251*7c478bd9Sstevel@tonic-gate return (FALSE); 252*7c478bd9Sstevel@tonic-gate XDR_SETPOS(xdrs, position); 253*7c478bd9Sstevel@tonic-gate return (TRUE); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate return (FALSE); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate /* 259*7c478bd9Sstevel@tonic-gate * XDR remote call results 260*7c478bd9Sstevel@tonic-gate * written for XDR_DECODE direction only 261*7c478bd9Sstevel@tonic-gate */ 262*7c478bd9Sstevel@tonic-gate bool_t 263*7c478bd9Sstevel@tonic-gate xdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp) 264*7c478bd9Sstevel@tonic-gate { 265*7c478bd9Sstevel@tonic-gate caddr_t port_ptr; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate port_ptr = (caddr_t)crp->port_ptr; 268*7c478bd9Sstevel@tonic-gate if (xdr_reference(xdrs, &port_ptr, sizeof (uint_t), xdr_u_int) && 269*7c478bd9Sstevel@tonic-gate xdr_u_int(xdrs, &crp->resultslen)) { 270*7c478bd9Sstevel@tonic-gate crp->port_ptr = (rpcport_t *)port_ptr; 271*7c478bd9Sstevel@tonic-gate return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate return (FALSE); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * XDR remote call arguments 278*7c478bd9Sstevel@tonic-gate * written for XDR_ENCODE direction only 279*7c478bd9Sstevel@tonic-gate */ 280*7c478bd9Sstevel@tonic-gate bool_t 281*7c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallargs(XDR *xdrs, struct rpcb_rmtcallargs *objp) 282*7c478bd9Sstevel@tonic-gate { 283*7c478bd9Sstevel@tonic-gate uint_t lenposition, argposition, position; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate if (!xdr_rpcprog(xdrs, &objp->prog)) 286*7c478bd9Sstevel@tonic-gate return (FALSE); 287*7c478bd9Sstevel@tonic-gate if (!xdr_rpcvers(xdrs, &objp->vers)) 288*7c478bd9Sstevel@tonic-gate return (FALSE); 289*7c478bd9Sstevel@tonic-gate if (!xdr_rpcproc(xdrs, &objp->proc)) 290*7c478bd9Sstevel@tonic-gate return (FALSE); 291*7c478bd9Sstevel@tonic-gate /* 292*7c478bd9Sstevel@tonic-gate * All the jugglery for just getting the size of the arguments 293*7c478bd9Sstevel@tonic-gate */ 294*7c478bd9Sstevel@tonic-gate lenposition = XDR_GETPOS(xdrs); 295*7c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(objp->arglen))) 296*7c478bd9Sstevel@tonic-gate return (FALSE); 297*7c478bd9Sstevel@tonic-gate argposition = XDR_GETPOS(xdrs); 298*7c478bd9Sstevel@tonic-gate if (!(*(objp->xdr_args))(xdrs, objp->args_ptr)) 299*7c478bd9Sstevel@tonic-gate return (FALSE); 300*7c478bd9Sstevel@tonic-gate position = XDR_GETPOS(xdrs); 301*7c478bd9Sstevel@tonic-gate objp->arglen = position - argposition; 302*7c478bd9Sstevel@tonic-gate XDR_SETPOS(xdrs, lenposition); 303*7c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &(objp->arglen))) 304*7c478bd9Sstevel@tonic-gate return (FALSE); 305*7c478bd9Sstevel@tonic-gate XDR_SETPOS(xdrs, position); 306*7c478bd9Sstevel@tonic-gate return (TRUE); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * XDR remote call results 311*7c478bd9Sstevel@tonic-gate * written for XDR_DECODE direction only 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate bool_t 314*7c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallres(XDR *xdrs, struct rpcb_rmtcallres *objp) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate if (!xdr_string(xdrs, &objp->addr_ptr, ~0)) 317*7c478bd9Sstevel@tonic-gate return (FALSE); 318*7c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &objp->resultslen)) 319*7c478bd9Sstevel@tonic-gate return (FALSE); 320*7c478bd9Sstevel@tonic-gate return ((*(objp->xdr_results))(xdrs, objp->results_ptr)); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * bpmap_rmtcall: does PMAPPROC_CALLIT broadcasts w/ rpc_call requests. 325*7c478bd9Sstevel@tonic-gate * Lets one do a PMAPGETPORT/RPC PROC call in one easy step. sockaddr_in args 326*7c478bd9Sstevel@tonic-gate * are taken as network order. 327*7c478bd9Sstevel@tonic-gate * 328*7c478bd9Sstevel@tonic-gate * Code adapted from bpmap_rmtcall() in dlboot_inet.c (kernel) 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 331*7c478bd9Sstevel@tonic-gate enum clnt_stat 332*7c478bd9Sstevel@tonic-gate bpmap_rmtcall( 333*7c478bd9Sstevel@tonic-gate rpcprog_t prog, /* rpc program number to call. */ 334*7c478bd9Sstevel@tonic-gate rpcvers_t vers, /* rpc program version */ 335*7c478bd9Sstevel@tonic-gate rpcproc_t proc, /* rpc procedure to call */ 336*7c478bd9Sstevel@tonic-gate xdrproc_t in_xdr, /* routine to serialize arguments */ 337*7c478bd9Sstevel@tonic-gate caddr_t args, /* arg vector for remote call */ 338*7c478bd9Sstevel@tonic-gate xdrproc_t out_xdr, /* routine to deserialize results */ 339*7c478bd9Sstevel@tonic-gate caddr_t ret, /* addr of buf to place results in */ 340*7c478bd9Sstevel@tonic-gate int rexmit, /* retransmission interval (secs) */ 341*7c478bd9Sstevel@tonic-gate int wait, /* how long (secs) to wait for a resp */ 342*7c478bd9Sstevel@tonic-gate struct sockaddr_in *to, /* destination */ 343*7c478bd9Sstevel@tonic-gate struct sockaddr_in *from, /* filled in w/ responder's port/addr */ 344*7c478bd9Sstevel@tonic-gate uint_t auth) /* type of authentication wanted. */ 345*7c478bd9Sstevel@tonic-gate { 346*7c478bd9Sstevel@tonic-gate enum clnt_stat status; /* rpc_call status */ 347*7c478bd9Sstevel@tonic-gate rpcport_t port = 0; /* returned port # */ 348*7c478bd9Sstevel@tonic-gate struct rmtcallargs pmap_a; /* args for pmap call */ 349*7c478bd9Sstevel@tonic-gate struct rmtcallres pmap_r; /* results from pmap call */ 350*7c478bd9Sstevel@tonic-gate struct rpcb_rmtcallargs rpcb_a; /* args for rpcb call */ 351*7c478bd9Sstevel@tonic-gate struct rpcb_rmtcallres rpcb_r; /* results from rpcb call */ 352*7c478bd9Sstevel@tonic-gate char ua[UA_SIZE]; /* universal addr buffer */ 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* initialize pmap */ 355*7c478bd9Sstevel@tonic-gate pmap_a.prog = prog; 356*7c478bd9Sstevel@tonic-gate pmap_a.vers = vers; 357*7c478bd9Sstevel@tonic-gate pmap_a.proc = proc; 358*7c478bd9Sstevel@tonic-gate pmap_a.args_ptr = args; 359*7c478bd9Sstevel@tonic-gate pmap_a.xdr_args = in_xdr; 360*7c478bd9Sstevel@tonic-gate pmap_r.port_ptr = &port; 361*7c478bd9Sstevel@tonic-gate pmap_r.results_ptr = ret; 362*7c478bd9Sstevel@tonic-gate pmap_r.xdr_results = out_xdr; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate status = brpc_call((rpcprog_t)PMAPPROG, (rpcvers_t)PMAPVERS, 365*7c478bd9Sstevel@tonic-gate (rpcproc_t)PMAPPROC_CALLIT, xdr_rmtcall_args, (caddr_t)&pmap_a, 366*7c478bd9Sstevel@tonic-gate xdr_rmtcallres, (caddr_t)&pmap_r, rexmit, wait, to, from, 367*7c478bd9Sstevel@tonic-gate AUTH_NONE); 368*7c478bd9Sstevel@tonic-gate if (status != RPC_PROGUNAVAIL) { 369*7c478bd9Sstevel@tonic-gate if (status == RPC_SUCCESS) { 370*7c478bd9Sstevel@tonic-gate /* delete old port mapping, if it exists */ 371*7c478bd9Sstevel@tonic-gate bpmap_delport(prog, vers); 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate /* save the new port mapping */ 374*7c478bd9Sstevel@tonic-gate bpmap_addport(prog, vers, port); 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate return (status); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * PMAP is unavailable. Maybe there's a SVR4 machine, with rpcbind. 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate bzero(ua, sizeof (ua)); 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate /* initialize rpcb */ 385*7c478bd9Sstevel@tonic-gate rpcb_a.prog = prog; 386*7c478bd9Sstevel@tonic-gate rpcb_a.vers = vers; 387*7c478bd9Sstevel@tonic-gate rpcb_a.proc = proc; 388*7c478bd9Sstevel@tonic-gate rpcb_a.args_ptr = args; 389*7c478bd9Sstevel@tonic-gate rpcb_a.xdr_args = in_xdr; 390*7c478bd9Sstevel@tonic-gate rpcb_r.addr_ptr = ua; 391*7c478bd9Sstevel@tonic-gate rpcb_r.results_ptr = ret; 392*7c478bd9Sstevel@tonic-gate rpcb_r.xdr_results = out_xdr; 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate status = brpc_call((rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS, 395*7c478bd9Sstevel@tonic-gate (rpcproc_t)RPCBPROC_CALLIT, xdr_rpcb_rmtcallargs, (caddr_t)&rpcb_a, 396*7c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallres, (caddr_t)&rpcb_r, rexmit, wait, to, from, 397*7c478bd9Sstevel@tonic-gate AUTH_NONE); 398*7c478bd9Sstevel@tonic-gate if (status == RPC_SUCCESS) { 399*7c478bd9Sstevel@tonic-gate /* delete old port mapping, if it exists */ 400*7c478bd9Sstevel@tonic-gate bpmap_delport(prog, vers); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /* save the new port mapping */ 403*7c478bd9Sstevel@tonic-gate port = ntohs(uaddr2port(ua)); 404*7c478bd9Sstevel@tonic-gate bpmap_addport(prog, vers, port); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate return (status); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * bpmap_getport: Queries current list of cached pmap_list entries, 411*7c478bd9Sstevel@tonic-gate * returns the port number of the entry found. If the port number 412*7c478bd9Sstevel@tonic-gate * is not cached, then getport makes a rpc call first to the portmapper, 413*7c478bd9Sstevel@tonic-gate * and then to rpcbind (SVR4) if the portmapper does not respond. The 414*7c478bd9Sstevel@tonic-gate * returned port is then added to the cache, and the port number is 415*7c478bd9Sstevel@tonic-gate * returned. If both portmapper and rpc bind fail to give us the necessary 416*7c478bd9Sstevel@tonic-gate * port, we return 0 to signal we hit an error, and set rpc_stat to 417*7c478bd9Sstevel@tonic-gate * the appropriate RPC error code. Only IPPROTO_UDP protocol is supported. 418*7c478bd9Sstevel@tonic-gate * 419*7c478bd9Sstevel@tonic-gate * Port and sockaddr_in arguments taken in network order. rpcport_t is returned 420*7c478bd9Sstevel@tonic-gate * in host order. 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate rpcport_t 423*7c478bd9Sstevel@tonic-gate bpmap_getport(rpcprog_t prog, rpcvers_t vers, enum clnt_stat *rpc_stat, 424*7c478bd9Sstevel@tonic-gate struct sockaddr_in *to, struct sockaddr_in *from) 425*7c478bd9Sstevel@tonic-gate { 426*7c478bd9Sstevel@tonic-gate struct pmaplist *walk; 427*7c478bd9Sstevel@tonic-gate struct pmap pmap_send; /* portmap */ 428*7c478bd9Sstevel@tonic-gate in_port_t pmap_port; 429*7c478bd9Sstevel@tonic-gate rpcport_t dport; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 432*7c478bd9Sstevel@tonic-gate printf("bpmap_getport: called with: prog: %d, vers: %d\n", prog, vers); 433*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 434*7c478bd9Sstevel@tonic-gate for (walk = map_head; walk != 0; walk = walk->pml_next) { 435*7c478bd9Sstevel@tonic-gate if ((walk->pml_map.pm_prog == prog) && 436*7c478bd9Sstevel@tonic-gate (walk->pml_map.pm_vers == vers) && 437*7c478bd9Sstevel@tonic-gate (walk->pml_map.pm_prot == (rpcprot_t)IPPROTO_UDP)) { 438*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 439*7c478bd9Sstevel@tonic-gate printf("bpmap_getport: Found in cache. returning: %d\n", 440*7c478bd9Sstevel@tonic-gate walk->pml_map.pm_port); 441*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 442*7c478bd9Sstevel@tonic-gate return (walk->pml_map.pm_port); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * Not in the cache. First try the portmapper (SunOS server?) and 448*7c478bd9Sstevel@tonic-gate * if that fails, try rpcbind (SVR4 server). 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate pmap_send.pm_prog = prog; 451*7c478bd9Sstevel@tonic-gate pmap_send.pm_vers = vers; 452*7c478bd9Sstevel@tonic-gate pmap_send.pm_prot = (rpcprot_t)IPPROTO_UDP; 453*7c478bd9Sstevel@tonic-gate pmap_send.pm_port = 0; /* what we're after */ 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate *rpc_stat = brpc_call(PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, 456*7c478bd9Sstevel@tonic-gate xdr_pmap, (caddr_t)&pmap_send, xdr_u_short, 457*7c478bd9Sstevel@tonic-gate (caddr_t)&pmap_port, 0, 0, to, from, AUTH_NONE); 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate if (*rpc_stat == RPC_PROGUNAVAIL) { 460*7c478bd9Sstevel@tonic-gate /* 461*7c478bd9Sstevel@tonic-gate * The portmapper isn't available. Try rpcbind. 462*7c478bd9Sstevel@tonic-gate * Maybe the server is a SVR4 server. 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate char *ua; /* universal address */ 465*7c478bd9Sstevel@tonic-gate char ua_buf[UA_SIZE]; /* and its buffer */ 466*7c478bd9Sstevel@tonic-gate RPCB rpcb_send; 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate rpcb_send.r_prog = prog; 469*7c478bd9Sstevel@tonic-gate rpcb_send.r_vers = vers; 470*7c478bd9Sstevel@tonic-gate rpcb_send.r_netid = NULL; 471*7c478bd9Sstevel@tonic-gate rpcb_send.r_addr = NULL; 472*7c478bd9Sstevel@tonic-gate rpcb_send.r_owner = NULL; 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate bzero(ua_buf, UA_SIZE); 475*7c478bd9Sstevel@tonic-gate ua = ua_buf; 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * Again, default # of retries. xdr_wrapstring() 479*7c478bd9Sstevel@tonic-gate * wants a char **. 480*7c478bd9Sstevel@tonic-gate */ 481*7c478bd9Sstevel@tonic-gate *rpc_stat = brpc_call(RPCBPROG, RPCBVERS, RPCBPROC_GETADDR, 482*7c478bd9Sstevel@tonic-gate xdr_rpcb, (caddr_t)&rpcb_send, xdr_wrapstring, 483*7c478bd9Sstevel@tonic-gate (char *)&ua, 0, 0, to, from, AUTH_NONE); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate if (*rpc_stat == RPC_SUCCESS) { 486*7c478bd9Sstevel@tonic-gate if (ua[0] != '\0') 487*7c478bd9Sstevel@tonic-gate dport = ntohs(uaddr2port(ua)); 488*7c478bd9Sstevel@tonic-gate else 489*7c478bd9Sstevel@tonic-gate return (0); /* Address unknown */ 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate } else { 492*7c478bd9Sstevel@tonic-gate /* 493*7c478bd9Sstevel@tonic-gate * Why are rpcport_t's uint32_t? port numbers are uint16_t 494*7c478bd9Sstevel@tonic-gate * for ipv4 AND ipv6.... XXXX 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate dport = (rpcport_t)pmap_port; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (*rpc_stat != RPC_SUCCESS) { 500*7c478bd9Sstevel@tonic-gate dprintf("pmap_getport: Failed getting port.\n"); 501*7c478bd9Sstevel@tonic-gate return (0); /* we failed. */ 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 505*7c478bd9Sstevel@tonic-gate printf("bpmap_getport: prog: %d, vers: %d; returning port: %d.\n", 506*7c478bd9Sstevel@tonic-gate prog, vers, dport); 507*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate bpmap_addport(prog, vers, dport); 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate return (dport); 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate /* 515*7c478bd9Sstevel@tonic-gate * bpmap_memfree: frees up any dynamically allocated entries. 516*7c478bd9Sstevel@tonic-gate */ 517*7c478bd9Sstevel@tonic-gate void 518*7c478bd9Sstevel@tonic-gate bpmap_memfree(void) 519*7c478bd9Sstevel@tonic-gate { 520*7c478bd9Sstevel@tonic-gate struct pmaplist *current, *tmp; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (map_tail == &pre_init[PMAP_STATIC]) 523*7c478bd9Sstevel@tonic-gate return; /* no dynamic entries */ 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate /* free from head of the list to the tail. */ 526*7c478bd9Sstevel@tonic-gate current = pre_init[PMAP_STATIC].pml_next; 527*7c478bd9Sstevel@tonic-gate while (current != NULL) { 528*7c478bd9Sstevel@tonic-gate tmp = current->pml_next; 529*7c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)current, sizeof (struct pmaplist)); 530*7c478bd9Sstevel@tonic-gate current = tmp; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate } 533