mirror of
https://github.com/mabam/CAP.git
synced 2024-06-07 19:29:32 +00:00
1252 lines
30 KiB
C
1252 lines
30 KiB
C
|
static char rcsid[] = "$Author: djh $ $Date: 1996/06/18 10:51:30 $";
|
|||
|
static char rcsident[] = "$Header: /mac/src/cap60/etc/RCS/atis.c,v 2.11 1996/06/18 10:51:30 djh Rel djh $";
|
|||
|
static char revision[] = "$Revision: 2.11 $";
|
|||
|
|
|||
|
/*
|
|||
|
* atis.c - a simple appletalk information server
|
|||
|
*
|
|||
|
* This provides a simple name information and echo server.
|
|||
|
* The NBP it assumes is a slightly extended form (cf. nbp.ext).
|
|||
|
*
|
|||
|
* Also acts as the RTMP listener for use with Native EtherTalk and
|
|||
|
* Kernel EtherTalk for which we also maintain a simple routing table.
|
|||
|
*
|
|||
|
* Needs some cleaning. A quit signal causes it to dump it's database.
|
|||
|
* a HUP signal tells it to reload it.
|
|||
|
*
|
|||
|
* AppleTalk package for UNIX (4.2 BSD).
|
|||
|
*
|
|||
|
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University
|
|||
|
* in the City of New York.
|
|||
|
*
|
|||
|
*
|
|||
|
* Edit History:
|
|||
|
*
|
|||
|
* July 10, 1986 CCKim Created
|
|||
|
* August 2, 1986 CCKim Add dump and load functionality
|
|||
|
* December 17, 1986 CCKim Revise to rev1086 of UDP code
|
|||
|
* April 28, 1991 djh Add Phase 2 support
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <signal.h>
|
|||
|
#include <sys/param.h>
|
|||
|
#ifndef _TYPES
|
|||
|
# include <sys/types.h>
|
|||
|
#endif
|
|||
|
#include <sys/time.h>
|
|||
|
#include <sys/ioctl.h>
|
|||
|
#include <sys/socket.h>
|
|||
|
#include <netinet/in.h>
|
|||
|
#include <netat/appletalk.h>
|
|||
|
#include <netat/abnbp.h>
|
|||
|
#include <netat/compat.h>
|
|||
|
#ifdef USETIMES
|
|||
|
# include <time.h>
|
|||
|
#endif
|
|||
|
#ifdef USEVPRINTF
|
|||
|
# include <varargs.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef linux
|
|||
|
#define SIGEMT SIGUNUSED
|
|||
|
#endif /* linux */
|
|||
|
|
|||
|
/* signals in use */
|
|||
|
#define DUMPSIG sigmask(SIGQUIT)
|
|||
|
#define EXITSIG sigmask(SIGTERM)
|
|||
|
#define DBUGSIG sigmask(SIGIOT)
|
|||
|
#define NDBGSIG sigmask(SIGEMT)
|
|||
|
#define LOADSIG sigmask(SIGHUP)
|
|||
|
|
|||
|
#ifdef NOSIGMASK
|
|||
|
static int allsigs[] = { SIGIOT, SIGHUP, SIGTERM, SIGEMT, SIGQUIT, 0 };
|
|||
|
#else NOSIGMASK
|
|||
|
#define ALLSIGS (sigmask(SIGIOT)|sigmask(SIGHUP)|sigmask(SIGTERM)|\
|
|||
|
sigmask(SIGEMT)|sigmask(SIGQUIT))
|
|||
|
#endif NOSIGMASK
|
|||
|
|
|||
|
/* logging flags */
|
|||
|
#define L_UERR 0x20 /* want unix error message */
|
|||
|
#define L_EXIT 0x10 /* exit after logging */
|
|||
|
#define L_LVL 0xf /* debug levels */
|
|||
|
#define L_LVLMAX 15 /* maximum level */
|
|||
|
|
|||
|
/* good place to stick the copyright so it shows up in object files */
|
|||
|
private char Columbia_Copyright[] = "Copyright (c) 1986,1987,1988 by The Trustees of Columbia University in the City of New York";
|
|||
|
|
|||
|
private int tempdebugfile = 0;
|
|||
|
private int nbpskt = nbpNIS;
|
|||
|
private int echoskt = echoSkt;
|
|||
|
private int rtmpskt = rtmpSkt;
|
|||
|
|
|||
|
char *pidfile;
|
|||
|
|
|||
|
extern short lap_proto; /* identifies the "LAP" level */
|
|||
|
|
|||
|
extern u_char bridge_node;
|
|||
|
extern u_short this_net, nis_net, bridge_net;
|
|||
|
|
|||
|
#ifdef PHASE2
|
|||
|
extern u_short net_range_start, net_range_end;
|
|||
|
#endif PHASE2
|
|||
|
|
|||
|
#ifndef ETCDIR
|
|||
|
# define ETCDIR "/etc"
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef NISDUMPFILE
|
|||
|
# define NISDUMPFILE "/usr/tmp/nis.db"
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef ATISRUNFILE
|
|||
|
# define ATISRUNFILE "/usr/tmp/atis.run"
|
|||
|
#endif
|
|||
|
|
|||
|
private char *nisdumpfile = NISDUMPFILE;
|
|||
|
private char *atisrunfile = ATISRUNFILE;
|
|||
|
private char *progname;
|
|||
|
import DBUG dbug;
|
|||
|
|
|||
|
|
|||
|
/* each tuple is entity name + addrblock + enumerator */
|
|||
|
#define NBPTUPSIZE (sizeof(EntityName)+sizeof(AddrBlock)+1)
|
|||
|
/* for nbp, must offset for control word and nbp id */
|
|||
|
#define NUMREPLYMAX ((ddpMaxData-2)/NBPTUPSIZE)
|
|||
|
NBPTEntry reply[NUMREPLYMAX];
|
|||
|
|
|||
|
extern int get_debug_level();
|
|||
|
extern int set_debug_level();
|
|||
|
|
|||
|
void nbp_extensions();
|
|||
|
void nbp_reload();
|
|||
|
void nbp_dump();
|
|||
|
void nbp_listener();
|
|||
|
void echo_listener();
|
|||
|
void rtmp_listener();
|
|||
|
void atis_end();
|
|||
|
void atis_debuginc();
|
|||
|
void atis_undebug();
|
|||
|
private int nbpcpy(), c2pkt_ename(), pkt2c_ename();
|
|||
|
|
|||
|
void
|
|||
|
nbp_reload()
|
|||
|
{
|
|||
|
FILE *fd;
|
|||
|
int cnt;
|
|||
|
int mask;
|
|||
|
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold_all();
|
|||
|
#else NOSIGMASK
|
|||
|
mask = sigblock(ALLSIGS); /* block so we don't get interrupted */
|
|||
|
#endif NOSIGMASK
|
|||
|
(void)logit(1, "reloading from %s",nisdumpfile);
|
|||
|
nbptab_init(); /* reset tables */
|
|||
|
cnt = 0;
|
|||
|
if ((fd = fopen(nisdumpfile,"r")) != NULL) {
|
|||
|
cnt = nbptab_load(fd);
|
|||
|
(void)fclose(fd);
|
|||
|
} else logit(L_UERR|1, "dump file open failed");
|
|||
|
logit(1, "loaded %d entries",cnt);
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse_all();
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
(void)signal(SIGHUP, nbp_reload);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
nbp_dump()
|
|||
|
{
|
|||
|
FILE *fd;
|
|||
|
int cnt;
|
|||
|
int mask;
|
|||
|
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold_all();
|
|||
|
#else NOSIGMASK
|
|||
|
mask = sigblock(ALLSIGS); /* block so we don't get interrupted */
|
|||
|
#endif NOSIGMASK
|
|||
|
logit(1, "Dumping to %s",nisdumpfile);
|
|||
|
(void)signal(SIGQUIT, SIG_IGN);
|
|||
|
cnt = 0;
|
|||
|
if ((fd = fopen(nisdumpfile,"w+")) != NULL) {
|
|||
|
(void)chmod(nisdumpfile, 0774);
|
|||
|
cnt = nbptab_dump(fd);
|
|||
|
(void)fclose(fd);
|
|||
|
} else logit(L_UERR|1, "dump file (write) open failed");
|
|||
|
logit(1, "Dumped %d entries",cnt);
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse_all();
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
(void)signal(SIGQUIT, nbp_dump);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
atis_end()
|
|||
|
{
|
|||
|
#ifdef linux
|
|||
|
if (lap_proto == LAP_KERNEL) {
|
|||
|
void rtmp_release();
|
|||
|
rtmp_release();
|
|||
|
}
|
|||
|
#endif /* linux */
|
|||
|
logit(0, "exiting");
|
|||
|
(void)unlink(pidfile);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
atis_undebug()
|
|||
|
{
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold(DBUGSIG);
|
|||
|
sighold(NDBGSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
int mask = sigblock(DBUGSIG|NDBGSIG);
|
|||
|
#endif NOSIGMASK
|
|||
|
set_debug_level(0);
|
|||
|
logit(0, "DEBUGGING OFF");
|
|||
|
if (tempdebugfile)
|
|||
|
nologitfile();
|
|||
|
signal(SIGEMT, atis_undebug);
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse(DBUGSIG);
|
|||
|
sigrelse(NDBGSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
atis_debuginc()
|
|||
|
{
|
|||
|
int dlevel;
|
|||
|
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold(DBUGSIG);
|
|||
|
sighold(NDBGSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
int mask = sigblock(DBUGSIG|NDBGSIG);
|
|||
|
#endif NOSIGMASK
|
|||
|
if (!islogitfile()) {
|
|||
|
tempdebugfile++;
|
|||
|
logitfileis(atisrunfile, "w+");
|
|||
|
}
|
|||
|
if ((dlevel = get_debug_level()) < L_LVLMAX)
|
|||
|
set_debug_level(++dlevel);
|
|||
|
logit(0, "DEBUG LEVEL %d", dlevel);
|
|||
|
signal(SIGIOT, atis_debuginc);
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse(DBUGSIG);
|
|||
|
sigrelse(NDBGSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
}
|
|||
|
|
|||
|
usage()
|
|||
|
{
|
|||
|
fprintf(stderr,"usage: atis -l logfile -Dlevel -d<args> -E -N -R [reload]\n");
|
|||
|
fprintf(stderr," [dump] [exit] [debug] [nodebug]\n");
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
setuppidfilename()
|
|||
|
{
|
|||
|
int el;
|
|||
|
char *p;
|
|||
|
|
|||
|
el = strlen(ETCDIR);
|
|||
|
pidfile = (char *)malloc(el+sizeof("atis.pid")+5);
|
|||
|
if (pidfile == NULL) {
|
|||
|
fprintf(stderr,"Can't allocate memory for pid file");
|
|||
|
exit(999);
|
|||
|
}
|
|||
|
strcpy(pidfile, ETCDIR);
|
|||
|
if (el > 0) {
|
|||
|
p = pidfile+el - 1; /* point to last char */
|
|||
|
while (el-- && *p == '/') /* strip trailing slashes */
|
|||
|
*p-- = '\0';
|
|||
|
p++; /* make sure at end of string */
|
|||
|
}
|
|||
|
strcpy(p, "/atis.pid");
|
|||
|
#ifdef DEBUG
|
|||
|
printf("pid file name = %s\n", pidfile);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
setatispid()
|
|||
|
{
|
|||
|
FILE *fd;
|
|||
|
|
|||
|
if ((fd = fopen(pidfile, "w")) != NULL) {
|
|||
|
fprintf(fd, "%d\n",getpid());
|
|||
|
(void)fclose(fd);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
getatispid()
|
|||
|
{
|
|||
|
FILE *fp;
|
|||
|
int pid;
|
|||
|
|
|||
|
if ((fp = fopen(pidfile, "r")) == NULL) {
|
|||
|
logit(L_UERR|0, "No pid file - maybe the daemon wasn't running?");
|
|||
|
return(-1);
|
|||
|
}
|
|||
|
if (fscanf(fp, "%d\n", &pid) != 1) {
|
|||
|
logit(0, "pid file was bad");
|
|||
|
return(-1);
|
|||
|
}
|
|||
|
return(pid);
|
|||
|
}
|
|||
|
|
|||
|
#define NSIGACT 5
|
|||
|
|
|||
|
struct sigtab {
|
|||
|
char *s_name;
|
|||
|
int s_signal;
|
|||
|
char *s_action;
|
|||
|
} sigtab[NSIGACT] = {
|
|||
|
"reload", SIGHUP, "reload nis database",
|
|||
|
"dump", SIGQUIT, "dump nis database",
|
|||
|
"debug", SIGIOT, "increment debug level",
|
|||
|
"nodebug", SIGEMT, "no debug level",
|
|||
|
"exit", SIGTERM, "stop running atis"
|
|||
|
};
|
|||
|
|
|||
|
handlesigact(s, pid)
|
|||
|
char *s;
|
|||
|
{
|
|||
|
int i;
|
|||
|
struct sigtab *st;
|
|||
|
|
|||
|
pid = getatispid();
|
|||
|
for (st = sigtab, i = 0; i < NSIGACT; i++, st++) {
|
|||
|
if (strcmp(s, st->s_name) != 0)
|
|||
|
continue;
|
|||
|
if (kill(pid, st->s_signal) < 0)
|
|||
|
logit(0, "Couldn't send %s signal to daemon[%d] - is it running?",
|
|||
|
st->s_action, pid);
|
|||
|
else
|
|||
|
logit(0, "Sent %s signal to daemon[%d]",st->s_action,pid);
|
|||
|
return(0);
|
|||
|
}
|
|||
|
return(-1);
|
|||
|
}
|
|||
|
|
|||
|
doargs(argc, argv)
|
|||
|
int argc;
|
|||
|
char **argv;
|
|||
|
{
|
|||
|
int pid;
|
|||
|
int c, dlevel;
|
|||
|
extern char *optarg;
|
|||
|
extern int optind;
|
|||
|
extern boolean dochecksum;
|
|||
|
|
|||
|
while ((c = getopt(argc, argv, "kENRD:d:l:")) != EOF) {
|
|||
|
switch (c) {
|
|||
|
case 'k':
|
|||
|
dochecksum = 0;
|
|||
|
break;
|
|||
|
case 'N':
|
|||
|
nbpskt = 0;
|
|||
|
logit(0, "no nis server will be established");
|
|||
|
break;
|
|||
|
case 'E':
|
|||
|
echoskt = 0;
|
|||
|
logit(0, "no echo listener will be established");
|
|||
|
break;
|
|||
|
case 'R':
|
|||
|
rtmpskt = 0;
|
|||
|
logit(0, "no rtmp listener will be established");
|
|||
|
break;
|
|||
|
case 'D':
|
|||
|
dlevel = atoi(optarg);
|
|||
|
if (dlevel > L_LVLMAX)
|
|||
|
dlevel = L_LVLMAX;
|
|||
|
set_debug_level(dlevel);
|
|||
|
break;
|
|||
|
case 'd':
|
|||
|
dbugarg(optarg);
|
|||
|
set_debug_level(1);
|
|||
|
break;
|
|||
|
case 'l':
|
|||
|
logitfileis(optarg, "w");
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (optind == argc)
|
|||
|
return;
|
|||
|
if ((pid = getatispid()) < 0) {
|
|||
|
logit(L_EXIT|0, "Couldn't get pid of daemon - is it running?");
|
|||
|
}
|
|||
|
for (; optind < argc; optind++)
|
|||
|
if (handlesigact(argv[optind], pid) < 0)
|
|||
|
usage();
|
|||
|
exit(0);
|
|||
|
}
|
|||
|
|
|||
|
disassociate()
|
|||
|
{
|
|||
|
int i;
|
|||
|
/* disassociate */
|
|||
|
if (fork())
|
|||
|
_exit(0); /* kill parent */
|
|||
|
for (i=0; i < 3; i++) close(i); /* kill */
|
|||
|
(void)open("/",0);
|
|||
|
#ifdef NODUP2
|
|||
|
(void)dup(0); /* slot 1 */
|
|||
|
(void)dup(0); /* slot 2 */
|
|||
|
#else NODUP2
|
|||
|
(void)dup2(0,1);
|
|||
|
(void)dup2(0,2);
|
|||
|
#endif NODUP2
|
|||
|
#ifndef POSIX
|
|||
|
#ifdef TIOCNOTTY
|
|||
|
if ((i = open("/dev/tty",2)) > 0) {
|
|||
|
(void)ioctl(i, TIOCNOTTY, (caddr_t)0);
|
|||
|
(void)close(i);
|
|||
|
}
|
|||
|
#endif TIOCNOTTY
|
|||
|
#ifdef xenix5
|
|||
|
/*
|
|||
|
* USG process groups:
|
|||
|
* The fork guarantees that the child is not a process group leader.
|
|||
|
* Then setpgrp() can work, whick loses the controllong tty.
|
|||
|
* Note that we must be careful not to be the first to open any tty,
|
|||
|
* or it will become our controlling tty. C'est la vie.
|
|||
|
*/
|
|||
|
setpgrp();
|
|||
|
#endif xenix5
|
|||
|
#else POSIX
|
|||
|
(void) setsid();
|
|||
|
#endif POSIX
|
|||
|
}
|
|||
|
|
|||
|
main(argc, argv)
|
|||
|
int argc;
|
|||
|
char **argv;
|
|||
|
{
|
|||
|
int nbperr = noErr;
|
|||
|
int echoerr = noErr;
|
|||
|
int rtmperr = noErr;
|
|||
|
|
|||
|
set_debug_level(0);
|
|||
|
setuppidfilename();
|
|||
|
|
|||
|
progname = argv[0];
|
|||
|
doargs(argc, argv);
|
|||
|
|
|||
|
abInit(TRUE); /* init driver */
|
|||
|
nbpInit(); /* init NBP */
|
|||
|
nbptab_init();
|
|||
|
(void)signal(SIGHUP, nbp_reload);
|
|||
|
(void)signal(SIGQUIT, nbp_dump);
|
|||
|
(void)signal(SIGTERM, atis_end);
|
|||
|
(void)signal(SIGIOT, atis_debuginc);
|
|||
|
(void)signal(SIGEMT, atis_undebug);
|
|||
|
|
|||
|
logit(0, "Reply num max for lkup reply is %d (based on %d)",
|
|||
|
NUMREPLYMAX, NBPTUPSIZE);
|
|||
|
|
|||
|
if (nbpskt) {
|
|||
|
if ((nbperr = DDPOpenSocket(&nbpskt, nbp_listener)) != noErr)
|
|||
|
logit(L_UERR|0, "NIS: NIS socket not available: error %d", nbperr);
|
|||
|
}
|
|||
|
|
|||
|
if (echoskt) {
|
|||
|
if ((echoerr = DDPOpenSocket(&echoskt, echo_listener)) != noErr)
|
|||
|
logit(L_UERR|0, "ECHO: ECHO socket not available: error %d", echoerr);
|
|||
|
}
|
|||
|
|
|||
|
if ((lap_proto == LAP_ETALK || lap_proto == LAP_KERNEL) && rtmpskt) {
|
|||
|
if ((rtmperr = DDPOpenSocket(&rtmpskt, rtmp_listener)) != noErr)
|
|||
|
logit(L_UERR|0, "RTMP: RTMP socket not available: error %d", rtmperr);
|
|||
|
#ifdef linux
|
|||
|
if (lap_proto == LAP_KERNEL) {
|
|||
|
extern void rtmp_timer();
|
|||
|
Timeout(rtmp_timer, 0, 40);
|
|||
|
}
|
|||
|
#endif /* linux */
|
|||
|
}
|
|||
|
|
|||
|
if (echoerr != noErr && nbperr != noErr && rtmperr != noErr)
|
|||
|
logit(0|L_EXIT,"Couldn't establish nis, rtmp or echo socket, nothing to do");
|
|||
|
|
|||
|
if (!dbug.db_flgs && (get_debug_level() == 0))
|
|||
|
disassociate();
|
|||
|
|
|||
|
/* store pid where people can see it */
|
|||
|
setatispid();
|
|||
|
logit(0,"pid = %d",getpid());
|
|||
|
|
|||
|
/* sleep for a day (but wake up on events) */
|
|||
|
|
|||
|
for (;;)
|
|||
|
abSleep(sectotick(60*60*24), TRUE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* This is the NBP NIS listener
|
|||
|
*
|
|||
|
*/
|
|||
|
void
|
|||
|
nbp_listener(skt, type, nbp, len, addr)
|
|||
|
u_char skt;
|
|||
|
u_char type;
|
|||
|
NBP *nbp;
|
|||
|
int len;
|
|||
|
AddrBlock *addr;
|
|||
|
{
|
|||
|
int cnt;
|
|||
|
NBPTEntry looks;
|
|||
|
|
|||
|
if (len < nbpMinSize || type != ddpNBP) {
|
|||
|
logit(3, "Packet too small or bad packet type");
|
|||
|
return;
|
|||
|
}
|
|||
|
/* technically, we should check to see if it is ourselves and not */
|
|||
|
/* respond if so, but it is convient to do so and is part of the */
|
|||
|
/* nbp extensions */
|
|||
|
switch (nbp->control) {
|
|||
|
default:
|
|||
|
case nbpLkUpReply:
|
|||
|
logit(3, "Dropping nbp of type %d",nbp->control);
|
|||
|
return; /* drop the packet */
|
|||
|
case nbpTickle:
|
|||
|
case nbpRegister:
|
|||
|
case nbpDelete:
|
|||
|
case nbpBrRq:
|
|||
|
case nbpLkUp:
|
|||
|
break;
|
|||
|
}
|
|||
|
/* at this point we know we have a lookup */
|
|||
|
logit(2, "Got nbp %d lkup from net %d.%d, node %d, skt %d",
|
|||
|
nbp->tcnt, ntohs(addr->net)>>8, ntohs(addr->net)&0xff,
|
|||
|
addr->node, addr->skt);
|
|||
|
/* should only get one entity in incoming packet */
|
|||
|
switch (nbp->control) {
|
|||
|
case nbpBrRq: /* treat as lkup */
|
|||
|
case nbpLkUp:
|
|||
|
cnt = nbpcpy(&looks, 0, 1, nbp, (int)nbp->tcnt, FALSE);
|
|||
|
answer(&looks, &looks.addr, nbp->id);
|
|||
|
break;
|
|||
|
case nbpTickle:
|
|||
|
/* tickle may be implemented in the future */
|
|||
|
/* tickle may take list of entities in future */
|
|||
|
break;
|
|||
|
case nbpRegister:
|
|||
|
case nbpDelete:
|
|||
|
cnt = nbpcpy(&looks, 0, 1, nbp, 1, FALSE);
|
|||
|
nbp_extensions(&looks, addr, nbp, len);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* reply to a NBP LkUp request
|
|||
|
*
|
|||
|
*/
|
|||
|
answer(en, addr, id)
|
|||
|
NBPTEntry *en;
|
|||
|
AddrBlock *addr;
|
|||
|
u_char id;
|
|||
|
{
|
|||
|
NBP nbp;
|
|||
|
ABusRecord ddp;
|
|||
|
ddpProto *ddpr;
|
|||
|
int cnt, nsize, tsize;
|
|||
|
NBPTuple *tp;
|
|||
|
int i, start = 0;
|
|||
|
int mask;
|
|||
|
|
|||
|
#ifdef ISO_TRANSLATE
|
|||
|
EntityName isoEn;
|
|||
|
void cMac2ISO();
|
|||
|
|
|||
|
bcopy(en->ent.objStr.s, isoEn.objStr.s, sizeof(Str32));
|
|||
|
bcopy(en->ent.typeStr.s, isoEn.typeStr.s, sizeof(Str32));
|
|||
|
bcopy(en->ent.zoneStr.s, isoEn.zoneStr.s, sizeof(Str32));
|
|||
|
cMac2ISO(isoEn.objStr.s);
|
|||
|
cMac2ISO(isoEn.typeStr.s);
|
|||
|
cMac2ISO(isoEn.zoneStr.s);
|
|||
|
logit(2, "Looking for entities to answer a lookup with %s:%s@%s",
|
|||
|
isoEn.objStr.s, isoEn.typeStr.s, isoEn.zoneStr.s);
|
|||
|
#else ISO_TRANSLATE
|
|||
|
logit(2, "Looking for entities to answer a lookup with %s:%s@%s",
|
|||
|
en->ent.objStr.s, en->ent.typeStr.s, en->ent.zoneStr.s);
|
|||
|
#endif ISO_TRANSLATE
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold(DUMPSIG);
|
|||
|
sighold(LOADSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
mask = sigblock(DUMPSIG|LOADSIG); /* prevent inconsistency */
|
|||
|
#endif NOSIGMASK
|
|||
|
while ((cnt = nbpt_find(&en->ent, &start, reply, NUMREPLYMAX)) > 0) {
|
|||
|
if (cnt > 255) {
|
|||
|
logit(3, "Dropping count to 255 from %d",cnt);
|
|||
|
cnt = 255;
|
|||
|
}
|
|||
|
logit(2, "Answering lookup with %d entities",cnt);
|
|||
|
nbp.tcnt = cnt;
|
|||
|
nbp.control = nbpLkUpReply;
|
|||
|
nbp.id = id;
|
|||
|
for (i = 0, tsize = 0, tp = nbp.tuple; i < cnt; i++) {
|
|||
|
tp->enume = (byte)reply[i].enume;
|
|||
|
bcopy((caddr_t)&reply[i].addr, (caddr_t)&tp->addr, sizeof(AddrBlock));
|
|||
|
nsize = c2pkt_ename(&reply[i].ent, tp->name);
|
|||
|
nsize += sizeof(AddrBlock) + sizeof(tp->enume);
|
|||
|
tsize += nsize;
|
|||
|
tp = (NBPTuple *)(((char *)tp) + nsize);
|
|||
|
}
|
|||
|
ddpr = &ddp.proto.ddp; /* handle on DDP protocol args */
|
|||
|
ddpr->ddpAddress = *addr;
|
|||
|
ddpr->ddpSocket = nbpskt;
|
|||
|
ddpr->ddpType = ddpNBP;
|
|||
|
ddpr->ddpDataPtr = (u_char *) &nbp;
|
|||
|
ddpr->ddpReqCount = 2+tsize; /* control + id + rest */
|
|||
|
DDPWrite(&ddp,FALSE); /* write it out... */
|
|||
|
}
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse(DUMPSIG);
|
|||
|
sigrelse(LOADSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Handle the extended NBP functions
|
|||
|
*
|
|||
|
*/
|
|||
|
void
|
|||
|
nbp_extensions(nbptent, addr, nbp, len)
|
|||
|
NBPTEntry *nbptent;
|
|||
|
AddrBlock *addr;
|
|||
|
NBP *nbp;
|
|||
|
int len;
|
|||
|
{
|
|||
|
ABusRecord abr;
|
|||
|
int mask;
|
|||
|
int rc;
|
|||
|
char objStr[33], typeStr[33], zoneStr[33];
|
|||
|
|
|||
|
switch (nbp->control) {
|
|||
|
case nbpRegister:
|
|||
|
logit(2, "Register from net %3d.%02d node %d skt %d ",
|
|||
|
ntohs(addr->net)>>8, ntohs(addr->net)&0xff,addr->node, addr->skt);
|
|||
|
if (get_debug_level() > 1) {
|
|||
|
objStr[32] = typeStr[32] = zoneStr[32] = '\0'; /* tie off? */
|
|||
|
strcpy(objStr, (char *)nbptent->ent.objStr.s);
|
|||
|
strcpy(typeStr, (char *)nbptent->ent.typeStr.s);
|
|||
|
strcpy(zoneStr, (char *)nbptent->ent.zoneStr.s);
|
|||
|
logit(2, "\tfor %s:%s@%s, net %3d.%02d node %d skt %d ",
|
|||
|
objStr, typeStr, zoneStr,
|
|||
|
ntohs(nbptent->addr.net)>>8,
|
|||
|
ntohs(nbptent->addr.net)&0xff, nbptent->addr.node,
|
|||
|
nbptent->addr.skt);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold(DUMPSIG);
|
|||
|
sighold(LOADSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
mask = sigblock(DUMPSIG|LOADSIG); /* prevent inconsistency */
|
|||
|
#endif NOSIGMASK
|
|||
|
rc = nbptab_insert(addr, &nbptent->addr, &nbptent->ent);
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse(DUMPSIG);
|
|||
|
sigrelse(LOADSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
logit(2, "Register return code %d",rc);
|
|||
|
/* return address */
|
|||
|
bcopy((caddr_t)&nbptent->addr, (caddr_t)&abr.proto.ddp.ddpAddress,
|
|||
|
sizeof(AddrBlock));
|
|||
|
break;
|
|||
|
case nbpDelete:
|
|||
|
if (get_debug_level() > 1) {
|
|||
|
objStr[32] = typeStr[32] = zoneStr[32] = '\0'; /* tie off? */
|
|||
|
strcpy(objStr, (char *)nbptent->ent.objStr.s);
|
|||
|
strcpy(typeStr, (char *)nbptent->ent.typeStr.s);
|
|||
|
strcpy(zoneStr, (char *)nbptent->ent.zoneStr.s);
|
|||
|
logit(2, "Delete %32s:%32s@%32s, net %3d.%02d node %d skt %d",
|
|||
|
objStr, typeStr, zoneStr, ntohs(addr->net)>>8,
|
|||
|
ntohs(addr->net)&0xff,addr->node, addr->skt);
|
|||
|
}
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sighold(DUMPSIG);
|
|||
|
sighold(LOADSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
mask = sigblock(DUMPSIG|LOADSIG); /* prevent inconsistency */
|
|||
|
#endif NOSIGMASK
|
|||
|
rc = nbptab_delete(addr, &nbptent->ent) ;
|
|||
|
#ifdef NOSIGMASK
|
|||
|
sigrelse(DUMPSIG);
|
|||
|
sigrelse(LOADSIG);
|
|||
|
#else NOSIGMASK
|
|||
|
sigsetmask(mask);
|
|||
|
#endif NOSIGMASK
|
|||
|
logit(2, "Delete returns code %d",rc);
|
|||
|
abr.proto.ddp.ddpAddress = *addr; /* return address */
|
|||
|
break;
|
|||
|
case nbpTickle:
|
|||
|
logit(2, "Got a tickle");
|
|||
|
return;
|
|||
|
default:
|
|||
|
logit(2, "Unknown NBP type %d",nbp->control);
|
|||
|
return;
|
|||
|
}
|
|||
|
nbp->control = nbpStatusReply;
|
|||
|
nbp->tcnt = rc;
|
|||
|
abr.proto.ddp.ddpSocket = nbpskt;
|
|||
|
abr.proto.ddp.ddpType = ddpNBP;
|
|||
|
abr.proto.ddp.ddpDataPtr = (u_char *)nbp;
|
|||
|
abr.proto.ddp.ddpReqCount = len;
|
|||
|
DDPWrite(&abr, FALSE);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* This is the Echo Protocol listener
|
|||
|
*
|
|||
|
*/
|
|||
|
void
|
|||
|
echo_listener(skt, type, pkt, len, addr)
|
|||
|
u_char skt;
|
|||
|
u_char type;
|
|||
|
char *pkt;
|
|||
|
int len;
|
|||
|
AddrBlock *addr;
|
|||
|
{
|
|||
|
u_char ec; /* echo command */
|
|||
|
ABusRecord abr;
|
|||
|
|
|||
|
if (type != ddpECHO) {
|
|||
|
logit(1, "Got non-echo pkt in echolistener");
|
|||
|
return; /* drop packet */
|
|||
|
}
|
|||
|
ec = (u_char)*pkt;
|
|||
|
if (ec != echoRequest) {
|
|||
|
printf("got %u when expecting echorequest\n",ec);
|
|||
|
return; /* drop packet */
|
|||
|
}
|
|||
|
*pkt = echoReply;
|
|||
|
abr.proto.ddp.ddpAddress = *addr;
|
|||
|
abr.proto.ddp.ddpSocket = echoskt;
|
|||
|
abr.proto.ddp.ddpType = ddpECHO;
|
|||
|
abr.proto.ddp.ddpDataPtr = (u_char *)pkt;
|
|||
|
abr.proto.ddp.ddpReqCount = len;
|
|||
|
DDPWrite(&abr, FALSE);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* This is the RTMP listener
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
rtmp_listener(skt, type, pkt, len, addr)
|
|||
|
u_char skt;
|
|||
|
u_char type;
|
|||
|
u_char *pkt;
|
|||
|
int len;
|
|||
|
AddrBlock *addr;
|
|||
|
{
|
|||
|
u_char rc; /* rtmp command */
|
|||
|
time_t now;
|
|||
|
u_short net;
|
|||
|
ABusRecord abr;
|
|||
|
static int goodness = 0;
|
|||
|
static AddrBlock last_addr;
|
|||
|
static time_t last_time = 0;
|
|||
|
static AddrBlock current_addr;
|
|||
|
static time_t current_time = 0;
|
|||
|
static int current_goodness = -1;
|
|||
|
#ifdef PHASE2
|
|||
|
u_short new_net_range_start, new_net_range_end, increment;
|
|||
|
#endif PHASE2
|
|||
|
|
|||
|
if (type != ddpRTMP) {
|
|||
|
logit(1, "Got non-rtmp pkt in rtmplistener");
|
|||
|
return; /* drop packet */
|
|||
|
}
|
|||
|
|
|||
|
net = htons((pkt[0] << 8) | pkt[1]);
|
|||
|
|
|||
|
logit(5, "Got RTMP pkt net %d from %d.%d",
|
|||
|
ntohs(net), ntohs(addr->net), addr->node);
|
|||
|
|
|||
|
if (bridge_net == 0 && net != 0) {
|
|||
|
addr->net = net;
|
|||
|
SetBridgeAddress(addr);
|
|||
|
logit(1, "Gleaned network number %d from bridge %d",ntohs(net),addr->node);
|
|||
|
}
|
|||
|
|
|||
|
#ifdef PHASE2
|
|||
|
if (ntohs(net)>=ntohs(net_range_start) && ntohs(net)<=ntohs(net_range_end)) {
|
|||
|
#else PHASE2
|
|||
|
if (net == addr->net) {
|
|||
|
#endif PHASE2
|
|||
|
/*
|
|||
|
* Compute the goodness of this router. We prefer routers that do
|
|||
|
* split horizon, and among them, those that have the most routes.
|
|||
|
* The goodness is thus the number of routes, and 0 for non-split horizon.
|
|||
|
* At Rutgers the effect is to prefer cisco (which does split horizon)
|
|||
|
* over Kinetics, and to pick the cisco that is the most "central".
|
|||
|
* This should tend to produce the best routes. It will probably
|
|||
|
* work reasonably at most other places as well. We expire an old
|
|||
|
* router after 15 sec. This allows us to miss one update, but no
|
|||
|
* more. Apple wants us to use the most recent router we heard from,
|
|||
|
* but that allows no selectivity at all, and also tends to lead to
|
|||
|
* inconsistent results. Unfortunately Apple specifies that when
|
|||
|
* several routes have the same metric, routers choose the most recently
|
|||
|
* heard. This leads to rapidly changing entries. The result can be
|
|||
|
* small changes in goodness. If two routers are very close, we could
|
|||
|
* end up going between them. If this is a problem for you, redefine
|
|||
|
* MARGIN to be 10% or more of the current_goodness.
|
|||
|
*
|
|||
|
* Be aware that very good routers can send a full RTMP packet followed
|
|||
|
* by a small "overflow" RTMP packet, be careful not to overreact.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
* go to beginning of routing triples
|
|||
|
*
|
|||
|
*/
|
|||
|
#ifdef PHASE2
|
|||
|
pkt += 4;
|
|||
|
len -= 4;
|
|||
|
if (pkt[0] == 0 && pkt[1] == 0 && pkt[2] == 0x82) { /* non-extended net */
|
|||
|
new_net_range_start = net; /* net byte order */
|
|||
|
new_net_range_end = net; /* net byte order */
|
|||
|
} else if (pkt[2] & 0x80 && pkt[5] == 0x82) { /* extended network */
|
|||
|
new_net_range_start = htons((pkt[0] << 8) | pkt[1]);
|
|||
|
new_net_range_end = htons((pkt[3] << 8) | pkt[4]);
|
|||
|
pkt += 3;
|
|||
|
len -= 3;
|
|||
|
} else {
|
|||
|
logit(2, "RTMP: unknown format packet, dropped!");
|
|||
|
return;
|
|||
|
}
|
|||
|
pkt += 3;
|
|||
|
len -= 3;
|
|||
|
#ifdef notdef
|
|||
|
/* ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ */
|
|||
|
/* we should be doing this, in case the router was down when */
|
|||
|
/* we started up. However, doing so will proably confuse our */
|
|||
|
/* clients too much. We should also do it to ensure that the */
|
|||
|
/* correct zone multicast address gets enabled on the intrfc */
|
|||
|
/* ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ */
|
|||
|
if (net_range_start == 0x00 && net_range_end == htons(0xfffe)) {
|
|||
|
this_net = nis_net = net_range_start = new_net_range_start;
|
|||
|
net_range_end = new_net_range_end;
|
|||
|
SetNetRange(net_range_start, net_range_end);
|
|||
|
}
|
|||
|
#endif notdef
|
|||
|
#else PHASE2
|
|||
|
pkt += 7;
|
|||
|
len -= 7;
|
|||
|
#endif PHASE2
|
|||
|
|
|||
|
#ifdef linux
|
|||
|
/*
|
|||
|
* build RTMP table for kernel
|
|||
|
*
|
|||
|
*/
|
|||
|
if (lap_proto == LAP_KERNEL) {
|
|||
|
void rtmp_data();
|
|||
|
rtmp_data(addr->node, addr->net, pkt, len);
|
|||
|
}
|
|||
|
#endif /* linux */
|
|||
|
|
|||
|
now = time(NULL);
|
|||
|
|
|||
|
/*
|
|||
|
* reset goodness if more than 2 seconds
|
|||
|
* old or this is from a different router.
|
|||
|
*
|
|||
|
*/
|
|||
|
if (now > last_time+2
|
|||
|
|| last_addr.net != addr->net
|
|||
|
|| last_addr.node != addr->node)
|
|||
|
goodness = 0;
|
|||
|
|
|||
|
/*
|
|||
|
* loop over routing triples, counting them.
|
|||
|
* If we find the router network, this router
|
|||
|
* isn't doing split horizon.
|
|||
|
*
|
|||
|
*/
|
|||
|
while (len > 0) {
|
|||
|
net = htons((pkt[0] << 8) | pkt[1]); /* pkt data is not aligned */
|
|||
|
if (net == addr->net) { /* not doing split horizon */
|
|||
|
logit (10, "No split horizon in router %d.%d",
|
|||
|
ntohs(addr->net), addr->node);
|
|||
|
goodness = 0;
|
|||
|
}
|
|||
|
goodness++;
|
|||
|
#ifdef PHASE2
|
|||
|
if (pkt[2] & 0x80 && pkt[5] == 0x82)
|
|||
|
increment = 3;
|
|||
|
else
|
|||
|
increment = 0;
|
|||
|
len -= increment;
|
|||
|
pkt += increment;
|
|||
|
#endif PHASE2
|
|||
|
len -= 3;
|
|||
|
pkt += 3;
|
|||
|
}
|
|||
|
|
|||
|
logit (8, "Router %d.%d has goodness %d",
|
|||
|
ntohs(addr->net), addr->node, goodness);
|
|||
|
|
|||
|
last_time = now;
|
|||
|
last_addr.net = addr->net;
|
|||
|
last_addr.node = addr->node;
|
|||
|
|
|||
|
#define MARGIN (current_goodness / 20) /* currently 5% */
|
|||
|
|
|||
|
/*
|
|||
|
* this router knows more than 5% more
|
|||
|
* routes than the current one, adopt it
|
|||
|
* (may be subsequent packets from current)
|
|||
|
*
|
|||
|
*/
|
|||
|
if (goodness > (current_goodness+MARGIN)) {
|
|||
|
if (addr->node != current_addr.node
|
|||
|
|| addr->net != current_addr.net) {
|
|||
|
SetBridgeAddress(addr);
|
|||
|
logit (1, "New default router %d.%d, goodness %d -> %d",
|
|||
|
ntohs(addr->net), addr->node, current_goodness, goodness);
|
|||
|
current_addr.node = addr->node;
|
|||
|
current_addr.net = addr->net;
|
|||
|
}
|
|||
|
current_goodness = goodness;
|
|||
|
current_time = now;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* same router, update heard-from time
|
|||
|
*
|
|||
|
*/
|
|||
|
if (addr->node == current_addr.node
|
|||
|
&& addr->net == current_addr.net) {
|
|||
|
logit (1, "Current default router %d.%d, goodness %d",
|
|||
|
ntohs(addr->net), addr->node, current_goodness);
|
|||
|
current_time = now;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* different router, and we haven't heard
|
|||
|
* from our current router for more than
|
|||
|
* 15 seconds, adopt it
|
|||
|
*
|
|||
|
*/
|
|||
|
if ((addr->node != current_addr.node
|
|||
|
|| addr->net != current_addr.net)
|
|||
|
&& (now - current_time) > 15) {
|
|||
|
SetBridgeAddress(addr);
|
|||
|
logit (1, "New default router %d.%d (old expired)",
|
|||
|
ntohs(addr->net), addr->node);
|
|||
|
current_addr.node = addr->node;
|
|||
|
current_addr.net = addr->net;
|
|||
|
current_goodness = goodness;
|
|||
|
current_time = now;
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* The following should be integrated into ABNBP.C someday
|
|||
|
* (Looks like that someday will never come :-).
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
* private int nbpcpy(en, enc, start, nbp, nbptcnt, unique)
|
|||
|
*
|
|||
|
* nbpcpy copies the entities in nbp to the NBP Table entry array
|
|||
|
* pointed to by en. Maximum number of entities is enc. Start specifies
|
|||
|
* where in the array to start. Unique is used as a flag: if true
|
|||
|
* then make sure the incoming items are unique (e.g. don't duplicate
|
|||
|
* items in the table pointed to by en).
|
|||
|
*
|
|||
|
* at end number of entries inserted is returned
|
|||
|
*
|
|||
|
*/
|
|||
|
private int
|
|||
|
nbpcpy(entab, enstart, entabmax, nbp, nbptcnt, unique)
|
|||
|
NBPTEntry *entab;
|
|||
|
int enstart;
|
|||
|
int entabmax;
|
|||
|
NBP *nbp;
|
|||
|
int nbptcnt;
|
|||
|
int unique;
|
|||
|
{
|
|||
|
NBPTuple *ep;
|
|||
|
int i, tcount, len;
|
|||
|
NBPTEntry curr;
|
|||
|
|
|||
|
/* Add NBP tuples to user's data structure */
|
|||
|
/* make sure curr's ent is empty */
|
|||
|
bzero((caddr_t)&curr.ent, sizeof(curr.ent));
|
|||
|
for (i=enstart, tcount=nbptcnt, ep = nbp->tuple;
|
|||
|
tcount != 0 && i < entabmax;
|
|||
|
tcount--) {
|
|||
|
bcopy((caddr_t)&ep->addr,(caddr_t)&curr.addr, sizeof(AddrBlock));
|
|||
|
bcopy((caddr_t)&ep->enume,(caddr_t)&curr.enume, sizeof(curr.enume));
|
|||
|
len = pkt2c_ename(ep->name,&curr.ent);
|
|||
|
ep = (NBPTuple *) ((char *) ep+(len+sizeof(AddrBlock)+1));
|
|||
|
i += nbpinsertentry(entab, i, &curr, unique);
|
|||
|
}
|
|||
|
return(i-enstart);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* insert entry into specified NBP Table. Check previous entries for */
|
|||
|
/* conflict - if conflict - then update entry if update flag is on */
|
|||
|
/* ow. insert at specified point */
|
|||
|
/* returns 1 if inserted item, zero o.w. - no errors possible */
|
|||
|
nbpinsertentry(entab, point, nbptentry, update)
|
|||
|
NBPTEntry entab[];
|
|||
|
int point;
|
|||
|
NBPTEntry *nbptentry;
|
|||
|
boolean update;
|
|||
|
{
|
|||
|
NBPTEntry *cetp = entab;
|
|||
|
int i;
|
|||
|
|
|||
|
if (update) { /* update==false ==> always insert */
|
|||
|
for (i=0; i < (point-1); i++) {
|
|||
|
if (bcmp((caddr_t)&cetp->addr, (caddr_t)&nbptentry->addr,
|
|||
|
sizeof(cetp->addr)) == 0)
|
|||
|
if (cetp->enume == nbptentry->enume) {
|
|||
|
bcopy((caddr_t)&nbptentry->ent,(caddr_t)&cetp->ent,
|
|||
|
sizeof(cetp->ent));
|
|||
|
return(0); /* done */
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
bcopy((caddr_t)nbptentry, (caddr_t)cetp, sizeof(NBPTEntry));
|
|||
|
return(1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Private int c2pkt_ename(EntityName *cn, u_char *pn)
|
|||
|
*
|
|||
|
* Copy entity name from c form into contiguous Apple Pascal
|
|||
|
* form (packet form).
|
|||
|
*
|
|||
|
* return: length of pascal form entity name
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
private int
|
|||
|
c2pkt_ename(cn,pn)
|
|||
|
u_char *pn;
|
|||
|
EntityName *cn;
|
|||
|
{
|
|||
|
int i, cnt;
|
|||
|
byte *s;
|
|||
|
byte *pc;
|
|||
|
|
|||
|
cnt = 0;
|
|||
|
for (s = cn->objStr.s, pc = pn++, i = 0; i < ENTITYSIZE; i++, pn++, s++) {
|
|||
|
*pn = *s;
|
|||
|
if (*s == '\0')
|
|||
|
break;
|
|||
|
}
|
|||
|
if (i > ENTITYSIZE) /* increment to cnt and check aginst cutoff */
|
|||
|
i = ENTITYSIZE; /* too large: turncated to 32 chars */
|
|||
|
*pc = i;
|
|||
|
cnt += (i+1);
|
|||
|
for (s = cn->typeStr.s, pc = pn++, i = 0; i < ENTITYSIZE; i++, pn++, s++) {
|
|||
|
*pn = *s;
|
|||
|
if (*s == '\0')
|
|||
|
break;
|
|||
|
}
|
|||
|
if (i > ENTITYSIZE) /* increment to cnt and check aginst cutoff */
|
|||
|
i = ENTITYSIZE; /* too large: turncated to 32 chars */
|
|||
|
*pc = i;
|
|||
|
cnt += (i+1);
|
|||
|
for (s = cn->zoneStr.s, pc = pn++, i = 0; i < ENTITYSIZE; i++, pn++, s++) {
|
|||
|
*pn = *s;
|
|||
|
if (*s == '\0')
|
|||
|
break;
|
|||
|
}
|
|||
|
if (i > ENTITYSIZE) /* increment to cnt and check aginst cutoff */
|
|||
|
i = ENTITYSIZE; /* too large: turncated to 32 chars */
|
|||
|
*pc = i;
|
|||
|
cnt += (i+1);
|
|||
|
return(cnt); /* return number of bytes used */
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Private int pkt2c_enames(u_char *pn, EntityName *cn);
|
|||
|
*
|
|||
|
* Copy entity names from packet form (abutting Apple Pascal
|
|||
|
* strings) to c form into structure of type EntityName.
|
|||
|
*
|
|||
|
* return: the length of the packed string.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
private int
|
|||
|
pkt2c_ename(pn,cn)
|
|||
|
u_char *pn;
|
|||
|
EntityName *cn;
|
|||
|
{
|
|||
|
int ol,tl,zl;
|
|||
|
|
|||
|
ol = *pn; /* length of object */
|
|||
|
tl = *(pn+ol+1); /* length of type */
|
|||
|
zl = *(pn+ol+tl+2); /* length of zone */
|
|||
|
if (ol > ENTITYSIZE || tl > ENTITYSIZE || zl > ENTITYSIZE) {
|
|||
|
logit(3,"pkt2c_entity_names: invalid length!");
|
|||
|
return(0);
|
|||
|
}
|
|||
|
cpyp2cstr(cn->objStr.s,pn); /* copy them... */
|
|||
|
cpyp2cstr(cn->typeStr.s,pn+ol+1);
|
|||
|
cpyp2cstr(cn->zoneStr.s,pn+ol+tl+2);
|
|||
|
return(ol+tl+zl+3); /* return length */
|
|||
|
}
|
|||
|
|
|||
|
#ifdef notdef
|
|||
|
|
|||
|
/*
|
|||
|
* print message - use vprintf whenever possible (solves the problem
|
|||
|
* of using the varargs macros -- you must interpret the format).
|
|||
|
* This is something all machine should, but don't have :-)
|
|||
|
*/
|
|||
|
|
|||
|
private FILE *lfp = stderr;
|
|||
|
|
|||
|
|
|||
|
#ifndef USEVPRINTF
|
|||
|
/* Bletch - gotta do it because pyramids don't work the other way */
|
|||
|
/* (using _doprnt and &args) and don't have vprintf */
|
|||
|
/* of course, there will be something that is just one arg larger :-) */
|
|||
|
/*VARARGS1*/
|
|||
|
logit(level, fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af)
|
|||
|
int level;
|
|||
|
char *fmt;
|
|||
|
#else
|
|||
|
logit(va_alist)
|
|||
|
va_dcl
|
|||
|
#endif
|
|||
|
{
|
|||
|
long time(), tloc;
|
|||
|
char *timestr;
|
|||
|
#ifdef USEVPRINTF
|
|||
|
register char *fmt;
|
|||
|
va_list args;
|
|||
|
int level;
|
|||
|
#endif
|
|||
|
int saveerr;
|
|||
|
extern int errno;
|
|||
|
extern int sys_nerr;
|
|||
|
extern char *sys_errlist[];
|
|||
|
|
|||
|
if (lfp == NULL) /* no logging? */
|
|||
|
return;
|
|||
|
|
|||
|
saveerr = errno;
|
|||
|
#ifdef USEVPRINTF
|
|||
|
va_start(args);
|
|||
|
level = va_arg(args, int);
|
|||
|
fmt = va_arg(args, char *);
|
|||
|
#endif
|
|||
|
|
|||
|
if (dlevel < (level & L_LVL))
|
|||
|
return;
|
|||
|
(void)time(&tloc);
|
|||
|
timestr = (char *)ctime(&tloc);
|
|||
|
timestr[24] = '\0'; /* hokey */
|
|||
|
fprintf(lfp,"atis: %s ",timestr);
|
|||
|
|
|||
|
#ifdef USEVPRINTF
|
|||
|
vfprintf(lfp, fmt, args);
|
|||
|
va_end(args);
|
|||
|
#else
|
|||
|
fprintf(lfp, fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af);
|
|||
|
#endif
|
|||
|
if (level & L_UERR) {
|
|||
|
if (saveerr < sys_nerr)
|
|||
|
fprintf(lfp, ": %s", sys_errlist[saveerr]);
|
|||
|
else
|
|||
|
fprintf(lfp, ": error %d\n", saveerr);
|
|||
|
}
|
|||
|
putc('\n', lfp);
|
|||
|
fflush(lfp);
|
|||
|
if (level & L_EXIT)
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
islogitfile()
|
|||
|
{
|
|||
|
if (lfp == stderr)
|
|||
|
return(FALSE);
|
|||
|
return(lfp != NULL);
|
|||
|
}
|
|||
|
|
|||
|
logitfileis(filename, mode)
|
|||
|
char *filename;
|
|||
|
char *mode;
|
|||
|
{
|
|||
|
FILE *fp;
|
|||
|
|
|||
|
if ((fp = fopen(filename, mode)) != NULL) {
|
|||
|
logit(0, "log file name %s", filename);
|
|||
|
} else {
|
|||
|
logit(0|L_UERR, "couldn't open logfile %s", filename);
|
|||
|
}
|
|||
|
lfp = fp; /* reset */
|
|||
|
}
|
|||
|
|
|||
|
nologitfile()
|
|||
|
{
|
|||
|
if (lfp && lfp != stderr)
|
|||
|
fclose(lfp);
|
|||
|
}
|
|||
|
#endif notdef
|
|||
|
|
|||
|
#ifdef NOSIGMASK
|
|||
|
|
|||
|
sighold_all()
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
for (i = 0; allsigs[i]; ++i)
|
|||
|
sighold(allsigs[i]);
|
|||
|
}
|
|||
|
|
|||
|
sigrelse_all()
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
for (i = 0; allsigs[i]; ++i)
|
|||
|
sigrelse(allsigs[i]);
|
|||
|
}
|
|||
|
|
|||
|
#endif NOSIGMASK
|