|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)portmap.c 1.2 85/03/13 Copyr 1984 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1984 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * portmap.c, Implements the program,version to port number mapping for
11: * rpc.
12: */
13:
14: /*
15: * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
16: * unrestricted use provided that this legend is included on all tape
17: * media and as a part of the software program in whole or part. Users
18: * may copy or modify Sun RPC without charge, but are not authorized
19: * to license or distribute it to anyone else except as part of a product or
20: * program developed by the user.
21: *
22: * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
23: * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
24: * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
25: *
26: * Sun RPC is provided with no support and without any obligation on the
27: * part of Sun Microsystems, Inc. to assist in its use, correction,
28: * modification or enhancement.
29: *
30: * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
31: * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
32: * OR ANY PART THEREOF.
33: *
34: * In no event will Sun Microsystems, Inc. be liable for any lost revenue
35: * or profits or other special, indirect and consequential damages, even if
36: * Sun has been advised of the possibility of such damages.
37: *
38: * Sun Microsystems, Inc.
39: * 2550 Garcia Avenue
40: * Mountain View, California 94043
41: */
42:
43: #include <rpc/rpc.h>
44: #include <rpc/pmap_prot.h>
45: #include <stdio.h>
46: #include <netdb.h>
47: #include <sys/socket.h>
48: #include <sys/time.h>
49: #include <sys/ioctl.h>
50:
51: char *malloc();
52: int reg_service();
53: static int debugging = 0;
54:
55: main()
56: {
57: SVCXPRT *xprt;
58: int sock, pid, t;
59: struct sockaddr_in addr;
60: int len = sizeof(struct sockaddr_in);
61:
62: #ifndef DEBUG
63: pid = fork();
64: if (pid < 0) {
65: perror("portmap: fork");
66: exit(1);
67: }
68: if (pid != 0)
69: exit(0);
70: for (t = 0; t < 20; t++)
71: close(t);
72: open("/", 0);
73: dup2(0, 1);
74: dup2(0, 2);
75: t = open("/dev/tty", 2);
76: if (t >= 0) {
77: ioctl(t, TIOCNOTTY, (char *)0);
78: close(t);
79: }
80: #endif
81: if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
82: perror("portmap cannot create socket");
83: exit(1);
84: }
85:
86: addr.sin_addr.s_addr = 0;
87: addr.sin_family = AF_INET;
88: addr.sin_port = htons(PMAPPORT);
89: if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
90: perror("portmap cannot bind");
91: exit(1);
92: }
93:
94: if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
95: fprintf(stderr, "couldn't do udp_create\n");
96: exit(1);
97: }
98:
99: if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
100: perror("portmap cannot create socket");
101: exit(1);
102: }
103: if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
104: perror("portmap cannot bind");
105: exit(1);
106: }
107: if ((xprt = svctcp_create(sock, 0, 0)) == (SVCXPRT *)NULL) {
108: fprintf(stderr, "couldn't do tcp_create\n");
109: exit(1);
110: }
111:
112: (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
113: svc_run();
114: fprintf(stderr, "run_svc returned unexpectedly\n");
115: abort();
116: }
117:
118: struct pmaplist *pmaplist;
119:
120: static struct pmaplist *
121: find_service(prog, vers, prot)
122: u_long prog;
123: u_long vers;
124: {
125: register struct pmaplist *hit = NULL;
126: register struct pmaplist *pml;
127:
128: for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
129: if ((pml->pml_map.pm_prog != prog) ||
130: (pml->pml_map.pm_prot != prot))
131: continue;
132: hit = pml;
133: if (pml->pml_map.pm_vers == vers)
134: break;
135: }
136: return (hit);
137: }
138:
139: /*
140: * 1 OK, 0 not
141: */
142: reg_service(rqstp, xprt)
143: struct svc_req *rqstp;
144: SVCXPRT *xprt;
145: {
146: struct pmap reg;
147: struct pmaplist *pml, *prevpml, *fnd;
148: int ans, port;
149: caddr_t t;
150:
151: #ifdef DEBUG
152: fprintf(stderr, "server: about do a switch\n");
153: #endif
154: switch (rqstp->rq_proc) {
155:
156: case PMAPPROC_NULL:
157: /*
158: * Null proc call
159: */
160: if ((!svc_sendreply(xprt, xdr_void, NULL)) && debugging) {
161: abort();
162: }
163: break;
164:
165: case PMAPPROC_SET:
166: /*
167: * Set a program,version to port mapping
168: */
169: if (!svc_getargs(xprt, xdr_pmap, ®))
170: svcerr_decode(xprt);
171: else {
172: /*
173: * check to see if already used
174: * find_service returns a hit even if
175: * the versions don't match, so check for it
176: */
177: fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
178: if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
179: if (fnd->pml_map.pm_port == reg.pm_port) {
180: ans = 1;
181: goto done;
182: }
183: else {
184: ans = 0;
185: goto done;
186: }
187: } else {
188: /*
189: * add to list
190: */
191: pml = (struct pmaplist *)
192: malloc((u_int)sizeof(struct pmaplist));
193: pml->pml_map = reg;
194: pml->pml_next = pmaplist;
195: pmaplist = pml;
196: ans = 1;
197: }
198: done:
199: if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
200: debugging) {
201: fprintf(stderr, "svc_sendreply\n");
202: abort();
203: }
204: }
205: break;
206:
207: case PMAPPROC_UNSET:
208: /*
209: * Remove a program,version to port mapping.
210: */
211: if (!svc_getargs(xprt, xdr_pmap, ®))
212: svcerr_decode(xprt);
213: else {
214: ans = 0;
215: for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
216: if ((pml->pml_map.pm_prog != reg.pm_prog) ||
217: (pml->pml_map.pm_vers != reg.pm_vers)) {
218: /* both pml & prevpml move forwards */
219: prevpml = pml;
220: pml = pml->pml_next;
221: continue;
222: }
223: /* found it; pml moves forward, prevpml stays */
224: ans = 1;
225: t = (caddr_t)pml;
226: pml = pml->pml_next;
227: if (prevpml == NULL)
228: pmaplist = pml;
229: else
230: prevpml->pml_next = pml;
231: free(t);
232: }
233: if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
234: debugging) {
235: fprintf(stderr, "svc_sendreply\n");
236: abort();
237: }
238: }
239: break;
240:
241: case PMAPPROC_GETPORT:
242: /*
243: * Lookup the mapping for a program,version and return its port
244: */
245: if (!svc_getargs(xprt, xdr_pmap, ®))
246: svcerr_decode(xprt);
247: else {
248: fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
249: if (fnd)
250: port = fnd->pml_map.pm_port;
251: else
252: port = 0;
253: if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
254: debugging) {
255: fprintf(stderr, "svc_sendreply\n");
256: abort();
257: }
258: }
259: break;
260:
261: case PMAPPROC_DUMP:
262: /*
263: * Return the current set of mapped program,version
264: */
265: if (!svc_getargs(xprt, xdr_void, NULL))
266: svcerr_decode(xprt);
267: else {
268: if ((!svc_sendreply(xprt, xdr_pmaplist,
269: (caddr_t)&pmaplist)) && debugging) {
270: fprintf(stderr, "svc_sendreply\n");
271: abort();
272: }
273: }
274: break;
275:
276: case PMAPPROC_CALLIT:
277: /*
278: * Calls a procedure on the local machine. If the requested
279: * procedure is not registered this procedure does not return
280: * error information!!
281: * This procedure is only supported on rpc/udp and calls via
282: * rpc/udp. It passes null authentication parameters.
283: */
284: callit(rqstp, xprt);
285: break;
286:
287: default:
288: svcerr_noproc(xprt);
289: break;
290: }
291: }
292:
293:
294: /*
295: * Stuff for the rmtcall service
296: */
297: #define ARGSIZE 9000
298:
299: typedef struct encap_parms {
300: u_long arglen;
301: char *args;
302: };
303:
304: static bool_t
305: xdr_encap_parms(xdrs, epp)
306: XDR *xdrs;
307: struct encap_parms *epp;
308: {
309:
310: return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
311: }
312:
313: typedef struct rmtcallargs {
314: u_long rmt_prog;
315: u_long rmt_vers;
316: u_long rmt_port;
317: u_long rmt_proc;
318: struct encap_parms rmt_args;
319: };
320:
321: static bool_t
322: xdr_rmtcall_args(xdrs, cap)
323: register XDR *xdrs;
324: register struct rmtcallargs *cap;
325: {
326:
327: /* does not get a port number */
328: if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
329: xdr_u_long(xdrs, &(cap->rmt_vers)) &&
330: xdr_u_long(xdrs, &(cap->rmt_proc))) {
331: return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
332: }
333: return (FALSE);
334: }
335:
336: static bool_t
337: xdr_rmtcall_result(xdrs, cap)
338: register XDR *xdrs;
339: register struct rmtcallargs *cap;
340: {
341: if (xdr_u_long(xdrs, &(cap->rmt_port)))
342: return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
343: return (FALSE);
344: }
345:
346: /*
347: * only worries about the struct encap_parms part of struct rmtcallargs.
348: * The arglen must already be set!!
349: */
350: static bool_t
351: xdr_opaque_parms(xdrs, cap)
352: XDR *xdrs;
353: struct rmtcallargs *cap;
354: {
355:
356: return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
357: }
358:
359: /*
360: * This routine finds and sets the length of incoming opaque paraters
361: * and then calls xdr_opaque_parms.
362: */
363: static bool_t
364: xdr_len_opaque_parms(xdrs, cap)
365: register XDR *xdrs;
366: struct rmtcallargs *cap;
367: {
368: register u_int beginpos, lowpos, highpos, currpos, pos;
369:
370: beginpos = lowpos = pos = xdr_getpos(xdrs);
371: highpos = lowpos + ARGSIZE;
372: while ((int)(highpos - lowpos) >= 0) {
373: currpos = (lowpos + highpos) / 2;
374: if (xdr_setpos(xdrs, currpos)) {
375: pos = currpos;
376: lowpos = currpos + 1;
377: } else {
378: highpos = currpos - 1;
379: }
380: }
381: xdr_setpos(xdrs, beginpos);
382: cap->rmt_args.arglen = pos - beginpos;
383: return (xdr_opaque_parms(xdrs, cap));
384: }
385:
386: /*
387: * Call a remote procedure service
388: * This procedure is very quiet when things go wrong.
389: * The proc is written to support broadcast rpc. In the broadcast case,
390: * a machine should shut-up instead of complain, less the requestor be
391: * overrun with complaints at the expense of not hearing a valid reply ...
392: */
393: static
394: callit(rqstp, xprt)
395: struct svc_req *rqstp;
396: SVCXPRT *xprt;
397: {
398: char buf[2000];
399: struct rmtcallargs a;
400: struct pmaplist *pml;
401: u_short port;
402: struct sockaddr_in me;
403: int socket = -1;
404: CLIENT *client;
405: struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
406: struct timeval timeout;
407:
408: timeout.tv_sec = 5;
409: timeout.tv_usec = 0;
410: a.rmt_args.args = buf;
411: if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
412: return;
413: if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
414: return;
415: port = pml->pml_map.pm_port;
416: get_myaddress(&me);
417: me.sin_port = htons(port);
418: client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
419: if (client != (CLIENT *)NULL) {
420: if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
421: client->cl_auth = authunix_create(au->aup_machname,
422: au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
423: }
424: a.rmt_port = (u_long)port;
425: if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
426: xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
427: svc_sendreply(xprt, xdr_rmtcall_result, &a);
428: }
429: AUTH_DESTROY(client->cl_auth);
430: clnt_destroy(client);
431: }
432: (void)close(socket);
433: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.