]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
verify/warn icmpv6 checksum. from jinmei@kame
[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[] =
39 "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.61 2003-02-11 06:28:39 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 /* data should follow */
100 };
101 #define BGP_NOTIFICATION_SIZE 21 /* unaligned */
102
103 struct bgp_route_refresh {
104 u_int8_t bgp_marker[16];
105 u_int16_t len;
106 u_int8_t type;
107 u_int8_t afi[2]; /* the compiler messes this structure up */
108 u_int8_t res; /* when doing misaligned sequences of int8 and int16 */
109 u_int8_t safi; /* afi should be int16 - so we have to access it using */
110 }; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */
111 #define BGP_ROUTE_REFRESH_SIZE 23
112
113 struct bgp_attr {
114 u_int8_t bgpa_flags;
115 u_int8_t bgpa_type;
116 union {
117 u_int8_t len;
118 u_int16_t elen;
119 } bgpa_len;
120 #define bgp_attr_len(p) \
121 (((p)->bgpa_flags & 0x10) ? \
122 EXTRACT_16BITS(&(p)->bgpa_len.elen) : (p)->bgpa_len.len)
123 #define bgp_attr_off(p) \
124 (((p)->bgpa_flags & 0x10) ? 4 : 3)
125 };
126
127 #define BGPTYPE_ORIGIN 1
128 #define BGPTYPE_AS_PATH 2
129 #define BGPTYPE_NEXT_HOP 3
130 #define BGPTYPE_MULTI_EXIT_DISC 4
131 #define BGPTYPE_LOCAL_PREF 5
132 #define BGPTYPE_ATOMIC_AGGREGATE 6
133 #define BGPTYPE_AGGREGATOR 7
134 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
135 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */
136 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */
137 #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */
138 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */
139 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */
140 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
141 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
142 #define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */
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 { 255, "Reserved for development"},
162 { 0, NULL}
163 };
164
165 #define BGP_OPT_AUTH 1
166 #define BGP_OPT_CAP 2
167
168
169 static struct tok bgp_opt_values[] = {
170 { BGP_OPT_AUTH, "Authentication Information"},
171 { BGP_OPT_CAP, "Capabilities Advertisement"},
172 { 0, NULL}
173 };
174
175 #define BGP_CAPCODE_MP 1
176 #define BGP_CAPCODE_RR 2
177 #define BGP_CAPCODE_RESTART 64 /* draft-ietf-idr-restart-05 */
178 #define BGP_CAPCODE_RR_CISCO 128
179
180 static struct tok bgp_capcode_values[] = {
181 { BGP_CAPCODE_MP, "Multiprotocol Extensions"},
182 { BGP_CAPCODE_RR, "Route Refresh"},
183 { BGP_CAPCODE_RESTART, "Graceful Restart"},
184 { BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"},
185 { 0, NULL}
186 };
187
188 #define BGP_NOTIFY_MAJOR_MSG 1
189 #define BGP_NOTIFY_MAJOR_OPEN 2
190 #define BGP_NOTIFY_MAJOR_UPDATE 3
191 #define BGP_NOTIFY_MAJOR_HOLDTIME 4
192 #define BGP_NOTIFY_MAJOR_FSM 5
193 #define BGP_NOTIFY_MAJOR_CEASE 6
194
195 static struct tok bgp_notify_major_values[] = {
196 { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"},
197 { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"},
198 { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"},
199 { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
200 { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"},
201 { BGP_NOTIFY_MAJOR_CEASE, "Cease"},
202 { 0, NULL}
203 };
204
205 static struct tok bgp_notify_minor_msg_values[] = {
206 { 1, "Connection Not Synchronized"},
207 { 2, "Bad Message Length"},
208 { 3, "Bad Message Type"},
209 { 0, NULL}
210 };
211
212 static struct tok bgp_notify_minor_open_values[] = {
213 { 1, "Unsupported Version Number"},
214 { 2, "Bad Peer AS"},
215 { 3, "Bad BGP Identifier"},
216 { 4, "Unsupported Optional Parameter"},
217 { 5, "Authentication Failure"},
218 { 6, "Unacceptable Hold Time"},
219 { 0, NULL}
220 };
221
222 static struct tok bgp_notify_minor_update_values[] = {
223 { 1, "Malformed Attribute List"},
224 { 2, "Unrecognized Well-known Attribute"},
225 { 3, "Missing Well-known Attribute"},
226 { 4, "Attribute Flags Error"},
227 { 5, "Attribute Length Error"},
228 { 6, "Invalid ORIGIN Attribute"},
229 { 7, "AS Routing Loop"},
230 { 8, "Invalid NEXT_HOP Attribute"},
231 { 9, "Optional Attribute Error"},
232 { 10, "Invalid Network Field"},
233 { 11, "Malformed AS_PATH"},
234 { 0, NULL}
235 };
236
237 static struct tok bgp_origin_values[] = {
238 { 0, "IGP"},
239 { 1, "EGP"},
240 { 2, "Incomplete"},
241 { 0, NULL}
242 };
243
244 /* Subsequent address family identifier, RFC2283 section 7 */
245 #define SAFNUM_RES 0
246 #define SAFNUM_UNICAST 1
247 #define SAFNUM_MULTICAST 2
248 #define SAFNUM_UNIMULTICAST 3
249 /* labeled BGP RFC3107 */
250 #define SAFNUM_LABUNICAST 4
251 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */
252 #define SAFNUM_VPNUNICAST 128
253 #define SAFNUM_VPNMULTICAST 129
254 #define SAFNUM_VPNUNIMULTICAST 130
255
256 #define BGP_VPN_RD_LEN 8
257
258 static struct tok bgp_safi_values[] = {
259 { SAFNUM_RES, "Reserved"},
260 { SAFNUM_UNICAST, "Unicast"},
261 { SAFNUM_MULTICAST, "Multicast"},
262 { SAFNUM_UNIMULTICAST, "Unicast+Multicast"},
263 { SAFNUM_LABUNICAST, "labeled Unicast"},
264 { SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
265 { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
266 { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
267 { 0, NULL }
268 };
269
270 /* well-known community */
271 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01
272 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02
273 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
274
275 /* RFC1700 address family numbers */
276 #define AFNUM_INET 1
277 #define AFNUM_INET6 2
278 #define AFNUM_NSAP 3
279 #define AFNUM_HDLC 4
280 #define AFNUM_BBN1822 5
281 #define AFNUM_802 6
282 #define AFNUM_E163 7
283 #define AFNUM_E164 8
284 #define AFNUM_F69 9
285 #define AFNUM_X121 10
286 #define AFNUM_IPX 11
287 #define AFNUM_ATALK 12
288 #define AFNUM_DECNET 13
289 #define AFNUM_BANYAN 14
290 #define AFNUM_E164NSAP 15
291 /* draft-kompella-ppvpn-l2vpn */
292 #define AFNUM_L2VPN 196 /* still to be approved by IANA */
293
294 static struct tok bgp_afi_values[] = {
295 { 0, "Reserved"},
296 { AFNUM_INET, "IPv4"},
297 { AFNUM_INET6, "IPv6"},
298 { AFNUM_NSAP, "NSAP"},
299 { AFNUM_HDLC, "HDLC"},
300 { AFNUM_BBN1822, "BBN 1822"},
301 { AFNUM_802, "802"},
302 { AFNUM_E163, "E.163"},
303 { AFNUM_E164, "E.164"},
304 { AFNUM_F69, "F.69"},
305 { AFNUM_X121, "X.121"},
306 { AFNUM_IPX, "Novell IPX"},
307 { AFNUM_ATALK, "Appletalk"},
308 { AFNUM_DECNET, "Decnet IV"},
309 { AFNUM_BANYAN, "Banyan Vines"},
310 { AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
311 { AFNUM_L2VPN, "Layer-2 VPN"},
312 { 0, NULL},
313 };
314
315 /* Extended community type - draft-ramachandra-bgp-ext-communities */
316 #define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */
317 #define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */
318 #define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */
319 #define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */
320 #define BGP_EXT_COM_LINKBAND 0x4004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
321 /* rfc2547 bgp-mpls-vpns */
322
323 #define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domain ID / VPN of Origin - draft-rosen-vpns-ospf-bgp-mpls */
324 #define BGP_EXT_COM_VPN_ORIGIN2 0x0105 /* duplicate - keep for backwards compatability */
325 #define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatability */
326 #define BGP_EXT_COM_VPN_ORIGIN4 0x8005 /* duplicate - keep for backwards compatability */
327
328 #define BGP_EXT_COM_OSPF_RTYPE 0x0306 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
329 #define BGP_EXT_COM_OSPF_RTYPE2 0x8000 /* duplicate - keep for backwards compatability */
330
331 #define BGP_EXT_COM_OSPF_RID 0x0107 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
332 #define BGP_EXT_COM_OSPF_RID2 0x8001 /* duplicate - keep for backwards compatability */
333
334 #define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
335
336 static struct tok bgp_extd_comm_subtype_values[] = {
337 { BGP_EXT_COM_RT_0, "target"},
338 { BGP_EXT_COM_RT_1, "target"},
339 { BGP_EXT_COM_RO_0, "origin"},
340 { BGP_EXT_COM_RO_1, "origin"},
341 { BGP_EXT_COM_LINKBAND, "link-BW"},
342 { BGP_EXT_COM_VPN_ORIGIN, "ospf-domain"},
343 { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
344 { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
345 { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
346 { BGP_EXT_COM_OSPF_RTYPE, "ospf-route-type"},
347 { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
348 { BGP_EXT_COM_OSPF_RID, "ospf-router-id"},
349 { BGP_EXT_COM_OSPF_RID2, "ospf-router-id"},
350 { BGP_EXT_COM_L2INFO, "layer2-info"},
351 { 0, NULL},
352 };
353
354 /* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */
355 #define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */
356 #define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */
357 #define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */
358 #define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
359 #define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/
360 #define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */
361 #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
362
363 static struct tok bgp_extd_comm_ospf_rtype_values[] = {
364 { BGP_OSPF_RTYPE_RTR, "Router" },
365 { BGP_OSPF_RTYPE_NET, "Network" },
366 { BGP_OSPF_RTYPE_SUM, "Summary" },
367 { BGP_OSPF_RTYPE_EXT, "External" },
368 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
369 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
370 { 0, NULL },
371 };
372
373 static struct tok bgp_l2vpn_encaps_values[] = {
374 { 0, "Reserved"},
375 { 1, "Frame Relay"},
376 { 2, "ATM AAL5 VCC transport"},
377 { 3, "ATM transparent cell transport"},
378 { 4, "Ethernet VLAN"},
379 { 5, "Ethernet"},
380 { 6, "Cisco-HDLC"},
381 { 7, "PPP"},
382 { 8, "CEM"},
383 { 9, "ATM VCC cell transport"},
384 { 10, "ATM VPC cell transport"},
385 { 11, "MPLS"},
386 { 12, "VPLS"},
387 { 64, "IP-interworking"},
388 { 0, NULL},
389 };
390
391 static int
392 decode_prefix4(const u_char *pptr, char *buf, u_int buflen)
393 {
394 struct in_addr addr;
395 u_int plen;
396
397 plen = pptr[0];
398 if (32 < plen)
399 return -1;
400
401 memset(&addr, 0, sizeof(addr));
402 memcpy(&addr, &pptr[1], (plen + 7) / 8);
403 if (plen % 8) {
404 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
405 ((0xff00 >> (plen % 8)) & 0xff);
406 }
407 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
408 return 1 + (plen + 7) / 8;
409 }
410
411 static int
412 decode_labeled_prefix4(const u_char *pptr, char *buf, u_int buflen)
413 {
414 struct in_addr addr;
415 u_int plen;
416
417 plen = pptr[0]; /* get prefix length */
418
419 /* this is one of the weirdnesses of rfc3107
420 the label length (actually the label + COS bits)
421 is added to the prefix length;
422 we also do only read out just one label -
423 there is no real application for advertisement of
424 stacked labels in a a single BGP message
425 */
426
427 plen-=24; /* adjust prefixlen - labellength */
428
429 if (32 < plen)
430 return -1;
431
432 memset(&addr, 0, sizeof(addr));
433 memcpy(&addr, &pptr[4], (plen + 7) / 8);
434 if (plen % 8) {
435 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
436 ((0xff00 >> (plen % 8)) & 0xff);
437 }
438 /* the label may get offsetted by 4 bits so lets shift it right */
439 snprintf(buf, buflen, "%s/%d, label:%u %s",
440 getname((u_char *)&addr),
441 plen,
442 EXTRACT_24BITS(pptr+1)>>4,
443 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
444
445 return 4 + (plen + 7) / 8;
446 }
447
448 static char *
449 bgp_vpn_rd_print (const u_char *pptr) {
450
451 /* allocate space for the following string
452 * xxx.xxx.xxx.xxx:xxxxx
453 * 21 bytes plus one termination byte */
454 static char rd[22];
455 char *pos = rd;
456
457 /* ok lets load the RD format */
458 switch (EXTRACT_16BITS(pptr)) {
459 /* AS:IP-address fmt*/
460 case 0:
461 sprintf(pos, "%u:%u.%u.%u.%u",
462 EXTRACT_16BITS(pptr+2),
463 *(pptr+4),
464 *(pptr+5),
465 *(pptr+6),
466 *(pptr+7));
467 break;
468 /* IP-address:AS fmt*/
469 case 1:
470 sprintf(pos, "%u.%u.%u.%u:%u",
471 *(pptr+2),
472 *(pptr+3),
473 *(pptr+4),
474 *(pptr+5),
475 EXTRACT_16BITS(pptr+6));
476 break;
477 default:
478 sprintf(pos, "unknown RD format");
479 break;
480 }
481 pos+=strlen(pos);
482 *(pos) = '\0';
483 return (rd);
484 }
485
486 static int
487 decode_labeled_vpn_prefix4(const u_char *pptr, char *buf, u_int buflen)
488 {
489 struct in_addr addr;
490 u_int plen;
491
492 plen = pptr[0]; /* get prefix length */
493
494 plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
495
496 if (32 < plen)
497 return -1;
498
499 memset(&addr, 0, sizeof(addr));
500 memcpy(&addr, &pptr[12], (plen + 7) / 8);
501 if (plen % 8) {
502 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
503 ((0xff00 >> (plen % 8)) & 0xff);
504 }
505 /* the label may get offsetted by 4 bits so lets shift it right */
506 snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
507 bgp_vpn_rd_print(pptr+4),
508 getname((u_char *)&addr),
509 plen,
510 EXTRACT_24BITS(pptr+1)>>4,
511 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
512
513 return 12 + (plen + 7) / 8;
514 }
515
516 static int
517 decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
518 {
519 int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len;
520 plen=EXTRACT_16BITS(pptr);
521 tlen=plen;
522 pptr+=2;
523 strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
524 bgp_vpn_rd_print(pptr),
525 EXTRACT_16BITS(pptr+8),
526 EXTRACT_16BITS(pptr+10),
527 EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
528 pptr+=15;
529 tlen-=15;
530
531 /* ok now the variable part - lets read out TLVs*/
532 while (tlen>0) {
533 tlv_type=*pptr++;
534 tlv_len=EXTRACT_16BITS(pptr);
535 ttlv_len=tlv_len;
536 pptr+=2;
537
538 switch(tlv_type) {
539 case 1:
540 strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
541 tlv_type,
542 tlv_len);
543 ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
544 while (ttlv_len>0) {
545 strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
546 ttlv_len--;
547 }
548 break;
549 default:
550 snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u",
551 tlv_type,
552 tlv_len);
553 break;
554 }
555 tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
556 }
557 return plen+2;
558 }
559
560 #ifdef INET6
561 static int
562 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
563 {
564 struct in6_addr addr;
565 u_int plen;
566
567 plen = pd[0];
568 if (128 < plen)
569 return -1;
570
571 memset(&addr, 0, sizeof(addr));
572 memcpy(&addr, &pd[1], (plen + 7) / 8);
573 if (plen % 8) {
574 addr.s6_addr[(plen + 7) / 8 - 1] &=
575 ((0xff00 >> (plen % 8)) & 0xff);
576 }
577 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
578 return 1 + (plen + 7) / 8;
579 }
580
581 static int
582 decode_labeled_prefix6(const u_char *pptr, char *buf, u_int buflen)
583 {
584 struct in6_addr addr;
585 u_int plen;
586
587 plen = pptr[0]; /* get prefix length */
588 plen-=24; /* adjust prefixlen - labellength */
589
590 if (128 < plen)
591 return -1;
592
593 memset(&addr, 0, sizeof(addr));
594 memcpy(&addr, &pptr[4], (plen + 7) / 8);
595 if (plen % 8) {
596 addr.s6_addr[(plen + 7) / 8 - 1] &=
597 ((0xff00 >> (plen % 8)) & 0xff);
598 }
599 /* the label may get offsetted by 4 bits so lets shift it right */
600 snprintf(buf, buflen, "%s/%d, label:%u %s",
601 getname6((u_char *)&addr),
602 plen,
603 EXTRACT_24BITS(pptr+1)>>4,
604 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
605
606 return 4 + (plen + 7) / 8;
607 }
608
609 static int
610 decode_labeled_vpn_prefix6(const u_char *pptr, char *buf, u_int buflen)
611 {
612 struct in6_addr addr;
613 u_int plen;
614
615 plen = pptr[0]; /* get prefix length */
616
617 plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
618
619 if (128 < plen)
620 return -1;
621
622 memset(&addr, 0, sizeof(addr));
623 memcpy(&addr, &pptr[12], (plen + 7) / 8);
624 if (plen % 8) {
625 addr.s6_addr[(plen + 7) / 8 - 1] &=
626 ((0xff00 >> (plen % 8)) & 0xff);
627 }
628 /* the label may get offsetted by 4 bits so lets shift it right */
629 snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
630 bgp_vpn_rd_print(pptr+4),
631 getname6((u_char *)&addr),
632 plen,
633 EXTRACT_24BITS(pptr+1)>>4,
634 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
635
636 return 12 + (plen + 7) / 8;
637 }
638 #endif
639
640 static void
641 bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
642 {
643 int i;
644 u_int16_t af;
645 u_int8_t safi, snpa;
646 float bw; /* copy buffer for bandwidth values */
647 int advance;
648 int tlen;
649 const u_char *tptr;
650 char buf[MAXHOSTNAMELEN + 100];
651
652 tptr = pptr;
653 tlen=len;
654
655 switch (attr->bgpa_type) {
656 case BGPTYPE_ORIGIN:
657 if (len != 1)
658 printf("invalid len");
659 else
660 printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
661 break;
662 case BGPTYPE_AS_PATH:
663 if (len % 2) {
664 printf("invalid len");
665 break;
666 }
667 if (!len) {
668 printf("empty");
669 break;
670 }
671 while (tptr < pptr + len) {
672 /*
673 * under RFC1965, p[0] means:
674 * 1: AS_SET 2: AS_SEQUENCE
675 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
676 */
677 if (tptr[0] == 3 || tptr[0] == 4)
678 printf("confed");
679 printf("%s", (tptr[0] & 1) ? "{" : "");
680 for (i = 0; i < tptr[1] * 2; i += 2) {
681 printf("%s%u", i == 0 ? "" : " ",
682 EXTRACT_16BITS(&tptr[2 + i]));
683 }
684 printf("%s", (tptr[0] & 1) ? "}" : "");
685 tptr += 2 + tptr[1] * 2;
686 }
687 break;
688 case BGPTYPE_NEXT_HOP:
689 if (len != 4)
690 printf("invalid len");
691 else
692 printf("%s", getname(tptr));
693 break;
694 case BGPTYPE_MULTI_EXIT_DISC:
695 case BGPTYPE_LOCAL_PREF:
696 if (len != 4)
697 printf("invalid len");
698 else
699 printf("%u", EXTRACT_32BITS(tptr));
700 break;
701 case BGPTYPE_ATOMIC_AGGREGATE:
702 if (len != 0)
703 printf("invalid len");
704 break;
705 case BGPTYPE_AGGREGATOR:
706 if (len != 6) {
707 printf("invalid len");
708 break;
709 }
710 printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
711 getname(tptr + 2));
712 break;
713 case BGPTYPE_COMMUNITIES:
714 if (len % 4) {
715 printf("invalid len");
716 break;
717 }
718 while (tlen>0) {
719 u_int32_t comm;
720 comm = EXTRACT_32BITS(tptr);
721 switch (comm) {
722 case BGP_COMMUNITY_NO_EXPORT:
723 printf(" NO_EXPORT");
724 break;
725 case BGP_COMMUNITY_NO_ADVERT:
726 printf(" NO_ADVERTISE");
727 break;
728 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
729 printf(" NO_EXPORT_SUBCONFED");
730 break;
731 default:
732 printf("%u:%u%s",
733 (comm >> 16) & 0xffff,
734 comm & 0xffff,
735 (tlen>4) ? ", " : "");
736 break;
737 }
738 tlen -=4;
739 tptr +=4;
740 }
741 break;
742 case BGPTYPE_ORIGINATOR_ID:
743 if (len != 4) {
744 printf("invalid len");
745 break;
746 }
747 printf("%s",getname(tptr));
748 break;
749 case BGPTYPE_CLUSTER_LIST:
750 while (tlen>0) {
751 printf("%s%s",
752 getname(tptr),
753 (tlen>4) ? ", " : "");
754 tlen -=4;
755 tptr +=4;
756 }
757 break;
758 case BGPTYPE_MP_REACH_NLRI:
759 af = EXTRACT_16BITS(tptr);
760 safi = tptr[2];
761
762 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
763 tok2str(bgp_afi_values, "Unknown AFI", af),
764 af,
765 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
766 tok2str(bgp_safi_values, "Unknown SAFI", safi),
767 safi);
768
769 if (af == AFNUM_INET || af==AFNUM_L2VPN)
770 ;
771 #ifdef INET6
772 else if (af == AFNUM_INET6)
773 ;
774 #endif
775 else {
776 printf("\n\t no AFI %u decoder",af);
777 if (vflag <= 1)
778 print_unknown_data(tptr,"\n\t ",tlen);
779 break;
780 }
781
782 tptr +=3;
783
784 tlen = tptr[0];
785 tptr++;
786
787 if (tlen) {
788 printf("\n\t nexthop: ");
789 while (tlen > 0) {
790 switch (af) {
791 case AFNUM_INET:
792 switch(safi) {
793 case SAFNUM_UNICAST:
794 case SAFNUM_MULTICAST:
795 case SAFNUM_UNIMULTICAST:
796 case SAFNUM_LABUNICAST:
797 printf("%s",getname(tptr));
798 tlen -= sizeof(struct in_addr);
799 tptr += sizeof(struct in_addr);
800 break;
801 case SAFNUM_VPNUNICAST:
802 case SAFNUM_VPNMULTICAST:
803 case SAFNUM_VPNUNIMULTICAST:
804 printf("RD: %s, %s",
805 bgp_vpn_rd_print(tptr),
806 getname(tptr+BGP_VPN_RD_LEN));
807 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
808 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
809 break;
810 default:
811 printf("no SAFI %u decoder",safi);
812 if (vflag <= 1)
813 print_unknown_data(tptr,"\n\t ",tlen);
814 break;
815 }
816 break;
817 #ifdef INET6
818 case AFNUM_INET6:
819 switch(safi) {
820 case SAFNUM_UNICAST:
821 case SAFNUM_MULTICAST:
822 case SAFNUM_UNIMULTICAST:
823 case SAFNUM_LABUNICAST:
824 printf("%s", getname6(tptr));
825 tlen -= sizeof(struct in6_addr);
826 tptr += sizeof(struct in6_addr);
827 break;
828 case SAFNUM_VPNUNICAST:
829 case SAFNUM_VPNMULTICAST:
830 case SAFNUM_VPNUNIMULTICAST:
831 printf("RD: %s, %s",
832 bgp_vpn_rd_print(tptr),
833 getname6(tptr+BGP_VPN_RD_LEN));
834 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
835 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
836 break;
837 default:
838 printf("no SAFI %u decoder",safi);
839 if (vflag <= 1)
840 print_unknown_data(tptr,"\n\t ",tlen);
841 break;
842 }
843 break;
844 #endif
845 case AFNUM_L2VPN:
846 switch(safi) {
847 case SAFNUM_VPNUNICAST:
848 case SAFNUM_VPNMULTICAST:
849 case SAFNUM_VPNUNIMULTICAST:
850 printf("%s", getname(tptr));
851 tlen -= (sizeof(struct in_addr));
852 tptr += (sizeof(struct in_addr));
853 break;
854 default:
855 printf("no SAFI %u decoder",safi);
856 if (vflag <= 1)
857 print_unknown_data(tptr,"\n\t ",tlen);
858 break;
859 }
860 break;
861
862 default:
863 printf("no AFI %u decoder",af);
864 if (vflag <= 1)
865 print_unknown_data(tptr,"\n\t ",tlen);
866 break;
867 }
868 }
869 }
870 tptr += tlen;
871
872 snpa = tptr[0];
873 tptr++;
874
875 if (snpa) {
876 printf("\n\t %u SNPA", snpa);
877 for (/*nothing*/; snpa > 0; snpa--) {
878 printf("\n\t %d bytes", tptr[0]);
879 tptr += tptr[0] + 1;
880 }
881 } else {
882 printf(", no SNPA");
883 }
884
885 while (len - (tptr - pptr) > 0) {
886 switch (af) {
887 case AFNUM_INET:
888 switch (safi) {
889 case SAFNUM_UNICAST:
890 case SAFNUM_MULTICAST:
891 case SAFNUM_UNIMULTICAST:
892 advance = decode_prefix4(tptr, buf, sizeof(buf));
893 if (advance >= 0)
894 printf("\n\t %s", buf);
895 else
896 printf("\n\t (illegal prefix length)");
897 break;
898 case SAFNUM_LABUNICAST:
899 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
900 printf("\n\t %s", buf);
901 break;
902 case SAFNUM_VPNUNICAST:
903 case SAFNUM_VPNMULTICAST:
904 case SAFNUM_VPNUNIMULTICAST:
905 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
906 printf("\n\t %s", buf);
907 break;
908 default:
909 printf("\n\t no SAFI %u decoder",safi);
910 if (vflag <= 1)
911 print_unknown_data(tptr-3,"\n\t ",tlen);
912 advance = 0;
913 tptr = pptr + len;
914 break;
915 }
916 break;
917 #ifdef INET6
918 case AFNUM_INET6:
919 switch (safi) {
920 case SAFNUM_UNICAST:
921 case SAFNUM_MULTICAST:
922 case SAFNUM_UNIMULTICAST:
923 advance = decode_prefix6(tptr, buf, sizeof(buf));
924 printf("\n\t %s", buf);
925 break;
926 case SAFNUM_LABUNICAST:
927 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
928 printf("\n\t %s", buf);
929 break;
930 case SAFNUM_VPNUNICAST:
931 case SAFNUM_VPNMULTICAST:
932 case SAFNUM_VPNUNIMULTICAST:
933 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
934 printf("\n\t %s", buf);
935 break;
936 default:
937 printf("\n\t no SAFI %u decoder ",safi);
938 if (vflag <= 1)
939 print_unknown_data(tptr-3,"\n\t ",tlen);
940 advance = 0;
941 tptr = pptr + len;
942 break;
943 }
944 break;
945 #endif
946 case AFNUM_L2VPN:
947 switch(safi) {
948 case SAFNUM_VPNUNICAST:
949 case SAFNUM_VPNMULTICAST:
950 case SAFNUM_VPNUNIMULTICAST:
951 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
952 printf("\n\t %s", buf);
953 break;
954 default:
955 printf("no SAFI %u decoder",safi);
956 if (vflag <= 1)
957 print_unknown_data(tptr,"\n\t ",tlen);
958 advance = 0;
959 tptr = pptr + len;
960 break;
961 }
962 break;
963
964
965 default:
966 printf("\n\t no AFI %u decoder ",af);
967 if (vflag <= 1)
968 print_unknown_data(tptr-3,"\n\t ",tlen);
969 advance = 0;
970 tptr = pptr + len;
971 break;
972 }
973 tptr += advance;
974 }
975 break;
976
977 case BGPTYPE_MP_UNREACH_NLRI:
978 af = EXTRACT_16BITS(tptr);
979 safi = tptr[2];
980
981 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
982 tok2str(bgp_afi_values, "Unknown AFI", af),
983 af,
984 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
985 tok2str(bgp_safi_values, "Unknown SAFI", safi),
986 safi);
987
988 tptr += 3;
989
990 while (len - (tptr - pptr) > 0) {
991 switch (af) {
992 case AFNUM_INET:
993 switch (safi) {
994 case SAFNUM_UNICAST:
995 case SAFNUM_MULTICAST:
996 case SAFNUM_UNIMULTICAST:
997 advance = decode_prefix4(tptr, buf, sizeof(buf));
998 if (advance >= 0)
999 printf("\n\t %s", buf);
1000 else
1001 printf("\n\t (illegal prefix length)");
1002 break;
1003 case SAFNUM_LABUNICAST:
1004 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1005 printf("\n\t %s", buf);
1006 break;
1007 case SAFNUM_VPNUNICAST:
1008 case SAFNUM_VPNMULTICAST:
1009 case SAFNUM_VPNUNIMULTICAST:
1010 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1011 printf("\n\t %s", buf);
1012 break;
1013 default:
1014 printf("\n\t no SAFI %u decoder",safi);
1015 if (vflag <= 1)
1016 print_unknown_data(tptr-3,"\n\t ",tlen);
1017 advance = 0;
1018 tptr = pptr + len;
1019 break;
1020 }
1021 break;
1022
1023 #ifdef INET6
1024 case AFNUM_INET6:
1025 switch (safi) {
1026 case SAFNUM_UNICAST:
1027 case SAFNUM_MULTICAST:
1028 case SAFNUM_UNIMULTICAST:
1029 advance = decode_prefix6(tptr, buf, sizeof(buf));
1030 printf("\n\t %s", buf);
1031 break;
1032 case SAFNUM_LABUNICAST:
1033 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1034 printf("\n\t %s", buf);
1035 break;
1036 case SAFNUM_VPNUNICAST:
1037 case SAFNUM_VPNMULTICAST:
1038 case SAFNUM_VPNUNIMULTICAST:
1039 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1040 printf("\n\t %s", buf);
1041 break;
1042 default:
1043 printf("\n\t no SAFI %u decoder",safi);
1044 if (vflag <= 1)
1045 print_unknown_data(tptr-3,"\n\t ",tlen);
1046 advance = 0;
1047 tptr = pptr + len;
1048 break;
1049 }
1050 break;
1051 #endif
1052
1053 case AFNUM_L2VPN:
1054 switch(safi) {
1055 case SAFNUM_VPNUNICAST:
1056 case SAFNUM_VPNMULTICAST:
1057 case SAFNUM_VPNUNIMULTICAST:
1058 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1059 printf("\n\t %s", buf);
1060 break;
1061 default:
1062 printf("no SAFI %u decoder",safi);
1063 if (vflag <= 1)
1064 print_unknown_data(tptr-3,"\n\t ",tlen);
1065 advance = 0;
1066 tptr = pptr + len;
1067 break;
1068 }
1069 break;
1070
1071 default:
1072 printf("\n\t no AFI %u decoder",af);
1073 if (vflag <= 1)
1074 print_unknown_data(tptr-3,"\n\t ",tlen);
1075 advance = 0;
1076 tptr = pptr + len;
1077 break;
1078 }
1079
1080 tptr += advance;
1081 }
1082 break;
1083 case BGPTYPE_EXTD_COMMUNITIES:
1084 if (len % 8) {
1085 printf("invalid len");
1086 break;
1087 }
1088 while (tlen>0) {
1089 u_int16_t extd_comm;
1090 extd_comm=EXTRACT_16BITS(tptr);
1091 switch(extd_comm) {
1092 case BGP_EXT_COM_RT_0:
1093 case BGP_EXT_COM_RO_0:
1094 printf("\n\t %s%s%s(0x%04x):%u:%s",
1095 (extd_comm&0x8000) ? "vendor-specific: " : "",
1096 (extd_comm&0x4000) ? "non-transitive: " : "",
1097 tok2str(bgp_extd_comm_subtype_values,
1098 "unknown",
1099 extd_comm),
1100 extd_comm,
1101 EXTRACT_16BITS(tptr+2),
1102 getname(tptr+4));
1103 break;
1104 case BGP_EXT_COM_RT_1:
1105 case BGP_EXT_COM_RO_1:
1106 printf("\n\t %s%s%s(0x%04x):%s:%u",
1107 (extd_comm&0x8000) ? "vendor-specific: " : "",
1108 (extd_comm&0x4000) ? "non-transitive: " : "",
1109 tok2str(bgp_extd_comm_subtype_values,
1110 "unknown",
1111 extd_comm),
1112 extd_comm,
1113 getname(tptr+2),
1114 EXTRACT_16BITS(tptr+6));
1115 break;
1116 case BGP_EXT_COM_LINKBAND:
1117 memcpy (&bw, tptr+2, 4);
1118 printf("\n\t %s%s%s(0x%04x):bandwidth: %.3f Mbps",
1119 (extd_comm&0x8000) ? "vendor-specific: " : "",
1120 (extd_comm&0x4000) ? "non-transitive: " : "",
1121 tok2str(bgp_extd_comm_subtype_values,
1122 "unknown",
1123 extd_comm),
1124 extd_comm,
1125 bw*8/1000000);
1126 break;
1127 case BGP_EXT_COM_VPN_ORIGIN:
1128 case BGP_EXT_COM_VPN_ORIGIN2:
1129 case BGP_EXT_COM_VPN_ORIGIN3:
1130 case BGP_EXT_COM_VPN_ORIGIN4:
1131 case BGP_EXT_COM_OSPF_RID:
1132 case BGP_EXT_COM_OSPF_RID2:
1133 printf("\n\t %s%s%s(0x%04x):%s",
1134 (extd_comm&0x8000) ? "vendor-specific: " : "",
1135 (extd_comm&0x4000) ? "non-transitive: " : "",
1136 tok2str(bgp_extd_comm_subtype_values,
1137 "unknown",
1138 extd_comm),
1139 extd_comm,
1140 getname(tptr+2));
1141 break;
1142 case BGP_EXT_COM_OSPF_RTYPE:
1143 case BGP_EXT_COM_OSPF_RTYPE2:
1144 printf("\n\t %s%s%s(0x%04x), area:%s, router-type:%s, metric-type:%s%s",
1145 (extd_comm&0x8000) ? "vendor-specific: " : "",
1146 (extd_comm&0x4000) ? "non-transitive: " : "",
1147 tok2str(bgp_extd_comm_subtype_values,
1148 "unknown",
1149 extd_comm),
1150 extd_comm,
1151 getname(tptr+2),
1152 tok2str(bgp_extd_comm_ospf_rtype_values,
1153 "unknown (0x%02x)",
1154 *(tptr+6)),
1155 (*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
1156 (*(tptr+6) == (BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA )) ? "E1" : "");
1157 break;
1158 case BGP_EXT_COM_L2INFO:
1159 printf("\n\t %s%s(0x%04x):%s Control Flags [0x%02x]:MTU %u",
1160 (extd_comm&0x4000) ? "non-transitive: " : "",
1161 tok2str(bgp_extd_comm_subtype_values,
1162 "unknown",
1163 extd_comm),
1164 extd_comm,
1165 tok2str(bgp_l2vpn_encaps_values,
1166 "unknown encaps",
1167 *(tptr+2)),
1168 *(tptr+3),
1169 EXTRACT_16BITS(tptr+4));
1170 break;
1171 default:
1172 printf("\n\t unknown extd community typecode (0x%04x)",
1173 extd_comm);
1174 print_unknown_data(tptr,"\n\t ",8);
1175 break;
1176 }
1177 tlen -=8;
1178 tptr +=8;
1179 }
1180 break;
1181
1182 default:
1183 printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
1184 if (vflag <= 1)
1185 print_unknown_data(pptr,"\n\t ",len);
1186 break;
1187 }
1188 if (vflag > 1 && len) /* omit zero length attributes*/
1189 print_unknown_data(pptr,"\n\t ",len);
1190 }
1191
1192 static void
1193 bgp_open_print(const u_char *dat, int length)
1194 {
1195 struct bgp_open bgpo;
1196 struct bgp_opt bgpopt;
1197 int hlen;
1198 const u_char *opt;
1199 int i,cap_type,cap_len,tcap_len,cap_offset;
1200
1201 TCHECK2(dat[0], BGP_OPEN_SIZE);
1202 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
1203 hlen = ntohs(bgpo.bgpo_len);
1204
1205 printf("\n\t Version %d, ", bgpo.bgpo_version);
1206 printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
1207 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
1208 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
1209 printf("\n\t Optional parameters, length: %u", bgpo.bgpo_optlen);
1210
1211 /* some little sanity checking */
1212 if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
1213 return;
1214
1215 /* ugly! */
1216 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
1217 opt++;
1218
1219 i = 0;
1220 while (i < bgpo.bgpo_optlen) {
1221 TCHECK2(opt[i], BGP_OPT_SIZE);
1222 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
1223 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
1224 printf("\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
1225 break;
1226 }
1227
1228 printf("\n\t Option %s (%u), length: %u",
1229 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
1230 bgpopt.bgpopt_type,
1231 bgpopt.bgpopt_len);
1232
1233 /* now lets decode the options we know*/
1234 switch(bgpopt.bgpopt_type) {
1235 case BGP_OPT_CAP:
1236 cap_type=opt[i+BGP_OPT_SIZE];
1237 cap_len=opt[i+BGP_OPT_SIZE+1];
1238 tcap_len=cap_len;
1239 printf("\n\t %s, length: %u",
1240 tok2str(bgp_capcode_values,"Unknown", cap_type),
1241 cap_len);
1242 switch(cap_type) {
1243 case BGP_CAPCODE_MP:
1244 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
1245 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
1246 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
1247 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
1248 opt[i+BGP_OPT_SIZE+5]);
1249 break;
1250 case BGP_CAPCODE_RESTART:
1251 printf("\n\t\tRestart Flags: [%s], Restart Time %us",
1252 ((opt[i+BGP_OPT_SIZE+2])&0x80) ? "R" : "none",
1253 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)&0xfff);
1254 tcap_len-=2;
1255 cap_offset=4;
1256 while(tcap_len>=4) {
1257 printf("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
1258 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset)),
1259 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
1260 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+cap_offset+2]),
1261 opt[i+BGP_OPT_SIZE+cap_offset+2],
1262 ((opt[i+BGP_OPT_SIZE+cap_offset+3])&0x80) ? "yes" : "no" );
1263 tcap_len-=4;
1264 cap_offset+=4;
1265 }
1266 break;
1267 case BGP_CAPCODE_RR:
1268 case BGP_CAPCODE_RR_CISCO:
1269 break;
1270 default:
1271 printf("\n\t\tno decoder for Capability %u",
1272 cap_type);
1273 if (vflag <= 1)
1274 print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1275 break;
1276 }
1277 if (vflag > 1)
1278 print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1279 break;
1280 case BGP_OPT_AUTH:
1281 default:
1282 printf("\n\t no decoder for option %u",
1283 bgpopt.bgpopt_type);
1284 break;
1285 }
1286
1287 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
1288 }
1289 return;
1290 trunc:
1291 printf("[|BGP]");
1292 }
1293
1294 static void
1295 bgp_update_print(const u_char *dat, int length)
1296 {
1297 struct bgp bgp;
1298 struct bgp_attr bgpa;
1299 int hlen;
1300 const u_char *p;
1301 int len;
1302 int i;
1303
1304 TCHECK2(dat[0], BGP_SIZE);
1305 memcpy(&bgp, dat, BGP_SIZE);
1306 hlen = ntohs(bgp.bgp_len);
1307 p = dat + BGP_SIZE; /*XXX*/
1308
1309 /* Unfeasible routes */
1310 len = EXTRACT_16BITS(p);
1311 if (len) {
1312 /*
1313 * Without keeping state from the original NLRI message,
1314 * it's not possible to tell if this a v4 or v6 route,
1315 * so only try to decode it if we're not v6 enabled.
1316 */
1317 #ifdef INET6
1318 printf("\n\t Withdrawn routes: %d bytes", len);
1319 #else
1320 char buf[MAXHOSTNAMELEN + 100];
1321 int wpfx;
1322
1323 TCHECK2(p[2], len);
1324 i = 2;
1325
1326 printf("\n\t Withdrawn routes:");
1327
1328 while(i < 2 + len) {
1329 wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
1330 if (wpfx >= 0) {
1331 i += wpfx;
1332 printf("\n\t %s", buf);
1333 } else {
1334 printf("\n\t (illegal prefix length)");
1335 break;
1336 }
1337 }
1338 #endif
1339 }
1340 p += 2 + len;
1341
1342 TCHECK2(p[0], 2);
1343 len = EXTRACT_16BITS(p);
1344 if (len) {
1345 /* do something more useful!*/
1346 i = 2;
1347 while (i < 2 + len) {
1348 int alen, aoff;
1349
1350 TCHECK2(p[i], sizeof(bgpa));
1351 memcpy(&bgpa, &p[i], sizeof(bgpa));
1352 alen = bgp_attr_len(&bgpa);
1353 aoff = bgp_attr_off(&bgpa);
1354
1355 printf("\n\t %s (%u), length: %u",
1356 tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1357 bgpa.bgpa_type,
1358 alen);
1359
1360 if (bgpa.bgpa_flags) {
1361 printf(", flags [%s%s%s%s",
1362 bgpa.bgpa_flags & 0x80 ? "O" : "",
1363 bgpa.bgpa_flags & 0x40 ? "T" : "",
1364 bgpa.bgpa_flags & 0x20 ? "P" : "",
1365 bgpa.bgpa_flags & 0x10 ? "E" : "");
1366 if (bgpa.bgpa_flags & 0xf)
1367 printf("+%x", bgpa.bgpa_flags & 0xf);
1368 printf("]: ");
1369 }
1370 bgp_attr_print(&bgpa, &p[i + aoff], alen);
1371 i += aoff + alen;
1372 }
1373 }
1374 p += 2 + len;
1375
1376 if (dat + length > p) {
1377 printf("\n\t Updated routes:");
1378 while (dat + length > p) {
1379 char buf[MAXHOSTNAMELEN + 100];
1380 i = decode_prefix4(p, buf, sizeof(buf));
1381 if (i >= 0) {
1382 printf("\n\t %s", buf);
1383 p += i;
1384 } else {
1385 printf("\n\t (illegal prefix length)");
1386 break;
1387 }
1388 }
1389 }
1390 return;
1391 trunc:
1392 printf("[|BGP]");
1393 }
1394
1395 static void
1396 bgp_notification_print(const u_char *dat, int length)
1397 {
1398 struct bgp_notification bgpn;
1399 int hlen;
1400
1401 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1402 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1403 hlen = ntohs(bgpn.bgpn_len);
1404
1405 /* some little sanity checking */
1406 if (length<BGP_NOTIFICATION_SIZE)
1407 return;
1408
1409 printf(", Error - %s", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
1410
1411 switch (bgpn.bgpn_major) {
1412
1413 case BGP_NOTIFY_MAJOR_MSG:
1414 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
1415 break;
1416 case BGP_NOTIFY_MAJOR_OPEN:
1417 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
1418 break;
1419 case BGP_NOTIFY_MAJOR_UPDATE:
1420 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
1421 break;
1422 default:
1423 break;
1424 }
1425
1426 return;
1427 trunc:
1428 printf("[|BGP]");
1429 }
1430
1431 static void
1432 bgp_route_refresh_print(const u_char *pptr, int len) {
1433
1434 const struct bgp_route_refresh *bgp_route_refresh_header;
1435 bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
1436
1437 printf("\n\t AFI %s (%u), SAFI %s (%u)",
1438 tok2str(bgp_afi_values,"Unknown",
1439 EXTRACT_16BITS(&bgp_route_refresh_header->afi)), /* this stinks but the compiler pads the structure weird */
1440 EXTRACT_16BITS(&bgp_route_refresh_header->afi),
1441 tok2str(bgp_safi_values,"Unknown",
1442 bgp_route_refresh_header->safi),
1443 bgp_route_refresh_header->safi);
1444
1445 if (vflag > 1)
1446 print_unknown_data(pptr,"\n\t ", len);
1447
1448 return;
1449 }
1450
1451 static void
1452 bgp_header_print(const u_char *dat, int length)
1453 {
1454 struct bgp bgp;
1455
1456 TCHECK2(dat[0], BGP_SIZE);
1457 memcpy(&bgp, dat, BGP_SIZE);
1458 printf("\n\t%s Message (%u), length: %u",
1459 tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
1460 bgp.bgp_type,
1461 length);
1462
1463 switch (bgp.bgp_type) {
1464 case BGP_OPEN:
1465 bgp_open_print(dat, length);
1466 break;
1467 case BGP_UPDATE:
1468 bgp_update_print(dat, length);
1469 break;
1470 case BGP_NOTIFICATION:
1471 bgp_notification_print(dat, length);
1472 break;
1473 case BGP_KEEPALIVE:
1474 break;
1475 case BGP_ROUTE_REFRESH:
1476 bgp_route_refresh_print(dat, length);
1477 break;
1478 default:
1479 /* we have no decoder for the BGP message */
1480 printf("\n\t no Message %u decoder",bgp.bgp_type);
1481 print_unknown_data(dat,"\n\t ",length);
1482 break;
1483 }
1484 return;
1485 trunc:
1486 printf("[|BGP]");
1487 }
1488
1489 void
1490 bgp_print(const u_char *dat, int length)
1491 {
1492 const u_char *p;
1493 const u_char *ep;
1494 const u_char *start;
1495 const u_char marker[] = {
1496 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1497 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1498 };
1499 struct bgp bgp;
1500 u_int16_t hlen;
1501
1502 ep = dat + length;
1503 if (snapend < dat + length)
1504 ep = snapend;
1505
1506 printf(": BGP, length: %u",length);
1507
1508 if (vflag < 1) /* lets be less chatty */
1509 return;
1510
1511 p = dat;
1512 start = p;
1513 while (p < snapend) {
1514 if (!TTEST2(p[0], 1))
1515 break;
1516 if (p[0] != 0xff) {
1517 p++;
1518 continue;
1519 }
1520
1521 if (!TTEST2(p[0], sizeof(marker)))
1522 break;
1523 if (memcmp(p, marker, sizeof(marker)) != 0) {
1524 p++;
1525 continue;
1526 }
1527
1528 /* found BGP header */
1529 TCHECK2(p[0], BGP_SIZE); /*XXX*/
1530 memcpy(&bgp, p, BGP_SIZE);
1531
1532 if (start != p)
1533 printf(" [|BGP]");
1534
1535 hlen = ntohs(bgp.bgp_len);
1536
1537 if (TTEST2(p[0], hlen)) {
1538 bgp_header_print(p, hlen);
1539 p += hlen;
1540 start = p;
1541 } else {
1542 printf("\n[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
1543 break;
1544 }
1545 }
1546
1547 return;
1548
1549 trunc:
1550 printf(" [|BGP]");
1551 }
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562