diff options
author | whitespace / reindent <invalid@invalid.invalid> | 2017-08-09 11:49:42 +0200 |
---|---|---|
committer | whitespace / reindent <invalid@invalid.invalid> | 2017-08-09 12:03:17 +0200 |
commit | ac4d0be5874fafd14212d6007fff7495edc9b152 (patch) | |
tree | 5e2f0d3189de928c849f9983406389ade3b098cb /pimd/pim_iface.c | |
parent | Merge pull request #920 from opensourcerouting/static-routes-ifindex-update-3.0 (diff) | |
download | frr-ac4d0be5874fafd14212d6007fff7495edc9b152.tar.xz frr-ac4d0be5874fafd14212d6007fff7495edc9b152.zip |
*: reindentreindent-3.0-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'pimd/pim_iface.c')
-rw-r--r-- | pimd/pim_iface.c | 2380 |
1 files changed, 1201 insertions, 1179 deletions
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index cce87ae5f..73ff86c46 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -10,7 +10,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; see the file COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, @@ -51,892 +51,907 @@ static int pim_iface_vif_index[MAXVIFS]; static void pim_if_igmp_join_del_all(struct interface *ifp); static int igmp_join_sock(const char *ifname, ifindex_t ifindex, - struct in_addr group_addr, struct in_addr source_addr); + struct in_addr group_addr, + struct in_addr source_addr); -void -pim_if_init (void) +void pim_if_init(void) { - int i; + int i; - for (i = 0; i < MAXVIFS; i++) - pim_iface_vif_index[i] = 0; + for (i = 0; i < MAXVIFS; i++) + pim_iface_vif_index[i] = 0; - vrf_iflist_create(VRF_DEFAULT); - pim_ifchannel_list = list_new(); - pim_ifchannel_list->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + vrf_iflist_create(VRF_DEFAULT); + pim_ifchannel_list = list_new(); + pim_ifchannel_list->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; } -void -pim_if_terminate (void) +void pim_if_terminate(void) { - if (pim_ifchannel_list) - list_free (pim_ifchannel_list); + if (pim_ifchannel_list) + list_free(pim_ifchannel_list); } static void *if_list_clean(struct pim_interface *pim_ifp) { - if (pim_ifp->igmp_join_list) { - list_delete(pim_ifp->igmp_join_list); - } + if (pim_ifp->igmp_join_list) { + list_delete(pim_ifp->igmp_join_list); + } - if (pim_ifp->igmp_socket_list) { - list_delete(pim_ifp->igmp_socket_list); - } + if (pim_ifp->igmp_socket_list) { + list_delete(pim_ifp->igmp_socket_list); + } - if (pim_ifp->pim_neighbor_list) { - list_delete(pim_ifp->pim_neighbor_list); - } + if (pim_ifp->pim_neighbor_list) { + list_delete(pim_ifp->pim_neighbor_list); + } - if (pim_ifp->upstream_switch_list) - list_delete(pim_ifp->upstream_switch_list); + if (pim_ifp->upstream_switch_list) + list_delete(pim_ifp->upstream_switch_list); - if (pim_ifp->pim_ifchannel_list) { - list_delete(pim_ifp->pim_ifchannel_list); - } + if (pim_ifp->pim_ifchannel_list) { + list_delete(pim_ifp->pim_ifchannel_list); + } - if (pim_ifp->pim_ifchannel_hash) - hash_free(pim_ifp->pim_ifchannel_hash); + if (pim_ifp->pim_ifchannel_hash) + hash_free(pim_ifp->pim_ifchannel_hash); - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - return 0; + return 0; } struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) { - struct pim_interface *pim_ifp; - - zassert(ifp); - zassert(!ifp->info); - - pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); - if (!pim_ifp) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); - return 0; - } - - pim_ifp->options = 0; - pim_ifp->mroute_vif_index = -1; - - pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; - pim_ifp->igmp_default_robustness_variable = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; - pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; - pim_ifp->igmp_query_max_response_time_dsec = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; - pim_ifp->igmp_specific_query_max_response_time_dsec = IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; - - /* - RFC 3376: 8.3. Query Response Interval - The number of seconds represented by the [Query Response Interval] - must be less than the [Query Interval]. - */ - zassert(pim_ifp->igmp_query_max_response_time_dsec < pim_ifp->igmp_default_query_interval); - - if (pim) - PIM_IF_DO_PIM(pim_ifp->options); - if (igmp) - PIM_IF_DO_IGMP(pim_ifp->options); - - PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); - - pim_ifp->igmp_join_list = NULL; - pim_ifp->igmp_socket_list = NULL; - pim_ifp->pim_neighbor_list = NULL; - pim_ifp->upstream_switch_list = NULL; - pim_ifp->pim_ifchannel_list = NULL; - pim_ifp->pim_ifchannel_hash = NULL; - pim_ifp->pim_generation_id = 0; - - /* list of struct igmp_sock */ - pim_ifp->igmp_socket_list = list_new(); - if (!pim_ifp->igmp_socket_list) { - zlog_err("%s %s: failure: igmp_socket_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->igmp_socket_list->del = (void (*)(void *)) igmp_sock_free; - - /* list of struct pim_neighbor */ - pim_ifp->pim_neighbor_list = list_new(); - if (!pim_ifp->pim_neighbor_list) { - zlog_err("%s %s: failure: pim_neighbor_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->pim_neighbor_list->del = (void (*)(void *)) pim_neighbor_free; - - pim_ifp->upstream_switch_list = list_new(); - if (!pim_ifp->upstream_switch_list) { - zlog_err("%s %s: failure: upstream_switch_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - - /* list of struct pim_ifchannel */ - pim_ifp->pim_ifchannel_list = list_new(); - if (!pim_ifp->pim_ifchannel_list) { - zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free; - pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare; - - pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key, - pim_ifchannel_equal); - - ifp->info = pim_ifp; - - pim_sock_reset(ifp); - - pim_if_add_vif(ifp); - - return pim_ifp; + struct pim_interface *pim_ifp; + + zassert(ifp); + zassert(!ifp->info); + + pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); + if (!pim_ifp) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); + return 0; + } + + pim_ifp->options = 0; + pim_ifp->mroute_vif_index = -1; + + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; + pim_ifp->igmp_default_robustness_variable = + IGMP_DEFAULT_ROBUSTNESS_VARIABLE; + pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; + pim_ifp->igmp_query_max_response_time_dsec = + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; + pim_ifp->igmp_specific_query_max_response_time_dsec = + IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; + + /* + RFC 3376: 8.3. Query Response Interval + The number of seconds represented by the [Query Response Interval] + must be less than the [Query Interval]. + */ + zassert(pim_ifp->igmp_query_max_response_time_dsec + < pim_ifp->igmp_default_query_interval); + + if (pim) + PIM_IF_DO_PIM(pim_ifp->options); + if (igmp) + PIM_IF_DO_IGMP(pim_ifp->options); + + PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); + + pim_ifp->igmp_join_list = NULL; + pim_ifp->igmp_socket_list = NULL; + pim_ifp->pim_neighbor_list = NULL; + pim_ifp->upstream_switch_list = NULL; + pim_ifp->pim_ifchannel_list = NULL; + pim_ifp->pim_ifchannel_hash = NULL; + pim_ifp->pim_generation_id = 0; + + /* list of struct igmp_sock */ + pim_ifp->igmp_socket_list = list_new(); + if (!pim_ifp->igmp_socket_list) { + zlog_err("%s %s: failure: igmp_socket_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free; + + /* list of struct pim_neighbor */ + pim_ifp->pim_neighbor_list = list_new(); + if (!pim_ifp->pim_neighbor_list) { + zlog_err("%s %s: failure: pim_neighbor_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free; + + pim_ifp->upstream_switch_list = list_new(); + if (!pim_ifp->upstream_switch_list) { + zlog_err("%s %s: failure: upstream_switch_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + + /* list of struct pim_ifchannel */ + pim_ifp->pim_ifchannel_list = list_new(); + if (!pim_ifp->pim_ifchannel_list) { + zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->pim_ifchannel_list->del = (void (*)(void *))pim_ifchannel_free; + pim_ifp->pim_ifchannel_list->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; + + pim_ifp->pim_ifchannel_hash = + hash_create(pim_ifchannel_hash_key, pim_ifchannel_equal); + + ifp->info = pim_ifp; + + pim_sock_reset(ifp); + + pim_if_add_vif(ifp); + + return pim_ifp; } void pim_if_delete(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (pim_ifp->igmp_join_list) { - pim_if_igmp_join_del_all(ifp); - } + if (pim_ifp->igmp_join_list) { + pim_if_igmp_join_del_all(ifp); + } - pim_ifchannel_delete_all (ifp); - igmp_sock_delete_all (ifp); + pim_ifchannel_delete_all(ifp); + igmp_sock_delete_all(ifp); - pim_neighbor_delete_all (ifp, "Interface removed from configuration"); + pim_neighbor_delete_all(ifp, "Interface removed from configuration"); - pim_if_del_vif(ifp); + pim_if_del_vif(ifp); - list_delete(pim_ifp->igmp_socket_list); - list_delete(pim_ifp->pim_neighbor_list); - list_delete(pim_ifp->upstream_switch_list); - list_delete(pim_ifp->pim_ifchannel_list); + list_delete(pim_ifp->igmp_socket_list); + list_delete(pim_ifp->pim_neighbor_list); + list_delete(pim_ifp->upstream_switch_list); + list_delete(pim_ifp->pim_ifchannel_list); - hash_free (pim_ifp->pim_ifchannel_hash); + hash_free(pim_ifp->pim_ifchannel_hash); - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - ifp->info = NULL; + ifp->info = NULL; } void pim_if_update_could_assert(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_could_assert(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_could_assert(ch); + } } static void pim_if_update_my_assert_metric(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_my_assert_metric(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_my_assert_metric(ch); + } } static void pim_addr_change(struct interface *ifp) { - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- Done TODO T30 */ - pim_if_update_join_desired(pim_ifp); /* depends on DR */ - pim_if_update_could_assert(ifp); /* depends on DR */ - pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ - pim_if_update_assert_tracking_desired(ifp); /* depends on DR, join_desired */ - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - 1) Before an interface goes down or changes primary IP address, a - Hello message with a zero HoldTime should be sent immediately - (with the old IP address if the IP address changed). - -- FIXME See CAVEAT C13 - - 2) After an interface has changed its IP address, it MUST send a - Hello message with its new IP address. - -- DONE below - - 3) If an interface changes one of its secondary IP addresses, a - Hello message with an updated Address_List option and a non-zero - HoldTime should be sent immediately. - -- FIXME See TODO T31 - */ - pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ - if (pim_ifp->pim_sock_fd < 0) - return; - pim_hello_restart_now(ifp); /* send hello and restart timer */ + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- + Done TODO T30 */ + pim_if_update_join_desired(pim_ifp); /* depends on DR */ + pim_if_update_could_assert(ifp); /* depends on DR */ + pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ + pim_if_update_assert_tracking_desired( + ifp); /* depends on DR, join_desired */ + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + 1) Before an interface goes down or changes primary IP address, a + Hello message with a zero HoldTime should be sent immediately + (with the old IP address if the IP address changed). + -- FIXME See CAVEAT C13 + + 2) After an interface has changed its IP address, it MUST send a + Hello message with its new IP address. + -- DONE below + + 3) If an interface changes one of its secondary IP addresses, a + Hello message with an updated Address_List option and a non-zero + HoldTime should be sent immediately. + -- FIXME See TODO T31 + */ + pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ + if (pim_ifp->pim_sock_fd < 0) + return; + pim_hello_restart_now(ifp); /* send hello and restart timer */ } static int detect_primary_address_change(struct interface *ifp, int force_prim_as_any, const char *caller) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr new_prim_addr; - int changed; - - if (force_prim_as_any) - new_prim_addr = qpim_inaddr_any; - else - new_prim_addr = pim_find_primary_addr(ifp); - - changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; - - if (PIM_DEBUG_ZEBRA) { - char new_prim_str[INET_ADDRSTRLEN]; - char old_prim_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, sizeof(new_prim_str)); - pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, sizeof(old_prim_str)); - zlog_debug("%s: old=%s new=%s on interface %s: %s", - __PRETTY_FUNCTION__, - old_prim_str, new_prim_str, ifp->name, - changed ? "changed" : "unchanged"); - } - - if (changed) { - pim_ifp->primary_address = new_prim_addr; - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr new_prim_addr; + int changed; + + if (force_prim_as_any) + new_prim_addr = qpim_inaddr_any; + else + new_prim_addr = pim_find_primary_addr(ifp); + + changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; + + if (PIM_DEBUG_ZEBRA) { + char new_prim_str[INET_ADDRSTRLEN]; + char old_prim_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, + sizeof(new_prim_str)); + pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, + sizeof(old_prim_str)); + zlog_debug("%s: old=%s new=%s on interface %s: %s", + __PRETTY_FUNCTION__, old_prim_str, new_prim_str, + ifp->name, changed ? "changed" : "unchanged"); + } + + if (changed) { + pim_ifp->primary_address = new_prim_addr; + } + + return changed; } static int pim_sec_addr_comp(const void *p1, const void *p2) { - const struct pim_secondary_addr *sec1 = p1; - const struct pim_secondary_addr *sec2 = p2; + const struct pim_secondary_addr *sec1 = p1; + const struct pim_secondary_addr *sec2 = p2; - if (ntohl(sec1->addr.s_addr) < ntohl(sec2->addr.s_addr)) - return -1; + if (ntohl(sec1->addr.s_addr) < ntohl(sec2->addr.s_addr)) + return -1; - if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr)) - return 1; + if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr)) + return 1; - return 0; + return 0; } static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) { - XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); + XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); } static struct pim_secondary_addr * pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr) { - struct pim_secondary_addr *sec_addr; - struct listnode *node; + struct pim_secondary_addr *sec_addr; + struct listnode *node; - if (!pim_ifp->sec_addr_list) { - return NULL; - } + if (!pim_ifp->sec_addr_list) { + return NULL; + } - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (sec_addr->addr.s_addr == addr.s_addr) { - return sec_addr; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (sec_addr->addr.s_addr == addr.s_addr) { + return sec_addr; + } + } - return NULL; + return NULL; } static void pim_sec_addr_del(struct pim_interface *pim_ifp, - struct pim_secondary_addr *sec_addr) + struct pim_secondary_addr *sec_addr) { - listnode_delete(pim_ifp->sec_addr_list, sec_addr); - pim_sec_addr_free(sec_addr); + listnode_delete(pim_ifp->sec_addr_list, sec_addr); + pim_sec_addr_free(sec_addr); } static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr) { - int changed = 0; - struct pim_secondary_addr *sec_addr; - - sec_addr = pim_sec_addr_find(pim_ifp, addr); - if (sec_addr) { - sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; - return changed; - } - - if (!pim_ifp->sec_addr_list) { - pim_ifp->sec_addr_list = list_new(); - pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; - pim_ifp->sec_addr_list->cmp = (int (*)(void *, void *))pim_sec_addr_comp; - } - - sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); - if (!sec_addr) { - if (list_isempty(pim_ifp->sec_addr_list)) { - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - return changed; - } - - changed = 1; - sec_addr->addr = addr; - listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); - - return changed; + int changed = 0; + struct pim_secondary_addr *sec_addr; + + sec_addr = pim_sec_addr_find(pim_ifp, addr); + if (sec_addr) { + sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; + return changed; + } + + if (!pim_ifp->sec_addr_list) { + pim_ifp->sec_addr_list = list_new(); + pim_ifp->sec_addr_list->del = + (void (*)(void *))pim_sec_addr_free; + pim_ifp->sec_addr_list->cmp = + (int (*)(void *, void *))pim_sec_addr_comp; + } + + sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); + if (!sec_addr) { + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + return changed; + } + + changed = 1; + sec_addr->addr = addr; + listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); + + return changed; } static int pim_sec_addr_del_all(struct pim_interface *pim_ifp) { - int changed = 0; - - if (!pim_ifp->sec_addr_list) { - return changed; - } - if (!list_isempty(pim_ifp->sec_addr_list)) { - changed = 1; - /* remove all nodes and free up the list itself */ - list_delete_all_node(pim_ifp->sec_addr_list); - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - - return changed; + int changed = 0; + + if (!pim_ifp->sec_addr_list) { + return changed; + } + if (!list_isempty(pim_ifp->sec_addr_list)) { + changed = 1; + /* remove all nodes and free up the list itself */ + list_delete_all_node(pim_ifp->sec_addr_list); + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + + return changed; } static int pim_sec_addr_update(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - struct pim_secondary_addr *sec_addr; - int changed = 0; - - if (pim_ifp->sec_addr_list) { - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - sec_addr->flags |= PIM_SEC_ADDRF_STALE; - } - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) { - continue; - } - - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - continue; - } - - if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { - /* don't add the primary address into the secondary address list */ - continue; - } - - if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) { - changed = 1; - } - } - - if (pim_ifp->sec_addr_list) { - /* Drop stale entries */ - for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, sec_addr)) { - if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { - pim_sec_addr_del(pim_ifp, sec_addr); - changed = 1; - } - } - - /* If the list went empty free it up */ - if (list_isempty(pim_ifp->sec_addr_list)) { - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + struct pim_secondary_addr *sec_addr; + int changed = 0; + + if (pim_ifp->sec_addr_list) { + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, + sec_addr)) { + sec_addr->flags |= PIM_SEC_ADDRF_STALE; + } + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) { + continue; + } + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + continue; + } + + if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { + /* don't add the primary address into the secondary + * address list */ + continue; + } + + if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) { + changed = 1; + } + } + + if (pim_ifp->sec_addr_list) { + /* Drop stale entries */ + for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, + sec_addr)) { + if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { + pim_sec_addr_del(pim_ifp, sec_addr); + changed = 1; + } + } + + /* If the list went empty free it up */ + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + } + + return changed; } static int detect_secondary_address_change(struct interface *ifp, - int force_prim_as_any, - const char *caller) + int force_prim_as_any, + const char *caller) { - struct pim_interface *pim_ifp = ifp->info; - int changed = 0; - - if (force_prim_as_any) { - /* if primary address is being forced to zero just flush the - * secondary address list */ - changed = pim_sec_addr_del_all(pim_ifp); - } else { - /* re-evaluate the secondary address list */ - changed = pim_sec_addr_update(ifp); - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + int changed = 0; + + if (force_prim_as_any) { + /* if primary address is being forced to zero just flush the + * secondary address list */ + changed = pim_sec_addr_del_all(pim_ifp); + } else { + /* re-evaluate the secondary address list */ + changed = pim_sec_addr_update(ifp); + } + + return changed; } -static void detect_address_change(struct interface *ifp, - int force_prim_as_any, - const char *caller) +static void detect_address_change(struct interface *ifp, int force_prim_as_any, + const char *caller) { - int changed = 0; - struct pim_interface *pim_ifp; + int changed = 0; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - if (!pim_ifp) - return; + pim_ifp = ifp->info; + if (!pim_ifp) + return; - if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { - changed = 1; - } + if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } - if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { - changed = 1; - } + if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } - if (changed) { - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - return; - } + if (changed) { + if (!PIM_IF_TEST_PIM(pim_ifp->options)) { + return; + } - pim_addr_change(ifp); - } + pim_addr_change(ifp); + } - /* XXX: if we have unnumbered interfaces we need to run detect address - * address change on all of them when the lo address changes */ + /* XXX: if we have unnumbered interfaces we need to run detect address + * address change on all of them when the lo address changes */ } int pim_update_source_set(struct interface *ifp, struct in_addr source) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - return PIM_IFACE_NOT_FOUND; - } + if (!pim_ifp) { + return PIM_IFACE_NOT_FOUND; + } - if (pim_ifp->update_source.s_addr == source.s_addr) { - return PIM_UPDATE_SOURCE_DUP; - } + if (pim_ifp->update_source.s_addr == source.s_addr) { + return PIM_UPDATE_SOURCE_DUP; + } - pim_ifp->update_source = source; - detect_address_change(ifp, 0 /* force_prim_as_any */, - __PRETTY_FUNCTION__); + pim_ifp->update_source = source; + detect_address_change(ifp, 0 /* force_prim_as_any */, + __PRETTY_FUNCTION__); - return PIM_SUCCESS; + return PIM_SUCCESS; } void pim_if_addr_add(struct connected *ifc) { - struct pim_interface *pim_ifp; - struct interface *ifp; - struct in_addr ifaddr; - - zassert(ifc); - - ifp = ifc->ifp; - zassert(ifp); - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - if (!if_is_operative(ifp)) - return; - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(ifc->address, buf, BUFSIZ); - zlog_debug("%s: %s ifindex=%d connected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } - - ifaddr = ifc->address->u.prefix4; - - detect_address_change(ifp, 0, __PRETTY_FUNCTION__); - - if (PIM_IF_TEST_IGMP(pim_ifp->options)) { - struct igmp_sock *igmp; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); - if (!igmp) { - /* if addr new, add IGMP socket */ - pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); - } - - /* Replay Static IGMP groups */ - if (pim_ifp->igmp_join_list) - { - struct listnode *node; - struct listnode *nextnode; - struct igmp_join *ij; - int join_fd; - - for (ALL_LIST_ELEMENTS (pim_ifp->igmp_join_list, node, nextnode, ij)) - { - /* Close socket and reopen with Source and Group */ - close(ij->sock_fd); - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr); - if (join_fd < 0) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - /* warning only */ - } - else - ij->sock_fd = join_fd; - } - } - } /* igmp */ - - if (PIM_IF_TEST_PIM(pim_ifp->options)) - { - - if (PIM_INADDR_ISNOT_ANY (pim_ifp->primary_address)) - { - - /* Interface has a valid socket ? */ - if (pim_ifp->pim_sock_fd < 0) - { - if (pim_sock_add (ifp)) - { - zlog_warn ("Failure creating PIM socket for interface %s", - ifp->name); - } - } - struct pim_nexthop_cache *pnc = NULL; - struct pim_rpf rpf; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - /* RP config might come prior to (local RP's interface) IF UP event. - In this case, pnc would not have pim enabled nexthops. - Once Interface is UP and pim info is available, reregister - with RNH address to receive update and add the interface as nexthop. */ - memset (&rpf, 0, sizeof (struct pim_rpf)); - rpf.rpf_addr.family = AF_INET; - rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; - rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; - pnc = pim_nexthop_cache_find (&rpf); - if (pnc) - pim_sendmsg_zebra_rnh (zclient, pnc, - ZEBRA_NEXTHOP_REGISTER); - } - } /* pim */ - - /* - PIM or IGMP is enabled on interface, and there is at least one - address assigned, then try to create a vif_index. - */ - if (pim_ifp->mroute_vif_index < 0) { - pim_if_add_vif(ifp); - } - pim_ifchannel_scan_forward_start (ifp); + struct pim_interface *pim_ifp; + struct interface *ifp; + struct in_addr ifaddr; + + zassert(ifc); + + ifp = ifc->ifp; + zassert(ifp); + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + if (!if_is_operative(ifp)) + return; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(ifc->address, buf, BUFSIZ); + zlog_debug("%s: %s ifindex=%d connected IP address %s %s", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } + + ifaddr = ifc->address->u.prefix4; + + detect_address_change(ifp, 0, __PRETTY_FUNCTION__); + + if (PIM_IF_TEST_IGMP(pim_ifp->options)) { + struct igmp_sock *igmp; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + if (!igmp) { + /* if addr new, add IGMP socket */ + pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, + ifp); + } + + /* Replay Static IGMP groups */ + if (pim_ifp->igmp_join_list) { + struct listnode *node; + struct listnode *nextnode; + struct igmp_join *ij; + int join_fd; + + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, + nextnode, ij)) { + /* Close socket and reopen with Source and Group + */ + close(ij->sock_fd); + join_fd = igmp_join_sock( + ifp->name, ifp->ifindex, ij->group_addr, + ij->source_addr); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", ij->group_addr, + group_str, + sizeof(group_str)); + pim_inet4_dump( + "<src?>", ij->source_addr, + source_str, sizeof(source_str)); + zlog_warn( + "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, + source_str, ifp->name); + /* warning only */ + } else + ij->sock_fd = join_fd; + } + } + } /* igmp */ + + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn( + "Failure creating PIM socket for interface %s", + ifp->name); + } + } + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + /* RP config might come prior to (local RP's interface) + IF UP event. + In this case, pnc would not have pim enabled + nexthops. + Once Interface is UP and pim info is available, + reregister + with RNH address to receive update and add the + interface as nexthop. */ + memset(&rpf, 0, sizeof(struct pim_rpf)); + rpf.rpf_addr.family = AF_INET; + rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; + rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; + pnc = pim_nexthop_cache_find(&rpf); + if (pnc) + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + } + } /* pim */ + + /* + PIM or IGMP is enabled on interface, and there is at least one + address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start(ifp); } static void pim_if_addr_del_igmp(struct connected *ifc) { - struct pim_interface *pim_ifp = ifc->ifp->info; - struct igmp_sock *igmp; - struct in_addr ifaddr; - - if (ifc->address->family != AF_INET) { - /* non-IPv4 address */ - return; - } - - if (!pim_ifp) { - /* IGMP not enabled on interface */ - return; - } - - ifaddr = ifc->address->u.prefix4; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); - if (igmp) { - /* if addr found, del IGMP socket */ - igmp_sock_delete(igmp); - } + struct pim_interface *pim_ifp = ifc->ifp->info; + struct igmp_sock *igmp; + struct in_addr ifaddr; + + if (ifc->address->family != AF_INET) { + /* non-IPv4 address */ + return; + } + + if (!pim_ifp) { + /* IGMP not enabled on interface */ + return; + } + + ifaddr = ifc->address->u.prefix4; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); + if (igmp) { + /* if addr found, del IGMP socket */ + igmp_sock_delete(igmp); + } } static void pim_if_addr_del_pim(struct connected *ifc) { - struct pim_interface *pim_ifp = ifc->ifp->info; - - if (ifc->address->family != AF_INET) { - /* non-IPv4 address */ - return; - } - - if (!pim_ifp) { - /* PIM not enabled on interface */ - return; - } - - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { - /* Interface keeps a valid primary address */ - return; - } - - if (pim_ifp->pim_sock_fd < 0) { - /* Interface does not hold a valid socket any longer */ - return; - } - - /* - pim_sock_delete() closes the socket, stops read and timer threads, - and kills all neighbors. - */ - pim_sock_delete(ifc->ifp, "last address has been removed from interface"); + struct pim_interface *pim_ifp = ifc->ifp->info; + + if (ifc->address->family != AF_INET) { + /* non-IPv4 address */ + return; + } + + if (!pim_ifp) { + /* PIM not enabled on interface */ + return; + } + + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + /* Interface keeps a valid primary address */ + return; + } + + if (pim_ifp->pim_sock_fd < 0) { + /* Interface does not hold a valid socket any longer */ + return; + } + + /* + pim_sock_delete() closes the socket, stops read and timer threads, + and kills all neighbors. + */ + pim_sock_delete(ifc->ifp, + "last address has been removed from interface"); } void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) { - struct interface *ifp; - - zassert(ifc); - ifp = ifc->ifp; - zassert(ifp); - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(ifc->address, buf, BUFSIZ); - zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } - - detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); - - pim_if_addr_del_igmp(ifc); - pim_if_addr_del_pim(ifc); + struct interface *ifp; + + zassert(ifc); + ifp = ifc->ifp; + zassert(ifp); + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(ifc->address, buf, BUFSIZ); + zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } + + detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); + + pim_if_addr_del_igmp(ifc); + pim_if_addr_del_pim(ifc); } void pim_if_addr_add_all(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - int v4_addrs = 0; - int v6_addrs = 0; - struct pim_interface *pim_ifp = ifp->info; - - - /* PIM/IGMP enabled ? */ - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - { - v6_addrs++; - continue; - } - - v4_addrs++; - pim_if_addr_add(ifc); - } - - if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) - { - if (PIM_IF_TEST_PIM(pim_ifp->options)) { - - /* Interface has a valid primary address ? */ - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + int v4_addrs = 0; + int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; - /* Interface has a valid socket ? */ - if (pim_ifp->pim_sock_fd < 0) { - if (pim_sock_add(ifp)) { - zlog_warn("Failure creating PIM socket for interface %s", - ifp->name); - } - } - - } - } /* pim */ - } - /* - * PIM or IGMP is enabled on interface, and there is at least one - * address assigned, then try to create a vif_index. - */ - if (pim_ifp->mroute_vif_index < 0) { - pim_if_add_vif(ifp); - } - pim_ifchannel_scan_forward_start (ifp); - - pim_rp_setup(); - pim_rp_check_on_if_add(pim_ifp); + + /* PIM/IGMP enabled ? */ + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) { + v6_addrs++; + continue; + } + + v4_addrs++; + pim_if_addr_add(ifc); + } + + if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + + /* Interface has a valid primary address ? */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn( + "Failure creating PIM socket for interface %s", + ifp->name); + } + } + } + } /* pim */ + } + /* + * PIM or IGMP is enabled on interface, and there is at least one + * address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start(ifp); + + pim_rp_setup(); + pim_rp_check_on_if_add(pim_ifp); } void pim_if_addr_del_all(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; - pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); - } + if (p->family != AF_INET) + continue; + + pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); + } - pim_rp_setup(); - pim_i_am_rp_re_evaluate(); + pim_rp_setup(); + pim_i_am_rp_re_evaluate(); } void pim_if_addr_del_all_igmp(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - pim_if_addr_del_igmp(ifc); - } + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + pim_if_addr_del_igmp(ifc); + } } void pim_if_addr_del_all_pim(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - pim_if_addr_del_pim(ifc); - } + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + pim_if_addr_del_pim(ifc); + } } -struct in_addr -pim_find_primary_addr (struct interface *ifp) +struct in_addr pim_find_primary_addr(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct in_addr addr; - int v4_addrs = 0; - int v6_addrs = 0; - struct pim_interface *pim_ifp = ifp->info; - - if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { - return pim_ifp->update_source; - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - { - v6_addrs++; - continue; - } - - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - zlog_warn("%s: null IPv4 address connected to interface %s", - __PRETTY_FUNCTION__, ifp->name); - continue; - } - - v4_addrs++; - - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) - continue; - - return p->u.prefix4; - } - - /* - * If we have no v4_addrs and v6 is configured - * We probably are using unnumbered - * So let's grab the loopbacks v4 address - * and use that as the primary address - */ - if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) - { - struct interface *lo_ifp; - lo_ifp = if_lookup_by_name ("lo", VRF_DEFAULT); - if (lo_ifp) - return pim_find_primary_addr (lo_ifp); - } - - addr.s_addr = PIM_NET_INADDR_ANY; - - return addr; + struct connected *ifc; + struct listnode *node; + struct in_addr addr; + int v4_addrs = 0; + int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + + if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + return pim_ifp->update_source; + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) { + v6_addrs++; + continue; + } + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + zlog_warn( + "%s: null IPv4 address connected to interface %s", + __PRETTY_FUNCTION__, ifp->name); + continue; + } + + v4_addrs++; + + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + return p->u.prefix4; + } + + /* + * If we have no v4_addrs and v6 is configured + * We probably are using unnumbered + * So let's grab the loopbacks v4 address + * and use that as the primary address + */ + if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { + struct interface *lo_ifp; + lo_ifp = if_lookup_by_name("lo", VRF_DEFAULT); + if (lo_ifp) + return pim_find_primary_addr(lo_ifp); + } + + addr.s_addr = PIM_NET_INADDR_ANY; + + return addr; } -static int -pim_iface_next_vif_index (struct interface *ifp) +static int pim_iface_next_vif_index(struct interface *ifp) { - int i; - /* - * The pimreg vif is always going to be in index 0 - * of the table. - */ - if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) - return 0; - - for (i = 1 ; i < MAXVIFS; i++) - { - if (pim_iface_vif_index[i] == 0) - return i; - } - return MAXVIFS; + int i; + /* + * The pimreg vif is always going to be in index 0 + * of the table. + */ + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + return 0; + + for (i = 1; i < MAXVIFS; i++) { + if (pim_iface_vif_index[i] == 0) + return i; + } + return MAXVIFS; } /* @@ -946,130 +961,131 @@ pim_iface_next_vif_index (struct interface *ifp) */ int pim_if_add_vif(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr ifaddr; - unsigned char flags = 0; - - zassert(pim_ifp); - - if (pim_ifp->mroute_vif_index > 0) { - zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", - __PRETTY_FUNCTION__, - pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); - return -1; - } - - if (ifp->ifindex < 0) { - zlog_warn("%s: ifindex=%d < 1 on interface %s", - __PRETTY_FUNCTION__, - ifp->ifindex, ifp->name); - return -2; - } - - ifaddr = pim_ifp->primary_address; - if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF && PIM_INADDR_IS_ANY(ifaddr)) { - zlog_warn("%s: could not get address for interface %s ifindex=%d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex); - return -4; - } - - pim_ifp->mroute_vif_index = pim_iface_next_vif_index (ifp); - - if (pim_ifp->mroute_vif_index >= MAXVIFS) - { - zlog_warn("%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", - __PRETTY_FUNCTION__, - MAXVIFS, ifp->name); - return -3; - } - - if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) - flags = VIFF_REGISTER; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr ifaddr; + unsigned char flags = 0; + + zassert(pim_ifp); + + if (pim_ifp->mroute_vif_index > 0) { + zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", + __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, + ifp->name, ifp->ifindex); + return -1; + } + + if (ifp->ifindex < 0) { + zlog_warn("%s: ifindex=%d < 1 on interface %s", + __PRETTY_FUNCTION__, ifp->ifindex, ifp->name); + return -2; + } + + ifaddr = pim_ifp->primary_address; + if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF + && PIM_INADDR_IS_ANY(ifaddr)) { + zlog_warn( + "%s: could not get address for interface %s ifindex=%d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex); + return -4; + } + + pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp); + + if (pim_ifp->mroute_vif_index >= MAXVIFS) { + zlog_warn( + "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", + __PRETTY_FUNCTION__, MAXVIFS, ifp->name); + return -3; + } + + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + flags = VIFF_REGISTER; #ifdef VIFF_USE_IFINDEX - else - flags = VIFF_USE_IFINDEX; + else + flags = VIFF_USE_IFINDEX; #endif - if (pim_mroute_add_vif(ifp, ifaddr, flags)) { - /* pim_mroute_add_vif reported error */ - return -5; - } + if (pim_mroute_add_vif(ifp, ifaddr, flags)) { + /* pim_mroute_add_vif reported error */ + return -5; + } - pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; - return 0; + pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; + return 0; } int pim_if_del_vif(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (pim_ifp->mroute_vif_index < 1) { - zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", - __PRETTY_FUNCTION__, - pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); - return -1; - } + if (pim_ifp->mroute_vif_index < 1) { + zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", + __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, + ifp->name, ifp->ifindex); + return -1; + } - pim_mroute_del_vif(pim_ifp->mroute_vif_index); + pim_mroute_del_vif(pim_ifp->mroute_vif_index); - /* - Update vif_index - */ - pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; + /* + Update vif_index + */ + pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; - pim_ifp->mroute_vif_index = -1; + pim_ifp->mroute_vif_index = -1; - return 0; + return 0; } void pim_if_add_vif_all() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (!ifp->info) + continue; - pim_if_add_vif(ifp); - } + pim_if_add_vif(ifp); + } } void pim_if_del_vif_all() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (!ifp->info) + continue; - pim_if_del_vif(ifp); - } + pim_if_del_vif(ifp); + } } struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) { - struct listnode *ifnode; - struct interface *ifp; + struct listnode *ifnode; + struct interface *ifp; - if (vif_index == 0) - return if_lookup_by_name ("pimreg", VRF_DEFAULT); + if (vif_index == 0) + return if_lookup_by_name("pimreg", VRF_DEFAULT); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - if (ifp->info) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + if (ifp->info) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; - if (vif_index == pim_ifp->mroute_vif_index) - return ifp; - } - } + if (vif_index == pim_ifp->mroute_vif_index) + return ifp; + } + } - return 0; + return 0; } /* @@ -1077,69 +1093,67 @@ struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) */ int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) { - struct pim_interface *pim_ifp; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct interface *ifp; - ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); - if (!ifp || !ifp->info) - return -1; - pim_ifp = ifp->info; + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (!ifp || !ifp->info) + return -1; + pim_ifp = ifp->info; - return pim_ifp->mroute_vif_index; + return pim_ifp->mroute_vif_index; } int pim_if_lan_delay_enabled(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - zassert(pim_ifp); - zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); + pim_ifp = ifp->info; + zassert(pim_ifp); + zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); - return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; + return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; } uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp) { - if (pim_if_lan_delay_enabled(ifp)) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - return pim_ifp->pim_neighbors_highest_propagation_delay_msec; - } - else { - return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; - } + if (pim_if_lan_delay_enabled(ifp)) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; + return pim_ifp->pim_neighbors_highest_propagation_delay_msec; + } else { + return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; + } } uint16_t pim_if_effective_override_interval_msec(struct interface *ifp) { - if (pim_if_lan_delay_enabled(ifp)) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - return pim_ifp->pim_neighbors_highest_override_interval_msec; - } - else { - return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; - } + if (pim_if_lan_delay_enabled(ifp)) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; + return pim_ifp->pim_neighbors_highest_override_interval_msec; + } else { + return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; + } } int pim_if_t_override_msec(struct interface *ifp) { - int effective_override_interval_msec; - int t_override_msec; + int effective_override_interval_msec; + int t_override_msec; - effective_override_interval_msec = - pim_if_effective_override_interval_msec(ifp); + effective_override_interval_msec = + pim_if_effective_override_interval_msec(ifp); - t_override_msec = random() % (effective_override_interval_msec + 1); + t_override_msec = random() % (effective_override_interval_msec + 1); - return t_override_msec; + return t_override_msec; } uint16_t pim_if_jp_override_interval_msec(struct interface *ifp) { - return pim_if_effective_propagation_delay_msec(ifp) + - pim_if_effective_override_interval_msec(ifp); + return pim_if_effective_propagation_delay_msec(ifp) + + pim_if_effective_override_interval_msec(ifp); } /* @@ -1154,289 +1168,298 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp) struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, struct in_addr addr) { - struct listnode *neighnode; - struct pim_neighbor *neigh; - struct pim_interface *pim_ifp; - - zassert(ifp); - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return 0; - } - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - - /* primary address ? */ - if (neigh->source_addr.s_addr == addr.s_addr) - return neigh; - - /* secondary address ? */ - if (pim_neighbor_find_secondary(neigh, addr)) - return neigh; - } - - if (PIM_DEBUG_PIM_TRACE) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: neighbor not found for address %s on interface %s", - __PRETTY_FUNCTION__, - addr_str, ifp->name); - } - - return NULL; + struct listnode *neighnode; + struct pim_neighbor *neigh; + struct pim_interface *pim_ifp; + + zassert(ifp); + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return 0; + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + + /* primary address ? */ + if (neigh->source_addr.s_addr == addr.s_addr) + return neigh; + + /* secondary address ? */ + if (pim_neighbor_find_secondary(neigh, addr)) + return neigh; + } + + if (PIM_DEBUG_PIM_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); + zlog_debug( + "%s: neighbor not found for address %s on interface %s", + __PRETTY_FUNCTION__, addr_str, ifp->name); + } + + return NULL; } long pim_if_t_suppressed_msec(struct interface *ifp) { - struct pim_interface *pim_ifp; - long t_suppressed_msec; - uint32_t ramount = 0; + struct pim_interface *pim_ifp; + long t_suppressed_msec; + uint32_t ramount = 0; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - /* join suppression disabled ? */ - if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) - return 0; + /* join suppression disabled ? */ + if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) + return 0; - /* t_suppressed = t_periodic * rand(1.1, 1.4) */ - ramount = 1100 + (random() % (1400 - 1100 + 1)); - t_suppressed_msec = qpim_t_periodic * ramount; + /* t_suppressed = t_periodic * rand(1.1, 1.4) */ + ramount = 1100 + (random() % (1400 - 1100 + 1)); + t_suppressed_msec = qpim_t_periodic * ramount; - return t_suppressed_msec; + return t_suppressed_msec; } static void igmp_join_free(struct igmp_join *ij) { - XFREE(MTYPE_PIM_IGMP_JOIN, ij); + XFREE(MTYPE_PIM_IGMP_JOIN, ij); } static struct igmp_join *igmp_join_find(struct list *join_list, struct in_addr group_addr, struct in_addr source_addr) { - struct listnode *node; - struct igmp_join *ij; + struct listnode *node; + struct igmp_join *ij; - zassert(join_list); + zassert(join_list); - for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { - if ((group_addr.s_addr == ij->group_addr.s_addr) && - (source_addr.s_addr == ij->source_addr.s_addr)) - return ij; - } + for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { + if ((group_addr.s_addr == ij->group_addr.s_addr) + && (source_addr.s_addr == ij->source_addr.s_addr)) + return ij; + } - return 0; + return 0; } -static int igmp_join_sock(const char *ifname, - ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr) +static int igmp_join_sock(const char *ifname, ifindex_t ifindex, + struct in_addr group_addr, struct in_addr source_addr) { - int join_fd; + int join_fd; - join_fd = pim_socket_raw(IPPROTO_IGMP); - if (join_fd < 0) { - return -1; - } + join_fd = pim_socket_raw(IPPROTO_IGMP); + if (join_fd < 0) { + return -1; + } - if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, ifname)) { - close(join_fd); - return -2; - } + if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, + ifname)) { + close(join_fd); + return -2; + } - return join_fd; + return join_fd; } static struct igmp_join *igmp_join_new(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - int join_fd; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr); - if (join_fd < 0) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return 0; - } - - ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - sizeof(*ij), group_str, source_str, ifp->name); - close(join_fd); - return 0; - } - - ij->sock_fd = join_fd; - ij->group_addr = group_addr; - ij->source_addr = source_addr; - ij->sock_creation = pim_time_monotonic_sec(); - - listnode_add(pim_ifp->igmp_join_list, ij); - - return ij; + struct pim_interface *pim_ifp; + struct igmp_join *ij; + int join_fd; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, + source_addr); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return 0; + } + + ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_err( + "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str, + ifp->name); + close(join_fd); + return 0; + } + + ij->sock_fd = join_fd; + ij->group_addr = group_addr; + ij->source_addr = source_addr; + ij->sock_creation = pim_time_monotonic_sec(); + + listnode_add(pim_ifp->igmp_join_list, ij); + + return ij; } -int pim_if_igmp_join_add(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -1; - } - - if (!pim_ifp->igmp_join_list) { - pim_ifp->igmp_join_list = list_new(); - if (!pim_ifp->igmp_join_list) { - zlog_err("%s %s: failure: igmp_join_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return -2; - } - pim_ifp->igmp_join_list->del = (void (*)(void *)) igmp_join_free; - } - - ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); - if (ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: can't re-join existing IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -3; - } - - ij = igmp_join_new(ifp, group_addr, source_addr); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -4; - } - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", - __PRETTY_FUNCTION__, - source_str, group_str, ifp->name); - } - - return 0; -} + struct pim_interface *pim_ifp; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -1; + } + + if (!pim_ifp->igmp_join_list) { + pim_ifp->igmp_join_list = list_new(); + if (!pim_ifp->igmp_join_list) { + zlog_err("%s %s: failure: igmp_join_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return -2; + } + pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free; + } + + ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); + if (ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: can't re-join existing IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -3; + } + ij = igmp_join_new(ifp, group_addr, source_addr); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -4; + } + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", + __PRETTY_FUNCTION__, source_str, group_str, ifp->name); + } -int pim_if_igmp_join_del(struct interface *ifp, - struct in_addr group_addr, + return 0; +} + + +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -1; - } - - if (!pim_ifp->igmp_join_list) { - zlog_warn("%s: no IGMP join on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -2; - } - - ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: could not find IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -3; - } - - if (close(ij->sock_fd)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", - __PRETTY_FUNCTION__, - ij->sock_fd, group_str, source_str, ifp->name, errno, safe_strerror(errno)); - /* warning only */ - } - listnode_delete(pim_ifp->igmp_join_list, ij); - igmp_join_free(ij); - if (listcount(pim_ifp->igmp_join_list) < 1) { - list_delete(pim_ifp->igmp_join_list); - pim_ifp->igmp_join_list = 0; - } - - return 0; + struct pim_interface *pim_ifp; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -1; + } + + if (!pim_ifp->igmp_join_list) { + zlog_warn("%s: no IGMP join on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -2; + } + + ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: could not find IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -3; + } + + if (close(ij->sock_fd)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", + __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str, + ifp->name, errno, safe_strerror(errno)); + /* warning only */ + } + listnode_delete(pim_ifp->igmp_join_list, ij); + igmp_join_free(ij); + if (listcount(pim_ifp->igmp_join_list) < 1) { + list_delete(pim_ifp->igmp_join_list); + pim_ifp->igmp_join_list = 0; + } + + return 0; } static void pim_if_igmp_join_del_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *nextnode; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return; - } - - if (!pim_ifp->igmp_join_list) - return; - - for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) - pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *nextnode; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return; + } + + if (!pim_ifp->igmp_join_list) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) + pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); } /* @@ -1456,63 +1479,66 @@ static void pim_if_igmp_join_del_all(struct interface *ifp) void pim_if_assert_on_neighbor_down(struct interface *ifp, struct in_addr neigh_addr) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - /* Is (S,G,I) assert loser ? */ - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - continue; - /* Dead neighbor was winner ? */ - if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) - continue; - - assert_action_a5(ch); - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + /* Is (S,G,I) assert loser ? */ + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) + continue; + /* Dead neighbor was winner ? */ + if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) + continue; + + assert_action_a5(ch); + } } void pim_if_update_join_desired(struct pim_interface *pim_ifp) { - struct listnode *ch_node; - struct pim_ifchannel *ch; + struct listnode *ch_node; + struct pim_ifchannel *ch; - /* clear off flag from interface's upstreams */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(ch->upstream->flags); - } + /* clear off flag from interface's upstreams */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED( + ch->upstream->flags); + } - /* scan per-interface (S,G,I) state on this I interface */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - struct pim_upstream *up = ch->upstream; + /* scan per-interface (S,G,I) state on this I interface */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + struct pim_upstream *up = ch->upstream; - if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) - continue; + if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) + continue; - /* update join_desired for the global (S,G) state */ - pim_upstream_update_join_desired(up); - PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); - } + /* update join_desired for the global (S,G) state */ + pim_upstream_update_join_desired(up); + PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); + } } void pim_if_update_assert_tracking_desired(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_assert_tracking_desired(ch); - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; + + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_assert_tracking_desired(ch); + } } /* @@ -1520,52 +1546,48 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp) * The pimreg is a special interface that we have that is not * quite an inteface but a VIF is created for it. */ -void pim_if_create_pimreg (void) +void pim_if_create_pimreg(void) { - if (!pim_regiface) { - pim_regiface = if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); - pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; + if (!pim_regiface) { + pim_regiface = + if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); + pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; - pim_if_new(pim_regiface, 0, 0); - } + pim_if_new(pim_regiface, 0, 0); + } } -int -pim_if_connected_to_source (struct interface *ifp, struct in_addr src) +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src) { - struct listnode *cnode; - struct connected *c; - struct prefix p; - - if (!ifp) - return 0; - - p.family = AF_INET; - p.u.prefix4 = src; - p.prefixlen = IPV4_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if ((c->address->family == AF_INET) && - prefix_match (CONNECTED_PREFIX (c), &p)) - { - return 1; - } - } - - return 0; + struct listnode *cnode; + struct connected *c; + struct prefix p; + + if (!ifp) + return 0; + + p.family = AF_INET; + p.u.prefix4 = src; + p.prefixlen = IPV4_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + if ((c->address->family == AF_INET) + && prefix_match(CONNECTED_PREFIX(c), &p)) { + return 1; + } + } + + return 0; } -struct interface * -pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) +struct interface *pim_if_lookup_address_vrf(struct in_addr src, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - if (pim_if_connected_to_source (ifp, src) && ifp->info) - return ifp; - } - return NULL; + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + if (pim_if_connected_to_source(ifp, src) && ifp->info) + return ifp; + } + return NULL; } |