|
|
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.