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
bpmap_addport(rpcprog_t prog,rpcvers_t vers,rpcport_t port)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
bpmap_delport(rpcprog_t prog,rpcvers_t vers)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
strtoi(char * str,char ** ptr)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
uaddr2port(char * addr)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
xdr_pmap(XDR * xdrs,struct pmap * regs)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
xdr_rpcb(XDR * xdrs,RPCB * objp)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
xdr_rmtcall_args(XDR * xdrs,struct rmtcallargs * cap)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
xdr_rmtcallres(XDR * xdrs,struct rmtcallres * crp)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
xdr_rpcb_rmtcallargs(XDR * xdrs,struct rpcb_rmtcallargs * objp)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
xdr_rpcb_rmtcallres(XDR * xdrs,struct rpcb_rmtcallres * objp)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
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)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
bpmap_getport(rpcprog_t prog,rpcvers_t vers,enum clnt_stat * rpc_stat,struct sockaddr_in * to,struct sockaddr_in * from)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
bpmap_memfree(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