home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / kboot22.zoo / kboot22.1 next >
Encoding:
Text File  |  1991-02-22  |  44.0 KB  |  1,921 lines

  1.  
  2. #! /bin/sh
  3. # This is a shell archive.  Remove anything before this line, then unpack
  4. # it by saving it into a file and typing "sh file".  To overwrite existing
  5. # files, type "sh file -c".  You can also feed this as standard input via
  6. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  7. # will see the following message at the end:
  8. #        "End of archive 1 (of 2)."
  9. # Contents:  cmd.c icmp.c kboot.c nitlib.c
  10. # Wrapped by bobs@chumley on Wed Feb 13 22:14:58 1991
  11. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  12. if test -f 'cmd.c' -a "${1}" != "-c" ; then 
  13.   echo shar: Will not clobber existing file \"'cmd.c'\"
  14. else
  15. echo shar: Extracting \"'cmd.c'\" \(15515 characters\)
  16. sed "s/^X//" >'cmd.c' <<'END_OF_FILE'
  17. X#ifndef lint
  18. Xstatic char    *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/cmd.c,v 1.2 91/02/12 19:38:49 root Exp $";
  19. X#endif lint
  20. X
  21. X/*
  22. X * $Log:    cmd.c,v $
  23. X * Revision 1.2  91/02/12  19:38:49  root
  24. X * Removed unused commands.
  25. X * 
  26. X * Revision 1.1  91/01/29  17:36:59  root
  27. X * Initial revision
  28. X * 
  29. X */
  30. X
  31. X/*
  32. X * cmd.c - Send commands to kboxes.
  33. X */
  34. X
  35. X#include <stdio.h>
  36. X#include <syslog.h>
  37. X#include <netdb.h>
  38. X#include <sys/types.h>
  39. X#include <sys/socket.h>
  40. X#include <sys/errno.h>
  41. X#include <net/if.h>
  42. X#include <netinet/in.h>
  43. X#include <netinet/if_ether.h>
  44. X#include <sys/time.h>
  45. X#include <sys/timeb.h>
  46. X#include "appletalk.h"
  47. X#include "cmdidx.h"
  48. X#include "kbox.h"
  49. X#include "config.h"
  50. X
  51. Xextern struct hostent        *gethostbyaddr ();
  52. Xextern char            *inet_ntoa ();
  53. Xstruct kbox            *get_kbox ();
  54. Xextern int            errno;
  55. Xextern char            *sys_errlist[];
  56. Xextern int            numkbox;
  57. Xextern int            debug;
  58. Xextern struct ether_addr    ebc;
  59. Xextern struct ether_header    eh;
  60. Xextern struct kbox        *kboxtab[HTSIZE];
  61. Xextern long            atalkaddr;
  62. Xextern unsigned char        kboxstate[STATE_LENGTH];
  63. Xextern unsigned char        newstate[STATE_LENGTH];
  64. Xextern char            *etcdir;
  65. Xextern unsigned char        *zonelistp;
  66. X
  67. X#define HEX(i)            ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
  68. X
  69. X/*
  70. X * Globals.
  71. X */
  72. Xint            (*recv_copyproc) () = NULL;
  73. Xstruct ether_fastpath    fppkt;
  74. Xstruct fp_promram    promram;
  75. Xint            num_resp;
  76. Xint            expected_resp;
  77. Xint            destkbox;
  78. Xstruct kbox        *kboxaddr[MAXKBOX];
  79. Xstruct timeval        timeout;
  80. X
  81. X/*
  82. X * Receive functions.  There should be a recv_ function for each send_
  83. X * function.
  84. X */
  85. X
  86. X/*
  87. X * recv_who - Process who packet.  Algorithm is to look up the ethernet
  88. X *   address in the ethers file and then add this kbox to the hash
  89. X *   table it's not already there.  It would probably be more efficient
  90. X *   to look up the ethernet address directly in a table hashed by ethernet
  91. X *   address, however recv_who isn't called very often so I won't bother.
  92. X */
  93. Xrecv_who (p)
  94. X
  95. Xstruct fp_packet    *p;
  96. X
  97. X{
  98. X  char        name[MAXHOSTNAME];
  99. X  char        buf[20];
  100. X  struct kbox    *kp;
  101. X
  102. X  if (ether_ntohost (name, &p->fp_shost) != 0) {
  103. X      logerr ("recv_who: Can't find %s in ethers table\n",
  104. X          ether_ntoa (&p->fp_shost));
  105. X      return;
  106. X  }
  107. X  if (kp = get_kbox (name)) {
  108. X      if (!bcmp (&kp->ea, &p->fp_shost, sizeof(struct ether_addr))) {
  109. X      if (kp->aa == AT_Broadcast) {
  110. X          kp->aa = p->fp_lapsrc;
  111. X          kboxaddr[kp->aa] = kp;
  112. X          if (debug)
  113. X              fprintf (stderr, "recv_who: Adding kbox %s %s\n",
  114. X               name, ether_ntoa (&p->fp_shost));
  115. X          num_resp++;
  116. X      }
  117. X      } else {
  118. X      strcpy (buf, ether_ntoa (&kp->ea));
  119. X      logerr ("recv_who: Mismatched ether address for %s: %s != %s\n",
  120. X          name, buf, ether_ntoa (&p->fp_shost));
  121. X      }
  122. X  } else if (debug)
  123. X      fprintf (stderr, "recv_who: Unknown kbox %s %s\n",
  124. X           name, ether_ntoa (&p->fp_shost));
  125. X}
  126. X
  127. X/*
  128. X * recv_promram - Receive promram vector.  On sparc machines the
  129. X *   fp_promram structure doesn't align properly, so copy the count
  130. X *   field separately.
  131. X */
  132. Xrecv_promram (p)
  133. X
  134. Xstruct fp_packet    *p;
  135. X
  136. X{
  137. X  bcopy (p->fp_data, &promram.fpr_count, sizeof(promram.fpr_count));
  138. X  bcopy (&p->fp_data[sizeof(promram.fpr_count)], &promram.fpr_jtable,
  139. X     PROMRAMSIZE - sizeof(promram.fpr_count));
  140. X  num_resp++;
  141. X}
  142. X
  143. X/*
  144. X * recv_getstate - Receive state vector.
  145. X */
  146. Xrecv_getstate (p)
  147. X
  148. Xstruct fp_packet    *p;
  149. X
  150. X{
  151. X  bcopy (&p->fp_data[FPCOPYSIZE], kboxstate, STATE_LENGTH);
  152. X  if (debug) {
  153. X      fprintf (stderr, "recv_getstate: Received state...\n");
  154. X      show_state (stderr, kboxstate);
  155. X  }
  156. X  num_resp++;
  157. X}
  158. X
  159. X/*
  160. X * inet_ntos - Translate ip address to hostname.
  161. X */
  162. Xchar *inet_ntos (addr)
  163. X
  164. Xunsigned char    *addr;
  165. X
  166. X{
  167. X  struct in_addr    a;
  168. X  struct hostent    *he;
  169. X
  170. X  bcopy (addr, &a.s_addr, 4);
  171. X  if ((he = gethostbyaddr (&a, 4, AF_INET)) == NULL)
  172. X      return (inet_ntoa (a));
  173. X  else
  174. X      return (he->h_name);
  175. X}
  176. X
  177. X/*
  178. X * show_state - Print state vector.
  179. X */
  180. Xshow_state (f, s)
  181. X
  182. XFILE        *f;
  183. Xunsigned char    s[STATE_LENGTH];
  184. X
  185. X{
  186. X  int    options;
  187. X  int    i;
  188. X  int    first;
  189. X  long    l;
  190. X  short    st;
  191. X
  192. X  fprintf (f, "\tAppletalk: %d.%d.%d Ethertalk: %d.%d.%d IPtalk: %d.%d.%d",
  193. X       s[O_ATNET], s[O_ATNET+1], s[O_NODE],
  194. X       s[O_ETNET], s[O_ETNET+1], s[O_ETNODE],
  195. X       s[O_UDPNET], s[O_UDPNET+1], s[O_UDPNODE]);
  196. X  fprintf (f, " Bridge: %d\n", s[O_BRIDGE]);
  197. X  fprintf (f, "\tEthernet: %s Name: \"%s\" File: \"%s\"\n",
  198. X       ether_ntoa (&s[O_ETHER]), &s[O_NAME], &s[O_FILE]);
  199. X  fprintf (f, "\tConfig: \"%s\"\n", &s[O_CONFIG]);
  200. X  fprintf (f, "\tATzone: \"%s\" ETzone: \"%s\" UDPzone: \"%s\"\n",
  201. X       &s[O_ATZONE], &s[O_ETZONE], &s[O_UDPZONE]);
  202. X  fprintf (f, "\tPforce: %d Autoconfig: %s", s[O_PFORCE],
  203. X       (s[O_AUTOCONFIG] || s[O_AUTOCONFIG+1]) ? "yes" : "no");
  204. X  fprintf (f, " Autoboot: %s",
  205. X       (s[O_AUTOBOOT] || s[O_AUTOBOOT+1]) ? "yes\n" : "no\n");
  206. X  fprintf (f, "\tOptions: ");
  207. X  bcopy (&s[O_OPTIONS], &options, sizeof(options));
  208. X  if (options) {
  209. X      for (first = 1, i = 0; i < 32; i++)
  210. X      if ((1 << i) & options)
  211. X          if (first) {
  212. X          first = 0;
  213. X          fprintf (f, "%d", i + 1);
  214. X          } else
  215. X          fprintf (f, ", %d", i+1);
  216. X  } else
  217. X      fprintf (f, "none");
  218. X  bcopy (&s[O_SN], &l, sizeof (l));
  219. X  bcopy (&s[O_TYPE], &st, sizeof (st));
  220. X  fprintf (f, " Serial: %d Type: %d\n", l, st);
  221. X  fprintf (f, "\tRouter: \"%s\"", inet_ntos (&s[O_IPDEFROUTER]));
  222. X  fprintf (f, " ETip: \"%s\"", inet_ntos (&s[O_IPADDRESS]));
  223. X  fprintf (f, " ATip: \"%s\"", inet_ntos (&s[O_ATIPADDRESS]));
  224. X  fprintf (f, " Broadcast: \"%s\"\n", inet_ntos (&s[O_IPBROADCAST]));
  225. X  fprintf (f, "\tSubnet: \"%s\"", inet_ntos (&s[O_IPSUBMASK]));
  226. X  fprintf (f, " KIP: \"%s\"", inet_ntos (&s[O_IPKIPSERVER]));
  227. X  fprintf (f, " Name: \"%s\"", inet_ntos (&s[O_NAMESERVER]));
  228. X  fprintf (f, " File: \"%s\"\n", inet_ntos (&s[O_FILESERVER]));
  229. X  bcopy (&s[O_LP1], &l, sizeof (l));
  230. X  fprintf (f, "\tLocal1: 0x%x", l);
  231. X  bcopy (&s[O_LP2], &l, sizeof (l));
  232. X  fprintf (f, " Local2: 0x%x", l);
  233. X  bcopy (&s[O_LP3], &l, sizeof (l));
  234. X  fprintf (f, " Local3: 0x%x", l);
  235. X  bcopy (&s[O_LP4], &l, sizeof (l));
  236. X  fprintf (f, " Local4: 0x%x\n", l);
  237. X  bcopy (&s[O_NDYNAMICS], &st, sizeof (st));
  238. X  fprintf (f, "\tDynamics: %d", st);
  239. X  bcopy (&s[O_NSTATICS], &st, sizeof (st));
  240. X  fprintf (f, " Statics: %d", st);
  241. X  bcopy (&s[O_ZONELIST], &l, sizeof (l));
  242. X  fprintf (f, " Zonelist 0x%X\n", l);
  243. X}
  244. X
  245. X/*
  246. X * recv_gen - Generic receive routine.
  247. X */
  248. Xrecv_gen (p)
  249. X
  250. Xstruct fp_packet    *p;
  251. X
  252. X{
  253. X  num_resp++;
  254. X}
  255. X
  256. X/*
  257. X * recv_pkt - Call appropriate function to deal with packet from fastpath.
  258. X */
  259. Xrecv_pkt (p)
  260. X
  261. Xstruct fp_packet    *p;
  262. X
  263. X{
  264. X  char    buf[100];
  265. X
  266. X  if (p->fp_laptype != FP_TYPE) {
  267. X      return;
  268. X  }
  269. X  if (destkbox != AT_Broadcast && p->fp_lapsrc != destkbox) {
  270. X    /*
  271. X     * X_WHO responses from unconfigured fastpaths to broadcasts may come
  272. X     * in after we've already started talking to a real fastpath, so
  273. X     * just ignore all X_WHO responses with no error message.
  274. X     */
  275. X      if (p->fp_scmd != X_WHO)
  276. X      logerr ("recv_pkt: Bogus response %d from %s\n",
  277. X          p->fp_scmd, ether_ntoa (&p->fp_shost));
  278. X      return;
  279. X  }
  280. X  if (p->fp_cmd == FP_ACK) {
  281. X      num_resp++;
  282. X      return;
  283. X  }
  284. X  if (p->fp_cmd != FP_RESP)
  285. X      return;
  286. X  switch (p->fp_scmd) {
  287. X    case X_COPYMEM :    if (recv_copyproc)
  288. X                (*recv_copyproc) (p);
  289. X            break;
  290. X
  291. X    case X_PROMRAM :    recv_promram (p); break;
  292. X
  293. X    case X_WHO :    recv_who (p); break;
  294. X
  295. X    case X_RESET :    recv_gen ();
  296. X            break;
  297. X
  298. X    default :        ether_ntohost (buf, &p->fp_shost);
  299. X            logerr ("recv_pkt: Received %d from %s\n",
  300. X                p->fp_scmd, buf);
  301. X            break;
  302. X  }
  303. X}
  304. X
  305. X/*
  306. X * Send procedures.  Those that have no parameters are macros that invoke
  307. X * send_gen(), defined in kbox.h.
  308. X */
  309. X
  310. X/*
  311. X * send_who - Broadcast who packet.
  312. X */
  313. Xint send_who ()
  314. X
  315. X{
  316. X  int    i;
  317. X
  318. X  for (i = 0; i < MAXKBOX; i++)
  319. X      if (kboxaddr[i])
  320. X        kboxaddr[i]->aa = AT_Broadcast;
  321. X  nit_timeout (60, &timeout);
  322. X  return (send_pkt (NULL, (int) FP_CMD, X_WHO, 0, 5, &timeout));
  323. X}
  324. X
  325. X/*
  326. X * send_boot - Download file to kbox.
  327. X */
  328. Xint send_boot (kp, zonedata, zonelen)
  329. X
  330. Xstruct kbox    *kp;
  331. Xunsigned char    *zonedata;
  332. Xint        zonelen;
  333. X
  334. X{
  335. X  FILE    *f;
  336. X  int    l;
  337. X  int    ch;
  338. X  int    cmd;
  339. X  int    scmd;
  340. X  char    fn[MAXFN];
  341. X  int    size = 0;
  342. X  int    lastlen;
  343. X  int    lastaddr;
  344. X
  345. X  sprintf (fn, "%s/%s", etcdir, kp->bootfile);
  346. X  if ((f = fopen (fn, "r")) == NULL) {
  347. X      logerr ("send_boot: %s to %s - %s\n", fn, kp->name, sys_errlist[errno]);
  348. X      return (0);
  349. X  }
  350. X  nit_timeout (30, &timeout);
  351. X  while ((cmd = fgetc (f)) > 0) {
  352. X      if (cmd != 'S') {
  353. X      logerr ("send_boot: Bad S record %d\n", cmd);
  354. X      return (-1);
  355. X      }
  356. X      scmd = fgetc (f);
  357. X      if (scmd == '8') {
  358. X    /*
  359. X     * With KSTAR 8.0 it is necessary to download a zonelist with
  360. X     * KSTAR.  The following code converts the zonelist read from
  361. X     * the config file written by the Fastpath Manager into
  362. X     * s-records and sends them to the kbox.  The address where
  363. X     * the zonelist is downloaded is the first even address after
  364. X     * the last s-record, which is the address of the last s-record
  365. X     * plus its length, rounded up to the nearest even address.
  366. X     * The first s-record describes the following data, it looks like:
  367. X     *
  368. X     *    short num_elements;
  369. X     *    struct {
  370. X     *      short    type;
  371. X     *      short length;
  372. X     *    } element[NUMELEMENTS];
  373. X     *
  374. X     * For a zonelist the type is 1.  The second s-record contains
  375. X     * the zonelist itself.  These extra s-records get sent right
  376. X     * before the last s-record, which seems to have scmd == 8.
  377. X     * Much of the information on the format of the s-records and
  378. X     * their location was reverse engineered from packet traces,
  379. X     * I don't guarantee this code to be correct, although it
  380. X     * works for me.
  381. X     */
  382. X      lastlen = atox (fppkt.fastpath_data, 2);
  383. X      lastaddr = atox (&fppkt.fastpath_data[2], 6);
  384. X      zonelistp = (unsigned char *) (lastaddr + lastlen - 4);
  385. X      if ((int) zonelistp % 2 == 1)
  386. X          zonelistp++;
  387. X      makeelemlist (fppkt.fastpath_data, zonelen);
  388. X      if (debug)
  389. X          fprintf (stderr, "send_boot: %s\n", fppkt.fastpath_data);
  390. X      if (send_pkt (kp, 'S', '2', strlen(fppkt.fastpath_data),
  391. X            5, &timeout) != 1)
  392. X          return (0);
  393. X      makezonedata (fppkt.fastpath_data, zonedata, zonelen);
  394. X      if (debug)
  395. X          fprintf (stderr, "send_boot: %s\n", fppkt.fastpath_data);
  396. X      if (send_pkt (kp, 'S', '2', strlen(fppkt.fastpath_data),
  397. X            5, &timeout) != 1)
  398. X          return (0);
  399. X      }
  400. X      l = 0;
  401. X      while ((ch = fgetc (f)) > 0 && ch != '\r' && ch != '\n')
  402. X      fppkt.fastpath_data[l++] = ch;
  403. X      size += l;
  404. X      if (send_pkt (kp, cmd, scmd, l, 5, &timeout) != 1)
  405. X      return (0);
  406. X  }
  407. X  if (debug)
  408. X      fprintf (stderr, "send_boot: Downloaded %d bytes\n", size);
  409. X  return (1);
  410. X}
  411. X
  412. X/*
  413. X * atox - Convert ascii string of length l to hex.
  414. X */
  415. Xint atox (s, l)
  416. X
  417. Xchar    *s;
  418. Xint    l;
  419. X
  420. X{
  421. X  int    r = 0;
  422. X  int    i;
  423. X
  424. X  for (i = 0; i < l; i++)
  425. X      r = (r << 4) | ((s[i] >= '0' && s[i] <= '9') ? s[i] - '0' :
  426. X              (s[i] >= 'a' && s[i] <= 'f') ? s[i] - 'a' + 10 :
  427. X              s[i] - 'A' + 10);
  428. X  return (r);
  429. X}
  430. X
  431. X/*
  432. X * csumsrec - Compute checksum for s-record.
  433. X */
  434. Xunsigned char csumsrec (s, l)
  435. X
  436. Xunsigned char    *s;
  437. Xint        l;
  438. X
  439. X{
  440. X  unsigned char    sum;
  441. X  static char    buf[3];
  442. X
  443. X  sum = 0;
  444. X  while (l--)
  445. X      sum += *s++;
  446. X  sum ^= 0xFF;
  447. X  return (sum);
  448. X}
  449. X
  450. X/*
  451. X * makeelemlist - Make element list srecord.
  452. X */
  453. Xmakeelemlist (p, l)
  454. X
  455. Xunsigned char    *p;
  456. Xint        l;
  457. X
  458. X{
  459. X  static elemlist    el = {1, 1, 0};
  460. X  unsigned char        buf[BUFSIZ];
  461. X
  462. X  el.bytes = l + 2;                /* Don't know why +2    */
  463. X  bcopy (&zonelistp, buf, sizeof (zonelistp));    /* First byte is length */
  464. X  *buf = 4 + sizeof (el);            /* so overwrite it    */
  465. X  bcopy (&el, &buf[4], sizeof (el));
  466. X  buf[4 + sizeof (el)] = csumsrec (buf, 4 + sizeof (el));
  467. X  hexify (buf, p, 4 + sizeof (el) + 1);
  468. X}
  469. X
  470. X/*
  471. X * makezonedata - Make zone data srecord.
  472. X */
  473. Xmakezonedata (p, data, l)
  474. X
  475. Xunsigned char    *p;
  476. Xunsigned char    *data;
  477. Xint        l;
  478. X
  479. X{
  480. X  unsigned char    *addr;
  481. X  unsigned char    buf[BUFSIZ];
  482. X
  483. X  addr = zonelistp + sizeof (elemlist);
  484. X  bcopy (&addr, buf, sizeof (addr));
  485. X  *buf = 4 + l;
  486. X  bcopy (data, &buf[4], l);
  487. X  buf[4 + l] = csumsrec (buf, 4 + l);
  488. X  hexify (buf, p, 4 + l + 1);
  489. X}
  490. X
  491. X/*
  492. X * hexify - Convert buffer to hex ascii characters.
  493. X */
  494. Xhexify (buf, p, len)
  495. X
  496. Xunsigned char    *buf;
  497. Xunsigned char    *p;
  498. Xint        len;
  499. X
  500. X{
  501. X  int    i;
  502. X
  503. X  for (i = 0; i < len; i++) {
  504. X      p[2 * i] = HEX (buf[i] >> 4);
  505. X      p[2 * i + 1] = HEX (buf[i] & 0xF);
  506. X  }
  507. X  p[2 * len] = '\0';
  508. X}
  509. X
  510. X
  511. X/*
  512. X * send_getstate - Get state vector.
  513. X */
  514. Xint send_getstate (kp)
  515. X
  516. Xstruct kbox    *kp;
  517. X
  518. X{
  519. X  struct fp_copy    copy;
  520. X
  521. X  copy.fpc_from = (char *) promram.fpr_state;
  522. X  copy.fpc_to = (char *) -1;
  523. X  copy.fpc_count = STATE_LENGTH;
  524. X  bcopy (©, fppkt.fastpath_data, FPCOPYSIZE);
  525. X  recv_copyproc = recv_getstate;
  526. X  nit_timeout (30, &timeout);
  527. X  return (send_pkt (kp, (int) FP_CMD, X_COPYMEM, FPCOPYSIZE, 5, &timeout));
  528. X}
  529. X
  530. X/*
  531. X * send_putstate - Put state vector.
  532. X */
  533. Xint send_putstate (kp)
  534. X
  535. Xstruct kbox    *kp;
  536. X
  537. X{
  538. X  struct fp_copy    copy;
  539. X
  540. X  copy.fpc_from = (char *) -1;
  541. X  copy.fpc_to = (char *) promram.fpr_state;
  542. X  copy.fpc_count = htons (STATE_LENGTH);
  543. X  bcopy (©, fppkt.fastpath_data, FPCOPYSIZE);
  544. X  newstate[O_NODE] = kboxstate[O_NODE];
  545. X  bcopy (newstate, &fppkt.fastpath_data[FPCOPYSIZE], STATE_LENGTH);
  546. X  if (debug) {
  547. X      fprintf (stderr, "send_putstate: Sending state...\n");
  548. X      show_state (stderr, newstate);
  549. X  }
  550. X  recv_copyproc = recv_gen;
  551. X  nit_timeout (30, &timeout);
  552. X  return (send_pkt (kp, (int) FP_CMD, X_COPYMEM,
  553. X            FPCOPYSIZE + STATE_LENGTH, 5, &timeout));
  554. X}
  555. X
  556. X/*
  557. X * send_gen - Generic send command.
  558. X */
  559. Xint send_gen (kp, scmd, retries)
  560. X
  561. Xstruct kbox    *kp;
  562. Xint        scmd;
  563. Xint        retries;
  564. X
  565. X{
  566. X  nit_timeout (60, &timeout);
  567. X  return (send_pkt (kp, (int) FP_CMD, scmd, 0, retries, &timeout));
  568. X}
  569. X
  570. X/*
  571. X * send_pkt - Send command packet (in fppkt).  Returns # of responders,
  572. X *   or -1 on error.  If retries is 0, don't expect any response.
  573. X */
  574. Xint send_pkt (kp, cmd, scmd, len, retries, timeout)
  575. X
  576. Xstruct kbox    *kp;
  577. Xint        cmd;
  578. Xint        scmd;
  579. Xint        len;
  580. Xint        retries;
  581. Xstruct timeval    *timeout;
  582. X
  583. X{
  584. X  short            count;
  585. X  int            h;
  586. X  struct kbox        *p;
  587. X  struct timeb        tstart;
  588. X  struct timeb        tcur;
  589. X  int            utotal;
  590. X  int            ucur;
  591. X
  592. X  if (kp) {
  593. X      if (kp->aa == AT_Broadcast) {
  594. X      logerr ("send_pkt: Invalid appletalk address for %s\n", kp->name);
  595. X      return (-1);
  596. X      }
  597. X      destkbox = kp->aa;
  598. X      ether_copy (&kboxaddr[destkbox]->ea, &eh.ether_dhost);
  599. X      if (retries == 0) {
  600. X      expected_resp = 0;
  601. X      retries = 1;
  602. X      } else
  603. X      expected_resp = 1;
  604. X  } else {
  605. X      destkbox = AT_Broadcast;
  606. X      ether_copy (&ebc, &eh.ether_dhost);
  607. X      expected_resp = numkbox;
  608. X  }
  609. X  num_resp = 0;
  610. X  fppkt.fastpath_lapdest = destkbox;
  611. X  fppkt.fastpath_lapsrc = atalkaddr;
  612. X  fppkt.fastpath_laptype = FP_TYPE;
  613. X  fppkt.fastpath_cmd = cmd;
  614. X  fppkt.fastpath_scmd = scmd;
  615. X  count = htons (len + 4);
  616. X  bcopy (&count, fppkt.fastpath_len, sizeof(count));
  617. X  utotal = timeout->tv_sec * 1000000 + timeout->tv_usec;
  618. X  for (count = 0; count < retries; count++) {
  619. X      if (debug && count >= 1)
  620. X      fprintf (stderr, "send_pkt: Retransmitting cmd %d scmd %d\n",
  621. X           fppkt.fastpath_cmd, fppkt.fastpath_scmd);
  622. X      nit_write (&eh, &fppkt, len + sizeof(struct ether_fastpath) - MAXFPPKT);
  623. X      ftime (&tstart);
  624. X      ucur = 0;
  625. X      while (num_resp < expected_resp && utotal > ucur) {
  626. X      nit_dispatch (recv_pkt, 1, NULL, NULL, timeout);
  627. X      ftime (&tcur);
  628. X      ucur = (tcur.time - tstart.time) * 1000000 +
  629. X         (tcur.millitm - tstart.millitm) * 1000;
  630. X      }
  631. X      if (num_resp >= expected_resp)
  632. X      break;
  633. X  }
  634. X  if (num_resp != expected_resp)
  635. X      if (destkbox == AT_Broadcast) {
  636. X          for (h = 0; h < HTSIZE; h++)
  637. X              for (p = kboxtab[h]; p; p = p->nxt)
  638. X              if (p->aa == AT_Broadcast)
  639. X                  logerr ("send_pkt(%d,%d): No response from %s\n",
  640. X                   cmd, scmd, p->name);
  641. X      } else
  642. X      logerr ("send_pkt(%d,%d): No response from %s\n",
  643. X          cmd, scmd, kboxaddr[destkbox]->name);
  644. X  return (num_resp);
  645. X}
  646. END_OF_FILE
  647. if test 15515 -ne `wc -c <'cmd.c'`; then
  648.     echo shar: \"'cmd.c'\" unpacked with wrong size!
  649. fi
  650. # end of 'cmd.c'
  651. fi
  652. if test -f 'icmp.c' -a "${1}" != "-c" ; then 
  653.   echo shar: Will not clobber existing file \"'icmp.c'\"
  654. else
  655. echo shar: Extracting \"'icmp.c'\" \(3355 characters\)
  656. sed "s/^X//" >'icmp.c' <<'END_OF_FILE'
  657. X#ifndef lint
  658. Xstatic char    *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/icmp.c,v 1.1 91/01/29 17:37:23 root Exp $";
  659. X#endif lint
  660. X
  661. X/*
  662. X * $Log:    icmp.c,v $
  663. X * Revision 1.1  91/01/29  17:37:23  root
  664. X * Initial revision
  665. X * 
  666. X */
  667. X
  668. X#include <stdio.h>
  669. X#include <syslog.h>
  670. X#include <sys/types.h>
  671. X#include <sys/time.h>
  672. X#include <sys/socket.h>
  673. X#include <sys/errno.h>
  674. X#include <netdb.h>
  675. X#include <net/if.h>
  676. X#include <netinet/in_systm.h>
  677. X#include <netinet/in.h>
  678. X#include <netinet/ip.h>
  679. X#include <netinet/ip_icmp.h>
  680. X#include <netinet/if_ether.h>
  681. X#include "kbox.h"
  682. X#include "config.h"
  683. X
  684. Xextern int    errno;
  685. Xextern char    *sys_errlist[];
  686. Xextern int    debug;
  687. X
  688. X/*
  689. X * Globals.
  690. X */
  691. Xstruct icmp        icmp_pkt;
  692. Xint            icmp_sock;
  693. Xfd_set            icmp_fds;
  694. X
  695. X/*
  696. X * icmp_init - Initialize icmp stuff.
  697. X */
  698. Xicmp_init ()
  699. X
  700. X{
  701. X  if ((icmp_sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
  702. X      logerr ("icmp_init: %s\n", sys_errlist[errno]);
  703. X      exit (1);
  704. X  }
  705. X  FD_SET (icmp_sock, &icmp_fds);
  706. X  icmp_pkt.icmp_type = ICMP_ECHO;
  707. X  icmp_pkt.icmp_code = 0;
  708. X  icmp_pkt.icmp_seq = 0;
  709. X  icmp_pkt.icmp_id = (getpid () & 0xFFFF);
  710. X}
  711. X
  712. X
  713. X/*
  714. X * in_cksum - Compute IP checksum.
  715. X */
  716. Xu_short in_cksum (a, l)
  717. X
  718. Xu_short    *a;
  719. Xint    l;
  720. X
  721. X{
  722. X  int    sum = 0;
  723. X
  724. X  while (l > 1) {
  725. X      sum += *a++;
  726. X      l -= 2;
  727. X  }
  728. X  if (l == 1)
  729. X      sum += *(u_char *) a;
  730. X  sum += (sum >> 16);
  731. X  return ((~sum) & 0xFFFF);
  732. X}
  733. X
  734. X/*
  735. X * icmp_ping - Ping kbox.
  736. X */
  737. Xint icmp_ping (kp)
  738. X
  739. Xstruct kbox    *kp;
  740. X
  741. X{
  742. X  struct sockaddr_in    dest;
  743. X  struct sockaddr_in    from;
  744. X  static struct timeval    icmp_timeout = {PINGTIMEOUT, 0};
  745. X  char            buf[BUFSIZ];
  746. X  struct ip        *ip;
  747. X  struct icmp        *p;
  748. X  int            i;
  749. X  int            r;
  750. X  fd_set        readfds;
  751. X
  752. X  icmp_pkt.icmp_seq++;
  753. X  icmp_pkt.icmp_cksum = 0;
  754. X  icmp_pkt.icmp_cksum = in_cksum (&icmp_pkt, sizeof (icmp_pkt));
  755. X  bzero (&dest, sizeof (dest));
  756. X  dest.sin_family = AF_INET;
  757. X  dest.sin_addr.s_addr = kp->ip.sin_addr.s_addr;
  758. X  for (i = 0; i < PINGRETRIES; i++) {
  759. X      p = NULL;
  760. X    /*
  761. X     * Send ping
  762. X     */
  763. X      if (debug)
  764. X      fprintf (stderr, "icmp_ping: Pinging %s id %d seq %d\n",
  765. X           inet_ntoa (dest.sin_addr), icmp_pkt.icmp_id,
  766. X           icmp_pkt.icmp_seq);
  767. X      if (sendto (icmp_sock, &icmp_pkt, sizeof (icmp_pkt), 0,
  768. X          &dest, sizeof (dest)) != sizeof (icmp_pkt)) {
  769. X      logerr ("icmp_ping: sendto - %s\n", sys_errlist[errno]);
  770. X      exit (1);
  771. X      }
  772. X    /*
  773. X     * Wait for reply
  774. X     */
  775. Xwaitreply:
  776. X      readfds = icmp_fds;
  777. X      r = select (icmp_sock+1, &readfds, NULL, NULL, &icmp_timeout);
  778. X      if (r < 0) {
  779. X      logerr ("icmp_ping: select - %s\n", sys_errlist[errno]);
  780. X      exit (1);
  781. X      } else if (r == 0)
  782. X      continue;
  783. X    /*
  784. X     * Read reply
  785. X     */
  786. X      r = sizeof (from);
  787. X      if (recvfrom (icmp_sock, buf, BUFSIZ, 0, &from, &r) <= 0) {
  788. X      logerr ("icmp_ping: recvfrom - %s\n", sys_errlist[errno]);
  789. X      exit (1);
  790. X      }
  791. X    /*
  792. X     * Verify reply
  793. X     */
  794. X      ip = (struct ip *) buf;
  795. X      p = (struct icmp *) (buf + (ip->ip_hl << 2));
  796. X      if (p->icmp_type == ICMP_ECHOREPLY &&
  797. X      p->icmp_id == icmp_pkt.icmp_id &&
  798. X      p->icmp_seq == icmp_pkt.icmp_seq &&
  799. X      from.sin_addr.s_addr == kp->ip.sin_addr.s_addr) {
  800. X      if (debug)
  801. X          fprintf (stderr, "icmp_ping: Reply from %s id %d seq %d\n",
  802. X               inet_ntoa (from.sin_addr), p->icmp_id, p->icmp_seq);
  803. X      return (1);
  804. X      } else {
  805. X      if (debug)
  806. X          fprintf (stderr, "icmp_ping: Discarding packet from %s\n",
  807. X               inet_ntoa (from.sin_addr));
  808. X      goto waitreply;
  809. X      }
  810. X  }
  811. X  return (0);
  812. X}
  813. END_OF_FILE
  814. if test 3355 -ne `wc -c <'icmp.c'`; then
  815.     echo shar: \"'icmp.c'\" unpacked with wrong size!
  816. fi
  817. # end of 'icmp.c'
  818. fi
  819. if test -f 'kboot.c' -a "${1}" != "-c" ; then 
  820.   echo shar: Will not clobber existing file \"'kboot.c'\"
  821. else
  822. echo shar: Extracting \"'kboot.c'\" \(15749 characters\)
  823. sed "s/^X//" >'kboot.c' <<'END_OF_FILE'
  824. X#ifndef lint
  825. Xstatic char    *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/kboot.c,v 1.3 91/02/13 11:47:07 root Exp $";
  826. X#endif lint
  827. X
  828. X/*
  829. X * $Log:    kboot.c,v $
  830. X * Revision 1.3  91/02/13  11:47:07  root
  831. X * Accept rpc requests from privileged ports only.
  832. X * 
  833. X * Revision 1.2  91/02/12  19:27:39  root
  834. X * Remove -m option, add -t.
  835. X * 
  836. X * Revision 1.1  91/01/29  17:37:26  root
  837. X * Initial revision
  838. X * 
  839. X */
  840. X
  841. X/*
  842. X * kboot - Boot and configure fastpaths over an ethernet.  Depends on NIT
  843. X *       interface in SunOS 4.x.
  844. X *
  845. X * Author: Bob Schwartzkopf, The RAND Corporation.  Based on an earlier
  846. X *       version written by Dan Tappan at BBN that ran under SunOS 3.x.
  847. X *
  848. X * Comments, suggestions, patches, bug reports, etc. may be sent to
  849. X * bobs@rand.org.
  850. X */
  851. X
  852. X#include <stdio.h>
  853. X#include <syslog.h>
  854. X#include <fcntl.h>
  855. X#include <signal.h>
  856. X#include <sys/types.h>
  857. X#include <sys/socket.h>
  858. X#include <sys/errno.h>
  859. X#include <sys/termios.h>
  860. X#include <netdb.h>
  861. X#include <net/if.h>
  862. X#include <netinet/in.h>
  863. X#include <netinet/if_ether.h>
  864. X#include <rpc/rpc.h>
  865. X#include "appletalk.h"
  866. X#include "cmdidx.h"
  867. X#include "kbox.h"
  868. X#include "config.h"
  869. X#include "patchlevel.h"
  870. X#include "kboot.h"
  871. X
  872. X#define VERSION        2
  873. X
  874. Xextern char            *rindex ();
  875. Xstruct kbox            *get_kbox ();
  876. Xextern int            errno;
  877. Xextern char            *sys_errlist[];
  878. Xextern struct ether_addr    myether;
  879. X
  880. X/*
  881. X * Globals.
  882. X */
  883. Xchar            *progname;
  884. Xstruct ether_addr    ebc = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  885. Xstruct ether_header    eh;
  886. Xchar            *interface = NULL;
  887. Xlong            atalkaddr;
  888. Xchar            *etcdir = ETCDIR;
  889. Xint            detached = 0;
  890. Xint            debug = 0;
  891. Xint            watchf = 0;
  892. Xint            downloadf = 0;
  893. Xint            configf = 0;
  894. Xint            liststatef = 0;
  895. Xint            savestatef = 0;
  896. Xint            resetf = 0;
  897. Xint            rbootf = 0;
  898. Xstruct kbox        *kboxtab[HTSIZE];
  899. Xint            numkbox;
  900. Xunsigned char        kboxstate[STATE_LENGTH];
  901. Xunsigned char        newstate[STATE_LENGTH];
  902. Xunsigned char        zonedata[MAXZONELIST];
  903. Xint            zonelen;
  904. Xint            pinginterval = PINGINTERVAL;
  905. Xunsigned char        *zonelistp;
  906. X
  907. Xmain (argc, argv)
  908. X
  909. Xint    argc;
  910. Xchar    **argv;
  911. X
  912. X{
  913. X  int        i;
  914. X  char        c;
  915. X  char        *name = NULL;
  916. X  struct kbox    *kp;
  917. X  char        *errmsg;
  918. X  char        *rhost;
  919. X
  920. X  if ((progname = rindex (argv[0], '/')) == NULL)
  921. X      progname = *argv;
  922. X  else
  923. X      progname++;
  924. X  while (--argc > 0) {
  925. X      argv++;
  926. X      c = (*argv)[0] == '-' ? (*argv)[1] : (*argv)[0];
  927. X      switch (c) {
  928. X    case 'b' :
  929. X      if (argc <= 1)
  930. X          usage ();
  931. X      argv++; argc--;
  932. X      downloadf++;
  933. X      name = *argv;
  934. X      break;
  935. X    case 'c' :
  936. X      if (argc <= 1)
  937. X          usage ();
  938. X      argv++; argc--;
  939. X      configf++;
  940. X      name = *argv;
  941. X      break;
  942. X    case 'd' :
  943. X      debug++;
  944. X      break;
  945. X    case 'i' :
  946. X      if (argc <= 1)
  947. X          usage ();
  948. X      argv++; argc--;
  949. X      interface = *argv;
  950. X      break;
  951. X    case 'l' :
  952. X      if (argc <= 1)
  953. X          usage ();
  954. X      argv++; argc--;
  955. X      liststatef++;
  956. X      name = *argv;
  957. X      break;
  958. X    case 'p' :
  959. X      if (argc <= 1)
  960. X          usage ();
  961. X      argv++; argc--;
  962. X      pinginterval = atoi (*argv);
  963. X      break;
  964. X    case 'r' :
  965. X      if (argc <= 1)
  966. X          usage ();
  967. X      argv++; argc--;
  968. X      resetf++;
  969. X      name = *argv;
  970. X      break;
  971. X    case 's' :
  972. X      if (argc <= 1)
  973. X          usage ();
  974. X      argv++; argc--;
  975. X      savestatef++;
  976. X      name = *argv;
  977. X      break;
  978. X    case 't' :
  979. X      if (argc <= 1)
  980. X          usage ();
  981. X      argv++; argc--;
  982. X      rbootf++;
  983. X      name = *argv;
  984. X      if (argc > 1 && *argv[1] != '-') {
  985. X          argv++; argc--;
  986. X          rhost = *argv;
  987. X      } else
  988. X          rhost = NULL;
  989. X      break;
  990. X    case 'v' :
  991. X      printf ("%s version %d.%d\n", progname, VERSION, PATCHLEVEL);
  992. X      exit (0);
  993. X    case 'w' :
  994. X      watchf++;
  995. X      break;
  996. X    default :
  997. X      usage ();
  998. X      break;
  999. X      }
  1000. X  }
  1001. X  if (rbootf) {
  1002. X      kboot_reload (name, rhost);
  1003. X      exit (0);
  1004. X  }
  1005. X  if (watchf && !debug) {        /* Detach ourselves        */
  1006. X      detached++;
  1007. X      if (fork ())
  1008. X      exit (0);
  1009. X      if ((i = open ("/dev/tty", O_RDONLY)) >= 0)
  1010. X      ioctl (i, TIOCNOTTY, 0);
  1011. X      i = getdtablesize ();
  1012. X      while (--i >= 0)
  1013. X      close (i);
  1014. X      open ("/dev/null", 0);
  1015. X      dup2 (0, 1);
  1016. X      dup2 (0, 2);
  1017. X      openlog (progname, 0, LOG_DAEMON);
  1018. X      writepid ();
  1019. X  }
  1020. X  if ((i = getaa (NULL, &atalkaddr)) != 0) {
  1021. X      errmsg = clnt_sperrno (i);
  1022. X      logerr ("getaa: %s\n", errmsg);
  1023. X      exit (1);
  1024. X  }
  1025. X  if (debug)
  1026. X      fprintf (stderr, "main: Using appletalk address %d\n", atalkaddr);
  1027. X  nit_init (interface);
  1028. X  ht_init ();
  1029. X  readcf ();
  1030. X  ether_copy (&myether, &eh.ether_shost);
  1031. X  eh.ether_type = htons (P_AppleTalk);
  1032. X  if (watchf)
  1033. X      watch ();
  1034. X  else  {
  1035. X      if (!name)
  1036. X      usage ();
  1037. X      if (!(kp = get_kbox (name))) {
  1038. X      logerr ("main: No such kbox %s\n", name);
  1039. X      exit (1);
  1040. X      }
  1041. X      nit_open (0, P_AppleTalk);
  1042. X      if (downloadf)
  1043. X      download (kp);
  1044. X      else if (configf)
  1045. X      config (kp);
  1046. X      else if (savestatef)
  1047. X      savestate (kp);
  1048. X      else if (resetf)
  1049. X      reset (kp);
  1050. X      else if (liststatef)
  1051. X      liststate (kp);
  1052. X  }
  1053. X  exit (0);
  1054. X}
  1055. X
  1056. X/*
  1057. X * reconfig - Free old kbox hash table and reread config file.
  1058. X */
  1059. Xreconfig ()
  1060. X
  1061. X{
  1062. X  if (debug)
  1063. X      fprintf (stderr, "reconfig: Reading config file\n");
  1064. X  ht_free ();
  1065. X  readcf ();
  1066. X}
  1067. X
  1068. X/*
  1069. X * ping - Ping kboxes, reload any that don't respond or any that've
  1070. X *   been flagged for reloading.
  1071. X */
  1072. Xping ()
  1073. X
  1074. X{
  1075. X  int        i;
  1076. X  struct kbox    *kp;
  1077. X
  1078. X  for (i = 0; i < HTSIZE; i++)
  1079. X      for (kp = kboxtab[i]; kp; kp = kp->nxt)
  1080. X      if (kp->reload || !icmp_ping (kp)) {
  1081. X          logerr ("ping: Reloading %s\n", kp->name);
  1082. X          nit_open (0, P_AppleTalk);
  1083. X          download (kp);
  1084. X          kp->reload = 0;
  1085. X          nit_close ();
  1086. X      }
  1087. X  alarm (pinginterval);
  1088. X}
  1089. X
  1090. X/*
  1091. X * watch - Watch kboxes, rebooting if not answering pings or if someone
  1092. X *   asks us to.
  1093. X */
  1094. Xwatch ()
  1095. X
  1096. X{
  1097. X  signal (SIGHUP, reconfig);
  1098. X  signal (SIGALRM, ping);
  1099. X  icmp_init ();
  1100. X  rpc_init ();
  1101. X  alarm (pinginterval);
  1102. X  svc_run ();
  1103. X}
  1104. X
  1105. X/*
  1106. X * download - Download kstar to kbox.
  1107. X */
  1108. Xdownload (kp)
  1109. X
  1110. Xstruct kbox    *kp;
  1111. X
  1112. X{
  1113. X  int    i;
  1114. X
  1115. X  if ((i = readstate (kp, newstate, zonedata)) != STATE_LENGTH) {
  1116. X      logerr ("config: State file wrong length %d for %s\n", i, kp->name);
  1117. X      return;
  1118. X  }
  1119. X  if (send_who () < 0)
  1120. X      return;
  1121. X  if (send_reset (kp) < 0)
  1122. X      return;
  1123. X  sleep (3);            /* Give kbox time to reset    */
  1124. X  if (send_who () < 0)
  1125. X      return;
  1126. X  if (send_promram (kp) <= 0)
  1127. X      return;
  1128. X  if (send_boot (kp, zonedata, zonelen) <= 0)
  1129. X      return;
  1130. X  if (send_getstate (kp) <= 0)
  1131. X      return;
  1132. X  newstate[O_NODE] = kboxstate[O_NODE];
  1133. X  newstate[O_ETNODE] = kboxstate[O_ETNODE];
  1134. X  strcpy (&newstate[O_NAME], kp->name);
  1135. X  strcpy (&newstate[O_FILE], kp->bootfile);
  1136. X  strcpy (&newstate[O_CONFIG], kp->conffile);
  1137. X  if (debug)
  1138. X      fprintf (stderr, "download: Setting zonelist to %X\n", zonelistp);
  1139. X  bcopy (&zonelistp, &newstate[O_ZONELIST], sizeof (zonelistp));
  1140. X  if (send_putstate (kp) <= 0)
  1141. X      return;
  1142. X  send_execute (kp);
  1143. X}
  1144. X
  1145. X/*
  1146. X * config - Config kbox.
  1147. X */
  1148. Xconfig (kp)
  1149. X
  1150. Xstruct kbox    *kp;
  1151. X
  1152. X{
  1153. X  int    i;
  1154. X
  1155. X  if ((i = readstate (kp, newstate, zonedata)) != STATE_LENGTH) {
  1156. X      logerr ("config: State file wrong length %d for %s\n", i, kp->name);
  1157. X      return;
  1158. X  }
  1159. X  if (send_who () < 0)
  1160. X      return;
  1161. X  if (send_exprom (kp) < 0)
  1162. X      return;
  1163. X  if (send_who () < 0)
  1164. X      return;
  1165. X  if (send_promram (kp) <= 0)
  1166. X      return;
  1167. X  if (send_getstate (kp) <= 0)
  1168. X      return;
  1169. X  newstate[O_NODE] = kboxstate[O_NODE];
  1170. X  newstate[O_ETNODE] = kboxstate[O_ETNODE];
  1171. X  strncpy (&newstate[O_NAME], &kboxstate[O_NAME], NAMELEN);
  1172. X  strncpy (&newstate[O_FILE], &kboxstate[O_FILE], NAMELEN);
  1173. X  strncpy (&newstate[O_CONFIG], kp->conffile, CONFIGLEN);
  1174. X  if (send_putstate (kp) <= 0)
  1175. X      return;
  1176. X  if (send_who () < 0)
  1177. X      return;
  1178. X  send_execute (kp);
  1179. X}
  1180. X
  1181. X/*
  1182. X * savestate - Read state for kbox and save to file.
  1183. X */
  1184. Xsavestate (kp)
  1185. X
  1186. Xstruct kbox    *kp;
  1187. X
  1188. X{
  1189. X  char    fn[MAXFN];
  1190. X  int    fd;
  1191. X
  1192. X  if (send_who () < 0)
  1193. X      return;
  1194. X  if (send_promram (kp) <= 0)
  1195. X      return;
  1196. X  if (send_getstate (kp) <= 0)
  1197. X      return;
  1198. X  sprintf (fn, "%s/%s.state", etcdir, kp->name);
  1199. X  if ((fd = open (fn, O_WRONLY|O_CREAT, 0644)) == -1) {
  1200. X      logerr ("savestate: %s - %s\n", fn, sys_errlist[errno]);
  1201. X      return;
  1202. X  }
  1203. X  write (fd, kboxstate, STATE_LENGTH);
  1204. X  close (fd);
  1205. X}
  1206. X
  1207. X/*
  1208. X * liststate - Read state for kbox and print.
  1209. X */
  1210. Xliststate (kp)
  1211. X
  1212. Xstruct kbox    *kp;
  1213. X
  1214. X{
  1215. X  char    fn[MAXFN];
  1216. X  int    fd;
  1217. X
  1218. X  if (send_who () < 0)
  1219. X      return;
  1220. X  if (send_promram (kp) <= 0)
  1221. X      return;
  1222. X  if (send_getstate (kp) <= 0)
  1223. X      return;
  1224. X  show_state (stdout, kboxstate);
  1225. X}
  1226. X
  1227. X/*
  1228. X * reset - Reset kbox.
  1229. X */
  1230. Xreset (kp)
  1231. X
  1232. Xstruct kbox    *kp;
  1233. X
  1234. X{
  1235. X  if (send_who () < 0)
  1236. X      return;
  1237. X  send_reset (kp);
  1238. X}
  1239. X
  1240. X/*
  1241. X * writepid - Save pid to file.
  1242. X */
  1243. Xwritepid ()
  1244. X
  1245. X{
  1246. X  char    fn[MAXFN];
  1247. X  FILE    *f;
  1248. X
  1249. X  sprintf (fn, "%s/kboot.pid", etcdir);
  1250. X  if ((f = fopen (fn, "w")) == NULL)
  1251. X      logerr ("main: Can't write pid file %s\n", fn);
  1252. X  else {
  1253. X      fprintf (f, "%d\n", getpid ());
  1254. X      fclose (f);
  1255. X  }
  1256. X}
  1257. X
  1258. X/*
  1259. X * usage - Print usage and die.
  1260. X */
  1261. Xusage ()
  1262. X
  1263. X{
  1264. X  fprintf (stderr, "Usage: %s options\n", progname);
  1265. X  exit (1);
  1266. X}
  1267. X
  1268. X/*
  1269. X * hash - Return hash index into kbox hash table.
  1270. X */
  1271. Xint hash (s)
  1272. X
  1273. Xregister char    *s;
  1274. X
  1275. X{
  1276. X  register int    h;
  1277. X
  1278. X  while (*s)
  1279. X      h = (h << 1) ^ *s++;
  1280. X  return (h % HTSIZE);
  1281. X}
  1282. X
  1283. X/*
  1284. X * ht_init - Init kbox hash table.
  1285. X */
  1286. Xht_init ()
  1287. X
  1288. X{
  1289. X  int    i;
  1290. X
  1291. X  for (i = 0; i < HTSIZE; i++)
  1292. X      kboxtab[i] = NULL;
  1293. X}
  1294. X
  1295. X/*
  1296. X * ht_free - Clear out hash table.
  1297. X */
  1298. Xht_free ()
  1299. X
  1300. X{
  1301. X  int        i;
  1302. X  struct kbox    *kp;
  1303. X  struct kbox    *nkp;
  1304. X
  1305. X  for (i = 0; i < HTSIZE; i++) {
  1306. X      for (kp = kboxtab[i]; kp; kp = nkp) {
  1307. X      nkp = kp->nxt;
  1308. X      free (kp);
  1309. X      }
  1310. X      kboxtab[i] = NULL;
  1311. X  }
  1312. X}
  1313. X      
  1314. X/*
  1315. X * add_kbox - Add kbox to hash table.
  1316. X */
  1317. Xadd_kbox (name, bootfile)
  1318. X
  1319. Xchar    *name;
  1320. Xchar    *bootfile;
  1321. X
  1322. X{
  1323. X  int            h;
  1324. X  struct kbox        *kp;
  1325. X  char            *p;
  1326. X  struct hostent    *he;
  1327. X  struct ether_addr    e;
  1328. X
  1329. X  if (ether_hostton (name, &e) != 0) {
  1330. X      logerr ("add_kbox: Can't find %s in ethers file\n", name);
  1331. X      return;
  1332. X  }
  1333. X  if ((he = gethostbyname (name)) == NULL) {
  1334. X      logerr ("add_kbox: Can't find %s in host table\n", name);
  1335. X      return;
  1336. X  }
  1337. X  if ((kp = (struct kbox *) malloc (sizeof (struct kbox))) == NULL) {
  1338. X      logerr ("add_kbox: No memory for %s in table\n", name);
  1339. X      exit (1);
  1340. X  }
  1341. X  h = hash (name);
  1342. X  kp->nxt = kboxtab[h];
  1343. X  kboxtab[h] = kp;
  1344. X  kp->reload = 0;
  1345. X  strcpy (kp->name, name);
  1346. X  strcpy (kp->bootfile, bootfile);
  1347. X  kp->aa = AT_Broadcast;    /* Set to bogus value until get from kb    */
  1348. X  ether_copy (&e, &kp->ea);
  1349. X  bcopy (he->h_addr, &kp->ip.sin_addr.s_addr, he->h_length);
  1350. X}
  1351. X
  1352. X/*
  1353. X * get_kbox - Find kbox in hash table.
  1354. X */
  1355. Xstruct kbox *get_kbox (name)
  1356. X
  1357. Xchar    *name;
  1358. X
  1359. X{
  1360. X  register struct kbox    *kp;
  1361. X
  1362. X  kp = kboxtab[hash (name)];
  1363. X  while (kp)
  1364. X      if (!strcmp (name, kp->name))
  1365. X      return (kp);
  1366. X      else
  1367. X      kp = kp->nxt;
  1368. X  return (NULL);
  1369. X}
  1370. X
  1371. X/*
  1372. X * readcf - Read config file.
  1373. X */
  1374. Xreadcf ()
  1375. X
  1376. X
  1377. X{
  1378. X  FILE    *f;
  1379. X  char    fn[MAXFN];
  1380. X  char    name[MAXHOSTNAME];
  1381. X  char    bootfile[MAXFN];
  1382. X
  1383. X  sprintf (fn, "%s/kbootcf", etcdir);
  1384. X  if ((f = fopen (fn, "r")) == NULL) {
  1385. X      logerr ("readcf: %s - %s\n", fn, sys_errlist[errno]);
  1386. X      exit (1);
  1387. X  }
  1388. X  while (!feof (f)) {
  1389. X      numkbox++;
  1390. X      if (fscanf (f, "%s %s\n", name, bootfile) != 2) {
  1391. X      logerr ("readcf: Badly formatted config file '%s' line %d\n",
  1392. X          fn, numkbox);
  1393. X      exit (1);
  1394. X      }
  1395. X      add_kbox (name, bootfile);
  1396. X  }
  1397. X  fclose (f);
  1398. X}
  1399. X
  1400. X/*
  1401. X * readstate - Read kbox config.  Returns length.  Looks for ascii file
  1402. X *   generated by fastpath manager first, then looks for binary file
  1403. X *   made by savestate().
  1404. X */
  1405. Xint readstate (kp, state, zonedata)
  1406. X
  1407. Xstruct kbox    *kp;
  1408. Xunsigned char    *state;
  1409. Xunsigned char    *zonedata;
  1410. X
  1411. X{
  1412. X  FILE        *f;
  1413. X  int        c;
  1414. X  unsigned char    *cp;
  1415. X  int        fd;
  1416. X  int        len;
  1417. X
  1418. X  zonelen = 0;
  1419. X  sprintf (kp->conffile, "%s/%s.config", etcdir, kp->name);
  1420. X  if ((f = fopen (kp->conffile, "r")) == NULL) {
  1421. X      sprintf (kp->conffile, "%s/%s.state", etcdir, kp->name);
  1422. X      if ((fd = open (kp->conffile, O_RDONLY)) == -1) {
  1423. X      logerr ("readstate: Can't read state file for %s\n", kp->name);
  1424. X      return;
  1425. X      }
  1426. X      len = read (fd, state, STATE_LENGTH);
  1427. X      close (fd);
  1428. X  } else {
  1429. X      cp = state;
  1430. X      len = 0;
  1431. X      while ((c = fgetc (f)) >= 0) {
  1432. X      if (c == '*') {
  1433. X          while ((c = fgetc (f)) >= 0 && c != '\n' && c != '\r');
  1434. X          continue;
  1435. X      }
  1436. X      while (c >= 0 && c != '\n' && c != '\r') {
  1437. X          *cp = fromhex (c) << 4;
  1438. X          *cp++ |= fromhex (c = fgetc (f));
  1439. X          c = fgetc (f);
  1440. X      }
  1441. X      if (cp - state == STATE_LENGTH) {
  1442. X          zonelen = readzones (f, c, zonedata);
  1443. X          break;
  1444. X      }
  1445. X      }
  1446. X      fclose (f);
  1447. X      len = cp - state;
  1448. X  }
  1449. X  if (zonelen == 0) {
  1450. X      zonedata[0] = 0;
  1451. X      zonedata[1] = 0;
  1452. X      zonelen = 2;
  1453. X  }
  1454. X  return (len);
  1455. X}
  1456. X
  1457. X/*
  1458. X * readzones - Read zone list from config file, c is first char.
  1459. X */
  1460. Xint readzones (f, c, zonedata)
  1461. X
  1462. XFILE        *f;
  1463. Xint        c;
  1464. Xunsigned char    *zonedata;
  1465. X
  1466. X{
  1467. X  unsigned char    *cp;
  1468. X  unsigned char    *lenp;
  1469. X  short        numzones;
  1470. X
  1471. X  cp = zonedata + 2;            /* Skip # zones        */
  1472. X  numzones = 0;
  1473. X  while ((c = fgetc (f)) >= 0) {
  1474. X      if (c == '\r' || c == '\n')
  1475. X      continue;
  1476. X      if (c == '*') {
  1477. X      while ((c = fgetc (f)) >= 0 && c != '\n' && c != '\r');
  1478. X      continue;
  1479. X      }
  1480. X      lenp = cp++;
  1481. X      while (c >= 0 && c != '\n' && c != '\r') {
  1482. X      *cp++ = c;
  1483. X      c = fgetc (f);
  1484. X      }
  1485. X      *lenp = (cp - lenp) - 1;
  1486. X      numzones++;
  1487. X  }
  1488. X  bcopy (&numzones, zonedata, sizeof (numzones));
  1489. X  return (cp - zonedata);
  1490. X}
  1491. X
  1492. X/*
  1493. X * fromhex - Convert char from hex to decimal.
  1494. X */
  1495. Xint fromhex (c)
  1496. X
  1497. Xchar    c;
  1498. X
  1499. X{
  1500. X  if (c >= '0' && c <= '9')
  1501. X      return (c - '0');
  1502. X  else if (c >= 'a' && c <= 'f')
  1503. X      return (c - 'a' + 10);
  1504. X  else
  1505. X      return (c - 'A' + 10);
  1506. X}
  1507. X
  1508. X/*
  1509. X * kboot_rpcsvr - Handle rpc requests.
  1510. X */
  1511. Xkboot_rpcsvr (request, xprt)
  1512. X
  1513. Xstruct svc_req    *request;
  1514. XSVCXPRT        *xprt;
  1515. X
  1516. X{
  1517. X  struct sockaddr_in    *sa;
  1518. X  char            *kbox;
  1519. X  int            r;
  1520. X  struct kbox        *kp;
  1521. X
  1522. X  sa = svc_getcaller (xprt);
  1523. X  if (debug)
  1524. X      fprintf (stderr, "kboot_rpcsvr: Request %d from %s\n",
  1525. X           request->rq_proc, inet_ntoa (sa->sin_addr));
  1526. X  if (sa->sin_port >= IPPORT_RESERVED) {
  1527. X      logerr ("kboot_rpcsvr: Bad port %d from %s\n",
  1528. X          sa->sin_port, inet_ntoa (sa->sin_addr));
  1529. X      r = -1;
  1530. X      if (!svc_sendreply (xprt, xdr_int, (caddr_t) &r))
  1531. X      logerr ("kboot_rpcsvr: svc_sendreply failed\n");
  1532. X      return;
  1533. X  }
  1534. X  switch (request->rq_proc) {
  1535. X    case NULLPROC:
  1536. X      if (!svc_sendreply (xprt, xdr_void, 0))
  1537. X      logerr ("kboot_rpcsvr(NULLPROC): svc_sendreply failed\n");
  1538. X      break;
  1539. X
  1540. X    case KBOOTPROC_RELOAD:
  1541. X      kbox = NULL;
  1542. X      if (svc_getargs (xprt, xdr_wrapstring, &kbox)) {
  1543. X      if (!(kp = get_kbox (kbox))) {
  1544. X          logerr ("kboot_rpcsvr: No such kbox %s\n", kbox);
  1545. X          r = -1;
  1546. X      } else
  1547. X          r = 0;
  1548. X      } else {
  1549. X      logerr ("kboot_rpcsvr(RELOAD): svc_getargs failed\n");
  1550. X      r = -1;
  1551. X      }
  1552. X      if (!svc_sendreply (xprt, xdr_int, (caddr_t) &r))
  1553. X      logerr ("kboot_rpcsvr(RELOAD): svc_sendreply failed\n");
  1554. X      if (r >= 0) {
  1555. X      kp->reload++;
  1556. X      alarm (1);
  1557. X      if (debug)
  1558. X          fprintf (stderr, "kboot_rpcsvr: Requesting load of %s\n", kbox);
  1559. X      }
  1560. X      xdr_free (xdr_wrapstring, &kbox);
  1561. X      break;
  1562. X
  1563. X    default:
  1564. X      svcerr_noproc (xprt);
  1565. X      break;
  1566. X  }
  1567. X}
  1568. X
  1569. X/*
  1570. X * Initialize RPC stuff.
  1571. X */
  1572. Xrpc_init ()
  1573. X
  1574. X{
  1575. X  SVCXPRT    *xprt;
  1576. X
  1577. X  if ((xprt = svcudp_create (RPC_ANYSOCK)) == NULL) {
  1578. X      logerr ("rpc_init: svcudp_create failed\n");
  1579. X      exit (1);
  1580. X  }
  1581. X  pmap_unset (KBOOTPROG, KBOOTVERS);
  1582. X  if (!svc_register (xprt, KBOOTPROG, KBOOTVERS, kboot_rpcsvr, IPPROTO_UDP)) {
  1583. X      logerr ("rpc_init: Can't register %d %d\n", KBOOTPROG, KBOOTVERS);
  1584. X      exit (1);
  1585. X  }
  1586. X}
  1587. X
  1588. X/*
  1589. X * kboot_reload - Ask kboot on rhost to reload kbox.
  1590. X */
  1591. Xkboot_reload (kbox, rhost)
  1592. X
  1593. Xchar    *kbox;
  1594. Xchar    *rhost;
  1595. X
  1596. X{
  1597. X  int    s;
  1598. X  int    r;
  1599. X
  1600. X  if (rhost == NULL)
  1601. X      rhost = "localhost";
  1602. X  if (debug)
  1603. X      fprintf (stderr, "kboot_reload: Requesting reboot of %s on %s\n",
  1604. X           kbox, rhost);
  1605. X/*
  1606. X * kboot will only accept rpc requests from privileged ports. callrpc
  1607. X * will use a privileged port by default if it can (we're root).
  1608. X */
  1609. X  if ((s = callrpc (rhost, KBOOTPROG, KBOOTVERS, KBOOTPROC_RELOAD,
  1610. X            xdr_wrapstring, &kbox, xdr_int, &r)) != 0) {
  1611. X      clnt_perrno (s);
  1612. X      exit (1);
  1613. X  }
  1614. X  printf ("%s reload request %s\n", kbox, r == 0 ? "accepted" : "failed");
  1615. X}
  1616. END_OF_FILE
  1617. if test 15749 -ne `wc -c <'kboot.c'`; then
  1618.     echo shar: \"'kboot.c'\" unpacked with wrong size!
  1619. fi
  1620. # end of 'kboot.c'
  1621. fi
  1622. if test -f 'nitlib.c' -a "${1}" != "-c" ; then 
  1623.   echo shar: Will not clobber existing file \"'nitlib.c'\"
  1624. else
  1625. echo shar: Extracting \"'nitlib.c'\" \(6314 characters\)
  1626. sed "s/^X//" >'nitlib.c' <<'END_OF_FILE'
  1627. X#ifndef lint
  1628. Xstatic char    *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/nitlib.c,v 1.2 91/02/12 19:38:10 root Exp $";
  1629. X#endif lint
  1630. X
  1631. X/*
  1632. X * $Log:    nitlib.c,v $
  1633. X * Revision 1.2  91/02/12  19:38:10  root
  1634. X * Don't call fdfunc() if NULL.
  1635. X * 
  1636. X * Revision 1.1  91/01/29  17:37:28  root
  1637. X * Initial revision
  1638. X * 
  1639. X */
  1640. X
  1641. X#include <stdio.h>
  1642. X#include <syslog.h>
  1643. X#include <sys/types.h>
  1644. X#include <sys/time.h>
  1645. X#include <sys/socket.h>
  1646. X#include <sys/file.h>
  1647. X#include <sys/signal.h>
  1648. X#include <netdb.h>
  1649. X#include <net/if.h>
  1650. X#include <sys/ioctl.h>
  1651. X#include <sys/stropts.h>
  1652. X#include <net/nit_if.h>
  1653. X#include <net/nit_pf.h>
  1654. X#include <netinet/in.h>
  1655. X#include <netinet/in_systm.h>
  1656. X#include <netinet/if_ether.h>
  1657. X#include <net/packetfilt.h>
  1658. X#include "config.h"
  1659. X
  1660. X#define MAXPKT        1500
  1661. X#define OFFSET(t,f)    ((int) &(((t *) NULL)->f))
  1662. X
  1663. Xextern char    *malloc ();
  1664. Xextern char    *strdup ();
  1665. X
  1666. Xextern int    debug;
  1667. Xextern int    detached;
  1668. Xextern int    errno;
  1669. Xextern char    *sys_errlist[];
  1670. X
  1671. X/*
  1672. X * Globals.
  1673. X */
  1674. Xstruct ether_addr    myether;
  1675. Xint            nit_fd;
  1676. Xchar            nitbuf[MAXPKT];
  1677. Xint            numfds;
  1678. Xchar            *interface;
  1679. X
  1680. X/*
  1681. X * nit_init - Initialize nit library.
  1682. X */
  1683. Xnit_init (dev)
  1684. X
  1685. Xchar    *dev;
  1686. X
  1687. X{
  1688. X  struct ifconf        ifc;
  1689. X  int            s;
  1690. X  char            buf[BUFSIZ];
  1691. X
  1692. X  numfds = getdtablesize ();
  1693. X  if (dev == NULL) {
  1694. X      if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
  1695. X            logerr ("nit_init: socket - %s\n", sys_errlist[errno]);
  1696. X            exit(1);
  1697. X      }
  1698. X      ifc.ifc_len = BUFSIZ;
  1699. X      ifc.ifc_buf = buf;
  1700. X      if (ioctl (s, SIOCGIFCONF, (caddr_t) &ifc) < 0) {
  1701. X          logerr ("nit_init: ioctl(SIOCGIFCONF) - %s\n", sys_errlist[errno]);
  1702. X          exit(1);
  1703. X      }
  1704. X      close(s);
  1705. X      interface = strdup (ifc.ifc_req->ifr_name);
  1706. X  } else
  1707. X      interface = dev;
  1708. X  if (debug)
  1709. X      fprintf (stderr, "nit_init: Using interface %s\n", interface);
  1710. X}
  1711. X
  1712. X/*
  1713. X * nit_open - Open NIT device and bind to an interface.
  1714. X *   Prints an error and exits if there's a problem.
  1715. X */
  1716. Xnit_open (snaplen, pkttype)
  1717. X
  1718. Xint    snaplen;
  1719. Xint    pkttype;
  1720. X
  1721. X{
  1722. X  int            s;
  1723. X  struct packetfilt    pf;
  1724. X  u_short        *pfp;
  1725. X  struct ifreq        ifr;
  1726. X
  1727. X  if ((nit_fd = open ("/dev/nit", O_RDWR)) < 0) {    /* Open NIT dev    */
  1728. X      logerr ("nit_open: open(/dev/nit) - %s\n", sys_errlist[errno]);
  1729. X      exit (1);
  1730. X  }
  1731. X  if (ioctl (nit_fd, I_SRDOPT, (caddr_t) RMSGD) < 0) {    /* Discrete msgs*/
  1732. X      logerr ("nit_open: ioctl(I_SRDOPT) - %s\n", sys_errlist[errno]);
  1733. X      exit (1);
  1734. X  }
  1735. X  if (pkttype) {
  1736. X      if (ioctl (nit_fd, I_PUSH, "pf") < 0) {    /* Setup packet filter    */
  1737. X          logerr ("nit_open: ioctl(I_PUSH: pf) - %s\n", sys_errlist[errno]);
  1738. X          exit (1);
  1739. X      }
  1740. X      pfp = pf.Pf_Filter;
  1741. X      *pfp++ = ENF_PUSHWORD +
  1742. X    OFFSET (struct ether_header, ether_type) / sizeof (u_short);
  1743. X      *pfp++ = ENF_PUSHLIT | ENF_EQ;
  1744. X      *pfp++ = htons (pkttype);
  1745. X      pf.Pf_FilterLen = ((int) pfp - (int) pf.Pf_Filter) / sizeof (u_short);
  1746. X      if (ioctl (nit_fd, NIOCSETF, (caddr_t) &pf) < 0) {
  1747. X          logerr ("nit_open: ioctl(NIOCSETF) - %s\n", sys_errlist[errno]);
  1748. X          exit (1);
  1749. X      }
  1750. X  }
  1751. X  strncpy (ifr.ifr_name, interface, sizeof ifr.ifr_name);
  1752. X  ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0';
  1753. X  if (ioctl (nit_fd, NIOCBIND, &ifr) < 0) {
  1754. X      logerr ("nit_open: ioctl(NIOCBIND) - %s\n", sys_errlist[errno]);
  1755. X      exit(1);
  1756. X  }
  1757. X                        /* Get ethernet address    */
  1758. X  if (ioctl (nit_fd, SIOCGIFADDR, (caddr_t) &ifr) < 0) {
  1759. X      logerr ("nit_open: ioctl(SIOCGIFADDR) - %s\n", sys_errlist[errno]);
  1760. X      exit (1);
  1761. X  }
  1762. X  ether_copy (ifr.ifr_addr.sa_data, &myether);
  1763. X  if (snaplen > 0) {                            /* Set snapshot length  */
  1764. X      if (ioctl (nit_fd, NIOCSSNAP, (caddr_t) &snaplen) < 0) {
  1765. X          logerr ("nit_open: ioctl (NIOCSSNAP) - %s\n", sys_errlist[errno]);
  1766. X          exit (1);
  1767. X      }
  1768. X  }
  1769. X}
  1770. X
  1771. X/*
  1772. X * nit_close - Close nit file descriptor.
  1773. X */
  1774. Xnit_close ()
  1775. X
  1776. X{
  1777. X  close (nit_fd);
  1778. X}
  1779. X
  1780. X/*
  1781. X * timeout - Return timeval structure for timeout specified in ticks for
  1782. X *   reads from nit device.  Ticks are 1/60 of a second.  A timeout of 0
  1783. X *   means reads will not timeout.
  1784. X */
  1785. Xnit_timeout (ticks, tv)
  1786. X
  1787. Xint        ticks;
  1788. Xstruct timeval    *tv;
  1789. X
  1790. X{
  1791. X  tv->tv_sec = ticks / 60;            /* Set timeout        */
  1792. X  tv->tv_usec = ((ticks * 1000000) / 60) % 1000000;
  1793. X}
  1794. X
  1795. X/*
  1796. X * nit_write - Send a raw ethernet packet.
  1797. X */
  1798. Xnit_write (eh, pkt, len)
  1799. X
  1800. Xstruct ether_header    *eh;
  1801. Xcaddr_t            pkt;
  1802. Xint            len;
  1803. X
  1804. X{
  1805. X  struct sockaddr    sa;
  1806. X  struct strbuf        cbuf;
  1807. X  struct strbuf        dbuf;
  1808. X
  1809. X  sa.sa_family = AF_UNSPEC;
  1810. X  bcopy (eh, sa.sa_data, sizeof (*eh));
  1811. X  cbuf.len = sizeof sa;
  1812. X  cbuf.buf = (caddr_t) &sa;
  1813. X  dbuf.len = len;
  1814. X  dbuf.buf = pkt;
  1815. X  if (putmsg (nit_fd, &cbuf, &dbuf, 0) < 0) {
  1816. X      logerr ("nit_write: putmsg - %s\n", sys_errlist[errno]);
  1817. X      exit (1);
  1818. X  }
  1819. X}
  1820. X
  1821. X/*
  1822. X * nit_dispatch - Read and process n packets.  If n is 0 read forever.
  1823. X *   Calls "func" for each packet with the arguments:
  1824. X *
  1825. X *    (*func) (pp, pl)
  1826. X *      pp = packet pointer
  1827. X *      pl = length of packet
  1828. X *
  1829. X *   If an application is waiting for input on other file descriptors
  1830. X *   they can be specified in "fds".  "fdfunc" will be called with
  1831. X *   the set of descriptors that have input waiting before the current
  1832. X *   packet is processed.  Returns 0 on timeout, 1 otherwise.
  1833. X */
  1834. Xint nit_dispatch (func, n, fds, fdfunc, timeout)
  1835. X
  1836. Xint        (*func)();
  1837. Xint        n;
  1838. Xfd_set        *fds;
  1839. Xint        (*fdfunc)();
  1840. Xstruct timeval    *timeout;
  1841. X
  1842. X{
  1843. X  int        i;
  1844. X  int        numpkts;
  1845. X  fd_set    fdset;
  1846. X  fd_set    rfds;
  1847. X
  1848. X  numpkts = 0;
  1849. X  if (fds)
  1850. X      fdset = *fds;
  1851. X  else
  1852. X      FD_ZERO (&fdset);
  1853. X  FD_SET (nit_fd, &fdset);
  1854. X  while (n == 0 || numpkts < n) {
  1855. X      rfds = fdset;
  1856. X      i = select (numfds, &rfds, NULL, NULL, timeout);
  1857. X      if (i == 0)
  1858. X      return (0);            /* Timeout            */
  1859. X      if (FD_ISSET (nit_fd, &rfds)) {
  1860. X      numpkts++;
  1861. X      FD_CLR (nit_fd, &rfds);
  1862. X      if (i > 1)
  1863. X          (*fdfunc) (&rfds);
  1864. X      } else if (fdfunc) {
  1865. X      (*fdfunc) (&rfds);
  1866. X      continue;
  1867. X      }
  1868. X      if ((i = read (nit_fd, nitbuf, MAXPKT)) < 0) {
  1869. X          lseek (nit_fd, 0, 0);        /* File pointer may've wrapped    */
  1870. X          if ((i = read (nit_fd, nitbuf, MAXPKT)) < 0) {
  1871. X          logerr ("nit_dispatch: read - %s\n", sys_errlist[errno]);
  1872. X          exit (1);
  1873. X          }
  1874. X      }
  1875. X      (*func) (nitbuf, i);
  1876. X  }
  1877. X  return (1);
  1878. X}
  1879. X
  1880. X/*
  1881. X * logerr - Log error to stderr (if debug) or syslog.
  1882. X */
  1883. Xlogerr (fmt, a1, a2, a3)
  1884. X
  1885. Xchar    *fmt;
  1886. Xchar    *a1;
  1887. Xchar    *a2;
  1888. Xchar    *a3;
  1889. X
  1890. X{
  1891. X  if (detached)
  1892. X      syslog (LOG_ERR, fmt, a1, a2, a3);
  1893. X  else
  1894. X      fprintf (stderr, fmt, a1, a2, a3);
  1895. X}
  1896. END_OF_FILE
  1897. if test 6314 -ne `wc -c <'nitlib.c'`; then
  1898.     echo shar: \"'nitlib.c'\" unpacked with wrong size!
  1899. fi
  1900. # end of 'nitlib.c'
  1901. fi
  1902. echo shar: End of archive 1 \(of 2\).
  1903. cp /dev/null ark1isdone
  1904. MISSING=""
  1905. for I in 1 2 ; do
  1906.     if test ! -f ark${I}isdone ; then
  1907.     MISSING="${MISSING} ${I}"
  1908.     fi
  1909. done
  1910. if test "${MISSING}" = "" ; then
  1911.     echo You have unpacked both archives.
  1912.     rm -f ark[1-9]isdone
  1913. else
  1914.     echo You still need to unpack the following archives:
  1915.     echo "        " ${MISSING}
  1916. fi
  1917. ##  End of shell archive.
  1918. exit 0
  1919.  
  1920.  
  1921.