]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_igmpv3.c
Merge pull request #2603 from pacovn/PVS-Studio_format_warnings
[mirror_frr.git] / pimd / pim_igmpv3.c
index ad37ad8762e89d4d207ee352b005570a99105267..5ccad39b3356e32cbc60841881139f933702a9d0 100644 (file)
@@ -39,269 +39,271 @@ static void group_query_send(struct igmp_group *group);
 static void source_query_send_by_flag(struct igmp_group *group,
                                      int num_sources_tosend);
 
-static void on_trace(const char *label,
-                    struct interface *ifp, struct in_addr from,
-                    struct in_addr group_addr,
+static void on_trace(const char *label, struct interface *ifp,
+                    struct in_addr from, struct in_addr group_addr,
                     int num_sources, struct in_addr *sources)
 {
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char from_str[INET_ADDRSTRLEN];
-    char group_str[INET_ADDRSTRLEN];
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char from_str[INET_ADDRSTRLEN];
+               char group_str[INET_ADDRSTRLEN];
 
-    pim_inet4_dump("<from?>", from, from_str, sizeof(from_str));
-    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str));
+               pim_inet4_dump("<from?>", from, from_str, sizeof(from_str));
+               pim_inet4_dump("<group?>", group_addr, group_str,
+                              sizeof(group_str));
 
-    zlog_debug("%s: from %s on %s: group=%s sources=%d",
-              label, from_str, ifp->name, group_str, num_sources);
-  }
+               zlog_debug("%s: from %s on %s: group=%s sources=%d", label,
+                          from_str, ifp->name, group_str, num_sources);
+       }
 }
 
 void igmp_group_reset_gmi(struct igmp_group *group)
 {
-  long group_membership_interval_msec;
-  struct pim_interface *pim_ifp;
-  struct igmp_sock *igmp;
-  struct interface *ifp;
-
-  igmp = group->group_igmp_sock;
-  ifp = igmp->interface;
-  pim_ifp = ifp->info;
-
-  /*
-    RFC 3376: 8.4. Group Membership Interval
-
-    The Group Membership Interval is the amount of time that must pass
-    before a multicast router decides there are no more members of a
-    group or a particular source on a network.
-
-    This value MUST be ((the Robustness Variable) times (the Query
-    Interval)) plus (one Query Response Interval).
-
-    group_membership_interval_msec = querier_robustness_variable *
-                                     (1000 * querier_query_interval) +
-                                     100 * query_response_interval_dsec;
-  */
-  group_membership_interval_msec =
-    PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable,
-                     igmp->querier_query_interval,
-                     pim_ifp->igmp_query_max_response_time_dsec);
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    zlog_debug("Resetting group %s timer to GMI=%ld.%03ld sec on %s",
-              group_str,
-              group_membership_interval_msec / 1000,
-              group_membership_interval_msec % 1000,
-              ifp->name);
-  }
-
-  /*
-    RFC 3376: 6.2.2. Definition of Group Timers
-
-    The group timer is only used when a group is in EXCLUDE mode and
-    it represents the time for the *filter-mode* of the group to
-    expire and switch to INCLUDE mode.
-  */
-  zassert(group->group_filtermode_isexcl);
-
-  igmp_group_timer_on(group, group_membership_interval_msec, ifp->name);
+       long group_membership_interval_msec;
+       struct pim_interface *pim_ifp;
+       struct igmp_sock *igmp;
+       struct interface *ifp;
+
+       igmp = group->group_igmp_sock;
+       ifp = igmp->interface;
+       pim_ifp = ifp->info;
+
+       /*
+         RFC 3376: 8.4. Group Membership Interval
+
+         The Group Membership Interval is the amount of time that must pass
+         before a multicast router decides there are no more members of a
+         group or a particular source on a network.
+
+         This value MUST be ((the Robustness Variable) times (the Query
+         Interval)) plus (one Query Response Interval).
+
+         group_membership_interval_msec = querier_robustness_variable *
+                                          (1000 * querier_query_interval) +
+                                          100 * query_response_interval_dsec;
+       */
+       group_membership_interval_msec = PIM_IGMP_GMI_MSEC(
+               igmp->querier_robustness_variable, igmp->querier_query_interval,
+               pim_ifp->igmp_query_max_response_time_dsec);
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "Resetting group %s timer to GMI=%ld.%03ld sec on %s",
+                       group_str, group_membership_interval_msec / 1000,
+                       group_membership_interval_msec % 1000, ifp->name);
+       }
+
+       /*
+         RFC 3376: 6.2.2. Definition of Group Timers
+
+         The group timer is only used when a group is in EXCLUDE mode and
+         it represents the time for the *filter-mode* of the group to
+         expire and switch to INCLUDE mode.
+       */
+       zassert(group->group_filtermode_isexcl);
+
+       igmp_group_timer_on(group, group_membership_interval_msec, ifp->name);
 }
 
 static int igmp_source_timer(struct thread *t)
 {
-  struct igmp_source *source;
-  struct igmp_group *group;
-
-  source = THREAD_ARG(t);
-
-  group = source->source_group;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-    zlog_debug("%s: Source timer expired for group %s source %s on %s",
-              __PRETTY_FUNCTION__,
-              group_str, source_str,
-              group->group_igmp_sock->interface->name);
-  }
-
-  /*
-    RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules
-
-    Group
-    Filter-Mode    Source Timer Value    Action
-    -----------    ------------------    ------
-    INCLUDE        TIMER == 0            Suggest to stop forwarding
-                                         traffic from source and
-                                         remove source record.  If
-                                         there are no more source
-                                         records for the group, delete
-                                         group record.
-
-    EXCLUDE        TIMER == 0            Suggest to not forward
-                                         traffic from source
-                                         (DO NOT remove record)
-
-    Source timer switched from (T > 0) to (T == 0): disable forwarding.
-   */
-
-  if (group->group_filtermode_isexcl) {
-    /* EXCLUDE mode */
-
-    igmp_source_forward_stop(source);
-  }
-  else {
-    /* INCLUDE mode */
-
-    /* igmp_source_delete() will stop forwarding source */
-    igmp_source_delete(source);
-
-    /*
-      If there are no more source records for the group, delete group
-      record.
-    */
-    if (!listcount(group->group_source_list)) {
-      igmp_group_delete_empty_include(group);
-    }
-  }
-
-  return 0;
+       struct igmp_source *source;
+       struct igmp_group *group;
+
+       source = THREAD_ARG(t);
+
+       group = source->source_group;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+               zlog_debug(
+                       "%s: Source timer expired for group %s source %s on %s",
+                       __PRETTY_FUNCTION__, group_str, source_str,
+                       group->group_igmp_sock->interface->name);
+       }
+
+       /*
+         RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules
+
+         Group
+         Filter-Mode    Source Timer Value    Action
+         -----------    ------------------    ------
+         INCLUDE        TIMER == 0            Suggest to stop forwarding
+                                              traffic from source and
+                                              remove source record.  If
+                                              there are no more source
+                                              records for the group, delete
+                                              group record.
+
+         EXCLUDE        TIMER == 0            Suggest to not forward
+                                              traffic from source
+                                              (DO NOT remove record)
+
+         Source timer switched from (T > 0) to (T == 0): disable forwarding.
+        */
+
+       if (group->group_filtermode_isexcl) {
+               /* EXCLUDE mode */
+
+               igmp_source_forward_stop(source);
+       } else {
+               /* INCLUDE mode */
+
+               /* igmp_source_delete() will stop forwarding source */
+               igmp_source_delete(source);
+
+               /*
+                 If there are no more source records for the group, delete
+                 group
+                 record.
+               */
+               if (!listcount(group->group_source_list)) {
+                       igmp_group_delete_empty_include(group);
+               }
+       }
+
+       return 0;
 }
 
 static void source_timer_off(struct igmp_group *group,
                             struct igmp_source *source)
 {
-  if (!source->t_source_timer)
-    return;
-  
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-    zlog_debug("Cancelling TIMER event for group %s source %s on %s",
-              group_str, source_str,
-              group->group_igmp_sock->interface->name);
-  }
-
-  THREAD_OFF(source->t_source_timer);
+       if (!source->t_source_timer)
+               return;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+               zlog_debug(
+                       "Cancelling TIMER event for group %s source %s on %s",
+                       group_str, source_str,
+                       group->group_igmp_sock->interface->name);
+       }
+
+       THREAD_OFF(source->t_source_timer);
 }
 
 static void igmp_source_timer_on(struct igmp_group *group,
-                                struct igmp_source *source,
-                                long interval_msec)
+                                struct igmp_source *source, long interval_msec)
 {
-  source_timer_off(group, source);
-
-  if (PIM_DEBUG_IGMP_EVENTS) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-    zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s",
-              interval_msec / 1000,
-              interval_msec % 1000,
-              group_str, source_str,
-              group->group_igmp_sock->interface->name);
-  }
-
-  thread_add_timer_msec(master, igmp_source_timer, source, interval_msec,
-                        &source->t_source_timer);
-
-  /*
-    RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules
-    
-    Source timer switched from (T == 0) to (T > 0): enable forwarding.
-  */
-  igmp_source_forward_start(source);
+       source_timer_off(group, source);
+       struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
+
+       if (PIM_DEBUG_IGMP_EVENTS) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+               zlog_debug(
+                       "Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s",
+                       interval_msec / 1000, interval_msec % 1000, group_str,
+                       source_str, group->group_igmp_sock->interface->name);
+       }
+
+       thread_add_timer_msec(master, igmp_source_timer, source, interval_msec,
+                             &source->t_source_timer);
+
+       /*
+         RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules
+
+         Source timer switched from (T == 0) to (T > 0): enable forwarding.
+       */
+       igmp_source_forward_start(pim_ifp->pim, source);
 }
 
-void igmp_source_reset_gmi(struct igmp_sock *igmp,
-                          struct igmp_group *group,
+void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group,
                           struct igmp_source *source)
 {
-  long group_membership_interval_msec;
-  struct pim_interface *pim_ifp;
-  struct interface *ifp;
-
-  ifp = igmp->interface;
-  pim_ifp = ifp->info;
-
-  group_membership_interval_msec =
-    PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable,
-                     igmp->querier_query_interval,
-                     pim_ifp->igmp_query_max_response_time_dsec);
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-
-    zlog_debug("Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s",
-              source_str,
-              group_membership_interval_msec / 1000,
-              group_membership_interval_msec % 1000,
-              group_str,
-              ifp->name);
-  }
-
-  igmp_source_timer_on(group, source,
-                      group_membership_interval_msec);
+       long group_membership_interval_msec;
+       struct pim_interface *pim_ifp;
+       struct interface *ifp;
+
+       ifp = igmp->interface;
+       pim_ifp = ifp->info;
+
+       group_membership_interval_msec = PIM_IGMP_GMI_MSEC(
+               igmp->querier_robustness_variable, igmp->querier_query_interval,
+               pim_ifp->igmp_query_max_response_time_dsec);
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+
+               zlog_debug(
+                       "Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s",
+                       source_str, group_membership_interval_msec / 1000,
+                       group_membership_interval_msec % 1000, group_str,
+                       ifp->name);
+       }
+
+       igmp_source_timer_on(group, source, group_membership_interval_msec);
 }
 
 static void source_mark_delete_flag(struct igmp_group *group)
 {
-  struct listnode    *src_node;
-  struct igmp_source *src;
+       struct listnode *src_node;
+       struct igmp_source *src;
 
-  for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) {
-    IGMP_SOURCE_DO_DELETE(src->source_flags);
-  }
+       for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
+               IGMP_SOURCE_DO_DELETE(src->source_flags);
+       }
 }
 
-static void source_mark_send_flag (struct igmp_group *group)
+static void source_mark_send_flag(struct igmp_group *group)
 {
-  struct listnode    *src_node;
-  struct igmp_source *src;
+       struct listnode *src_node;
+       struct igmp_source *src;
 
-  for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) {
-    IGMP_SOURCE_DO_SEND(src->source_flags);
-  }
+       for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
+               IGMP_SOURCE_DO_SEND(src->source_flags);
+       }
 }
 
-static int source_mark_send_flag_by_timer (struct igmp_group *group)
+static int source_mark_send_flag_by_timer(struct igmp_group *group)
 {
-  struct listnode    *src_node;
-  struct igmp_source *src;
-  int                 num_marked_sources = 0;
-
-  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
-    /* Is source timer running? */
-    if (src->t_source_timer) {
-      IGMP_SOURCE_DO_SEND(src->source_flags);
-      ++num_marked_sources;
-    }
-    else {
-      IGMP_SOURCE_DONT_SEND(src->source_flags);
-    }
-  }
-
-  return num_marked_sources;
+       struct listnode *src_node;
+       struct igmp_source *src;
+       int num_marked_sources = 0;
+
+       for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
+               /* Is source timer running? */
+               if (src->t_source_timer) {
+                       IGMP_SOURCE_DO_SEND(src->source_flags);
+                       ++num_marked_sources;
+               } else {
+                       IGMP_SOURCE_DONT_SEND(src->source_flags);
+               }
+       }
+
+       return num_marked_sources;
 }
 
 static void source_clear_send_flag(struct list *source_list)
 {
-  struct listnode    *src_node;
-  struct igmp_source *src;
+       struct listnode *src_node;
+       struct igmp_source *src;
 
-  for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) {
-    IGMP_SOURCE_DONT_SEND(src->source_flags);
-  }
+       for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) {
+               IGMP_SOURCE_DONT_SEND(src->source_flags);
+       }
 }
 
 /*
@@ -309,27 +311,29 @@ static void source_clear_send_flag(struct list *source_list)
 */
 static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group)
 {
-  zassert(group->group_filtermode_isexcl);
+       struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
 
-  if (listcount(group->group_source_list) < 1) {
-    igmp_anysource_forward_start(group);
-  }
+       zassert(group->group_filtermode_isexcl);
+
+       if (listcount(group->group_source_list) < 1) {
+               igmp_anysource_forward_start(pim_ifp->pim, group);
+       }
 }
 
 void igmp_source_free(struct igmp_source *source)
 {
-  /* make sure there is no source timer running */
-  zassert(!source->t_source_timer);
+       /* make sure there is no source timer running */
+       zassert(!source->t_source_timer);
 
-  XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source);
+       XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source);
 }
 
 static void source_channel_oil_detach(struct igmp_source *source)
 {
-  if (source->source_channel_oil) {
-    pim_channel_oil_del(source->source_channel_oil);
-    source->source_channel_oil = NULL;
-  }
+       if (source->source_channel_oil) {
+               pim_channel_oil_del(source->source_channel_oil);
+               source->source_channel_oil = NULL;
+       }
 }
 
 /*
@@ -338,662 +342,662 @@ static void source_channel_oil_detach(struct igmp_source *source)
 */
 void igmp_source_delete(struct igmp_source *source)
 {
-  struct igmp_group *group;
-  struct in_addr src;
-
-  group = source->source_group;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-    zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d",
-              source_str, group_str,
-              group->group_igmp_sock->fd,
-              group->group_igmp_sock->interface->name,
-               source->source_channel_oil ? source->source_channel_oil->oil_ref_count : 0);
-  }
-
-  source_timer_off(group, source);
-  igmp_source_forward_stop(source);
-
-  /* sanity check that forwarding has been disabled */
-  if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-    zlog_warn("%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s",
-             __PRETTY_FUNCTION__,
-             source_str, group_str,
-             group->group_igmp_sock->fd,
-             group->group_igmp_sock->interface->name);
-    /* warning only */
-  }
-
-  source_channel_oil_detach(source);
-
-  /*
-    notice that listnode_delete() can't be moved
-    into igmp_source_free() because the later is
-    called by list_delete_all_node()
-  */
-  listnode_delete(group->group_source_list, source);
-
-  src.s_addr = source->source_addr.s_addr;
-  igmp_source_free(source);
-
-  /* Group source list is empty and current source is * then
-   *,G group going away so do not trigger start */
-  if (group->group_filtermode_isexcl &&
-      (listcount (group->group_source_list) != 0) &&
-      src.s_addr != INADDR_ANY)
-    {
-      group_exclude_fwd_anysrc_ifempty (group);
-    }
+       struct igmp_group *group;
+       struct in_addr src;
+
+       group = source->source_group;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+               zlog_debug(
+                       "Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d",
+                       source_str, group_str, group->group_igmp_sock->fd,
+                       group->group_igmp_sock->interface->name,
+                       source->source_channel_oil
+                               ? source->source_channel_oil->oil_ref_count
+                               : 0);
+       }
+
+       source_timer_off(group, source);
+       igmp_source_forward_stop(source);
+
+       /* sanity check that forwarding has been disabled */
+       if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+               zlog_warn(
+                       "%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s",
+                       __PRETTY_FUNCTION__, source_str, group_str,
+                       group->group_igmp_sock->fd,
+                       group->group_igmp_sock->interface->name);
+               /* warning only */
+       }
+
+       source_channel_oil_detach(source);
+
+       /*
+         notice that listnode_delete() can't be moved
+         into igmp_source_free() because the later is
+         called by list_delete_all_node()
+       */
+       listnode_delete(group->group_source_list, source);
+
+       src.s_addr = source->source_addr.s_addr;
+       igmp_source_free(source);
+
+       /* Group source list is empty and current source is * then
+        *,G group going away so do not trigger start */
+       if (group->group_filtermode_isexcl
+           && (listcount(group->group_source_list) != 0)
+           && src.s_addr != INADDR_ANY) {
+               group_exclude_fwd_anysrc_ifempty(group);
+       }
 }
 
 static void source_delete_by_flag(struct list *source_list)
 {
-  struct listnode    *src_node;
-  struct listnode    *src_nextnode;
-  struct igmp_source *src;
-  
-  for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src))
-    if (IGMP_SOURCE_TEST_DELETE(src->source_flags))
-      igmp_source_delete(src);
+       struct listnode *src_node;
+       struct listnode *src_nextnode;
+       struct igmp_source *src;
+
+       for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src))
+               if (IGMP_SOURCE_TEST_DELETE(src->source_flags))
+                       igmp_source_delete(src);
 }
 
 void igmp_source_delete_expired(struct list *source_list)
 {
-  struct listnode    *src_node;
-  struct listnode    *src_nextnode;
-  struct igmp_source *src;
-  
-  for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src))
-    if (!src->t_source_timer)
-      igmp_source_delete(src);
+       struct listnode *src_node;
+       struct listnode *src_nextnode;
+       struct igmp_source *src;
+
+       for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src))
+               if (!src->t_source_timer)
+                       igmp_source_delete(src);
 }
 
 struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group,
                                             struct in_addr src_addr)
 {
-  struct listnode    *src_node;
-  struct igmp_source *src;
+       struct listnode *src_node;
+       struct igmp_source *src;
 
-  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src))
-    if (src_addr.s_addr == src->source_addr.s_addr)
-      return src;
+       for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src))
+               if (src_addr.s_addr == src->source_addr.s_addr)
+                       return src;
 
-  return 0;
+       return 0;
 }
 
-struct igmp_source *
-source_new (struct igmp_group *group,
-           struct in_addr src_addr)
+struct igmp_source *source_new(struct igmp_group *group,
+                              struct in_addr src_addr)
 {
-  struct igmp_source *src;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", src_addr, source_str, sizeof(source_str));
-    zlog_debug("Creating new IGMP source %s for group %s on socket %d interface %s",
-              source_str, group_str,
-              group->group_igmp_sock->fd,
-              group->group_igmp_sock->interface->name);
-  }
-
-  src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src));
-  if (!src) {
-    zlog_warn("%s %s: XCALLOC() failure",
-             __FILE__, __PRETTY_FUNCTION__);
-    return 0; /* error, not found, could not create */
-  }
-  
-  src->t_source_timer                = NULL;
-  src->source_group                  = group; /* back pointer */
-  src->source_addr                   = src_addr;
-  src->source_creation               = pim_time_monotonic_sec();
-  src->source_flags                  = 0;
-  src->source_query_retransmit_count = 0;
-  src->source_channel_oil            = NULL;
-
-  listnode_add(group->group_source_list, src);
-
-  /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
-  igmp_anysource_forward_stop(group);
-
-  return src;
+       struct igmp_source *src;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", src_addr, source_str,
+                              sizeof(source_str));
+               zlog_debug(
+                       "Creating new IGMP source %s for group %s on socket %d interface %s",
+                       source_str, group_str, group->group_igmp_sock->fd,
+                       group->group_igmp_sock->interface->name);
+       }
+
+       src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src));
+       if (!src) {
+               zlog_warn("%s %s: XCALLOC() failure", __FILE__,
+                         __PRETTY_FUNCTION__);
+               return 0; /* error, not found, could not create */
+       }
+
+       src->t_source_timer = NULL;
+       src->source_group = group; /* back pointer */
+       src->source_addr = src_addr;
+       src->source_creation = pim_time_monotonic_sec();
+       src->source_flags = 0;
+       src->source_query_retransmit_count = 0;
+       src->source_channel_oil = NULL;
+
+       listnode_add(group->group_source_list, src);
+
+       /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
+       igmp_anysource_forward_stop(group);
+
+       return src;
 }
 
 static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp,
                                              struct igmp_group *group,
                                              struct in_addr src_addr)
 {
-  struct igmp_source *src;
+       struct igmp_source *src;
 
-  src = igmp_find_source_by_addr(group, src_addr);
-  if (src) {
-    return src;
-  }
+       src = igmp_find_source_by_addr(group, src_addr);
+       if (src) {
+               return src;
+       }
 
-  src = source_new(group, src_addr);
-  if (!src) {
-    return 0;
-  }
+       src = source_new(group, src_addr);
+       if (!src) {
+               return 0;
+       }
 
-  return src;
+       return src;
 }
 
 static void allow(struct igmp_sock *igmp, struct in_addr from,
-                 struct in_addr group_addr,
-                 int num_sources, struct in_addr *sources)
+                 struct in_addr group_addr, int num_sources,
+                 struct in_addr *sources)
 {
-  struct igmp_source *source;
-  struct igmp_group *group;
-  int    i;
-
-  /* non-existant group is created as INCLUDE {empty} */
-  group = igmp_add_group_by_addr(igmp, group_addr);
-  if (!group) {
-    return;
-  }
-
-  /* scan received sources */
-  for (i = 0; i < num_sources; ++i) {
-    struct in_addr     *src_addr;
-
-    src_addr = sources + i;
-
-    source = add_source_by_addr(igmp, group, *src_addr);
-    if (!source) {
-      continue;
-    }
-
-    /*
-      RFC 3376: 6.4.1. Reception of Current-State Records
-
-      When receiving IS_IN reports for groups in EXCLUDE mode is
-      sources should be moved from set with (timers = 0) to set with
-      (timers > 0).
-
-      igmp_source_reset_gmi() below, resetting the source timers to
-      GMI, accomplishes this.
-    */
-    igmp_source_reset_gmi(igmp, group, source);
-
-  } /* scan received sources */
-
-  if ((num_sources == 0) &&
-      (group->group_filtermode_isexcl) &&
-      (listcount (group->group_source_list) == 1))
-    {
-      struct in_addr star = { .s_addr = INADDR_ANY };
-
-      source = igmp_find_source_by_addr (group, star);
-      if (source)
-       igmp_source_reset_gmi (igmp, group, source);
-    }
+       struct igmp_source *source;
+       struct igmp_group *group;
+       int i;
+
+       /* non-existant group is created as INCLUDE {empty} */
+       group = igmp_add_group_by_addr(igmp, group_addr);
+       if (!group) {
+               return;
+       }
+
+       /* scan received sources */
+       for (i = 0; i < num_sources; ++i) {
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               source = add_source_by_addr(igmp, group, *src_addr);
+               if (!source) {
+                       continue;
+               }
+
+               /*
+                 RFC 3376: 6.4.1. Reception of Current-State Records
+
+                 When receiving IS_IN reports for groups in EXCLUDE mode is
+                 sources should be moved from set with (timers = 0) to set with
+                 (timers > 0).
+
+                 igmp_source_reset_gmi() below, resetting the source timers to
+                 GMI, accomplishes this.
+               */
+               igmp_source_reset_gmi(igmp, group, source);
+
+       } /* scan received sources */
+
+       if ((num_sources == 0) && (group->group_filtermode_isexcl)
+           && (listcount(group->group_source_list) == 1)) {
+               struct in_addr star = {.s_addr = INADDR_ANY};
+
+               source = igmp_find_source_by_addr(group, star);
+               if (source)
+                       igmp_source_reset_gmi(igmp, group, source);
+       }
 }
 
 void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from,
-                       struct in_addr group_addr,
-                       int num_sources, struct in_addr *sources)
+                       struct in_addr group_addr, int num_sources,
+                       struct in_addr *sources)
 {
-  on_trace(__PRETTY_FUNCTION__,
-          igmp->interface, from, group_addr, num_sources, sources);
+       on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr,
+                num_sources, sources);
 
-  allow(igmp, from, group_addr, num_sources, sources);
+       allow(igmp, from, group_addr, num_sources, sources);
 }
 
-static void isex_excl(struct igmp_group *group,
-                     int num_sources, struct in_addr *sources)
+static void isex_excl(struct igmp_group *group, int num_sources,
+                     struct in_addr *sources)
 {
-  struct igmp_source *source;
-  int     i;
-
-  /* EXCLUDE mode */
-  zassert(group->group_filtermode_isexcl);
-  
-  /* E.1: set deletion flag for known sources (X,Y) */
-  source_mark_delete_flag (group);
-
-  /* scan received sources (A) */
-  for (i = 0; i < num_sources; ++i) {
-    struct in_addr     *src_addr;
-
-    src_addr = sources + i;
-
-    /* E.2: lookup reported source from (A) in (X,Y) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */
-      IGMP_SOURCE_DONT_DELETE(source->source_flags);
-    }
-    else {
-      /* E.4: if not found, create source with timer=GMI: (A-X-Y) */
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-      zassert(!source->t_source_timer); /* timer == 0 */
-      igmp_source_reset_gmi(group->group_igmp_sock, group, source);
-      zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
-    }
-
-  } /* scan received sources */
-
-  /*
-   * If we are in isexcl mode and num_sources == 0
-   * than that means we have a *,g entry that
-   * needs to be handled
-   */
-  if (group->group_filtermode_isexcl && num_sources == 0)
-    {
-       struct in_addr star = { .s_addr = INADDR_ANY };
-       source = igmp_find_source_by_addr (group, star);
-       if (source)
-         {
-           IGMP_SOURCE_DONT_DELETE(source->source_flags);
-           igmp_source_reset_gmi (group->group_igmp_sock, group, source);
-         }
-    }
-
-  /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */
-  source_delete_by_flag(group->group_source_list);
+       struct igmp_source *source;
+       int i;
+
+       /* EXCLUDE mode */
+       zassert(group->group_filtermode_isexcl);
+
+       /* E.1: set deletion flag for known sources (X,Y) */
+       source_mark_delete_flag(group);
+
+       /* scan received sources (A) */
+       for (i = 0; i < num_sources; ++i) {
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* E.2: lookup reported source from (A) in (X,Y) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */
+                       IGMP_SOURCE_DONT_DELETE(source->source_flags);
+               } else {
+                       /* E.4: if not found, create source with timer=GMI:
+                        * (A-X-Y) */
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+                       zassert(!source->t_source_timer); /* timer == 0 */
+                       igmp_source_reset_gmi(group->group_igmp_sock, group,
+                                             source);
+                       zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
+               }
+
+       } /* scan received sources */
+
+       /*
+        * If we are in isexcl mode and num_sources == 0
+        * than that means we have a *,g entry that
+        * needs to be handled
+        */
+       if (group->group_filtermode_isexcl && num_sources == 0) {
+               struct in_addr star = {.s_addr = INADDR_ANY};
+               source = igmp_find_source_by_addr(group, star);
+               if (source) {
+                       IGMP_SOURCE_DONT_DELETE(source->source_flags);
+                       igmp_source_reset_gmi(group->group_igmp_sock, group,
+                                             source);
+               }
+       }
+
+       /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */
+       source_delete_by_flag(group->group_source_list);
 }
 
