]>
Commit | Line | Data |
---|---|---|
46f4a4d2 PJ |
1 | /* |
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 | ||
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 { | |
55 | const char *name; | |
56 | const char *desc; | |
57 | const u_char data[1024]; | |
58 | int len; | |
59 | #define SHOULD_PARSE 0 | |
60 | #define SHOULD_ERR -1 | |
61 | int parses; /* whether it should parse or not */ | |
1dba254e | 62 | as_t peek_for; /* what peek_for_as4_capability should say */ |
0b2aa3a0 | 63 | |
e08286bc PJ |
64 | /* AFI/SAFI validation */ |
65 | int validate_afi; | |
66 | afi_t afi; | |
67 | safi_t safi; | |
68 | #define VALID_AFI 1 | |
69 | #define INVALID_AFI 0 | |
70 | int afi_valid; | |
ed6ef902 PJ |
71 | } test_segments [] = |
72 | { | |
73 | /* 0 */ | |
74 | { "caphdr", | |
75 | "capability header, and no more", | |
76 | { CAPABILITY_CODE_REFRESH, 0x0 }, | |
77 | 2, SHOULD_PARSE, | |
78 | }, | |
79 | /* 1 */ | |
80 | { "nodata", | |
81 | "header, no data but length says there is", | |
82 | { 0x1, 0xa }, | |
83 | 2, SHOULD_ERR, | |
84 | }, | |
85 | /* 2 */ | |
86 | { "padded", | |
87 | "valid, with padding", | |
88 | { CAPABILITY_CODE_REFRESH, 0x2, 0x0, 0x0 }, | |
89 | 4, SHOULD_PARSE, | |
90 | }, | |
91 | /* 3 */ | |
92 | { "minsize", | |
93 | "violates minsize requirement", | |
94 | { CAPABILITY_CODE_ORF, 0x2, 0x0, 0x0 }, | |
95 | 4, SHOULD_ERR, | |
96 | }, | |
e08286bc PJ |
97 | { NULL, NULL, {0}, 0, 0}, |
98 | }; | |
99 | ||
100 | static struct test_segment mp_segments[] = | |
101 | { | |
102 | { "MP4", | |
ed6ef902 PJ |
103 | "MP IP/Uni", |
104 | { 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 }, | |
0b2aa3a0 PJ |
105 | 6, SHOULD_PARSE, 0, |
106 | 1, AFI_IP, SAFI_UNICAST, VALID_AFI, | |
e08286bc PJ |
107 | }, |
108 | { "MPv6", | |
109 | "MP IPv6/Uni", | |
110 | { 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 }, | |
0b2aa3a0 | 111 | 6, SHOULD_PARSE, 0, |
e08286bc | 112 | 1, AFI_IP6, SAFI_UNICAST, VALID_AFI, |
ed6ef902 PJ |
113 | }, |
114 | /* 5 */ | |
115 | { "MP2", | |
116 | "MP IP/Multicast", | |
117 | { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2 }, | |
0b2aa3a0 | 118 | 6, SHOULD_PARSE, 0, |
e08286bc | 119 | 1, AFI_IP, SAFI_MULTICAST, VALID_AFI, |
ed6ef902 PJ |
120 | }, |
121 | /* 6 */ | |
122 | { "MP3", | |
42e6d745 | 123 | "MP IP6/MPLS-labeled VPN", |
ed6ef902 | 124 | { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 }, |
42e6d745 | 125 | 6, SHOULD_PARSE, 0, |
9cabb64b | 126 | 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI, |
ed6ef902 PJ |
127 | }, |
128 | /* 7 */ | |
129 | { "MP5", | |
130 | "MP IP6/MPLS-VPN", | |
131 | { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 }, | |
0b2aa3a0 | 132 | 6, SHOULD_PARSE, 0, |
9cabb64b | 133 | 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI, |
ed6ef902 PJ |
134 | }, |
135 | /* 8 */ | |
136 | { "MP6", | |
42e6d745 | 137 | "MP IP4/MPLS-laveled VPN", |
ed6ef902 | 138 | { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 }, |
0b2aa3a0 | 139 | 6, SHOULD_PARSE, 0, |
9cabb64b | 140 | 1, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, |
ed6ef902 | 141 | }, |
ed6ef902 PJ |
142 | /* 10 */ |
143 | { "MP8", | |
42e6d745 | 144 | "MP unknown AFI/SAFI", |
ed6ef902 | 145 | { CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81 }, |
0b2aa3a0 | 146 | 6, SHOULD_PARSE, 0, |
e08286bc | 147 | 1, 0xa, 0x81, INVALID_AFI, /* parses, but unknown */ |
ed6ef902 PJ |
148 | }, |
149 | /* 11 */ | |
150 | { "MP-short", | |
151 | "MP IP4/Unicast, length too short (< minimum)", | |
152 | { CAPABILITY_CODE_MP, 0x2, 0x0, 0x1, 0x0, 0x1 }, | |
153 | 6, SHOULD_ERR, | |
154 | }, | |
155 | /* 12 */ | |
156 | { "MP-overflow", | |
157 | "MP IP4/Unicast, length too long", | |
158 | { CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1 }, | |
0b2aa3a0 | 159 | 6, SHOULD_ERR, 0, |
e08286bc | 160 | 1, AFI_IP, SAFI_UNICAST, VALID_AFI, |
ed6ef902 | 161 | }, |
e08286bc PJ |
162 | { NULL, NULL, {0}, 0, 0} |
163 | }; | |
164 | ||
165 | static struct test_segment misc_segments[] = | |
166 | { | |
ed6ef902 PJ |
167 | /* 13 */ |
168 | { "ORF", | |
169 | "ORF, simple, single entry, single tuple", | |
170 | { /* hdr */ CAPABILITY_CODE_ORF, 0x7, | |
171 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
172 | /* num */ 0x1, | |
173 | /* tuples */ 0x40, 0x3 | |
174 | }, | |
175 | 9, SHOULD_PARSE, | |
176 | }, | |
177 | /* 14 */ | |
178 | { "ORF-many", | |
179 | "ORF, multi entry/tuple", | |
180 | { /* hdr */ CAPABILITY_CODE_ORF, 0x21, | |
181 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
182 | /* num */ 0x3, | |
183 | /* tuples */ 0x40, ORF_MODE_BOTH, | |
184 | 0x80, ORF_MODE_RECEIVE, | |
185 | 0x80, ORF_MODE_SEND, | |
186 | /* mpc */ 0x0, 0x2, 0x0, 0x1, | |
187 | /* num */ 0x3, | |
188 | /* tuples */ 0x40, ORF_MODE_BOTH, | |
189 | 0x80, ORF_MODE_RECEIVE, | |
190 | 0x80, ORF_MODE_SEND, | |
191 | /* mpc */ 0x0, 0x2, 0x0, 0x2, | |
192 | /* num */ 0x3, | |
193 | /* tuples */ 0x40, ORF_MODE_RECEIVE, | |
194 | 0x80, ORF_MODE_SEND, | |
195 | 0x80, ORF_MODE_BOTH, | |
196 | }, | |
197 | 35, SHOULD_PARSE, | |
198 | }, | |
199 | /* 15 */ | |
200 | { "ORFlo", | |
201 | "ORF, multi entry/tuple, hdr length too short", | |
202 | { /* hdr */ CAPABILITY_CODE_ORF, 0x15, | |
203 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
204 | /* num */ 0x3, | |
205 | /* tuples */ 0x40, 0x3, | |
206 | 0x80, 0x1, | |
207 | 0x80, 0x2, | |
208 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
209 | /* num */ 0x3, | |
210 | /* tuples */ 0x40, 0x3, | |
211 | 0x80, 0x1, | |
212 | 0x80, 0x2, | |
213 | /* mpc */ 0x0, 0x2, 0x0, 0x2, | |
214 | /* num */ 0x3, | |
215 | /* tuples */ 0x40, 0x3, | |
216 | 0x80, 0x1, | |
217 | 0x80, 0x2, | |
218 | }, | |
219 | 35, SHOULD_ERR, /* It should error on invalid Route-Refresh.. */ | |
220 | }, | |
221 | /* 16 */ | |
222 | { "ORFlu", | |
223 | "ORF, multi entry/tuple, length too long", | |
224 | { /* hdr */ 0x3, 0x22, | |
225 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
226 | /* num */ 0x3, | |
227 | /* tuples */ 0x40, 0x3, | |
228 | 0x80, 0x1, | |
229 | 0x80, 0x2, | |
230 | /* mpc */ 0x0, 0x2, 0x0, 0x1, | |
231 | /* num */ 0x3, | |
232 | /* tuples */ 0x40, 0x3, | |
233 | 0x80, 0x1, | |
234 | 0x80, 0x2, | |
235 | /* mpc */ 0x0, 0x2, 0x0, 0x2, | |
236 | /* num */ 0x3, | |
237 | /* tuples */ 0x40, 0x3, | |
238 | 0x80, 0x1, | |
239 | 0x80, 0x2, | |
240 | }, | |
241 | 35, SHOULD_ERR | |
242 | }, | |
243 | /* 17 */ | |
244 | { "ORFnu", | |
245 | "ORF, multi entry/tuple, entry number too long", | |
246 | { /* hdr */ 0x3, 0x21, | |
247 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
248 | /* num */ 0x3, | |
249 | /* tuples */ 0x40, 0x3, | |
250 | 0x80, 0x1, | |
251 | 0x80, 0x2, | |
252 | /* mpc */ 0x0, 0x2, 0x0, 0x1, | |
253 | /* num */ 0x4, | |
254 | /* tuples */ 0x40, 0x3, | |
255 | 0x80, 0x1, | |
256 | 0x80, 0x2, | |
257 | /* mpc */ 0x0, 0x2, 0x0, 0x2, | |
258 | /* num */ 0x3, | |
259 | /* tuples */ 0x40, 0x3, | |
260 | 0x80, 0x1, | |
261 | 0x80, 0x2, | |
262 | }, | |
263 | 35, SHOULD_PARSE, /* parses, but last few tuples should be gibberish */ | |
264 | }, | |
265 | /* 18 */ | |
266 | { "ORFno", | |
267 | "ORF, multi entry/tuple, entry number too short", | |
268 | { /* hdr */ 0x3, 0x21, | |
269 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
270 | /* num */ 0x3, | |
271 | /* tuples */ 0x40, 0x3, | |
272 | 0x80, 0x1, | |
273 | 0x80, 0x2, | |
274 | /* mpc */ 0x0, 0x2, 0x0, 0x1, | |
275 | /* num */ 0x1, | |
276 | /* tuples */ 0x40, 0x3, | |
277 | 0x80, 0x1, | |
278 | 0x80, 0x2, | |
279 | /* mpc */ 0x0, 0x2, 0x0, 0x2, | |
280 | /* num */ 0x3, | |
281 | /* tuples */ 0x40, 0x3, | |
282 | 0x80, 0x1, | |
283 | 0x80, 0x2, | |
284 | }, | |
285 | 35, SHOULD_PARSE, /* Parses, but should get gibberish afi/safis */ | |
286 | }, | |
287 | /* 17 */ | |
288 | { "ORFpad", | |
289 | "ORF, multi entry/tuple, padded to align", | |
290 | { /* hdr */ 0x3, 0x22, | |
291 | /* mpc */ 0x0, 0x1, 0x0, 0x1, | |
292 | /* num */ 0x3, | |
293 | /* tuples */ 0x40, 0x3, | |
294 | 0x80, 0x1, | |
295 | 0x80, 0x2, | |
296 | /* mpc */ 0x0, 0x2, 0x0, 0x1, | |
297 | /* num */ 0x3, | |
298 | /* tuples */ 0x40, 0x3, | |
299 | 0x80, 0x1, | |
300 | 0x80, 0x2, | |
301 | /* mpc */ 0x0, 0x2, 0x0, 0x2, | |
302 | /* num */ 0x3, | |
303 | /* tuples */ 0x40, 0x3, | |
304 | 0x80, 0x1, | |
305 | 0x80, 0x2, | |
306 | 0x00, | |
307 | }, | |
308 | 36, SHOULD_PARSE, | |
309 | }, | |
310 | /* 19 */ | |
311 | { "AS4", | |
312 | "AS4 capability", | |
0b2aa3a0 PJ |
313 | { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 }, /* AS: 2882400018 */ |
314 | 6, SHOULD_PARSE, 2882400018, | |
ed6ef902 | 315 | }, |
3c88dab5 PJ |
316 | { "AS4", |
317 | "AS4 capability: short", | |
318 | { 0x41, 0x4, 0xab, 0xcd, 0xef }, /* AS: 2882400018 */ | |
319 | 5, SHOULD_ERR, | |
320 | }, | |
321 | { "AS4", | |
322 | "AS4 capability: long", | |
323 | { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12 }, | |
324 | 7, SHOULD_ERR, 2882400018, | |
325 | }, | |
ed6ef902 PJ |
326 | { "GR", |
327 | "GR capability", | |
328 | { /* hdr */ CAPABILITY_CODE_RESTART, 0xe, | |
329 | /* R-bit, time */ 0xf1, 0x12, | |
330 | /* afi */ 0x0, 0x1, | |
331 | /* safi */ 0x1, | |
332 | /* flags */ 0xf, | |
333 | /* afi */ 0x0, 0x2, | |
334 | /* safi */ 0x1, | |
335 | /* flags */ 0x0, | |
336 | /* afi */ 0x0, 0x2, | |
337 | /* safi */ 0x2, | |
338 | /* flags */ 0x1, | |
339 | }, | |
340 | 16, SHOULD_PARSE, | |
341 | }, | |
ed6ef902 PJ |
342 | { "GR-short", |
343 | "GR capability, but header length too short", | |
344 | { /* hdr */ 0x40, 0xa, | |
345 | /* R-bit, time */ 0xf1, 0x12, | |
346 | /* afi */ 0x0, 0x1, | |
347 | /* safi */ 0x1, | |
348 | /* flags */ 0xf, | |
349 | /* afi */ 0x0, 0x2, | |
350 | /* safi */ 0x1, | |
351 | /* flags */ 0x0, | |
352 | /* afi */ 0x0, 0x2, | |
353 | /* safi */ 0x2, | |
354 | /* flags */ 0x1, | |
355 | }, | |
3c88dab5 | 356 | 15 /* array is 16 though */, SHOULD_ERR, |
ed6ef902 | 357 | }, |
ed6ef902 PJ |
358 | { "GR-long", |
359 | "GR capability, but header length too long", | |
360 | { /* hdr */ 0x40, 0xf, | |
361 | /* R-bit, time */ 0xf1, 0x12, | |
362 | /* afi */ 0x0, 0x1, | |
363 | /* safi */ 0x1, | |
364 | /* flags */ 0xf, | |
365 | /* afi */ 0x0, 0x2, | |
366 | /* safi */ 0x1, | |
367 | /* flags */ 0x0, | |
368 | /* afi */ 0x0, 0x2, | |
369 | /* safi */ 0x2, | |
3c88dab5 | 370 | /* flags */ 0x01, |
ed6ef902 PJ |
371 | }, |
372 | 16, SHOULD_ERR, | |
373 | }, | |
374 | { "GR-trunc", | |
375 | "GR capability, but truncated", | |
376 | { /* hdr */ 0x40, 0xf, | |
377 | /* R-bit, time */ 0xf1, 0x12, | |
378 | /* afi */ 0x0, 0x1, | |
379 | /* safi */ 0x1, | |
380 | /* flags */ 0xf, | |
381 | /* afi */ 0x0, 0x2, | |
382 | /* safi */ 0x1, | |
383 | /* flags */ 0x0, | |
384 | /* afi */ 0x0, 0x2, | |
385 | /* safi */ 0x2, | |
386 | /* flags */ 0x1, | |
387 | }, | |
388 | 15, SHOULD_ERR, | |
389 | }, | |
370b64a2 PJ |
390 | { "GR-empty", |
391 | "GR capability, but empty.", | |
392 | { /* hdr */ 0x40, 0x0, | |
393 | }, | |
394 | 2, SHOULD_ERR, | |
395 | }, | |
396 | { "MP-empty", | |
397 | "MP capability, but empty.", | |
398 | { /* hdr */ 0x1, 0x0, | |
399 | }, | |
400 | 2, SHOULD_ERR, | |
401 | }, | |
402 | { "ORF-empty", | |
403 | "ORF capability, but empty.", | |
404 | { /* hdr */ 0x3, 0x0, | |
405 | }, | |
406 | 2, SHOULD_ERR, | |
407 | }, | |
408 | { "AS4-empty", | |
409 | "AS4 capability, but empty.", | |
410 | { /* hdr */ 0x41, 0x0, | |
411 | }, | |
412 | 2, SHOULD_ERR, | |
413 | }, | |
414 | { "dyn-empty", | |
415 | "Dynamic capability, but empty.", | |
416 | { /* hdr */ 0x42, 0x0, | |
417 | }, | |
418 | 2, SHOULD_PARSE, | |
419 | }, | |
ed6ef902 PJ |
420 | { "dyn-old", |
421 | "Dynamic capability (deprecated version)", | |
422 | { CAPABILITY_CODE_DYNAMIC, 0x0 }, | |
423 | 2, SHOULD_PARSE, | |
424 | }, | |
425 | { NULL, NULL, {0}, 0, 0} | |
426 | }; | |
427 | ||
0b2aa3a0 | 428 | /* DYNAMIC message */ |
ed6ef902 PJ |
429 | struct test_segment dynamic_cap_msgs[] = |
430 | { | |
431 | { "DynCap", | |
432 | "Dynamic Capability Message, IP/Multicast", | |
433 | { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 }, | |
434 | 7, SHOULD_PARSE, /* horrible alignment, just as with ORF */ | |
435 | }, | |
436 | { "DynCapLong", | |
437 | "Dynamic Capability Message, IP/Multicast, truncated", | |
438 | { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 }, | |
439 | 5, SHOULD_ERR, | |
440 | }, | |
441 | { "DynCapPadded", | |
442 | "Dynamic Capability Message, IP/Multicast, padded", | |
443 | { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0 }, | |
444 | 8, SHOULD_ERR, /* No way to tell padding from data.. */ | |
445 | }, | |
446 | { "DynCapMPCpadded", | |
447 | "Dynamic Capability Message, IP/Multicast, cap data padded", | |
448 | { 0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0 }, | |
449 | 8, SHOULD_PARSE, /* You can though add padding to the capability data */ | |
450 | }, | |
451 | { "DynCapMPCoverflow", | |
452 | "Dynamic Capability Message, IP/Multicast, cap data != length", | |
453 | { 0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0 }, | |
454 | 8, SHOULD_ERR, | |
455 | }, | |
456 | { NULL, NULL, {0}, 0, 0} | |
457 | }; | |
0b2aa3a0 PJ |
458 | |
459 | /* Entire Optional-Parameters block */ | |
460 | struct test_segment opt_params[] = | |
461 | { | |
462 | { "Cap-singlets", | |
463 | "One capability per Optional-Param", | |
464 | { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ | |
465 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
466 | 0x02, 0x02, 0x80, 0x00, /* RR (old) */ | |
467 | 0x02, 0x02, 0x02, 0x00, /* RR */ | |
468 | }, | |
469 | 24, SHOULD_PARSE, | |
470 | }, | |
471 | { "Cap-series", | |
472 | "Series of capability, one Optional-Param", | |
473 | { 0x02, 0x10, | |
474 | 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ | |
475 | 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
476 | 0x80, 0x00, /* RR (old) */ | |
477 | 0x02, 0x00, /* RR */ | |
478 | }, | |
479 | 18, SHOULD_PARSE, | |
480 | }, | |
481 | { "AS4more", | |
482 | "AS4 capability after other caps (singlets)", | |
483 | { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ | |
484 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
485 | 0x02, 0x02, 0x80, 0x00, /* RR (old) */ | |
486 | 0x02, 0x02, 0x02, 0x00, /* RR */ | |
487 | 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ | |
488 | }, | |
489 | 32, SHOULD_PARSE, 196614, | |
490 | }, | |
491 | { "AS4series", | |
492 | "AS4 capability, in series of capabilities", | |
493 | { 0x02, 0x16, | |
494 | 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ | |
495 | 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ | |
496 | 0x80, 0x00, /* RR (old) */ | |
497 | 0x02, 0x00, /* RR */ | |
498 | 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ | |
499 | }, | |
500 | 24, SHOULD_PARSE, 196614, | |
501 | }, | |
502 | { "AS4real", | |
503 | "AS4 capability, in series of capabilities", | |
504 | { | |
505 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */ | |
506 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */ | |
507 | 0x02, 0x02, 0x80, 0x00, /* RR old */ | |
508 | 0x02, 0x02, 0x02, 0x00, /* RR */ | |
509 | 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06, /* AS4 */ | |
510 | }, | |
511 | 32, SHOULD_PARSE, 196614, | |
512 | }, | |
513 | { "AS4real2", | |
514 | "AS4 capability, in series of capabilities", | |
515 | { | |
516 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, | |
517 | 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, | |
518 | 0x02, 0x02, 0x80, 0x00, | |
519 | 0x02, 0x02, 0x02, 0x00, | |
520 | 0x02, 0x06, 0x41, 0x04, 0x00, 0x00, 0xfc, 0x03, | |
521 | 0x02, 0x09, 0x82, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03, | |
522 | 0x02, 0x09, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03, | |
523 | 0x02, 0x02, 0x42, 0x00, | |
524 | }, | |
525 | 58, SHOULD_PARSE, 64515, | |
526 | }, | |
527 | ||
528 | { NULL, NULL, {0}, 0, 0} | |
529 | }; | |
530 | ||
ed6ef902 PJ |
531 | /* basic parsing test */ |
532 | static void | |
533 | parse_test (struct peer *peer, struct test_segment *t, int type) | |
534 | { | |
535 | int ret; | |
536 | int capability = 0; | |
0b2aa3a0 | 537 | as_t as4 = 0; |
e08286bc | 538 | int oldfailed = failed; |
0b2aa3a0 PJ |
539 | int len = t->len; |
540 | #define RANDOM_FUZZ 35 | |
ed6ef902 PJ |
541 | |
542 | stream_reset (peer->ibuf); | |
0b2aa3a0 PJ |
543 | stream_put (peer->ibuf, NULL, RANDOM_FUZZ); |
544 | stream_set_getp (peer->ibuf, RANDOM_FUZZ); | |
545 | ||
ed6ef902 PJ |
546 | switch (type) |
547 | { | |
0b2aa3a0 | 548 | case CAPABILITY: |
ed6ef902 PJ |
549 | stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP); |
550 | stream_putc (peer->ibuf, t->len); | |
551 | break; | |
552 | case DYNCAP: | |
553 | /* for (i = 0; i < BGP_MARKER_SIZE; i++) | |
554 | stream_putc (peer->, 0xff); | |
555 | stream_putw (s, 0); | |
556 | stream_putc (s, BGP_MSG_CAPABILITY);*/ | |
557 | break; | |
558 | } | |
559 | stream_write (peer->ibuf, t->data, t->len); | |
560 | ||
561 | printf ("%s: %s\n", t->name, t->desc); | |
0b2aa3a0 | 562 | |
ed6ef902 PJ |
563 | switch (type) |
564 | { | |
0b2aa3a0 PJ |
565 | case CAPABILITY: |
566 | len += 2; /* to cover the OPT-Param header */ | |
567 | case OPT_PARAM: | |
568 | printf ("len: %u\n", len); | |
569 | /* peek_for_as4 wants getp at capibility*/ | |
570 | as4 = peek_for_as4_capability (peer, len); | |
571 | printf ("peek_for_as4: as4 is %u\n", as4); | |
572 | /* and it should leave getp as it found it */ | |
573 | assert (stream_get_getp (peer->ibuf) == RANDOM_FUZZ); | |
574 | ||
575 | ret = bgp_open_option_parse (peer, len, &capability); | |
ed6ef902 PJ |
576 | break; |
577 | case DYNCAP: | |
578 | ret = bgp_capability_receive (peer, t->len); | |
579 | break; | |
580 | default: | |
581 | printf ("unknown type %u\n", type); | |
582 | exit(1); | |
583 | } | |
584 | ||
e08286bc PJ |
585 | if (!ret && t->validate_afi) |
586 | { | |
9cabb64b | 587 | afi_t afi; |
588 | safi_t safi; | |
e08286bc | 589 | |
9cabb64b | 590 | /* Convert AFI, SAFI to internal values, check. */ |
52e61532 | 591 | if (bgp_map_afi_safi_iana2int (afi_int2iana(t->afi), t->safi, &afi, &safi)) |
9cabb64b | 592 | { |
593 | if (t->afi_valid == VALID_AFI) | |
594 | failed++; | |
595 | } | |
596 | printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n", | |
597 | t->afi, afi, t->safi, safi, | |
598 | peer->afc_recv[afi][safi], | |
599 | peer->afc_nego[afi][safi]); | |
e08286bc PJ |
600 | |
601 | if (t->afi_valid == VALID_AFI) | |
602 | { | |
603 | ||
9cabb64b | 604 | if (!peer->afc_recv[afi][safi]) |
e08286bc | 605 | failed++; |
9cabb64b | 606 | if (!peer->afc_nego[afi][safi]) |
e08286bc PJ |
607 | failed++; |
608 | } | |
609 | } | |
610 | ||
0b2aa3a0 PJ |
611 | if (as4 != t->peek_for) |
612 | { | |
613 | printf ("as4 %u != %u\n", as4, t->peek_for); | |
614 | failed++; | |
615 | } | |
616 | ||
ed6ef902 PJ |
617 | printf ("parsed?: %s\n", ret ? "no" : "yes"); |
618 | ||
e08286bc PJ |
619 | if (ret != t->parses) |
620 | failed++; | |
621 | ||
622 | if (tty) | |
0b2aa3a0 | 623 | printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET |
e08286bc | 624 | : VT100_GREEN "OK" VT100_RESET); |
ed6ef902 | 625 | else |
0b2aa3a0 PJ |
626 | printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); |
627 | ||
628 | if (failed) | |
629 | printf (" (%u)", failed); | |
ed6ef902 | 630 | |
0b2aa3a0 | 631 | printf ("\n\n"); |
ed6ef902 PJ |
632 | } |
633 | ||
634 | static struct bgp *bgp; | |
635 | static as_t asn = 100; | |
636 | ||
637 | int | |
638 | main (void) | |
639 | { | |
640 | struct peer *peer; | |
641 | int i, j; | |
642 | ||
16286195 | 643 | conf_bgp_debug_neighbor_events = -1UL; |
ed6ef902 | 644 | conf_bgp_debug_packet = -1UL; |
0b2aa3a0 | 645 | conf_bgp_debug_as4 = -1UL; |
16286195 | 646 | term_bgp_debug_neighbor_events = -1UL; |
ed6ef902 | 647 | term_bgp_debug_packet = -1UL; |
0b2aa3a0 | 648 | term_bgp_debug_as4 = -1UL; |
ed6ef902 | 649 | |
1bf9f027 | 650 | qobj_init (); |
ed6ef902 | 651 | master = thread_master_create (); |
4f04a76b | 652 | bgp_master_init (master); |
ebf00458 | 653 | vrf_init (); |
c9e4f862 | 654 | bgp_option_set (BGP_OPT_NO_LISTEN); |
ed6ef902 | 655 | |
e08286bc PJ |
656 | if (fileno (stdout) >= 0) |
657 | tty = isatty (fileno (stdout)); | |
658 | ||
ebf00458 | 659 | if (bgp_get (&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) |
ed6ef902 PJ |
660 | return -1; |
661 | ||
662 | peer = peer_create_accept (bgp); | |
1dba254e | 663 | peer->host = (char *) "foo"; |
ed6ef902 PJ |
664 | |
665 | for (i = AFI_IP; i < AFI_MAX; i++) | |
666 | for (j = SAFI_UNICAST; j < SAFI_MAX; j++) | |
e08286bc PJ |
667 | { |
668 | peer->afc[i][j] = 1; | |
669 | peer->afc_adv[i][j] = 1; | |
670 | } | |
ed6ef902 | 671 | |
e08286bc PJ |
672 | i = 0; |
673 | while (mp_segments[i].name) | |
0b2aa3a0 | 674 | parse_test (peer, &mp_segments[i++], CAPABILITY); |
e08286bc PJ |
675 | |
676 | /* These tests assume mp_segments tests set at least | |
677 | * one of the afc_nego's | |
678 | */ | |
679 | i = 0; | |
ed6ef902 | 680 | while (test_segments[i].name) |
0b2aa3a0 | 681 | parse_test (peer, &test_segments[i++], CAPABILITY); |
ed6ef902 | 682 | |
e08286bc PJ |
683 | i = 0; |
684 | while (misc_segments[i].name) | |
0b2aa3a0 PJ |
685 | parse_test (peer, &misc_segments[i++], CAPABILITY); |
686 | ||
687 | i = 0; | |
688 | while (opt_params[i].name) | |
689 | parse_test (peer, &opt_params[i++], OPT_PARAM); | |
e08286bc | 690 | |
ed6ef902 PJ |
691 | SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); |
692 | peer->status = Established; | |
693 | ||
694 | i = 0; | |
695 | while (dynamic_cap_msgs[i].name) | |
696 | parse_test (peer, &dynamic_cap_msgs[i++], DYNCAP); | |
697 | ||
698 | printf ("failures: %d\n", failed); | |
699 | return failed; | |
700 | } |