blob: 020dfb0f7fabb7e0c953ac13cee77646c89c9ca3 [file] [log] [blame]
Paul Jakmaed6ef902007-08-08 14:13:03 +00001#include <zebra.h>
2
3#include "vty.h"
4#include "stream.h"
5#include "privs.h"
6#include "memory.h"
7
8#include "bgpd/bgpd.h"
9#include "bgpd/bgp_open.h"
10#include "bgpd/bgp_debug.h"
11
Paul Jakmae08286b2007-09-18 12:11:26 +000012#define VT100_RESET "\x1b[0m"
13#define VT100_RED "\x1b[31m"
14#define VT100_GREEN "\x1b[32m"
15#define VT100_YELLOW "\x1b[33m"
16
17
Paul Jakmaed6ef902007-08-08 14:13:03 +000018#define OPEN 0
19#define DYNCAP 1
20
21/* need these to link in libbgp */
22struct zebra_privs_t *bgpd_privs = NULL;
23struct thread_master *master = NULL;
24
25static int failed = 0;
Paul Jakmae08286b2007-09-18 12:11:26 +000026static int tty = 0;
Paul Jakmaed6ef902007-08-08 14:13:03 +000027
28/* test segments to parse and validate, and use for other tests */
29static struct test_segment {
30 const char *name;
31 const char *desc;
32 const u_char data[1024];
33 int len;
34#define SHOULD_PARSE 0
35#define SHOULD_ERR -1
36 int parses; /* whether it should parse or not */
Paul Jakmae08286b2007-09-18 12:11:26 +000037
38 /* AFI/SAFI validation */
39 int validate_afi;
40 afi_t afi;
41 safi_t safi;
42#define VALID_AFI 1
43#define INVALID_AFI 0
44 int afi_valid;
Paul Jakmaed6ef902007-08-08 14:13:03 +000045} test_segments [] =
46{
47 /* 0 */
48 { "caphdr",
49 "capability header, and no more",
50 { CAPABILITY_CODE_REFRESH, 0x0 },
51 2, SHOULD_PARSE,
52 },
53 /* 1 */
54 { "nodata",
55 "header, no data but length says there is",
56 { 0x1, 0xa },
57 2, SHOULD_ERR,
58 },
59 /* 2 */
60 { "padded",
61 "valid, with padding",
62 { CAPABILITY_CODE_REFRESH, 0x2, 0x0, 0x0 },
63 4, SHOULD_PARSE,
64 },
65 /* 3 */
66 { "minsize",
67 "violates minsize requirement",
68 { CAPABILITY_CODE_ORF, 0x2, 0x0, 0x0 },
69 4, SHOULD_ERR,
70 },
Paul Jakmae08286b2007-09-18 12:11:26 +000071 { NULL, NULL, {0}, 0, 0},
72};
73
74static struct test_segment mp_segments[] =
75{
76 { "MP4",
Paul Jakmaed6ef902007-08-08 14:13:03 +000077 "MP IP/Uni",
78 { 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 },
Paul Jakmae08286b2007-09-18 12:11:26 +000079 6, SHOULD_PARSE, AFI_IP, SAFI_UNICAST,
80 },
81 { "MPv6",
82 "MP IPv6/Uni",
83 { 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 },
84 6, SHOULD_PARSE,
85 1, AFI_IP6, SAFI_UNICAST, VALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +000086 },
87 /* 5 */
88 { "MP2",
89 "MP IP/Multicast",
90 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2 },
Paul Jakmae08286b2007-09-18 12:11:26 +000091 6, SHOULD_PARSE,
92 1, AFI_IP, SAFI_MULTICAST, VALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +000093 },
94 /* 6 */
95 { "MP3",
96 "MP IP6/VPNv4",
97 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 },
98 6, SHOULD_PARSE, /* parses, but invalid afi,safi */
Paul Jakmae08286b2007-09-18 12:11:26 +000099 1, AFI_IP6, BGP_SAFI_VPNV4, INVALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +0000100 },
101 /* 7 */
102 { "MP5",
103 "MP IP6/MPLS-VPN",
104 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 },
Paul Jakmae08286b2007-09-18 12:11:26 +0000105 6, SHOULD_PARSE,
106 1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +0000107 },
108 /* 8 */
109 { "MP6",
110 "MP IP4/VPNv4",
111 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 },
Paul Jakmae08286b2007-09-18 12:11:26 +0000112 6, SHOULD_PARSE,
113 1, AFI_IP, BGP_SAFI_VPNV4, VALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +0000114 },
115 /* 9 */
116 { "MP7",
117 "MP IP4/VPNv6",
118 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x81 },
Paul Jakmae08286b2007-09-18 12:11:26 +0000119 6, SHOULD_PARSE, /* parses, but invalid afi,safi tuple */
120 1, AFI_IP, BGP_SAFI_VPNV6, INVALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +0000121 },
122 /* 10 */
123 { "MP8",
124 "MP unknown AFI",
125 { CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81 },
Paul Jakmae08286b2007-09-18 12:11:26 +0000126 6, SHOULD_PARSE,
127 1, 0xa, 0x81, INVALID_AFI, /* parses, but unknown */
Paul Jakmaed6ef902007-08-08 14:13:03 +0000128 },
129 /* 11 */
130 { "MP-short",
131 "MP IP4/Unicast, length too short (< minimum)",
132 { CAPABILITY_CODE_MP, 0x2, 0x0, 0x1, 0x0, 0x1 },
133 6, SHOULD_ERR,
134 },
135 /* 12 */
136 { "MP-overflow",
137 "MP IP4/Unicast, length too long",
138 { CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1 },
139 6, SHOULD_ERR,
Paul Jakmae08286b2007-09-18 12:11:26 +0000140 1, AFI_IP, SAFI_UNICAST, VALID_AFI,
Paul Jakmaed6ef902007-08-08 14:13:03 +0000141 },
Paul Jakmae08286b2007-09-18 12:11:26 +0000142 { NULL, NULL, {0}, 0, 0}
143};
144
145static struct test_segment misc_segments[] =
146{
Paul Jakmaed6ef902007-08-08 14:13:03 +0000147 /* 13 */
148 { "ORF",
149 "ORF, simple, single entry, single tuple",
150 { /* hdr */ CAPABILITY_CODE_ORF, 0x7,
151 /* mpc */ 0x0, 0x1, 0x0, 0x1,
152 /* num */ 0x1,
153 /* tuples */ 0x40, 0x3
154 },
155 9, SHOULD_PARSE,
156 },
157 /* 14 */
158 { "ORF-many",
159 "ORF, multi entry/tuple",
160 { /* hdr */ CAPABILITY_CODE_ORF, 0x21,
161 /* mpc */ 0x0, 0x1, 0x0, 0x1,
162 /* num */ 0x3,
163 /* tuples */ 0x40, ORF_MODE_BOTH,
164 0x80, ORF_MODE_RECEIVE,
165 0x80, ORF_MODE_SEND,
166 /* mpc */ 0x0, 0x2, 0x0, 0x1,
167 /* num */ 0x3,
168 /* tuples */ 0x40, ORF_MODE_BOTH,
169 0x80, ORF_MODE_RECEIVE,
170 0x80, ORF_MODE_SEND,
171 /* mpc */ 0x0, 0x2, 0x0, 0x2,
172 /* num */ 0x3,
173 /* tuples */ 0x40, ORF_MODE_RECEIVE,
174 0x80, ORF_MODE_SEND,
175 0x80, ORF_MODE_BOTH,
176 },
177 35, SHOULD_PARSE,
178 },
179 /* 15 */
180 { "ORFlo",
181 "ORF, multi entry/tuple, hdr length too short",
182 { /* hdr */ CAPABILITY_CODE_ORF, 0x15,
183 /* mpc */ 0x0, 0x1, 0x0, 0x1,
184 /* num */ 0x3,
185 /* tuples */ 0x40, 0x3,
186 0x80, 0x1,
187 0x80, 0x2,
188 /* mpc */ 0x0, 0x1, 0x0, 0x1,
189 /* num */ 0x3,
190 /* tuples */ 0x40, 0x3,
191 0x80, 0x1,
192 0x80, 0x2,
193 /* mpc */ 0x0, 0x2, 0x0, 0x2,
194 /* num */ 0x3,
195 /* tuples */ 0x40, 0x3,
196 0x80, 0x1,
197 0x80, 0x2,
198 },
199 35, SHOULD_ERR, /* It should error on invalid Route-Refresh.. */
200 },
201 /* 16 */
202 { "ORFlu",
203 "ORF, multi entry/tuple, length too long",
204 { /* hdr */ 0x3, 0x22,
205 /* mpc */ 0x0, 0x1, 0x0, 0x1,
206 /* num */ 0x3,
207 /* tuples */ 0x40, 0x3,
208 0x80, 0x1,
209 0x80, 0x2,
210 /* mpc */ 0x0, 0x2, 0x0, 0x1,
211 /* num */ 0x3,
212 /* tuples */ 0x40, 0x3,
213 0x80, 0x1,
214 0x80, 0x2,
215 /* mpc */ 0x0, 0x2, 0x0, 0x2,
216 /* num */ 0x3,
217 /* tuples */ 0x40, 0x3,
218 0x80, 0x1,
219 0x80, 0x2,
220 },
221 35, SHOULD_ERR
222 },
223 /* 17 */
224 { "ORFnu",
225 "ORF, multi entry/tuple, entry number too long",
226 { /* hdr */ 0x3, 0x21,
227 /* mpc */ 0x0, 0x1, 0x0, 0x1,
228 /* num */ 0x3,
229 /* tuples */ 0x40, 0x3,
230 0x80, 0x1,
231 0x80, 0x2,
232 /* mpc */ 0x0, 0x2, 0x0, 0x1,
233 /* num */ 0x4,
234 /* tuples */ 0x40, 0x3,
235 0x80, 0x1,
236 0x80, 0x2,
237 /* mpc */ 0x0, 0x2, 0x0, 0x2,
238 /* num */ 0x3,
239 /* tuples */ 0x40, 0x3,
240 0x80, 0x1,
241 0x80, 0x2,
242 },
243 35, SHOULD_PARSE, /* parses, but last few tuples should be gibberish */
244 },
245 /* 18 */
246 { "ORFno",
247 "ORF, multi entry/tuple, entry number too short",
248 { /* hdr */ 0x3, 0x21,
249 /* mpc */ 0x0, 0x1, 0x0, 0x1,
250 /* num */ 0x3,
251 /* tuples */ 0x40, 0x3,
252 0x80, 0x1,
253 0x80, 0x2,
254 /* mpc */ 0x0, 0x2, 0x0, 0x1,
255 /* num */ 0x1,
256 /* tuples */ 0x40, 0x3,
257 0x80, 0x1,
258 0x80, 0x2,
259 /* mpc */ 0x0, 0x2, 0x0, 0x2,
260 /* num */ 0x3,
261 /* tuples */ 0x40, 0x3,
262 0x80, 0x1,
263 0x80, 0x2,
264 },
265 35, SHOULD_PARSE, /* Parses, but should get gibberish afi/safis */
266 },
267 /* 17 */
268 { "ORFpad",
269 "ORF, multi entry/tuple, padded to align",
270 { /* hdr */ 0x3, 0x22,
271 /* mpc */ 0x0, 0x1, 0x0, 0x1,
272 /* num */ 0x3,
273 /* tuples */ 0x40, 0x3,
274 0x80, 0x1,
275 0x80, 0x2,
276 /* mpc */ 0x0, 0x2, 0x0, 0x1,
277 /* num */ 0x3,
278 /* tuples */ 0x40, 0x3,
279 0x80, 0x1,
280 0x80, 0x2,
281 /* mpc */ 0x0, 0x2, 0x0, 0x2,
282 /* num */ 0x3,
283 /* tuples */ 0x40, 0x3,
284 0x80, 0x1,
285 0x80, 0x2,
286 0x00,
287 },
288 36, SHOULD_PARSE,
289 },
290 /* 19 */
291 { "AS4",
292 "AS4 capability",
293 { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 },
294 6, SHOULD_PARSE,
295 },
296 /* 20 */
297 { "GR",
298 "GR capability",
299 { /* hdr */ CAPABILITY_CODE_RESTART, 0xe,
300 /* R-bit, time */ 0xf1, 0x12,
301 /* afi */ 0x0, 0x1,
302 /* safi */ 0x1,
303 /* flags */ 0xf,
304 /* afi */ 0x0, 0x2,
305 /* safi */ 0x1,
306 /* flags */ 0x0,
307 /* afi */ 0x0, 0x2,
308 /* safi */ 0x2,
309 /* flags */ 0x1,
310 },
311 16, SHOULD_PARSE,
312 },
313 /* 21 */
314 { "GR-short",
315 "GR capability, but header length too short",
316 { /* hdr */ 0x40, 0xa,
317 /* R-bit, time */ 0xf1, 0x12,
318 /* afi */ 0x0, 0x1,
319 /* safi */ 0x1,
320 /* flags */ 0xf,
321 /* afi */ 0x0, 0x2,
322 /* safi */ 0x1,
323 /* flags */ 0x0,
324 /* afi */ 0x0, 0x2,
325 /* safi */ 0x2,
326 /* flags */ 0x1,
327 },
328 16, SHOULD_PARSE,
329 },
330 /* 22 */
331 { "GR-long",
332 "GR capability, but header length too long",
333 { /* hdr */ 0x40, 0xf,
334 /* R-bit, time */ 0xf1, 0x12,
335 /* afi */ 0x0, 0x1,
336 /* safi */ 0x1,
337 /* flags */ 0xf,
338 /* afi */ 0x0, 0x2,
339 /* safi */ 0x1,
340 /* flags */ 0x0,
341 /* afi */ 0x0, 0x2,
342 /* safi */ 0x2,
343 },
344 16, SHOULD_ERR,
345 },
346 { "GR-trunc",
347 "GR capability, but truncated",
348 { /* hdr */ 0x40, 0xf,
349 /* R-bit, time */ 0xf1, 0x12,
350 /* afi */ 0x0, 0x1,
351 /* safi */ 0x1,
352 /* flags */ 0xf,
353 /* afi */ 0x0, 0x2,
354 /* safi */ 0x1,
355 /* flags */ 0x0,
356 /* afi */ 0x0, 0x2,
357 /* safi */ 0x2,
358 /* flags */ 0x1,
359 },
360 15, SHOULD_ERR,
361 },
362 { "dyn-old",
363 "Dynamic capability (deprecated version)",
364 { CAPABILITY_CODE_DYNAMIC, 0x0 },
365 2, SHOULD_PARSE,
366 },
367 { NULL, NULL, {0}, 0, 0}
368};
369
370
371struct test_segment dynamic_cap_msgs[] =
372{
373 { "DynCap",
374 "Dynamic Capability Message, IP/Multicast",
375 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
376 7, SHOULD_PARSE, /* horrible alignment, just as with ORF */
377 },
378 { "DynCapLong",
379 "Dynamic Capability Message, IP/Multicast, truncated",
380 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
381 5, SHOULD_ERR,
382 },
383 { "DynCapPadded",
384 "Dynamic Capability Message, IP/Multicast, padded",
385 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0 },
386 8, SHOULD_ERR, /* No way to tell padding from data.. */
387 },
388 { "DynCapMPCpadded",
389 "Dynamic Capability Message, IP/Multicast, cap data padded",
390 { 0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0 },
391 8, SHOULD_PARSE, /* You can though add padding to the capability data */
392 },
393 { "DynCapMPCoverflow",
394 "Dynamic Capability Message, IP/Multicast, cap data != length",
395 { 0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0 },
396 8, SHOULD_ERR,
397 },
398 { NULL, NULL, {0}, 0, 0}
399};
400/* basic parsing test */
401static void
402parse_test (struct peer *peer, struct test_segment *t, int type)
403{
404 int ret;
405 int capability = 0;
Paul Jakmae08286b2007-09-18 12:11:26 +0000406 int oldfailed = failed;
Paul Jakmaed6ef902007-08-08 14:13:03 +0000407
408 stream_reset (peer->ibuf);
409 switch (type)
410 {
411 case OPEN:
412 stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP);
413 stream_putc (peer->ibuf, t->len);
414 break;
415 case DYNCAP:
416/* for (i = 0; i < BGP_MARKER_SIZE; i++)
417 stream_putc (peer->, 0xff);
418 stream_putw (s, 0);
419 stream_putc (s, BGP_MSG_CAPABILITY);*/
420 break;
421 }
422 stream_write (peer->ibuf, t->data, t->len);
423
424 printf ("%s: %s\n", t->name, t->desc);
425
426 switch (type)
427 {
428 case OPEN:
429 ret = bgp_open_option_parse (peer, t->len + 2, &capability);
430 break;
431 case DYNCAP:
432 ret = bgp_capability_receive (peer, t->len);
433 break;
434 default:
435 printf ("unknown type %u\n", type);
436 exit(1);
437 }
438
Paul Jakmae08286b2007-09-18 12:11:26 +0000439 if (!ret && t->validate_afi)
440 {
441 safi_t safi = t->safi;
442
443 if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid)
444 failed++;
445
446 printf ("MP: %u/%u (%u): recv %u, nego %u\n",
447 t->afi, t->safi, safi,
448 peer->afc_recv[t->afi][safi],
449 peer->afc_nego[t->afi][safi]);
450
451 if (t->afi_valid == VALID_AFI)
452 {
453
454 if (!peer->afc_recv[t->afi][safi])
455 failed++;
456 if (!peer->afc_nego[t->afi][safi])
457 failed++;
458 }
459 }
460
Paul Jakmaed6ef902007-08-08 14:13:03 +0000461 printf ("parsed?: %s\n", ret ? "no" : "yes");
462
Paul Jakmae08286b2007-09-18 12:11:26 +0000463 if (ret != t->parses)
464 failed++;
465
466 if (tty)
467 printf ("%s\n", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET
468 : VT100_GREEN "OK" VT100_RESET);
Paul Jakmaed6ef902007-08-08 14:13:03 +0000469 else
Paul Jakmae08286b2007-09-18 12:11:26 +0000470 printf ("%s\n", (failed > oldfailed) ? "failed!" : "OK" );
Paul Jakmaed6ef902007-08-08 14:13:03 +0000471
472 printf ("\n");
473}
474
475static struct bgp *bgp;
476static as_t asn = 100;
477
478int
479main (void)
480{
481 struct peer *peer;
482 int i, j;
483
484 conf_bgp_debug_fsm = -1UL;
485 conf_bgp_debug_events = -1UL;
486 conf_bgp_debug_packet = -1UL;
487 conf_bgp_debug_normal = -1UL;
488 term_bgp_debug_fsm = -1UL;
489 term_bgp_debug_events = -1UL;
490 term_bgp_debug_packet = -1UL;
491 term_bgp_debug_normal = -1UL;
492
493 master = thread_master_create ();
494 bgp_master_init ();
495
Paul Jakmae08286b2007-09-18 12:11:26 +0000496 if (fileno (stdout) >= 0)
497 tty = isatty (fileno (stdout));
498
Paul Jakmaed6ef902007-08-08 14:13:03 +0000499 if (bgp_get (&bgp, &asn, NULL))
500 return -1;
501
502 peer = peer_create_accept (bgp);
503
504 for (i = AFI_IP; i < AFI_MAX; i++)
505 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
Paul Jakmae08286b2007-09-18 12:11:26 +0000506 {
507 peer->afc[i][j] = 1;
508 peer->afc_adv[i][j] = 1;
509 }
Paul Jakmaed6ef902007-08-08 14:13:03 +0000510
Paul Jakmae08286b2007-09-18 12:11:26 +0000511 i = 0;
512 while (mp_segments[i].name)
513 parse_test (peer, &mp_segments[i++], OPEN);
514
515 /* These tests assume mp_segments tests set at least
516 * one of the afc_nego's
517 */
518 i = 0;
Paul Jakmaed6ef902007-08-08 14:13:03 +0000519 while (test_segments[i].name)
520 parse_test (peer, &test_segments[i++], OPEN);
521
Paul Jakmae08286b2007-09-18 12:11:26 +0000522 i = 0;
523 while (misc_segments[i].name)
524 parse_test (peer, &misc_segments[i++], OPEN);
525
Paul Jakmaed6ef902007-08-08 14:13:03 +0000526 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
527 peer->status = Established;
528
529 i = 0;
530 while (dynamic_cap_msgs[i].name)
531 parse_test (peer, &dynamic_cap_msgs[i++], DYNCAP);
532
533 printf ("failures: %d\n", failed);
534 return failed;
535}