home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
kboot22.zoo
/
kboot22.2
/
aarpd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-22
|
7KB
|
304 lines
#ifndef lint
static char *RCSid="$Header: /tmp_mnt/home/src/rand/etc/kboot/RCS/aarpd.c,v 1.1 91/01/29 17:36:55 root Exp $";
#endif lint
/*
* $Log: aarpd.c,v $
* Revision 1.1 91/01/29 17:36:55 root
* Initial revision
*
*/
/*
* aarpd - Appletalk ARP daemon. Obtain an appletalk protocol address,
* then listen forever, responding to any appletalk probes and
* requests sent to us. Depends on SunOS 4.x NIT interface.
*
* Author: Bob Schwartzkopf, The RAND Corporation. Based on an earlier
* version written by Dan Tappan at BBN that ran under SunOS 3.x.
*
* Comments, suggestions, patches, bug reports, etc. may be sent to
* bobs@rand.org.
*/
#include <stdio.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <sys/termios.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <rpc/rpc.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include "appletalk.h"
#include "aarpd.h"
#include "config.h"
#include "patchlevel.h"
extern char *rindex ();
int aarp_read ();
extern struct ether_addr myether; /* Setup by nit_init */
extern int errno;
extern char *sys_errlist[];
#define VERSION 2
/*
* Globals.
*/
char *progname;
char *interface = NULL;
struct ether_addr ebc = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
long atalkaddr; /* Current appletalk address */
int haveaddr = 0; /* Have appletalk address */
int conflict; /* We're in confict with someone*/
int detached = 0; /* Detached from tty */
int debug = 0; /* Debugging */
struct ether_header eh; /* Output ethernet header */
struct ether_aarp ap; /* Output packet */
main (argc, argv)
int argc;
char **argv;
{
char c;
int i;
if ((progname = rindex (argv[0], '/')) == NULL)
progname = *argv;
else
progname++;
while (--argc > 0) {
argv++;
c = (*argv)[0] == '-' ? (*argv)[1] : (*argv)[0];
switch (c) {
case 'd' :
debug++;
break;
case 'i' :
if (argc <= 1)
usage ();
argv++;
argc--;
interface = *argv;
break;
case 'v' :
printf ("%s version number %d.%d\n", progname, VERSION, PATCHLEVEL);
exit (0);
default :
usage ();
}
}
if (!debug) { /* Detach ourselves */
detached++;
if (fork ())
exit (0);
if ((i = open ("/dev/tty", O_RDONLY)) >= 0)
ioctl (i, TIOCNOTTY, 0);
i = getdtablesize ();
while (--i >= 0)
close (i);
open ("/dev/null", 0);
dup2 (0, 1);
dup2 (0, 2);
openlog (progname, 0, LOG_DAEMON);
}
nit_init (interface);
nit_open (sizeof (ap) + sizeof (eh), AARP);
aarp_probe (); /* Get appletalk address */
initrpc (); /* Prepare for RPC */
ap.aarp_op = htons (AARPResp); /* Set up for sending replies */
nit_dispatch (aarp_read, 0, &svc_fdset, svc_getreqset, NULL);
}
/*
* usage - Print usage and die.
*/
usage ()
{
fprintf (stderr, "Usage: %s [-d] [-i interface]\n", progname);
exit (1);
}
/*
* aarp_probe - Get unused appletalk address. Algorithm is to try each
* in turn, probing to see if anyone else is using each address. When
* no one answers a probe, we use that address. Note this routine
* initializes some global data structures (eh, ap), parts of which are
* used later by aarp_read ().
*/
aarp_probe ()
{
u_long spa;
int i;
struct timeval timeout;
struct timeb tstart;
struct timeb tcur;
int utotal;
int ucur;
/* Init ether header */
ether_copy (&ebc, &eh.ether_dhost);
ether_copy (&myether, &eh.ether_shost);
eh.ether_type = htons (AARP);
/* Init aarp header */
ap.aarp_hrd = htons (H_Ethernet);
ap.aarp_pro = htons (P_AppleTalk);
ap.aarp_hln = HL_Ethernet;
ap.aarp_pln = PL_AppleTalk;
ap.aarp_op = htons (AARPProbe);
ether_copy (&myether, &ap.aarp_sha);
bzero (&ap.aarp_tha, HL_Ethernet);
nit_timeout (APrbTicks, &timeout);
utotal = timeout.tv_sec * 1000000 + timeout.tv_usec;
for (atalkaddr = 1; atalkaddr < 254; atalkaddr++) {
spa = htonl (atalkaddr);
bcopy (&spa, ap.aarp_spa, PL_AppleTalk);
bcopy (&spa, ap.aarp_tpa, PL_AppleTalk);
conflict = 0;
for (i = 0; !conflict && i < APrbTries; i++) {
nit_write ((caddr_t) &eh, (caddr_t) &ap, sizeof ap);
ftime (&tstart);
do {
nit_dispatch (aarp_read, 1, NULL, NULL, &timeout);
ftime (&tcur);
ucur = (tcur.time - tstart.time) * 1000000 +
(tcur.millitm - tstart.millitm) * 1000;
} while (!conflict && utotal > ucur);
}
if (!conflict) {
if (debug)
fprintf (stderr, "aarp_probe: Using appletalk address %d\n",
atalkaddr);
break;
}
}
if (conflict) {
logerr ("aarp_probe: Couldn't find appletalk address, exiting...\n");
exit (1);
}
haveaddr++;
}
/*
* aarp_read - Handle AARP response packets.
*/
aarp_read (p, pl)
struct aarp_packet *p;
int pl;
{
int op;
long spa;
long tpa;
if (pl != sizeof (*p)) {
if (debug)
fprintf (stderr, "aarp_read: Truncated packet len %d\n", pl);
return;
}
op = ntohs (p->ap_op);
bcopy ((caddr_t) p->ap_spa, &spa, PL_AppleTalk);
spa = ntohl (spa);
switch (op) {
case AARPProbe :
case AARPReq :
bcopy ((caddr_t) p->ap_tpa, &tpa, PL_AppleTalk);
tpa = ntohl (tpa);
if (haveaddr && tpa == atalkaddr) {
/*
* Most of the output header and packet (eh, ap) should already be
* set up since it was used for probing initially. Should only need
* to fill in destination addresses.
*/
ether_copy (&p->ap_sha, &eh.ether_dhost);
ether_copy (&p->ap_sha, &ap.aarp_tha);
bcopy (p->ap_spa, ap.aarp_tpa, PL_AppleTalk);
if (debug) {
fprintf (stderr, "aarp_read: Replying to %s from %d (%s)\n",
op == AARPProbe ? "probe" : "request",
spa, ether_ntoa (&p->ap_sha));
}
nit_write ((caddr_t) &eh, (caddr_t) &ap, sizeof ap);
}
break;
case AARPResp :
if (debug)
fprintf (stderr, "aarp_read: Reply from %d (%s)\n",
spa, ether_ntoa (&p->ap_sha));
if (!haveaddr && spa == atalkaddr)
conflict++;
break;
default :
logerr ("aarp_read: Unknown AARP operation %d\n", op);
}
}
/*
* getaa - Return appletalk address for this host.
*/
getaa (request, xprt)
struct svc_req *request;
SVCXPRT *xprt;
{
struct sockaddr_in *sa;
if (debug) {
sa = svc_getcaller (xprt);
fprintf (stderr, "getaa: Returning %d to %s\n",
atalkaddr, inet_ntoa (sa->sin_addr));
}
switch (request->rq_proc) {
case NULLPROC:
if (!svc_sendreply (xprt, xdr_void, 0)) {
logerr ("getaa(NULLPROC): svc_sendreply failed\n");
exit (1);
}
break;
case GETAAPROC:
if (!svc_sendreply (xprt, xdr_u_long, (caddr_t) &atalkaddr)) {
logerr ("getaa(GETAAPROC): svc_sendreply failed\n");
exit (1);
}
break;
default:
svcerr_noproc (xprt);
break;
}
}
/*
* Initialize RPC stuff.
*/
initrpc ()
{
SVCXPRT *xprt;
if ((xprt = svcudp_create (RPC_ANYSOCK)) == NULL) {
logerr ("initrpc: svcudp_create failed\n");
exit (1);
}
pmap_unset (GETAAPROG, GETAAVERS);
if (!svc_register (xprt, GETAAPROG, GETAAVERS, getaa, IPPROTO_UDP)) {
logerr ("initrpc: Can't register %d %d\n", GETAAPROG, GETAAVERS);
exit (1);
}
}