📄 rrriptx.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: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 + -