📄 rrriptx.c
字号:
MD5Final(&context); rrCopyMem((unsigned char *)&start->ra_ipa3, context.digest, 16 ); } /* for src addr, use config src addr if we are unnumbered */ if(!ipna->ip_add){ /* this may also be unconfigured, in which case ip uses routerid */ sipa = rc->rc_srcipa; } else{ sipa = ipna->ip_add; } udptx(rip_bd,len,dport,RIP_PORT, dadd,sipa,cid,DELETE); num_ipadd = 0; have_hdr = 0; } RT_TABLEWALKEND normal; /* look at each route in the garbage collection list */ for(iprt= r_node->rn_garb_fwd; iprt; iprt= iprt->iprt_gfwd){ 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_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); } /* 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; } } /* build a header if we dont have one */ if(!have_hdr){ /* allocate max len */ if( (rip_bd= (ibd_pt)ripOfAlloc(MAX_RIP_LEN)) == 0){ 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,(unsigned char *)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); */ MD5Final(&context); rrCopyMem((unsigned char *)&start->ra_ipa3, context.digest, 16 ); } /* for src addr, use config src addr if we are unnumbered */ if(!ipna->ip_add){ /* this may also be unconfigured, in which case ip uses routerid */ sipa = rc->rc_srcipa; } else{ sipa = ipna->ip_add; } udptx(rip_bd,len,dport,RIP_PORT, dadd,sipa,cid,DELETE); num_ipadd = 0; have_hdr = 0; } } /* send off to udp if anything in last fragment */ if(num_ipadd){ 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,(unsigned char *)start, len - RIP_OPT_LEN - RIP_HLEN); MD5Update(&context,(unsigned char *)rc->rc_auth_key,16); start = (ripa_pt)((unsigned char *)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); */ MD5Final(&context); rrCopyMem((unsigned char *)&start->ra_ipa3, context.digest, 16 ); } /* for src addr, use config src addr if we are unnumbered */ if(!ipna->ip_add){ /* this may also be unconfigured, in which case ip uses routerid */ sipa = rc->rc_srcipa; } else{ sipa = ipna->ip_add; } udptx(rip_bd,len,dport,RIP_PORT, dadd,sipa,cid,DELETE); }}/*********************************************************RipMetric:get metric value for a route.If owner is RIP, use value in table.If directly connected, use 1.If ISIS and internal type, use rnode.rn_impmet.If ISIS and external, use value in table.********************************************************/int RipMetric(iproute_ent_pt iprt){ /* compiler seems to have problem with switch statement */ /* rip is owner */ if(RT_OWNER(iprt) == IPRT_RIP){ return(RT_TOS0_COST(iprt)); } /* direct net */ else if(RT_OWNER(iprt) == IPRT_LOCAL){ return(1); } /* static */ else if(RT_OWNER(iprt) == IPRT_STATIC){ return(RT_TOS0_COST(iprt)); } else if(RT_OWNER(iprt) == IPRT_STATICLOW){ return(RT_TOS0_COST(iprt)); } /* ISIS is owner */ else if(RT_OWNER(iprt) == IPRT_ISIS){ /* internal */ if(RT_IS_INTERNAL(iprt)){ return(r_node->rn_impmet); } } else if(RT_OWNER(iprt) == IPRT_OSPF){ /* internal */ if(RT_IS_INTERNAL(iprt)){ return(r_node->rn_impmet); } else{ return(RT_COST2(iprt)); } } else if(RT_OWNER(iprt) == IPRT_BGP){ return(r_node->rn_impmet); } else{ return(RIP_INFINITE +1); } /* for compiler */ return(0);}/**********************************************RipInPdu:determines if address has already been added to pdu.**********************************************/int RipInPdu(rripa ipadd,ripa_pt ripa, int num){ int i; for(i = 0; i < num; i++, ripa++){ if( XIPA(&ripa->ra_ipa3) == ipadd) return(TRUE); } return(FALSE);}/**********************************************RipTxReq:builds and transmits a rip gen request PDU on agiven circuit.**********************************************/void RipTxReq(ipna_pt ipna,int cid){ ibd_pt rip_bd; rpdu_pt rpdu; ripa_pt radd; int len; rcirc_pt rc; rripa dadd; if(r_node->rn_radmst != ROUTER_ON) return; rc = ripCircFromId(cid); /* must be on and talking */ if (!rc || rc->rc_state != RCIRC_UP || !rc->rc_talk) { return; } /* allocate max*/ len = RIP_HLEN +RIP_OPT_LEN; if ((rip_bd = (ibd_pt) ripOfAlloc(len)) == 0) { return; } rpdu = (rpdu_pt) rip_bd->ibd_buf; /* build header */ rpdu->rp_cmd = RIP_CMD_REQ; 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); } radd = (ripa_pt)((byte *)rpdu + RIP_HLEN); /* IP address option = all routes */ WTOPDU(&radd->ra_afi1, 0); WTOPDU(&radd->ra_tag1,0); WIPA(&radd->ra_ipa3,0); DWTOPDU(&radd->ra_msk3,0); DWTOPDU(&radd->ra_nh3,0); DWTOPDU(&radd->ra_met3, RIP_INFINITE); /* broadcast dest */ /* always 255.255.255.255 broadcast on ptpt links. 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; } udptx(rip_bd,len,RIP_PORT,RIP_PORT, dadd,ipna->ip_add,cid,DELETE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -