Metropoli BBS
VIEWER: ipxrip.c MODE: TEXT (ASCII)
/* File IPXRIP.C : IPX Routing Information Protocol functions
*/

/*
    Copyright (C) 1992 Indian Institute of Technology, Bombay
    Written by V. Srinivas and Vishwas Joglekar,
    Dept of Computer Science and Engineering.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/



#include "yapcbr.h"
#include "ipxwatch.h"
#include "ipxrip.h"
#include "diag.h"

extern struct rip_table *rip_lookup[];
extern struct rxstruct *rxptr;
extern struct my_route my_route_info;
extern struct ipxpktdv Ipxpktdv;
extern struct network_info *net_lookup(BYTE *net_id,int append_flag);

extern WORD getword(BYTE *);

void nlist();
int rip_hash_lookup(int hashret,RIP_INFO *route_info,BYTE *router_id );
void disp_route_info(ROUT_TABLE *rip_ptr);
void  proc_rip_pkt(RIP_PKT *rip_pkt,unsigned char *disp,int bcast);
int check_more(int *row);
void *ibuf_alloc(int type);
ROUT_TABLE *find_route(BYTE *net_id);

 /* search for the  network/route information   in the hashed list  */
 int rip_hash_lookup(int hashret,RIP_INFO *route_info,BYTE *router_id )
  {
    ROUT_TABLE *new_addr,*tmp,*hash_ptr;
    WORD new_tick,old_tick;
    int alt_route;

    alt_route = FALSE;
    hash_ptr = rip_lookup[hashret];
    tmp=hash_ptr;
    if((route_info->no_of_hops & 0x0f00) > 0x0f00 ) return(NOTFOUND);
#ifdef DBG1
    cprintf("Searching Hash table, bucket %d\n",hashret);
#endif
 while(hash_ptr != 0){
      /* add the network information into the network information table */
     /* is the route already known	 ?	*/
      if(memcmp(hash_ptr->route_info.net_id,route_info->net_id,NET_ID_LEN) == 0){
      /* check whether it is a new/faster route or the same */
	 new_tick = getword((BYTE *)&route_info->no_of_ticks);
	 if( new_tick > hash_ptr->route_info.no_of_ticks)
	    return(FOUND); /* new route is a slower route, discard */
	 if( new_tick < hash_ptr->route_info.no_of_ticks){
      /* the new route is a faster route, delete the old route info */
	    hash_ptr->route_info.no_of_ticks = new_tick;
	    hash_ptr->route_info.no_of_hops  = getword((BYTE *)&route_info->no_of_hops);
	    hash_ptr->dev = rxptr->dev; /* save the NIC no */
	    hash_ptr->age_timer = FLUSH_TIME;  /* 60 secs timer  */
	    memcpy(hash_ptr->router_id,router_id,ETHER_ADDR_LEN);
	    hash_ptr->alternate_route = 0;
	    return(FOUND);
	 }
	else{ /* Is it is an alternate route with the same number of ticks ? */
	   if(memcmp(hash_ptr->router_id,router_id,ETHER_ADDR_LEN) == 0){
	      /* same route, reset the timer       */
	      hash_ptr->age_timer = FLUSH_TIME;  /* 60 secs timer  */
	      return(FOUND);
	   }
	    else{
	       alt_route = TRUE;
	       break;
	    }
        }
  }
  tmp = hash_ptr;
  hash_ptr = hash_ptr->next;
} /* while */

/* address not in table, add */
 new_addr = (struct rip_table *)ibuf_alloc(NOVLRIP);
 if(new_addr == 0) {
    printf("Malloc failed \n");
    return(0);
 }
 memcpy(new_addr->route_info.net_id,route_info->net_id,NET_ID_LEN);
 new_addr->route_info.no_of_ticks = getword((BYTE *)&route_info->no_of_ticks);
 new_addr->route_info.no_of_hops  = getword((BYTE *) &route_info->no_of_hops);
 new_addr->dev = rxptr->dev; /* save the NIC no */
 memcpy(new_addr->router_id,router_id,ETHER_ADDR_LEN);
 new_addr->alternate_route = 0;
 new_addr->next = 0;
 new_addr->age_timer = FLUSH_TIME; /* 60 sec timer   */
 new_addr->net_status = 0;
 if(alt_route == TRUE){ /* it is an alternate route */
      hash_ptr->alternate_route = new_addr;
      return(NOTFOUND);
 }
 if(tmp == 0)  /* is this bucket empty  ? */
    rip_lookup[hashret] = new_addr;
 else 		       /* the bucket is not empty */
 tmp->next = new_addr;
 net_lookup(route_info->net_id,TRUE); /* update the network information table */
return(NOTFOUND);
}


/* list all the networks & the correspond routers by looking at the
   route information table
 */
