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