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