]>
The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
2 * Copyright (C) 1999 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/ip_var.h>
39 #include <netinet/udp.h>
40 #include <netinet/udp_var.h>
45 #include <netinet/ip6.h>
48 #include "interface.h"
49 #include "addrtoname.h"
52 u_int8_t bgp_marker
[16];
56 #define BGP_SIZE 19 /* unaligned */
60 #define BGP_NOTIFICATION 3
61 #define BGP_KEEPALIVE 4
64 u_int8_t bgpo_marker
[16];
67 u_int8_t bgpo_version
;
69 u_int16_t bgpo_holdtime
;
72 /* options should follow */
75 struct bgp_notification
{
76 u_int8_t bgpn_marker
[16];
81 /* data should follow */
91 #define bgp_attr_len(p) \
92 (((p)->bgpa_flags & 0x10) ? \
93 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len)
94 #define bgp_attr_off(p) \
95 (((p)->bgpa_flags & 0x10) ? 4 : 3)
98 #define BGPTYPE_ORIGIN 1
99 #define BGPTYPE_AS_PATH 2
100 #define BGPTYPE_NEXT_HOP 3
101 #define BGPTYPE_MULTI_EXIT_DISC 4
102 #define BGPTYPE_LOCAL_PREF 5
103 #define BGPTYPE_ATOMIC_AGGREGATE 6
104 #define BGPTYPE_AGGREGATOR 7
105 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
106 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
109 static const char *bgptype
[] = {
110 NULL
, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE",
112 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x))
114 static const char *bgpnotify_major
[] = {
115 NULL
, "Message Header Error",
116 "OPEN Message Error", "UPDATE Message Error",
117 "Hold Timer Expired", "Finite State Machine Error",
120 #define bgp_notify_major(x) \
121 num_or_str(bgpnotify_major, \
122 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x))
124 static const char *bgpnotify_minor_1
[] = {
125 NULL
, "Connection Not Synchronized",
126 "Bad Message Length", "Bad Message Type",
129 static const char *bgpnotify_minor_2
[] = {
130 NULL
, "Unsupported Version Number",
131 "Bad Peer AS", "Bad BGP Identifier",
132 "Unsupported Optional Parameter", "Authentication Failure",
133 "Unacceptable Hold Time",
136 static const char *bgpnotify_minor_3
[] = {
137 NULL
, "Malformed Attribute List",
138 "Unrecognized Well-known Attribute", "Missing Well-known Attribute",
139 "Attribute Flags Error", "Attribute Length Error",
140 "Invalid ORIGIN Attribute", "AS Routing Loop",
141 "Invalid NEXT_HOP Attribute", "Optional Attribute Error",
142 "Invalid Network Field", "Malformed AS_PATH",
145 static const char **bgpnotify_minor
[] = {
146 NULL
, bgpnotify_minor_1
, bgpnotify_minor_2
, bgpnotify_minor_3
,
148 static const int bgpnotify_minor_siz
[] = {
149 0, sizeof(bgpnotify_minor_1
)/sizeof(bgpnotify_minor_1
[0]),
150 sizeof(bgpnotify_minor_2
)/sizeof(bgpnotify_minor_2
[0]),
151 sizeof(bgpnotify_minor_3
)/sizeof(bgpnotify_minor_3
[0]),
154 static const char *bgpattr_origin
[] = {
155 "IGP", "EGP", "INCOMPLETE",
157 #define bgp_attr_origin(x) \
158 num_or_str(bgpattr_origin, \
159 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x))
161 static const char *bgpattr_type
[] = {
162 NULL
, "ORIGIN", "AS_PATH", "NEXT_HOP",
163 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR",
164 NULL
, NULL
, NULL
, NULL
,
165 NULL
, NULL
, "MP_REACH_NLRI", "MP_UNREACH_NLRI",
167 #define bgp_attr_type(x) \
168 num_or_str(bgpattr_type, \
169 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x))
171 /* Subsequent address family identifier, RFC2283 section 7 */
172 static const char *bgpattr_nlri_safi
[] = {
173 "Reserved", "Unicast", "Multicast", "Unicast+Multicast",
175 #define bgp_attr_nlri_safi(x) \
176 num_or_str(bgpattr_nlri_safi, \
177 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x))
179 /* RFC1700 address family numbers */
181 #define AFNUM_INET6 2
184 #define AFNUM_BBN1822 5
189 #define AFNUM_X121 10
191 #define AFNUM_ATALK 12
192 #define AFNUM_DECNET 13
193 #define AFNUM_BANYAN 14
194 #define AFNUM_E164NSAP 15
196 static const char *afnumber
[] = {
197 "Reserved", "IPv4", "IPv6", "NSAP", "HDLC",
198 "BBN 1822", "802", "E.163", "E.164", "F.69",
199 "X.121", "IPX", "Appletalk", "Decnet IV", "Banyan Vines",
200 "E.164 with NSAP subaddress",
203 (((x) == 65535) ? afnumber[0] : \
204 num_or_str(afnumber, \
205 sizeof(afnumber)/sizeof(afnumber[0]), (x)))
209 num_or_str(const char **table
, size_t siz
, int value
)
212 if (value
< 0 || siz
<= value
|| table
[value
] == NULL
) {
213 snprintf(buf
, sizeof(buf
), "#%d", value
);
220 bgp_notify_minor(int major
, int minor
)
222 static const char **table
;
228 && major
< sizeof(bgpnotify_minor
)/sizeof(bgpnotify_minor
[0])
229 && bgpnotify_minor
[major
]) {
230 table
= bgpnotify_minor
[major
];
231 siz
= bgpnotify_minor_siz
[major
];
232 if (0 <= minor
&& minor
< siz
&& table
[minor
])
239 snprintf(buf
, sizeof(buf
), "#%d", minor
);
246 decode_prefix4(const u_char
*pd
, char *buf
, int buflen
)
252 if (plen
< 0 || 32 < plen
)
255 memset(&addr
, 0, sizeof(addr
));
256 memcpy(&addr
, &pd
[1], (plen
+ 7) / 8);
258 ((u_char
*)&addr
)[(plen
+ 7) / 8 - 1] &=
259 ((0xff00 >> (plen
% 8)) & 0xff);
261 snprintf(buf
, buflen
, "%s/%d", getname((char *)&addr
), plen
);
262 return 1 + (plen
+ 7) / 8;
267 decode_prefix6(const u_char
*pd
, char *buf
, int buflen
)
269 struct in6_addr addr
;
273 if (plen
< 0 || 128 < plen
)
276 memset(&addr
, 0, sizeof(addr
));
277 memcpy(&addr
, &pd
[1], (plen
+ 7) / 8);
279 addr
.s6_addr
[(plen
+ 7) / 8 - 1] &=
280 ((0xff00 >> (plen
% 8)) & 0xff);
282 snprintf(buf
, buflen
, "%s/%d", getname6((char *)&addr
), plen
);
283 return 1 + (plen
+ 7) / 8;
288 bgp_attr_print(const struct bgp_attr
*attr
, const u_char
*dat
, int len
)
301 switch (attr
->bgpa_type
) {
304 printf(" invalid len");
306 printf(" %s", bgp_attr_origin(p
[0]));
308 case BGPTYPE_AS_PATH
:
310 printf(" invalid len");
313 for (i
= 0; i
< len
; i
+= 2)
314 printf(" %u", ntohs(*(u_int16_t
*)&p
[i
]));
316 case BGPTYPE_NEXT_HOP
:
318 printf(" invalid len");
320 printf(" %s", getname(p
));
322 case BGPTYPE_MULTI_EXIT_DISC
:
323 case BGPTYPE_LOCAL_PREF
:
325 printf(" invalid len");
327 printf(" %u", (u_int32_t
)ntohl(*(u_int32_t
*)p
));
329 case BGPTYPE_ATOMIC_AGGREGATE
:
331 printf(" invalid len");
333 case BGPTYPE_AGGREGATOR
:
335 printf(" invalid len");
338 printf(" AS #%u, origin %s", ntohs(*(u_int16_t
*)p
),
341 case BGPTYPE_MP_REACH_NLRI
:
342 af
= ntohs(*(u_int16_t
*)p
);
345 printf(" %s vendor specific,", af_name(af
));
347 printf(" %s %s,", af_name(af
),
348 bgp_attr_nlri_safi(safi
));
352 if (af
== AFNUM_INET
)
355 else if (af
== AFNUM_INET6
)
364 if (af
== AFNUM_INET
)
367 else if (af
== AFNUM_INET6
)
371 for (i
= 0; i
< tlen
; i
+= advance
) {
372 if (af
== AFNUM_INET
)
373 printf(" %s", getname(p
+ 1 + i
));
375 else if (af
== AFNUM_INET6
)
376 printf(" %s", getname6(p
+ 1 + i
));
386 printf(" %u snpa", snpa
);
387 for (/*nothing*/; snpa
> 0; snpa
--) {
388 printf("(%d bytes)", p
[0]);
395 while (len
- (p
- dat
) > 0) {
396 if (af
== AFNUM_INET
)
397 advance
= decode_prefix4(p
, buf
, sizeof(buf
));
399 else if (af
== AFNUM_INET6
)
400 advance
= decode_prefix6(p
, buf
, sizeof(buf
));
409 case BGPTYPE_MP_UNREACH_NLRI
:
410 af
= ntohs(*(u_int16_t
*)p
);
413 printf(" %s vendor specific,", af_name(af
));
415 printf(" %s %s,", af_name(af
),
416 bgp_attr_nlri_safi(safi
));
421 while (len
- (p
- dat
) > 0) {
422 if (af
== AFNUM_INET
)
423 advance
= decode_prefix4(p
, buf
, sizeof(buf
));
425 else if (af
== AFNUM_INET6
)
426 advance
= decode_prefix6(p
, buf
, sizeof(buf
));
439 bgp_open_print(const u_char
*dat
, int length
)
441 struct bgp_open bgpo
;
444 memcpy(&bgpo
, dat
, sizeof(bgpo
));
445 hlen
= ntohs(bgpo
.bgpo_len
);
447 printf(": Version %d,", bgpo
.bgpo_version
);
448 printf(" AS #%u,", ntohs(bgpo
.bgpo_myas
));
449 printf(" Holdtime %u,", ntohs(bgpo
.bgpo_holdtime
));
450 printf(" ID %s,", getname((char *)&bgpo
.bgpo_id
));
451 printf(" Option length %u", bgpo
.bgpo_optlen
);
455 bgp_update_print(const u_char
*dat
, int length
)
458 struct bgp_attr bgpa
;
464 memcpy(&bgp
, dat
, sizeof(bgp
));
465 hlen
= ntohs(bgp
.bgp_len
);
466 p
= dat
+ BGP_SIZE
; /*XXX*/
469 /* Unfeasible routes */
470 len
= ntohs(*(u_int16_t
*)p
);
472 printf(" (Withdrawn routes: %d bytes)", len
);
476 len
= ntohs(*(u_int16_t
*)p
);
478 /* do something more useful!*/
480 printf(" (Path attributes:"); /* ) */
481 while (i
< 2 + len
) {
484 memcpy(&bgpa
, &p
[i
], sizeof(bgpa
));
485 alen
= bgp_attr_len(&bgpa
);
486 aoff
= bgp_attr_off(&bgpa
);
488 printf(" ("); /* ) */
489 printf("%s", bgp_attr_type(bgpa
.bgpa_type
));
490 if (bgpa
.bgpa_flags
) {
492 bgpa
.bgpa_flags
& 0x80 ? "O" : "",
493 bgpa
.bgpa_flags
& 0x40 ? "T" : "",
494 bgpa
.bgpa_flags
& 0x20 ? "P" : "",
495 bgpa
.bgpa_flags
& 0x00 ? "E" : "");
498 bgp_attr_print(&bgpa
, &p
[i
+ aoff
], alen
);
502 proto_tree_add_text(subtree2
, p
- pd
+ i
+ aoff
, alen
,
503 "Unknown (%d bytes)", alen
);
522 bgp_notification_print(const u_char
*dat
, int length
)
524 struct bgp_notification bgpn
;
527 memcpy(&bgpn
, dat
, sizeof(bgpn
));
528 hlen
= ntohs(bgpn
.bgpn_len
);
530 printf(": error %s,", bgp_notify_major(bgpn
.bgpn_major
));
531 printf(" subcode %s",
532 bgp_notify_minor(bgpn
.bgpn_major
, bgpn
.bgpn_minor
));
536 bgp_header_print(const u_char
*dat
, int length
, int newline
)
540 memcpy(&bgp
, dat
, sizeof(bgp
));
541 printf(newline
? "\n\t" : " ");
542 printf("(%s", bgp_type(bgp
.bgp_type
)); /* ) */
544 switch (bgp
.bgp_type
) {
546 bgp_open_print(dat
, length
);
549 bgp_update_print(dat
, length
);
551 case BGP_NOTIFICATION
:
552 bgp_notification_print(dat
, length
);
561 bgp_print(const u_char
*dat
, int length
)
565 const u_char marker
[] = {
566 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
567 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
574 if (snapend
< dat
+ length
)
581 while (p
< snapend
) {
582 if (!TTEST2(p
[0], 1))
589 if (!TTEST2(p
[0], sizeof(marker
)))
591 if (memcmp(p
, marker
, sizeof(marker
)) != 0) {
596 /* found BGP header */
597 TCHECK2(p
[0], BGP_SIZE
); /*XXX*/
598 memcpy(&bgp
, p
, sizeof(bgp
));
600 hlen
= ntohs(bgp
.bgp_len
);
601 if (TTEST2(p
[0], hlen
)) {
602 bgp_header_print(p
, hlen
, vflag
? newline
: 0);
606 printf(" [|BGP %s]", bgp_type(bgp
.bgp_type
));