?? nr3.c
字號:
static int
accept_bc(addr,ifnum)
uint8 *addr;
unsigned ifnum;
{
struct nrnf_tab *fp;
if(Nr_nfmode == NRNF_NOFILTER) /* no filtering in effect */
return 1;
fp = find_nrnf(addr,ifnum); /* look it up */
if((fp != NULL && Nr_nfmode == NRNF_ACCEPT)
|| (fp == NULL && Nr_nfmode == NRNF_REJECT))
return 1;
else
return 0;
}
/* receive and process node broadcasts. */
void
nr_nodercv(
struct iface *iface,
uint8 *source,
struct mbuf **bpp
){
register int ifnum;
char bcalias[AXALEN];
struct nr3dest ds;
/* First, see if this is even a net/rom interface: */
for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
if(iface == Nrifaces[ifnum].iface)
break;
if(ifnum == Nr_numiface){ /* not in the interface table */
free_p(bpp);
return;
}
if(!accept_bc(source,ifnum)){ /* check against filter */
free_p(bpp);
return;
}
/* See if it has a routing broadcast signature: */
if(PULLCHAR(bpp) != NR3NODESIG){
free_p(bpp);
return;
}
/* now try to get the alias */
if(pullup(bpp,bcalias,ALEN) < ALEN){
free_p(bpp);
return;
}
bcalias[ALEN] = '\0'; /* null terminate */
/* enter the neighbor into our routing table */
if(nr_routeadd(bcalias,source,ifnum,Nrifaces[ifnum].quality,
source, 0, 0) == -1){
free_p(bpp);
return;
}
/* we've digested the header; now digest the actual */
/* routing information */
while(ntohnrdest(&ds,bpp) != -1){
/* ignore routes to me! */
if(ismycall(ds.dest))
continue;
/* ignore routes below the minimum quality threshhold */
if(ds.quality < Nr_autofloor)
continue;
/* set loopback paths to 0 quality */
if(ismycall(ds.neighbor))
ds.quality = 0;
else
ds.quality = ((ds.quality * Nrifaces[ifnum].quality + 128)
/ 256) & 0xff;
if(nr_routeadd(ds.alias,ds.dest,ifnum,ds.quality,source,0,0)
== -1)
break;
}
free_p(bpp); /* This will free the mbuf if anything fails above */
}
/* The following are utilities for manipulating the routing table */
/* hash function for callsigns. Look familiar? */
uint16
nrhash(s)
uint8 *s;
{
register uint8 x;
register int i;
x = 0;
for(i = ALEN; i !=0; i--)
x ^= *s++ & 0xfe;
x ^= *s & SSID;
return (uint16)(x % NRNUMCHAINS);
}
/* Find a neighbor table entry. Neighbors are determined by
* their callsign and the interface number. This takes care
* of the case where the same switch or hosts uses the same
* callsign on two different channels. This isn't done by
* net/rom, but it might be done by stations running *our*
* software.
*/
static struct nrnbr_tab *
find_nrnbr(addr,ifnum)
register uint8 *addr;
unsigned ifnum;
{
uint16 hashval;
register struct nrnbr_tab *np;
/* Find appropriate hash chain */
hashval = nrhash(addr);
/* search hash chain */
for(np = Nrnbr_tab[hashval]; np != NULL; np = np->next){
/* convert first in list to ax25 address format */
if(addreq(np->call,addr) && np->iface == ifnum){
return np;
}
}
return NULL;
}
/* Find a route table entry */
struct nrroute_tab *
find_nrroute(addr)
register uint8 *addr;
{
uint16 hashval;
register struct nrroute_tab *rp;
/* Find appropriate hash chain */
hashval = nrhash(addr);
/* search hash chain */
for(rp = Nrroute_tab[hashval]; rp != NULL; rp = rp->next){
if(addreq(rp->call,addr)){
return rp;
}
}
return NULL;
}
/* Try to find the AX.25 address of a node with the given alias. Return */
/* a pointer to the AX.25 address if found, otherwise NULL. The alias */
/* should be a six character, blank-padded, upper-case string. */
uint8 *
find_nralias(alias)
char *alias;
{
int i;
register struct nrroute_tab *rp;
/* Since the route entries are hashed by ax.25 address, we'll */
/* have to search all the chains */
for(i = 0; i < NRNUMCHAINS; i++)
for(rp = Nrroute_tab[i]; rp != NULL; rp = rp->next)
if(strncmp(alias, rp->alias, 6) == 0)
return rp->call;
/* If we get to here, we're out of luck */
return NULL;
}
/* Find a binding in a list by its neighbor structure's address */
static struct nr_bind *
find_binding(list,neighbor)
struct nr_bind *list;
register struct nrnbr_tab *neighbor;
{
register struct nr_bind *bp;
for(bp = list; bp != NULL; bp = bp->next)
if(bp->via == neighbor)
return bp;
return NULL;
}
/* Find the worst quality non-permanent binding in a list */
static
struct nr_bind *
find_worst(list)
struct nr_bind *list;
{
register struct nr_bind *bp;
struct nr_bind *worst = NULL;
unsigned minqual = 1000; /* infinity */
for(bp = list; bp != NULL; bp = bp->next)
if(!(bp->flags & NRB_PERMANENT) && bp->quality < minqual){
worst = bp;
minqual = bp->quality;
}
return worst;
}
/* Find the best binding of any sort in a list. If obso is 1,
* include entries below the obsolescence threshhold in the
* search (used when this is called for routing broadcasts).
* If it is 0, routes below the threshhold are treated as
* though they don't exist.
*/
static
struct nr_bind *
find_best(list,obso)
struct nr_bind *list;
unsigned obso;
{
register struct nr_bind *bp;
struct nr_bind *best = NULL;
int maxqual = -1; /* negative infinity */
for(bp = list; bp != NULL; bp = bp->next)
if((int)bp->quality > maxqual)
if(obso || bp->obsocnt >= Obso_minbc){
best = bp;
maxqual = bp->quality;
}
return best;
}
/* Add a route to the net/rom routing table */
int
nr_routeadd(alias,dest,ifnum,quality,neighbor,permanent,record)
char *alias; /* net/rom node alias, blank-padded and */
/* null-terminated */
uint8 *dest; /* destination node callsign */
unsigned ifnum; /* net/rom interface number */
unsigned quality; /* route quality */
uint8 *neighbor; /* neighbor node + 2 digis (max) in arp format */
unsigned permanent; /* 1 if route is permanent (hand-entered) */
unsigned record; /* 1 if route is a "record route" */
{
struct nrroute_tab *rp;
struct nr_bind *bp;
struct nrnbr_tab *np;
uint16 rhash, nhash;
/* See if a routing table entry exists for this destination */
if((rp = find_nrroute(dest)) == NULL){
rp = (struct nrroute_tab *)callocw(1,sizeof(struct nrroute_tab));
/* create a new route table entry */
strncpy(rp->alias,alias,6);
memcpy(rp->call,dest,AXALEN);
rhash = nrhash(dest);
rp->next = Nrroute_tab[rhash];
if(rp->next != NULL)
rp->next->prev = rp;
Nrroute_tab[rhash] = rp; /* link at head of hash chain */
} else if(!record){
strncpy(rp->alias,alias,6); /* update the alias */
}
/* See if an entry exists for this neighbor */
if((np = find_nrnbr(neighbor,ifnum)) == NULL){
np = (struct nrnbr_tab *)callocw(1,sizeof(struct nrnbr_tab));
/* create a new neighbor entry */
memcpy(np->call,neighbor,AXALEN);
np->iface = ifnum;
nhash = nrhash(neighbor);
np->next = Nrnbr_tab[nhash];
if(np->next != NULL)
np->next->prev = np;
Nrnbr_tab[nhash] = np;
} else if(permanent){ /* force this path to the neighbor */
memcpy(np->call,neighbor,AXALEN);
}
/* See if there is a binding between the dest and neighbor */
if((bp = find_binding(rp->routes,np)) == NULL){
bp = (struct nr_bind *)callocw(1,sizeof(struct nr_bind));
/* create a new binding and link it in */
bp->via = np; /* goes via this neighbor */
bp->next = rp->routes; /* link into binding chain */
if(bp->next != NULL)
bp->next->prev = bp;
rp->routes = bp;
rp->num_routes++; /* bump route count */
np->refcnt++; /* bump neighbor ref count */
bp->quality = quality;
bp->obsocnt = Obso_init; /* use initial value */
if(permanent)
bp->flags |= NRB_PERMANENT;
else if(record) /* notice permanent overrides record! */
bp->flags |= NRB_RECORDED;
} else {
if(permanent){ /* permanent request trumps all */
bp->quality = quality;
bp->obsocnt = Obso_init;
bp->flags |= NRB_PERMANENT;
bp->flags &= ~NRB_RECORDED; /* perm is not recorded */
} else if(!(bp->flags & NRB_PERMANENT)){ /* not permanent */
if(record){ /* came from nr_route */
if(bp->flags & NRB_RECORDED){ /* no mod non-rec bindings */
bp->quality = quality;
bp->obsocnt = Obso_init; /* freshen recorded routes */
}
} else { /* came from a routing broadcast */
bp->quality = quality;
bp->obsocnt = Obso_init;
bp->flags &= ~NRB_RECORDED; /* no longer a recorded route */
}
}
}
/* Now, check to see if we have too many bindings, and drop */
/* the worst if we do */
if(rp->num_routes > Nr_maxroutes){
/* since find_worst never returns permanent entries, the */
/* limitation on number of routes is circumvented for */
/* permanent routes */
if((bp = find_worst(rp->routes)) != NULL){
nr_routedrop(dest,bp->via->call,bp->via->iface);
}
}
return 0;
}
/* Drop a route to dest via neighbor */
int
nr_routedrop(dest,neighbor,ifnum)
uint8 *dest, *neighbor;
unsigned ifnum;
{
register struct nrroute_tab *rp;
register struct nrnbr_tab *np;
register struct nr_bind *bp;
if((rp = find_nrroute(dest)) == NULL)
return -1;
if((np = find_nrnbr(neighbor,ifnum)) == NULL)
return -1;
if((bp = find_binding(rp->routes,np)) == NULL)
return -1;
/* drop the binding first */
if(bp->next != NULL)
bp->next->prev = bp->prev;
if(bp->prev != NULL)
bp->prev->next = bp->next;
else
rp->routes = bp->next;
free(bp);
rp->num_routes--; /* decrement the number of bindings */
np->refcnt--; /* and the number of neighbor references */
/* now see if we should drop the route table entry */
if(rp->num_routes == 0){
if(rp->next != NULL)
rp->next->prev = rp->prev;
if(rp->prev != NULL)
rp->prev->next = rp->next;
else
Nrroute_tab[nrhash(dest)] = rp->next;
free(rp);
}
/* and check to see if this neighbor can be dropped */
if(np->refcnt == 0){
if(np->next != NULL)
np->next->prev = np->prev;
if(np->prev != NULL)
np->prev->next = np->next;
else
Nrnbr_tab[nrhash(neighbor)] = np->next;
free(np);
}
return 0;
}
#ifdef notused
/* Find the best neighbor for destination dest, in arp format */
static uint8 *
nr_getroute(dest)
uint8 *dest;
{
register struct nrroute_tab *rp;
register struct nr_bind *bp;
if((rp = find_nrroute(dest)) == NULL)
return NULL;
if((bp = find_best(rp->routes,1)) == NULL) /* shouldn't happen! */
return NULL;
return bp->via->call;
}
#endif /* notused */
/* Find an entry in the filter table */
static struct nrnf_tab *
find_nrnf(addr,ifnum)
register uint8 *addr;
unsigned ifnum;
{
uint16 hashval;
register struct nrnf_tab *fp;
/* Find appropriate hash chain */
hashval = nrhash(addr);
/* search hash chain */
for(fp = Nrnf_tab[hashval]; fp != NULL; fp = fp->next){
if(addreq(fp->neighbor,addr) && fp->iface == ifnum){
return fp;
}
}
return NULL;
}
/* Add an entry to the filter table. Return 0 on success,
* -1 on failure
*/
int
nr_nfadd(addr,ifnum)
uint8 *addr;
unsigned ifnum;
{
struct nrnf_tab *fp;
uint16 hashval;
if(find_nrnf(addr,ifnum) != NULL)
return 0; /* already there; it's a no-op */
fp = (struct nrnf_tab *)callocw(1,sizeof(struct nrnf_tab));
hashval = nrhash(addr);
memcpy(fp->neighbor,addr,AXALEN);
fp->iface = ifnum;
fp->next = Nrnf_tab[hashval];
if(fp->next != NULL)
fp->next->prev = fp;
Nrnf_tab[hashval] = fp;
return 0;
}
/* Drop a neighbor from the filter table. Returns 0 on success, -1
* on failure.
*/
int
nr_nfdrop(addr,ifnum)
uint8 *addr;
unsigned ifnum;
{
struct nrnf_tab *fp;
if((fp = find_nrnf(addr,ifnum)) == NULL)
return -1; /* not in the table */
if(fp->next != NULL)
fp->next->prev = fp->prev;
if(fp->prev != NULL)
fp->prev->next = fp->next;
else
Nrnf_tab[nrhash(addr)] = fp->next;
free(fp);
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -