/* 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;iroute_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); }