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

📄 rrriptx.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:52 $*  $Source: M:/psisrc/routing/rip/rcs/rrriptx.c $*  $Revision: 1.9 $****************************************************************************  File Description: RIP packet transmission routines ***************************************************************************/#include <riproute.h>#include <ipaccess.h>#include <ipsec.h>fnc_prot(rcirc_pt, ripCircFromId, (int))/**********************************************riptx:builds and transmits a rip response PDU on agiven circuit.If enabled, implements split-horizon  with poisonedreverse, otherwise implements just split-horizon.If routing table contains more than 25 routes, multiplepdus are generated.ipna = source address/maskcid  = dest circ idtrig = true if triggered updatedadd = dest ip address or 0 if broadcastdport = dest portdoinf = true if shutting down, should set all        metrics to infinite **********************************************/void riptx(ipna_pt ipna,int cid, int trig, rripa dadd,word dport,int doinf){	ibd_pt rip_bd;	rpdu_pt rpdu;	iproute_ent_pt iprt;	ripa_pt radd, start;	int len,met;	int num_ipadd = 0;	rripa ipadd;	rcirc_pt rc;	rripa lmask, lnet,lclass_mask, mask,xmask;	int have_hdr = FALSE;	MD5_CTX context;	rripa sipa,nhop;	RNEIGH *rnbr,*rnfwd;	iproute_ent_pt grt;	int  rval;    use_critical;	rc = ripCircFromId(cid);	if(r_node->rn_radmst != ROUTER_ON) return;	/* must be on and talking */	if(rc->rc_state != RCIRC_UP || !rc->rc_talk){		return;	}	if(trig){#ifdef SNMP_PROTOCOL		rc->rc_ripSentUpdates++;#endif	}	else{		/* age nbr structs */		for(rnbr = rc->rc_nbr_fwd; rnbr; rnbr = rnfwd){			rnfwd = rnbr->n_fwd;			if(rnbr->n_tstamp + 180 < r_node->rn_tics){				rrULink((dll_pt)rnbr,(dll_pt)&rc->rc_nbr_fwd);				RipNeighFree(rnbr);			}		}	}	/* make broadcast addr */	if(!dadd){		/* always broadcast on ptpt links because		   they may be un-numbered.		*/		if(rc->rc_type == RCIRC_PTPT){			DWTOPDU(&dadd,0xffffffff);		}		/* if rip2 tx mode = rip2, send mcast */		else if(rc->rc_r2txmode == R2M_TXV2){			DWTOPDU(&dadd,RIPV2_MCAST);		}		else{			/* local broadcast */			dadd = ipna->ip_add & ipna->ip_mask;			dadd |= ~ipna->ip_mask;		}	}	if(!dport){		dport = RIP_PORT;	}	/* determine our subnet mask and mask	   for our class */	lmask = ipna->ip_mask;	lnet  = ipna->ip_add & lmask;	IP_CLASS_MASK(&ipna->ip_add,&lclass_mask);    critical;	/* look at each route in table regardless of owner */	RT_TABLEWALK			/* check distribute list */			if(rc->rc_distlist_out){				rval = ipAccessListCheck(rc->rc_distlist_out,					   RT_DEST(iprt),RT_MASK(iprt));				if(rval == IPAL_DENY){					/* ignore route */					continue;				}			}			/* ignore bcast/multicast */			if( (RT_OWNER(iprt) == IPRT_LOCAL)				 && RT_IS_BCAST(iprt)){				continue;			}			/* Ignore localhost */			if( (RT_OWNER(iprt) == IPRT_LOCAL) 				&& ((RT_DEST(iprt) & IP_CLASS_A_MSK) == IP_LOOP) ) {				continue;			}			/* determine metric to use, if > infinite,			   dont use. if doinf, circuit is going			   down, all met = inf. */			if(!doinf){				if( (met = RipMetric(iprt)) > RIP_INFINITE){					continue;				}			}			else{				met = RIP_INFINITE;			}			/* if this is a triggered update, send only			   routes owned by RIP (leaked routes must			   wait) that have the change flag (level			   field used for this) set.			*/			if( trig ){				if(RT_OWNER(iprt) != IPRT_RIP){					if(RT_IS_TRIG(iprt,IPRT_RIP_CHANGED) &&					   RT_IS_TRIG(iprt,IPRT_RIP_IMPORT)){						/* if route in garbage						collection list, delete */						grt = ripFindGarbageList(						     RT_DEST(iprt),						     RT_MASK(iprt));						if(grt) ripRmGarbageList(grt);					}					continue;				}				else if(!RT_IS_TRIG(iprt,IPRT_RIP_CHANGED)){					continue;				}			}			/* reset change flag for rip owned routes.			   Only do this for timed updates because			   riptx is called for each port and we			   have no way of knowing in here what the			   last port is.			*/			else if( RT_OWNER(iprt) == IPRT_RIP ){				RT_TRIG_CLR(iprt,IPRT_RIP_CHANGED);			}			if( RT_OWNER(iprt) != IPRT_RIP ){				/* dont include external routes that				   have not been imported				*/				if(!RT_IS_TRIG(iprt,IPRT_RIP_IMPORT))					continue;			}			/* WE MAY HAVE ROUTES FROM OTHER			   THAN RIP IN THE FDB,			   truncate down to network # if not on			   our subnet, down to our subnet			   mask if in our subnet */			if(rc->rc_r2txmode == R2M_TXV2){				ipadd = RT_DEST(iprt);				mask  = RT_MASK(iprt);			}			else{				/* a real host route */				if( ~RT_MASK(iprt) == 0 ){					ipadd = RT_DEST(iprt);					mask = RT_MASK(iprt);				}				else if( (RT_DEST(iprt) & lclass_mask) ==				    (lnet & lclass_mask) ){					/* same net, diffenent subnet,				        use our subnet mask */					ipadd = RT_DEST(iprt) & lmask;					mask = lmask;				}				else{					/* Truncate add & mask down to class				  	 mask. This does not affect				  	 non-subnets and supernets.					*/					IP_CLASS_MASK(&RT_DEST(iprt), &xmask);					ipadd = RT_DEST(iprt) & xmask;					mask  = RT_MASK(iprt) & xmask;				}				/* make be duplicates due to truncation,				   filter them */				if( have_hdr && RipInPdu(ipadd, start, num_ipadd)){					continue;				}			}						/* dont include yourself			   (but make sure can include default			    on unnumbered link			*/			if((ipadd ==  lnet) && lnet){				continue;			}				/* implement poison and split horizon */			/* To check whether we need to do something			   we look at the (sub)network number of the			   source and compare it with our network			   number. We cannot just check circuit ID			   because we can be multi-homed and the			   results will be different for each			   of our IP addresses.			*/			/* only applies to RIP routes */			if(RT_OWNER(iprt) == IPRT_RIP &&			   iprt->iprt_cid != INVALID_CIRC){				/* if its a ptpt link, poison anything				   whose next hop is this circ.				   ( this addition allows unnumbered					RIP)				*/				if( !(rc->rc_type & RCIRC_LAN) ){					if(RT_TOS0_NHCID(iprt) == cid){						if(rc->rc_poison){							/* infinite metric */							met = RIP_INFINITE;						}						else{							/* dont include route */							continue;						}					}				}				/* now do normal multihome processing */				else if((RT_TOS0_NHIPA(iprt) & lmask) == lnet){					if(rc->rc_poison){						/* infinite metric */						met = RIP_INFINITE;					}					else{						/* dont include route */						continue;					}				}			}			/* build a header if we dont have one */			if(!have_hdr){				/* allocate max len */				if( (rip_bd= (ibd_pt)ripOfAlloc(MAX_RIP_LEN)) == 0){                    normal;					return;				}				rpdu = (rpdu_pt)rip_bd->ibd_buf;					/* build header ,version1 or 2 */				rpdu->rp_cmd = RIP_CMD_RSP;				if(rc->rc_r2txmode == R2M_TXV1){					rpdu->rp_ver = 1;					rpdu->rp_rd1 = rpdu->rp_rd0 = 0;				}				else{					rpdu->rp_ver = 2;					WTOPDU(&rpdu->rp_rd1,r_node->rn_rdom);				}				start = radd = (ripa_pt)((byte *)rpdu + RIP_HLEN);				if(rc->rc_auth_type == RIP_AUTH_SIMPLE &&				   rc->rc_r2txmode != R2M_TXV1){					/* add an auth entry */					WTOPDU(&radd->ra_afi1, RIP_AFI_AUTH);					WTOPDU(&radd->ra_tag1,rc->rc_auth_type);					rrCopyMem(&radd->ra_ipa3,					          rc->rc_auth_key,16);					radd = ROPT_FWD(radd);					start = radd;					num_ipadd++;				}				else if(rc->rc_auth_type == RIP_AUTH_MD5 &&				   rc->rc_r2txmode != R2M_TXV1){					/* add an auth entry, fill					   in signature before transmit */					WTOPDU(&radd->ra_afi1, RIP_AFI_AUTH);					WTOPDU(&radd->ra_tag1,rc->rc_auth_type);					rrFillMem(&radd->ra_ipa3,0,16);					radd = ROPT_FWD(radd);					start = radd;					num_ipadd++;				}				have_hdr = TRUE;			}			/* fill in IP address option */			WTOPDU(&radd->ra_afi1, RIP_AFI_IP);			WIPA(&radd->ra_ipa3,ipadd);			DWTOPDU(&radd->ra_met3, met);				if(rc->rc_r2txmode == R2M_TXV1){				WIPA(&radd->ra_nh3,0);				WTOPDU(&radd->ra_tag1,0);				DWTOPDU(&radd->ra_msk3,0);			}			else{				if(RT_OWNER(iprt) != IPRT_RIP &&				   RT_OWNER(iprt) != IPRT_LOCAL &&				   RT_TOS0_NHCID(iprt) == cid){					/* route from other prots can				        go directly to next hop */					nhop = RT_TOS0_NHIPA(iprt);				}				else{					nhop = 0;				}				WIPA(&radd->ra_nh3,nhop);				WTOPDU(&radd->ra_tag1,RT_TAG(iprt));				WIPA(&radd->ra_msk3,mask);			}			radd = ROPT_FWD(radd);			if(++num_ipadd >= RIP_MAX_IPADD){				/* pdu full, send it */				len = RIP_HLEN + (num_ipadd * RIP_OPT_LEN); 				/* if md5, need to gen sig now */				if(rc->rc_auth_type == RIP_AUTH_MD5){					MD5Init(&context);					MD5Update(&context,(byte *)start,				       len - RIP_OPT_LEN - RIP_HLEN);					MD5Update(&context,rc->rc_auth_key,16);					start = (ripa_pt)((byte *)start - RIP_OPT_LEN);					/* Fusion MD5 is slightly different.  The digest					   is contained in the MD5_CTX structure.										MD5Final(((unsigned char *)&start->ra_ipa3),&context);					*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -