]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-bgp.c
Add two missing eventhandler.h headers
[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@gredler.at) 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         char asbuf[sizeof(astostr)]; /* bgp_vpn_rd_print() overwrites astostr */
760
761         /* NLRI "prefix length" from RFC 2858 Section 4. */
762         ND_TCHECK(pptr[0]);
763         plen = pptr[0];   /* get prefix length */
764
765         /* NLRI "prefix" (ibid), valid lengths are { 0, 32, 33, ..., 96 } bits.
766          * RFC 4684 Section 4 defines the layout of "origin AS" and "route
767          * target" fields inside the "prefix" depending on its length.
768          */
769         if (0 == plen) {
770                 /* Without "origin AS", without "route target". */
771                 snprintf(buf, buflen, "default route target");
772                 return 1;
773         }
774
775         if (32 > plen)
776                 return -1;
777
778         /* With at least "origin AS", possibly with "route target". */
779         ND_TCHECK_32BITS(pptr + 1);
780         as_printf(ndo, asbuf, sizeof(asbuf), EXTRACT_32BITS(pptr + 1));
781
782         plen-=32; /* adjust prefix length */
783
784         if (64 < plen)
785                 return -1;
786
787         /* From now on (plen + 7) / 8 evaluates to { 0, 1, 2, ..., 8 }
788          * and gives the number of octets in the variable-length "route
789          * target" field inside this NLRI "prefix". Look for it.
790          */
791         memset(&route_target, 0, sizeof(route_target));
792         ND_TCHECK2(pptr[5], (plen + 7) / 8);
793         memcpy(&route_target, &pptr[5], (plen + 7) / 8);
794         /* Which specification says to do this? */
795         if (plen % 8) {
796                 ((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
797                         ((0xff00 >> (plen % 8)) & 0xff);
798         }
799         snprintf(buf, buflen, "origin AS: %s, route target %s",
800             asbuf,
801             bgp_vpn_rd_print(ndo, (u_char *)&route_target));
802
803         return 5 + (plen + 7) / 8;
804
805 trunc:
806         return -2;
807 }
808
809 static int
810 decode_labeled_vpn_prefix4(netdissect_options *ndo,
811                            const u_char *pptr, char *buf, u_int buflen)
812 {
813         struct in_addr addr;
814         u_int plen;
815
816         ND_TCHECK(pptr[0]);
817         plen = pptr[0];   /* get prefix length */
818
819         if ((24+64) > plen)
820                 return -1;
821
822         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
823
824         if (32 < plen)
825                 return -1;
826
827         memset(&addr, 0, sizeof(addr));
828         ND_TCHECK2(pptr[12], (plen + 7) / 8);
829         memcpy(&addr, &pptr[12], (plen + 7) / 8);
830         if (plen % 8) {
831                 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
832                         ((0xff00 >> (plen % 8)) & 0xff);
833         }
834         /* the label may get offsetted by 4 bits so lets shift it right */
835         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
836                  bgp_vpn_rd_print(ndo, pptr+4),
837                  ipaddr_string(ndo, &addr),
838                  plen,
839                  EXTRACT_24BITS(pptr+1)>>4,
840                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
841
842         return 12 + (plen + 7) / 8;
843
844 trunc:
845         return -2;
846 }
847
848 /*
849  * +-------------------------------+
850  * |                               |
851  * |  RD:IPv4-address (12 octets)  |
852  * |                               |
853  * +-------------------------------+
854  * |  MDT Group-address (4 octets) |
855  * +-------------------------------+
856  */
857
858 #define MDT_VPN_NLRI_LEN 16
859
860 static int
861 decode_mdt_vpn_nlri(netdissect_options *ndo,
862                     const u_char *pptr, char *buf, u_int buflen)
863 {
864
865     const u_char *rd;
866     const u_char *vpn_ip;
867
868     ND_TCHECK(pptr[0]);
869
870     /* if the NLRI is not predefined length, quit.*/
871     if (*pptr != MDT_VPN_NLRI_LEN * 8)
872         return -1;
873     pptr++;
874
875     /* RD */
876     ND_TCHECK2(pptr[0], 8);
877     rd = pptr;
878     pptr+=8;
879
880     /* IPv4 address */
881     ND_TCHECK2(pptr[0], sizeof(struct in_addr));
882     vpn_ip = pptr;
883     pptr+=sizeof(struct in_addr);
884
885     /* MDT Group Address */
886     ND_TCHECK2(pptr[0], sizeof(struct in_addr));
887
888     snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s",
889              bgp_vpn_rd_print(ndo, rd), ipaddr_string(ndo, vpn_ip), ipaddr_string(ndo, pptr));
890
891     return MDT_VPN_NLRI_LEN + 1;
892
893  trunc:
894
895 return -2;
896 }
897
898 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI   1
899 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI   2
900 #define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI            3
901 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4
902 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE     5
903 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN  6
904 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN  7
905
906 static const struct tok bgp_multicast_vpn_route_type_values[] = {
907     { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"},
908     { BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"},
909     { BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"},
910     { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"},
911     { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"},
912     { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"},
913     { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"},
914     { 0, NULL}
915 };
916
917 static int
918 decode_multicast_vpn(netdissect_options *ndo,
919                      const u_char *pptr, char *buf, u_int buflen)
920 {
921         uint8_t route_type, route_length, addr_length, sg_length;
922         u_int offset;
923
924         ND_TCHECK2(pptr[0], 2);
925         route_type = *pptr++;
926         route_length = *pptr++;
927
928         snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
929                  tok2str(bgp_multicast_vpn_route_type_values,
930                          "Unknown", route_type),
931                  route_type, route_length);
932
933         switch(route_type) {
934         case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
935             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
936             offset = strlen(buf);
937             snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
938                      bgp_vpn_rd_print(ndo, pptr),
939                      bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN,
940                                       (route_length - BGP_VPN_RD_LEN) << 3));
941             break;
942         case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
943             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
944             offset = strlen(buf);
945             snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
946                 bgp_vpn_rd_print(ndo, pptr),
947                 as_printf(ndo, astostr, sizeof(astostr),
948                 EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN)));
949             break;
950
951         case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
952             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
953             offset = strlen(buf);
954             snprintf(buf + offset, buflen - offset, ", RD: %s",
955                      bgp_vpn_rd_print(ndo, pptr));
956             pptr += BGP_VPN_RD_LEN;
957
958             sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen);
959             addr_length =  route_length - sg_length;
960
961             ND_TCHECK2(pptr[0], addr_length);
962             offset = strlen(buf);
963             snprintf(buf + offset, buflen - offset, ", Originator %s",
964                      bgp_vpn_ip_print(ndo, pptr, addr_length << 3));
965             break;
966
967         case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
968             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
969             offset = strlen(buf);
970             snprintf(buf + offset, buflen - offset, ", RD: %s",
971                      bgp_vpn_rd_print(ndo, pptr));
972             pptr += BGP_VPN_RD_LEN;
973
974             bgp_vpn_sg_print(ndo, pptr, buf, buflen);
975             break;
976
977         case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */
978         case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
979             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
980             offset = strlen(buf);
981             snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
982                 bgp_vpn_rd_print(ndo, pptr),
983                 as_printf(ndo, astostr, sizeof(astostr),
984                 EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN)));
985             pptr += BGP_VPN_RD_LEN + 4;
986
987             bgp_vpn_sg_print(ndo, pptr, buf, buflen);
988             break;
989
990             /*
991              * no per route-type printing yet.
992              */
993         case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF:
994         default:
995             break;
996         }
997
998         return route_length + 2;
999
1000 trunc:
1001         return -2;
1002 }
1003
1004 /*
1005  * As I remember, some versions of systems have an snprintf() that
1006  * returns -1 if the buffer would have overflowed.  If the return
1007  * value is negative, set buflen to 0, to indicate that we've filled
1008  * the buffer up.
1009  *
1010  * If the return value is greater than buflen, that means that
1011  * the buffer would have overflowed; again, set buflen to 0 in
1012  * that case.
1013  */
1014 #define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \
1015     if (stringlen<0) \
1016         buflen=0; \
1017     else if ((u_int)stringlen>buflen) \
1018         buflen=0; \
1019     else { \
1020         buflen-=stringlen; \
1021         buf+=stringlen; \
1022     }
1023
1024 static int
1025 decode_labeled_vpn_l2(netdissect_options *ndo,
1026                       const u_char *pptr, char *buf, u_int buflen)
1027 {
1028         int plen,tlen,stringlen,tlv_type,tlv_len,ttlv_len;
1029
1030         ND_TCHECK2(pptr[0], 2);
1031         plen=EXTRACT_16BITS(pptr);
1032         tlen=plen;
1033         pptr+=2;
1034         /* Old and new L2VPN NLRI share AFI/SAFI
1035          *   -> Assume a 12 Byte-length NLRI is auto-discovery-only
1036          *      and > 17 as old format. Complain for the middle case
1037          */
1038         if (plen==12) {
1039             /* assume AD-only with RD, BGPNH */
1040             ND_TCHECK2(pptr[0],12);
1041             buf[0]='\0';
1042             stringlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s",
1043                                bgp_vpn_rd_print(ndo, pptr),
1044                                ipaddr_string(ndo, pptr+8)
1045                                );
1046             UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1047             pptr+=12;
1048             tlen-=12;
1049             return plen;
1050         } else if (plen>17) {
1051             /* assume old format */
1052             /* RD, ID, LBLKOFF, LBLBASE */
1053
1054             ND_TCHECK2(pptr[0],15);
1055             buf[0]='\0';
1056             stringlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
1057                                bgp_vpn_rd_print(ndo, pptr),
1058                                EXTRACT_16BITS(pptr+8),
1059                                EXTRACT_16BITS(pptr+10),
1060                                EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
1061             UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1062             pptr+=15;
1063             tlen-=15;
1064
1065             /* ok now the variable part - lets read out TLVs*/
1066             while (tlen>0) {
1067                 if (tlen < 3)
1068                     return -1;
1069                 ND_TCHECK2(pptr[0], 3);
1070                 tlv_type=*pptr++;
1071                 tlv_len=EXTRACT_16BITS(pptr);
1072                 ttlv_len=tlv_len;
1073                 pptr+=2;
1074
1075                 switch(tlv_type) {
1076                 case 1:
1077                     if (buflen!=0) {
1078                         stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
1079                                            tlv_type,
1080                                            tlv_len);
1081                         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1082                     }
1083                     ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
1084                     while (ttlv_len>0) {
1085                         ND_TCHECK(pptr[0]);
1086                         if (buflen!=0) {
1087                             stringlen=snprintf(buf,buflen, "%02x",*pptr++);
1088                             UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1089                         }
1090                         ttlv_len--;
1091                     }
1092                     break;
1093                 default:
1094                     if (buflen!=0) {
1095                         stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
1096                                            tlv_type,
1097                                            tlv_len);
1098                         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1099                     }
1100                     break;
1101                 }
1102                 tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
1103             }
1104             return plen+2;
1105
1106         } else {
1107             /* complain bitterly ? */
1108             /* fall through */
1109             goto trunc;
1110         }
1111
1112 trunc:
1113         return -2;
1114 }
1115
1116 int
1117 decode_prefix6(netdissect_options *ndo,
1118                const u_char *pd, u_int itemlen, char *buf, u_int buflen)
1119 {
1120         struct in6_addr addr;
1121         u_int plen, plenbytes;
1122
1123         ND_TCHECK(pd[0]);
1124         ITEMCHECK(1);
1125         plen = pd[0];
1126         if (128 < plen)
1127                 return -1;
1128         itemlen -= 1;
1129
1130         memset(&addr, 0, sizeof(addr));
1131         plenbytes = (plen + 7) / 8;
1132         ND_TCHECK2(pd[1], plenbytes);
1133         ITEMCHECK(plenbytes);
1134         memcpy(&addr, &pd[1], plenbytes);
1135         if (plen % 8) {
1136                 addr.s6_addr[plenbytes - 1] &=
1137                         ((0xff00 >> (plen % 8)) & 0xff);
1138         }
1139         snprintf(buf, buflen, "%s/%d", ip6addr_string(ndo, &addr), plen);
1140         return 1 + plenbytes;
1141
1142 trunc:
1143         return -2;
1144
1145 badtlv:
1146         return -3;
1147 }
1148
1149 static int
1150 decode_labeled_prefix6(netdissect_options *ndo,
1151                        const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
1152 {
1153         struct in6_addr addr;
1154         u_int plen, plenbytes;
1155
1156         /* prefix length and label = 4 bytes */
1157         ND_TCHECK2(pptr[0], 4);
1158         ITEMCHECK(4);
1159         plen = pptr[0]; /* get prefix length */
1160
1161         if (24 > plen)
1162                 return -1;
1163
1164         plen-=24; /* adjust prefixlen - labellength */
1165
1166         if (128 < plen)
1167                 return -1;
1168         itemlen -= 4;
1169
1170         memset(&addr, 0, sizeof(addr));
1171         plenbytes = (plen + 7) / 8;
1172         ND_TCHECK2(pptr[4], plenbytes);
1173         memcpy(&addr, &pptr[4], plenbytes);
1174         if (plen % 8) {
1175                 addr.s6_addr[plenbytes - 1] &=
1176                         ((0xff00 >> (plen % 8)) & 0xff);
1177         }
1178         /* the label may get offsetted by 4 bits so lets shift it right */
1179         snprintf(buf, buflen, "%s/%d, label:%u %s",
1180                  ip6addr_string(ndo, &addr),
1181                  plen,
1182                  EXTRACT_24BITS(pptr+1)>>4,
1183                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1184
1185         return 4 + plenbytes;
1186
1187 trunc:
1188         return -2;
1189
1190 badtlv:
1191         return -3;
1192 }
1193
1194 static int
1195 decode_labeled_vpn_prefix6(netdissect_options *ndo,
1196                            const u_char *pptr, char *buf, u_int buflen)
1197 {
1198         struct in6_addr addr;
1199         u_int plen;
1200
1201         ND_TCHECK(pptr[0]);
1202         plen = pptr[0];   /* get prefix length */
1203
1204         if ((24+64) > plen)
1205                 return -1;
1206
1207         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
1208
1209         if (128 < plen)
1210                 return -1;
1211
1212         memset(&addr, 0, sizeof(addr));
1213         ND_TCHECK2(pptr[12], (plen + 7) / 8);
1214         memcpy(&addr, &pptr[12], (plen + 7) / 8);
1215         if (plen % 8) {
1216                 addr.s6_addr[(plen + 7) / 8 - 1] &=
1217                         ((0xff00 >> (plen % 8)) & 0xff);
1218         }
1219         /* the label may get offsetted by 4 bits so lets shift it right */
1220         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
1221                  bgp_vpn_rd_print(ndo, pptr+4),
1222                  ip6addr_string(ndo, &addr),
1223                  plen,
1224                  EXTRACT_24BITS(pptr+1)>>4,
1225                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1226
1227         return 12 + (plen + 7) / 8;
1228
1229 trunc:
1230         return -2;
1231 }
1232
1233 static int
1234 decode_clnp_prefix(netdissect_options *ndo,
1235                    const u_char *pptr, char *buf, u_int buflen)
1236 {
1237         uint8_t addr[19];
1238         u_int plen;
1239
1240         ND_TCHECK(pptr[0]);
1241         plen = pptr[0]; /* get prefix length */
1242
1243         if (152 < plen)
1244                 return -1;
1245
1246         memset(&addr, 0, sizeof(addr));
1247         ND_TCHECK2(pptr[4], (plen + 7) / 8);
1248         memcpy(&addr, &pptr[4], (plen + 7) / 8);
1249         if (plen % 8) {
1250                 addr[(plen + 7) / 8 - 1] &=
1251                         ((0xff00 >> (plen % 8)) & 0xff);
1252         }
1253         snprintf(buf, buflen, "%s/%d",
1254                  isonsap_string(ndo, addr,(plen + 7) / 8),
1255                  plen);
1256
1257         return 1 + (plen + 7) / 8;
1258
1259 trunc:
1260         return -2;
1261 }
1262
1263 static int
1264 decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
1265                                const u_char *pptr, char *buf, u_int buflen)
1266 {
1267         uint8_t addr[19];
1268         u_int plen;
1269
1270         ND_TCHECK(pptr[0]);
1271         plen = pptr[0];   /* get prefix length */
1272
1273         if ((24+64) > plen)
1274                 return -1;
1275
1276         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
1277
1278         if (152 < plen)
1279                 return -1;
1280
1281         memset(&addr, 0, sizeof(addr));
1282         ND_TCHECK2(pptr[12], (plen + 7) / 8);
1283         memcpy(&addr, &pptr[12], (plen + 7) / 8);
1284         if (plen % 8) {
1285                 addr[(plen + 7) / 8 - 1] &=
1286                         ((0xff00 >> (plen % 8)) & 0xff);
1287         }
1288         /* the label may get offsetted by 4 bits so lets shift it right */
1289         snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
1290                  bgp_vpn_rd_print(ndo, pptr+4),
1291                  isonsap_string(ndo, addr,(plen + 7) / 8),
1292                  plen,
1293                  EXTRACT_24BITS(pptr+1)>>4,
1294                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1295
1296         return 12 + (plen + 7) / 8;
1297
1298 trunc:
1299         return -2;
1300 }
1301
1302 /*
1303  * bgp_attr_get_as_size
1304  *
1305  * Try to find the size of the ASs encoded in an as-path. It is not obvious, as
1306  * both Old speakers that do not support 4 byte AS, and the new speakers that do
1307  * support, exchange AS-Path with the same path-attribute type value 0x02.
1308  */
1309 static int
1310 bgp_attr_get_as_size(netdissect_options *ndo,
1311                      uint8_t bgpa_type, const u_char *pptr, int len)
1312 {
1313     const u_char *tptr = pptr;
1314
1315     /*
1316      * If the path attribute is the optional AS4 path type, then we already
1317      * know, that ASs must be encoded in 4 byte format.
1318      */
1319     if (bgpa_type == BGPTYPE_AS4_PATH) {
1320         return 4;
1321     }
1322
1323     /*
1324      * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path
1325      * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes
1326      * each.
1327      */
1328     while (tptr < pptr + len) {
1329         ND_TCHECK(tptr[0]);
1330
1331         /*
1332          * If we do not find a valid segment type, our guess might be wrong.
1333          */
1334         if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) {
1335             goto trunc;
1336         }
1337         ND_TCHECK(tptr[1]);
1338         tptr += 2 + tptr[1] * 2;
1339     }
1340
1341     /*
1342      * If we correctly reached end of the AS path attribute data content,
1343      * then most likely ASs were indeed encoded as 2 bytes.
1344      */
1345     if (tptr == pptr + len) {
1346         return 2;
1347     }
1348
1349 trunc:
1350
1351     /*
1352      * We can come here, either we did not have enough data, or if we
1353      * try to decode 4 byte ASs in 2 byte format. Either way, return 4,
1354      * so that calller can try to decode each AS as of 4 bytes. If indeed
1355      * there was not enough data, it will crib and end the parse anyways.
1356      */
1357    return 4;
1358 }
1359
1360 static int
1361 bgp_attr_print(netdissect_options *ndo,
1362                u_int atype, const u_char *pptr, u_int len)
1363 {
1364         int i;
1365         uint16_t af;
1366         uint8_t safi, snpa, nhlen;
1367         union { /* copy buffer for bandwidth values */
1368             float f;
1369             uint32_t i;
1370         } bw;
1371         int advance;
1372         u_int tlen;
1373         const u_char *tptr;
1374         char buf[MAXHOSTNAMELEN + 100];
1375         int  as_size;
1376
1377         tptr = pptr;
1378         tlen=len;
1379
1380         switch (atype) {
1381         case BGPTYPE_ORIGIN:
1382                 if (len != 1)
1383                         ND_PRINT((ndo, "invalid len"));
1384                 else {
1385                         ND_TCHECK(*tptr);
1386                         ND_PRINT((ndo, "%s", tok2str(bgp_origin_values,
1387                                                 "Unknown Origin Typecode",
1388                                                 tptr[0])));
1389                 }
1390                 break;
1391
1392         /*
1393          * Process AS4 byte path and AS2 byte path attributes here.
1394          */
1395         case BGPTYPE_AS4_PATH:
1396         case BGPTYPE_AS_PATH:
1397                 if (len % 2) {
1398                         ND_PRINT((ndo, "invalid len"));
1399                         break;
1400                 }
1401                 if (!len) {
1402                         ND_PRINT((ndo, "empty"));
1403                         break;
1404                 }
1405
1406                 /*
1407                  * BGP updates exchanged between New speakers that support 4
1408                  * byte AS, ASs are always encoded in 4 bytes. There is no
1409                  * definitive way to find this, just by the packet's
1410                  * contents. So, check for packet's TLV's sanity assuming
1411                  * 2 bytes first, and it does not pass, assume that ASs are
1412                  * encoded in 4 bytes format and move on.
1413                  */
1414                 as_size = bgp_attr_get_as_size(ndo, atype, pptr, len);
1415
1416                 while (tptr < pptr + len) {
1417                         ND_TCHECK(tptr[0]);
1418                         ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values,
1419                                                 "?", tptr[0])));
1420                         ND_TCHECK(tptr[1]);
1421                         for (i = 0; i < tptr[1] * as_size; i += as_size) {
1422                             ND_TCHECK2(tptr[2 + i], as_size);
1423                             ND_PRINT((ndo, "%s ",
1424                                 as_printf(ndo, astostr, sizeof(astostr),
1425                                 as_size == 2 ?
1426                                 EXTRACT_16BITS(&tptr[2 + i]) :
1427                                 EXTRACT_32BITS(&tptr[2 + i]))));
1428                         }
1429                         ND_TCHECK(tptr[0]);
1430                         ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_close_values,
1431                                                 "?", tptr[0])));
1432                         ND_TCHECK(tptr[1]);
1433                         tptr += 2 + tptr[1] * as_size;
1434                 }
1435                 break;
1436         case BGPTYPE_NEXT_HOP:
1437                 if (len != 4)
1438                         ND_PRINT((ndo, "invalid len"));
1439                 else {
1440                         ND_TCHECK2(tptr[0], 4);
1441                         ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
1442                 }
1443                 break;
1444         case BGPTYPE_MULTI_EXIT_DISC:
1445         case BGPTYPE_LOCAL_PREF:
1446                 if (len != 4)
1447                         ND_PRINT((ndo, "invalid len"));
1448                 else {
1449                         ND_TCHECK2(tptr[0], 4);
1450                         ND_PRINT((ndo, "%u", EXTRACT_32BITS(tptr)));
1451                 }
1452                 break;
1453         case BGPTYPE_ATOMIC_AGGREGATE:
1454                 if (len != 0)
1455                         ND_PRINT((ndo, "invalid len"));
1456                 break;
1457         case BGPTYPE_AGGREGATOR:
1458
1459                 /*
1460                  * Depending on the AS encoded is of 2 bytes or of 4 bytes,
1461                  * the length of this PA can be either 6 bytes or 8 bytes.
1462                  */
1463                 if (len != 6 && len != 8) {
1464                     ND_PRINT((ndo, "invalid len"));
1465                     break;
1466                 }
1467                 ND_TCHECK2(tptr[0], len);
1468                 if (len == 6) {
1469                     ND_PRINT((ndo, " AS #%s, origin %s",
1470                         as_printf(ndo, astostr, sizeof(astostr), EXTRACT_16BITS(tptr)),
1471                         ipaddr_string(ndo, tptr + 2)));
1472                 } else {
1473                     ND_PRINT((ndo, " AS #%s, origin %s",
1474                         as_printf(ndo, astostr, sizeof(astostr),
1475                         EXTRACT_32BITS(tptr)), ipaddr_string(ndo, tptr + 4)));
1476                 }
1477                 break;
1478         case BGPTYPE_AGGREGATOR4:
1479                 if (len != 8) {
1480                         ND_PRINT((ndo, "invalid len"));
1481                         break;
1482                 }
1483                 ND_TCHECK2(tptr[0], 8);
1484                 ND_PRINT((ndo, " AS #%s, origin %s",
1485                     as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)),
1486                     ipaddr_string(ndo, tptr + 4)));
1487                 break;
1488         case BGPTYPE_COMMUNITIES:
1489                 if (len % 4) {
1490                         ND_PRINT((ndo, "invalid len"));
1491                         break;
1492                 }
1493                 while (tlen>0) {
1494                         uint32_t comm;
1495                         ND_TCHECK2(tptr[0], 4);
1496                         comm = EXTRACT_32BITS(tptr);
1497                         switch (comm) {
1498                         case BGP_COMMUNITY_NO_EXPORT:
1499                                 ND_PRINT((ndo, " NO_EXPORT"));
1500                                 break;
1501                         case BGP_COMMUNITY_NO_ADVERT:
1502                                 ND_PRINT((ndo, " NO_ADVERTISE"));
1503                                 break;
1504                         case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
1505                                 ND_PRINT((ndo, " NO_EXPORT_SUBCONFED"));
1506                                 break;
1507                         default:
1508                                 ND_PRINT((ndo, "%u:%u%s",
1509                                        (comm >> 16) & 0xffff,
1510                                        comm & 0xffff,
1511                                        (tlen>4) ? ", " : ""));
1512                                 break;
1513                         }
1514                         tlen -=4;
1515                         tptr +=4;
1516                 }
1517                 break;
1518         case BGPTYPE_ORIGINATOR_ID:
1519                 if (len != 4) {
1520                         ND_PRINT((ndo, "invalid len"));
1521                         break;
1522                 }
1523                 ND_TCHECK2(tptr[0], 4);
1524                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
1525                 break;
1526         case BGPTYPE_CLUSTER_LIST:
1527                 if (len % 4) {
1528                         ND_PRINT((ndo, "invalid len"));
1529                         break;
1530                 }
1531                 while (tlen>0) {
1532                         ND_TCHECK2(tptr[0], 4);
1533                         ND_PRINT((ndo, "%s%s",
1534                                ipaddr_string(ndo, tptr),
1535                                 (tlen>4) ? ", " : ""));
1536                         tlen -=4;
1537                         tptr +=4;
1538                 }
1539                 break;
1540         case BGPTYPE_MP_REACH_NLRI:
1541                 ND_TCHECK2(tptr[0], 3);
1542                 af = EXTRACT_16BITS(tptr);
1543                 safi = tptr[2];
1544
1545                 ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1546                        tok2str(af_values, "Unknown AFI", af),
1547                        af,
1548                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1549                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
1550                        safi));
1551
1552                 switch(af<<8 | safi) {
1553                 case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1554                 case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1555                 case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1556                 case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1557                 case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1558                 case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1559                 case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1560                 case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1561                 case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1562                 case (AFNUM_INET<<8 | SAFNUM_MDT):
1563                 case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1564                 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1565                 case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1566                 case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1567                 case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1568                 case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1569                 case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1570                 case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1571                 case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1572                 case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1573                 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1574                 case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1575                 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1576                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1577                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1578                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1579                 case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1580                     break;
1581                 default:
1582                     ND_TCHECK2(tptr[0], tlen);
1583                     ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
1584                     if (ndo->ndo_vflag <= 1)
1585                         print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1586                     goto done;
1587                     break;
1588                 }
1589
1590                 tptr +=3;
1591
1592                 ND_TCHECK(tptr[0]);
1593                 nhlen = tptr[0];
1594                 tlen = nhlen;
1595                 tptr++;
1596
1597                 if (tlen) {
1598                     int nnh = 0;
1599                     ND_PRINT((ndo, "\n\t    nexthop: "));
1600                     while (tlen > 0) {
1601                         if ( nnh++ > 0 ) {
1602                             ND_PRINT((ndo,  ", " ));
1603                         }
1604                         switch(af<<8 | safi) {
1605                         case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1606                         case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1607                         case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1608                         case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1609                         case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1610                         case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1611                         case (AFNUM_INET<<8 | SAFNUM_MDT):
1612                             if (tlen < (int)sizeof(struct in_addr)) {
1613                                 ND_PRINT((ndo, "invalid len"));
1614                                 tlen = 0;
1615                             } else {
1616                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr));
1617                                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
1618                                 tlen -= sizeof(struct in_addr);
1619                                 tptr += sizeof(struct in_addr);
1620                             }
1621                             break;
1622                         case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1623                         case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1624                         case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1625                             if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
1626                                 ND_PRINT((ndo, "invalid len"));
1627                                 tlen = 0;
1628                             } else {
1629                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1630                                 ND_PRINT((ndo, "RD: %s, %s",
1631                                        bgp_vpn_rd_print(ndo, tptr),
1632                                        ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN)));
1633                                 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1634                                 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1635                             }
1636                             break;
1637                         case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1638                         case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1639                         case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1640                         case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1641                             if (tlen < (int)sizeof(struct in6_addr)) {
1642                                 ND_PRINT((ndo, "invalid len"));
1643                                 tlen = 0;
1644                             } else {
1645                                 ND_TCHECK2(tptr[0], sizeof(struct in6_addr));
1646                                 ND_PRINT((ndo, "%s", ip6addr_string(ndo, tptr)));
1647                                 tlen -= sizeof(struct in6_addr);
1648                                 tptr += sizeof(struct in6_addr);
1649                             }
1650                             break;
1651                         case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1652                         case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1653                         case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1654                             if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1655                                 ND_PRINT((ndo, "invalid len"));
1656                                 tlen = 0;
1657                             } else {
1658                                 ND_TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1659                                 ND_PRINT((ndo, "RD: %s, %s",
1660                                        bgp_vpn_rd_print(ndo, tptr),
1661                                        ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN)));
1662                                 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1663                                 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1664                             }
1665                             break;
1666                         case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1667                         case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1668                         case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1669                         case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1670                             if (tlen < (int)sizeof(struct in_addr)) {
1671                                 ND_PRINT((ndo, "invalid len"));
1672                                 tlen = 0;
1673                             } else {
1674                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr));
1675                                 ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
1676                                 tlen -= (sizeof(struct in_addr));
1677                                 tptr += (sizeof(struct in_addr));
1678                             }
1679                             break;
1680                         case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1681                         case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1682                         case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1683                             ND_TCHECK2(tptr[0], tlen);
1684                             ND_PRINT((ndo, "%s", isonsap_string(ndo, tptr, tlen)));
1685                             tptr += tlen;
1686                             tlen = 0;
1687                             break;
1688
1689                         case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1690                         case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1691                         case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1692                             if (tlen < BGP_VPN_RD_LEN+1) {
1693                                 ND_PRINT((ndo, "invalid len"));
1694                                 tlen = 0;
1695                             } else {
1696                                 ND_TCHECK2(tptr[0], tlen);
1697                                 ND_PRINT((ndo, "RD: %s, %s",
1698                                        bgp_vpn_rd_print(ndo, tptr),
1699                                        isonsap_string(ndo, tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN)));
1700                                 /* rfc986 mapped IPv4 address ? */
1701                                 if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) ==  0x47000601)
1702                                     ND_PRINT((ndo, " = %s", ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN+4)));
1703                                 /* rfc1888 mapped IPv6 address ? */
1704                                 else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) ==  0x350000)
1705                                     ND_PRINT((ndo, " = %s", ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN+3)));
1706                                 tptr += tlen;
1707                                 tlen = 0;
1708                             }
1709                             break;
1710                         default:
1711                             ND_TCHECK2(tptr[0], tlen);
1712                             ND_PRINT((ndo, "no AFI %u/SAFI %u decoder", af, safi));
1713                             if (ndo->ndo_vflag <= 1)
1714                                 print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1715                             tptr += tlen;
1716                             tlen = 0;
1717                             goto done;
1718                             break;
1719                         }
1720                     }
1721                 }
1722                 ND_PRINT((ndo, ", nh-length: %u", nhlen));
1723                 tptr += tlen;
1724
1725                 ND_TCHECK(tptr[0]);
1726                 snpa = tptr[0];
1727                 tptr++;
1728
1729                 if (snpa) {
1730                         ND_PRINT((ndo, "\n\t    %u SNPA", snpa));
1731                         for (/*nothing*/; snpa > 0; snpa--) {
1732                                 ND_TCHECK(tptr[0]);
1733                                 ND_PRINT((ndo, "\n\t      %d bytes", tptr[0]));
1734                                 tptr += tptr[0] + 1;
1735                         }
1736                 } else {
1737                         ND_PRINT((ndo, ", no SNPA"));
1738                 }
1739
1740                 while (tptr < pptr + len) {
1741                     switch (af<<8 | safi) {
1742                     case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1743                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1744                     case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1745                         advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
1746                         if (advance == -1)
1747                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1748                         else if (advance == -2)
1749                             goto trunc;
1750                         else if (advance == -3)
1751                             break; /* bytes left, but not enough */
1752                         else
1753                             ND_PRINT((ndo, "\n\t      %s", buf));
1754                         break;
1755                     case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1756                         advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
1757                         if (advance == -1)
1758                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1759                         else if (advance == -2)
1760                             goto trunc;
1761                         else if (advance == -3)
1762                             break; /* bytes left, but not enough */
1763                         else
1764                             ND_PRINT((ndo, "\n\t      %s", buf));
1765                         break;
1766                     case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1767                     case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1768                     case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1769                         advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
1770                         if (advance == -1)
1771                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1772                         else if (advance == -2)
1773                             goto trunc;
1774                         else
1775                             ND_PRINT((ndo, "\n\t      %s", buf));
1776                         break;
1777                     case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1778                         advance = decode_rt_routing_info(ndo, tptr, buf, sizeof(buf));
1779                         if (advance == -1)
1780                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1781                         else if (advance == -2)
1782                             goto trunc;
1783                         else
1784                             ND_PRINT((ndo, "\n\t      %s", buf));
1785                         break;
1786                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
1787                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
1788                         advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
1789                         if (advance == -1)
1790                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1791                         else if (advance == -2)
1792                             goto trunc;
1793                         else
1794                             ND_PRINT((ndo, "\n\t      %s", buf));
1795                         break;
1796
1797                     case (AFNUM_INET<<8 | SAFNUM_MDT):
1798                       advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
1799                       if (advance == -1)
1800                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1801                         else if (advance == -2)
1802                             goto trunc;
1803                         else
1804                             ND_PRINT((ndo, "\n\t      %s", buf));
1805                        break;
1806                     case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1807                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1808                     case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1809                         advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
1810                         if (advance == -1)
1811                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1812                         else if (advance == -2)
1813                             goto trunc;
1814                         else if (advance == -3)
1815                             break; /* bytes left, but not enough */
1816                         else
1817                             ND_PRINT((ndo, "\n\t      %s", buf));
1818                         break;
1819                     case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1820                         advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
1821                         if (advance == -1)
1822                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1823                         else if (advance == -2)
1824                             goto trunc;
1825                         else if (advance == -3)
1826                             break; /* bytes left, but not enough */
1827                         else
1828                             ND_PRINT((ndo, "\n\t      %s", buf));
1829                         break;
1830                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1831                     case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1832                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1833                         advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
1834                         if (advance == -1)
1835                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1836                         else if (advance == -2)
1837                             goto trunc;
1838                         else
1839                             ND_PRINT((ndo, "\n\t      %s", buf));
1840                         break;
1841                     case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1842                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1843                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1844                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1845                         advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
1846                         if (advance == -1)
1847                             ND_PRINT((ndo, "\n\t    (illegal length)"));
1848                         else if (advance == -2)
1849                             goto trunc;
1850                         else
1851                             ND_PRINT((ndo, "\n\t      %s", buf));
1852                         break;
1853                     case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1854                     case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1855                     case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1856                         advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1857                         if (advance == -1)
1858                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1859                         else if (advance == -2)
1860                             goto trunc;
1861                         else
1862                             ND_PRINT((ndo, "\n\t      %s", buf));
1863                         break;
1864                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1865                     case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1866                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1867                         advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1868                         if (advance == -1)
1869                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1870                         else if (advance == -2)
1871                             goto trunc;
1872                         else
1873                             ND_PRINT((ndo, "\n\t      %s", buf));
1874                         break;
1875                     default:
1876                         ND_TCHECK2(*tptr,tlen);
1877                         ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
1878                         if (ndo->ndo_vflag <= 1)
1879                             print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1880                         advance = 0;
1881                         tptr = pptr + len;
1882                         break;
1883                     }
1884                     if (advance < 0)
1885                         break;
1886                     tptr += advance;
1887                 }
1888         done:
1889                 break;
1890
1891         case BGPTYPE_MP_UNREACH_NLRI:
1892                 ND_TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE);
1893                 af = EXTRACT_16BITS(tptr);
1894                 safi = tptr[2];
1895
1896                 ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1897                        tok2str(af_values, "Unknown AFI", af),
1898                        af,
1899                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1900                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
1901                        safi));
1902
1903                 if (len == BGP_MP_NLRI_MINSIZE)
1904                     ND_PRINT((ndo, "\n\t      End-of-Rib Marker (empty NLRI)"));
1905
1906                 tptr += 3;
1907
1908                 while (tptr < pptr + len) {
1909                     switch (af<<8 | safi) {
1910                     case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1911                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1912                     case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1913                         advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
1914                         if (advance == -1)
1915                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1916                         else if (advance == -2)
1917                             goto trunc;
1918                         else if (advance == -3)
1919                             break; /* bytes left, but not enough */
1920                         else
1921                             ND_PRINT((ndo, "\n\t      %s", buf));
1922                         break;
1923                     case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1924                         advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
1925                         if (advance == -1)
1926                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1927                         else if (advance == -2)
1928                             goto trunc;
1929                         else if (advance == -3)
1930                             break; /* bytes left, but not enough */
1931                         else
1932                             ND_PRINT((ndo, "\n\t      %s", buf));
1933                         break;
1934                     case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1935                     case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1936                     case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1937                         advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
1938                         if (advance == -1)
1939                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1940                         else if (advance == -2)
1941                             goto trunc;
1942                         else
1943                             ND_PRINT((ndo, "\n\t      %s", buf));
1944                         break;
1945                     case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1946                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1947                     case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1948                         advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
1949                         if (advance == -1)
1950                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1951                         else if (advance == -2)
1952                             goto trunc;
1953                         else if (advance == -3)
1954                             break; /* bytes left, but not enough */
1955                         else
1956                             ND_PRINT((ndo, "\n\t      %s", buf));
1957                         break;
1958                     case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1959                         advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
1960                         if (advance == -1)
1961                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1962                         else if (advance == -2)
1963                             goto trunc;
1964                         else if (advance == -3)
1965                             break; /* bytes left, but not enough */
1966                         else
1967                             ND_PRINT((ndo, "\n\t      %s", buf));
1968                         break;
1969                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1970                     case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1971                     case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1972                         advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
1973                         if (advance == -1)
1974                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1975                         else if (advance == -2)
1976                             goto trunc;
1977                         else
1978                             ND_PRINT((ndo, "\n\t      %s", buf));
1979                         break;
1980                     case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1981                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1982                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1983                     case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1984                         advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
1985                         if (advance == -1)
1986                             ND_PRINT((ndo, "\n\t    (illegal length)"));
1987                         else if (advance == -2)
1988                             goto trunc;
1989                         else
1990                             ND_PRINT((ndo, "\n\t      %s", buf));
1991                         break;
1992                     case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1993                     case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1994                     case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1995                         advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1996                         if (advance == -1)
1997                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1998                         else if (advance == -2)
1999                             goto trunc;
2000                         else
2001                             ND_PRINT((ndo, "\n\t      %s", buf));
2002                         break;
2003                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
2004                     case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
2005                     case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
2006                         advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
2007                         if (advance == -1)
2008                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2009                         else if (advance == -2)
2010                             goto trunc;
2011                         else
2012                             ND_PRINT((ndo, "\n\t      %s", buf));
2013                         break;
2014                     case (AFNUM_INET<<8 | SAFNUM_MDT):
2015                       advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
2016                       if (advance == -1)
2017                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2018                         else if (advance == -2)
2019                             goto trunc;
2020                         else
2021                             ND_PRINT((ndo, "\n\t      %s", buf));
2022                        break;
2023                     case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
2024                     case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
2025                         advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
2026                         if (advance == -1)
2027                             ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2028                         else if (advance == -2)
2029                             goto trunc;
2030                         else
2031                             ND_PRINT((ndo, "\n\t      %s", buf));
2032                         break;
2033                     default:
2034                         ND_TCHECK2(*(tptr-3),tlen);
2035                         ND_PRINT((ndo, "no AFI %u / SAFI %u decoder", af, safi));
2036                         if (ndo->ndo_vflag <= 1)
2037                             print_unknown_data(ndo, tptr-3, "\n\t    ", tlen);
2038                         advance = 0;
2039                         tptr = pptr + len;
2040                         break;
2041                     }
2042                     if (advance < 0)
2043                         break;
2044                     tptr += advance;
2045                 }
2046                 break;
2047         case BGPTYPE_EXTD_COMMUNITIES:
2048                 if (len % 8) {
2049                         ND_PRINT((ndo, "invalid len"));
2050                         break;
2051                 }
2052                 while (tlen>0) {
2053                     uint16_t extd_comm;
2054
2055                     ND_TCHECK2(tptr[0], 2);
2056                     extd_comm=EXTRACT_16BITS(tptr);
2057
2058                     ND_PRINT((ndo, "\n\t    %s (0x%04x), Flags [%s]",
2059                            tok2str(bgp_extd_comm_subtype_values,
2060                                       "unknown extd community typecode",
2061                                       extd_comm),
2062                            extd_comm,
2063                            bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
2064
2065                     ND_TCHECK2(*(tptr+2), 6);
2066                     switch(extd_comm) {
2067                     case BGP_EXT_COM_RT_0:
2068                     case BGP_EXT_COM_RO_0:
2069                     case BGP_EXT_COM_L2VPN_RT_0:
2070                         ND_PRINT((ndo, ": %u:%u (= %s)",
2071                                EXTRACT_16BITS(tptr+2),
2072                                EXTRACT_32BITS(tptr+4),
2073                                ipaddr_string(ndo, tptr+4)));
2074                         break;
2075                     case BGP_EXT_COM_RT_1:
2076                     case BGP_EXT_COM_RO_1:
2077                     case BGP_EXT_COM_L2VPN_RT_1:
2078                     case BGP_EXT_COM_VRF_RT_IMP:
2079                         ND_PRINT((ndo, ": %s:%u",
2080                                ipaddr_string(ndo, tptr+2),
2081                                EXTRACT_16BITS(tptr+6)));
2082                         break;
2083                     case BGP_EXT_COM_RT_2:
2084                     case BGP_EXT_COM_RO_2:
2085                         ND_PRINT((ndo, ": %s:%u",
2086                             as_printf(ndo, astostr, sizeof(astostr),
2087                             EXTRACT_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6)));
2088                         break;
2089                     case BGP_EXT_COM_LINKBAND:
2090                         bw.i = EXTRACT_32BITS(tptr+2);
2091                         ND_PRINT((ndo, ": bandwidth: %.3f Mbps",
2092                                bw.f*8/1000000));
2093                         break;
2094                     case BGP_EXT_COM_VPN_ORIGIN:
2095                     case BGP_EXT_COM_VPN_ORIGIN2:
2096                     case BGP_EXT_COM_VPN_ORIGIN3:
2097                     case BGP_EXT_COM_VPN_ORIGIN4:
2098                     case BGP_EXT_COM_OSPF_RID:
2099                     case BGP_EXT_COM_OSPF_RID2:
2100                         ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr+2)));
2101                         break;
2102                     case BGP_EXT_COM_OSPF_RTYPE:
2103                     case BGP_EXT_COM_OSPF_RTYPE2:
2104                         ND_PRINT((ndo, ": area:%s, router-type:%s, metric-type:%s%s",
2105                                ipaddr_string(ndo, tptr+2),
2106                                tok2str(bgp_extd_comm_ospf_rtype_values,
2107                                           "unknown (0x%02x)",
2108                                           *(tptr+6)),
2109                                (*(tptr+7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
2110                                ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""));
2111                         break;
2112                     case BGP_EXT_COM_L2INFO:
2113                         ND_PRINT((ndo, ": %s Control Flags [0x%02x]:MTU %u",
2114                                tok2str(l2vpn_encaps_values,
2115                                           "unknown encaps",
2116                                           *(tptr+2)),
2117                                        *(tptr+3),
2118                                EXTRACT_16BITS(tptr+4)));
2119                         break;
2120                     case BGP_EXT_COM_SOURCE_AS:
2121                         ND_PRINT((ndo, ": AS %u", EXTRACT_16BITS(tptr+2)));
2122                         break;
2123                     default:
2124                         ND_TCHECK2(*tptr,8);
2125                         print_unknown_data(ndo, tptr, "\n\t      ", 8);
2126                         break;
2127                     }
2128                     tlen -=8;
2129                     tptr +=8;
2130                 }
2131                 break;
2132
2133         case BGPTYPE_PMSI_TUNNEL:
2134         {
2135                 uint8_t tunnel_type, flags;
2136
2137                 ND_TCHECK2(tptr[0], 5);
2138                 tunnel_type = *(tptr+1);
2139                 flags = *tptr;
2140                 tlen = len;
2141
2142                 ND_PRINT((ndo, "\n\t    Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
2143                        tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
2144                        tunnel_type,
2145                        bittok2str(bgp_pmsi_flag_values, "none", flags),
2146                        EXTRACT_24BITS(tptr+2)>>4));
2147
2148                 tptr +=5;
2149                 tlen -= 5;
2150
2151                 switch (tunnel_type) {
2152                 case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
2153                 case BGP_PMSI_TUNNEL_PIM_BIDIR:
2154                     ND_TCHECK2(tptr[0], 8);
2155                     ND_PRINT((ndo, "\n\t      Sender %s, P-Group %s",
2156                            ipaddr_string(ndo, tptr),
2157                            ipaddr_string(ndo, tptr+4)));
2158                     break;
2159
2160                 case BGP_PMSI_TUNNEL_PIM_SSM:
2161                     ND_TCHECK2(tptr[0], 8);
2162                     ND_PRINT((ndo, "\n\t      Root-Node %s, P-Group %s",
2163                            ipaddr_string(ndo, tptr),
2164                            ipaddr_string(ndo, tptr+4)));
2165                     break;
2166                 case BGP_PMSI_TUNNEL_INGRESS:
2167                     ND_TCHECK2(tptr[0], 4);
2168                     ND_PRINT((ndo, "\n\t      Tunnel-Endpoint %s",
2169                            ipaddr_string(ndo, tptr)));
2170                     break;
2171                 case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
2172                 case BGP_PMSI_TUNNEL_LDP_MP2MP:
2173                     ND_TCHECK2(tptr[0], 8);
2174                     ND_PRINT((ndo, "\n\t      Root-Node %s, LSP-ID 0x%08x",
2175                            ipaddr_string(ndo, tptr),
2176                            EXTRACT_32BITS(tptr+4)));
2177                     break;
2178                 case BGP_PMSI_TUNNEL_RSVP_P2MP:
2179                     ND_TCHECK2(tptr[0], 8);
2180                     ND_PRINT((ndo, "\n\t      Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
2181                            ipaddr_string(ndo, tptr),
2182                            EXTRACT_32BITS(tptr+4)));
2183                     break;
2184                 default:
2185                     if (ndo->ndo_vflag <= 1) {
2186                         print_unknown_data(ndo, tptr, "\n\t      ", tlen);
2187                     }
2188                 }
2189                 break;
2190         }
2191         case BGPTYPE_AIGP:
2192         {
2193                 uint8_t type;
2194                 uint16_t length;
2195
2196                 tlen = len;
2197
2198                 while (tlen >= 3) {
2199
2200                     ND_TCHECK2(tptr[0], 3);
2201
2202                     type = *tptr;
2203                     length = EXTRACT_16BITS(tptr+1);
2204                     tptr += 3;
2205                     tlen -= 3;
2206
2207                     ND_PRINT((ndo, "\n\t    %s TLV (%u), length %u",
2208                               tok2str(bgp_aigp_values, "Unknown", type),
2209                               type, length));
2210
2211                     if (length < 3)
2212                         goto trunc;
2213                     length -= 3;
2214
2215                     /*
2216                      * Check if we can read the TLV data.
2217                      */
2218                     ND_TCHECK2(tptr[3], length);
2219
2220                     switch (type) {
2221
2222                     case BGP_AIGP_TLV:
2223                         if (length < 8)
2224                             goto trunc;
2225                         ND_PRINT((ndo, ", metric %" PRIu64,
2226                                   EXTRACT_64BITS(tptr)));
2227                         break;
2228
2229                     default:
2230                         if (ndo->ndo_vflag <= 1) {
2231                             print_unknown_data(ndo, tptr,"\n\t      ", length);
2232                         }
2233                     }
2234
2235                     tptr += length;
2236                     tlen -= length;
2237                 }
2238                 break;
2239         }
2240         case BGPTYPE_ATTR_SET:
2241                 ND_TCHECK2(tptr[0], 4);
2242                 if (len < 4)
2243                         goto trunc;
2244                 ND_PRINT((ndo, "\n\t    Origin AS: %s",
2245                     as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr))));
2246                 tptr+=4;
2247                 len -=4;
2248
2249                 while (len) {
2250                     u_int aflags, alenlen, alen;
2251
2252                     ND_TCHECK2(tptr[0], 2);
2253                     if (len < 2)
2254                         goto trunc;
2255                     aflags = *tptr;
2256                     atype = *(tptr + 1);
2257                     tptr += 2;
2258                     len -= 2;
2259                     alenlen = bgp_attr_lenlen(aflags, tptr);
2260                     ND_TCHECK2(tptr[0], alenlen);
2261                     if (len < alenlen)
2262                         goto trunc;
2263                     alen = bgp_attr_len(aflags, tptr);
2264                     tptr += alenlen;
2265                     len -= alenlen;
2266
2267                     ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
2268                            tok2str(bgp_attr_values,
2269                                       "Unknown Attribute", atype),
2270                            atype,
2271                            alen));
2272
2273                     if (aflags) {
2274                         ND_PRINT((ndo, ", Flags [%s%s%s%s",
2275                                aflags & 0x80 ? "O" : "",
2276                                aflags & 0x40 ? "T" : "",
2277                                aflags & 0x20 ? "P" : "",
2278                                aflags & 0x10 ? "E" : ""));
2279                         if (aflags & 0xf)
2280                             ND_PRINT((ndo, "+%x", aflags & 0xf));
2281                         ND_PRINT((ndo, "]: "));
2282                     }
2283                     /* FIXME check for recursion */
2284                     if (!bgp_attr_print(ndo, atype, tptr, alen))
2285                         return 0;
2286                     tptr += alen;
2287                     len -= alen;
2288                 }
2289                 break;
2290
2291         case BGPTYPE_LARGE_COMMUNITY:
2292                 if (len == 0 || len % 12) {
2293                         ND_PRINT((ndo, "invalid len"));
2294                         break;
2295                 }
2296                 ND_PRINT((ndo, "\n\t    "));
2297                 while (len > 0) {
2298                         ND_TCHECK2(*tptr, 12);
2299                         ND_PRINT((ndo, "%u:%u:%u%s",
2300                                  EXTRACT_32BITS(tptr),
2301                                  EXTRACT_32BITS(tptr + 4),
2302                                  EXTRACT_32BITS(tptr + 8),
2303                                  (len > 12) ? ", " : ""));
2304                         tptr += 12;
2305                         len -= 12;
2306                 }
2307                 break;
2308         default:
2309             ND_TCHECK2(*pptr,len);
2310             ND_PRINT((ndo, "\n\t    no Attribute %u decoder", atype)); /* we have no decoder for the attribute */
2311             if (ndo->ndo_vflag <= 1)
2312                 print_unknown_data(ndo, pptr, "\n\t    ", len);
2313             break;
2314         }
2315         if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/
2316             ND_TCHECK2(*pptr,len);
2317             print_unknown_data(ndo, pptr, "\n\t    ", len);
2318         }
2319         return 1;
2320
2321 trunc:
2322         return 0;
2323 }
2324
2325 static void
2326 bgp_capabilities_print(netdissect_options *ndo,
2327                        const u_char *opt, int caps_len)
2328 {
2329         int cap_type, cap_len, tcap_len, cap_offset;
2330         int i = 0;
2331
2332         while (i < caps_len) {
2333                 ND_TCHECK2(opt[i], BGP_CAP_HEADER_SIZE);
2334                 cap_type=opt[i];
2335                 cap_len=opt[i+1];
2336                 tcap_len=cap_len;
2337                 ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
2338                        tok2str(bgp_capcode_values, "Unknown",
2339                                   cap_type),
2340                        cap_type,
2341                        cap_len));
2342                 ND_TCHECK2(opt[i+2], cap_len);
2343                 switch (cap_type) {
2344                 case BGP_CAPCODE_MP:
2345                     ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u)",
2346                            tok2str(af_values, "Unknown",
2347                                       EXTRACT_16BITS(opt+i+2)),
2348                            EXTRACT_16BITS(opt+i+2),
2349                            tok2str(bgp_safi_values, "Unknown",
2350                                       opt[i+5]),
2351                            opt[i+5]));
2352                     break;
2353                 case BGP_CAPCODE_RESTART:
2354                     ND_PRINT((ndo, "\n\t\tRestart Flags: [%s], Restart Time %us",
2355                            ((opt[i+2])&0x80) ? "R" : "none",
2356                            EXTRACT_16BITS(opt+i+2)&0xfff));
2357                     tcap_len-=2;
2358                     cap_offset=4;
2359                     while(tcap_len>=4) {
2360                         ND_PRINT((ndo, "\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
2361                                tok2str(af_values,"Unknown",
2362                                           EXTRACT_16BITS(opt+i+cap_offset)),
2363                                EXTRACT_16BITS(opt+i+cap_offset),
2364                                tok2str(bgp_safi_values,"Unknown",
2365                                           opt[i+cap_offset+2]),
2366                                opt[i+cap_offset+2],
2367                                ((opt[i+cap_offset+3])&0x80) ? "yes" : "no" ));
2368                         tcap_len-=4;
2369                         cap_offset+=4;
2370                     }
2371                     break;
2372                 case BGP_CAPCODE_RR:
2373                 case BGP_CAPCODE_RR_CISCO:
2374                     break;
2375                 case BGP_CAPCODE_AS_NEW:
2376
2377                     /*
2378                      * Extract the 4 byte AS number encoded.
2379                      */
2380                     if (cap_len == 4) {
2381                         ND_PRINT((ndo, "\n\t\t 4 Byte AS %s",
2382                             as_printf(ndo, astostr, sizeof(astostr),
2383                             EXTRACT_32BITS(opt + i + 2))));
2384                     }
2385                     break;
2386                 case BGP_CAPCODE_ADD_PATH:
2387                     cap_offset=2;
2388                     if (tcap_len == 0) {
2389                         ND_PRINT((ndo, " (bogus)")); /* length */
2390                         break;
2391                     }
2392                     while (tcap_len > 0) {
2393                         if (tcap_len < 4) {
2394                             ND_PRINT((ndo, "\n\t\t(invalid)"));
2395                             break;
2396                         }
2397                         ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
2398                                   tok2str(af_values,"Unknown",EXTRACT_16BITS(opt+i+cap_offset)),
2399                                   EXTRACT_16BITS(opt+i+cap_offset),
2400                                   tok2str(bgp_safi_values,"Unknown",opt[i+cap_offset+2]),
2401                                   opt[i+cap_offset+2],
2402                                   tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",opt[i+cap_offset+3])
2403                         ));
2404                         tcap_len-=4;
2405                         cap_offset+=4;
2406                     }
2407                     break;
2408                 default:
2409                     ND_PRINT((ndo, "\n\t\tno decoder for Capability %u",
2410                            cap_type));
2411                     if (ndo->ndo_vflag <= 1)
2412                         print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
2413                     break;
2414                 }
2415                 if (ndo->ndo_vflag > 1 && cap_len > 0) {
2416                     print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
2417                 }
2418                 i += BGP_CAP_HEADER_SIZE + cap_len;
2419         }
2420         return;
2421
2422 trunc:
2423         ND_PRINT((ndo, "[|BGP]"));
2424 }
2425
2426 static void
2427 bgp_open_print(netdissect_options *ndo,
2428                const u_char *dat, int length)
2429 {
2430         struct bgp_open bgpo;
2431         struct bgp_opt bgpopt;
2432         const u_char *opt;
2433         int i;
2434
2435         ND_TCHECK2(dat[0], BGP_OPEN_SIZE);
2436         memcpy(&bgpo, dat, BGP_OPEN_SIZE);
2437
2438         ND_PRINT((ndo, "\n\t  Version %d, ", bgpo.bgpo_version));
2439         ND_PRINT((ndo, "my AS %s, ",
2440             as_printf(ndo, astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas))));
2441         ND_PRINT((ndo, "Holdtime %us, ", ntohs(bgpo.bgpo_holdtime)));
2442         ND_PRINT((ndo, "ID %s", ipaddr_string(ndo, &bgpo.bgpo_id)));
2443         ND_PRINT((ndo, "\n\t  Optional parameters, length: %u", bgpo.bgpo_optlen));
2444
2445         /* some little sanity checking */
2446         if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
2447             return;
2448
2449         /* ugly! */
2450         opt = &((const struct bgp_open *)dat)->bgpo_optlen;
2451         opt++;
2452
2453         i = 0;
2454         while (i < bgpo.bgpo_optlen) {
2455                 ND_TCHECK2(opt[i], BGP_OPT_SIZE);
2456                 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
2457                 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
2458                         ND_PRINT((ndo, "\n\t     Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len));
2459                         break;
2460                 }
2461
2462                 ND_PRINT((ndo, "\n\t    Option %s (%u), length: %u",
2463                        tok2str(bgp_opt_values,"Unknown",
2464                                   bgpopt.bgpopt_type),
2465                        bgpopt.bgpopt_type,
2466                        bgpopt.bgpopt_len));
2467
2468                 /* now let's decode the options we know*/
2469                 switch(bgpopt.bgpopt_type) {
2470
2471                 case BGP_OPT_CAP:
2472                         bgp_capabilities_print(ndo, &opt[i+BGP_OPT_SIZE],
2473                             bgpopt.bgpopt_len);
2474                         break;
2475
2476                 case BGP_OPT_AUTH:
2477                 default:
2478                        ND_PRINT((ndo, "\n\t      no decoder for option %u",
2479                            bgpopt.bgpopt_type));
2480                        break;
2481                 }
2482                 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
2483         }
2484         return;
2485 trunc:
2486         ND_PRINT((ndo, "[|BGP]"));
2487 }
2488
2489 static void
2490 bgp_update_print(netdissect_options *ndo,
2491                  const u_char *dat, int length)
2492 {
2493         struct bgp bgp;
2494         const u_char *p;
2495         int withdrawn_routes_len;
2496         int len;
2497         int i;
2498
2499         ND_TCHECK2(dat[0], BGP_SIZE);
2500         if (length < BGP_SIZE)
2501                 goto trunc;
2502         memcpy(&bgp, dat, BGP_SIZE);
2503         p = dat + BGP_SIZE;     /*XXX*/
2504         length -= BGP_SIZE;
2505
2506         /* Unfeasible routes */
2507         ND_TCHECK2(p[0], 2);
2508         if (length < 2)
2509                 goto trunc;
2510         withdrawn_routes_len = EXTRACT_16BITS(p);
2511         p += 2;
2512         length -= 2;
2513         if (withdrawn_routes_len) {
2514                 /*
2515                  * Without keeping state from the original NLRI message,
2516                  * it's not possible to tell if this a v4 or v6 route,
2517                  * so only try to decode it if we're not v6 enabled.
2518                  */
2519                 ND_TCHECK2(p[0], withdrawn_routes_len);
2520                 if (length < withdrawn_routes_len)
2521                         goto trunc;
2522                 ND_PRINT((ndo, "\n\t  Withdrawn routes: %d bytes", withdrawn_routes_len));
2523                 p += withdrawn_routes_len;
2524                 length -= withdrawn_routes_len;
2525         }
2526
2527         ND_TCHECK2(p[0], 2);
2528         if (length < 2)
2529                 goto trunc;
2530         len = EXTRACT_16BITS(p);
2531         p += 2;
2532         length -= 2;
2533
2534         if (withdrawn_routes_len == 0 && len == 0 && length == 0) {
2535             /* No withdrawn routes, no path attributes, no NLRI */
2536             ND_PRINT((ndo, "\n\t  End-of-Rib Marker (empty NLRI)"));
2537             return;
2538         }
2539
2540         if (len) {
2541                 /* do something more useful!*/
2542                 while (len) {
2543                         int aflags, atype, alenlen, alen;
2544
2545                         ND_TCHECK2(p[0], 2);
2546                         if (len < 2)
2547                             goto trunc;
2548                         if (length < 2)
2549                             goto trunc;
2550                         aflags = *p;
2551                         atype = *(p + 1);
2552                         p += 2;
2553                         len -= 2;
2554                         length -= 2;
2555                         alenlen = bgp_attr_lenlen(aflags, p);
2556                         ND_TCHECK2(p[0], alenlen);
2557                         if (len < alenlen)
2558                             goto trunc;
2559                         if (length < alenlen)
2560                             goto trunc;
2561                         alen = bgp_attr_len(aflags, p);
2562                         p += alenlen;
2563                         len -= alenlen;
2564                         length -= alenlen;
2565
2566                         ND_PRINT((ndo, "\n\t  %s (%u), length: %u",
2567                               tok2str(bgp_attr_values, "Unknown Attribute",
2568                                          atype),
2569                               atype,
2570                               alen));
2571
2572                         if (aflags) {
2573                                 ND_PRINT((ndo, ", Flags [%s%s%s%s",
2574                                         aflags & 0x80 ? "O" : "",
2575                                         aflags & 0x40 ? "T" : "",
2576                                         aflags & 0x20 ? "P" : "",
2577                                         aflags & 0x10 ? "E" : ""));
2578                                 if (aflags & 0xf)
2579                                         ND_PRINT((ndo, "+%x", aflags & 0xf));
2580                                 ND_PRINT((ndo, "]: "));
2581                         }
2582                         if (len < alen)
2583                                 goto trunc;
2584                         if (length < alen)
2585                                 goto trunc;
2586                         if (!bgp_attr_print(ndo, atype, p, alen))
2587                                 goto trunc;
2588                         p += alen;
2589                         len -= alen;
2590                         length -= alen;
2591                 }
2592         }
2593
2594         if (length) {
2595                 /*
2596                  * XXX - what if they're using the "Advertisement of
2597                  * Multiple Paths in BGP" feature:
2598                  *
2599                  * https://datatracker.ietf.org/doc/draft-ietf-idr-add-paths/
2600                  *
2601                  * http://tools.ietf.org/html/draft-ietf-idr-add-paths-06
2602                  */
2603                 ND_PRINT((ndo, "\n\t  Updated routes:"));
2604                 while (length) {
2605                         char buf[MAXHOSTNAMELEN + 100];
2606                         i = decode_prefix4(ndo, p, length, buf, sizeof(buf));
2607                         if (i == -1) {
2608                                 ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2609                                 break;
2610                         } else if (i == -2)
2611                                 goto trunc;
2612                         else if (i == -3)
2613                                 goto trunc; /* bytes left, but not enough */
2614                         else {
2615                                 ND_PRINT((ndo, "\n\t    %s", buf));
2616                                 p += i;
2617                                 length -= i;
2618                         }
2619                 }
2620         }
2621         return;
2622 trunc:
2623         ND_PRINT((ndo, "[|BGP]"));
2624 }
2625
2626 static void
2627 bgp_notification_print(netdissect_options *ndo,
2628                        const u_char *dat, int length)
2629 {
2630         struct bgp_notification bgpn;
2631         const u_char *tptr;
2632
2633         ND_TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
2634         memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
2635
2636         /* some little sanity checking */
2637         if (length<BGP_NOTIFICATION_SIZE)
2638             return;
2639
2640         ND_PRINT((ndo, ", %s (%u)",
2641                tok2str(bgp_notify_major_values, "Unknown Error",
2642                           bgpn.bgpn_major),
2643                bgpn.bgpn_major));
2644
2645         switch (bgpn.bgpn_major) {
2646
2647         case BGP_NOTIFY_MAJOR_MSG:
2648             ND_PRINT((ndo, ", subcode %s (%u)",
2649                    tok2str(bgp_notify_minor_msg_values, "Unknown",
2650                               bgpn.bgpn_minor),
2651                    bgpn.bgpn_minor));
2652             break;
2653         case BGP_NOTIFY_MAJOR_OPEN:
2654             ND_PRINT((ndo, ", subcode %s (%u)",
2655                    tok2str(bgp_notify_minor_open_values, "Unknown",
2656                               bgpn.bgpn_minor),
2657                    bgpn.bgpn_minor));
2658             break;
2659         case BGP_NOTIFY_MAJOR_UPDATE:
2660             ND_PRINT((ndo, ", subcode %s (%u)",
2661                    tok2str(bgp_notify_minor_update_values, "Unknown",
2662                               bgpn.bgpn_minor),
2663                    bgpn.bgpn_minor));
2664             break;
2665         case BGP_NOTIFY_MAJOR_FSM:
2666             ND_PRINT((ndo, " subcode %s (%u)",
2667                    tok2str(bgp_notify_minor_fsm_values, "Unknown",
2668                               bgpn.bgpn_minor),
2669                    bgpn.bgpn_minor));
2670             break;
2671         case BGP_NOTIFY_MAJOR_CAP:
2672             ND_PRINT((ndo, " subcode %s (%u)",
2673                    tok2str(bgp_notify_minor_cap_values, "Unknown",
2674                               bgpn.bgpn_minor),
2675                    bgpn.bgpn_minor));
2676             break;
2677         case BGP_NOTIFY_MAJOR_CEASE:
2678             ND_PRINT((ndo, ", subcode %s (%u)",
2679                    tok2str(bgp_notify_minor_cease_values, "Unknown",
2680                               bgpn.bgpn_minor),
2681                    bgpn.bgpn_minor));
2682
2683             /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
2684              * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
2685              */
2686             if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
2687                 tptr = dat + BGP_NOTIFICATION_SIZE;
2688                 ND_TCHECK2(*tptr, 7);
2689                 ND_PRINT((ndo, ", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
2690                        tok2str(af_values, "Unknown",
2691                                   EXTRACT_16BITS(tptr)),
2692                        EXTRACT_16BITS(tptr),
2693                        tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
2694                        *(tptr+2),
2695                        EXTRACT_32BITS(tptr+3)));
2696             }
2697             break;
2698         default:
2699             break;
2700         }
2701
2702         return;
2703 trunc:
2704         ND_PRINT((ndo, "[|BGP]"));
2705 }
2706
2707 static void
2708 bgp_route_refresh_print(netdissect_options *ndo,
2709                         const u_char *pptr, int len)
2710 {
2711         const struct bgp_route_refresh *bgp_route_refresh_header;
2712
2713         ND_TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE);
2714
2715         /* some little sanity checking */
2716         if (len<BGP_ROUTE_REFRESH_SIZE)
2717             return;
2718
2719         bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
2720
2721         ND_PRINT((ndo, "\n\t  AFI %s (%u), SAFI %s (%u)",
2722                tok2str(af_values,"Unknown",
2723                           /* this stinks but the compiler pads the structure
2724                            * weird */
2725                           EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
2726                EXTRACT_16BITS(&bgp_route_refresh_header->afi),
2727                tok2str(bgp_safi_values,"Unknown",
2728                           bgp_route_refresh_header->safi),
2729                bgp_route_refresh_header->safi));
2730
2731         if (ndo->ndo_vflag > 1) {
2732             ND_TCHECK2(*pptr, len);
2733             print_unknown_data(ndo, pptr, "\n\t  ", len);
2734         }
2735
2736         return;
2737 trunc:
2738         ND_PRINT((ndo, "[|BGP]"));
2739 }
2740
2741 static int
2742 bgp_header_print(netdissect_options *ndo,
2743                  const u_char *dat, int length)
2744 {
2745         struct bgp bgp;
2746
2747         ND_TCHECK2(dat[0], BGP_SIZE);
2748         memcpy(&bgp, dat, BGP_SIZE);
2749         ND_PRINT((ndo, "\n\t%s Message (%u), length: %u",
2750                tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
2751                bgp.bgp_type,
2752                length));
2753
2754         switch (bgp.bgp_type) {
2755         case BGP_OPEN:
2756                 bgp_open_print(ndo, dat, length);
2757                 break;
2758         case BGP_UPDATE:
2759                 bgp_update_print(ndo, dat, length);
2760                 break;
2761         case BGP_NOTIFICATION:
2762                 bgp_notification_print(ndo, dat, length);
2763                 break;
2764         case BGP_KEEPALIVE:
2765                 break;
2766         case BGP_ROUTE_REFRESH:
2767                 bgp_route_refresh_print(ndo, dat, length);
2768                 break;
2769         default:
2770                 /* we have no decoder for the BGP message */
2771                 ND_TCHECK2(*dat, length);
2772                 ND_PRINT((ndo, "\n\t  no Message %u decoder", bgp.bgp_type));
2773                 print_unknown_data(ndo, dat, "\n\t  ", length);
2774                 break;
2775         }
2776         return 1;
2777 trunc:
2778         ND_PRINT((ndo, "[|BGP]"));
2779         return 0;
2780 }
2781
2782 void
2783 bgp_print(netdissect_options *ndo,
2784           const u_char *dat, int length)
2785 {
2786         const u_char *p;
2787         const u_char *ep;
2788         const u_char *start;
2789         const u_char marker[] = {
2790                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2791                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2792         };
2793         struct bgp bgp;
2794         uint16_t hlen;
2795
2796         ep = dat + length;
2797         if (ndo->ndo_snapend < dat + length)
2798                 ep = ndo->ndo_snapend;
2799
2800         ND_PRINT((ndo, ": BGP"));
2801
2802         if (ndo->ndo_vflag < 1) /* lets be less chatty */
2803                 return;
2804
2805         p = dat;
2806         start = p;
2807         while (p < ep) {
2808                 if (!ND_TTEST2(p[0], 1))
2809                         break;
2810                 if (p[0] != 0xff) {
2811                         p++;
2812                         continue;
2813                 }
2814
2815                 if (!ND_TTEST2(p[0], sizeof(marker)))
2816                         break;
2817                 if (memcmp(p, marker, sizeof(marker)) != 0) {
2818                         p++;
2819                         continue;
2820                 }
2821
2822                 /* found BGP header */
2823                 ND_TCHECK2(p[0], BGP_SIZE);     /*XXX*/
2824                 memcpy(&bgp, p, BGP_SIZE);
2825
2826                 if (start != p)
2827                         ND_PRINT((ndo, " [|BGP]"));
2828
2829                 hlen = ntohs(bgp.bgp_len);
2830                 if (hlen < BGP_SIZE) {
2831                         ND_PRINT((ndo, "\n[|BGP Bogus header length %u < %u]", hlen,
2832                             BGP_SIZE));
2833                         break;
2834                 }
2835
2836                 if (ND_TTEST2(p[0], hlen)) {
2837                         if (!bgp_header_print(ndo, p, hlen))
2838                                 return;
2839                         p += hlen;
2840                         start = p;
2841                 } else {
2842                         ND_PRINT((ndo, "\n[|BGP %s]",
2843                                tok2str(bgp_msg_values,
2844                                           "Unknown Message Type",
2845                                           bgp.bgp_type)));
2846                         break;
2847                 }
2848         }
2849
2850         return;
2851
2852 trunc:
2853         ND_PRINT((ndo, " [|BGP]"));
2854 }
2855
2856 /*
2857  * Local Variables:
2858  * c-style: whitesmith
2859  * c-basic-offset: 4
2860  * End:
2861  */