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