nr3.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:25k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* net/rom level 3 low level processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "iface.h"
  10. #include "pktdrvr.h"
  11. #include "netuser.h"
  12. #include "arp.h"
  13. #include "slip.h"
  14. #include "ax25.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "lapb.h"
  18. #include "socket.h"
  19. #include "trace.h"
  20. #include "ip.h"
  21. #include "commands.h"
  22. static int accept_bc(uint8 *addr,unsigned ifnum);
  23. static struct nr_bind *find_best(struct nr_bind *list,unsigned obso);
  24. static struct nr_bind *find_binding(struct nr_bind *list,struct nrnbr_tab *neighbor);
  25. static struct nrnbr_tab *find_nrnbr(uint8 *, unsigned);
  26. static struct nrnf_tab *find_nrnf(uint8 *, unsigned);
  27. static struct nr_bind *find_worst(struct nr_bind *list);
  28. static int ismycall(uint8 *addr);
  29. #ifdef notdef
  30. static uint8 *nr_getroute(uint8 *);
  31. #endif
  32. static struct raw_nr *Raw_nr;
  33. /* Nodes message broadcast address: "NODES" in shifted ASCII */
  34. uint8 Nr_nodebc[AXALEN] = {
  35. 'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1,
  36. ('0'<<1) | E
  37. };
  38. struct nriface Nrifaces[NRNUMIFACE];
  39. unsigned Nr_numiface;
  40. struct nrnbr_tab *Nrnbr_tab[NRNUMCHAINS];
  41. struct nrroute_tab *Nrroute_tab[NRNUMCHAINS];
  42. struct nrnf_tab *Nrnf_tab[NRNUMCHAINS];
  43. unsigned Nr_nfmode = NRNF_NOFILTER;
  44. unsigned short Nr_ttl = 64;
  45. static unsigned Obso_init = 6;
  46. static unsigned Obso_minbc = 5;
  47. static unsigned Nr_maxroutes = 5;
  48. static unsigned Nr_autofloor = 1;
  49. int Nr_verbose = 0;
  50. struct iface *Nr_iface;
  51. /* send a NET/ROM layer 3 datagram */
  52. void
  53. nr3output(
  54. uint8 *dest,
  55. struct mbuf **data
  56. ){
  57. struct nr3hdr n3hdr;
  58. struct mbuf *n3b;
  59. memcpy(n3hdr.dest,dest,AXALEN); /* copy destination field */
  60. n3hdr.ttl = Nr_ttl; /* time to live from initializer parm */
  61. if((n3b = htonnr3(&n3hdr)) == NULL){
  62. free_p(data);
  63. return;
  64. }
  65. append(&n3b, data);
  66. /* The null interface indicates that the packet needs to have */
  67. /* an appropriate source address inserted by nr_route */
  68. nr_route(&n3b,NULL);
  69. }
  70. /* send IP datagrams across a net/rom network connection */
  71. int
  72. nr_send(
  73. struct mbuf **bpp,
  74. struct iface *iface,
  75. int32 gateway,
  76. uint8 tos
  77. ){
  78. struct arp_tab *arp;
  79. dump(iface,IF_TRACE_OUT,*bpp);
  80. iface->rawsndcnt++;
  81. iface->lastsent = secclock();
  82. if((arp = arp_lookup(ARP_NETROM,gateway)) == NULL){
  83. free_p(bpp); /* drop the packet if no route */
  84. return -1;
  85. }
  86. nr_sendraw(arp->hw_addr, NRPROTO_IP, NRPROTO_IP, bpp);
  87. return 0;
  88. }
  89. /* Send arbitrary protocol data on top of a NET/ROM connection */
  90. void
  91. nr_sendraw(
  92. uint8 *dest,
  93. unsigned family,
  94. unsigned proto,
  95. struct mbuf **data
  96. ){
  97. struct mbuf *pbp;
  98. struct nr4hdr n4hdr;
  99. /* Create a "network extension" transport header */
  100. n4hdr.opcode = NR4OPPID;
  101. n4hdr.u.pid.family = family;
  102. n4hdr.u.pid.proto = proto;
  103. if((pbp = htonnr4(&n4hdr)) == NULL){
  104. free_p(data);
  105. return;
  106. }
  107. append(&pbp,data); /* Append the data to that */
  108. nr3output(dest, &pbp); /* and pass off to level 3 code */
  109. }
  110. /* Arrange for receipt of raw NET/ROM datagrams */
  111. struct raw_nr *
  112. raw_nr(protocol)
  113. uint8 protocol;
  114. {
  115. register struct raw_nr *rp;
  116. rp = (struct raw_nr *)callocw(1,sizeof(struct raw_nr));
  117. rp->protocol = protocol;
  118. rp->next = Raw_nr;
  119. if(rp->next != NULL)
  120. rp->next->prev = rp;
  121. Raw_nr = rp;
  122. return rp;
  123. }
  124. /* Free a raw NET/ROM descriptor */
  125. void
  126. del_rnr(rpp)
  127. struct raw_nr *rpp;
  128. {
  129. register struct raw_nr *rp;
  130. /* Do sanity check on arg */
  131. for(rp = Raw_nr;rp != NULL;rp = rp->next)
  132. if(rp == rpp)
  133. break;
  134. if(rp == NULL)
  135. return; /* Doesn't exist */
  136. /* Unlink */
  137. if(rp->prev != NULL)
  138. rp->prev->next = rp->next;
  139. else
  140. Raw_nr = rp->next;
  141. if(rp->next != NULL)
  142. rp->next->prev = rp->prev;
  143. /* Free resources */
  144. free_q(&rp->rcvq);
  145. free(rp);
  146. }
  147. /* Figure out if a call is assigned to one of my net/rom
  148.  * interfaces.
  149.  */
  150. static int
  151. ismycall(addr)
  152. uint8 *addr;
  153. {
  154. register int i;
  155. int found = 0;
  156. for(i = 0; i < Nr_numiface; i++)
  157. if(addreq(Nrifaces[i].iface->hwaddr,addr)){
  158. found = 1;
  159. break;
  160. }
  161. return found;
  162. }
  163. /* Route net/rom network layer packets.
  164.  */
  165. void
  166. nr_route(bpp, iaxp)
  167. struct mbuf **bpp; /* network packet */
  168. struct ax25_cb *iaxp; /* incoming ax25 control block */
  169. {
  170. struct nr3hdr n3hdr;
  171. struct nr4hdr n4hdr;
  172. struct ax25_cb *axp;
  173. struct mbuf *hbp, *pbp;
  174. struct raw_nr *rnr;
  175. register struct nrnbr_tab *np;
  176. register struct nrroute_tab *rp;
  177. register struct nr_bind *bindp;
  178. struct iface *iface;
  179. unsigned ifnum;
  180. if(ntohnr3(&n3hdr,bpp) == -1){
  181. free_p(bpp);
  182. return;
  183. }
  184. /* If this isn't an internally generated network packet,
  185.  * give the router a chance to record a route back to the
  186.  * sender, in case they aren't in the local node's routing
  187.  * table yet.
  188.  */
  189. if(iaxp != NULL && ax_lookup(iaxp->remote) != NULL){
  190. /* find the interface number */
  191. for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  192. if(iaxp->iface == Nrifaces[ifnum].iface)
  193. break;
  194. if(ifnum == Nr_numiface){ /* Not a net/rom interface! */
  195. free_p(bpp);
  196. return;
  197. }
  198. /* Add (possibly) a zero-quality recorded route via */
  199. /* the neighbor from which this packet was received */
  200. /* Note that this doesn't work with digipeated neighbors. */
  201. (void) nr_routeadd("      ",n3hdr.source,ifnum,0,iaxp->remote,0,1);
  202. }
  203. /* A packet from me, to me, can only be one thing:
  204.  * a horrible routing loop.  This will probably result
  205.  * from a bad manual ARP entry, but we should fix these
  206.  * obscure errors as we find them.
  207.  */
  208. if(ismycall(n3hdr.dest)){
  209. /* Toss if from me, or if we can't read the header */
  210. if(iaxp == NULL || ntohnr4(&n4hdr,bpp) == -1){
  211. free_p(bpp);
  212. } else if((n4hdr.opcode & NR4OPCODE) == NR4OPPID){
  213. for(rnr = Raw_nr;rnr!=NULL;rnr = rnr->next){
  214. if(rnr->protocol!=n4hdr.u.pid.family ||
  215.  rnr->protocol != n4hdr.u.pid.proto)
  216. continue;
  217. /* Duplicate the data portion, and put the
  218.  * level 3 header back on
  219.  */
  220. dup_p(&pbp,*bpp,0,len_p(*bpp));
  221. if(pbp != NULL &&
  222.  (hbp = htonnr3(&n3hdr)) != NULL){
  223. append(&hbp,&pbp);
  224. enqueue(&rnr->rcvq,&hbp);
  225. } else {
  226. free_p(&pbp);
  227. free_p(&hbp);
  228. }
  229. }
  230. /* IP does not use a NET/ROM level 3 socket */
  231. if(n4hdr.u.pid.family == NRPROTO_IP
  232.  && n4hdr.u.pid.proto == NRPROTO_IP)
  233. ip_route(iaxp->iface,bpp,0);
  234. else /* we don't do this proto */
  235. free_p(bpp);
  236. } else {
  237. /* Must be net/rom transport: */
  238. nr4input(&n4hdr,bpp);
  239. }
  240. return;
  241. }
  242. if((rp = find_nrroute(n3hdr.dest)) == NULL){
  243. /* no route, drop the packet */
  244. free_p(bpp);
  245. return;
  246. }
  247. if((bindp = find_best(rp->routes,1)) == NULL){
  248. /* This shouldn't happen yet, but might if we add */
  249. /* dead route detection */
  250. free_p(bpp);
  251. return;
  252. }
  253. np = bindp->via;
  254. iface = Nrifaces[np->iface].iface;
  255. /* Now check to see if iaxp is null.  That is */
  256. /* a signal that the packet originates here, */
  257. /* so we need to insert the callsign of the appropriate  */
  258. /* interface */
  259. if(iaxp == NULL)
  260. memcpy(n3hdr.source,iface->hwaddr,AXALEN);
  261. /* Make sure there is a connection to the neighbor */
  262. if((axp = find_ax25(np->call)) == NULL ||
  263. (axp->state != LAPB_CONNECTED && axp->state != LAPB_RECOVERY)){
  264. /* Open a new connection or reinitialize old one */
  265. /* hwaddr has been advanced to point to neighbor + digis */
  266. axp = open_ax25(iface,iface->hwaddr,np->call, AX_ACTIVE, Axwindow, s_arcall, s_atcall, s_ascall,-1);
  267. if(axp == NULL){
  268. free_p(bpp);
  269. return;
  270. }
  271. }
  272. if(--n3hdr.ttl == 0){ /* the packet's time to live is over! */
  273. free_p(bpp);
  274. return;
  275. }
  276. /* now format network header */
  277. if((pbp = htonnr3(&n3hdr)) == NULL){
  278. free_p(bpp);
  279. return;
  280. }
  281. append(&pbp,bpp); /* append data to header */
  282. /* put AX.25 PID on front */
  283. pushdown(&pbp,NULL,1);
  284. pbp->data[0] = PID_NETROM;
  285. if((pbp = segmenter(&pbp,axp->paclen)) == NULL){
  286. free_p(&pbp);
  287. return;
  288. }
  289. send_ax25(axp,&pbp,-1); /* pass it off to ax25 code */
  290. }
  291. /* Perform a nodes broadcast on interface # ifno in the net/rom
  292.  * interface table.
  293.  */
  294. void
  295. nr_bcnodes(ifno)
  296. unsigned ifno;
  297. {
  298. struct mbuf *hbp, *dbp, *savehdr;
  299. struct nrroute_tab *rp;
  300. struct nrnbr_tab *np;
  301. struct nr_bind * bp;
  302. struct nr3dest nrdest;
  303. int i, didsend = 0, numdest = 0;
  304. register uint8 *cp;
  305. struct iface *axif = Nrifaces[ifno].iface;
  306. /* prepare the header */
  307. if((hbp = alloc_mbuf(NR3NODEHL)) == NULL)
  308. return;
  309. hbp->cnt = NR3NODEHL;
  310. *hbp->data = NR3NODESIG;
  311. memcpy(hbp->data+1,Nrifaces[ifno].alias,ALEN);
  312. /* Some people don't want to advertise any routes; they
  313.  * just want to be a terminal node.  In that case we just
  314.  * want to send our call and alias and be done with it.
  315.  */
  316. if(!Nr_verbose){
  317. (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  318. PID_NETROM, &hbp); /* send it */
  319. return;
  320. }
  321. /* make a copy of the header in case we need to send more than */
  322. /* one packet */
  323. savehdr = copy_p(hbp,NR3NODEHL);
  324. /* now scan through the routing table, finding the best routes */
  325. /* and their neighbors.  create destination subpackets and append */
  326. /* them to the header */
  327. for(i = 0; i < NRNUMCHAINS; i++){
  328. for(rp = Nrroute_tab[i]; rp != NULL; rp = rp->next){
  329. /* look for best, non-obsolescent route */
  330. if((bp = find_best(rp->routes,0)) == NULL)
  331. continue; /* no non-obsolescent routes found */
  332. if(bp->quality == 0) /* this is a loopback route */
  333. continue; /* we never broadcast these */
  334. np = bp->via;
  335. /* insert best neighbor */
  336. memcpy(nrdest.neighbor,np->call,AXALEN);
  337. /* insert destination from route table */
  338. memcpy(nrdest.dest,rp->call,AXALEN);
  339. /* insert alias from route table */
  340. strcpy(nrdest.alias,rp->alias);
  341. /* insert quality from binding */
  342. nrdest.quality = bp->quality;
  343. /* create a network format destination subpacket */
  344. if((dbp = htonnrdest(&nrdest)) == NULL){
  345. free_p(&hbp); /* drop the whole idea ... */
  346. free_p(&savehdr);
  347. return;
  348. }
  349. /* we now have a partially filled packet */
  350. didsend = 0;
  351. append(&hbp,&dbp);/* append to header and others */
  352. /* see if we have appended as many destinations
  353.  * as we can fit into a single broadcast.  If we
  354.  * have, go ahead and send them out.
  355.  */
  356. if(++numdest == NRDESTPERPACK){ /* filled it up */
  357. /* indicate that we did broadcast */
  358. didsend = 1;
  359. /* reset the destination counter */
  360. numdest = 0;
  361. (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  362.  PID_NETROM,&hbp); /* send it */
  363. /* new header */
  364. hbp = copy_p(savehdr,NR3NODEHL);
  365. }
  366. }
  367. }
  368. /* Now, here is something totally weird.  If our interfaces */
  369. /* have different callsigns than this one, advertise a very */
  370. /* high quality route to them.  Is this a good idea?  I don't */
  371. /* know.  However, it allows us to simulate a bunch of net/roms */
  372. /* hooked together with a diode matrix coupler. */
  373. for(i = 0; i < Nr_numiface; i++){
  374. if(i == ifno)
  375. continue; /* don't bother with ours */
  376. cp = Nrifaces[i].iface->hwaddr;
  377. if(!addreq((uint8 *)axif->hwaddr,cp)){
  378. /* both destination and neighbor address */
  379. memcpy(nrdest.dest,cp,AXALEN);
  380. memcpy(nrdest.neighbor,cp,AXALEN);
  381. /* alias of the interface */
  382. strcpy(nrdest.alias,Nrifaces[i].alias);
  383. /* and the very highest quality */
  384. nrdest.quality = 255;
  385. /* create a network format destination subpacket */
  386. if((dbp = htonnrdest(&nrdest)) == NULL){
  387. free_p(&hbp); /* drop the whole idea ... */
  388. free_p(&savehdr);
  389. return;
  390. }
  391. /* we now have a partially filled packet */
  392. didsend = 0;
  393. /* append to header and others */
  394. append(&hbp,&dbp);
  395. if(++numdest == NRDESTPERPACK){ /* filled it up */
  396. /* indicate that we did broadcast */
  397. didsend = 1;
  398. /* reset the destination counter */
  399. numdest = 0;
  400. (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  401.  PID_NETROM,&hbp); /* send it */
  402. /* new header */
  403. hbp = copy_p(savehdr,NR3NODEHL);
  404. }
  405. }
  406. }
  407. /* If we have a partly filled packet left over, or we never */
  408. /* sent one at all, we broadcast: */
  409. if(!didsend || numdest > 0)
  410. (*axif->output)(axif, Nr_nodebc, axif->hwaddr,PID_NETROM, &hbp);
  411. /* free the header copies */
  412. if(numdest == 0)
  413. free_p(&hbp);
  414. free_p(&savehdr);
  415. }
  416. /* attach the net/rom interface.  no parms for now. */
  417. int
  418. nr_attach(argc,argv,p)
  419. int argc;
  420. char *argv[];
  421. void *p;
  422. {
  423. if(Nr_iface != (struct iface *)0){
  424. printf("netrom interface already attachedn");
  425. return -1;
  426. }
  427. Nr_iface = (struct iface *)callocw(1,sizeof(struct iface));
  428. Nr_iface->addr = Ip_addr;
  429. /* The strdup is needed to keep the detach routine happy (it'll
  430.  * free the allocated memory)
  431.  */
  432. Nr_iface->name = strdup("netrom");
  433. if(Nr_iface->hwaddr == NULL){
  434. Nr_iface->hwaddr = mallocw(AXALEN);
  435. memcpy(Nr_iface->hwaddr,Mycall,AXALEN);
  436. }
  437. Nr_iface->mtu = NR4MAXINFO;
  438. setencap(Nr_iface,"NETROM");
  439. Nr_iface->next = Ifaces;
  440. Ifaces = Nr_iface;
  441. memcpy(Nr4user,Mycall,AXALEN);
  442. Nr_iface->txproc = newproc("nr tx",512,if_tx,0,Nr_iface,NULL,0);
  443. return 0;
  444. }
  445. /* This function checks an ax.25 address and interface number against
  446.  * the filter table and mode, and returns 1 if the address is to be
  447.  * accepted, and 0 if it is to be filtered out.
  448.  */
  449. static int
  450. accept_bc(addr,ifnum)
  451. uint8 *addr;
  452. unsigned ifnum;
  453. {
  454. struct nrnf_tab *fp;
  455. if(Nr_nfmode == NRNF_NOFILTER) /* no filtering in effect */
  456. return 1;
  457. fp = find_nrnf(addr,ifnum); /* look it up */
  458. if((fp != NULL && Nr_nfmode == NRNF_ACCEPT)
  459. || (fp == NULL && Nr_nfmode == NRNF_REJECT))
  460. return 1;
  461. else
  462. return 0;
  463. }
  464. /* receive and process node broadcasts. */
  465. void
  466. nr_nodercv(
  467. struct iface *iface,
  468. uint8 *source,
  469. struct mbuf **bpp
  470. ){
  471. register int ifnum;
  472. char bcalias[AXALEN];
  473. struct nr3dest ds;
  474. /* First, see if this is even a net/rom interface: */
  475. for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  476. if(iface == Nrifaces[ifnum].iface)
  477. break;
  478. if(ifnum == Nr_numiface){ /* not in the interface table */
  479. free_p(bpp);
  480. return;
  481. }
  482. if(!accept_bc(source,ifnum)){ /* check against filter */
  483. free_p(bpp);
  484. return;
  485. }
  486. /* See if it has a routing broadcast signature: */
  487. if(PULLCHAR(bpp) != NR3NODESIG){
  488. free_p(bpp);
  489. return;
  490. }
  491. /* now try to get the alias */
  492. if(pullup(bpp,bcalias,ALEN) < ALEN){
  493. free_p(bpp);
  494. return;
  495. }
  496. bcalias[ALEN] = ''; /* null terminate */
  497. /* enter the neighbor into our routing table */
  498. if(nr_routeadd(bcalias,source,ifnum,Nrifaces[ifnum].quality,
  499.  source, 0, 0) == -1){
  500. free_p(bpp);
  501. return;
  502. }
  503. /* we've digested the header; now digest the actual */
  504. /* routing information */
  505. while(ntohnrdest(&ds,bpp) != -1){
  506. /* ignore routes to me! */
  507. if(ismycall(ds.dest))
  508. continue;
  509. /* ignore routes below the minimum quality threshhold */
  510. if(ds.quality < Nr_autofloor)
  511. continue;
  512. /* set loopback paths to 0 quality */
  513. if(ismycall(ds.neighbor))
  514. ds.quality = 0;
  515. else
  516. ds.quality = ((ds.quality * Nrifaces[ifnum].quality + 128)
  517.  / 256) & 0xff;
  518. if(nr_routeadd(ds.alias,ds.dest,ifnum,ds.quality,source,0,0)
  519. == -1)
  520. break;
  521. }
  522. free_p(bpp); /* This will free the mbuf if anything fails above */
  523. }
  524. /* The following are utilities for manipulating the routing table */
  525. /* hash function for callsigns.  Look familiar? */
  526. uint16
  527. nrhash(s)
  528. uint8 *s;
  529. {
  530. register uint8 x;
  531. register int i;
  532. x = 0;
  533. for(i = ALEN; i !=0; i--)
  534. x ^= *s++ & 0xfe;
  535. x ^= *s & SSID;
  536. return (uint16)(x % NRNUMCHAINS);
  537. }
  538. /* Find a neighbor table entry.  Neighbors are determined by
  539.  * their callsign and the interface number.  This takes care
  540.  * of the case where the same switch or hosts uses the same
  541.  * callsign on two different channels.  This isn't done by
  542.  * net/rom, but it might be done by stations running *our*
  543.  * software.
  544.  */
  545. static struct nrnbr_tab *
  546. find_nrnbr(addr,ifnum)
  547. register uint8 *addr;
  548. unsigned ifnum;
  549. {
  550. uint16 hashval;
  551. register struct nrnbr_tab *np;
  552. /* Find appropriate hash chain */
  553. hashval = nrhash(addr);
  554. /* search hash chain */
  555. for(np = Nrnbr_tab[hashval]; np != NULL; np = np->next){
  556. /* convert first in  list to ax25 address format */
  557. if(addreq(np->call,addr) && np->iface == ifnum){
  558. return np;
  559. }
  560. }
  561. return NULL;
  562. }
  563. /* Find a route table entry */
  564. struct nrroute_tab *
  565. find_nrroute(addr)
  566. register uint8 *addr;
  567. {
  568. uint16 hashval;
  569. register struct nrroute_tab *rp;
  570. /* Find appropriate hash chain */
  571. hashval = nrhash(addr);
  572. /* search hash chain */
  573. for(rp = Nrroute_tab[hashval]; rp != NULL; rp = rp->next){
  574. if(addreq(rp->call,addr)){
  575. return rp;
  576. }
  577. }
  578. return NULL;
  579. }
  580. /* Try to find the AX.25 address of a node with the given alias.  Return */
  581. /* a pointer to the AX.25 address if found, otherwise NULL.  The alias */
  582. /* should be a six character, blank-padded, upper-case string. */
  583. uint8 *
  584. find_nralias(alias)
  585. char *alias;
  586. {
  587. int i;
  588. register struct nrroute_tab *rp;
  589. /* Since the route entries are hashed by ax.25 address, we'll */
  590. /* have to search all the chains */
  591. for(i = 0; i < NRNUMCHAINS; i++)
  592. for(rp = Nrroute_tab[i]; rp != NULL; rp = rp->next)
  593. if(strncmp(alias, rp->alias, 6) == 0)
  594. return rp->call;
  595. /* If we get to here, we're out of luck */
  596. return NULL;
  597. }
  598. /* Find a binding in a list by its neighbor structure's address */
  599. static struct nr_bind *
  600. find_binding(list,neighbor)
  601. struct nr_bind *list;
  602. register struct nrnbr_tab *neighbor;
  603. {
  604. register struct nr_bind *bp;
  605. for(bp = list; bp != NULL; bp = bp->next)
  606. if(bp->via == neighbor)
  607. return bp;
  608. return NULL;
  609. }
  610. /* Find the worst quality non-permanent binding in a list */
  611. static
  612. struct nr_bind *
  613. find_worst(list)
  614. struct nr_bind *list;
  615. {
  616. register struct nr_bind *bp;
  617. struct nr_bind *worst = NULL;
  618. unsigned minqual = 1000; /* infinity */
  619. for(bp = list; bp != NULL; bp = bp->next)
  620. if(!(bp->flags & NRB_PERMANENT) && bp->quality < minqual){
  621. worst = bp;
  622. minqual = bp->quality;
  623. }
  624. return worst;
  625. }
  626. /* Find the best binding of any sort in a list.  If obso is 1,
  627.  * include entries below the obsolescence threshhold in the
  628.  * search (used when this is called for routing broadcasts).
  629.  * If it is 0, routes below the threshhold are treated as
  630.  * though they don't exist.
  631.  */
  632. static
  633. struct nr_bind *
  634. find_best(list,obso)
  635. struct nr_bind *list;
  636. unsigned obso;
  637. {
  638. register struct nr_bind *bp;
  639. struct nr_bind *best = NULL;
  640. int maxqual = -1; /* negative infinity */
  641. for(bp = list; bp != NULL; bp = bp->next)
  642. if((int)bp->quality > maxqual)
  643. if(obso || bp->obsocnt >= Obso_minbc){
  644. best = bp;
  645. maxqual = bp->quality;
  646. }
  647. return best;
  648. }
  649. /* Add a route to the net/rom routing table */
  650. int
  651. nr_routeadd(alias,dest,ifnum,quality,neighbor,permanent,record)
  652. char *alias; /* net/rom node alias, blank-padded and */
  653. /* null-terminated */
  654. uint8 *dest; /* destination node callsign */
  655. unsigned ifnum; /* net/rom interface number */
  656. unsigned quality; /* route quality */
  657. uint8 *neighbor; /* neighbor node + 2 digis (max) in arp format */
  658. unsigned permanent; /* 1 if route is permanent (hand-entered) */
  659. unsigned record; /* 1 if route is a "record route" */
  660. {
  661. struct nrroute_tab *rp;
  662. struct nr_bind *bp;
  663. struct nrnbr_tab *np;
  664. uint16 rhash, nhash;
  665. /* See if a routing table entry exists for this destination */
  666. if((rp = find_nrroute(dest)) == NULL){
  667. rp = (struct nrroute_tab *)callocw(1,sizeof(struct nrroute_tab));
  668. /* create a new route table entry */
  669. strncpy(rp->alias,alias,6);
  670. memcpy(rp->call,dest,AXALEN);
  671. rhash = nrhash(dest);
  672. rp->next = Nrroute_tab[rhash];
  673. if(rp->next != NULL)
  674. rp->next->prev = rp;
  675. Nrroute_tab[rhash] = rp; /* link at head of hash chain */
  676. } else if(!record){
  677. strncpy(rp->alias,alias,6); /* update the alias */
  678. }
  679. /* See if an entry exists for this neighbor */
  680. if((np = find_nrnbr(neighbor,ifnum)) == NULL){
  681. np = (struct nrnbr_tab *)callocw(1,sizeof(struct nrnbr_tab));
  682. /* create a new neighbor entry */
  683. memcpy(np->call,neighbor,AXALEN);
  684. np->iface = ifnum;
  685. nhash = nrhash(neighbor);
  686. np->next = Nrnbr_tab[nhash];
  687. if(np->next != NULL)
  688. np->next->prev = np;
  689. Nrnbr_tab[nhash] = np;
  690. } else if(permanent){ /* force this path to the neighbor */
  691. memcpy(np->call,neighbor,AXALEN);
  692. }
  693. /* See if there is a binding between the dest and neighbor */
  694. if((bp = find_binding(rp->routes,np)) == NULL){
  695. bp = (struct nr_bind *)callocw(1,sizeof(struct nr_bind));
  696. /* create a new binding and link it in */
  697. bp->via = np; /* goes via this neighbor */
  698. bp->next = rp->routes; /* link into binding chain */
  699. if(bp->next != NULL)
  700. bp->next->prev = bp;
  701. rp->routes = bp;
  702. rp->num_routes++; /* bump route count */
  703. np->refcnt++; /* bump neighbor ref count */
  704. bp->quality = quality;
  705. bp->obsocnt = Obso_init; /* use initial value */
  706. if(permanent)
  707. bp->flags |= NRB_PERMANENT;
  708. else if(record) /* notice permanent overrides record! */
  709. bp->flags |= NRB_RECORDED;
  710. } else {
  711. if(permanent){ /* permanent request trumps all */
  712. bp->quality = quality;
  713. bp->obsocnt = Obso_init;
  714. bp->flags |= NRB_PERMANENT;
  715. bp->flags &= ~NRB_RECORDED; /* perm is not recorded */
  716. } else if(!(bp->flags & NRB_PERMANENT)){ /* not permanent */
  717. if(record){ /* came from nr_route */
  718. if(bp->flags & NRB_RECORDED){ /* no mod non-rec bindings */
  719. bp->quality = quality;
  720. bp->obsocnt = Obso_init; /* freshen recorded routes */
  721. }
  722. } else { /* came from a routing broadcast */
  723. bp->quality = quality;
  724. bp->obsocnt = Obso_init;
  725. bp->flags &= ~NRB_RECORDED; /* no longer a recorded route */
  726. }
  727. }
  728. }
  729. /* Now, check to see if we have too many bindings, and drop */
  730. /* the worst if we do */
  731. if(rp->num_routes > Nr_maxroutes){
  732. /* since find_worst never returns permanent entries, the */
  733. /* limitation on number of routes is circumvented for    */
  734. /* permanent routes */
  735. if((bp = find_worst(rp->routes)) != NULL){
  736. nr_routedrop(dest,bp->via->call,bp->via->iface);
  737. }
  738. }
  739. return 0;
  740. }
  741. /* Drop a route to dest via neighbor */
  742. int
  743. nr_routedrop(dest,neighbor,ifnum)
  744. uint8 *dest, *neighbor;
  745. unsigned ifnum;
  746. {
  747. register struct nrroute_tab *rp;
  748. register struct nrnbr_tab *np;
  749. register struct nr_bind *bp;
  750. if((rp = find_nrroute(dest)) == NULL)
  751. return -1;
  752. if((np = find_nrnbr(neighbor,ifnum)) == NULL)
  753. return -1;
  754. if((bp = find_binding(rp->routes,np)) == NULL)
  755. return -1;
  756. /* drop the binding first */
  757. if(bp->next != NULL)
  758. bp->next->prev = bp->prev;
  759. if(bp->prev != NULL)
  760. bp->prev->next = bp->next;
  761. else
  762. rp->routes = bp->next;
  763. free(bp);
  764. rp->num_routes--; /* decrement the number of bindings */
  765. np->refcnt--; /* and the number of neighbor references */
  766. /* now see if we should drop the route table entry */
  767. if(rp->num_routes == 0){
  768. if(rp->next != NULL)
  769. rp->next->prev = rp->prev;
  770. if(rp->prev != NULL)
  771. rp->prev->next = rp->next;
  772. else
  773. Nrroute_tab[nrhash(dest)] = rp->next;
  774. free(rp);
  775. }
  776. /* and check to see if this neighbor can be dropped */
  777. if(np->refcnt == 0){
  778. if(np->next != NULL)
  779. np->next->prev = np->prev;
  780. if(np->prev != NULL)
  781. np->prev->next = np->next;
  782. else
  783. Nrnbr_tab[nrhash(neighbor)] = np->next;
  784. free(np);
  785. }
  786. return 0;
  787. }
  788. #ifdef notused
  789. /* Find the best neighbor for destination dest, in arp format */
  790. static uint8 *
  791. nr_getroute(dest)
  792. uint8 *dest;
  793. {
  794. register struct nrroute_tab *rp;
  795. register struct nr_bind *bp;
  796. if((rp = find_nrroute(dest)) == NULL)
  797. return NULL;
  798. if((bp = find_best(rp->routes,1)) == NULL) /* shouldn't happen! */
  799. return NULL;
  800. return bp->via->call;
  801. }
  802. #endif /* notused */
  803. /* Find an entry in the filter table */
  804. static struct nrnf_tab *
  805. find_nrnf(addr,ifnum)
  806. register uint8 *addr;
  807. unsigned ifnum;
  808. {
  809. uint16 hashval;
  810. register struct nrnf_tab *fp;
  811. /* Find appropriate hash chain */
  812. hashval = nrhash(addr);
  813. /* search hash chain */
  814. for(fp = Nrnf_tab[hashval]; fp != NULL; fp = fp->next){
  815. if(addreq(fp->neighbor,addr) && fp->iface == ifnum){
  816. return fp;
  817. }
  818. }
  819. return NULL;
  820. }
  821. /* Add an entry to the filter table.  Return 0 on success,
  822.  * -1 on failure
  823.  */
  824. int
  825. nr_nfadd(addr,ifnum)
  826. uint8 *addr;
  827. unsigned ifnum;
  828. {
  829. struct nrnf_tab *fp;
  830. uint16 hashval;
  831. if(find_nrnf(addr,ifnum) != NULL)
  832. return 0; /* already there; it's a no-op */
  833. fp = (struct nrnf_tab *)callocw(1,sizeof(struct nrnf_tab));
  834. hashval = nrhash(addr);
  835. memcpy(fp->neighbor,addr,AXALEN);
  836. fp->iface = ifnum;
  837. fp->next = Nrnf_tab[hashval];
  838. if(fp->next != NULL)
  839. fp->next->prev = fp;
  840. Nrnf_tab[hashval] = fp;
  841. return 0;
  842. }
  843. /* Drop a neighbor from the filter table.  Returns 0 on success, -1
  844.  * on failure.
  845.  */
  846. int
  847. nr_nfdrop(addr,ifnum)
  848. uint8 *addr;
  849. unsigned ifnum;
  850. {
  851. struct nrnf_tab *fp;
  852. if((fp = find_nrnf(addr,ifnum)) == NULL)
  853. return -1; /* not in the table */
  854. if(fp->next != NULL)
  855. fp->next->prev = fp->prev;
  856. if(fp->prev != NULL)
  857. fp->prev->next = fp->next;
  858. else
  859. Nrnf_tab[nrhash(addr)] = fp->next;
  860. free(fp);
  861. return 0;
  862. }