1 |
|
|
/* $OpenBSD: print-bgp.c,v 1.25 2017/08/30 09:23:00 otto Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (C) 1999 WIDE Project. |
5 |
|
|
* All rights reserved. |
6 |
|
|
* |
7 |
|
|
* Redistribution and use in source and binary forms, with or without |
8 |
|
|
* modification, are permitted provided that the following conditions |
9 |
|
|
* are met: |
10 |
|
|
* 1. Redistributions of source code must retain the above copyright |
11 |
|
|
* notice, this list of conditions and the following disclaimer. |
12 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
|
|
* notice, this list of conditions and the following disclaimer in the |
14 |
|
|
* documentation and/or other materials provided with the distribution. |
15 |
|
|
* 3. Neither the name of the project nor the names of its contributors |
16 |
|
|
* may be used to endorse or promote products derived from this software |
17 |
|
|
* without specific prior written permission. |
18 |
|
|
* |
19 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
20 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
23 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 |
|
|
* SUCH DAMAGE. |
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
#include <sys/time.h> |
33 |
|
|
#include <sys/types.h> |
34 |
|
|
#include <sys/socket.h> |
35 |
|
|
|
36 |
|
|
#include <netinet/in.h> |
37 |
|
|
|
38 |
|
|
#include <errno.h> |
39 |
|
|
#include <stdio.h> |
40 |
|
|
#include <string.h> |
41 |
|
|
#include <netdb.h> |
42 |
|
|
#include <limits.h> |
43 |
|
|
|
44 |
|
|
#include "interface.h" |
45 |
|
|
#include "addrtoname.h" |
46 |
|
|
#include "extract.h" |
47 |
|
|
#include "afnum.h" |
48 |
|
|
|
49 |
|
|
struct bgp { |
50 |
|
|
u_int8_t bgp_marker[16]; |
51 |
|
|
u_int16_t bgp_len; |
52 |
|
|
u_int8_t bgp_type; |
53 |
|
|
}; |
54 |
|
|
#define BGP_SIZE 19 /* unaligned */ |
55 |
|
|
|
56 |
|
|
#define BGP_OPEN 1 |
57 |
|
|
#define BGP_UPDATE 2 |
58 |
|
|
#define BGP_NOTIFICATION 3 |
59 |
|
|
#define BGP_KEEPALIVE 4 |
60 |
|
|
#define BGP_ROUTE_REFRESH 5 |
61 |
|
|
|
62 |
|
|
struct bgp_open { |
63 |
|
|
u_int8_t bgpo_marker[16]; |
64 |
|
|
u_int16_t bgpo_len; |
65 |
|
|
u_int8_t bgpo_type; |
66 |
|
|
u_int8_t bgpo_version; |
67 |
|
|
u_int16_t bgpo_myas; |
68 |
|
|
u_int16_t bgpo_holdtime; |
69 |
|
|
u_int32_t bgpo_id; |
70 |
|
|
u_int8_t bgpo_optlen; |
71 |
|
|
/* options should follow */ |
72 |
|
|
}; |
73 |
|
|
#define BGP_OPEN_SIZE 29 /* unaligned */ |
74 |
|
|
|
75 |
|
|
struct bgp_opt { |
76 |
|
|
u_int8_t bgpopt_type; |
77 |
|
|
u_int8_t bgpopt_len; |
78 |
|
|
/* variable length */ |
79 |
|
|
}; |
80 |
|
|
#define BGP_OPT_CAP 2 |
81 |
|
|
#define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ |
82 |
|
|
|
83 |
|
|
#define BGP_UPDATE_MINSIZE 23 |
84 |
|
|
|
85 |
|
|
struct bgp_notification { |
86 |
|
|
u_int8_t bgpn_marker[16]; |
87 |
|
|
u_int16_t bgpn_len; |
88 |
|
|
u_int8_t bgpn_type; |
89 |
|
|
u_int8_t bgpn_major; |
90 |
|
|
u_int8_t bgpn_minor; |
91 |
|
|
/* data should follow */ |
92 |
|
|
}; |
93 |
|
|
#define BGP_NOTIFICATION_SIZE 21 /* unaligned */ |
94 |
|
|
|
95 |
|
|
struct bgp_route_refresh { |
96 |
|
|
u_int8_t bgp_marker[16]; |
97 |
|
|
u_int16_t len; |
98 |
|
|
u_int8_t type; |
99 |
|
|
u_int8_t afi[2]; /* unaligned; should be u_int16_t */ |
100 |
|
|
u_int8_t res; |
101 |
|
|
u_int8_t safi; |
102 |
|
|
}; |
103 |
|
|
#define BGP_ROUTE_REFRESH_SIZE 23 |
104 |
|
|
|
105 |
|
|
struct bgp_attr { |
106 |
|
|
u_int8_t bgpa_flags; |
107 |
|
|
u_int8_t bgpa_type; |
108 |
|
|
union { |
109 |
|
|
u_int8_t len; |
110 |
|
|
u_int16_t elen; |
111 |
|
|
} bgpa_len; |
112 |
|
|
#define bgp_attr_len(p) \ |
113 |
|
|
(((p)->bgpa_flags & 0x10) ? \ |
114 |
|
|
ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len) |
115 |
|
|
#define bgp_attr_off(p) \ |
116 |
|
|
(((p)->bgpa_flags & 0x10) ? 4 : 3) |
117 |
|
|
}; |
118 |
|
|
|
119 |
|
|
#define BGPTYPE_ORIGIN 1 |
120 |
|
|
#define BGPTYPE_AS_PATH 2 |
121 |
|
|
#define BGPTYPE_NEXT_HOP 3 |
122 |
|
|
#define BGPTYPE_MULTI_EXIT_DISC 4 |
123 |
|
|
#define BGPTYPE_LOCAL_PREF 5 |
124 |
|
|
#define BGPTYPE_ATOMIC_AGGREGATE 6 |
125 |
|
|
#define BGPTYPE_AGGREGATOR 7 |
126 |
|
|
#define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ |
127 |
|
|
#define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */ |
128 |
|
|
#define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ |
129 |
|
|
#define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */ |
130 |
|
|
#define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ |
131 |
|
|
#define BGPTYPE_RCID_PATH 13 /* RFC1863 */ |
132 |
|
|
#define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ |
133 |
|
|
#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ |
134 |
|
|
#define BGPTYPE_EXTD_COMMUNITIES 16 /* RFC4360 */ |
135 |
|
|
#define BGPTYPE_AS4_PATH 17 /* RFC4893 */ |
136 |
|
|
#define BGPTYPE_AGGREGATOR4 18 /* RFC4893 */ |
137 |
|
|
#define BGPTYPE_LARGE_COMMUNITIES 32 /* draft-ietf-idr-large-community */ |
138 |
|
|
|
139 |
|
|
#define BGP_AS_SET 1 |
140 |
|
|
#define BGP_AS_SEQUENCE 2 |
141 |
|
|
#define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */ |
142 |
|
|
#define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */ |
143 |
|
|
|
144 |
|
|
static struct tok bgp_as_path_segment_open_values[] = { |
145 |
|
|
{ BGP_AS_SET, " {" }, |
146 |
|
|
{ BGP_AS_SEQUENCE, " " }, |
147 |
|
|
{ BGP_CONFED_AS_SEQUENCE, " (" }, |
148 |
|
|
{ BGP_CONFED_AS_SET, " ({" }, |
149 |
|
|
{ 0, NULL}, |
150 |
|
|
}; |
151 |
|
|
|
152 |
|
|
static struct tok bgp_as_path_segment_close_values[] = { |
153 |
|
|
{ BGP_AS_SET, "}" }, |
154 |
|
|
{ BGP_AS_SEQUENCE, "" }, |
155 |
|
|
{ BGP_CONFED_AS_SEQUENCE, ")" }, |
156 |
|
|
{ BGP_CONFED_AS_SET, "})" }, |
157 |
|
|
{ 0, NULL}, |
158 |
|
|
}; |
159 |
|
|
|
160 |
|
|
#define BGP_MP_NLRI_MINSIZE 3 |
161 |
|
|
|
162 |
|
|
static const char *bgptype[] = { |
163 |
|
|
NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", |
164 |
|
|
}; |
165 |
|
|
#define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) |
166 |
|
|
|
167 |
|
|
static const char *bgpopt_type[] = { |
168 |
|
|
NULL, "Authentication Information", "Capabilities Advertisement", |
169 |
|
|
}; |
170 |
|
|
#define bgp_opttype(x) \ |
171 |
|
|
num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x)) |
172 |
|
|
|
173 |
|
|
#define BGP_CAPCODE_MP 1 |
174 |
|
|
#define BGP_CAPCODE_REFRESH 2 |
175 |
|
|
#define BGP_CAPCODE_RESTART 64 /* draft-ietf-idr-restart-05 */ |
176 |
|
|
#define BGP_CAPCODE_AS4 65 /* RFC4893 */ |
177 |
|
|
|
178 |
|
|
static const char *bgp_capcode[] = { |
179 |
|
|
NULL, "MULTI_PROTOCOL", "ROUTE_REFRESH", |
180 |
|
|
/* 3: RFC5291 */ "OUTBOUND_ROUTE_FILTERING", |
181 |
|
|
/* 4: RFC3107 */ "MULTIPLE_ROUTES", |
182 |
|
|
/* 5: RFC5549 */ "EXTENDED_NEXTHOP_ENCODING", |
183 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
184 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
185 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
186 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
187 |
|
|
/* 64: RFC4724 */ "GRACEFUL_RESTART", |
188 |
|
|
/* 65: RFC4893 */ "AS4", 0, |
189 |
|
|
/* 67: [Chen] */ "DYNAMIC_CAPABILITY", |
190 |
|
|
/* 68: [Appanna] */ "MULTISESSION", |
191 |
|
|
/* 69: [draft-ietf-idr-add-paths] */ "ADD-PATH", |
192 |
|
|
}; |
193 |
|
|
|
194 |
|
|
#define bgp_capcode(x) \ |
195 |
|
|
num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode[0]), (x)) |
196 |
|
|
|
197 |
|
|
#define BGP_NOTIFY_MAJOR_CEASE 6 |
198 |
|
|
static const char *bgpnotify_major[] = { |
199 |
|
|
NULL, "Message Header Error", |
200 |
|
|
"OPEN Message Error", "UPDATE Message Error", |
201 |
|
|
"Hold Timer Expired", "Finite State Machine Error", |
202 |
|
|
"Cease", "Capability Message Error", |
203 |
|
|
}; |
204 |
|
|
#define bgp_notify_major(x) \ |
205 |
|
|
num_or_str(bgpnotify_major, \ |
206 |
|
|
sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x)) |
207 |
|
|
|
208 |
|
|
static const char *bgpnotify_minor_msg[] = { |
209 |
|
|
NULL, "Connection Not Synchronized", |
210 |
|
|
"Bad Message Length", "Bad Message Type", |
211 |
|
|
}; |
212 |
|
|
|
213 |
|
|
static const char *bgpnotify_minor_open[] = { |
214 |
|
|
NULL, "Unsupported Version Number", |
215 |
|
|
"Bad Peer AS", "Bad BGP Identifier", |
216 |
|
|
"Unsupported Optional Parameter", "Authentication Failure", |
217 |
|
|
"Unacceptable Hold Time", "Unsupported Capability", |
218 |
|
|
}; |
219 |
|
|
|
220 |
|
|
static const char *bgpnotify_minor_update[] = { |
221 |
|
|
NULL, "Malformed Attribute List", |
222 |
|
|
"Unrecognized Well-known Attribute", "Missing Well-known Attribute", |
223 |
|
|
"Attribute Flags Error", "Attribute Length Error", |
224 |
|
|
"Invalid ORIGIN Attribute", "AS Routing Loop", |
225 |
|
|
"Invalid NEXT_HOP Attribute", "Optional Attribute Error", |
226 |
|
|
"Invalid Network Field", "Malformed AS_PATH", |
227 |
|
|
}; |
228 |
|
|
|
229 |
|
|
static const char *bgpnotify_minor_holdtime[] = { |
230 |
|
|
NULL, |
231 |
|
|
}; |
232 |
|
|
|
233 |
|
|
/* RFC 6608 */ |
234 |
|
|
static const char *bgpnotify_minor_fsm[] = { |
235 |
|
|
"Unspecified Error", "In OpenSent State", "In OpenConfirm State", |
236 |
|
|
"In Established State", |
237 |
|
|
}; |
238 |
|
|
|
239 |
|
|
/* RFC 4486 */ |
240 |
|
|
#define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1 |
241 |
|
|
/* RFC 8203 */ |
242 |
|
|
#define BGP_NOTIFY_MINOR_CEASE_SHUT 2 |
243 |
|
|
#define BGP_NOTIFY_MINOR_CEASE_RESET 4 |
244 |
|
|
#define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN 128 |
245 |
|
|
static const char *bgpnotify_minor_cease[] = { |
246 |
|
|
NULL, "Maximum Number of Prefixes Reached", "Administrative Shutdown", |
247 |
|
|
"Peer De-configured", "Administrative Reset", "Connection Rejected", |
248 |
|
|
"Other Configuration Change", "Connection Collision Resolution", |
249 |
|
|
"Out of Resources", |
250 |
|
|
}; |
251 |
|
|
|
252 |
|
|
/* RFC 7313 */ |
253 |
|
|
static const char *bgpnotify_minor_err[] = { |
254 |
|
|
NULL, "Invalid Message Length", |
255 |
|
|
}; |
256 |
|
|
|
257 |
|
|
static const char **bgpnotify_minor[] = { |
258 |
|
|
NULL, bgpnotify_minor_msg, bgpnotify_minor_open, bgpnotify_minor_update, |
259 |
|
|
bgpnotify_minor_holdtime, bgpnotify_minor_fsm, bgpnotify_minor_cease, |
260 |
|
|
bgpnotify_minor_err, |
261 |
|
|
}; |
262 |
|
|
static const int bgpnotify_minor_siz[] = { |
263 |
|
|
0, |
264 |
|
|
sizeof(bgpnotify_minor_msg)/sizeof(bgpnotify_minor_msg[0]), |
265 |
|
|
sizeof(bgpnotify_minor_open)/sizeof(bgpnotify_minor_open[0]), |
266 |
|
|
sizeof(bgpnotify_minor_update)/sizeof(bgpnotify_minor_update[0]), |
267 |
|
|
sizeof(bgpnotify_minor_holdtime)/sizeof(bgpnotify_minor_holdtime[0]), |
268 |
|
|
sizeof(bgpnotify_minor_fsm)/sizeof(bgpnotify_minor_fsm[0]), |
269 |
|
|
sizeof(bgpnotify_minor_cease)/sizeof(bgpnotify_minor_cease[0]), |
270 |
|
|
sizeof(bgpnotify_minor_err)/sizeof(bgpnotify_minor_err[0]), |
271 |
|
|
}; |
272 |
|
|
|
273 |
|
|
static const char *bgpattr_origin[] = { |
274 |
|
|
"IGP", "EGP", "INCOMPLETE", |
275 |
|
|
}; |
276 |
|
|
#define bgp_attr_origin(x) \ |
277 |
|
|
num_or_str(bgpattr_origin, \ |
278 |
|
|
sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x)) |
279 |
|
|
|
280 |
|
|
static const char *bgpattr_type[] = { |
281 |
|
|
NULL, "ORIGIN", "AS_PATH", "NEXT_HOP", |
282 |
|
|
"MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR", |
283 |
|
|
"COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA", |
284 |
|
|
"ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI", |
285 |
|
|
"EXTD_COMMUNITIES", "AS4_PATH", "AGGREGATOR4", NULL, NULL, NULL, |
286 |
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
287 |
|
|
"LARGE_COMMUNITIES", |
288 |
|
|
}; |
289 |
|
|
#define bgp_attr_type(x) \ |
290 |
|
|
num_or_str(bgpattr_type, \ |
291 |
|
|
sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x)) |
292 |
|
|
|
293 |
|
|
/* Subsequent address family identifier, RFC2283 section 7 */ |
294 |
|
|
static const char *bgpattr_nlri_safi[] = { |
295 |
|
|
"Reserved", "Unicast", "Multicast", "Unicast+Multicast", |
296 |
|
|
"labeled Unicast", /* MPLS BGP RFC3107 */ |
297 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
298 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
299 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
300 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
301 |
|
|
/* 64-66: MPLS BGP RFC3107 */ |
302 |
|
|
"Tunnel", "VPLS", "MDT", |
303 |
|
|
}; |
304 |
|
|
#define bgp_attr_nlri_safi(x) \ |
305 |
|
|
num_or_str(bgpattr_nlri_safi, \ |
306 |
|
|
sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x)) |
307 |
|
|
|
308 |
|
|
/* well-known community */ |
309 |
|
|
#define BGP_COMMUNITY_NO_EXPORT 0xffffff01 |
310 |
|
|
#define BGP_COMMUNITY_NO_ADVERT 0xffffff02 |
311 |
|
|
#define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 |
312 |
|
|
#define BGP_COMMUNITY_NO_PEER 0xffffff04 |
313 |
|
|
|
314 |
|
|
static const char *afnumber[] = AFNUM_NAME_STR; |
315 |
|
|
#define af_name(x) \ |
316 |
|
|
(((x) == 65535) ? afnumber[0] : \ |
317 |
|
|
num_or_str(afnumber, \ |
318 |
|
|
sizeof(afnumber)/sizeof(afnumber[0]), (x))) |
319 |
|
|
|
320 |
|
|
|
321 |
|
|
static const char * |
322 |
|
|
num_or_str(const char **table, size_t siz, int value) |
323 |
|
|
{ |
324 |
|
|
static char buf[20]; |
325 |
|
|
if (value < 0 || siz <= value || table[value] == NULL) { |
326 |
|
|
snprintf(buf, sizeof(buf), "#%d", value); |
327 |
|
|
return buf; |
328 |
|
|
} else |
329 |
|
|
return table[value]; |
330 |
|
|
} |
331 |
|
|
|
332 |
|
|
static const char * |
333 |
|
|
bgp_notify_minor(int major, int minor) |
334 |
|
|
{ |
335 |
|
|
static const char **table; |
336 |
|
|
int siz; |
337 |
|
|
static char buf[20]; |
338 |
|
|
const char *p; |
339 |
|
|
|
340 |
|
|
if (0 <= major |
341 |
|
|
&& major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0]) |
342 |
|
|
&& bgpnotify_minor[major]) { |
343 |
|
|
table = bgpnotify_minor[major]; |
344 |
|
|
siz = bgpnotify_minor_siz[major]; |
345 |
|
|
if (0 <= minor && minor < siz && table[minor]) |
346 |
|
|
p = table[minor]; |
347 |
|
|
else |
348 |
|
|
p = NULL; |
349 |
|
|
} else |
350 |
|
|
p = NULL; |
351 |
|
|
if (p == NULL) { |
352 |
|
|
snprintf(buf, sizeof(buf), "#%d", minor); |
353 |
|
|
return buf; |
354 |
|
|
} else |
355 |
|
|
return p; |
356 |
|
|
} |
357 |
|
|
|
358 |
|
|
static int |
359 |
|
|
decode_prefix4(const u_char *pd, char *buf, u_int buflen) |
360 |
|
|
{ |
361 |
|
|
struct in_addr addr; |
362 |
|
|
u_int plen; |
363 |
|
|
int n; |
364 |
|
|
|
365 |
|
|
TCHECK(pd[0]); |
366 |
|
|
plen = pd[0]; /* |
367 |
|
|
* prefix length is in bits; packet only contains |
368 |
|
|
* enough bytes of address to contain this many bits |
369 |
|
|
*/ |
370 |
|
|
plen = pd[0]; |
371 |
|
|
if (32 < plen) |
372 |
|
|
return -1; |
373 |
|
|
memset(&addr, 0, sizeof(addr)); |
374 |
|
|
TCHECK2(pd[1], (plen + 7) / 8); |
375 |
|
|
memcpy(&addr, &pd[1], (plen + 7) / 8); |
376 |
|
|
if (plen % 8) { |
377 |
|
|
((u_char *)&addr)[(plen + 7) / 8 - 1] &= |
378 |
|
|
((0xff00 >> (plen % 8)) & 0xff); |
379 |
|
|
} |
380 |
|
|
n = snprintf(buf, buflen, "%s/%u", getname((u_char *)&addr), plen); |
381 |
|
|
if (n == -1 || n >= buflen) |
382 |
|
|
return -1; |
383 |
|
|
|
384 |
|
|
return 1 + (plen + 7) / 8; |
385 |
|
|
|
386 |
|
|
trunc: |
387 |
|
|
return -2; |
388 |
|
|
} |
389 |
|
|
|
390 |
|
|
#ifdef INET6 |
391 |
|
|
static int |
392 |
|
|
decode_prefix6(const u_char *pd, char *buf, u_int buflen) |
393 |
|
|
{ |
394 |
|
|
struct in6_addr addr; |
395 |
|
|
u_int plen; |
396 |
|
|
int n; |
397 |
|
|
|
398 |
|
|
TCHECK(pd[0]); |
399 |
|
|
plen = pd[0]; |
400 |
|
|
if (128 < plen) |
401 |
|
|
return -1; |
402 |
|
|
|
403 |
|
|
memset(&addr, 0, sizeof(addr)); |
404 |
|
|
TCHECK2(pd[1], (plen + 7) / 8); |
405 |
|
|
memcpy(&addr, &pd[1], (plen + 7) / 8); |
406 |
|
|
if (plen % 8) { |
407 |
|
|
addr.s6_addr[(plen + 7) / 8 - 1] &= |
408 |
|
|
((0xff00 >> (plen % 8)) & 0xff); |
409 |
|
|
} |
410 |
|
|
|
411 |
|
|
n = snprintf(buf, buflen, "%s/%u", getname6((u_char *)&addr), plen); |
412 |
|
|
if (n == -1 || n >= buflen) |
413 |
|
|
return -1; |
414 |
|
|
|
415 |
|
|
return 1 + (plen + 7) / 8; |
416 |
|
|
|
417 |
|
|
trunc: |
418 |
|
|
return -2; |
419 |
|
|
} |
420 |
|
|
#endif |
421 |
|
|
|
422 |
|
|
static int |
423 |
|
|
bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len) |
424 |
|
|
{ |
425 |
|
|
int i; |
426 |
|
|
u_int16_t af; |
427 |
|
|
u_int8_t safi, snpa; |
428 |
|
|
int advance; |
429 |
|
|
int tlen, asn_bytes; |
430 |
|
|
const u_char *p; |
431 |
|
|
char buf[HOST_NAME_MAX+1 + 100]; |
432 |
|
|
|
433 |
|
|
p = dat; |
434 |
|
|
tlen = len; |
435 |
|
|
asn_bytes = 0; |
436 |
|
|
|
437 |
|
|
switch (attr->bgpa_type) { |
438 |
|
|
case BGPTYPE_ORIGIN: |
439 |
|
|
if (len != 1) |
440 |
|
|
printf(" invalid len"); |
441 |
|
|
else { |
442 |
|
|
TCHECK(p[0]); |
443 |
|
|
printf(" %s", bgp_attr_origin(p[0])); |
444 |
|
|
} |
445 |
|
|
break; |
446 |
|
|
case BGPTYPE_AS4_PATH: |
447 |
|
|
asn_bytes = 4; |
448 |
|
|
/* FALLTHROUGH */ |
449 |
|
|
case BGPTYPE_AS_PATH: |
450 |
|
|
/* |
451 |
|
|
* 2-byte speakers will receive AS4_PATH as well AS_PATH (2-byte). |
452 |
|
|
* 4-byte speakers will only receive AS_PATH but it will be 4-byte. |
453 |
|
|
* To identify which is the case, compare the length of the path |
454 |
|
|
* segment value in bytes, with the path segment length from the |
455 |
|
|
* message (counted in # of AS) |
456 |
|
|
*/ |
457 |
|
|
|
458 |
|
|
if (len % 2) { |
459 |
|
|
printf(" invalid len"); |
460 |
|
|
break; |
461 |
|
|
} |
462 |
|
|
if (!len) { |
463 |
|
|
/* valid: local originated routes to IBGP peers */ |
464 |
|
|
printf(" empty"); |
465 |
|
|
break; |
466 |
|
|
} |
467 |
|
|
while (p < dat + len) { |
468 |
|
|
TCHECK2(p[0], 2); |
469 |
|
|
if (asn_bytes == 0) { |
470 |
|
|
if (p[1] == 0) { |
471 |
|
|
/* invalid: segment contains one or more AS */ |
472 |
|
|
printf(" malformed"); |
473 |
|
|
break; |
474 |
|
|
} |
475 |
|
|
asn_bytes = (len-2)/p[1]; |
476 |
|
|
} |
477 |
|
|
printf("%s", |
478 |
|
|
tok2str(bgp_as_path_segment_open_values, |
479 |
|
|
"?", p[0])); |
480 |
|
|
for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) { |
481 |
|
|
TCHECK2(p[2 + i], asn_bytes); |
482 |
|
|
printf("%s", i == 0 ? "" : " "); |
483 |
|
|
if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i])) |
484 |
|
|
printf("%u%s", |
485 |
|
|
EXTRACT_16BITS(&p[2 + i]), |
486 |
|
|
asn_bytes == 4 ? "." : ""); |
487 |
|
|
if (asn_bytes == 4) |
488 |
|
|
printf("%u", |
489 |
|
|
EXTRACT_16BITS(&p[2 + i + 2])); |
490 |
|
|
} |
491 |
|
|
printf("%s", |
492 |
|
|
tok2str(bgp_as_path_segment_close_values, |
493 |
|
|
"?", p[0])); |
494 |
|
|
p += 2 + p[1] * asn_bytes; |
495 |
|
|
} |
496 |
|
|
break; |
497 |
|
|
case BGPTYPE_NEXT_HOP: |
498 |
|
|
if (len != 4) |
499 |
|
|
printf(" invalid len"); |
500 |
|
|
else { |
501 |
|
|
TCHECK2(p[0], 4); |
502 |
|
|
printf(" %s", getname(p)); |
503 |
|
|
} |
504 |
|
|
break; |
505 |
|
|
case BGPTYPE_MULTI_EXIT_DISC: |
506 |
|
|
case BGPTYPE_LOCAL_PREF: |
507 |
|
|
if (len != 4) |
508 |
|
|
printf(" invalid len"); |
509 |
|
|
else { |
510 |
|
|
TCHECK2(p[0], 4); |
511 |
|
|
printf(" %u", EXTRACT_32BITS(p)); |
512 |
|
|
} |
513 |
|
|
break; |
514 |
|
|
case BGPTYPE_ATOMIC_AGGREGATE: |
515 |
|
|
if (len != 0) |
516 |
|
|
printf(" invalid len"); |
517 |
|
|
break; |
518 |
|
|
case BGPTYPE_AGGREGATOR4: |
519 |
|
|
case BGPTYPE_AGGREGATOR: |
520 |
|
|
/* |
521 |
|
|
* like AS_PATH/AS4_PATH, AGGREGATOR can contain |
522 |
|
|
* either 2-byte or 4-byte ASN, and AGGREGATOR4 |
523 |
|
|
* always contains 4-byte ASN. |
524 |
|
|
*/ |
525 |
|
|
if (len != 6 && len != 8) { |
526 |
|
|
printf(" invalid len"); |
527 |
|
|
break; |
528 |
|
|
} |
529 |
|
|
TCHECK2(p[0], len); |
530 |
|
|
printf(" AS #"); |
531 |
|
|
if (len == 6 || EXTRACT_16BITS(p)) |
532 |
|
|
printf("%u%s", EXTRACT_16BITS(p), len == 8 ? "." : ""); |
533 |
|
|
if (len == 8) |
534 |
|
|
printf("%u", EXTRACT_16BITS(p+2)); |
535 |
|
|
printf(", origin %s", getname(p+len-4)); |
536 |
|
|
break; |
537 |
|
|
case BGPTYPE_COMMUNITIES: |
538 |
|
|
if (len % 4) { |
539 |
|
|
printf(" invalid len"); |
540 |
|
|
break; |
541 |
|
|
} |
542 |
|
|
while (tlen>0) { |
543 |
|
|
u_int32_t comm; |
544 |
|
|
TCHECK2(p[0], 4); |
545 |
|
|
comm = EXTRACT_32BITS(p); |
546 |
|
|
switch (comm) { |
547 |
|
|
case BGP_COMMUNITY_NO_EXPORT: |
548 |
|
|
printf(" NO_EXPORT"); |
549 |
|
|
break; |
550 |
|
|
case BGP_COMMUNITY_NO_ADVERT: |
551 |
|
|
printf(" NO_ADVERTISE"); |
552 |
|
|
break; |
553 |
|
|
case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: |
554 |
|
|
printf(" NO_EXPORT_SUBCONFED"); |
555 |
|
|
break; |
556 |
|
|
case BGP_COMMUNITY_NO_PEER: |
557 |
|
|
printf(" NO_PEER"); |
558 |
|
|
break; |
559 |
|
|
default: |
560 |
|
|
printf(" %d:%d", |
561 |
|
|
(comm >> 16) & 0xffff, comm & 0xffff); |
562 |
|
|
break; |
563 |
|
|
} |
564 |
|
|
tlen -= 4; |
565 |
|
|
p += 4; |
566 |
|
|
} |
567 |
|
|
break; |
568 |
|
|
case BGPTYPE_LARGE_COMMUNITIES: |
569 |
|
|
if (len == 0 || len % 12) { |
570 |
|
|
printf(" invalid len"); |
571 |
|
|
break; |
572 |
|
|
} |
573 |
|
|
while (tlen>0) { |
574 |
|
|
TCHECK2(p[0], 12); |
575 |
|
|
printf(" %u:%u:%u", |
576 |
|
|
EXTRACT_32BITS(p), |
577 |
|
|
EXTRACT_32BITS(p + 4), |
578 |
|
|
EXTRACT_32BITS(p + 8)); |
579 |
|
|
tlen -= 12; |
580 |
|
|
p += 12; |
581 |
|
|
} |
582 |
|
|
break; |
583 |
|
|
case BGPTYPE_ORIGINATOR_ID: |
584 |
|
|
if (len != 4) { |
585 |
|
|
printf(" invalid len"); |
586 |
|
|
break; |
587 |
|
|
} |
588 |
|
|
TCHECK2(p[0], 4); |
589 |
|
|
printf("%s",getname(p)); |
590 |
|
|
break; |
591 |
|
|
case BGPTYPE_CLUSTER_LIST: |
592 |
|
|
if (len % 4) { |
593 |
|
|
printf(" invalid len"); |
594 |
|
|
break; |
595 |
|
|
} |
596 |
|
|
while (tlen>0) { |
597 |
|
|
TCHECK2(p[0], 4); |
598 |
|
|
printf(" %s%s", |
599 |
|
|
getname(p), |
600 |
|
|
(tlen>4) ? ", " : ""); |
601 |
|
|
tlen -=4; |
602 |
|
|
p +=4; |
603 |
|
|
} |
604 |
|
|
break; |
605 |
|
|
case BGPTYPE_MP_REACH_NLRI: |
606 |
|
|
TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); |
607 |
|
|
af = EXTRACT_16BITS(p); |
608 |
|
|
safi = p[2]; |
609 |
|
|
if (safi >= 128) |
610 |
|
|
printf(" %s vendor specific %u,", af_name(af), safi); |
611 |
|
|
else { |
612 |
|
|
printf(" %s %s,", af_name(af), |
613 |
|
|
bgp_attr_nlri_safi(safi)); |
614 |
|
|
} |
615 |
|
|
p += 3; |
616 |
|
|
|
617 |
|
|
if (af == AFNUM_INET) |
618 |
|
|
; |
619 |
|
|
#ifdef INET6 |
620 |
|
|
else if (af == AFNUM_INET6) |
621 |
|
|
; |
622 |
|
|
#endif |
623 |
|
|
else |
624 |
|
|
break; |
625 |
|
|
|
626 |
|
|
TCHECK(p[0]); |
627 |
|
|
tlen = p[0]; |
628 |
|
|
if (tlen) { |
629 |
|
|
printf(" nexthop"); |
630 |
|
|
i = 0; |
631 |
|
|
while (i < tlen) { |
632 |
|
|
switch (af) { |
633 |
|
|
case AFNUM_INET: |
634 |
|
|
TCHECK2(p[1+i], sizeof(struct in_addr)); |
635 |
|
|
printf(" %s", getname(p + 1 + i)); |
636 |
|
|
i += sizeof(struct in_addr); |
637 |
|
|
break; |
638 |
|
|
#ifdef INET6 |
639 |
|
|
case AFNUM_INET6: |
640 |
|
|
TCHECK2(p[1+i], sizeof(struct in6_addr)); |
641 |
|
|
printf(" %s", getname6(p + 1 + i)); |
642 |
|
|
i += sizeof(struct in6_addr); |
643 |
|
|
break; |
644 |
|
|
#endif |
645 |
|
|
default: |
646 |
|
|
printf(" (unknown af)"); |
647 |
|
|
i = tlen; /*exit loop*/ |
648 |
|
|
break; |
649 |
|
|
} |
650 |
|
|
} |
651 |
|
|
printf(","); |
652 |
|
|
} |
653 |
|
|
p += 1 + tlen; |
654 |
|
|
|
655 |
|
|
TCHECK(p[0]); |
656 |
|
|
snpa = p[0]; |
657 |
|
|
p++; |
658 |
|
|
if (snpa) { |
659 |
|
|
printf(" %u snpa", snpa); |
660 |
|
|
for (/*nothing*/; snpa > 0; snpa--) { |
661 |
|
|
TCHECK(p[0]); |
662 |
|
|
printf("(%d bytes)", p[0]); |
663 |
|
|
p += p[0] + 1; |
664 |
|
|
} |
665 |
|
|
printf(","); |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
printf(" NLRI"); |
669 |
|
|
while (len - (p - dat) > 0) { |
670 |
|
|
switch (af) { |
671 |
|
|
case AFNUM_INET: |
672 |
|
|
advance = decode_prefix4(p, buf, sizeof(buf)); |
673 |
|
|
break; |
674 |
|
|
#ifdef INET6 |
675 |
|
|
case AFNUM_INET6: |
676 |
|
|
advance = decode_prefix6(p, buf, sizeof(buf)); |
677 |
|
|
break; |
678 |
|
|
#endif |
679 |
|
|
default: |
680 |
|
|
printf(" (unknown af)"); |
681 |
|
|
advance = 0; |
682 |
|
|
p = dat + len; |
683 |
|
|
break; |
684 |
|
|
} |
685 |
|
|
|
686 |
|
|
if (advance <= 0) |
687 |
|
|
break; |
688 |
|
|
|
689 |
|
|
printf(" %s", buf); |
690 |
|
|
p += advance; |
691 |
|
|
} |
692 |
|
|
|
693 |
|
|
break; |
694 |
|
|
|
695 |
|
|
case BGPTYPE_MP_UNREACH_NLRI: |
696 |
|
|
TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); |
697 |
|
|
af = EXTRACT_16BITS(p); |
698 |
|
|
safi = p[2]; |
699 |
|
|
if (safi >= 128) |
700 |
|
|
printf(" %s vendor specific %u,", af_name(af), safi); |
701 |
|
|
else { |
702 |
|
|
printf(" %s %s,", af_name(af), |
703 |
|
|
bgp_attr_nlri_safi(safi)); |
704 |
|
|
} |
705 |
|
|
p += 3; |
706 |
|
|
|
707 |
|
|
printf(" Withdraw"); |
708 |
|
|
while (len - (p - dat) > 0) { |
709 |
|
|
switch (af) { |
710 |
|
|
case AFNUM_INET: |
711 |
|
|
advance = decode_prefix4(p, buf, sizeof(buf)); |
712 |
|
|
break; |
713 |
|
|
#ifdef INET6 |
714 |
|
|
case AFNUM_INET6: |
715 |
|
|
advance = decode_prefix6(p, buf, sizeof(buf)); |
716 |
|
|
break; |
717 |
|
|
#endif |
718 |
|
|
default: |
719 |
|
|
printf(" (unknown af)"); |
720 |
|
|
advance = 0; |
721 |
|
|
p = dat + len; |
722 |
|
|
break; |
723 |
|
|
} |
724 |
|
|
|
725 |
|
|
if (advance <= 0) |
726 |
|
|
break; |
727 |
|
|
|
728 |
|
|
printf(" %s", buf); |
729 |
|
|
p += advance; |
730 |
|
|
} |
731 |
|
|
break; |
732 |
|
|
default: |
733 |
|
|
break; |
734 |
|
|
} |
735 |
|
|
return 1; |
736 |
|
|
|
737 |
|
|
trunc: |
738 |
|
|
return 0; |
739 |
|
|
} |
740 |
|
|
|
741 |
|
|
static void |
742 |
|
|
bgp_open_capa_print(const u_char *opt, int length) |
743 |
|
|
{ |
744 |
|
|
int i,cap_type,cap_len,tcap_len,cap_offset; |
745 |
|
|
|
746 |
|
|
i = 0; |
747 |
|
|
while (i < length) { |
748 |
|
|
TCHECK2(opt[i], 2); |
749 |
|
|
|
750 |
|
|
cap_type=opt[i]; |
751 |
|
|
cap_len=opt[i+1]; |
752 |
|
|
printf("%sCAP %s", i == 0 ? "(" : " ", /* ) */ |
753 |
|
|
bgp_capcode(cap_type)); |
754 |
|
|
|
755 |
|
|
/* can we print the capability? */ |
756 |
|
|
TCHECK2(opt[i+2],cap_len); |
757 |
|
|
i += 2; |
758 |
|
|
|
759 |
|
|
switch(cap_type) { |
760 |
|
|
case BGP_CAPCODE_MP: |
761 |
|
|
if (cap_len != 4) { |
762 |
|
|
printf(" BAD ENCODING"); |
763 |
|
|
break; |
764 |
|
|
} |
765 |
|
|
printf(" [%s %s]", |
766 |
|
|
af_name(EXTRACT_16BITS(opt+i)), |
767 |
|
|
bgp_attr_nlri_safi(opt[i+3])); |
768 |
|
|
break; |
769 |
|
|
case BGP_CAPCODE_REFRESH: |
770 |
|
|
if (cap_len != 0) { |
771 |
|
|
printf(" BAD ENCODING"); |
772 |
|
|
break; |
773 |
|
|
} |
774 |
|
|
break; |
775 |
|
|
case BGP_CAPCODE_RESTART: |
776 |
|
|
if (cap_len < 2 || (cap_len - 2) % 4) { |
777 |
|
|
printf(" BAD ENCODING"); |
778 |
|
|
break; |
779 |
|
|
} |
780 |
|
|
printf(" [%s], Time %us", |
781 |
|
|
((opt[i])&0x80) ? "R" : "none", |
782 |
|
|
EXTRACT_16BITS(opt+i)&0xfff); |
783 |
|
|
tcap_len=cap_len - 2; |
784 |
|
|
cap_offset=2; |
785 |
|
|
while(tcap_len>=4) { |
786 |
|
|
printf(" (%s %s)%s", |
787 |
|
|
af_name(EXTRACT_16BITS(opt+i+cap_offset)), |
788 |
|
|
bgp_attr_nlri_safi(opt[i+cap_offset+2]), |
789 |
|
|
((opt[i+cap_offset+3])&0x80) ? |
790 |
|
|
" forwarding state preserved" : "" ); |
791 |
|
|
tcap_len-=4; |
792 |
|
|
cap_offset+=4; |
793 |
|
|
} |
794 |
|
|
break; |
795 |
|
|
case BGP_CAPCODE_AS4: |
796 |
|
|
if (cap_len != 4) { |
797 |
|
|
printf(" BAD ENCODING"); |
798 |
|
|
break; |
799 |
|
|
} |
800 |
|
|
printf(" #"); |
801 |
|
|
if (EXTRACT_16BITS(opt+i)) |
802 |
|
|
printf("%u.", |
803 |
|
|
EXTRACT_16BITS(opt+i)); |
804 |
|
|
printf("%u", |
805 |
|
|
EXTRACT_16BITS(opt+i+2)); |
806 |
|
|
break; |
807 |
|
|
default: |
808 |
|
|
printf(" len %d", cap_len); |
809 |
|
|
break; |
810 |
|
|
} |
811 |
|
|
i += cap_len; |
812 |
|
|
if (i + cap_len < length) |
813 |
|
|
printf(","); |
814 |
|
|
} |
815 |
|
|
/* ( */ |
816 |
|
|
printf(")"); |
817 |
|
|
return; |
818 |
|
|
trunc: |
819 |
|
|
printf("[|BGP]"); |
820 |
|
|
} |
821 |
|
|
|
822 |
|
|
static void |
823 |
|
|
bgp_open_print(const u_char *dat, int length) |
824 |
|
|
{ |
825 |
|
|
struct bgp_open bgpo; |
826 |
|
|
struct bgp_opt bgpopt; |
827 |
|
|
const u_char *opt; |
828 |
|
|
int i; |
829 |
|
|
|
830 |
|
|
TCHECK2(dat[0], BGP_OPEN_SIZE); |
831 |
|
|
memcpy(&bgpo, dat, BGP_OPEN_SIZE); |
832 |
|
|
|
833 |
|
|
printf(": Version %d,", bgpo.bgpo_version); |
834 |
|
|
printf(" AS #%u,", ntohs(bgpo.bgpo_myas)); |
835 |
|
|
printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)); |
836 |
|
|
printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id)); |
837 |
|
|
printf(" Option length %u", bgpo.bgpo_optlen); |
838 |
|
|
|
839 |
|
|
/* sanity checking */ |
840 |
|
|
if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) || (!bgpo.bgpo_optlen)) |
841 |
|
|
return; |
842 |
|
|
|
843 |
|
|
/* ugly! */ |
844 |
|
|
opt = &((const struct bgp_open *)dat)->bgpo_optlen; |
845 |
|
|
opt++; |
846 |
|
|
|
847 |
|
|
i = 0; |
848 |
|
|
while (i < bgpo.bgpo_optlen) { |
849 |
|
|
TCHECK2(opt[i], BGP_OPT_SIZE); |
850 |
|
|
memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); |
851 |
|
|
if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { |
852 |
|
|
printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); |
853 |
|
|
break; |
854 |
|
|
} |
855 |
|
|
|
856 |
|
|
if (i == 0) |
857 |
|
|
printf(" ("); /* ) */ |
858 |
|
|
else |
859 |
|
|
printf(" "); |
860 |
|
|
|
861 |
|
|
switch(bgpopt.bgpopt_type) { |
862 |
|
|
case BGP_OPT_CAP: |
863 |
|
|
bgp_open_capa_print(opt + i + BGP_OPT_SIZE, |
864 |
|
|
bgpopt.bgpopt_len); |
865 |
|
|
break; |
866 |
|
|
default: |
867 |
|
|
printf(" (option %s, len=%u)", |
868 |
|
|
bgp_opttype(bgpopt.bgpopt_type), |
869 |
|
|
bgpopt.bgpopt_len); |
870 |
|
|
break; |
871 |
|
|
} |
872 |
|
|
|
873 |
|
|
i += BGP_OPT_SIZE + bgpopt.bgpopt_len; |
874 |
|
|
} |
875 |
|
|
/* ( */ |
876 |
|
|
printf(")"); |
877 |
|
|
return; |
878 |
|
|
trunc: |
879 |
|
|
printf("[|BGP]"); |
880 |
|
|
} |
881 |
|
|
|
882 |
|
|
static void |
883 |
|
|
bgp_update_print(const u_char *dat, int length) |
884 |
|
|
{ |
885 |
|
|
struct bgp bgp; |
886 |
|
|
struct bgp_attr bgpa; |
887 |
|
|
const u_char *p; |
888 |
|
|
int len; |
889 |
|
|
int i; |
890 |
|
|
int newline; |
891 |
|
|
|
892 |
|
|
TCHECK2(dat[0], BGP_SIZE); |
893 |
|
|
memcpy(&bgp, dat, BGP_SIZE); |
894 |
|
|
p = dat + BGP_SIZE; /*XXX*/ |
895 |
|
|
printf(":"); |
896 |
|
|
|
897 |
|
|
/* Unfeasible routes */ |
898 |
|
|
len = EXTRACT_16BITS(p); |
899 |
|
|
if (len) { |
900 |
|
|
/* |
901 |
|
|
* Without keeping state from the original NLRI message, |
902 |
|
|
* it's not possible to tell if this a v4 or v6 route, |
903 |
|
|
* so only try to decode it if we're not v6 enabled. |
904 |
|
|
*/ |
905 |
|
|
#ifdef INET6 |
906 |
|
|
printf(" (Withdrawn routes: %d bytes)", len); |
907 |
|
|
#else |
908 |
|
|
char buf[HOST_NAME_MAX+1 + 100]; |
909 |
|
|
int wpfx; |
910 |
|
|
|
911 |
|
|
TCHECK2(p[2], len); |
912 |
|
|
i = 2; |
913 |
|
|
|
914 |
|
|
printf(" (Withdrawn routes:"); |
915 |
|
|
|
916 |
|
|
while(i < 2 + len) { |
917 |
|
|
wpfx = decode_prefix4(&p[i], buf, sizeof(buf)); |
918 |
|
|
if (wpfx == -1) { |
919 |
|
|
printf(" (illegal prefix length)"); |
920 |
|
|
break; |
921 |
|
|
} else if (wpfx == -2) |
922 |
|
|
goto trunc; |
923 |
|
|
i += wpfx; |
924 |
|
|
printf(" %s", buf); |
925 |
|
|
} |
926 |
|
|
printf(")"); |
927 |
|
|
#endif |
928 |
|
|
} |
929 |
|
|
p += 2 + len; |
930 |
|
|
|
931 |
|
|
TCHECK2(p[0], 2); |
932 |
|
|
len = EXTRACT_16BITS(p); |
933 |
|
|
|
934 |
|
|
if (len == 0 && length == BGP_UPDATE_MINSIZE) { |
935 |
|
|
printf(" End-of-Rib Marker (empty NLRI)"); |
936 |
|
|
return; |
937 |
|
|
} |
938 |
|
|
|
939 |
|
|
if (len) { |
940 |
|
|
/* do something more useful!*/ |
941 |
|
|
i = 2; |
942 |
|
|
printf(" (Path attributes:"); /* ) */ |
943 |
|
|
newline = 0; |
944 |
|
|
while (i < 2 + len) { |
945 |
|
|
int alen, aoff; |
946 |
|
|
|
947 |
|
|
TCHECK2(p[i], sizeof(bgpa)); |
948 |
|
|
memcpy(&bgpa, &p[i], sizeof(bgpa)); |
949 |
|
|
alen = bgp_attr_len(&bgpa); |
950 |
|
|
aoff = bgp_attr_off(&bgpa); |
951 |
|
|
|
952 |
|
|
if (vflag && newline) |
953 |
|
|
printf("\n\t\t"); |
954 |
|
|
else |
955 |
|
|
printf(" "); |
956 |
|
|
printf("("); /* ) */ |
957 |
|
|
printf("%s", bgp_attr_type(bgpa.bgpa_type)); |
958 |
|
|
if (bgpa.bgpa_flags) { |
959 |
|
|
printf("[%s%s%s%s", |
960 |
|
|
bgpa.bgpa_flags & 0x80 ? "O" : "", |
961 |
|
|
bgpa.bgpa_flags & 0x40 ? "T" : "", |
962 |
|
|
bgpa.bgpa_flags & 0x20 ? "P" : "", |
963 |
|
|
bgpa.bgpa_flags & 0x10 ? "E" : ""); |
964 |
|
|
if (bgpa.bgpa_flags & 0xf) |
965 |
|
|
printf("+%x", bgpa.bgpa_flags & 0xf); |
966 |
|
|
printf("]"); |
967 |
|
|
} |
968 |
|
|
|
969 |
|
|
if (!bgp_attr_print(&bgpa, &p[i + aoff], alen)) |
970 |
|
|
goto trunc; |
971 |
|
|
newline = 1; |
972 |
|
|
|
973 |
|
|
/* ( */ |
974 |
|
|
printf(")"); |
975 |
|
|
|
976 |
|
|
i += aoff + alen; |
977 |
|
|
} |
978 |
|
|
|
979 |
|
|
/* ( */ |
980 |
|
|
printf(")"); |
981 |
|
|
} |
982 |
|
|
p += 2 + len; |
983 |
|
|
|
984 |
|
|
if (len && dat + length > p) |
985 |
|
|
printf("\n\t\t"); |
986 |
|
|
if (dat + length > p) { |
987 |
|
|
printf("(NLRI:"); /* ) */ |
988 |
|
|
while (dat + length > p) { |
989 |
|
|
char buf[HOST_NAME_MAX+1 + 100]; |
990 |
|
|
i = decode_prefix4(p, buf, sizeof(buf)); |
991 |
|
|
if (i == -1) { |
992 |
|
|
printf(" (illegal prefix length)"); |
993 |
|
|
break; |
994 |
|
|
} else if (i == -2) |
995 |
|
|
goto trunc; |
996 |
|
|
printf(" %s", buf); |
997 |
|
|
p += i; |
998 |
|
|
} |
999 |
|
|
|
1000 |
|
|
/* ( */ |
1001 |
|
|
printf(")"); |
1002 |
|
|
} |
1003 |
|
|
return; |
1004 |
|
|
trunc: |
1005 |
|
|
printf("[|BGP]"); |
1006 |
|
|
} |
1007 |
|
|
|
1008 |
|
|
static void |
1009 |
|
|
bgp_notification_print(const u_char *dat, int length) |
1010 |
|
|
{ |
1011 |
|
|
struct bgp_notification bgpn; |
1012 |
|
|
u_int16_t af; |
1013 |
|
|
u_int8_t safi; |
1014 |
|
|
const u_char *p; |
1015 |
|
|
uint8_t shutdown_comm_length; |
1016 |
|
|
char shutstring[BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN + 1]; |
1017 |
|
|
|
1018 |
|
|
TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); |
1019 |
|
|
memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); |
1020 |
|
|
|
1021 |
|
|
/* sanity checking */ |
1022 |
|
|
if (length<BGP_NOTIFICATION_SIZE) |
1023 |
|
|
return; |
1024 |
|
|
|
1025 |
|
|
printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)); |
1026 |
|
|
printf(" subcode %s", |
1027 |
|
|
bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); |
1028 |
|
|
|
1029 |
|
|
if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE) { |
1030 |
|
|
/* |
1031 |
|
|
* RFC 4486: optional maxprefix subtype of 7 bytes |
1032 |
|
|
* may contain AFI, SAFI and MAXPREFIXES |
1033 |
|
|
*/ |
1034 |
|
|
if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && |
1035 |
|
|
length >= BGP_NOTIFICATION_SIZE + 7) { |
1036 |
|
|
|
1037 |
|
|
p = dat + BGP_NOTIFICATION_SIZE; |
1038 |
|
|
TCHECK2(*p, 7); |
1039 |
|
|
|
1040 |
|
|
af = EXTRACT_16BITS(p); |
1041 |
|
|
safi = p[2]; |
1042 |
|
|
printf(" %s %s,", af_name(af), |
1043 |
|
|
bgp_attr_nlri_safi(safi)); |
1044 |
|
|
|
1045 |
|
|
printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3)); |
1046 |
|
|
} |
1047 |
|
|
|
1048 |
|
|
/* |
1049 |
|
|
* RFC 8203 describes a method to send a message intended |
1050 |
|
|
* for human consumption regarding the Administrative |
1051 |
|
|
* Shutdown or Reset event. This is called the "Shutdown |
1052 |
|
|
* Communication". The communication is UTF-8 encoded |
1053 |
|
|
* and may be no longer than 128 bytes. |
1054 |
|
|
*/ |
1055 |
|
|
if ((bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT || |
1056 |
|
|
bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) && |
1057 |
|
|
(length >= BGP_NOTIFICATION_SIZE + 1)) { |
1058 |
|
|
p = dat + BGP_NOTIFICATION_SIZE; |
1059 |
|
|
TCHECK2(*p, 1); |
1060 |
|
|
shutdown_comm_length = *(p); |
1061 |
|
|
|
1062 |
|
|
/* sanity checking */ |
1063 |
|
|
if (shutdown_comm_length == 0) |
1064 |
|
|
return; |
1065 |
|
|
if (shutdown_comm_length > |
1066 |
|
|
BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN) |
1067 |
|
|
return; |
1068 |
|
|
if (length < (shutdown_comm_length + 1 + BGP_NOTIFICATION_SIZE)) |
1069 |
|
|
return; |
1070 |
|
|
TCHECK2(*(p+1), shutdown_comm_length); |
1071 |
|
|
|
1072 |
|
|
/* a proper shutdown communication */ |
1073 |
|
|
printf(", Shutdown Communication [len %u]: \"", |
1074 |
|
|
shutdown_comm_length); |
1075 |
|
|
memset(shutstring, 0, BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN + 1); |
1076 |
|
|
memcpy(shutstring, p+1, shutdown_comm_length); |
1077 |
|
|
safeputs(shutstring); |
1078 |
|
|
printf("\""); |
1079 |
|
|
} |
1080 |
|
|
} |
1081 |
|
|
|
1082 |
|
|
return; |
1083 |
|
|
|
1084 |
|
|
trunc: |
1085 |
|
|
printf("[|BGP]"); |
1086 |
|
|
} |
1087 |
|
|
|
1088 |
|
|
static void |
1089 |
|
|
bgp_route_refresh_print(const u_char *dat, int length) |
1090 |
|
|
{ |
1091 |
|
|
const struct bgp_route_refresh *bgp_route_refresh_header; |
1092 |
|
|
|
1093 |
|
|
TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE); |
1094 |
|
|
|
1095 |
|
|
/* sanity checking */ |
1096 |
|
|
if (length<BGP_ROUTE_REFRESH_SIZE) |
1097 |
|
|
return; |
1098 |
|
|
|
1099 |
|
|
bgp_route_refresh_header = (const struct bgp_route_refresh *)dat; |
1100 |
|
|
|
1101 |
|
|
printf(" (%s %s)", |
1102 |
|
|
af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi)), |
1103 |
|
|
bgp_attr_nlri_safi(bgp_route_refresh_header->safi)); |
1104 |
|
|
|
1105 |
|
|
return; |
1106 |
|
|
trunc: |
1107 |
|
|
printf("[|BGP]"); |
1108 |
|
|
} |
1109 |
|
|
|
1110 |
|
|
static int |
1111 |
|
|
bgp_header_print(const u_char *dat, int length) |
1112 |
|
|
{ |
1113 |
|
|
struct bgp bgp; |
1114 |
|
|
|
1115 |
|
|
TCHECK2(dat[0], BGP_SIZE); |
1116 |
|
|
memcpy(&bgp, dat, BGP_SIZE); |
1117 |
|
|
printf("(%s", bgp_type(bgp.bgp_type)); /* ) */ |
1118 |
|
|
|
1119 |
|
|
switch (bgp.bgp_type) { |
1120 |
|
|
case BGP_OPEN: |
1121 |
|
|
bgp_open_print(dat, length); |
1122 |
|
|
break; |
1123 |
|
|
case BGP_UPDATE: |
1124 |
|
|
bgp_update_print(dat, length); |
1125 |
|
|
break; |
1126 |
|
|
case BGP_NOTIFICATION: |
1127 |
|
|
bgp_notification_print(dat, length); |
1128 |
|
|
break; |
1129 |
|
|
case BGP_KEEPALIVE: |
1130 |
|
|
break; |
1131 |
|
|
case BGP_ROUTE_REFRESH: |
1132 |
|
|
bgp_route_refresh_print(dat, length); |
1133 |
|
|
default: |
1134 |
|
|
TCHECK2(*dat, length); |
1135 |
|
|
break; |
1136 |
|
|
} |
1137 |
|
|
|
1138 |
|
|
/* ( */ |
1139 |
|
|
printf(")"); |
1140 |
|
|
return 1; |
1141 |
|
|
trunc: |
1142 |
|
|
printf("[|BGP]"); |
1143 |
|
|
return 0; |
1144 |
|
|
} |
1145 |
|
|
|
1146 |
|
|
void |
1147 |
|
|
bgp_print(const u_char *dat, int length) |
1148 |
|
|
{ |
1149 |
|
|
const u_char *p; |
1150 |
|
|
const u_char *ep; |
1151 |
|
|
const u_char *start; |
1152 |
|
|
const u_char marker[] = { |
1153 |
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
1154 |
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
1155 |
|
|
}; |
1156 |
|
|
struct bgp bgp; |
1157 |
|
|
u_int16_t hlen; |
1158 |
|
|
int newline; |
1159 |
|
|
|
1160 |
|
|
ep = dat + length; |
1161 |
|
|
if (snapend < dat + length) |
1162 |
|
|
ep = snapend; |
1163 |
|
|
|
1164 |
|
|
printf(": BGP"); |
1165 |
|
|
|
1166 |
|
|
p = dat; |
1167 |
|
|
newline = 0; |
1168 |
|
|
start = p; |
1169 |
|
|
while (p < ep) { |
1170 |
|
|
if (!TTEST2(p[0], 1)) |
1171 |
|
|
break; |
1172 |
|
|
if (p[0] != 0xff) { |
1173 |
|
|
p++; |
1174 |
|
|
continue; |
1175 |
|
|
} |
1176 |
|
|
|
1177 |
|
|
if (!TTEST2(p[0], sizeof(marker))) |
1178 |
|
|
break; |
1179 |
|
|
if (memcmp(p, marker, sizeof(marker)) != 0) { |
1180 |
|
|
p++; |
1181 |
|
|
continue; |
1182 |
|
|
} |
1183 |
|
|
|
1184 |
|
|
/* found BGP header */ |
1185 |
|
|
TCHECK2(p[0], BGP_SIZE); /*XXX*/ |
1186 |
|
|
memcpy(&bgp, p, BGP_SIZE); |
1187 |
|
|
|
1188 |
|
|
if (start != p) |
1189 |
|
|
printf(" [|BGP]"); |
1190 |
|
|
|
1191 |
|
|
hlen = ntohs(bgp.bgp_len); |
1192 |
|
|
if (vflag && newline) |
1193 |
|
|
printf("\n\t"); |
1194 |
|
|
else |
1195 |
|
|
printf(" "); |
1196 |
|
|
if (hlen < BGP_SIZE) { |
1197 |
|
|
printf("\n[|BGP Bogus header length %u < %u]", |
1198 |
|
|
hlen, BGP_SIZE); |
1199 |
|
|
break; |
1200 |
|
|
} |
1201 |
|
|
if (TTEST2(p[0], hlen)) { |
1202 |
|
|
if (!bgp_header_print(p, hlen)) |
1203 |
|
|
return; |
1204 |
|
|
newline = 1; |
1205 |
|
|
p += hlen; |
1206 |
|
|
start = p; |
1207 |
|
|
} else { |
1208 |
|
|
printf("[|BGP %s]", bgp_type(bgp.bgp_type)); |
1209 |
|
|
break; |
1210 |
|
|
} |
1211 |
|
|
} |
1212 |
|
|
|
1213 |
|
|
return; |
1214 |
|
|
|
1215 |
|
|
trunc: |
1216 |
|
|
printf(" [|BGP]"); |
1217 |
|
|
} |