]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
Add bounds checking.
[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.81 2004-03-24 00:01:00 guy 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 "addrtoname.h"
49 #include "extract.h"
50
51 struct bgp {
52 u_int8_t bgp_marker[16];
53 u_int16_t bgp_len;
54 u_int8_t bgp_type;
55 };
56 #define BGP_SIZE 19 /* unaligned */
57
58 #define BGP_OPEN 1
59 #define BGP_UPDATE 2
60 #define BGP_NOTIFICATION 3
61 #define BGP_KEEPALIVE 4
62 #define BGP_ROUTE_REFRESH 5
63
64 static struct tok bgp_msg_values[] = {
65 { BGP_OPEN, "Open"},
66 { BGP_UPDATE, "Update"},
67 { BGP_NOTIFICATION, "Notification"},
68 { BGP_KEEPALIVE, "Keepalive"},
69 { BGP_ROUTE_REFRESH, "Route Refresh"},
70 { 0, NULL}
71 };
72
73 struct bgp_open {
74 u_int8_t bgpo_marker[16];
75 u_int16_t bgpo_len;
76 u_int8_t bgpo_type;
77 u_int8_t bgpo_version;
78 u_int16_t bgpo_myas;
79 u_int16_t bgpo_holdtime;
80 u_int32_t bgpo_id;
81 u_int8_t bgpo_optlen;
82 /* options should follow */
83 };
84 #define BGP_OPEN_SIZE 29 /* unaligned */
85
86 struct bgp_opt {
87 u_int8_t bgpopt_type;
88 u_int8_t bgpopt_len;
89 /* variable length */
90 };
91 #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */
92
93 struct bgp_notification {
94 u_int8_t bgpn_marker[16];
95 u_int16_t bgpn_len;
96 u_int8_t bgpn_type;
97 u_int8_t bgpn_major;
98 u_int8_t bgpn_minor;
99 };
100 #define BGP_NOTIFICATION_SIZE 21 /* unaligned */
101
102 struct bgp_route_refresh {
103 u_int8_t bgp_marker[16];
104 u_int16_t len;
105 u_int8_t type;
106 u_int8_t afi[2]; /* the compiler messes this structure up */
107 u_int8_t res; /* when doing misaligned sequences of int8 and int16 */
108 u_int8_t safi; /* afi should be int16 - so we have to access it using */
109 }; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */
110 #define BGP_ROUTE_REFRESH_SIZE 23
111
112 struct bgp_attr {
113 u_int8_t bgpa_flags;
114 u_int8_t bgpa_type;
115 union {
116 u_int8_t len;
117 u_int16_t elen;
118 } bgpa_len;
119 #define bgp_attr_len(p) \
120 (((p)->bgpa_flags & 0x10) ? \
121 EXTRACT_16BITS(&(p)->bgpa_len.elen) : (p)->bgpa_len.len)
122 #define bgp_attr_off(p) \
123 (((p)->bgpa_flags & 0x10) ? 4 : 3)
124 };
125
126 #define BGPTYPE_ORIGIN 1
127 #define BGPTYPE_AS_PATH 2
128 #define BGPTYPE_NEXT_HOP 3
129 #define BGPTYPE_MULTI_EXIT_DISC 4
130 #define BGPTYPE_LOCAL_PREF 5
131 #define BGPTYPE_ATOMIC_AGGREGATE 6
132 #define BGPTYPE_AGGREGATOR 7
133 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
134 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */
135 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */
136 #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */
137 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */
138 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */
139 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
140 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
141 #define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */
142 #define BGPTYPE_ATTR_SET 128 /* draft-marques-ppvpn-ibgp */
143
144 static struct tok bgp_attr_values[] = {
145 { BGPTYPE_ORIGIN, "Origin"},
146 { BGPTYPE_AS_PATH, "AS Path"},
147 { BGPTYPE_NEXT_HOP, "Next Hop"},
148 { BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"},
149 { BGPTYPE_LOCAL_PREF, "Local Preference"},
150 { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
151 { BGPTYPE_AGGREGATOR, "Aggregator"},
152 { BGPTYPE_COMMUNITIES, "Community"},
153 { BGPTYPE_ORIGINATOR_ID, "Originator ID"},
154 { BGPTYPE_CLUSTER_LIST, "Cluster List"},
155 { BGPTYPE_DPA, "DPA"},
156 { BGPTYPE_ADVERTISERS, "Advertisers"},
157 { BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"},
158 { BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"},
159 { BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"},
160 { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
161 { BGPTYPE_ATTR_SET, "Attribute Set"},
162 { 255, "Reserved for development"},
163 { 0, NULL}
164 };
165
166 #define BGP_AS_SET 1
167 #define BGP_AS_SEQUENCE 2
168 #define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
169 #define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */
170
171 static struct tok bgp_as_path_segment_open_values[] = {
172 { BGP_AS_SEQUENCE, ""},
173 { BGP_AS_SET, "{ "},
174 { BGP_CONFED_AS_SEQUENCE, "( "},
175 { BGP_CONFED_AS_SET, "({ "},
176 { 0, NULL}
177 };
178
179 static struct tok bgp_as_path_segment_close_values[] = {
180 { BGP_AS_SEQUENCE, ""},
181 { BGP_AS_SET, "}"},
182 { BGP_CONFED_AS_SEQUENCE, ")"},
183 { BGP_CONFED_AS_SET, "})"},
184 { 0, NULL}
185 };
186
187 #define BGP_OPT_AUTH 1
188 #define BGP_OPT_CAP 2
189
190
191 static struct tok bgp_opt_values[] = {
192 { BGP_OPT_AUTH, "Authentication Information"},
193 { BGP_OPT_CAP, "Capabilities Advertisement"},
194 { 0, NULL}
195 };
196
197 #define BGP_CAPCODE_MP 1
198 #define BGP_CAPCODE_RR 2
199 #define BGP_CAPCODE_ORF 3 /* XXX */
200 #define BGP_CAPCODE_RESTART 64 /* draft-ietf-idr-restart-05 */
201 #define BGP_CAPCODE_AS_NEW 65 /* XXX */
202 #define BGP_CAPCODE_DYN_CAP 67 /* XXX */
203 #define BGP_CAPCODE_RR_CISCO 128
204
205 static struct tok bgp_capcode_values[] = {
206 { BGP_CAPCODE_MP, "Multiprotocol Extensions"},
207 { BGP_CAPCODE_RR, "Route Refresh"},
208 { BGP_CAPCODE_ORF, "Cooperative Route Filtering"},
209 { BGP_CAPCODE_RESTART, "Graceful Restart"},
210 { BGP_CAPCODE_AS_NEW, "32-Bit AS Number"},
211 { BGP_CAPCODE_DYN_CAP, "Dynamic Capability"},
212 { BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"},
213 { 0, NULL}
214 };
215
216 #define BGP_NOTIFY_MAJOR_MSG 1
217 #define BGP_NOTIFY_MAJOR_OPEN 2
218 #define BGP_NOTIFY_MAJOR_UPDATE 3
219 #define BGP_NOTIFY_MAJOR_HOLDTIME 4
220 #define BGP_NOTIFY_MAJOR_FSM 5
221 #define BGP_NOTIFY_MAJOR_CEASE 6
222 #define BGP_NOTIFY_MAJOR_CAP 7
223
224 static struct tok bgp_notify_major_values[] = {
225 { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"},
226 { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"},
227 { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"},
228 { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
229 { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"},
230 { BGP_NOTIFY_MAJOR_CEASE, "Cease"},
231 { BGP_NOTIFY_MAJOR_CAP, "Capability Message Error"},
232 { 0, NULL}
233 };
234
235 /* draft-ietf-idr-cease-subcode-02 */
236 #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1
237 static struct tok bgp_notify_minor_cease_values[] = {
238 { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"},
239 { 2, "Administratively Shutdown"},
240 { 3, "Peer Unconfigured"},
241 { 4, "Administratively Reset"},
242 { 5, "Connection Rejected"},
243 { 6, "Other Configuration Change"},
244 { 7, "Connection Collision Resolution"},
245 { 0, NULL}
246 };
247
248 static struct tok bgp_notify_minor_msg_values[] = {
249 { 1, "Connection Not Synchronized"},
250 { 2, "Bad Message Length"},
251 { 3, "Bad Message Type"},
252 { 0, NULL}
253 };
254
255 static struct tok bgp_notify_minor_open_values[] = {
256 { 1, "Unsupported Version Number"},
257 { 2, "Bad Peer AS"},
258 { 3, "Bad BGP Identifier"},
259 { 4, "Unsupported Optional Parameter"},
260 { 5, "Authentication Failure"},
261 { 6, "Unacceptable Hold Time"},
262 { 0, NULL}
263 };
264
265 static struct tok bgp_notify_minor_update_values[] = {
266 { 1, "Malformed Attribute List"},
267 { 2, "Unrecognized Well-known Attribute"},
268 { 3, "Missing Well-known Attribute"},
269 { 4, "Attribute Flags Error"},
270 { 5, "Attribute Length Error"},
271 { 6, "Invalid ORIGIN Attribute"},
272 { 7, "AS Routing Loop"},
273 { 8, "Invalid NEXT_HOP Attribute"},
274 { 9, "Optional Attribute Error"},
275 { 10, "Invalid Network Field"},
276 { 11, "Malformed AS_PATH"},
277 { 0, NULL}
278 };
279
280 static struct tok bgp_notify_minor_cap_values[] = {
281 { 1, "Invalid Action Value" },
282 { 2, "Invalid Capability Length" },
283 { 3, "Malformed Capability Value" },
284 { 4, "Unsupported Capability Code" },
285 { 0, NULL }
286 };
287
288 static struct tok bgp_origin_values[] = {
289 { 0, "IGP"},
290 { 1, "EGP"},
291 { 2, "Incomplete"},
292 { 0, NULL}
293 };
294
295 /* Subsequent address family identifier, RFC2283 section 7 */
296 #define SAFNUM_RES 0
297 #define SAFNUM_UNICAST 1
298 #define SAFNUM_MULTICAST 2
299 #define SAFNUM_UNIMULTICAST 3
300 /* labeled BGP RFC3107 */
301 #define SAFNUM_LABUNICAST 4
302 #define SAFNUM_TUNNEL 64 /* XXX */
303 #define SAFNUM_VPLS 65 /* XXX */
304 #define SAFNUM_MDT 66 /* XXX */
305 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */
306 #define SAFNUM_VPNUNICAST 128
307 #define SAFNUM_VPNMULTICAST 129
308 #define SAFNUM_VPNUNIMULTICAST 130
309 /* draft-marques-ppvpn-rt-constrain-01.txt */
310 #define SAFNUM_RT_ROUTING_INFO 132
311
312 #define BGP_VPN_RD_LEN 8
313
314 static struct tok bgp_safi_values[] = {
315 { SAFNUM_RES, "Reserved"},
316 { SAFNUM_UNICAST, "Unicast"},
317 { SAFNUM_MULTICAST, "Multicast"},
318 { SAFNUM_UNIMULTICAST, "Unicast+Multicast"},
319 { SAFNUM_LABUNICAST, "labeled Unicast"},
320 { SAFNUM_TUNNEL, "Tunnel"},
321 { SAFNUM_VPLS, "VPLS"},
322 { SAFNUM_MDT, "MDT"},
323 { SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
324 { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
325 { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
326 { SAFNUM_RT_ROUTING_INFO, "Route Target Routing Information"}, /* draft-marques-ppvpn-rt-constrain-01.txt */
327 { 0, NULL }
328 };
329
330 /* well-known community */
331 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01
332 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02
333 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
334
335 /* RFC1700 address family numbers */
336 #define AFNUM_INET 1
337 #define AFNUM_INET6 2
338 #define AFNUM_NSAP 3
339 #define AFNUM_HDLC 4
340 #define AFNUM_BBN1822 5
341 #define AFNUM_802 6
342 #define AFNUM_E163 7
343 #define AFNUM_E164 8
344 #define AFNUM_F69 9
345 #define AFNUM_X121 10
346 #define AFNUM_IPX 11
347 #define AFNUM_ATALK 12
348 #define AFNUM_DECNET 13
349 #define AFNUM_BANYAN 14
350 #define AFNUM_E164NSAP 15
351 /* draft-kompella-ppvpn-l2vpn */
352 #define AFNUM_L2VPN 196 /* still to be approved by IANA */
353
354 static struct tok bgp_afi_values[] = {
355 { 0, "Reserved"},
356 { AFNUM_INET, "IPv4"},
357 { AFNUM_INET6, "IPv6"},
358 { AFNUM_NSAP, "NSAP"},
359 { AFNUM_HDLC, "HDLC"},
360 { AFNUM_BBN1822, "BBN 1822"},
361 { AFNUM_802, "802"},
362 { AFNUM_E163, "E.163"},
363 { AFNUM_E164, "E.164"},
364 { AFNUM_F69, "F.69"},
365 { AFNUM_X121, "X.121"},
366 { AFNUM_IPX, "Novell IPX"},
367 { AFNUM_ATALK, "Appletalk"},
368 { AFNUM_DECNET, "Decnet IV"},
369 { AFNUM_BANYAN, "Banyan Vines"},
370 { AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
371 { AFNUM_L2VPN, "Layer-2 VPN"},
372 { 0, NULL},
373 };
374
375 /* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
376 #define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */
377 #define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */
378 #define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AN(4bytes):local(2bytes) */
379 #define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */
380 #define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */
381 #define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AN(4bytes):local(2bytes) */
382 #define BGP_EXT_COM_LINKBAND 0x4004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
383 /* rfc2547 bgp-mpls-vpns */
384 #define BGP_EXT_COM_CISCO_MCAST 0x0009 /* cisco proprietary */
385
386 #define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domain ID / VPN of Origin - draft-rosen-vpns-ospf-bgp-mpls */
387 #define BGP_EXT_COM_VPN_ORIGIN2 0x0105 /* duplicate - keep for backwards compatability */
388 #define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatability */
389 #define BGP_EXT_COM_VPN_ORIGIN4 0x8005 /* duplicate - keep for backwards compatability */
390
391 #define BGP_EXT_COM_OSPF_RTYPE 0x0306 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
392 #define BGP_EXT_COM_OSPF_RTYPE2 0x8000 /* duplicate - keep for backwards compatability */
393
394 #define BGP_EXT_COM_OSPF_RID 0x0107 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
395 #define BGP_EXT_COM_OSPF_RID2 0x8001 /* duplicate - keep for backwards compatability */
396
397 #define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
398
399 static struct tok bgp_extd_comm_flag_values[] = {
400 { 0x8000, "vendor-specific"},
401 { 0x4000, "non-transitive"},
402 { 0, NULL},
403 };
404
405 static struct tok bgp_extd_comm_subtype_values[] = {
406 { BGP_EXT_COM_RT_0, "target"},
407 { BGP_EXT_COM_RT_1, "target"},
408 { BGP_EXT_COM_RT_2, "target"},
409 { BGP_EXT_COM_RO_0, "origin"},
410 { BGP_EXT_COM_RO_1, "origin"},
411 { BGP_EXT_COM_RO_2, "origin"},
412 { BGP_EXT_COM_LINKBAND, "link-BW"},
413 { BGP_EXT_COM_CISCO_MCAST, "mdt-group"},
414 { BGP_EXT_COM_VPN_ORIGIN, "ospf-domain"},
415 { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
416 { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
417 { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
418 { BGP_EXT_COM_OSPF_RTYPE, "ospf-route-type"},
419 { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
420 { BGP_EXT_COM_OSPF_RID, "ospf-router-id"},
421 { BGP_EXT_COM_OSPF_RID2, "ospf-router-id"},
422 { BGP_EXT_COM_L2INFO, "layer2-info"},
423 { 0, NULL},
424 };
425
426 /* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */
427 #define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */
428 #define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */
429 #define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */
430 #define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
431 #define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/
432 #define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */
433 #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
434
435 static struct tok bgp_extd_comm_ospf_rtype_values[] = {
436 { BGP_OSPF_RTYPE_RTR, "Router" },
437 { BGP_OSPF_RTYPE_NET, "Network" },
438 { BGP_OSPF_RTYPE_SUM, "Summary" },
439 { BGP_OSPF_RTYPE_EXT, "External" },
440 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
441 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
442 { 0, NULL },
443 };
444
445 static struct tok bgp_l2vpn_encaps_values[] = {
446 { 0, "Reserved"},
447 { 1, "Frame Relay"},
448 { 2, "ATM AAL5 VCC transport"},
449 { 3, "ATM transparent cell transport"},
450 { 4, "Ethernet VLAN"},
451 { 5, "Ethernet"},
452 { 6, "Cisco-HDLC"},
453 { 7, "PPP"},
454 { 8, "CEM"},
455 { 9, "ATM VCC cell transport"},
456 { 10, "ATM VPC cell transport"},
457 { 11, "MPLS"},
458 { 12, "VPLS"},
459 { 64, "IP-interworking"},
460 { 0, NULL},
461 };
462
463 static int
464 decode_prefix4(const u_char *pptr, char *buf, u_int buflen)
465 {
466 struct in_addr addr;
467 u_int plen;
468
469 TCHECK(pptr[0]);
470 plen = pptr[0];
471 if (32 < plen)
472 return -1;
473
474 memset(&addr, 0, sizeof(addr));
475 TCHECK2(pptr[1], (plen + 7) / 8);
476 memcpy(&addr, &pptr[1], (plen + 7) / 8);
477 if (plen % 8) {
478 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
479 ((0xff00 >> (plen % 8)) & 0xff);
480 }
481 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
482 return 1 + (plen + 7) / 8;
483
484 trunc:
485 return -2;
486 }
487
488 static int
489 decode_labeled_prefix4(const u_char *pptr, char *buf, u_int buflen)
490 {
491 struct in_addr addr;
492 u_int plen;
493
494 TCHECK(pptr[0]);
495 plen = pptr[0]; /* get prefix length */
496
497 /* this is one of the weirdnesses of rfc3107
498 the label length (actually the label + COS bits)
499 is added to the prefix length;
500 we also do only read out just one label -
501 there is no real application for advertisement of
502 stacked labels in a a single BGP message
503 */
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 /* RDs and RTs share the same semantics
531 * we use bgp_vpn_rd_print for
532 * printing route targets inside a NLRI */
533 static char *
534 bgp_vpn_rd_print (const u_char *pptr) {
535
536 /* allocate space for the largest possible string */
537 static char rd[sizeof("xxxxxxxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")];
538 char *pos = rd;
539
540 /* ok lets load the RD format */
541 switch (EXTRACT_16BITS(pptr)) {
542
543 /* AS:IP-address fmt*/
544 case 0:
545 snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u.%u.%u.%u",
546 EXTRACT_16BITS(pptr+2), *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
547 break;
548 /* IP-address:AS fmt*/
549
550 case 1:
551 snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
552 *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6));
553 break;
554
555 /* 4-byte-AS:number fmt*/
556 case 2:
557 snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (%u.%u.%u.%u:%u)",
558 EXTRACT_32BITS(pptr+2), EXTRACT_16BITS(pptr+6),
559 *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6));
560 break;
561 default:
562 snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
563 break;
564 }
565 pos += strlen(pos);
566 *(pos) = '\0';
567 return (rd);
568 }
569
570 static int
571 decode_rt_routing_info(const u_char *pptr, char *buf, u_int buflen)
572 {
573 u_int8_t route_target[8];
574 u_int plen;
575
576 TCHECK(pptr[0]);
577 plen = pptr[0]; /* get prefix length */
578
579 plen-=32; /* adjust prefix length */
580
581 if (0 < plen)
582 return -1;
583
584 memset(&route_target, 0, sizeof(route_target));
585 TCHECK2(pptr[1], (plen + 7) / 8);
586 memcpy(&route_target, &pptr[1], (plen + 7) / 8);
587 if (plen % 8) {
588 ((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
589 ((0xff00 >> (plen % 8)) & 0xff);
590 }
591 snprintf(buf, buflen, "origin AS: %u, route target %s",
592 EXTRACT_32BITS(pptr+1),
593 bgp_vpn_rd_print((u_char *)&route_target));
594
595 return 5 + (plen + 7) / 8;
596
597 trunc:
598 return -2;
599 }
600
601 static int
602 decode_labeled_vpn_prefix4(const u_char *pptr, char *buf, u_int buflen)
603 {
604 struct in_addr addr;
605 u_int plen;
606
607 TCHECK(pptr[0]);
608 plen = pptr[0]; /* get prefix length */
609
610 plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
611
612 if (32 < plen)
613 return -1;
614
615 memset(&addr, 0, sizeof(addr));
616 TCHECK2(pptr[12], (plen + 7) / 8);
617 memcpy(&addr, &pptr[12], (plen + 7) / 8);
618 if (plen % 8) {
619 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
620 ((0xff00 >> (plen % 8)) & 0xff);
621 }
622 /* the label may get offsetted by 4 bits so lets shift it right */
623 snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
624 bgp_vpn_rd_print(pptr+4),
625 getname((u_char *)&addr),
626 plen,
627 EXTRACT_24BITS(pptr+1)>>4,
628 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
629
630 return 12 + (plen + 7) / 8;
631
632 trunc:
633 return -2;
634 }
635
636 static int
637 decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
638 {
639 int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len;
640
641 TCHECK2(pptr[0], 2);
642 plen=EXTRACT_16BITS(pptr);
643 tlen=plen;
644 pptr+=2;
645 TCHECK2(pptr[0],15);
646 strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
647 bgp_vpn_rd_print(pptr),
648 EXTRACT_16BITS(pptr+8),
649 EXTRACT_16BITS(pptr+10),
650 EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
651 pptr+=15;
652 tlen-=15;
653
654 /* ok now the variable part - lets read out TLVs*/
655 while (tlen>0) {
656 if (tlen < 3)
657 return -1;
658 TCHECK2(pptr[0], 3);
659 tlv_type=*pptr++;
660 tlv_len=EXTRACT_16BITS(pptr);
661 ttlv_len=tlv_len;
662 pptr+=2;
663
664 switch(tlv_type) {
665 case 1:
666 strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
667 tlv_type,
668 tlv_len);
669 ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
670 while (ttlv_len>0) {
671 TCHECK(pptr[0]);
672 strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
673 ttlv_len--;
674 }
675 break;
676 default:
677 snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u",
678 tlv_type,
679 tlv_len);
680 break;
681 }
682 tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
683 }
684 return plen+2;
685
686 trunc:
687 return -2;
688 }
689
690 #ifdef INET6
691 static int
692 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
693 {
694 struct in6_addr addr;
695 u_int plen;
696
697 TCHECK(pd[0]);
698 plen = pd[0];
699 if (128 < plen)
700 return -1;
701
702 memset(&addr, 0, sizeof(addr));
703 TCHECK2(pd[1], (plen + 7) / 8);
704 memcpy(&addr, &pd[1], (plen + 7) / 8);
705 if (plen % 8) {
706 addr.s6_addr[(plen + 7) / 8 - 1] &=
707 ((0xff00 >> (plen % 8)) & 0xff);
708 }
709 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
710 return 1 + (plen + 7) / 8;
711
712 trunc:
713 return -2;
714 }
715
716 static int
717 decode_labeled_prefix6(const u_char *pptr, char *buf, u_int buflen)
718 {
719 struct in6_addr addr;
720 u_int plen;
721
722 TCHECK(pptr[0]);
723 plen = pptr[0]; /* get prefix length */
724 plen-=24; /* adjust prefixlen - labellength */
725
726 if (128 < plen)
727 return -1;
728
729 memset(&addr, 0, sizeof(addr));
730 TCHECK2(pptr[4], (plen + 7) / 8);
731 memcpy(&addr, &pptr[4], (plen + 7) / 8);
732 if (plen % 8) {
733 addr.s6_addr[(plen + 7) / 8 - 1] &=
734 ((0xff00 >> (plen % 8)) & 0xff);
735 }
736 /* the label may get offsetted by 4 bits so lets shift it right */
737 snprintf(buf, buflen, "%s/%d, label:%u %s",
738 getname6((u_char *)&addr),
739 plen,
740 EXTRACT_24BITS(pptr+1)>>4,
741 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
742
743 return 4 + (plen + 7) / 8;
744
745 trunc:
746 return -2;
747 }
748
749 static int
750 decode_labeled_vpn_prefix6(const u_char *pptr, char *buf, u_int buflen)
751 {
752 struct in6_addr addr;
753 u_int plen;
754
755 TCHECK(pptr[0]);
756 plen = pptr[0]; /* get prefix length */
757
758 plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
759
760 if (128 < plen)
761 return -1;
762
763 memset(&addr, 0, sizeof(addr));
764 TCHECK2(pptr[12], (plen + 7) / 8);
765 memcpy(&addr, &pptr[12], (plen + 7) / 8);
766 if (plen % 8) {
767 addr.s6_addr[(plen + 7) / 8 - 1] &=
768 ((0xff00 >> (plen % 8)) & 0xff);
769 }
770 /* the label may get offsetted by 4 bits so lets shift it right */
771 snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
772 bgp_vpn_rd_print(pptr+4),
773 getname6((u_char *)&addr),
774 plen,
775 EXTRACT_24BITS(pptr+1)>>4,
776 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
777
778 return 12 + (plen + 7) / 8;
779
780 trunc:
781 return -2;
782 }
783 #endif
784
785 static int
786 bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
787 {
788 int i;
789 u_int16_t af;
790 u_int8_t safi, snpa;
791 union { /* copy buffer for bandwidth values */
792 float f;
793 u_int32_t i;
794 } bw;
795 int advance;
796 int tlen;
797 const u_char *tptr;
798 char buf[MAXHOSTNAMELEN + 100];
799
800 tptr = pptr;
801 tlen=len;
802
803 switch (attr->bgpa_type) {
804 case BGPTYPE_ORIGIN:
805 if (len != 1)
806 printf("invalid len");
807 else {
808 TCHECK(*tptr);
809 printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
810 }
811 break;
812 case BGPTYPE_AS_PATH:
813 if (len % 2) {
814 printf("invalid len");
815 break;
816 }
817 if (!len) {
818 printf("empty");
819 break;
820 }
821
822 while (tptr < pptr + len) {
823 TCHECK(tptr[0]);
824 printf("%s", tok2str(bgp_as_path_segment_open_values, "?", tptr[0]));
825 for (i = 0; i < tptr[1] * 2; i += 2) {
826 TCHECK2(tptr[2 + i], 2);
827 printf("%u ", EXTRACT_16BITS(&tptr[2 + i]));
828 }
829 TCHECK(tptr[0]);
830 printf("%s", tok2str(bgp_as_path_segment_close_values, "?", tptr[0]));
831 TCHECK(tptr[1]);
832 tptr += 2 + tptr[1] * 2;
833 }
834 break;
835 case BGPTYPE_NEXT_HOP:
836 if (len != 4)
837 printf("invalid len");
838 else {
839 TCHECK2(tptr[0], 4);
840 printf("%s", getname(tptr));
841 }
842 break;
843 case BGPTYPE_MULTI_EXIT_DISC:
844 case BGPTYPE_LOCAL_PREF:
845 if (len != 4)
846 printf("invalid len");
847 else {
848 TCHECK2(tptr[0], 4);
849 printf("%u", EXTRACT_32BITS(tptr));
850 }
851 break;
852 case BGPTYPE_ATOMIC_AGGREGATE:
853 if (len != 0)
854 printf("invalid len");
855 break;
856 case BGPTYPE_AGGREGATOR:
857 if (len != 6) {
858 printf("invalid len");
859 break;
860 }
861 TCHECK2(tptr[0], 6);
862 printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
863 getname(tptr + 2));
864 break;
865 case BGPTYPE_COMMUNITIES:
866 if (len % 4) {
867 printf("invalid len");
868 break;
869 }
870 while (tlen>0) {
871 u_int32_t comm;
872 TCHECK2(tptr[0], 4);
873 comm = EXTRACT_32BITS(tptr);
874 switch (comm) {
875 case BGP_COMMUNITY_NO_EXPORT:
876 printf(" NO_EXPORT");
877 break;
878 case BGP_COMMUNITY_NO_ADVERT:
879 printf(" NO_ADVERTISE");
880 break;
881 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
882 printf(" NO_EXPORT_SUBCONFED");
883 break;
884 default:
885 printf("%u:%u%s",
886 (comm >> 16) & 0xffff,
887 comm & 0xffff,
888 (tlen>4) ? ", " : "");
889 break;
890 }
891 tlen -=4;
892 tptr +=4;
893 }
894 break;
895 case BGPTYPE_ORIGINATOR_ID:
896 if (len != 4) {
897 printf("invalid len");
898 break;
899 }
900 TCHECK2(tptr[0], 4);
901 printf("%s",getname(tptr));
902 break;
903 case BGPTYPE_CLUSTER_LIST:
904 if (len % 4) {
905 printf("invalid len");
906 break;
907 }
908 while (tlen>0) {
909 TCHECK2(tptr[0], 4);
910 printf("%s%s",
911 getname(tptr),
912 (tlen>4) ? ", " : "");
913 tlen -=4;
914 tptr +=4;
915 }
916 break;
917 case BGPTYPE_MP_REACH_NLRI:
918 TCHECK2(tptr[0], 3);
919 af = EXTRACT_16BITS(tptr);
920 safi = tptr[2];
921
922 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
923 tok2str(bgp_afi_values, "Unknown AFI", af),
924 af,
925 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
926 tok2str(bgp_safi_values, "Unknown SAFI", safi),
927 safi);
928
929 if (af == AFNUM_INET || af==AFNUM_L2VPN)
930 ;
931 #ifdef INET6
932 else if (af == AFNUM_INET6)
933 ;
934 #endif
935 else {
936 printf("\n\t no AFI %u decoder",af);
937 if (vflag <= 1)
938 print_unknown_data(tptr,"\n\t ",tlen);
939 break;
940 }
941
942 tptr +=3;
943
944 TCHECK(tptr[0]);
945 tlen = tptr[0];
946 tptr++;
947
948 if (tlen) {
949 printf("\n\t nexthop: ");
950 while (tlen > 0) {
951 switch (af) {
952 case AFNUM_INET:
953 switch(safi) {
954 case SAFNUM_UNICAST:
955 case SAFNUM_MULTICAST:
956 case SAFNUM_UNIMULTICAST:
957 case SAFNUM_LABUNICAST:
958 case SAFNUM_RT_ROUTING_INFO:
959 if (tlen < (int)sizeof(struct in_addr)) {
960 printf("invalid len");
961 tlen = 0;
962 } else {
963 TCHECK2(tptr[0], sizeof(struct in_addr));
964 printf("%s",getname(tptr));
965 tlen -= sizeof(struct in_addr);
966 tptr += sizeof(struct in_addr);
967 }
968 break;
969 case SAFNUM_VPNUNICAST:
970 case SAFNUM_VPNMULTICAST:
971 case SAFNUM_VPNUNIMULTICAST:
972 if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
973 printf("invalid len");
974 tlen = 0;
975 } else {
976 TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
977 printf("RD: %s, %s",
978 bgp_vpn_rd_print(tptr),
979 getname(tptr+BGP_VPN_RD_LEN));
980 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
981 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
982 }
983 break;
984 default:
985 TCHECK2(tptr[0], tlen);
986 printf("no SAFI %u decoder",safi);
987 if (vflag <= 1)
988 print_unknown_data(tptr,"\n\t ",tlen);
989 tptr += tlen;
990 tlen = 0;
991 break;
992 }
993 break;
994 #ifdef INET6
995 case AFNUM_INET6:
996 switch(safi) {
997 case SAFNUM_UNICAST:
998 case SAFNUM_MULTICAST:
999 case SAFNUM_UNIMULTICAST:
1000 case SAFNUM_LABUNICAST:
1001 case SAFNUM_RT_ROUTING_INFO:
1002 if (tlen < (int)sizeof(struct in6_addr)) {
1003 printf("invalid len");
1004 tlen = 0;
1005 } else {
1006 TCHECK2(tptr[0], sizeof(struct in6_addr));
1007 printf("%s", getname6(tptr));
1008 tlen -= sizeof(struct in6_addr);
1009 tptr += sizeof(struct in6_addr);
1010 }
1011 break;
1012 case SAFNUM_VPNUNICAST:
1013 case SAFNUM_VPNMULTICAST:
1014 case SAFNUM_VPNUNIMULTICAST:
1015 if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1016 printf("invalid len");
1017 tlen = 0;
1018 } else {
1019 TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1020 printf("RD: %s, %s",
1021 bgp_vpn_rd_print(tptr),
1022 getname6(tptr+BGP_VPN_RD_LEN));
1023 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1024 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1025 }
1026 break;
1027 default:
1028 TCHECK2(tptr[0], tlen);
1029 printf("no SAFI %u decoder",safi);
1030 if (vflag <= 1)
1031 print_unknown_data(tptr,"\n\t ",tlen);
1032 tptr += tlen;
1033 tlen = 0;
1034 break;
1035 }
1036 break;
1037 #endif
1038 case AFNUM_L2VPN:
1039 switch(safi) {
1040 case SAFNUM_VPNUNICAST:
1041 case SAFNUM_VPNMULTICAST:
1042 case SAFNUM_VPNUNIMULTICAST:
1043 if (tlen < (int)sizeof(struct in_addr)) {
1044 printf("invalid len");
1045 tlen = 0;
1046 } else {
1047 TCHECK2(tptr[0], sizeof(struct in_addr));
1048 printf("%s", getname(tptr));
1049 tlen -= (sizeof(struct in_addr));
1050 tptr += (sizeof(struct in_addr));
1051 }
1052 break;
1053 default:
1054 TCHECK2(tptr[0], tlen);
1055 printf("no SAFI %u decoder",safi);
1056 if (vflag <= 1)
1057 print_unknown_data(tptr,"\n\t ",tlen);
1058 tptr += tlen;
1059 tlen = 0;
1060 break;
1061 }
1062 break;
1063
1064 default:
1065 TCHECK2(tptr[0], tlen);
1066 printf("no AFI %u decoder",af);
1067 if (vflag <= 1)
1068 print_unknown_data(tptr,"\n\t ",tlen);
1069 tptr += tlen;
1070 tlen = 0;
1071 break;
1072 }
1073 }
1074 }
1075 tptr += tlen;
1076
1077 TCHECK(tptr[0]);
1078 snpa = tptr[0];
1079 tptr++;
1080
1081 if (snpa) {
1082 printf("\n\t %u SNPA", snpa);
1083 for (/*nothing*/; snpa > 0; snpa--) {
1084 TCHECK(tptr[0]);
1085 printf("\n\t %d bytes", tptr[0]);
1086 tptr += tptr[0] + 1;
1087 }
1088 } else {
1089 printf(", no SNPA");
1090 }
1091
1092 while (len - (tptr - pptr) > 0) {
1093 switch (af) {
1094 case AFNUM_INET:
1095 switch (safi) {
1096 case SAFNUM_UNICAST:
1097 case SAFNUM_MULTICAST:
1098 case SAFNUM_UNIMULTICAST:
1099 advance = decode_prefix4(tptr, buf, sizeof(buf));
1100 if (advance == -1)
1101 printf("\n\t (illegal prefix length)");
1102 else if (advance == -2)
1103 goto trunc;
1104 else
1105 printf("\n\t %s", buf);
1106 break;
1107 case SAFNUM_LABUNICAST:
1108 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1109 if (advance == -1)
1110 printf("\n\t (illegal prefix length)");
1111 else if (advance == -2)
1112 goto trunc;
1113 else
1114 printf("\n\t %s", buf);
1115 break;
1116 case SAFNUM_VPNUNICAST:
1117 case SAFNUM_VPNMULTICAST:
1118 case SAFNUM_VPNUNIMULTICAST:
1119 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1120 if (advance == -1)
1121 printf("\n\t (illegal prefix length)");
1122 else if (advance == -2)
1123 goto trunc;
1124 else
1125 printf("\n\t %s", buf);
1126 break;
1127 case SAFNUM_RT_ROUTING_INFO:
1128 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1129 if (advance == -1)
1130 printf("\n\t (illegal prefix length)");
1131 else if (advance == -2)
1132 goto trunc;
1133 else
1134 printf("\n\t %s", buf);
1135 break;
1136 default:
1137 TCHECK2(*(tptr-3),tlen);
1138 printf("\n\t no SAFI %u decoder",safi);
1139 if (vflag <= 1)
1140 print_unknown_data(tptr-3,"\n\t ",tlen);
1141 advance = 0;
1142 tptr = pptr + len;
1143 break;
1144 }
1145 break;
1146 #ifdef INET6
1147 case AFNUM_INET6:
1148 switch (safi) {
1149 case SAFNUM_UNICAST:
1150 case SAFNUM_MULTICAST:
1151 case SAFNUM_UNIMULTICAST:
1152 advance = decode_prefix6(tptr, buf, sizeof(buf));
1153 if (advance == -1)
1154 printf("\n\t (illegal prefix length)");
1155 else if (advance == -2)
1156 goto trunc;
1157 else
1158 printf("\n\t %s", buf);
1159 break;
1160 case SAFNUM_LABUNICAST:
1161 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1162 if (advance == -1)
1163 printf("\n\t (illegal prefix length)");
1164 else if (advance == -2)
1165 goto trunc;
1166 else
1167 printf("\n\t %s", buf);
1168 break;
1169 case SAFNUM_VPNUNICAST:
1170 case SAFNUM_VPNMULTICAST:
1171 case SAFNUM_VPNUNIMULTICAST:
1172 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1173 if (advance == -1)
1174 printf("\n\t (illegal prefix length)");
1175 else if (advance == -2)
1176 goto trunc;
1177 else
1178 printf("\n\t %s", buf);
1179 break;
1180 case SAFNUM_RT_ROUTING_INFO:
1181 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1182 if (advance == -1)
1183 printf("\n\t (illegal prefix length)");
1184 else if (advance == -2)
1185 goto trunc;
1186 else
1187 printf("\n\t %s", buf);
1188 break;
1189 default:
1190 TCHECK2(*(tptr-3),tlen);
1191 printf("\n\t no SAFI %u decoder ",safi);
1192 if (vflag <= 1)
1193 print_unknown_data(tptr-3,"\n\t ",tlen);
1194 advance = 0;
1195 tptr = pptr + len;
1196 break;
1197 }
1198 break;
1199 #endif
1200 case AFNUM_L2VPN:
1201 switch(safi) {
1202 case SAFNUM_VPNUNICAST:
1203 case SAFNUM_VPNMULTICAST:
1204 case SAFNUM_VPNUNIMULTICAST:
1205 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1206 if (advance == -1)
1207 printf("\n\t (illegal length)");
1208 else if (advance == -2)
1209 goto trunc;
1210 else
1211 printf("\n\t %s", buf);
1212 break;
1213 default:
1214 TCHECK2(*tptr,tlen);
1215 printf("no SAFI %u decoder",safi);
1216 if (vflag <= 1)
1217 print_unknown_data(tptr,"\n\t ",tlen);
1218 advance = 0;
1219 tptr = pptr + len;
1220 break;
1221 }
1222 break;
1223
1224
1225 default:
1226 TCHECK2(*(tptr-3),tlen);
1227 printf("\n\t no AFI %u decoder ",af);
1228 if (vflag <= 1)
1229 print_unknown_data(tptr-3,"\n\t ",tlen);
1230 advance = 0;
1231 tptr = pptr + len;
1232 break;
1233 }
1234 tptr += advance;
1235 }
1236 break;
1237
1238 case BGPTYPE_MP_UNREACH_NLRI:
1239 TCHECK2(tptr[0], 3);
1240 af = EXTRACT_16BITS(tptr);
1241 safi = tptr[2];
1242
1243 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
1244 tok2str(bgp_afi_values, "Unknown AFI", af),
1245 af,
1246 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1247 tok2str(bgp_safi_values, "Unknown SAFI", safi),
1248 safi);
1249
1250 tptr += 3;
1251
1252 while (len - (tptr - pptr) > 0) {
1253 switch (af) {
1254 case AFNUM_INET:
1255 switch (safi) {
1256 case SAFNUM_UNICAST:
1257 case SAFNUM_MULTICAST:
1258 case SAFNUM_UNIMULTICAST:
1259 advance = decode_prefix4(tptr, buf, sizeof(buf));
1260 if (advance == -1)
1261 printf("\n\t (illegal prefix length)");
1262 else if (advance == -2)
1263 goto trunc;
1264 else
1265 printf("\n\t %s", buf);
1266 break;
1267 case SAFNUM_LABUNICAST:
1268 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1269 if (advance == -1)
1270 printf("\n\t (illegal prefix length)");
1271 else if (advance == -2)
1272 goto trunc;
1273 else
1274 printf("\n\t %s", buf);
1275 break;
1276 case SAFNUM_VPNUNICAST:
1277 case SAFNUM_VPNMULTICAST:
1278 case SAFNUM_VPNUNIMULTICAST:
1279 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1280 if (advance == -1)
1281 printf("\n\t (illegal prefix length)");
1282 else if (advance == -2)
1283 goto trunc;
1284 else
1285 printf("\n\t %s", buf);
1286 break;
1287 default:
1288 TCHECK2(*(tptr-3),tlen);
1289 printf("\n\t no SAFI %u decoder",safi);
1290 if (vflag <= 1)
1291 print_unknown_data(tptr-3,"\n\t ",tlen);
1292 advance = 0;
1293 tptr = pptr + len;
1294 break;
1295 }
1296 break;
1297
1298 #ifdef INET6
1299 case AFNUM_INET6:
1300 switch (safi) {
1301 case SAFNUM_UNICAST:
1302 case SAFNUM_MULTICAST:
1303 case SAFNUM_UNIMULTICAST:
1304 advance = decode_prefix6(tptr, buf, sizeof(buf));
1305 if (advance == -1)
1306 printf("\n\t (illegal prefix length)");
1307 else if (advance == -2)
1308 goto trunc;
1309 else
1310 printf("\n\t %s", buf);
1311 break;
1312 case SAFNUM_LABUNICAST:
1313 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1314 if (advance == -1)
1315 printf("\n\t (illegal prefix length)");
1316 else if (advance == -2)
1317 goto trunc;
1318 else
1319 printf("\n\t %s", buf);
1320 break;
1321 case SAFNUM_VPNUNICAST:
1322 case SAFNUM_VPNMULTICAST:
1323 case SAFNUM_VPNUNIMULTICAST:
1324 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1325 if (advance == -1)
1326 printf("\n\t (illegal prefix length)");
1327 else if (advance == -2)
1328 goto trunc;
1329 else
1330 printf("\n\t %s", buf);
1331 break;
1332 default:
1333 TCHECK2(*(tptr-3),tlen);
1334 printf("\n\t no SAFI %u decoder",safi);
1335 if (vflag <= 1)
1336 print_unknown_data(tptr-3,"\n\t ",tlen);
1337 advance = 0;
1338 tptr = pptr + len;
1339 break;
1340 }
1341 break;
1342 #endif
1343
1344 case AFNUM_L2VPN:
1345 switch(safi) {
1346 case SAFNUM_VPNUNICAST:
1347 case SAFNUM_VPNMULTICAST:
1348 case SAFNUM_VPNUNIMULTICAST:
1349 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1350 if (advance == -1)
1351 printf("\n\t (illegal length)");
1352 else if (advance == -2)
1353 goto trunc;
1354 else
1355 printf("\n\t %s", buf);
1356 break;
1357 default:
1358 TCHECK2(*(tptr-3),tlen);
1359 printf("no SAFI %u decoder",safi);
1360 if (vflag <= 1)
1361 print_unknown_data(tptr-3,"\n\t ",tlen);
1362 advance = 0;
1363 tptr = pptr + len;
1364 break;
1365 }
1366 break;
1367
1368 default:
1369 TCHECK2(*(tptr-3),tlen);
1370 printf("\n\t no AFI %u decoder",af);
1371 if (vflag <= 1)
1372 print_unknown_data(tptr-3,"\n\t ",tlen);
1373 advance = 0;
1374 tptr = pptr + len;
1375 break;
1376 }
1377
1378 tptr += advance;
1379 }
1380 break;
1381 case BGPTYPE_EXTD_COMMUNITIES:
1382 if (len % 8) {
1383 printf("invalid len");
1384 break;
1385 }
1386 while (tlen>0) {
1387 u_int16_t extd_comm;
1388
1389 TCHECK2(tptr[0], 2);
1390 extd_comm=EXTRACT_16BITS(tptr);
1391
1392 printf("\n\t %s (0x%04x), Flags [%s]",
1393 tok2str(bgp_extd_comm_subtype_values, "unknown extd community typecode", extd_comm),
1394 extd_comm,
1395 bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
1396
1397 TCHECK2(*(tptr+2), 6);
1398 switch(extd_comm) {
1399 case BGP_EXT_COM_RT_0:
1400 case BGP_EXT_COM_RO_0:
1401 printf(": %u:%s",
1402 EXTRACT_16BITS(tptr+2),
1403 getname(tptr+4));
1404 break;
1405 case BGP_EXT_COM_RT_1:
1406 case BGP_EXT_COM_RO_1:
1407 printf(": %s:%u",
1408 getname(tptr+2),
1409 EXTRACT_16BITS(tptr+6));
1410 break;
1411 case BGP_EXT_COM_RT_2:
1412 case BGP_EXT_COM_RO_2:
1413 printf(": %u:%u",
1414 EXTRACT_32BITS(tptr+2),
1415 EXTRACT_16BITS(tptr+6));
1416 break;
1417 case BGP_EXT_COM_LINKBAND:
1418 bw.i = EXTRACT_32BITS(tptr+2);
1419 printf(": bandwidth: %.3f Mbps",
1420 bw.f*8/1000000);
1421 break;
1422 case BGP_EXT_COM_CISCO_MCAST:
1423 printf(": AS %u, group %s",
1424 EXTRACT_16BITS(tptr+2),
1425 getname(tptr+4));
1426 break;
1427 case BGP_EXT_COM_VPN_ORIGIN:
1428 case BGP_EXT_COM_VPN_ORIGIN2:
1429 case BGP_EXT_COM_VPN_ORIGIN3:
1430 case BGP_EXT_COM_VPN_ORIGIN4:
1431 case BGP_EXT_COM_OSPF_RID:
1432 case BGP_EXT_COM_OSPF_RID2:
1433 printf("%s", getname(tptr+2));
1434 break;
1435 case BGP_EXT_COM_OSPF_RTYPE:
1436 case BGP_EXT_COM_OSPF_RTYPE2:
1437 printf(": area:%s, router-type:%s, metric-type:%s%s",
1438 getname(tptr+2),
1439 tok2str(bgp_extd_comm_ospf_rtype_values,
1440 "unknown (0x%02x)",
1441 *(tptr+6)),
1442 (*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
1443 (*(tptr+6) == (BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA )) ? "E1" : "");
1444 break;
1445 case BGP_EXT_COM_L2INFO:
1446 printf(": %s Control Flags [0x%02x]:MTU %u",
1447 tok2str(bgp_l2vpn_encaps_values,
1448 "unknown encaps",
1449 *(tptr+2)),
1450 *(tptr+3),
1451 EXTRACT_16BITS(tptr+4));
1452 break;
1453 default:
1454 print_unknown_data(tptr,"\n\t ",8);
1455 break;
1456 }
1457 tlen -=8;
1458 tptr +=8;
1459 }
1460 break;
1461
1462 case BGPTYPE_ATTR_SET:
1463 TCHECK2(tptr[0], 4);
1464 printf("\n\t Origin AS: %u", EXTRACT_32BITS(tptr));
1465 tptr+=4;
1466 len -=4;
1467
1468 while (len >= 2 ) {
1469 int alen;
1470 struct bgp_attr bgpa;
1471
1472 TCHECK2(tptr[0], sizeof(bgpa));
1473 memcpy(&bgpa, tptr, sizeof(bgpa));
1474 alen = bgp_attr_len(&bgpa);
1475 tptr += bgp_attr_off(&bgpa);
1476 len -= bgp_attr_off(&bgpa);
1477
1478 printf("\n\t %s (%u), length: %u",
1479 tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1480 bgpa.bgpa_type,
1481 alen);
1482
1483 if (bgpa.bgpa_flags) {
1484 printf(", Flags [%s%s%s%s",
1485 bgpa.bgpa_flags & 0x80 ? "O" : "",
1486 bgpa.bgpa_flags & 0x40 ? "T" : "",
1487 bgpa.bgpa_flags & 0x20 ? "P" : "",
1488 bgpa.bgpa_flags & 0x10 ? "E" : "");
1489 if (bgpa.bgpa_flags & 0xf)
1490 printf("+%x", bgpa.bgpa_flags & 0xf);
1491 printf("]: ");
1492 }
1493 /* FIXME check for recursion */
1494 if (!bgp_attr_print(&bgpa, tptr, alen))
1495 return 0;
1496 tptr += alen;
1497 len -= alen;
1498 }
1499 break;
1500
1501
1502 default:
1503 TCHECK2(*pptr,len);
1504 printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
1505 if (vflag <= 1)
1506 print_unknown_data(pptr,"\n\t ",len);
1507 break;
1508 }
1509 if (vflag > 1 && len) /* omit zero length attributes*/
1510 print_unknown_data(pptr,"\n\t ",len);
1511 return 1;
1512
1513 trunc:
1514 return 0;
1515 }
1516
1517 static void
1518 bgp_open_print(const u_char *dat, int length)
1519 {
1520 struct bgp_open bgpo;
1521 struct bgp_opt bgpopt;
1522 int hlen;
1523 const u_char *opt;
1524 int i,cap_type,cap_len,tcap_len,cap_offset;
1525
1526 TCHECK2(dat[0], BGP_OPEN_SIZE);
1527 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
1528 hlen = ntohs(bgpo.bgpo_len);
1529
1530 printf("\n\t Version %d, ", bgpo.bgpo_version);
1531 printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
1532 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
1533 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
1534 printf("\n\t Optional parameters, length: %u", bgpo.bgpo_optlen);
1535
1536 /* some little sanity checking */
1537 if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
1538 return;
1539
1540 /* ugly! */
1541 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
1542 opt++;
1543
1544 i = 0;
1545 while (i < bgpo.bgpo_optlen) {
1546 TCHECK2(opt[i], BGP_OPT_SIZE);
1547 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
1548 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
1549 printf("\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
1550 break;
1551 }
1552
1553 printf("\n\t Option %s (%u), length: %u",
1554 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
1555 bgpopt.bgpopt_type,
1556 bgpopt.bgpopt_len);
1557
1558 /* now lets decode the options we know*/
1559 switch(bgpopt.bgpopt_type) {
1560 case BGP_OPT_CAP:
1561 cap_type=opt[i+BGP_OPT_SIZE];
1562 cap_len=opt[i+BGP_OPT_SIZE+1];
1563 tcap_len=cap_len;
1564 printf("\n\t %s, length: %u",
1565 tok2str(bgp_capcode_values,"Unknown", cap_type),
1566 cap_len);
1567 switch(cap_type) {
1568 case BGP_CAPCODE_MP:
1569 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
1570 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
1571 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
1572 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
1573 opt[i+BGP_OPT_SIZE+5]);
1574 break;
1575 case BGP_CAPCODE_RESTART:
1576 printf("\n\t\tRestart Flags: [%s], Restart Time %us",
1577 ((opt[i+BGP_OPT_SIZE+2])&0x80) ? "R" : "none",
1578 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)&0xfff);
1579 tcap_len-=2;
1580 cap_offset=4;
1581 while(tcap_len>=4) {
1582 printf("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
1583 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset)),
1584 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
1585 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+cap_offset+2]),
1586 opt[i+BGP_OPT_SIZE+cap_offset+2],
1587 ((opt[i+BGP_OPT_SIZE+cap_offset+3])&0x80) ? "yes" : "no" );
1588 tcap_len-=4;
1589 cap_offset+=4;
1590 }
1591 break;
1592 case BGP_CAPCODE_RR:
1593 case BGP_CAPCODE_RR_CISCO:
1594 break;
1595 default:
1596 printf("\n\t\tno decoder for Capability %u",
1597 cap_type);
1598 if (vflag <= 1)
1599 print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1600 break;
1601 }
1602 if (vflag > 1)
1603 print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1604 break;
1605 case BGP_OPT_AUTH:
1606 default:
1607 printf("\n\t no decoder for option %u",
1608 bgpopt.bgpopt_type);
1609 break;
1610 }
1611
1612 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
1613 }
1614 return;
1615 trunc:
1616 printf("[|BGP]");
1617 }
1618
1619 static void
1620 bgp_update_print(const u_char *dat, int length)
1621 {
1622 struct bgp bgp;
1623 struct bgp_attr bgpa;
1624 int hlen;
1625 const u_char *p;
1626 int len;
1627 int i;
1628
1629 TCHECK2(dat[0], BGP_SIZE);
1630 memcpy(&bgp, dat, BGP_SIZE);
1631 hlen = ntohs(bgp.bgp_len);
1632 p = dat + BGP_SIZE; /*XXX*/
1633
1634 /* Unfeasible routes */
1635 len = EXTRACT_16BITS(p);
1636 if (len) {
1637 /*
1638 * Without keeping state from the original NLRI message,
1639 * it's not possible to tell if this a v4 or v6 route,
1640 * so only try to decode it if we're not v6 enabled.
1641 */
1642 #ifdef INET6
1643 printf("\n\t Withdrawn routes: %d bytes", len);
1644 #else
1645 char buf[MAXHOSTNAMELEN + 100];
1646 int wpfx;
1647
1648 TCHECK2(p[2], len);
1649 i = 2;
1650
1651 printf("\n\t Withdrawn routes:");
1652
1653 while(i < 2 + len) {
1654 wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
1655 if (wpfx == -1) {
1656 printf("\n\t (illegal prefix length)");
1657 break;
1658 } else if (wpfx == -2)
1659 goto trunc;
1660 else {
1661 i += wpfx;
1662 printf("\n\t %s", buf);
1663 }
1664 }
1665 #endif
1666 }
1667 p += 2 + len;
1668
1669 TCHECK2(p[0], 2);
1670 len = EXTRACT_16BITS(p);
1671 if (len) {
1672 /* do something more useful!*/
1673 i = 2;
1674 while (i < 2 + len) {
1675 int alen, aoff;
1676
1677 TCHECK2(p[i], sizeof(bgpa));
1678 memcpy(&bgpa, &p[i], sizeof(bgpa));
1679 alen = bgp_attr_len(&bgpa);
1680 aoff = bgp_attr_off(&bgpa);
1681
1682 printf("\n\t %s (%u), length: %u",
1683 tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1684 bgpa.bgpa_type,
1685 alen);
1686
1687 if (bgpa.bgpa_flags) {
1688 printf(", Flags [%s%s%s%s",
1689 bgpa.bgpa_flags & 0x80 ? "O" : "",
1690 bgpa.bgpa_flags & 0x40 ? "T" : "",
1691 bgpa.bgpa_flags & 0x20 ? "P" : "",
1692 bgpa.bgpa_flags & 0x10 ? "E" : "");
1693 if (bgpa.bgpa_flags & 0xf)
1694 printf("+%x", bgpa.bgpa_flags & 0xf);
1695 printf("]: ");
1696 }
1697 if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
1698 goto trunc;
1699 i += aoff + alen;
1700 }
1701 }
1702 p += 2 + len;
1703
1704 if (dat + length > p) {
1705 printf("\n\t Updated routes:");
1706 while (dat + length > p) {
1707 char buf[MAXHOSTNAMELEN + 100];
1708 i = decode_prefix4(p, buf, sizeof(buf));
1709 if (i == -1)
1710 printf("\n\t (illegal prefix length)");
1711 else if (i == -2)
1712 goto trunc;
1713 else {
1714 printf("\n\t %s", buf);
1715 p += i;
1716 }
1717 }
1718 }
1719 return;
1720 trunc:
1721 printf("[|BGP]");
1722 }
1723
1724 static void
1725 bgp_notification_print(const u_char *dat, int length)
1726 {
1727 struct bgp_notification bgpn;
1728 int hlen;
1729 const u_char *tptr;
1730
1731 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1732 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1733 hlen = ntohs(bgpn.bgpn_len);
1734
1735 /* some little sanity checking */
1736 if (length<BGP_NOTIFICATION_SIZE)
1737 return;
1738
1739 printf(", %s (%u)",
1740 tok2str(bgp_notify_major_values, "Unknown Error", bgpn.bgpn_major),
1741 bgpn.bgpn_major);
1742
1743 switch (bgpn.bgpn_major) {
1744
1745 case BGP_NOTIFY_MAJOR_MSG:
1746 printf(", subcode %s (%u)",
1747 tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor),
1748 bgpn.bgpn_minor);
1749 break;
1750 case BGP_NOTIFY_MAJOR_OPEN:
1751 printf(", subcode %s (%u)",
1752 tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor),
1753 bgpn.bgpn_minor);
1754 break;
1755 case BGP_NOTIFY_MAJOR_UPDATE:
1756 printf(", subcode %s (%u)",
1757 tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor),
1758 bgpn.bgpn_minor);
1759 break;
1760 case BGP_NOTIFY_MAJOR_CAP:
1761 printf(" subcode %s (%u)",
1762 tok2str(bgp_notify_minor_cap_values, "Unknown", bgpn.bgpn_minor),
1763 bgpn.bgpn_minor);
1764 case BGP_NOTIFY_MAJOR_CEASE:
1765 printf(", subcode %s (%u)",
1766 tok2str(bgp_notify_minor_cease_values, "Unknown", bgpn.bgpn_minor),
1767 bgpn.bgpn_minor);
1768
1769 /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
1770 * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
1771 */
1772 if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
1773 tptr = dat + BGP_NOTIFICATION_SIZE;
1774 TCHECK2(*tptr, 7);
1775 printf(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
1776 tok2str(bgp_afi_values, "Unknown", EXTRACT_16BITS(tptr)),
1777 EXTRACT_16BITS(tptr),
1778 tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
1779 *(tptr+2),
1780 EXTRACT_32BITS(tptr+3));
1781 }
1782 break;
1783 default:
1784 break;
1785 }
1786
1787 return;
1788 trunc:
1789 printf("[|BGP]");
1790 }
1791
1792 static void
1793 bgp_route_refresh_print(const u_char *pptr, int len) {
1794
1795 const struct bgp_route_refresh *bgp_route_refresh_header;
1796 bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
1797
1798 printf("\n\t AFI %s (%u), SAFI %s (%u)",
1799 tok2str(bgp_afi_values,"Unknown",
1800 EXTRACT_16BITS(&bgp_route_refresh_header->afi)), /* this stinks but the compiler pads the structure weird */
1801 EXTRACT_16BITS(&bgp_route_refresh_header->afi),
1802 tok2str(bgp_safi_values,"Unknown",
1803 bgp_route_refresh_header->safi),
1804 bgp_route_refresh_header->safi);
1805
1806 if (vflag > 1)
1807 print_unknown_data(pptr,"\n\t ", len);
1808
1809 return;
1810 }
1811
1812 static int
1813 bgp_header_print(const u_char *dat, int length)
1814 {
1815 struct bgp bgp;
1816
1817 TCHECK2(dat[0], BGP_SIZE);
1818 memcpy(&bgp, dat, BGP_SIZE);
1819 printf("\n\t%s Message (%u), length: %u",
1820 tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
1821 bgp.bgp_type,
1822 length);
1823
1824 switch (bgp.bgp_type) {
1825 case BGP_OPEN:
1826 bgp_open_print(dat, length);
1827 break;
1828 case BGP_UPDATE:
1829 bgp_update_print(dat, length);
1830 break;
1831 case BGP_NOTIFICATION:
1832 bgp_notification_print(dat, length);
1833 break;
1834 case BGP_KEEPALIVE:
1835 break;
1836 case BGP_ROUTE_REFRESH:
1837 bgp_route_refresh_print(dat, length);
1838 break;
1839 default:
1840 /* we have no decoder for the BGP message */
1841 printf("\n\t no Message %u decoder",bgp.bgp_type);
1842 print_unknown_data(dat,"\n\t ",length);
1843 break;
1844 }
1845 return 1;
1846 trunc:
1847 printf("[|BGP]");
1848 return 0;
1849 }
1850
1851 void
1852 bgp_print(const u_char *dat, int length)
1853 {
1854 const u_char *p;
1855 const u_char *ep;
1856 const u_char *start;
1857 const u_char marker[] = {
1858 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1859 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1860 };
1861 struct bgp bgp;
1862 u_int16_t hlen;
1863
1864 ep = dat + length;
1865 if (snapend < dat + length)
1866 ep = snapend;
1867
1868 printf(": BGP, length: %u",length);
1869
1870 if (vflag < 1) /* lets be less chatty */
1871 return;
1872
1873 p = dat;
1874 start = p;
1875 while (p < snapend) {
1876 if (!TTEST2(p[0], 1))
1877 break;
1878 if (p[0] != 0xff) {
1879 p++;
1880 continue;
1881 }
1882
1883 if (!TTEST2(p[0], sizeof(marker)))
1884 break;
1885 if (memcmp(p, marker, sizeof(marker)) != 0) {
1886 p++;
1887 continue;
1888 }
1889
1890 /* found BGP header */
1891 TCHECK2(p[0], BGP_SIZE); /*XXX*/
1892 memcpy(&bgp, p, BGP_SIZE);
1893
1894 if (start != p)
1895 printf(" [|BGP]");
1896
1897 hlen = ntohs(bgp.bgp_len);
1898 if (hlen < BGP_SIZE) {
1899 printf("\n[|BGP Bogus header length %u < %u]", hlen,
1900 BGP_SIZE);
1901 break;
1902 }
1903
1904 if (TTEST2(p[0], hlen)) {
1905 if (!bgp_header_print(p, hlen))
1906 return;
1907 p += hlen;
1908 start = p;
1909 } else {
1910 printf("\n[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
1911 break;
1912 }
1913 }
1914
1915 return;
1916
1917 trunc:
1918 printf(" [|BGP]");
1919 }