-static void isex_incl(struct igmp_group *group,
-                     int num_sources, struct in_addr *sources)
+static void isex_incl(struct igmp_group *group, int num_sources,
+                     struct in_addr *sources)
 {
-  int i;
-
-  /* INCLUDE mode */
-  zassert(!group->group_filtermode_isexcl);
-  
-  /* I.1: set deletion flag for known sources (A) */
-  source_mark_delete_flag (group);
-
-  /* scan received sources (B) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-
-    src_addr = sources + i;
-
-    /* I.2: lookup reported source (B) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      /* I.3: if found, clear deletion flag (A*B) */
-      IGMP_SOURCE_DONT_DELETE(source->source_flags);
-    }
-    else {
-      /* I.4: if not found, create source with timer=0 (B-A) */
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-      zassert(!source->t_source_timer); /* (B-A) timer=0 */
-    }
-
-  } /* scan received sources */
-
-  /* I.5: delete all sources marked with deletion flag (A-B) */
-  source_delete_by_flag(group->group_source_list);
-
-  group->group_filtermode_isexcl = 1; /* boolean=true */
-
-  zassert(group->group_filtermode_isexcl);
-
-  group_exclude_fwd_anysrc_ifempty(group);
+       int i;
+
+       /* INCLUDE mode */
+       zassert(!group->group_filtermode_isexcl);
+
+       /* I.1: set deletion flag for known sources (A) */
+       source_mark_delete_flag(group);
+
+       /* scan received sources (B) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* I.2: lookup reported source (B) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       /* I.3: if found, clear deletion flag (A*B) */
+                       IGMP_SOURCE_DONT_DELETE(source->source_flags);
+               } else {
+                       /* I.4: if not found, create source with timer=0 (B-A)
+                        */
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+                       zassert(!source->t_source_timer); /* (B-A) timer=0 */
+               }
+
+       } /* scan received sources */
+
+       /* I.5: delete all sources marked with deletion flag (A-B) */
+       source_delete_by_flag(group->group_source_list);
+
+       group->group_filtermode_isexcl = 1; /* boolean=true */
+
+       zassert(group->group_filtermode_isexcl);
+
+       group_exclude_fwd_anysrc_ifempty(group);
 }
 
 void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from,
-                       struct in_addr group_addr,
-                       int num_sources, struct in_addr *sources,
-                        int from_igmp_v2_report)
+                       struct in_addr group_addr, int num_sources,
+                       struct in_addr *sources, int from_igmp_v2_report)
 {
-  struct interface *ifp = igmp->interface;
-  struct igmp_group *group;
-
-  on_trace(__PRETTY_FUNCTION__,
-          ifp, from, group_addr, num_sources, sources);
-
-  /* non-existant group is created as INCLUDE {empty} */
-  group = igmp_add_group_by_addr(igmp, group_addr);
-  if (!group) {
-    return;
-  }
-
-  /* So we can display how we learned the group in our show command output */
-  if (from_igmp_v2_report)
-    group->igmp_version = 2;
-
-  if (group->group_filtermode_isexcl) {
-    /* EXCLUDE mode */
-    isex_excl(group, num_sources, sources);
-  }
-  else {
-    /* INCLUDE mode */
-    isex_incl(group, num_sources, sources);
-    zassert(group->group_filtermode_isexcl);
-  }
-
-  zassert(group->group_filtermode_isexcl);
-
-  igmp_group_reset_gmi(group);
+       struct interface *ifp = igmp->interface;
+       struct igmp_group *group;
+
+       on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources,
+                sources);
+
+       if (pim_is_group_filtered(ifp->info, &group_addr))
+               return;
+
+       /* non-existant group is created as INCLUDE {empty} */
+       group = igmp_add_group_by_addr(igmp, group_addr);
+       if (!group) {
+               return;
+       }
+
+       /* So we can display how we learned the group in our show command output
+        */
+       if (from_igmp_v2_report)
+               group->igmp_version = 2;
+
+       if (group->group_filtermode_isexcl) {
+               /* EXCLUDE mode */
+               isex_excl(group, num_sources, sources);
+       } else {
+               /* INCLUDE mode */
+               isex_incl(group, num_sources, sources);
+               zassert(group->group_filtermode_isexcl);
+       }
+
+       zassert(group->group_filtermode_isexcl);
+
+       igmp_group_reset_gmi(group);
 }
 
-static void toin_incl(struct igmp_group *group,
-                     int num_sources, struct in_addr *sources)
+static void toin_incl(struct igmp_group *group, int num_sources,
+                     struct in_addr *sources)
 {
-  struct igmp_sock *igmp = group->group_igmp_sock;
-  int num_sources_tosend = listcount(group->group_source_list);
-  int i;
-
-  /* Set SEND flag for all known sources (A) */
-  source_mark_send_flag (group);
-
-  /* Scan received sources (B) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-
-    src_addr = sources + i;
-
-    /* Lookup reported source (B) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      /* If found, clear SEND flag (A*B) */
-      IGMP_SOURCE_DONT_SEND(source->source_flags);
-      --num_sources_tosend;
-    }
-    else {
-      /* If not found, create new source */
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-    }
-
-    /* (B)=GMI */
-    igmp_source_reset_gmi(igmp, group, source);
-  }
-
-  /* Send sources marked with SEND flag: Q(G,A-B) */
-  if (num_sources_tosend > 0) {
-    source_query_send_by_flag(group, num_sources_tosend);
-  }
+       struct igmp_sock *igmp = group->group_igmp_sock;
+       int num_sources_tosend = listcount(group->group_source_list);
+       int i;
+
+       /* Set SEND flag for all known sources (A) */
+       source_mark_send_flag(group);
+
+       /* Scan received sources (B) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* Lookup reported source (B) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       /* If found, clear SEND flag (A*B) */
+                       IGMP_SOURCE_DONT_SEND(source->source_flags);
+                       --num_sources_tosend;
+               } else {
+                       /* If not found, create new source */
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+               }
+
+               /* (B)=GMI */
+               igmp_source_reset_gmi(igmp, group, source);
+       }
+
+       /* Send sources marked with SEND flag: Q(G,A-B) */
+       if (num_sources_tosend > 0) {
+               source_query_send_by_flag(group, num_sources_tosend);
+       }
 }
 
-static void toin_excl(struct igmp_group *group,
-                     int num_sources, struct in_addr *sources)
+static void toin_excl(struct igmp_group *group, int num_sources,
+                     struct in_addr *sources)
 {
-  struct igmp_sock *igmp = group->group_igmp_sock;
-  int num_sources_tosend;
-  int i;
-
-  /* Set SEND flag for X (sources with timer > 0) */
-  num_sources_tosend = source_mark_send_flag_by_timer (group);
-
-  /* Scan received sources (A) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-
-    src_addr = sources + i;
-
-    /* Lookup reported source (A) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      if (source->t_source_timer) {
-       /* If found and timer running, clear SEND flag (X*A) */
-       IGMP_SOURCE_DONT_SEND(source->source_flags);
-       --num_sources_tosend;
-      }
-    }
-    else {
-      /* If not found, create new source */
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-    }
-
-    /* (A)=GMI */
-    igmp_source_reset_gmi(igmp, group, source);
-  }
-
-  /* Send sources marked with SEND flag: Q(G,X-A) */
-  if (num_sources_tosend > 0) {
-    source_query_send_by_flag(group, num_sources_tosend);
-  }
-
-  /* Send Q(G) */
-  group_query_send(group);
+       struct igmp_sock *igmp = group->group_igmp_sock;
+       int num_sources_tosend;
+       int i;
+
+       /* Set SEND flag for X (sources with timer > 0) */
+       num_sources_tosend = source_mark_send_flag_by_timer(group);
+
+       /* Scan received sources (A) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* Lookup reported source (A) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       if (source->t_source_timer) {
+                               /* If found and timer running, clear SEND flag
+                                * (X*A) */
+                               IGMP_SOURCE_DONT_SEND(source->source_flags);
+                               --num_sources_tosend;
+                       }
+               } else {
+                       /* If not found, create new source */
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+               }
+
+               /* (A)=GMI */
+               igmp_source_reset_gmi(igmp, group, source);
+       }
+
+       /* Send sources marked with SEND flag: Q(G,X-A) */
+       if (num_sources_tosend > 0) {
+               source_query_send_by_flag(group, num_sources_tosend);
+       }
+
+       /* Send Q(G) */
+       group_query_send(group);
 }
 
 void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from,
-                       struct in_addr group_addr,
-                       int num_sources, struct in_addr *sources)
+                       struct in_addr group_addr, int num_sources,
+                       struct in_addr *sources)
 {
-  struct interface *ifp = igmp->interface;
-  struct igmp_group *group;
-
-  on_trace(__PRETTY_FUNCTION__,
-          ifp, from, group_addr, num_sources, sources);
-
-  /*
-   * If the requested filter mode is INCLUDE *and* the requested source
-   * list is empty, then the entry corresponding to the requested
-   * interface and multicast address is deleted if present.  If no such
-   * entry is present, the request is ignored.
-   */
-  if (num_sources)
-    {
-      /* non-existant group is created as INCLUDE {empty} */
-      group = igmp_add_group_by_addr(igmp, group_addr);
-      if (!group) {
-       return;
-      }
-    }
-  else
-    {
-      group = find_group_by_addr (igmp, group_addr);
-      if (!group)
-       return;
-    }
-
-  if (group->group_filtermode_isexcl) {
-    /* EXCLUDE mode */
-    toin_excl(group, num_sources, sources);
-  }
-  else {
-    /* INCLUDE mode */
-    toin_incl(group, num_sources, sources);
-  }
+       struct interface *ifp = igmp->interface;
+       struct igmp_group *group;
+
+       on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources,
+                sources);
+
+       /*
+        * If the requested filter mode is INCLUDE *and* the requested source
+        * list is empty, then the entry corresponding to the requested
+        * interface and multicast address is deleted if present.  If no such
+        * entry is present, the request is ignored.
+        */
+       if (num_sources) {
+               /* non-existant group is created as INCLUDE {empty} */
+               group = igmp_add_group_by_addr(igmp, group_addr);
+               if (!group) {
+                       return;
+               }
+       } else {
+               group = find_group_by_addr(igmp, group_addr);
+               if (!group)
+                       return;
+       }
+
+       if (group->group_filtermode_isexcl) {
+               /* EXCLUDE mode */
+               toin_excl(group, num_sources, sources);
+       } else {
+               /* INCLUDE mode */
+               toin_incl(group, num_sources, sources);
+       }
 }
 
-static void toex_incl(struct igmp_group *group,
-                     int num_sources, struct in_addr *sources)
+static void toex_incl(struct igmp_group *group, int num_sources,
+                     struct in_addr *sources)
 {
-  int num_sources_tosend = 0;
-  int i;
-
-  zassert(!group->group_filtermode_isexcl);
-
-  /* Set DELETE flag for all known sources (A) */
-  source_mark_delete_flag (group);
-
-  /* Clear off SEND flag from all known sources (A) */
-  source_clear_send_flag(group->group_source_list);
-
-  /* Scan received sources (B) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-
-    src_addr = sources + i;
-
-    /* Lookup reported source (B) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      /* If found, clear deletion flag: (A*B) */
-      IGMP_SOURCE_DONT_DELETE(source->source_flags);
-      /* and set SEND flag (A*B) */
-      IGMP_SOURCE_DO_SEND(source->source_flags);
-      ++num_sources_tosend;
-    }
-    else {
-      /* If source not found, create source with timer=0: (B-A)=0 */
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-      zassert(!source->t_source_timer); /* (B-A) timer=0 */
-    }
-
-  } /* Scan received sources (B) */
-
-  group->group_filtermode_isexcl = 1; /* boolean=true */
-
-  /* Delete all sources marked with DELETE flag (A-B) */
-  source_delete_by_flag(group->group_source_list);
-
-  /* Send sources marked with SEND flag: Q(G,A*B) */
-  if (num_sources_tosend > 0) {
-    source_query_send_by_flag(group, num_sources_tosend);
-  }
-
-  zassert(group->group_filtermode_isexcl);
-
-  group_exclude_fwd_anysrc_ifempty(group);
+       int num_sources_tosend = 0;
+       int i;
+
+       zassert(!group->group_filtermode_isexcl);
+
+       /* Set DELETE flag for all known sources (A) */
+       source_mark_delete_flag(group);
+
+       /* Clear off SEND flag from all known sources (A) */
+       source_clear_send_flag(group->group_source_list);
+
+       /* Scan received sources (B) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* Lookup reported source (B) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       /* If found, clear deletion flag: (A*B) */
+                       IGMP_SOURCE_DONT_DELETE(source->source_flags);
+                       /* and set SEND flag (A*B) */
+                       IGMP_SOURCE_DO_SEND(source->source_flags);
+                       ++num_sources_tosend;
+               } else {
+                       /* If source not found, create source with timer=0:
+                        * (B-A)=0 */
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+                       zassert(!source->t_source_timer); /* (B-A) timer=0 */
+               }
+
+       } /* Scan received sources (B) */
+
+       group->group_filtermode_isexcl = 1; /* boolean=true */
+
+       /* Delete all sources marked with DELETE flag (A-B) */
+       source_delete_by_flag(group->group_source_list);
+
+       /* Send sources marked with SEND flag: Q(G,A*B) */
+       if (num_sources_tosend > 0) {
+               source_query_send_by_flag(group, num_sources_tosend);
+       }
+
+       zassert(group->group_filtermode_isexcl);
+
+       group_exclude_fwd_anysrc_ifempty(group);
 }
 
-static void toex_excl(struct igmp_group *group,
-                     int num_sources, struct in_addr *sources)
+static void toex_excl(struct igmp_group *group, int num_sources,
+                     struct in_addr *sources)
 {
-  int num_sources_tosend = 0;
-  int i;
-
-  /* set DELETE flag for all known sources (X,Y) */
-  source_mark_delete_flag (group);
-
-  /* clear off SEND flag from all known sources (X,Y) */
-  source_clear_send_flag(group->group_source_list);
-
-  if (num_sources == 0)
-    {
-      struct igmp_source *source;
-      struct in_addr any = { .s_addr = INADDR_ANY };
-
-      source = igmp_find_source_by_addr (group, any);
-      if (source)
-        IGMP_SOURCE_DONT_DELETE(source->source_flags);
-    }
-
-  /* scan received sources (A) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-    
-    src_addr = sources + i;
-    
-    /* lookup reported source (A) in known sources (X,Y) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      /* if found, clear off DELETE flag from reported source (A) */
-      IGMP_SOURCE_DONT_DELETE(source->source_flags);
-    }
-    else {
-      /* if not found, create source with Group Timer: (A-X-Y)=Group Timer */
-      long group_timer_msec;
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-
-      zassert(!source->t_source_timer); /* timer == 0 */
-      group_timer_msec = igmp_group_timer_remain_msec(group);
-      igmp_source_timer_on(group, source, group_timer_msec);
-      zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
-
-      /* make sure source is created with DELETE flag unset */
-      zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
-    }
-
-    /* make sure reported source has DELETE flag unset */
-    zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
-
-    if (source->t_source_timer) {
-      /* if source timer>0 mark SEND flag: Q(G,A-Y) */
-      IGMP_SOURCE_DO_SEND(source->source_flags);
-      ++num_sources_tosend;
-    }
-
-  } /* scan received sources (A) */
-
-  /*
-    delete all sources marked with DELETE flag:
-    Delete (X-A)
-    Delete (Y-A)
-  */
-  source_delete_by_flag(group->group_source_list);
-  /* send sources marked with SEND flag: Q(G,A-Y) */
-  if (num_sources_tosend > 0) {
-    source_query_send_by_flag(group, num_sources_tosend);
-  }
+       int num_sources_tosend = 0;
+       int i;
+
+       /* set DELETE flag for all known sources (X,Y) */
+       source_mark_delete_flag(group);
+
+       /* clear off SEND flag from all known sources (X,Y) */
+       source_clear_send_flag(group->group_source_list);
+
+       if (num_sources == 0) {
+               struct igmp_source *source;
+               struct in_addr any = {.s_addr = INADDR_ANY};
+
+               source = igmp_find_source_by_addr(group, any);
+               if (source)
+                       IGMP_SOURCE_DONT_DELETE(source->source_flags);
+       }
+
+       /* scan received sources (A) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* lookup reported source (A) in known sources (X,Y) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       /* if found, clear off DELETE flag from reported source
+                        * (A) */
+                       IGMP_SOURCE_DONT_DELETE(source->source_flags);
+               } else {
+                       /* if not found, create source with Group Timer:
+                        * (A-X-Y)=Group Timer */
+                       long group_timer_msec;
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+
+                       zassert(!source->t_source_timer); /* timer == 0 */
+                       group_timer_msec = igmp_group_timer_remain_msec(group);
+                       igmp_source_timer_on(group, source, group_timer_msec);
+                       zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
+
+                       /* make sure source is created with DELETE flag unset */
+                       zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
+               }
+
+               /* make sure reported source has DELETE flag unset */
+               zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
+
+               if (source->t_source_timer) {
+                       /* if source timer>0 mark SEND flag: Q(G,A-Y) */
+                       IGMP_SOURCE_DO_SEND(source->source_flags);
+                       ++num_sources_tosend;
+               }
+
+       } /* scan received sources (A) */
+
+       /*
+         delete all sources marked with DELETE flag:
+         Delete (X-A)
+         Delete (Y-A)
+       */
+       source_delete_by_flag(group->group_source_list);
+
+       /* send sources marked with SEND flag: Q(G,A-Y) */
+       if (num_sources_tosend > 0) {
+               source_query_send_by_flag(group, num_sources_tosend);
+       }
 }
 
 void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from,
-                       struct in_addr group_addr,
-                       int num_sources, struct in_addr *sources)
+                       struct in_addr group_addr, int num_sources,
+                       struct in_addr *sources)
 {
-  struct interface *ifp = igmp->interface;
-  struct igmp_group *group;
-
-  on_trace(__PRETTY_FUNCTION__,
-          ifp, from, group_addr, num_sources, sources);
-
-  /* non-existant group is created as INCLUDE {empty} */
-  group = igmp_add_group_by_addr(igmp, group_addr);
-  if (!group) {
-    return;
-  }
-
-  if (group->group_filtermode_isexcl) {
-    /* EXCLUDE mode */
-    toex_excl(group, num_sources, sources);
-  }
-  else {
-    /* INCLUDE mode */
-    toex_incl(group, num_sources, sources);
-    zassert(group->group_filtermode_isexcl);
-  }
-  zassert(group->group_filtermode_isexcl);
-
-  /* Group Timer=GMI */
-  igmp_group_reset_gmi(group);
+       struct interface *ifp = igmp->interface;
+       struct igmp_group *group;
+
+       on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources,
+                sources);
+
+       /* non-existant group is created as INCLUDE {empty} */
+       group = igmp_add_group_by_addr(igmp, group_addr);
+       if (!group) {
+               return;
+       }
+
+       if (group->group_filtermode_isexcl) {
+               /* EXCLUDE mode */
+               toex_excl(group, num_sources, sources);
+       } else {
+               /* INCLUDE mode */
+               toex_incl(group, num_sources, sources);
+               zassert(group->group_filtermode_isexcl);
+       }
+       zassert(group->group_filtermode_isexcl);
+
+       /* Group Timer=GMI */
+       igmp_group_reset_gmi(group);
 }
 
 void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from,
-                        struct in_addr group_addr,
-                        int num_sources, struct in_addr *sources)
+                        struct in_addr group_addr, int num_sources,
+                        struct in_addr *sources)
 {
-  on_trace(__PRETTY_FUNCTION__,
-          igmp->interface, from, group_addr, num_sources, sources);
+       on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr,
+                num_sources, sources);
 
