]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_msg.c
pimd: Only debug in the unusual case
[mirror_frr.git] / pimd / pim_msg.c
1 /*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "if.h"
24 #include "log.h"
25 #include "prefix.h"
26 #include "vty.h"
27 #include "plist.h"
28
29 #include "pimd.h"
30 #include "pim_vty.h"
31 #include "pim_pim.h"
32 #include "pim_msg.h"
33 #include "pim_util.h"
34 #include "pim_str.h"
35 #include "pim_iface.h"
36 #include "pim_rp.h"
37 #include "pim_rpf.h"
38 #include "pim_register.h"
39
40 void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type)
41 {
42 struct pim_msg_header *header = (struct pim_msg_header *)pim_msg;
43
44 /*
45 * Write header
46 */
47 header->ver = PIM_PROTO_VERSION;
48 header->type = pim_msg_type;
49 header->reserved = 0;
50
51
52 header->checksum = 0;
53 /*
54 * The checksum for Registers is done only on the first 8 bytes of the packet,
55 * including the PIM header and the next 4 bytes, excluding the data packet portion
56 */
57 if (pim_msg_type == PIM_MSG_TYPE_REGISTER)
58 header->checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN);
59 else
60 header->checksum = in_cksum (pim_msg, pim_msg_size);
61 }
62
63 uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr)
64 {
65 buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
66 buf[1] = '\0'; /* native encoding */
67 memcpy(buf+2, &addr, sizeof(struct in_addr));
68
69 return buf + PIM_ENCODED_IPV4_UCAST_SIZE;
70 }
71
72 uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr)
73 {
74 buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
75 buf[1] = '\0'; /* native encoding */
76 buf[2] = '\0'; /* reserved */
77 buf[3] = 32; /* mask len */
78 memcpy(buf+4, &addr, sizeof(struct in_addr));
79
80 return buf + PIM_ENCODED_IPV4_GROUP_SIZE;
81 }
82
83 uint8_t *
84 pim_msg_addr_encode_ipv4_source(uint8_t *buf,
85 struct in_addr addr, uint8_t bits)
86 {
87 buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
88 buf[1] = '\0'; /* native encoding */
89 buf[2] = bits;
90 buf[3] = 32; /* mask len */
91 memcpy(buf+4, &addr, sizeof(struct in_addr));
92
93 return buf + PIM_ENCODED_IPV4_SOURCE_SIZE;
94 }
95
96 /*
97 * J/P Message Format
98 *
99 * While the RFC clearly states that this is 32 bits wide, it
100 * is cheating. These fields:
101 * Encoded-Unicast format (6 bytes MIN)
102 * Encoded-Group format (8 bytes MIN)
103 * Encoded-Source format (8 bytes MIN)
104 * are *not* 32 bits wide.
105 *
106 * Nor does the RFC explicitly call out the size for:
107 * Reserved (1 byte)
108 * Num Groups (1 byte)
109 * Holdtime (2 bytes)
110 * Number of Joined Sources (2 bytes)
111 * Number of Pruned Sources (2 bytes)
112 *
113 * This leads to a missleading representation from casual
114 * reading and making assumptions. Be careful!
115 *
116 * 0 1 2 3
117 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
118 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 * |PIM Ver| Type | Reserved | Checksum |
120 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121 * | Upstream Neighbor Address (Encoded-Unicast format) |
122 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 * | Reserved | Num groups | Holdtime |
124 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 * | Multicast Group Address 1 (Encoded-Group format) |
126 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127 * | Number of Joined Sources | Number of Pruned Sources |
128 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 * | Joined Source Address 1 (Encoded-Source format) |
130 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 * | . |
132 * | . |
133 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134 * | Joined Source Address n (Encoded-Source format) |
135 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 * | Pruned Source Address 1 (Encoded-Source format) |
137 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 * | . |
139 * | . |
140 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141 * | Pruned Source Address n (Encoded-Source format) |
142 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143 * | Multicast Group Address m (Encoded-Group format) |
144 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145 * | Number of Joined Sources | Number of Pruned Sources |
146 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
147 * | Joined Source Address 1 (Encoded-Source format) |
148 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 * | . |
150 * | . |
151 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 * | Joined Source Address n (Encoded-Source format) |
153 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 * | Pruned Source Address 1 (Encoded-Source format) |
155 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156 * | . |
157 * | . |
158 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 * | Pruned Source Address n (Encoded-Source format) |
160 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 */
162 int
163 pim_msg_join_prune_encode (uint8_t *buf, size_t buf_size, int is_join,
164 struct pim_upstream *up,
165 struct in_addr upstream, int holdtime)
166 {
167 struct pim_jp *msg = (struct pim_jp *)buf;
168 struct in_addr stosend;
169 uint8_t bits;
170
171 assert(buf_size > sizeof (struct pim_jp));
172
173 if (!pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, upstream)) {
174 char dst_str[INET_ADDRSTRLEN];
175 pim_inet4_dump("<dst?>", upstream, dst_str, sizeof(dst_str));
176 zlog_warn("%s: failure encoding destination address %s",
177 __PRETTY_FUNCTION__, dst_str);
178 return -3;
179 }
180
181 msg->reserved = 0;
182 msg->num_groups = 1;
183 msg->holdtime = htons(holdtime);
184
185 if (!pim_msg_addr_encode_ipv4_group ((uint8_t *)&msg->groups[0].g, up->sg.grp)) {
186 char group_str[INET_ADDRSTRLEN];
187 pim_inet4_dump("<grp?>", up->sg.grp, group_str, sizeof(group_str));
188 zlog_warn("%s: failure encoding group address %s",
189 __PRETTY_FUNCTION__, group_str);
190 return -5;
191 }
192
193 /* number of joined/pruned sources */
194 msg->groups[0].joins = htons(is_join ? 1 : 0);
195 msg->groups[0].prunes = htons(is_join ? 0 : 1);
196
197 if (up->sg.src.s_addr == INADDR_ANY)
198 {
199 struct pim_rpf *rpf = pim_rp_g (up->sg.grp);
200 bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT;
201 stosend = rpf->rpf_addr.u.prefix4;
202 }
203 else
204 {
205 bits = PIM_ENCODE_SPARSE_BIT;
206 stosend = up->sg.src;
207 }
208
209 if (!pim_msg_addr_encode_ipv4_source ((uint8_t *)&msg->groups[0].s[0], stosend, bits)) {
210 char source_str[INET_ADDRSTRLEN];
211 pim_inet4_dump("<src?>", up->sg.src, source_str, sizeof(source_str));
212 zlog_warn("%s: failure encoding source address %s",
213 __PRETTY_FUNCTION__, source_str);
214 return -7;
215 }
216
217 /*
218 * This is not implemented correctly at this point in time
219 * Make it stop.
220 */
221 #if 0
222 if (up->sg.src.s_addr == INADDR_ANY)
223 {
224 struct pim_upstream *child;
225 struct listnode *up_node;
226 int send_prune = 0;
227
228 zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune",
229 __PRETTY_FUNCTION__, up->sg_str);
230 for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
231 {
232 if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
233 {
234 if (!pim_rpf_is_same(&up->rpf, &child->rpf))
235 {
236 send_prune = 1;
237 if (PIM_DEBUG_PIM_PACKETS)
238 zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message",
239 __PRETTY_FUNCTION__, up->sg_str, child->sg_str);
240 }
241 else
242 if (PIM_DEBUG_PIM_PACKETS)
243 zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)",
244 __PRETTY_FUNCTION__, up->sg_str, child->sg_str);
245 }
246 else if (pim_upstream_is_sg_rpt (child))
247 {
248 if (pim_upstream_empty_inherited_olist (child))
249 {
250 send_prune = 1;
251 if (PIM_DEBUG_PIM_PACKETS)
252 zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message",
253 __PRETTY_FUNCTION__, child->sg_str);
254 }
255 else if (!pim_rpf_is_same (&up->rpf, &child->rpf))
256 {
257 send_prune = 1;
258 if (PIM_DEBUG_PIM_PACKETS)
259 zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message",
260 __PRETTY_FUNCTION__, up->sg_str, child->sg_str);
261 }
262 else
263 if (PIM_DEBUG_PIM_PACKETS)
264 zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message",
265 __PRETTY_FUNCTION__, up->sg_str, child->sg_str);
266 }
267 else
268 if (PIM_DEBUG_PIM_PACKETS)
269 zlog_debug ("%s: SPT bit is not set for (%s)",
270 __PRETTY_FUNCTION__, child->sg_str);
271 if (send_prune)
272 {
273 pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain,
274 child->sg.src,
275 PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT);
276 remain = pim_msg_curr - pim_msg;
277 *prunes = htons(ntohs(*prunes) + 1);
278 send_prune = 0;
279 }
280 }
281 }
282 #endif
283 pim_msg_build_header (buf, sizeof (struct pim_jp), PIM_MSG_TYPE_JOIN_PRUNE);
284
285 return sizeof (struct pim_jp);
286 }