home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / comm / amitcp-3.0ß2.lha / AmiTCP / src / util / portmap / portmap.c next >
C/C++ Source or Header  |  1994-05-03  |  12KB  |  498 lines

  1. RCS_ID_C="$Id: portmap.c,v 3.9 1994/05/02 19:52:55 jraja Exp $";
  2. /*
  3.  * portmap.c -- implements the program, version to port number mapping for rpc
  4.  */
  5.  
  6. #include "portmap_rev.h"
  7.  
  8. static const char version[] = VERSTAG
  9. " Copyright © 1994 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  10. "Helsinki University of Technology, Finland.\n"
  11. "Copyright © 1990 The Regents of the University of California.\n"
  12. "All rights reserved.\n";
  13.  
  14. /****** netutil.doc/portmap *************************************************
  15.     NAME
  16.         portmap - DARPA port to RPC program number mapper
  17.  
  18.     SYNOPSIS
  19.         AmiTCP:bin/portmap
  20.  
  21.     DESCRIPTION
  22.         `portmap' is a server that converts RPC program numbers into DARPA
  23.         protocol port numbers.  It must be running in order to make RPC
  24.         calls.  When an RPC server is started, it will tell `portmap' what
  25.         port number it is listening to, and what RPC program numbers it is
  26.         prepared to serve.  When a client wishes to make an RPC call to a
  27.         given program number, it will first contact `portmap' on the
  28.         server machine to determine the port number where RPC packets
  29.         should be sent.  Normally, standard RPC servers are started by
  30.         `inetd', so `portmap' must be started before `inetd' is invoked.
  31.  
  32.     SEE ALSO
  33.         netutil.doc/rpcinfo
  34.  
  35.     BUGS
  36.         If `portmap' crashes, all servers must be restarted.
  37.  
  38. *****************************************************************************
  39. */
  40.  
  41. /*
  42.  * @(#)portmap.c 5.4 (Berkeley) 4/19/91
  43.  * @(#)portmap.c 2.3 88/08/11 4.0 RPCSRC
  44.  * @(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
  45.  */
  46.  
  47. #include <rpc/rpc.h>
  48. #include <rpc/pmap_prot.h>
  49. #include <sys/syslog.h>
  50. #include <sys/socket.h>
  51. #include <sys/ioctl.h>
  52. #include <netdb.h>
  53. #include <errno.h>
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <string.h>
  57. #include <signal.h>
  58.  
  59. void reg_service(struct svc_req *rqstp, SVCXPRT *xprt);
  60. static void callit(struct svc_req *rqstp, SVCXPRT *xprt);
  61.  
  62. struct pmaplist *pmaplist;
  63. int debugging = 0;
  64.  
  65. main(int argc, char **argv)
  66. {
  67.     SVCXPRT *xprt;
  68.     int sock, c;
  69.     struct sockaddr_in addr = { 0 };
  70.     int len = sizeof(struct sockaddr_in);
  71.     register struct pmaplist *pml;
  72.  
  73.     signal(SIGINT, SIG_IGN); /* Prevent ANSI Signal handling */
  74.  
  75.     while ((c = getopt(argc, argv, "d")) != EOF) {
  76.         switch (c) {
  77.  
  78.         case 'd':
  79.             debugging = 1;
  80.             break;
  81.  
  82.         default:
  83.             (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]);
  84.             exit(1);
  85.         }
  86.     }
  87.  
  88.     openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID,
  89.         LOG_DAEMON);
  90. #ifndef amigados
  91.     if (!debugging && daemon(0, 0)) {
  92.         (void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
  93.         exit(1);
  94.     }
  95. #else
  96.     /*
  97.      * We could probably detach here, but don't bother now...
  98.      */
  99. #endif
  100.  
  101.     if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  102.         syslog(LOG_ERR, "cannot create udp socket: %m");
  103.         exit(1);
  104.     }
  105.  
  106.     addr.sin_addr.s_addr = 0;
  107.     addr.sin_family = AF_INET;
  108.     addr.sin_port = htons(PMAPPORT);
  109.     if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
  110.         syslog(LOG_ERR, "cannot bind udp: %m");
  111.         exit(1);
  112.     }
  113.  
  114.     if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
  115.         syslog(LOG_ERR, "couldn't do udp_create");
  116.         exit(1);
  117.     }
  118.     /* make an entry for ourself */
  119.     pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
  120.     pml->pml_next = 0;
  121.     pml->pml_map.pm_prog = PMAPPROG;
  122.     pml->pml_map.pm_vers = PMAPVERS;
  123.     pml->pml_map.pm_prot = IPPROTO_UDP;
  124.     pml->pml_map.pm_port = PMAPPORT;
  125.     pmaplist = pml;
  126.  
  127.     if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
  128.         syslog(LOG_ERR, "cannot create tcp socket: %m");
  129.         exit(1);
  130.     }
  131.     if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
  132.         syslog(LOG_ERR, "cannot bind udp: %m");
  133.         exit(1);
  134.     }
  135.     if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
  136.         == (SVCXPRT *)NULL) {
  137.         syslog(LOG_ERR, "couldn't do tcp_create");
  138.         exit(1);
  139.     }
  140.     /* make an entry for ourself */
  141.     pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
  142.     pml->pml_map.pm_prog = PMAPPROG;
  143.     pml->pml_map.pm_vers = PMAPVERS;
  144.     pml->pml_map.pm_prot = IPPROTO_TCP;
  145.     pml->pml_map.pm_port = PMAPPORT;
  146.     pml->pml_next = pmaplist;
  147.     pmaplist = pml;
  148.  
  149.     (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
  150.  
  151.     svc_run();
  152.     syslog(LOG_ERR, "svc_run returned unexpectedly");
  153.     exit(0);
  154. }
  155.  
  156. /*
  157.  * Overrides the strlib perror
  158.  */
  159. void
  160. perror(const char *what)
  161. {
  162.     syslog(LOG_ERR, "%s: %m", what);
  163. }
  164.  
  165. static struct pmaplist *
  166. find_service(u_long prog, u_long vers, u_long prot)
  167. {
  168.     register struct pmaplist *hit = NULL;
  169.     register struct pmaplist *pml;
  170.  
  171.     for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
  172.         if ((pml->pml_map.pm_prog != prog) ||
  173.             (pml->pml_map.pm_prot != prot))
  174.             continue;
  175.         hit = pml;
  176.         if (pml->pml_map.pm_vers == vers)
  177.             break;
  178.     }
  179.     return (hit);
  180. }
  181.  
  182. /* 
  183.  * 1 OK, 0 not
  184.  */
  185. void
  186. reg_service(struct svc_req *rqstp, SVCXPRT *xprt)
  187. {
  188.     struct pmap reg;
  189.     struct pmaplist *pml, *prevpml, *fnd;
  190.     int ans, port;
  191.     caddr_t t;
  192.     
  193.     if (debugging)
  194.         (void) fprintf(stderr, "server: about do a switch\n");
  195.     switch (rqstp->rq_proc) {
  196.  
  197.     case PMAPPROC_NULL:
  198.         /*
  199.          * Null proc call
  200.          */
  201.         if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
  202.             exit(20);
  203.         }
  204.         break;
  205.  
  206.     case PMAPPROC_SET:
  207.         /*
  208.          * Set a program,version to port mapping
  209.          */
  210.         if (!svc_getargs(xprt, xdr_pmap, ®))
  211.             svcerr_decode(xprt);
  212.         else {
  213.             /*
  214.              * check to see if already used
  215.              * find_service returns a hit even if
  216.              * the versions don't match, so check for it
  217.              */
  218.             fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
  219.             if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
  220.                 if (fnd->pml_map.pm_port == reg.pm_port) {
  221.                     ans = 1;
  222.                     goto done;
  223.                 }
  224.                 else {
  225.                     ans = 0;
  226.                     goto done;
  227.                 }
  228.             } else {
  229.                 /* 
  230.                  * add to END of list
  231.                  */
  232.                 pml = (struct pmaplist *)
  233.                     malloc((u_int)sizeof(struct pmaplist));
  234.                 pml->pml_map = reg;
  235.                 pml->pml_next = 0;
  236.                 if (pmaplist == 0) {
  237.                     pmaplist = pml;
  238.                 } else {
  239.                     for (fnd= pmaplist; fnd->pml_next != 0;
  240.                         fnd = fnd->pml_next);
  241.                     fnd->pml_next = pml;
  242.                 }
  243.                 ans = 1;
  244.             }
  245.         done:
  246.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  247.                 debugging) {
  248.                 (void) fprintf(stderr, "svc_sendreply\n");
  249.                 exit(20);
  250.             }
  251.         }
  252.         break;
  253.  
  254.     case PMAPPROC_UNSET:
  255.         /*
  256.          * Remove a program,version to port mapping.
  257.          */
  258.         if (!svc_getargs(xprt, xdr_pmap, ®))
  259.             svcerr_decode(xprt);
  260.         else {
  261.             ans = 0;
  262.             for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
  263.                 if ((pml->pml_map.pm_prog != reg.pm_prog) ||
  264.                     (pml->pml_map.pm_vers != reg.pm_vers)) {
  265.                     /* both pml & prevpml move forwards */
  266.                     prevpml = pml;
  267.                     pml = pml->pml_next;
  268.                     continue;
  269.                 }
  270.                 /* found it; pml moves forward, prevpml stays */
  271.                 ans = 1;
  272.                 t = (caddr_t)pml;
  273.                 pml = pml->pml_next;
  274.                 if (prevpml == NULL)
  275.                     pmaplist = pml;
  276.                 else
  277.                     prevpml->pml_next = pml;
  278.                 free(t);
  279.             }
  280.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  281.                 debugging) {
  282.                 (void) fprintf(stderr, "svc_sendreply\n");
  283.                 exit(20);
  284.             }
  285.         }
  286.         break;
  287.  
  288.     case PMAPPROC_GETPORT:
  289.         /*
  290.          * Lookup the mapping for a program,version and return its port
  291.          */
  292.         if (!svc_getargs(xprt, xdr_pmap, ®))
  293.             svcerr_decode(xprt);
  294.         else {
  295.             fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
  296.             if (fnd)
  297.                 port = fnd->pml_map.pm_port;
  298.             else
  299.                 port = 0;
  300.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
  301.                 debugging) {
  302.                 (void) fprintf(stderr, "svc_sendreply\n");
  303.                 exit(20);
  304.             }
  305.         }
  306.         break;
  307.  
  308.     case PMAPPROC_DUMP:
  309.         /*
  310.          * Return the current set of mapped program,version
  311.          */
  312.         if (!svc_getargs(xprt, xdr_void, NULL))
  313.             svcerr_decode(xprt);
  314.         else {
  315.             if ((!svc_sendreply(xprt, xdr_pmaplist,
  316.                 (caddr_t)&pmaplist)) && debugging) {
  317.                 (void) fprintf(stderr, "svc_sendreply\n");
  318.                 exit(20);
  319.             }
  320.         }
  321.         break;
  322.  
  323.     case PMAPPROC_CALLIT:
  324.         /*
  325.          * Calls a procedure on the local machine.  If the requested
  326.          * procedure is not registered this procedure does not return
  327.          * error information!!
  328.          * This procedure is only supported on rpc/udp and calls via 
  329.          * rpc/udp.  It passes null authentication parameters.
  330.          */
  331.         callit(rqstp, xprt);
  332.         break;
  333.  
  334.     default:
  335.         svcerr_noproc(