home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume6 / rpc2 / part09 / rpc / tools / portmap.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  10.0 KB  |  441 lines

  1. #ifndef lint
  2. static    char sccsid[] = "@(#)portmap.c 1.1 86/02/03 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_un.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, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
  108.         == (SVCXPRT *)NULL) {
  109.         fprintf(stderr, "couldn't do tcp_create\n");
  110.         exit(1);
  111.     }
  112.  
  113.         (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
  114.     svc_run();
  115.     fprintf(stderr, "run_svc returned unexpectedly\n");
  116.     abort();
  117. }
  118.  
  119. struct pmaplist *pmaplist;
  120.  
  121. static struct pmaplist *
  122. find_service(prog, vers, prot)
  123.     u_long prog;
  124.     u_long vers;
  125. {
  126.     register struct pmaplist *hit = NULL;
  127.     register struct pmaplist *pml;
  128.  
  129.     for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
  130.         if ((pml->pml_map.pm_prog != prog) ||
  131.             (pml->pml_map.pm_prot != prot))
  132.             continue;
  133.         hit = pml;
  134.         if (pml->pml_map.pm_vers == vers)
  135.             break;
  136.     }
  137.     return (hit);
  138. }
  139.  
  140. /* 
  141.  * 1 OK, 0 not
  142.  */
  143. reg_service(rqstp, xprt)
  144.     struct svc_req *rqstp;
  145.     SVCXPRT *xprt;
  146. {
  147.     struct pmap reg;
  148.     struct pmaplist *pml, *prevpml, *fnd;
  149.     int ans, port;
  150.     caddr_t t;
  151.     
  152. #ifdef DEBUG
  153.     fprintf(stderr, "server: about do a switch\n");
  154. #endif
  155.     switch (rqstp->rq_proc) {
  156.  
  157.     case PMAPPROC_NULL:
  158.         /*
  159.          * Null proc call
  160.          */
  161.         if ((!svc_sendreply(xprt, xdr_void, NULL)) && debugging) {
  162.             abort();
  163.         }
  164.         break;
  165.  
  166.     case PMAPPROC_SET:
  167.         /*
  168.          * Set a program,version to port mapping
  169.          */
  170.         if (!svc_getargs(xprt, xdr_pmap, ®))
  171.             svcerr_decode(xprt);
  172.         else {
  173.             /*
  174.              * check to see if already used
  175.              * find_service returns a hit even if
  176.              * the versions don't match, so check for it
  177.              */
  178.             fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
  179.             if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
  180.                 if (fnd->pml_map.pm_port == reg.pm_port) {
  181.                     ans = 1;
  182.                     goto done;
  183.                 }
  184.                 else {
  185.                     ans = 0;
  186.                     goto done;
  187.                 }
  188.             } else {
  189.                 /* 
  190.                  * add to END of list
  191.                  */
  192.                 pml = (struct pmaplist *)
  193.                     malloc((u_int)sizeof(struct pmaplist));
  194.                 pml->pml_map = reg;
  195.                 pml->pml_next = 0;
  196.                 if (pmaplist == 0) {
  197.                     pmaplist = pml;
  198.                 } else {
  199.                     for (fnd= pmaplist; fnd->pml_next != 0;
  200.                         fnd = fnd->pml_next);
  201.                     fnd->pml_next = pml;
  202.                 }
  203.                 ans = 1;
  204.             }
  205.         done:
  206.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  207.                 debugging) {
  208.                 fprintf(stderr, "svc_sendreply\n");
  209.                 abort();
  210.             }
  211.         }
  212.         break;
  213.  
  214.     case PMAPPROC_UNSET:
  215.         /*
  216.          * Remove a program,version to port mapping.
  217.          */
  218.         if (!svc_getargs(xprt, xdr_pmap, ®))
  219.             svcerr_decode(xprt);
  220.         else {
  221.             ans = 0;
  222.             for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
  223.                 if ((pml->pml_map.pm_prog != reg.pm_prog) ||
  224.                     (pml->pml_map.pm_vers != reg.pm_vers)) {
  225.                     /* both pml & prevpml move forwards */
  226.                     prevpml = pml;
  227.                     pml = pml->pml_next;
  228.                     continue;
  229.                 }
  230.                 /* found it; pml moves forward, prevpml stays */
  231.                 ans = 1;
  232.                 t = (caddr_t)pml;
  233.                 pml = pml->pml_next;
  234.                 if (prevpml == NULL)
  235.                     pmaplist = pml;
  236.                 else
  237.                     prevpml->pml_next = pml;
  238.                 free(t);
  239.             }
  240.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  241.                 debugging) {
  242.                 fprintf(stderr, "svc_sendreply\n");
  243.                 abort();
  244.             }
  245.         }
  246.         break;
  247.  
  248.     case PMAPPROC_GETPORT:
  249.         /*
  250.          * Lookup the mapping for a program,version and return its port
  251.          */
  252.         if (!svc_getargs(xprt, xdr_pmap, ®))
  253.             svcerr_decode(xprt);
  254.         else {
  255.             fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
  256.             if (fnd)
  257.                 port = fnd->pml_map.pm_port;
  258.             else
  259.                 port = 0;
  260.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
  261.                 debugging) {
  262.                 fprintf(stderr, "svc_sendreply\n");
  263.                 abort();
  264.             }
  265.         }
  266.         break;
  267.  
  268.     case PMAPPROC_DUMP:
  269.         /*
  270.          * Return the current set of mapped program,version
  271.          */
  272.         if (!svc_getargs(xprt, xdr_void, NULL))
  273.             svcerr_decode(xprt);
  274.         else {
  275.             if ((!svc_sendreply(xprt, xdr_pmaplist,
  276.                 (caddr_t)&pmaplist)) && debugging) {
  277.                 fprintf(stderr, "svc_sendreply\n");
  278.                 abort();
  279.             }
  280.         }
  281.         break;
  282.  
  283.     case PMAPPROC_CALLIT:
  284.         /*
  285.          * Calls a procedure on the local machine.  If the requested
  286.          * procedure is not registered this procedure does not return
  287.          * error information!!
  288.          * This procedure is only supported on rpc/udp and calls via 
  289.          * rpc/udp.  It passes null authentication parameters.
  290.          */
  291.         callit(rqstp, xprt);
  292.         break;
  293.  
  294.     default:
  295.         svcerr_noproc(xprt);
  296.         break;
  297.     }
  298. }
  299.  
  300.  
  301. /*
  302.  * Stuff for the rmtcall service
  303.  */
  304. #define ARGSIZE 9000
  305.  
  306. typedef struct encap_parms {
  307.     u_long arglen;
  308.     char *args;
  309. };
  310.  
  311. static bool_t
  312. xdr_encap_parms(xdrs, epp)
  313.     XDR *xdrs;
  314.     struct encap_parms *epp;
  315. {
  316.  
  317.     return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
  318. }
  319.  
  320. typedef struct rmtcallargs {
  321.     u_long    rmt_prog;
  322.     u_long    rmt_vers;
  323.     u_long    rmt_port;
  324.     u_long    rmt_proc;
  325.     struct encap_parms rmt_args;
  326. };
  327.  
  328. static bool_t
  329. xdr_rmtcall_args(xdrs, cap)
  330.     register XDR *xdrs;
  331.     register struct rmtcallargs *cap;
  332. {
  333.  
  334.     /* does not get a port number */
  335.     if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
  336.         xdr_u_long(xdrs, &(cap->rmt_vers)) &&
  337.         xdr_u_long(xdrs, &(cap->rmt_proc))) {
  338.         return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
  339.     }
  340.     return (FALSE);
  341. }
  342.  
  343. static bool_t
  344. xdr_rmtcall_result(xdrs, cap)
  345.     register XDR *xdrs;
  346.     register struct rmtcallargs *cap;
  347. {
  348.     if (xdr_u_long(xdrs, &(cap->rmt_port)))
  349.         return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
  350.     return (FALSE);
  351. }
  352.  
  353. /*
  354.  * only worries about the struct encap_parms part of struct rmtcallargs.
  355.  * The arglen must already be set!!
  356.  */
  357. static bool_t
  358. xdr_opaque_parms(xdrs, cap)
  359.     XDR *xdrs;
  360.     struct rmtcallargs *cap;
  361. {
  362.  
  363.     return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
  364. }
  365.  
  366. /*
  367.  * This routine finds and sets the length of incoming opaque paraters
  368.  * and then calls xdr_opaque_parms.
  369.  */
  370. static bool_t
  371. xdr_len_opaque_parms(xdrs, cap)
  372.     register XDR *xdrs;
  373.     struct rmtcallargs *cap;
  374. {
  375.     register u_int beginpos, lowpos, highpos, currpos, pos;
  376.  
  377.     beginpos = lowpos = pos = xdr_getpos(xdrs);
  378.     highpos = lowpos + ARGSIZE;
  379.     while ((int)(highpos - lowpos) >= 0) {
  380.         currpos = (lowpos + highpos) / 2;
  381.         if (xdr_setpos(xdrs, currpos)) {
  382.             pos = currpos;
  383.             lowpos = currpos + 1;
  384.         } else {
  385.             highpos = currpos - 1;
  386.         }
  387.     }
  388.     xdr_setpos(xdrs, beginpos);
  389.     cap->rmt_args.arglen = pos - beginpos;
  390.     return (xdr_opaque_parms(xdrs, cap));
  391. }
  392.  
  393. /*
  394.  * Call a remote procedure service
  395.  * This procedure is very quiet when things go wrong.
  396.  * The proc is written to support broadcast rpc.  In the broadcast case,
  397.  * a machine should shut-up instead of complain, less the requestor be
  398.  * overrun with complaints at the expense of not hearing a valid reply ...
  399.  */
  400. static
  401. callit(rqstp, xprt)
  402.     struct svc_req *rqstp;
  403.     SVCXPRT *xprt;
  404. {
  405.     char buf[2000];
  406.     struct rmtcallargs a;
  407.     struct pmaplist *pml;
  408.     u_short port;
  409.     struct sockaddr_in me;
  410.     int socket = -1;
  411.     CLIENT *client;
  412.     struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
  413.     struct timeval timeout;
  414.  
  415.     timeout.tv_sec = 5;
  416.     timeout.tv_usec = 0;
  417.     a.rmt_args.args = buf;
  418.     if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
  419.         return;
  420.     if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
  421.         return;
  422.     port = pml->pml_map.pm_port;
  423.     get_myaddress(&me);
  424.     me.sin_port = htons(port);
  425.     client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
  426.     if (client != (CLIENT *)NULL) {
  427.         if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
  428.             client->cl_auth = authunix_create(au->aup_machname,
  429.                au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
  430.         }
  431.         a.rmt_port = (u_long)port;
  432.         if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
  433.             xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
  434.             svc_sendreply(xprt, xdr_rmtcall_result, &a);
  435.         }
  436.         AUTH_DESTROY(client->cl_auth);
  437.         clnt_destroy(client);
  438.     }
  439.     (void)close(socket);
  440. }
  441.