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