]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_register.c
pimd: Add debug messages as to why a register packet is rejected.
[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
47 struct thread *send_test_packet_timer = NULL;
48
49 void
50 pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg,
51 struct in_addr src, struct in_addr originator)
52 {
53 struct pim_interface *pinfo;
54 unsigned char buffer[3000];
55 unsigned int b1length = 0;
56 unsigned int length;
57 uint8_t *b1;
58 struct prefix p;
59
60 if (PIM_DEBUG_PIM_REG)
61 {
62 zlog_debug ("Sending Register stop for %s to %s on %s",
63 pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name);
64 }
65
66 memset (buffer, 0, 3000);
67 b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN;
68
69 length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp);
70 b1length += length;
71 b1 += length;
72
73 p.family = AF_INET;
74 p.u.prefix4 = sg->src;
75 p.prefixlen = 32;
76 length = pim_encode_addr_ucast (b1, &p);
77 b1length += length;
78
79 pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP);
80
81 pinfo = (struct pim_interface *)ifp->info;
82 if (!pinfo)
83 {
84 if (PIM_DEBUG_PIM_TRACE)
85 zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__);
86 return;
87 }
88 if (pim_msg_send (pinfo->pim_sock_fd, src, originator,
89 buffer, b1length + PIM_MSG_REGISTER_STOP_LEN,
90 ifp->name))
91 {
92 if (PIM_DEBUG_PIM_TRACE)
93 {
94 zlog_debug ("%s: could not send PIM register stop message on interface %s",
95 __PRETTY_FUNCTION__, ifp->name);
96 }
97 }
98 }
99
100 int
101 pim_register_stop_recv (uint8_t *buf, int buf_size)
102 {
103 struct pim_upstream *upstream = NULL;
104 struct prefix source;
105 struct prefix group;
106 struct prefix_sg sg;
107 int l;
108
109 l = pim_parse_addr_group (&group, buf, buf_size);
110 buf += l;
111 buf_size -= l;
112 pim_parse_addr_ucast (&source, buf, buf_size);
113 memset (&sg, 0, sizeof (struct prefix_sg));
114 sg.src = source.u.prefix4;
115 sg.grp = group.u.prefix4;
116
117 if (PIM_DEBUG_PIM_REG)
118 {
119 zlog_debug ("Received Register stop for %s",
120 pim_str_sg_dump (&sg));
121 }
122
123 upstream = pim_upstream_find (&sg);
124 if (!upstream)
125 {
126 return 0;
127 }
128
129 switch (upstream->join_state)
130 {
131 case PIM_UPSTREAM_NOTJOINED:
132 case PIM_UPSTREAM_PRUNE:
133 return 0;
134 break;
135 case PIM_UPSTREAM_JOINED:
136 upstream->join_state = PIM_UPSTREAM_PRUNE;
137 pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
138 pim_upstream_start_register_stop_timer (upstream, 0);
139 case PIM_UPSTREAM_JOIN_PENDING:
140 upstream->join_state = PIM_UPSTREAM_PRUNE;
141 pim_upstream_start_register_stop_timer (upstream, 0);
142 return 0;
143 break;
144 }
145
146 return 0;
147 }
148
149 void
150 pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register)
151 {
152 unsigned char buffer[3000];
153 unsigned char *b1;
154 struct pim_interface *pinfo;
155 struct interface *ifp;
156
157 if (PIM_DEBUG_PIM_REG)
158 {
159 char rp_str[100];
160 strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4));
161 zlog_debug ("Sending %sRegister Packet to %s", null_register ? "NULL " : "", rp_str);
162 }
163
164 ifp = rpg->source_nexthop.interface;
165 if (!ifp)
166 {
167 if (PIM_DEBUG_PIM_REG)
168 zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__);
169 return;
170 }
171 pinfo = (struct pim_interface *)ifp->info;
172 if (!pinfo) {
173 if (PIM_DEBUG_PIM_REG)
174 zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__, ifp->name);
175 return;
176 }
177
178 memset(buffer, 0, 3000);
179 b1 = buffer + PIM_MSG_HEADER_LEN;
180 *b1 |= null_register << 6;
181 b1 = buffer + PIM_MSG_REGISTER_LEN;
182
183 memcpy(b1, (const unsigned char *)buf, buf_size);
184
185 pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER);
186
187 if (pim_msg_send(pinfo->pim_sock_fd,
188 src,
189 rpg->rpf_addr.u.prefix4,
190 buffer,
191 buf_size + PIM_MSG_REGISTER_LEN,
192 ifp->name)) {
193 if (PIM_DEBUG_PIM_TRACE) {
194 zlog_debug("%s: could not send PIM register message on interface %s",
195 __PRETTY_FUNCTION__, ifp->name);
196 }
197 return;
198 }
199 }
200
201 /*
202 * 4.4.2 Receiving Register Messages at the RP
203 *
204 * When an RP receives a Register message, the course of action is
205 * decided according to the following pseudocode:
206 *
207 * packet_arrives_on_rp_tunnel( pkt ) {
208 * if( outer.dst is not one of my addresses ) {
209 * drop the packet silently.
210 * # Note: this may be a spoofing attempt
211 * }
212 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
213 * sentRegisterStop = FALSE;
214 * if ( register.borderbit == TRUE ) {
215 * if ( PMBR(S,G) == unknown ) {
216 * PMBR(S,G) = outer.src
217 * } else if ( outer.src != PMBR(S,G) ) {
218 * send Register-Stop(S,G) to outer.src
219 * drop the packet silently.
220 * }
221 * }
222 * if ( SPTbit(S,G) OR
223 * ( SwitchToSptDesired(S,G) AND
224 * ( inherited_olist(S,G) == NULL ))) {
225 * send Register-Stop(S,G) to outer.src
226 * sentRegisterStop = TRUE;
227 * }
228 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
229 * if ( sentRegisterStop == TRUE ) {
230 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
231 * } else {
232 * set KeepaliveTimer(S,G) to Keepalive_Period;
233 * }
234 * }
235 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
236 * decapsulate and forward the inner packet to
237 * inherited_olist(S,G,rpt) # Note (+)
238 * }
239 * } else {
240 * send Register-Stop(S,G) to outer.src
241 * # Note (*)
242 * }
243 * }
244 */
245 int
246 pim_register_recv (struct interface *ifp,
247 struct in_addr dest_addr,
248 struct in_addr src_addr,
249 uint8_t *tlv_buf, int tlv_buf_size)
250 {
251 int sentRegisterStop = 0;
252 struct ip *ip_hdr;
253 struct prefix_sg sg;
254 uint32_t *bits;
255 int i_am_rp = 0;
256
257 #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
258 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
259
260 if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) {
261 if (PIM_DEBUG_PIM_REG) {
262 char dest[100];
263
264 pim_inet4_dump ("<dst?>", dest_addr, dest, sizeof(dest));
265 zlog_debug ("%s: Received Register message for %s that I do not own", __func__,
266 dest);
267 }
268 return 0;
269 }
270
271 if (PIM_DEBUG_PIM_REG)
272 {
273 char src_str[100];
274
275 pim_inet4_dump ("<src?>", src_addr, src_str, sizeof (src_str));
276 zlog_debug ("Received Register message from %s on %s", src_str, ifp->name);
277 }
278
279 /*
280 * Please note this is not drawn to get the correct bit/data size
281 *
282 * The entirety of the REGISTER packet looks like this:
283 * -------------------------------------------------------------
284 * | Ver | Type | Reserved | Checksum |
285 * |-----------------------------------------------------------|
286 * |B|N| Reserved 2 |
287 * |-----------------------------------------------------------|
288 * | Encap | IP HDR |
289 * | Mcast | |
290 * | Packet |--------------------------------------------------|
291 * | | Mcast Data |
292 * | | |
293 * ...
294 *
295 * tlv_buf when received from the caller points at the B bit
296 * We need to know the inner source and dest
297 */
298 bits = (uint32_t *)tlv_buf;
299
300 /*
301 * tlv_buf points to the start of the |B|N|... Reserved
302 * Line above. So we need to add 4 bytes to get to the
303 * start of the actual Encapsulated data.
304 */
305 memset (&sg, 0, sizeof (struct prefix_sg));
306 sg.src = ip_hdr->ip_src;
307 sg.grp = ip_hdr->ip_dst;
308
309 i_am_rp = I_am_RP (sg.grp);
310 if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) {
311 sentRegisterStop = 0;
312
313 if (*bits & PIM_REGISTER_BORDER_BIT) {
314 struct in_addr pimbr = pim_br_get_pmbr (&sg);
315 if (PIM_DEBUG_PIM_PACKETS)
316 zlog_debug("%s: Received Register message with Border bit set", __func__);
317
318 if (pimbr.s_addr == pim_br_unknown.s_addr)
319 pim_br_set_pmbr(&sg, src_addr);
320 else if (src_addr.s_addr != pimbr.s_addr) {
321 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
322 if (PIM_DEBUG_PIM_PACKETS)
323 zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet",
324 __func__, "Sender");
325 /* Drop Packet Silently */
326 return 1;
327 }
328 }
329
330 struct pim_upstream *upstream = pim_upstream_find (&sg);
331 /*
332 * If we don't have a place to send ignore the packet
333 */
334 if (!upstream)
335 {
336 upstream = pim_upstream_add (&sg, ifp);
337 if (!upstream)
338 {
339 zlog_warn ("Failure to create upstream state");
340 return 1;
341 }
342 upstream->upstream_register = src_addr;
343 pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp);
344 pim_nexthop_lookup (&upstream->rpf.source_nexthop,
345 upstream->upstream_addr, 1);
346 upstream->sg.src = sg.src;
347 upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr;
348
349 upstream->join_state = PIM_UPSTREAM_PRUNE;
350
351 }
352
353 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
354 ((SwitchToSptDesired(&sg)) &&
355 pim_upstream_inherited_olist (upstream) == 0)) {
356 //pim_scan_individual_oil (upstream->channel_oil);
357 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
358 sentRegisterStop = 1;
359 }
360
361 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
362 (SwitchToSptDesired(&sg))) {
363 if (sentRegisterStop) {
364 pim_upstream_keep_alive_timer_start (upstream, qpim_rp_keep_alive_time);
365 } else {
366 pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time);
367 }
368 }
369
370 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) &&
371 !(*bits & PIM_REGISTER_NR_BIT))
372 {
373 //decapsulate and forward the iner packet to
374 //inherited_olist(S,G,rpt)
375 // This is taken care of by the kernel for us
376 }
377 } else {
378 if (PIM_DEBUG_PIM_REG)
379 {
380 if (!i_am_rp)
381 zlog_debug ("Received Register packet for %s, Rejecting packet because I am not the RP configured for group",
382 pim_str_sg_dump (&sg));
383 else
384 zlog_debug ("Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP",
385 pim_str_sg_dump (&sg));
386 }
387 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
388 }
389
390 return 1;
391 }
392
393
394 static int
395 pim_register_send_test_packet (struct thread *t)
396 {
397 uint8_t *packet;
398
399 packet = THREAD_ARG(t);
400
401 *packet = 4;
402
403 return 1;
404 }
405
406 /*
407 * pim_register_send_test_packet
408 *
409 * Send a test packet to the RP from source, in group and pps packets per second
410 */
411 void
412 pim_register_send_test_packet_start (struct in_addr source,
413 struct in_addr group,
414 uint32_t pps)
415 {
416 uint8_t *packet = NULL;
417
418 THREAD_TIMER_MSEC_ON(master, send_test_packet_timer,
419 pim_register_send_test_packet, packet, 1000/pps);
420
421 return;
422 }