home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-22 | 44.0 KB | 1,921 lines |
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 2)."
- # Contents: cmd.c icmp.c kboot.c nitlib.c
- # Wrapped by bobs@chumley on Wed Feb 13 22:14:58 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'cmd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cmd.c'\"
- else
- echo shar: Extracting \"'cmd.c'\" \(15515 characters\)
- sed "s/^X//" >'cmd.c' <<'END_OF_FILE'
- X#ifndef lint
- 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 $";
- X#endif lint
- X
- X/*
- X * $Log: cmd.c,v $
- X * Revision 1.2 91/02/12 19:38:49 root
- X * Removed unused commands.
- X *
- X * Revision 1.1 91/01/29 17:36:59 root
- X * Initial revision
- X *
- X */
- X
- X/*
- X * cmd.c - Send commands to kboxes.
- X */
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <netdb.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <sys/errno.h>
- X#include <net/if.h>
- X#include <netinet/in.h>
- X#include <netinet/if_ether.h>
- X#include <sys/time.h>
- X#include <sys/timeb.h>
- X#include "appletalk.h"
- X#include "cmdidx.h"
- X#include "kbox.h"
- X#include "config.h"
- X
- Xextern struct hostent *gethostbyaddr ();
- Xextern char *inet_ntoa ();
- Xstruct kbox *get_kbox ();
- Xextern int errno;
- Xextern char *sys_errlist[];
- Xextern int numkbox;
- Xextern int debug;
- Xextern struct ether_addr ebc;
- Xextern struct ether_header eh;
- Xextern struct kbox *kboxtab[HTSIZE];
- Xextern long atalkaddr;
- Xextern unsigned char kboxstate[STATE_LENGTH];
- Xextern unsigned char newstate[STATE_LENGTH];
- Xextern char *etcdir;
- Xextern unsigned char *zonelistp;
- X
- X#define HEX(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
- X
- X/*
- X * Globals.
- X */
- Xint (*recv_copyproc) () = NULL;
- Xstruct ether_fastpath fppkt;
- Xstruct fp_promram promram;
- Xint num_resp;
- Xint expected_resp;
- Xint destkbox;
- Xstruct kbox *kboxaddr[MAXKBOX];
- Xstruct timeval timeout;
- X
- X/*
- X * Receive functions. There should be a recv_ function for each send_
- X * function.
- X */
- X
- X/*
- X * recv_who - Process who packet. Algorithm is to look up the ethernet
- X * address in the ethers file and then add this kbox to the hash
- X * table it's not already there. It would probably be more efficient
- X * to look up the ethernet address directly in a table hashed by ethernet
- X * address, however recv_who isn't called very often so I won't bother.
- X */
- Xrecv_who (p)
- X
- Xstruct fp_packet *p;
- X
- X{
- X char name[MAXHOSTNAME];
- X char buf[20];
- X struct kbox *kp;
- X
- X if (ether_ntohost (name, &p->fp_shost) != 0) {
- X logerr ("recv_who: Can't find %s in ethers table\n",
- X ether_ntoa (&p->fp_shost));
- X return;
- X }
- X if (kp = get_kbox (name)) {
- X if (!bcmp (&kp->ea, &p->fp_shost, sizeof(struct ether_addr))) {
- X if (kp->aa == AT_Broadcast) {
- X kp->aa = p->fp_lapsrc;
- X kboxaddr[kp->aa] = kp;
- X if (debug)
- X fprintf (stderr, "recv_who: Adding kbox %s %s\n",
- X name, ether_ntoa (&p->fp_shost));
- X num_resp++;
- X }
- X } else {
- X strcpy (buf, ether_ntoa (&kp->ea));
- X logerr ("recv_who: Mismatched ether address for %s: %s != %s\n",
- X name, buf, ether_ntoa (&p->fp_shost));
- X }
- X } else if (debug)
- X fprintf (stderr, "recv_who: Unknown kbox %s %s\n",
- X name, ether_ntoa (&p->fp_shost));
- X}
- X
- X/*
- X * recv_promram - Receive promram vector. On sparc machines the
- X * fp_promram structure doesn't align properly, so copy the count
- X * field separately.
- X */
- Xrecv_promram (p)
- X
- Xstruct fp_packet *p;
- X
- X{
- X bcopy (p->fp_data, &promram.fpr_count, sizeof(promram.fpr_count));
- X bcopy (&p->fp_data[sizeof(promram.fpr_count)], &promram.fpr_jtable,
- X PROMRAMSIZE - sizeof(promram.fpr_count));
- X num_resp++;
- X}
- X
- X/*
- X * recv_getstate - Receive state vector.
- X */
- Xrecv_getstate (p)
- X
- Xstruct fp_packet *p;
- X
- X{
- X bcopy (&p->fp_data[FPCOPYSIZE], kboxstate, STATE_LENGTH);
- X if (debug) {
- X fprintf (stderr, "recv_getstate: Received state...\n");
- X show_state (stderr, kboxstate);
- X }
- X num_resp++;
- X}
- X
- X/*
- X * inet_ntos - Translate ip address to hostname.
- X */
- Xchar *inet_ntos (addr)
- X
- Xunsigned char *addr;
- X
- X{
- X struct in_addr a;
- X struct hostent *he;
- X
- X bcopy (addr, &a.s_addr, 4);
- X if ((he = gethostbyaddr (&a, 4, AF_INET)) == NULL)
- X return (inet_ntoa (a));
- X else
- X return (he->h_name);
- X}
- X
- X/*
- X * show_state - Print state vector.
- X */
- Xshow_state (f, s)
- X
- XFILE *f;
- Xunsigned char s[STATE_LENGTH];
- X
- X{
- X int options;
- X int i;
- X int first;
- X long l;
- X short st;
- X
- X fprintf (f, "\tAppletalk: %d.%d.%d Ethertalk: %d.%d.%d IPtalk: %d.%d.%d",
- X s[O_ATNET], s[O_ATNET+1], s[O_NODE],
- X s[O_ETNET], s[O_ETNET+1], s[O_ETNODE],
- X s[O_UDPNET], s[O_UDPNET+1], s[O_UDPNODE]);
- X fprintf (f, " Bridge: %d\n", s[O_BRIDGE]);
- X fprintf (f, "\tEthernet: %s Name: \"%s\" File: \"%s\"\n",
- X ether_ntoa (&s[O_ETHER]), &s[O_NAME], &s[O_FILE]);
- X fprintf (f, "\tConfig: \"%s\"\n", &s[O_CONFIG]);
- X fprintf (f, "\tATzone: \"%s\" ETzone: \"%s\" UDPzone: \"%s\"\n",
- X &s[O_ATZONE], &s[O_ETZONE], &s[O_UDPZONE]);
- X fprintf (f, "\tPforce: %d Autoconfig: %s", s[O_PFORCE],
- X (s[O_AUTOCONFIG] || s[O_AUTOCONFIG+1]) ? "yes" : "no");
- X fprintf (f, " Autoboot: %s",
- X (s[O_AUTOBOOT] || s[O_AUTOBOOT+1]) ? "yes\n" : "no\n");
- X fprintf (f, "\tOptions: ");
- X bcopy (&s[O_OPTIONS], &options, sizeof(options));
- X if (options) {
- X for (first = 1, i = 0; i < 32; i++)
- X if ((1 << i) & options)
- X if (first) {
- X first = 0;
- X fprintf (f, "%d", i + 1);
- X } else
- X fprintf (f, ", %d", i+1);
- X } else
- X fprintf (f, "none");
- X bcopy (&s[O_SN], &l, sizeof (l));
- X bcopy (&s[O_TYPE], &st, sizeof (st));
- X fprintf (f, " Serial: %d Type: %d\n", l, st);
- X fprintf (f, "\tRouter: \"%s\"", inet_ntos (&s[O_IPDEFROUTER]));
- X fprintf (f, " ETip: \"%s\"", inet_ntos (&s[O_IPADDRESS]));
- X fprintf (f, " ATip: \"%s\"", inet_ntos (&s[O_ATIPADDRESS]));
- X fprintf (f, " Broadcast: \"%s\"\n", inet_ntos (&s[O_IPBROADCAST]));
- X fprintf (f, "\tSubnet: \"%s\"", inet_ntos (&s[O_IPSUBMASK]));
- X fprintf (f, " KIP: \"%s\"", inet_ntos (&s[O_IPKIPSERVER]));
- X fprintf (f, " Name: \"%s\"", inet_ntos (&s[O_NAMESERVER]));
- X fprintf (f, " File: \"%s\"\n", inet_ntos (&s[O_FILESERVER]));
- X bcopy (&s[O_LP1], &l, sizeof (l));
- X fprintf (f, "\tLocal1: 0x%x", l);
- X bcopy (&s[O_LP2], &l, sizeof (l));
- X fprintf (f, " Local2: 0x%x", l);
- X bcopy (&s[O_LP3], &l, sizeof (l));
- X fprintf (f, " Local3: 0x%x", l);
- X bcopy (&s[O_LP4], &l, sizeof (l));
- X fprintf (f, " Local4: 0x%x\n", l);
- X bcopy (&s[O_NDYNAMICS], &st, sizeof (st));
- X fprintf (f, "\tDynamics: %d", st);
- X bcopy (&s[O_NSTATICS], &st, sizeof (st));
- X fprintf (f, " Statics: %d", st);
- X bcopy (&s[O_ZONELIST], &l, sizeof (l));
- X fprintf (f, " Zonelist 0x%X\n", l);
- X}
- X
- X/*
- X * recv_gen - Generic receive routine.
- X */
- Xrecv_gen (p)
- X
- Xstruct fp_packet *p;
- X
- X{
- X num_resp++;
- X}
- X
- X/*
- X * recv_pkt - Call appropriate function to deal with packet from fastpath.
- X */
- Xrecv_pkt (p)
- X
- Xstruct fp_packet *p;
- X
- X{
- X char buf[100];
- X
- X if (p->fp_laptype != FP_TYPE) {
- X return;
- X }
- X if (destkbox != AT_Broadcast && p->fp_lapsrc != destkbox) {
- X /*
- X * X_WHO responses from unconfigured fastpaths to broadcasts may come
- X * in after we've already started talking to a real fastpath, so
- X * just ignore all X_WHO responses with no error message.
- X */
- X if (p->fp_scmd != X_WHO)
- X logerr ("recv_pkt: Bogus response %d from %s\n",
- X p->fp_scmd, ether_ntoa (&p->fp_shost));
- X return;
- X }
- X if (p->fp_cmd == FP_ACK) {
- X num_resp++;
- X return;
- X }
- X if (p->fp_cmd != FP_RESP)
- X return;
- X switch (p->fp_scmd) {
- X case X_COPYMEM : if (recv_copyproc)
- X (*recv_copyproc) (p);
- X break;
- X
- X case X_PROMRAM : recv_promram (p); break;
- X
- X case X_WHO : recv_who (p); break;
- X
- X case X_RESET : recv_gen ();
- X break;
- X
- X default : ether_ntohost (buf, &p->fp_shost);
- X logerr ("recv_pkt: Received %d from %s\n",
- X p->fp_scmd, buf);
- X break;
- X }
- X}
- X
- X/*
- X * Send procedures. Those that have no parameters are macros that invoke
- X * send_gen(), defined in kbox.h.
- X */
- X
- X/*
- X * send_who - Broadcast who packet.
- X */
- Xint send_who ()
- X
- X{
- X int i;
- X
- X for (i = 0; i < MAXKBOX; i++)
- X if (kboxaddr[i])
- X kboxaddr[i]->aa = AT_Broadcast;
- X nit_timeout (60, &timeout);
- X return (send_pkt (NULL, (int) FP_CMD, X_WHO, 0, 5, &timeout));
- X}
- X
- X/*
- X * send_boot - Download file to kbox.
- X */
- Xint send_boot (kp, zonedata, zonelen)
- X
- Xstruct kbox *kp;
- Xunsigned char *zonedata;
- Xint zonelen;
- X
- X{
- X FILE *f;
- X int l;
- X int ch;
- X int cmd;
- X int scmd;
- X char fn[MAXFN];
- X int size = 0;
- X int lastlen;
- X int lastaddr;
- X
- X sprintf (fn, "%s/%s", etcdir, kp->bootfile);
- X if ((f = fopen (fn, "r")) == NULL) {
- X logerr ("send_boot: %s to %s - %s\n", fn, kp->name, sys_errlist[errno]);
- X return (0);
- X }
- X nit_timeout (30, &timeout);
- X while ((cmd = fgetc (f)) > 0) {
- X if (cmd != 'S') {
- X logerr ("send_boot: Bad S record %d\n", cmd);
- X return (-1);
- X }
- X scmd = fgetc (f);
- X if (scmd == '8') {
- X /*
- X * With KSTAR 8.0 it is necessary to download a zonelist with
- X * KSTAR. The following code converts the zonelist read from
- X * the config file written by the Fastpath Manager into
- X * s-records and sends them to the kbox. The address where
- X * the zonelist is downloaded is the first even address after
- X * the last s-record, which is the address of the last s-record
- X * plus its length, rounded up to the nearest even address.
- X * The first s-record describes the following data, it looks like:
- X *
- X * short num_elements;
- X * struct {
- X * short type;
- X * short length;
- X * } element[NUMELEMENTS];
- X *
- X * For a zonelist the type is 1. The second s-record contains
- X * the zonelist itself. These extra s-records get sent right
- X * before the last s-record, which seems to have scmd == 8.
- X * Much of the information on the format of the s-records and
- X * their location was reverse engineered from packet traces,
- X * I don't guarantee this code to be correct, although it
- X * works for me.
- X */
- X lastlen = atox (fppkt.fastpath_data, 2);
- X lastaddr = atox (&fppkt.fastpath_data[2], 6);
- X zonelistp = (unsigned char *) (lastaddr + lastlen - 4);
- X if ((int) zonelistp % 2 == 1)
- X zonelistp++;
- X makeelemlist (fppkt.fastpath_data, zonelen);
- X if (debug)
- X fprintf (stderr, "send_boot: %s\n", fppkt.fastpath_data);
- X if (send_pkt (kp, 'S', '2', strlen(fppkt.fastpath_data),
- X 5, &timeout) != 1)
- X return (0);
- X makezonedata (fppkt.fastpath_data, zonedata, zonelen);
- X if (debug)
- X fprintf (stderr, "send_boot: %s\n", fppkt.fastpath_data);
- X if (send_pkt (kp, 'S', '2', strlen(fppkt.fastpath_data),
- X 5, &timeout) != 1)
- X return (0);
- X }
- X l = 0;
- X while ((ch = fgetc (f)) > 0 && ch != '\r' && ch != '\n')
- X fppkt.fastpath_data[l++] = ch;
- X size += l;
- X if (send_pkt (kp, cmd, scmd, l, 5, &timeout) != 1)
- X return (0);
- X }
- X if (debug)
- X fprintf (stderr, "send_boot: Downloaded %d bytes\n", size);
- X return (1);
- X}
- X
- X/*
- X * atox - Convert ascii string of length l to hex.
- X */
- Xint atox (s, l)
- X
- Xchar *s;
- Xint l;
- X
- X{
- X int r = 0;
- X int i;
- X
- X for (i = 0; i < l; i++)
- X r = (r << 4) | ((s[i] >= '0' && s[i] <= '9') ? s[i] - '0' :
- X (s[i] >= 'a' && s[i] <= 'f') ? s[i] - 'a' + 10 :
- X s[i] - 'A' + 10);
- X return (r);
- X}
- X
- X/*
- X * csumsrec - Compute checksum for s-record.
- X */
- Xunsigned char csumsrec (s, l)
- X
- Xunsigned char *s;
- Xint l;
- X
- X{
- X unsigned char sum;
- X static char buf[3];
- X
- X sum = 0;
- X while (l--)
- X sum += *s++;
- X sum ^= 0xFF;
- X return (sum);
- X}
- X
- X/*
- X * makeelemlist - Make element list srecord.
- X */
- Xmakeelemlist (p, l)
- X
- Xunsigned char *p;
- Xint l;
- X
- X{
- X static elemlist el = {1, 1, 0};
- X unsigned char buf[BUFSIZ];
- X
- X el.bytes = l + 2; /* Don't know why +2 */
- X bcopy (&zonelistp, buf, sizeof (zonelistp)); /* First byte is length */
- X *buf = 4 + sizeof (el); /* so overwrite it */
- X bcopy (&el, &buf[4], sizeof (el));
- X buf[4 + sizeof (el)] = csumsrec (buf, 4 + sizeof (el));
- X hexify (buf, p, 4 + sizeof (el) + 1);
- X}
- X
- X/*
- X * makezonedata - Make zone data srecord.
- X */
- Xmakezonedata (p, data, l)
- X
- Xunsigned char *p;
- Xunsigned char *data;
- Xint l;
- X
- X{
- X unsigned char *addr;
- X unsigned char buf[BUFSIZ];
- X
- X addr = zonelistp + sizeof (elemlist);
- X bcopy (&addr, buf, sizeof (addr));
- X *buf = 4 + l;
- X bcopy (data, &buf[4], l);
- X buf[4 + l] = csumsrec (buf, 4 + l);
- X hexify (buf, p, 4 + l + 1);
- X}
- X
- X/*
- X * hexify - Convert buffer to hex ascii characters.
- X */
- Xhexify (buf, p, len)
- X
- Xunsigned char *buf;
- Xunsigned char *p;
- Xint len;
- X
- X{
- X int i;
- X
- X for (i = 0; i < len; i++) {
- X p[2 * i] = HEX (buf[i] >> 4);
- X p[2 * i + 1] = HEX (buf[i] & 0xF);
- X }
- X p[2 * len] = '\0';
- X}
- X
- X
- X/*
- X * send_getstate - Get state vector.
- X */
- Xint send_getstate (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X struct fp_copy copy;
- X
- X copy.fpc_from = (char *) promram.fpr_state;
- X copy.fpc_to = (char *) -1;
- X copy.fpc_count = STATE_LENGTH;
- X bcopy (©, fppkt.fastpath_data, FPCOPYSIZE);
- X recv_copyproc = recv_getstate;
- X nit_timeout (30, &timeout);
- X return (send_pkt (kp, (int) FP_CMD, X_COPYMEM, FPCOPYSIZE, 5, &timeout));
- X}
- X
- X/*
- X * send_putstate - Put state vector.
- X */
- Xint send_putstate (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X struct fp_copy copy;
- X
- X copy.fpc_from = (char *) -1;
- X copy.fpc_to = (char *) promram.fpr_state;
- X copy.fpc_count = htons (STATE_LENGTH);
- X bcopy (©, fppkt.fastpath_data, FPCOPYSIZE);
- X newstate[O_NODE] = kboxstate[O_NODE];
- X bcopy (newstate, &fppkt.fastpath_data[FPCOPYSIZE], STATE_LENGTH);
- X if (debug) {
- X fprintf (stderr, "send_putstate: Sending state...\n");
- X show_state (stderr, newstate);
- X }
- X recv_copyproc = recv_gen;
- X nit_timeout (30, &timeout);
- X return (send_pkt (kp, (int) FP_CMD, X_COPYMEM,
- X FPCOPYSIZE + STATE_LENGTH, 5, &timeout));
- X}
- X
- X/*
- X * send_gen - Generic send command.
- X */
- Xint send_gen (kp, scmd, retries)
- X
- Xstruct kbox *kp;
- Xint scmd;
- Xint retries;
- X
- X{
- X nit_timeout (60, &timeout);
- X return (send_pkt (kp, (int) FP_CMD, scmd, 0, retries, &timeout));
- X}
- X
- X/*
- X * send_pkt - Send command packet (in fppkt). Returns # of responders,
- X * or -1 on error. If retries is 0, don't expect any response.
- X */
- Xint send_pkt (kp, cmd, scmd, len, retries, timeout)
- X
- Xstruct kbox *kp;
- Xint cmd;
- Xint scmd;
- Xint len;
- Xint retries;
- Xstruct timeval *timeout;
- X
- X{
- X short count;
- X int h;
- X struct kbox *p;
- X struct timeb tstart;
- X struct timeb tcur;
- X int utotal;
- X int ucur;
- X
- X if (kp) {
- X if (kp->aa == AT_Broadcast) {
- X logerr ("send_pkt: Invalid appletalk address for %s\n", kp->name);
- X return (-1);
- X }
- X destkbox = kp->aa;
- X ether_copy (&kboxaddr[destkbox]->ea, &eh.ether_dhost);
- X if (retries == 0) {
- X expected_resp = 0;
- X retries = 1;
- X } else
- X expected_resp = 1;
- X } else {
- X destkbox = AT_Broadcast;
- X ether_copy (&ebc, &eh.ether_dhost);
- X expected_resp = numkbox;
- X }
- X num_resp = 0;
- X fppkt.fastpath_lapdest = destkbox;
- X fppkt.fastpath_lapsrc = atalkaddr;
- X fppkt.fastpath_laptype = FP_TYPE;
- X fppkt.fastpath_cmd = cmd;
- X fppkt.fastpath_scmd = scmd;
- X count = htons (len + 4);
- X bcopy (&count, fppkt.fastpath_len, sizeof(count));
- X utotal = timeout->tv_sec * 1000000 + timeout->tv_usec;
- X for (count = 0; count < retries; count++) {
- X if (debug && count >= 1)
- X fprintf (stderr, "send_pkt: Retransmitting cmd %d scmd %d\n",
- X fppkt.fastpath_cmd, fppkt.fastpath_scmd);
- X nit_write (&eh, &fppkt, len + sizeof(struct ether_fastpath) - MAXFPPKT);
- X ftime (&tstart);
- X ucur = 0;
- X while (num_resp < expected_resp && utotal > ucur) {
- X nit_dispatch (recv_pkt, 1, NULL, NULL, timeout);
- X ftime (&tcur);
- X ucur = (tcur.time - tstart.time) * 1000000 +
- X (tcur.millitm - tstart.millitm) * 1000;
- X }
- X if (num_resp >= expected_resp)
- X break;
- X }
- X if (num_resp != expected_resp)
- X if (destkbox == AT_Broadcast) {
- X for (h = 0; h < HTSIZE; h++)
- X for (p = kboxtab[h]; p; p = p->nxt)
- X if (p->aa == AT_Broadcast)
- X logerr ("send_pkt(%d,%d): No response from %s\n",
- X cmd, scmd, p->name);
- X } else
- X logerr ("send_pkt(%d,%d): No response from %s\n",
- X cmd, scmd, kboxaddr[destkbox]->name);
- X return (num_resp);
- X}
- END_OF_FILE
- if test 15515 -ne `wc -c <'cmd.c'`; then
- echo shar: \"'cmd.c'\" unpacked with wrong size!
- fi
- # end of 'cmd.c'
- fi
- if test -f 'icmp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'icmp.c'\"
- else
- echo shar: Extracting \"'icmp.c'\" \(3355 characters\)
- sed "s/^X//" >'icmp.c' <<'END_OF_FILE'
- X#ifndef lint
- 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 $";
- X#endif lint
- X
- X/*
- X * $Log: icmp.c,v $
- X * Revision 1.1 91/01/29 17:37:23 root
- X * Initial revision
- X *
- X */
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/socket.h>
- X#include <sys/errno.h>
- X#include <netdb.h>
- X#include <net/if.h>
- X#include <netinet/in_systm.h>
- X#include <netinet/in.h>
- X#include <netinet/ip.h>
- X#include <netinet/ip_icmp.h>
- X#include <netinet/if_ether.h>
- X#include "kbox.h"
- X#include "config.h"
- X
- Xextern int errno;
- Xextern char *sys_errlist[];
- Xextern int debug;
- X
- X/*
- X * Globals.
- X */
- Xstruct icmp icmp_pkt;
- Xint icmp_sock;
- Xfd_set icmp_fds;
- X
- X/*
- X * icmp_init - Initialize icmp stuff.
- X */
- Xicmp_init ()
- X
- X{
- X if ((icmp_sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
- X logerr ("icmp_init: %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X FD_SET (icmp_sock, &icmp_fds);
- X icmp_pkt.icmp_type = ICMP_ECHO;
- X icmp_pkt.icmp_code = 0;
- X icmp_pkt.icmp_seq = 0;
- X icmp_pkt.icmp_id = (getpid () & 0xFFFF);
- X}
- X
- X
- X/*
- X * in_cksum - Compute IP checksum.
- X */
- Xu_short in_cksum (a, l)
- X
- Xu_short *a;
- Xint l;
- X
- X{
- X int sum = 0;
- X
- X while (l > 1) {
- X sum += *a++;
- X l -= 2;
- X }
- X if (l == 1)
- X sum += *(u_char *) a;
- X sum += (sum >> 16);
- X return ((~sum) & 0xFFFF);
- X}
- X
- X/*
- X * icmp_ping - Ping kbox.
- X */
- Xint icmp_ping (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X struct sockaddr_in dest;
- X struct sockaddr_in from;
- X static struct timeval icmp_timeout = {PINGTIMEOUT, 0};
- X char buf[BUFSIZ];
- X struct ip *ip;
- X struct icmp *p;
- X int i;
- X int r;
- X fd_set readfds;
- X
- X icmp_pkt.icmp_seq++;
- X icmp_pkt.icmp_cksum = 0;
- X icmp_pkt.icmp_cksum = in_cksum (&icmp_pkt, sizeof (icmp_pkt));
- X bzero (&dest, sizeof (dest));
- X dest.sin_family = AF_INET;
- X dest.sin_addr.s_addr = kp->ip.sin_addr.s_addr;
- X for (i = 0; i < PINGRETRIES; i++) {
- X p = NULL;
- X /*
- X * Send ping
- X */
- X if (debug)
- X fprintf (stderr, "icmp_ping: Pinging %s id %d seq %d\n",
- X inet_ntoa (dest.sin_addr), icmp_pkt.icmp_id,
- X icmp_pkt.icmp_seq);
- X if (sendto (icmp_sock, &icmp_pkt, sizeof (icmp_pkt), 0,
- X &dest, sizeof (dest)) != sizeof (icmp_pkt)) {
- X logerr ("icmp_ping: sendto - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X /*
- X * Wait for reply
- X */
- Xwaitreply:
- X readfds = icmp_fds;
- X r = select (icmp_sock+1, &readfds, NULL, NULL, &icmp_timeout);
- X if (r < 0) {
- X logerr ("icmp_ping: select - %s\n", sys_errlist[errno]);
- X exit (1);
- X } else if (r == 0)
- X continue;
- X /*
- X * Read reply
- X */
- X r = sizeof (from);
- X if (recvfrom (icmp_sock, buf, BUFSIZ, 0, &from, &r) <= 0) {
- X logerr ("icmp_ping: recvfrom - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X /*
- X * Verify reply
- X */
- X ip = (struct ip *) buf;
- X p = (struct icmp *) (buf + (ip->ip_hl << 2));
- X if (p->icmp_type == ICMP_ECHOREPLY &&
- X p->icmp_id == icmp_pkt.icmp_id &&
- X p->icmp_seq == icmp_pkt.icmp_seq &&
- X from.sin_addr.s_addr == kp->ip.sin_addr.s_addr) {
- X if (debug)
- X fprintf (stderr, "icmp_ping: Reply from %s id %d seq %d\n",
- X inet_ntoa (from.sin_addr), p->icmp_id, p->icmp_seq);
- X return (1);
- X } else {
- X if (debug)
- X fprintf (stderr, "icmp_ping: Discarding packet from %s\n",
- X inet_ntoa (from.sin_addr));
- X goto waitreply;
- X }
- X }
- X return (0);
- X}
- END_OF_FILE
- if test 3355 -ne `wc -c <'icmp.c'`; then
- echo shar: \"'icmp.c'\" unpacked with wrong size!
- fi
- # end of 'icmp.c'
- fi
- if test -f 'kboot.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'kboot.c'\"
- else
- echo shar: Extracting \"'kboot.c'\" \(15749 characters\)
- sed "s/^X//" >'kboot.c' <<'END_OF_FILE'
- X#ifndef lint
- 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 $";
- X#endif lint
- X
- X/*
- X * $Log: kboot.c,v $
- X * Revision 1.3 91/02/13 11:47:07 root
- X * Accept rpc requests from privileged ports only.
- X *
- X * Revision 1.2 91/02/12 19:27:39 root
- X * Remove -m option, add -t.
- X *
- X * Revision 1.1 91/01/29 17:37:26 root
- X * Initial revision
- X *
- X */
- X
- X/*
- X * kboot - Boot and configure fastpaths over an ethernet. Depends on NIT
- X * interface in SunOS 4.x.
- X *
- X * Author: Bob Schwartzkopf, The RAND Corporation. Based on an earlier
- X * version written by Dan Tappan at BBN that ran under SunOS 3.x.
- X *
- X * Comments, suggestions, patches, bug reports, etc. may be sent to
- X * bobs@rand.org.
- X */
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <sys/errno.h>
- X#include <sys/termios.h>
- X#include <netdb.h>
- X#include <net/if.h>
- X#include <netinet/in.h>
- X#include <netinet/if_ether.h>
- X#include <rpc/rpc.h>
- X#include "appletalk.h"
- X#include "cmdidx.h"
- X#include "kbox.h"
- X#include "config.h"
- X#include "patchlevel.h"
- X#include "kboot.h"
- X
- X#define VERSION 2
- X
- Xextern char *rindex ();
- Xstruct kbox *get_kbox ();
- Xextern int errno;
- Xextern char *sys_errlist[];
- Xextern struct ether_addr myether;
- X
- X/*
- X * Globals.
- X */
- Xchar *progname;
- Xstruct ether_addr ebc = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- Xstruct ether_header eh;
- Xchar *interface = NULL;
- Xlong atalkaddr;
- Xchar *etcdir = ETCDIR;
- Xint detached = 0;
- Xint debug = 0;
- Xint watchf = 0;
- Xint downloadf = 0;
- Xint configf = 0;
- Xint liststatef = 0;
- Xint savestatef = 0;
- Xint resetf = 0;
- Xint rbootf = 0;
- Xstruct kbox *kboxtab[HTSIZE];
- Xint numkbox;
- Xunsigned char kboxstate[STATE_LENGTH];
- Xunsigned char newstate[STATE_LENGTH];
- Xunsigned char zonedata[MAXZONELIST];
- Xint zonelen;
- Xint pinginterval = PINGINTERVAL;
- Xunsigned char *zonelistp;
- X
- Xmain (argc, argv)
- X
- Xint argc;
- Xchar **argv;
- X
- X{
- X int i;
- X char c;
- X char *name = NULL;
- X struct kbox *kp;
- X char *errmsg;
- X char *rhost;
- X
- X if ((progname = rindex (argv[0], '/')) == NULL)
- X progname = *argv;
- X else
- X progname++;
- X while (--argc > 0) {
- X argv++;
- X c = (*argv)[0] == '-' ? (*argv)[1] : (*argv)[0];
- X switch (c) {
- X case 'b' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X downloadf++;
- X name = *argv;
- X break;
- X case 'c' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X configf++;
- X name = *argv;
- X break;
- X case 'd' :
- X debug++;
- X break;
- X case 'i' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X interface = *argv;
- X break;
- X case 'l' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X liststatef++;
- X name = *argv;
- X break;
- X case 'p' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X pinginterval = atoi (*argv);
- X break;
- X case 'r' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X resetf++;
- X name = *argv;
- X break;
- X case 's' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X savestatef++;
- X name = *argv;
- X break;
- X case 't' :
- X if (argc <= 1)
- X usage ();
- X argv++; argc--;
- X rbootf++;
- X name = *argv;
- X if (argc > 1 && *argv[1] != '-') {
- X argv++; argc--;
- X rhost = *argv;
- X } else
- X rhost = NULL;
- X break;
- X case 'v' :
- X printf ("%s version %d.%d\n", progname, VERSION, PATCHLEVEL);
- X exit (0);
- X case 'w' :
- X watchf++;
- X break;
- X default :
- X usage ();
- X break;
- X }
- X }
- X if (rbootf) {
- X kboot_reload (name, rhost);
- X exit (0);
- X }
- X if (watchf && !debug) { /* Detach ourselves */
- X detached++;
- X if (fork ())
- X exit (0);
- X if ((i = open ("/dev/tty", O_RDONLY)) >= 0)
- X ioctl (i, TIOCNOTTY, 0);
- X i = getdtablesize ();
- X while (--i >= 0)
- X close (i);
- X open ("/dev/null", 0);
- X dup2 (0, 1);
- X dup2 (0, 2);
- X openlog (progname, 0, LOG_DAEMON);
- X writepid ();
- X }
- X if ((i = getaa (NULL, &atalkaddr)) != 0) {
- X errmsg = clnt_sperrno (i);
- X logerr ("getaa: %s\n", errmsg);
- X exit (1);
- X }
- X if (debug)
- X fprintf (stderr, "main: Using appletalk address %d\n", atalkaddr);
- X nit_init (interface);
- X ht_init ();
- X readcf ();
- X ether_copy (&myether, &eh.ether_shost);
- X eh.ether_type = htons (P_AppleTalk);
- X if (watchf)
- X watch ();
- X else {
- X if (!name)
- X usage ();
- X if (!(kp = get_kbox (name))) {
- X logerr ("main: No such kbox %s\n", name);
- X exit (1);
- X }
- X nit_open (0, P_AppleTalk);
- X if (downloadf)
- X download (kp);
- X else if (configf)
- X config (kp);
- X else if (savestatef)
- X savestate (kp);
- X else if (resetf)
- X reset (kp);
- X else if (liststatef)
- X liststate (kp);
- X }
- X exit (0);
- X}
- X
- X/*
- X * reconfig - Free old kbox hash table and reread config file.
- X */
- Xreconfig ()
- X
- X{
- X if (debug)
- X fprintf (stderr, "reconfig: Reading config file\n");
- X ht_free ();
- X readcf ();
- X}
- X
- X/*
- X * ping - Ping kboxes, reload any that don't respond or any that've
- X * been flagged for reloading.
- X */
- Xping ()
- X
- X{
- X int i;
- X struct kbox *kp;
- X
- X for (i = 0; i < HTSIZE; i++)
- X for (kp = kboxtab[i]; kp; kp = kp->nxt)
- X if (kp->reload || !icmp_ping (kp)) {
- X logerr ("ping: Reloading %s\n", kp->name);
- X nit_open (0, P_AppleTalk);
- X download (kp);
- X kp->reload = 0;
- X nit_close ();
- X }
- X alarm (pinginterval);
- X}
- X
- X/*
- X * watch - Watch kboxes, rebooting if not answering pings or if someone
- X * asks us to.
- X */
- Xwatch ()
- X
- X{
- X signal (SIGHUP, reconfig);
- X signal (SIGALRM, ping);
- X icmp_init ();
- X rpc_init ();
- X alarm (pinginterval);
- X svc_run ();
- X}
- X
- X/*
- X * download - Download kstar to kbox.
- X */
- Xdownload (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X int i;
- X
- X if ((i = readstate (kp, newstate, zonedata)) != STATE_LENGTH) {
- X logerr ("config: State file wrong length %d for %s\n", i, kp->name);
- X return;
- X }
- X if (send_who () < 0)
- X return;
- X if (send_reset (kp) < 0)
- X return;
- X sleep (3); /* Give kbox time to reset */
- X if (send_who () < 0)
- X return;
- X if (send_promram (kp) <= 0)
- X return;
- X if (send_boot (kp, zonedata, zonelen) <= 0)
- X return;
- X if (send_getstate (kp) <= 0)
- X return;
- X newstate[O_NODE] = kboxstate[O_NODE];
- X newstate[O_ETNODE] = kboxstate[O_ETNODE];
- X strcpy (&newstate[O_NAME], kp->name);
- X strcpy (&newstate[O_FILE], kp->bootfile);
- X strcpy (&newstate[O_CONFIG], kp->conffile);
- X if (debug)
- X fprintf (stderr, "download: Setting zonelist to %X\n", zonelistp);
- X bcopy (&zonelistp, &newstate[O_ZONELIST], sizeof (zonelistp));
- X if (send_putstate (kp) <= 0)
- X return;
- X send_execute (kp);
- X}
- X
- X/*
- X * config - Config kbox.
- X */
- Xconfig (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X int i;
- X
- X if ((i = readstate (kp, newstate, zonedata)) != STATE_LENGTH) {
- X logerr ("config: State file wrong length %d for %s\n", i, kp->name);
- X return;
- X }
- X if (send_who () < 0)
- X return;
- X if (send_exprom (kp) < 0)
- X return;
- X if (send_who () < 0)
- X return;
- X if (send_promram (kp) <= 0)
- X return;
- X if (send_getstate (kp) <= 0)
- X return;
- X newstate[O_NODE] = kboxstate[O_NODE];
- X newstate[O_ETNODE] = kboxstate[O_ETNODE];
- X strncpy (&newstate[O_NAME], &kboxstate[O_NAME], NAMELEN);
- X strncpy (&newstate[O_FILE], &kboxstate[O_FILE], NAMELEN);
- X strncpy (&newstate[O_CONFIG], kp->conffile, CONFIGLEN);
- X if (send_putstate (kp) <= 0)
- X return;
- X if (send_who () < 0)
- X return;
- X send_execute (kp);
- X}
- X
- X/*
- X * savestate - Read state for kbox and save to file.
- X */
- Xsavestate (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X char fn[MAXFN];
- X int fd;
- X
- X if (send_who () < 0)
- X return;
- X if (send_promram (kp) <= 0)
- X return;
- X if (send_getstate (kp) <= 0)
- X return;
- X sprintf (fn, "%s/%s.state", etcdir, kp->name);
- X if ((fd = open (fn, O_WRONLY|O_CREAT, 0644)) == -1) {
- X logerr ("savestate: %s - %s\n", fn, sys_errlist[errno]);
- X return;
- X }
- X write (fd, kboxstate, STATE_LENGTH);
- X close (fd);
- X}
- X
- X/*
- X * liststate - Read state for kbox and print.
- X */
- Xliststate (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X char fn[MAXFN];
- X int fd;
- X
- X if (send_who () < 0)
- X return;
- X if (send_promram (kp) <= 0)
- X return;
- X if (send_getstate (kp) <= 0)
- X return;
- X show_state (stdout, kboxstate);
- X}
- X
- X/*
- X * reset - Reset kbox.
- X */
- Xreset (kp)
- X
- Xstruct kbox *kp;
- X
- X{
- X if (send_who () < 0)
- X return;
- X send_reset (kp);
- X}
- X
- X/*
- X * writepid - Save pid to file.
- X */
- Xwritepid ()
- X
- X{
- X char fn[MAXFN];
- X FILE *f;
- X
- X sprintf (fn, "%s/kboot.pid", etcdir);
- X if ((f = fopen (fn, "w")) == NULL)
- X logerr ("main: Can't write pid file %s\n", fn);
- X else {
- X fprintf (f, "%d\n", getpid ());
- X fclose (f);
- X }
- X}
- X
- X/*
- X * usage - Print usage and die.
- X */
- Xusage ()
- X
- X{
- X fprintf (stderr, "Usage: %s options\n", progname);
- X exit (1);
- X}
- X
- X/*
- X * hash - Return hash index into kbox hash table.
- X */
- Xint hash (s)
- X
- Xregister char *s;
- X
- X{
- X register int h;
- X
- X while (*s)
- X h = (h << 1) ^ *s++;
- X return (h % HTSIZE);
- X}
- X
- X/*
- X * ht_init - Init kbox hash table.
- X */
- Xht_init ()
- X
- X{
- X int i;
- X
- X for (i = 0; i < HTSIZE; i++)
- X kboxtab[i] = NULL;
- X}
- X
- X/*
- X * ht_free - Clear out hash table.
- X */
- Xht_free ()
- X
- X{
- X int i;
- X struct kbox *kp;
- X struct kbox *nkp;
- X
- X for (i = 0; i < HTSIZE; i++) {
- X for (kp = kboxtab[i]; kp; kp = nkp) {
- X nkp = kp->nxt;
- X free (kp);
- X }
- X kboxtab[i] = NULL;
- X }
- X}
- X
- X/*
- X * add_kbox - Add kbox to hash table.
- X */
- Xadd_kbox (name, bootfile)
- X
- Xchar *name;
- Xchar *bootfile;
- X
- X{
- X int h;
- X struct kbox *kp;
- X char *p;
- X struct hostent *he;
- X struct ether_addr e;
- X
- X if (ether_hostton (name, &e) != 0) {
- X logerr ("add_kbox: Can't find %s in ethers file\n", name);
- X return;
- X }
- X if ((he = gethostbyname (name)) == NULL) {
- X logerr ("add_kbox: Can't find %s in host table\n", name);
- X return;
- X }
- X if ((kp = (struct kbox *) malloc (sizeof (struct kbox))) == NULL) {
- X logerr ("add_kbox: No memory for %s in table\n", name);
- X exit (1);
- X }
- X h = hash (name);
- X kp->nxt = kboxtab[h];
- X kboxtab[h] = kp;
- X kp->reload = 0;
- X strcpy (kp->name, name);
- X strcpy (kp->bootfile, bootfile);
- X kp->aa = AT_Broadcast; /* Set to bogus value until get from kb */
- X ether_copy (&e, &kp->ea);
- X bcopy (he->h_addr, &kp->ip.sin_addr.s_addr, he->h_length);
- X}
- X
- X/*
- X * get_kbox - Find kbox in hash table.
- X */
- Xstruct kbox *get_kbox (name)
- X
- Xchar *name;
- X
- X{
- X register struct kbox *kp;
- X
- X kp = kboxtab[hash (name)];
- X while (kp)
- X if (!strcmp (name, kp->name))
- X return (kp);
- X else
- X kp = kp->nxt;
- X return (NULL);
- X}
- X
- X/*
- X * readcf - Read config file.
- X */
- Xreadcf ()
- X
- X
- X{
- X FILE *f;
- X char fn[MAXFN];
- X char name[MAXHOSTNAME];
- X char bootfile[MAXFN];
- X
- X sprintf (fn, "%s/kbootcf", etcdir);
- X if ((f = fopen (fn, "r")) == NULL) {
- X logerr ("readcf: %s - %s\n", fn, sys_errlist[errno]);
- X exit (1);
- X }
- X while (!feof (f)) {
- X numkbox++;
- X if (fscanf (f, "%s %s\n", name, bootfile) != 2) {
- X logerr ("readcf: Badly formatted config file '%s' line %d\n",
- X fn, numkbox);
- X exit (1);
- X }
- X add_kbox (name, bootfile);
- X }
- X fclose (f);
- X}
- X
- X/*
- X * readstate - Read kbox config. Returns length. Looks for ascii file
- X * generated by fastpath manager first, then looks for binary file
- X * made by savestate().
- X */
- Xint readstate (kp, state, zonedata)
- X
- Xstruct kbox *kp;
- Xunsigned char *state;
- Xunsigned char *zonedata;
- X
- X{
- X FILE *f;
- X int c;
- X unsigned char *cp;
- X int fd;
- X int len;
- X
- X zonelen = 0;
- X sprintf (kp->conffile, "%s/%s.config", etcdir, kp->name);
- X if ((f = fopen (kp->conffile, "r")) == NULL) {
- X sprintf (kp->conffile, "%s/%s.state", etcdir, kp->name);
- X if ((fd = open (kp->conffile, O_RDONLY)) == -1) {
- X logerr ("readstate: Can't read state file for %s\n", kp->name);
- X return;
- X }
- X len = read (fd, state, STATE_LENGTH);
- X close (fd);
- X } else {
- X cp = state;
- X len = 0;
- X while ((c = fgetc (f)) >= 0) {
- X if (c == '*') {
- X while ((c = fgetc (f)) >= 0 && c != '\n' && c != '\r');
- X continue;
- X }
- X while (c >= 0 && c != '\n' && c != '\r') {
- X *cp = fromhex (c) << 4;
- X *cp++ |= fromhex (c = fgetc (f));
- X c = fgetc (f);
- X }
- X if (cp - state == STATE_LENGTH) {
- X zonelen = readzones (f, c, zonedata);
- X break;
- X }
- X }
- X fclose (f);
- X len = cp - state;
- X }
- X if (zonelen == 0) {
- X zonedata[0] = 0;
- X zonedata[1] = 0;
- X zonelen = 2;
- X }
- X return (len);
- X}
- X
- X/*
- X * readzones - Read zone list from config file, c is first char.
- X */
- Xint readzones (f, c, zonedata)
- X
- XFILE *f;
- Xint c;
- Xunsigned char *zonedata;
- X
- X{
- X unsigned char *cp;
- X unsigned char *lenp;
- X short numzones;
- X
- X cp = zonedata + 2; /* Skip # zones */
- X numzones = 0;
- X while ((c = fgetc (f)) >= 0) {
- X if (c == '\r' || c == '\n')
- X continue;
- X if (c == '*') {
- X while ((c = fgetc (f)) >= 0 && c != '\n' && c != '\r');
- X continue;
- X }
- X lenp = cp++;
- X while (c >= 0 && c != '\n' && c != '\r') {
- X *cp++ = c;
- X c = fgetc (f);
- X }
- X *lenp = (cp - lenp) - 1;
- X numzones++;
- X }
- X bcopy (&numzones, zonedata, sizeof (numzones));
- X return (cp - zonedata);
- X}
- X
- X/*
- X * fromhex - Convert char from hex to decimal.
- X */
- Xint fromhex (c)
- X
- Xchar c;
- X
- X{
- X if (c >= '0' && c <= '9')
- X return (c - '0');
- X else if (c >= 'a' && c <= 'f')
- X return (c - 'a' + 10);
- X else
- X return (c - 'A' + 10);
- X}
- X
- X/*
- X * kboot_rpcsvr - Handle rpc requests.
- X */
- Xkboot_rpcsvr (request, xprt)
- X
- Xstruct svc_req *request;
- XSVCXPRT *xprt;
- X
- X{
- X struct sockaddr_in *sa;
- X char *kbox;
- X int r;
- X struct kbox *kp;
- X
- X sa = svc_getcaller (xprt);
- X if (debug)
- X fprintf (stderr, "kboot_rpcsvr: Request %d from %s\n",
- X request->rq_proc, inet_ntoa (sa->sin_addr));
- X if (sa->sin_port >= IPPORT_RESERVED) {
- X logerr ("kboot_rpcsvr: Bad port %d from %s\n",
- X sa->sin_port, inet_ntoa (sa->sin_addr));
- X r = -1;
- X if (!svc_sendreply (xprt, xdr_int, (caddr_t) &r))
- X logerr ("kboot_rpcsvr: svc_sendreply failed\n");
- X return;
- X }
- X switch (request->rq_proc) {
- X case NULLPROC:
- X if (!svc_sendreply (xprt, xdr_void, 0))
- X logerr ("kboot_rpcsvr(NULLPROC): svc_sendreply failed\n");
- X break;
- X
- X case KBOOTPROC_RELOAD:
- X kbox = NULL;
- X if (svc_getargs (xprt, xdr_wrapstring, &kbox)) {
- X if (!(kp = get_kbox (kbox))) {
- X logerr ("kboot_rpcsvr: No such kbox %s\n", kbox);
- X r = -1;
- X } else
- X r = 0;
- X } else {
- X logerr ("kboot_rpcsvr(RELOAD): svc_getargs failed\n");
- X r = -1;
- X }
- X if (!svc_sendreply (xprt, xdr_int, (caddr_t) &r))
- X logerr ("kboot_rpcsvr(RELOAD): svc_sendreply failed\n");
- X if (r >= 0) {
- X kp->reload++;
- X alarm (1);
- X if (debug)
- X fprintf (stderr, "kboot_rpcsvr: Requesting load of %s\n", kbox);
- X }
- X xdr_free (xdr_wrapstring, &kbox);
- X break;
- X
- X default:
- X svcerr_noproc (xprt);
- X break;
- X }
- X}
- X
- X/*
- X * Initialize RPC stuff.
- X */
- Xrpc_init ()
- X
- X{
- X SVCXPRT *xprt;
- X
- X if ((xprt = svcudp_create (RPC_ANYSOCK)) == NULL) {
- X logerr ("rpc_init: svcudp_create failed\n");
- X exit (1);
- X }
- X pmap_unset (KBOOTPROG, KBOOTVERS);
- X if (!svc_register (xprt, KBOOTPROG, KBOOTVERS, kboot_rpcsvr, IPPROTO_UDP)) {
- X logerr ("rpc_init: Can't register %d %d\n", KBOOTPROG, KBOOTVERS);
- X exit (1);
- X }
- X}
- X
- X/*
- X * kboot_reload - Ask kboot on rhost to reload kbox.
- X */
- Xkboot_reload (kbox, rhost)
- X
- Xchar *kbox;
- Xchar *rhost;
- X
- X{
- X int s;
- X int r;
- X
- X if (rhost == NULL)
- X rhost = "localhost";
- X if (debug)
- X fprintf (stderr, "kboot_reload: Requesting reboot of %s on %s\n",
- X kbox, rhost);
- X/*
- X * kboot will only accept rpc requests from privileged ports. callrpc
- X * will use a privileged port by default if it can (we're root).
- X */
- X if ((s = callrpc (rhost, KBOOTPROG, KBOOTVERS, KBOOTPROC_RELOAD,
- X xdr_wrapstring, &kbox, xdr_int, &r)) != 0) {
- X clnt_perrno (s);
- X exit (1);
- X }
- X printf ("%s reload request %s\n", kbox, r == 0 ? "accepted" : "failed");
- X}
- END_OF_FILE
- if test 15749 -ne `wc -c <'kboot.c'`; then
- echo shar: \"'kboot.c'\" unpacked with wrong size!
- fi
- # end of 'kboot.c'
- fi
- if test -f 'nitlib.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'nitlib.c'\"
- else
- echo shar: Extracting \"'nitlib.c'\" \(6314 characters\)
- sed "s/^X//" >'nitlib.c' <<'END_OF_FILE'
- X#ifndef lint
- 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 $";
- X#endif lint
- X
- X/*
- X * $Log: nitlib.c,v $
- X * Revision 1.2 91/02/12 19:38:10 root
- X * Don't call fdfunc() if NULL.
- X *
- X * Revision 1.1 91/01/29 17:37:28 root
- X * Initial revision
- X *
- X */
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/socket.h>
- X#include <sys/file.h>
- X#include <sys/signal.h>
- X#include <netdb.h>
- X#include <net/if.h>
- X#include <sys/ioctl.h>
- X#include <sys/stropts.h>
- X#include <net/nit_if.h>
- X#include <net/nit_pf.h>
- X#include <netinet/in.h>
- X#include <netinet/in_systm.h>
- X#include <netinet/if_ether.h>
- X#include <net/packetfilt.h>
- X#include "config.h"
- X
- X#define MAXPKT 1500
- X#define OFFSET(t,f) ((int) &(((t *) NULL)->f))
- X
- Xextern char *malloc ();
- Xextern char *strdup ();
- X
- Xextern int debug;
- Xextern int detached;
- Xextern int errno;
- Xextern char *sys_errlist[];
- X
- X/*
- X * Globals.
- X */
- Xstruct ether_addr myether;
- Xint nit_fd;
- Xchar nitbuf[MAXPKT];
- Xint numfds;
- Xchar *interface;
- X
- X/*
- X * nit_init - Initialize nit library.
- X */
- Xnit_init (dev)
- X
- Xchar *dev;
- X
- X{
- X struct ifconf ifc;
- X int s;
- X char buf[BUFSIZ];
- X
- X numfds = getdtablesize ();
- X if (dev == NULL) {
- X if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
- X logerr ("nit_init: socket - %s\n", sys_errlist[errno]);
- X exit(1);
- X }
- X ifc.ifc_len = BUFSIZ;
- X ifc.ifc_buf = buf;
- X if (ioctl (s, SIOCGIFCONF, (caddr_t) &ifc) < 0) {
- X logerr ("nit_init: ioctl(SIOCGIFCONF) - %s\n", sys_errlist[errno]);
- X exit(1);
- X }
- X close(s);
- X interface = strdup (ifc.ifc_req->ifr_name);
- X } else
- X interface = dev;
- X if (debug)
- X fprintf (stderr, "nit_init: Using interface %s\n", interface);
- X}
- X
- X/*
- X * nit_open - Open NIT device and bind to an interface.
- X * Prints an error and exits if there's a problem.
- X */
- Xnit_open (snaplen, pkttype)
- X
- Xint snaplen;
- Xint pkttype;
- X
- X{
- X int s;
- X struct packetfilt pf;
- X u_short *pfp;
- X struct ifreq ifr;
- X
- X if ((nit_fd = open ("/dev/nit", O_RDWR)) < 0) { /* Open NIT dev */
- X logerr ("nit_open: open(/dev/nit) - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X if (ioctl (nit_fd, I_SRDOPT, (caddr_t) RMSGD) < 0) { /* Discrete msgs*/
- X logerr ("nit_open: ioctl(I_SRDOPT) - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X if (pkttype) {
- X if (ioctl (nit_fd, I_PUSH, "pf") < 0) { /* Setup packet filter */
- X logerr ("nit_open: ioctl(I_PUSH: pf) - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X pfp = pf.Pf_Filter;
- X *pfp++ = ENF_PUSHWORD +
- X OFFSET (struct ether_header, ether_type) / sizeof (u_short);
- X *pfp++ = ENF_PUSHLIT | ENF_EQ;
- X *pfp++ = htons (pkttype);
- X pf.Pf_FilterLen = ((int) pfp - (int) pf.Pf_Filter) / sizeof (u_short);
- X if (ioctl (nit_fd, NIOCSETF, (caddr_t) &pf) < 0) {
- X logerr ("nit_open: ioctl(NIOCSETF) - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X }
- X strncpy (ifr.ifr_name, interface, sizeof ifr.ifr_name);
- X ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0';
- X if (ioctl (nit_fd, NIOCBIND, &ifr) < 0) {
- X logerr ("nit_open: ioctl(NIOCBIND) - %s\n", sys_errlist[errno]);
- X exit(1);
- X }
- X /* Get ethernet address */
- X if (ioctl (nit_fd, SIOCGIFADDR, (caddr_t) &ifr) < 0) {
- X logerr ("nit_open: ioctl(SIOCGIFADDR) - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X ether_copy (ifr.ifr_addr.sa_data, &myether);
- X if (snaplen > 0) { /* Set snapshot length */
- X if (ioctl (nit_fd, NIOCSSNAP, (caddr_t) &snaplen) < 0) {
- X logerr ("nit_open: ioctl (NIOCSSNAP) - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X }
- X}
- X
- X/*
- X * nit_close - Close nit file descriptor.
- X */
- Xnit_close ()
- X
- X{
- X close (nit_fd);
- X}
- X
- X/*
- X * timeout - Return timeval structure for timeout specified in ticks for
- X * reads from nit device. Ticks are 1/60 of a second. A timeout of 0
- X * means reads will not timeout.
- X */
- Xnit_timeout (ticks, tv)
- X
- Xint ticks;
- Xstruct timeval *tv;
- X
- X{
- X tv->tv_sec = ticks / 60; /* Set timeout */
- X tv->tv_usec = ((ticks * 1000000) / 60) % 1000000;
- X}
- X
- X/*
- X * nit_write - Send a raw ethernet packet.
- X */
- Xnit_write (eh, pkt, len)
- X
- Xstruct ether_header *eh;
- Xcaddr_t pkt;
- Xint len;
- X
- X{
- X struct sockaddr sa;
- X struct strbuf cbuf;
- X struct strbuf dbuf;
- X
- X sa.sa_family = AF_UNSPEC;
- X bcopy (eh, sa.sa_data, sizeof (*eh));
- X cbuf.len = sizeof sa;
- X cbuf.buf = (caddr_t) &sa;
- X dbuf.len = len;
- X dbuf.buf = pkt;
- X if (putmsg (nit_fd, &cbuf, &dbuf, 0) < 0) {
- X logerr ("nit_write: putmsg - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X}
- X
- X/*
- X * nit_dispatch - Read and process n packets. If n is 0 read forever.
- X * Calls "func" for each packet with the arguments:
- X *
- X * (*func) (pp, pl)
- X * pp = packet pointer
- X * pl = length of packet
- X *
- X * If an application is waiting for input on other file descriptors
- X * they can be specified in "fds". "fdfunc" will be called with
- X * the set of descriptors that have input waiting before the current
- X * packet is processed. Returns 0 on timeout, 1 otherwise.
- X */
- Xint nit_dispatch (func, n, fds, fdfunc, timeout)
- X
- Xint (*func)();
- Xint n;
- Xfd_set *fds;
- Xint (*fdfunc)();
- Xstruct timeval *timeout;
- X
- X{
- X int i;
- X int numpkts;
- X fd_set fdset;
- X fd_set rfds;
- X
- X numpkts = 0;
- X if (fds)
- X fdset = *fds;
- X else
- X FD_ZERO (&fdset);
- X FD_SET (nit_fd, &fdset);
- X while (n == 0 || numpkts < n) {
- X rfds = fdset;
- X i = select (numfds, &rfds, NULL, NULL, timeout);
- X if (i == 0)
- X return (0); /* Timeout */
- X if (FD_ISSET (nit_fd, &rfds)) {
- X numpkts++;
- X FD_CLR (nit_fd, &rfds);
- X if (i > 1)
- X (*fdfunc) (&rfds);
- X } else if (fdfunc) {
- X (*fdfunc) (&rfds);
- X continue;
- X }
- X if ((i = read (nit_fd, nitbuf, MAXPKT)) < 0) {
- X lseek (nit_fd, 0, 0); /* File pointer may've wrapped */
- X if ((i = read (nit_fd, nitbuf, MAXPKT)) < 0) {
- X logerr ("nit_dispatch: read - %s\n", sys_errlist[errno]);
- X exit (1);
- X }
- X }
- X (*func) (nitbuf, i);
- X }
- X return (1);
- X}
- X
- X/*
- X * logerr - Log error to stderr (if debug) or syslog.
- X */
- Xlogerr (fmt, a1, a2, a3)
- X
- Xchar *fmt;
- Xchar *a1;
- Xchar *a2;
- Xchar *a3;
- X
- X{
- X if (detached)
- X syslog (LOG_ERR, fmt, a1, a2, a3);
- X else
- X fprintf (stderr, fmt, a1, a2, a3);
- X}
- END_OF_FILE
- if test 6314 -ne `wc -c <'nitlib.c'`; then
- echo shar: \"'nitlib.c'\" unpacked with wrong size!
- fi
- # end of 'nitlib.c'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-
-