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