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, &reg))
 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, &reg))
 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, &reg))
 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: }

Defined functions

callit defined in line 393; used 1 times
find_service defined in line 120; used 3 times
main defined in line 55; never used
reg_service defined in line 142; used 2 times
xdr_encap_parms defined in line 304; used 2 times
xdr_len_opaque_parms defined in line 363; used 1 times
xdr_opaque_parms defined in line 350; used 2 times
xdr_rmtcall_args defined in line 321; used 1 times
xdr_rmtcall_result defined in line 336; used 1 times

Defined variables

debugging defined in line 53; used 5 times
pmaplist defined in line 118; used 6 times
sccsid defined in line 2; never used

Defined struct's

encap_parms defined in line 299; used 4 times
rmtcallargs defined in line 313; used 10 times

Defined macros

ARGSIZE defined in line 297; used 2 times
Last modified: 1985-08-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1984
Valid CSS Valid XHTML 1.0 Strict