diff options
Diffstat (limited to 'pimd/pim_mroute.c')
| -rw-r--r-- | pimd/pim_mroute.c | 1574 |
1 files changed, 799 insertions, 775 deletions
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index ce2f98f318..bb7f4c02f0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, @@ -48,358 +48,360 @@ static void mroute_read_on(void); static int pim_mroute_set(int fd, int enable) { - int err; - int opt = enable ? MRT_INIT : MRT_DONE; - socklen_t opt_len = sizeof(opt); - int rcvbuf = 1024 * 1024 * 8; - long flags; - - err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - fd, enable ? "MRT_INIT" : "MRT_DONE", opt, errno, safe_strerror(errno)); - return -1; - } - - err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); - if (err) { - zlog_warn("%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", - __PRETTY_FUNCTION__, fd, rcvbuf, errno, safe_strerror(errno)); - } - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) - { - zlog_warn("Could not get flags on socket fd:%d %d %s", - fd, errno, safe_strerror(errno)); - close (fd); - return -1; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) - { - zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", - fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } + int err; + int opt = enable ? MRT_INIT : MRT_DONE; + socklen_t opt_len = sizeof(opt); + int rcvbuf = 1024 * 1024 * 8; + long flags; + + err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, + enable ? "MRT_INIT" : "MRT_DONE", opt, errno, + safe_strerror(errno)); + return -1; + } - if (enable) - { + err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); + if (err) { + zlog_warn( + "%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", + __PRETTY_FUNCTION__, fd, rcvbuf, errno, + safe_strerror(errno)); + } + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn("Could not get flags on socket fd:%d %d %s", fd, + errno, safe_strerror(errno)); + close(fd); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", fd, + errno, safe_strerror(errno)); + close(fd); + return -1; + } + + if (enable) { #if defined linux - int upcalls = IGMPMSG_WRVIFWHOLE; - opt = MRT_PIM; - - err = setsockopt (fd, IPPROTO_IP, opt, &upcalls, sizeof (upcalls)); - if (err) - { - zlog_warn ("Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", - errno, safe_strerror (errno)); - return -1; - } + int upcalls = IGMPMSG_WRVIFWHOLE; + opt = MRT_PIM; + + err = setsockopt(fd, IPPROTO_IP, opt, &upcalls, + sizeof(upcalls)); + if (err) { + zlog_warn( + "Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", + errno, safe_strerror(errno)); + return -1; + } #else - zlog_warn ("PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); + zlog_warn( + "PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); #endif - } - - return 0; + } + + return 0; } static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = { - "<unknown_upcall?>", - "NOCACHE", - "WRONGVIF", - "WHOLEPKT", - "WRVIFWHOLE" }; - -static int -pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg) + "<unknown_upcall?>", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"}; + +static int pim_mroute_msg_nocache(int fd, struct interface *ifp, + const struct igmpmsg *msg) { - struct pim_interface *pim_ifp = ifp->info; - struct pim_upstream *up; - struct pim_rpf *rpg; - struct prefix_sg sg; - - rpg = RP(msg->im_dst); - /* - * If the incoming interface is unknown OR - * the Interface type is SSM we don't need to - * do anything here - */ - if ((pim_rpf_addr_is_inaddr_none (rpg)) || - (!pim_ifp) || - (!(PIM_I_am_DR(pim_ifp)))) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", - __PRETTY_FUNCTION__); - return 0; - } + struct pim_interface *pim_ifp = ifp->info; + struct pim_upstream *up; + struct pim_rpf *rpg; + struct prefix_sg sg; + + rpg = RP(msg->im_dst); + /* + * If the incoming interface is unknown OR + * the Interface type is SSM we don't need to + * do anything here + */ + if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + || (!(PIM_I_am_DR(pim_ifp)))) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug( + "%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", + __PRETTY_FUNCTION__); + return 0; + } - /* - * If we've received a multicast packet that isn't connected to - * us - */ - if (!pim_if_connected_to_source (ifp, msg->im_src)) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", - __PRETTY_FUNCTION__); - return 0; - } + /* + * If we've received a multicast packet that isn't connected to + * us + */ + if (!pim_if_connected_to_source(ifp, msg->im_src)) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug( + "%s: Received incoming packet that doesn't originate on our seg", + __PRETTY_FUNCTION__); + return 0; + } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + + up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: Failure to add upstream information for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + } + return 0; + } - up = pim_upstream_find_or_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - { - zlog_debug("%s: Failure to add upstream information for %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); - } - return 0; - } + /* + * I moved this debug till after the actual add because + * I want to take advantage of the up->sg_str being filled in. + */ + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", + __PRETTY_FUNCTION__, up->sg_str); + } - /* - * I moved this debug till after the actual add because - * I want to take advantage of the up->sg_str being filled in. - */ - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", - __PRETTY_FUNCTION__, up->sg_str); - } - - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - - up->channel_oil->cc.pktcnt++; - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - // resolve mfcc_parent prior to mroute_add in channel_add_oif - if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) - { - int vif_index = 0; - vif_index = - pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop. - interface->ifindex); - up->channel_oil->oil.mfcc_parent = vif_index; - } - pim_register_join (up); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + + up->channel_oil->cc.pktcnt++; + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + // resolve mfcc_parent prior to mroute_add in channel_add_oif + if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) { + int vif_index = 0; + vif_index = pim_if_find_vifindex_by_ifindex( + up->rpf.source_nexthop.interface->ifindex); + up->channel_oil->oil.mfcc_parent = vif_index; + } + pim_register_join(up); - return 0; + return 0; } -static int -pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, + const char *buf) { - struct pim_interface *pim_ifp; - struct prefix_sg sg; - struct pim_rpf *rpg; - const struct ip *ip_hdr; - struct pim_upstream *up; - - ip_hdr = (const struct ip *)buf; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - up = pim_upstream_find(&sg); - if (!up) { - struct prefix_sg star = sg; - star.src.s_addr = INADDR_ANY; - - up = pim_upstream_find(&star); - - if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) - { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Unable to create upstream information for %s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - return 0; - } - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_upstream_inherited_olist (up); - pim_upstream_switch(up, PIM_UPSTREAM_JOINED); - - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Creating %s upstream on LHR", - __PRETTY_FUNCTION__, up->sg_str); - return 0; - } - if (PIM_DEBUG_MROUTE_DETAIL) { - zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - } - return 0; - } + struct pim_interface *pim_ifp; + struct prefix_sg sg; + struct pim_rpf *rpg; + const struct ip *ip_hdr; + struct pim_upstream *up; + + ip_hdr = (const struct ip *)buf; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + up = pim_upstream_find(&sg); + if (!up) { + struct prefix_sg star = sg; + star.src.s_addr = INADDR_ANY; + + up = pim_upstream_find(&star); + + if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) { + up = pim_upstream_add(&sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_LHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: Unable to create upstream information for %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + return 0; + } + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_upstream_inherited_olist(up); + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + + if (PIM_DEBUG_MROUTE) + zlog_debug("%s: Creating %s upstream on LHR", + __PRETTY_FUNCTION__, up->sg_str); + return 0; + } + if (PIM_DEBUG_MROUTE_DETAIL) { + zlog_debug( + "%s: Unable to find upstream channel WHOLEPKT%s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + } + return 0; + } - pim_ifp = up->rpf.source_nexthop.interface->info; + pim_ifp = up->rpf.source_nexthop.interface->info; - rpg = RP(sg.grp); + rpg = RP(sg.grp); - if ((pim_rpf_addr_is_inaddr_none (rpg)) || - (!pim_ifp) || - (!(PIM_I_am_DR(pim_ifp)))) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__); - } - return 0; - } + if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + || (!(PIM_I_am_DR(pim_ifp)))) { + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Failed Check send packet", + __PRETTY_FUNCTION__); + } + return 0; + } - /* - * If we've received a register suppress - */ - if (!up->t_rs_timer) - { - if (pim_is_grp_ssm (sg.grp)) - { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("%s register forward skipped as group is SSM", - pim_str_sg_dump (&sg)); - return 0; - } - pim_register_send((uint8_t *)buf + sizeof(struct ip), - ntohs (ip_hdr->ip_len) - sizeof (struct ip), - pim_ifp->primary_address, rpg, 0, up); - } - return 0; + /* + * If we've received a register suppress + */ + if (!up->t_rs_timer) { + if (pim_is_grp_ssm(sg.grp)) { + if (PIM_DEBUG_PIM_REG) + zlog_debug( + "%s register forward skipped as group is SSM", + pim_str_sg_dump(&sg)); + return 0; + } + pim_register_send((uint8_t *)buf + sizeof(struct ip), + ntohs(ip_hdr->ip_len) - sizeof(struct ip), + pim_ifp->primary_address, rpg, 0, up); + } + return 0; } -static int -pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg) +static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, + const struct igmpmsg *msg) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - struct prefix_sg sg; + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct prefix_sg sg; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + + /* + Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + + RFC 4601 4.8.2. PIM-SSM-Only Routers + + iif is the incoming interface of the packet. + if (iif is in inherited_olist(S,G)) { + send Assert(S,G) on iif + } + */ + + if (!ifp) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + msg->im_vif); + return -1; + } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; + pim_ifp = ifp->info; + if (!pim_ifp) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + ifp->name); + return -2; + } - /* - Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + ch = pim_ifchannel_find(ifp, &sg); + if (!ch) { + struct prefix_sg star_g = sg; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + ifp->name); + + star_g.src.s_addr = INADDR_ANY; + ch = pim_ifchannel_find(ifp, &star_g); + if (!ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (*,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&star_g), ifp->name); + return -3; + } + } - RFC 4601 4.8.2. PIM-SSM-Only Routers + /* + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from NoInfo State + + An (S,G) data packet arrives on interface I, AND + CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an + downstream interface that is in our (S,G) outgoing interface + list. We optimistically assume that we will be the assert + winner for this (S,G), and so we transition to the "I am Assert + Winner" state and perform Actions A1 (below), which will + initiate the assert negotiation for (S,G). + */ + + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -4; + } - iif is the incoming interface of the packet. - if (iif is in inherited_olist(S,G)) { - send Assert(S,G) on iif - } - */ - - if (!ifp) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), msg->im_vif); - return -1; - } - - pim_ifp = ifp->info; - if (!pim_ifp) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - - ch = pim_ifchannel_find(ifp, &sg); - if (!ch) { - struct prefix_sg star_g = sg; - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s could not find channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&sg), ifp->name); - - star_g.src.s_addr = INADDR_ANY; - ch = pim_ifchannel_find(ifp, &star_g); - if (!ch) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (*,G)=%s could not find channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&star_g), ifp->name); - return -3; - } - } - - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from NoInfo State - - An (S,G) data packet arrives on interface I, AND - CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an - downstream interface that is in our (S,G) outgoing interface - list. We optimistically assume that we will be the assert - winner for this (S,G), and so we transition to the "I am Assert - Winner" state and perform Actions A1 (below), which will - initiate the assert negotiation for (S,G). - */ - - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -4; - } - - if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -5; - } - - if (assert_action_a1(ch)) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -6; - } + if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -5; + } + + if (assert_action_a1(ch)) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -6; + } - return 0; + return 0; } -static int -pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, + const char *buf) { - const struct ip *ip_hdr = (const struct ip *)buf; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_upstream *up; - struct prefix_sg star_g; - struct prefix_sg sg; - struct channel_oil *oil; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - ch = pim_ifchannel_find(ifp, &sg); - if (ch) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", - ch->sg_str, ifp->name); - return -1; - } + const struct ip *ip_hdr = (const struct ip *)buf; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + struct prefix_sg star_g; + struct prefix_sg sg; + struct channel_oil *oil; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + ch = pim_ifchannel_find(ifp, &sg); + if (ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", + ch->sg_str, ifp->name); + return -1; + } - star_g = sg; - star_g.src.s_addr = INADDR_ANY; + star_g = sg; + star_g.src.s_addr = INADDR_ANY; #if 0 ch = pim_ifchannel_find(ifp, &star_g); if (ch) @@ -411,293 +413,316 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) } #endif - up = pim_upstream_find (&sg); - if (up) - { - struct pim_upstream *parent; - struct pim_nexthop source; - struct pim_rpf *rpf = RP (sg.grp); - if (!rpf || !rpf->source_nexthop.interface) - return 0; - - /* - * If we have received a WRVIFWHOLE and are at this - * point, we could be receiving the packet on the *,G - * tree, let's check and if so we can safely drop - * it. - */ - parent = pim_upstream_find (&star_g); - if (parent && parent->rpf.source_nexthop.interface == ifp) - return 0; - - pim_ifp = rpf->source_nexthop.interface->info; - - memset (&source, 0, sizeof (source)); - /* - * If we are the fhr that means we are getting a callback during - * the pimreg period, so I believe we can ignore this packet - */ - if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - { - //No if channel, but upstream we are at the RP. - if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); - if (!up->channel_oil) - up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - pim_upstream_inherited_olist (up); - if (!up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - pim_upstream_set_sptbit (up, ifp); - } - else - { - if (I_am_RP (up->sg.grp)) - { - if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - } - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_upstream_inherited_olist (up); - pim_mroute_msg_wholepkt (fd, ifp, buf); - } - return 0; - } + up = pim_upstream_find(&sg); + if (up) { + struct pim_upstream *parent; + struct pim_nexthop source; + struct pim_rpf *rpf = RP(sg.grp); + if (!rpf || !rpf->source_nexthop.interface) + return 0; + + /* + * If we have received a WRVIFWHOLE and are at this + * point, we could be receiving the packet on the *,G + * tree, let's check and if so we can safely drop + * it. + */ + parent = pim_upstream_find(&star_g); + if (parent && parent->rpf.source_nexthop.interface == ifp) + return 0; + + pim_ifp = rpf->source_nexthop.interface->info; + + memset(&source, 0, sizeof(source)); + /* + * If we are the fhr that means we are getting a callback during + * the pimreg period, so I believe we can ignore this packet + */ + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { + // No if channel, but upstream we are at the RP. + if (pim_nexthop_lookup(&source, up->upstream_register, + 0) + == 0) + pim_register_stop_send(source.interface, &sg, + pim_ifp->primary_address, + up->upstream_register); + if (!up->channel_oil) + up->channel_oil = pim_channel_oil_add( + &sg, pim_ifp->mroute_vif_index); + pim_upstream_inherited_olist(up); + if (!up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + pim_upstream_set_sptbit(up, ifp); + } else { + if (I_am_RP(up->sg.grp)) { + if (pim_nexthop_lookup(&source, + up->upstream_register, 0) + == 0) + pim_register_stop_send( + source.interface, &sg, + pim_ifp->primary_address, + up->upstream_register); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + } + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_upstream_inherited_olist(up); + pim_mroute_msg_wholepkt(fd, ifp, buf); + } + return 0; + } - pim_ifp = ifp->info; - oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - if (!oil->installed) - pim_mroute_add (oil, __PRETTY_FUNCTION__); - if (pim_if_connected_to_source (ifp, sg.src)) - { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - up->channel_oil = oil; - up->channel_oil->cc.pktcnt++; - pim_register_join (up); - pim_upstream_inherited_olist (up); - - // Send the packet to the RP - pim_mroute_msg_wholepkt (fd, ifp, buf); - } + pim_ifp = ifp->info; + oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); + if (!oil->installed) + pim_mroute_add(oil, __PRETTY_FUNCTION__); + if (pim_if_connected_to_source(ifp, sg.src)) { + up = pim_upstream_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF%s unable to create upstream on interface", + pim_str_sg_dump(&sg), ifp->name); + return -2; + } + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + up->channel_oil = oil; + up->channel_oil->cc.pktcnt++; + pim_register_join(up); + pim_upstream_inherited_olist(up); + + // Send the packet to the RP + pim_mroute_msg_wholepkt(fd, ifp, buf); + } - return 0; + return 0; } int pim_mroute_msg(int fd, const char *buf, int buf_size) { - struct interface *ifp; - struct pim_interface *pim_ifp; - const struct ip *ip_hdr; - const struct igmpmsg *msg; - char ip_src_str[INET_ADDRSTRLEN] = ""; - char ip_dst_str[INET_ADDRSTRLEN] = ""; - char src_str[INET_ADDRSTRLEN] = "<src?>"; - char grp_str[INET_ADDRSTRLEN] = "<grp?>"; - struct in_addr ifaddr; - struct igmp_sock *igmp; - - ip_hdr = (const struct ip *) buf; - - if (ip_hdr->ip_p == IPPROTO_IGMP) { - - /* We have the IP packet but we do not know which interface this packet was - * received on. Find the interface that is on the same subnet as the source - * of the IP packet. - */ - ifp = pim_if_lookup_address_vrf (ip_hdr->ip_src, VRF_DEFAULT); - - if (!ifp) { - if (PIM_DEBUG_MROUTE_DETAIL) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); - pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - - zlog_warn("%s: igmp kernel upcall could not find usable interface for %s -> %s", - __PRETTY_FUNCTION__, - ip_src_str, - ip_dst_str); - } - return 0; - } - pim_ifp = ifp->info; - ifaddr = pim_find_primary_addr(ifp); - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); - - if (PIM_DEBUG_MROUTE) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); - pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - - zlog_warn("%s: igmp kernel upcall on %s(%p) for %s -> %s", - __PRETTY_FUNCTION__, ifp->name, igmp, ip_src_str, ip_dst_str); - } - if (igmp) - pim_igmp_packet(igmp, (char *)buf, buf_size); - - } else if (ip_hdr->ip_p) { - if (PIM_DEBUG_MROUTE_DETAIL) { - pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); - zlog_debug("%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", - __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); - } - - } else { - msg = (const struct igmpmsg *) buf; - - ifp = pim_if_find_by_vif_index(msg->im_vif); - - if (!ifp) - return 0; - if (PIM_DEBUG_MROUTE) { - pim_inet4_dump("<src?>", msg->im_src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", msg->im_dst, grp_str, sizeof(grp_str)); - zlog_warn("%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", - __PRETTY_FUNCTION__, - igmpmsgtype2str[msg->im_msgtype], - msg->im_msgtype, - ip_hdr->ip_p, - fd, - src_str, - grp_str, - ifp->name, - msg->im_vif, buf_size); - } - - switch (msg->im_msgtype) { - case IGMPMSG_WRONGVIF: - return pim_mroute_msg_wrongvif(fd, ifp, msg); - break; - case IGMPMSG_NOCACHE: - return pim_mroute_msg_nocache(fd, ifp, msg); - break; - case IGMPMSG_WHOLEPKT: - return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); - break; - case IGMPMSG_WRVIFWHOLE: - return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); - break; - default: - break; - } - } + struct interface *ifp; + struct pim_interface *pim_ifp; + const struct ip *ip_hdr; + const struct igmpmsg *msg; + char ip_src_str[INET_ADDRSTRLEN] = ""; + char ip_dst_str[INET_ADDRSTRLEN] = ""; + char src_str[INET_ADDRSTRLEN] = "<src?>"; + char grp_str[INET_ADDRSTRLEN] = "<grp?>"; + struct in_addr ifaddr; + struct igmp_sock *igmp; + + ip_hdr = (const struct ip *)buf; + + if (ip_hdr->ip_p == IPPROTO_IGMP) { + + /* We have the IP packet but we do not know which interface this + * packet was + * received on. Find the interface that is on the same subnet as + * the source + * of the IP packet. + */ + ifp = pim_if_lookup_address_vrf(ip_hdr->ip_src, VRF_DEFAULT); + + if (!ifp) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, + ip_src_str, sizeof(ip_src_str)); + pim_inet4_dump("<dst?>", ip_hdr->ip_dst, + ip_dst_str, sizeof(ip_dst_str)); + + zlog_warn( + "%s: igmp kernel upcall could not find usable interface for %s -> %s", + __PRETTY_FUNCTION__, ip_src_str, + ip_dst_str); + } + return 0; + } + pim_ifp = ifp->info; + ifaddr = pim_find_primary_addr(ifp); + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + + if (PIM_DEBUG_MROUTE) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, + sizeof(ip_src_str)); + pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, + sizeof(ip_dst_str)); + + zlog_warn( + "%s: igmp kernel upcall on %s(%p) for %s -> %s", + __PRETTY_FUNCTION__, ifp->name, igmp, + ip_src_str, ip_dst_str); + } + if (igmp) + pim_igmp_packet(igmp, (char *)buf, buf_size); + + } else if (ip_hdr->ip_p) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, + sizeof(src_str)); + pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", + __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, + grp_str, buf_size); + } + + } else { + msg = (const struct igmpmsg *)buf; + + ifp = pim_if_find_by_vif_index(msg->im_vif); + + if (!ifp) + return 0; + if (PIM_DEBUG_MROUTE) { + pim_inet4_dump("<src?>", msg->im_src, src_str, + sizeof(src_str)); + pim_inet4_dump("<grp?>", msg->im_dst, grp_str, + sizeof(grp_str)); + zlog_warn( + "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", + __PRETTY_FUNCTION__, + igmpmsgtype2str[msg->im_msgtype], + msg->im_msgtype, ip_hdr->ip_p, fd, src_str, + grp_str, ifp->name, msg->im_vif, buf_size); + } + + switch (msg->im_msgtype) { + case IGMPMSG_WRONGVIF: + return pim_mroute_msg_wrongvif(fd, ifp, msg); + break; + case IGMPMSG_NOCACHE: + return pim_mroute_msg_nocache(fd, ifp, msg); + break; + case IGMPMSG_WHOLEPKT: + return pim_mroute_msg_wholepkt(fd, ifp, + (const char *)msg); + break; + case IGMPMSG_WRVIFWHOLE: + return pim_mroute_msg_wrvifwhole(fd, ifp, + (const char *)msg); + break; + default: + break; + } + } - return 0; + return 0; } static int mroute_read(struct thread *t) { - static long long count; - char buf[10000]; - int result = 0; - int cont = 1; - int fd; - int rd; - - fd = THREAD_FD(t); - - while (cont) - { - rd = read(fd, buf, sizeof(buf)); - if (rd < 0) { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - if (PIM_DEBUG_MROUTE) - zlog_warn("%s: failure reading fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - goto done; - } - - result = pim_mroute_msg(fd, buf, rd); - - count++; - if (count % qpim_packet_process == 0) - cont = 0; - } - /* Keep reading */ - done: - qpim_mroute_socket_reader = NULL; - mroute_read_on(); + static long long count; + char buf[10000]; + int result = 0; + int cont = 1; + int fd; + int rd; + + fd = THREAD_FD(t); + + while (cont) { + rd = read(fd, buf, sizeof(buf)); + if (rd < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s: failure reading fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + goto done; + } + + result = pim_mroute_msg(fd, buf, rd); + + count++; + if (count % qpim_packet_process == 0) + cont = 0; + } +/* Keep reading */ +done: + qpim_mroute_socket_reader = NULL; + mroute_read_on(); - return result; + return result; } static void mroute_read_on() { - zassert(!qpim_mroute_socket_reader); + zassert(!qpim_mroute_socket_reader); - THREAD_READ_ON(master, qpim_mroute_socket_reader, - mroute_read, 0, qpim_mroute_socket_fd); + THREAD_READ_ON(master, qpim_mroute_socket_reader, mroute_read, 0, + qpim_mroute_socket_fd); } static void mroute_read_off() { - THREAD_OFF(qpim_mroute_socket_reader); + THREAD_OFF(qpim_mroute_socket_reader); } int pim_mroute_socket_enable() { - int fd; + int fd; - if ( pimd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("pim_mroute_socket_enable: could not raise privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("pim_mroute_socket_enable: could not raise privs, %s", + safe_strerror(errno)); - fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); - if ( pimd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("pim_mroute_socket_enable: could not lower privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("pim_mroute_socket_enable: could not lower privs, %s", + safe_strerror(errno)); - if (fd < 0) { - zlog_warn("Could not create mroute socket: errno=%d: %s", - errno, safe_strerror(errno)); - return -2; - } + if (fd < 0) { + zlog_warn("Could not create mroute socket: errno=%d: %s", errno, + safe_strerror(errno)); + return -2; + } - if (pim_mroute_set(fd, 1)) { - zlog_warn("Could not enable mroute on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return -3; - } + if (pim_mroute_set(fd, 1)) { + zlog_warn( + "Could not enable mroute on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return -3; + } - qpim_mroute_socket_fd = fd; + qpim_mroute_socket_fd = fd; - qpim_mroute_socket_creation = pim_time_monotonic_sec(); - mroute_read_on(); + qpim_mroute_socket_creation = pim_time_monotonic_sec(); + mroute_read_on(); - return 0; + return 0; } int pim_mroute_socket_disable() { - if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { - zlog_warn("Could not disable mroute on socket fd=%d: errno=%d: %s", - qpim_mroute_socket_fd, errno, safe_strerror(errno)); - return -2; - } - - if (close(qpim_mroute_socket_fd)) { - zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", - qpim_mroute_socket_fd, errno, safe_strerror(errno)); - return -3; - } - - mroute_read_off(); - qpim_mroute_socket_fd = -1; - - return 0; + if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { + zlog_warn( + "Could not disable mroute on socket fd=%d: errno=%d: %s", + qpim_mroute_socket_fd, errno, safe_strerror(errno)); + return -2; + } + + if (close(qpim_mroute_socket_fd)) { + zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", + qpim_mroute_socket_fd, errno, safe_strerror(errno)); + return -3; + } + + mroute_read_off(); + qpim_mroute_socket_fd = -1; + + return 0; } /* @@ -705,249 +730,248 @@ int pim_mroute_socket_disable() would be used for multicast forwarding, a corresponding multicast interface must be added to the kernel. */ -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags) +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, + unsigned char flags) { - struct pim_interface *pim_ifp = ifp->info; - struct vifctl vc; - int err; + struct pim_interface *pim_ifp = ifp->info; + struct vifctl vc; + int err; - memset(&vc, 0, sizeof(vc)); - vc.vifc_vifi = pim_ifp->mroute_vif_index; + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = pim_ifp->mroute_vif_index; #ifdef VIFF_USE_IFINDEX - vc.vifc_lcl_ifindex = ifp->ifindex; + vc.vifc_lcl_ifindex = ifp->ifindex; #else - if (ifaddr.s_addr == INADDR_ANY) { - zlog_warn("%s: unnumbered interfaces are not supported on this platform", - __PRETTY_FUNCTION__); - return -1; - } - memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); + if (ifaddr.s_addr == INADDR_ANY) { + zlog_warn( + "%s: unnumbered interfaces are not supported on this platform", + __PRETTY_FUNCTION__); + return -1; + } + memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); #endif - vc.vifc_flags = flags; - vc.vifc_threshold = PIM_MROUTE_MIN_TTL; - vc.vifc_rate_limit = 0; - -#ifdef PIM_DVMRP_TUNNEL - if (vc.vifc_flags & VIFF_TUNNEL) { - memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, sizeof(vc.vifc_rmt_addr)); - } + vc.vifc_flags = flags; + vc.vifc_threshold = PIM_MROUTE_MIN_TTL; + vc.vifc_rate_limit = 0; + +#ifdef PIM_DVMRP_TUNNEL + if (vc.vifc_flags & VIFF_TUNNEL) { + memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, + sizeof(vc.vifc_rmt_addr)); + } #endif - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc)); - if (err) { - char ifaddr_str[INET_ADDRSTRLEN]; + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, + (void *)&vc, sizeof(vc)); + if (err) { + char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, sizeof(ifaddr_str)); + pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, + sizeof(ifaddr_str)); - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, ifp->ifindex, ifaddr_str, flags, - errno, safe_strerror(errno)); - return -2; - } + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + ifp->ifindex, ifaddr_str, flags, errno, + safe_strerror(errno)); + return -2; + } - return 0; + return 0; } int pim_mroute_del_vif(int vif_index) { - struct vifctl vc; - int err; - - if (PIM_DEBUG_MROUTE) - { - struct interface *ifp = pim_if_find_by_vif_index (vif_index); - zlog_debug ("%s %s: Del Vif %d (%s) ", __FILE__, - __PRETTY_FUNCTION__, vif_index, ifp ? ifp->name : "NULL"); - } - - memset(&vc, 0, sizeof(vc)); - vc.vifc_vifi = vif_index; + struct vifctl vc; + int err; + + if (PIM_DEBUG_MROUTE) { + struct interface *ifp = pim_if_find_by_vif_index(vif_index); + zlog_debug("%s %s: Del Vif %d (%s) ", __FILE__, + __PRETTY_FUNCTION__, vif_index, + ifp ? ifp->name : "NULL"); + } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, (void*) &vc, sizeof(vc)); - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, vif_index, - errno, safe_strerror(errno)); - return -2; - } + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = vif_index; + + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, + (void *)&vc, sizeof(vc)); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + vif_index, errno, safe_strerror(errno)); + return -2; + } - return 0; + return 0; } int pim_mroute_add(struct channel_oil *c_oil, const char *name) { - int err; - int orig = 0; - int orig_iif_vif = 0; - - qpim_mroute_add_last = pim_time_monotonic_sec(); - ++qpim_mroute_add_events; - - /* Do not install route if incoming interface is undefined. */ - if (c_oil->oil.mfcc_parent >= MAXVIFS) - { - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s) %s Attempting to add vifi that is invalid to mroute table", - __PRETTY_FUNCTION__, name, pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } - return -2; - } - - /* The linux kernel *expects* the incoming - * vif to be part of the outgoing list - * in the case of a (*,G). - */ - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - { - orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; - } + int err; + int orig = 0; + int orig_iif_vif = 0; + + qpim_mroute_add_last = pim_time_monotonic_sec(); + ++qpim_mroute_add_events; + + /* Do not install route if incoming interface is undefined. */ + if (c_oil->oil.mfcc_parent >= MAXVIFS) { + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug( + "%s(%s) %s Attempting to add vifi that is invalid to mroute table", + __PRETTY_FUNCTION__, name, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } + return -2; + } - /* - * If we have an unresolved cache entry for the S,G - * it is owned by the pimreg for the incoming IIF - * So set pimreg as the IIF temporarily to cause - * the packets to be forwarded. Then set it - * to the correct IIF afterwords. - */ - if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && - c_oil->oil.mfcc_parent != 0) - { - orig_iif_vif = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = 0; - } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof(c_oil->oil)); + /* The linux kernel *expects* the incoming + * vif to be part of the outgoing list + * in the case of a (*,G). + */ + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) { + orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; + } - if (!err && !c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && - orig_iif_vif != 0) - { - c_oil->oil.mfcc_parent = orig_iif_vif; - err = setsockopt (qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof (c_oil->oil)); - } + /* + * If we have an unresolved cache entry for the S,G + * it is owned by the pimreg for the incoming IIF + * So set pimreg as the IIF temporarily to cause + * the packets to be forwarded. Then set it + * to the correct IIF afterwords. + */ + if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY + && c_oil->oil.mfcc_parent != 0) { + orig_iif_vif = c_oil->oil.mfcc_parent; + c_oil->oil.mfcc_parent = 0; + } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + + if (!err && !c_oil->installed + && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY + && orig_iif_vif != 0) { + c_oil->oil.mfcc_parent = orig_iif_vif; + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + } - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); - return -2; - } + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + errno, safe_strerror(errno)); + return -2; + } - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s), Added Route: %s", - __PRETTY_FUNCTION__, name, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug("%s(%s), Added Route: %s", __PRETTY_FUNCTION__, name, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } - c_oil->installed = 1; - return 0; + c_oil->installed = 1; + return 0; } -int pim_mroute_del (struct channel_oil *c_oil, const char *name) +int pim_mroute_del(struct channel_oil *c_oil, const char *name) { - int err; - - qpim_mroute_del_last = pim_time_monotonic_sec(); - ++qpim_mroute_del_events; + int err; + + qpim_mroute_del_last = pim_time_monotonic_sec(); + ++qpim_mroute_del_events; + + if (!c_oil->installed) { + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug( + "%s %s: vifi %d for route is %s not installed, do not need to send del req. ", + __FILE__, __PRETTY_FUNCTION__, + c_oil->oil.mfcc_parent, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } + return -2; + } - if (!c_oil->installed) - { - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s %s: vifi %d for route is %s not installed, do not need to send del req. ", - __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } - return -2; - } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + if (err) { + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, + qpim_mroute_socket_fd, errno, + safe_strerror(errno)); + return -2; + } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); - if (err) { - if (PIM_DEBUG_MROUTE) - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); - return -2; - } - - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s), Deleted Route: %s", - __PRETTY_FUNCTION__, name, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug("%s(%s), Deleted Route: %s", __PRETTY_FUNCTION__, + name, pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } - //Reset kernel installed flag - c_oil->installed = 0; + // Reset kernel installed flag + c_oil->installed = 0; - return 0; + return 0; } -void -pim_mroute_update_counters (struct channel_oil *c_oil) +void pim_mroute_update_counters(struct channel_oil *c_oil) { - struct sioc_sg_req sgreq; - - c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; - c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; - c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; - - if (!c_oil->installed) - { - c_oil->cc.lastused = 100 * qpim_keep_alive_time; - if (PIM_DEBUG_MROUTE) - { - struct prefix_sg sg; - - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - if (PIM_DEBUG_MROUTE) - zlog_debug("Channel(%s) is not installed no need to collect data from kernel", - pim_str_sg_dump (&sg)); + struct sioc_sg_req sgreq; + + c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; + c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; + c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + + if (!c_oil->installed) { + c_oil->cc.lastused = 100 * qpim_keep_alive_time; + if (PIM_DEBUG_MROUTE) { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "Channel(%s) is not installed no need to collect data from kernel", + pim_str_sg_dump(&sg)); + } + return; } - return; - } - - memset (&sgreq, 0, sizeof(sgreq)); - sgreq.src = c_oil->oil.mfcc_origin; - sgreq.grp = c_oil->oil.mfcc_mcastgrp; - - pim_zlookup_sg_statistics (c_oil); - if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) - { - if (PIM_DEBUG_MROUTE) - { - struct prefix_sg sg; - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - - zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", - (unsigned long)SIOCGETSGCNT, - pim_str_sg_dump (&sg), - errno, - safe_strerror(errno)); + memset(&sgreq, 0, sizeof(sgreq)); + sgreq.src = c_oil->oil.mfcc_origin; + sgreq.grp = c_oil->oil.mfcc_mcastgrp; + + pim_zlookup_sg_statistics(c_oil); + if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { + if (PIM_DEBUG_MROUTE) { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + + zlog_warn( + "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", + (unsigned long)SIOCGETSGCNT, + pim_str_sg_dump(&sg), errno, + safe_strerror(errno)); + } + return; } - return; - } - c_oil->cc.pktcnt = sgreq.pktcnt; - c_oil->cc.bytecnt = sgreq.bytecnt; - c_oil->cc.wrong_if = sgreq.wrong_if; + c_oil->cc.pktcnt = sgreq.pktcnt; + c_oil->cc.bytecnt = sgreq.bytecnt; + c_oil->cc.wrong_if = sgreq.wrong_if; - return; + return; } |
