]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
ported large parts of ethereal extended community decoder to tcpdump;
[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.48 2002-08-24 13:55:31 hannes Exp $";
40 #endif
41
42 #include <tcpdump-stdinc.h>
43
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "interface.h"
48 #include "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 (plen < 0 || 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 (plen < 0 || 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 (plen < 0 || 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 int advance;
574 int tlen;
575 const u_char *tptr;
576 char buf[MAXHOSTNAMELEN + 100];
577
578 tptr = pptr;
579 tlen=len;
580
581 switch (attr->bgpa_type) {
582 case BGPTYPE_ORIGIN:
583 if (len != 1)
584 printf("invalid len");
585 else
586 printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
587 break;
588 case BGPTYPE_AS_PATH:
589 if (len % 2) {
590 printf("invalid len");
591 break;
592 }
593 if (!len) {
594 printf("empty");
595 break;
596 }
597 while (tptr < pptr + len) {
598 /*
599 * under RFC1965, p[0] means:
600 * 1: AS_SET 2: AS_SEQUENCE
601 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
602 */
603 if (tptr[0] == 3 || tptr[0] == 4)
604 printf("confed");
605 printf("%s", (tptr[0] & 1) ? "{" : "");
606 for (i = 0; i < tptr[1] * 2; i += 2) {
607 printf("%s%u", i == 0 ? "" : " ",
608 EXTRACT_16BITS(&tptr[2 + i]));
609 }
610 printf("%s", (tptr[0] & 1) ? "}" : "");
611 tptr += 2 + tptr[1] * 2;
612 }
613 break;
614 case BGPTYPE_NEXT_HOP:
615 if (len != 4)
616 printf("invalid len");
617 else
618 printf("%s", getname(tptr));
619 break;
620 case BGPTYPE_MULTI_EXIT_DISC:
621 case BGPTYPE_LOCAL_PREF:
622 if (len != 4)
623 printf("invalid len");
624 else
625 printf("%u", EXTRACT_32BITS(tptr));
626 break;
627 case BGPTYPE_ATOMIC_AGGREGATE:
628 if (len != 0)
629 printf("invalid len");
630 break;
631 case BGPTYPE_AGGREGATOR:
632 if (len != 6) {
633 printf("invalid len");
634 break;
635 }
636 printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
637 getname(tptr + 2));
638 break;
639 case BGPTYPE_COMMUNITIES:
640 if (len % 4) {
641 printf("invalid len");
642 break;
643 }
644 while (tlen>0) {
645 u_int32_t comm;
646 comm = EXTRACT_32BITS(tptr);
647 switch (comm) {
648 case BGP_COMMUNITY_NO_EXPORT:
649 printf(" NO_EXPORT");
650 break;
651 case BGP_COMMUNITY_NO_ADVERT:
652 printf(" NO_ADVERTISE");
653 break;
654 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
655 printf(" NO_EXPORT_SUBCONFED");
656 break;
657 default:
658 printf("%u:%u%s",
659 (comm >> 16) & 0xffff,
660 comm & 0xffff,
661 (tlen>4) ? ", " : "");
662 break;
663 }
664 tlen -=4;
665 tptr +=4;
666 }
667 break;
668 case BGPTYPE_ORIGINATOR_ID:
669 if (len != 4) {
670 printf("invalid len");
671 break;
672 }
673 printf("%s",getname(tptr));
674 break;
675 case BGPTYPE_CLUSTER_LIST:
676 while (tlen>0) {
677 printf("%s%s",
678 getname(tptr),
679 (tlen>4) ? ", " : "");
680 tlen -=4;
681 tptr +=4;
682 }
683 break;
684 case BGPTYPE_MP_REACH_NLRI:
685 af = EXTRACT_16BITS(tptr);
686 safi = tptr[2];
687
688 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
689 tok2str(bgp_afi_values, "Unknown AFI", af),
690 af,
691 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
692 tok2str(bgp_safi_values, "Unknown SAFI", safi),
693 safi);
694
695 if (af == AFNUM_INET || af==AFNUM_L2VPN)
696 ;
697 #ifdef INET6
698 else if (af == AFNUM_INET6)
699 ;
700 #endif
701 else {
702 printf("\n\t no AFI %u decoder",af);
703 if (!vflag)
704 print_unknown_data(tptr,"\n\t ",tlen);
705 break;
706 }
707
708 tptr +=3;
709
710 tlen = tptr[0];
711 tptr++;
712
713 if (tlen) {
714 printf("\n\t nexthop: ");
715 while (tlen > 0) {
716 switch (af) {
717 case AFNUM_INET:
718 switch(safi) {
719 case SAFNUM_UNICAST:
720 case SAFNUM_MULTICAST:
721 case SAFNUM_UNIMULTICAST:
722 case SAFNUM_LABUNICAST:
723 printf("%s",getname(tptr));
724 tlen -= sizeof(struct in_addr);
725 tptr += sizeof(struct in_addr);
726 break;
727 case SAFNUM_VPNUNICAST:
728 case SAFNUM_VPNMULTICAST:
729 case SAFNUM_VPNUNIMULTICAST:
730 printf("RD: %s, %s",
731 bgp_vpn_rd_print(tptr),
732 getname(tptr+BGP_VPN_RD_LEN));
733 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
734 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
735 break;
736 default:
737 printf("no SAFI %u decoder",safi);
738 if (!vflag)
739 print_unknown_data(tptr,"\n\t ",tlen);
740 break;
741 }
742 break;
743 #ifdef INET6
744 case AFNUM_INET6:
745 switch(safi) {
746 case SAFNUM_UNICAST:
747 case SAFNUM_MULTICAST:
748 case SAFNUM_UNIMULTICAST:
749 case SAFNUM_LABUNICAST:
750 printf("%s", getname6(tptr));
751 tlen -= sizeof(struct in6_addr);
752 tptr += sizeof(struct in6_addr);
753 break;
754 case SAFNUM_VPNUNICAST:
755 case SAFNUM_VPNMULTICAST:
756 case SAFNUM_VPNUNIMULTICAST:
757 printf("RD: %s, %s",
758 bgp_vpn_rd_print(tptr),
759 getname6(tptr+BGP_VPN_RD_LEN));
760 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
761 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
762 break;
763 default:
764 printf("no SAFI %u decoder",safi);
765 if (!vflag)
766 print_unknown_data(tptr,"\n\t ",tlen);
767 break;
768 }
769 break;
770 #endif
771 case AFNUM_L2VPN:
772 switch(safi) {
773 case SAFNUM_VPNUNICAST:
774 case SAFNUM_VPNMULTICAST:
775 case SAFNUM_VPNUNIMULTICAST:
776 printf("%s", getname(tptr));
777 tlen -= (sizeof(struct in_addr));
778 tptr += (sizeof(struct in_addr));
779 break;
780 default:
781 printf("no SAFI %u decoder",safi);
782 if (!vflag)
783 print_unknown_data(tptr,"\n\t ",tlen);
784 break;
785 }
786 break;
787
788 default:
789 printf("no AFI %u decoder",af);
790 if (!vflag)
791 print_unknown_data(tptr,"\n\t ",tlen);
792 break;
793 }
794 }
795 }
796 tptr += tlen;
797
798 snpa = tptr[0];
799 tptr++;
800
801 if (snpa) {
802 printf("\n\t %u SNPA", snpa);
803 for (/*nothing*/; snpa > 0; snpa--) {
804 printf("\n\t %d bytes", tptr[0]);
805 tptr += tptr[0] + 1;
806 }
807 } else {
808 printf(", no SNPA");
809 }
810
811 while (len - (tptr - pptr) > 0) {
812 switch (af) {
813 case AFNUM_INET:
814 switch (safi) {
815 case SAFNUM_UNICAST:
816 case SAFNUM_MULTICAST:
817 case SAFNUM_UNIMULTICAST:
818 advance = decode_prefix4(tptr, buf, sizeof(buf));
819 printf("\n\t %s", buf);
820 break;
821 case SAFNUM_LABUNICAST:
822 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
823 printf("\n\t %s", buf);
824 break;
825 case SAFNUM_VPNUNICAST:
826 case SAFNUM_VPNMULTICAST:
827 case SAFNUM_VPNUNIMULTICAST:
828 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
829 printf("\n\t %s", buf);
830 break;
831 default:
832 printf("\n\t no SAFI %u decoder",safi);
833 if (!vflag)
834 print_unknown_data(tptr-3,"\n\t ",tlen);
835 advance = 0;
836 tptr = pptr + len;
837 break;
838 }
839 break;
840 #ifdef INET6
841 case AFNUM_INET6:
842 switch (safi) {
843 case SAFNUM_UNICAST:
844 case SAFNUM_MULTICAST:
845 case SAFNUM_UNIMULTICAST:
846 advance = decode_prefix6(tptr, buf, sizeof(buf));
847 printf("\n\t %s", buf);
848 break;
849 default:
850 printf("\n\t no SAFI %u decoder ",safi);
851 if (!vflag)
852 print_unknown_data(tptr-3,"\n\t ",tlen);
853 advance = 0;
854 tptr = pptr + len;
855 break;
856 }
857 break;
858 #endif
859 case AFNUM_L2VPN:
860 switch(safi) {
861 case SAFNUM_VPNUNICAST:
862 case SAFNUM_VPNMULTICAST:
863 case SAFNUM_VPNUNIMULTICAST:
864 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
865 printf("\n\t %s", buf);
866 break;
867 default:
868 printf("no SAFI %u decoder",safi);
869 if (!vflag)
870 print_unknown_data(tptr,"\n\t ",tlen);
871 advance = 0;
872 tptr = pptr + len;
873 break;
874 }
875 break;
876
877
878 default:
879 printf("\n\t no AFI %u decoder ",af);
880 if (!vflag)
881 print_unknown_data(tptr-3,"\n\t ",tlen);
882 advance = 0;
883 tptr = pptr + len;
884 break;
885 }
886 tptr += advance;
887 }
888 break;
889
890 case BGPTYPE_MP_UNREACH_NLRI:
891 af = EXTRACT_16BITS(tptr);
892 safi = tptr[2];
893
894 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
895 tok2str(bgp_afi_values, "Unknown AFI", af),
896 af,
897 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
898 tok2str(bgp_safi_values, "Unknown SAFI", safi),
899 safi);
900
901 tptr += 3;
902
903 while (len - (tptr - pptr) > 0) {
904 switch (af) {
905 case AFNUM_INET:
906 switch (safi) {
907 case SAFNUM_UNICAST:
908 case SAFNUM_MULTICAST:
909 case SAFNUM_UNIMULTICAST:
910 advance = decode_prefix4(tptr, buf, sizeof(buf));
911 printf("\n\t %s", buf);
912 break;
913 case SAFNUM_LABUNICAST:
914 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
915 printf("\n\t %s", buf);
916 break;
917 case SAFNUM_VPNUNICAST:
918 case SAFNUM_VPNMULTICAST:
919 case SAFNUM_VPNUNIMULTICAST:
920 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
921 printf("\n\t %s", buf);
922 break;
923 default:
924 printf("\n\t no SAFI %u decoder",safi);
925 if (!vflag)
926 print_unknown_data(tptr-3,"\n\t ",tlen);
927 advance = 0;
928 tptr = pptr + len;
929 break;
930 }
931 break;
932
933 #ifdef INET6
934 case AFNUM_INET6:
935 switch (safi) {
936 case SAFNUM_UNICAST:
937 case SAFNUM_MULTICAST:
938 case SAFNUM_UNIMULTICAST:
939 advance = decode_prefix6(tptr, buf, sizeof(buf));
940 printf("\n\t %s", buf);
941 break;
942 default:
943 printf("\n\t no SAFI %u decoder",safi);
944 if (!vflag)
945 print_unknown_data(tptr-3,"\n\t ",tlen);
946 advance = 0;
947 tptr = pptr + len;
948 break;
949 }
950 break;
951 #endif
952
953 case AFNUM_L2VPN:
954 switch(safi) {
955 case SAFNUM_VPNUNICAST:
956 case SAFNUM_VPNMULTICAST:
957 case SAFNUM_VPNUNIMULTICAST:
958 advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
959 printf("\n\t %s", buf);
960 break;
961 default:
962 printf("no SAFI %u decoder",safi);
963 if (!vflag)
964 print_unknown_data(tptr-3,"\n\t ",tlen);
965 advance = 0;
966 tptr = pptr + len;
967 break;
968 }
969 break;
970
971 default:
972 printf("\n\t no AFI %u decoder",af);
973 if (!vflag)
974 print_unknown_data(tptr-3,"\n\t ",tlen);
975 advance = 0;
976 tptr = pptr + len;
977 break;
978 }
979
980 tptr += advance;
981 }
982 break;
983 case BGPTYPE_EXTD_COMMUNITIES:
984 if (len % 8) {
985 printf("invalid len");
986 break;
987 }
988 while (tlen>0) {
989 u_int16_t extd_comm;
990 extd_comm=EXTRACT_16BITS(tptr);
991 switch(extd_comm) {
992 case BGP_EXT_COM_RT_0:
993 case BGP_EXT_COM_RO_0:
994 printf("\n\t %s%s%s:%u:%s",
995 (extd_comm&0x8000) ? "vendor-specific: " : "",
996 (extd_comm&0x4000) ? "non-transitive: " : "",
997 tok2str(bgp_extd_comm_subtype_values,
998 "unknown",
999 extd_comm),
1000 EXTRACT_16BITS(tptr+2),
1001 getname(tptr+4));
1002 break;
1003 case BGP_EXT_COM_RT_1:
1004 case BGP_EXT_COM_RO_1:
1005 printf("\n\t %s%s%s:%s:%u",
1006 (extd_comm&0x8000) ? "vendor-specific: " : "",
1007 (extd_comm&0x4000) ? "non-transitive: " : "",
1008 tok2str(bgp_extd_comm_subtype_values,
1009 "unknown",
1010 extd_comm),
1011 getname(tptr+2),
1012 EXTRACT_16BITS(tptr+6));
1013 break;
1014 case BGP_EXT_COM_VPN_ORIGIN:
1015 case BGP_EXT_COM_OSPF_RID:
1016 printf("\n\t %s%s%s:%s",
1017 (extd_comm&0x8000) ? "vendor-specific: " : "",
1018 (extd_comm&0x4000) ? "non-transitive: " : "",
1019 tok2str(bgp_extd_comm_subtype_values,
1020 "unknown",
1021 extd_comm),
1022 getname(tptr+2));
1023 break;
1024 case BGP_EXT_COM_OSPF_RTYPE:
1025 printf("\n\t %s%s%s, area:%s, router-type:%s, metric-type:%s%s",
1026 (extd_comm&0x8000) ? "vendor-specific: " : "",
1027 (extd_comm&0x4000) ? "non-transitive: " : "",
1028 tok2str(bgp_extd_comm_subtype_values,
1029 "unknown",
1030 extd_comm),
1031 getname(tptr+2),
1032 tok2str(bgp_extd_comm_ospf_rtype_values,
1033 "unknown",
1034 extd_comm),
1035 (*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
1036 (*(tptr+6) == (BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA )) ? "E1" : "");
1037 break;
1038 case BGP_EXT_COM_L2INFO:
1039 printf("\n\t %s%s:%s:Control Flags [0x%02x]:MTU %u",
1040 (extd_comm&0x4000) ? "non-transitive: " : "",
1041 tok2str(bgp_extd_comm_subtype_values,
1042 "unknown",
1043 extd_comm),
1044 tok2str(bgp_l2vpn_encaps_values,
1045 "unknown encaps",
1046 *(tptr+2)),
1047 *(tptr+3),
1048 EXTRACT_16BITS(tptr+4));
1049 break;
1050 default:
1051 printf("\n\t no typecode %u decoder",
1052 extd_comm);
1053 print_unknown_data(tptr,"\n\t ",8);
1054 break;
1055 }
1056 tlen -=8;
1057 tptr +=8;
1058 }
1059 break;
1060
1061 default:
1062 printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
1063 if (!vflag)
1064 print_unknown_data(pptr,"\n\t ",len);
1065 break;
1066 }
1067 if (vflag&&len) /* omit zero length attributes*/
1068 print_unknown_data(pptr,"\n\t ",len);
1069 }
1070
1071 static void
1072 bgp_open_print(const u_char *dat, int length)
1073 {
1074 struct bgp_open bgpo;
1075 struct bgp_opt bgpopt;
1076 int hlen;
1077 const u_char *opt;
1078 int i,cap_type,cap_len;
1079
1080 TCHECK2(dat[0], BGP_OPEN_SIZE);
1081 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
1082 hlen = ntohs(bgpo.bgpo_len);
1083
1084 printf("\n\t Version %d, ", bgpo.bgpo_version);
1085 printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
1086 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
1087 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
1088 printf("\n\t Optional parameters, length: %u", bgpo.bgpo_optlen);
1089
1090 /* ugly! */
1091 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
1092 opt++;
1093
1094 i = 0;
1095 while (i < bgpo.bgpo_optlen) {
1096 TCHECK2(opt[i], BGP_OPT_SIZE);
1097 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
1098 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
1099 printf("\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
1100 break;
1101 }
1102
1103 printf("\n\t Option %s (%u), length: %u",
1104 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
1105 bgpopt.bgpopt_type,
1106 bgpopt.bgpopt_len);
1107
1108 /* now lets decode the options we know*/
1109 switch(bgpopt.bgpopt_type) {
1110 case BGP_OPT_CAP:
1111 cap_type=opt[i+BGP_OPT_SIZE];
1112 cap_len=opt[i+BGP_OPT_SIZE+1];
1113 printf("\n\t %s, length: %u",
1114 tok2str(bgp_capcode_values,"Unknown", cap_type),
1115 cap_len);
1116 switch(cap_type) {
1117 case BGP_CAPCODE_MP:
1118 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
1119 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
1120 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
1121 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
1122 opt[i+BGP_OPT_SIZE+5]);
1123 break;
1124 case BGP_CAPCODE_RR:
1125 case BGP_CAPCODE_RR_CISCO:
1126 break;
1127 default:
1128 printf("\n\t\tno decoder for Capability %u",
1129 cap_type);
1130 break;
1131 }
1132 break;
1133 case BGP_OPT_AUTH:
1134 default:
1135 printf("\n\t no decoder for option %u",
1136 bgpopt.bgpopt_type);
1137 break;
1138 }
1139
1140 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
1141 }
1142 return;
1143 trunc:
1144 printf("[|BGP]");
1145 }
1146
1147 static void
1148 bgp_update_print(const u_char *dat, int length)
1149 {
1150 struct bgp bgp;
1151 struct bgp_attr bgpa;
1152 int hlen;
1153 const u_char *p;
1154 int len;
1155 int i;
1156
1157 TCHECK2(dat[0], BGP_SIZE);
1158 memcpy(&bgp, dat, BGP_SIZE);
1159 hlen = ntohs(bgp.bgp_len);
1160 p = dat + BGP_SIZE; /*XXX*/
1161
1162 /* Unfeasible routes */
1163 len = EXTRACT_16BITS(p);
1164 if (len) {
1165 /*
1166 * Without keeping state from the original NLRI message,
1167 * it's not possible to tell if this a v4 or v6 route,
1168 * so only try to decode it if we're not v6 enabled.
1169 */
1170 #ifdef INET6
1171 printf("\n\t Withdrawn routes: %d bytes", len);
1172 #else
1173 char buf[MAXHOSTNAMELEN + 100];
1174
1175 TCHECK2(p[2], len);
1176 i = 2;
1177
1178 printf("\n\t Withdrawn routes:");
1179
1180 while(i < 2 + len) {
1181 i += decode_prefix4(&p[i], buf, sizeof(buf));
1182 printf("\n\t %s", buf);
1183 }
1184 #endif
1185 }
1186 p += 2 + len;
1187
1188 TCHECK2(p[0], 2);
1189 len = EXTRACT_16BITS(p);
1190 if (len) {
1191 /* do something more useful!*/
1192 i = 2;
1193 while (i < 2 + len) {
1194 int alen, aoff;
1195
1196 TCHECK2(p[i], sizeof(bgpa));
1197 memcpy(&bgpa, &p[i], sizeof(bgpa));
1198 alen = bgp_attr_len(&bgpa);
1199 aoff = bgp_attr_off(&bgpa);
1200
1201 printf("\n\t %s (%u), length: %u",
1202 tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1203 bgpa.bgpa_type,
1204 alen);
1205
1206 if (bgpa.bgpa_flags) {
1207 printf(", flags [%s%s%s%s",
1208 bgpa.bgpa_flags & 0x80 ? "O" : "",
1209 bgpa.bgpa_flags & 0x40 ? "T" : "",
1210 bgpa.bgpa_flags & 0x20 ? "P" : "",
1211 bgpa.bgpa_flags & 0x10 ? "E" : "");
1212 if (bgpa.bgpa_flags & 0xf)
1213 printf("+%x", bgpa.bgpa_flags & 0xf);
1214 printf("]: ");
1215 }
1216 bgp_attr_print(&bgpa, &p[i + aoff], alen);
1217 i += aoff + alen;
1218 }
1219 }
1220 p += 2 + len;
1221
1222 if (dat + length > p) {
1223 printf("\n\t Updated routes:");
1224 while (dat + length > p) {
1225 char buf[MAXHOSTNAMELEN + 100];
1226 i = decode_prefix4(p, buf, sizeof(buf));
1227 printf("\n\t %s", buf);
1228 if (i < 0)
1229 break;
1230 p += i;
1231 }
1232 }
1233 return;
1234 trunc:
1235 printf("[|BGP]");
1236 }
1237
1238 static void
1239 bgp_notification_print(const u_char *dat, int length)
1240 {
1241 struct bgp_notification bgpn;
1242 int hlen;
1243
1244 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1245 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1246 hlen = ntohs(bgpn.bgpn_len);
1247
1248 printf(", Error - %s", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
1249
1250 switch (bgpn.bgpn_major) {
1251
1252 case BGP_NOTIFY_MAJOR_MSG:
1253 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
1254 break;
1255 case BGP_NOTIFY_MAJOR_OPEN:
1256 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
1257 break;
1258 case BGP_NOTIFY_MAJOR_UPDATE:
1259 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
1260 break;
1261 default:
1262 break;
1263 }
1264
1265 return;
1266 trunc:
1267 printf("[|BGP]");
1268 }
1269
1270 static void
1271 bgp_route_refresh_print(const u_char *pptr, int len) {
1272
1273 const struct bgp_route_refresh *bgp_route_refresh_header;
1274 bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
1275
1276 printf("\n\t AFI %s (%u), SAFI %s (%u)",
1277 tok2str(bgp_afi_values,"Unknown",
1278 EXTRACT_16BITS(&bgp_route_refresh_header->afi)), /* this stinks but the compiler pads the structure weird */
1279 EXTRACT_16BITS(&bgp_route_refresh_header->afi),
1280 tok2str(bgp_safi_values,"Unknown",
1281 bgp_route_refresh_header->safi),
1282 bgp_route_refresh_header->safi);
1283
1284 if (vflag)
1285 print_unknown_data(pptr,"\n\t ", len);
1286
1287 return;
1288 }
1289
1290 static void
1291 bgp_header_print(const u_char *dat, int length)
1292 {
1293 struct bgp bgp;
1294
1295 TCHECK2(dat[0], BGP_SIZE);
1296 memcpy(&bgp, dat, BGP_SIZE);
1297 printf("\n\t%s Message (%u), length: %u",
1298 tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
1299 bgp.bgp_type,
1300 length);
1301
1302 switch (bgp.bgp_type) {
1303 case BGP_OPEN:
1304 bgp_open_print(dat, length);
1305 break;
1306 case BGP_UPDATE:
1307 bgp_update_print(dat, length);
1308 break;
1309 case BGP_NOTIFICATION:
1310 bgp_notification_print(dat, length);
1311 break;
1312 case BGP_KEEPALIVE:
1313 break;
1314 case BGP_ROUTE_REFRESH:
1315 bgp_route_refresh_print(dat, length);
1316 break;
1317 default:
1318 /* we have no decoder for the BGP message */
1319 printf("\n\t no Message %u decoder",bgp.bgp_type);
1320 print_unknown_data(dat,"\n\t ",length);
1321 break;
1322 }
1323 return;
1324 trunc:
1325 printf("[|BGP]");
1326 }
1327
1328 void
1329 bgp_print(const u_char *dat, int length)
1330 {
1331 const u_char *p;
1332 const u_char *ep;
1333 const u_char *start;
1334 const u_char marker[] = {
1335 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1336 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1337 };
1338 struct bgp bgp;
1339 u_int16_t hlen;
1340
1341 ep = dat + length;
1342 if (snapend < dat + length)
1343 ep = snapend;
1344
1345 printf(": BGP, length: %u",length);
1346
1347 p = dat;
1348 start = p;
1349 while (p < snapend) {
1350 if (!TTEST2(p[0], 1))
1351 break;
1352 if (p[0] != 0xff) {
1353 p++;
1354 continue;
1355 }
1356
1357 if (!TTEST2(p[0], sizeof(marker)))
1358 break;
1359 if (memcmp(p, marker, sizeof(marker)) != 0) {
1360 p++;
1361 continue;
1362 }
1363
1364 /* found BGP header */
1365 TCHECK2(p[0], BGP_SIZE); /*XXX*/
1366 memcpy(&bgp, p, BGP_SIZE);
1367
1368 if (start != p)
1369 printf(" [|BGP]");
1370
1371 hlen = ntohs(bgp.bgp_len);
1372
1373 if (TTEST2(p[0], hlen)) {
1374 bgp_header_print(p, hlen);
1375 p += hlen;
1376 start = p;
1377 } else {
1378 printf("[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
1379 break;
1380 }
1381 }
1382
1383 return;
1384
1385 trunc:
1386 printf(" [|BGP]");
1387 }
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398