-  allow(igmp, from, group_addr, num_sources, sources);
+       allow(igmp, from, group_addr, num_sources, sources);
 }
 
 /*
@@ -1005,67 +1009,64 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from,
 */
 static void group_retransmit_group(struct igmp_group *group)
 {
-  struct igmp_sock     *igmp;
-  struct pim_interface *pim_ifp;
-  long                  lmqc;      /* Last Member Query Count */
-  long                  lmqi_msec; /* Last Member Query Interval */
-  long                  lmqt_msec; /* Last Member Query Time */
-  int                   s_flag;
-  int                   query_buf_size;
-
-  igmp = group->group_igmp_sock;
-  pim_ifp = igmp->interface->info;
-
-  if (pim_ifp->igmp_version == 3) {
-    query_buf_size = PIM_IGMP_BUFSIZE_WRITE;
-  } else {
-    query_buf_size = IGMP_V12_MSG_SIZE;
-  }
-
-  char query_buf[query_buf_size];
-
-  lmqc      = igmp->querier_robustness_variable;
-  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
-  lmqt_msec = lmqc * lmqi_msec;
-
-  /*
-    RFC3376: 6.6.3.1. Building and Sending Group Specific Queries
-    
-    When transmitting a group specific query, if the group timer is
-    larger than LMQT, the "Suppress Router-Side Processing" bit is set
-    in the query message.
-  */
-  s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    zlog_debug("retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d",
-              group_str, igmp->interface->name, s_flag,
-              group->group_specific_query_retransmit_count);
-  }
-
-  /*
-    RFC3376: 4.1.12. IP Destination Addresses for Queries
-
-    Group-Specific and Group-and-Source-Specific Queries are sent with
-    an IP destination address equal to the multicast address of
-    interest.
-  */
-
-  igmp_send_query(pim_ifp->igmp_version,
-                  group,
-                  igmp->fd,
-                  igmp->interface->name,
-                  query_buf,
-                  sizeof(query_buf),
-                  0 /* num_sources_tosend */,
-                  group->group_addr /* dst_addr */,
-                  group->group_addr /* group_addr */,
-                  pim_ifp->igmp_specific_query_max_response_time_dsec,
-                  s_flag,
-                  igmp->querier_robustness_variable,
-                  igmp->querier_query_interval);
+       struct igmp_sock *igmp;
+       struct pim_interface *pim_ifp;
+       long lmqc;      /* Last Member Query Count */
+       long lmqi_msec; /* Last Member Query Interval */
+       long lmqt_msec; /* Last Member Query Time */
+       int s_flag;
+       int query_buf_size;
+
+       igmp = group->group_igmp_sock;
+       pim_ifp = igmp->interface->info;
+
+       if (pim_ifp->igmp_version == 3) {
+               query_buf_size = PIM_IGMP_BUFSIZE_WRITE;
+       } else {
+               query_buf_size = IGMP_V12_MSG_SIZE;
+       }
+
+       char query_buf[query_buf_size];
+
+       lmqc = igmp->querier_robustness_variable;
+       lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
+       lmqt_msec = lmqc * lmqi_msec;
+
+       /*
+         RFC3376: 6.6.3.1. Building and Sending Group Specific Queries
+
+         When transmitting a group specific query, if the group timer is
+         larger than LMQT, the "Suppress Router-Side Processing" bit is set
+         in the query message.
+       */
+       s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d",
+                       group_str, igmp->interface->name, s_flag,
+                       group->group_specific_query_retransmit_count);
+       }
+
+       /*
+         RFC3376: 4.1.12. IP Destination Addresses for Queries
+
+         Group-Specific and Group-and-Source-Specific Queries are sent with
+         an IP destination address equal to the multicast address of
+         interest.
+       */
+
+       igmp_send_query(pim_ifp->igmp_version, group, igmp->fd,
+                       igmp->interface->name, query_buf, sizeof(query_buf),
+                       0 /* num_sources_tosend */,
+                       group->group_addr /* dst_addr */,
+                       group->group_addr /* group_addr */,
+                       pim_ifp->igmp_specific_query_max_response_time_dsec,
+                       s_flag, igmp->querier_robustness_variable,
+                       igmp->querier_query_interval);
 }
 
 /*
@@ -1083,205 +1084,214 @@ static void group_retransmit_group(struct igmp_group *group)
 static int group_retransmit_sources(struct igmp_group *group,
                                    int send_with_sflag_set)
 {
-  struct igmp_sock     *igmp;
-  struct pim_interface *pim_ifp;
-  long                  lmqc;      /* Last Member Query Count */
-  long                  lmqi_msec; /* Last Member Query Interval */
-  long                  lmqt_msec; /* Last Member Query Time */
-  char                  query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */
-  char                  query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */
-  int                   query_buf1_max_sources;
-  int                   query_buf2_max_sources;
-  struct in_addr       *source_addr1;
-  struct in_addr       *source_addr2;
-  int                   num_sources_tosend1;
-  int                   num_sources_tosend2;
-  struct listnode      *src_node;
-  struct igmp_source   *src;
-  int                   num_retransmit_sources_left = 0;
-  
-  source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET);
-  source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET);
-
-  igmp = group->group_igmp_sock;
-  pim_ifp = igmp->interface->info;
-
-  lmqc      = igmp->querier_robustness_variable;
-  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
-  lmqt_msec = lmqc * lmqi_msec;
-
-  /* Scan all group sources */
-  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
-
-    /* Source has retransmission state? */
-    if (src->source_query_retransmit_count < 1)
-      continue;
-
-    if (--src->source_query_retransmit_count > 0) {
-      ++num_retransmit_sources_left;
-    }
-
-    /* Copy source address into appropriate query buffer */
-    if (igmp_source_timer_remain_msec(src) > lmqt_msec) {
-      *source_addr1 = src->source_addr;
-      ++source_addr1;
-    }
-    else {
-      *source_addr2 = src->source_addr;
-      ++source_addr2;
-    }
-
-  }
-  
-  num_sources_tosend1 = source_addr1 - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET);
-  num_sources_tosend2 = source_addr2 - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET);
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    zlog_debug("retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d",
-              group_str, igmp->interface->name,
-              num_sources_tosend1,
-              num_sources_tosend2,
-              send_with_sflag_set,
-              num_retransmit_sources_left);
-  }
-
-  if (num_sources_tosend1 > 0) {
-    /*
-      Send group-and-source-specific query with s_flag set and all
-      sources with timers greater than LMQT.
-    */
-
-    if (send_with_sflag_set) {
-
-      query_buf1_max_sources = (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) >> 2;
-      if (num_sources_tosend1 > query_buf1_max_sources) {
-       char group_str[INET_ADDRSTRLEN];
-       pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-       zlog_warn("%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)",
-                 __PRETTY_FUNCTION__, group_str, igmp->interface->name,
-                 num_sources_tosend1, sizeof(query_buf1), query_buf1_max_sources);
-      }
-      else {
-       /*
-         RFC3376: 4.1.12. IP Destination Addresses for Queries
-      
-         Group-Specific and Group-and-Source-Specific Queries are sent with
-         an IP destination address equal to the multicast address of
-         interest.
-       */
-    
-        igmp_send_query(pim_ifp->igmp_version,
-                        group,
-                        igmp->fd,
-                        igmp->interface->name,
-                        query_buf1,
-                        sizeof(query_buf1),
-                        num_sources_tosend1,
-                        group->group_addr,
-                        group->group_addr,
-                        pim_ifp->igmp_specific_query_max_response_time_dsec,
-                        1 /* s_flag */,
-                        igmp->querier_robustness_variable,
-                        igmp->querier_query_interval);
-      }
-
-    } /* send_with_sflag_set */
-
-  }
-
-  if (num_sources_tosend2 > 0) {
-    /*
-      Send group-and-source-specific query with s_flag clear and all
-      sources with timers lower or equal to LMQT.
-    */
-  
-    query_buf2_max_sources = (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2;
-    if (num_sources_tosend2 > query_buf2_max_sources) {
-      char group_str[INET_ADDRSTRLEN];
-      pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-      zlog_warn("%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)",
-               __PRETTY_FUNCTION__, group_str, igmp->interface->name,
-               num_sources_tosend2, sizeof(query_buf2), query_buf2_max_sources);
-    }
-    else {
-      /*
-       RFC3376: 4.1.12. IP Destination Addresses for Queries
-
-       Group-Specific and Group-and-Source-Specific Queries are sent with
-       an IP destination address equal to the multicast address of
-       interest.
-      */
-
-      igmp_send_query(pim_ifp->igmp_version,
-                      group,
-                      igmp->fd,
-                      igmp->interface->name,
-                      query_buf2,
-                      sizeof(query_buf2),
-                      num_sources_tosend2,
-                      group->group_addr,
-                      group->group_addr,
-                      pim_ifp->igmp_specific_query_max_response_time_dsec,
-                      0 /* s_flag */,
-                      igmp->querier_robustness_variable,
-                      igmp->querier_query_interval);
-    }
-  }
-
-  return num_retransmit_sources_left;
+       struct igmp_sock *igmp;
+       struct pim_interface *pim_ifp;
+       long lmqc;      /* Last Member Query Count */
+       long lmqi_msec; /* Last Member Query Interval */
+       long lmqt_msec; /* Last Member Query Time */
+       char query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */
+       char query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */
+       int query_buf1_max_sources;
+       int query_buf2_max_sources;
+       struct in_addr *source_addr1;
+       struct in_addr *source_addr2;
+       int num_sources_tosend1;
+       int num_sources_tosend2;
+       struct listnode *src_node;
+       struct igmp_source *src;
+       int num_retransmit_sources_left = 0;
+
+       source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET);
+       source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET);
+
+       igmp = group->group_igmp_sock;
+       pim_ifp = igmp->interface->info;
+
+       lmqc = igmp->querier_robustness_variable;
+       lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
+       lmqt_msec = lmqc * lmqi_msec;
+
+       /* Scan all group sources */
+       for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
+
+               /* Source has retransmission state? */
+               if (src->source_query_retransmit_count < 1)
+                       continue;
+
+               if (--src->source_query_retransmit_count > 0) {
+                       ++num_retransmit_sources_left;
+               }
+
+               /* Copy source address into appropriate query buffer */
+               if (igmp_source_timer_remain_msec(src) > lmqt_msec) {
+                       *source_addr1 = src->source_addr;
+                       ++source_addr1;
+               } else {
+                       *source_addr2 = src->source_addr;
+                       ++source_addr2;
+               }
+       }
+
+       num_sources_tosend1 =
+               source_addr1
+               - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET);
+       num_sources_tosend2 =
+               source_addr2
+               - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET);
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d",
+                       group_str, igmp->interface->name, num_sources_tosend1,
+                       num_sources_tosend2, send_with_sflag_set,
+                       num_retransmit_sources_left);
+       }
+
+       if (num_sources_tosend1 > 0) {
+               /*
+                 Send group-and-source-specific query with s_flag set and all
+                 sources with timers greater than LMQT.
+               */
+
+               if (send_with_sflag_set) {
+
+                       query_buf1_max_sources =
+                               (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET)
+                               >> 2;
+                       if (num_sources_tosend1 > query_buf1_max_sources) {
+                               char group_str[INET_ADDRSTRLEN];
+                               pim_inet4_dump("<group?>", group->group_addr,
+                                              group_str, sizeof(group_str));
+                               zlog_warn(
+                                       "%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)",
+                                       __PRETTY_FUNCTION__, group_str,
+                                       igmp->interface->name,
+                                       num_sources_tosend1, sizeof(query_buf1),
+                                       query_buf1_max_sources);
+                       } else {
+                               /*
+                                 RFC3376: 4.1.12. IP Destination Addresses for
+                                 Queries
+
+                                 Group-Specific and Group-and-Source-Specific
+                                 Queries are sent with
+                                 an IP destination address equal to the
+                                 multicast address of
+                                 interest.
+                               */
+
+                               igmp_send_query(
+                                       pim_ifp->igmp_version, group, igmp->fd,
+                                       igmp->interface->name, query_buf1,
+                                       sizeof(query_buf1), num_sources_tosend1,
+                                       group->group_addr, group->group_addr,
+                                       pim_ifp->igmp_specific_query_max_response_time_dsec,
+                                       1 /* s_flag */,
+                                       igmp->querier_robustness_variable,
+                                       igmp->querier_query_interval);
+                       }
+
+               } /* send_with_sflag_set */
+       }
+
+       if (num_sources_tosend2 > 0) {
+               /*
+                 Send group-and-source-specific query with s_flag clear and all
+                 sources with timers lower or equal to LMQT.
+               */
+
+               query_buf2_max_sources =
+                       (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2;
+               if (num_sources_tosend2 > query_buf2_max_sources) {
+                       char group_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<group?>", group->group_addr, group_str,
+                                      sizeof(group_str));
+                       zlog_warn(
+                               "%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)",
+                               __PRETTY_FUNCTION__, group_str,
+                               igmp->interface->name, num_sources_tosend2,
+                               sizeof(query_buf2), query_buf2_max_sources);
+               } else {
+                       /*
+                         RFC3376: 4.1.12. IP Destination Addresses for Queries
+
+                         Group-Specific and Group-and-Source-Specific Queries
+                         are sent with
+                         an IP destination address equal to the multicast
+                         address of
+                         interest.
+                       */
+
+                       igmp_send_query(
+                               pim_ifp->igmp_version, group, igmp->fd,
+                               igmp->interface->name, query_buf2,
+                               sizeof(query_buf2), num_sources_tosend2,
+                               group->group_addr, group->group_addr,
+                               pim_ifp->igmp_specific_query_max_response_time_dsec,
+                               0 /* s_flag */,
+                               igmp->querier_robustness_variable,
+                               igmp->querier_query_interval);
+               }
+       }
+
+       return num_retransmit_sources_left;
 }
 
 static int igmp_group_retransmit(struct thread *t)
 {
-  struct igmp_group *group;
-  int num_retransmit_sources_left;
-  int send_with_sflag_set; /* boolean */
-
-  group = THREAD_ARG(t);
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    zlog_debug("group_retransmit_timer: group %s on %s",
-              group_str, group->group_igmp_sock->interface->name);
-  }
-
-  /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */
-  if (group->group_specific_query_retransmit_count > 0) {
-
-    /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */
-    group_retransmit_group(group);
-    --group->group_specific_query_retransmit_count;
-
-    /*
-      RFC3376: 6.6.3.2
-      If a group specific query is scheduled to be transmitted at the
-      same time as a group and source specific query for the same group,
-      then transmission of the group and source specific message with the
-      "Suppress Router-Side Processing" bit set may be suppressed.
-    */
-    send_with_sflag_set = 0; /* boolean=false */
-  }
-  else {
-    send_with_sflag_set = 1; /* boolean=true */
-  }
-
-  /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */
-  num_retransmit_sources_left = group_retransmit_sources(group,
-                                                        send_with_sflag_set);
-
-  /*
-    Keep group retransmit timer running if there is any retransmit
-    counter pending
-  */
-  if ((num_retransmit_sources_left > 0) ||
-      (group->group_specific_query_retransmit_count > 0)) {
-    group_retransmit_timer_on(group);
-  }
-
-  return 0;
+       struct igmp_group *group;
+       int num_retransmit_sources_left;
+       int send_with_sflag_set; /* boolean */
+
+       group = THREAD_ARG(t);
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug("group_retransmit_timer: group %s on %s", group_str,
+                          group->group_igmp_sock->interface->name);
+       }
+
+       /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */
+       if (group->group_specific_query_retransmit_count > 0) {
+
+               /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */
+               group_retransmit_group(group);
+               --group->group_specific_query_retransmit_count;
+
+               /*
+                 RFC3376: 6.6.3.2
+                 If a group specific query is scheduled to be transmitted at
+                 the
+                 same time as a group and source specific query for the same
+                 group,
+                 then transmission of the group and source specific message
+                 with the
+                 "Suppress Router-Side Processing" bit set may be suppressed.
+               */
+               send_with_sflag_set = 0; /* boolean=false */
+       } else {
+               send_with_sflag_set = 1; /* boolean=true */
+       }
+
+       /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */
+       num_retransmit_sources_left =
+               group_retransmit_sources(group, send_with_sflag_set);
+
+       /*
+         Keep group retransmit timer running if there is any retransmit
+         counter pending
+       */
+       if ((num_retransmit_sources_left > 0)
+           || (group->group_specific_query_retransmit_count > 0)) {
+               group_retransmit_timer_on(group);
+       }
+
+       return 0;
 }
 
 /*
@@ -1291,42 +1301,42 @@ static int igmp_group_retransmit(struct thread *t)
 */
 static void group_retransmit_timer_on(struct igmp_group *group)
 {
-  struct igmp_sock     *igmp;
-  struct pim_interface *pim_ifp;
-  long                  lmqi_msec; /* Last Member Query Interval */
-
-  /* if group retransmit timer is running, do nothing */
-  if (group->t_group_query_retransmit_timer) {
-    return;
-  }
-
-  igmp = group->group_igmp_sock;
-  pim_ifp = igmp->interface->info;
-
-  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    zlog_debug("Scheduling %ld.%03ld sec retransmit timer for group %s on %s",
-              lmqi_msec / 1000,
-              lmqi_msec % 1000,
-              group_str,
-              igmp->interface->name);
-  }
-
-  thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec,
-                        &group->t_group_query_retransmit_timer);
+       struct igmp_sock *igmp;
+       struct pim_interface *pim_ifp;
+       long lmqi_msec; /* Last Member Query Interval */
+
+       /* if group retransmit timer is running, do nothing */
+       if (group->t_group_query_retransmit_timer) {
+               return;
+       }
+
+       igmp = group->group_igmp_sock;
+       pim_ifp = igmp->interface->info;
+
+       lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "Scheduling %ld.%03ld sec retransmit timer for group %s on %s",
+                       lmqi_msec / 1000, lmqi_msec % 1000, group_str,
+                       igmp->interface->name);
+       }
+
+       thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec,
+                             &group->t_group_query_retransmit_timer);
 }
 
 static long igmp_group_timer_remain_msec(struct igmp_group *group)
 {
-  return pim_time_timer_remain_msec(group->t_group_timer);
+       return pim_time_timer_remain_msec(group->t_group_timer);
 }
 
 static long igmp_source_timer_remain_msec(struct igmp_source *source)
 {
-  return pim_time_timer_remain_msec(source->t_source_timer);
+       return pim_time_timer_remain_msec(source->t_source_timer);
 }
 
 /*
@@ -1334,21 +1344,22 @@ static long igmp_source_timer_remain_msec(struct igmp_source *source)
 */
 static void group_query_send(struct igmp_group *group)
 {
-  long              lmqc;    /* Last Member Query Count */
+       long lmqc; /* Last Member Query Count */
 
-  lmqc = group->group_igmp_sock->querier_robustness_variable;
+       lmqc = group->group_igmp_sock->querier_robustness_variable;
 
-  /* lower group timer to lmqt */
-  igmp_group_timer_lower_to_lmqt(group);
+       /* lower group timer to lmqt */
+       igmp_group_timer_lower_to_lmqt(group);
 
-  /* reset retransmission counter */
-  group->group_specific_query_retransmit_count = lmqc;
+       /* reset retransmission counter */
+       group->group_specific_query_retransmit_count = lmqc;
 
-  /* immediately send group specific query (decrease retransmit counter by 1)*/
-  group_retransmit_group(group);
+       /* immediately send group specific query (decrease retransmit counter by
+        * 1)*/
+       group_retransmit_group(group);
 
-  /* make sure group retransmit timer is running */
-  group_retransmit_timer_on(group);
+       /* make sure group retransmit timer is running */
+       group_retransmit_timer_on(group);
 }
 
 /*
@@ -1357,612 +1368,694 @@ static void group_query_send(struct igmp_group *group)
 static void source_query_send_by_flag(struct igmp_group *group,
                                      int num_sources_tosend)
 {
-  struct igmp_sock     *igmp;
-  struct pim_interface *pim_ifp;
-  struct listnode      *src_node;
-  struct igmp_source   *src;
-  long                  lmqc;      /* Last Member Query Count */
-  long                  lmqi_msec; /* Last Member Query Interval */
-  long                  lmqt_msec; /* Last Member Query Time */
-
-  zassert(num_sources_tosend > 0);
-
-  igmp = group->group_igmp_sock;
-  pim_ifp = igmp->interface->info;
-
-  lmqc      = igmp->querier_robustness_variable;
-  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
-  lmqt_msec = lmqc * lmqi_msec;
-
-  /*
-    RFC3376: 6.6.3.2. Building and Sending Group and Source Specific Queries
-
-    (...) for each of the sources in X of group G, with source timer larger
-    than LMQT:
-    o Set number of retransmissions for each source to [Last Member
-    Query Count].
-    o Lower source timer to LMQT.
-  */
-  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
-    if (IGMP_SOURCE_TEST_SEND(src->source_flags)) {
-      /* source "src" in X of group G */
-      if (igmp_source_timer_remain_msec(src) > lmqt_msec) {
-       src->source_query_retransmit_count = lmqc;
-       igmp_source_timer_lower_to_lmqt(src);
-      }
-    }
-  }
-
-  /* send group-and-source specific queries */
-  group_retransmit_sources(group, 1 /* send_with_sflag_set=true */);
-
-  /* make sure group retransmit timer is running */
-  group_retransmit_timer_on(group);
+       struct igmp_sock *igmp;
+       struct pim_interface *pim_ifp;
+       struct listnode *src_node;
+       struct igmp_source *src;
+       long lmqc;      /* Last Member Query Count */
+       long lmqi_msec; /* Last Member Query Interval */
+       long lmqt_msec; /* Last Member Query Time */
+
+       zassert(num_sources_tosend > 0);
+
+       igmp = group->group_igmp_sock;
+       pim_ifp = igmp->interface->info;
+
+       lmqc = igmp->querier_robustness_variable;
+       lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
+       lmqt_msec = lmqc * lmqi_msec;
+
+       /*
+         RFC3376: 6.6.3.2. Building and Sending Group and Source Specific
+         Queries
+
+         (...) for each of the sources in X of group G, with source timer
+         larger
+         than LMQT:
+         o Set number of retransmissions for each source to [Last Member
+         Query Count].
+         o Lower source timer to LMQT.
+       */
+       for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) {
+               if (IGMP_SOURCE_TEST_SEND(src->source_flags)) {
+                       /* source "src" in X of group G */
+                       if (igmp_source_timer_remain_msec(src) > lmqt_msec) {
+                               src->source_query_retransmit_count = lmqc;
+                               igmp_source_timer_lower_to_lmqt(src);
+                       }
+               }
+       }
+
+       /* send group-and-source specific queries */
+       group_retransmit_sources(group, 1 /* send_with_sflag_set=true */);
+
+       /* make sure group retransmit timer is running */
+       group_retransmit_timer_on(group);
 }
 
