]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-bgp.c
MFV r323530,r323533,r323534: 7431 ZFS Channel Programs, and followups
[FreeBSD/FreeBSD.git] / contrib / tcpdump / 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 /* \summary: Border Gateway Protocol (BGP) printer */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <netdissect-stdinc.h>
40
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "netdissect.h"
45 #include "addrtoname.h"
46 #include "extract.h"
47 #include "af.h"
48 #include "l2vpn.h"
49
50 struct bgp {
51         uint8_t bgp_marker[16];
52         uint16_t bgp_len;
53         uint8_t bgp_type;
54 };
55 #define BGP_SIZE                19      /* unaligned */
56
57 #define BGP_OPEN                1
58 #define BGP_UPDATE              2
59 #define BGP_NOTIFICATION        3
60 #define BGP_KEEPALIVE           4
61 #define BGP_ROUTE_REFRESH       5
62
63 static const struct tok bgp_msg_values[] = {
64     { BGP_OPEN,                 "Open"},
65     { BGP_UPDATE,               "Update"},
66     { BGP_NOTIFICATION,         "Notification"},
67     { BGP_KEEPALIVE,            "Keepalive"},
68     { BGP_ROUTE_REFRESH,        "Route Refresh"},
69     { 0, NULL}
70 };
71
72 struct bgp_open {
73         uint8_t bgpo_marker[16];
74         uint16_t bgpo_len;
75         uint8_t bgpo_type;
76         uint8_t bgpo_version;
77         uint16_t bgpo_myas;
78         uint16_t bgpo_holdtime;
79         uint32_t bgpo_id;
80         uint8_t bgpo_optlen;
81         /* options should follow */
82 };
83 #define BGP_OPEN_SIZE           29      /* unaligned */
84
85 struct bgp_opt {
86         uint8_t bgpopt_type;
87         uint8_t bgpopt_len;
88         /* variable length */
89 };
90 #define BGP_OPT_SIZE            2       /* some compilers may pad to 4 bytes */
91 #define BGP_CAP_HEADER_SIZE     2       /* some compilers may pad to 4 bytes */
92
93 struct bgp_notification {
94         uint8_t bgpn_marker[16];
95         uint16_t bgpn_len;
96         uint8_t bgpn_type;
97         uint8_t bgpn_major;
98         uint8_t bgpn_minor;
99 };
100 #define BGP_NOTIFICATION_SIZE           21      /* unaligned */
101
102 struct bgp_route_refresh {
103     uint8_t  bgp_marker[16];
104     uint16_t len;
105     uint8_t  type;
106     uint8_t  afi[2]; /* the compiler messes this structure up               */
107     uint8_t  res;    /* when doing misaligned sequences of int8 and int16   */
108     uint8_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 #define bgp_attr_lenlen(flags, p) \
113         (((flags) & 0x10) ? 2 : 1)
114 #define bgp_attr_len(flags, p) \
115         (((flags) & 0x10) ? EXTRACT_16BITS(p) : *(p))
116
117 #define BGPTYPE_ORIGIN                  1
118 #define BGPTYPE_AS_PATH                 2
119 #define BGPTYPE_NEXT_HOP                3
120 #define BGPTYPE_MULTI_EXIT_DISC         4
121 #define BGPTYPE_LOCAL_PREF              5
122 #define BGPTYPE_ATOMIC_AGGREGATE        6
123 #define BGPTYPE_AGGREGATOR              7
124 #define BGPTYPE_COMMUNITIES             8       /* RFC1997 */
125 #define BGPTYPE_ORIGINATOR_ID           9       /* RFC4456 */
126 #define BGPTYPE_CLUSTER_LIST            10      /* RFC4456 */
127 #define BGPTYPE_DPA                     11      /* deprecated, draft-ietf-idr-bgp-dpa */
128 #define BGPTYPE_ADVERTISERS             12      /* deprecated RFC1863 */
129 #define BGPTYPE_RCID_PATH               13      /* deprecated RFC1863 */
130 #define BGPTYPE_MP_REACH_NLRI           14      /* RFC4760 */
131 #define BGPTYPE_MP_UNREACH_NLRI         15      /* RFC4760 */
132 #define BGPTYPE_EXTD_COMMUNITIES        16      /* RFC4360 */
133 #define BGPTYPE_AS4_PATH                17      /* RFC6793 */
134 #define BGPTYPE_AGGREGATOR4             18      /* RFC6793 */
135 #define BGPTYPE_PMSI_TUNNEL             22      /* RFC6514 */
136 #define BGPTYPE_TUNNEL_ENCAP            23      /* RFC5512 */
137 #define BGPTYPE_TRAFFIC_ENG             24      /* RFC5543 */
138 #define BGPTYPE_IPV6_EXTD_COMMUNITIES   25      /* RFC5701 */
139 #define BGPTYPE_AIGP                    26      /* RFC7311 */
140 #define BGPTYPE_PE_DISTINGUISHER_LABEL  27      /* RFC6514 */
141 #define BGPTYPE_ENTROPY_LABEL           28      /* RFC6790 */
142 #define BGPTYPE_LARGE_COMMUNITY         32      /* draft-ietf-idr-large-community-05 */
143 #define BGPTYPE_ATTR_SET               128      /* RFC6368 */
144
145 #define BGP_MP_NLRI_MINSIZE              3       /* End of RIB Marker detection */
146
147 static const struct tok bgp_attr_values[] = {
148     { BGPTYPE_ORIGIN,           "Origin"},
149     { BGPTYPE_AS_PATH,          "AS Path"},
150     { BGPTYPE_AS4_PATH,         "AS4 Path"},
151     { BGPTYPE_NEXT_HOP,         "Next Hop"},
152     { BGPTYPE_MULTI_EXIT_DISC,  "Multi Exit Discriminator"},
153     { BGPTYPE_LOCAL_PREF,       "Local Preference"},
154     { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
155     { BGPTYPE_AGGREGATOR,       "Aggregator"},
156     { BGPTYPE_AGGREGATOR4,      "Aggregator4"},
157     { BGPTYPE_COMMUNITIES,      "Community"},
158     { BGPTYPE_ORIGINATOR_ID,    "Originator ID"},
159     { BGPTYPE_CLUSTER_LIST,     "Cluster List"},
160     { BGPTYPE_DPA,              "DPA"},
161     { BGPTYPE_ADVERTISERS,      "Advertisers"},
162     { BGPTYPE_RCID_PATH,        "RCID Path / Cluster ID"},
163     { BGPTYPE_MP_REACH_NLRI,    "Multi-Protocol Reach NLRI"},
164     { BGPTYPE_MP_UNREACH_NLRI,  "Multi-Protocol Unreach NLRI"},
165     { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
166     { BGPTYPE_PMSI_TUNNEL,      "PMSI Tunnel"},
167     { BGPTYPE_TUNNEL_ENCAP,     "Tunnel Encapsulation"},
168     { BGPTYPE_TRAFFIC_ENG,      "Traffic Engineering"},
169     { BGPTYPE_IPV6_EXTD_COMMUNITIES, "IPv6 Extended Community"},
170     { BGPTYPE_AIGP,             "Accumulated IGP Metric"},
171     { BGPTYPE_PE_DISTINGUISHER_LABEL, "PE Distinguisher Label"},
172     { BGPTYPE_ENTROPY_LABEL,    "Entropy Label"},
173     { BGPTYPE_LARGE_COMMUNITY,  "Large Community"},
174     { BGPTYPE_ATTR_SET,         "Attribute Set"},
175     { 255,                      "Reserved for development"},
176     { 0, NULL}
177 };
178
179 #define BGP_AS_SET             1
180 #define BGP_AS_SEQUENCE        2
181 #define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
182 #define BGP_CONFED_AS_SET      4 /* draft-ietf-idr-rfc3065bis-01  */
183
184 #define BGP_AS_SEG_TYPE_MIN    BGP_AS_SET
185 #define BGP_AS_SEG_TYPE_MAX    BGP_CONFED_AS_SET
186
187 static const struct tok bgp_as_path_segment_open_values[] = {
188     { BGP_AS_SEQUENCE,         ""},
189     { BGP_AS_SET,              "{ "},
190     { BGP_CONFED_AS_SEQUENCE,  "( "},
191     { BGP_CONFED_AS_SET,       "({ "},
192     { 0, NULL}
193 };
194
195 static const struct tok bgp_as_path_segment_close_values[] = {
196     { BGP_AS_SEQUENCE,         ""},
197     { BGP_AS_SET,              "}"},
198     { BGP_CONFED_AS_SEQUENCE,  ")"},
199     { BGP_CONFED_AS_SET,       "})"},
200     { 0, NULL}
201 };
202
203 #define BGP_OPT_AUTH                    1
204 #define BGP_OPT_CAP                     2
205
206 static const struct tok bgp_opt_values[] = {
207     { BGP_OPT_AUTH,             "Authentication Information"},
208     { BGP_OPT_CAP,              "Capabilities Advertisement"},
209     { 0, NULL}
210 };
211
212 #define BGP_CAPCODE_MP                  1 /* RFC2858 */
213 #define BGP_CAPCODE_RR                  2 /* RFC2918 */
214 #define BGP_CAPCODE_ORF                 3 /* RFC5291 */
215 #define BGP_CAPCODE_MR                  4 /* RFC3107 */
216 #define BGP_CAPCODE_EXT_NH              5 /* RFC5549 */
217 #define BGP_CAPCODE_RESTART            64 /* RFC4724  */
218 #define BGP_CAPCODE_AS_NEW             65 /* RFC6793 */
219 #define BGP_CAPCODE_DYN_CAP            67 /* draft-ietf-idr-dynamic-cap */
220 #define BGP_CAPCODE_MULTISESS          68 /* draft-ietf-idr-bgp-multisession */
221 #define BGP_CAPCODE_ADD_PATH           69 /* RFC7911 */
222 #define BGP_CAPCODE_ENH_RR             70 /* draft-keyur-bgp-enhanced-route-refresh */
223 #define BGP_CAPCODE_RR_CISCO          128
224
225 static const struct tok bgp_capcode_values[] = {
226     { BGP_CAPCODE_MP,           "Multiprotocol Extensions"},
227     { BGP_CAPCODE_RR,           "Route Refresh"},
228     { BGP_CAPCODE_ORF,          "Cooperative Route Filtering"},
229     { BGP_CAPCODE_MR,           "Multiple Routes to a Destination"},
230     { BGP_CAPCODE_EXT_NH,       "Extended Next Hop Encoding"},
231     { BGP_CAPCODE_RESTART,      "Graceful Restart"},
232     { BGP_CAPCODE_AS_NEW,       "32-Bit AS Number"},
233     { BGP_CAPCODE_DYN_CAP,      "Dynamic Capability"},
234     { BGP_CAPCODE_MULTISESS,    "Multisession BGP"},
235     { BGP_CAPCODE_ADD_PATH,     "Multiple Paths"},
236     { BGP_CAPCODE_ENH_RR,       "Enhanced Route Refresh"},
237     { BGP_CAPCODE_RR_CISCO,     "Route Refresh (Cisco)"},
238     { 0, NULL}
239 };
240
241 #define BGP_NOTIFY_MAJOR_MSG            1
242 #define BGP_NOTIFY_MAJOR_OPEN           2
243 #define BGP_NOTIFY_MAJOR_UPDATE         3
244 #define BGP_NOTIFY_MAJOR_HOLDTIME       4
245 #define BGP_NOTIFY_MAJOR_FSM            5
246 #define BGP_NOTIFY_MAJOR_CEASE          6
247 #define BGP_NOTIFY_MAJOR_CAP            7
248
249 static const struct tok bgp_notify_major_values[] = {
250     { BGP_NOTIFY_MAJOR_MSG,     "Message Header Error"},
251     { BGP_NOTIFY_MAJOR_OPEN,    "OPEN Message Error"},
252     { BGP_NOTIFY_MAJOR_UPDATE,  "UPDATE Message Error"},
253     { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
254     { BGP_NOTIFY_MAJOR_FSM,     "Finite State Machine Error"},
255     { BGP_NOTIFY_MAJOR_CEASE,   "Cease"},
256     { BGP_NOTIFY_MAJOR_CAP,     "Capability Message Error"},
257     { 0, NULL}
258 };
259
260 /* draft-ietf-idr-cease-subcode-02 */
261 #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX  1
262 static const struct tok bgp_notify_minor_cease_values[] = {
263     { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"},
264     { 2,                        "Administratively Shutdown"},
265     { 3,                        "Peer Unconfigured"},
266     { 4,                        "Administratively Reset"},
267     { 5,                        "Connection Rejected"},
268     { 6,                        "Other Configuration Change"},
269     { 7,                        "Connection Collision Resolution"},
270     { 0, NULL}
271 };
272
273 static const struct tok bgp_notify_minor_msg_values[] = {
274     { 1,                        "Connection Not Synchronized"},
275     { 2,                        "Bad Message Length"},
276     { 3,                        "Bad Message Type"},
277     { 0, NULL}
278 };
279
280 static const struct tok bgp_notify_minor_open_values[] = {
281     { 1,                        "Unsupported Version Number"},
282     { 2,                        "Bad Peer AS"},
283     { 3,                        "Bad BGP Identifier"},
284     { 4,                        "Unsupported Optional Parameter"},
285     { 5,                        "Authentication Failure"},
286     { 6,                        "Unacceptable Hold Time"},
287     { 7,                        "Capability Message Error"},
288     { 0, NULL}
289 };
290
291 static const struct tok bgp_notify_minor_update_values[] = {
292     { 1,                        "Malformed Attribute List"},
293     { 2,                        "Unrecognized Well-known Attribute"},
294     { 3,                        "Missing Well-known Attribute"},
295     { 4,                        "Attribute Flags Error"},
296     { 5,                        "Attribute Length Error"},
297     { 6,                        "Invalid ORIGIN Attribute"},
298     { 7,                        "AS Routing Loop"},
299     { 8,                        "Invalid NEXT_HOP Attribute"},
300     { 9,                        "Optional Attribute Error"},
301     { 10,                       "Invalid Network Field"},
302     { 11,                       "Malformed AS_PATH"},
303     { 0, NULL}
304 };
305
306 static const struct tok bgp_notify_minor_fsm_values[] = {
307     { 1,                        "In OpenSent State"},
308     { 2,                        "In OpenConfirm State"},
309     { 3,                        "In Established State"},
310     { 0, NULL }
311 };
312
313 static const struct tok bgp_notify_minor_cap_values[] = {
314     { 1,                        "Invalid Action Value" },
315     { 2,                        "Invalid Capability Length" },
316     { 3,                        "Malformed Capability Value" },
317     { 4,                        "Unsupported Capability Code" },
318     { 0, NULL }
319 };
320
321 static const struct tok bgp_origin_values[] = {
322     { 0,                        "IGP"},
323     { 1,                        "EGP"},
324     { 2,                        "Incomplete"},
325     { 0, NULL}
326 };
327
328 #define BGP_PMSI_TUNNEL_RSVP_P2MP 1
329 #define BGP_PMSI_TUNNEL_LDP_P2MP  2
330 #define BGP_PMSI_TUNNEL_PIM_SSM   3
331 #define BGP_PMSI_TUNNEL_PIM_SM    4
332 #define BGP_PMSI_TUNNEL_PIM_BIDIR 5
333 #define BGP_PMSI_TUNNEL_INGRESS   6
334 #define BGP_PMSI_TUNNEL_LDP_MP2MP 7
335
336 static const struct tok bgp_pmsi_tunnel_values[] = {
337     { BGP_PMSI_TUNNEL_RSVP_P2MP, "RSVP-TE P2MP LSP"},
338     { BGP_PMSI_TUNNEL_LDP_P2MP, "LDP P2MP LSP"},
339     { BGP_PMSI_TUNNEL_PIM_SSM, "PIM-SSM Tree"},
340     { BGP_PMSI_TUNNEL_PIM_SM, "PIM-SM Tree"},
341     { BGP_PMSI_TUNNEL_PIM_BIDIR, "PIM-Bidir Tree"},
342     { BGP_PMSI_TUNNEL_INGRESS, "Ingress Replication"},
343     { BGP_PMSI_TUNNEL_LDP_MP2MP, "LDP MP2MP LSP"},
344     { 0, NULL}
345 };
346
347 static const struct tok bgp_pmsi_flag_values[] = {
348     { 0x01, "Leaf Information required"},
349     { 0, NULL}
350 };
351
352 #define BGP_AIGP_TLV 1
353
354 static const struct tok bgp_aigp_values[] = {
355     { BGP_AIGP_TLV, "AIGP"},
356     { 0, NULL}
357 };
358
359 /* Subsequent address family identifier, RFC2283 section 7 */
360 #define SAFNUM_RES                      0
361 #define SAFNUM_UNICAST                  1
362 #define SAFNUM_MULTICAST                2
363 #define SAFNUM_UNIMULTICAST             3       /* deprecated now */
364 /* labeled BGP RFC3107 */
365 #define SAFNUM_LABUNICAST               4
366 /* RFC6514 */
367 #define SAFNUM_MULTICAST_VPN            5
368 /* draft-nalawade-kapoor-tunnel-safi */
369 #define SAFNUM_TUNNEL                   64
370 /* RFC4761 */
371 #define SAFNUM_VPLS                     65
372 /* RFC6037 */
373 #define SAFNUM_MDT                      66
374 /* RFC4364 */
375 #define SAFNUM_VPNUNICAST               128
376 /* RFC6513 */
377 #define SAFNUM_VPNMULTICAST             129
378 #define SAFNUM_VPNUNIMULTICAST          130     /* deprecated now */
379 /* RFC4684 */
380 #define SAFNUM_RT_ROUTING_INFO          132
381
382 #define BGP_VPN_RD_LEN                  8
383
384 static const struct tok bgp_safi_values[] = {
385     { SAFNUM_RES,               "Reserved"},
386     { SAFNUM_UNICAST,           "Unicast"},
387     { SAFNUM_MULTICAST,         "Multicast"},
388     { SAFNUM_UNIMULTICAST,      "Unicast+Multicast"},
389     { SAFNUM_LABUNICAST,        "labeled Unicast"},
390     { SAFNUM_TUNNEL,            "Tunnel"},
391     { SAFNUM_VPLS,              "VPLS"},
392     { SAFNUM_MDT,               "MDT"},
393     { SAFNUM_VPNUNICAST,        "labeled VPN Unicast"},
394     { SAFNUM_VPNMULTICAST,      "labeled VPN Multicast"},
395     { SAFNUM_VPNUNIMULTICAST,   "labeled VPN Unicast+Multicast"},
396     { SAFNUM_RT_ROUTING_INFO,   "Route Target Routing Information"},
397     { SAFNUM_MULTICAST_VPN,     "Multicast VPN"},
398     { 0, NULL }
399 };
400
401 /* well-known community */
402 #define BGP_COMMUNITY_NO_EXPORT                 0xffffff01
403 #define BGP_COMMUNITY_NO_ADVERT                 0xffffff02
404 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED       0xffffff03
405
406 /* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
407 #define BGP_EXT_COM_RT_0        0x0002  /* Route Target,Format AS(2bytes):AN(4bytes) */
408 #define BGP_EXT_COM_RT_1        0x0102  /* Route Target,Format IP address:AN(2bytes) */
409 #define BGP_EXT_COM_RT_2        0x0202  /* Route Target,Format AN(4bytes):local(2bytes) */
410 #define BGP_EXT_COM_RO_0        0x0003  /* Route Origin,Format AS(2bytes):AN(4bytes) */
411 #define BGP_EXT_COM_RO_1        0x0103  /* Route Origin,Format IP address:AN(2bytes) */
412 #define BGP_EXT_COM_RO_2        0x0203  /* Route Origin,Format AN(4bytes):local(2bytes) */
413 #define BGP_EXT_COM_LINKBAND    0x4004  /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
414                                         /* rfc2547 bgp-mpls-vpns */
415 #define BGP_EXT_COM_VPN_ORIGIN  0x0005  /* OSPF Domain ID / VPN of Origin  - draft-rosen-vpns-ospf-bgp-mpls */
416 #define BGP_EXT_COM_VPN_ORIGIN2 0x0105  /* duplicate - keep for backwards compatability */
417 #define BGP_EXT_COM_VPN_ORIGIN3 0x0205  /* duplicate - keep for backwards compatability */
418 #define BGP_EXT_COM_VPN_ORIGIN4 0x8005  /* duplicate - keep for backwards compatability */
419
420 #define BGP_EXT_COM_OSPF_RTYPE  0x0306  /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
421 #define BGP_EXT_COM_OSPF_RTYPE2 0x8000  /* duplicate - keep for backwards compatability */
422
423 #define BGP_EXT_COM_OSPF_RID    0x0107  /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
424 #define BGP_EXT_COM_OSPF_RID2   0x8001  /* duplicate - keep for backwards compatability */
425
426 #define BGP_EXT_COM_L2INFO      0x800a  /* draft-kompella-ppvpn-l2vpn */
427
428 #define BGP_EXT_COM_SOURCE_AS   0x0009  /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
429 #define BGP_EXT_COM_VRF_RT_IMP  0x010b  /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
430 #define BGP_EXT_COM_L2VPN_RT_0  0x000a  /* L2VPN Identifier,Format AS(2bytes):AN(4bytes) */
431 #define BGP_EXT_COM_L2VPN_RT_1  0xF10a  /* L2VPN Identifier,Format IP address:AN(2bytes) */
432
433 /* http://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml  */
434 #define BGP_EXT_COM_EIGRP_GEN   0x8800
435 #define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY  0x8801
436 #define BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW 0x8802
437 #define BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU  0x8803
438 #define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID  0x8804
439 #define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805
440
441 static const struct tok bgp_extd_comm_flag_values[] = {
442     { 0x8000,                  "vendor-specific"},
443     { 0x4000,                  "non-transitive"},
444     { 0, NULL},
445 };
446
447 static const struct tok bgp_extd_comm_subtype_values[] = {
448     { BGP_EXT_COM_RT_0,        "target"},
449     { BGP_EXT_COM_RT_1,        "target"},
450     { BGP_EXT_COM_RT_2,        "target"},
451     { BGP_EXT_COM_RO_0,        "origin"},
452     { BGP_EXT_COM_RO_1,        "origin"},
453     { BGP_EXT_COM_RO_2,        "origin"},
454     { BGP_EXT_COM_LINKBAND,    "link-BW"},
455     { BGP_EXT_COM_VPN_ORIGIN,  "ospf-domain"},
456     { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
457     { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
458     { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
459     { BGP_EXT_COM_OSPF_RTYPE,  "ospf-route-type"},
460     { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
461     { BGP_EXT_COM_OSPF_RID,    "ospf-router-id"},
462     { BGP_EXT_COM_OSPF_RID2,   "ospf-router-id"},
463     { BGP_EXT_COM_L2INFO,      "layer2-info"},
464     { BGP_EXT_COM_EIGRP_GEN , "eigrp-general-route (flag, tag)" },
465     { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY , "eigrp-route-metric (AS, delay)" },
466     { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW , "eigrp-route-metric (reliability, nexthop, bandwidth)" },
467     { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU , "eigrp-route-metric (load, MTU)" },
468     { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID , "eigrp-external-route (remote-AS, remote-ID)" },
469     { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC , "eigrp-external-route (remote-proto, remote-metric)" },
470     { BGP_EXT_COM_SOURCE_AS, "source-AS" },
471     { BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"},
472     { BGP_EXT_COM_L2VPN_RT_0, "l2vpn-id"},
473     { BGP_EXT_COM_L2VPN_RT_1, "l2vpn-id"},
474     { 0, NULL},
475 };
476
477 /* OSPF codes for  BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls  */
478 #define BGP_OSPF_RTYPE_RTR      1 /* OSPF Router LSA */
479 #define BGP_OSPF_RTYPE_NET      2 /* OSPF Network LSA */
480 #define BGP_OSPF_RTYPE_SUM      3 /* OSPF Summary LSA */
481 #define BGP_OSPF_RTYPE_EXT      5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
482 #define BGP_OSPF_RTYPE_NSSA     7 /* OSPF NSSA External*/
483 #define BGP_OSPF_RTYPE_SHAM     129 /* OSPF-MPLS-VPN Sham link */
484 #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
485
486 static const struct tok bgp_extd_comm_ospf_rtype_values[] = {
487   { BGP_OSPF_RTYPE_RTR, "Router" },
488   { BGP_OSPF_RTYPE_NET, "Network" },
489   { BGP_OSPF_RTYPE_SUM, "Summary" },
490   { BGP_OSPF_RTYPE_EXT, "External" },
491   { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
492   { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
493   { 0, NULL },
494 };
495
496 /* ADD-PATH Send/Receive field values */
497 static const struct tok bgp_add_path_recvsend[] = {
498   { 1, "Receive" },
499   { 2, "Send" },
500   { 3, "Both" },
501   { 0, NULL },
502 };
503
504 static char astostr[20];
505
506 /*
507  * as_printf
508  *
509  * Convert an AS number into a string and return string pointer.
510  *
511  * Depending on bflag is set or not, AS number is converted into ASDOT notation
512  * or plain number notation.
513  *
514  */
515 static char *
516 as_printf(netdissect_options *ndo,
517           char *str, int size, u_int asnum)
518 {
519         if (!ndo->ndo_bflag || asnum <= 0xFFFF) {
520                 snprintf(str, size, "%u", asnum);
521         } else {
522                 snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF);
523         }
524         return str;
525 }
526
527 #define ITEMCHECK(minlen) if (itemlen < minlen) goto badtlv;
528
529 int
530 decode_prefix4(netdissect_options *ndo,
531                const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
532 {
533         struct in_addr addr;
534         u_int plen, plenbytes;
535
536         ND_TCHECK(pptr[0]);
537         ITEMCHECK(1);
538         plen = pptr[0];
539         if (32 < plen)
540                 return -1;
541         itemlen -= 1;
542
543         memset(&addr, 0, sizeof(addr));
544         plenbytes = (plen + 7) / 8;
545         ND_TCHECK2(pptr[1], plenbytes);
546         ITEMCHECK(plenbytes);
547         memcpy(&addr, &pptr[1], plenbytes);
548         if (plen % 8) {
549                 ((u_char *)&addr)[plenbytes - 1] &=
550                         ((0xff00 >> (plen % 8)) & 0xff);
551         }
552         snprintf(buf, buflen, "%s/%d", ipaddr_string(ndo, &addr), plen);
553         return 1 + plenbytes;
554
555 trunc:
556         return -2;
557
558 badtlv:
559         return -3;
560 }
561
562 static int
563 decode_labeled_prefix4(netdissect_options *ndo,
564                        const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
565 {
566         struct in_addr addr;
567         u_int plen, plenbytes;
568
569         /* prefix length and label = 4 bytes */
570         ND_TCHECK2(pptr[0], 4);
571         ITEMCHECK(4);
572         plen = pptr[0];   /* get prefix length */
573
574         /* this is one of the weirdnesses of rfc3107
575            the label length (actually the label + COS bits)
576            is added to the prefix length;
577            we also do only read out just one label -
578            there is no real application for advertisement of
579            stacked labels in a single BGP message
580         */
581
582         if (24 > plen)
583                 return -1;
584
585         plen-=24; /* adjust prefixlen - labellength */
586
587         if (32 < plen)
588                 return -1;
589         itemlen -= 4;
590
591         memset(&addr, 0, sizeof(addr));
592         plenbytes = (plen + 7) / 8;
593         ND_TCHECK2(pptr[4], plenbytes);
594         ITEMCHECK(plenbytes);
595         memcpy(&addr, &pptr[4], plenbytes);
596         if (plen % 8) {
597                 ((u_char *)&addr)[plenbytes - 1] &=
598                         ((0xff00 >> (plen % 8)) & 0xff);
599         }
600         /* the label may get offsetted by 4 bits so lets shift it right */
601         snprintf(buf, buflen, "%s/%d, label:%u %s",
602                  ipaddr_string(ndo, &addr),
603                  plen,
604                  EXTRACT_24BITS(pptr+1)>>4,
605                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
606
607         return 4 + plenbytes;
608
609 trunc:
610         return -2;
611
612 badtlv:
613         return -3;
614 }
615
616 /*
617  * bgp_vpn_ip_print
618  *
619  * print an ipv4 or ipv6 address into a buffer dependend on address length.
620  */
621 static char *
622 bgp_vpn_ip_print(netdissect_options *ndo,
623                  const u_char *pptr, u_int addr_length)
624 {
625
626     /* worst case string is s fully formatted v6 address */
627     static char addr[sizeof("1234:5678:89ab:cdef:1234:5678:89ab:cdef")];
628     char *pos = addr;
629
630     switch(addr_length) {
631     case (sizeof(struct in_addr) << 3): /* 32 */
632         ND_TCHECK2(pptr[0], sizeof(struct in_addr));
633         snprintf(pos, sizeof(addr), "%s", ipaddr_string(ndo, pptr));
634         break;
635     case (sizeof(struct in6_addr) << 3): /* 128 */
636         ND_TCHECK2(pptr[0], sizeof(struct in6_addr));
637         snprintf(pos, sizeof(addr), "%s", ip6addr_string(ndo, pptr));
638         break;
639     default:
640         snprintf(pos, sizeof(addr), "bogus address length %u", addr_length);
641         break;
642     }
643     pos += strlen(pos);
644
645 trunc:
646     *(pos) = '\0';
647     return (addr);
648 }
649
650 /*
651  * bgp_vpn_sg_print
652  *
653  * print an multicast s,g entry into a buffer.
654  * the s,g entry is encoded like this.
655  *
656  * +-----------------------------------+
657  * | Multicast Source Length (1 octet) |
658  * +-----------------------------------+
659  * |   Multicast Source (Variable)     |
660  * +-----------------------------------+
661  * |  Multicast Group Length (1 octet) |
662  * +-----------------------------------+
663  * |  Multicast Group   (Variable)     |
664  * +-----------------------------------+
665  *
666  * return the number of bytes read from the wire.
667  */
668 static int
669 bgp_vpn_sg_print(netdissect_options *ndo,
670                  const u_char *pptr, char *buf, u_int buflen)
671 {
672     uint8_t addr_length;
673     u_int total_length, offset;
674
675     total_length = 0;
676
677     /* Source address length, encoded in bits */
678     ND_TCHECK2(pptr[0], 1);
679     addr_length =  *pptr++;
680
681     /* Source address */
682     ND_TCHECK2(pptr[0], (addr_length >> 3));
683     total_length += (addr_length >> 3) + 1;
684     offset = strlen(buf);
685     if (addr_length) {
686         snprintf(buf + offset, buflen - offset, ", Source %s",
687                  bgp_vpn_ip_print(ndo, pptr, addr_length));
688         pptr += (addr_length >> 3);
689     }
690
691     /* Group address length, encoded in bits */
692     ND_TCHECK2(pptr[0], 1);
693     addr_length =  *pptr++;
694
695     /* Group address */
696     ND_TCHECK2(pptr[0], (addr_length >> 3));
697     total_length += (addr_length >> 3) + 1;
698     offset = strlen(buf);
699     if (addr_length) {
700         snprintf(buf + offset, buflen - offset, ", Group %s",
701                  bgp_vpn_ip_print(ndo, pptr, addr_length));
702         pptr += (addr_length >> 3);
703     }
704
705 trunc:
706     return (total_length);
707 }
708
709 /* RDs and RTs share the same semantics
710  * we use bgp_vpn_rd_print for
711  * printing route targets inside a NLRI */
712 char *
713 bgp_vpn_rd_print(netdissect_options *ndo,
714                  const u_char *pptr)
715 {
716    /* allocate space for the largest possible string */
717     static char rd[sizeof("xxxxxxxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")];
718     char *pos = rd;
719
720     /* ok lets load the RD format */
721     switch (EXTRACT_16BITS(pptr)) {
722
723         /* 2-byte-AS:number fmt*/
724     case 0:
725         snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)",
726                  EXTRACT_16BITS(pptr+2),
727                  EXTRACT_32BITS(pptr+4),
728                  *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
729         break;
730         /* IP-address:AS fmt*/
731
732     case 1:
733         snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
734             *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6));
735         break;
736
737         /* 4-byte-AS:number fmt*/
738     case 2:
739         snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)",
740             as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+2)),
741             EXTRACT_16BITS(pptr+6), *(pptr+2), *(pptr+3), *(pptr+4),
742             *(pptr+5), EXTRACT_16BITS(pptr+6));
743         break;
744     default:
745         snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
746         break;
747     }
748     pos += strlen(pos);
749     *(pos) = '\0';
750     return (rd);
751 }
752
753 static int
754 decode_rt_routing_info(netdissect_options *ndo,
755                        const u_char *pptr, char *buf, u_int buflen)
756 {
757         uint8_t route_target[8];
758         u_int plen;
759
760         ND_TCHECK(pptr[0]);
761         plen = pptr[0];   /* get prefix length */
762
763         if (0 == plen) {
764                 snprintf(buf, buflen, "default route target");
765                 return 1;
766         }
767
768         if (32 > plen)
769                 return -1;
770
771         plen-=32; /* adjust prefix length */
772
773         if (64 < plen)
774                 return -1;
775
776         memset(&route_target, 0, sizeof(route_target));
777         ND_TCHECK2(pptr[1], (plen + 7) / 8);
778         memcpy(&route_target, &pptr[1], (plen + 7) / 8);
779         if (plen % 8) {
780                 ((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
781                         ((0xff00 >> (plen % 8)) & 0xff);
782         }
783         snprintf(buf, buflen, "origin AS: %s, route target %s",
784             as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+1)),
785             bgp_vpn_rd_print(ndo, (u_char *)&route_target));
786
787         return 5 + (plen + 7) / 8;
788
789 trunc:
790         return -2;
791 }
792
793 static int
794 decode_labeled_vpn_prefix4(netdissect_options *ndo,
795                            const u_char *pptr, char *buf, u_int buflen)
796 {
797         struct in_addr addr;
798         u_int plen;
799
800         ND_TCHECK(pptr[0]);
801         plen = pptr[0];   /* get prefix length */
802
803         if ((24+64) > plen)
804                 return -1;
805
806         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
807
808         if (32 < plen)
809                 return -1;
810
811         memset(&addr, 0, sizeof(addr));
812         ND_TCHECK2(pptr[12], (plen + 7) / 8);
813         memcpy(&addr, &pptr[12], (plen + 7) / 8);
814         if (plen % 8) {
815                 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
816                         ((0xff00 >> (plen % 8)) & 0xff);
817         }
818         /* the label may get offsetted by 4 bits so lets shift it right */
819         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
820                  bgp_vpn_rd_print(ndo, pptr+4),
821                  ipaddr_string(ndo, &addr),
822                  plen,
823                  EXTRACT_24BITS(pptr+1)>>4,
824                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
825
826         return 12 + (plen + 7) / 8;
827
828 trunc:
829         return -2;
830 }
831
832 /*
833  * +-------------------------------+
834  * |                               |
835  * |  RD:IPv4-address (12 octets)  |
836  * |                               |
837  * +-------------------------------+
838  * |  MDT Group-address (4 octets) |
839  * +-------------------------------+
840  */
841
842 #define MDT_VPN_NLRI_LEN 16
843
844 static int
845 decode_mdt_vpn_nlri(netdissect_options *ndo,
846                     const u_char *pptr, char *buf, u_int buflen)
847 {
848
849     const u_char *rd;
850     const u_char *vpn_ip;
851
852     ND_TCHECK(pptr[0]);
853
854     /* if the NLRI is not predefined length, quit.*/
855     if (*pptr != MDT_VPN_NLRI_LEN * 8)
856         return -1;
857     pptr++;
858
859     /* RD */
860     ND_TCHECK2(pptr[0], 8);
861     rd = pptr;
862     pptr+=8;
863
864     /* IPv4 address */
865     ND_TCHECK2(pptr[0], sizeof(struct in_addr));
866     vpn_ip = pptr;
867     pptr+=sizeof(struct in_addr);
868
869     /* MDT Group Address */
870     ND_TCHECK2(pptr[0], sizeof(struct in_addr));
871
872     snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s",
873              bgp_vpn_rd_print(ndo, rd), ipaddr_string(ndo, vpn_ip), ipaddr_string(ndo, pptr));
874
875     return MDT_VPN_NLRI_LEN + 1;
876
877  trunc:
878
879 return -2;
880 }
881
882 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI   1
883 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI   2
884 #define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI            3
885 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4
886 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE     5
887 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN  6
888 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN  7
889
890 static const struct tok bgp_multicast_vpn_route_type_values[] = {
891     { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"},
892     { BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"},
893     { BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"},
894     { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"},
895     { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"},
896     { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"},
897     { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"},
898 };
899
900 static int
901 decode_multicast_vpn(netdissect_options *ndo,
902                      const u_char *pptr, char *buf, u_int buflen)
903 {
904         uint8_t route_type, route_length, addr_length, sg_length;
905         u_int offset;
906
907         ND_TCHECK2(pptr[0], 2);
908         route_type = *pptr++;
909         route_length = *pptr++;
910
911         snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
912                  tok2str(bgp_multicast_vpn_route_type_values,
913                          "Unknown", route_type),
914                  route_type, route_length);
915
916         switch(route_type) {
917         case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
918             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
919             offset = strlen(buf);
920             snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
921                      bgp_vpn_rd_print(ndo, pptr),
922                      bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN,
923                                       (route_length - BGP_VPN_RD_LEN) << 3));
924             break;
925         case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
926             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
927             offset = strlen(buf);
928             snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
929                 bgp_vpn_rd_print(ndo, pptr),
930                 as_printf(ndo, astostr, sizeof(astostr),
931                 EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN)));
932             break;
933
934         case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
935             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
936             offset = strlen(buf);
937             snprintf(buf + offset, buflen - offset, ", RD: %s",
938                      bgp_vpn_rd_print(ndo, pptr));
939             pptr += BGP_VPN_RD_LEN;
940
941             sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen);
942             addr_length =  route_length - sg_length;
943
944             ND_TCHECK2(pptr[0], addr_length);
945             offset = strlen(buf);
946             snprintf(buf + offset, buflen - offset, ", Originator %s",
947                      bgp_vpn_ip_print(ndo, pptr, addr_length << 3));
948             break;
949
950         case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
951             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
952             offset = strlen(buf);
953             snprintf(buf + offset, buflen - offset, ", RD: %s",
954                      bgp_vpn_rd_print(ndo, pptr));
955             pptr += BGP_VPN_RD_LEN;
956
957             bgp_vpn_sg_print(ndo, pptr, buf, buflen);
958             break;
959
960         case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */
961         case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
962             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
963             offset = strlen(buf);
964             snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
965                 bgp_vpn_rd_print(ndo, pptr),
966                 as_printf(ndo, astostr, sizeof(astostr),
967                 EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN)));
968             pptr += BGP_VPN_RD_LEN;
969
970             bgp_vpn_sg_print(ndo, pptr, buf, buflen);
971             break;
972
973             /*
974              * no per route-type printing yet.
975              */
976         case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF:
977         default:
978             break;
979         }
980
981         return route_length + 2;
982
983 trunc:
984         return -2;
985 }
986
987 /*
988  * As I remember, some versions of systems have an snprintf() that
989  * returns -1 if the buffer would have overflowed.  If the return
990  * value is negative, set buflen to 0, to indicate that we've filled
991  * the buffer up.
992  *
993  * If the return value is greater than buflen, that means that
994  * the buffer would have overflowed; again, set buflen to 0 in
995  * that case.
996  */
997 #define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \
998     if (stringlen<0) \
999         buflen=0; \
1000     else if ((u_int)stringlen>buflen) \
1001         buflen=0; \
1002     else { \
1003         buflen-=stringlen; \
1004         buf+=stringlen; \
1005     }
1006
1007 static int
1008 decode_labeled_vpn_l2(netdissect_options *ndo,
1009                       const u_char *pptr, char *buf, u_int buflen)
1010 {
1011         int plen,tlen,stringlen,tlv_type,tlv_len,ttlv_len;
1012
1013         ND_TCHECK2(pptr[0], 2);
1014         plen=EXTRACT_16BITS(pptr);
1015         tlen=plen;
1016         pptr+=2;
1017         /* Old and new L2VPN NLRI share AFI/SAFI
1018          *   -> Assume a 12 Byte-length NLRI is auto-discovery-only
1019          *      and > 17 as old format. Complain for the middle case
1020          */
1021         if (plen==12) {
1022             /* assume AD-only with RD, BGPNH */
1023             ND_TCHECK2(pptr[0],12);
1024             buf[0]='\0';
1025             stringlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s",
1026                                bgp_vpn_rd_print(ndo, pptr),
1027                                ipaddr_string(ndo, pptr+8)
1028                                );
1029             UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1030             pptr+=12;
1031             tlen-=12;
1032             return plen;
1033         } else if (plen>17) {
1034             /* assume old format */
1035             /* RD, ID, LBLKOFF, LBLBASE */
1036
1037             ND_TCHECK2(pptr[0],15);
1038             buf[0]='\0';
1039             stringlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
1040                                bgp_vpn_rd_print(ndo, pptr),
1041                                EXTRACT_16BITS(pptr+8),
1042                                EXTRACT_16BITS(pptr+10),
1043                                EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
1044             UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1045             pptr+=15;
1046             tlen-=15;
1047
1048             /* ok now the variable part - lets read out TLVs*/
1049             while (tlen>0) {
1050                 if (tlen < 3)
1051                     return -1;
1052                 ND_TCHECK2(pptr[0], 3);
1053                 tlv_type=*pptr++;
1054                 tlv_len=EXTRACT_16BITS(pptr);
1055                 ttlv_len=tlv_len;
1056                 pptr+=2;
1057
1058                 switch(tlv_type) {
1059                 case 1:
1060                     if (buflen!=0) {
1061                         stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
1062                                            tlv_type,
1063                                            tlv_len);
1064                         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1065                     }
1066                     ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
1067                     while (ttlv_len>0) {
1068                         ND_TCHECK(pptr[0]);
1069                         if (buflen!=0) {
1070                             stringlen=snprintf(buf,buflen, "%02x",*pptr++);
1071                             UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1072                         }
1073                         ttlv_len--;
1074                     }
1075                     break;
1076                 default:
1077                     if (buflen!=0) {
1078                         stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
1079                                            tlv_type,
1080                                            tlv_len);
1081                         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1082                     }
1083                     break;
1084                 }
1085                 tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
1086             }
1087             return plen+2;
1088
1089         } else {
1090             /* complain bitterly ? */
1091             /* fall through */
1092             goto trunc;
1093         }
1094
1095 trunc:
1096         return -2;
1097 }
1098
1099 int
1100 decode_prefix6(netdissect_options *ndo,
1101                const u_char *pd, u_int itemlen, char *buf, u_int buflen)
1102 {
1103         struct in6_addr addr;
1104         u_int plen, plenbytes;
1105
1106         ND_TCHECK(pd[0]);
1107         ITEMCHECK(1);
1108         plen = pd[0];
1109         if (128 < plen)
1110                 return -1;
1111         itemlen -= 1;
1112
1113         memset(&addr, 0, sizeof(addr));
1114         plenbytes = (plen + 7) / 8;
1115         ND_TCHECK2(pd[1], plenbytes);
1116         ITEMCHECK(plenbytes);
1117         memcpy(&addr, &pd[1], plenbytes);
1118         if (plen % 8) {
1119                 addr.s6_addr[plenbytes - 1] &=
1120                         ((0xff00 >> (plen % 8)) & 0xff);
1121         }
1122         snprintf(buf, buflen, "%s/%d", ip6addr_string(ndo, &addr), plen);
1123         return 1 + plenbytes;
1124
1125 trunc:
1126         return -2;
1127
1128 badtlv:
1129         return -3;
1130 }
1131
1132 static int
1133 decode_labeled_prefix6(netdissect_options *ndo,
1134                        const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
1135 {
1136         struct in6_addr addr;
1137         u_int plen, plenbytes;
1138
1139         /* prefix length and label = 4 bytes */
1140         ND_TCHECK2(pptr[0], 4);
1141         ITEMCHECK(4);
1142         plen = pptr[0]; /* get prefix length */
1143
1144         if (24 > plen)
1145                 return -1;
1146
1147         plen-=24; /* adjust prefixlen - labellength */
1148
1149         if (128 < plen)
1150                 return -1;
1151         itemlen -= 4;
1152
1153         memset(&addr, 0, sizeof(addr));
1154         plenbytes = (plen + 7) / 8;
1155         ND_TCHECK2(pptr[4], plenbytes);
1156         memcpy(&addr, &pptr[4], plenbytes);
1157         if (plen % 8) {
1158                 addr.s6_addr[plenbytes - 1] &=
1159                         ((0xff00 >> (plen % 8)) & 0xff);
1160         }
1161         /* the label may get offsetted by 4 bits so lets shift it right */
1162         snprintf(buf, buflen, "%s/%d, label:%u %s",
1163                  ip6addr_string(ndo, &addr),
1164                  plen,
1165                  EXTRACT_24BITS(pptr+1)>>4,
1166                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1167
1168         return 4 + plenbytes;
1169
1170 trunc:
1171         return -2;
1172
1173 badtlv:
1174         return -3;
1175 }
1176
1177 static int
1178 decode_labeled_vpn_prefix6(netdissect_options *ndo,
1179                            const u_char *pptr, char *buf, u_int buflen)
1180 {
1181         struct in6_addr addr;
1182         u_int plen;
1183
1184         ND_TCHECK(pptr[0]);
1185         plen = pptr[0];   /* get prefix length */
1186
1187         if ((24+64) > plen)
1188                 return -1;
1189
1190         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
1191
1192         if (128 < plen)
1193                 return -1;
1194
1195         memset(&addr, 0, sizeof(addr));
1196         ND_TCHECK2(pptr[12], (plen + 7) / 8);
1197         memcpy(&addr, &pptr[12], (plen + 7) / 8);
1198         if (plen % 8) {
1199                 addr.s6_addr[(plen + 7) / 8 - 1] &=
1200                         ((0xff00 >> (plen % 8)) & 0xff);
1201         }
1202         /* the label may get offsetted by 4 bits so lets shift it right */
1203         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
1204                  bgp_vpn_rd_print(ndo, pptr+4),
1205                  ip6addr_string(ndo, &addr),
1206                  plen,
1207                  EXTRACT_24BITS(pptr+1)>>4,
1208                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1209
1210         return 12 + (plen + 7) / 8;
1211
1212 trunc:
1213         return -2;
1214 }
1215
1216 static int
1217 decode_clnp_prefix(netdissect_options *ndo,
1218                    const u_char *pptr, char *buf, u_int buflen)
1219 {
1220         uint8_t addr[19];
1221         u_int plen;
1222
1223         ND_TCHECK(pptr[0]);
1224         plen = pptr[0]; /* get prefix length */
1225
1226         if (152 < plen)
1227                 return -1;
1228
1229         memset(&addr, 0, sizeof(addr));
1230         ND_TCHECK2(pptr[4], (plen + 7) / 8);
1231         memcpy(&addr, &pptr[4], (plen + 7) / 8);
1232         if (plen % 8) {
1233                 addr[(plen + 7) / 8 - 1] &=
1234                         ((0xff00 >> (plen % 8)) & 0xff);
1235         }
1236         snprintf(buf, buflen, "%s/%d",
1237                  isonsap_string(ndo, addr,(plen + 7) / 8),
1238                  plen);
1239
1240         return 1 + (plen + 7) / 8;
1241
1242 trunc:
1243         return -2;
1244 }
1245
1246 static int
1247 decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
1248                                const u_char *pptr, char *buf, u_int buflen)
1249 {
1250         uint8_t addr[19];
1251         u_int plen;
1252
1253         ND_TCHECK(pptr[0]);
1254         plen = pptr[0];   /* get prefix length */
1255
1256         if ((24+64) > plen)
1257                 return -1;
1258
1259         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
1260
1261         if (152 < plen)
1262                 return -1;
1263
1264         memset(&addr, 0, sizeof(addr));
1265         ND_TCHECK2(pptr[12], (plen + 7) / 8);
1266         memcpy(&addr, &pptr[12], (plen + 7) / 8);
1267         if (plen % 8) {
1268                 addr[(plen + 7) / 8 - 1] &=
1269                         ((0xff00 >> (plen % 8)) & 0xff);
1270         }
1271         /* the label may get offsetted by 4 bits so lets shift it right */
1272         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
1273                  bgp_vpn_rd_print(ndo, pptr+4),
1274                  isonsap_string(ndo, addr,(plen + 7) / 8),
1275                  plen,
1276                  EXTRACT_24BITS(pptr+1)>>4,
1277                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1278
1279         return 12 + (plen + 7) / 8;
1280
1281 trunc:
1282         return -2;
1283 }
1284
1285 /*
1286  * bgp_attr_get_as_size
1287  *
1288  * Try to find the size of the ASs encoded in an as-path. It is not obvious, as
1289  * both Old speakers that do not support 4 byte AS, and the new speakers that do
1290  * support, exchange AS-Path with the same path-attribute type value 0x02.
1291  */
1292 static int
1293 bgp_attr_get_as_size(netdissect_options *ndo,
1294                      uint8_t bgpa_type, const u_char *pptr, int len)
1295 {
1296     const u_char *tptr = pptr;
1297
1298     /*
1299      * If the path attribute is the optional AS4 path type, then we already
1300      * know, that ASs must be encoded in 4 byte format.
1301      */
1302     if (bgpa_type == BGPTYPE_AS4_PATH) {
1303         return 4;
1304     }
1305
1306     /*
1307      * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path
1308      * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes
1309      * each.
1310      */
1311     while (tptr < pptr + len) {
1312         ND_TCHECK(tptr[0]);
1313
1314         /*
1315          * If we do not find a valid segment type, our guess might be wrong.
1316          */
1317         if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) {
1318             goto trunc;
1319         }
1320         ND_TCHECK(tptr[1]);
1321         tptr += 2 + tptr[1] * 2;
1322     }
1323
1324     /*
1325      * If we correctly reached end of the AS path attribute data content,
1326      * then most likely ASs were indeed encoded as 2 bytes.
1327      */
1328     if (tptr == pptr + len) {
1329         return 2;
1330     }
1331
1332 trunc:
1333
1334     /*
1335      * We can come here, either we did not have enough data, or if we
1336      * try to decode 4 byte ASs in 2 byte format. Either way, return 4,
1337      * so that calller can try to decode each AS as of 4 bytes. If indeed
1338      * there was not enough data, it will crib and end the parse anyways.
1339      */
1340    return 4;
1341 }
1342
1343 static int
1344 bgp_attr_print(netdissect_options *ndo,
1345                u_int atype, const u_char *pptr, u_int len)
1346 {
1347         int i;
1348         uint16_t af;
1349         uint8_t safi, snpa, nhlen;
1350         union { /* copy buffer for bandwidth values */
1351             float f;
1352             uint32_t i;
1353         } bw;
1354         int advance;
1355         u_int tlen;
1356         const u_char *tptr;
1357         char buf[MAXHOSTNAMELEN + 100];
1358         int  as_size;
1359
1360         tptr = pptr;
1361         tlen=len;
1362
1363         switch (atype) {
1364         case BGPTYPE_ORIGIN:
1365                 if (len != 1)
1366                         ND_PRINT((ndo, "invalid len"));
1367                 else {
1368                         ND_TCHECK(*tptr);
1369                         ND_PRINT((ndo, "%s", tok2str(bgp_origin_values,
1370                                                 "Unknown Origin Typecode",
1371                                                 tptr[0])));
1372                 }
1373                 break;
1374
1375         /*
1376          * Process AS4 byte path and AS2 byte path attributes here.
1377          */
1378         case BGPTYPE_AS4_PATH:
1379         case BGPTYPE_AS_PATH:
1380                 if (len % 2) {
1381                         ND_PRINT((ndo, "invalid len"));
1382                         break;
1383                 }
1384                 if (!len) {
1385                         ND_PRINT((ndo, "empty"));
1386                         break;
1387                 }
1388
1389                 /*
1390                  * BGP updates exchanged between New speakers that support 4
1391                  * byte AS, ASs are always encoded in 4 bytes. There is no
1392                  * definitive way to find this, just by the packet's
1393                  * contents. So, check for packet's TLV's sanity assuming
1394                  * 2 bytes first, and it does not pass, assume that ASs are
1395                  * encoded in 4 bytes format and move on.
1396                  */
1397                 as_size = bgp_attr_get_as_size(ndo, atype, pptr, len);
1398
1399                 while (tptr < pptr + len) {
1400                         ND_TCHECK(tptr[0]);
1401                         ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values,
1402                                                 "?", tptr[0])));
1403                         for (i = 0; i < tptr[1] * as_size; i += as_size) {
1404                             ND_TCHECK2(tptr[2 + i], as_size);
1405                             ND_PRINT((ndo, "%s ",
1406                                 as_printf(ndo, astostr, sizeof(astostr),
1407                                 as_size == 2 ?
1408                                 EXTRACT_16BITS(&tptr[2 + i]) :
1409                                 EXTRACT_32BITS(&tptr[2 + i]))));
1410                         }
1411                         ND_TCHECK(tptr[0]);
1412                         ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_close_values,
1413                                                 "?", tptr[0])));
1414                         ND_TCHECK(tptr[1]);
1415                         tptr += 2 + tptr[1] * as_size;
1416                 }
1417                 break;
1418         case BGPTYPE_NEXT_HOP:
1419                 if (len != 4)
1420                         ND_PRINT((ndo, "invalid len"));
1421                 else {
1422                         ND_TCHECK2(tptr[0], 4);
1423                         ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
1424                 }
1425                 break;
1426         case BGPTYPE_MULTI_EXIT_DISC:
1427         case BGPTYPE_LOCAL_PREF:
1428                 if (len != 4)
1429                         ND_PRINT((ndo, "invalid len"));
1430                 else {
1431                         ND_TCHECK2(tptr[0], 4);
1432                         ND_PRINT((ndo, "%u", EXTRACT_32BITS(tptr)));
1433                 }
1434                 break;
1435         case BGPTYPE_ATOMIC_AGGREGATE:
1436                 if (len != 0)
1437                         ND_PRINT((ndo, "invalid len"));
1438                 break;
1439         case BGPTYPE_AGGREGATOR:
1440
1441                 /*
1442                  * Depending on the AS encoded is of 2 bytes or of 4 bytes,
1443                  * the length of this PA can be either 6 bytes or 8 bytes.
1444                  */
1445                 if (len != 6 && len != 8) {
1446                     ND_PRINT((ndo, "invalid len"));
1447                     break;
1448                 }
1449                 ND_TCHECK2(tptr[0], len);
1450                 if (len == 6) {
1451                     ND_PRINT((ndo, " AS #%s, origin %s",
1452                         as_printf(ndo, astostr, sizeof(astostr), EXTRACT_16BITS(tptr)),
1453                         ipaddr_string(ndo, tptr + 2)));
1454                 } else {
1455                     ND_PRINT((ndo, " AS #%s, origin %s",
1456                         as_printf(ndo, astostr, sizeof(astostr),
1457                         EXTRACT_32BITS(tptr)), ipaddr_string(ndo, tptr + 4)));
1458                 }
1459                 break;
1460         case BGPTYPE_AGGREGATOR4:
1461                 if (len != 8) {
1462                         ND_PRINT((ndo, "invalid len"));
1463                         break;
1464                 }
1465                 ND_TCHECK2(tptr[0], 8);
1466                 ND_PRINT((ndo, " AS #%s, origin %s",
1467                     as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)),
1468                     ipaddr_string(ndo, tptr + 4)));
1469                 break;
1470         case BGPTYPE_COMMUNITIES:
1471                 if (len % 4) {
1472                         ND_PRINT((ndo, "invalid len"));
1473                         break;
1474                 }
1475                 while (tlen>0) {
1476                         uint32_t comm;
1477                         ND_TCHECK2(tptr[0], 4);
1478                         comm = EXTRACT_32BITS(tptr);
1479                         switch (comm) {
1480                         case BGP_COMMUNITY_NO_EXPORT:
1481                                 ND_PRINT((ndo, " NO_EXPORT"));
1482                                 break;
1483                         case BGP_COMMUNITY_NO_ADVERT:
1484                                 ND_PRINT((ndo, " NO_ADVERTISE"));
1485                                 break;
1486                         case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
1487                                 ND_PRINT((ndo, " NO_EXPORT_SUBCONFED"));
1488                                 break;
1489                         default:
1490                                 ND_PRINT((ndo, "%u:%u%s",
1491                                        (comm >> 16) & 0xffff,
1492                                        comm & 0xffff,
1493                                        (tlen>4) ? ", " : ""));
1494                                 break;
1495                         }
1496                         tlen -=4;
1497                         tptr +=4;
1498                 }
1499                 break;
1500         case BGPTYPE_ORIGINATOR_ID:
1501                 if (len != 4) {
1502                         ND_PRINT((ndo, "invalid len"));
1503                         break;
1504                 }
1505                 ND_TCHECK2(tptr[0], 4);
1506                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
1507                 break;
1508         case BGPTYPE_CLUSTER_LIST:
1509                 if (len % 4) {
1510                         ND_PRINT((ndo, "invalid len"));
1511                         break;
1512                 }
1513                 while (tlen>0) {
1514                         ND_TCHECK2(tptr[0], 4);
1515                         ND_PRINT((ndo, "%s%s",
1516                                ipaddr_string(ndo, tptr),
1517                                 (tlen>4) ? ", " : ""));
1518                         tlen -=4;
1519                         tptr +=4;
1520                 }
1521                 break;
1522         case BGPTYPE_MP_REACH_NLRI:
1523                 ND_TCHECK2(tptr[0], 3);
1524                 af = EXTRACT_16BITS(tptr);
1525                 safi = tptr[2];
1526
1527                 ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1528                        tok2str(af_values, "Unknown AFI", af),
1529                        af,
1530                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1531                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
1532                        safi));
1533
1534                 switch(af<<8 | safi) {
1535                 case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1536                 case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1537                 case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1538                 case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1539                 case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1540                 case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1541                 case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1542                 case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1543                 case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1544                 case (AFNUM_INET<<8 | SAFNUM_MDT):
1545                 case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1546                 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1547                 case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1548                 case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1549                 case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1550                 case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1551                 case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1552                 case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1553                 case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1554                 case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1555                 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1556                 case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1557                 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1558                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1559                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1560                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1561                 case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1562                     break;
1563                 default:
1564                     ND_TCHECK2(tptr[0], tlen);
1565                     ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
1566                     if (ndo->ndo_vflag <= 1)
1567                         print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1568                     goto done;
1569                     break;
1570                 }
1571
1572                 tptr +=3;
1573
1574                 ND_TCHECK(tptr[0]);
1575                 nhlen = tptr[0];
1576                 tlen = nhlen;
1577                 tptr++;
1578
1579                 if (tlen) {
1580                     int nnh = 0;
1581                     ND_PRINT((ndo, "\n\t    nexthop: "));
1582                     while (tlen > 0) {
1583                         if ( nnh++ > 0 ) {
1584                             ND_PRINT((ndo,  ", " ));
1585                         }
1586                         switch(af<<8 | safi) {
1587                         case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1588                         case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1589                         case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1590                         case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1591                         case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1592                         case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1593                         case (AFNUM_INET<<8 | SAFNUM_MDT):
1594                             if (tlen < (int)sizeof(struct in_addr)) {
1595                                 ND_PRINT((ndo, "invalid len"));
1596                                 tlen = 0;
1597                             } else {
1598                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr));
1599                                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
1600                                 tlen -= sizeof(struct in_addr);
1601                                 tptr += sizeof(struct in_addr);
1602                             }
1603                             break;
1604                         case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1605                         case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1606                         case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1607                             if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
1608                                 ND_PRINT((ndo, "invalid len"));
1609                                 tlen = 0;
1610                             } else {
1611                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1612                                 ND_PRINT((ndo, "RD: %s, %s",
1613                                        bgp_vpn_rd_print(ndo, tptr),
1614                                        ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN)));
1615                                 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1616                                 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1617                             }
1618                             break;
1619                         case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1620                         case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1621                         case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1622                         case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1623                             if (tlen < (int)sizeof(struct in6_addr)) {
1624                                 ND_PRINT((ndo, "invalid len"));
1625                                 tlen = 0;
1626                             } else {
1627                                 ND_TCHECK2(tptr[0], sizeof(struct in6_addr));
1628                                 ND_PRINT((ndo, "%s", ip6addr_string(ndo, tptr)));
1629                                 tlen -= sizeof(struct in6_addr);
1630                                 tptr += sizeof(struct in6_addr);
1631                             }
1632                             break;
1633                         case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1634                         case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1635                         case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1636                             if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1637                                 ND_PRINT((ndo, "invalid len"));
1638                                 tlen = 0;
1639                             } else {
1640                                 ND_TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1641                                 ND_PRINT((ndo, "RD: %s, %s",
1642                                        bgp_vpn_rd_print(ndo, tptr),
1643                                        ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN)));
1644                                 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1645                                 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1646                             }
1647                             break;
1648                         case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1649                         case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1650                         case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1651                         case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1652                             if (tlen < (int)sizeof(struct in_addr)) {
1653                                 ND_PRINT((ndo, "invalid len"));
1654                                 tlen = 0;
1655                             } else {
1656                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr));
1657                                 ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
1658                                 tlen -= (sizeof(struct in_addr));
1659                                 tptr += (sizeof(struct in_addr));
1660                             }
1661                             break;
1662                         case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1663                         case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1664                         case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1665                             ND_TCHECK2(tptr[0], tlen);
1666                             ND_PRINT((ndo, "%s", isonsap_string(ndo, tptr, tlen)));
1667                             tptr += tlen;
1668                             tlen = 0;
1669                             break;
1670
1671                         case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1672                         case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1673                         case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1674                             if (tlen < BGP_VPN_RD_LEN+1) {
1675                                 ND_PRINT((ndo, "invalid len"));
1676                                 tlen = 0;
1677                             } else {
1678                                 ND_TCHECK2(tptr[0], tlen);
1679                                 ND_PRINT((ndo, "RD: %s, %s",
1680                                        bgp_vpn_rd_print(ndo, tptr),
1681                                        isonsap_string(ndo, tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN)));
1682                                 /* rfc986 mapped IPv4 address ? */
1683                                 if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) ==  0x47000601)
1684                                     ND_PRINT((ndo, " = %s", ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN+4)));
1685                                 /* rfc1888 mapped IPv6 address ? */
1686                                 else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) ==  0x350000)
1687                                     ND_PRINT((ndo, " = %s", ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN+3)));
1688                                 tptr += tlen;
1689                                 tlen = 0;
1690                             }
1691                             break;
1692                         default:
1693                             ND_TCHECK2(tptr[0], tlen);
1694                             ND_PRINT((ndo, "no AFI %u/SAFI %u decoder", af, safi));
1695                             if (ndo->ndo_vflag <= 1)
1696                                 print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1697                             tptr += tlen;
1698                             tlen = 0;
1699                             goto done;
1700                             break;
1701                         }
1702                     }
1703                 }
1704                 ND_PRINT((ndo, ", nh-length: %u", nhlen));
1705                 tptr += tlen;
1706
1707                 ND_TCHECK(tptr[0]);
1708                 snpa = tptr[0];
1709                 tptr++;
1710
1711                 if (snpa) {
1712                         ND_PRINT((ndo, "\n\t    %u SNPA", snpa));
1713                         for (/*nothing*/; snpa > 0; snpa--) {
1714                                 ND_TCHECK(tptr[0]);
1715                                 ND_PRINT((ndo, "\n\t      %d bytes", tptr[0]));
1716                                 tptr += tptr[0] + 1;
1717                         }
1718                 } else {
1719                         ND_PRINT((ndo, ", no SNPA"));
1720                 }
1721
1722                 while (len - (tptr - pptr) > 0) {
1723                     switch (af<<8 | safi) {
1724                     case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1725                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1726                     case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1727                         advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
1728                         if (advance == -1)
1729                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1730                         else if (advance == -2)
1731                             goto trunc;
1732                         else if (advance == -3)
1733                             break; /* bytes left, but not enough */
1734                         else
1735                             ND_PRINT((ndo, "\n\t      %s", buf));
1736                         break;
1737                     case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1738                         advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
1739                         if (advance == -1)
1740                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1741                         else if (advance == -2)
1742                             goto trunc;
1743                         else if (advance == -3)
1744                             break; /* bytes left, but not enough */
1745                         else
1746                             ND_PRINT((ndo, "\n\t      %s", buf));
1747                         break;
1748                     case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1749                     case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1750                     case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1751                         advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
1752                         if (advance == -1)
1753                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1754                         else if (advance == -2)
1755                             goto trunc;
1756                         else
1757                             ND_PRINT((ndo, "\n\t      %s", buf));
1758                         break;
1759                     case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1760                         advance = decode_rt_routing_info(ndo, tptr, buf, sizeof(buf));
1761                         if (advance == -1)
1762                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1763                         else if (advance == -2)
1764                             goto trunc;
1765                         else
1766                             ND_PRINT((ndo, "\n\t      %s", buf));
1767                         break;
1768                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
1769                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
1770                         advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
1771                         if (advance == -1)
1772                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1773                         else if (advance == -2)
1774                             goto trunc;
1775                         else
1776                             ND_PRINT((ndo, "\n\t      %s", buf));
1777                         break;
1778
1779                     case (AFNUM_INET<<8 | SAFNUM_MDT):
1780                       advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
1781                       if (advance == -1)
1782                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1783                         else if (advance == -2)
1784                             goto trunc;
1785                         else
1786                             ND_PRINT((ndo, "\n\t      %s", buf));
1787                        break;
1788                     case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1789                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1790                     case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1791                         advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
1792                         if (advance == -1)
1793                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1794                         else if (advance == -2)
1795                             goto trunc;
1796                         else if (advance == -3)
1797                             break; /* bytes left, but not enough */
1798                         else
1799                             ND_PRINT((ndo, "\n\t      %s", buf));
1800                         break;
1801                     case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1802                         advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
1803                         if (advance == -1)
1804                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1805                         else if (advance == -2)
1806                             goto trunc;
1807                         else if (advance == -3)
1808                             break; /* bytes left, but not enough */
1809                         else
1810                             ND_PRINT((ndo, "\n\t      %s", buf));
1811                         break;
1812                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1813                     case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1814                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1815                         advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
1816                         if (advance == -1)
1817                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1818                         else if (advance == -2)
1819                             goto trunc;
1820                         else
1821                             ND_PRINT((ndo, "\n\t      %s", buf));
1822                         break;
1823                     case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1824                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1825                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1826                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1827                         advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
1828                         if (advance == -1)
1829                             ND_PRINT((ndo, "\n\t    (illegal length)"));
1830                         else if (advance == -2)
1831                             goto trunc;
1832                         else
1833                             ND_PRINT((ndo, "\n\t      %s", buf));
1834                         break;
1835                     case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1836                     case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1837                     case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1838                         advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1839                         if (advance == -1)
1840                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1841                         else if (advance == -2)
1842                             goto trunc;
1843                         else
1844                             ND_PRINT((ndo, "\n\t      %s", buf));
1845                         break;
1846                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1847                     case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1848                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1849                         advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1850                         if (advance == -1)
1851                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1852                         else if (advance == -2)
1853                             goto trunc;
1854                         else
1855                             ND_PRINT((ndo, "\n\t      %s", buf));
1856                         break;
1857                     default:
1858                         ND_TCHECK2(*tptr,tlen);
1859                         ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
1860                         if (ndo->ndo_vflag <= 1)
1861                             print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1862                         advance = 0;
1863                         tptr = pptr + len;
1864                         break;
1865                     }
1866                     if (advance < 0)
1867                         break;
1868                     tptr += advance;
1869                 }
1870         done:
1871                 break;
1872
1873         case BGPTYPE_MP_UNREACH_NLRI:
1874                 ND_TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE);
1875                 af = EXTRACT_16BITS(tptr);
1876                 safi = tptr[2];
1877
1878                 ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1879                        tok2str(af_values, "Unknown AFI", af),
1880                        af,
1881                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1882                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
1883                        safi));
1884
1885                 if (len == BGP_MP_NLRI_MINSIZE)
1886                     ND_PRINT((ndo, "\n\t      End-of-Rib Marker (empty NLRI)"));
1887
1888                 tptr += 3;
1889
1890                 while (len - (tptr - pptr) > 0) {
1891                     switch (af<<8 | safi) {
1892                     case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1893                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1894                     case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1895                         advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
1896                         if (advance == -1)
1897                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1898                         else if (advance == -2)
1899                             goto trunc;
1900                         else if (advance == -3)
1901                             break; /* bytes left, but not enough */
1902                         else
1903                             ND_PRINT((ndo, "\n\t      %s", buf));
1904                         break;
1905                     case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1906                         advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
1907                         if (advance == -1)
1908                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1909                         else if (advance == -2)
1910                             goto trunc;
1911                         else if (advance == -3)
1912                             break; /* bytes left, but not enough */
1913                         else
1914                             ND_PRINT((ndo, "\n\t      %s", buf));
1915                         break;
1916                     case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1917                     case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1918                     case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1919                         advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
1920                         if (advance == -1)
1921                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1922                         else if (advance == -2)
1923                             goto trunc;
1924                         else
1925                             ND_PRINT((ndo, "\n\t      %s", buf));
1926                         break;
1927                     case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1928                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1929                     case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1930                         advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
1931                         if (advance == -1)
1932                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1933                         else if (advance == -2)
1934                             goto trunc;
1935                         else if (advance == -3)
1936                             break; /* bytes left, but not enough */
1937                         else
1938                             ND_PRINT((ndo, "\n\t      %s", buf));
1939                         break;
1940                     case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1941                         advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
1942                         if (advance == -1)
1943                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1944                         else if (advance == -2)
1945                             goto trunc;
1946                         else if (advance == -3)
1947                             break; /* bytes left, but not enough */
1948                         else
1949                             ND_PRINT((ndo, "\n\t      %s", buf));
1950                         break;
1951                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1952                     case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1953                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1954                         advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
1955                         if (advance == -1)
1956                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1957                         else if (advance == -2)
1958                             goto trunc;
1959                         else
1960                             ND_PRINT((ndo, "\n\t      %s", buf));
1961                         break;
1962                     case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1963                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1964                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1965                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1966                         advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
1967                         if (advance == -1)
1968                             ND_PRINT((ndo, "\n\t    (illegal length)"));
1969                         else if (advance == -2)
1970                             goto trunc;
1971                         else
1972                             ND_PRINT((ndo, "\n\t      %s", buf));
1973                         break;
1974                     case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1975                     case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1976                     case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1977                         advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1978                         if (advance == -1)
1979                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1980                         else if (advance == -2)
1981                             goto trunc;
1982                         else
1983                             ND_PRINT((ndo, "\n\t      %s", buf));
1984                         break;
1985                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1986                     case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1987                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1988                         advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1989                         if (advance == -1)
1990                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1991                         else if (advance == -2)
1992                             goto trunc;
1993                         else
1994                             ND_PRINT((ndo, "\n\t      %s", buf));
1995                         break;
1996                     case (AFNUM_INET<<8 | SAFNUM_MDT):
1997                       advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
1998                       if (advance == -1)
1999                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2000                         else if (advance == -2)
2001                             goto trunc;
2002                         else
2003                             ND_PRINT((ndo, "\n\t      %s", buf));
2004                        break;
2005                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
2006                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
2007                         advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
2008                         if (advance == -1)
2009                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2010                         else if (advance == -2)
2011                             goto trunc;
2012                         else
2013                             ND_PRINT((ndo, "\n\t      %s", buf));
2014                         break;
2015                     default:
2016                         ND_TCHECK2(*(tptr-3),tlen);
2017                         ND_PRINT((ndo, "no AFI %u / SAFI %u decoder", af, safi));
2018                         if (ndo->ndo_vflag <= 1)
2019                             print_unknown_data(ndo, tptr-3, "\n\t    ", tlen);
2020                         advance = 0;
2021                         tptr = pptr + len;
2022                         break;
2023                     }
2024                     if (advance < 0)
2025                         break;
2026                     tptr += advance;
2027                 }
2028                 break;
2029         case BGPTYPE_EXTD_COMMUNITIES:
2030                 if (len % 8) {
2031                         ND_PRINT((ndo, "invalid len"));
2032                         break;
2033                 }
2034                 while (tlen>0) {
2035                     uint16_t extd_comm;
2036
2037                     ND_TCHECK2(tptr[0], 2);
2038                     extd_comm=EXTRACT_16BITS(tptr);
2039
2040                     ND_PRINT((ndo, "\n\t    %s (0x%04x), Flags [%s]",
2041                            tok2str(bgp_extd_comm_subtype_values,
2042                                       "unknown extd community typecode",
2043                                       extd_comm),
2044                            extd_comm,
2045                            bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
2046
2047                     ND_TCHECK2(*(tptr+2), 6);
2048                     switch(extd_comm) {
2049                     case BGP_EXT_COM_RT_0:
2050                     case BGP_EXT_COM_RO_0:
2051                     case BGP_EXT_COM_L2VPN_RT_0:
2052                         ND_PRINT((ndo, ": %u:%u (= %s)",
2053                                EXTRACT_16BITS(tptr+2),
2054                                EXTRACT_32BITS(tptr+4),
2055                                ipaddr_string(ndo, tptr+4)));
2056                         break;
2057                     case BGP_EXT_COM_RT_1:
2058                     case BGP_EXT_COM_RO_1:
2059                     case BGP_EXT_COM_L2VPN_RT_1:
2060                     case BGP_EXT_COM_VRF_RT_IMP:
2061                         ND_PRINT((ndo, ": %s:%u",
2062                                ipaddr_string(ndo, tptr+2),
2063                                EXTRACT_16BITS(tptr+6)));
2064                         break;
2065                     case BGP_EXT_COM_RT_2:
2066                     case BGP_EXT_COM_RO_2:
2067                         ND_PRINT((ndo, ": %s:%u",
2068                             as_printf(ndo, astostr, sizeof(astostr),
2069                             EXTRACT_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6)));
2070                         break;
2071                     case BGP_EXT_COM_LINKBAND:
2072                         bw.i = EXTRACT_32BITS(tptr+2);
2073                         ND_PRINT((ndo, ": bandwidth: %.3f Mbps",
2074                                bw.f*8/1000000));
2075                         break;
2076                     case BGP_EXT_COM_VPN_ORIGIN:
2077                     case BGP_EXT_COM_VPN_ORIGIN2:
2078                     case BGP_EXT_COM_VPN_ORIGIN3:
2079                     case BGP_EXT_COM_VPN_ORIGIN4:
2080                     case BGP_EXT_COM_OSPF_RID:
2081                     case BGP_EXT_COM_OSPF_RID2:
2082                         ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr+2)));
2083                         break;
2084                     case BGP_EXT_COM_OSPF_RTYPE:
2085                     case BGP_EXT_COM_OSPF_RTYPE2:
2086                         ND_PRINT((ndo, ": area:%s, router-type:%s, metric-type:%s%s",
2087                                ipaddr_string(ndo, tptr+2),
2088                                tok2str(bgp_extd_comm_ospf_rtype_values,
2089                                           "unknown (0x%02x)",
2090                                           *(tptr+6)),
2091                                (*(tptr+7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
2092                                ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""));
2093                         break;
2094                     case BGP_EXT_COM_L2INFO:
2095                         ND_PRINT((ndo, ": %s Control Flags [0x%02x]:MTU %u",
2096                                tok2str(l2vpn_encaps_values,
2097                                           "unknown encaps",
2098                                           *(tptr+2)),
2099                                        *(tptr+3),
2100                                EXTRACT_16BITS(tptr+4)));
2101                         break;
2102                     case BGP_EXT_COM_SOURCE_AS:
2103                         ND_PRINT((ndo, ": AS %u", EXTRACT_16BITS(tptr+2)));
2104                         break;
2105                     default:
2106                         ND_TCHECK2(*tptr,8);
2107                         print_unknown_data(ndo, tptr, "\n\t      ", 8);
2108                         break;
2109                     }
2110                     tlen -=8;
2111                     tptr +=8;
2112                 }
2113                 break;
2114
2115         case BGPTYPE_PMSI_TUNNEL:
2116         {
2117                 uint8_t tunnel_type, flags;
2118
2119                 tunnel_type = *(tptr+1);
2120                 flags = *tptr;
2121                 tlen = len;
2122
2123                 ND_TCHECK2(tptr[0], 5);
2124                 ND_PRINT((ndo, "\n\t    Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
2125                        tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
2126                        tunnel_type,
2127                        bittok2str(bgp_pmsi_flag_values, "none", flags),
2128                        EXTRACT_24BITS(tptr+2)>>4));
2129
2130                 tptr +=5;
2131                 tlen -= 5;
2132
2133                 switch (tunnel_type) {
2134                 case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
2135                 case BGP_PMSI_TUNNEL_PIM_BIDIR:
2136                     ND_TCHECK2(tptr[0], 8);
2137                     ND_PRINT((ndo, "\n\t      Sender %s, P-Group %s",
2138                            ipaddr_string(ndo, tptr),
2139                            ipaddr_string(ndo, tptr+4)));
2140                     break;
2141
2142                 case BGP_PMSI_TUNNEL_PIM_SSM:
2143                     ND_TCHECK2(tptr[0], 8);
2144                     ND_PRINT((ndo, "\n\t      Root-Node %s, P-Group %s",
2145                            ipaddr_string(ndo, tptr),
2146                            ipaddr_string(ndo, tptr+4)));
2147                     break;
2148                 case BGP_PMSI_TUNNEL_INGRESS:
2149                     ND_TCHECK2(tptr[0], 4);
2150                     ND_PRINT((ndo, "\n\t      Tunnel-Endpoint %s",
2151                            ipaddr_string(ndo, tptr)));
2152                     break;
2153                 case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
2154                 case BGP_PMSI_TUNNEL_LDP_MP2MP:
2155                     ND_TCHECK2(tptr[0], 8);
2156                     ND_PRINT((ndo, "\n\t      Root-Node %s, LSP-ID 0x%08x",
2157                            ipaddr_string(ndo, tptr),
2158                            EXTRACT_32BITS(tptr+4)));
2159                     break;
2160                 case BGP_PMSI_TUNNEL_RSVP_P2MP:
2161                     ND_TCHECK2(tptr[0], 8);
2162                     ND_PRINT((ndo, "\n\t      Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
2163                            ipaddr_string(ndo, tptr),
2164                            EXTRACT_32BITS(tptr+4)));
2165                     break;
2166                 default:
2167                     if (ndo->ndo_vflag <= 1) {
2168                         print_unknown_data(ndo, tptr, "\n\t      ", tlen);
2169                     }
2170                 }
2171                 break;
2172         }
2173         case BGPTYPE_AIGP:
2174         {
2175                 uint8_t type;
2176                 uint16_t length;
2177
2178                 ND_TCHECK2(tptr[0], 3);
2179
2180                 tlen = len;
2181
2182                 while (tlen >= 3) {
2183
2184                     type = *tptr;
2185                     length = EXTRACT_16BITS(tptr+1);
2186
2187                     ND_PRINT((ndo, "\n\t    %s TLV (%u), length %u",
2188                               tok2str(bgp_aigp_values, "Unknown", type),
2189                               type, length));
2190
2191                     /*
2192                      * Check if we can read the TLV data.
2193                      */
2194                     ND_TCHECK2(tptr[3], length - 3);
2195
2196                     switch (type) {
2197
2198                     case BGP_AIGP_TLV:
2199                         ND_TCHECK2(tptr[3], 8);
2200                         ND_PRINT((ndo, ", metric %" PRIu64,
2201                                   EXTRACT_64BITS(tptr+3)));
2202                         break;
2203
2204                     default:
2205                         if (ndo->ndo_vflag <= 1) {
2206                             print_unknown_data(ndo, tptr+3,"\n\t      ", length-3);
2207                         }
2208                     }
2209
2210                     tptr += length;
2211                     tlen -= length;
2212                 }
2213                 break;
2214         }
2215         case BGPTYPE_ATTR_SET:
2216                 ND_TCHECK2(tptr[0], 4);
2217                 if (len < 4)
2218                         goto trunc;
2219                 ND_PRINT((ndo, "\n\t    Origin AS: %s",
2220                     as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr))));
2221                 tptr+=4;
2222                 len -=4;
2223
2224                 while (len) {
2225                     u_int aflags, alenlen, alen;
2226
2227                     ND_TCHECK2(tptr[0], 2);
2228                     if (len < 2)
2229                         goto trunc;
2230                     aflags = *tptr;
2231                     atype = *(tptr + 1);
2232                     tptr += 2;
2233                     len -= 2;
2234                     alenlen = bgp_attr_lenlen(aflags, tptr);
2235                     ND_TCHECK2(tptr[0], alenlen);
2236                     if (len < alenlen)
2237                         goto trunc;
2238                     alen = bgp_attr_len(aflags, tptr);
2239                     tptr += alenlen;
2240                     len -= alenlen;
2241
2242                     ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
2243                            tok2str(bgp_attr_values,
2244                                       "Unknown Attribute", atype),
2245                            atype,
2246                            alen));
2247
2248                     if (aflags) {
2249                         ND_PRINT((ndo, ", Flags [%s%s%s%s",
2250                                aflags & 0x80 ? "O" : "",
2251                                aflags & 0x40 ? "T" : "",
2252                                aflags & 0x20 ? "P" : "",
2253                                aflags & 0x10 ? "E" : ""));
2254                         if (aflags & 0xf)
2255                             ND_PRINT((ndo, "+%x", aflags & 0xf));
2256                         ND_PRINT((ndo, "]: "));
2257                     }
2258                     /* FIXME check for recursion */
2259                     if (!bgp_attr_print(ndo, atype, tptr, alen))
2260                         return 0;
2261                     tptr += alen;
2262                     len -= alen;
2263                 }
2264                 break;
2265
2266         case BGPTYPE_LARGE_COMMUNITY:
2267                 if (len == 0 || len % 12) {
2268                         ND_PRINT((ndo, "invalid len"));
2269                         break;
2270                 }
2271                 ND_PRINT((ndo, "\n\t    "));
2272                 while (len > 0) {
2273                         ND_TCHECK2(*tptr, 12);
2274                         ND_PRINT((ndo, "%u:%u:%u%s",
2275                                  EXTRACT_32BITS(tptr),
2276                                  EXTRACT_32BITS(tptr + 4),
2277                                  EXTRACT_32BITS(tptr + 8),
2278                                  (len > 12) ? ", " : ""));
2279                         tptr += 12;
2280                         len -= 12;
2281                 }
2282                 break;
2283         default:
2284             ND_TCHECK2(*pptr,len);
2285             ND_PRINT((ndo, "\n\t    no Attribute %u decoder", atype)); /* we have no decoder for the attribute */
2286             if (ndo->ndo_vflag <= 1)
2287                 print_unknown_data(ndo, pptr, "\n\t    ", len);
2288             break;
2289         }
2290         if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/
2291             ND_TCHECK2(*pptr,len);
2292             print_unknown_data(ndo, pptr, "\n\t    ", len);
2293         }
2294         return 1;
2295
2296 trunc:
2297         return 0;
2298 }
2299
2300 static void
2301 bgp_capabilities_print(netdissect_options *ndo,
2302                        const u_char *opt, int caps_len)
2303 {
2304         int cap_type, cap_len, tcap_len, cap_offset;
2305         int i = 0;
2306
2307         while (i < caps_len) {
2308                 ND_TCHECK2(opt[i], BGP_CAP_HEADER_SIZE);
2309                 cap_type=opt[i];
2310                 cap_len=opt[i+1];
2311                 tcap_len=cap_len;
2312                 ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
2313                        tok2str(bgp_capcode_values, "Unknown",
2314                                   cap_type),
2315                        cap_type,
2316                        cap_len));
2317                 ND_TCHECK2(opt[i+2], cap_len);
2318                 switch (cap_type) {
2319                 case BGP_CAPCODE_MP:
2320                     ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u)",
2321                            tok2str(af_values, "Unknown",
2322                                       EXTRACT_16BITS(opt+i+2)),
2323                            EXTRACT_16BITS(opt+i+2),
2324                            tok2str(bgp_safi_values, "Unknown",
2325                                       opt[i+5]),
2326                            opt[i+5]));
2327                     break;
2328                 case BGP_CAPCODE_RESTART:
2329                     ND_PRINT((ndo, "\n\t\tRestart Flags: [%s], Restart Time %us",
2330                            ((opt[i+2])&0x80) ? "R" : "none",
2331                            EXTRACT_16BITS(opt+i+2)&0xfff));
2332                     tcap_len-=2;
2333                     cap_offset=4;
2334                     while(tcap_len>=4) {
2335                         ND_PRINT((ndo, "\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
2336                                tok2str(af_values,"Unknown",
2337                                           EXTRACT_16BITS(opt+i+cap_offset)),
2338                                EXTRACT_16BITS(opt+i+cap_offset),
2339                                tok2str(bgp_safi_values,"Unknown",
2340                                           opt[i+cap_offset+2]),
2341                                opt[i+cap_offset+2],
2342                                ((opt[i+cap_offset+3])&0x80) ? "yes" : "no" ));
2343                         tcap_len-=4;
2344                         cap_offset+=4;
2345                     }
2346                     break;
2347                 case BGP_CAPCODE_RR:
2348                 case BGP_CAPCODE_RR_CISCO:
2349                     break;
2350                 case BGP_CAPCODE_AS_NEW:
2351
2352                     /*
2353                      * Extract the 4 byte AS number encoded.
2354                      */
2355                     if (cap_len == 4) {
2356                         ND_PRINT((ndo, "\n\t\t 4 Byte AS %s",
2357                             as_printf(ndo, astostr, sizeof(astostr),
2358                             EXTRACT_32BITS(opt + i + 2))));
2359                     }
2360                     break;
2361                 case BGP_CAPCODE_ADD_PATH:
2362                     cap_offset=2;
2363                     if (tcap_len == 0) {
2364                         ND_PRINT((ndo, " (bogus)")); /* length */
2365                         break;
2366                     }
2367                     while (tcap_len > 0) {
2368                         if (tcap_len < 4) {
2369                             ND_PRINT((ndo, "\n\t\t(invalid)"));
2370                             break;
2371                         }
2372                         ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
2373                                   tok2str(af_values,"Unknown",EXTRACT_16BITS(opt+i+cap_offset)),
2374                                   EXTRACT_16BITS(opt+i+cap_offset),
2375                                   tok2str(bgp_safi_values,"Unknown",opt[i+cap_offset+2]),
2376                                   opt[i+cap_offset+2],
2377                                   tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",opt[i+cap_offset+3])
2378                         ));
2379                         tcap_len-=4;
2380                         cap_offset+=4;
2381                     }
2382                     break;
2383                 default:
2384                     ND_PRINT((ndo, "\n\t\tno decoder for Capability %u",
2385                            cap_type));
2386                     if (ndo->ndo_vflag <= 1)
2387                         print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
2388                     break;
2389                 }
2390                 if (ndo->ndo_vflag > 1 && cap_len > 0) {
2391                     print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
2392                 }
2393                 i += BGP_CAP_HEADER_SIZE + cap_len;
2394         }
2395         return;
2396
2397 trunc:
2398         ND_PRINT((ndo, "[|BGP]"));
2399 }
2400
2401 static void
2402 bgp_open_print(netdissect_options *ndo,
2403                const u_char *dat, int length)
2404 {
2405         struct bgp_open bgpo;
2406         struct bgp_opt bgpopt;
2407         const u_char *opt;
2408         int i;
2409
2410         ND_TCHECK2(dat[0], BGP_OPEN_SIZE);
2411         memcpy(&bgpo, dat, BGP_OPEN_SIZE);
2412
2413         ND_PRINT((ndo, "\n\t  Version %d, ", bgpo.bgpo_version));
2414         ND_PRINT((ndo, "my AS %s, ",
2415             as_printf(ndo, astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas))));
2416         ND_PRINT((ndo, "Holdtime %us, ", ntohs(bgpo.bgpo_holdtime)));
2417         ND_PRINT((ndo, "ID %s", ipaddr_string(ndo, &bgpo.bgpo_id)));
2418         ND_PRINT((ndo, "\n\t  Optional parameters, length: %u", bgpo.bgpo_optlen));
2419
2420         /* some little sanity checking */
2421         if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
2422             return;
2423
2424         /* ugly! */
2425         opt = &((const struct bgp_open *)dat)->bgpo_optlen;
2426         opt++;
2427
2428         i = 0;
2429         while (i < bgpo.bgpo_optlen) {
2430                 ND_TCHECK2(opt[i], BGP_OPT_SIZE);
2431                 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
2432                 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
2433                         ND_PRINT((ndo, "\n\t     Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len));
2434                         break;
2435                 }
2436
2437                 ND_PRINT((ndo, "\n\t    Option %s (%u), length: %u",
2438                        tok2str(bgp_opt_values,"Unknown",
2439                                   bgpopt.bgpopt_type),
2440                        bgpopt.bgpopt_type,
2441                        bgpopt.bgpopt_len));
2442
2443                 /* now let's decode the options we know*/
2444                 switch(bgpopt.bgpopt_type) {
2445
2446                 case BGP_OPT_CAP:
2447                         bgp_capabilities_print(ndo, &opt[i+BGP_OPT_SIZE],
2448                             bgpopt.bgpopt_len);
2449                         break;
2450
2451                 case BGP_OPT_AUTH:
2452                 default:
2453                        ND_PRINT((ndo, "\n\t      no decoder for option %u",
2454                            bgpopt.bgpopt_type));
2455                        break;
2456                 }
2457                 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
2458         }
2459         return;
2460 trunc:
2461         ND_PRINT((ndo, "[|BGP]"));
2462 }
2463
2464 static void
2465 bgp_update_print(netdissect_options *ndo,
2466                  const u_char *dat, int length)
2467 {
2468         struct bgp bgp;
2469         const u_char *p;
2470         int withdrawn_routes_len;
2471         int len;
2472         int i;
2473
2474         ND_TCHECK2(dat[0], BGP_SIZE);
2475         if (length < BGP_SIZE)
2476                 goto trunc;
2477         memcpy(&bgp, dat, BGP_SIZE);
2478         p = dat + BGP_SIZE;     /*XXX*/
2479         length -= BGP_SIZE;
2480
2481         /* Unfeasible routes */
2482         ND_TCHECK2(p[0], 2);
2483         if (length < 2)
2484                 goto trunc;
2485         withdrawn_routes_len = EXTRACT_16BITS(p);
2486         p += 2;
2487         length -= 2;
2488         if (withdrawn_routes_len) {
2489                 /*
2490                  * Without keeping state from the original NLRI message,
2491                  * it's not possible to tell if this a v4 or v6 route,
2492                  * so only try to decode it if we're not v6 enabled.
2493                  */
2494                 ND_TCHECK2(p[0], withdrawn_routes_len);
2495                 if (length < withdrawn_routes_len)
2496                         goto trunc;
2497                 ND_PRINT((ndo, "\n\t  Withdrawn routes: %d bytes", withdrawn_routes_len));
2498                 p += withdrawn_routes_len;
2499                 length -= withdrawn_routes_len;
2500         }
2501
2502         ND_TCHECK2(p[0], 2);
2503         if (length < 2)
2504                 goto trunc;
2505         len = EXTRACT_16BITS(p);
2506         p += 2;
2507         length -= 2;
2508
2509         if (withdrawn_routes_len == 0 && len == 0 && length == 0) {
2510             /* No withdrawn routes, no path attributes, no NLRI */
2511             ND_PRINT((ndo, "\n\t  End-of-Rib Marker (empty NLRI)"));
2512             return;
2513         }
2514
2515         if (len) {
2516                 /* do something more useful!*/
2517                 while (len) {
2518                         int aflags, atype, alenlen, alen;
2519
2520                         ND_TCHECK2(p[0], 2);
2521                         if (len < 2)
2522                             goto trunc;
2523                         if (length < 2)
2524                             goto trunc;
2525                         aflags = *p;
2526                         atype = *(p + 1);
2527                         p += 2;
2528                         len -= 2;
2529                         length -= 2;
2530                         alenlen = bgp_attr_lenlen(aflags, p);
2531                         ND_TCHECK2(p[0], alenlen);
2532                         if (len < alenlen)
2533                             goto trunc;
2534                         if (length < alenlen)
2535                             goto trunc;
2536                         alen = bgp_attr_len(aflags, p);
2537                         p += alenlen;
2538                         len -= alenlen;
2539                         length -= alenlen;
2540
2541                         ND_PRINT((ndo, "\n\t  %s (%u), length: %u",
2542                               tok2str(bgp_attr_values, "Unknown Attribute",
2543                                          atype),
2544                               atype,
2545                               alen));
2546
2547                         if (aflags) {
2548                                 ND_PRINT((ndo, ", Flags [%s%s%s%s",
2549                                         aflags & 0x80 ? "O" : "",
2550                                         aflags & 0x40 ? "T" : "",
2551                                         aflags & 0x20 ? "P" : "",
2552                                         aflags & 0x10 ? "E" : ""));
2553                                 if (aflags & 0xf)
2554                                         ND_PRINT((ndo, "+%x", aflags & 0xf));
2555                                 ND_PRINT((ndo, "]: "));
2556                         }
2557                         if (len < alen)
2558                                 goto trunc;
2559                         if (length < alen)
2560                                 goto trunc;
2561                         if (!bgp_attr_print(ndo, atype, p, alen))
2562                                 goto trunc;
2563                         p += alen;
2564                         len -= alen;
2565                         length -= alen;
2566                 }
2567         }
2568
2569         if (length) {
2570                 /*
2571                  * XXX - what if they're using the "Advertisement of
2572                  * Multiple Paths in BGP" feature:
2573                  *
2574                  * https://datatracker.ietf.org/doc/draft-ietf-idr-add-paths/
2575                  *
2576                  * http://tools.ietf.org/html/draft-ietf-idr-add-paths-06
2577                  */
2578                 ND_PRINT((ndo, "\n\t  Updated routes:"));
2579                 while (length) {
2580                         char buf[MAXHOSTNAMELEN + 100];
2581                         i = decode_prefix4(ndo, p, length, buf, sizeof(buf));
2582                         if (i == -1) {
2583                                 ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2584                                 break;
2585                         } else if (i == -2)
2586                                 goto trunc;
2587                         else if (i == -3)
2588                                 goto trunc; /* bytes left, but not enough */
2589                         else {
2590                                 ND_PRINT((ndo, "\n\t    %s", buf));
2591                                 p += i;
2592                                 length -= i;
2593                         }
2594                 }
2595         }
2596         return;
2597 trunc:
2598         ND_PRINT((ndo, "[|BGP]"));
2599 }
2600
2601 static void
2602 bgp_notification_print(netdissect_options *ndo,
2603                        const u_char *dat, int length)
2604 {
2605         struct bgp_notification bgpn;
2606         const u_char *tptr;
2607
2608         ND_TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
2609         memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
2610
2611         /* some little sanity checking */
2612         if (length<BGP_NOTIFICATION_SIZE)
2613             return;
2614
2615         ND_PRINT((ndo, ", %s (%u)",
2616                tok2str(bgp_notify_major_values, "Unknown Error",
2617                           bgpn.bgpn_major),
2618                bgpn.bgpn_major));
2619
2620         switch (bgpn.bgpn_major) {
2621
2622         case BGP_NOTIFY_MAJOR_MSG:
2623             ND_PRINT((ndo, ", subcode %s (%u)",
2624                    tok2str(bgp_notify_minor_msg_values, "Unknown",
2625                               bgpn.bgpn_minor),
2626                    bgpn.bgpn_minor));
2627             break;
2628         case BGP_NOTIFY_MAJOR_OPEN:
2629             ND_PRINT((ndo, ", subcode %s (%u)",
2630                    tok2str(bgp_notify_minor_open_values, "Unknown",
2631                               bgpn.bgpn_minor),
2632                    bgpn.bgpn_minor));
2633             break;
2634         case BGP_NOTIFY_MAJOR_UPDATE:
2635             ND_PRINT((ndo, ", subcode %s (%u)",
2636                    tok2str(bgp_notify_minor_update_values, "Unknown",
2637                               bgpn.bgpn_minor),
2638                    bgpn.bgpn_minor));
2639             break;
2640         case BGP_NOTIFY_MAJOR_FSM:
2641             ND_PRINT((ndo, " subcode %s (%u)",
2642                    tok2str(bgp_notify_minor_fsm_values, "Unknown",
2643                               bgpn.bgpn_minor),
2644                    bgpn.bgpn_minor));
2645             break;
2646         case BGP_NOTIFY_MAJOR_CAP:
2647             ND_PRINT((ndo, " subcode %s (%u)",
2648                    tok2str(bgp_notify_minor_cap_values, "Unknown",
2649                               bgpn.bgpn_minor),
2650                    bgpn.bgpn_minor));
2651             break;
2652         case BGP_NOTIFY_MAJOR_CEASE:
2653             ND_PRINT((ndo, ", subcode %s (%u)",
2654                    tok2str(bgp_notify_minor_cease_values, "Unknown",
2655                               bgpn.bgpn_minor),
2656                    bgpn.bgpn_minor));
2657
2658             /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
2659              * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
2660              */
2661             if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
2662                 tptr = dat + BGP_NOTIFICATION_SIZE;
2663                 ND_TCHECK2(*tptr, 7);
2664                 ND_PRINT((ndo, ", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
2665                        tok2str(af_values, "Unknown",
2666                                   EXTRACT_16BITS(tptr)),
2667                        EXTRACT_16BITS(tptr),
2668                        tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
2669                        *(tptr+2),
2670                        EXTRACT_32BITS(tptr+3)));
2671             }
2672             break;
2673         default:
2674             break;
2675         }
2676
2677         return;
2678 trunc:
2679         ND_PRINT((ndo, "[|BGP]"));
2680 }
2681
2682 static void
2683 bgp_route_refresh_print(netdissect_options *ndo,
2684                         const u_char *pptr, int len)
2685 {
2686         const struct bgp_route_refresh *bgp_route_refresh_header;
2687
2688         ND_TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE);
2689
2690         /* some little sanity checking */
2691         if (len<BGP_ROUTE_REFRESH_SIZE)
2692             return;
2693
2694         bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
2695
2696         ND_PRINT((ndo, "\n\t  AFI %s (%u), SAFI %s (%u)",
2697                tok2str(af_values,"Unknown",
2698                           /* this stinks but the compiler pads the structure
2699                            * weird */
2700                           EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
2701                EXTRACT_16BITS(&bgp_route_refresh_header->afi),
2702                tok2str(bgp_safi_values,"Unknown",
2703                           bgp_route_refresh_header->safi),
2704                bgp_route_refresh_header->safi));
2705
2706         if (ndo->ndo_vflag > 1) {
2707             ND_TCHECK2(*pptr, len);
2708             print_unknown_data(ndo, pptr, "\n\t  ", len);
2709         }
2710
2711         return;
2712 trunc:
2713         ND_PRINT((ndo, "[|BGP]"));
2714 }
2715
2716 static int
2717 bgp_header_print(netdissect_options *ndo,
2718                  const u_char *dat, int length)
2719 {
2720         struct bgp bgp;
2721
2722         ND_TCHECK2(dat[0], BGP_SIZE);
2723         memcpy(&bgp, dat, BGP_SIZE);
2724         ND_PRINT((ndo, "\n\t%s Message (%u), length: %u",
2725                tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
2726                bgp.bgp_type,
2727                length));
2728
2729         switch (bgp.bgp_type) {
2730         case BGP_OPEN:
2731                 bgp_open_print(ndo, dat, length);
2732                 break;
2733         case BGP_UPDATE:
2734                 bgp_update_print(ndo, dat, length);
2735                 break;
2736         case BGP_NOTIFICATION:
2737                 bgp_notification_print(ndo, dat, length);
2738                 break;
2739         case BGP_KEEPALIVE:
2740                 break;
2741         case BGP_ROUTE_REFRESH:
2742                 bgp_route_refresh_print(ndo, dat, length);
2743                 break;
2744         default:
2745                 /* we have no decoder for the BGP message */
2746                 ND_TCHECK2(*dat, length);
2747                 ND_PRINT((ndo, "\n\t  no Message %u decoder", bgp.bgp_type));
2748                 print_unknown_data(ndo, dat, "\n\t  ", length);
2749                 break;
2750         }
2751         return 1;
2752 trunc:
2753         ND_PRINT((ndo, "[|BGP]"));
2754         return 0;
2755 }
2756
2757 void
2758 bgp_print(netdissect_options *ndo,
2759           const u_char *dat, int length)
2760 {
2761         const u_char *p;
2762         const u_char *ep;
2763         const u_char *start;
2764         const u_char marker[] = {
2765                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2766                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2767         };
2768         struct bgp bgp;
2769         uint16_t hlen;
2770
2771         ep = dat + length;
2772         if (ndo->ndo_snapend < dat + length)
2773                 ep = ndo->ndo_snapend;
2774
2775         ND_PRINT((ndo, ": BGP"));
2776
2777         if (ndo->ndo_vflag < 1) /* lets be less chatty */
2778                 return;
2779
2780         p = dat;
2781         start = p;
2782         while (p < ep) {
2783                 if (!ND_TTEST2(p[0], 1))
2784                         break;
2785                 if (p[0] != 0xff) {
2786                         p++;
2787                         continue;
2788                 }
2789
2790                 if (!ND_TTEST2(p[0], sizeof(marker)))
2791                         break;
2792                 if (memcmp(p, marker, sizeof(marker)) != 0) {
2793                         p++;
2794                         continue;
2795                 }
2796
2797                 /* found BGP header */
2798                 ND_TCHECK2(p[0], BGP_SIZE);     /*XXX*/
2799                 memcpy(&bgp, p, BGP_SIZE);
2800
2801                 if (start != p)
2802                         ND_PRINT((ndo, " [|BGP]"));
2803
2804                 hlen = ntohs(bgp.bgp_len);
2805                 if (hlen < BGP_SIZE) {
2806                         ND_PRINT((ndo, "\n[|BGP Bogus header length %u < %u]", hlen,
2807                             BGP_SIZE));
2808                         break;
2809                 }
2810
2811                 if (ND_TTEST2(p[0], hlen)) {
2812                         if (!bgp_header_print(ndo, p, hlen))
2813                                 return;
2814                         p += hlen;
2815                         start = p;
2816                 } else {
2817                         ND_PRINT((ndo, "\n[|BGP %s]",
2818                                tok2str(bgp_msg_values,
2819                                           "Unknown Message Type",
2820                                           bgp.bgp_type)));
2821                         break;
2822                 }
2823         }
2824
2825         return;
2826
2827 trunc:
2828         ND_PRINT((ndo, " [|BGP]"));
2829 }
2830
2831 /*
2832  * Local Variables:
2833  * c-style: whitesmith
2834  * c-basic-offset: 4
2835  * End:
2836  */