3 * Copyright (C) 2015 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
32 #include "pim_mroute.h"
33 #include "pim_iface.h"
38 #include "pim_register.h"
39 #include "pim_upstream.h"
43 #include "pim_zebra.h"
48 struct thread
*send_test_packet_timer
= NULL
;
51 pim_register_join (struct pim_upstream
*up
)
53 if (pim_is_grp_ssm (up
->sg
.grp
))
55 if (PIM_DEBUG_PIM_EVENTS
)
56 zlog_debug ("%s register setup skipped as group is SSM", up
->sg_str
);
60 pim_channel_add_oif (up
->channel_oil
, pim_regiface
, PIM_OIF_FLAG_PROTO_PIM
);
61 up
->reg_state
= PIM_REG_JOIN
;
65 pim_register_stop_send (struct interface
*ifp
, struct prefix_sg
*sg
,
66 struct in_addr src
, struct in_addr originator
)
68 struct pim_interface
*pinfo
;
69 unsigned char buffer
[10000];
70 unsigned int b1length
= 0;
75 if (PIM_DEBUG_PIM_REG
)
77 zlog_debug ("Sending Register stop for %s to %s on %s",
78 pim_str_sg_dump (sg
), inet_ntoa(originator
), ifp
->name
);
81 memset (buffer
, 0, 10000);
82 b1
= (uint8_t *)buffer
+ PIM_MSG_REGISTER_STOP_LEN
;
84 length
= pim_encode_addr_group (b1
, AFI_IP
, 0, 0, sg
->grp
);
89 p
.u
.prefix4
= sg
->src
;
91 length
= pim_encode_addr_ucast (b1
, &p
);
94 pim_msg_build_header (buffer
, b1length
+ PIM_MSG_REGISTER_STOP_LEN
, PIM_MSG_TYPE_REG_STOP
);
96 pinfo
= (struct pim_interface
*)ifp
->info
;
99 if (PIM_DEBUG_PIM_TRACE
)
100 zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__
);
103 if (pim_msg_send (pinfo
->pim_sock_fd
, src
, originator
,
104 buffer
, b1length
+ PIM_MSG_REGISTER_STOP_LEN
,
107 if (PIM_DEBUG_PIM_TRACE
)
109 zlog_debug ("%s: could not send PIM register stop message on interface %s",
110 __PRETTY_FUNCTION__
, ifp
->name
);
113 ++pinfo
->pim_ifstat_reg_stop_send
;
117 pim_register_stop_recv (uint8_t *buf
, int buf_size
)
119 struct pim_upstream
*upstream
= NULL
;
120 struct prefix source
;
124 memset (&sg
, 0, sizeof (struct prefix_sg
));
125 l
= pim_parse_addr_group (&sg
, buf
, buf_size
);
128 pim_parse_addr_ucast (&source
, buf
, buf_size
);
129 sg
.src
= source
.u
.prefix4
;
131 upstream
= pim_upstream_find (&sg
);
137 if (PIM_DEBUG_PIM_REG
)
138 zlog_debug ("Received Register stop for %s",
141 switch (upstream
->reg_state
)
148 upstream
->reg_state
= PIM_REG_PRUNE
;
149 pim_channel_del_oif (upstream
->channel_oil
, pim_regiface
, PIM_OIF_FLAG_PROTO_PIM
);
150 pim_upstream_start_register_stop_timer (upstream
, 0);
152 case PIM_REG_JOIN_PENDING
:
153 upstream
->reg_state
= PIM_REG_PRUNE
;
154 pim_upstream_start_register_stop_timer (upstream
, 0);
163 pim_register_send (const uint8_t *buf
, int buf_size
, struct in_addr src
, struct pim_rpf
*rpg
, int null_register
, struct pim_upstream
*up
)
165 unsigned char buffer
[10000];
167 struct pim_interface
*pinfo
;
168 struct interface
*ifp
;
170 if (PIM_DEBUG_PIM_REG
)
172 zlog_debug ("Sending %s %sRegister Packet to %s",
173 up
->sg_str
, null_register
? "NULL " : "",
174 inet_ntoa (rpg
->rpf_addr
.u
.prefix4
));
177 ifp
= rpg
->source_nexthop
.interface
;
180 if (PIM_DEBUG_PIM_REG
)
181 zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__
);
184 pinfo
= (struct pim_interface
*)ifp
->info
;
186 if (PIM_DEBUG_PIM_REG
)
187 zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__
, ifp
->name
);
191 if (PIM_DEBUG_PIM_REG
)
193 char rp_str
[INET_ADDRSTRLEN
];
194 strncpy (rp_str
, inet_ntoa (rpg
->rpf_addr
.u
.prefix4
), INET_ADDRSTRLEN
-1);
195 zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s",
196 __PRETTY_FUNCTION__
, up
->sg_str
,
197 null_register
? "NULL " : "", rp_str
, ifp
->name
);
200 memset(buffer
, 0, 10000);
201 b1
= buffer
+ PIM_MSG_HEADER_LEN
;
202 *b1
|= null_register
<< 6;
203 b1
= buffer
+ PIM_MSG_REGISTER_LEN
;
205 memcpy(b1
, (const unsigned char *)buf
, buf_size
);
207 pim_msg_build_header(buffer
, buf_size
+ PIM_MSG_REGISTER_LEN
, PIM_MSG_TYPE_REGISTER
);
209 ++pinfo
->pim_ifstat_reg_send
;
211 if (pim_msg_send(pinfo
->pim_sock_fd
,
213 rpg
->rpf_addr
.u
.prefix4
,
215 buf_size
+ PIM_MSG_REGISTER_LEN
,
217 if (PIM_DEBUG_PIM_TRACE
) {
218 zlog_debug("%s: could not send PIM register message on interface %s",
219 __PRETTY_FUNCTION__
, ifp
->name
);
226 * 4.4.2 Receiving Register Messages at the RP
228 * When an RP receives a Register message, the course of action is
229 * decided according to the following pseudocode:
231 * packet_arrives_on_rp_tunnel( pkt ) {
232 * if( outer.dst is not one of my addresses ) {
233 * drop the packet silently.
234 * # Note: this may be a spoofing attempt
236 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
237 * sentRegisterStop = FALSE;
238 * if ( register.borderbit == TRUE ) {
239 * if ( PMBR(S,G) == unknown ) {
240 * PMBR(S,G) = outer.src
241 * } else if ( outer.src != PMBR(S,G) ) {
242 * send Register-Stop(S,G) to outer.src
243 * drop the packet silently.
246 * if ( SPTbit(S,G) OR
247 * ( SwitchToSptDesired(S,G) AND
248 * ( inherited_olist(S,G) == NULL ))) {
249 * send Register-Stop(S,G) to outer.src
250 * sentRegisterStop = TRUE;
252 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
253 * if ( sentRegisterStop == TRUE ) {
254 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
256 * set KeepaliveTimer(S,G) to Keepalive_Period;
259 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
260 * decapsulate and forward the inner packet to
261 * inherited_olist(S,G,rpt) # Note (+)
264 * send Register-Stop(S,G) to outer.src
270 pim_register_recv (struct interface
*ifp
,
271 struct in_addr dest_addr
,
272 struct in_addr src_addr
,
273 uint8_t *tlv_buf
, int tlv_buf_size
)
275 int sentRegisterStop
= 0;
280 struct pim_interface
*pim_ifp
= NULL
;
282 #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
283 ip_hdr
= (struct ip
*)(tlv_buf
+ PIM_MSG_REGISTER_BIT_RESERVED_LEN
);
285 if (!pim_rp_check_is_my_ip_address (ip_hdr
->ip_dst
, dest_addr
)) {
286 if (PIM_DEBUG_PIM_REG
) {
287 char dest
[INET_ADDRSTRLEN
];
289 pim_inet4_dump ("<dst?>", dest_addr
, dest
, sizeof(dest
));
290 zlog_debug ("%s: Received Register message for %s that I do not own", __func__
,
298 ++pim_ifp
->pim_ifstat_reg_recv
;
301 * Please note this is not drawn to get the correct bit/data size
303 * The entirety of the REGISTER packet looks like this:
304 * -------------------------------------------------------------
305 * | Ver | Type | Reserved | Checksum |
306 * |-----------------------------------------------------------|
308 * |-----------------------------------------------------------|
311 * | Packet |--------------------------------------------------|
316 * tlv_buf when received from the caller points at the B bit
317 * We need to know the inner source and dest
319 bits
= (uint32_t *)tlv_buf
;
322 * tlv_buf points to the start of the |B|N|... Reserved
323 * Line above. So we need to add 4 bytes to get to the
324 * start of the actual Encapsulated data.
326 memset (&sg
, 0, sizeof (struct prefix_sg
));
327 sg
.src
= ip_hdr
->ip_src
;
328 sg
.grp
= ip_hdr
->ip_dst
;
330 i_am_rp
= I_am_RP (sg
.grp
);
332 if (PIM_DEBUG_PIM_REG
)
334 char src_str
[INET_ADDRSTRLEN
];
336 pim_inet4_dump ("<src?>", src_addr
, src_str
, sizeof (src_str
));
337 zlog_debug ("Received Register message(%s) from %s on %s, rp: %d",
338 pim_str_sg_dump (&sg
), src_str
, ifp
->name
, i_am_rp
);
341 if (i_am_rp
&& (dest_addr
.s_addr
== ((RP (sg
.grp
))->rpf_addr
.u
.prefix4
.s_addr
))) {
342 sentRegisterStop
= 0;
344 if (*bits
& PIM_REGISTER_BORDER_BIT
) {
345 struct in_addr pimbr
= pim_br_get_pmbr (&sg
);
346 if (PIM_DEBUG_PIM_PACKETS
)
347 zlog_debug("%s: Received Register message with Border bit set", __func__
);
349 if (pimbr
.s_addr
== pim_br_unknown
.s_addr
)
350 pim_br_set_pmbr(&sg
, src_addr
);
351 else if (src_addr
.s_addr
!= pimbr
.s_addr
) {
352 pim_register_stop_send (ifp
, &sg
, dest_addr
, src_addr
);
353 if (PIM_DEBUG_PIM_PACKETS
)
354 zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet",
356 /* Drop Packet Silently */
361 struct pim_upstream
*upstream
= pim_upstream_find (&sg
);
363 * If we don't have a place to send ignore the packet
367 upstream
= pim_upstream_add (&sg
, ifp
,
368 PIM_UPSTREAM_FLAG_MASK_SRC_STREAM
,
369 __PRETTY_FUNCTION__
);
372 zlog_warn ("Failure to create upstream state");
376 upstream
->upstream_register
= src_addr
;
379 if ((upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
) ||
380 ((SwitchToSptDesired(&sg
)) &&
381 pim_upstream_inherited_olist (upstream
) == 0)) {
382 //pim_scan_individual_oil (upstream->channel_oil);
383 pim_register_stop_send (ifp
, &sg
, dest_addr
, src_addr
);
384 sentRegisterStop
= 1;
386 if (PIM_DEBUG_PIM_REG
)
387 zlog_debug ("(%s) sptbit: %d", upstream
->sg_str
, upstream
->sptbit
);
389 if ((upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
) ||
390 (SwitchToSptDesired(&sg
))) {
391 if (sentRegisterStop
) {
392 pim_upstream_keep_alive_timer_start (upstream
, qpim_rp_keep_alive_time
);
394 pim_upstream_keep_alive_timer_start (upstream
, qpim_keep_alive_time
);
398 if (!(upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
) &&
399 !(*bits
& PIM_REGISTER_NR_BIT
))
401 //decapsulate and forward the iner packet to
402 //inherited_olist(S,G,rpt)
403 // This is taken care of by the kernel for us
405 pim_upstream_msdp_reg_timer_start(upstream
);
407 if (PIM_DEBUG_PIM_REG
)
410 zlog_debug ("Received Register packet for %s, Rejecting packet because I am not the RP configured for group",
411 pim_str_sg_dump (&sg
));
413 zlog_debug ("Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP",
414 pim_str_sg_dump (&sg
));
416 pim_register_stop_send (ifp
, &sg
, dest_addr
, src_addr
);