rpc.c revision 1.4 1 1.4 mycroft /* $NetBSD: rpc.c,v 1.4 1995/02/20 11:04:18 mycroft Exp $ */
2 1.2 cgd
3 1.1 brezak /*
4 1.1 brezak * Copyright (c) 1992 Regents of the University of California.
5 1.1 brezak * All rights reserved.
6 1.1 brezak *
7 1.1 brezak * This software was developed by the Computer Systems Engineering group
8 1.1 brezak * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 1.1 brezak * contributed to Berkeley.
10 1.1 brezak *
11 1.1 brezak * Redistribution and use in source and binary forms, with or without
12 1.1 brezak * modification, are permitted provided that the following conditions
13 1.1 brezak * are met:
14 1.1 brezak * 1. Redistributions of source code must retain the above copyright
15 1.1 brezak * notice, this list of conditions and the following disclaimer.
16 1.1 brezak * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 brezak * notice, this list of conditions and the following disclaimer in the
18 1.1 brezak * documentation and/or other materials provided with the distribution.
19 1.1 brezak * 3. All advertising materials mentioning features or use of this software
20 1.1 brezak * must display the following acknowledgement:
21 1.1 brezak * This product includes software developed by the University of
22 1.1 brezak * California, Lawrence Berkeley Laboratory and its contributors.
23 1.1 brezak * 4. Neither the name of the University nor the names of its contributors
24 1.1 brezak * may be used to endorse or promote products derived from this software
25 1.1 brezak * without specific prior written permission.
26 1.1 brezak *
27 1.1 brezak * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 1.1 brezak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.1 brezak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.1 brezak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 1.1 brezak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 1.1 brezak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 1.1 brezak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 1.1 brezak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 1.1 brezak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 1.1 brezak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 1.1 brezak * SUCH DAMAGE.
38 1.1 brezak *
39 1.2 cgd * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL)
40 1.1 brezak */
41 1.1 brezak
42 1.1 brezak #include <sys/param.h>
43 1.1 brezak #include <sys/socket.h>
44 1.1 brezak
45 1.1 brezak #include <netinet/in.h>
46 1.1 brezak #include <netinet/in_systm.h>
47 1.1 brezak
48 1.1 brezak #include <nfs/rpcv2.h>
49 1.1 brezak #include <nfs/nfsv2.h>
50 1.4 mycroft #include <nfs/xdr_subs.h>
51 1.4 mycroft
52 1.1 brezak #include <string.h>
53 1.1 brezak
54 1.1 brezak #include "stand.h"
55 1.1 brezak #include "net.h"
56 1.1 brezak #include "netif.h"
57 1.1 brezak #include "rpc.h"
58 1.1 brezak
59 1.1 brezak /* XXX Data part of nfs rpc reply (also the largest thing we receive) */
60 1.1 brezak struct nfs_reply_data {
61 1.1 brezak u_long errno;
62 1.1 brezak u_char fa[NFSX_FATTR(0)];
63 1.1 brezak u_long count;
64 1.1 brezak u_char data[1200];
65 1.1 brezak };
66 1.1 brezak #define NFSREAD_SIZE sizeof(((struct nfs_reply_data *)0)->data)
67 1.1 brezak
68 1.1 brezak /* Cache stuff */
69 1.1 brezak #define PMAP_NUM 8 /* need at most 5 pmap entries */
70 1.1 brezak
71 1.1 brezak static struct pmap_list {
72 1.1 brezak u_long addr; /* address of server */
73 1.1 brezak u_long prog;
74 1.1 brezak u_long vers;
75 1.1 brezak u_short port; /* cached port for service */
76 1.1 brezak } pmap_list[PMAP_NUM] = {
77 1.1 brezak { 0, PMAPPROG, PMAPVERS, PMAPPORT }
78 1.1 brezak };
79 1.1 brezak static int pmap_num = 1;
80 1.1 brezak
81 1.1 brezak /* Local forwards */
82 1.4 mycroft static size_t recvrpc __P((struct iodesc *, void *, size_t, time_t));
83 1.1 brezak
84 1.1 brezak /* Make a rpc call; return length of answer */
85 1.4 mycroft size_t
86 1.1 brezak callrpc(d, prog, vers, proc, sdata, slen, rdata, rlen)
87 1.1 brezak register struct iodesc *d;
88 1.1 brezak register u_long prog, vers, proc;
89 1.1 brezak register void *sdata;
90 1.4 mycroft register size_t slen;
91 1.1 brezak register void *rdata;
92 1.4 mycroft register size_t rlen;
93 1.1 brezak {
94 1.4 mycroft register size_t cc;
95 1.4 mycroft register u_long *tl;
96 1.1 brezak struct {
97 1.1 brezak u_char header[HEADER_SIZE];
98 1.4 mycroft u_long data[96]; /* XXX */
99 1.1 brezak } wbuf;
100 1.1 brezak struct {
101 1.4 mycroft u_char header[HEADER_SIZE];
102 1.1 brezak struct rpc_reply rrpc;
103 1.1 brezak union {
104 1.1 brezak u_long errno;
105 1.1 brezak u_char data[sizeof(struct nfs_reply_data)];
106 1.1 brezak } ru;
107 1.1 brezak } rbuf;
108 1.1 brezak
109 1.1 brezak #ifdef RPC_DEBUG
110 1.1 brezak if (debug)
111 1.3 mycroft printf("callrpc: called\n");
112 1.1 brezak #endif
113 1.1 brezak if (rlen > sizeof(rbuf.ru.data))
114 1.1 brezak panic("callrpc: huge read (%d > %d)",
115 1.1 brezak rlen, sizeof(rbuf.ru.data));
116 1.1 brezak
117 1.1 brezak d->destport = getport(d, prog, vers);
118 1.1 brezak
119 1.4 mycroft tl = wbuf.data;
120 1.4 mycroft
121 1.4 mycroft /* Fill in RPC call structure. */
122 1.4 mycroft *tl++ = txdr_unsigned(d->xid);
123 1.4 mycroft *tl++ = txdr_unsigned(RPC_CALL);
124 1.4 mycroft *tl++ = txdr_unsigned(RPC_VER2);
125 1.4 mycroft *tl++ = txdr_unsigned(prog);
126 1.4 mycroft *tl++ = txdr_unsigned(vers);
127 1.4 mycroft *tl++ = txdr_unsigned(proc);
128 1.4 mycroft
129 1.4 mycroft /* Fill in authorization info. */
130 1.4 mycroft if (prog != NFS_PROG) {
131 1.4 mycroft *tl++ = txdr_unsigned(RPCAUTH_NULL);
132 1.4 mycroft *tl++ = txdr_unsigned(0);
133 1.4 mycroft } else {
134 1.4 mycroft *tl++ = txdr_unsigned(RPCAUTH_UNIX);
135 1.4 mycroft *tl++ = txdr_unsigned(3*NFSX_UNSIGNED);
136 1.4 mycroft *tl++ = txdr_unsigned(0); /* time */
137 1.4 mycroft *tl++ = txdr_unsigned(0); /* host name length */
138 1.4 mycroft *tl++ = txdr_unsigned(0); /* uid */
139 1.4 mycroft *tl++ = txdr_unsigned(0); /* gid */
140 1.4 mycroft *tl++ = txdr_unsigned(0); /* gid list length */
141 1.4 mycroft }
142 1.4 mycroft *tl++ = txdr_unsigned(RPCAUTH_NULL);
143 1.4 mycroft *tl++ = txdr_unsigned(0);
144 1.1 brezak
145 1.4 mycroft /* Fill in RPC call arguments. */
146 1.4 mycroft bcopy(sdata, tl, slen);
147 1.1 brezak
148 1.4 mycroft cc = sendrecv(d,
149 1.4 mycroft sendudp, wbuf.data,
150 1.4 mycroft (tl - wbuf.data) * NFSX_UNSIGNED + slen,
151 1.4 mycroft recvrpc, &rbuf.rrpc,
152 1.4 mycroft sizeof(struct rpc_reply) + sizeof(struct nfs_reply_data));
153 1.1 brezak
154 1.3 mycroft #ifdef RPC_DEBUG
155 1.3 mycroft if (debug)
156 1.3 mycroft printf("callrpc: cc=%d rlen=%d, rp_stat=%d\n", cc, rlen,
157 1.3 mycroft rbuf.rrpc.rp_stat);
158 1.3 mycroft #endif
159 1.3 mycroft
160 1.4 mycroft /* Bump xid so next request will be unique. */
161 1.3 mycroft ++d->xid;
162 1.1 brezak
163 1.4 mycroft if (cc == -1)
164 1.4 mycroft return (-1);
165 1.1 brezak if (cc < rlen) {
166 1.1 brezak /* Check for an error return */
167 1.1 brezak if (cc >= sizeof(rbuf.ru.errno) && rbuf.ru.errno != 0) {
168 1.1 brezak errno = ntohl(rbuf.ru.errno);
169 1.1 brezak return (-1);
170 1.1 brezak }
171 1.1 brezak panic("callrpc: missing data (%d < %d)", cc, rlen);
172 1.1 brezak }
173 1.1 brezak if (cc > sizeof(rbuf.ru.data))
174 1.1 brezak panic("callrpc: huge return (%d > %d)",
175 1.1 brezak cc, sizeof(rbuf.ru.data));
176 1.1 brezak bcopy(rbuf.ru.data, rdata, cc);
177 1.1 brezak return (cc);
178 1.1 brezak }
179 1.1 brezak
180 1.1 brezak /* Returns true if packet is the one we're waiting for */
181 1.4 mycroft static size_t
182 1.4 mycroft recvrpc(d, pkt, len, tleft)
183 1.1 brezak register struct iodesc *d;
184 1.1 brezak register void *pkt;
185 1.4 mycroft register size_t len;
186 1.4 mycroft time_t tleft;
187 1.1 brezak {
188 1.1 brezak register struct rpc_reply *rpc;
189 1.1 brezak
190 1.1 brezak errno = 0;
191 1.1 brezak #ifdef RPC_DEBUG
192 1.1 brezak if (debug)
193 1.3 mycroft printf("recvrpc: called len=%d\n", len);
194 1.1 brezak #endif
195 1.1 brezak
196 1.4 mycroft len = readudp(d, pkt, len, tleft);
197 1.4 mycroft if (len == -1 || len < sizeof(struct rpc_reply))
198 1.4 mycroft goto bad;
199 1.4 mycroft
200 1.4 mycroft rpc = (struct rpc_reply *)pkt;
201 1.4 mycroft NTOHL(rpc->rp_xid);
202 1.1 brezak NTOHL(rpc->rp_direction);
203 1.1 brezak NTOHL(rpc->rp_stat);
204 1.1 brezak
205 1.4 mycroft if (rpc->rp_xid != d->xid ||
206 1.4 mycroft rpc->rp_direction != RPC_REPLY ||
207 1.4 mycroft rpc->rp_stat != RPC_MSGACCEPTED) {
208 1.1 brezak #ifdef RPC_DEBUG
209 1.1 brezak if (debug) {
210 1.1 brezak if (rpc->rp_xid != d->xid)
211 1.1 brezak printf("recvrpc: rp_xid %d != xid %d\n",
212 1.4 mycroft rpc->rp_xid, d->xid);
213 1.4 mycroft if (rpc->rp_direction != RPC_REPLY)
214 1.4 mycroft printf("recvrpc: rp_direction %d != RPC_REPLY\n",
215 1.4 mycroft rpc->rp_direction);
216 1.4 mycroft if (rpc->rp_stat != RPC_MSGACCEPTED)
217 1.4 mycroft printf("recvrpc: rp_stat %d != RPC_MSGACCEPTED\n",
218 1.4 mycroft rpc->rp_stat);
219 1.1 brezak }
220 1.1 brezak #endif
221 1.4 mycroft goto bad;
222 1.1 brezak }
223 1.1 brezak
224 1.1 brezak /* Return data count (thus indicating success) */
225 1.1 brezak return (len - sizeof(*rpc));
226 1.4 mycroft
227 1.4 mycroft bad:
228 1.4 mycroft return (-1);
229 1.1 brezak }
230 1.1 brezak
231 1.1 brezak /* Request a port number from the port mapper */
232 1.1 brezak u_short
233 1.1 brezak getport(d, prog, vers)
234 1.1 brezak register struct iodesc *d;
235 1.1 brezak u_long prog;
236 1.1 brezak u_long vers;
237 1.1 brezak {
238 1.1 brezak register int i;
239 1.1 brezak register struct pmap_list *pl;
240 1.1 brezak u_long port;
241 1.1 brezak struct {
242 1.1 brezak u_long prog; /* call program */
243 1.1 brezak u_long vers; /* call version */
244 1.1 brezak u_long proto; /* call protocol */
245 1.1 brezak u_long port; /* call port (unused) */
246 1.1 brezak } sdata;
247 1.1 brezak
248 1.1 brezak #ifdef RPC_DEBUG
249 1.1 brezak if (debug)
250 1.1 brezak printf("getport: called\n");
251 1.1 brezak #endif
252 1.1 brezak /* Try for cached answer first */
253 1.1 brezak for (i = 0, pl = pmap_list; i < pmap_num; ++i, ++pl)
254 1.1 brezak if ((pl->addr == d->destip || pl->addr == 0) &&
255 1.1 brezak pl->prog == prog && pl->vers == vers)
256 1.1 brezak return (pl->port);
257 1.1 brezak
258 1.1 brezak /* Don't overflow cache */
259 1.1 brezak if (pmap_num > PMAP_NUM - 1)
260 1.1 brezak panic("getport: overflowed pmap_list!");
261 1.1 brezak
262 1.1 brezak sdata.prog = htonl(prog);
263 1.1 brezak sdata.vers = htonl(vers);
264 1.1 brezak sdata.proto = htonl(IPPROTO_UDP);
265 1.1 brezak sdata.port = 0;
266 1.1 brezak
267 1.1 brezak if (callrpc(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
268 1.1 brezak &sdata, sizeof(sdata), &port, sizeof(port)) < 0) {
269 1.1 brezak printf("getport: %s", strerror(errno));
270 1.1 brezak return(-1);
271 1.1 brezak }
272 1.1 brezak
273 1.1 brezak /* Cache answer */
274 1.1 brezak pl->addr = d->destip;
275 1.1 brezak pl->prog = prog;
276 1.1 brezak pl->vers = vers;
277 1.1 brezak pl->port = port;
278 1.1 brezak ++pmap_num;
279 1.1 brezak
280 1.1 brezak return ((u_short)port);
281 1.1 brezak }
282