home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / kboot22.zoo / kboot22.2 / aarpd.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  7KB  |  304 lines

  1. #ifndef lint
  2. static char    *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/aarpd.c,v 1.1 91/01/29 17:36:55 root Exp $";
  3. #endif lint
  4.  
  5. /*
  6.  * $Log:    aarpd.c,v $
  7.  * Revision 1.1  91/01/29  17:36:55  root
  8.  * Initial revision
  9.  * 
  10.  */
  11.  
  12. /*
  13.  * aarpd - Appletalk ARP daemon.  Obtain an appletalk protocol address,
  14.  *       then listen forever, responding to any appletalk probes and
  15.  *       requests sent to us.  Depends on SunOS 4.x NIT interface.
  16.  *
  17.  * Author: Bob Schwartzkopf, The RAND Corporation.  Based on an earlier
  18.  *       version written by Dan Tappan at BBN that ran under SunOS 3.x.
  19.  *
  20.  * Comments, suggestions, patches, bug reports, etc. may be sent to
  21.  * bobs@rand.org.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <syslog.h>
  26. #include <sys/types.h>
  27. #include <sys/errno.h>
  28. #include <sys/socket.h>
  29. #include <sys/fcntl.h>
  30. #include <sys/termios.h>
  31. #include <net/if.h>
  32. #include <netinet/in.h>
  33. #include <netinet/if_ether.h>
  34. #include <rpc/rpc.h>
  35. #include <sys/time.h>
  36. #include <sys/timeb.h>
  37. #include "appletalk.h"
  38. #include "aarpd.h"
  39. #include "config.h"
  40. #include "patchlevel.h"
  41.  
  42. extern char    *rindex ();
  43. int        aarp_read ();
  44.  
  45. extern struct ether_addr    myether;    /* Setup by nit_init    */
  46. extern int            errno;
  47. extern char            *sys_errlist[];
  48.  
  49. #define VERSION        2
  50.  
  51. /*
  52.  * Globals.
  53.  */
  54. char            *progname;
  55. char            *interface = NULL;
  56. struct ether_addr    ebc = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  57. long            atalkaddr;    /* Current appletalk address    */
  58. int            haveaddr = 0;    /* Have appletalk address    */
  59. int            conflict;    /* We're in confict with someone*/
  60. int            detached = 0;    /* Detached from tty        */
  61. int            debug = 0;    /* Debugging            */
  62. struct ether_header    eh;        /* Output ethernet header    */
  63. struct ether_aarp    ap;        /* Output packet        */
  64.  
  65. main (argc, argv)
  66.  
  67. int    argc;
  68. char    **argv;
  69.  
  70. {
  71.   char    c;
  72.   int    i;
  73.   
  74.   if ((progname = rindex (argv[0], '/')) == NULL)
  75.       progname = *argv;
  76.   else
  77.       progname++;
  78.   while (--argc > 0) {
  79.       argv++;
  80.       c = (*argv)[0] == '-' ? (*argv)[1] : (*argv)[0];
  81.       switch (c) {
  82.     case 'd' :
  83.       debug++;
  84.       break;
  85.     case 'i' :
  86.       if (argc <= 1)
  87.           usage ();
  88.       argv++;
  89.       argc--;
  90.       interface = *argv;
  91.       break;
  92.     case 'v' :
  93.       printf ("%s version number %d.%d\n", progname, VERSION, PATCHLEVEL);
  94.       exit (0);
  95.     default :
  96.       usage ();
  97.       }
  98.   }
  99.   if (!debug) {                /* Detach ourselves        */
  100.       detached++;
  101.       if (fork ())
  102.       exit (0);
  103.       if ((i = open ("/dev/tty", O_RDONLY)) >= 0)
  104.       ioctl (i, TIOCNOTTY, 0);
  105.       i = getdtablesize ();
  106.       while (--i >= 0)
  107.       close (i);
  108.       open ("/dev/null", 0);
  109.       dup2 (0, 1);
  110.       dup2 (0, 2);
  111.       openlog (progname, 0, LOG_DAEMON);
  112.   }
  113.   nit_init (interface);
  114.   nit_open (sizeof (ap) + sizeof (eh), AARP);
  115.   aarp_probe ();            /* Get appletalk address    */
  116.   initrpc ();                /* Prepare for RPC        */
  117.   ap.aarp_op = htons (AARPResp);    /* Set up for sending replies    */
  118.   nit_dispatch (aarp_read, 0, &svc_fdset, svc_getreqset, NULL);
  119. }
  120.  
  121. /*
  122.  * usage - Print usage and die.
  123.  */
  124. usage ()
  125.  
  126. {
  127.   fprintf (stderr, "Usage: %s [-d] [-i interface]\n", progname);
  128.   exit (1);
  129. }
  130.  
  131. /*
  132.  * aarp_probe - Get unused appletalk address.  Algorithm is to try each
  133.  *   in turn, probing to see if anyone else is using each address.  When
  134.  *   no one answers a probe, we use that address.  Note this routine
  135.  *   initializes some global data structures (eh, ap), parts of which are
  136.  *   used later by aarp_read ().
  137.  */
  138. aarp_probe ()
  139.  
  140. {
  141.   u_long        spa;
  142.   int            i;
  143.   struct timeval    timeout;
  144.   struct timeb        tstart;
  145.   struct timeb        tcur;
  146.   int            utotal;
  147.   int            ucur;
  148.  
  149.     /* Init ether header        */
  150.   ether_copy (&ebc, &eh.ether_dhost);
  151.   ether_copy (&myether, &eh.ether_shost);
  152.   eh.ether_type = htons (AARP);
  153.     /* Init aarp header        */
  154.   ap.aarp_hrd = htons (H_Ethernet);
  155.   ap.aarp_pro = htons (P_AppleTalk);
  156.   ap.aarp_hln = HL_Ethernet;
  157.   ap.aarp_pln = PL_AppleTalk;
  158.   ap.aarp_op = htons (AARPProbe);
  159.   ether_copy (&myether, &ap.aarp_sha);
  160.   bzero (&ap.aarp_tha, HL_Ethernet);
  161.   nit_timeout (APrbTicks, &timeout);
  162.   utotal = timeout.tv_sec * 1000000 + timeout.tv_usec;
  163.   for (atalkaddr = 1; atalkaddr < 254; atalkaddr++) {
  164.       spa = htonl (atalkaddr);
  165.       bcopy (&spa, ap.aarp_spa, PL_AppleTalk);
  166.       bcopy (&spa, ap.aarp_tpa, PL_AppleTalk);
  167.       conflict = 0;
  168.       for (i = 0; !conflict && i < APrbTries; i++) {
  169.       nit_write ((caddr_t) &eh, (caddr_t) &ap, sizeof ap);
  170.       ftime (&tstart);
  171.       do {
  172.           nit_dispatch (aarp_read, 1, NULL, NULL, &timeout);
  173.           ftime (&tcur);
  174.           ucur = (tcur.time - tstart.time) * 1000000 +
  175.              (tcur.millitm - tstart.millitm) * 1000;
  176.       } while (!conflict && utotal > ucur);
  177.       }
  178.       if (!conflict) {
  179.       if (debug)
  180.           fprintf (stderr, "aarp_probe: Using appletalk address %d\n",
  181.                atalkaddr);
  182.       break;
  183.       }
  184.   }
  185.   if (conflict) {
  186.       logerr ("aarp_probe: Couldn't find appletalk address, exiting...\n");
  187.       exit (1);
  188.   }
  189.   haveaddr++;
  190. }
  191.  
  192. /*
  193.  * aarp_read - Handle AARP response packets.
  194.  */
  195. aarp_read (p, pl)
  196.  
  197. struct aarp_packet    *p;
  198. int            pl;
  199.  
  200. {
  201.   int    op;
  202.   long    spa;
  203.   long    tpa;
  204.  
  205.   if (pl != sizeof (*p)) {
  206.       if (debug)
  207.           fprintf (stderr, "aarp_read: Truncated packet len %d\n", pl);
  208.       return;
  209.   }
  210.   op = ntohs (p->ap_op);
  211.   bcopy ((caddr_t) p->ap_spa, &spa, PL_AppleTalk);
  212.   spa = ntohl (spa);
  213.   switch (op) {
  214.     case AARPProbe :
  215.     case AARPReq :
  216.       bcopy ((caddr_t) p->ap_tpa, &tpa, PL_AppleTalk);
  217.       tpa = ntohl (tpa);
  218.       if (haveaddr && tpa == atalkaddr) {
  219.     /*
  220.      * Most of the output header and packet (eh, ap) should already be
  221.      * set up since it was used for probing initially.  Should only need
  222.      * to fill in destination addresses.
  223.      */
  224.       ether_copy (&p->ap_sha, &eh.ether_dhost);
  225.       ether_copy (&p->ap_sha, &ap.aarp_tha);
  226.       bcopy (p->ap_spa, ap.aarp_tpa, PL_AppleTalk);
  227.       if (debug) {
  228.           fprintf (stderr, "aarp_read: Replying to %s from %d (%s)\n",
  229.               op == AARPProbe ? "probe" : "request",
  230.               spa, ether_ntoa (&p->ap_sha));
  231.       }
  232.       nit_write ((caddr_t) &eh, (caddr_t) &ap, sizeof ap);
  233.       }
  234.       break;
  235.  
  236.     case AARPResp :
  237.       if (debug)
  238.       fprintf (stderr, "aarp_read: Reply from %d (%s)\n",
  239.            spa, ether_ntoa (&p->ap_sha));
  240.       if (!haveaddr && spa == atalkaddr)
  241.           conflict++;
  242.       break;
  243.  
  244.     default :
  245.       logerr ("aarp_read: Unknown AARP operation %d\n", op);
  246.   }
  247. }
  248.  
  249. /*
  250.  * getaa - Return appletalk address for this host.
  251.  */
  252. getaa (request, xprt)
  253.  
  254. struct svc_req    *request;
  255. SVCXPRT        *xprt;
  256.  
  257. {
  258.   struct sockaddr_in    *sa;
  259.  
  260.   if (debug) {
  261.       sa = svc_getcaller (xprt);
  262.       fprintf (stderr, "getaa: Returning %d to %s\n",
  263.           atalkaddr, inet_ntoa (sa->sin_addr));
  264.   }
  265.   switch (request->rq_proc) {
  266.     case NULLPROC:
  267.       if (!svc_sendreply (xprt, xdr_void, 0)) {
  268.       logerr ("getaa(NULLPROC): svc_sendreply failed\n");
  269.       exit (1);
  270.       }
  271.       break;
  272.  
  273.     case GETAAPROC:
  274.       if (!svc_sendreply (xprt, xdr_u_long, (caddr_t) &atalkaddr)) {
  275.       logerr ("getaa(GETAAPROC): svc_sendreply failed\n");
  276.       exit (1);
  277.       }
  278.       break;
  279.  
  280.     default:
  281.       svcerr_noproc (xprt);
  282.       break;
  283.   }
  284. }
  285.  
  286. /*
  287.  * Initialize RPC stuff.
  288.  */
  289. initrpc ()
  290.  
  291. {
  292.   SVCXPRT    *xprt;
  293.  
  294.   if ((xprt = svcudp_create (RPC_ANYSOCK)) == NULL) {
  295.       logerr ("initrpc: svcudp_create failed\n");
  296.       exit (1);
  297.   }
  298.   pmap_unset (GETAAPROG, GETAAVERS);
  299.   if (!svc_register (xprt, GETAAPROG, GETAAVERS, getaa, IPPROTO_UDP)) {
  300.       logerr ("initrpc: Can't register %d %d\n", GETAAPROG, GETAAVERS);
  301.       exit (1);
  302.   }
  303. }
  304.