]>
Commit | Line | Data |
---|---|---|
d62a17ae | 1 | /* |
46f4a4d2 PJ |
2 | * Copyright (C) 2007 Sun Microsystems, Inc. |
3 | * | |
4 | * This file is part of Quagga. | |
5 | * | |
6 | * Quagga is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2, or (at your option) any | |
9 | * later version. | |
10 | * | |
11 | * Quagga 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 | |
46f4a4d2 PJ |
19 | */ |
20 | ||
ed6ef902 PJ |
21 | #include <zebra.h> |
22 | ||
1bf9f027 | 23 | #include "qobj.h" |
ed6ef902 PJ |
24 | #include "vty.h" |
25 | #include "stream.h" | |
26 | #include "privs.h" | |
27 | #include "memory.h" | |
3f9c7369 | 28 | #include "queue.h" |
039f3a34 | 29 | #include "filter.h" |
ed6ef902 PJ |
30 | |
31 | #include "bgpd/bgpd.h" | |
32 | #include "bgpd/bgp_open.h" | |
33 | #include "bgpd/bgp_debug.h" | |
1dba254e | 34 | #include "bgpd/bgp_packet.h" |
ed6ef902 | 35 | |
e08286bc PJ |
36 | #define VT100_RESET "\x1b[0m" |
37 | #define VT100_RED "\x1b[31m" | |
38 | #define VT100_GREEN "\x1b[32m" | |
39 | #define VT100_YELLOW "\x1b[33m" | |
40 | ||
0b2aa3a0 PJ |
41 | #define CAPABILITY 0 |
42 | #define DYNCAP 1 | |
43 | #define OPT_PARAM 2 | |
ed6ef902 PJ |
44 | |
45 | /* need these to link in libbgp */ | |
46 | struct zebra_privs_t *bgpd_privs = NULL; | |
47 | struct thread_master *master = NULL; | |
48 | ||
49 | static int failed = 0; | |
e08286bc | 50 | static int tty = 0; |
ed6ef902 PJ |
51 | |
52 | /* test segments to parse and validate, and use for other tests */ | |
53 | static struct test_segment { | |
d62a17ae | 54 | const char *name; |
55 | const char *desc; | |
56 | const u_char data[1024]; | |
57 | int len; | |
ed6ef902 PJ |
58 | #define SHOULD_PARSE 0 |
59 | #define SHOULD_ERR -1 | |
d62a17ae | 60 | int parses; /* whether it should parse or not */ |
61 | as_t peek_for; /* what peek_for_as4_capability should say */ | |
62 | ||
63 | /* AFI/SAFI validation */ | |
64 | int validate_afi; | |
65 | afi_t afi; | |
66 | safi_t safi; | |
e08286bc PJ |
67 | #define VALID_AFI 1 |
68 | #define INVALID_AFI 0 | |
d62a17ae | 69 | int afi_valid; |
70 | } test_segments[] = { | |
71 | /* 0 */ | |
72 | { | |
73 | "caphdr", | |
74 | "capability header, and no more", | |
75 | {CAPABILITY_CODE_REFRESH, 0x0}, | |
76 | 2, | |
77 | SHOULD_PARSE, | |
78 | }, | |
79 | /* 1 */ | |
80 | { | |
81 | "nodata", | |
82 | "header, no data but length says there is", | |
83 | {0x1, 0xa}, | |
84 | 2, | |
85 | SHOULD_ERR, | |
86 | }, | |
87 | /* 2 */ | |
88 | { | |
89 | "padded", | |
90 | "valid, with padding", | |
91 | {CAPABILITY_CODE_REFRESH, 0x2, 0x0, 0x0}, | |
92 | 4, | |
93 | SHOULD_PARSE, | |
94 | }, | |
95 | /* 3 */ | |
96 | { | |
97 | "minsize", | |
98 | "violates minsize requirement", | |
99 | {CAPABILITY_CODE_ORF, 0x2, 0x0, 0x0}, | |
100 | 4, | |
101 | SHOULD_ERR, | |
102 | }, | |
103 | {NULL, NULL, {0}, 0, 0}, | |
e08286bc PJ |
104 | }; |
105 | ||
d62a17ae | 106 | static struct test_segment mp_segments[] = { |
107 | { | |
108 | "MP4", | |
109 | "MP IP/Uni", | |
110 | {0x1, 0x4, 0x0, 0x1, 0x0, 0x1}, | |
111 | 6, | |
112 | SHOULD_PARSE, | |
113 | 0, | |
114 | 1, | |
115 | AFI_IP, | |
116 | SAFI_UNICAST, | |
117 | VALID_AFI, | |
118 | }, | |
119 | { | |
120 | "MPv6", | |
121 | "MP IPv6/Uni", | |
122 | {0x1, 0x4, 0x0, 0x2, 0x0, 0x1}, | |
123 | 6, | |
124 | SHOULD_PARSE, | |
125 | 0, | |
126 | 1, | |
127 | AFI_IP6, | |
128 | SAFI_UNICAST, | |
129 | VALID_AFI, | |
130 | }, | |
131 | /* 5 */ | |
132 | { | |
133 | "MP2", | |
134 | "MP IP/Multicast", | |
135 | {CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2}, | |
136 | 6, | |
137 | SHOULD_PARSE, | |
138 | 0, | |
139 | 1, | |
140 | AFI_IP, | |
141 | SAFI_MULTICAST, | |
142 | VALID_AFI, | |
143 | }, | |
144 | /* 6 */ | |
145 | { | |
146 | "MP3", | |
147 | "MP IP6/MPLS-labeled VPN", | |
148 | {CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80}, | |
149 | 6, | |
150 | SHOULD_PARSE, | |
151 | 0, | |
152 | 1, | |
153 | AFI_IP6, | |
154 | IANA_SAFI_MPLS_VPN, | |
155 | VALID_AFI, | |
156 | }, | |
157 | /* 7 */ | |
158 | { | |
159 | "MP5", | |
160 | "MP IP6/MPLS-VPN", | |
161 | {CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4}, | |
162 | 6, | |
163 | SHOULD_PARSE, | |
164 | 0, | |
165 | 1, | |
166 | AFI_IP6, | |
167 | IANA_SAFI_MPLS_VPN, | |
168 | VALID_AFI, | |
169 | }, | |
170 | /* 8 */ | |
171 | { | |
172 | "MP6", | |
399aedd6 | 173 | "MP IP4/MPLS-labeled VPN", |
d62a17ae | 174 | {CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80}, |
175 | 6, | |
176 | SHOULD_PARSE, | |
177 | 0, | |
178 | 1, | |
179 | AFI_IP, | |
180 | IANA_SAFI_MPLS_VPN, | |
181 | VALID_AFI, | |
182 | }, | |
183 | /* 10 */ | |
184 | { | |
185 | "MP8", | |
186 | "MP unknown AFI/SAFI", | |
187 | {CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81}, | |
188 | 6, | |
189 | SHOULD_PARSE, | |
190 | 0, | |
191 | 1, | |
192 | 0xa, | |
193 | 0x81, | |
194 | INVALID_AFI, /* parses, but unknown */ | |
195 | }, | |
196 | /* 11 */ | |
197 | { | |
198 | "MP-short", | |
199 | "MP IP4/Unicast, length too short (< minimum)", | |
200 | {CAPABILITY_CODE_MP, 0x2, 0x0, 0x1, 0x0, 0x1}, | |
201 | 6, | |
202 | SHOULD_ERR, | |
203 | }, | |
204 | /* 12 */ | |
205 | { | |
206 | "MP-overflow", | |
207 | "MP IP4/Unicast, length too long", | |
208 | {CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1}, | |
209 | 6, | |
210 | SHOULD_ERR, | |
211 | 0, | |
212 | 1, | |
213 | AFI_IP, | |
214 | SAFI_UNICAST, | |
215 | VALID_AFI, | |
216 | }, | |
217 | {NULL, NULL, {0}, 0, 0}}; | |
e08286bc | 218 | |
9d303b37 | 219 | static struct test_segment misc_segments[] = |
d62a17ae | 220 | { |
9d303b37 | 221 | /* 13 */ |
d62a17ae | 222 | { |
9d303b37 DL |
223 | "ORF", |
224 | "ORF, simple, single entry, single tuple", | |
225 | {/* hdr */ CAPABILITY_CODE_ORF, 0x7, | |
226 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
227 | /* num */ 0x1, | |
228 | /* tuples */ 0x40, 0x3}, | |
229 | 9, | |
230 | SHOULD_PARSE, | |
d62a17ae | 231 | }, |
9d303b37 | 232 | /* 14 */ |
d62a17ae | 233 | { |
9d303b37 DL |
234 | "ORF-many", |
235 | "ORF, multi entry/tuple", | |
236 | { | |
237 | /* hdr */ CAPABILITY_CODE_ORF, | |
238 | 0x21, | |
239 | /* mpc */ 0x0, | |
240 | 0x1, | |
241 | 0x0, | |
242 | 0x1, | |
243 | /* num */ 0x3, | |
244 | /* tuples */ 0x40, | |
245 | ORF_MODE_BOTH, | |
246 | 0x80, | |
247 | ORF_MODE_RECEIVE, | |
248 | 0x80, | |
249 | ORF_MODE_SEND, | |
250 | /* mpc */ 0x0, | |
251 | 0x2, | |
252 | 0x0, | |
253 | 0x1, | |
254 | /* num */ 0x3, | |
255 | /* tuples */ 0x40, | |
256 | ORF_MODE_BOTH, | |
257 | 0x80, | |
258 | ORF_MODE_RECEIVE, | |
259 | 0x80, | |
260 | ORF_MODE_SEND, | |
261 | /* mpc */ 0x0, | |
262 | 0x2, | |
263 | 0x0, | |
264 | 0x2, | |
265 | /* num */ 0x3, | |
266 | /* tuples */ 0x40, | |
267 | ORF_MODE_RECEIVE, | |
268 | 0x80, | |
269 | ORF_MODE_SEND, | |
270 | 0x80, | |
271 | ORF_MODE_BOTH, | |
272 | }, | |
273 | 35, | |
274 | SHOULD_PARSE, | |
d62a17ae | 275 | }, |
9d303b37 | 276 | /* 15 */ |
d62a17ae | 277 | { |
9d303b37 DL |
278 | "ORFlo", |
279 | "ORF, multi entry/tuple, hdr length too short", | |
280 | { | |
281 | /* hdr */ CAPABILITY_CODE_ORF, | |
282 | 0x15, | |
283 | /* mpc */ 0x0, | |
284 | 0x1, | |
285 | 0x0, | |
286 | 0x1, | |
287 | /* num */ 0x3, | |
288 | /* tuples */ 0x40, | |
289 | 0x3, | |
290 | 0x80, | |
291 | 0x1, | |
292 | 0x80, | |
293 | 0x2, | |
294 | /* mpc */ 0x0, | |
295 | 0x1, | |
296 | 0x0, | |
297 | 0x1, | |
298 | /* num */ 0x3, | |
299 | /* tuples */ 0x40, | |
300 | 0x3, | |
301 | 0x80, | |
302 | 0x1, | |
303 | 0x80, | |
304 | 0x2, | |
305 | /* mpc */ 0x0, | |
306 | 0x2, | |
307 | 0x0, | |
308 | 0x2, | |
309 | /* num */ 0x3, | |
310 | /* tuples */ 0x40, | |
311 | 0x3, | |
312 | 0x80, | |
313 | 0x1, | |
314 | 0x80, | |
315 | 0x2, | |
316 | }, | |
317 | 35, | |
318 | SHOULD_ERR, /* It should error on invalid | |
319 | Route-Refresh.. */ | |
d62a17ae | 320 | }, |
9d303b37 DL |
321 | /* 16 */ |
322 | {"ORFlu", | |
323 | "ORF, multi entry/tuple, length too long", | |
324 | { | |
325 | /* hdr */ 0x3, | |
326 | 0x22, | |
327 | /* mpc */ 0x0, | |
328 | 0x1, | |
329 | 0x0, | |
330 | 0x1, | |
331 | /* num */ 0x3, | |
332 | /* tuples */ 0x40, | |
333 | 0x3, | |
334 | 0x80, | |
335 | 0x1, | |
336 | 0x80, | |
337 | 0x2, | |
338 | /* mpc */ 0x0, | |
339 | 0x2, | |
340 | 0x0, | |
341 | 0x1, | |
342 | /* num */ 0x3, | |
343 | /* tuples */ 0x40, | |
344 | 0x3, | |
345 | 0x80, | |
346 | 0x1, | |
347 | 0x80, | |
348 | 0x2, | |
349 | /* mpc */ 0x0, | |
350 | 0x2, | |
351 | 0x0, | |
352 | 0x2, | |
353 | /* num */ 0x3, | |
354 | /* tuples */ 0x40, | |
355 | 0x3, | |
356 | 0x80, | |
357 | 0x1, | |
358 | 0x80, | |
359 | 0x2, | |
360 | }, | |
361 | 35, | |
362 | SHOULD_ERR}, | |
363 | /* 17 */ | |
d62a17ae | 364 | { |
9d303b37 DL |
365 | "ORFnu", |
366 | "ORF, multi entry/tuple, entry number too long", | |
367 | { | |
368 | /* hdr */ 0x3, | |
369 | 0x21, | |
370 | /* mpc */ 0x0, | |
371 | 0x1, | |
372 | 0x0, | |
373 | 0x1, | |
374 | /* num */ 0x3, | |
375 | /* tuples */ 0x40, | |
376 | 0x3, | |
377 | 0x80, | |
378 | 0x1, | |
379 | 0x80, | |
380 | 0x2, | |
381 | /* mpc */ 0x0, | |
382 | 0x2, | |
383 | 0x0, | |
384 | 0x1, | |
385 | /* num */ 0x4, | |
386 | /* tuples */ 0x40, | |
387 | 0x3, | |
388 | 0x80, | |
389 | 0x1, | |
390 | 0x80, | |
391 | 0x2, | |
392 | /* mpc */ 0x0, | |
393 | 0x2, | |
394 | 0x0, | |
395 | 0x2, | |
396 | /* num */ 0x3, | |
397 | /* tuples */ 0x40, | |
398 | 0x3, | |
399 | 0x80, | |
400 | 0x1, | |
401 | 0x80, | |
402 | 0x2, | |
403 | }, | |
404 | 35, | |
405 | SHOULD_PARSE, /* parses, but last few tuples should be | |
406 | gibberish */ | |
d62a17ae | 407 | }, |
9d303b37 | 408 | /* 18 */ |
d62a17ae | 409 | { |
9d303b37 DL |
410 | "ORFno", |
411 | "ORF, multi entry/tuple, entry number too short", | |
412 | { | |
413 | /* hdr */ 0x3, | |
414 | 0x21, | |
415 | /* mpc */ 0x0, | |
416 | 0x1, | |
417 | 0x0, | |
418 | 0x1, | |
419 | /* num */ 0x3, | |
420 | /* tuples */ 0x40, | |
421 | 0x3, | |
422 | 0x80, | |
423 | 0x1, | |
424 | 0x80, | |
425 | 0x2, | |
426 | /* mpc */ 0x0, | |
427 | 0x2, | |
428 | 0x0, | |
429 | 0x1, | |
430 | /* num */ 0x1, | |
431 | /* tuples */ 0x40, | |
432 | 0x3, | |
433 | 0x80, | |
434 | 0x1, | |
435 | 0x80, | |
436 | 0x2, | |
437 | /* mpc */ 0x0, | |
438 | 0x2, | |
439 | 0x0, | |
440 | 0x2, | |
441 | /* num */ 0x3, | |
442 | /* tuples */ 0x40, | |
443 | 0x3, | |
444 | 0x80, | |
445 | 0x1, | |
446 | 0x80, | |
447 | 0x2, | |
448 | }, | |
449 | 35, | |
450 | SHOULD_PARSE, /* Parses, but should get gibberish | |
451 | afi/safis */ | |
d62a17ae | 452 | }, |
9d303b37 | 453 | /* 17 */ |
d62a17ae | 454 | { |
9d303b37 DL |
455 | "ORFpad", |
456 | "ORF, multi entry/tuple, padded to align", | |
457 | { | |
458 | /* hdr */ 0x3, | |
459 | 0x22, | |
460 | /* mpc */ 0x0, | |
461 | 0x1, | |
462 | 0x0, | |
463 | 0x1, | |
464 | /* num */ 0x3, | |
465 | /* tuples */ 0x40, | |
466 | 0x3, | |
467 | 0x80, | |
468 | 0x1, | |
469 | 0x80, | |
470 | 0x2, | |
471 | /* mpc */ 0x0, | |
472 | 0x2, | |
473 | 0x0, | |
474 | 0x1, | |
475 | /* num */ 0x3, | |
476 | /* tuples */ 0x40, | |
477 | 0x3, | |
478 | 0x80, | |
479 | 0x1, | |
480 | 0x80, | |
481 | 0x2, | |
482 | /* mpc */ 0x0, | |
483 | 0x2, | |
484 | 0x0, | |
485 | 0x2, | |
486 | /* num */ 0x3, | |
487 | /* tuples */ 0x40, | |
488 | 0x3, | |
489 | 0x80, | |
490 | 0x1, | |
491 | 0x80, | |
492 | 0x2, | |
493 | 0x00, | |
494 | }, | |
495 | 36, | |
496 | SHOULD_PARSE, | |
d62a17ae | 497 | }, |
9d303b37 | 498 | /* 19 */ |
d62a17ae | 499 | { |
9d303b37 DL |
500 | "AS4", |
501 | "AS4 capability", | |
502 | {0x41, 0x4, 0xab, 0xcd, 0xef, | |
503 | 0x12}, /* AS: 2882400018 */ | |
504 | 6, | |
505 | SHOULD_PARSE, | |
506 | 2882400018, | |
d62a17ae | 507 | }, |
508 | { | |
9d303b37 DL |
509 | "AS4", |
510 | "AS4 capability: short", | |
511 | {0x41, 0x4, 0xab, 0xcd, 0xef}, /* AS: 2882400018 */ | |
512 | 5, | |
513 | SHOULD_ERR, | |
d62a17ae | 514 | }, |
515 | { | |
9d303b37 DL |
516 | "AS4", |
517 | "AS4 capability: long", | |
518 | {0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12}, | |
519 | 7, | |
520 | SHOULD_ERR, | |
521 | 2882400018, | |
d62a17ae | 522 | }, |
523 | { | |
9d303b37 DL |
524 | "GR", |
525 | "GR capability", | |
526 | { | |
527 | /* hdr */ CAPABILITY_CODE_RESTART, 0xe, | |
528 | /* R-bit, time */ 0xf1, 0x12, | |
529 | /* afi */ 0x0, 0x1, | |
530 | /* safi */ 0x1, | |
531 | /* flags */ 0xf, | |
532 | /* afi */ 0x0, 0x2, | |
533 | /* safi */ 0x1, | |
534 | /* flags */ 0x0, | |
535 | /* afi */ 0x0, 0x2, | |
536 | /* safi */ 0x2, | |
537 | /* flags */ 0x1, | |
538 | }, | |
539 | 16, | |
540 | SHOULD_PARSE, | |
d62a17ae | 541 | }, |
542 | { | |
9d303b37 DL |
543 | "GR-short", |
544 | "GR capability, but header length too short", | |
545 | { | |
546 | /* hdr */ 0x40, 0xa, | |
547 | /* R-bit, time */ 0xf1, 0x12, | |
548 | /* afi */ 0x0, 0x1, | |
549 | /* safi */ 0x1, | |
550 | /* flags */ 0xf, | |
551 | /* afi */ 0x0, 0x2, | |
552 | /* safi */ 0x1, | |
553 | /* flags */ 0x0, | |
554 | /* afi */ 0x0, 0x2, | |
555 | /* safi */ 0x2, | |
556 | /* flags */ 0x1, | |
557 | }, | |
558 | 15 /* array is 16 though */, | |
559 | SHOULD_ERR, | |
d62a17ae | 560 | }, |
561 | { | |
9d303b37 DL |
562 | "GR-long", |
563 | "GR capability, but header length too long", | |
564 | { | |
565 | /* hdr */ 0x40, 0xf, | |
566 | /* R-bit, time */ 0xf1, 0x12, | |
567 | /* afi */ 0x0, 0x1, | |
568 | /* safi */ 0x1, | |
569 | /* flags */ 0xf, | |
570 | /* afi */ 0x0, 0x2, | |
571 | /* safi */ 0x1, | |
572 | /* flags */ 0x0, | |
573 | /* afi */ 0x0, 0x2, | |
574 | /* safi */ 0x2, | |
575 | /* flags */ 0x01, | |
576 | }, | |
577 | 16, | |
578 | SHOULD_ERR, | |
d62a17ae | 579 | }, |
580 | { | |
9d303b37 DL |
581 | "GR-trunc", |
582 | "GR capability, but truncated", | |
583 | { | |
584 | /* hdr */ 0x40, 0xf, | |
585 | /* R-bit, time */ 0xf1, 0x12, | |
586 | /* afi */ 0x0, 0x1, | |
587 | /* safi */ 0x1, | |
588 | /* flags */ 0xf, | |
589 | /* afi */ 0x0, 0x2, | |
590 | /* safi */ 0x1, | |
591 | /* flags */ 0x0, | |
592 | /* afi */ 0x0, 0x2, | |
593 | /* safi */ 0x2, | |
594 | /* flags */ 0x1, | |
595 | }, | |
596 | 15, | |
597 | SHOULD_ERR, | |
d62a17ae | 598 | }, |
599 | { | |
9d303b37 DL |
600 | "GR-empty", |
601 | "GR capability, but empty.", | |
602 | { | |
603 | /* hdr */ 0x40, 0x0, | |
604 | }, | |
605 | 2, | |
606 | SHOULD_ERR, | |
d62a17ae | 607 | }, |
9d303b37 DL |
608 | { |
609 | "MP-empty", | |
610 | "MP capability, but empty.", | |
611 | { | |
612 | /* hdr */ 0x1, 0x0, | |
613 | }, | |
614 | 2, | |
615 | SHOULD_ERR, | |
616 | }, | |
617 | { | |
618 | "ORF-empty", | |
619 | "ORF capability, but empty.", | |
620 | { | |
621 | /* hdr */ 0x3, 0x0, | |
622 | }, | |
623 | 2, | |
624 | SHOULD_ERR, | |
625 | }, | |
626 | { | |
627 | "AS4-empty", | |
628 | "AS4 capability, but empty.", | |
629 | { | |
630 | /* hdr */ 0x41, 0x0, | |
631 | }, | |
632 | 2, | |
633 | SHOULD_ERR, | |
634 | }, | |
635 | { | |
636 | "dyn-empty", | |
637 | "Dynamic capability, but empty.", | |
638 | { | |
639 | /* hdr */ 0x42, 0x0, | |
640 | }, | |
641 | 2, | |
642 | SHOULD_PARSE, | |
643 | }, | |
644 | { | |
645 | "dyn-old", | |
646 | "Dynamic capability (deprecated version)", | |
647 | {CAPABILITY_CODE_DYNAMIC, 0x0}, | |
648 | 2, | |
649 | SHOULD_PARSE, | |
650 | }, | |
651 | {NULL, NULL, {0}, 0, 0}}; | |
ed6ef902 | 652 | |
0b2aa3a0 | 653 | /* DYNAMIC message */ |
d62a17ae | 654 | struct test_segment dynamic_cap_msgs[] = { |
655 | { | |
656 | "DynCap", | |
657 | "Dynamic Capability Message, IP/Multicast", | |
658 | {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2}, | |
659 | 7, | |
660 | SHOULD_PARSE, /* horrible alignment, just as with ORF */ | |
661 | }, | |
662 | { | |
663 | "DynCapLong", | |
664 | "Dynamic Capability Message, IP/Multicast, truncated", | |
665 | {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2}, | |
666 | 5, | |
667 | SHOULD_ERR, | |
668 | }, | |
669 | { | |
670 | "DynCapPadded", | |
671 | "Dynamic Capability Message, IP/Multicast, padded", | |
672 | {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0}, | |
673 | 8, | |
674 | SHOULD_ERR, /* No way to tell padding from data.. */ | |
675 | }, | |
676 | { | |
677 | "DynCapMPCpadded", | |
678 | "Dynamic Capability Message, IP/Multicast, cap data padded", | |
679 | {0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0}, | |
680 | 8, | |
681 | SHOULD_PARSE, /* You can though add padding to the capability | |
682 | data */ | |
683 | }, | |
684 | { | |
685 | "DynCapMPCoverflow", | |
686 | "Dynamic Capability Message, IP/Multicast, cap data != length", | |
687 | {0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0}, | |
688 | 8, | |
689 | SHOULD_ERR, | |
690 | }, | |
691 | {NULL, NULL, {0}, 0, 0}}; | |
0b2aa3a0 PJ |
692 | |
693 | /* Entire Optional-Parameters block */ | |
d62a17ae | 694 | struct test_segment opt_params[] = { |
695 | { | |
696 | "Cap-singlets", | |
697 | "One capability per Optional-Param", | |
698 | { | |
699 | 0x02, 0x06, 0x01, 0x04, | |
700 | 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ | |
701 | 0x02, 0x06, 0x01, 0x04, | |
702 | 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
703 | 0x02, 0x02, 0x80, 0x00, /* RR (old) */ | |
704 | 0x02, 0x02, 0x02, 0x00, /* RR */ | |
705 | }, | |
706 | 24, | |
707 | SHOULD_PARSE, | |
708 | }, | |
709 | { | |
710 | "Cap-series", | |
711 | "Series of capability, one Optional-Param", | |
712 | { | |
713 | 0x02, 0x10, 0x01, 0x04, 0x00, 0x01, 0x00, | |
714 | 0x01, /* MP IPv4/Uni */ | |
715 | 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
716 | 0x80, 0x00, /* RR (old) */ | |
717 | 0x02, 0x00, /* RR */ | |
718 | }, | |
719 | 18, | |
720 | SHOULD_PARSE, | |
721 | }, | |
722 | { | |
723 | "AS4more", | |
724 | "AS4 capability after other caps (singlets)", | |
725 | { | |
726 | 0x02, 0x06, 0x01, 0x04, | |
727 | 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ | |
728 | 0x02, 0x06, 0x01, 0x04, | |
729 | 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
730 | 0x02, 0x02, 0x80, 0x00, /* RR (old) */ | |
731 | 0x02, 0x02, 0x02, 0x00, /* RR */ | |
732 | 0x02, 0x06, 0x41, 0x04, | |
733 | 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ | |
734 | }, | |
735 | 32, | |
736 | SHOULD_PARSE, | |
737 | 196614, | |
738 | }, | |
739 | { | |
740 | "AS4series", | |
741 | "AS4 capability, in series of capabilities", | |
742 | { | |
743 | 0x02, 0x16, 0x01, 0x04, 0x00, 0x01, | |
744 | 0x00, 0x01, /* MP IPv4/Uni */ | |
745 | 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
746 | 0x80, 0x00, /* RR (old) */ | |
747 | 0x02, 0x00, /* RR */ | |
748 | 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ | |
749 | }, | |
750 | 24, | |
751 | SHOULD_PARSE, | |
752 | 196614, | |
753 | }, | |
754 | { | |
755 | "AS4real", | |
756 | "AS4 capability, in series of capabilities", | |
757 | { | |
758 | 0x02, 0x06, 0x01, 0x04, | |
759 | 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */ | |
760 | 0x02, 0x06, 0x01, 0x04, | |
761 | 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */ | |
762 | 0x02, 0x02, 0x80, 0x00, /* RR old */ | |
763 | 0x02, 0x02, 0x02, 0x00, /* RR */ | |
764 | 0x02, 0x06, 0x41, 0x04, | |
765 | 0x00, 0x03, 0x00, 0x06, /* AS4 */ | |
766 | }, | |
767 | 32, | |
768 | SHOULD_PARSE, | |
769 | 196614, | |
770 | }, | |
771 | { | |
772 | "AS4real2", | |
773 | "AS4 capability, in series of capabilities", | |
774 | { | |
775 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x02, | |
776 | 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, 0x02, 0x02, | |
777 | 0x80, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x06, 0x41, | |
778 | 0x04, 0x00, 0x00, 0xfc, 0x03, 0x02, 0x09, 0x82, 0x07, | |
779 | 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03, 0x02, 0x09, | |
780 | 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03, | |
781 | 0x02, 0x02, 0x42, 0x00, | |
782 | }, | |
783 | 58, | |
784 | SHOULD_PARSE, | |
785 | 64515, | |
786 | }, | |
787 | ||
788 | {NULL, NULL, {0}, 0, 0}}; | |
0b2aa3a0 | 789 | |
ed6ef902 | 790 | /* basic parsing test */ |
d62a17ae | 791 | static void parse_test(struct peer *peer, struct test_segment *t, int type) |
ed6ef902 | 792 | { |
d62a17ae | 793 | int ret; |
794 | int capability = 0; | |
795 | as_t as4 = 0; | |
796 | int oldfailed = failed; | |
797 | int len = t->len; | |
0b2aa3a0 | 798 | #define RANDOM_FUZZ 35 |
d62a17ae | 799 | stream_reset(peer->ibuf); |
800 | stream_put(peer->ibuf, NULL, RANDOM_FUZZ); | |
801 | stream_set_getp(peer->ibuf, RANDOM_FUZZ); | |
802 | ||
803 | switch (type) { | |
804 | case CAPABILITY: | |
805 | stream_putc(peer->ibuf, BGP_OPEN_OPT_CAP); | |
806 | stream_putc(peer->ibuf, t->len); | |
807 | break; | |
808 | case DYNCAP: | |
809 | /* for (i = 0; i < BGP_MARKER_SIZE; i++) | |
810 | stream_putc (peer->, 0xff); | |
811 | stream_putw (s, 0); | |
812 | stream_putc (s, BGP_MSG_CAPABILITY);*/ | |
813 | break; | |
814 | } | |
815 | stream_write(peer->ibuf, t->data, t->len); | |
816 | ||
817 | printf("%s: %s\n", t->name, t->desc); | |
818 | ||
819 | switch (type) { | |
820 | case CAPABILITY: | |
821 | len += 2; /* to cover the OPT-Param header */ | |
822 | case OPT_PARAM: | |
823 | printf("len: %u\n", len); | |
824 | /* peek_for_as4 wants getp at capibility*/ | |
825 | as4 = peek_for_as4_capability(peer, len); | |
826 | printf("peek_for_as4: as4 is %u\n", as4); | |
827 | /* and it should leave getp as it found it */ | |
828 | assert(stream_get_getp(peer->ibuf) == RANDOM_FUZZ); | |
829 | ||
830 | ret = bgp_open_option_parse(peer, len, &capability); | |
831 | break; | |
832 | case DYNCAP: | |
833 | ret = bgp_capability_receive(peer, t->len); | |
834 | break; | |
835 | default: | |
836 | printf("unknown type %u\n", type); | |
837 | exit(1); | |
838 | } | |
839 | ||
840 | if (!ret && t->validate_afi) { | |
841 | afi_t afi; | |
842 | safi_t safi; | |
843 | ||
844 | /* Convert AFI, SAFI to internal values, check. */ | |
845 | if (bgp_map_afi_safi_iana2int(afi_int2iana(t->afi), t->safi, | |
846 | &afi, &safi)) { | |
847 | if (t->afi_valid == VALID_AFI) | |
848 | failed++; | |
849 | } | |
850 | printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", t->afi, afi, | |
851 | t->safi, safi, peer->afc_recv[afi][safi], | |
852 | peer->afc_nego[afi][safi]); | |
853 | ||
854 | if (t->afi_valid == VALID_AFI) { | |
855 | ||
856 | if (!peer->afc_recv[afi][safi]) | |
857 | failed++; | |
858 | if (!peer->afc_nego[afi][safi]) | |
859 | failed++; | |
860 | } | |
861 | } | |
862 | ||
863 | if (as4 != t->peek_for) { | |
864 | printf("as4 %u != %u\n", as4, t->peek_for); | |
865 | failed++; | |
866 | } | |
867 | ||
868 | printf("parsed?: %s\n", ret ? "no" : "yes"); | |
869 | ||
870 | if (ret != t->parses) | |
871 | failed++; | |
872 | ||
873 | if (tty) | |
9d303b37 DL |
874 | printf("%s", |
875 | (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET | |
876 | : VT100_GREEN "OK" VT100_RESET); | |
d62a17ae | 877 | else |
878 | printf("%s", (failed > oldfailed) ? "failed!" : "OK"); | |
879 | ||
880 | if (failed) | |
881 | printf(" (%u)", failed); | |
882 | ||
883 | printf("\n\n"); | |
ed6ef902 PJ |
884 | } |
885 | ||
886 | static struct bgp *bgp; | |
887 | static as_t asn = 100; | |
888 | ||
d62a17ae | 889 | int main(void) |
ed6ef902 | 890 | { |
d62a17ae | 891 | struct peer *peer; |
892 | int i, j; | |
893 | ||
894 | conf_bgp_debug_neighbor_events = -1UL; | |
895 | conf_bgp_debug_packet = -1UL; | |
896 | conf_bgp_debug_as4 = -1UL; | |
897 | term_bgp_debug_neighbor_events = -1UL; | |
898 | term_bgp_debug_packet = -1UL; | |
899 | term_bgp_debug_as4 = -1UL; | |
900 | ||
901 | qobj_init(); | |
902 | master = thread_master_create(NULL); | |
903 | bgp_master_init(master); | |
904 | vrf_init(NULL, NULL, NULL, NULL); | |
905 | bgp_option_set(BGP_OPT_NO_LISTEN); | |
906 | ||
907 | if (fileno(stdout) >= 0) | |
908 | tty = isatty(fileno(stdout)); | |
909 | ||
910 | if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) | |
911 | return -1; | |
912 | ||
913 | peer = peer_create_accept(bgp); | |
914 | peer->host = (char *)"foo"; | |
915 | ||
916 | for (i = AFI_IP; i < AFI_MAX; i++) | |
917 | for (j = SAFI_UNICAST; j < SAFI_MAX; j++) { | |
918 | peer->afc[i][j] = 1; | |
919 | peer->afc_adv[i][j] = 1; | |
920 | } | |
921 | ||
922 | i = 0; | |
923 | while (mp_segments[i].name) | |
924 | parse_test(peer, &mp_segments[i++], CAPABILITY); | |
925 | ||
926 | /* These tests assume mp_segments tests set at least | |
927 | * one of the afc_nego's | |
928 | */ | |
929 | i = 0; | |
930 | while (test_segments[i].name) | |
931 | parse_test(peer, &test_segments[i++], CAPABILITY); | |
932 | ||
933 | i = 0; | |
934 | while (misc_segments[i].name) | |
935 | parse_test(peer, &misc_segments[i++], CAPABILITY); | |
936 | ||
937 | i = 0; | |
938 | while (opt_params[i].name) | |
939 | parse_test(peer, &opt_params[i++], OPT_PARAM); | |
940 | ||
941 | SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV); | |
942 | peer->status = Established; | |
943 | ||
944 | i = 0; | |
945 | while (dynamic_cap_msgs[i].name) | |
946 | parse_test(peer, &dynamic_cap_msgs[i++], DYNCAP); | |
947 | ||
948 | printf("failures: %d\n", failed); | |
949 | return failed; | |
ed6ef902 | 950 | } |