📄 rrriprx.c
字号:
RipProcIpa:process individual ip address.************************************************/void RipProcIpa(ipna_pt ipna, int met, rripa sipa, rripa nhop,int cid,word tag){ iproute_ent_pt iprt; iprt = ipFindRoute(ipna,IPRT_RIP); /* FDB now stores routes from all sources, best or not */ /* if no existing RIP route, add one */ if(!iprt){ /* dont add if infinite */ if(met == RIP_INFINITE){ return; } /* dont add promoted subnet */ if(ripIsPromotedSubnet(ipna)){ return; } RipAddRoute(ipna, sipa, nhop,cid, met,IPRT_RIP,tag); } else{ /* we know was not infinite, or would not have iprt, owner is rip here */ /* reinit timer if same source */ if(RT_SRC(iprt) == sipa){ /* dont do it if infinite */ if(met != RIP_INFINITE){ rrTimerSet( RT_TTL(iprt), r_node->rn_riptimer * 6, (vfcnptr)ripTimeout, &ripTimers); /* Hmm...the code called this function which was unresolved. It takes the same args as rrTimerSet though. rrTimerUpdate( RT_TTL(iprt), r_node->rn_riptimer * 6, (vfcnptr)ripTimeout, &ripTimers); */ iprt->iprt_tcreate = RIP_GET_SYSTIME; } else{ RipPurgeRoute(iprt, 1); return; } } /* replace if lower cost */ if(RT_TOS0_COST(iprt) > met){ RipReplaceRoute(iprt, sipa, nhop,cid, met,tag); } /* update if from same source, higher cost */ else if(RT_TOS0_COST(iprt) < met){ if(RT_SRC(iprt) == sipa){ RipReplaceRoute(iprt, sipa, nhop,cid, met,tag); } } /* equal cost, if not infinite, and route is on its way to timing out, pick a different path instead of waiting for timeout. */ else if((met < RIP_INFINITE) && (RT_SRC(iprt) != sipa) && (ripRemLife(RT_TTL(iprt)) < r_node->rn_riptimer * 2) ){ RipReplaceRoute(iprt, sipa, nhop,cid, met,tag); } }}/********************************************************RipAddRoute:Adds a RIP route to table. Also tries to add an ARPentry if one does not exist for the next hop.********************************************************/void RipAddRoute(ipna_pt ipna,rripa src,rripa nhop,int cid,int cost,int owner,word tag){ iproute_ent_pt iprt,grt; rrtimer_pt timer; iprt = ipAddRoute(ipna,nhop,cid,cost,owner,(rripa)tag); if(!iprt) return; /* source may not be nhop */ RT_SRC_SET(iprt,src); /* this is a "route changed" flag */ RT_TRIG_SET(iprt,IPRT_RIP_CHANGED); /* we need to send triggered update */ ripTrigger(); timer = rrTimerCreate( (vfcnptr)ripTimeout,(void *)iprt, (cost < RIP_INFINITE)? r_node->rn_riptimer * 6: r_node->rn_riptimer * 4, TTYPE_ONESHOT,&ripTimers); if(!timer){ ipDelRoute(iprt); return; } RT_TTL_SET(iprt,timer); /* Remember time, in msecs, when route was created so that SNMP can provide the route age. */ iprt->iprt_tcreate = RIP_GET_SYSTIME; /* if route in garbage list, toss it */ grt = ripFindGarbageList(RT_DEST(iprt),RT_MASK(iprt)); if(grt) ripRmGarbageList(grt); r_node->rn_rip2GlobalRouteChanges++;}/********************************************************RipReplaceRoute:Replaces existin RIP route in table. Also adds arpif one does not exist.********************************************************/void RipReplaceRoute(iproute_ent_pt iprt,rripa src,rripa nhop,int cid,int cost,word tag){ /* tell ip to mod */ ipReplaceRoute(iprt,nhop,cid,cost,(rripa)tag); RT_SRC_SET(iprt,src); /* this is a "route changed" flag */ RT_TRIG_SET(iprt,IPRT_RIP_CHANGED); /* we need to send triggered update */ ripTrigger(); /* update timer */ ASSERT(RT_OWNER(iprt) == IPRT_RIP,"ripReplaceRoute: no timer"); rrTimerSet( RT_TTL(iprt), (cost < RIP_INFINITE)? r_node->rn_riptimer * 6: r_node->rn_riptimer * 4, (vfcnptr)ripTimeout,&ripTimers); iprt->iprt_tcreate = RIP_GET_SYSTIME; r_node->rn_rip2GlobalRouteChanges++;}/*************************************************RipPurgeRoute:Route has timed out. Mark route cost as infiniteand put in garbage list. If bDel true then remove from fdb also. Withroute leaking RipPurgeRoute is used just to markit as infinite for when we are purging a routeleaked to RIP from another protocol, or a staticor local route which is no longer being leaked toRIP.**************************************************/void RipPurgeRoute(iproute_ent_pt iprt, int bDel){ iproute_ent_pt nrt; rrtimer_pt timer; /* ignore bcast/multicast - we don't put them on garbage list because we never advertised them to begin with. */ if( (RT_OWNER(iprt) == IPRT_LOCAL) && RT_IS_BCAST(iprt)){ goto skip_glist; } /* Ignore localhost - ditto as broadcast */ if( (RT_OWNER(iprt) == IPRT_LOCAL) && ((RT_DEST(iprt) & IP_CLASS_A_MSK) == IP_LOOP) ) { goto skip_glist; } nrt = rip2GarbageList(iprt); if(nrt){ /* this is a "route changed" flag */ RT_TRIG_SET(nrt,IPRT_RIP_CHANGED); timer = rrTimerCreate( (vfcnptr)ripTimeout,(void *)nrt, RIP_PURGE_TTL, TTYPE_ONESHOT,&ripTimers); if(!timer){ RT_GARBAGE_FREE(nrt); return; } RT_TTL_SET(nrt,timer); }skip_glist: ripTrigger(); if(RT_TTL(iprt)){ rrTimerDelete(RT_TTL(iprt),&ripTimers); } if( bDel ) ipDelRoute(iprt); r_node->rn_rip2GlobalRouteChanges++;}/*************************************************RipPurgeRouteByCirc:Route has timed out. Mark route cost as infinite. **************************************************/void RipPurgeRouteByCirc(rcirc_pt c){ iproute_ent_pt iprt; RT_TABLEWALK if(RT_OWNER(iprt) == IPRT_RIP && iprt->iprt_cid != INVALID_CIRC && RT_TOS0_NHCID(iprt) == c->rc_id){ /* We call RipPurgeRoute with bDel == 1 to actually delete the route. */ RipPurgeRoute(iprt, 1); } RT_TABLEWALKEND}/*************************************************RipDelRoute:Infinite cost route "garbage-time" has expired, get rid of it.**************************************************/void RipDelRoute(iproute_ent_pt iprt){ ripRmGarbageList(iprt); r_node->rn_rip2GlobalRouteChanges++;}/*********************************************ripAddExtRt:non-rip route has been added/changed. set riptrigger.*********************************************/void ripAddExtRt(ipna_pt ipna){ use_critical; critical; /* we need to send triggered update */ ripTrigger(); normal;}/*********************************************RipSpecReq:Process specific rip request.*********************************************/void RipSpecReq(rpdu_pt rpdu,int len,rripa sipa,word sport){ ibd_pt rip_bd; ripa_pt ripa, pdu_end; rpdu_pt npdu; IPNA ipna; int met; iproute_ent_pt iprt; /* allocate new buf and copy */ if( (rip_bd= (ibd_pt)ripOfAlloc(len)) == 0){ return; } npdu = (rpdu_pt)rip_bd->ibd_buf; ipCopyMem(npdu,rpdu,len); npdu->rp_cmd = RIP_CMD_RSP; ripa = (ripa_pt)((byte *)npdu + RIP_HLEN); /* process each entry */ pdu_end = (ripa_pt)( (byte *)npdu + len ); for(;ripa < pdu_end; ripa = ROPT_FWD(ripa)){ /* note that we dont care about split-horizon or subnet hiding in specific requests. */ ipna.ip_add = XIPA(&ripa->ra_ipa3); if(ripvers == 2){ ipna.ip_mask = XIPA(&ripa->ra_msk3); } else if(!ipna.ip_add){ ipna.ip_mask = 0; } else{ /* for subnets, we are at a loss to to know what the requested mask is, so try the class mask. */ IP_CLASS_MASK(&ipna.ip_add, &ipna.ip_mask); ipna.ip_add = ipna.ip_add & ipna.ip_mask; } /* do we have an entry ? */ if( (iprt = ipFindRoute( &ipna,IPRT_RIP )) == 0 ){ /* no */ DWTOPDU( &ripa->ra_met3, RIP_INFINITE ); } else{ /* yes, convert metric to hops */ met = RipMetric( iprt ); DWTOPDU( &ripa->ra_met3, met ); } } /* send response */ udptx(rip_bd,len,sport,RIP_PORT,sipa,(rripa)0,0,DELETE);} /**************************************************ripFindGarbageList:locates exact match in garbage collection list, whichis linear linked list**************************************************/iproute_ent_pt ripFindGarbageList(rripa dest,rripa mask){ iproute_ent_pt iprt; iproute_ent_pt fwd; /* go through routes in this bin */ for(iprt= r_node->rn_garb_fwd; iprt; iprt= fwd){ fwd = iprt->iprt_gfwd; /* compare address */ if( dest == iprt->iprt_ipa.ip_add && mask == iprt->iprt_ipa.ip_mask){ return(iprt); } } return(0);}/*******************************************************rip2GarbageList:adds route to garbage collection list.*******************************************************/iproute_ent_pt rip2GarbageList(iproute_ent_pt iprt){ iproute_ent_pt nrt; /* alloc route struct */ nrt = RT_GARBAGE_ALLOC(); if(!nrt) return(0); /* copy it all */ rrCopyMem(nrt,iprt,sizeof(iproute_ent)); /* nrt->t[0].iprt_fent[0] = 0; */ nrt->iprt_cid = INVALID_CIRC; nrt->t[0].iprt_cost = RIP_INFINITE; rrLink((dll_pt)nrt,(dll_pt)&r_node->rn_garb_fwd); return(nrt);}/***************************************************ripRmGarbageList:remove route from garbage collection list and deleteit***************************************************/void ripRmGarbageList(iproute_ent_pt iprt){ /* free timer */ if(RT_TTL(iprt)){ rrTimerDelete(RT_TTL(iprt),&ripTimers); } rrULink((dll_pt)iprt,(dll_pt)&r_node->rn_garb_fwd); RT_GARBAGE_FREE(iprt);}/*********************************************ripIsPromotedSubnet:returns true if route is one of our interfacespromoted from subnet to net**********************************************/int ripIsPromotedSubnet(ipna_pt ipna){ rcirc_pt c; rripa xmask; int i; for(i= 0; i < CIRC_HASHES; i++){ for(c = (rcirc_pt)rip_circ_hash[i].dll_fwd;c; c= c->rc_fwd){ /* look for ipna with strictly shorter mask */ if(ipna->ip_mask >= c->rc_ipa[0].ip_mask) continue; /* must be as would be if promoted */ IP_CLASS_MASK(&c->rc_ipa[0].ip_add, &xmask); if(ipna->ip_mask != xmask) continue; if((c->rc_ipa[0].ip_add & xmask) != ipna->ip_add) continue; return(1); } } return(0);}/******************************************ripNeigFind:locate neighbor on given circuit.*******************************************/RNEIGH *ripNeighFind(rripa naddr,rcirc_pt c){ RNEIGH *rnbr; for(rnbr = c->rc_nbr_fwd; rnbr; rnbr = rnbr->n_fwd){ if(rnbr->n_ipa == naddr) return(rnbr); } return(0);}/**********************************************ripDelExtRt:This function is used to poison routes thatwere being advertised by RIP but aren'towned by RIP. It doesn't delete the routesbut merely copies them to RIP's garbage collectionlist and clears the IPRT_RIP_IMPORT flag.*********************************************/void ripDelExtRt(iproute_ent_pt iprt){ if( RT_IS_TRIG(iprt, IPRT_RIP_IMPORT )) { /* Purge from RIP advertisements (mark infinite cost etc.) but do not actually delete the route - we don't own it. */ RT_TRIG_CLR(iprt, IPRT_RIP_IMPORT); RipPurgeRoute(iprt, 0); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -