1 commit 6d58272b4cf96f0daa846210dd2104877900f921 |
|
2 Author: Paul Jakma <[email protected]> |
|
3 Date: Mon Aug 6 15:21:45 2007 +0000 |
|
4 |
|
5 [bgpd] cleanup, compact and consolidate capability parsing code |
|
6 |
|
7 2007-07-26 Paul Jakma <[email protected]> |
|
8 |
|
9 * (general) Clean up and compact capability parsing slightly. |
|
10 Consolidate validation of length and logging of generic TLV, and |
|
11 memcpy of capability data, thus removing such from cap specifc |
|
12 code (not always present or correct). |
|
13 * bgp_open.h: Add structures for the generic capability TLV header |
|
14 and for the data formats of the various specific capabilities we |
|
15 support. Hence remove the badly named, or else misdefined, struct |
|
16 capability. |
|
17 * bgp_open.c: (bgp_capability_vty_out) Use struct capability_mp_data. |
|
18 Do the length checks *before* memcpy()'ing based on that length |
|
19 (stored capability - should have been validated anyway on input, |
|
20 but..). |
|
21 (bgp_afi_safi_valid_indices) new function to validate (afi,safi) |
|
22 which is about to be used as index into arrays, consolidates |
|
23 several instances of same, at least one of which appeared to be |
|
24 incomplete.. |
|
25 (bgp_capability_mp) Much condensed. |
|
26 (bgp_capability_orf_entry) New, process one ORF entry |
|
27 (bgp_capability_orf) Condensed. Fixed to process all ORF entries. |
|
28 (bgp_capability_restart) Condensed, and fixed to use a |
|
29 cap-specific type, rather than abusing capability_mp. |
|
30 (struct message capcode_str) added to aid generic logging. |
|
31 (size_t cap_minsizes[]) added to aid generic validation of |
|
32 capability length field. |
|
33 (bgp_capability_parse) Generic logging and validation of TLV |
|
34 consolidated here. Code compacted as much as possible. |
|
35 * bgp_packet.c: (bgp_open_receive) Capability parsers now use |
|
36 streams, so no more need here to manually fudge the input stream |
|
37 getp. |
|
38 (bgp_capability_msg_parse) use struct capability_mp_data. Validate |
|
39 lengths /before/ memcpy. Use bgp_afi_safi_valid_indices. |
|
40 (bgp_capability_receive) Exported for use by test harness. |
|
41 * bgp_vty.c: (bgp_show_summary) fix conversion warning |
|
42 (bgp_show_peer) ditto |
|
43 * bgp_debug.h: Fix storage 'extern' after type 'const'. |
|
44 * lib/log.c: (mes_lookup) warning about code not being in |
|
45 same-number array slot should be debug, not warning. E.g. BGP |
|
46 has several discontigious number spaces, allocating from |
|
47 different parts of a space is not uncommon (e.g. IANA |
|
48 assigned versus vendor-assigned code points in some number |
|
49 space). |
|
50 |
|
51 --- bgpd/bgp_debug.h |
|
52 +++ bgpd/bgp_debug.h |
|
53 @@ -110,7 +110,7 @@ extern unsigned long term_bgp_debug_zebra; |
|
54 #define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b) |
|
55 #define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b) |
|
56 |
|
57 -const extern char *bgp_type_str[]; |
|
58 +extern const char *bgp_type_str[]; |
|
59 |
|
60 extern int bgp_dump_attr (struct peer *, struct attr *, char *, size_t); |
|
61 extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *); |
|
62 diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c |
|
63 index e44bd2a..d4f7cdf 100644 |
|
64 --- bgpd/bgp_open.c |
|
65 +++ bgpd/bgp_open.c |
|
66 @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
|
67 #include "thread.h" |
|
68 #include "log.h" |
|
69 #include "command.h" |
|
70 +#include "memory.h" |
|
71 |
|
72 #include "bgpd/bgpd.h" |
|
73 #include "bgpd/bgp_attr.h" |
|
74 @@ -50,25 +51,28 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) |
|
75 { |
|
76 char *pnt; |
|
77 char *end; |
|
78 - struct capability cap; |
|
79 + struct capability_mp_data mpc; |
|
80 + struct capability_header *hdr; |
|
81 |
|
82 pnt = peer->notify.data; |
|
83 end = pnt + peer->notify.length; |
|
84 - |
|
85 + |
|
86 while (pnt < end) |
|
87 { |
|
88 - memcpy(&cap, pnt, sizeof(struct capability)); |
|
89 - |
|
90 - if (pnt + 2 > end) |
|
91 + if (pnt + sizeof (struct capability_mp_data) + 2 > end) |
|
92 return; |
|
93 - if (pnt + (cap.length + 2) > end) |
|
94 + |
|
95 + hdr = (struct capability_header *)pnt; |
|
96 + if (pnt + hdr->length + 2 > end) |
|
97 return; |
|
98 |
|
99 - if (cap.code == CAPABILITY_CODE_MP) |
|
100 + memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data)); |
|
101 + |
|
102 + if (hdr->code == CAPABILITY_CODE_MP) |
|
103 { |
|
104 vty_out (vty, " Capability error for: Multi protocol "); |
|
105 |
|
106 - switch (ntohs (cap.mpc.afi)) |
|
107 + switch (ntohs (mpc.afi)) |
|
108 { |
|
109 case AFI_IP: |
|
110 vty_out (vty, "AFI IPv4, "); |
|
111 @@ -77,10 +81,10 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) |
|
112 vty_out (vty, "AFI IPv6, "); |
|
113 break; |
|
114 default: |
|
115 - vty_out (vty, "AFI Unknown %d, ", ntohs (cap.mpc.afi)); |
|
116 + vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi)); |
|
117 break; |
|
118 } |
|
119 - switch (cap.mpc.safi) |
|
120 + switch (mpc.safi) |
|
121 { |
|
122 case SAFI_UNICAST: |
|
123 vty_out (vty, "SAFI Unicast"); |
|
124 @@ -95,88 +99,87 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) |
|
125 vty_out (vty, "SAFI MPLS-VPN"); |
|
126 break; |
|
127 default: |
|
128 - vty_out (vty, "SAFI Unknown %d ", cap.mpc.safi); |
|
129 + vty_out (vty, "SAFI Unknown %d ", mpc.safi); |
|
130 break; |
|
131 } |
|
132 vty_out (vty, "%s", VTY_NEWLINE); |
|
133 } |
|
134 - else if (cap.code >= 128) |
|
135 + else if (hdr->code >= 128) |
|
136 vty_out (vty, " Capability error: vendor specific capability code %d", |
|
137 - cap.code); |
|
138 + hdr->code); |
|
139 else |
|
140 vty_out (vty, " Capability error: unknown capability code %d", |
|
141 - cap.code); |
|
142 + hdr->code); |
|
143 |
|
144 - pnt += cap.length + 2; |
|
145 + pnt += hdr->length + 2; |
|
146 } |
|
147 } |
|
148 |
|
149 -/* Set negotiated capability value. */ |
|
150 -static int |
|
151 -bgp_capability_mp (struct peer *peer, struct capability *cap) |
|
152 +static void |
|
153 +bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc) |
|
154 { |
|
155 - if (ntohs (cap->mpc.afi) == AFI_IP) |
|
156 - { |
|
157 - if (cap->mpc.safi == SAFI_UNICAST) |
|
158 - { |
|
159 - peer->afc_recv[AFI_IP][SAFI_UNICAST] = 1; |
|
160 - |
|
161 - if (peer->afc[AFI_IP][SAFI_UNICAST]) |
|
162 - peer->afc_nego[AFI_IP][SAFI_UNICAST] = 1; |
|
163 - else |
|
164 - return -1; |
|
165 - } |
|
166 - else if (cap->mpc.safi == SAFI_MULTICAST) |
|
167 - { |
|
168 - peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 1; |
|
169 - |
|
170 - if (peer->afc[AFI_IP][SAFI_MULTICAST]) |
|
171 - peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 1; |
|
172 - else |
|
173 - return -1; |
|
174 - } |
|
175 - else if (cap->mpc.safi == BGP_SAFI_VPNV4) |
|
176 - { |
|
177 - peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 1; |
|
178 + mpc->afi = stream_getw (s); |
|
179 + mpc->reserved = stream_getc (s); |
|
180 + mpc->safi = stream_getc (s); |
|
181 +} |
|
182 |
|
183 - if (peer->afc[AFI_IP][SAFI_MPLS_VPN]) |
|
184 - peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 1; |
|
185 - else |
|
186 - return -1; |
|
187 - } |
|
188 - else |
|
189 - return -1; |
|
190 - } |
|
191 -#ifdef HAVE_IPV6 |
|
192 - else if (ntohs (cap->mpc.afi) == AFI_IP6) |
|
193 +int |
|
194 +bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) |
|
195 +{ |
|
196 + /* VPNvX are AFI specific */ |
|
197 + if ((afi == AFI_IP6 && *safi == BGP_SAFI_VPNV4) |
|
198 + || (afi == AFI_IP && *safi == BGP_SAFI_VPNV6)) |
|
199 { |
|
200 - if (cap->mpc.safi == SAFI_UNICAST) |
|
201 - { |
|
202 - peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 1; |
|
203 - |
|
204 - if (peer->afc[AFI_IP6][SAFI_UNICAST]) |
|
205 - peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 1; |
|
206 - else |
|
207 - return -1; |
|
208 - } |
|
209 - else if (cap->mpc.safi == SAFI_MULTICAST) |
|
210 - { |
|
211 - peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 1; |
|
212 - |
|
213 - if (peer->afc[AFI_IP6][SAFI_MULTICAST]) |
|
214 - peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 1; |
|
215 - else |
|
216 - return -1; |
|
217 - } |
|
218 - else |
|
219 - return -1; |
|
220 + zlog_warn ("Invalid afi/safi combination (%u/%u)", afi, *safi); |
|
221 + return 0; |
|
222 } |
|
223 -#endif /* HAVE_IPV6 */ |
|
224 - else |
|
225 + |
|
226 + switch (afi) |
|
227 { |
|
228 - /* Unknown Address Family. */ |
|
229 - return -1; |
|
230 + case AFI_IP: |
|
231 +#ifdef HAVE_IPV6 |
|
232 + case AFI_IP6: |
|
233 +#endif |
|
234 + switch (*safi) |
|
235 + { |
|
236 + /* BGP VPNvX SAFI isn't contigious with others, remap */ |
|
237 + case BGP_SAFI_VPNV4: |
|
238 + case BGP_SAFI_VPNV6: |
|
239 + *safi = SAFI_MPLS_VPN; |
|
240 + case SAFI_UNICAST: |
|
241 + case SAFI_MULTICAST: |
|
242 + case SAFI_MPLS_VPN: |
|
243 + return 1; |
|
244 + } |
|
245 } |
|
246 + zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi); |
|
247 + |
|
248 + return 0; |
|
249 +} |
|
250 + |
|
251 +/* Set negotiated capability value. */ |
|
252 +static int |
|
253 +bgp_capability_mp (struct peer *peer, struct capability_header *hdr) |
|
254 +{ |
|
255 + struct capability_mp_data mpc; |
|
256 + struct stream *s = BGP_INPUT (peer); |
|
257 + |
|
258 + bgp_capability_mp_data (s, &mpc); |
|
259 + |
|
260 + if (BGP_DEBUG (normal, NORMAL)) |
|
261 + zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", |
|
262 + peer->host, mpc.afi, mpc.safi); |
|
263 + |
|
264 + if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi)) |
|
265 + return -1; |
|
266 + |
|
267 + /* Now safi remapped, and afi/safi are valid array indices */ |
|
268 + peer->afc_recv[mpc.afi][mpc.safi] = 1; |
|
269 + |
|
270 + if (peer->afc[mpc.afi][mpc.safi]) |
|
271 + peer->afc_nego[mpc.safi][mpc.safi] = 1; |
|
272 + else |
|
273 + return -1; |
|
274 |
|
275 return 0; |
|
276 } |
|
277 @@ -190,98 +193,133 @@ bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi, |
|
278 peer->host, afi, safi, type, mode); |
|
279 } |
|
280 |
|
281 +static struct message orf_type_str[] = |
|
282 +{ |
|
283 + { ORF_TYPE_PREFIX, "Prefixlist" }, |
|
284 + { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" }, |
|
285 +}; |
|
286 +static int orf_type_str_max = sizeof(orf_type_str)/sizeof(orf_type_str[0]); |
|
287 + |
|
288 +static struct message orf_mode_str[] = |
|
289 +{ |
|
290 + { ORF_MODE_RECEIVE, "Receive" }, |
|
291 + { ORF_MODE_SEND, "Send" }, |
|
292 + { ORF_MODE_BOTH, "Both" }, |
|
293 +}; |
|
294 +static int orf_mode_str_max = sizeof(orf_mode_str)/sizeof(orf_mode_str[0]); |
|
295 + |
|
296 static int |
|
297 -bgp_capability_orf (struct peer *peer, struct capability *cap, |
|
298 - u_char *pnt) |
|
299 +bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) |
|
300 { |
|
301 - afi_t afi = ntohs(cap->mpc.afi); |
|
302 - safi_t safi = cap->mpc.safi; |
|
303 - u_char number_of_orfs; |
|
304 + struct stream *s = BGP_INPUT (peer); |
|
305 + struct capability_orf_entry entry; |
|
306 + afi_t afi; |
|
307 + safi_t safi; |
|
308 u_char type; |
|
309 u_char mode; |
|
310 u_int16_t sm_cap = 0; /* capability send-mode receive */ |
|
311 u_int16_t rm_cap = 0; /* capability receive-mode receive */ |
|
312 int i; |
|
313 |
|
314 - /* Check length. */ |
|
315 - if (cap->length < 7) |
|
316 - { |
|
317 - zlog_info ("%s ORF Capability length error %d", |
|
318 - peer->host, cap->length); |
|
319 - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
320 - return -1; |
|
321 - } |
|
322 - |
|
323 + /* ORF Entry header */ |
|
324 + bgp_capability_mp_data (s, &entry.mpc); |
|
325 + entry.num = stream_getc (s); |
|
326 + afi = entry.mpc.afi; |
|
327 + safi = entry.mpc.safi; |
|
328 + |
|
329 if (BGP_DEBUG (normal, NORMAL)) |
|
330 - zlog_debug ("%s OPEN has ORF CAP(%s) for afi/safi: %u/%u", |
|
331 - peer->host, (cap->code == CAPABILITY_CODE_ORF ? |
|
332 - "new" : "old"), afi, safi); |
|
333 + zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", |
|
334 + peer->host, entry.mpc.afi, entry.mpc.safi); |
|
335 |
|
336 /* Check AFI and SAFI. */ |
|
337 - if ((afi != AFI_IP && afi != AFI_IP6) |
|
338 - || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST |
|
339 - && safi != BGP_SAFI_VPNV4)) |
|
340 + if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi)) |
|
341 + { |
|
342 + zlog_info ("%s Addr-family %d/%d not supported." |
|
343 + " Ignoring the ORF capability", |
|
344 + peer->host, entry.mpc.afi, entry.mpc.safi); |
|
345 + return 0; |
|
346 + } |
|
347 + |
|
348 + /* validate number field */ |
|
349 + if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length) |
|
350 { |
|
351 - zlog_info ("%s Addr-family %d/%d not supported. Ignoring the ORF capability", |
|
352 - peer->host, afi, safi); |
|
353 + zlog_info ("%s ORF Capability entry length error," |
|
354 + " Cap length %u, num %u", |
|
355 + peer->host, hdr->length, entry.num); |
|
356 + bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
357 return -1; |
|
358 } |
|
359 |
|
360 - number_of_orfs = *pnt++; |
|
361 - |
|
362 - for (i = 0 ; i < number_of_orfs ; i++) |
|
363 + for (i = 0 ; i < entry.num ; i++) |
|
364 { |
|
365 - type = *pnt++; |
|
366 - mode = *pnt++; |
|
367 - |
|
368 + type = stream_getc(s); |
|
369 + mode = stream_getc(s); |
|
370 + |
|
371 /* ORF Mode error check */ |
|
372 - if (mode != ORF_MODE_BOTH && mode != ORF_MODE_SEND |
|
373 - && mode != ORF_MODE_RECEIVE) |
|
374 - { |
|
375 - bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
376 - continue; |
|
377 + switch (mode) |
|
378 + { |
|
379 + case ORF_MODE_BOTH: |
|
380 + case ORF_MODE_SEND: |
|
381 + case ORF_MODE_RECEIVE: |
|
382 + break; |
|
383 + default: |
|
384 + bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
385 + continue; |
|
386 } |
|
387 + /* ORF Type and afi/safi error checks */ |
|
388 + /* capcode versus type */ |
|
389 + switch (hdr->code) |
|
390 + { |
|
391 + case CAPABILITY_CODE_ORF: |
|
392 + switch (type) |
|
393 + { |
|
394 + case ORF_TYPE_PREFIX: |
|
395 + break; |
|
396 + default: |
|
397 + bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
398 + continue; |
|
399 + } |
|
400 + break; |
|
401 + case CAPABILITY_CODE_ORF_OLD: |
|
402 + switch (type) |
|
403 + { |
|
404 + case ORF_TYPE_PREFIX_OLD: |
|
405 + break; |
|
406 + default: |
|
407 + bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
408 + continue; |
|
409 + } |
|
410 + break; |
|
411 + default: |
|
412 + bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
413 + continue; |
|
414 + } |
|
415 + |
|
416 + /* AFI vs SAFI */ |
|
417 + if (!((afi == AFI_IP && safi == SAFI_UNICAST) |
|
418 + || (afi == AFI_IP && safi == SAFI_MULTICAST) |
|
419 + || (afi == AFI_IP6 && safi == SAFI_UNICAST))) |
|
420 + { |
|
421 + bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
422 + continue; |
|
423 + } |
|
424 + |
|
425 + if (BGP_DEBUG (normal, NORMAL)) |
|
426 + zlog_debug ("%s OPEN has %s ORF capability" |
|
427 + " as %s for afi/safi: %d/%d", |
|
428 + peer->host, LOOKUP (orf_type_str, type), |
|
429 + LOOKUP (orf_mode_str, mode), |
|
430 + entry.mpc.afi, safi); |
|
431 |
|
432 - /* ORF Type and afi/safi error check */ |
|
433 - if (cap->code == CAPABILITY_CODE_ORF) |
|
434 + if (hdr->code == CAPABILITY_CODE_ORF) |
|
435 { |
|
436 - if (type == ORF_TYPE_PREFIX && |
|
437 - ((afi == AFI_IP && safi == SAFI_UNICAST) |
|
438 - || (afi == AFI_IP && safi == SAFI_MULTICAST) |
|
439 - || (afi == AFI_IP6 && safi == SAFI_UNICAST))) |
|
440 - { |
|
441 - sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV; |
|
442 - rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV; |
|
443 - if (BGP_DEBUG (normal, NORMAL)) |
|
444 - zlog_debug ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d", |
|
445 - peer->host, ORF_TYPE_PREFIX, (mode == ORF_MODE_SEND ? "SEND" : |
|
446 - mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi); |
|
447 - } |
|
448 - else |
|
449 - { |
|
450 - bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
451 - continue; |
|
452 - } |
|
453 + sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV; |
|
454 + rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV; |
|
455 } |
|
456 - else if (cap->code == CAPABILITY_CODE_ORF_OLD) |
|
457 + else if (hdr->code == CAPABILITY_CODE_ORF_OLD) |
|
458 { |
|
459 - if (type == ORF_TYPE_PREFIX_OLD && |
|
460 - ((afi == AFI_IP && safi == SAFI_UNICAST) |
|
461 - || (afi == AFI_IP && safi == SAFI_MULTICAST) |
|
462 - || (afi == AFI_IP6 && safi == SAFI_UNICAST))) |
|
463 - { |
|
464 - sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV; |
|
465 - rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV; |
|
466 - if (BGP_DEBUG (normal, NORMAL)) |
|
467 - zlog_debug ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d", |
|
468 - peer->host, ORF_TYPE_PREFIX_OLD, (mode == ORF_MODE_SEND ? "SEND" : |
|
469 - mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi); |
|
470 - } |
|
471 - else |
|
472 - { |
|
473 - bgp_capability_orf_not_support (peer, afi, safi, type, mode); |
|
474 - continue; |
|
475 - } |
|
476 + sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV; |
|
477 + rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV; |
|
478 } |
|
479 else |
|
480 { |
|
481 @@ -306,206 +344,258 @@ bgp_capability_orf (struct peer *peer, struct capability *cap, |
|
482 return 0; |
|
483 } |
|
484 |
|
485 -/* Parse given capability. */ |
|
486 static int |
|
487 -bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length, |
|
488 - u_char **error) |
|
489 +bgp_capability_orf (struct peer *peer, struct capability_header *hdr) |
|
490 { |
|
491 - int ret; |
|
492 - u_char *end; |
|
493 - struct capability cap; |
|
494 - |
|
495 - end = pnt + length; |
|
496 - |
|
497 - while (pnt < end) |
|
498 + struct stream *s = BGP_INPUT (peer); |
|
499 + size_t end = stream_get_getp (s) + hdr->length; |
|
500 + |
|
501 + assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end); |
|
502 + |
|
503 + /* We must have at least one ORF entry, as the caller has already done |
|
504 + * minimum length validation for the capability code - for ORF there must |
|
505 + * at least one ORF entry (header and unknown number of pairs of bytes). |
|
506 + */ |
|
507 + do |
|
508 { |
|
509 - afi_t afi; |
|
510 - safi_t safi; |
|
511 + if (bgp_capability_orf_entry (peer, hdr) == -1) |
|
512 + return -1; |
|
513 + } |
|
514 + while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end); |
|
515 + |
|
516 + return 0; |
|
517 +} |
|
518 |
|
519 - /* Fetch structure to the byte stream. */ |
|
520 - memcpy (&cap, pnt, sizeof (struct capability)); |
|
521 +static int |
|
522 +bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) |
|
523 +{ |
|
524 + struct stream *s = BGP_INPUT (peer); |
|
525 + u_int16_t restart_flag_time; |
|
526 + int restart_bit = 0; |
|
527 + size_t end = stream_get_getp (s) + caphdr->length; |
|
528 + |
|
529 + SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV); |
|
530 + restart_flag_time = stream_getw(s); |
|
531 + if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT)) |
|
532 + restart_bit = 1; |
|
533 + UNSET_FLAG (restart_flag_time, 0xF000); |
|
534 + peer->v_gr_restart = restart_flag_time; |
|
535 |
|
536 - afi = ntohs(cap.mpc.afi); |
|
537 - safi = cap.mpc.safi; |
|
538 + if (BGP_DEBUG (normal, NORMAL)) |
|
539 + { |
|
540 + zlog_debug ("%s OPEN has Graceful Restart capability", peer->host); |
|
541 + zlog_debug ("%s Peer has%srestarted. Restart Time : %d", |
|
542 + peer->host, restart_bit ? " " : " not ", |
|
543 + peer->v_gr_restart); |
|
544 + } |
|
545 |
|
546 - if (BGP_DEBUG (normal, NORMAL)) |
|
547 - zlog_debug ("%s OPEN has CAPABILITY code: %d, length %d", |
|
548 - peer->host, cap.code, cap.length); |
|
549 + while (stream_get_getp (s) + 4 < end) |
|
550 + { |
|
551 + afi_t afi = stream_getw (s); |
|
552 + safi_t safi = stream_getc (s); |
|
553 + u_char flag = stream_getc (s); |
|
554 + |
|
555 + if (!bgp_afi_safi_valid_indices (afi, &safi)) |
|
556 + { |
|
557 + if (BGP_DEBUG (normal, NORMAL)) |
|
558 + zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." |
|
559 + " Ignore the Graceful Restart capability", |
|
560 + peer->host, afi, safi); |
|
561 + } |
|
562 + else if (!peer->afc[afi][safi]) |
|
563 + { |
|
564 + if (BGP_DEBUG (normal, NORMAL)) |
|
565 + zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." |
|
566 + " Ignore the Graceful Restart capability", |
|
567 + peer->host, afi, safi); |
|
568 + } |
|
569 + else |
|
570 + { |
|
571 + if (BGP_DEBUG (normal, NORMAL)) |
|
572 + zlog_debug ("%s Address family %s is%spreserved", peer->host, |
|
573 + afi_safi_print (afi, safi), |
|
574 + CHECK_FLAG (peer->af_cap[afi][safi], |
|
575 + PEER_CAP_RESTART_AF_PRESERVE_RCV) |
|
576 + ? " " : " not "); |
|
577 + |
|
578 + SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV); |
|
579 + if (CHECK_FLAG (flag, RESTART_F_BIT)) |
|
580 + SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV); |
|
581 + |
|
582 + } |
|
583 + } |
|
584 + return 0; |
|
585 +} |
|
586 |
|
587 +static struct message capcode_str[] = |
|
588 +{ |
|
589 + { 0, ""}, |
|
590 + { CAPABILITY_CODE_MP, "MultiProtocol Extensions" }, |
|
591 + { CAPABILITY_CODE_REFRESH, "Route Refresh" }, |
|
592 + { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" }, |
|
593 + { CAPABILITY_CODE_RESTART, "Graceful Restart" }, |
|
594 + { CAPABILITY_CODE_AS4, "4-octet AS number" }, |
|
595 + { CAPABILITY_CODE_DYNAMIC, "Dynamic" }, |
|
596 + { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" }, |
|
597 + { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" }, |
|
598 +}; |
|
599 +int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]); |
|
600 + |
|
601 +/* Minimum sizes for length field of each cap (so not inc. the header) */ |
|
602 +static size_t cap_minsizes[] = |
|
603 +{ |
|
604 + [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data), |
|
605 + [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, |
|
606 + [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry), |
|
607 + [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr) - 2, |
|
608 + [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, |
|
609 + [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, |
|
610 + [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, |
|
611 + [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry), |
|
612 +}; |
|
613 + |
|
614 +/* Parse given capability. |
|
615 + * XXX: This is reading into a stream, but not using stream API |
|
616 + */ |
|
617 +static int |
|
618 +bgp_capability_parse (struct peer *peer, size_t length, u_char **error) |
|
619 +{ |
|
620 + int ret; |
|
621 + struct stream *s = BGP_INPUT (peer); |
|
622 + size_t end = stream_get_getp (s) + length; |
|
623 + |
|
624 + assert (STREAM_READABLE (s) >= length); |
|
625 + |
|
626 + while (stream_get_getp (s) < end) |
|
627 + { |
|
628 + size_t start; |
|
629 + u_char *sp = stream_pnt (s); |
|
630 + struct capability_header caphdr; |
|
631 + |
|
632 /* We need at least capability code and capability length. */ |
|
633 - if (pnt + 2 > end) |
|
634 + if (stream_get_getp(s) + 2 > end) |
|
635 { |
|
636 - zlog_info ("%s Capability length error", peer->host); |
|
637 + zlog_info ("%s Capability length error (< header)", peer->host); |
|
638 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
639 return -1; |
|
640 } |
|
641 - |
|
642 - /* Capability length check. */ |
|
643 - if (pnt + (cap.length + 2) > end) |
|
644 + |
|
645 + caphdr.code = stream_getc (s); |
|
646 + caphdr.length = stream_getc (s); |
|
647 + start = stream_get_getp (s); |
|
648 + |
|
649 + /* Capability length check sanity check. */ |
|
650 + if (start + caphdr.length > end) |
|
651 { |
|
652 - zlog_info ("%s Capability length error", peer->host); |
|
653 + zlog_info ("%s Capability length error (< length)", peer->host); |
|
654 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
655 return -1; |
|
656 } |
|
657 - |
|
658 - /* We know MP Capability Code. */ |
|
659 - if (cap.code == CAPABILITY_CODE_MP) |
|
660 - { |
|
661 - if (BGP_DEBUG (normal, NORMAL)) |
|
662 - zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", |
|
663 - peer->host, afi, safi); |
|
664 - |
|
665 - /* Ignore capability when override-capability is set. */ |
|
666 - if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) |
|
667 - { |
|
668 - /* Set negotiated value. */ |
|
669 - ret = bgp_capability_mp (peer, &cap); |
|
670 - |
|
671 - /* Unsupported Capability. */ |
|
672 - if (ret < 0) |
|
673 - { |
|
674 - /* Store return data. */ |
|
675 - memcpy (*error, &cap, cap.length + 2); |
|
676 - *error += cap.length + 2; |
|
677 - } |
|
678 - } |
|
679 - } |
|
680 - else if (cap.code == CAPABILITY_CODE_REFRESH |
|
681 - || cap.code == CAPABILITY_CODE_REFRESH_OLD) |
|
682 - { |
|
683 - /* Check length. */ |
|
684 - if (cap.length != CAPABILITY_CODE_REFRESH_LEN) |
|
685 - { |
|
686 - zlog_info ("%s Route Refresh Capability length error %d", |
|
687 - peer->host, cap.length); |
|
688 - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
689 - return -1; |
|
690 - } |
|
691 - |
|
692 - if (BGP_DEBUG (normal, NORMAL)) |
|
693 - zlog_debug ("%s OPEN has ROUTE-REFRESH capability(%s) for all address-families", |
|
694 - peer->host, |
|
695 - cap.code == CAPABILITY_CODE_REFRESH_OLD ? "old" : "new"); |
|
696 - |
|
697 - /* BGP refresh capability */ |
|
698 - if (cap.code == CAPABILITY_CODE_REFRESH_OLD) |
|
699 - SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV); |
|
700 - else |
|
701 - SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV); |
|
702 - } |
|
703 - else if (cap.code == CAPABILITY_CODE_ORF |
|
704 - || cap.code == CAPABILITY_CODE_ORF_OLD) |
|
705 - bgp_capability_orf (peer, &cap, pnt + sizeof (struct capability)); |
|
706 - else if (cap.code == CAPABILITY_CODE_RESTART) |
|
707 - { |
|
708 - struct graceful_restart_af graf; |
|
709 - u_int16_t restart_flag_time; |
|
710 - int restart_bit = 0; |
|
711 - u_char *restart_pnt; |
|
712 - u_char *restart_end; |
|
713 - |
|
714 - /* Check length. */ |
|
715 - if (cap.length < CAPABILITY_CODE_RESTART_LEN) |
|
716 - { |
|
717 - zlog_info ("%s Graceful Restart Capability length error %d", |
|
718 - peer->host, cap.length); |
|
719 - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
720 - return -1; |
|
721 - } |
|
722 - |
|
723 - SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV); |
|
724 - restart_flag_time = ntohs(cap.mpc.afi); |
|
725 - if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT)) |
|
726 - restart_bit = 1; |
|
727 - UNSET_FLAG (restart_flag_time, 0xF000); |
|
728 - peer->v_gr_restart = restart_flag_time; |
|
729 - |
|
730 - if (BGP_DEBUG (normal, NORMAL)) |
|
731 - { |
|
732 - zlog_debug ("%s OPEN has Graceful Restart capability", peer->host); |
|
733 - zlog_debug ("%s Peer has%srestarted. Restart Time : %d", |
|
734 - peer->host, restart_bit ? " " : " not ", |
|
735 - peer->v_gr_restart); |
|
736 - } |
|
737 - |
|
738 - restart_pnt = pnt + 4; |
|
739 - restart_end = pnt + cap.length + 2; |
|
740 - |
|
741 - while (restart_pnt < restart_end) |
|
742 - { |
|
743 - memcpy (&graf, restart_pnt, sizeof (struct graceful_restart_af)); |
|
744 - |
|
745 - afi = ntohs(graf.afi); |
|
746 - safi = graf.safi; |
|
747 - |
|
748 - if (CHECK_FLAG (graf.flag, RESTART_F_BIT)) |
|
749 - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV); |
|
750 - |
|
751 - if (strcmp (afi_safi_print (afi, safi), "Unknown") == 0) |
|
752 - { |
|
753 - if (BGP_DEBUG (normal, NORMAL)) |
|
754 - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported. I gnore the Graceful Restart capability", |
|
755 - peer->host, afi, safi); |
|
756 - } |
|
757 - else if (! peer->afc[afi][safi]) |
|
758 - { |
|
759 - if (BGP_DEBUG (normal, NORMAL)) |
|
760 - zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled. Ignore the Graceful Restart capability", |
|
761 - peer->host, afi, safi); |
|
762 - } |
|
763 - else |
|
764 - { |
|
765 - if (BGP_DEBUG (normal, NORMAL)) |
|
766 - zlog_debug ("%s Address family %s is%spreserved", peer->host, |
|
767 - afi_safi_print (afi, safi), |
|
768 - CHECK_FLAG (peer->af_cap[afi][safi], |
|
769 - PEER_CAP_RESTART_AF_PRESERVE_RCV) |
|
770 - ? " " : " not "); |
|
771 - |
|
772 - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV); |
|
773 - } |
|
774 - restart_pnt += 4; |
|
775 - } |
|
776 - } |
|
777 - else if (cap.code == CAPABILITY_CODE_DYNAMIC) |
|
778 - { |
|
779 - /* Check length. */ |
|
780 - if (cap.length != CAPABILITY_CODE_DYNAMIC_LEN) |
|
781 - { |
|
782 - zlog_info ("%s Dynamic Capability length error %d", |
|
783 - peer->host, cap.length); |
|
784 - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
785 - return -1; |
|
786 - } |
|
787 - |
|
788 - if (BGP_DEBUG (normal, NORMAL)) |
|
789 - zlog_debug ("%s OPEN has DYNAMIC capability", peer->host); |
|
790 - |
|
791 - SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV); |
|
792 - } |
|
793 - |
|
794 - else if (cap.code > 128) |
|
795 - { |
|
796 - /* We don't send Notification for unknown vendor specific |
|
797 - capabilities. It seems reasonable for now... */ |
|
798 - zlog_warn ("%s Vendor specific capability %d", |
|
799 - peer->host, cap.code); |
|
800 - } |
|
801 - else |
|
802 - { |
|
803 - zlog_warn ("%s unrecognized capability code: %d - ignored", |
|
804 - peer->host, cap.code); |
|
805 - memcpy (*error, &cap, cap.length + 2); |
|
806 - *error += cap.length + 2; |
|
807 - } |
|
808 - |
|
809 - pnt += cap.length + 2; |
|
810 + |
|
811 + if (BGP_DEBUG (normal, NORMAL)) |
|
812 + zlog_debug ("%s OPEN has %s capability (%u), length %u", |
|
813 + peer->host, |
|
814 + LOOKUP (capcode_str, caphdr.code), |
|
815 + caphdr.code, caphdr.length); |
|
816 + |
|
817 + /* Length sanity check, type-specific, for known capabilities */ |
|
818 + switch (caphdr.code) |
|
819 + { |
|
820 + case CAPABILITY_CODE_MP: |
|
821 + case CAPABILITY_CODE_REFRESH: |
|
822 + case CAPABILITY_CODE_REFRESH_OLD: |
|
823 + case CAPABILITY_CODE_ORF: |
|
824 + case CAPABILITY_CODE_ORF_OLD: |
|
825 + case CAPABILITY_CODE_RESTART: |
|
826 + case CAPABILITY_CODE_DYNAMIC: |
|
827 + /* Check length. */ |
|
828 + if (caphdr.length < cap_minsizes[caphdr.code]) |
|
829 + { |
|
830 + zlog_info ("%s %s Capability length error: got %u," |
|
831 + " expected at least %u", |
|
832 + peer->host, |
|
833 + LOOKUP (capcode_str, caphdr.code), |
|
834 + caphdr.length, cap_minsizes[caphdr.code]); |
|
835 + bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
836 + return -1; |
|
837 + } |
|
838 + /* we deliberately ignore unknown codes, see below */ |
|
839 + default: |
|
840 + break; |
|
841 + } |
|
842 + |
|
843 + switch (caphdr.code) |
|
844 + { |
|
845 + case CAPABILITY_CODE_MP: |
|
846 + { |
|
847 + /* Ignore capability when override-capability is set. */ |
|
848 + if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) |
|
849 + { |
|
850 + /* Set negotiated value. */ |
|
851 + ret = bgp_capability_mp (peer, &caphdr); |
|
852 + |
|
853 + /* Unsupported Capability. */ |
|
854 + if (ret < 0) |
|
855 + { |
|
856 + /* Store return data. */ |
|
857 + memcpy (*error, sp, caphdr.length + 2); |
|
858 + *error += caphdr.length + 2; |
|
859 + } |
|
860 + } |
|
861 + } |
|
862 + break; |
|
863 + case CAPABILITY_CODE_REFRESH: |
|
864 + case CAPABILITY_CODE_REFRESH_OLD: |
|
865 + { |
|
866 + /* BGP refresh capability */ |
|
867 + if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD) |
|
868 + SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV); |
|
869 + else |
|
870 + SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV); |
|
871 + } |
|
872 + break; |
|
873 + case CAPABILITY_CODE_ORF: |
|
874 + case CAPABILITY_CODE_ORF_OLD: |
|
875 + if (bgp_capability_orf (peer, &caphdr)) |
|
876 + return -1; |
|
877 + break; |
|
878 + case CAPABILITY_CODE_RESTART: |
|
879 + if (bgp_capability_restart (peer, &caphdr)) |
|
880 + return -1; |
|
881 + break; |
|
882 + case CAPABILITY_CODE_DYNAMIC: |
|
883 + SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV); |
|
884 + break; |
|
885 + default: |
|
886 + if (caphdr.code > 128) |
|
887 + { |
|
888 + /* We don't send Notification for unknown vendor specific |
|
889 + capabilities. It seems reasonable for now... */ |
|
890 + zlog_warn ("%s Vendor specific capability %d", |
|
891 + peer->host, caphdr.code); |
|
892 + } |
|
893 + else |
|
894 + { |
|
895 + zlog_warn ("%s unrecognized capability code: %d - ignored", |
|
896 + peer->host, caphdr.code); |
|
897 + memcpy (*error, sp, caphdr.length + 2); |
|
898 + *error += caphdr.length + 2; |
|
899 + } |
|
900 + } |
|
901 + if (stream_get_getp(s) != (start + caphdr.length)) |
|
902 + { |
|
903 + if (stream_get_getp(s) > (start + caphdr.length)) |
|
904 + zlog_warn ("%s Cap-parser for %s read past cap-length, %u!", |
|
905 + peer->host, LOOKUP (capcode_str, caphdr.code), |
|
906 + caphdr.length); |
|
907 + stream_set_getp (s, start + caphdr.length); |
|
908 + } |
|
909 } |
|
910 return 0; |
|
911 } |
|
912 |
|
913 static int |
|
914 -bgp_auth_parse (struct peer *peer, u_char *pnt, size_t length) |
|
915 +bgp_auth_parse (struct peer *peer, size_t length) |
|
916 { |
|
917 bgp_notify_send (peer, |
|
918 BGP_NOTIFY_OPEN_ERR, |
|
919 @@ -530,30 +620,25 @@ int |
|
920 bgp_open_option_parse (struct peer *peer, u_char length, int *capability) |
|
921 { |
|
922 int ret; |
|
923 - u_char *end; |
|
924 - u_char opt_type; |
|
925 - u_char opt_length; |
|
926 - u_char *pnt; |
|
927 u_char *error; |
|
928 u_char error_data[BGP_MAX_PACKET_SIZE]; |
|
929 - |
|
930 - /* Fetch pointer. */ |
|
931 - pnt = stream_pnt (peer->ibuf); |
|
932 + struct stream *s = BGP_INPUT(peer); |
|
933 + size_t end = stream_get_getp (s) + length; |
|
934 |
|
935 ret = 0; |
|
936 - opt_type = 0; |
|
937 - opt_length = 0; |
|
938 - end = pnt + length; |
|
939 error = error_data; |
|
940 |
|
941 if (BGP_DEBUG (normal, NORMAL)) |
|
942 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u", |
|
943 peer->host, length); |
|
944 |
|
945 - while (pnt < end) |
|
946 + while (stream_get_getp(s) < end) |
|
947 { |
|
948 - /* Check the length. */ |
|
949 - if (pnt + 2 > end) |
|
950 + u_char opt_type; |
|
951 + u_char opt_length; |
|
952 + |
|
953 + /* Must have at least an OPEN option header */ |
|
954 + if (STREAM_READABLE(s) < 2) |
|
955 { |
|
956 zlog_info ("%s Option length error", peer->host); |
|
957 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
958 @@ -561,11 +646,11 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) |
|
959 } |
|
960 |
|
961 /* Fetch option type and length. */ |
|
962 - opt_type = *pnt++; |
|
963 - opt_length = *pnt++; |
|
964 + opt_type = stream_getc (s); |
|
965 + opt_length = stream_getc (s); |
|
966 |
|
967 /* Option length check. */ |
|
968 - if (pnt + opt_length > end) |
|
969 + if (STREAM_READABLE (s) < opt_length) |
|
970 { |
|
971 zlog_info ("%s Option length error", peer->host); |
|
972 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
973 @@ -582,10 +667,10 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) |
|
974 switch (opt_type) |
|
975 { |
|
976 case BGP_OPEN_OPT_AUTH: |
|
977 - ret = bgp_auth_parse (peer, pnt, opt_length); |
|
978 + ret = bgp_auth_parse (peer, opt_length); |
|
979 break; |
|
980 case BGP_OPEN_OPT_CAP: |
|
981 - ret = bgp_capability_parse (peer, pnt, opt_length, &error); |
|
982 + ret = bgp_capability_parse (peer, opt_length, &error); |
|
983 *capability = 1; |
|
984 break; |
|
985 default: |
|
986 @@ -602,9 +687,6 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability) |
|
987 error and erro_data pointer, like below. */ |
|
988 if (ret < 0) |
|
989 return -1; |
|
990 - |
|
991 - /* Forward pointer. */ |
|
992 - pnt += opt_length; |
|
993 } |
|
994 |
|
995 /* All OPEN option is parsed. Check capability when strict compare |
|
996 diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h |
|
997 index 7515d3f..436eb01 100644 |
|
998 --- bgpd/bgp_open.h |
|
999 +++ bgpd/bgp_open.h |
|
1000 @@ -21,21 +21,32 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
|
1001 #ifndef _QUAGGA_BGP_OPEN_H |
|
1002 #define _QUAGGA_BGP_OPEN_H |
|
1003 |
|
1004 -/* MP Capability information. */ |
|
1005 -struct capability_mp |
|
1006 +/* Standard header for capability TLV */ |
|
1007 +struct capability_header |
|
1008 +{ |
|
1009 + u_char code; |
|
1010 + u_char length; |
|
1011 +}; |
|
1012 + |
|
1013 +/* Generic MP capability data */ |
|
1014 +struct capability_mp_data |
|
1015 { |
|
1016 u_int16_t afi; |
|
1017 u_char reserved; |
|
1018 u_char safi; |
|
1019 }; |
|
1020 |
|
1021 -/* BGP open message capability. */ |
|
1022 -struct capability |
|
1023 +#pragma pack(1) |
|
1024 +struct capability_orf_entry |
|
1025 { |
|
1026 - u_char code; |
|
1027 - u_char length; |
|
1028 - struct capability_mp mpc; |
|
1029 -}; |
|
1030 + struct capability_mp_data mpc; |
|
1031 + u_char num; |
|
1032 + struct { |
|
1033 + u_char type; |
|
1034 + u_char mode; |
|
1035 + } orfs[]; |
|
1036 +} __attribute__ ((packed)); |
|
1037 +#pragma pack() |
|
1038 |
|
1039 struct graceful_restart_af |
|
1040 { |
|
1041 @@ -44,12 +55,18 @@ struct graceful_restart_af |
|
1042 u_char flag; |
|
1043 }; |
|
1044 |
|
1045 +struct capability_gr |
|
1046 +{ |
|
1047 + u_int16_t restart_flag_time; |
|
1048 + struct graceful_restart_af gr[]; |
|
1049 +}; |
|
1050 + |
|
1051 /* Capability Code */ |
|
1052 #define CAPABILITY_CODE_MP 1 /* Multiprotocol Extensions */ |
|
1053 #define CAPABILITY_CODE_REFRESH 2 /* Route Refresh Capability */ |
|
1054 #define CAPABILITY_CODE_ORF 3 /* Cooperative Route Filtering Capability */ |
|
1055 #define CAPABILITY_CODE_RESTART 64 /* Graceful Restart Capability */ |
|
1056 -#define CAPABILITY_CODE_4BYTE_AS 65 /* 4-octet AS number Capability */ |
|
1057 +#define CAPABILITY_CODE_AS4 65 /* 4-octet AS number Capability */ |
|
1058 #define CAPABILITY_CODE_DYNAMIC 66 /* Dynamic Capability */ |
|
1059 #define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */ |
|
1060 #define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */ |
|
1061 @@ -59,6 +76,7 @@ struct graceful_restart_af |
|
1062 #define CAPABILITY_CODE_REFRESH_LEN 0 |
|
1063 #define CAPABILITY_CODE_DYNAMIC_LEN 0 |
|
1064 #define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */ |
|
1065 +#define CAPABILITY_CODE_AS4_LEN 4 |
|
1066 |
|
1067 /* Cooperative Route Filtering Capability. */ |
|
1068 |
|
1069 @@ -82,5 +100,6 @@ struct graceful_restart_af |
|
1070 extern int bgp_open_option_parse (struct peer *, u_char, int *); |
|
1071 extern void bgp_open_capability (struct stream *, struct peer *); |
|
1072 extern void bgp_capability_vty_out (struct vty *, struct peer *); |
|
1073 +extern int bgp_afi_safi_valid_indices (afi_t, safi_t *); |
|
1074 |
|
1075 #endif /* _QUAGGA_BGP_OPEN_H */ |
|
1076 diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c |
|
1077 index 2653201..17ac1f7 100644 |
|
1078 --- bgpd/bgp_packet.c |
|
1079 +++ bgpd/bgp_packet.c |
|
1080 @@ -1371,8 +1371,6 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) |
|
1081 ret = bgp_open_option_parse (peer, optlen, &capability); |
|
1082 if (ret < 0) |
|
1083 return ret; |
|
1084 - |
|
1085 - stream_forward_getp (peer->ibuf, optlen); |
|
1086 } |
|
1087 else |
|
1088 { |
|
1089 @@ -1991,7 +1989,8 @@ static int |
|
1090 bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) |
|
1091 { |
|
1092 u_char *end; |
|
1093 - struct capability cap; |
|
1094 + struct capability_mp_data mpc; |
|
1095 + struct capability_header *hdr; |
|
1096 u_char action; |
|
1097 struct bgp *bgp; |
|
1098 afi_t afi; |
|
1099 @@ -2001,7 +2000,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) |
|
1100 end = pnt + length; |
|
1101 |
|
1102 while (pnt < end) |
|
1103 - { |
|
1104 + { |
|
1105 /* We need at least action, capability code and capability length. */ |
|
1106 if (pnt + 3 > end) |
|
1107 { |
|
1108 @@ -2009,12 +2008,9 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) |
|
1109 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
1110 return -1; |
|
1111 } |
|
1112 - |
|
1113 action = *pnt; |
|
1114 - |
|
1115 - /* Fetch structure to the byte stream. */ |
|
1116 - memcpy (&cap, pnt + 1, sizeof (struct capability)); |
|
1117 - |
|
1118 + hdr = (struct capability_header *)(pnt + 1); |
|
1119 + |
|
1120 /* Action value check. */ |
|
1121 if (action != CAPABILITY_ACTION_SET |
|
1122 && action != CAPABILITY_ACTION_UNSET) |
|
1123 @@ -2027,77 +2023,77 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) |
|
1124 |
|
1125 if (BGP_DEBUG (normal, NORMAL)) |
|
1126 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u", |
|
1127 - peer->host, action, cap.code, cap.length); |
|
1128 + peer->host, action, hdr->code, hdr->length); |
|
1129 |
|
1130 /* Capability length check. */ |
|
1131 - if (pnt + (cap.length + 3) > end) |
|
1132 + if ((pnt + hdr->length + 3) > end) |
|
1133 { |
|
1134 zlog_info ("%s Capability length error", peer->host); |
|
1135 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); |
|
1136 return -1; |
|
1137 } |
|
1138 |
|
1139 + /* Fetch structure to the byte stream. */ |
|
1140 + memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data)); |
|
1141 + |
|
1142 /* We know MP Capability Code. */ |
|
1143 - if (cap.code == CAPABILITY_CODE_MP) |
|
1144 + if (hdr->code == CAPABILITY_CODE_MP) |
|
1145 { |
|
1146 - afi = ntohs (cap.mpc.afi); |
|
1147 - safi = cap.mpc.safi; |
|
1148 + afi = ntohs (mpc.afi); |
|
1149 + safi = mpc.safi; |
|
1150 |
|
1151 /* Ignore capability when override-capability is set. */ |
|
1152 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) |
|
1153 continue; |
|
1154 - |
|
1155 + |
|
1156 + if (!bgp_afi_safi_valid_indices (afi, &safi)) |
|
1157 + { |
|
1158 + if (BGP_DEBUG (normal, NORMAL)) |
|
1159 + zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid", |
|
1160 + peer->host, afi, safi); |
|
1161 + continue; |
|
1162 + } |
|
1163 + |
|
1164 /* Address family check. */ |
|
1165 - if ((afi == AFI_IP |
|
1166 - || afi == AFI_IP6) |
|
1167 - && (safi == SAFI_UNICAST |
|
1168 - || safi == SAFI_MULTICAST |
|
1169 - || safi == BGP_SAFI_VPNV4)) |
|
1170 - { |
|
1171 - if (BGP_DEBUG (normal, NORMAL)) |
|
1172 - zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u", |
|
1173 - peer->host, |
|
1174 - action == CAPABILITY_ACTION_SET |
|
1175 - ? "Advertising" : "Removing", |
|
1176 - ntohs(cap.mpc.afi) , cap.mpc.safi); |
|
1177 - |
|
1178 - /* Adjust safi code. */ |
|
1179 - if (safi == BGP_SAFI_VPNV4) |
|
1180 - safi = SAFI_MPLS_VPN; |
|
1181 - |
|
1182 - if (action == CAPABILITY_ACTION_SET) |
|
1183 - { |
|
1184 - peer->afc_recv[afi][safi] = 1; |
|
1185 - if (peer->afc[afi][safi]) |
|
1186 - { |
|
1187 - peer->afc_nego[afi][safi] = 1; |
|
1188 - bgp_announce_route (peer, afi, safi); |
|
1189 - } |
|
1190 - } |
|
1191 - else |
|
1192 - { |
|
1193 - peer->afc_recv[afi][safi] = 0; |
|
1194 - peer->afc_nego[afi][safi] = 0; |
|
1195 - |
|
1196 - if (peer_active_nego (peer)) |
|
1197 - bgp_clear_route (peer, afi, safi); |
|
1198 - else |
|
1199 - BGP_EVENT_ADD (peer, BGP_Stop); |
|
1200 - } |
|
1201 - } |
|
1202 + if (BGP_DEBUG (normal, NORMAL)) |
|
1203 + zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u", |
|
1204 + peer->host, |
|
1205 + action == CAPABILITY_ACTION_SET |
|
1206 + ? "Advertising" : "Removing", |
|
1207 + ntohs(mpc.afi) , mpc.safi); |
|
1208 + |
|
1209 + if (action == CAPABILITY_ACTION_SET) |
|
1210 + { |
|
1211 + peer->afc_recv[afi][safi] = 1; |
|
1212 + if (peer->afc[afi][safi]) |
|
1213 + { |
|
1214 + peer->afc_nego[afi][safi] = 1; |
|
1215 + bgp_announce_route (peer, afi, safi); |
|
1216 + } |
|
1217 + } |
|
1218 + else |
|
1219 + { |
|
1220 + peer->afc_recv[afi][safi] = 0; |
|
1221 + peer->afc_nego[afi][safi] = 0; |
|
1222 + |
|
1223 + if (peer_active_nego (peer)) |
|
1224 + bgp_clear_route (peer, afi, safi); |
|
1225 + else |
|
1226 + BGP_EVENT_ADD (peer, BGP_Stop); |
|
1227 + } |
|
1228 } |
|
1229 else |
|
1230 { |
|
1231 zlog_warn ("%s unrecognized capability code: %d - ignored", |
|
1232 - peer->host, cap.code); |
|
1233 + peer->host, hdr->code); |
|
1234 } |
|
1235 - pnt += cap.length + 3; |
|
1236 + pnt += hdr->length + 3; |
|
1237 } |
|
1238 return 0; |
|
1239 } |
|
1240 |
|
1241 /* Dynamic Capability is received. */ |
|
1242 -static void |
|
1243 +int |
|
1244 bgp_capability_receive (struct peer *peer, bgp_size_t size) |
|
1245 { |
|
1246 u_char *pnt; |
|
1247 @@ -2130,7 +2126,7 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size) |
|
1248 } |
|
1249 |
|
1250 /* Parse packet. */ |
|
1251 - ret = bgp_capability_msg_parse (peer, pnt, size); |
|
1252 + return bgp_capability_msg_parse (peer, pnt, size); |
|
1253 } |
|
1254 |
|
1255 /* BGP read utility function. */ |
|
1256 diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c |
|
1257 index 1e21c74..3eeb5f9 100644 |
|
1258 --- bgpd/bgp_vty.c |
|
1259 +++ bgpd/bgp_vty.c |
|
1260 @@ -6681,14 +6681,14 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi) |
|
1261 |
|
1262 vty_out (vty, "4 "); |
|
1263 |
|
1264 - vty_out (vty, "%5d %7d %7d %8d %4d %4ld ", |
|
1265 + vty_out (vty, "%5d %7d %7d %8d %4d %4lu ", |
|
1266 peer->as, |
|
1267 peer->open_in + peer->update_in + peer->keepalive_in |
|
1268 + peer->notify_in + peer->refresh_in + peer->dynamic_cap_in, |
|
1269 peer->open_out + peer->update_out + peer->keepalive_out |
|
1270 + peer->notify_out + peer->refresh_out |
|
1271 + peer->dynamic_cap_out, |
|
1272 - 0, 0, peer->obuf->count); |
|
1273 + 0, 0, (unsigned long)peer->obuf->count); |
|
1274 |
|
1275 vty_out (vty, "%8s", |
|
1276 peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN)); |
|
1277 @@ -7403,7 +7403,7 @@ bgp_show_peer (struct vty *vty, struct peer *p) |
|
1278 /* Packet counts. */ |
|
1279 vty_out (vty, " Message statistics:%s", VTY_NEWLINE); |
|
1280 vty_out (vty, " Inq depth is 0%s", VTY_NEWLINE); |
|
1281 - vty_out (vty, " Outq depth is %ld%s", p->obuf->count, VTY_NEWLINE); |
|
1282 + vty_out (vty, " Outq depth is %lu%s", (unsigned long)p->obuf->count, VTY_NEWLINE); |
|
1283 vty_out (vty, " Sent Rcvd%s", VTY_NEWLINE); |
|
1284 vty_out (vty, " Opens: %10d %10d%s", p->open_out, p->open_in, VTY_NEWLINE); |
|
1285 vty_out (vty, " Notifications: %10d %10d%s", p->notify_out, p->notify_in, VTY_NEWLINE); |
|
1286 diff --git a/lib/log.c b/lib/log.c |
|
1287 index cbf76af..ff47cae 100644 |
|
1288 --- lib/log.c |
|
1289 +++ lib/log.c |
|
1290 @@ -769,7 +769,7 @@ mes_lookup (struct message *meslist, int max, int index) |
|
1291 { |
|
1292 if (meslist->key == index) |
|
1293 { |
|
1294 - zlog_warn("message index %d [%s] found in position %d (max is %d)", |
|
1295 + zlog_debug ("message index %d [%s] found in position %d (max is %d)", |
|
1296 index, meslist->str, i, max); |
|
1297 return meslist->str; |
|
1298 } |
|