void nlist()
{
  int i,temp,count=0;
  ROUT_TABLE *rip_ptr;
  make_win(8,5,74,22,1,"ROUTING INFORMATION");
  disp_mesg("ESC Close Window");
  make_win(9,6,73,21,1,"Network  Router Address  Hops  Ticks  Net Status  Age Timer");
  gotoxy(1,1);
  _setcursortype(_NOCURSOR);
  for(i=0;i< MAX_PRIME;i++){
      rip_ptr = rip_lookup[i];
      while(rip_ptr!= 0){
	 disp_route_info(rip_ptr);
	 if(check_more(&count) == ESC) return;
	 if(rip_ptr->alternate_route != 0){
	    disp_route_info(rip_ptr->alternate_route);
	    if(check_more(&count) == ESC) return;
	 }
	 rip_ptr = rip_ptr->next;
      }/* while */
  } /* for */
  while(read_key()!= ESC);
 }

/* Display routing table info  */
   void disp_route_info(ROUT_TABLE *rip_ptr)
   {
    unsigned char buff[50];

    buff[0] = '\0';
    prnt_hex(rip_ptr->route_info.net_id,buff,4);
    cprintf(" %s ",buff);
/*    cprintf("%2d  ",rip_ptr->dev); */
    buff[0] = '\0';
    prnt_hex(rip_ptr->router_id,buff,6);
    cputs(buff);
    cprintf("   %.2u    ",rip_ptr->route_info.no_of_hops);
    cprintf("  %.2u  ",rip_ptr->route_info.no_of_ticks);
    cprintf("  %.2u        ",rip_ptr->net_status);
    cprintf("  %.4u \r\n",rip_ptr->age_timer);
   }

/* Determine the type of RIP packet */

void  proc_rip_pkt(RIP_PKT *rip_pkt,unsigned char *disp,int bcast)
{
   WORD resp_type,len;
   struct network_info *my_net;
   extern struct network_info *current_net;
   int i,no_of_routes,hashret;
   resp_type  = getword(rip_pkt->type);  /* get rip pkt type */
   switch(resp_type){
   case ROUTE_REQUEST:	/* route request pkt  */
			sprintf(disp,"Route Request -> ");
			prnt_hex(rip_pkt->route_info[0].net_id,disp+strlen(disp),4);
			break;
   case ROUTE_RESP:
		/* respose to a route request or a periodic broadcast */
	  if(bcast == TRUE){
			      /* It is a broadcast packet from a router, update
		      the router information table */
		      len = getword(rip_pkt->header.length); /* get length of IPX packet */
		      no_of_routes = (len-sizeof(IPX_HEADER) - sizeof(WORD))/sizeof(RIP_INFO);
		      if(no_of_routes >MAX_ROUTES) return; /* invalid  rip packet */
		      sprintf(disp,"Route Info ");
                       /* get my network address by looking at the ipx header */
		      my_net = net_lookup(rip_pkt->header.source_node.net_id,TRUE);
		      if(current_net == 0){
			 current_net = my_net;
			 memcpy(my_route_info.route_info.net_id,my_net->net_id,4);
			 memcpy(Ipxpktdv.net_id,my_net->net_id,4);
		      }
		      hashret = hash_addr(my_net->net_id,4);
		      rip_hash_lookup(hashret,&my_route_info.route_info,my_route_info.router_id);
		      for(i=0;i<no_of_routes;i++){
			 hashret = hash_addr(rip_pkt->route_info[i].net_id,4);
			 rip_hash_lookup(hashret,&rip_pkt->route_info[i],rip_pkt->header.source_node.node_id);
		      }
		   }
		    else  sprintf(disp,"Route Response ");
		    prnt_hex(rip_pkt->route_info[0].net_id,disp+strlen(disp),4);
		    sprintf(disp+strlen(disp),"%2.2d/%2.2d",getword((BYTE *) &rip_pkt->route_info[0].no_of_hops),
				    getword((BYTE *) &rip_pkt->route_info[0].no_of_ticks));
		   break;

     default:	   break;

      }
}


    int check_more(int *pos)
    {
	 int k =0;
	 fflush(stdin);
	 (*pos)++;
	 if(*pos == 13){
	    *pos=1;
	    gotoxy(5,20);
	    highvideo();
	    cprintf("More");
	    lowvideo();
	    k = getch();
	 }
	 else if(kbhit()!= 0)k= getch();
	 return(k);
    }


    /* determines the route to a given network and returns a pointer to the
     routing information table, containing the router id and other information */

  ROUT_TABLE *find_route(BYTE *net_id)
    {
    int hash_indx;
    ROUT_TABLE *oldptr;

    hash_indx = hash_addr(net_id,4);
    for(oldptr = rip_lookup[hash_indx];oldptr != 0; oldptr = oldptr->next){
       /* is the route already known  ?	*/
       if(memcmp(oldptr->route_info.net_id,net_id,NET_ID_LEN) == 0)
	   return(oldptr);
     }
     return(0);
    }

[ RETURN TO DIRECTORY ]