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