From 30b277e1588ef0d0bce37fb9b3d7edbc6fa2e974 Mon Sep 17 00:00:00 2001 From: plsaranya Date: Mon, 7 Mar 2022 10:08:31 +0530 Subject: [PATCH] pim6d: Register message send handling Register and Null register send handling In IPv6 PIM Null Register message if dummy PIM Header is included as data, this dummy PIM header checksum needs to be valuated Signed-off-by: plsaranya --- pimd/pim6_stubs.c | 37 ------------ pimd/pim_register.c | 135 ++++++++++++++++++++++++++++++++++++++------ pimd/subdir.am | 2 +- 3 files changed, 120 insertions(+), 54 deletions(-) diff --git a/pimd/pim6_stubs.c b/pimd/pim6_stubs.c index cf61685fb1..f799f04f33 100644 --- a/pimd/pim6_stubs.c +++ b/pimd/pim6_stubs.c @@ -37,21 +37,6 @@ void pim_nht_bsr_del(struct pim_instance *pim, struct in_addr addr) { } -/* - * PIM register - */ -void pim_register_join(struct pim_upstream *up) -{ -} - -void pim_null_register_send(struct pim_upstream *up) -{ -} - -void pim_reg_del_on_couldreg_fail(struct interface *ifp) -{ -} - bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) { return false; @@ -80,25 +65,3 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, { return 0; } - -void pim_register_send(const uint8_t *buf, int buf_size, pim_addr src, - struct pim_rpf *rpg, int null_register, - struct pim_upstream *up) -{ -} - -void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, pim_addr src, - pim_addr originator) -{ -} - -int pim_register_recv(struct interface *ifp, pim_addr dest_addr, - pim_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size) -{ - return 0; -} - -int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size) -{ - return 0; -} diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 45bcad3c26..fef5339749 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -44,6 +44,7 @@ #include "pim_util.h" #include "pim_ssm.h" #include "pim_vxlan.h" +#include "pim_addr.h" struct thread *send_test_packet_timer = NULL; @@ -64,8 +65,8 @@ void pim_register_join(struct pim_upstream *up) pim_vxlan_update_sg_reg_state(pim, up, true); } -void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, - struct in_addr src, struct in_addr originator) +void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, pim_addr src, + pim_addr originator) { struct pim_interface *pinfo; unsigned char buffer[10000]; @@ -74,7 +75,7 @@ void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, uint8_t *b1; if (PIM_DEBUG_PIM_REG) { - zlog_debug("Sending Register stop for %pSG to %pI4 on %s", sg, + zlog_debug("Sending Register stop for %pSG to %pPA on %s", sg, &originator, ifp->name); } @@ -218,7 +219,7 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size) return 0; } -void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, +void pim_register_send(const uint8_t *buf, int buf_size, pim_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up) { @@ -226,11 +227,11 @@ void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, unsigned char *b1; struct pim_interface *pinfo; struct interface *ifp; + pim_addr dst = pim_addr_from_prefix(&rpg->rpf_addr); if (PIM_DEBUG_PIM_REG) { - zlog_debug("Sending %s %sRegister Packet to %pI4", up->sg_str, - null_register ? "NULL " : "", - &rpg->rpf_addr.u.prefix4); + zlog_debug("Sending %s %sRegister Packet to %pPA", up->sg_str, + null_register ? "NULL " : "", &dst); } ifp = rpg->source_nexthop.interface; @@ -250,9 +251,9 @@ void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, } if (PIM_DEBUG_PIM_REG) { - zlog_debug("%s: Sending %s %sRegister Packet to %pI4 on %s", + zlog_debug("%s: Sending %s %sRegister Packet to %pPA on %s", __func__, up->sg_str, null_register ? "NULL " : "", - &rpg->rpf_addr.u.prefix4, ifp->name); + &dst, ifp->name); } memset(buffer, 0, 10000); @@ -262,14 +263,13 @@ void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, memcpy(b1, (const unsigned char *)buf, buf_size); - pim_msg_build_header(src, rpg->rpf_addr.u.prefix4, buffer, - buf_size + PIM_MSG_REGISTER_LEN, + pim_msg_build_header(src, dst, buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER, false); ++pinfo->pim_ifstat_reg_send; - if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr.u.prefix4, - buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { + if (pim_msg_send(pinfo->pim_sock_fd, src, dst, buffer, + buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { if (PIM_DEBUG_PIM_TRACE) { zlog_debug( "%s: could not send PIM register message on interface %s", @@ -279,12 +279,13 @@ void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, } } +#if PIM_IPV == 4 void pim_null_register_send(struct pim_upstream *up) { struct ip ip_hdr; struct pim_interface *pim_ifp; struct pim_rpf *rpg; - struct in_addr src; + pim_addr src; pim_ifp = up->rpf.source_nexthop.interface->info; if (!pim_ifp) { @@ -323,9 +324,71 @@ void pim_null_register_send(struct pim_upstream *up) return; } } - pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), - src, rpg, 1, up); + pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), src, rpg, 1, + up); } +#else +void pim_null_register_send(struct pim_upstream *up) +{ + struct ip6_hdr ip6_hdr; + struct pim_msg_header pim_msg_header; + struct pim_interface *pim_ifp; + struct pim_rpf *rpg; + pim_addr src; + unsigned char buffer[sizeof(ip6_hdr) + sizeof(pim_msg_header)]; + struct ipv6_ph ph; + + pim_ifp = up->rpf.source_nexthop.interface->info; + if (!pim_ifp) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "Cannot send null-register for %s no valid iif", + up->sg_str); + return; + } + + rpg = RP(pim_ifp->pim, up->sg.grp); + if (!rpg) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "Cannot send null-register for %s no RPF to the RP", + up->sg_str); + return; + } + + memset(&ip6_hdr, 0, sizeof(ip6_hdr)); + ip6_hdr.ip6_nxt = PIM_IP_PROTO_PIM; + ip6_hdr.ip6_plen = PIM_MSG_HEADER_LEN; + ip6_hdr.ip6_vfc = 6 << 4; + ip6_hdr.ip6_hlim = MAXTTL; + ip6_hdr.ip6_src = up->sg.src; + ip6_hdr.ip6_dst = up->sg.grp; + + memset(buffer, 0, (sizeof(ip6_hdr) + sizeof(pim_msg_header))); + memcpy(buffer, &ip6_hdr, sizeof(ip6_hdr)); + + pim_msg_header.ver = 0; + pim_msg_header.type = 0; + pim_msg_header.reserved = 0; + + pim_msg_header.checksum = 0; + + ph.src = up->sg.src; + ph.dst = up->sg.grp; + ph.ulpl = htonl(PIM_MSG_HEADER_LEN); + ph.next_hdr = IPPROTO_PIM; + pim_msg_header.checksum = + in_cksum_with_ph6(&ph, &pim_msg_header, PIM_MSG_HEADER_LEN); + + memcpy(buffer + sizeof(ip6_hdr), &pim_msg_header, PIM_MSG_HEADER_LEN); + + + src = pim_ifp->primary_address; + pim_register_send((uint8_t *)buffer, + sizeof(ip6_hdr) + PIM_MSG_HEADER_LEN, src, rpg, 1, + up); +} +#endif /* * 4.4.2 Receiving Register Messages at the RP @@ -425,6 +488,46 @@ int pim_register_recv(struct interface *ifp, pim_addr dest_addr, memset(&sg, 0, sizeof(sg)); sg = pim_sgaddr_from_iphdr(ip_hdr); +#if PIM_IPV == 6 + /* + * According to RFC section 4.9.3, If Dummy PIM Header is included + * in NULL Register as a payload there would be two PIM headers. + * The inner PIM Header's checksum field should also be validated + * in addition to the outer PIM Header's checksum. Validation of + * inner PIM header checksum is done here. + */ + if ((*bits & PIM_REGISTER_NR_BIT) && + ((tlv_buf_size - PIM_MSG_REGISTER_BIT_RESERVED_LEN) > + (int)sizeof(struct ip6_hdr))) { + uint16_t computed_checksum; + uint16_t received_checksum; + struct ipv6_ph ph; + struct pim_msg_header *header; + + header = (struct pim_msg_header + *)(tlv_buf + + PIM_MSG_REGISTER_BIT_RESERVED_LEN + + sizeof(struct ip6_hdr)); + ph.src = sg.src; + ph.dst = sg.grp; + ph.ulpl = htonl(PIM_MSG_HEADER_LEN); + ph.next_hdr = IPPROTO_PIM; + + received_checksum = header->checksum; + + header->checksum = 0; + computed_checksum = in_cksum_with_ph6( + &ph, header, htonl(PIM_MSG_HEADER_LEN)); + + if (computed_checksum != received_checksum) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring Null Register message%pSG from %pPA due to bad checksum in Encapsulated dummy PIM header", + &sg, &src_addr); + return 0; + } + } +#endif i_am_rp = I_am_RP(pim, sg.grp); if (PIM_DEBUG_PIM_REG) diff --git a/pimd/subdir.am b/pimd/subdir.am index 41fc6dc632..9dd6961d92 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -57,6 +57,7 @@ pim_common = \ pimd/pim_zebra.c \ pimd/pim_zlookup.c \ pimd/pim_vxlan.c \ + pimd/pim_register.c \ pimd/pimd.c \ # end @@ -74,7 +75,6 @@ pimd_pimd_SOURCES = \ pimd/pim_msdp.c \ pimd/pim_msdp_packet.c \ pimd/pim_msdp_socket.c \ - pimd/pim_register.c \ pimd/pim_signals.c \ pimd/pim_zpthread.c \ pimd/pim_mroute_msg.c \ -- 2.39.5