]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
Separate multiple nexthops.
[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 int nnh = 0;
1514 printf("\n\t nexthop: ");
1515 while (tlen > 0) {
1516 if ( nnh++ > 0 ) {
1517 printf( ", " );
1518 }
1519 switch(af<<8 | safi) {
1520 case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1521 case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1522 case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1523 case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1524 case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1525 case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1526 case (AFNUM_INET<<8 | SAFNUM_MDT):
1527 if (tlen < (int)sizeof(struct in_addr)) {
1528 printf("invalid len");
1529 tlen = 0;
1530 } else {
1531 TCHECK2(tptr[0], sizeof(struct in_addr));
1532 printf("%s",getname(tptr));
1533 tlen -= sizeof(struct in_addr);
1534 tptr += sizeof(struct in_addr);
1535 }
1536 break;
1537 case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1538 case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1539 case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1540 if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
1541 printf("invalid len");
1542 tlen = 0;
1543 } else {
1544 TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1545 printf("RD: %s, %s",
1546 bgp_vpn_rd_print(tptr),
1547 getname(tptr+BGP_VPN_RD_LEN));
1548 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1549 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1550 }
1551 break;
1552 #ifdef INET6
1553 case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1554 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1555 case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1556 case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1557 if (tlen < (int)sizeof(struct in6_addr)) {
1558 printf("invalid len");
1559 tlen = 0;
1560 } else {
1561 TCHECK2(tptr[0], sizeof(struct in6_addr));
1562 printf("%s", getname6(tptr));
1563 tlen -= sizeof(struct in6_addr);
1564 tptr += sizeof(struct in6_addr);
1565 }
1566 break;
1567 case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1568 case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1569 case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1570 if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1571 printf("invalid len");
1572 tlen = 0;
1573 } else {
1574 TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1575 printf("RD: %s, %s",
1576 bgp_vpn_rd_print(tptr),
1577 getname6(tptr+BGP_VPN_RD_LEN));
1578 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1579 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1580 }
1581 break;
1582 #endif
1583 case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1584 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1585 case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1586 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1587 if (tlen < (int)sizeof(struct in_addr)) {
1588 printf("invalid len");
1589 tlen = 0;
1590 } else {
1591 TCHECK2(tptr[0], sizeof(struct in_addr));
1592 printf("%s", getname(tptr));
1593 tlen -= (sizeof(struct in_addr));
1594 tptr += (sizeof(struct in_addr));
1595 }
1596 break;
1597 case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1598 case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1599 case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1600 TCHECK2(tptr[0], tlen);
1601 printf("%s",isonsap_string(tptr,tlen));
1602 tptr += tlen;
1603 tlen = 0;
1604 break;
1605
1606 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1607 case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1608 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1609 if (tlen < BGP_VPN_RD_LEN+1) {
1610 printf("invalid len");
1611 tlen = 0;
1612 } else {
1613 TCHECK2(tptr[0], tlen);
1614 printf("RD: %s, %s",
1615 bgp_vpn_rd_print(tptr),
1616 isonsap_string(tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN));
1617 /* rfc986 mapped IPv4 address ? */
1618 if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) == 0x47000601)
1619 printf(" = %s", getname(tptr+BGP_VPN_RD_LEN+4));
1620 #ifdef INET6
1621 /* rfc1888 mapped IPv6 address ? */
1622 else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) == 0x350000)
1623 printf(" = %s", getname6(tptr+BGP_VPN_RD_LEN+3));
1624 #endif
1625 tptr += tlen;
1626 tlen = 0;
1627 }
1628 break;
1629 default:
1630 TCHECK2(tptr[0], tlen);
1631 printf("no AFI %u/SAFI %u decoder",af,safi);
1632 if (vflag <= 1)
1633 print_unknown_data(tptr,"\n\t ",tlen);
1634 tptr += tlen;
1635 tlen = 0;
1636 goto done;
1637 break;
1638 }
1639 }
1640 }
1641 printf(", nh-length: %u", nhlen);
1642 tptr += tlen;
1643
1644 TCHECK(tptr[0]);
1645 snpa = tptr[0];
1646 tptr++;
1647
1648 if (snpa) {
1649 printf("\n\t %u SNPA", snpa);
1650 for (/*nothing*/; snpa > 0; snpa--) {
1651 TCHECK(tptr[0]);
1652 printf("\n\t %d bytes", tptr[0]);
1653 tptr += tptr[0] + 1;
1654 }
1655 } else {
1656 printf(", no SNPA");
1657 }
1658
1659 while (len - (tptr - pptr) > 0) {
1660 switch (af<<8 | safi) {
1661 case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1662 case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1663 case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1664 advance = decode_prefix4(tptr, buf, sizeof(buf));
1665 if (advance == -1)
1666 printf("\n\t (illegal prefix length)");
1667 else if (advance == -2)
1668 goto trunc;
1669 else
1670 printf("\n\t %s", buf);
1671 break;
1672 case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1673 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1674 if (advance == -1)
1675 printf("\n\t (illegal prefix length)");
1676 else if (advance == -2)
1677 goto trunc;
1678 else
1679 printf("\n\t %s", buf);
1680 break;
1681 case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1682 case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1683 case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1684 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1685 if (advance == -1)
1686 printf("\n\t (illegal prefix length)");
1687 else if (advance == -2)
1688 goto trunc;
1689 else
1690 printf("\n\t %s", buf);
1691 break;
1692 case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1693 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1694 if (advance == -1)
1695 printf("\n\t (illegal prefix length)");
1696 else if (advance == -2)
1697 goto trunc;
1698 else
1699 printf("\n\t %s", buf);
1700 break;
1701 case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
1702 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
1703 advance = decode_multicast_vpn(tptr, buf, sizeof(buf));
1704 if (advance == -1)
1705 printf("\n\t (illegal prefix length)");
1706 else if (advance == -2)
1707 goto trunc;
1708 else
1709 printf("\n\t %s", buf);
1710 break;
1711
1712 case (AFNUM_INET<<8 | SAFNUM_MDT):
1713 advance = decode_mdt_vpn_nlri(tptr, buf, sizeof(buf));
1714 if (advance == -1)
1715 printf("\n\t (illegal prefix length)");
1716 else if (advance == -2)
1717 goto trunc;
1718 else
1719 printf("\n\t %s", buf);
1720 break;
1721 #ifdef INET6
1722 case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1723 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1724 case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1725 advance = decode_prefix6(tptr, buf, sizeof(buf));
1726 if (advance == -1)
1727 printf("\n\t (illegal prefix length)");
1728 else if (advance == -2)
1729 goto trunc;
1730 else
1731 printf("\n\t %s", buf);
1732 break;
1733 case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1734 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1735 if (advance == -1)
1736 printf("\n\t (illegal prefix length)");
1737 else if (advance == -2)
1738 goto trunc;
1739 else
1740 printf("\n\t %s", buf);
1741 break;
1742 case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1743 case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1744 case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1745 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1746 if (advance == -1)
1747 printf("\n\t (illegal prefix length)");
1748 else if (advance == -2)
1749 goto trunc;
1750 else
1751 printf("\n\t %s", buf);
1752 break;
1753 #endif
1754 case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1755 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1756 case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1757 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1758 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1759 if (advance == -1)
1760 printf("\n\t (illegal length)");
1761 else if (advance == -2)
1762 goto trunc;
1763 else
1764 printf("\n\t %s", buf);
1765 break;
1766 case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1767 case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1768 case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1769 advance = decode_clnp_prefix(tptr, buf, sizeof(buf));
1770 if (advance == -1)
1771 printf("\n\t (illegal prefix length)");
1772 else if (advance == -2)
1773 goto trunc;
1774 else
1775 printf("\n\t %s", buf);
1776 break;
1777 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1778 case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1779 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1780 advance = decode_labeled_vpn_clnp_prefix(tptr, buf, sizeof(buf));
1781 if (advance == -1)
1782 printf("\n\t (illegal prefix length)");
1783 else if (advance == -2)
1784 goto trunc;
1785 else
1786 printf("\n\t %s", buf);
1787 break;
1788 default:
1789 TCHECK2(*tptr,tlen);
1790 printf("\n\t no AFI %u / SAFI %u decoder",af,safi);
1791 if (vflag <= 1)
1792 print_unknown_data(tptr,"\n\t ",tlen);
1793 advance = 0;
1794 tptr = pptr + len;
1795 break;
1796 }
1797 if (advance < 0)
1798 break;
1799 tptr += advance;
1800 }
1801 done:
1802 break;
1803
1804 case BGPTYPE_MP_UNREACH_NLRI:
1805 TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE);
1806 af = EXTRACT_16BITS(tptr);
1807 safi = tptr[2];
1808
1809 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
1810 tok2strbuf(af_values, "Unknown AFI", af,
1811 tokbuf, sizeof(tokbuf)),
1812 af,
1813 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1814 tok2strbuf(bgp_safi_values, "Unknown SAFI", safi,
1815 tokbuf, sizeof(tokbuf)),
1816 safi);
1817
1818 if (len == BGP_MP_NLRI_MINSIZE)
1819 printf("\n\t End-of-Rib Marker (empty NLRI)");
1820
1821 tptr += 3;
1822
1823 while (len - (tptr - pptr) > 0) {
1824 switch (af<<8 | safi) {
1825 case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1826 case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1827 case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1828 advance = decode_prefix4(tptr, buf, sizeof(buf));
1829 if (advance == -1)
1830 printf("\n\t (illegal prefix length)");
1831 else if (advance == -2)
1832 goto trunc;
1833 else
1834 printf("\n\t %s", buf);
1835 break;
1836 case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1837 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1838 if (advance == -1)
1839 printf("\n\t (illegal prefix length)");
1840 else if (advance == -2)
1841 goto trunc;
1842 else
1843 printf("\n\t %s", buf);
1844 break;
1845 case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1846 case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1847 case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1848 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1849 if (advance == -1)
1850 printf("\n\t (illegal prefix length)");
1851 else if (advance == -2)
1852 goto trunc;
1853 else
1854 printf("\n\t %s", buf);
1855 break;
1856 #ifdef INET6
1857 case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1858 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1859 case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1860 advance = decode_prefix6(tptr, buf, sizeof(buf));
1861 if (advance == -1)
1862 printf("\n\t (illegal prefix length)");
1863 else if (advance == -2)
1864 goto trunc;
1865 else
1866 printf("\n\t %s", buf);
1867 break;
1868 case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1869 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1870 if (advance == -1)
1871 printf("\n\t (illegal prefix length)");
1872 else if (advance == -2)
1873 goto trunc;
1874 else
1875 printf("\n\t %s", buf);
1876 break;
1877 case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1878 case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1879 case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1880 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1881 if (advance == -1)
1882 printf("\n\t (illegal prefix length)");
1883 else if (advance == -2)
1884 goto trunc;
1885 else
1886 printf("\n\t %s", buf);
1887 break;
1888 #endif
1889 case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1890 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1891 case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1892 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1893 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1894 if (advance == -1)
1895 printf("\n\t (illegal length)");
1896 else if (advance == -2)
1897 goto trunc;
1898 else
1899 printf("\n\t %s", buf);
1900 break;
1901 case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1902 case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1903 case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1904 advance = decode_clnp_prefix(tptr, buf, sizeof(buf));
1905 if (advance == -1)
1906 printf("\n\t (illegal prefix length)");
1907 else if (advance == -2)
1908 goto trunc;
1909 else
1910 printf("\n\t %s", buf);
1911 break;
1912 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1913 case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1914 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1915 advance = decode_labeled_vpn_clnp_prefix(tptr, buf, sizeof(buf));
1916 if (advance == -1)
1917 printf("\n\t (illegal prefix length)");
1918 else if (advance == -2)
1919 goto trunc;
1920 else
1921 printf("\n\t %s", buf);
1922 break;
1923 case (AFNUM_INET<<8 | SAFNUM_MDT):
1924 advance = decode_mdt_vpn_nlri(tptr, buf, sizeof(buf));
1925 if (advance == -1)
1926 printf("\n\t (illegal prefix length)");
1927 else if (advance == -2)
1928 goto trunc;
1929 else
1930 printf("\n\t %s", buf);
1931 break;
1932 case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
1933 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
1934 advance = decode_multicast_vpn(tptr, buf, sizeof(buf));
1935 if (advance == -1)
1936 printf("\n\t (illegal prefix length)");
1937 else if (advance == -2)
1938 goto trunc;
1939 else
1940 printf("\n\t %s", buf);
1941 break;
1942 default:
1943 TCHECK2(*(tptr-3),tlen);
1944 printf("no AFI %u / SAFI %u decoder",af,safi);
1945 if (vflag <= 1)
1946 print_unknown_data(tptr-3,"\n\t ",tlen);
1947 advance = 0;
1948 tptr = pptr + len;
1949 break;
1950 }
1951 if (advance < 0)
1952 break;
1953 tptr += advance;
1954 }
1955 break;
1956 case BGPTYPE_EXTD_COMMUNITIES:
1957 if (len % 8) {
1958 printf("invalid len");
1959 break;
1960 }
1961 while (tlen>0) {
1962 u_int16_t extd_comm;
1963
1964 TCHECK2(tptr[0], 2);
1965 extd_comm=EXTRACT_16BITS(tptr);
1966
1967 printf("\n\t %s (0x%04x), Flags [%s]",
1968 tok2strbuf(bgp_extd_comm_subtype_values,
1969 "unknown extd community typecode",
1970 extd_comm, tokbuf, sizeof(tokbuf)),
1971 extd_comm,
1972 bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
1973
1974 TCHECK2(*(tptr+2), 6);
1975 switch(extd_comm) {
1976 case BGP_EXT_COM_RT_0:
1977 case BGP_EXT_COM_RO_0:
1978 case BGP_EXT_COM_L2VPN_RT_0:
1979 printf(": %u:%u (= %s)",
1980 EXTRACT_16BITS(tptr+2),
1981 EXTRACT_32BITS(tptr+4),
1982 getname(tptr+4));
1983 break;
1984 case BGP_EXT_COM_RT_1:
1985 case BGP_EXT_COM_RO_1:
1986 case BGP_EXT_COM_L2VPN_RT_1:
1987 case BGP_EXT_COM_VRF_RT_IMP:
1988 printf(": %s:%u",
1989 getname(tptr+2),
1990 EXTRACT_16BITS(tptr+6));
1991 break;
1992 case BGP_EXT_COM_RT_2:
1993 case BGP_EXT_COM_RO_2:
1994 printf(": %s:%u",
1995 as_printf(astostr, sizeof(astostr),
1996 EXTRACT_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6));
1997 break;
1998 case BGP_EXT_COM_LINKBAND:
1999 bw.i = EXTRACT_32BITS(tptr+2);
2000 printf(": bandwidth: %.3f Mbps",
2001 bw.f*8/1000000);
2002 break;
2003 case BGP_EXT_COM_VPN_ORIGIN:
2004 case BGP_EXT_COM_VPN_ORIGIN2:
2005 case BGP_EXT_COM_VPN_ORIGIN3:
2006 case BGP_EXT_COM_VPN_ORIGIN4:
2007 case BGP_EXT_COM_OSPF_RID:
2008 case BGP_EXT_COM_OSPF_RID2:
2009 printf("%s", getname(tptr+2));
2010 break;
2011 case BGP_EXT_COM_OSPF_RTYPE:
2012 case BGP_EXT_COM_OSPF_RTYPE2:
2013 printf(": area:%s, router-type:%s, metric-type:%s%s",
2014 getname(tptr+2),
2015 tok2strbuf(bgp_extd_comm_ospf_rtype_values,
2016 "unknown (0x%02x)",
2017 *(tptr+6),
2018 tokbuf, sizeof(tokbuf)),
2019 (*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
2020 ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : "");
2021 break;
2022 case BGP_EXT_COM_L2INFO:
2023 printf(": %s Control Flags [0x%02x]:MTU %u",
2024 tok2strbuf(l2vpn_encaps_values,
2025 "unknown encaps",
2026 *(tptr+2),
2027 tokbuf, sizeof(tokbuf)),
2028 *(tptr+3),
2029 EXTRACT_16BITS(tptr+4));
2030 break;
2031 case BGP_EXT_COM_SOURCE_AS:
2032 printf(": AS %u", EXTRACT_16BITS(tptr+2));
2033 break;
2034 default:
2035 TCHECK2(*tptr,8);
2036 print_unknown_data(tptr,"\n\t ",8);
2037 break;
2038 }
2039 tlen -=8;
2040 tptr +=8;
2041 }
2042 break;
2043
2044 case BGPTYPE_PMSI_TUNNEL:
2045 {
2046 u_int8_t tunnel_type, flags;
2047
2048 tunnel_type = *(tptr+1);
2049 flags = *tptr;
2050 tlen = len;
2051
2052 TCHECK2(tptr[0], 5);
2053 printf("\n\t Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
2054 tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
2055 tunnel_type,
2056 bittok2str(bgp_pmsi_flag_values, "none", flags),
2057 EXTRACT_24BITS(tptr+2)>>4);
2058
2059 tptr +=5;
2060 tlen -= 5;
2061
2062 switch (tunnel_type) {
2063 case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
2064 case BGP_PMSI_TUNNEL_PIM_BIDIR:
2065 TCHECK2(tptr[0], 8);
2066 printf("\n\t Sender %s, P-Group %s",
2067 ipaddr_string(tptr),
2068 ipaddr_string(tptr+4));
2069 break;
2070
2071 case BGP_PMSI_TUNNEL_PIM_SSM:
2072 TCHECK2(tptr[0], 8);
2073 printf("\n\t Root-Node %s, P-Group %s",
2074 ipaddr_string(tptr),
2075 ipaddr_string(tptr+4));
2076 break;
2077 case BGP_PMSI_TUNNEL_INGRESS:
2078 TCHECK2(tptr[0], 4);
2079 printf("\n\t Tunnel-Endpoint %s",
2080 ipaddr_string(tptr));
2081 break;
2082 case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
2083 case BGP_PMSI_TUNNEL_LDP_MP2MP:
2084 TCHECK2(tptr[0], 8);
2085 printf("\n\t Root-Node %s, LSP-ID 0x%08x",
2086 ipaddr_string(tptr),
2087 EXTRACT_32BITS(tptr+4));
2088 break;
2089 case BGP_PMSI_TUNNEL_RSVP_P2MP:
2090 TCHECK2(tptr[0], 8);
2091 printf("\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
2092 ipaddr_string(tptr),
2093 EXTRACT_32BITS(tptr+4));
2094 break;
2095 default:
2096 if (vflag <= 1) {
2097 print_unknown_data(tptr,"\n\t ",tlen);
2098 }
2099 }
2100 break;
2101 }
2102 case BGPTYPE_ATTR_SET:
2103 TCHECK2(tptr[0], 4);
2104 printf("\n\t Origin AS: %s",
2105 as_printf(astostr, sizeof(astostr), EXTRACT_32BITS(tptr)));
2106 tptr+=4;
2107 len -=4;
2108
2109 while (len >= 2 ) {
2110 int alen;
2111 struct bgp_attr bgpa;
2112
2113 TCHECK2(tptr[0], sizeof(bgpa));
2114 memcpy(&bgpa, tptr, sizeof(bgpa));
2115 alen = bgp_attr_len(&bgpa);
2116 tptr += bgp_attr_off(&bgpa);
2117 len -= bgp_attr_off(&bgpa);
2118
2119 printf("\n\t %s (%u), length: %u",
2120 tok2strbuf(bgp_attr_values,
2121 "Unknown Attribute", bgpa.bgpa_type,
2122 tokbuf, sizeof(tokbuf)),
2123 bgpa.bgpa_type,
2124 alen);
2125
2126 if (bgpa.bgpa_flags) {
2127 printf(", Flags [%s%s%s%s",
2128 bgpa.bgpa_flags & 0x80 ? "O" : "",
2129 bgpa.bgpa_flags & 0x40 ? "T" : "",
2130 bgpa.bgpa_flags & 0x20 ? "P" : "",
2131 bgpa.bgpa_flags & 0x10 ? "E" : "");
2132 if (bgpa.bgpa_flags & 0xf)
2133 printf("+%x", bgpa.bgpa_flags & 0xf);
2134 printf("]: ");
2135 }
2136 /* FIXME check for recursion */
2137 if (!bgp_attr_print(&bgpa, tptr, alen))
2138 return 0;
2139 tptr += alen;
2140 len -= alen;
2141 }
2142 break;
2143
2144
2145 default:
2146 TCHECK2(*pptr,len);
2147 printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
2148 if (vflag <= 1)
2149 print_unknown_data(pptr,"\n\t ",len);
2150 break;
2151 }
2152 if (vflag > 1 && len) { /* omit zero length attributes*/
2153 TCHECK2(*pptr,len);
2154 print_unknown_data(pptr,"\n\t ",len);
2155 }
2156 return 1;
2157
2158 trunc:
2159 return 0;
2160 }
2161
2162 static void
2163 bgp_open_print(const u_char *dat, int length)
2164 {
2165 struct bgp_open bgpo;
2166 struct bgp_opt bgpopt;
2167 const u_char *opt;
2168 int i,cap_type,cap_len,tcap_len,cap_offset;
2169 char tokbuf[TOKBUFSIZE];
2170 char tokbuf2[TOKBUFSIZE];
2171
2172 TCHECK2(dat[0], BGP_OPEN_SIZE);
2173 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
2174
2175 printf("\n\t Version %d, ", bgpo.bgpo_version);
2176 printf("my AS %s, ",
2177 as_printf(astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas)));
2178 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
2179 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
2180 printf("\n\t Optional parameters, length: %u", bgpo.bgpo_optlen);
2181
2182 /* some little sanity checking */
2183 if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
2184 return;
2185
2186 /* ugly! */
2187 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
2188 opt++;
2189
2190 i = 0;
2191 while (i < bgpo.bgpo_optlen) {
2192 TCHECK2(opt[i], BGP_OPT_SIZE);
2193 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
2194 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
2195 printf("\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
2196 break;
2197 }
2198
2199 printf("\n\t Option %s (%u), length: %u",
2200 tok2strbuf(bgp_opt_values,"Unknown",
2201 bgpopt.bgpopt_type,
2202 tokbuf, sizeof(tokbuf)),
2203 bgpopt.bgpopt_type,
2204 bgpopt.bgpopt_len);
2205
2206 /* now lets decode the options we know*/
2207 switch(bgpopt.bgpopt_type) {
2208 case BGP_OPT_CAP:
2209 cap_type=opt[i+BGP_OPT_SIZE];
2210 cap_len=opt[i+BGP_OPT_SIZE+1];
2211 tcap_len=cap_len;
2212 printf("\n\t %s (%u), length: %u",
2213 tok2strbuf(bgp_capcode_values, "Unknown",
2214 cap_type, tokbuf, sizeof(tokbuf)),
2215 cap_type,
2216 cap_len);
2217 switch(cap_type) {
2218 case BGP_CAPCODE_MP:
2219 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
2220 tok2strbuf(af_values, "Unknown",
2221 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
2222 tokbuf, sizeof(tokbuf)),
2223 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
2224 tok2strbuf(bgp_safi_values, "Unknown",
2225 opt[i+BGP_OPT_SIZE+5],
2226 tokbuf, sizeof(tokbuf)),
2227 opt[i+BGP_OPT_SIZE+5]);
2228 break;
2229 case BGP_CAPCODE_RESTART:
2230 printf("\n\t\tRestart Flags: [%s], Restart Time %us",
2231 ((opt[i+BGP_OPT_SIZE+2])&0x80) ? "R" : "none",
2232 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)&0xfff);
2233 tcap_len-=2;
2234 cap_offset=4;
2235 while(tcap_len>=4) {
2236 printf("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
2237 tok2strbuf(af_values,"Unknown",
2238 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
2239 tokbuf, sizeof(tokbuf)),
2240 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
2241 tok2strbuf(bgp_safi_values,"Unknown",
2242 opt[i+BGP_OPT_SIZE+cap_offset+2],
2243 tokbuf2, sizeof(tokbuf2)),
2244 opt[i+BGP_OPT_SIZE+cap_offset+2],
2245 ((opt[i+BGP_OPT_SIZE+cap_offset+3])&0x80) ? "yes" : "no" );
2246 tcap_len-=4;
2247 cap_offset+=4;
2248 }
2249 break;
2250 case BGP_CAPCODE_RR:
2251 case BGP_CAPCODE_RR_CISCO:
2252 break;
2253 case BGP_CAPCODE_AS_NEW:
2254
2255 /*
2256 * Extract the 4 byte AS number encoded.
2257 */
2258 TCHECK2(opt[i + BGP_OPT_SIZE + 2], cap_len);
2259 if (cap_len == 4) {
2260 printf("\n\t\t 4 Byte AS %s",
2261 as_printf(astostr, sizeof(astostr),
2262 EXTRACT_32BITS(opt + i + BGP_OPT_SIZE + 2)));
2263 }
2264 break;
2265 default:
2266 TCHECK2(opt[i+BGP_OPT_SIZE+2],cap_len);
2267 printf("\n\t\tno decoder for Capability %u",
2268 cap_type);
2269 if (vflag <= 1)
2270 print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
2271 break;
2272 }
2273 if (vflag > 1) {
2274 TCHECK2(opt[i+BGP_OPT_SIZE+2],cap_len);
2275 print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
2276 }
2277 break;
2278 case BGP_OPT_AUTH:
2279 default:
2280 printf("\n\t no decoder for option %u",
2281 bgpopt.bgpopt_type);
2282 break;
2283 }
2284
2285 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
2286 }
2287 return;
2288 trunc:
2289 printf("[|BGP]");
2290 }
2291
2292 static void
2293 bgp_update_print(const u_char *dat, int length)
2294 {
2295 struct bgp bgp;
2296 struct bgp_attr bgpa;
2297 const u_char *p;
2298 int len;
2299 int i;
2300 char tokbuf[TOKBUFSIZE];
2301
2302 TCHECK2(dat[0], BGP_SIZE);
2303 memcpy(&bgp, dat, BGP_SIZE);
2304 p = dat + BGP_SIZE; /*XXX*/
2305
2306 /* Unfeasible routes */
2307 len = EXTRACT_16BITS(p);
2308 if (len) {
2309 /*
2310 * Without keeping state from the original NLRI message,
2311 * it's not possible to tell if this a v4 or v6 route,
2312 * so only try to decode it if we're not v6 enabled.
2313 */
2314 #ifdef INET6
2315 printf("\n\t Withdrawn routes: %d bytes", len);
2316 #else
2317 char buf[MAXHOSTNAMELEN + 100];
2318 int wpfx;
2319
2320 TCHECK2(p[2], len);
2321 i = 2;
2322
2323 printf("\n\t Withdrawn routes:");
2324
2325 while(i < 2 + len) {
2326 wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
2327 if (wpfx == -1) {
2328 printf("\n\t (illegal prefix length)");
2329 break;
2330 } else if (wpfx == -2)
2331 goto trunc;
2332 else {
2333 i += wpfx;
2334 printf("\n\t %s", buf);
2335 }
2336 }
2337 #endif
2338 }
2339 p += 2 + len;
2340
2341 TCHECK2(p[0], 2);
2342 len = EXTRACT_16BITS(p);
2343
2344 if (len == 0 && length == BGP_UPDATE_MINSIZE) {
2345 printf("\n\t End-of-Rib Marker (empty NLRI)");
2346 return;
2347 }
2348
2349 if (len) {
2350 /* do something more useful!*/
2351 i = 2;
2352 while (i < 2 + len) {
2353 int alen, aoff;
2354
2355 TCHECK2(p[i], sizeof(bgpa));
2356 memcpy(&bgpa, &p[i], sizeof(bgpa));
2357 alen = bgp_attr_len(&bgpa);
2358 aoff = bgp_attr_off(&bgpa);
2359
2360 printf("\n\t %s (%u), length: %u",
2361 tok2strbuf(bgp_attr_values, "Unknown Attribute",
2362 bgpa.bgpa_type,
2363 tokbuf, sizeof(tokbuf)),
2364 bgpa.bgpa_type,
2365 alen);
2366
2367 if (bgpa.bgpa_flags) {
2368 printf(", Flags [%s%s%s%s",
2369 bgpa.bgpa_flags & 0x80 ? "O" : "",
2370 bgpa.bgpa_flags & 0x40 ? "T" : "",
2371 bgpa.bgpa_flags & 0x20 ? "P" : "",
2372 bgpa.bgpa_flags & 0x10 ? "E" : "");
2373 if (bgpa.bgpa_flags & 0xf)
2374 printf("+%x", bgpa.bgpa_flags & 0xf);
2375 printf("]: ");
2376 }
2377 if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
2378 goto trunc;
2379 i += aoff + alen;
2380 }
2381 }
2382 p += 2 + len;
2383
2384 if (dat + length > p) {
2385 printf("\n\t Updated routes:");
2386 while (dat + length > p) {
2387 char buf[MAXHOSTNAMELEN + 100];
2388 i = decode_prefix4(p, buf, sizeof(buf));
2389 if (i == -1) {
2390 printf("\n\t (illegal prefix length)");
2391 break;
2392 } else if (i == -2)
2393 goto trunc;
2394 else {
2395 printf("\n\t %s", buf);
2396 p += i;
2397 }
2398 }
2399 }
2400 return;
2401 trunc:
2402 printf("[|BGP]");
2403 }
2404
2405 static void
2406 bgp_notification_print(const u_char *dat, int length)
2407 {
2408 struct bgp_notification bgpn;
2409 const u_char *tptr;
2410 char tokbuf[TOKBUFSIZE];
2411 char tokbuf2[TOKBUFSIZE];
2412
2413 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
2414 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
2415
2416 /* some little sanity checking */
2417 if (length<BGP_NOTIFICATION_SIZE)
2418 return;
2419
2420 printf(", %s (%u)",
2421 tok2strbuf(bgp_notify_major_values, "Unknown Error",
2422 bgpn.bgpn_major, tokbuf, sizeof(tokbuf)),
2423 bgpn.bgpn_major);
2424
2425 switch (bgpn.bgpn_major) {
2426
2427 case BGP_NOTIFY_MAJOR_MSG:
2428 printf(", subcode %s (%u)",
2429 tok2strbuf(bgp_notify_minor_msg_values, "Unknown",
2430 bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)),
2431 bgpn.bgpn_minor);
2432 break;
2433 case BGP_NOTIFY_MAJOR_OPEN:
2434 printf(", subcode %s (%u)",
2435 tok2strbuf(bgp_notify_minor_open_values, "Unknown",
2436 bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)),
2437 bgpn.bgpn_minor);
2438 break;
2439 case BGP_NOTIFY_MAJOR_UPDATE:
2440 printf(", subcode %s (%u)",
2441 tok2strbuf(bgp_notify_minor_update_values, "Unknown",
2442 bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)),
2443 bgpn.bgpn_minor);
2444 break;
2445 case BGP_NOTIFY_MAJOR_CAP:
2446 printf(" subcode %s (%u)",
2447 tok2strbuf(bgp_notify_minor_cap_values, "Unknown",
2448 bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)),
2449 bgpn.bgpn_minor);
2450 case BGP_NOTIFY_MAJOR_CEASE:
2451 printf(", subcode %s (%u)",
2452 tok2strbuf(bgp_notify_minor_cease_values, "Unknown",
2453 bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)),
2454 bgpn.bgpn_minor);
2455
2456 /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
2457 * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
2458 */
2459 if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
2460 tptr = dat + BGP_NOTIFICATION_SIZE;
2461 TCHECK2(*tptr, 7);
2462 printf(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
2463 tok2strbuf(af_values, "Unknown",
2464 EXTRACT_16BITS(tptr), tokbuf, sizeof(tokbuf)),
2465 EXTRACT_16BITS(tptr),
2466 tok2strbuf(bgp_safi_values, "Unknown", *(tptr+2),
2467 tokbuf2, sizeof(tokbuf)),
2468 *(tptr+2),
2469 EXTRACT_32BITS(tptr+3));
2470 }
2471 break;
2472 default:
2473 break;
2474 }
2475
2476 return;
2477 trunc:
2478 printf("[|BGP]");
2479 }
2480
2481 static void
2482 bgp_route_refresh_print(const u_char *pptr, int len) {
2483
2484 const struct bgp_route_refresh *bgp_route_refresh_header;
2485 char tokbuf[TOKBUFSIZE];
2486 char tokbuf2[TOKBUFSIZE];
2487
2488 TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE);
2489
2490 /* some little sanity checking */
2491 if (len<BGP_ROUTE_REFRESH_SIZE)
2492 return;
2493
2494 bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
2495
2496 printf("\n\t AFI %s (%u), SAFI %s (%u)",
2497 tok2strbuf(af_values,"Unknown",
2498 /* this stinks but the compiler pads the structure
2499 * weird */
2500 EXTRACT_16BITS(&bgp_route_refresh_header->afi),
2501 tokbuf, sizeof(tokbuf)),
2502 EXTRACT_16BITS(&bgp_route_refresh_header->afi),
2503 tok2strbuf(bgp_safi_values,"Unknown",
2504 bgp_route_refresh_header->safi,
2505 tokbuf2, sizeof(tokbuf2)),
2506 bgp_route_refresh_header->safi);
2507
2508 if (vflag > 1) {
2509 TCHECK2(*pptr, len);
2510 print_unknown_data(pptr,"\n\t ", len);
2511 }
2512
2513 return;
2514 trunc:
2515 printf("[|BGP]");
2516 }
2517
2518 static int
2519 bgp_header_print(const u_char *dat, int length)
2520 {
2521 struct bgp bgp;
2522 char tokbuf[TOKBUFSIZE];
2523
2524 TCHECK2(dat[0], BGP_SIZE);
2525 memcpy(&bgp, dat, BGP_SIZE);
2526 printf("\n\t%s Message (%u), length: %u",
2527 tok2strbuf(bgp_msg_values, "Unknown", bgp.bgp_type,
2528 tokbuf, sizeof(tokbuf)),
2529 bgp.bgp_type,
2530 length);
2531
2532 switch (bgp.bgp_type) {
2533 case BGP_OPEN:
2534 bgp_open_print(dat, length);
2535 break;
2536 case BGP_UPDATE:
2537 bgp_update_print(dat, length);
2538 break;
2539 case BGP_NOTIFICATION:
2540 bgp_notification_print(dat, length);
2541 break;
2542 case BGP_KEEPALIVE:
2543 break;
2544 case BGP_ROUTE_REFRESH:
2545 bgp_route_refresh_print(dat, length);
2546 break;
2547 default:
2548 /* we have no decoder for the BGP message */
2549 TCHECK2(*dat, length);
2550 printf("\n\t no Message %u decoder",bgp.bgp_type);
2551 print_unknown_data(dat,"\n\t ",length);
2552 break;
2553 }
2554 return 1;
2555 trunc:
2556 printf("[|BGP]");
2557 return 0;
2558 }
2559
2560 void
2561 bgp_print(const u_char *dat, int length)
2562 {
2563 const u_char *p;
2564 const u_char *ep;
2565 const u_char *start;
2566 const u_char marker[] = {
2567 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2568 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2569 };
2570 struct bgp bgp;
2571 u_int16_t hlen;
2572 char tokbuf[TOKBUFSIZE];
2573
2574 ep = dat + length;
2575 if (snapend < dat + length)
2576 ep = snapend;
2577
2578 printf(": BGP, length: %u",length);
2579
2580 if (vflag < 1) /* lets be less chatty */
2581 return;
2582
2583 p = dat;
2584 start = p;
2585 while (p < ep) {
2586 if (!TTEST2(p[0], 1))
2587 break;
2588 if (p[0] != 0xff) {
2589 p++;
2590 continue;
2591 }
2592
2593 if (!TTEST2(p[0], sizeof(marker)))
2594 break;
2595 if (memcmp(p, marker, sizeof(marker)) != 0) {
2596 p++;
2597 continue;
2598 }
2599
2600 /* found BGP header */
2601 TCHECK2(p[0], BGP_SIZE); /*XXX*/
2602 memcpy(&bgp, p, BGP_SIZE);
2603
2604 if (start != p)
2605 printf(" [|BGP]");
2606
2607 hlen = ntohs(bgp.bgp_len);
2608 if (hlen < BGP_SIZE) {
2609 printf("\n[|BGP Bogus header length %u < %u]", hlen,
2610 BGP_SIZE);
2611 break;
2612 }
2613
2614 if (TTEST2(p[0], hlen)) {
2615 if (!bgp_header_print(p, hlen))
2616 return;
2617 p += hlen;
2618 start = p;
2619 } else {
2620 printf("\n[|BGP %s]",
2621 tok2strbuf(bgp_msg_values,
2622 "Unknown Message Type",
2623 bgp.bgp_type,
2624 tokbuf, sizeof(tokbuf)));
2625 break;
2626 }
2627 }
2628
2629 return;
2630
2631 trunc:
2632 printf(" [|BGP]");
2633 }
2634
2635 /*
2636 * Local Variables:
2637 * c-style: whitesmith
2638 * c-basic-offset: 4
2639 * End:
2640 */