-static void block_excl(struct igmp_group *group,
-                      int num_sources, struct in_addr *sources)
+static void block_excl(struct igmp_group *group, int num_sources,
+                      struct in_addr *sources)
 {
-  int num_sources_tosend = 0;
-  int i;
-
-  /* 1. clear off SEND flag from all known sources (X,Y) */
-  source_clear_send_flag(group->group_source_list);
-
-  /* 2. scan received sources (A) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-    
-    src_addr = sources + i;
-    
-    /* lookup reported source (A) in known sources (X,Y) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (!source) {
-      /* 3: if not found, create source with Group Timer: (A-X-Y)=Group Timer */
-      long group_timer_msec;
-      source = source_new(group, *src_addr);
-      if (!source) {
-       /* ugh, internal malloc failure, skip source */
-       continue;
-      }
-
-      zassert(!source->t_source_timer); /* timer == 0 */
-      group_timer_msec = igmp_group_timer_remain_msec(group);
-      igmp_source_timer_on(group, source, group_timer_msec);
-      zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
-    }
-
-    if (source->t_source_timer) {
-      /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */
-      IGMP_SOURCE_DO_SEND(source->source_flags);
-      ++num_sources_tosend;
-    }
-  }
-  /* 5. send sources marked with SEND flag: Q(G,A-Y) */
-  if (num_sources_tosend > 0) {
-    source_query_send_by_flag(group, num_sources_tosend);
-  }
+       int num_sources_tosend = 0;
+       int i;
+
+       /* 1. clear off SEND flag from all known sources (X,Y) */
+       source_clear_send_flag(group->group_source_list);
+
+       /* 2. scan received sources (A) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* lookup reported source (A) in known sources (X,Y) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (!source) {
+                       /* 3: if not found, create source with Group Timer:
+                        * (A-X-Y)=Group Timer */
+                       long group_timer_msec;
+                       source = source_new(group, *src_addr);
+                       if (!source) {
+                               /* ugh, internal malloc failure, skip source */
+                               continue;
+                       }
+
+                       zassert(!source->t_source_timer); /* timer == 0 */
+                       group_timer_msec = igmp_group_timer_remain_msec(group);
+                       igmp_source_timer_on(group, source, group_timer_msec);
+                       zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
+               }
+
+               if (source->t_source_timer) {
+                       /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */
+                       IGMP_SOURCE_DO_SEND(source->source_flags);
+                       ++num_sources_tosend;
+               }
+       }
+
+       /* 5. send sources marked with SEND flag: Q(G,A-Y) */
+       if (num_sources_tosend > 0) {
+               source_query_send_by_flag(group, num_sources_tosend);
+       }
 }
 
-static void block_incl(struct igmp_group *group,
-                      int num_sources, struct in_addr *sources)
+static void block_incl(struct igmp_group *group, int num_sources,
+                      struct in_addr *sources)
 {
-  int num_sources_tosend = 0;
-  int i;
-
-  /* 1. clear off SEND flag from all known sources (B) */
-  source_clear_send_flag(group->group_source_list);
-
-  /* 2. scan received sources (A) */
-  for (i = 0; i < num_sources; ++i) {
-    struct igmp_source *source;
-    struct in_addr     *src_addr;
-    
-    src_addr = sources + i;
-    
-    /* lookup reported source (A) in known sources (B) */
-    source = igmp_find_source_by_addr(group, *src_addr);
-    if (source) {
-      /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */
-      IGMP_SOURCE_DO_SEND(source->source_flags);
-      ++num_sources_tosend;
-    }
-  } 
-  /* 4. send sources marked with SEND flag: Q(G,A*B) */
-  if (num_sources_tosend > 0) {
-    source_query_send_by_flag(group, num_sources_tosend);
-  }
+       int num_sources_tosend = 0;
+       int i;
+
+       /* 1. clear off SEND flag from all known sources (B) */
+       source_clear_send_flag(group->group_source_list);
+
+       /* 2. scan received sources (A) */
+       for (i = 0; i < num_sources; ++i) {
+               struct igmp_source *source;
+               struct in_addr *src_addr;
+
+               src_addr = sources + i;
+
+               /* lookup reported source (A) in known sources (B) */
+               source = igmp_find_source_by_addr(group, *src_addr);
+               if (source) {
+                       /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */
+                       IGMP_SOURCE_DO_SEND(source->source_flags);
+                       ++num_sources_tosend;
+               }
+       }
+
+       /* 4. send sources marked with SEND flag: Q(G,A*B) */
+       if (num_sources_tosend > 0) {
+               source_query_send_by_flag(group, num_sources_tosend);
+       }
 }
 
 void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from,
-                        struct in_addr group_addr,
-                        int num_sources, struct in_addr *sources)
+                        struct in_addr group_addr, int num_sources,
+                        struct in_addr *sources)
 {
-  struct interface *ifp = igmp->interface;
-  struct igmp_group *group;
-
-  on_trace(__PRETTY_FUNCTION__,
-          ifp, from, group_addr, num_sources, sources);
-
-  /* non-existant group is created as INCLUDE {empty} */
-  group = igmp_add_group_by_addr(igmp, group_addr);
-  if (!group) {
-    return;
-  }
-
-  if (group->group_filtermode_isexcl) {
-    /* EXCLUDE mode */
-    block_excl(group, num_sources, sources);
-  }
-  else {
-    /* INCLUDE mode */
-    block_incl(group, num_sources, sources);
-  }
+       struct interface *ifp = igmp->interface;
+       struct igmp_group *group;
+
+       on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources,
+                sources);
+
+       /* non-existant group is created as INCLUDE {empty} */
+       group = igmp_add_group_by_addr(igmp, group_addr);
+       if (!group) {
+               return;
+       }
+
+       if (group->group_filtermode_isexcl) {
+               /* EXCLUDE mode */
+               block_excl(group, num_sources, sources);
+       } else {
+               /* INCLUDE mode */
+               block_incl(group, num_sources, sources);
+       }
 }
 
 void igmp_group_timer_lower_to_lmqt(struct igmp_group *group)
 {
-  struct igmp_sock     *igmp;
-  struct interface     *ifp;
-  struct pim_interface *pim_ifp;
-  char                 *ifname;
-  int   lmqi_dsec; /* Last Member Query Interval */
-  int   lmqc;      /* Last Member Query Count */
-  int   lmqt_msec; /* Last Member Query Time */
-
-  /*
-    RFC 3376: 6.2.2. Definition of Group Timers
-    
-    The group timer is only used when a group is in EXCLUDE mode and
-    it represents the time for the *filter-mode* of the group to
-    expire and switch to INCLUDE mode.
-  */
-  if (!group->group_filtermode_isexcl) {
-    return;
-  }
-
-  igmp    = group->group_igmp_sock;
-  ifp     = igmp->interface;
-  pim_ifp = ifp->info;
-  ifname  = ifp->name;
-
-  lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec;
-  lmqc      = igmp->querier_robustness_variable;
-  lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    zlog_debug("%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec",
-              __PRETTY_FUNCTION__,
-              group_str, ifname,
-              lmqc, lmqi_dsec, lmqt_msec);
-  }
-
-  zassert(group->group_filtermode_isexcl);
-
-  igmp_group_timer_on(group, lmqt_msec, ifname);
+       struct igmp_sock *igmp;
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       char *ifname;
+       int lmqi_dsec; /* Last Member Query Interval */
+       int lmqc;      /* Last Member Query Count */
+       int lmqt_msec; /* Last Member Query Time */
+
+       /*
+         RFC 3376: 6.2.2. Definition of Group Timers
+
+         The group timer is only used when a group is in EXCLUDE mode and
+         it represents the time for the *filter-mode* of the group to
+         expire and switch to INCLUDE mode.
+       */
+       if (!group->group_filtermode_isexcl) {
+               return;
+       }
+
+       igmp = group->group_igmp_sock;
+       ifp = igmp->interface;
+       pim_ifp = ifp->info;
+       ifname = ifp->name;
+
+       lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec;
+       lmqc = igmp->querier_robustness_variable;
+       lmqt_msec = PIM_IGMP_LMQT_MSEC(
+               lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec",
+                       __PRETTY_FUNCTION__, group_str, ifname, lmqc, lmqi_dsec,
+                       lmqt_msec);
+       }
+
+       zassert(group->group_filtermode_isexcl);
+
+       igmp_group_timer_on(group, lmqt_msec, ifname);
 }
 
 void igmp_source_timer_lower_to_lmqt(struct igmp_source *source)
 {
-  struct igmp_group    *group;
-  struct igmp_sock     *igmp;
-  struct interface     *ifp;
-  struct pim_interface *pim_ifp;
-  char                 *ifname;
-  int   lmqi_dsec; /* Last Member Query Interval */
-  int   lmqc;      /* Last Member Query Count */
-  int   lmqt_msec; /* Last Member Query Time */
-
-  group   = source->source_group;
-  igmp    = group->group_igmp_sock;
-  ifp     = igmp->interface;
-  pim_ifp = ifp->info;
-  ifname  = ifp->name;
-
-  lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec;
-  lmqc      = igmp->querier_robustness_variable;
-  lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
-
-  if (PIM_DEBUG_IGMP_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
-    zlog_debug("%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec",
-              __PRETTY_FUNCTION__,
-              group_str, source_str, ifname,
-              lmqc, lmqi_dsec, lmqt_msec);
-  }
-
-  igmp_source_timer_on(group, source, lmqt_msec);
+       struct igmp_group *group;
+       struct igmp_sock *igmp;
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       char *ifname;
+       int lmqi_dsec; /* Last Member Query Interval */
+       int lmqc;      /* Last Member Query Count */
+       int lmqt_msec; /* Last Member Query Time */
+
+       group = source->source_group;
+       igmp = group->group_igmp_sock;
+       ifp = igmp->interface;
+       pim_ifp = ifp->info;
+       ifname = ifp->name;
+
+       lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec;
+       lmqc = igmp->querier_robustness_variable;
+       lmqt_msec = PIM_IGMP_LMQT_MSEC(
+               lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
+
+       if (PIM_DEBUG_IGMP_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char source_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<group?>", group->group_addr, group_str,
+                              sizeof(group_str));
+               pim_inet4_dump("<source?>", source->source_addr, source_str,
+                              sizeof(source_str));
+               zlog_debug(
+                       "%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec",
+                       __PRETTY_FUNCTION__, group_str, source_str, ifname,
+                       lmqc, lmqi_dsec, lmqt_msec);
+       }
+
+       igmp_source_timer_on(group, source, lmqt_msec);
 }
 
