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