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