-void
-igmp_v3_send_query (struct igmp_group *group,
-                    int fd,
-                    const char *ifname,
-                    char *query_buf,
-                    int query_buf_size,
-                    int num_sources,
-                    struct in_addr dst_addr,
-                    struct in_addr group_addr,
-                    int query_max_response_time_dsec,
-                    uint8_t s_flag,
-                    uint8_t querier_robustness_variable,
-                    uint16_t querier_query_interval)
+void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname,
+                       char *query_buf, int query_buf_size, int num_sources,
+                       struct in_addr dst_addr, struct in_addr group_addr,
+                       int query_max_response_time_dsec, uint8_t s_flag,
+                       uint8_t querier_robustness_variable,
+                       uint16_t querier_query_interval)
 {
-  ssize_t             msg_size;
-  uint8_t             max_resp_code;
-  uint8_t             qqic;
-  ssize_t             sent;
-  struct sockaddr_in  to;
-  socklen_t           tolen;
-  uint16_t            checksum;
-
-  zassert(num_sources >= 0);
-
-  msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2);
-  if (msg_size > query_buf_size) {
-    zlog_err("%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d",
-            __FILE__, __PRETTY_FUNCTION__,
-            msg_size, query_buf_size);
-    return;
-  }
-
-  s_flag = PIM_FORCE_BOOLEAN(s_flag);
-  zassert((s_flag == 0) || (s_flag == 1));
-
-  max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec);
-  qqic          = igmp_msg_encode16to8(querier_query_interval);
-
-  /*
-    RFC 3376: 4.1.6. QRV (Querier's Robustness Variable)
-
-    If non-zero, the QRV field contains the [Robustness Variable]
-    value used by the querier, i.e., the sender of the Query.  If the
-    querier's [Robustness Variable] exceeds 7, the maximum value of
-    the QRV field, the QRV is set to zero.
-  */
-  if (querier_robustness_variable > 7) {
-    querier_robustness_variable = 0;
-  }
-
-  query_buf[0]                                         = PIM_IGMP_MEMBERSHIP_QUERY;
-  query_buf[1]                                         = max_resp_code;
-  *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET)   = 0; /* for computing checksum */
-  memcpy(query_buf+4, &group_addr, sizeof(struct in_addr));
-
-  query_buf[8]                                         = (s_flag << 3) | querier_robustness_variable;
-  query_buf[9]                                         = qqic;
-  *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = htons(num_sources);
-
-  checksum = in_cksum(query_buf, msg_size);
-  *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum;
-
-  if (PIM_DEBUG_IGMP_PACKETS) {
-    char dst_str[INET_ADDRSTRLEN];
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
-    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str));
-    zlog_debug("Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x",
-              dst_str, ifname, group_str,
-               num_sources, msg_size, s_flag, querier_robustness_variable,
-               querier_query_interval, qqic);
-  }
-
-  memset(&to, 0, sizeof(to));
-  to.sin_family = AF_INET;
-  to.sin_addr = dst_addr;
-  tolen = sizeof(to);
-
-  sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT,
-                (struct sockaddr *)&to, tolen);
-  if (sent != (ssize_t) msg_size) {
-    char dst_str[INET_ADDRSTRLEN];
-    char group_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
-    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str));
-    if (sent < 0) {
-      zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s",
-               dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno));
-    }
-    else {
-      zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd",
-               dst_str, ifname, group_str, msg_size, sent);
-    }
-    return;
-  }
-
-  /*
-    s_flag sanity test: s_flag must be set for general queries
-
-    RFC 3376: 6.6.1. Timer Updates
-
-    When a router sends or receives a query with a clear Suppress
-    Router-Side Processing flag, it must update its timers to reflect
-    the correct timeout values for the group or sources being queried.
-
-    General queries don't trigger timer update.
-  */
-  if (!s_flag) {
-    /* general query? */
-    if (PIM_INADDR_IS_ANY(group_addr)) {
-      char dst_str[INET_ADDRSTRLEN];
-      char group_str[INET_ADDRSTRLEN];
-      pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
-      pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str));
-      zlog_warn("%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!",
-               __PRETTY_FUNCTION__,
-               dst_str, ifname, group_str, num_sources);
-    }
-  }
+       ssize_t msg_size;
+       uint8_t max_resp_code;
+       uint8_t qqic;
+       ssize_t sent;
+       struct sockaddr_in to;
+       socklen_t tolen;
+       uint16_t checksum;
+
+       zassert(num_sources >= 0);
+
+       msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2);
+       if (msg_size > query_buf_size) {
+               zlog_err(
+                       "%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d",
+                       __FILE__, __PRETTY_FUNCTION__, msg_size,
+                       query_buf_size);
+               return;
+       }
+
+       s_flag = PIM_FORCE_BOOLEAN(s_flag);
+       zassert((s_flag == 0) || (s_flag == 1));
+
+       max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec);
+       qqic = igmp_msg_encode16to8(querier_query_interval);
+
+       /*
+         RFC 3376: 4.1.6. QRV (Querier's Robustness Variable)
+
+         If non-zero, the QRV field contains the [Robustness Variable]
+         value used by the querier, i.e., the sender of the Query.  If the
+         querier's [Robustness Variable] exceeds 7, the maximum value of
+         the QRV field, the QRV is set to zero.
+       */
+       if (querier_robustness_variable > 7) {
+               querier_robustness_variable = 0;
+       }
+
+       query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY;
+       query_buf[1] = max_resp_code;
+       *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) =
+               0; /* for computing checksum */
+       memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr));
+
+       query_buf[8] = (s_flag << 3) | querier_robustness_variable;
+       query_buf[9] = qqic;
+       *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) =
+               htons(num_sources);
+
+       checksum = in_cksum(query_buf, msg_size);
+       *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum;
+
+       if (PIM_DEBUG_IGMP_PACKETS) {
+               char dst_str[INET_ADDRSTRLEN];
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
+               pim_inet4_dump("<group?>", group_addr, group_str,
+                              sizeof(group_str));
+               zlog_debug(
+                       "Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x",
+                       dst_str, ifname, group_str, num_sources, msg_size,
+                       s_flag, querier_robustness_variable,
+                       querier_query_interval, qqic);
+       }
+
+       memset(&to, 0, sizeof(to));
+       to.sin_family = AF_INET;
+       to.sin_addr = dst_addr;
+       tolen = sizeof(to);
+
+       sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT,
+                     (struct sockaddr *)&to, tolen);
+       if (sent != (ssize_t)msg_size) {
+               char dst_str[INET_ADDRSTRLEN];
+               char group_str[INET_ADDRSTRLEN];
+               pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
+               pim_inet4_dump("<group?>", group_addr, group_str,
+                              sizeof(group_str));
+               if (sent < 0) {
+                       zlog_warn(
+                               "Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s",
+                               dst_str, ifname, group_str, msg_size, errno,
+                               safe_strerror(errno));
+               } else {
+                       zlog_warn(
+                               "Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd",
+                               dst_str, ifname, group_str, msg_size, sent);
+               }
+               return;
+       }
+
+       /*
+         s_flag sanity test: s_flag must be set for general queries
+
+         RFC 3376: 6.6.1. Timer Updates
+
+         When a router sends or receives a query with a clear Suppress
+         Router-Side Processing flag, it must update its timers to reflect
+         the correct timeout values for the group or sources being queried.
+
+         General queries don't trigger timer update.
+       */
+       if (!s_flag) {
+               /* general query? */
+               if (PIM_INADDR_IS_ANY(group_addr)) {
+                       char dst_str[INET_ADDRSTRLEN];
+                       char group_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<dst?>", dst_addr, dst_str,
+                                      sizeof(dst_str));
+                       pim_inet4_dump("<group?>", group_addr, group_str,
+                                      sizeof(group_str));
+                       zlog_warn(
+                               "%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!",
+                               __PRETTY_FUNCTION__, dst_str, ifname, group_str,
+                               num_sources);
+               }
+       }
 }
 
-void
-igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg)
+void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str,
+                       char *igmp_msg)
 {
-  struct interface     *ifp;
-  struct pim_interface *pim_ifp;
-  struct in_addr        group_addr;
-  uint8_t resv_s_qrv = 0;
-  uint8_t s_flag = 0;
-  uint8_t qrv = 0;
-  int     i;
-
-  memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
-  ifp = igmp->interface;
-  pim_ifp = ifp->info;
-
-  /*
-   * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable)
-   *
-   * Routers adopt the QRV value from the most recently received Query
-   * as their own [Robustness Variable] value, unless that most
-   * recently received QRV was zero, in which case the receivers use
-   * the default [Robustness Variable] value specified in section 8.1
-   * or a statically configured value.
-   */
-  resv_s_qrv = igmp_msg[8];
-  qrv = 7 & resv_s_qrv;
-  igmp->querier_robustness_variable = qrv ? qrv : pim_ifp->igmp_default_robustness_variable;
-
-  /*
-   * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
-   *
-   * Multicast routers that are not the current querier adopt the QQI
-   * value from the most recently received Query as their own [Query
-   * Interval] value, unless that most recently received QQI was zero,
-   * in which case the receiving routers use the default.
-   */
-  if (igmp->t_other_querier_timer) {
-    /* other querier present */
-    uint8_t  qqic;
-    uint16_t qqi;
-    qqic = igmp_msg[9];
-    qqi = igmp_msg_decode8to16(qqic);
-    igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval;
-
-    if (PIM_DEBUG_IGMP_TRACE) {
-      char ifaddr_str[INET_ADDRSTRLEN];
-      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
-      zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)",
-                 ifaddr_str,
-                 qqi ? "recv-non-default" : "default",
-                 igmp->querier_query_interval,
-                 qqic,
-                 from_str);
-    }
-  }
-
-  /*
-   * RFC 3376: 6.6.1. Timer Updates
-   *
-   * When a router sends or receives a query with a clear Suppress
-   * Router-Side Processing flag, it must update its timers to reflect
-   * the correct timeout values for the group or sources being queried.
-   *
-   * General queries don't trigger timer update.
-   */
-  s_flag = (1 << 3) & resv_s_qrv;
-
-  if (!s_flag) {
-    /* s_flag is clear */
-
-    if (PIM_INADDR_IS_ANY(group_addr)) {
-      /* this is a general query */
-      /* log that general query should have the s_flag set */
-      zlog_warn("General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear",
-                from_str, ifp->name);
-    } else {
-      struct igmp_group *group;
-
-      /* this is a non-general query: perform timer updates */
-
-      group = find_group_by_addr(igmp, group_addr);
-      if (group) {
-        int recv_num_sources = ntohs(*(uint16_t *)(igmp_msg + IGMP_V3_NUMSOURCES_OFFSET));
-
-        /*
-         * RFC 3376: 6.6.1. Timer Updates
-         * Query Q(G,A): Source Timer for sources in A are lowered to LMQT
-         * Query Q(G): Group Timer is lowered to LMQT
-         */
-        if (recv_num_sources < 1) {
-          /* Query Q(G): Group Timer is lowered to LMQT */
-
-          igmp_group_timer_lower_to_lmqt(group);
-        } else {
-          /* Query Q(G,A): Source Timer for sources in A are lowered to LMQT */
-
-          /* Scan sources in query and lower their timers to LMQT */
-          struct in_addr *sources = (struct in_addr *)(igmp_msg + IGMP_V3_SOURCES_OFFSET);
-          for (i = 0; i < recv_num_sources; ++i) {
-            struct in_addr src_addr;
-            struct igmp_source *src;
-            memcpy(&src_addr, sources + i, sizeof(struct in_addr));
-            src = igmp_find_source_by_addr(group, src_addr);
-            if (src) {
-              igmp_source_timer_lower_to_lmqt(src);
-            }
-          }
-        }
-      } else {
-        char group_str[INET_ADDRSTRLEN];
-        pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str));
-        zlog_warn("IGMP query v3 from %s on %s: could not find group %s for timer update",
-                  from_str, ifp->name, group_str);
-      }
-    }
-  } /* s_flag is clear: timer updates */
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+       struct in_addr group_addr;
+       uint8_t resv_s_qrv = 0;
+       uint8_t s_flag = 0;
+       uint8_t qrv = 0;
+       int i;
+
+       memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
+       ifp = igmp->interface;
+       pim_ifp = ifp->info;
+
+       /*
+        * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable)
+        *
+        * Routers adopt the QRV value from the most recently received Query
+        * as their own [Robustness Variable] value, unless that most
+        * recently received QRV was zero, in which case the receivers use
+        * the default [Robustness Variable] value specified in section 8.1
+        * or a statically configured value.
+        */
+       resv_s_qrv = igmp_msg[8];
+       qrv = 7 & resv_s_qrv;
+       igmp->querier_robustness_variable =
+               qrv ? qrv : pim_ifp->igmp_default_robustness_variable;
+
+       /*
+        * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
+        *
+        * Multicast routers that are not the current querier adopt the QQI
+        * value from the most recently received Query as their own [Query
+        * Interval] value, unless that most recently received QQI was zero,
+        * in which case the receiving routers use the default.
+        */
+       if (igmp->t_other_querier_timer) {
+               /* other querier present */
+               uint8_t qqic;
+               uint16_t qqi;
+               qqic = igmp_msg[9];
+               qqi = igmp_msg_decode8to16(qqic);
+               igmp->querier_query_interval =
+                       qqi ? qqi : pim_ifp->igmp_default_query_interval;
+
+               if (PIM_DEBUG_IGMP_TRACE) {
+                       char ifaddr_str[INET_ADDRSTRLEN];
+                       pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
+                                      sizeof(ifaddr_str));
+                       zlog_debug(
+                               "Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)",
+                               ifaddr_str,
+                               qqi ? "recv-non-default" : "default",
+                               igmp->querier_query_interval, qqic, from_str);
+               }
+       }
+
+       /*
+        * RFC 3376: 6.6.1. Timer Updates
+        *
+        * When a router sends or receives a query with a clear Suppress
+        * Router-Side Processing flag, it must update its timers to reflect
+        * the correct timeout values for the group or sources being queried.
+        *
+        * General queries don't trigger timer update.
+        */
+       s_flag = (1 << 3) & resv_s_qrv;
+
+       if (!s_flag) {
+               /* s_flag is clear */
+
+               if (PIM_INADDR_IS_ANY(group_addr)) {
+                       /* this is a general query */
+                       /* log that general query should have the s_flag set */
+                       zlog_warn(
+                               "General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear",
+                               from_str, ifp->name);
+               } else {
+                       struct igmp_group *group;
+
+                       /* this is a non-general query: perform timer updates */
+
+                       group = find_group_by_addr(igmp, group_addr);
+                       if (group) {
+                               int recv_num_sources = ntohs(*(
+                                       uint16_t
+                                               *)(igmp_msg
+                                                  + IGMP_V3_NUMSOURCES_OFFSET));
+
+                               /*
+                                * RFC 3376: 6.6.1. Timer Updates
+                                * Query Q(G,A): Source Timer for sources in A
+                                * are lowered to LMQT
+                                * Query Q(G): Group Timer is lowered to LMQT
+                                */
+                               if (recv_num_sources < 1) {
+                                       /* Query Q(G): Group Timer is lowered to
+                                        * LMQT */
+
+                                       igmp_group_timer_lower_to_lmqt(group);
+                               } else {
+                                       /* Query Q(G,A): Source Timer for
+                                        * sources in A are lowered to LMQT */
+
+                                       /* Scan sources in query and lower their
+                                        * timers to LMQT */
+                                       struct in_addr *sources =
+                                               (struct in_addr
+                                                        *)(igmp_msg
+                                                           + IGMP_V3_SOURCES_OFFSET);
+                                       for (i = 0; i < recv_num_sources; ++i) {
+                                               struct in_addr src_addr;
+                                               struct igmp_source *src;
+                                               memcpy(&src_addr, sources + i,
+                                                      sizeof(struct in_addr));
+                                               src = igmp_find_source_by_addr(
+                                                       group, src_addr);
+                                               if (src) {
+                                                       igmp_source_timer_lower_to_lmqt(
+                                                               src);
+                                               }
+                                       }
+                               }
+                       } else {
+                               char group_str[INET_ADDRSTRLEN];
+                               pim_inet4_dump("<group?>", group_addr,
+                                              group_str, sizeof(group_str));
+                               zlog_warn(
+                                       "IGMP query v3 from %s on %s: could not find group %s for timer update",
+                                       from_str, ifp->name, group_str);
+                       }
+               }
+       } /* s_flag is clear: timer updates */
 }
 
