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