📄 ip_mroute.c
字号:
); s = splnet(); if (mfccp->mfcc_origin.s_addr == 0) {/* updating a 0,g entry updates all s,g entries for that interface*/ rt->mfc_parent = mfccp->mfcc_parent; MRTDEBUG ( (mrtdebug & DEBUG_FORWARD), "MROUTE: add_mfc updating all rts %p p %x, val=%x\n", ntohl(mfccp->mfcc_mcastgrp.s_addr), rt->mfc_parent, viftable[rt->mfc_parent].v_threshold, 4,5,6 ); if (mfccp->mfcc_ttls[rt->mfc_parent] != 0) mRouteOifsAdd(rt, rt->mfc_parent, viftable[rt->mfc_parent].v_threshold); else mRouteOifsAdd(rt, rt->mfc_parent, 0); } else { for (i=0; i<numvifs; i++) {/* an s,g add/update doesn't affect other entries*/ rt->mfc_parent = mfccp->mfcc_parent; MRTDEBUG ( (mrtdebug & DEBUG_FORWARD), "MROUTE: add_mfc updating rts o=%p g=%p p %x, val=%x\n", ntohl(rt->mfc_origin.s_addr), ntohl(rt->mfc_mcastgrp.s_addr), rt->mfc_parent, viftable[rt->mfc_parent].v_threshold, 5,6 ); rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; } rt->mfc_notify = mfccp->mfcc_notify; } MRTDEBUG ( (mrtdebug & DEBUG_MFC), "MROUTE: add_mfc updated o %p g%p p%p, root_rt=%p.\n", ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), (u_long)rt->mfc_parent, (u_long)rt->mfc_root_rt, 5,6 ); 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 (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && (rt->mfc_stall != NULL)) {/* looking for entry with packet waiting on it */ if (nstl++) { MRTDEBUG ( (mrtdebug), "MROUTE: add_mfc multiple kernel entries \ o %p g %p p %x dbx %p\n", ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent, (int)rt->mfc_stall, 5,6 ); } MRTDEBUG ( (mrtdebug & DEBUG_MFC), "MROUTE: add_mfc o %p g %p p %x dbg %p\n", ntohl(mfccp->mfcc_origin.s_addr), ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent, (int)rt->mfc_stall, 5,6 ); /* copy the information into rt entry */ rt->mfc_origin = mfccp->mfcc_origin; rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; rt->mfc_notify = mfccp->mfcc_notify; if (! (mfccp->mfcc_parent > numvifs) ) /* can't be less, it's a USHORT value */ rt->mfc_parent = mfccp->mfcc_parent; if (mfccp->mfcc_origin.s_addr == 0) { MRTDEBUG ( (mrtdebug & DEBUG_FORWARD), "MROUTE: add_mfc updating rts o=%p g=%p p %x, val=%x\n", ntohl(rt->mfc_origin.s_addr), ntohl(rt->mfc_mcastgrp.s_addr), rt->mfc_parent, viftable[rt->mfc_parent].v_threshold, 5,6 ); mRouteOifsAdd(rt, rt->mfc_parent, viftable[rt->mfc_parent].v_threshold); }/* update all routes for *,g entry add */ else for (i = 0; i < numvifs; i++) { if ( (mfccp->mfcc_origin.s_addr != 0) &&(mfccp->mfcc_ttls[i] != 0) ) { MRTDEBUG ( (mrtdebug & DEBUG_FORWARD), "MROUTE: add_mfc changing rt %p,%p vif %i to %i\n", ntohl(rt->mfc_origin.s_addr), ntohl(rt->mfc_mcastgrp.s_addr), i, viftable[i].v_threshold, 5,6 ); rt->mfc_ttls[i] = viftable[i].v_threshold; }/* copy the oif list for s,g entries */ } /* 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 = 0; rt->mfc_last_assert = 0; rt->mfc_expire = 0; /* Don't clean this guy up */ nexpire[hash]--; /* free packets Qed at the end of this entry */ for (rte = rt->mfc_stall; rte != NULL; ) { struct rtdetq *n = rte->next; MRTDEBUG ( (mrtdebug & DEBUG_FORWARD), "MROUTE: add_mfc add_mfc calls ip_mdq.\n", 1,2,3,4,5,6 ); ip_mdq(rte->m, rte->ifp, rt, -1); MRTDEBUG ( (mrtdebug & DEBUG_FORWARD), "MROUTE: add_mfc add_mfc done calling ip_mdq.\n", 1,2,3,4,5,6 ); m_freem(rte->m); MRT_FREE((char*) rte); rte = n; } rt->mfc_stall = NULL; }/* dQing stall entries */ }/* for mfctable[hash] loop */ /* * It is possible that an entry is being inserted without an upcall * This would be primarily found in s,g joins from an overlying protcol * e.g. PIM */ if (nstl == 0) { MRTDEBUG ( (mrtdebug & DEBUG_MFC), "MROUTE: add_mfc no upcall h %lu o %lx g %lx p %x\n", hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr), (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), mfccp->mfcc_parent, 5,6 ); for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) { if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { for (i = 0; i < numvifs; i++) {/* if the entry exists, copy the oiflist */ if (mfccp->mfcc_ttls[i] != 0) rt->mfc_ttls[i] = viftable[i].v_threshold; else rt->mfc_ttls[i] = 0; } /* 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 = 0; rt->mfc_last_assert = 0; if (rt->mfc_expire) nexpire[hash]--; rt->mfc_expire = 0; } } if (rt == NULL) { /* no upcall, so make a new entry */ rt = MRT_ALLOC(sizeof(struct mfc)); if (rt == NULL) { splx(s);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 17, 1, WV_NETEVENT_ADDMRT_NOBUFS)#endif /* INCLUDE_WVNET */#endif return ENOBUFS; } rt->mfc_notify = 0; rt->mfc_origin = mfccp->mfcc_origin; rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; /* link into hash chain now so the search for the root_rt will work */ rt->mfc_next = mfctable[hash]; mfctable[hash] = rt; for (i = 0; i < numvifs; i++) { if (mfccp->mfcc_ttls[i] != 0) rt->mfc_ttls[i] = viftable[i].v_threshold; else rt->mfc_ttls[i] = 0; } /* find the *,g entry and link in */ MFCFIND(0, mfccp->mfcc_mcastgrp.s_addr, root_rt); if (root_rt == NULL) { root_rt = MRT_ALLOC(sizeof(struct mfc)); if (root_rt == NULL) { MRT_FREE((char*) rt); splx(s); return ENOBUFS; } root_rt->mfc_notify = 0; /* inset NULL entry at head of hash chain */ root_rt->mfc_origin.s_addr = 0; root_rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; root_rt->mfc_parent = 0; for (i = 0; i < numvifs; i++) { root_rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; } /* initialize pkt counters per src-grp */ root_rt->mfc_pkt_cnt = 0; root_rt->mfc_byte_cnt = 0; root_rt->mfc_wrong_if = 0; root_rt->mfc_last_assert = 0; rt->mfc_last_assert = 0; root_rt->mfc_expire = 0; root_rt->mfc_stall = NULL; /* link *,g into table */ root_rt->mfc_next = mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr)]; mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr)] = root_rt; root_rt->mfc_next_g = root_rt; /* next group in same chain */ root_rt->mfc_root_rt = root_rt; /* 0,g entry in hash table, itself in this case*/ } rt->mfc_root_rt = root_rt; /* insert into front of group chain*/ rt->mfc_next_g = root_rt->mfc_next_g; root_rt->mfc_next_g = rt; if (!(mfccp->mfcc_parent > numvifs) )/* can't be less than 0, it's a USHORT */ rt->mfc_parent = mfccp->mfcc_parent; /* take care of the details before you alter the forwarding state. */ rt->mfc_pkt_cnt = 0; rt->mfc_byte_cnt = 0; rt->mfc_wrong_if = 0; rt->mfc_last_assert = 0; rt->mfc_last_assert = 0; rt->mfc_expire = 0; rt->mfc_stall = NULL; }/* rt == null */ }/* nstl == 0 */ splx(s); return 0;}/* * Resets the passed oif to 0 for a chain */static int mRouteOifsRemove ( struct mfc* rt, int oif ){ struct mfc* probe; if (rt == NULL) return (EINVAL); rt->mfc_root_rt->mfc_ttls[oif] = 0; probe = rt->mfc_root_rt; while (probe->mfc_next_g != probe->mfc_root_rt) { probe = probe->mfc_next_g; probe->mfc_ttls[oif] = 0; } return (OK);}/* * Removes from the chain of all g entries */static intmRouteGroupLoopRemove ( struct mfc* rt, struct mfc* root ){ struct mfc* probe; probe = root; while (probe->mfc_next_g != probe->mfc_root_rt) { probe = probe->mfc_next_g ; if (probe->mfc_next_g == rt) break; } if (probe->mfc_next_g == rt) { probe->mfc_next_g = rt->mfc_next_g ; } return (OK);} /* * Delete an mfc entry */static int del_mfc(mfccp) struct mfcctl *mfccp;{ struct in_addr origin; struct in_addr mcastgrp; struct mfc *rt; struct mfc *root; struct mfc **nptr; u_long hash; int s; origin = mfccp->mfcc_origin; mcastgrp = mfccp->mfcc_mcastgrp; hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); MRTDEBUG ( (mrtdebug & DEBUG_MFC), "MROUTE: del_mfc orig %lx mcastgrp %lx\n", (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr), 3,4,5,6 ); s = splnet(); nptr = &mfctable[hash]; while ((rt = *nptr) != NULL) { if (origin.s_addr == rt->mfc_origin.s_addr && mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && rt->mfc_stall == NULL) break; nptr = &rt->mfc_next; } if (rt == NULL) { splx(s); return EADDRNOTAVAIL; } /* if *,g remove, remove all oifs from group chain */ if (rt->mfc_origin.s_addr == 0) mRouteOifsRemove(rt, mfccp->mfcc_parent); else { /* remove entry from group chain */ root = rt->mfc_root_rt; mRouteGroupLoopRemove(rt, root); *nptr = rt->mfc_next;/* removes from hash chain */ MRT_FREE((char*) rt);/* removes the s,g entry */ if ( (u_long)root->mfc_next_g == (u_long)root->mfc_root_rt == (u_long)root) /* this is the only g entry in the table */ { hash = MFCHASH(0, mcastgrp.s_addr); nptr = &mfctable[hash]; while ((rt = *nptr) != NULL) { if (origin.s_addr == rt->mfc_origin.s_addr && mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && rt->mfc_stall == NULL) break; nptr = &rt->mfc_next; } if (root == rt) { *nptr = rt->mfc_next;/* removes from hash chain */ MRT_FREE((char*) rt);/* frees up the 0,g entry */ } } }/* origin not == NULL */ splx(s); return 0;}/******************************************************************************** mRouteGroupAdd - add a multicast group to the given interface** Adds the given group to the list of multicast groups on the given port.* Thus, multicast packets to that address will go out the port.** RETURNS: OK if successful, ERROR otherwise**/STATUS mRouteGroupAdd ( struct ifnet* ifp, struct in_addr srcAddr, /* multicast source to add */ struct in_addr groupAddr /* multicast group to add */ ) { struct mfcctl gCtl; int sockfd; int port; struct mfc *rt; rt = NULL; MFCFIND(0, groupAddr.s_addr, rt); if (ifp == NULL) { return (ERROR); } port = mRouteNameToPort(ifp->if_name, ifp->if_unit); if ( (port == ERROR) ) return (ERROR); gCtl.mfcc_parent = port; /* ports are vifs for now */ gCtl.mfcc_mcastgrp = groupAddr; gCtl.mfcc_origin = srcAddr;/* 0 for a star,g entry */ gCtl.mfcc_notify = 0; /* mfcc_notify set to 0 so pimNotify never called */ if (rt != NULL) { memcpy(gCtl.mfcc_ttls, rt->mfc_ttls, numvifs); } else { bzero (gCtl.mfcc_ttls, 32); } sockfd = (int)ip_mrouter; if (sockfd <= 0) return (ERROR); MRTDEBUG ( (mrtdebug & DEBUG_MFC), "MROUTE: IP_MROUTER calling mfc_add.\n", 1,2,3,4,5,6 ); if (setsockopt (sockfd, IPPROTO_IP, MRT_ADD_MFC, (char *) &gCtl, sizeof(gCtl)) == ERROR) { MRTDEBUG ( (mrtdebug), "MROUTE: igmpGroupAdd failed with errno: %d", errno,2,3,4,5,6 ); return ERROR; } return (OK);}/******************************************************************************** pimNotify - notifies pim daemon about new packet on an interface** RETURNS: OK for success, ERROR for failure**/static int pimNotify ( struct ip * pIp, struct mbuf* pMbuf, struct mfc* pRt, vifi_t vifi, struct ifnet* pIfnet ){ struct sockaddr_in k_igmpsrc; struct mbuf *pMbufCopy; struct igmpmsg *pIGMPMessage; struct ip * pIpNew; UINT now; int hlen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -