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