From: Donald Sharp Date: Mon, 22 Aug 2016 13:10:05 +0000 (-0400) Subject: pimd: Fix pim to use correct src address for packets X-Git-Tag: frr-3.0-branchpoint~64^2~10^2~274 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=4df01a4e66fec6472d9d0b89d199654eb5c6e8bd;p=mirror%2Ffrr.git pimd: Fix pim to use correct src address for packets When sending register packets to the RP from the FHR we should be using the ip address of the incoming interface that received the mcast packet. Ticket: CM-12445 Signed-off-by: Donald Sharp --- diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 4443e4459a..1add2ebb00 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -474,6 +474,7 @@ static int pim_assert_do(struct pim_ifchannel *ch, } if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 80e77ecb32..c7d54d3c04 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -434,6 +434,7 @@ int pim_joinprune_send(struct interface *ifp, return pim_msg_size; if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index a17a8b1006..65696f6d33 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -218,7 +218,8 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) * If we've received a register suppress */ if (!up->t_rs_timer) - pim_register_send((uint8_t *)buf + sizeof(struct ip), ntohs (ip_hdr->ip_len), rpg, 0); + pim_register_send((uint8_t *)buf + sizeof(struct ip), ntohs (ip_hdr->ip_len), + pim_ifp->primary_address, rpg, 0); return 0; } @@ -357,9 +358,12 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) if (!up->fhr) { struct pim_nexthop source; + struct pim_rpf *rpf = RP (sg.grp); + pim_ifp = rpf->source_nexthop.interface->info; + //No if channel, but upstream we are at the RP. pim_nexthop_lookup (&source, up->upstream_register); - pim_register_stop_send(source.interface, &sg, up->upstream_register); + pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); //Send S bit down the join. up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; } diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 382c9bc46d..f58e326d16 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -480,7 +480,10 @@ void pim_sock_reset(struct interface *ifp) pim_ifstat_reset(ifp); } +static uint16_t ip_id = 0; + int pim_msg_send(int fd, + struct in_addr src, struct in_addr dst, uint8_t *pim_msg, int pim_msg_size, @@ -489,6 +492,25 @@ int pim_msg_send(int fd, ssize_t sent; struct sockaddr_in to; socklen_t tolen; + unsigned char buffer[3000]; + unsigned char *msg_start; + struct ip *ip; + + memset (buffer, 0, 3000); + int sendlen = sizeof (struct ip) + pim_msg_size; + + msg_start = buffer + sizeof (struct ip); + memcpy (msg_start, pim_msg, pim_msg_size); + + ip = (struct ip *)buffer; + ip->ip_id = htons (++ip_id); + ip->ip_hl = 5; + ip->ip_v = 4; + ip->ip_p = PIM_IP_PROTO_PIM; + ip->ip_src = src; + ip->ip_dst = dst; + ip->ip_ttl = MAXTTL; + ip->ip_len = htons (sendlen); if (PIM_DEBUG_PIM_PACKETS) { char dst_str[100]; @@ -508,9 +530,9 @@ int pim_msg_send(int fd, pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); } - sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT, + sent = sendto(fd, buffer, sendlen, MSG_DONTWAIT, (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) pim_msg_size) { + if (sent != (ssize_t) sendlen) { char dst_str[100]; pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); if (sent < 0) { @@ -577,6 +599,7 @@ static int hello_send(struct interface *ifp, PIM_MSG_TYPE_HELLO); if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, qpim_all_pim_routers_addr, pim_msg, pim_msg_size, @@ -759,6 +782,8 @@ int pim_sock_add(struct interface *ifp) return -2; } + pim_socket_ip_hdr (pim_ifp->pim_sock_fd); + pim_ifp->t_pim_sock_read = NULL; pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 01c9044a26..fad572a125 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -70,6 +70,7 @@ void pim_hello_restart_triggered(struct interface *ifp); int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len); int pim_msg_send(int fd, + struct in_addr src, struct in_addr dst, uint8_t *pim_msg, int pim_msg_size, diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 4cc4a2703c..bd41f1f4f0 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -46,7 +46,7 @@ struct thread *send_test_packet_timer = NULL; void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, - struct in_addr originator) + struct in_addr src, struct in_addr originator) { struct pim_interface *pinfo; unsigned char buffer[3000]; @@ -83,7 +83,7 @@ pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__); return; } - if (pim_msg_send (pinfo->pim_sock_fd, originator, + if (pim_msg_send (pinfo->pim_sock_fd, src, originator, buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, ifp->name)) { @@ -145,7 +145,7 @@ pim_register_stop_recv (uint8_t *buf, int buf_size) } void -pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register) +pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register) { unsigned char buffer[3000]; unsigned char *b1; @@ -176,6 +176,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int nu pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); if (pim_msg_send(pinfo->pim_sock_fd, + src, rpg->rpf_addr, buffer, buf_size + PIM_MSG_REGISTER_LEN, @@ -306,7 +307,7 @@ pim_register_recv (struct interface *ifp, if (pimbr.s_addr == pim_br_unknown.s_addr) pim_br_set_pmbr(&sg, src_addr); else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send (ifp, &sg, src_addr); + pim_register_stop_send (ifp, &sg, dest_addr, src_addr); if (PIM_DEBUG_PIM_PACKETS) zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", __func__, "Sender"); @@ -338,7 +339,7 @@ pim_register_recv (struct interface *ifp, ((SwitchToSptDesired(&sg)) && pim_upstream_inherited_olist (upstream) == 0)) { //pim_scan_individual_oil (upstream->channel_oil); - pim_register_stop_send (ifp, &sg, src_addr); + pim_register_stop_send (ifp, &sg, dest_addr, src_addr); sentRegisterStop = 1; } @@ -359,7 +360,7 @@ pim_register_recv (struct interface *ifp, // This is taken care of by the kernel for us } } else { - pim_register_stop_send (ifp, &sg, src_addr); + pim_register_stop_send (ifp, &sg, dest_addr, src_addr); } return 1; diff --git a/pimd/pim_register.h b/pimd/pim_register.h index ce2e052104..4200c5e269 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -42,7 +42,7 @@ int pim_register_recv (struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -void pim_register_send (const uint8_t *buf, int buf_size, struct pim_rpf *rpg, int null_register); -void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr originator); +void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register); +void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 68c773d0c8..034878d20d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -932,6 +932,7 @@ pim_upstream_state2str (enum pim_upstream_state join_state) static int pim_upstream_register_stop_timer (struct thread *t) { + struct pim_interface *pim_ifp; struct pim_upstream *up; struct pim_rpf *rpg; struct ip ip_hdr; @@ -956,6 +957,7 @@ pim_upstream_register_stop_timer (struct thread *t) case PIM_UPSTREAM_JOINED: break; case PIM_UPSTREAM_PRUNE: + pim_ifp = up->rpf.source_nexthop.interface->info; up->join_state = PIM_UPSTREAM_JOIN_PENDING; pim_upstream_start_register_stop_timer (up, 1); @@ -968,7 +970,8 @@ pim_upstream_register_stop_timer (struct thread *t) ip_hdr.ip_dst = up->sg.grp; ip_hdr.ip_len = htons (20); // checksum is broken - pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), rpg, 1); + pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), + pim_ifp->primary_address, rpg, 1); break; default: break;