From 34687162ce39d4c34bf60bc55ea13b597b04c2ac Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:02:41 -0400 Subject: [PATCH 01/10] pimd: Convert pim address family from #define -> enum Convert the pim address family from a #define into an enum. Signed-off-by: Donald Sharp --- pimd/pim_msg.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index de663aa3b520..e5676289b73f 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -34,7 +34,11 @@ From: http://www.iana.org/assignments/address-family-numbers */ -#define PIM_MSG_ADDRESS_FAMILY_IPV4 (1) +enum pim_msg_address_family { + PIM_MSG_ADDRESS_FAMILY_RESERVED, + PIM_MSG_ADDRESS_FAMILY_IPV4, + PIM_MSG_ADDRESS_FAMILY_IPV6, +}; /* * Network Order pim_msg_hdr From 71bbe73dc4fb308b1abca5a326c6c59e1193d794 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:23:25 -0400 Subject: [PATCH 02/10] pimd: Add code to allow backwards compatibility This code change adds the ability to specify that we should be able to work with older versions of PIM. In future commits we will actually use this data. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 27 +++++++++++++++++++++++++++ pimd/pim_vty.c | 6 ++++++ pimd/pimd.c | 2 ++ pimd/pimd.h | 2 ++ 4 files changed, 37 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index cf101b3e245a..66fc8185d0f3 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3509,6 +3509,31 @@ DEFUN (no_ip_pim_packets, return CMD_SUCCESS; } +DEFUN (ip_pim_v6_secondary, + ip_pim_v6_secondary_cmd, + "ip pim send-v6-secondary", + IP_STR + "pim multicast routing\n" + "Send v6 secondary addresses\n") +{ + pimg->send_v6_secondary = 1; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_v6_secondary, + no_ip_pim_v6_secondary_cmd, + "no ip pim send-v6-secondary", + NO_STR + IP_STR + "pim multicast routing\n" + "Send v6 secondary addresses\n") +{ + pimg->send_v6_secondary = 0; + + return CMD_SUCCESS; +} + DEFUN (ip_pim_rp, ip_pim_rp_cmd, "ip pim rp A.B.C.D [A.B.C.D/M]", @@ -6037,6 +6062,8 @@ void pim_cmd_init() install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); install_element (CONFIG_NODE, &ip_pim_packets_cmd); install_element (CONFIG_NODE, &no_ip_pim_packets_cmd); + install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd); + install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); install_element (CONFIG_NODE, &ip_ssmpingd_cmd); install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); install_element (CONFIG_NODE, &ip_msdp_peer_cmd); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 5b6a79b95a0a..9788c58cd9b0 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -148,6 +148,12 @@ int pim_global_config_write(struct vty *vty) writes += pim_msdp_config_write (vty); + if (!pimg->send_v6_secondary) + { + vty_out (vty, "no ip pim send-v6-secondary%s", VTY_NEWLINE); + ++writes; + } + writes += pim_rp_config_write (vty); if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) diff --git a/pimd/pimd.c b/pimd/pimd.c index b67544b28efe..9058e14b0af1 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -109,6 +109,8 @@ pim_vrf_enable (struct vrf *vrf) if (pimg == NULL) zlog_err ("%s %s: pim class init failure ", __FILE__, __PRETTY_FUNCTION__); + + pimg->send_v6_secondary = 1; } return 0; } diff --git a/pimd/pimd.h b/pimd/pimd.h index b3bdd9e243ce..8dc58990229f 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -240,6 +240,8 @@ struct pim_instance afi_t afi; vrf_id_t vrf_id; struct hash *rpf_hash; + + int send_v6_secondary; }; extern struct pim_instance *pimg; //Pim Global Instance From 7399328a6fbd9e41e03cc8d0c9bfbf16a5738c9a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:27:25 -0400 Subject: [PATCH 03/10] pimd: Fix RP determination to handle secondary addresses better When we are checking RP addresses and looking at the secondary address. With the addition of the ability to handle v6 addresses in the secondary list. Assuming that the secondary address is a v4 address is a no go. Convert to prefix_same. Signed-off-by: Donald Sharp --- pimd/pim_rp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 6c83811d9af1..8afc87956d90 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -261,7 +261,7 @@ pim_rp_check_interface_addrs(struct rp_info *rp_info, } for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (sec_addr->addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) { + if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { return 1; } } From 07b17d5927499beaf42665bb7bd2bcaea0b1e9d6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Mar 2017 23:44:12 -0400 Subject: [PATCH 04/10] pimd: Add code to find neighbor by secondary With RFC 5549 we need a methodology to find a neighbor based upon a nexthop that is v6 based. This commit sets us up for that by allowing you to find the neigbor by the secondary list. In a future commit we will add code to pass the v6 secondary addresses. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 7 ++++++- pimd/pim_neighbor.c | 38 ++++++++++++++++++++++++++++++-------- pimd/pim_neighbor.h | 5 +++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 086479643166..a753cc4affc3 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1105,6 +1105,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, struct listnode *neighnode; struct pim_neighbor *neigh; struct pim_interface *pim_ifp; + struct prefix p; zassert(ifp); @@ -1116,6 +1117,10 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, return 0; } + p.family = AF_INET; + p.u.prefix4 = addr; + p.prefixlen = IPV4_MAX_PREFIXLEN; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { /* primary address ? */ @@ -1123,7 +1128,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, return neigh; /* secondary address ? */ - if (pim_neighbor_find_secondary(neigh, addr)) + if (pim_neighbor_find_secondary(neigh, &p)) return neigh; } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index c1325df2605e..133d4edb216e 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -423,6 +423,31 @@ void pim_neighbor_free(struct pim_neighbor *neigh) XFREE(MTYPE_PIM_NEIGHBOR, neigh); } +struct pim_neighbor * +pim_neighbor_find_by_secondary (struct interface *ifp, + struct prefix *src) +{ + struct pim_interface *pim_ifp; + struct listnode *node, *pnode; + struct pim_neighbor *neigh; + struct prefix *p; + + pim_ifp = ifp->info; + if (!pim_ifp) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) + { + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) + { + if (prefix_same (p, src)) + return neigh; + } + } + + return NULL; +} + struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr) { @@ -669,7 +694,7 @@ void pim_neighbor_delete_all(struct interface *ifp, } struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, - struct in_addr addr) + struct prefix *addr) { struct listnode *node; struct prefix *p; @@ -678,14 +703,11 @@ struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, return 0; for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { - if (p->family == AF_INET) { - if (addr.s_addr == p->u.prefix4.s_addr) { - return p; - } - } + if (prefix_same (p, addr)) + return p; } - return 0; + return NULL; } /* @@ -729,7 +751,7 @@ static void delete_from_neigh_addr(struct interface *ifp, for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { { - struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4); + struct prefix *p = pim_neighbor_find_secondary(neigh, addr); if (p) { char addr_str[INET_ADDRSTRLEN]; char this_neigh_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index 986721666eaa..e27920fdd8bf 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -50,7 +50,8 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime); void pim_neighbor_free(struct pim_neighbor *neigh); struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr); - +struct pim_neighbor *pim_neighbor_find_by_secondary (struct interface *ifp, + struct prefix *src); struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp); @@ -77,7 +78,7 @@ void pim_neighbor_update(struct pim_neighbor *neigh, uint32_t dr_priority, struct list *addr_list); struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, - struct in_addr addr); + struct prefix *addr); int pim_if_dr_election(struct interface *ifp); #endif /* PIM_NEIGHBOR_H */ From 0f4b1d2d95e4f9bdb1412b5792941289332a7cc6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 00:07:18 -0400 Subject: [PATCH 05/10] pimd: Add ability to encode/decode v6 secondary addresses Add ability to encode/decode the v6 secondary addresses if they are passed to us. This also fixes the issue where if we are passed a v6 secondary address list we will not refuse to form neighbors. Signed-off-by: Donald Sharp --- pimd/pim_hello.c | 3 ++- pimd/pim_tlv.c | 53 +++++++++++++++++++++++++++++++++++++++--------- pimd/pim_tlv.h | 3 ++- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 3d7ae4ad22bd..d9b04ea9526f 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -507,7 +507,8 @@ int pim_hello_build_tlv(const char *ifname, if (ifconnected) { curr = pim_tlv_append_addrlist_ucast(curr, pastend, - ifconnected); + ifconnected, + AF_INET); if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s", diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 5223f60e1b22..1d58ce3ac63f 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -94,6 +94,7 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, } #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) +#define ucast_ipv6_encoding_len (2 + sizeof(struct in6_addr)) /* * An Encoded-Unicast address takes the following format: @@ -135,6 +136,14 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) memcpy (buf, &p->u.prefix4, sizeof (struct in_addr)); return ucast_ipv4_encoding_len; break; + case AF_INET6: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr)); + return ucast_ipv6_encoding_len; + break; default: return 0; break; @@ -216,12 +225,13 @@ pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, - struct list *ifconnected) + struct list *ifconnected, + int family) { struct listnode *node; uint16_t option_len = 0; - uint8_t *curr; + size_t uel; node = listhead(ifconnected); @@ -230,8 +240,10 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, return buf; } - /* Skip first address (primary) */ - node = listnextnode(node); + if (family == AF_INET) + uel = ucast_ipv4_encoding_len; + else + uel = ucast_ipv6_encoding_len; /* Scan secondary address list */ curr = buf + 4; /* skip T and L */ @@ -240,8 +252,14 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, struct prefix *p = ifc->address; int l_encode; - if ((curr + ucast_ipv4_encoding_len) > buf_pastend) - return 0; + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + if ((curr + uel) > buf_pastend) + return 0; + + if (p->family != family) + continue; l_encode = pim_encode_addr_ucast (curr, p); curr += l_encode; @@ -251,7 +269,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, if (PIM_DEBUG_PIM_TRACE_DETAIL) { zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu", __PRETTY_FUNCTION__, - option_len / ucast_ipv4_encoding_len); + option_len / uel); } if (option_len < 1) { @@ -491,9 +509,23 @@ pim_parse_addr_ucast (struct prefix *p, p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); - + p->prefixlen = IPV4_MAX_PREFIXLEN; addr += sizeof(struct in_addr); + break; + case PIM_MSG_ADDRESS_FAMILY_IPV6: + if ((addr + sizeof(struct in6_addr)) > pastend) { + zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu", + __PRETTY_FUNCTION__, + pastend - addr, sizeof(struct in6_addr)); + return -3; + } + + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_PREFIXLEN; + memcpy(&p->u.prefix6, addr, 16); + addr += sizeof(struct in6_addr); + break; default: { @@ -706,6 +738,8 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, addr_str, src_str, ifname); } break; + case AF_INET6: + break; default: { char src_str[INET_ADDRSTRLEN]; @@ -759,8 +793,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, FREE_ADDR_LIST(*hello_option_addr_list); return -3; } - p->family = tmp.family; - p->u.prefix4 = tmp.u.prefix4; + prefix_copy(p, &tmp); listnode_add(*hello_option_addr_list, p); } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index 9c4ebc9f0f86..7e0a8a147f9e 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -80,7 +80,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, uint32_t option_value); uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, - struct list *ifconnected); + struct list *ifconnected, + int family); int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, From dba7860904ec03bf3c856efee1fae9fc06821121 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 09:01:09 -0400 Subject: [PATCH 06/10] pimd: Send v6 secondary addresses to neighbors in hello Send v6 secondary addresses to our neighbor in hello's. Additionally allow the disabling it via the cli introduced earlier. Signed-off-by: Donald Sharp --- pimd/pim_hello.c | 35 ++++++++++++++++++++++++----------- pimd/pim_hello.h | 5 ++--- pimd/pim_pim.c | 5 ++--- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index d9b04ea9526f..ee9433d7973b 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -428,15 +428,14 @@ int pim_hello_recv(struct interface *ifp, return 0; } -int pim_hello_build_tlv(const char *ifname, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, int tlv_buf_size, uint16_t holdtime, uint32_t dr_priority, uint32_t generation_id, uint16_t propagation_delay, uint16_t override_interval, - int can_disable_join_suppression, - struct list *ifconnected) + int can_disable_join_suppression) { uint8_t *curr = tlv_buf; uint8_t *pastend = tlv_buf + tlv_buf_size; @@ -454,7 +453,7 @@ int pim_hello_build_tlv(const char *ifname, if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello Holdtime option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -1; } @@ -468,7 +467,7 @@ int pim_hello_build_tlv(const char *ifname, if (!tmp) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -1; } @@ -485,7 +484,7 @@ int pim_hello_build_tlv(const char *ifname, if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello DR Priority option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -2; } @@ -498,24 +497,38 @@ int pim_hello_build_tlv(const char *ifname, if (!curr) { if (PIM_DEBUG_PIM_HELLO) { zlog_debug("%s: could not set PIM hello Generation ID option for interface %s", - __PRETTY_FUNCTION__, ifname); + __PRETTY_FUNCTION__, ifp->name); } return -3; } /* Secondary Address List */ - if (ifconnected) { + if (ifp->connected->count) { curr = pim_tlv_append_addrlist_ucast(curr, pastend, - ifconnected, + ifp->connected, AF_INET); if (!curr) { if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s", - __PRETTY_FUNCTION__, ifname); + zlog_debug("%s: could not set PIM hello v4 Secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); } return -4; } + if (pimg->send_v6_secondary) + { + curr = pim_tlv_append_addrlist_ucast(curr, + pastend, + ifp->connected, + AF_INET6); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug("%s: could not sent PIM hello v6 secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -4; + } + } } return curr - tlv_buf; diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index 3a6d3361ba3b..de5359e2c058 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -29,15 +29,14 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(const char *ifname, +int pim_hello_build_tlv(struct interface *ifname, uint8_t *tlv_buf, int tlv_buf_size, uint16_t holdtime, uint32_t dr_priority, uint32_t generation_id, uint16_t propagation_delay, uint16_t override_interval, - int can_disable_join_suppression, - struct list *ifconnected); + int can_disable_join_suppression); void pim_hello_require(struct interface *ifp); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f82687245d77..bc13e10a6117 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -629,7 +629,7 @@ static int hello_send(struct interface *ifp, listcount(ifp->connected)); } - pim_tlv_size = pim_hello_build_tlv(ifp->name, + pim_tlv_size = pim_hello_build_tlv(ifp, pim_msg + PIM_PIM_MIN_LEN, sizeof(pim_msg) - PIM_PIM_MIN_LEN, holdtime, @@ -637,8 +637,7 @@ static int hello_send(struct interface *ifp, pim_ifp->pim_generation_id, pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec, - PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options), - ifp->connected); + PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); if (pim_tlv_size < 0) { return -1; } From eeff6d3f99c8965bbb4870d9ca0f8da5f6a53e57 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 09:07:06 -0400 Subject: [PATCH 07/10] pimd: Use better 5549 resolution When we receive a v6 nexthop in v4, lookup the nbr by it's secondary address. Signed-off-by: Donald Sharp --- pimd/pim_zlookup.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f77990ab5ab8..620137b33b57 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -222,6 +222,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, for (i = 0; i < nexthop_num; ++i) { enum nexthop_types_t nexthop_type; struct pim_neighbor *nbr; + struct prefix p; nexthop_type = stream_getc(s); if (num_ifindex >= tab_size) { @@ -253,7 +254,18 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, s, 16); nexthop_tab[num_ifindex].ifindex = stream_getl (s); - nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); + + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + memcpy (&p.u.prefix6, &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, 16); + + /* + * If we are sending v6 secondary assume we receive v6 secondary + */ + if (pimg->send_v6_secondary) + nbr = pim_neighbor_find_by_secondary(if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT), &p); + else + nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); if (nbr) { nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; From 294b6d7243983270d69c85aaa8528c78a2521da5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 09:10:05 -0400 Subject: [PATCH 08/10] pimd: Receive incoming v6 addresses and place in pim_ifp list Add code to properly receive v6 addresses up from zebra and to properly place them into our interface secondary address list. Additionally cleanup some code in pim_cmd.c that was broken by these changes. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 17 +++++++------- pimd/pim_iface.c | 60 ++++++++++++++++++++++++++++++------------------ pimd/pim_iface.h | 2 +- pimd/pim_zebra.c | 22 +----------------- 4 files changed, 48 insertions(+), 53 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 66fc8185d0f3..91d870fb1edc 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -816,6 +816,7 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); if (uj) { + char pbuf[PREFIX2STR_BUFFER]; json_row = json_object_new_object(); json_object_pim_ifp_add(json_row, ifp); @@ -827,7 +828,8 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch sec_list = json_object_new_array(); for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { - json_object_array_add(sec_list, json_object_new_string(inet_ntoa(sec_addr->addr))); + json_object_array_add(sec_list, + json_object_new_string(prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER))); } json_object_object_add(json_row, "secondaryAddressList", sec_list); } @@ -918,11 +920,12 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE); } if (pim_ifp->sec_addr_list) { + char pbuf[PREFIX2STR_BUFFER]; vty_out(vty, "Address : %s (primary)%s", - inet_ntoa(ifaddr), VTY_NEWLINE); + inet_ntoa(ifaddr), VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { vty_out(vty, " %s%s", - inet_ntoa(sec_addr->addr), VTY_NEWLINE); + prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER), VTY_NEWLINE); } } else { vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); @@ -1607,13 +1610,9 @@ static void pim_show_neighbors_secondary(struct vty *vty) neigh_src_str, sizeof(neigh_src_str)); for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { - char neigh_sec_str[INET_ADDRSTRLEN]; + char neigh_sec_str[100]; - if (p->family != AF_INET) - continue; - - pim_inet4_dump("", p->u.prefix4, - neigh_sec_str, sizeof(neigh_sec_str)); + prefix2str(p, neigh_sec_str, 100); vty_out(vty, "%-9s %-15s %-15s %-15s%s", ifp->name, diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index a753cc4affc3..f038acab8f6b 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -324,12 +324,29 @@ 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; - if (ntohl(sec1->addr.s_addr) < ntohl(sec2->addr.s_addr)) + if (sec1->addr.family == AF_INET && + sec2->addr.family == AF_INET6) return -1; - if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr)) + if (sec1->addr.family == AF_INET6 && + sec2->addr.family == AF_INET) return 1; + if (sec1->addr.family == AF_INET) + { + if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr)) + return -1; + + if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr)) + return 1; + } + else + { + return memcmp (&sec1->addr.u.prefix6, + &sec2->addr.u.prefix6, + sizeof (struct in6_addr)); + } + return 0; } @@ -339,7 +356,7 @@ static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) } static struct pim_secondary_addr * -pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr) +pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr) { struct pim_secondary_addr *sec_addr; struct listnode *node; @@ -349,7 +366,7 @@ pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr) } for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (sec_addr->addr.s_addr == addr.s_addr) { + if (prefix_cmp(&sec_addr->addr, addr)) { return sec_addr; } } @@ -364,7 +381,7 @@ static void pim_sec_addr_del(struct pim_interface *pim_ifp, pim_sec_addr_free(sec_addr); } -static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr) +static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr) { int changed = 0; struct pim_secondary_addr *sec_addr; @@ -391,7 +408,7 @@ static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr) } changed = 1; - sec_addr->addr = addr; + sec_addr->addr = *addr; listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); return changed; @@ -433,10 +450,6 @@ static int pim_sec_addr_update(struct interface *ifp) 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; } @@ -446,7 +459,7 @@ static int pim_sec_addr_update(struct interface *ifp) continue; } - if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) { + if (pim_sec_addr_add(pim_ifp, p)) { changed = 1; } } @@ -571,12 +584,15 @@ void pim_if_addr_add(struct connected *ifc) detect_address_change(ifp, 0, __PRETTY_FUNCTION__); + if (ifc->address->family != AF_INET) + return; + 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); + ifaddr); if (!igmp) { /* if addr new, add IGMP socket */ pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); @@ -675,14 +691,17 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) ifp = ifc->ifp; zassert(ifp); + if (ifc->address->family != AF_INET) + return; + 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"); + __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__); @@ -709,12 +728,9 @@ void pim_if_addr_add_all(struct interface *ifp) struct prefix *p = ifc->address; if (p->family != AF_INET) - { - v6_addrs++; - continue; - } - - v4_addrs++; + v6_addrs++; + else + v4_addrs++; pim_if_addr_add(ifc); } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 8d332c70b08a..f4d7518d7afe 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -69,7 +69,7 @@ enum pim_secondary_addr_flags { }; struct pim_secondary_addr { - struct in_addr addr; + struct prefix addr; enum pim_secondary_addr_flags flags; }; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index d02560bfc2d6..bbee95bddd7d 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -257,31 +257,11 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient, #endif } - if (p->family != AF_INET) - { - struct listnode *cnode; - struct connected *conn; - int v4addrs = 0; - - for (ALL_LIST_ELEMENTS_RO (c->ifp->connected, cnode, conn)) - { - if (conn->address->family == AF_INET) - v4addrs++; - } - if (!v4addrs && pim_ifp) - { - pim_ifp->primary_address = pim_find_primary_addr (c->ifp); - pim_if_addr_add_all (c->ifp); - pim_if_add_vif (c->ifp); - } - return 0; - } - if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { /* trying to add primary address */ struct in_addr primary_addr = pim_find_primary_addr(c->ifp); - if (primary_addr.s_addr != p->u.prefix4.s_addr) { + if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) { if (PIM_DEBUG_ZEBRA) { /* but we had a primary address already */ From 2e725ad140e14ed03195028881be65c2cefc079a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 10:22:00 -0400 Subject: [PATCH 09/10] pimd: Fix header to be more descriptive of what it is doing Signed-off-by: Donald Sharp --- pimd/pim_hello.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index de5359e2c058..1f8b348bd776 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -29,7 +29,7 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(struct interface *ifname, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, int tlv_buf_size, uint16_t holdtime, uint32_t dr_priority, From 4390fb9991e78d759c25ffc23be378c8b9242614 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 6 Apr 2017 17:57:24 -0400 Subject: [PATCH 10/10] pimd: Fix various sizeof and buffer length issues Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 12 ++++++++---- pimd/pim_tlv.c | 2 +- pimd/pim_zlookup.c | 8 ++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 627971d3f977..0478dc1b4815 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -830,7 +830,9 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch sec_list = json_object_new_array(); for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { json_object_array_add(sec_list, - json_object_new_string(prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER))); + json_object_new_string(prefix2str(&sec_addr->addr, + pbuf, + sizeof(pbuf)))); } json_object_object_add(json_row, "secondaryAddressList", sec_list); } @@ -926,7 +928,9 @@ static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_ch inet_ntoa(ifaddr), VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { vty_out(vty, " %s%s", - prefix2str(&sec_addr->addr, pbuf, PREFIX2STR_BUFFER), VTY_NEWLINE); + prefix2str(&sec_addr->addr, + pbuf, + sizeof(pbuf)), VTY_NEWLINE); } } else { vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE); @@ -1611,9 +1615,9 @@ static void pim_show_neighbors_secondary(struct vty *vty) neigh_src_str, sizeof(neigh_src_str)); for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { - char neigh_sec_str[100]; + char neigh_sec_str[PREFIX2STR_BUFFER]; - prefix2str(p, neigh_sec_str, 100); + prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str)); vty_out(vty, "%-9s %-15s %-15s %-15s%s", ifp->name, diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 1d58ce3ac63f..259ed44c714d 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -523,7 +523,7 @@ pim_parse_addr_ucast (struct prefix *p, p->family = AF_INET6; p->prefixlen = IPV6_MAX_PREFIXLEN; - memcpy(&p->u.prefix6, addr, 16); + memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); addr += sizeof(struct in6_addr); break; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 620137b33b57..27bd1370438a 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -252,12 +252,16 @@ static int zclient_read_nexthop(struct zclient *zlookup, break; case NEXTHOP_TYPE_IPV6_IFINDEX: nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; - stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, s, 16); + stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + s, + sizeof(struct in6_addr)); nexthop_tab[num_ifindex].ifindex = stream_getl (s); p.family = AF_INET6; p.prefixlen = IPV6_MAX_PREFIXLEN; - memcpy (&p.u.prefix6, &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, 16); + memcpy (&p.u.prefix6, + &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + sizeof(struct in6_addr)); /* * If we are sending v6 secondary assume we receive v6 secondary