12518b873Sbostic /*-
2*3483ac59Sbostic * Copyright (c) 1990, 1993
3*3483ac59Sbostic * The Regents of the University of California. All rights reserved.
4f9468666Smckusick *
52518b873Sbostic * %sccs.include.redist.c%
6f9468666Smckusick */
7f9468666Smckusick
8f9468666Smckusick #ifndef lint
9*3483ac59Sbostic static char copyright[] =
10*3483ac59Sbostic "@(#) Copyright (c) 1990, 1993\n\
11*3483ac59Sbostic The Regents of the University of California. All rights reserved.\n";
122518b873Sbostic #endif /* not lint */
132518b873Sbostic
142518b873Sbostic #ifndef lint
15*3483ac59Sbostic static char sccsid[] = "@(#)portmap.c 8.1 (Berkeley) 06/06/93";
162518b873Sbostic #endif /* not lint */
172518b873Sbostic
182518b873Sbostic /*
192518b873Sbostic @(#)portmap.c 2.3 88/08/11 4.0 RPCSRC
20f9468666Smckusick static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
212518b873Sbostic */
22f9468666Smckusick
23f9468666Smckusick /*
24f9468666Smckusick * portmap.c, Implements the program,version to port number mapping for
25f9468666Smckusick * rpc.
26f9468666Smckusick */
27f9468666Smckusick
28f9468666Smckusick /*
29f9468666Smckusick * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
30f9468666Smckusick * unrestricted use provided that this legend is included on all tape
31f9468666Smckusick * media and as a part of the software program in whole or part. Users
32f9468666Smckusick * may copy or modify Sun RPC without charge, but are not authorized
33f9468666Smckusick * to license or distribute it to anyone else except as part of a product or
34f9468666Smckusick * program developed by the user.
35f9468666Smckusick *
36f9468666Smckusick * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
37f9468666Smckusick * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
38f9468666Smckusick * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
39f9468666Smckusick *
40f9468666Smckusick * Sun RPC is provided with no support and without any obligation on the
41f9468666Smckusick * part of Sun Microsystems, Inc. to assist in its use, correction,
42f9468666Smckusick * modification or enhancement.
43f9468666Smckusick *
44f9468666Smckusick * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
45f9468666Smckusick * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
46f9468666Smckusick * OR ANY PART THEREOF.
47f9468666Smckusick *
48f9468666Smckusick * In no event will Sun Microsystems, Inc. be liable for any lost revenue
49f9468666Smckusick * or profits or other special, indirect and consequential damages, even if
50f9468666Smckusick * Sun has been advised of the possibility of such damages.
51f9468666Smckusick *
52f9468666Smckusick * Sun Microsystems, Inc.
53f9468666Smckusick * 2550 Garcia Avenue
54f9468666Smckusick * Mountain View, California 94043
55f9468666Smckusick */
56f9468666Smckusick
57f9468666Smckusick #include <rpc/rpc.h>
58f9468666Smckusick #include <rpc/pmap_prot.h>
59f9468666Smckusick #include <stdio.h>
60af6a243bSmckusick #include <stdlib.h>
61af6a243bSmckusick #include <string.h>
62af6a243bSmckusick #include <syslog.h>
6395698dd2Sdonn #include <unistd.h>
64f9468666Smckusick #include <netdb.h>
65f9468666Smckusick #include <sys/socket.h>
66f9468666Smckusick #include <sys/ioctl.h>
67f9468666Smckusick #include <sys/wait.h>
68f9468666Smckusick #include <sys/signal.h>
69af6a243bSmckusick #include <sys/resource.h>
70f9468666Smckusick
7195698dd2Sdonn void reg_service();
72f9468666Smckusick void reap();
7395698dd2Sdonn static void callit();
74f9468666Smckusick struct pmaplist *pmaplist;
75af6a243bSmckusick int debugging = 0;
76af6a243bSmckusick extern int errno;
77f9468666Smckusick
main(argc,argv)78af6a243bSmckusick main(argc, argv)
79af6a243bSmckusick int argc;
80af6a243bSmckusick char **argv;
81f9468666Smckusick {
82f9468666Smckusick SVCXPRT *xprt;
83af6a243bSmckusick int sock, c;
84f9468666Smckusick struct sockaddr_in addr;
85f9468666Smckusick int len = sizeof(struct sockaddr_in);
86f9468666Smckusick register struct pmaplist *pml;
87f9468666Smckusick
88af6a243bSmckusick while ((c = getopt(argc, argv, "d")) != EOF) {
89af6a243bSmckusick switch (c) {
90af6a243bSmckusick
91af6a243bSmckusick case 'd':
92af6a243bSmckusick debugging = 1;
93af6a243bSmckusick break;
94af6a243bSmckusick
95af6a243bSmckusick default:
96af6a243bSmckusick (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]);
97f9468666Smckusick exit(1);
98f9468666Smckusick }
99f9468666Smckusick }
100af6a243bSmckusick
101af6a243bSmckusick if (!debugging && daemon(0, 0)) {
102af6a243bSmckusick (void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
103af6a243bSmckusick exit(1);
104af6a243bSmckusick }
105af6a243bSmckusick
106af6a243bSmckusick openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID,
107af6a243bSmckusick LOG_DAEMON);
108af6a243bSmckusick
109f9468666Smckusick if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
110af6a243bSmckusick syslog(LOG_ERR, "cannot create udp socket: %m");
111f9468666Smckusick exit(1);
112f9468666Smckusick }
113f9468666Smckusick
114f9468666Smckusick addr.sin_addr.s_addr = 0;
115f9468666Smckusick addr.sin_family = AF_INET;
116f9468666Smckusick addr.sin_port = htons(PMAPPORT);
117f9468666Smckusick if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
118af6a243bSmckusick syslog(LOG_ERR, "cannot bind udp: %m");
119f9468666Smckusick exit(1);
120f9468666Smckusick }
121f9468666Smckusick
122f9468666Smckusick if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
123af6a243bSmckusick syslog(LOG_ERR, "couldn't do udp_create");
124f9468666Smckusick exit(1);
125f9468666Smckusick }
126f9468666Smckusick /* make an entry for ourself */
127f9468666Smckusick pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
128f9468666Smckusick pml->pml_next = 0;
129f9468666Smckusick pml->pml_map.pm_prog = PMAPPROG;
130f9468666Smckusick pml->pml_map.pm_vers = PMAPVERS;
131f9468666Smckusick pml->pml_map.pm_prot = IPPROTO_UDP;
132f9468666Smckusick pml->pml_map.pm_port = PMAPPORT;
133f9468666Smckusick pmaplist = pml;
134f9468666Smckusick
135f9468666Smckusick if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
136af6a243bSmckusick syslog(LOG_ERR, "cannot create tcp socket: %m");
137f9468666Smckusick exit(1);
138f9468666Smckusick }
139f9468666Smckusick if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
140af6a243bSmckusick syslog(LOG_ERR, "cannot bind udp: %m");
141f9468666Smckusick exit(1);
142f9468666Smckusick }
143f9468666Smckusick if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
144f9468666Smckusick == (SVCXPRT *)NULL) {
145af6a243bSmckusick syslog(LOG_ERR, "couldn't do tcp_create");
146f9468666Smckusick exit(1);
147f9468666Smckusick }
148f9468666Smckusick /* make an entry for ourself */
149f9468666Smckusick pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
150f9468666Smckusick pml->pml_map.pm_prog = PMAPPROG;
151f9468666Smckusick pml->pml_map.pm_vers = PMAPVERS;
152f9468666Smckusick pml->pml_map.pm_prot = IPPROTO_TCP;
153f9468666Smckusick pml->pml_map.pm_port = PMAPPORT;
154f9468666Smckusick pml->pml_next = pmaplist;
155f9468666Smckusick pmaplist = pml;
156f9468666Smckusick
157f9468666Smckusick (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
158f9468666Smckusick
159f9468666Smckusick (void)signal(SIGCHLD, reap);
160f9468666Smckusick svc_run();
161af6a243bSmckusick syslog(LOG_ERR, "run_svc returned unexpectedly");
162f9468666Smckusick abort();
163f9468666Smckusick }
164f9468666Smckusick
165af6a243bSmckusick #ifndef lint
166af6a243bSmckusick /* need to override perror calls in rpc library */
167af6a243bSmckusick void
perror(what)168af6a243bSmckusick perror(what)
16995698dd2Sdonn const char *what;
170af6a243bSmckusick {
171af6a243bSmckusick
172af6a243bSmckusick syslog(LOG_ERR, "%s: %m", what);
173af6a243bSmckusick }
174af6a243bSmckusick #endif
175af6a243bSmckusick
176f9468666Smckusick static struct pmaplist *
find_service(prog,vers,prot)177f9468666Smckusick find_service(prog, vers, prot)
178af6a243bSmckusick u_long prog, vers, prot;
179f9468666Smckusick {
180f9468666Smckusick register struct pmaplist *hit = NULL;
181f9468666Smckusick register struct pmaplist *pml;
182f9468666Smckusick
183f9468666Smckusick for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
184f9468666Smckusick if ((pml->pml_map.pm_prog != prog) ||
185f9468666Smckusick (pml->pml_map.pm_prot != prot))
186f9468666Smckusick continue;
187f9468666Smckusick hit = pml;
188f9468666Smckusick if (pml->pml_map.pm_vers == vers)
189f9468666Smckusick break;
190f9468666Smckusick }
191f9468666Smckusick return (hit);
192f9468666Smckusick }
193f9468666Smckusick
194f9468666Smckusick /*
195f9468666Smckusick * 1 OK, 0 not
196f9468666Smckusick */
19795698dd2Sdonn void
reg_service(rqstp,xprt)198f9468666Smckusick reg_service(rqstp, xprt)
199f9468666Smckusick struct svc_req *rqstp;
200f9468666Smckusick SVCXPRT *xprt;
201f9468666Smckusick {
202f9468666Smckusick struct pmap reg;
203f9468666Smckusick struct pmaplist *pml, *prevpml, *fnd;
204f9468666Smckusick int ans, port;
205f9468666Smckusick caddr_t t;
206f9468666Smckusick
207af6a243bSmckusick if (debugging)
208af6a243bSmckusick (void) fprintf(stderr, "server: about do a switch\n");
209f9468666Smckusick switch (rqstp->rq_proc) {
210f9468666Smckusick
211f9468666Smckusick case PMAPPROC_NULL:
212f9468666Smckusick /*
213f9468666Smckusick * Null proc call
214f9468666Smckusick */
215af6a243bSmckusick if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
216f9468666Smckusick abort();
217f9468666Smckusick }
218f9468666Smckusick break;
219f9468666Smckusick
220f9468666Smckusick case PMAPPROC_SET:
221f9468666Smckusick /*
222f9468666Smckusick * Set a program,version to port mapping
223f9468666Smckusick */
224f9468666Smckusick if (!svc_getargs(xprt, xdr_pmap, ®))
225f9468666Smckusick svcerr_decode(xprt);
226f9468666Smckusick else {
227f9468666Smckusick /*
228f9468666Smckusick * check to see if already used
229f9468666Smckusick * find_service returns a hit even if
230f9468666Smckusick * the versions don't match, so check for it
231f9468666Smckusick */
232f9468666Smckusick fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
233f9468666Smckusick if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
234f9468666Smckusick if (fnd->pml_map.pm_port == reg.pm_port) {
235f9468666Smckusick ans = 1;
236f9468666Smckusick goto done;
237f9468666Smckusick }
238f9468666Smckusick else {
239f9468666Smckusick ans = 0;
240f9468666Smckusick goto done;
241f9468666Smckusick }
242f9468666Smckusick } else {
243f9468666Smckusick /*
244f9468666Smckusick * add to END of list
245f9468666Smckusick */
246f9468666Smckusick pml = (struct pmaplist *)
247f9468666Smckusick malloc((u_int)sizeof(struct pmaplist));
248f9468666Smckusick pml->pml_map = reg;
249f9468666Smckusick pml->pml_next = 0;
250f9468666Smckusick if (pmaplist == 0) {
251f9468666Smckusick pmaplist = pml;
252f9468666Smckusick } else {
253f9468666Smckusick for (fnd= pmaplist; fnd->pml_next != 0;
254f9468666Smckusick fnd = fnd->pml_next);
255f9468666Smckusick fnd->pml_next = pml;
256f9468666Smckusick }
257f9468666Smckusick ans = 1;
258f9468666Smckusick }
259f9468666Smckusick done:
260f9468666Smckusick if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
261f9468666Smckusick debugging) {
262af6a243bSmckusick (void) fprintf(stderr, "svc_sendreply\n");
263f9468666Smckusick abort();
264f9468666Smckusick }
265f9468666Smckusick }
266f9468666Smckusick break;
267f9468666Smckusick
268f9468666Smckusick case PMAPPROC_UNSET:
269f9468666Smckusick /*
270f9468666Smckusick * Remove a program,version to port mapping.
271f9468666Smckusick */
272f9468666Smckusick if (!svc_getargs(xprt, xdr_pmap, ®))
273f9468666Smckusick svcerr_decode(xprt);
274f9468666Smckusick else {
275f9468666Smckusick ans = 0;
276f9468666Smckusick for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
277f9468666Smckusick if ((pml->pml_map.pm_prog != reg.pm_prog) ||
278f9468666Smckusick (pml->pml_map.pm_vers != reg.pm_vers)) {
279f9468666Smckusick /* both pml & prevpml move forwards */
280f9468666Smckusick prevpml = pml;
281f9468666Smckusick pml = pml->pml_next;
282f9468666Smckusick continue;
283f9468666Smckusick }
284f9468666Smckusick /* found it; pml moves forward, prevpml stays */
285f9468666Smckusick ans = 1;
286f9468666Smckusick t = (caddr_t)pml;
287f9468666Smckusick pml = pml->pml_next;
288f9468666Smckusick if (prevpml == NULL)
289f9468666Smckusick pmaplist = pml;
290f9468666Smckusick else
291f9468666Smckusick prevpml->pml_next = pml;
292f9468666Smckusick free(t);
293f9468666Smckusick }
294f9468666Smckusick if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
295f9468666Smckusick debugging) {
296af6a243bSmckusick (void) fprintf(stderr, "svc_sendreply\n");
297f9468666Smckusick abort();
298f9468666Smckusick }
299f9468666Smckusick }
300f9468666Smckusick break;
301f9468666Smckusick
302f9468666Smckusick case PMAPPROC_GETPORT:
303f9468666Smckusick /*
304f9468666Smckusick * Lookup the mapping for a program,version and return its port
305f9468666Smckusick */
306f9468666Smckusick if (!svc_getargs(xprt, xdr_pmap, ®))
307f9468666Smckusick svcerr_decode(xprt);
308f9468666Smckusick else {
309f9468666Smckusick fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
310f9468666Smckusick if (fnd)
311f9468666Smckusick port = fnd->pml_map.pm_port;
312f9468666Smckusick else
313f9468666Smckusick port = 0;
314f9468666Smckusick if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
315f9468666Smckusick debugging) {
316af6a243bSmckusick (void) fprintf(stderr, "svc_sendreply\n");
317f9468666Smckusick abort();
318f9468666Smckusick }
319f9468666Smckusick }
320f9468666Smckusick break;
321f9468666Smckusick
322f9468666Smckusick case PMAPPROC_DUMP:
323f9468666Smckusick /*
324f9468666Smckusick * Return the current set of mapped program,version
325f9468666Smckusick */
326f9468666Smckusick if (!svc_getargs(xprt, xdr_void, NULL))
327f9468666Smckusick svcerr_decode(xprt);
328f9468666Smckusick else {
329f9468666Smckusick if ((!svc_sendreply(xprt, xdr_pmaplist,
330f9468666Smckusick (caddr_t)&pmaplist)) && debugging) {
331af6a243bSmckusick (void) fprintf(stderr, "svc_sendreply\n");
332f9468666Smckusick abort();
333f9468666Smckusick }
334f9468666Smckusick }
335f9468666Smckusick break;
336f9468666Smckusick
337f9468666Smckusick case PMAPPROC_CALLIT:
338f9468666Smckusick /*
339f9468666Smckusick * Calls a procedure on the local machine. If the requested
340f9468666Smckusick * procedure is not registered this procedure does not return
341f9468666Smckusick * error information!!
342f9468666Smckusick * This procedure is only supported on rpc/udp and calls via
343f9468666Smckusick * rpc/udp. It passes null authentication parameters.
344f9468666Smckusick */
345f9468666Smckusick callit(rqstp, xprt);
346f9468666Smckusick break;
347f9468666Smckusick
348f9468666Smckusick default:
349f9468666Smckusick svcerr_noproc(xprt);
350f9468666Smckusick break;
351f9468666Smckusick }
352f9468666Smckusick }
353f9468666Smckusick
354f9468666Smckusick
355f9468666Smckusick /*
356f9468666Smckusick * Stuff for the rmtcall service
357f9468666Smckusick */
358f9468666Smckusick #define ARGSIZE 9000
359f9468666Smckusick
36095698dd2Sdonn struct encap_parms {
361f9468666Smckusick u_long arglen;
362f9468666Smckusick char *args;
363f9468666Smckusick };
364f9468666Smckusick
365f9468666Smckusick static bool_t
xdr_encap_parms(xdrs,epp)366f9468666Smckusick xdr_encap_parms(xdrs, epp)
367f9468666Smckusick XDR *xdrs;
368f9468666Smckusick struct encap_parms *epp;
369f9468666Smckusick {
370f9468666Smckusick
371f9468666Smckusick return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
372f9468666Smckusick }
373f9468666Smckusick
37495698dd2Sdonn struct rmtcallargs {
375f9468666Smckusick u_long rmt_prog;
376f9468666Smckusick u_long rmt_vers;
377f9468666Smckusick u_long rmt_port;
378f9468666Smckusick u_long rmt_proc;
379f9468666Smckusick struct encap_parms rmt_args;
380f9468666Smckusick };
381f9468666Smckusick
382f9468666Smckusick static bool_t
xdr_rmtcall_args(xdrs,cap)383f9468666Smckusick xdr_rmtcall_args(xdrs, cap)
384f9468666Smckusick register XDR *xdrs;
385f9468666Smckusick register struct rmtcallargs *cap;
386f9468666Smckusick {
387f9468666Smckusick
388f9468666Smckusick /* does not get a port number */
389f9468666Smckusick if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
390f9468666Smckusick xdr_u_long(xdrs, &(cap->rmt_vers)) &&
391f9468666Smckusick xdr_u_long(xdrs, &(cap->rmt_proc))) {
392f9468666Smckusick return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
393f9468666Smckusick }
394f9468666Smckusick return (FALSE);
395f9468666Smckusick }
396f9468666Smckusick
397f9468666Smckusick static bool_t
xdr_rmtcall_result(xdrs,cap)398f9468666Smckusick xdr_rmtcall_result(xdrs, cap)
399f9468666Smckusick register XDR *xdrs;
400f9468666Smckusick register struct rmtcallargs *cap;
401f9468666Smckusick {
402f9468666Smckusick if (xdr_u_long(xdrs, &(cap->rmt_port)))
403f9468666Smckusick return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
404f9468666Smckusick return (FALSE);
405f9468666Smckusick }
406f9468666Smckusick
407f9468666Smckusick /*
408f9468666Smckusick * only worries about the struct encap_parms part of struct rmtcallargs.
409f9468666Smckusick * The arglen must already be set!!
410f9468666Smckusick */
411f9468666Smckusick static bool_t
xdr_opaque_parms(xdrs,cap)412f9468666Smckusick xdr_opaque_parms(xdrs, cap)
413f9468666Smckusick XDR *xdrs;
414f9468666Smckusick struct rmtcallargs *cap;
415f9468666Smckusick {
416f9468666Smckusick
417f9468666Smckusick return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
418f9468666Smckusick }
419f9468666Smckusick
420f9468666Smckusick /*
421f9468666Smckusick * This routine finds and sets the length of incoming opaque paraters
422f9468666Smckusick * and then calls xdr_opaque_parms.
423f9468666Smckusick */
424f9468666Smckusick static bool_t
xdr_len_opaque_parms(xdrs,cap)425f9468666Smckusick xdr_len_opaque_parms(xdrs, cap)
426f9468666Smckusick register XDR *xdrs;
427f9468666Smckusick struct rmtcallargs *cap;
428f9468666Smckusick {
429f9468666Smckusick register u_int beginpos, lowpos, highpos, currpos, pos;
430f9468666Smckusick
431f9468666Smckusick beginpos = lowpos = pos = xdr_getpos(xdrs);
432f9468666Smckusick highpos = lowpos + ARGSIZE;
433f9468666Smckusick while ((int)(highpos - lowpos) >= 0) {
434f9468666Smckusick currpos = (lowpos + highpos) / 2;
435f9468666Smckusick if (xdr_setpos(xdrs, currpos)) {
436f9468666Smckusick pos = currpos;
437f9468666Smckusick lowpos = currpos + 1;
438f9468666Smckusick } else {
439f9468666Smckusick highpos = currpos - 1;
440f9468666Smckusick }
441f9468666Smckusick }
442f9468666Smckusick xdr_setpos(xdrs, beginpos);
443f9468666Smckusick cap->rmt_args.arglen = pos - beginpos;
444f9468666Smckusick return (xdr_opaque_parms(xdrs, cap));
445f9468666Smckusick }
446f9468666Smckusick
447f9468666Smckusick /*
448f9468666Smckusick * Call a remote procedure service
449f9468666Smckusick * This procedure is very quiet when things go wrong.
450f9468666Smckusick * The proc is written to support broadcast rpc. In the broadcast case,
451f9468666Smckusick * a machine should shut-up instead of complain, less the requestor be
452f9468666Smckusick * overrun with complaints at the expense of not hearing a valid reply ...
453f9468666Smckusick *
454f9468666Smckusick * This now forks so that the program & process that it calls can call
455f9468666Smckusick * back to the portmapper.
456f9468666Smckusick */
45795698dd2Sdonn static void
callit(rqstp,xprt)458f9468666Smckusick callit(rqstp, xprt)
459f9468666Smckusick struct svc_req *rqstp;
460f9468666Smckusick SVCXPRT *xprt;
461f9468666Smckusick {
462f9468666Smckusick struct rmtcallargs a;
463f9468666Smckusick struct pmaplist *pml;
464f9468666Smckusick u_short port;
465f9468666Smckusick struct sockaddr_in me;
466af6a243bSmckusick int pid, so = -1;
467f9468666Smckusick CLIENT *client;
468f9468666Smckusick struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
469f9468666Smckusick struct timeval timeout;
470f9468666Smckusick char buf[ARGSIZE];
471f9468666Smckusick
472f9468666Smckusick timeout.tv_sec = 5;
473f9468666Smckusick timeout.tv_usec = 0;
474f9468666Smckusick a.rmt_args.args = buf;
475f9468666Smckusick if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
476f9468666Smckusick return;
477af6a243bSmckusick if ((pml = find_service(a.rmt_prog, a.rmt_vers,
478af6a243bSmckusick (u_long)IPPROTO_UDP)) == NULL)
479f9468666Smckusick return;
480f9468666Smckusick /*
481f9468666Smckusick * fork a child to do the work. Parent immediately returns.
482f9468666Smckusick * Child exits upon completion.
483f9468666Smckusick */
484f9468666Smckusick if ((pid = fork()) != 0) {
485af6a243bSmckusick if (pid < 0)
486af6a243bSmckusick syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
487af6a243bSmckusick a.rmt_prog);
488f9468666Smckusick return;
489f9468666Smckusick }
490f9468666Smckusick port = pml->pml_map.pm_port;
491f9468666Smckusick get_myaddress(&me);
492f9468666Smckusick me.sin_port = htons(port);
493af6a243bSmckusick client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
494f9468666Smckusick if (client != (CLIENT *)NULL) {
495f9468666Smckusick if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
496f9468666Smckusick client->cl_auth = authunix_create(au->aup_machname,
497f9468666Smckusick au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
498f9468666Smckusick }
499f9468666Smckusick a.rmt_port = (u_long)port;
500f9468666Smckusick if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
501f9468666Smckusick xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
502af6a243bSmckusick svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
503f9468666Smckusick }
504f9468666Smckusick AUTH_DESTROY(client->cl_auth);
505f9468666Smckusick clnt_destroy(client);
506f9468666Smckusick }
507af6a243bSmckusick (void)close(so);
508f9468666Smckusick exit(0);
509f9468666Smckusick }
510f9468666Smckusick
511f9468666Smckusick void
reap()512f9468666Smckusick reap()
513f9468666Smckusick {
514af6a243bSmckusick while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
515f9468666Smckusick }
516