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