📄 rrriprx.c
字号:
/** Copyright (c) 1998-2001 by NETsilicon Inc.** This software is copyrighted by and is the sole property of* NETsilicon. All rights, title, ownership, or other interests* in the software remain the property of NETsilicon. This* software may only be used in accordance with the corresponding* license agreement. Any unauthorized use, duplication, transmission,* distribution, or disclosure of this software is expressly forbidden.** This Copyright notice may not be removed or modified without prior* written consent of NETsilicon.** NETsilicon, reserves the right to modify this software* without notice.** NETsilicon* 411 Waverley Oaks Road USA 781.647.1234* Suite 227 http://www.netsilicon.com* Waltham, MA 02452 AmericaSales@netsilicon.com*************************************************************************** $Name: Fusion 6.52 Fusion 6.51 $* $Date: 2002/01/22 14:10:50 $* $Source: M:/psisrc/routing/rip/rcs/rrriprx.c $* $Revision: 1.16 $**************************************************************************** File Description: RIP packet reception routines ***************************************************************************/#include <ipport.h>#include <riproute.h>#include <ipaccess.h>#include <ipsec.h>#include <rrproto.h>fnc_prot(ipna_pt, ipGetRTID, (void))fnc_prot(int, ripIsPromotedSubnet,(ipna_pt))fnc_prot(rcirc_pt, ripCircFromId, (int))fnc_prot(RNEIGH *, ripNeighFind, (rripa, rcirc_pt))fnc_prot(void, RipProcEntry,(ripa_pt, rripa, int, RNEIGH *))fnc_prot(void, RipProcIpa,(ipna_pt, int, rripa, rripa, int, word))fnc_prot(iproute_ent_pt, ipFindRoute,(ipna_pt,int))fnc_prot(void, ripTimeout,(iproute_ent_pt rt))fnc_prot(void, RipAddRoute,(ipna_pt,rripa,rripa,int,int,int,word))fnc_prot(iproute_ent_pt, ipAddRoute, (ipna_pt,rripa,int,int,int,rripa))fnc_prot(rrtimer_pt, rrTimerCreate,(vfcnptr,void *,int,int,rrthead_pt))fnc_prot(iproute_ent_pt, ripFindGarbageList,(rripa,rripa))fnc_prot(void, RipReplaceRoute,(iproute_ent_pt,rripa,rripa,int,int,word))fnc_prot(void, RipPurgeRoute,(iproute_ent_pt, int))fnc_prot(void, RipSpecReq,(rpdu_pt,int,rripa,word))fnc_prot(iproute_ent_pt, rip2GarbageList,(iproute_ent_pt))fnc_prot(void, ripRmGarbageList,(iproute_ent_pt))/**********************************************riprx:process incoming RIP pdu according to RFC 1058section 3.4.**********************************************/void riprx(void *pdu,int len,int cid,rripa sipa,word sport){ ripa_pt ripa,rtst,pdu_end; ipna_pt loc_ipa; rcirc_pt rc; rpdu_pt rpdu = (rpdu_pt)pdu; RNEIGH *rnbr; rc = ripCircFromId(cid); loc_circ = rc; /* must be on and listening */ if(!rc || rc->rc_state != RCIRC_UP){ return; } if((rnbr = ripNeighFind(sipa,rc)) == 0){ rnbr = (RNEIGH *)RipNeighAlloc(); if(!rnbr){ return; } rrFillMem(rnbr,0,sizeof(*rnbr)); rnbr->n_ipa = sipa; rrLink((dll_pt)rnbr,(dll_pt)&rc->rc_nbr_fwd); } rnbr->n_tstamp = r_node->rn_tics; /* verify rational len */ if(len > MAX_RIP_LEN){ rnbr->n_badpackets++;#ifdef SNMP rc->rc_ripRcvBadPkts++;#endif return; } /* ignore version 0 */ if(!rpdu->rp_ver){ rnbr->n_badpackets++;#ifdef SNMP rc->rc_ripRcvBadPkts++;#endif return; } /* if version 1, process must =0 fields */ if((ripvers = rpdu->rp_ver) == 1){ /* reject if we our mode is rip2 only */ if(rc->rc_r2rxmode == R2M_RXV2) return; if(WFROMPDU(&rpdu->rp_rd1)){#ifdef SNMP rc->rc_ripRcvBadPkts++;#endif return; } } else{ /* rip2 spec does not say what to do about versions higher than 2. */ /* reject if we our mode is rip1 only */ if(rc->rc_r2rxmode == R2M_RXV1) return; /* ignore anything from a different domain */ if((ripvers = rpdu->rp_ver) == 2){ /* no if(WFROMPDU(&rpdu->rp_rd1) != r_node->rn_rdom){ return; } */ } } rnbr->n_version = ripvers; ripa = (ripa_pt)((byte *)rpdu + RIP_HLEN); pdu_end = (ripa_pt)( (byte *)rpdu + len ); /* process command */ if(rpdu->rp_cmd == RIP_CMD_REQ){ r_node->rn_rip2GlobalQueries++; /* request command, tx some or all or table */ if( WFROMPDU(&ripa->ra_afi1) == 0 && DWFROMPDU(&ripa->ra_met3) == RIP_INFINITE && ROPT_FWD(ripa) == pdu_end ){ if(r_node->rn_radmst != ROUTER_ON) return; /* send whole table */ loc_ipa = rc->rc_ipa; /* if an un-numbered line, get router ID */ if(!loc_ipa->ip_add){ loc_ipa = ipGetRTID(); /* no router id, give up */ if(!loc_ipa) return; } riptx(loc_ipa,cid, FALSE, sipa,sport,0); } /* specific request */ else{ RipSpecReq(rpdu,len,sipa,sport); } } else if(rpdu->rp_cmd == RIP_CMD_RSP){ /* response to req or gratuitous tx */ if(r_node->rn_radmst != ROUTER_ON) return; if(!rc->rc_listen){ return; } /* verify udp source port */ if(sport != RIP_PORT){ return; } /* verify from valid neighbor */ loc_ipa = rc->rc_ipa; if( (loc_ipa->ip_add & loc_ipa->ip_mask) != (sipa & loc_ipa->ip_mask) ){ /* is it an unnumbered line ? */ if(loc_ipa->ip_add){ /* no, invalid neighbor */ return; } } /* verify trusted neighbor */ if(!ripIsTrusted(sipa)){ return; } /* verify not our own address */ if(loc_ipa->ip_add && (sipa == loc_ipa->ip_add)) return; /* verify authentication */ if(rc->rc_auth_type != RIP_AUTH_NONE){ if(ripAuthenticate(rc,ripa,pdu_end)){ return; } ripa = ROPT_FWD(ripa); } /* determine our subnet mask and mask for our class */ loc_mask = loc_ipa->ip_mask; loc_net = loc_ipa->ip_add & loc_mask; IP_CLASS_MASK(&loc_ipa->ip_add,&loc_class_mask); /* reject malformed packet */ rtst = ripa; for(;rtst < pdu_end; rtst = ROPT_FWD(rtst)){ /* verify all MBZ */ if(ripvers == 1){ if( WFROMPDU(&rtst->ra_tag1) || DWFROMPDU(&rtst->ra_msk3) || DWFROMPDU(&rtst->ra_nh3) ){ rnbr->n_badpackets++;#ifdef SNMP loc_circ->rc_ripRcvBadPkts++;#endif return; } } } if(rtst > pdu_end)return;#ifdef SNMP loc_circ->rc_ripRcvUpdates++;#endif /* process each entry */ for(;ripa < pdu_end; ripa = ROPT_FWD(ripa)){ RipProcEntry(ripa,sipa,cid,rnbr); } } /* ignore other command types */}/*************************************************ripAuthenticate:verify received packet has correct authentication.if not, return -1.************************************************/int ripAuthenticate(rcirc_pt rc, ripa_pt ripa,ripa_pt end){ word afi = WFROMPDU(&ripa->ra_afi1); word autype = WFROMPDU(&ripa->ra_tag1); MD5_CTX context; /* unsigned char digest[16];*/ unsigned char *d; unsigned int len; int i; if(afi != RIP_AFI_AUTH) return(-1); if(autype != rc->rc_auth_type) return(-1); switch(autype){ case RIP_AUTH_SIMPLE: if(!rrCmpMem(rc->rc_auth_key,&ripa->ra_ipa3,16)){ return(0); } break; case RIP_AUTH_MD5: d = (byte *)ROPT_FWD(ripa); len = (byte *)end - d; MD5Init(&context); MD5Update(&context,d,len); MD5Update(&context,rc->rc_auth_key,16); /* MD5Final(digest,&context); Fusion is slightly different. the context includes the digest. */ MD5Final(&context); d = (byte *)&ripa->ra_ipa3; for(i =0;i < 16;i++){ /* if(*d != digest[i]){ */ if(*d != context.digest[i]) { return(-1); } d++; } return(0); default: break; } return(-1);}/********************************************************RipProcEntry:process a single entry in a rip pdu.- validate entry.- If route does not exist in FDB, add it.- If it exists: * if from same router and different cost or any router and lower cost, replace route. * else update ttl.- If cost same & differnet next hop AND ttl at least half expired, replace route.REMEMBER: ipa/mask stored in net order********************************************************/void RipProcEntry(ripa_pt ripa, rripa sipa, int cid,RNEIGH *rnbr){ word afi = WFROMPDU(&ripa->ra_afi1); rripa ipadd = XIPA(&ripa->ra_ipa3); dword met = DWFROMPDU(&ripa->ra_met3); rripa mask,nhop; IPNA ipna; word tag; int rc; /* validate afi */ if(afi != RIP_AFI_IP){ return; } /* validate metric */ if(!met || met > RIP_INFINITE){ return; } /* validate all 'must be 0' */ if(ripvers == 1){ /* already did verify */ tag = 0; } else{ tag = 0; } /* validate address */ /* no loopback */ if( (ipadd & IP_CLASS_A_MSK) == IP_LOOP ){ rnbr->n_badroutes++;#ifdef SNMP loc_circ->rc_ripRcvBadRoutes++;#endif return; } /* 0 network (except default) */ if( !(ipadd & IP_CLASS_A_MSK) && ipadd ){ rnbr->n_badroutes++;#ifdef SNMP loc_circ->rc_ripRcvBadRoutes++;#endif return; } /* before proceeding, we need to determine the subnet mask of the route. If we are on a subnet and the route has the same network number portion, then the mask is our subnet mask. If its longer than the class mask, but not in our subner, its a host route. Otherwise, it is the default class mask. */ if( ripvers == 2 ){ mask = XIPA(&ripa->ra_msk3); } else if(!ipadd){ mask = 0; } else if( (ipadd & loc_class_mask) == (loc_net & loc_class_mask) ){ /* subnet */ mask = loc_mask; } else{ IP_CLASS_MASK(&ipadd, &mask); } /* validate not broadcast */ if( (mask & ipadd) == 0xffffffff ){ rnbr->n_badroutes++;#ifdef SNMP loc_circ->rc_ripRcvBadRoutes++;#endif return; } /* validate not class d or e */ if( (ripa->ra_ipa3 & IP_EXT_ADD) == IP_EXT_ADD ){ rnbr->n_badroutes++;#ifdef SNMP loc_circ->rc_ripRcvBadRoutes++;#endif return; } /* disallow net directed broadcast for v1 */ if(ripvers == 1 && ((~mask & ipadd) == (~mask & 0xffffffff)) ){ rnbr->n_badroutes++;#ifdef SNMP loc_circ->rc_ripRcvBadRoutes++;#endif return; } /* this may be a host route. the way we tell is if there are bits outside the mask we have determined. If it is a host route, set the mask to all 1's. */ if( ~mask & ipadd ){ mask = 0xffffffff; } /* inc cost */ met = MIN(met +1, RIP_INFINITE); /* check nexthop: this can be viewed in one of two ways: 1) a field to be put in the route's next hop, but still treat the source of the route as the advertising router. 2) treat the entry as being a proxy for the advertised nexthop. in this case the "source" of the route and its nexthop are the same, ie the nexthop contained in the update. The advantage of case 1 above is that you can differentiate between two routers that advertise the same next hop. */ nhop = XIPA(&ripa->ra_nh3); if(nhop){ /* verify nexthop on this network */ if((nhop & loc_mask) != (loc_net & loc_mask)){ nhop = sipa; } } else{ nhop = sipa; } /* check input distribute list, info from peer may be filtered */ if(loc_circ->rc_distlist_in){ rc = ipAccessListCheck(loc_circ->rc_distlist_in, ipadd,mask); if(rc == IPAL_DENY){ /* ignore input route */ return; } } /* look for existing route, add or replace */ ipna.ip_add = ipadd; ipna.ip_mask = mask; RipProcIpa(&ipna, met, sipa, nhop, cid, tag);}/************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -