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