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