]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Fix pim to use correct src address for packets
authorDonald Sharp <sharpd@cumulusnetwroks.com>
Mon, 22 Aug 2016 13:10:05 +0000 (09:10 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Dec 2016 01:26:07 +0000 (20:26 -0500)
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 <sharpd@cumulusnetworks.com>
pimd/pim_assert.c
pimd/pim_join.c
pimd/pim_mroute.c
pimd/pim_pim.c
pimd/pim_pim.h
pimd/pim_register.c
pimd/pim_register.h
pimd/pim_upstream.c

index 4443e4459ab8d0555716d698aae4fe26cfd9a8c8..1add2ebb009ca7caad4609430227d49969aa2e1a 100644 (file)
@@ -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,
index 80e77ecb3201143bdba70d5e754bc3632f1363e2..c7d54d3c04c8be7b5dfe08a3b9cb55a676e90903 100644 (file)
@@ -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,
index a17a8b1006669863a69255f2fceb78ea88e1fcb0..65696f6d33c536818307b51f6a12d9bb433dc6ec 100644 (file)
@@ -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;
        }
index 382c9bc46db9b8ee3bbbab9f996163ae7373936f..f58e326d1669a328a69ab819a6e6c8d4ca2168d7 100644 (file)
@@ -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, 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();
 
index 01c9044a26b2a02d7f561d4a04df7a4871461302..fad572a1257271164e3415368f3448b2f101b29e 100644 (file)
@@ -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,
index 4cc4a2703c8fe7d081d7fa2e14c82fba370e50ac..bd41f1f4f07771464f9aa1ee4987def5390319e7 100644 (file)
@@ -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;
index ce2e052104b89f8460f59f9cdd93a9ff6f22cae3..4200c5e269f0f3d5a3a9ff30a67c22447cf9994f 100644 (file)
@@ -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
index 68c773d0c87652cf1c8f43210cdbe0ce7fcc709b..034878d20da829c5f5a8c19363bd5043c73db24a 100644 (file)
@@ -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;