Import (slightly modified) ru.koi8-r.win.kbd:1.1 from FreeBSD (fjoe):
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-bgp.c
1 /*
2  * Copyright (C) 1999 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * Extensively modified by Hannes Gredler (hannes@juniper.net) for more
30  * complete BGP support.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #ifndef lint
38 static const char rcsid[] _U_ =
39      "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.72.2.4 2004/03/24 00:04:04 guy Exp $";
40 #endif
41
42 #include <tcpdump-stdinc.h>
43
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h"
50
51 struct bgp {
52         u_int8_t bgp_marker[16];
53         u_int16_t bgp_len;
54         u_int8_t bgp_type;
55 };
56 #define BGP_SIZE                19      /* unaligned */
57
58 #define BGP_OPEN                1
59 #define BGP_UPDATE              2
60 #define BGP_NOTIFICATION        3
61 #define BGP_KEEPALIVE           4
62 #define BGP_ROUTE_REFRESH       5
63
64 static struct tok bgp_msg_values[] = {
65     { BGP_OPEN,                 "Open"},
66     { BGP_UPDATE,               "Update"},
67     { BGP_NOTIFICATION,         "Notification"},
68     { BGP_KEEPALIVE,            "Keepalive"},
69     { BGP_ROUTE_REFRESH,        "Route Refresh"},
70     { 0, NULL}
71 };
72
73 struct bgp_open {
74         u_int8_t bgpo_marker[16];
75         u_int16_t bgpo_len;
76         u_int8_t bgpo_type;
77         u_int8_t bgpo_version;
78         u_int16_t bgpo_myas;
79         u_int16_t bgpo_holdtime;
80         u_int32_t bgpo_id;
81         u_int8_t bgpo_optlen;
82         /* options should follow */
83 };
84 #define BGP_OPEN_SIZE           29      /* unaligned */
85
86 struct bgp_opt {
87         u_int8_t bgpopt_type;
88         u_int8_t bgpopt_len;
89         /* variable length */
90 };
91 #define BGP_OPT_SIZE            2       /* some compilers may pad to 4 bytes */
92
93 struct bgp_notification {
94         u_int8_t bgpn_marker[16];
95         u_int16_t bgpn_len;
96         u_int8_t bgpn_type;
97         u_int8_t bgpn_major;
98         u_int8_t bgpn_minor;
99 };
100 #define BGP_NOTIFICATION_SIZE           21      /* unaligned */
101
102 struct bgp_route_refresh {
103     u_int8_t  bgp_marker[16];
104     u_int16_t len;
105     u_int8_t  type;
106     u_int8_t  afi[2]; /* the compiler messes this structure up               */
107     u_int8_t  res;    /* when doing misaligned sequences of int8 and int16   */
108     u_int8_t  safi;   /* afi should be int16 - so we have to access it using */
109 };                    /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh)      */ 
110 #define BGP_ROUTE_REFRESH_SIZE          23
111
112 struct bgp_attr {
113         u_int8_t bgpa_flags;
114         u_int8_t bgpa_type;
115         union {
116                 u_int8_t len;
117                 u_int16_t elen;
118         } bgpa_len;
119 #define bgp_attr_len(p) \
120         (((p)->bgpa_flags & 0x10) ? \
121                 EXTRACT_16BITS(&(p)->bgpa_len.elen) : (p)->bgpa_len.len)
122 #define bgp_attr_off(p) \
123         (((p)->bgpa_flags & 0x10) ? 4 : 3)
124 };
125
126 #define BGPTYPE_ORIGIN                  1
127 #define BGPTYPE_AS_PATH                 2
128 #define BGPTYPE_NEXT_HOP                3
129 #define BGPTYPE_MULTI_EXIT_DISC         4
130 #define BGPTYPE_LOCAL_PREF              5
131 #define BGPTYPE_ATOMIC_AGGREGATE        6
132 #define BGPTYPE_AGGREGATOR              7
133 #define BGPTYPE_COMMUNITIES             8       /* RFC1997 */
134 #define BGPTYPE_ORIGINATOR_ID           9       /* RFC1998 */
135 #define BGPTYPE_CLUSTER_LIST            10      /* RFC1998 */
136 #define BGPTYPE_DPA                     11      /* draft-ietf-idr-bgp-dpa */
137 #define BGPTYPE_ADVERTISERS             12      /* RFC1863 */
138 #define BGPTYPE_RCID_PATH               13      /* RFC1863 */
139 #define BGPTYPE_MP_REACH_NLRI           14      /* RFC2283 */
140 #define BGPTYPE_MP_UNREACH_NLRI         15      /* RFC2283 */
141 #define BGPTYPE_EXTD_COMMUNITIES        16      /* draft-ietf-idr-bgp-ext-communities */
142
143 static struct tok bgp_attr_values[] = {
144     { BGPTYPE_ORIGIN,           "Origin"},
145     { BGPTYPE_AS_PATH,          "AS Path"},
146     { BGPTYPE_NEXT_HOP,         "Next Hop"},
147     { BGPTYPE_MULTI_EXIT_DISC,  "Multi Exit Discriminator"},
148     { BGPTYPE_LOCAL_PREF,       "Local Preference"},
149     { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
150     { BGPTYPE_AGGREGATOR,       "Aggregator"},
151     { BGPTYPE_COMMUNITIES,      "Community"},
152     { BGPTYPE_ORIGINATOR_ID,    "Originator ID"},
153     { BGPTYPE_CLUSTER_LIST,     "Cluster List"},
154     { BGPTYPE_DPA,              "DPA"},
155     { BGPTYPE_ADVERTISERS,      "Advertisers"},
156     { BGPTYPE_RCID_PATH,        "RCID Path / Cluster ID"},
157     { BGPTYPE_MP_REACH_NLRI,    "Multi-Protocol Reach NLRI"},
158     { BGPTYPE_MP_UNREACH_NLRI,  "Multi-Protocol Unreach NLRI"},
159     { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
160     { 255,                      "Reserved for development"},
161     { 0, NULL}
162 };
163
164 #define BGP_AS_SET             1
165 #define BGP_AS_SEQUENCE        2
166 #define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
167 #define BGP_CONFED_AS_SET      4 /* draft-ietf-idr-rfc3065bis-01  */
168
169 static struct tok bgp_as_path_segment_open_values[] = {
170     { BGP_AS_SEQUENCE,         ""},
171     { BGP_AS_SET,              "{ "},
172     { BGP_CONFED_AS_SEQUENCE,  "( "},
173     { BGP_CONFED_AS_SET,       "({ "},
174     { 0, NULL}
175 };
176
177 static struct tok bgp_as_path_segment_close_values[] = {
178     { BGP_AS_SEQUENCE,         ""},
179     { BGP_AS_SET,              "}"},
180     { BGP_CONFED_AS_SEQUENCE,  ")"},
181     { BGP_CONFED_AS_SET,       "})"},
182     { 0, NULL}
183 };
184
185 #define BGP_OPT_AUTH                    1
186 #define BGP_OPT_CAP                     2
187
188
189 static struct tok bgp_opt_values[] = {
190     { BGP_OPT_AUTH,             "Authentication Information"},
191     { BGP_OPT_CAP,              "Capabilities Advertisement"},
192     { 0, NULL}
193 };
194
195 #define BGP_CAPCODE_MP                  1
196 #define BGP_CAPCODE_RR                  2
197 #define BGP_CAPCODE_RESTART            64 /* draft-ietf-idr-restart-05  */
198 #define BGP_CAPCODE_RR_CISCO          128
199
200 static struct tok bgp_capcode_values[] = {
201     { BGP_CAPCODE_MP,           "Multiprotocol Extensions"},
202     { BGP_CAPCODE_RR,           "Route Refresh"},
203     { BGP_CAPCODE_RESTART,      "Graceful Restart"},
204     { BGP_CAPCODE_RR_CISCO,     "Route Refresh (Cisco)"},
205     { 0, NULL}
206 };
207
208 #define BGP_NOTIFY_MAJOR_MSG            1
209 #define BGP_NOTIFY_MAJOR_OPEN           2
210 #define BGP_NOTIFY_MAJOR_UPDATE         3
211 #define BGP_NOTIFY_MAJOR_HOLDTIME       4
212 #define BGP_NOTIFY_MAJOR_FSM            5
213 #define BGP_NOTIFY_MAJOR_CEASE          6
214 #define BGP_NOTIFY_MAJOR_CAP            7
215
216 static struct tok bgp_notify_major_values[] = {
217     { BGP_NOTIFY_MAJOR_MSG,     "Message Header Error"},
218     { BGP_NOTIFY_MAJOR_OPEN,    "OPEN Message Error"},
219     { BGP_NOTIFY_MAJOR_UPDATE,  "UPDATE Message Error"},
220     { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
221     { BGP_NOTIFY_MAJOR_FSM,     "Finite State Machine Error"},
222     { BGP_NOTIFY_MAJOR_CEASE,   "Cease"},
223     { BGP_NOTIFY_MAJOR_CAP,     "Capability Message Error"},
224     { 0, NULL}
225 };
226
227 /* draft-ietf-idr-cease-subcode-02 */
228 #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX  1
229 static struct tok bgp_notify_minor_cease_values[] = {
230     { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"},
231     { 2,                        "Administratively Shutdown"},
232     { 3,                        "Peer Unconfigured"},
233     { 4,                        "Administratively Reset"},
234     { 5,                        "Connection Rejected"},
235     { 6,                        "Other Configuration Change"},
236     { 7,                        "Connection Collision Resolution"},
237     { 0, NULL}
238 };
239
240 static struct tok bgp_notify_minor_msg_values[] = {
241     { 1,                        "Connection Not Synchronized"},
242     { 2,                        "Bad Message Length"},
243     { 3,                        "Bad Message Type"},
244     { 0, NULL}
245 };
246
247 static struct tok bgp_notify_minor_open_values[] = {
248     { 1,                        "Unsupported Version Number"},
249     { 2,                        "Bad Peer AS"},
250     { 3,                        "Bad BGP Identifier"},
251     { 4,                        "Unsupported Optional Parameter"},
252     { 5,                        "Authentication Failure"},
253     { 6,                        "Unacceptable Hold Time"},
254     { 0, NULL}
255 };
256
257 static struct tok bgp_notify_minor_update_values[] = {
258     { 1,                        "Malformed Attribute List"},
259     { 2,                        "Unrecognized Well-known Attribute"},
260     { 3,                        "Missing Well-known Attribute"},
261     { 4,                        "Attribute Flags Error"},
262     { 5,                        "Attribute Length Error"},
263     { 6,                        "Invalid ORIGIN Attribute"},
264     { 7,                        "AS Routing Loop"},
265     { 8,                        "Invalid NEXT_HOP Attribute"},
266     { 9,                        "Optional Attribute Error"},
267     { 10,                       "Invalid Network Field"},
268     { 11,                       "Malformed AS_PATH"},
269     { 0, NULL}
270 };
271
272 static struct tok bgp_notify_minor_cap_values[] = {
273     { 1,                        "Invalid Action Value" },
274     { 2,                        "Invalid Capability Length" },
275     { 3,                        "Malformed Capability Value" },
276     { 4,                        "Unsupported Capability Code" },
277     { 0, NULL }
278 };
279
280 static struct tok bgp_origin_values[] = {
281     { 0,                        "IGP"},
282     { 1,                        "EGP"},
283     { 2,                        "Incomplete"},
284     { 0, NULL}
285 };
286
287 /* Subsequent address family identifier, RFC2283 section 7 */
288 #define SAFNUM_RES                      0
289 #define SAFNUM_UNICAST                  1
290 #define SAFNUM_MULTICAST                2
291 #define SAFNUM_UNIMULTICAST             3
292 /* labeled BGP RFC3107 */
293 #define SAFNUM_LABUNICAST               4
294 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt  */
295 #define SAFNUM_VPNUNICAST               128
296 #define SAFNUM_VPNMULTICAST             129
297 #define SAFNUM_VPNUNIMULTICAST          130
298 /* draft-marques-ppvpn-rt-constrain-01.txt */
299 #define SAFNUM_RT_ROUTING_INFO          132
300
301 #define BGP_VPN_RD_LEN                  8
302
303 static struct tok bgp_safi_values[] = {
304     { SAFNUM_RES,               "Reserved"},
305     { SAFNUM_UNICAST,           "Unicast"},
306     { SAFNUM_MULTICAST,         "Multicast"},
307     { SAFNUM_UNIMULTICAST,      "Unicast+Multicast"},
308     { SAFNUM_LABUNICAST,        "labeled Unicast"},
309     { SAFNUM_VPNUNICAST,        "labeled VPN Unicast"},
310     { SAFNUM_VPNMULTICAST,      "labeled VPN Multicast"},
311     { SAFNUM_VPNUNIMULTICAST,   "labeled VPN Unicast+Multicast"},
312     { SAFNUM_RT_ROUTING_INFO,   "Route Target Routing Information"},
313     { 0, NULL }
314 };
315
316 /* well-known community */
317 #define BGP_COMMUNITY_NO_EXPORT                 0xffffff01
318 #define BGP_COMMUNITY_NO_ADVERT                 0xffffff02
319 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED       0xffffff03
320
321 /* RFC1700 address family numbers */
322 #define AFNUM_INET      1
323 #define AFNUM_INET6     2
324 #define AFNUM_NSAP      3
325 #define AFNUM_HDLC      4
326 #define AFNUM_BBN1822   5
327 #define AFNUM_802       6
328 #define AFNUM_E163      7
329 #define AFNUM_E164      8
330 #define AFNUM_F69       9
331 #define AFNUM_X121      10
332 #define AFNUM_IPX       11
333 #define AFNUM_ATALK     12
334 #define AFNUM_DECNET    13
335 #define AFNUM_BANYAN    14
336 #define AFNUM_E164NSAP  15
337 /* draft-kompella-ppvpn-l2vpn */
338 #define AFNUM_L2VPN     196 /* still to be approved by IANA */
339
340 static struct tok bgp_afi_values[] = {
341     { 0,                      "Reserved"},
342     { AFNUM_INET,             "IPv4"},
343     { AFNUM_INET6,            "IPv6"},
344     { AFNUM_NSAP,             "NSAP"},
345     { AFNUM_HDLC,             "HDLC"},
346     { AFNUM_BBN1822,          "BBN 1822"},
347     { AFNUM_802,              "802"},
348     { AFNUM_E163,             "E.163"},
349     { AFNUM_E164,             "E.164"},
350     { AFNUM_F69,              "F.69"},
351     { AFNUM_X121,             "X.121"},
352     { AFNUM_IPX,              "Novell IPX"},
353     { AFNUM_ATALK,            "Appletalk"},
354     { AFNUM_DECNET,           "Decnet IV"},
355     { AFNUM_BANYAN,           "Banyan Vines"},
356     { AFNUM_E164NSAP,         "E.164 with NSAP subaddress"},
357     { AFNUM_L2VPN,            "Layer-2 VPN"},
358     { 0, NULL},
359 };
360
361 /* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
362 #define BGP_EXT_COM_RT_0        0x0002  /* Route Target,Format AS(2bytes):AN(4bytes) */
363 #define BGP_EXT_COM_RT_1        0x0102  /* Route Target,Format IP address:AN(2bytes) */
364 #define BGP_EXT_COM_RT_2        0x0202  /* Route Target,Format AN(4bytes):local(2bytes) */
365 #define BGP_EXT_COM_RO_0        0x0003  /* Route Origin,Format AS(2bytes):AN(4bytes) */
366 #define BGP_EXT_COM_RO_1        0x0103  /* Route Origin,Format IP address:AN(2bytes) */
367 #define BGP_EXT_COM_RO_2        0x0203  /* Route Origin,Format AN(4bytes):local(2bytes) */
368 #define BGP_EXT_COM_LINKBAND    0x4004  /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
369                                         /* rfc2547 bgp-mpls-vpns */
370
371 #define BGP_EXT_COM_VPN_ORIGIN  0x0005  /* OSPF Domain ID / VPN of Origin  - draft-rosen-vpns-ospf-bgp-mpls */
372 #define BGP_EXT_COM_VPN_ORIGIN2 0x0105  /* duplicate - keep for backwards compatability */
373 #define BGP_EXT_COM_VPN_ORIGIN3 0x0205  /* duplicate - keep for backwards compatability */
374 #define BGP_EXT_COM_VPN_ORIGIN4 0x8005  /* duplicate - keep for backwards compatability */
375
376 #define BGP_EXT_COM_OSPF_RTYPE  0x0306  /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
377 #define BGP_EXT_COM_OSPF_RTYPE2 0x8000  /* duplicate - keep for backwards compatability */
378
379 #define BGP_EXT_COM_OSPF_RID    0x0107  /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
380 #define BGP_EXT_COM_OSPF_RID2   0x8001  /* duplicate - keep for backwards compatability */ 
381
382 #define BGP_EXT_COM_L2INFO      0x800a  /* draft-kompella-ppvpn-l2vpn */
383
384 static struct tok bgp_extd_comm_flag_values[] = {
385     { 0x8000,                  "vendor-specific"},
386     { 0x4000,                  "non-transitive"},
387     { 0, NULL},
388 };
389
390 static struct tok bgp_extd_comm_subtype_values[] = {
391     { BGP_EXT_COM_RT_0,        "target"},
392     { BGP_EXT_COM_RT_1,        "target"},
393     { BGP_EXT_COM_RT_2,        "target"},
394     { BGP_EXT_COM_RO_0,        "origin"},
395     { BGP_EXT_COM_RO_1,        "origin"},
396     { BGP_EXT_COM_RO_2,        "origin"},
397     { BGP_EXT_COM_LINKBAND,    "link-BW"},
398     { BGP_EXT_COM_VPN_ORIGIN,  "ospf-domain"},
399     { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
400     { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
401     { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
402     { BGP_EXT_COM_OSPF_RTYPE,  "ospf-route-type"},
403     { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
404     { BGP_EXT_COM_OSPF_RID,    "ospf-router-id"},
405     { BGP_EXT_COM_OSPF_RID2,   "ospf-router-id"},
406     { BGP_EXT_COM_L2INFO,      "layer2-info"}, 
407     { 0, NULL},
408 };
409
410 /* OSPF codes for  BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls  */
411 #define BGP_OSPF_RTYPE_RTR      1 /* OSPF Router LSA */
412 #define BGP_OSPF_RTYPE_NET      2 /* OSPF Network LSA */
413 #define BGP_OSPF_RTYPE_SUM      3 /* OSPF Summary LSA */
414 #define BGP_OSPF_RTYPE_EXT      5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
415 #define BGP_OSPF_RTYPE_NSSA     7 /* OSPF NSSA External*/
416 #define BGP_OSPF_RTYPE_SHAM     129 /* OSPF-MPLS-VPN Sham link */
417 #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
418
419 static struct tok bgp_extd_comm_ospf_rtype_values[] = {
420   { BGP_OSPF_RTYPE_RTR, "Router" },  
421   { BGP_OSPF_RTYPE_NET, "Network" },  
422   { BGP_OSPF_RTYPE_SUM, "Summary" },  
423   { BGP_OSPF_RTYPE_EXT, "External" },  
424   { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
425   { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },  
426   { 0, NULL },
427 };
428
429 static struct tok bgp_l2vpn_encaps_values[] = {
430     { 0,                      "Reserved"},
431     { 1,                      "Frame Relay"},
432     { 2,                      "ATM AAL5 VCC transport"},
433     { 3,                      "ATM transparent cell transport"}, 
434     { 4,                      "Ethernet VLAN"}, 
435     { 5,                      "Ethernet"}, 
436     { 6,                      "Cisco-HDLC"}, 
437     { 7,                      "PPP"}, 
438     { 8,                      "CEM"}, 
439     { 9,                      "ATM VCC cell transport"}, 
440     { 10,                     "ATM VPC cell transport"}, 
441     { 11,                     "MPLS"}, 
442     { 12,                     "VPLS"}, 
443     { 64,                     "IP-interworking"}, 
444     { 0, NULL},
445 };
446
447 static int
448 decode_prefix4(const u_char *pptr, char *buf, u_int buflen)
449 {
450         struct in_addr addr;
451         u_int plen;
452
453         TCHECK(pptr[0]);
454         plen = pptr[0];
455         if (32 < plen)
456                 return -1;
457
458         memset(&addr, 0, sizeof(addr));
459         TCHECK2(pptr[1], (plen + 7) / 8);
460         memcpy(&addr, &pptr[1], (plen + 7) / 8);
461         if (plen % 8) {
462                 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
463                         ((0xff00 >> (plen % 8)) & 0xff);
464         }
465         snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
466         return 1 + (plen + 7) / 8;
467
468 trunc:
469         return -2;
470 }
471
472 static int
473 decode_labeled_prefix4(const u_char *pptr, char *buf, u_int buflen)
474 {
475         struct in_addr addr;
476         u_int plen;
477
478         TCHECK(pptr[0]);
479         plen = pptr[0];   /* get prefix length */
480
481         /* this is one of the weirdnesses of rfc3107
482            the label length (actually the label + COS bits)
483            is added to the prefix length;
484            we also do only read out just one label -
485            there is no real application for advertisement of
486            stacked labels in a a single BGP message
487         */
488
489         plen-=24; /* adjust prefixlen - labellength */
490
491         if (32 < plen)
492                 return -1;
493
494         memset(&addr, 0, sizeof(addr));
495         TCHECK2(pptr[4], (plen + 7) / 8);
496         memcpy(&addr, &pptr[4], (plen + 7) / 8);
497         if (plen % 8) {
498                 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
499                         ((0xff00 >> (plen % 8)) & 0xff);
500         }
501         /* the label may get offsetted by 4 bits so lets shift it right */
502         snprintf(buf, buflen, "%s/%d, label:%u %s",
503                  getname((u_char *)&addr),
504                  plen,
505                  EXTRACT_24BITS(pptr+1)>>4,
506                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
507
508         return 4 + (plen + 7) / 8;
509
510 trunc:
511         return -2;
512 }
513
514 /* RDs and RTs share the same semantics
515  * we use bgp_vpn_rd_print for
516  * printing route targets inside a NLRI */
517 static char *
518 bgp_vpn_rd_print (const u_char *pptr) {
519
520    /* allocate space for the following string
521     * xxx.xxx.xxx.xxx:xxxxx
522     * 21 bytes plus one termination byte */
523     static char rd[22];
524     char *pos = rd;
525
526     /* ok lets load the RD format */
527     switch (EXTRACT_16BITS(pptr)) {
528
529         /* AS:IP-address fmt*/
530     case 0:
531         snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u.%u.%u.%u",
532             EXTRACT_16BITS(pptr+2), *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
533         break;
534         /* IP-address:AS fmt*/
535
536     case 1:
537         snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
538             *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6));
539         break;
540
541         /* 4-byte-AS:number fmt*/
542     case 2:
543         snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u",
544             EXTRACT_32BITS(pptr+2), EXTRACT_16BITS(pptr+6));
545         break;
546     default:
547         snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
548         break;
549     }
550     pos += strlen(pos);
551     *(pos) = '\0';
552     return (rd);
553 }
554
555 static int
556 decode_rt_routing_info(const u_char *pptr, char *buf, u_int buflen)
557 {
558         u_int8_t route_target[8];
559         u_int plen;
560
561         TCHECK(pptr[0]);
562         plen = pptr[0];   /* get prefix length */
563
564         plen-=32; /* adjust prefix length */
565
566         if (0 < plen)
567                 return -1;
568
569         memset(&route_target, 0, sizeof(route_target));
570         TCHECK2(pptr[1], (plen + 7) / 8);
571         memcpy(&route_target, &pptr[1], (plen + 7) / 8);
572         if (plen % 8) {
573                 ((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
574                         ((0xff00 >> (plen % 8)) & 0xff);
575         }
576         snprintf(buf, buflen, "origin AS: %u, route target %s",
577                  EXTRACT_32BITS(pptr+1),
578                  bgp_vpn_rd_print((u_char *)&route_target));
579
580         return 5 + (plen + 7) / 8;
581
582 trunc:
583         return -2;
584 }
585
586 static int
587 decode_labeled_vpn_prefix4(const u_char *pptr, char *buf, u_int buflen)
588 {
589         struct in_addr addr;
590         u_int plen;
591
592         TCHECK(pptr[0]);
593         plen = pptr[0];   /* get prefix length */
594
595         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
596
597         if (32 < plen)
598                 return -1;
599
600         memset(&addr, 0, sizeof(addr));
601         TCHECK2(pptr[12], (plen + 7) / 8);
602         memcpy(&addr, &pptr[12], (plen + 7) / 8);
603         if (plen % 8) {
604                 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
605                         ((0xff00 >> (plen % 8)) & 0xff);
606         }
607         /* the label may get offsetted by 4 bits so lets shift it right */
608         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
609                  bgp_vpn_rd_print(pptr+4),
610                  getname((u_char *)&addr),
611                  plen,
612                  EXTRACT_24BITS(pptr+1)>>4,
613                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
614
615         return 12 + (plen + 7) / 8;
616
617 trunc:
618         return -2;
619 }
620
621 static int
622 decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
623 {
624         int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len;
625
626         TCHECK2(pptr[0], 2);
627         plen=EXTRACT_16BITS(pptr);
628         tlen=plen;
629         pptr+=2;
630         TCHECK2(pptr[0],15);
631         strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
632                         bgp_vpn_rd_print(pptr),
633                         EXTRACT_16BITS(pptr+8),
634                         EXTRACT_16BITS(pptr+10),
635                         EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
636         pptr+=15;
637         tlen-=15;
638
639         /* ok now the variable part - lets read out TLVs*/
640         while (tlen>0) {
641             if (tlen < 3)
642                 return -1;
643             TCHECK2(pptr[0], 3);
644             tlv_type=*pptr++;
645             tlv_len=EXTRACT_16BITS(pptr);
646             ttlv_len=tlv_len;
647             pptr+=2;
648
649             switch(tlv_type) {
650             case 1:
651                 strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
652                                  tlv_type,
653                                  tlv_len);
654                 ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
655                 while (ttlv_len>0) {
656                     TCHECK(pptr[0]);
657                     strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
658                     ttlv_len--;
659                 }
660                 break;
661             default:
662                 snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u",
663                          tlv_type,
664                          tlv_len);
665                 break;
666             }
667             tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
668         }
669         return plen+2;
670
671 trunc:
672         return -2;
673 }
674
675 #ifdef INET6
676 static int
677 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
678 {
679         struct in6_addr addr;
680         u_int plen;
681
682         TCHECK(pd[0]);
683         plen = pd[0];
684         if (128 < plen)
685                 return -1;
686
687         memset(&addr, 0, sizeof(addr));
688         TCHECK2(pd[1], (plen + 7) / 8);
689         memcpy(&addr, &pd[1], (plen + 7) / 8);
690         if (plen % 8) {
691                 addr.s6_addr[(plen + 7) / 8 - 1] &=
692                         ((0xff00 >> (plen % 8)) & 0xff);
693         }
694         snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
695         return 1 + (plen + 7) / 8;
696
697 trunc:
698         return -2;
699 }
700
701 static int
702 decode_labeled_prefix6(const u_char *pptr, char *buf, u_int buflen)
703 {
704         struct in6_addr addr;
705         u_int plen;
706
707         TCHECK(pptr[0]);
708         plen = pptr[0]; /* get prefix length */
709         plen-=24; /* adjust prefixlen - labellength */
710
711         if (128 < plen)
712                 return -1;
713
714         memset(&addr, 0, sizeof(addr));
715         TCHECK2(pptr[4], (plen + 7) / 8);
716         memcpy(&addr, &pptr[4], (plen + 7) / 8);
717         if (plen % 8) {
718                 addr.s6_addr[(plen + 7) / 8 - 1] &=
719                         ((0xff00 >> (plen % 8)) & 0xff);
720         }
721         /* the label may get offsetted by 4 bits so lets shift it right */
722         snprintf(buf, buflen, "%s/%d, label:%u %s",
723                  getname6((u_char *)&addr),
724                  plen,
725                  EXTRACT_24BITS(pptr+1)>>4,
726                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
727
728         return 4 + (plen + 7) / 8;
729
730 trunc:
731         return -2;
732 }
733
734 static int
735 decode_labeled_vpn_prefix6(const u_char *pptr, char *buf, u_int buflen)
736 {
737         struct in6_addr addr;
738         u_int plen;
739
740         TCHECK(pptr[0]);
741         plen = pptr[0];   /* get prefix length */
742
743         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
744
745         if (128 < plen)
746                 return -1;
747
748         memset(&addr, 0, sizeof(addr));
749         TCHECK2(pptr[12], (plen + 7) / 8);
750         memcpy(&addr, &pptr[12], (plen + 7) / 8);
751         if (plen % 8) {
752                 addr.s6_addr[(plen + 7) / 8 - 1] &=
753                         ((0xff00 >> (plen % 8)) & 0xff);
754         }
755         /* the label may get offsetted by 4 bits so lets shift it right */
756         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
757                  bgp_vpn_rd_print(pptr+4),
758                  getname6((u_char *)&addr),
759                  plen,
760                  EXTRACT_24BITS(pptr+1)>>4,
761                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
762
763         return 12 + (plen + 7) / 8;
764
765 trunc:
766         return -2;
767 }
768 #endif
769
770 static int
771 bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
772 {
773         int i;
774         u_int16_t af;
775         u_int8_t safi, snpa;
776         union { /* copy buffer for bandwidth values */
777             float f; 
778             u_int32_t i;
779         } bw;
780         int advance;
781         int tlen;
782         const u_char *tptr;
783         char buf[MAXHOSTNAMELEN + 100];
784
785         tptr = pptr;
786         tlen=len;
787
788         switch (attr->bgpa_type) {
789         case BGPTYPE_ORIGIN:
790                 if (len != 1)
791                         printf("invalid len");
792                 else {
793                         TCHECK(*tptr);
794                         printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
795                 }
796                 break;
797         case BGPTYPE_AS_PATH:
798                 if (len % 2) {
799                         printf("invalid len");
800                         break;
801                 }
802                 if (!len) {
803                         printf("empty");
804                         break;
805                 }
806
807                 while (tptr < pptr + len) {
808                         TCHECK(tptr[0]);
809                         printf("%s", tok2str(bgp_as_path_segment_open_values, "?", tptr[0]));
810                         for (i = 0; i < tptr[1] * 2; i += 2) {
811                             TCHECK2(tptr[2 + i], 2);
812                             printf("%u ", EXTRACT_16BITS(&tptr[2 + i]));
813                         }
814                         TCHECK(tptr[0]);
815                         printf("%s", tok2str(bgp_as_path_segment_close_values, "?", tptr[0]));
816                         TCHECK(tptr[1]);
817                         tptr += 2 + tptr[1] * 2;
818                 }
819                 break;
820         case BGPTYPE_NEXT_HOP:
821                 if (len != 4)
822                         printf("invalid len");
823                 else {
824                         TCHECK2(tptr[0], 4);
825                         printf("%s", getname(tptr));
826                 }
827                 break;
828         case BGPTYPE_MULTI_EXIT_DISC:
829         case BGPTYPE_LOCAL_PREF:
830                 if (len != 4)
831                         printf("invalid len");
832                 else {
833                         TCHECK2(tptr[0], 4);
834                         printf("%u", EXTRACT_32BITS(tptr));
835                 }
836                 break;
837         case BGPTYPE_ATOMIC_AGGREGATE:
838                 if (len != 0)
839                         printf("invalid len");
840                 break;
841         case BGPTYPE_AGGREGATOR:
842                 if (len != 6) {
843                         printf("invalid len");
844                         break;
845                 }
846                 TCHECK2(tptr[0], 6);
847                 printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
848                         getname(tptr + 2));
849                 break;
850         case BGPTYPE_COMMUNITIES:
851                 if (len % 4) {
852                         printf("invalid len");
853                         break;
854                 }
855                 while (tlen>0) {
856                         u_int32_t comm;
857                         TCHECK2(tptr[0], 4);
858                         comm = EXTRACT_32BITS(tptr);
859                         switch (comm) {
860                         case BGP_COMMUNITY_NO_EXPORT:
861                                 printf(" NO_EXPORT");
862                                 break;
863                         case BGP_COMMUNITY_NO_ADVERT:
864                                 printf(" NO_ADVERTISE");
865                                 break;
866                         case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
867                                 printf(" NO_EXPORT_SUBCONFED");
868                                 break;
869                         default:
870                                 printf("%u:%u%s",
871                                        (comm >> 16) & 0xffff,
872                                        comm & 0xffff,
873                                        (tlen>4) ? ", " : "");
874                                 break;
875                         }
876                         tlen -=4;
877                         tptr +=4;
878                 }
879                 break;
880         case BGPTYPE_ORIGINATOR_ID:
881                 if (len != 4) {
882                         printf("invalid len");
883                         break;
884                 }
885                 TCHECK2(tptr[0], 4);
886                 printf("%s",getname(tptr));
887                 break;
888         case BGPTYPE_CLUSTER_LIST:
889                 if (len % 4) {
890                         printf("invalid len");
891                         break;
892                 }
893                 while (tlen>0) {
894                         TCHECK2(tptr[0], 4);
895                         printf("%s%s",
896                                getname(tptr),
897                                 (tlen>4) ? ", " : "");
898                         tlen -=4;
899                         tptr +=4;
900                 }
901                 break;
902         case BGPTYPE_MP_REACH_NLRI:
903                 TCHECK2(tptr[0], 3);
904                 af = EXTRACT_16BITS(tptr);
905                 safi = tptr[2];
906         
907                 printf("\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
908                        tok2str(bgp_afi_values, "Unknown AFI", af),
909                        af,
910                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
911                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
912                        safi);
913
914                 if (af == AFNUM_INET || af==AFNUM_L2VPN)
915                         ;
916 #ifdef INET6
917                 else if (af == AFNUM_INET6)
918                         ;
919 #endif
920                 else {
921                     printf("\n\t    no AFI %u decoder",af);
922                     if (vflag <= 1)
923                         print_unknown_data(tptr,"\n\t    ",tlen);
924                     break;
925                 }
926
927                 tptr +=3;
928
929                 TCHECK(tptr[0]);
930                 tlen = tptr[0];
931                 tptr++;
932
933                 if (tlen) {
934                         printf("\n\t    nexthop: ");
935                         while (tlen > 0) {
936                                 switch (af) {
937                                 case AFNUM_INET:
938                                     switch(safi) {
939                                     case SAFNUM_UNICAST:
940                                     case SAFNUM_MULTICAST:
941                                     case SAFNUM_UNIMULTICAST:
942                                     case SAFNUM_LABUNICAST:
943                                     case SAFNUM_RT_ROUTING_INFO:
944                                         if (tlen < (int)sizeof(struct in_addr)) {
945                                             printf("invalid len");
946                                             tlen = 0;
947                                         } else {
948                                             TCHECK2(tptr[0], sizeof(struct in_addr));
949                                             printf("%s",getname(tptr));
950                                             tlen -= sizeof(struct in_addr);
951                                             tptr += sizeof(struct in_addr);
952                                         }
953                                         break;
954                                     case SAFNUM_VPNUNICAST:
955                                     case SAFNUM_VPNMULTICAST:
956                                     case SAFNUM_VPNUNIMULTICAST:
957                                         if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
958                                             printf("invalid len");
959                                             tlen = 0;
960                                         } else {
961                                             TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
962                                             printf("RD: %s, %s",
963                                                bgp_vpn_rd_print(tptr),
964                                                getname(tptr+BGP_VPN_RD_LEN));
965                                             tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
966                                             tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
967                                         }
968                                         break;
969                                     default:
970                                         TCHECK2(tptr[0], tlen);
971                                         printf("no SAFI %u decoder",safi);
972                                         if (vflag <= 1)
973                                             print_unknown_data(tptr,"\n\t    ",tlen);
974                                         tptr += tlen;
975                                         tlen = 0;
976                                         break;
977                                     }
978                                     break;
979 #ifdef INET6
980                                 case AFNUM_INET6:
981                                     switch(safi) {
982                                     case SAFNUM_UNICAST:
983                                     case SAFNUM_MULTICAST:
984                                     case SAFNUM_UNIMULTICAST:
985                                     case SAFNUM_LABUNICAST:
986                                     case SAFNUM_RT_ROUTING_INFO:
987                                         if (tlen < (int)sizeof(struct in6_addr)) {
988                                             printf("invalid len");
989                                             tlen = 0;
990                                         } else {
991                                             TCHECK2(tptr[0], sizeof(struct in6_addr));
992                                             printf("%s", getname6(tptr));
993                                             tlen -= sizeof(struct in6_addr);
994                                             tptr += sizeof(struct in6_addr);
995                                         }
996                                         break;
997                                     case SAFNUM_VPNUNICAST:
998                                     case SAFNUM_VPNMULTICAST:
999                                     case SAFNUM_VPNUNIMULTICAST:
1000                                         if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1001                                             printf("invalid len");
1002                                             tlen = 0;
1003                                         } else {
1004                                             TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1005                                             printf("RD: %s, %s",
1006                                                bgp_vpn_rd_print(tptr),
1007                                                getname6(tptr+BGP_VPN_RD_LEN));
1008                                             tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1009                                             tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1010                                         }
1011                                         break;
1012                                     default:
1013                                         TCHECK2(tptr[0], tlen);
1014                                         printf("no SAFI %u decoder",safi);
1015                                         if (vflag <= 1)
1016                                             print_unknown_data(tptr,"\n\t    ",tlen);                                        
1017                                         tptr += tlen;
1018                                         tlen = 0;
1019                                         break;
1020                                     }
1021                                     break;
1022 #endif
1023                                 case AFNUM_L2VPN:
1024                                    switch(safi) {
1025                                     case SAFNUM_VPNUNICAST:
1026                                     case SAFNUM_VPNMULTICAST:
1027                                     case SAFNUM_VPNUNIMULTICAST:
1028                                         if (tlen < (int)sizeof(struct in_addr)) {
1029                                             printf("invalid len");
1030                                             tlen = 0;
1031                                         } else {
1032                                             TCHECK2(tptr[0], sizeof(struct in_addr));
1033                                             printf("%s", getname(tptr));
1034                                             tlen -= (sizeof(struct in_addr));
1035                                             tptr += (sizeof(struct in_addr));
1036                                         }
1037                                         break;
1038                                    default:
1039                                         TCHECK2(tptr[0], tlen);
1040                                         printf("no SAFI %u decoder",safi);
1041                                         if (vflag <= 1)
1042                                             print_unknown_data(tptr,"\n\t    ",tlen);                                        
1043                                         tptr += tlen;
1044                                         tlen = 0;
1045                                         break;
1046                                    }
1047                                    break;
1048
1049                                 default:
1050                                     TCHECK2(tptr[0], tlen);
1051                                     printf("no AFI %u decoder",af);
1052                                     if (vflag <= 1)
1053                                       print_unknown_data(tptr,"\n\t    ",tlen);
1054                                     tptr += tlen;
1055                                     tlen = 0;
1056                                     break;
1057                                 }
1058                         }
1059                 }
1060                 tptr += tlen;
1061
1062                 TCHECK(tptr[0]);
1063                 snpa = tptr[0];
1064                 tptr++;
1065
1066                 if (snpa) {
1067                         printf("\n\t    %u SNPA", snpa);
1068                         for (/*nothing*/; snpa > 0; snpa--) {
1069                                 TCHECK(tptr[0]);
1070                                 printf("\n\t      %d bytes", tptr[0]);
1071                                 tptr += tptr[0] + 1;
1072                         }
1073                 } else {
1074                         printf(", no SNPA");
1075                 }
1076
1077                 while (len - (tptr - pptr) > 0) {
1078                         switch (af) {
1079                         case AFNUM_INET:
1080                             switch (safi) {
1081                             case SAFNUM_UNICAST:
1082                             case SAFNUM_MULTICAST:
1083                             case SAFNUM_UNIMULTICAST:
1084                                 advance = decode_prefix4(tptr, buf, sizeof(buf));
1085                                 if (advance == -1)
1086                                         printf("\n\t    (illegal prefix length)");
1087                                 else if (advance == -2)
1088                                         goto trunc;
1089                                 else
1090                                         printf("\n\t      %s", buf);
1091                                 break;
1092                             case SAFNUM_LABUNICAST:
1093                                 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1094                                 if (advance == -1)
1095                                         printf("\n\t    (illegal prefix length)");
1096                                 else if (advance == -2)
1097                                         goto trunc;
1098                                 else
1099                                         printf("\n\t      %s", buf);
1100                                 break;
1101                             case SAFNUM_VPNUNICAST:
1102                             case SAFNUM_VPNMULTICAST:
1103                             case SAFNUM_VPNUNIMULTICAST:
1104                                 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1105                                 if (advance == -1)
1106                                         printf("\n\t    (illegal prefix length)");
1107                                 else if (advance == -2)
1108                                         goto trunc;
1109                                 else
1110                                         printf("\n\t      %s", buf);
1111                                 break;
1112                             case SAFNUM_RT_ROUTING_INFO:
1113                                 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1114                                 if (advance == -1)
1115                                         printf("\n\t    (illegal prefix length)");
1116                                 else if (advance == -2)
1117                                         goto trunc;
1118                                 else
1119                                         printf("\n\t      %s", buf);
1120                                 break;
1121                             default:
1122                                 TCHECK2(*(tptr-3),tlen);
1123                                 printf("\n\t      no SAFI %u decoder",safi);
1124                                 if (vflag <= 1)
1125                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1126                                 advance = 0;
1127                                 tptr = pptr + len;
1128                                 break;  
1129                             }
1130                             break;
1131 #ifdef INET6
1132                         case AFNUM_INET6:
1133                             switch (safi) {
1134                             case SAFNUM_UNICAST:
1135                             case SAFNUM_MULTICAST:
1136                             case SAFNUM_UNIMULTICAST:
1137                                 advance = decode_prefix6(tptr, buf, sizeof(buf));
1138                                 if (advance == -1)
1139                                         printf("\n\t    (illegal prefix length)");
1140                                 else if (advance == -2)
1141                                         goto trunc;
1142                                 else
1143                                         printf("\n\t      %s", buf);
1144                                 break;
1145                             case SAFNUM_LABUNICAST:
1146                                 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1147                                 if (advance == -1)
1148                                         printf("\n\t    (illegal prefix length)");
1149                                 else if (advance == -2)
1150                                         goto trunc;
1151                                 else
1152                                         printf("\n\t      %s", buf);
1153                                 break;
1154                             case SAFNUM_VPNUNICAST:
1155                             case SAFNUM_VPNMULTICAST:
1156                             case SAFNUM_VPNUNIMULTICAST:
1157                                 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1158                                 if (advance == -1)
1159                                         printf("\n\t    (illegal prefix length)");
1160                                 else if (advance == -2)
1161                                         goto trunc;
1162                                 else
1163                                         printf("\n\t      %s", buf);
1164                                 break;
1165                             case SAFNUM_RT_ROUTING_INFO:
1166                                 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1167                                 if (advance == -1)
1168                                         printf("\n\t    (illegal prefix length)");
1169                                 else if (advance == -2)
1170                                         goto trunc;
1171                                 else
1172                                         printf("\n\t      %s", buf);
1173                                 break;
1174                             default:
1175                                 TCHECK2(*(tptr-3),tlen);
1176                                 printf("\n\t      no SAFI %u decoder ",safi);
1177                                 if (vflag <= 1)
1178                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1179                                 advance = 0;
1180                                 tptr = pptr + len;
1181                                 break;
1182                             }
1183                             break;
1184 #endif
1185                         case AFNUM_L2VPN:
1186                             switch(safi) {
1187                             case SAFNUM_VPNUNICAST:
1188                             case SAFNUM_VPNMULTICAST:
1189                             case SAFNUM_VPNUNIMULTICAST:
1190                                 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1191                                 if (advance == -1)
1192                                         printf("\n\t    (illegal length)");
1193                                 else if (advance == -2)
1194                                         goto trunc;
1195                                 else
1196                                         printf("\n\t      %s", buf);         
1197                                 break;                                   
1198                             default:
1199                                 TCHECK2(*tptr,tlen);
1200                                 printf("no SAFI %u decoder",safi);
1201                                 if (vflag <= 1)
1202                                     print_unknown_data(tptr,"\n\t    ",tlen);
1203                                 advance = 0;
1204                                 tptr = pptr + len;
1205                                 break;
1206                             }
1207                             break;
1208
1209
1210                         default:
1211                             TCHECK2(*(tptr-3),tlen);
1212                             printf("\n\t      no AFI %u decoder ",af);
1213                             if (vflag <= 1)
1214                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1215                             advance = 0;
1216                             tptr = pptr + len;
1217                             break;
1218                         }
1219                         tptr += advance;
1220                 }
1221                 break;
1222
1223         case BGPTYPE_MP_UNREACH_NLRI:
1224                 TCHECK2(tptr[0], 3);
1225                 af = EXTRACT_16BITS(tptr);
1226                 safi = tptr[2];
1227
1228                 printf("\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1229                        tok2str(bgp_afi_values, "Unknown AFI", af),
1230                        af,
1231                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1232                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
1233                        safi);
1234
1235                 tptr += 3;
1236                 
1237                 while (len - (tptr - pptr) > 0) {
1238                         switch (af) {
1239                         case AFNUM_INET:
1240                             switch (safi) {
1241                             case SAFNUM_UNICAST:
1242                             case SAFNUM_MULTICAST:
1243                             case SAFNUM_UNIMULTICAST:
1244                                 advance = decode_prefix4(tptr, buf, sizeof(buf));
1245                                 if (advance == -1)
1246                                         printf("\n\t    (illegal prefix length)");
1247                                 else if (advance == -2)
1248                                         goto trunc;
1249                                 else
1250                                         printf("\n\t      %s", buf);
1251                                 break;
1252                             case SAFNUM_LABUNICAST:
1253                                 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1254                                 if (advance == -1)
1255                                         printf("\n\t    (illegal prefix length)");
1256                                 else if (advance == -2)
1257                                         goto trunc;
1258                                 else
1259                                         printf("\n\t      %s", buf);
1260                                 break;
1261                             case SAFNUM_VPNUNICAST:
1262                             case SAFNUM_VPNMULTICAST:
1263                             case SAFNUM_VPNUNIMULTICAST:
1264                                 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1265                                 if (advance == -1)
1266                                         printf("\n\t    (illegal prefix length)");
1267                                 else if (advance == -2)
1268                                         goto trunc;
1269                                 else
1270                                         printf("\n\t      %s", buf);
1271                                 break;
1272                             default:
1273                                 TCHECK2(*(tptr-3),tlen);
1274                                 printf("\n\t      no SAFI %u decoder",safi);
1275                                 if (vflag <= 1)
1276                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1277                                 advance = 0;
1278                                 tptr = pptr + len;
1279                                 break;  
1280                             }
1281                             break;
1282
1283 #ifdef INET6
1284                         case AFNUM_INET6:
1285                             switch (safi) {
1286                             case SAFNUM_UNICAST:
1287                             case SAFNUM_MULTICAST:
1288                             case SAFNUM_UNIMULTICAST:
1289                                 advance = decode_prefix6(tptr, buf, sizeof(buf));
1290                                 if (advance == -1)
1291                                         printf("\n\t    (illegal prefix length)");
1292                                 else if (advance == -2)
1293                                         goto trunc;
1294                                 else
1295                                         printf("\n\t      %s", buf);
1296                                 break;
1297                             case SAFNUM_LABUNICAST:
1298                                 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1299                                 if (advance == -1)
1300                                         printf("\n\t    (illegal prefix length)");
1301                                 else if (advance == -2)
1302                                         goto trunc;
1303                                 else
1304                                         printf("\n\t      %s", buf);
1305                                 break;
1306                             case SAFNUM_VPNUNICAST:
1307                             case SAFNUM_VPNMULTICAST:
1308                             case SAFNUM_VPNUNIMULTICAST:
1309                                 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1310                                 if (advance == -1)
1311                                         printf("\n\t    (illegal prefix length)");
1312                                 else if (advance == -2)
1313                                         goto trunc;
1314                                 else
1315                                         printf("\n\t      %s", buf);
1316                                 break;
1317                             default:
1318                                 TCHECK2(*(tptr-3),tlen);
1319                                 printf("\n\t      no SAFI %u decoder",safi);
1320                                 if (vflag <= 1)
1321                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1322                                 advance = 0;
1323                                 tptr = pptr + len;
1324                                 break;
1325                             }
1326                             break;
1327 #endif
1328
1329                         case AFNUM_L2VPN:
1330                             switch(safi) {
1331                             case SAFNUM_VPNUNICAST:
1332                             case SAFNUM_VPNMULTICAST:
1333                             case SAFNUM_VPNUNIMULTICAST:
1334                                 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1335                                 if (advance == -1)
1336                                         printf("\n\t    (illegal length)");
1337                                 else if (advance == -2)
1338                                         goto trunc;
1339                                 else
1340                                         printf("\n\t      %s", buf);         
1341                                 break;                                   
1342                             default:
1343                                 TCHECK2(*(tptr-3),tlen);
1344                                 printf("no SAFI %u decoder",safi);
1345                                 if (vflag <= 1)
1346                                     print_unknown_data(tptr-3,"\n\t    ",tlen);                                        
1347                                 advance = 0;
1348                                 tptr = pptr + len;
1349                                 break;
1350                             }
1351                             break;
1352
1353                         default:
1354                                 TCHECK2(*(tptr-3),tlen);
1355                                 printf("\n\t    no AFI %u decoder",af);
1356                                 if (vflag <= 1)
1357                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1358                                 advance = 0;
1359                                 tptr = pptr + len;
1360                                 break;
1361                         }
1362
1363                         tptr += advance;
1364                 }
1365                 break;
1366         case BGPTYPE_EXTD_COMMUNITIES:
1367                 if (len % 8) {
1368                         printf("invalid len");
1369                         break;
1370                 }
1371                 while (tlen>0) {
1372                     u_int16_t extd_comm;
1373
1374                     TCHECK2(tptr[0], 2);
1375                     extd_comm=EXTRACT_16BITS(tptr);
1376
1377                     printf("\n\t    %s (0x%04x), Flags [%s]",
1378                            tok2str(bgp_extd_comm_subtype_values, "unknown extd community typecode", extd_comm),
1379                            extd_comm,
1380                            bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
1381
1382                     TCHECK2(*(tptr+2), 6);
1383                     switch(extd_comm) {
1384                     case BGP_EXT_COM_RT_0:
1385                     case BGP_EXT_COM_RO_0:
1386                         printf(": %u:%s",
1387                                EXTRACT_16BITS(tptr+2),
1388                                getname(tptr+4));
1389                         break;
1390                     case BGP_EXT_COM_RT_1:
1391                     case BGP_EXT_COM_RO_1:
1392                         printf(": %s:%u",
1393                                getname(tptr+2),
1394                                EXTRACT_16BITS(tptr+6));
1395                         break;
1396                     case BGP_EXT_COM_RT_2:
1397                     case BGP_EXT_COM_RO_2:
1398                         printf(": %u:%u",
1399                                EXTRACT_32BITS(tptr+2),
1400                                EXTRACT_16BITS(tptr+6));
1401                         break;
1402                     case BGP_EXT_COM_LINKBAND:
1403                         bw.i = EXTRACT_32BITS(tptr+2);
1404                         printf(": bandwidth: %.3f Mbps",
1405                                bw.f*8/1000000);
1406                         break;
1407                     case BGP_EXT_COM_VPN_ORIGIN:
1408                     case BGP_EXT_COM_VPN_ORIGIN2:
1409                     case BGP_EXT_COM_VPN_ORIGIN3:
1410                     case BGP_EXT_COM_VPN_ORIGIN4:
1411                     case BGP_EXT_COM_OSPF_RID:
1412                     case BGP_EXT_COM_OSPF_RID2:
1413                         printf("%s", getname(tptr+2));
1414                         break;
1415                     case BGP_EXT_COM_OSPF_RTYPE:
1416                     case BGP_EXT_COM_OSPF_RTYPE2: 
1417                         printf(": area:%s, router-type:%s, metric-type:%s%s",
1418                                getname(tptr+2),
1419                                tok2str(bgp_extd_comm_ospf_rtype_values,
1420                                        "unknown (0x%02x)",
1421                                        *(tptr+6)),
1422                                (*(tptr+7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
1423                                (*(tptr+6) == (BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA )) ? "E1" : "");
1424                         break;
1425                     case BGP_EXT_COM_L2INFO:
1426                         printf(": %s Control Flags [0x%02x]:MTU %u",
1427                                tok2str(bgp_l2vpn_encaps_values,
1428                                        "unknown encaps",
1429                                        *(tptr+2)),
1430                                        *(tptr+3),
1431                                EXTRACT_16BITS(tptr+4));
1432                         break;
1433                     default:
1434                         print_unknown_data(tptr,"\n\t      ",8);
1435                         break;
1436                     }
1437                     tlen -=8;
1438                     tptr +=8;
1439                 }
1440                 break;
1441
1442         default:
1443             TCHECK2(*pptr,len);
1444             printf("\n\t    no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
1445             if (vflag <= 1)
1446                 print_unknown_data(pptr,"\n\t    ",len);
1447             break;
1448         }
1449         if (vflag > 1 && len) /* omit zero length attributes*/
1450             print_unknown_data(pptr,"\n\t    ",len);
1451         return 1;
1452
1453 trunc:
1454         return 0;
1455 }
1456
1457 static void
1458 bgp_open_print(const u_char *dat, int length)
1459 {
1460         struct bgp_open bgpo;
1461         struct bgp_opt bgpopt;
1462         int hlen;
1463         const u_char *opt;
1464         int i,cap_type,cap_len,tcap_len,cap_offset;
1465
1466         TCHECK2(dat[0], BGP_OPEN_SIZE);
1467         memcpy(&bgpo, dat, BGP_OPEN_SIZE);
1468         hlen = ntohs(bgpo.bgpo_len);
1469
1470         printf("\n\t  Version %d, ", bgpo.bgpo_version);
1471         printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
1472         printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
1473         printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
1474         printf("\n\t  Optional parameters, length: %u", bgpo.bgpo_optlen);
1475
1476         /* some little sanity checking */
1477         if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) 
1478             return;
1479
1480         /* ugly! */
1481         opt = &((const struct bgp_open *)dat)->bgpo_optlen;
1482         opt++;
1483
1484         i = 0;
1485         while (i < bgpo.bgpo_optlen) {
1486                 TCHECK2(opt[i], BGP_OPT_SIZE);
1487                 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
1488                 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
1489                         printf("\n\t     Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
1490                         break;
1491                 }
1492
1493                 printf("\n\t    Option %s (%u), length: %u",
1494                        tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
1495                        bgpopt.bgpopt_type,
1496                        bgpopt.bgpopt_len);
1497
1498                 /* now lets decode the options we know*/
1499                 switch(bgpopt.bgpopt_type) {
1500                 case BGP_OPT_CAP:
1501                     cap_type=opt[i+BGP_OPT_SIZE];
1502                     cap_len=opt[i+BGP_OPT_SIZE+1];
1503                     tcap_len=cap_len;
1504                     printf("\n\t      %s, length: %u",
1505                            tok2str(bgp_capcode_values,"Unknown", cap_type),
1506                            cap_len);
1507                     switch(cap_type) {
1508                     case BGP_CAPCODE_MP:
1509                         printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
1510                                tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
1511                                EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
1512                                tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
1513                                opt[i+BGP_OPT_SIZE+5]);
1514                         break;
1515                     case BGP_CAPCODE_RESTART:
1516                         printf("\n\t\tRestart Flags: [%s], Restart Time %us",
1517                                ((opt[i+BGP_OPT_SIZE+2])&0x80) ? "R" : "none",
1518                                EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)&0xfff);
1519                         tcap_len-=2;
1520                         cap_offset=4;
1521                         while(tcap_len>=4) {
1522                             printf("\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
1523                                    tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset)),
1524                                    EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
1525                                    tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+cap_offset+2]),
1526                                    opt[i+BGP_OPT_SIZE+cap_offset+2],
1527                                    ((opt[i+BGP_OPT_SIZE+cap_offset+3])&0x80) ? "yes" : "no" );
1528                             tcap_len-=4;
1529                             cap_offset+=4;
1530                         }
1531                         break;
1532                     case BGP_CAPCODE_RR:
1533                     case BGP_CAPCODE_RR_CISCO:
1534                         break;
1535                     default:
1536                         printf("\n\t\tno decoder for Capability %u",
1537                                cap_type);
1538                         if (vflag <= 1)
1539                             print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1540                         break;
1541                     }
1542                     if (vflag > 1)
1543                         print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1544                     break;
1545                 case BGP_OPT_AUTH:
1546                 default:
1547                        printf("\n\t      no decoder for option %u",
1548                            bgpopt.bgpopt_type);
1549                        break;
1550                 }
1551
1552                 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
1553         }
1554         return;
1555 trunc:
1556         printf("[|BGP]");
1557 }
1558
1559 static void
1560 bgp_update_print(const u_char *dat, int length)
1561 {
1562         struct bgp bgp;
1563         struct bgp_attr bgpa;
1564         int hlen;
1565         const u_char *p;
1566         int len;
1567         int i;
1568
1569         TCHECK2(dat[0], BGP_SIZE);
1570         memcpy(&bgp, dat, BGP_SIZE);
1571         hlen = ntohs(bgp.bgp_len);
1572         p = dat + BGP_SIZE;     /*XXX*/
1573
1574         /* Unfeasible routes */
1575         len = EXTRACT_16BITS(p);
1576         if (len) {
1577                 /*
1578                  * Without keeping state from the original NLRI message,
1579                  * it's not possible to tell if this a v4 or v6 route,
1580                  * so only try to decode it if we're not v6 enabled.
1581                  */
1582 #ifdef INET6
1583                 printf("\n\t  Withdrawn routes: %d bytes", len);
1584 #else
1585                 char buf[MAXHOSTNAMELEN + 100];
1586                 int wpfx;
1587
1588                 TCHECK2(p[2], len);
1589                 i = 2;
1590
1591                 printf("\n\t  Withdrawn routes:");
1592
1593                 while(i < 2 + len) {
1594                         wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
1595                         if (wpfx == -1) {
1596                                 printf("\n\t    (illegal prefix length)");
1597                                 break;
1598                         } else if (wpfx == -2)
1599                                 goto trunc;
1600                         else {
1601                                 i += wpfx;
1602                                 printf("\n\t    %s", buf);
1603                         }
1604                 }
1605 #endif
1606         }
1607         p += 2 + len;
1608
1609         TCHECK2(p[0], 2);
1610         len = EXTRACT_16BITS(p);
1611         if (len) {
1612                 /* do something more useful!*/
1613                 i = 2;
1614                 while (i < 2 + len) {
1615                         int alen, aoff;
1616
1617                         TCHECK2(p[i], sizeof(bgpa));
1618                         memcpy(&bgpa, &p[i], sizeof(bgpa));
1619                         alen = bgp_attr_len(&bgpa);
1620                         aoff = bgp_attr_off(&bgpa);
1621
1622                        printf("\n\t  %s (%u), length: %u",
1623                               tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1624                               bgpa.bgpa_type,
1625                               alen);
1626
1627                         if (bgpa.bgpa_flags) {
1628                                 printf(", Flags [%s%s%s%s",
1629                                         bgpa.bgpa_flags & 0x80 ? "O" : "",
1630                                         bgpa.bgpa_flags & 0x40 ? "T" : "",
1631                                         bgpa.bgpa_flags & 0x20 ? "P" : "",
1632                                         bgpa.bgpa_flags & 0x10 ? "E" : "");
1633                                 if (bgpa.bgpa_flags & 0xf)
1634                                         printf("+%x", bgpa.bgpa_flags & 0xf);
1635                                 printf("]: ");
1636                         }
1637                         if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
1638                                 goto trunc;
1639                         i += aoff + alen;
1640                 }
1641         }
1642         p += 2 + len;
1643
1644         if (dat + length > p) {
1645             printf("\n\t  Updated routes:");
1646                 while (dat + length > p) {
1647                         char buf[MAXHOSTNAMELEN + 100];
1648                         i = decode_prefix4(p, buf, sizeof(buf));
1649                         if (i == -1)
1650                                 printf("\n\t    (illegal prefix length)");
1651                         else if (i == -2)
1652                                 goto trunc;
1653                         else {
1654                                 printf("\n\t    %s", buf);
1655                                 p += i;
1656                         }
1657                 }
1658         }
1659         return;
1660 trunc:
1661         printf("[|BGP]");
1662 }
1663
1664 static void
1665 bgp_notification_print(const u_char *dat, int length)
1666 {
1667         struct bgp_notification bgpn;
1668         int hlen;
1669         const u_char *tptr;
1670
1671         TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1672         memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1673         hlen = ntohs(bgpn.bgpn_len);
1674
1675         /* some little sanity checking */
1676         if (length<BGP_NOTIFICATION_SIZE)
1677             return;
1678
1679         printf(", %s (%u)",
1680                tok2str(bgp_notify_major_values, "Unknown Error", bgpn.bgpn_major),
1681                bgpn.bgpn_major);
1682
1683         switch (bgpn.bgpn_major) {
1684
1685         case BGP_NOTIFY_MAJOR_MSG:
1686             printf(", subcode %s (%u)",
1687                    tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor),
1688                    bgpn.bgpn_minor);
1689             break;
1690         case BGP_NOTIFY_MAJOR_OPEN:
1691             printf(", subcode %s (%u)",
1692                    tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor),
1693                    bgpn.bgpn_minor);
1694             break;
1695         case BGP_NOTIFY_MAJOR_UPDATE:
1696             printf(", subcode %s (%u)",
1697                    tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor),
1698                    bgpn.bgpn_minor);
1699             break;
1700         case BGP_NOTIFY_MAJOR_CAP:
1701             printf(" subcode %s (%u)",
1702                    tok2str(bgp_notify_minor_cap_values, "Unknown", bgpn.bgpn_minor),
1703                    bgpn.bgpn_minor);
1704         case BGP_NOTIFY_MAJOR_CEASE:
1705             printf(", subcode %s (%u)",
1706                    tok2str(bgp_notify_minor_cease_values, "Unknown", bgpn.bgpn_minor),
1707                    bgpn.bgpn_minor);
1708
1709             /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
1710              * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
1711              */
1712             if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
1713                 tptr = dat + BGP_NOTIFICATION_SIZE;
1714                 TCHECK2(*tptr, 7);
1715                 printf(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
1716                        tok2str(bgp_afi_values, "Unknown", EXTRACT_16BITS(tptr)),
1717                        EXTRACT_16BITS(tptr),
1718                        tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
1719                        *(tptr+2),
1720                        EXTRACT_32BITS(tptr+3));
1721             }
1722             break;
1723         default:
1724             break;
1725         }
1726
1727         return;
1728 trunc:
1729         printf("[|BGP]");
1730 }
1731
1732 static void
1733 bgp_route_refresh_print(const u_char *pptr, int len) {
1734
1735         const struct bgp_route_refresh *bgp_route_refresh_header;
1736         bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
1737
1738         printf("\n\t  AFI %s (%u), SAFI %s (%u)",
1739                tok2str(bgp_afi_values,"Unknown",
1740                        EXTRACT_16BITS(&bgp_route_refresh_header->afi)), /* this stinks but the compiler pads the structure weird */
1741                EXTRACT_16BITS(&bgp_route_refresh_header->afi),
1742                tok2str(bgp_safi_values,"Unknown",
1743                        bgp_route_refresh_header->safi),
1744                bgp_route_refresh_header->safi);
1745
1746         if (vflag > 1)
1747             print_unknown_data(pptr,"\n\t  ", len);
1748         
1749         return;
1750 }
1751
1752 static int
1753 bgp_header_print(const u_char *dat, int length)
1754 {
1755         struct bgp bgp;
1756
1757         TCHECK2(dat[0], BGP_SIZE);
1758         memcpy(&bgp, dat, BGP_SIZE);
1759         printf("\n\t%s Message (%u), length: %u",
1760                tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
1761                bgp.bgp_type,
1762                length);
1763
1764         switch (bgp.bgp_type) {
1765         case BGP_OPEN:
1766                 bgp_open_print(dat, length);
1767                 break;
1768         case BGP_UPDATE:
1769                 bgp_update_print(dat, length);
1770                 break;
1771         case BGP_NOTIFICATION:
1772                 bgp_notification_print(dat, length);
1773                 break;
1774         case BGP_KEEPALIVE:
1775                 break;
1776         case BGP_ROUTE_REFRESH:
1777                 bgp_route_refresh_print(dat, length);
1778                 break;
1779         default:
1780             /* we have no decoder for the BGP message */
1781             printf("\n\t  no Message %u decoder",bgp.bgp_type);
1782             print_unknown_data(dat,"\n\t  ",length);
1783                 break;
1784         }
1785         return 1;
1786 trunc:
1787         printf("[|BGP]");
1788         return 0;
1789 }
1790
1791 void
1792 bgp_print(const u_char *dat, int length)
1793 {
1794         const u_char *p;
1795         const u_char *ep;
1796         const u_char *start;
1797         const u_char marker[] = {
1798                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1799                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1800         };
1801         struct bgp bgp;
1802         u_int16_t hlen;
1803
1804         ep = dat + length;
1805         if (snapend < dat + length)
1806                 ep = snapend;
1807
1808         printf(": BGP, length: %u",length);
1809
1810         if (vflag < 1) /* lets be less chatty */
1811                 return;
1812
1813         p = dat;
1814         start = p;
1815         while (p < snapend) {
1816                 if (!TTEST2(p[0], 1))
1817                         break;
1818                 if (p[0] != 0xff) {
1819                         p++;
1820                         continue;
1821                 }
1822
1823                 if (!TTEST2(p[0], sizeof(marker)))
1824                         break;
1825                 if (memcmp(p, marker, sizeof(marker)) != 0) {
1826                         p++;
1827                         continue;
1828                 }
1829
1830                 /* found BGP header */
1831                 TCHECK2(p[0], BGP_SIZE);        /*XXX*/
1832                 memcpy(&bgp, p, BGP_SIZE);
1833
1834                 if (start != p)
1835                         printf(" [|BGP]");
1836
1837                 hlen = ntohs(bgp.bgp_len);
1838                 if (hlen < BGP_SIZE) {
1839                         printf("\n[|BGP Bogus header length %u < %u]", hlen,
1840                             BGP_SIZE);
1841                         break;
1842                 }
1843
1844                 if (TTEST2(p[0], hlen)) {
1845                         if (!bgp_header_print(p, hlen))
1846                                 return;
1847                         p += hlen;
1848                         start = p;
1849                 } else {
1850                         printf("\n[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
1851                         break;
1852                 }
1853         }
1854
1855         return;
1856
1857 trunc:
1858         printf(" [|BGP]");
1859 }