📄 ip_mroute.c
字号:
port, rt->mfc_parent, 3,4,5,6 ); if ( (xmt_vif < numvifs) || (rt == NULL) ) {/* rt== NULL makes up for missing xmit vif in x_ip_mforward */ MRTDEBUG ( (mrtdebug), "MROUTE: MDQ sending packet on VIF, xmt_vif=%i, numvifs=%i.\n", xmt_vif, numvifs, 3,4,5,6 ); MC_SEND(ip, viftable + xmt_vif, m); forwarded ++; return 1; } /* * Don't forward if it didn't arrive from the parent vif for its origin. */ vifi = rt->mfc_parent; if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { /* came in the wrong interface */ MRTDEBUG ( (mrtdebug), "MROUTE: wrong if: ifp %p vifi %d vififp %p\n", (int)ifp, vifi, (int)viftable[vifi].v_ifp, 4,5,6 ); ++mrtstat.mrts_wrong_if; ++rt->mfc_wrong_if; /* * If we are doing PIM assert processing, and we are forwarding * packets on this interface, and it is a broadcast medium * interface (and not a tunnel), send a message to the routing daemon. */ if (pim_assert && rt->mfc_ttls[port] && (ifp->if_flags & IFF_BROADCAST) && !(viftable[vifi].v_flags & VIFF_TUNNEL)) { pimNotify(ip, m, rt, vifi, ifp); } return 0; } vifi_original = vifi; /* If I sourced this packet, it counts as output, else it was input. */ if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { viftable[vifi].v_pkt_out++; viftable[vifi].v_bytes_out += plen; } else { viftable[vifi].v_pkt_in++; viftable[vifi].v_bytes_in += plen; } rt->mfc_pkt_cnt++; rt->mfc_byte_cnt += plen; /* * For each vif, decide if a copy of the packet should be forwarded. * Forward if: * - the ttl exceeds the vif's threshold * - there are group members downstream on interface */ MRTDEBUG ( (mrtdebug), "MROUTE: MDQ iterating through vifs to find oifs.\n", 1,2,3,4,5,6 ); for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) { MRTDEBUG ( (mrtdebug), "MROUTE: mdq vif %i has forward threshold %i. ip->ttl=%i, parent=%i.\n", vifi, rt->mfc_ttls[vifi], ip->ip_ttl, rt->mfc_parent, 5,6 ); if ( (rt->mfc_ttls[vifi] > 0) &&(ip->ip_ttl > rt->mfc_ttls[vifi]) &&(vifi != rt->mfc_parent) ) { vifp->v_pkt_out++; vifp->v_bytes_out += plen; MRTDEBUG ( (mrtdebug), "MROUTE: sending packet out vif %i name %s , ifp=%p.\n", vifi, (int)vifp->v_ifp->if_name, (int)ifp, 4,5,6 ); old_len = ip->ip_len; MC_SEND(ip, vifp, m); if (old_len != ip->ip_len) { HTONS(ip->ip_len);/* the kernel sometimes changes the byte ordering, so we have to change it back */ HTONS(ip->ip_off); } ip->ip_ttl ++; /* compensate for -1 in send routine */ forwarded ++; } } MRTDEBUG ( (mrtdebug), "MROUTE: MDQ forwarded %i times.\n", forwarded, 2,3,4,5,6 ); return 0;}/* * check if a vif number is legal/ok. This is used by ip_output, to export * numvifs there, */static intX_legal_vif_num(vif) int vif;{ if (vif >= 0 && vif < numvifs) return(1); else return(0);}int (*legal_vif_num)(int) = X_legal_vif_num;/* * Return the local address used by this vif */static u_longX_ip_mcast_src(vifi) int vifi;{ if (vifi >= 0 && vifi < numvifs) return viftable[vifi].v_lcl_addr.s_addr; else return INADDR_ANY;}static voidphyint_send(ip, vifp, m) struct ip *ip; struct vif *vifp; struct mbuf *m;{ struct mbuf *mb_copy; int hlen = ip->ip_hl << 2; /* * Make a new reference to the packet; make sure that * the IP header is actually copied, not just referenced, * so that ip_output() only scribbles on the copy. */ mb_copy = m_copy(m, 0, M_COPYALL); if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen)) mb_copy = m_pullup(mb_copy, hlen); if (mb_copy == NULL) return; if (vifp->v_rate_limit == 0) tbf_send_packet(vifp, mb_copy); else tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len);}static voidencap_send(ip, vifp, m) struct ip *ip; struct vif *vifp; struct mbuf *m;{ struct mbuf *mb_copy; struct ip *ip_copy; int i, len = ip->ip_len; /* * copy the old packet & pullup its IP header into the * new mbuf so we can modify it. Try to fill the new * mbuf since if we don't the ethernet driver will. */ MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER); if (mb_copy == NULL) return; mb_copy->m_data += max_linkhdr; mb_copy->m_len = sizeof(multicast_encap_iphdr); if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { m_freem(mb_copy); return; } i = MHLEN - M_LEADINGSPACE(mb_copy); if (i > len) i = len; mb_copy = m_pullup(mb_copy, i); if (mb_copy == NULL) return; mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr); /* * fill in the encapsulating IP header. */ ip_copy = mtod(mb_copy, struct ip *); *ip_copy = multicast_encap_iphdr;#ifndef VIRTUAL_STACK ip_copy->ip_id = htons(ip_id++);#else ip_copy->ip_id = htons(_ip_id++);#endif ip_copy->ip_len += len; ip_copy->ip_src = vifp->v_lcl_addr; ip_copy->ip_dst = vifp->v_rmt_addr; /* * turn the encapsulated IP header back into a valid one. */ ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr)); --ip->ip_ttl; HTONS(ip->ip_len); HTONS(ip->ip_off); ip->ip_sum = 0; mb_copy->m_data += sizeof(multicast_encap_iphdr); ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); mb_copy->m_data -= sizeof(multicast_encap_iphdr); if (vifp->v_rate_limit == 0) tbf_send_packet(vifp, mb_copy); else tbf_control(vifp, mb_copy, ip, ip_copy->ip_len);}/* * De-encapsulate a packet and feed it back through ip input (this * routine is called whenever IP gets a packet with proto type * ENCAP_PROTO and a local destination address). */voidipip_input(m, iphlen) struct mbuf *m; int iphlen;{ struct ifnet *ifp = m->m_pkthdr.rcvif; struct ip *ip = mtod(m, struct ip *); int hlen = ip->ip_hl << 2; int s; struct ifqueue *ifq; struct vif *vifp; if (!have_encap_tunnel) { rip_input(m); return; } /* * dump the packet if it's not to a multicast destination or if * we don't have an encapsulating tunnel with the source. * Note: This code assumes that the remote site IP address * uniquely identifies the tunnel (i.e., that this site has * at most one tunnel with the remote site). */ if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) { ++mrtstat.mrts_bad_tunnel; m_freem(m); return; } if (ip->ip_src.s_addr != last_encap_src) { struct vif *vife; vifp = viftable; vife = vifp + numvifs; last_encap_src = ip->ip_src.s_addr; last_encap_vif = 0; for ( ; vifp < vife; ++vifp) if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) { if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT)) == VIFF_TUNNEL) last_encap_vif = vifp; break; } } if ((vifp = last_encap_vif) == 0) { last_encap_src = 0; mrtstat.mrts_cant_tunnel++; /*XXX*/ m_freem(m); MRTDEBUG ( (mrtdebug), "MROUTE: ip_mforward: no tunnel with %lx\n", (u_long)ntohl(ip->ip_src.s_addr), 2,3,4,5,6 ); return; } ifp = vifp->v_ifp; if (hlen > IP_HDR_LEN) ip_stripoptions(m, (struct mbuf *) 0); m->m_data += IP_HDR_LEN; m->m_len -= IP_HDR_LEN; m->m_pkthdr.len -= IP_HDR_LEN; m->m_pkthdr.rcvif = ifp; ifq = &ipintrq; s = splimp(); if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m); } else { IF_ENQUEUE(ifq, m); /* * normally we would need a "schednetisr(NETISR_IP)" * here but we were called by ip_input and it is going * to loop back & try to dequeue the packet we just * queued as soon as we return so we avoid the * unnecessary software interrrupt. */ } splx(s);}static BOOL oifListIsEmpty ( struct mfc* rt ) { int i; int j = 0; if (rt == NULL) return (TRUE); for (i=0;i<numvifs; i++) { j+=rt->mfc_ttls[i]; } if (j == 0) return (TRUE); return(FALSE);}static void mRouteDumpMfctable(){ int i; int j; struct mfc* rt; vifi_t vifi; struct vif *vifp; MRTDEBUG ( (1), "MROUTE: IP_MROUTE dumping mfctable.\n", 1,2,3,4,5,6 ); for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) { MRTDEBUG ( (1), "MROUTE: vif %i is named %s%i.\n", vifi, (int)vifp->v_ifp->if_name, vifp->v_ifp->if_index, 4,5,6 ); } for (i=0;i<MFCTBLSIZ; i++) { if (mfctable[i] != NULL) { MRTDEBUG ( (1), "MROUTE: mfctable postion %i.\n", i, 2,3,4,5,6 ); for (rt = mfctable[i]; rt != NULL; rt = rt->mfc_next) { MRTDEBUG ( (1), "MROUTE: \tEntry g=%p, s=%p.\n", ntohl(rt->mfc_mcastgrp.s_addr), ntohl(rt->mfc_origin.s_addr), 3,4,5,6 ); MRTDEBUG ( (1), "MROUTE: \t\t OIFLIST=",1,2,3,4,5,6 ); for (j=0;j<=numvifs; j++) MRTDEBUG ( (1), "vif %i ttl=%i,",j,(int)rt->mfc_ttls[j],3,4,5,6 ); MRTDEBUG ( (1), "MROUTE: \n.", 1,2,3,4,5,6 ); } } }}/* * Token bucket filter module */static voidtbf_control(vifp, m, ip, p_len) struct vif *vifp; struct mbuf *m; struct ip *ip; u_long p_len;{ struct tbf *t = vifp->v_tbf; if (p_len > MAX_BKT_SIZE) { /* drop if packet is too large */ mrtstat.mrts_pkt2large++; m_freem(m); return; } tbf_update_tokens(vifp); /* if there are enough tokens, * and the queue is empty, * send this packet out */ if (t->tbf_q_len == 0) { /* queue empty, send packet if enough tokens */ if (p_len <= t->tbf_n_tok) { t->tbf_n_tok -= p_len; tbf_send_packet(vifp, m); } else { /* queue packet and timeout till later */ tbf_queue(vifp, m); timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); } } else if (t->tbf_q_len < t->tbf_max_q_len) { /* finite queue length, so queue pkts and process queue */ tbf_queue(vifp, m); tbf_process_q(vifp); } else { /* queue length too much, try to dq and queue and process */ if (!tbf_dq_sel(vifp, ip)) { mrtstat.mrts_q_overflow++; m_freem(m); return; } else { tbf_queue(vifp, m); tbf_process_q(vifp); } } return;}/* * adds a packet to the queue at the interface */static voidtbf_queue(vifp, m) struct vif *vifp; struct mbuf *m;{ int s = splnet(); struct tbf *t = vifp->v_tbf; if (t->tbf_t == NULL) { /* Queue was empty */ t->tbf_q = m; } else { /* Insert at tail */ t->tbf_t->m_act = m; } /* Set new tail pointer */ t->tbf_t = m;#ifdef DIAGNOSTIC /* Make sure we didn't get fed a bogus mbuf */ if (m->m_act) panic("tbf_queue: m_act");#endif m->m_act = NULL; t->tbf_q_len++; splx(s);}/* * processes the queue at the interface */static voidtbf_process_q(vifp) struct vif *vifp;{ struct mbuf *m; int len; int s = splnet(); struct tbf *t = vifp->v_tbf; /* loop through the queue at the interface and send as many packets * as possible *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -