📄 ip_mroute.c
字号:
= INADDR_ANY; ifp = viftable[vifi].v_ifp; (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); } } bzero((caddr_t)tbftable, sizeof(tbftable)); bzero((caddr_t)viftable, sizeof(viftable)); numvifs = 0; pim_assert = 0; untimeout(expire_upcalls, (caddr_t)NULL); /* * Free all multicast forwarding cache entries. */ for (i = 0; i < MFCTBLSIZ; i++) { mb_rt = mfctable[i]; while (mb_rt) { if (mb_rt->m_act != NULL) { while (mb_rt->m_act) { m = mb_rt->m_act; mb_rt->m_act = m->m_act; rte = mtod(m, struct rtdetq *); m_freem(rte->m); m_free(m); } } mb_rt = m_free(mb_rt); } } bzero((caddr_t)mfctable, sizeof(mfctable)); /* * Reset de-encapsulation cache */ last_encap_src = 0; last_encap_vif = NULL; have_encap_tunnel = 0; ip_mrouter = NULL; splx(s); if (mrtdebug) log(LOG_DEBUG, "ip_mrouter_done\n"); return 0;}#ifndef MROUTE_LKMint (*ip_mrouter_done)(void) = X_ip_mrouter_done;#endifstatic intget_version(mb) struct mbuf *mb;{ int *v; v = mtod(mb, int *); *v = 0x0305; /* XXX !!!! */ mb->m_len = sizeof(int); return 0;}/* * Set PIM assert processing global */static intset_assert(i) int *i;{ if ((*i != 1) && (*i != 0)) return EINVAL; pim_assert = *i; return 0;}/* * Get PIM assert processing global */static intget_assert(m) struct mbuf *m;{ int *i; i = mtod(m, int *); *i = pim_assert; return 0;}/* * Add a vif to the vif table */static intadd_vif(vifcp) register struct vifctl *vifcp;{ register struct vif *vifp = viftable + vifcp->vifc_vifi; static struct sockaddr_in sin = {sizeof sin, AF_INET}; struct ifaddr *ifa; struct ifnet *ifp; struct ifreq ifr; int error, s; struct tbf *v_tbf = tbftable + vifcp->vifc_vifi; if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL; if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE; /* Find the interface with an address in AF_INET family */ sin.sin_addr = vifcp->vifc_lcl_addr; ifa = ifa_ifwithaddr((struct sockaddr *)&sin); if (ifa == 0) return EADDRNOTAVAIL; ifp = ifa->ifa_ifp; if (vifcp->vifc_flags & VIFF_TUNNEL) { if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) { /* * An encapsulating tunnel is wanted. Tell ipip_input() to * start paying attention to encapsulated packets. */ if (have_encap_tunnel == 0) { have_encap_tunnel = 1; for (s = 0; s < MAXVIFS; ++s) { multicast_decap_if[s].if_name = "mdecap"; multicast_decap_if[s].if_unit = s; } } /* * Set interface to fake encapsulator interface */ ifp = &multicast_decap_if[vifcp->vifc_vifi]; /* * Prepare cached route entry */ bzero(&vifp->v_route, sizeof(vifp->v_route)); } else { log(LOG_ERR, "source routed tunnels not supported\n"); return EOPNOTSUPP; } } else { /* Make sure the interface supports multicast */ if ((ifp->if_flags & IFF_MULTICAST) == 0) return EOPNOTSUPP; /* Enable promiscuous reception of all IP multicasts from the if */ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; s = splnet(); error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); splx(s); if (error) return error; } s = splnet(); /* define parameters for the tbf structure */ vifp->v_tbf = v_tbf; GET_TIME(vifp->v_tbf->tbf_last_pkt_t); vifp->v_tbf->tbf_n_tok = 0; vifp->v_tbf->tbf_q_len = 0; vifp->v_tbf->tbf_max_q_len = MAXQSIZE; vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL; vifp->v_flags = vifcp->vifc_flags; vifp->v_threshold = vifcp->vifc_threshold; vifp->v_lcl_addr = vifcp->vifc_lcl_addr; vifp->v_rmt_addr = vifcp->vifc_rmt_addr; vifp->v_ifp = ifp; /* scaling up here allows division by 1024 in critical code */ vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000; vifp->v_rsvp_on = 0; vifp->v_rsvpd = NULL; /* initialize per vif pkt counters */ vifp->v_pkt_in = 0; vifp->v_pkt_out = 0; vifp->v_bytes_in = 0; vifp->v_bytes_out = 0; splx(s); /* Adjust numvifs up if the vifi is higher than numvifs */ if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; if (mrtdebug) log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n", vifcp->vifc_vifi, ntohl(vifcp->vifc_lcl_addr.s_addr), (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask", ntohl(vifcp->vifc_rmt_addr.s_addr), vifcp->vifc_threshold, vifcp->vifc_rate_limit); return 0;}/* * Delete a vif from the vif table */static intdel_vif(vifip) vifi_t *vifip;{ register struct vif *vifp = viftable + *vifip; register vifi_t vifi; register struct mbuf *m; struct ifnet *ifp; struct ifreq ifr; int s; if (*vifip >= numvifs) return EINVAL; if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL; s = splnet(); if (!(vifp->v_flags & VIFF_TUNNEL)) { ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; ifp = vifp->v_ifp; (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); } if (vifp == last_encap_vif) { last_encap_vif = 0; last_encap_src = 0; } /* * Free packets queued at the interface */ while (vifp->v_tbf->tbf_q) { m = vifp->v_tbf->tbf_q; vifp->v_tbf->tbf_q = m->m_act; m_freem(m); } bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf))); bzero((caddr_t)vifp, sizeof (*vifp)); /* Adjust numvifs down */ for (vifi = numvifs; vifi > 0; vifi--) if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break; numvifs = vifi; splx(s); if (mrtdebug) log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs); return 0;}/* * Add an mfc entry */static intadd_mfc(mfccp) struct mfcctl *mfccp;{ struct mfc *rt; register struct mbuf *mb_rt; u_long hash; struct mbuf *mb_ntry; struct rtdetq *rte; register u_short nstl; int s; int i; MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt); /* If an entry already exists, just update the fields */ if (rt) { if (mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"add_mfc update o %x g %x p %x\n", ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent); s = splnet(); rt->mfc_parent = mfccp->mfcc_parent; for (i = 0; i < numvifs; i++) rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; splx(s); return 0; } /* * Find the entry for which the upcall was made and update */ s = splnet(); hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); for (mb_rt = mfctable[hash], nstl = 0; mb_rt; mb_rt = mb_rt->m_next) { rt = mtod(mb_rt, struct mfc *); if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && (mb_rt->m_act != NULL)) { if (nstl++) log(LOG_ERR, "add_mfc %s o %x g %x p %x dbx %x\n", "multiple kernel entries", ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent, mb_rt->m_act); if (mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"add_mfc o %x g %x p %x dbg %x\n", ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent, mb_rt->m_act); rt->mfc_origin = mfccp->mfcc_origin; rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; rt->mfc_parent = mfccp->mfcc_parent; for (i = 0; i < numvifs; i++) rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; /* initialize pkt counters per src-grp */ rt->mfc_pkt_cnt = 0; rt->mfc_byte_cnt = 0; rt->mfc_wrong_if = 0; rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; rt->mfc_expire = 0; /* Don't clean this guy up */ nexpire[hash]--; /* free packets Qed at the end of this entry */ while (mb_rt->m_act) { mb_ntry = mb_rt->m_act; rte = mtod(mb_ntry, struct rtdetq *);/* #ifdef RSVP_ISI */ ip_mdq(rte->m, rte->ifp, rt, -1);/* #endif */ mb_rt->m_act = mb_ntry->m_act; m_freem(rte->m);#ifdef UPCALL_TIMING collate(&(rte->t));#endif /* UPCALL_TIMING */ m_free(mb_ntry); } } } /* * It is possible that an entry is being inserted without an upcall */ if (nstl == 0) { if (mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"add_mfc no upcall h %d o %x g %x p %x\n", hash, ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent); for (mb_rt = mfctable[hash]; mb_rt; mb_rt = mb_rt->m_next) { rt = mtod(mb_rt, struct mfc *); if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { rt->mfc_origin = mfccp->mfcc_origin; rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; rt->mfc_parent = mfccp->mfcc_parent; for (i = 0; i < numvifs; i++) rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; /* initialize pkt counters per src-grp */ rt->mfc_pkt_cnt = 0; rt->mfc_byte_cnt = 0; rt->mfc_wrong_if = 0; rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; if (rt->mfc_expire) nexpire[hash]--; rt->mfc_expire = 0; } } if (mb_rt == NULL) { /* no upcall, so make a new entry */ MGET(mb_rt, M_DONTWAIT, MT_MRTABLE); if (mb_rt == NULL) { splx(s); return ENOBUFS; } rt = mtod(mb_rt, struct mfc *); /* insert new entry at head of hash chain */ rt->mfc_origin = mfccp->mfcc_origin; rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; rt->mfc_parent = mfccp->mfcc_parent; for (i = 0; i < numvifs; i++) rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; /* initialize pkt counters per src-grp */ rt->mfc_pkt_cnt = 0; rt->mfc_byte_cnt = 0; rt->mfc_wrong_if = 0; rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; rt->mfc_expire = 0; /* link into table */ mb_rt->m_next = mfctable[hash]; mfctable[hash] = mb_rt; mb_rt->m_act = NULL; } } splx(s); return 0;}#ifdef UPCALL_TIMING/* * collect delay statistics on the upcalls */static void collate(t)register struct timeval *t;{ register u_long d; register struct timeval tp; register u_long delta; GET_TIME(tp); if (TV_LT(*t, tp)) { TV_DELTA(tp, *t, delta); d = delta >> 10; if (d > 50) d = 50; ++upcall_data[d]; }}#endif /* UPCALL_TIMING *//* * Delete an mfc entry */static intdel_mfc(mfccp) struct mfcctl *mfccp;{ struct in_addr origin; struct in_addr mcastgrp; struct mfc *rt; struct mbuf *mb_rt; struct mbuf **nptr; u_long hash; int s; origin = mfccp->mfcc_origin; mcastgrp = mfccp->mfcc_mcastgrp; hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); if (mrtdebug & DEBUG_MFC) log(LOG_DEBUG,"del_mfc orig %x mcastgrp %x\n", ntohl(origin.s_addr), ntohl(mcastgrp.s_addr)); s = splnet(); nptr = &mfctable[hash]; while ((mb_rt = *nptr) != NULL) { rt = mtod(mb_rt, struct mfc *); if (origin.s_addr == rt->mfc_origin.s_addr && mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && mb_rt->m_act == NULL) break; nptr = &mb_rt->m_next; } if (mb_rt == NULL) { splx(s); return EADDRNOTAVAIL; } MFREE(mb_rt, *nptr); splx(s); return 0;}/* * Send a message to mrouted on the multicast routing socket */static intsocket_send(s, mm, src) struct socket *s; struct mbuf *mm; struct sockaddr_in *src;{ if (s) { if (sbappendaddr(&s->so_rcv, (struct sockaddr *)src, mm, (struct mbuf *)0) != 0) { sorwakeup(s); return 0; } } m_freem(mm); return -1;}/* * IP multicast forwarding function. This function assumes that the packet * pointed to by "ip" has arrived on (or is about to be sent to) the interface * pointed to by "ifp", and the packet is to be relayed to other networks * that have members of the packet's destination IP multicast group. * * The packet is returned unscathed to the caller, unless it is * erroneous, in which case a non-zero return value tells the caller to * discard it. */#define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */static intX_ip_mforward(ip, ifp, m, imo) register struct ip *ip; struct ifnet *ifp; struct mbuf *m; struct ip_moptions *imo;{ register struct mfc *rt; register u_char *ipoptions; static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; static int srctun = 0; register struct mbuf *mm; int s; vifi_t vifi; struct vif *vifp; if (mrtdebug & DEBUG_FORWARD) log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %x\n", ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp); if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { /* * Packet arrived via a physical interface or * an encapsulated tunnel. */ } else { /* * Packet arrived through a source-route tunnel. * Source-route tunnels are no longer supported. */ if ((srctun++ % 1000) == 0) log(LOG_ERR, "ip_mforward: received source-routed packet from %x\n", ntohl(ip->ip_src.s_addr)); return 1; } if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) { if (ip->ip_ttl < 255) ip->ip_ttl++; /* compensate for -1 in *_send routines */ if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { vifp = viftable + vifi; printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n", ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), vifi, (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "", vifp->v_ifp->if_name, vifp->v_ifp->if_unit); } return (ip_mdq(m, ifp, NULL, vifi)); } if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr)); if(!imo) printf("In fact, no options were specified at all\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -