1 /*********************************************************************
2 * RPC for the Windows NT Operating System
3 * 1993 by Martin F. Gergeleit
4 * Users may use, copy or modify Sun RPC for the Windows NT Operating
5 * System according to the Sun copyright below.
7 * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO
8 * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE
9 * USE OF. USE ENTIRELY AT YOUR OWN RISK!!!
10 *********************************************************************/
12 #if !defined(lint) && !defined(_NOIDENT)
13 static char rcsid[] = "@(#)$RCSfile$ $Revision$ (OSF) $Date$";
16 static char sccsid[] = "@(#)portmap.c 1.2 85/03/13 Copyr 1984 Sun Micro";
20 * Copyright (c) 1984 by Sun Microsystems, Inc.
24 * portmap.c, Implements the program,version to port number mapping for
26 * Modified to debug based on global var. "debug" so that you can twiddle
27 * it with adb and to use syslog for errors. rick macklem
31 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
32 * unrestricted use provided that this legend is included on all tape
33 * media and as a part of the software program in whole or part. Users
34 * may copy or modify Sun RPC without charge, but are not authorized
35 * to license or distribute it to anyone else except as part of a product or
36 * program developed by the user.
38 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
39 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
42 * Sun RPC is provided with no support and without any obligation on the
43 * part of Sun Microsystems, Inc. to assist in its use, correction,
44 * modification or enhancement.
46 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
47 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
48 * OR ANY PART THEREOF.
50 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
51 * or profits or other special, indirect and consequential damages, even if
52 * Sun has been advised of the possibility of such damages.
54 * Sun Microsystems, Inc.
56 * Mountain View, California 94043
60 #include <rpc/pmap_prot.h>
67 #define syslog(e, s) fprintf(stderr, (s))
78 struct sockaddr_in addr;
79 int len = sizeof(struct sockaddr_in);
83 pid = daemon(0,0); /* from libutil */
85 perror("portmap: fork");
90 openlog("portmap:", LOG_PID, LOG_DAEMON);
93 if (rpc_nt_init() != 0) {
94 fprintf(stderr, "cannot init WinSock\n");
99 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
100 fprintf(stderr, "cannot create socket\n");
104 addr.sin_addr.s_addr = 0;
105 addr.sin_family = AF_INET;
106 addr.sin_port = htons(PMAPPORT);
107 if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
108 fprintf(stderr, "cannot bind\n");
112 if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
113 fprintf(stderr, "couldn't do udp_create\n");
117 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
118 fprintf(stderr, "cannot create socket\n");
121 if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
122 fprintf(stderr, "cannot bind\n");
125 if ((xprt = svctcp_create(sock, 0, 0)) == (SVCXPRT *)NULL) {
126 fprintf(stderr, "couldn't do tcp_create\n");
130 (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
132 fprintf(stderr, "run_svc returned unexpectedly\n");
139 struct pmaplist *pmaplist;
141 static struct pmaplist *
142 find_service(prog, vers, prot)
146 register struct pmaplist *hit = NULL;
147 register struct pmaplist *pml;
149 for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
150 if ((pml->pml_map.pm_prog != prog) ||
151 (pml->pml_map.pm_prot != prot))
154 if (pml->pml_map.pm_vers == vers)
164 reg_service(rqstp, xprt)
165 struct svc_req *rqstp;
169 struct pmaplist *pml, *prevpml, *fnd;
174 fprintf(stderr, "server: about do a switch\n");
175 switch (rqstp->rq_proc) {
181 if ((!svc_sendreply(xprt, xdr_void, NULL)) && debug) {
188 * Set a program,version to port mapping
190 if (!svc_getargs(xprt, xdr_pmap, ®))
194 * check to see if already used
195 * find_service returns a hit even if
196 * the versions don't match, so check for it
198 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
199 if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
200 if (fnd->pml_map.pm_port == reg.pm_port) {
212 pml = (struct pmaplist *)
213 malloc((u_int)sizeof(struct pmaplist));
215 pml->pml_next = pmaplist;
220 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
222 fprintf(stderr, "svc_sendreply\n");
230 * Remove a program,version to port mapping.
232 if (!svc_getargs(xprt, xdr_pmap, ®))
236 for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
237 if ((pml->pml_map.pm_prog != reg.pm_prog) ||
238 (pml->pml_map.pm_vers != reg.pm_vers)) {
239 /* both pml & prevpml move forwards */
244 /* found it; pml moves forward, prevpml stays */
251 prevpml->pml_next = pml;
254 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
256 fprintf(stderr, "svc_sendreply\n");
262 case PMAPPROC_GETPORT:
264 * Lookup the mapping for a program,version and return its port
266 if (!svc_getargs(xprt, xdr_pmap, ®))
269 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
271 port = fnd->pml_map.pm_port;
274 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
276 fprintf(stderr, "svc_sendreply\n");
284 * Return the current set of mapped program,version
286 if (!svc_getargs(xprt, xdr_void, NULL))
289 if ((!svc_sendreply(xprt, xdr_pmaplist,
290 (caddr_t)&pmaplist)) && debug) {
291 fprintf(stderr, "svc_sendreply\n");
297 case PMAPPROC_CALLIT:
299 * Calls a procedure on the local machine. If the requested
300 * procedure is not registered this procedure does not return
301 * error information!!
302 * This procedure is only supported on rpc/udp and calls via
303 * rpc/udp. It passes null authentication parameters.
316 * Stuff for the rmtcall service
320 typedef struct encap_parms {
326 xdr_encap_parms(xdrs, epp)
328 struct encap_parms *epp;
331 return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
334 typedef struct rmtcallargs {
339 struct encap_parms rmt_args;
343 xdr_rmtcall_args(xdrs, cap)
345 register struct rmtcallargs *cap;
348 /* does not get a port number */
349 if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
350 xdr_u_long(xdrs, &(cap->rmt_vers)) &&
351 xdr_u_long(xdrs, &(cap->rmt_proc))) {
352 return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
358 xdr_rmtcall_result(xdrs, cap)
360 register struct rmtcallargs *cap;
362 if (xdr_u_long(xdrs, &(cap->rmt_port)))
363 return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
368 * only worries about the struct encap_parms part of struct rmtcallargs.
369 * The arglen must already be set!!
372 xdr_opaque_parms(xdrs, cap)
374 struct rmtcallargs *cap;
377 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
381 * This routine finds and sets the length of incoming opaque paraters
382 * and then calls xdr_opaque_parms.
385 xdr_len_opaque_parms(xdrs, cap)
387 struct rmtcallargs *cap;
389 register u_int beginpos, lowpos, highpos, currpos, pos;
391 beginpos = lowpos = pos = xdr_getpos(xdrs);
392 highpos = lowpos + ARGSIZE;
393 while ((int)(highpos - lowpos) >= 0) {
394 currpos = (lowpos + highpos) / 2;
395 if (xdr_setpos(xdrs, currpos)) {
397 lowpos = currpos + 1;
399 highpos = currpos - 1;
402 xdr_setpos(xdrs, beginpos);
403 cap->rmt_args.arglen = pos - beginpos;
404 return (xdr_opaque_parms(xdrs, cap));
408 * Call a remote procedure service
409 * This procedure is very quiet when things go wrong.
410 * The proc is written to support broadcast rpc. In the broadcast case,
411 * a machine should shut-up instead of complain, less the requestor be
412 * overrun with complaints at the expense of not hearing a valid reply ...
416 struct svc_req *rqstp;
420 struct rmtcallargs a;
421 struct pmaplist *pml;
423 struct sockaddr_in me;
426 struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
427 struct timeval timeout;
431 a.rmt_args.args = buf;
432 if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
434 if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
436 port = pml->pml_map.pm_port;
438 me.sin_port = htons(port);
439 client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
440 if (client != (CLIENT *)NULL) {
441 if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
442 client->cl_auth = authunix_create(au->aup_machname,
443 au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
445 a.rmt_port = (u_long)port;
446 if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
447 xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
448 svc_sendreply(xprt, xdr_rmtcall_result, &a);
450 AUTH_DESTROY(client->cl_auth);
451 clnt_destroy(client);
453 (void)closesocket(socket);