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

  1. #ifndef lint
  2. static char    *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/kboot.c,v 1.3 91/02/13 11:47:07 root Exp $";
  3. #endif lint
  4.  
  5. /*
  6.  * $Log:    kboot.c,v $
  7.  * Revision 1.3  91/02/13  11:47:07  root
  8.  * Accept rpc requests from privileged ports only.
  9.  * 
  10.  * Revision 1.2  91/02/12  19:27:39  root
  11.  * Remove -m option, add -t.
  12.  * 
  13.  * Revision 1.1  91/01/29  17:37:26  root
  14.  * Initial revision
  15.  * 
  16.  */
  17.  
  18. /*
  19.  * kboot - Boot and configure fastpaths over an ethernet.  Depends on NIT
  20.  *       interface in SunOS 4.x.
  21.  *
  22.  * Author: Bob Schwartzkopf, The RAND Corporation.  Based on an earlier
  23.  *       version written by Dan Tappan at BBN that ran under SunOS 3.x.
  24.  *
  25.  * Comments, suggestions, patches, bug reports, etc. may be sent to
  26.  * bobs@rand.org.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <syslog.h>
  31. #include <fcntl.h>
  32. #include <signal.h>
  33. #include <sys/types.h>
  34. #include <sys/socket.h>
  35. #include <sys/errno.h>
  36. #include <sys/termios.h>
  37. #include <netdb.h>
  38. #include <net/if.h>
  39. #include <netinet/in.h>
  40. #include <netinet/if_ether.h>
  41. #include <rpc/rpc.h>
  42. #include "appletalk.h"
  43. #include "cmdidx.h"
  44. #include "kbox.h"
  45. #include "config.h"
  46. #include "patchlevel.h"
  47. #include "kboot.h"
  48.  
  49. #define VERSION        2
  50.  
  51. extern char            *rindex ();
  52. struct kbox            *get_kbox ();
  53. extern int            errno;
  54. extern char            *sys_errlist[];
  55. extern struct ether_addr    myether;
  56.  
  57. /*
  58.  * Globals.
  59.  */
  60. char            *progname;
  61. struct ether_addr    ebc = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  62. struct ether_header    eh;
  63. char            *interface = NULL;
  64. long            atalkaddr;
  65. char            *etcdir = ETCDIR;
  66. int            detached = 0;
  67. int            debug = 0;
  68. int            watchf = 0;
  69. int            downloadf = 0;
  70. int            configf = 0;
  71. int            liststatef = 0;
  72. int            savestatef = 0;
  73. int            resetf = 0;
  74. int            rbootf = 0;
  75. struct kbox        *kboxtab[HTSIZE];
  76. int            numkbox;
  77. unsigned char        kboxstate[STATE_LENGTH];
  78. unsigned char        newstate[STATE_LENGTH];
  79. unsigned char        zonedata[MAXZONELIST];
  80. int            zonelen;
  81. int            pinginterval = PINGINTERVAL;
  82. unsigned char        *zonelistp;
  83.  
  84. main (argc, argv)
  85.  
  86. int    argc;
  87. char    **argv;
  88.  
  89. {
  90.   int        i;
  91.   char        c;
  92.   char        *name = NULL;
  93.   struct kbox    *kp;
  94.   char        *errmsg;
  95.   char        *rhost;
  96.  
  97.   if ((progname = rindex (argv[0], '/')) == NULL)
  98.       progname = *argv;
  99.   else
  100.       progname++;
  101.   while (--argc > 0) {
  102.       argv++;
  103.       c = (*argv)[0] == '-' ? (*argv)[1] : (*argv)[0];
  104.       switch (c) {
  105.     case 'b' :
  106.       if (argc <= 1)
  107.           usage ();
  108.       argv++; argc--;
  109.       downloadf++;
  110.       name = *argv;
  111.       break;
  112.     case 'c' :
  113.       if (argc <= 1)
  114.           usage ();
  115.       argv++; argc--;
  116.       configf++;
  117.       name = *argv;
  118.       break;
  119.     case 'd' :
  120.       debug++;
  121.       break;
  122.     case 'i' :
  123.       if (argc <= 1)
  124.           usage ();
  125.       argv++; argc--;
  126.       interface = *argv;
  127.       break;
  128.     case 'l' :
  129.       if (argc <= 1)
  130.           usage ();
  131.       argv++; argc--;
  132.       liststatef++;
  133.       name = *argv;
  134.       break;
  135.     case 'p' :
  136.       if (argc <= 1)
  137.           usage ();
  138.       argv++; argc--;
  139.       pinginterval = atoi (*argv);
  140.       break;
  141.     case 'r' :
  142.       if (argc <= 1)
  143.           usage ();
  144.       argv++; argc--;
  145.       resetf++;
  146.       name = *argv;
  147.       break;
  148.     case 's' :
  149.       if (argc <= 1)
  150.           usage ();
  151.       argv++; argc--;
  152.       savestatef++;
  153.       name = *argv;
  154.       break;
  155.     case 't' :
  156.       if (argc <= 1)
  157.           usage ();
  158.       argv++; argc--;
  159.       rbootf++;
  160.       name = *argv;
  161.       if (argc > 1 && *argv[1] != '-') {
  162.           argv++; argc--;
  163.           rhost = *argv;
  164.       } else
  165.           rhost = NULL;
  166.       break;
  167.     case 'v' :
  168.       printf ("%s version %d.%d\n", progname, VERSION, PATCHLEVEL);
  169.       exit (0);
  170.     case 'w' :
  171.       watchf++;
  172.       break;
  173.     default :
  174.       usage ();
  175.       break;
  176.       }
  177.   }
  178.   if (rbootf) {
  179.       kboot_reload (name, rhost);
  180.       exit (0);
  181.   }
  182.   if (watchf && !debug) {        /* Detach ourselves        */
  183.       detached++;
  184.       if (fork ())
  185.       exit (0);
  186.       if ((i = open ("/dev/tty", O_RDONLY)) >= 0)
  187.       ioctl (i, TIOCNOTTY, 0);
  188.       i = getdtablesize ();
  189.       while (--i >= 0)
  190.       close (i);
  191.       open ("/dev/null", 0);
  192.       dup2 (0, 1);
  193.       dup2 (0, 2);
  194.       openlog (progname, 0, LOG_DAEMON);
  195.       writepid ();
  196.   }
  197.   if ((i = getaa (NULL, &atalkaddr)) != 0) {
  198.       errmsg = clnt_sperrno (i);
  199.       logerr ("getaa: %s\n", errmsg);
  200.       exit (1);
  201.   }
  202.   if (debug)
  203.       fprintf (stderr, "main: Using appletalk address %d\n", atalkaddr);
  204.   nit_init (interface);
  205.   ht_init ();
  206.   readcf ();
  207.   ether_copy (&myether, &eh.ether_shost);
  208.   eh.ether_type = htons (P_AppleTalk);
  209.   if (watchf)
  210.       watch ();
  211.   else  {
  212.       if (!name)
  213.       usage ();
  214.       if (!(kp = get_kbox (name))) {
  215.       logerr ("main: No such kbox %s\n", name);
  216.       exit (1);
  217.       }
  218.       nit_open (0, P_AppleTalk);
  219.       if (downloadf)
  220.       download (kp);
  221.       else if (configf)
  222.       config (kp);
  223.       else if (savestatef)
  224.       savestate (kp);
  225.       else if (resetf)
  226.       reset (kp);
  227.       else if (liststatef)
  228.       liststate (kp);
  229.   }
  230.   exit (0);
  231. }
  232.  
  233. /*
  234.  * reconfig - Free old kbox hash table and reread config file.
  235.  */
  236. reconfig ()
  237.  
  238. {
  239.   if (debug)
  240.       fprintf (stderr, "reconfig: Reading config file\n");
  241.   ht_free ();
  242.   readcf ();
  243. }
  244.  
  245. /*
  246.  * ping - Ping kboxes, reload any that don't respond or any that've
  247.  *   been flagged for reloading.
  248.  */
  249. ping ()
  250.  
  251. {
  252.   int        i;
  253.   struct kbox    *kp;
  254.  
  255.   for (i = 0; i < HTSIZE; i++)
  256.       for (kp = kboxtab[i]; kp; kp = kp->nxt)
  257.       if (kp->reload || !icmp_ping (kp)) {
  258.           logerr ("ping: Reloading %s\n", kp->name);
  259.           nit_open (0, P_AppleTalk);
  260.           download (kp);
  261.           kp->reload = 0;
  262.           nit_close ();
  263.       }
  264.   alarm (pinginterval);
  265. }
  266.  
  267. /*
  268.  * watch - Watch kboxes, rebooting if not answering pings or if someone
  269.  *   asks us to.
  270.  */
  271. watch ()
  272.  
  273. {
  274.   signal (SIGHUP, reconfig);
  275.   signal (SIGALRM, ping);
  276.   icmp_init ();
  277.   rpc_init ();
  278.   alarm (pinginterval);
  279.   svc_run ();
  280. }
  281.  
  282. /*
  283.  * download - Download kstar to kbox.
  284.  */
  285. download (kp)
  286.  
  287. struct kbox    *kp;
  288.  
  289. {
  290.   int    i;
  291.  
  292.   if ((i = readstate (kp, newstate, zonedata)) != STATE_LENGTH) {
  293.       logerr ("config: State file wrong length %d for %s\n", i, kp->name);
  294.       return;
  295.   }
  296.   if (send_who () < 0)
  297.       return;
  298.   if (send_reset (kp) < 0)
  299.       return;
  300.   sleep (3);            /* Give kbox time to reset    */
  301.   if (send_who () < 0)
  302.       return;
  303.   if (send_promram (kp) <= 0)
  304.       return;
  305.   if (send_boot (kp, zonedata, zonelen) <= 0)
  306.       return;
  307.   if (send_getstate (kp) <= 0)
  308.       return;
  309.   newstate[O_NODE] = kboxstate[O_NODE];
  310.   newstate[O_ETNODE] = kboxstate[O_ETNODE];
  311.   strcpy (&newstate[O_NAME], kp->name);
  312.   strcpy (&newstate[O_FILE], kp->bootfile);
  313.   strcpy (&newstate[O_CONFIG], kp->conffile);
  314.   if (debug)
  315.       fprintf (stderr, "download: Setting zonelist to %X\n", zonelistp);
  316.   bcopy (&zonelistp, &newstate[O_ZONELIST], sizeof (zonelistp));
  317.   if (send_putstate (kp) <= 0)
  318.       return;
  319.   send_execute (kp);
  320. }
  321.  
  322. /*
  323.  * config - Config kbox.
  324.  */
  325. config (kp)
  326.  
  327. struct kbox    *kp;
  328.  
  329. {
  330.   int    i;
  331.  
  332.   if ((i = readstate (kp, newstate, zonedata)) != STATE_LENGTH) {
  333.       logerr ("config: State file wrong length %d for %s\n", i, kp->name);
  334.       return;
  335.   }
  336.   if (send_who () < 0)
  337.       return;
  338.   if (send_exprom (kp) < 0)
  339.       return;
  340.   if (send_who () < 0)
  341.       return;
  342.   if (send_promram (kp) <= 0)
  343.       return;
  344.   if (send_getstate (kp) <= 0)
  345.       return;
  346.   newstate[O_NODE] = kboxstate[O_NODE];
  347.   newstate[O_ETNODE] = kboxstate[O_ETNODE];
  348.   strncpy (&newstate[O_NAME], &kboxstate[O_NAME], NAMELEN);
  349.   strncpy (&newstate[O_FILE], &kboxstate[O_FILE], NAMELEN);
  350.   strncpy (&newstate[O_CONFIG], kp->conffile, CONFIGLEN);
  351.   if (send_putstate (kp) <= 0)
  352.       return;
  353.   if (send_who () < 0)
  354.       return;
  355.   send_execute (kp);
  356. }
  357.  
  358. /*
  359.  * savestate - Read state for kbox and save to file.
  360.  */
  361. savestate (kp)
  362.  
  363. struct kbox    *kp;
  364.  
  365. {
  366.   char    fn[MAXFN];
  367.   int    fd;
  368.  
  369.   if (send_who () < 0)
  370.       return;
  371.   if (send_promram (kp) <= 0)
  372.       return;
  373.   if (send_getstate (kp) <= 0)
  374.       return;
  375.   sprintf (fn, "%s/%s.state", etcdir, kp->name);
  376.   if ((fd = open (fn, O_WRONLY|O_CREAT, 0644)) == -1) {
  377.       logerr ("savestate: %s - %s\n", fn, sys_errlist[errno]);
  378.       return;
  379.   }
  380.   write (fd, kboxstate, STATE_LENGTH);
  381.   close (fd);
  382. }
  383.  
  384. /*
  385.  * liststate - Read state for kbox and print.
  386.  */
  387. liststate (kp)
  388.  
  389. struct kbox    *kp;
  390.  
  391. {
  392.   char    fn[MAXFN];
  393.   int    fd;
  394.  
  395.   if (send_who () < 0)
  396.       return;
  397.   if (send_promram (kp) <= 0)
  398.       return;
  399.   if (send_getstate (kp) <= 0)
  400.       return;
  401.   show_state (stdout, kboxstate);
  402. }
  403.  
  404. /*
  405.  * reset - Reset kbox.
  406.  */
  407. reset (kp)
  408.  
  409. struct kbox    *kp;
  410.  
  411. {
  412.   if (send_who () < 0)
  413.       return;
  414.   send_reset (kp);
  415. }
  416.  
  417. /*
  418.  * writepid - Save pid to file.
  419.  */
  420. writepid ()
  421.  
  422. {
  423.   char    fn[MAXFN];
  424.   FILE    *f;
  425.  
  426.   sprintf (fn, "%s/kboot.pid", etcdir);
  427.   if ((f = fopen (fn, "w")) == NULL)
  428.       logerr ("main: Can't write pid file %s\n", fn);
  429.   else {
  430.       fprintf (f, "%d\n", getpid ());
  431.       fclose (f);
  432.   }
  433. }
  434.  
  435. /*
  436.  * usage - Print usage and die.
  437.  */
  438. usage ()
  439.  
  440. {
  441.   fprintf (stderr, "Usage: %s options\n", progname);
  442.   exit (1);
  443. }
  444.  
  445. /*
  446.  * hash - Return hash index into kbox hash table.
  447.  */
  448. int hash (s)
  449.  
  450. register char    *s;
  451.  
  452. {
  453.   register int    h;
  454.  
  455.   while (*s)
  456.       h = (h << 1) ^ *s++;
  457.   return (h % HTSIZE);
  458. }
  459.  
  460. /*
  461.  * ht_init - Init kbox hash table.
  462.  */
  463. ht_init ()
  464.  
  465. {
  466.   int    i;
  467.  
  468.   for (i = 0; i < HTSIZE; i++)
  469.       kboxtab[i] = NULL;
  470. }
  471.  
  472. /*
  473.  * ht_free - Clear out hash table.
  474.  */
  475. ht_free ()
  476.  
  477. {
  478.   int        i;
  479.   struct kbox    *kp;
  480.   struct kbox    *nkp;
  481.  
  482.   for (i = 0; i < HTSIZE; i++) {
  483.       for (kp = kboxtab[i]; kp; kp = nkp) {
  484.       nkp = kp->nxt;
  485.       free (kp);
  486.       }
  487.       kboxtab[i] = NULL;
  488.   }
  489. }
  490.       
  491. /*
  492.  * add_kbox - Add kbox to hash table.
  493.  */
  494. add_kbox (name, bootfile)
  495.  
  496. char    *name;
  497. char    *bootfile;
  498.  
  499. {
  500.   int            h;
  501.   struct kbox        *kp;
  502.   char            *p;
  503.   struct hostent    *he;
  504.   struct ether_addr    e;
  505.  
  506.   if (ether_hostton (name, &e) != 0) {
  507.       logerr ("add_kbox: Can't find %s in ethers file\n", name);
  508.       return;
  509.   }
  510.   if ((he = gethostbyname (name)) == NULL) {
  511.       logerr ("add_kbox: Can't find %s in host table\n", name);
  512.       return;
  513.   }
  514.   if ((kp = (struct kbox *) malloc (sizeof (struct kbox))) == NULL) {
  515.       logerr ("add_kbox: No memory for %s in table\n", name);
  516.       exit (1);
  517.   }
  518.   h = hash (name);
  519.   kp->nxt = kboxtab[h];
  520.   kboxtab[h] = kp;
  521.   kp->reload = 0;
  522.   strcpy (kp->name, name);
  523.   strcpy (kp->bootfile, bootfile);
  524.   kp->aa = AT_Broadcast;    /* Set to bogus value until get from kb    */
  525.   ether_copy (&e, &kp->ea);
  526.   bcopy (he->h_addr, &kp->ip.sin_addr.s_addr, he->h_length);
  527. }
  528.  
  529. /*
  530.  * get_kbox - Find kbox in hash table.
  531.  */
  532. struct kbox *get_kbox (name)
  533.  
  534. char    *name;
  535.  
  536. {
  537.   register struct kbox    *kp;
  538.  
  539.   kp = kboxtab[hash (name)];
  540.   while (kp)
  541.       if (!strcmp (name, kp->name))
  542.       return (kp);
  543.       else
  544.       kp = kp->nxt;
  545.   return (NULL);
  546. }
  547.  
  548. /*
  549.  * readcf - Read config file.
  550.  */
  551. readcf ()
  552.  
  553.  
  554. {
  555.   FILE    *f;
  556.   char    fn[MAXFN];
  557.   char    name[MAXHOSTNAME];
  558.   char    bootfile[MAXFN];
  559.  
  560.   sprintf (fn, "%s/kbootcf", etcdir);
  561.   if ((f = fopen (fn, "r")) == NULL) {
  562.       logerr ("readcf: %s - %s\n", fn, sys_errlist[errno]);
  563.       exit (1);
  564.   }
  565.   while (!feof (f)) {
  566.       numkbox++;
  567.       if (fscanf (f, "%s %s\n", name, bootfile) != 2) {
  568.       logerr ("readcf: Badly formatted config file '%s' line %d\n",
  569.           fn, numkbox);
  570.       exit (1);
  571.       }
  572.       add_kbox (name, bootfile);
  573.   }
  574.   fclose (f);
  575. }
  576.  
  577. /*
  578.  * readstate - Read kbox config.  Returns length.  Looks for ascii file
  579.  *   generated by fastpath manager first, then looks for binary file
  580.  *   made by savestate().
  581.  */
  582. int readstate (kp, state, zonedata)
  583.  
  584. struct kbox    *kp;
  585. unsigned char    *state;
  586. unsigned char    *zonedata;
  587.  
  588. {
  589.   FILE        *f;
  590.   int        c;
  591.   unsigned char    *cp;
  592.   int        fd;
  593.   int        len;
  594.  
  595.   zonelen = 0;
  596.   sprintf (kp->conffile, "%s/%s.config", etcdir, kp->name);
  597.   if ((f = fopen (kp->conffile, "r")) == NULL) {
  598.       sprintf (kp->conffile, "%s/%s.state", etcdir, kp->name);
  599.       if ((fd = open (kp->conffile, O_RDONLY)) == -1) {
  600.       logerr ("readstate: Can't read state file for %s\n", kp->name);
  601.       return;
  602.       }
  603.       len = read (fd, state, STATE_LENGTH);
  604.       close (fd);
  605.   } else {
  606.       cp = state;
  607.       len = 0;
  608.       while ((c = fgetc (f)) >= 0) {
  609.       if (c == '*') {
  610.           while ((c = fgetc (f)) >= 0 && c != '\n' && c != '\r');
  611.           continue;
  612.       }
  613.       while (c >= 0 && c != '\n' && c != '\r') {
  614.           *cp = fromhex (c) << 4;
  615.           *cp++ |= fromhex (c = fgetc (f));
  616.           c = fgetc (f);
  617.       }
  618.       if (cp - state == STATE_LENGTH) {
  619.           zonelen = readzones (f, c, zonedata);
  620.           break;
  621.       }
  622.       }
  623.       fclose (f);
  624.       len = cp - state;
  625.   }
  626.   if (zonelen == 0) {
  627.       zonedata[0] = 0;
  628.       zonedata[1] = 0;
  629.       zonelen = 2;
  630.   }
  631.   return (len);
  632. }
  633.  
  634. /*
  635.  * readzones - Read zone list from config file, c is first char.
  636.  */
  637. int readzones (f, c, zonedata)
  638.  
  639. FILE        *f;
  640. int        c;
  641. unsigned char    *zonedata;
  642.  
  643. {
  644.   unsigned char    *cp;
  645.   unsigned char    *lenp;
  646.   short        numzones;
  647.  
  648.   cp = zonedata + 2;            /* Skip # zones        */
  649.   numzones = 0;
  650.   while ((c = fgetc (f)) >= 0) {
  651.       if (c == '\r' || c == '\n')
  652.       continue;
  653.       if (c == '*') {
  654.       while ((c = fgetc (f)) >= 0 && c != '\n' && c != '\r');
  655.       continue;
  656.       }
  657.       lenp = cp++;
  658.       while (c >= 0 && c != '\n' && c != '\r') {
  659.       *cp++ = c;
  660.       c = fgetc (f);
  661.       }
  662.       *lenp = (cp - lenp) - 1;
  663.       numzones++;
  664.   }
  665.   bcopy (&numzones, zonedata, sizeof (numzones));
  666.   return (cp - zonedata);
  667. }
  668.  
  669. /*
  670.  * fromhex - Convert char from hex to decimal.
  671.  */
  672. int fromhex (c)
  673.  
  674. char    c;
  675.  
  676. {
  677.   if (c >= '0' && c <= '9')
  678.       return (c - '0');
  679.   else if (c >= 'a' && c <= 'f')
  680.       return (c - 'a' + 10);
  681.   else
  682.       return (c - 'A' + 10);
  683. }
  684.  
  685. /*
  686.  * kboot_rpcsvr - Handle rpc requests.
  687.  */
  688. kboot_rpcsvr (request, xprt)
  689.  
  690. struct svc_req    *request;
  691. SVCXPRT        *xprt;
  692.  
  693. {
  694.   struct sockaddr_in    *sa;
  695.   char            *kbox;
  696.   int            r;
  697.   struct kbox        *kp;
  698.  
  699.   sa = svc_getcaller (xprt);
  700.   if (debug)
  701.       fprintf (stderr, "kboot_rpcsvr: Request %d from %s\n",
  702.            request->rq_proc, inet_ntoa (sa->sin_addr));
  703.   if (sa->sin_port >= IPPORT_RESERVED) {
  704.       logerr ("kboot_rpcsvr: Bad port %d from %s\n",
  705.           sa->sin_port, inet_ntoa (sa->sin_addr));
  706.       r = -1;
  707.       if (!svc_sendreply (xprt, xdr_int, (caddr_t) &r))
  708.       logerr ("kboot_rpcsvr: svc_sendreply failed\n");
  709.       return;
  710.   }
  711.   switch (request->rq_proc) {
  712.     case NULLPROC:
  713.       if (!svc_sendreply (xprt, xdr_void, 0))
  714.       logerr ("kboot_rpcsvr(NULLPROC): svc_sendreply failed\n");
  715.       break;
  716.  
  717.     case KBOOTPROC_RELOAD:
  718.       kbox = NULL;
  719.       if (svc_getargs (xprt, xdr_wrapstring, &kbox)) {
  720.       if (!(kp = get_kbox (kbox))) {
  721.           logerr ("kboot_rpcsvr: No such kbox %s\n", kbox);
  722.           r = -1;
  723.       } else
  724.           r = 0;
  725.       } else {
  726.       logerr ("kboot_rpcsvr(RELOAD): svc_getargs failed\n");
  727.       r = -1;
  728.       }
  729.       if (!svc_sendreply (xprt, xdr_int, (caddr_t) &r))
  730.       logerr ("kboot_rpcsvr(RELOAD): svc_sendreply failed\n");
  731.       if (r >= 0) {
  732.       kp->reload++;
  733.       alarm (1);
  734.       if (debug)
  735.           fprintf (stderr, "kboot_rpcsvr: Requesting load of %s\n", kbox);
  736.       }
  737.       xdr_free (xdr_wrapstring, &kbox);
  738.       break;
  739.  
  740.     default:
  741.       svcerr_noproc (xprt);
  742.       break;
  743.   }
  744. }
  745.  
  746. /*
  747.  * Initialize RPC stuff.
  748.  */
  749. rpc_init ()
  750.  
  751. {
  752.   SVCXPRT    *xprt;
  753.  
  754.   if ((xprt = svcudp_create (RPC_ANYSOCK)) == NULL) {
  755.       logerr ("rpc_init: svcudp_create failed\n");
  756.       exit (1);
  757.   }
  758.   pmap_unset (KBOOTPROG, KBOOTVERS);
  759.   if (!svc_register (xprt, KBOOTPROG, KBOOTVERS, kboot_rpcsvr, IPPROTO_UDP)) {
  760.       logerr ("rpc_init: Can't register %d %d\n", KBOOTPROG, KBOOTVERS);
  761.       exit (1);
  762.   }
  763. }
  764.  
  765. /*
  766.  * kboot_reload - Ask kboot on rhost to reload kbox.
  767.  */
  768. kboot_reload (kbox, rhost)
  769.  
  770. char    *kbox;
  771. char    *rhost;
  772.  
  773. {
  774.   int    s;
  775.   int    r;
  776.  
  777.   if (rhost == NULL)
  778.       rhost = "localhost";
  779.   if (debug)
  780.       fprintf (stderr, "kboot_reload: Requesting reboot of %s on %s\n",
  781.            kbox, rhost);
  782. /*
  783.  * kboot will only accept rpc requests from privileged ports. callrpc
  784.  * will use a privileged port by default if it can (we're root).
  785.  */
  786.   if ((s = callrpc (rhost, KBOOTPROG, KBOOTVERS, KBOOTPROC_RELOAD,
  787.             xdr_wrapstring, &kbox, xdr_int, &r)) != 0) {
  788.       clnt_perrno (s);
  789.       exit (1);
  790.   }
  791.   printf ("%s reload request %s\n", kbox, r == 0 ? "accepted" : "failed");
  792. }
  793.