]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_register.c
Merge remote-tracking branch 'origin/stable/3.0'
[mirror_frr.git] / pimd / pim_register.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2015 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
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.
10 *
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.
15 *
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,
19 * MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23
24 #include "log.h"
25 #include "if.h"
26 #include "thread.h"
27 #include "prefix.h"
28 #include "vty.h"
29 #include "plist.h"
30
31 #include "pimd.h"
32 #include "pim_mroute.h"
33 #include "pim_iface.h"
34 #include "pim_msg.h"
35 #include "pim_pim.h"
36 #include "pim_str.h"
37 #include "pim_rp.h"
38 #include "pim_register.h"
39 #include "pim_upstream.h"
40 #include "pim_br.h"
41 #include "pim_rpf.h"
42 #include "pim_oil.h"
43 #include "pim_zebra.h"
44 #include "pim_join.h"
45 #include "pim_util.h"
46 #include "pim_ssm.h"
47
48 struct thread *send_test_packet_timer = NULL;
49
50 void
51 pim_register_join (struct pim_upstream *up)
52 {
53 if (pim_is_grp_ssm (up->sg.grp))
54 {
55 if (PIM_DEBUG_PIM_EVENTS)
56 zlog_debug ("%s register setup skipped as group is SSM", up->sg_str);
57 return;
58 }
59
60 pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
61 up->reg_state = PIM_REG_JOIN;
62 }
63
64 void
65 pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg,
66 struct in_addr src, struct in_addr originator)
67 {
68 struct pim_interface *pinfo;
69 unsigned char buffer[10000];
70 unsigned int b1length = 0;
71 unsigned int length;
72 uint8_t *b1;
73 struct prefix p;
74
75 if (PIM_DEBUG_PIM_REG)
76 {
77 zlog_debug ("Sending Register stop for %s to %s on %s",
78 pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name);
79 }
80
81 memset (buffer, 0, 10000);
82 b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN;
83
84 length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp);
85 b1length += length;
86 b1 += length;
87
88 p.family = AF_INET;
89 p.u.prefix4 = sg->src;
90 p.prefixlen = 32;
91 length = pim_encode_addr_ucast (b1, &p);
92 b1length += length;
93
94 pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP);
95
96 pinfo = (struct pim_interface *)ifp->info;
97 if (!pinfo)
98 {
99 if (PIM_DEBUG_PIM_TRACE)
100 zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__);
101 return;
102 }
103 if (pim_msg_send (pinfo->pim_sock_fd, src, originator,
104 buffer, b1length + PIM_MSG_REGISTER_STOP_LEN,
105 ifp->name))
106 {
107 if (PIM_DEBUG_PIM_TRACE)
108 {
109 zlog_debug ("%s: could not send PIM register stop message on interface %s",
110 __PRETTY_FUNCTION__, ifp->name);
111 }
112 }
113 ++pinfo->pim_ifstat_reg_stop_send;
114 }
115
116 int
117 pim_register_stop_recv (uint8_t *buf, int buf_size)
118 {
119 struct pim_upstream *upstream = NULL;
120 struct prefix source;
121 struct prefix_sg sg;
122 int l;
123
124 memset (&sg, 0, sizeof (struct prefix_sg));
125 l = pim_parse_addr_group (&sg, buf, buf_size);
126 buf += l;
127 buf_size -= l;
128 pim_parse_addr_ucast (&source, buf, buf_size);
129 sg.src = source.u.prefix4;
130
131 upstream = pim_upstream_find (&sg);
132 if (!upstream)
133 {
134 return 0;
135 }
136
137 if (PIM_DEBUG_PIM_REG)
138 zlog_debug ("Received Register stop for %s",
139 upstream->sg_str);
140
141 switch (upstream->reg_state)
142 {
143 case PIM_REG_NOINFO:
144 case PIM_REG_PRUNE:
145 return 0;
146 break;
147 case PIM_REG_JOIN:
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);
151 break;
152 case PIM_REG_JOIN_PENDING:
153 upstream->reg_state = PIM_REG_PRUNE;
154 pim_upstream_start_register_stop_timer (upstream, 0);
155 return 0;
156 break;
157 }
158
159 return 0;
160 }
161
162 void
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)
164 {
165 unsigned char buffer[10000];
166 unsigned char *b1;
167 struct pim_interface *pinfo;
168 struct interface *ifp;
169
170 if (PIM_DEBUG_PIM_REG)
171 {
172 zlog_debug ("Sending %s %sRegister Packet to %s",
173 up->sg_str, null_register ? "NULL " : "",
174 inet_ntoa (rpg->rpf_addr.u.prefix4));
175 }
176
177 ifp = rpg->source_nexthop.interface;
178 if (!ifp)
179 {
180 if (PIM_DEBUG_PIM_REG)
181 zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__);
182 return;
183 }
184 pinfo = (struct pim_interface *)ifp->info;
185 if (!pinfo) {
186 if (PIM_DEBUG_PIM_REG)
187 zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__, ifp->name);
188 return;
189 }
190
191 if (PIM_DEBUG_PIM_REG)
192 {
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);
198 }
199
200 memset(buffer, 0, 10000);
201 b1 = buffer + PIM_MSG_HEADER_LEN;
202 *b1 |= null_register << 6;
203 b1 = buffer + PIM_MSG_REGISTER_LEN;
204
205 memcpy(b1, (const unsigned char *)buf, buf_size);
206
207 pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER);
208
209 ++pinfo->pim_ifstat_reg_send;
210
211 if (pim_msg_send(pinfo->pim_sock_fd,
212 src,
213 rpg->rpf_addr.u.prefix4,
214 buffer,
215 buf_size + PIM_MSG_REGISTER_LEN,
216 ifp->name)) {
217 if (PIM_DEBUG_PIM_TRACE) {
218 zlog_debug("%s: could not send PIM register message on interface %s",
219 __PRETTY_FUNCTION__, ifp->name);
220 }
221 return;
222 }
223 }
224
225 /*
226 * 4.4.2 Receiving Register Messages at the RP
227 *
228 * When an RP receives a Register message, the course of action is
229 * decided according to the following pseudocode:
230 *
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
235 * }
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.
244 * }
245 * }
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;
251 * }
252 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
253 * if ( sentRegisterStop == TRUE ) {
254 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
255 * } else {
256 * set KeepaliveTimer(S,G) to Keepalive_Period;
257 * }
258 * }
259 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
260 * decapsulate and forward the inner packet to
261 * inherited_olist(S,G,rpt) # Note (+)
262 * }
263 * } else {
264 * send Register-Stop(S,G) to outer.src
265 * # Note (*)
266 * }
267 * }
268 */
269 int
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)
274 {
275 int sentRegisterStop = 0;
276 struct ip *ip_hdr;
277 struct prefix_sg sg;
278 uint32_t *bits;
279 int i_am_rp = 0;
280 struct pim_interface *pim_ifp = NULL;
281
282 #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
283 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
284
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];
288
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__,
291 dest);
292 }
293 return 0;
294 }
295
296 pim_ifp = ifp->info;
297 zassert(pim_ifp);
298 ++pim_ifp->pim_ifstat_reg_recv;
299
300 /*
301 * Please note this is not drawn to get the correct bit/data size
302 *
303 * The entirety of the REGISTER packet looks like this:
304 * -------------------------------------------------------------
305 * | Ver | Type | Reserved | Checksum |
306 * |-----------------------------------------------------------|
307 * |B|N| Reserved 2 |
308 * |-----------------------------------------------------------|
309 * | Encap | IP HDR |
310 * | Mcast | |
311 * | Packet |--------------------------------------------------|
312 * | | Mcast Data |
313 * | | |
314 * ...
315 *
316 * tlv_buf when received from the caller points at the B bit
317 * We need to know the inner source and dest
318 */
319 bits = (uint32_t *)tlv_buf;
320
321 /*
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.
325 */
326 memset (&sg, 0, sizeof (struct prefix_sg));
327 sg.src = ip_hdr->ip_src;
328 sg.grp = ip_hdr->ip_dst;
329
330 i_am_rp = I_am_RP (sg.grp);
331
332 if (PIM_DEBUG_PIM_REG)
333 {
334 char src_str[INET_ADDRSTRLEN];
335
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);
339 }
340
341 if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) {
342 sentRegisterStop = 0;
343
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__);
348
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",
355 __func__, "Sender");
356 /* Drop Packet Silently */
357 return 1;
358 }
359 }
360
361 struct pim_upstream *upstream = pim_upstream_find (&sg);
362 /*
363 * If we don't have a place to send ignore the packet
364 */
365 if (!upstream)
366 {
367 upstream = pim_upstream_add (&sg, ifp,
368 PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
369 __PRETTY_FUNCTION__);
370 if (!upstream)
371 {
372 zlog_warn ("Failure to create upstream state");
373 return 1;
374 }
375
376 upstream->upstream_register = src_addr;
377 }
378
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;
385 } else {
386 if (PIM_DEBUG_PIM_REG)
387 zlog_debug ("(%s) sptbit: %d", upstream->sg_str, upstream->sptbit);
388 }
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);
393 } else {
394 pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time);
395 }
396 }
397
398 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) &&
399 !(*bits & PIM_REGISTER_NR_BIT))
400 {
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
404 }
405 pim_upstream_msdp_reg_timer_start(upstream);
406 } else {
407 if (PIM_DEBUG_PIM_REG)
408 {
409 if (!i_am_rp)
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));
412 else
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));
415 }
416 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
417 }
418
419 return 1;
420 }