-int
-igmp_v3_recv_report (struct igmp_sock *igmp,
-                     struct in_addr from, const char *from_str,
-                     char *igmp_msg, int igmp_msg_len)
+int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from,
+                       const char *from_str, char *igmp_msg, int igmp_msg_len)
 {
-  uint16_t          recv_checksum;
-  uint16_t          checksum;
-  int               num_groups;
-  uint8_t          *group_record;
-  uint8_t          *report_pastend = (uint8_t *) igmp_msg + igmp_msg_len;
-  struct interface *ifp = igmp->interface;
-  int               i;
-  int               local_ncb = 0;
-
-  if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) {
-    zlog_warn("Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d",
-              from_str, ifp->name, igmp_msg_len, IGMP_V3_MSG_MIN_SIZE);
-    return -1;
-  }
-
-  recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET);
-
-  /* for computing checksum */
-  *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0;
-
-  checksum = in_cksum(igmp_msg, igmp_msg_len);
-  if (checksum != recv_checksum) {
-    zlog_warn("Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x",
-              from_str, ifp->name, recv_checksum, checksum);
-    return -1;
-  }
-
-  num_groups = ntohs(*(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET));
-  if (num_groups < 1) {
-    zlog_warn("Recv IGMP report v3 from %s on %s: missing group records",
-              from_str, ifp->name);
-    return -1;
-  }
-
-  if (PIM_DEBUG_IGMP_PACKETS) {
-    zlog_debug("Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d",
-               from_str, ifp->name, igmp_msg_len, checksum, num_groups);
-  }
-
-  group_record = (uint8_t *) igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET;
-
-  /* Scan groups */
-  for (i = 0; i < num_groups; ++i) {
-    struct in_addr  rec_group;
-    uint8_t        *sources;
-    uint8_t        *src;
-    int             rec_type;
-    int             rec_auxdatalen;
-    int             rec_num_sources;
-    int             j;
-    struct prefix   lncb;
-    struct prefix   g;
-
-    if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) {
-      zlog_warn("Recv IGMP report v3 from %s on %s: group record beyond report end",
-                from_str, ifp->name);
-      return -1;
-    }
-
-    rec_type        = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET];
-    rec_auxdatalen  = group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET];
-    rec_num_sources = ntohs(* (uint16_t *) (group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET));
-
-    memcpy(&rec_group, group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, sizeof(struct in_addr));
-
-    if (PIM_DEBUG_IGMP_PACKETS) {
-      zlog_debug("Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s",
-                 from_str, ifp->name, i, rec_type, rec_auxdatalen, rec_num_sources, inet_ntoa(rec_group));
-    }
-
-    /* Scan sources */
-
-    sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET;
-
-    for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) {
-
-      if ((src + 4) > report_pastend) {
-        zlog_warn("Recv IGMP report v3 from %s on %s: group source beyond report end",
-                  from_str, ifp->name);
-        return -1;
-      }
-
-      if (PIM_DEBUG_IGMP_PACKETS) {
-        char src_str[200];
-
-        if (!inet_ntop(AF_INET, src, src_str , sizeof(src_str)))
-          sprintf(src_str, "<source?>");
-
-        zlog_debug("Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s",
-                   from_str, ifp->name, i, inet_ntoa(rec_group), src_str);
-      }
-    } /* for (sources) */
-
-
-    lncb.family = AF_INET;
-    lncb.u.prefix4.s_addr = 0x000000E0;
-    lncb.prefixlen = 24;
-
-    g.family = AF_INET;
-    g.u.prefix4 = rec_group;
-    g.prefixlen = 32;
-    /*
-     * If we receive a igmp report with the group in 224.0.0.0/24
-     * then we should ignore it
-     */
-    if (prefix_match(&lncb, &g))
-      local_ncb = 1;
-
-    if (!local_ncb)
-      switch (rec_type) {
-      case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE:
-        igmpv3_report_isin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources);
-        break;
-      case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE:
-        igmpv3_report_isex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources, 0);
-        break;
-      case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE:
-        igmpv3_report_toin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources);
-        break;
-      case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE:
-        igmpv3_report_toex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources);
-        break;
-      case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES:
-        igmpv3_report_allow(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources);
-        break;
-      case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES:
-        igmpv3_report_block(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources);
-        break;
-      default:
-        zlog_warn("Recv IGMP report v3 from %s on %s: unknown record type: type=%d",
-                  from_str, ifp->name, rec_type);
-      }
-
-    group_record += 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2);
-    local_ncb = 0;
-
-  } /* for (group records) */
-
-  return 0;
+       uint16_t recv_checksum;
+       uint16_t checksum;
+       int num_groups;
+       uint8_t *group_record;
+       uint8_t *report_pastend = (uint8_t *)igmp_msg + igmp_msg_len;
+       struct interface *ifp = igmp->interface;
+       int i;
+       int local_ncb = 0;
+       struct pim_interface *pim_ifp;
+
+       if (igmp->mtrace_only)
+               return 0;
+
+       pim_ifp = igmp->interface->info;
+
+       if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) {
+               zlog_warn(
+                       "Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d",
+                       from_str, ifp->name, igmp_msg_len,
+                       IGMP_V3_MSG_MIN_SIZE);
+               return -1;
+       }
+
+       recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET);
+
+       /* for computing checksum */
+       *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0;
+
+       checksum = in_cksum(igmp_msg, igmp_msg_len);
+       if (checksum != recv_checksum) {
+               zlog_warn(
+                       "Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x",
+                       from_str, ifp->name, recv_checksum, checksum);
+               return -1;
+       }
+
+       /* Collecting IGMP Rx stats */
+       igmp->rx_stats.report_v3++;
+
+       num_groups = ntohs(
+               *(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET));
+       if (num_groups < 1) {
+               zlog_warn(
+                       "Recv IGMP report v3 from %s on %s: missing group records",
+                       from_str, ifp->name);
+               return -1;
+       }
+
+       if (PIM_DEBUG_IGMP_PACKETS) {
+               zlog_debug(
+                       "Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d",
+                       from_str, ifp->name, igmp_msg_len, checksum,
+                       num_groups);
+       }
+
+       group_record = (uint8_t *)igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET;
+
+       /* Scan groups */
+       for (i = 0; i < num_groups; ++i) {
+               struct in_addr rec_group;
+               uint8_t *sources;
+               uint8_t *src;
+               int rec_type;
+               int rec_auxdatalen;
+               int rec_num_sources;
+               int j;
+               struct prefix lncb;
+               struct prefix g;
+               bool filtered = false;
+
+               if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE)
+                   > report_pastend) {
+                       zlog_warn(
+                               "Recv IGMP report v3 from %s on %s: group record beyond report end",
+                               from_str, ifp->name);
+                       return -1;
+               }
+
+               rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET];
+               rec_auxdatalen =
+                       group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET];
+               rec_num_sources = ntohs(*(
+                       uint16_t *)(group_record
+                                   + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET));
+
+               memcpy(&rec_group,
+                      group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET,
+                      sizeof(struct in_addr));
+
+               if (PIM_DEBUG_IGMP_PACKETS) {
+                       zlog_debug(
+                               "Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s",
+                               from_str, ifp->name, i, rec_type,
+                               rec_auxdatalen, rec_num_sources,
+                               inet_ntoa(rec_group));
+               }
+
+               /* Scan sources */
+
+               sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET;
+
+               for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) {
+
+                       if ((src + 4) > report_pastend) {
+                               zlog_warn(
+                                       "Recv IGMP report v3 from %s on %s: group source beyond report end",
+                                       from_str, ifp->name);
+                               return -1;
+                       }
+
+                       if (PIM_DEBUG_IGMP_PACKETS) {
+                               char src_str[200];
+
+                               if (!inet_ntop(AF_INET, src, src_str,
+                                              sizeof(src_str)))
+                                       sprintf(src_str, "<source?>");
+
+                               zlog_debug(
+                                       "Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s",
+                                       from_str, ifp->name, i,
+                                       inet_ntoa(rec_group), src_str);
+                       }
+               } /* for (sources) */
+
+
+               lncb.family = AF_INET;
+               lncb.u.prefix4.s_addr = 0x000000E0;
+               lncb.prefixlen = 24;
+
+               g.family = AF_INET;
+               g.u.prefix4 = rec_group;
+               g.prefixlen = 32;
+
+               /* determine filtering status for group */
+               filtered = pim_is_group_filtered(ifp->info, &rec_group);
+
+               if (PIM_DEBUG_IGMP_PACKETS && filtered)
+                       zlog_debug(
+                               "Filtering IGMPv3 group record %s from %s on %s per prefix-list %s",
+                               inet_ntoa(rec_group), from_str, ifp->name,
+                               pim_ifp->boundary_oil_plist);
+
+               /*
+                * If we receive a igmp report with the group in 224.0.0.0/24
+                * then we should ignore it
+                */
+               if (prefix_match(&lncb, &g))
+                       local_ncb = 1;
+
+               if (!local_ncb && !filtered)
+                       switch (rec_type) {
+                       case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE:
+                               igmpv3_report_isin(igmp, from, rec_group,
+                                                  rec_num_sources,
+                                                  (struct in_addr *)sources);
+                               break;
+                       case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE:
+                               igmpv3_report_isex(
+                                       igmp, from, rec_group, rec_num_sources,
+                                       (struct in_addr *)sources, 0);
+                               break;
+                       case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE:
+                               igmpv3_report_toin(igmp, from, rec_group,
+                                                  rec_num_sources,
+                                                  (struct in_addr *)sources);
+                               break;
+                       case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE:
+                               igmpv3_report_toex(igmp, from, rec_group,
+                                                  rec_num_sources,
+                                                  (struct in_addr *)sources);
+                               break;
+                       case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES:
+                               igmpv3_report_allow(igmp, from, rec_group,
+                                                   rec_num_sources,
+                                                   (struct in_addr *)sources);
+                               break;
+                       case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES:
+                               igmpv3_report_block(igmp, from, rec_group,
+                                                   rec_num_sources,
+                                                   (struct in_addr *)sources);
+                               break;
+                       default:
+                               zlog_warn(
+                                       "Recv IGMP report v3 from %s on %s: unknown record type: type=%d",
+                                       from_str, ifp->name, rec_type);
+                       }
+
+               group_record +=
+                       8 + (rec_num_sources << 2) + (rec_auxdatalen << 2);
+               local_ncb = 0;
+
+       } /* for (group records) */
+
+       return 0;
 }