⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rrriprx.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 2 页
字号:
/**            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 + -