|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 25793 (0x64c1) Types: TextFile Names: »atalkad.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦3b20aab50⟧ »EurOpenD3/network/snmp/kip-snmp.91.tar.Z« └─⟦b503a39fe⟧ └─⟦this⟧ »kip/etc/atalkad.c«
#ifndef lint static char sccsid[] = "@(#)atalkad.c 1.2 (Stanford) 9/87"; #endif /* * Appletalk administration daemon. * * Answers request packets from client appletalk gateways by supplying * the appletalk-to-ip network configuration table and the local * appletalk gateway configuration information. */ /* * (C) 1986, Stanford Univ. CSLI. * May be used but not sold without permission. */ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/file.h> #include <sys/time.h> #include <netinet/in.h> #define iaddr_t long #include "gwctl.h" #include "ab.h" #include <signal.h> #include <stdio.h> #include <strings.h> #include <errno.h> #include <ctype.h> #include <netdb.h> /* for 4.2 systems */ #ifndef FD_SETSIZE # define FD_SETSIZE sizeof(int)*8 # define NFDBITS sizeof(int)*8 # define howmany(x,y) (1) # define FD_SET(n, p) (p)->fds_bits[0] |= (1<<(n)) # define FD_CLR(n, p) (p)->fds_bits[0] &= ~(1<<(n)) # define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) # define FD_ZERO(p) bzero((char *)p, sizeof(*p)) #endif #ifndef ATALKATAB #define ATALKATAB "/etc/atalkatab" #endif #ifndef ATALKALOG #define ATALKALOG "/usr/adm/atalkalog" #endif #ifndef ATALKAPID #define ATALKAPID "/usr/adm/atalkapid" #endif int debug; extern int errno; struct sockaddr_in sin = { AF_INET }; int s; /* socket fd */ struct sockaddr_in fsin; /* foreign sockaddr_in */ int fsinlen; int sig, sigint(), sighup(); struct aaconf aa; /* receive packet */ struct aaconf aas; /* send packet */ struct timeval tvwait; /* timer for select */ /* Mask of high 3 bytes of a network address */ iaddr_t node_mask; /* * Globals below are associated with the atalka database file (atalkatab). */ char *atalkatab = ATALKATAB; char *atalkalog = ATALKALOG; char *atalkapid = ATALKAPID; FILE *fp; char line[256]; /* line buffer for reading atalkatab */ char *linep; /* pointer to 'line' */ int linenum; /* current line number in atalkatab */ #define NANETS 64 /* max number of 'anets' structs */ struct anets { u_short net; /* atalk net */ u_char flags; /* flags, see aroute* in gwctl.h */ u_char confsize; /* size of databytes in conf below */ iaddr_t iaddr; /* ip address */ char zone[32]; /* zone name */ char conf[64]; /* configuration info, if kbox */ } anets[NANETS]; /* Internal format of conf structure */ struct conf { iaddr_t ipbroad; /* broadcast addr on ether */ iaddr_t ipname; /* address of name server */ iaddr_t ipdebug; /* address of debug host */ iaddr_t ipfile; /* address of file server */ u_long ipother[4]; /* other addresses passed via IPGP */ #define ipsmask anetet /* old use for this field */ u_short anetet; /* ethertalk net number of enet */ #define ipsshift startddpWKSUnix /* old: subnet shift (unused) */ u_short startddpWKSUnix; /* start of unix WKS udp ports */ u_long flags; /* various bit flags */ #define conf_stayinzone 0x1 /* no looking at other zones */ #define conf_laserfilter 0x2 /* NBP filtering for LaserWriters */ #define conf_tildefilter 0x4 /* NBP filtering, "name~" */ u_short ipstatic; /* number of static IP addrs */ u_short ipdynamic; /* number of dynamic IP addrs */ u_short atneta; /* atalk net #, appletalk */ u_short atnete; /* atalk net #, ethernet */ } conf_proto; int nanets; /* current number of anets */ long modtime; /* last modification time of atalkatab */ long size; /* last known size of file */ char aroutes[512]; /* route tuples built by buildart() */ int arouteslen; char azones[512]; /* zone table built by buildzone() */ int azoneslen; int scanonly = 0; usage() { printf("usage: atalkad [-c filename] [-debug] [route|boot|exit]\n"); printf("usage: -c means check file\n"); exit(1); } main(argc, argv) char *argv[]; { register int n; FILE *filep; int pid; for (argc--, argv++ ; argc > 0 ; argc--, argv++) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'd': debug++; break; case 'c': if (argv[0][2]) { atalkatab = argv[0]+2; } else if (argc > 1 && argv[1]) { atalkatab = argv[1]; argc--, argv++; } scanonly++; break; default: usage(); } continue; } if (scanonly) usage(); if (strcmp(argv[0], "boot") == 0) sig = SIGINT; else if (strcmp(argv[0], "route") == 0) sig = SIGHUP; else if (strcmp(argv[0], "exit") == 0) sig = SIGKILL; else usage(); if ((filep = fopen(atalkapid, "r")) == NULL || fscanf(filep, "%d", &pid) != 1 || kill(pid, sig) < 0) { printf("failed to send signal to daemon\n"); exit(1); } else { printf("sent signal to daemon\n"); exit(0); } } if (scanonly) { readtab(); dumptab(); exit(0); } if (debug == 0) { int t, f; if (fork()) exit(0); for (f = 0; f < 10; f++) (void) close(f); (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); t = open("/dev/tty", 2); if (t >= 0) { ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } } log("### ATALKA daemon starting"); pid = getpid(); if ((filep = fopen(atalkapid, "w")) == NULL) { log("couldnt create pid file %s\n", atalkapid); exit(1); } fprintf(filep, "%d", pid); fclose(filep); signal(SIGHUP, sighup); signal(SIGINT, sigint); while ((s = socket(AF_INET, SOCK_DGRAM, 0, 0)) < 0) { log("socket call failed"); sleep(5); } sin.sin_port = htons(aaPort); if (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) { log("bind call failed"); exit(1); } /* fill in node mask in a machine independent manner */ node_mask = inet_addr("255.255.255.0"); readtab(); for (;;) { fsinlen = sizeof (fsin); n = recvfrom(s, (caddr_t)&aa, sizeof aa, 0, (caddr_t)&fsin, &fsinlen); if (n < 0) { if (errno != EINTR) { log("recv failed"); exit(1); } readtab(); sendall(sig); continue; } if (n < aaconfMinSize || ntohl(aa.magic) != aaMagic) continue; readtab(); sendreply(); } } /* * Interrupts are used to signal type of sendall(). */ sighup() { sig = aaROUTEI; } sigint() { sig = aaRESTART; } /* * Send reply to packet aa. */ sendreply() { register struct anets *an; register n; switch (aa.type) { case aaCONF: for (an = &anets[0], n = 0 ; n < nanets ; an++, n++) if (an->iaddr == aa.ipaddr && an->confsize && (an->flags & arouteKbox) && (an->flags & arouteEtalk) == 0) goto found; log("aaCONF from %s ***** not in table", inet_ntoa(aa.ipaddr)); return; found: log("aaCONF to %s", inet_ntoa(aa.ipaddr)); n = an->confsize; bcopy(an->conf, aa.stuff, n); break; case aaZONE: log("aaZONE to %s", inet_ntoa(aa.ipaddr)); n = azoneslen; bcopy(azones, aa.stuff, n); break; case aaZONEQ: log("aaZONEq from %s", inet_ntoa(aa.ipaddr)); if ((n = zipinput()) <= 0) return; /* drop */ break; case aaROUTEI: log("aaROUTEI to %s", inet_ntoa(aa.ipaddr)); n = arouteslen; bcopy(aroutes, aa.stuff, n); break; default: /* don't reply here! */ return; } aa.count = htons(n); sendto(s, (caddr_t)&aa, aaconfMinSize + n, 0, &fsin, sizeof fsin); } char * netstring(n) u_short n; { int net; static char mynetstr[30]; net = ntohs(n); sprintf(mynetstr, "%d.%d", (net>>8) & 0xff, net & 0xff); return(mynetstr); } /* * return pointer to zone name * NULL if none */ char * zoneof(net) u_short net; { register struct anets *an; int n; for (an = &anets[0], n=0 ; n < nanets ; an++, n++) if (net == an->net) return(an->zone); return(NULL); } /* * return a value that is always printable * */ char * pzoneof(net) u_short net; { char *p = zoneof(net); return(p == NULL ? "unknown" : p); } dumptab() { register struct anets *an; register n, size; char *hostnameof(); struct conf *conf; iaddr_t rs, re; size = 0; for (an = &anets[0], n = 0 ; n < nanets ; an++, n++) { printf("Route %s %s, ", netstring(an->net), an->zone); if ((an->flags & arouteKbox) && (an->flags & arouteEtalk) == 0) printf(" Kinetics box"); if (an->flags & arouteCore) printf(" core gateway"); if (an->flags & arouteHost) printf(" host is redirector"); if (an->flags & arouteNet) if (an->flags & arouteBMask) printf(" net %d", an->flags & arouteBMask); else printf(" net 0: host is client"); if ((an->flags & (arouteKbox|arouteEtalk)) == (arouteKbox|arouteEtalk)) printf(" EtherTalk"); printf(" at %s", hostnameof(an->iaddr)); putchar('\n'); if ((an->flags & arouteKbox) && (an->flags & arouteEtalk) == 0) { conf = (struct conf *)an->conf; printf("\tIP Broadcast: %s, ", inet_ntoa(conf->ipbroad)); if (conf->ipname == conf->ipdebug) { printf("IP name and debug: %s\n", hostnameof(conf->ipname)); printf("\tIP file server (unused)", hostnameof(conf->ipfile)); } else { printf("IP name: %s\n",hostnameof(conf->ipname)); printf("\tIP debug %s, ", hostnameof(conf->ipdebug)); printf("IP file server (unused)", hostnameof(conf->ipfile)); } if (ntohl(conf->flags) & conf_stayinzone) printf(", marked stay in zone"); if (ntohl(conf->flags) & conf_laserfilter) printf(", laserwriters stay in zone"); if (ntohl(conf->flags) & conf_tildefilter) printf(", tilde marked names stay in zone"); putchar('\n'); if (conf->startddpWKSUnix == htons(defddpWKSUnix)) printf("\tUDP Port range for WKS starts at %d (old range)\n", defddpWKSUnix); else printf("\tUDP Port range for WKS starts at %d\n", ntohs(conf->startddpWKSUnix)); #ifdef SHORTFORMAT if (conf->ipstatic) printf("\t%d ", ntohs(conf->ipstatic)); else printf("\tNo"); printf(" static ip addresses, "); if (conf->ipdynamic) printf("\t%d ", ntohs(conf->ipdynamic)); else printf("\tNo"); printf(" dynamic ip addresses\n"); #else if (conf->ipstatic) { re = rs = ntohl(an->iaddr)+1; re += (ntohs(conf->ipstatic)-1); printf("\tIP static address range: %s", inet_ntoa(htonl(rs))); printf(" %s\n",inet_ntoa(htonl(re))); } else { printf("\tIP static address range: empty\n"); re = ntohl(an->iaddr); } if (conf->ipdynamic) { re = rs = re+1; re += (ntohs(conf->ipdynamic)-1); printf("\tIP dynamic address range: %s", inet_ntoa(htonl(rs))); printf(" %s\n",inet_ntoa(htonl(re))); } else { printf("\tIP dynamic address range: empty\n"); re = ntohl(an->iaddr); } #endif printf("\tKbox interfaces:\n"); printf("\t\tlocaltalk: %s zone %s\n", netstring(conf->atneta), pzoneof(conf->atneta)); printf("\t\tKIP: %s zone %s\n", netstring(conf->atnete), pzoneof(conf->atnete)); if (conf->anetet) { printf("\t\tEtherTalk: %s zone %s\n", netstring(conf->anetet), pzoneof(conf->anetet)); } } } } /* * Build arouteTuple's into area provided by caller. * Return byte count of tuples deposited. */ buildart(at, maxsize) register struct arouteTuple *at; int maxsize; { register struct anets *an; register n, size; size = 0; for (an = &anets[0], n = 0 ; n < nanets ; an++, n++, at++) { size += sizeof *at; at->node = an->iaddr; at->net = an->net; at->flags = an->flags; at->hops = 0; /* start at one - incremented in gateway */ } log("art build: %d entries, %d maximum", size/(sizeof(struct arouteTuple)), maxsize/(sizeof(struct arouteTuple))); if (size > maxsize) log("art build: routing table too big!!"); if (size > (maxsize - 10) ) log("art build: routing table size %d is near maximum of %d", size, maxsize ); return (size); } #define MAXZ 32 /* * Build zones structure to be returned by aaZONE. */ buildzones(az, azlen) char *az; int azlen; { char zname[MAXZ][33]; int nzname = 0; char netzone[NANETS]; register i, iz, n; register char *cp; int zonenamelen = 0; /* make a pass thru anets, finding all unique zone names. */ for (i = 0 ; i < nanets ; i++) { for (iz = 0 ; iz < nzname ; iz++) if (strcmp(anets[i].zone, zname[iz]) == 0) goto found; /* not found, make a new name */ strcpy(zname[iz], anets[i].zone); zonenamelen += strlen(zname[iz]) + 1; netzone[i] = iz; nzname++; continue; /* found it, note the zname index */ found: netzone[i] = iz; } /* * Build structure to send to gateway. Looks like: * net# net# ... 0 zonename * net# net# ... 0 zonename * 0xFFFF. */ cp = az; for (iz = 0 ; iz < nzname ; iz++) { for (i = 0 ; i < nanets ; i++) { if (netzone[i] != iz) continue; /* anets[].net has been swapped by readtab */ *cp++ = (ntohs(anets[i].net) >> 8); *cp++ = ntohs(anets[i].net); } *cp++ = 0; *cp++ = 0; *cp++ = n = strlen(zname[iz]); bcopy(zname[iz], cp, n); cp += n; } *cp++ = 0xFF; *cp++ = 0xFF; n = cp - az; /* length of table */ if (n > sizeof(azones)) { log("buildzones: ZIP table too large"); log("buildzones: don't worry if you are using a KIP later than 1/88"); } else if (n > (sizeof(azones)-10)) log("buildzones: ZIP table size %d approaching maximum of %d", n, sizeof(azones)); log("zone names take %d bytes in gateway"); return (n); } /* * Send aaRESTART or aaROUTEI to all gateways. */ sendall(sig) { register struct anets *an; register n; int trys, count, rcount; fd_set fds; struct sockaddr_in tsin; tsin = sin; log("sendall(%s)", sig == aaRESTART ? "aaRESTART" : "aaROUTEI"); aas.magic = htonl(aaMagic); /* setup send packet */ aas.type = sig; aas.flags = 0; if (sig == aaROUTEI) { bcopy(aroutes, aas.stuff, arouteslen); count = arouteslen; } else { count = 0; } aas.count = htons(count); count += aaconfMinSize; /* * send to each kbox in the table. */ for (an = &anets[0], n = 0 ; n < nanets ; an++, n++) { if ((an->flags & arouteKbox) == 0 || (an->flags & arouteEtalk)) continue; trys = 0; tsin.sin_addr.s_addr = an->iaddr; sendto(s, (caddr_t)&aas, count, 0, &tsin, sizeof tsin); /* * receive until we get a good reply or timeout. */ for (;;) { FD_ZERO(&fds); FD_SET(s, &fds); tvwait.tv_sec = 2; /* select waits 2 seconds */ tvwait.tv_usec = 0; if (select(NFDBITS, &fds, 0, 0, &tvwait) != 1) { /* timeout */ if (++trys < 4) { sendto(s, (caddr_t)&aas, count, 0, &tsin, sizeof tsin); continue; } log("no response from %s", inet_ntoa(an->iaddr)); break; } fsinlen = sizeof fsin; rcount = recvfrom(s, (caddr_t)&aa, sizeof aa, 0, (caddr_t)&fsin, &fsinlen); if (rcount < 0) { if (errno == EINTR) continue; log("recv failed"); exit(1); } if (rcount < aaconfMinSize || ntohl(aa.magic) != aaMagic) continue; if (aa.ipaddr != an->iaddr) { sendreply(); continue; } /* our request got thru! */ sendreply(); break; } } log("sendall(%s) complete",sig==aaRESTART ? "aaRESTART" : "aaROUTEI"); } /* * check over configurations * */ checkconfigs() { int i; struct anets *an; struct conf *cp; int rangestart = 0; int rangeconflict = 0; int badrange = 0; for (an = anets, i = 0; i < nanets; i++, an++) { if (an->confsize >= sizeof(struct conf)) { cp = (struct conf *)an->conf; if (!cp->startddpWKSUnix) { cp->startddpWKSUnix = htons(defddpWKSUnix); if (rangestart) { if (rangestart != cp->startddpWKSUnix) rangeconflict = 1; } else rangestart = cp->startddpWKSUnix; } else { if (rangestart) { if (rangestart != cp->startddpWKSUnix) rangeconflict = 1; } else rangestart = cp->startddpWKSUnix; } } } rangestart = ntohs(rangestart); if (rangeconflict) log("Conflict in UDP WKS range start!"); else if (rangestart != 200 && rangestart != defddpWKSUnix) { log("WARNING - UDP WKS range start %d is non-standard", ntohs(rangestart)); } } /* * Read atalkatab database file. Avoid rereading the file if the * write date hasnt changed since the last time we read it. */ readtab() { struct stat sbuf1, sbuf; register char *sp, *cpp; int v; register i; char st[128], *cp; register struct anets *an; iaddr_t iaddr; if (fp == 0) { if ((fp = fopen(atalkatab, "r")) == NULL) { log("can't open %s", atalkatab); exit(1); } } if (fstat(fileno(fp), &sbuf1) < 0) goto reopen; if (stat(atalkatab, &sbuf) < 0) goto reopen; if (sbuf1.st_dev == sbuf.st_dev && /* different... */ sbuf1.st_ino == sbuf.st_ino && /* ...file */ sbuf1.st_size == size && /* nec? */ sbuf.st_size == size && sbuf1.st_mtime == modtime && /* nec? */ sbuf.st_mtime == modtime) return; reopen: if (fp) fclose(fp); if ((fp = fopen(atalkatab, "r")) == NULL) { log("can't open %s", atalkatab); exit(1); } fstat(fileno(fp), &sbuf); log("(re)reading %s", atalkatab); modtime = sbuf.st_mtime; size = sbuf.st_size; nanets = 0; an = &anets[-1]; linenum = 0; /* * read and parse each line in the file. */ for (;;) { if (fgets(line, sizeof line, fp) == NULL) break; /* done */ if ((i = strlen(line))) line[i-1] = 0; /* remove trailing newline */ linep = line; linenum++; if (line[0] == '#' || line[0] == 0) continue; /* skip comment lines */ if (line[0] == ' ' || line[0] == '\t') goto confinfo; /* * lines not beginning with white space * represent a new net # */ if (++nanets > NANETS) { log("'anets' table length exceeded"); exit(1); } an++; cp = an->conf; /* store following lines here */ an->confsize = 0; getfield(st, sizeof st); an->net = htons(getashort(st)); getfield(st, sizeof st); i = 0; /* parse flags */ for (cpp = st ; *cpp ; cpp++) { if (isupper(*cpp)) *cpp = tolower(*cpp); switch (*cpp) { case 'c': i |= arouteCore; break; case 'k': i |= arouteKbox; break; case 'h': i |= arouteHost; break; case 'n': i |= arouteNet; break; case 'e': i |= (arouteEtalk|arouteKbox); break; case '0': case '1': case '2': case '3': i |= (*cpp - '0'); break; default: log("bad switch %s, linenum %d", st, linenum); } } an->flags = i; getfield(st, sizeof st); an->iaddr = getiaddr(st); getfield(an->zone, sizeof(an->zone)); continue; confinfo: /* * lines beginning with white space * are configuration data for gateway. */ for (;;) { /* for each field in line */ int len; getfield(st, sizeof st); sp = st; if (*sp == 0) break; if (isupper(*sp)) *sp = tolower(*sp); switch (*sp++) { case '%': /* escape code, one of 'n' */ if (isupper(*sp)) *sp = tolower(*sp); switch (*sp++) { int flag; case 'n': /* decide which type of network based on */ /* the offset in the config structure */ if (cp - an->conf == (char *)&conf_proto.atnete-(char *)&conf_proto) flag = arouteNet; else if (cp - an->conf == (char*)&conf_proto.anetet-(char*)&conf_proto) flag = arouteKbox|arouteEtalk; else if (cp - an->conf == (char*)&conf_proto.atneta-(char*)&conf_proto) flag = arouteKbox; else { log("%%N at unexpected offset %d, line %d\n", cp - an->conf, linenum); flag = arouteKbox; } if ((*(short *)cp = getanet(flag, an->iaddr)) == 0) log("%%N not set, line %d\n", linenum); cp += 2; an->confsize += 2; break; default: log("bad field type %s, linenum %d", st, linenum); break; } break; case 'i': /* IP address name or number */ iaddr = getiaddr(sp); bcopy((caddr_t)&iaddr, cp, sizeof iaddr); cp += sizeof iaddr; an->confsize += sizeof iaddr; break; case 'l': if ((int)cp & 1) goto badalign; *(long *)cp = htonl(atoii(sp)); cp += 4; an->confsize += 4; break; case 's': if ((int)cp & 1) goto badalign; *(short *)cp = htons(getashort(sp)); cp += 2; an->confsize += 2; break; case 'c': *cp = atoii(sp); cp++; an->confsize++; break; case '"': len = strlen(sp) - 1; /* drop trailing " */ bcopy(sp, cp, len); cp += len; *cp++ = 0; len++; an->confsize += len; break; case '\'': /* pascal string */ len = strlen(sp) - 1; /* drop trailing ' */ *cp++ = len; bcopy(sp, cp, len); cp += len; len++; /* skip over length field */ *cp++ = 0; len++; an->confsize += len; break; default: log("bad field type %s, linenum %d", st, linenum); break; } continue; /* get next field in line */ badalign: log("long/short bad alignment %s, linenum %d", st, linenum); break; } /* get next line */ } /* end of file */ checkconfigs(); arouteslen = buildart((struct arouteTuple *)aroutes, sizeof aroutes); azoneslen = buildzones(azones, sizeof azones); } /* * Get next field from 'line' buffer into 'str'. 'linep' is the * pointer to current position. No imbeded spaces are allowed in the * fields; however, an underscore '_' will convert to a space. (To get * a real underscore, double it.) */ getfield(str, len) char *str; { register char *cp = str; register und; for ( ; *linep && (*linep == ' ' || *linep == '\t') ; linep++) ; /* skip spaces/tabs */ if (*linep == 0 || *linep == '#') { *cp = 0; return; } und = 0; len--; /* save a spot for a null */ for ( ; *linep && *linep != ' ' && *linep != '\t' && *linep != '#' ; linep++) { if (*linep == '_') { if (und) { und = 0; cp--; len++; } else { und++; *linep = ' '; } } else { und = 0; } *cp++ = *linep; if (--len <= 0) { *cp = 0; log("string truncated: %s, linenum %d", str, linenum); return; } } *cp = 0; } /* * Ascii to integer, with base check. */ atoii(s) register char *s; { int v; char *c; if (isupper(*s)) *s = tolower(*s); if (*s == 'x' || *s == 'h') { c = "%x"; s++; } else { c = "%d"; } if (sscanf(s, c, &v) != 1) log("bad numeric field %s, linenum %d", s, linenum); return (v); } /* * Get an internet address as a hostname or dot format string. */ getiaddr(st) register char *st; { iaddr_t iaddr; register struct hostent *host; if (isdigit(*st)) { if ((iaddr = inet_addr(st)) == -1 || iaddr == 0) log("bad ipaddress %s, linenum %d", st, linenum); } else { if ((host = gethostbyname(st)) == 0) log("bad hostname %s, linenum %d", st, linenum); bcopy(host->h_addr, (caddr_t)&iaddr, sizeof iaddr); } return (iaddr); } /* * Get a short number or address. */ getashort(st) register char *st; { register char *cp; if ((cp = index(st, '.')) == 0) return (atoii(st)); *cp++ = 0; return ((atoii(st)<<8) | atoii(cp)); } /* * log an error message */ log(fmt, args) char *fmt; { FILE *fp; long time(), tloc; struct tm *tm, *localtime(); if (debug) fp = stderr; else if (scanonly) fp = stdout; else if ((fp = fopen(atalkalog, "a+")) == NULL) return; time(&tloc); tm = localtime(&tloc); fprintf(fp, "%d/%d %02d:%02d ", tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min); _doprnt(fmt, &args, fp); putc('\n', fp); if (fp != stderr && fp != stdout) fclose(fp); } \f /* * getanet - scan through the table so far and find an appletalk network * number. Called from the %x fields of the config structure * * flag field: * arouteNet - match an IP address, scan for a net route that matches addr * arouteKbox - scan for a route using this host * arouteKbox|arouteETalk - scan for an Ethertalk net using this host. * * Limitations: Only one bridge can be configured with a given Ethertalk * network number this way. Network numbers referenced must be defined before * use. */ getanet(flags, ia) iaddr_t ia; { register int i; struct anets *a; /* Scan table in reverse order - slightly more efficent */ for(i = nanets-1; i >= 0; --i) { a = &anets[i]; if ((flags == arouteNet && ((a->flags & arouteNet) != 0 || (a->flags & arouteHost) != 0) && match_net(a->flags, ia, a->iaddr)) || (flags == arouteKbox && (a->flags & arouteKbox|arouteEtalk) == arouteKbox && a->iaddr == ia) || (flags == arouteKbox|arouteEtalk && (a->flags & flags) == flags && a->iaddr == ia)) return(a->net); } log("unable to match appletalk net (%x), line %d\n", flags, linenum); return(0); } /* * match_net - match a network number, using mask field stored in * flags. */ match_net(flags, a1, a2) iaddr_t a1, a2; { return((a1 & node_mask) == (a2 & node_mask)); } char * hostnameof(ipaddr) struct in_addr ipaddr; { struct hostent *host; host = gethostbyaddr(&ipaddr.s_addr, sizeof(ipaddr.s_addr), AF_INET); if (!host) return((char *)inet_ntoa(ipaddr)); return(host->h_name); } zipinput() { u_short buf[1000]; u_short *bp; int icount; int len; u_char *p; char *zn; int zl; struct ZIP zipin; struct ZIP *z; icount = ntohs(aa.count); /* remember incoming count */ bcopy(aa.stuff, &zipin, sizeof(struct ZIP)); if (zipin.command != zipQuery || zipin.count == 0) return(-1); /* get the list of networks */ bcopy(aa.stuff+sizeof(struct ZIP), buf, zipin.count * sizeof(u_short)); bp = buf; z = (struct ZIP *)aa.stuff; z->command = zipReply; z->count = 0; len = sizeof(struct ZIP); for (p = (u_char *)(z+1); len<512&&zipin.count; zipin.count--, bp++) { if ((zn = zoneof(*bp)) == NULL) continue; bcopy(bp, p, sizeof(u_short)); /* copy in network */ p+= sizeof(u_short); /* move along */ len+= sizeof(u_short); /* move along */ zl = *p = strlen(zn); /* get zone length */ p++; /* bounce */ len++; z->count++; bcopy(zn, p, zl); /* copy in zone name */ p += zl; /* bounce p ...*/ len += zl; /* ... and len */ } return(len); }