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