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