File: | src/usr.sbin/tcpdump/print-bgp.c |
Warning: | line 378, column 2 Value stored to 'plen' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: print-bgp.c,v 1.30 2021/06/17 15:59:23 job 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(*__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_SIZE19 19 /* unaligned */ |
55 | |
56 | #define BGP_OPEN1 1 |
57 | #define BGP_UPDATE2 2 |
58 | #define BGP_NOTIFICATION3 3 |
59 | #define BGP_KEEPALIVE4 4 |
60 | #define BGP_ROUTE_REFRESH5 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_SIZE29 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_CAP2 2 |
81 | #define BGP_OPT_SIZE2 2 /* some compilers may pad to 4 bytes */ |
82 | |
83 | #define BGP_UPDATE_MINSIZE23 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_SIZE21 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 subtype; |
101 | u_int8_t safi; |
102 | }; |
103 | #define BGP_ROUTE_REFRESH_SIZE23 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)(((p)->bgpa_flags & 0x10) ? (__uint16_t)(__builtin_constant_p ((p)->bgpa_len.elen) ? (__uint16_t)(((__uint16_t)((p)-> bgpa_len.elen) & 0xffU) << 8 | ((__uint16_t)((p)-> bgpa_len.elen) & 0xff00U) >> 8) : __swap16md((p)-> bgpa_len.elen)) : (p)->bgpa_len.len) \ |
113 | (((p)->bgpa_flags & 0x10) ? \ |
114 | ntohs((p)->bgpa_len.elen)(__uint16_t)(__builtin_constant_p((p)->bgpa_len.elen) ? (__uint16_t )(((__uint16_t)((p)->bgpa_len.elen) & 0xffU) << 8 | ((__uint16_t)((p)->bgpa_len.elen) & 0xff00U) >> 8) : __swap16md((p)->bgpa_len.elen)) : (p)->bgpa_len.len) |
115 | #define bgp_attr_off(p)(((p)->bgpa_flags & 0x10) ? 4 : 3) \ |
116 | (((p)->bgpa_flags & 0x10) ? 4 : 3) |
117 | }; |
118 | |
119 | #define BGPTYPE_ORIGIN1 1 |
120 | #define BGPTYPE_AS_PATH2 2 |
121 | #define BGPTYPE_NEXT_HOP3 3 |
122 | #define BGPTYPE_MULTI_EXIT_DISC4 4 |
123 | #define BGPTYPE_LOCAL_PREF5 5 |
124 | #define BGPTYPE_ATOMIC_AGGREGATE6 6 |
125 | #define BGPTYPE_AGGREGATOR7 7 |
126 | #define BGPTYPE_COMMUNITIES8 8 /* RFC1997 */ |
127 | #define BGPTYPE_ORIGINATOR_ID9 9 /* RFC1998 */ |
128 | #define BGPTYPE_CLUSTER_LIST10 10 /* RFC1998 */ |
129 | #define BGPTYPE_DPA11 11 /* draft-ietf-idr-bgp-dpa */ |
130 | #define BGPTYPE_ADVERTISERS12 12 /* RFC1863 */ |
131 | #define BGPTYPE_RCID_PATH13 13 /* RFC1863 */ |
132 | #define BGPTYPE_MP_REACH_NLRI14 14 /* RFC2283 */ |
133 | #define BGPTYPE_MP_UNREACH_NLRI15 15 /* RFC2283 */ |
134 | #define BGPTYPE_EXTD_COMMUNITIES16 16 /* RFC4360 */ |
135 | #define BGPTYPE_AS4_PATH17 17 /* RFC4893 */ |
136 | #define BGPTYPE_AGGREGATOR418 18 /* RFC4893 */ |
137 | #define BGPTYPE_LARGE_COMMUNITIES32 32 /* draft-ietf-idr-large-community */ |
138 | |
139 | #define BGP_AS_SET1 1 |
140 | #define BGP_AS_SEQUENCE2 2 |
141 | #define BGP_CONFED_AS_SEQUENCE3 3 /* draft-ietf-idr-rfc3065bis-01 */ |
142 | #define BGP_CONFED_AS_SET4 4 /* draft-ietf-idr-rfc3065bis-01 */ |
143 | |
144 | static struct tok bgp_as_path_segment_open_values[] = { |
145 | { BGP_AS_SET1, " {" }, |
146 | { BGP_AS_SEQUENCE2, " " }, |
147 | { BGP_CONFED_AS_SEQUENCE3, " (" }, |
148 | { BGP_CONFED_AS_SET4, " ({" }, |
149 | { 0, NULL((void *)0)}, |
150 | }; |
151 | |
152 | static struct tok bgp_as_path_segment_close_values[] = { |
153 | { BGP_AS_SET1, "}" }, |
154 | { BGP_AS_SEQUENCE2, "" }, |
155 | { BGP_CONFED_AS_SEQUENCE3, ")" }, |
156 | { BGP_CONFED_AS_SET4, "})" }, |
157 | { 0, NULL((void *)0)}, |
158 | }; |
159 | |
160 | #define BGP_MP_NLRI_MINSIZE3 3 |
161 | |
162 | static const char *bgptype[] = { |
163 | NULL((void *)0), "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", |
164 | }; |
165 | #define bgp_type(x)num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) |
166 | |
167 | static const char *bgpopt_type[] = { |
168 | NULL((void *)0), "Authentication Information", "Capabilities Advertisement", |
169 | }; |
170 | #define bgp_opttype(x)num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type [0]), (x)) \ |
171 | num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x)) |
172 | |
173 | #define BGP_CAPCODE_MP1 1 |
174 | #define BGP_CAPCODE_REFRESH2 2 |
175 | #define BGP_CAPCODE_RESTART64 64 /* draft-ietf-idr-restart-05 */ |
176 | #define BGP_CAPCODE_AS465 65 /* RFC4893 */ |
177 | |
178 | static const char *bgp_capcode[] = { |
179 | NULL((void *)0), "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 | /* 70: RFC7313 */ "ENHANCED_ROUTE_REFRESH" |
193 | }; |
194 | |
195 | #define bgp_capcode(x)num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode [0]), (x)) \ |
196 | num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode[0]), (x)) |
197 | |
198 | #define BGP_NOTIFY_MAJOR_CEASE6 6 |
199 | static const char *bgpnotify_major[] = { |
200 | NULL((void *)0), "Message Header Error", |
201 | "OPEN Message Error", "UPDATE Message Error", |
202 | "Hold Timer Expired", "Finite State Machine Error", |
203 | "Cease", "ROUTE_REFRESH Message Error", |
204 | }; |
205 | #define bgp_notify_major(x)num_or_str(bgpnotify_major, sizeof(bgpnotify_major)/sizeof(bgpnotify_major [0]), (x)) \ |
206 | num_or_str(bgpnotify_major, \ |
207 | sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x)) |
208 | |
209 | static const char *bgpnotify_minor_msg[] = { |
210 | NULL((void *)0), "Connection Not Synchronized", |
211 | "Bad Message Length", "Bad Message Type", |
212 | }; |
213 | |
214 | static const char *bgpnotify_minor_open[] = { |
215 | NULL((void *)0), "Unsupported Version Number", |
216 | "Bad Peer AS", "Bad BGP Identifier", |
217 | "Unsupported Optional Parameter", "Authentication Failure", |
218 | "Unacceptable Hold Time", "Unsupported Capability", |
219 | }; |
220 | |
221 | static const char *bgpnotify_minor_update[] = { |
222 | NULL((void *)0), "Malformed Attribute List", |
223 | "Unrecognized Well-known Attribute", "Missing Well-known Attribute", |
224 | "Attribute Flags Error", "Attribute Length Error", |
225 | "Invalid ORIGIN Attribute", "AS Routing Loop", |
226 | "Invalid NEXT_HOP Attribute", "Optional Attribute Error", |
227 | "Invalid Network Field", "Malformed AS_PATH", |
228 | }; |
229 | |
230 | static const char *bgpnotify_minor_holdtime[] = { |
231 | NULL((void *)0), |
232 | }; |
233 | |
234 | /* RFC 6608 */ |
235 | static const char *bgpnotify_minor_fsm[] = { |
236 | "Unspecified Error", "In OpenSent State", "In OpenConfirm State", |
237 | "In Established State", |
238 | }; |
239 | |
240 | /* RFC 4486 */ |
241 | #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX1 1 |
242 | /* RFC 8203 */ |
243 | #define BGP_NOTIFY_MINOR_CEASE_SHUT2 2 |
244 | #define BGP_NOTIFY_MINOR_CEASE_RESET4 4 |
245 | #define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN255 255 |
246 | static const char *bgpnotify_minor_cease[] = { |
247 | NULL((void *)0), "Maximum Number of Prefixes Reached", "Administrative Shutdown", |
248 | "Peer De-configured", "Administrative Reset", "Connection Rejected", |
249 | "Other Configuration Change", "Connection Collision Resolution", |
250 | "Out of Resources", |
251 | }; |
252 | |
253 | /* RFC 7313 */ |
254 | static const char *bgpnotify_minor_err[] = { |
255 | NULL((void *)0), "Invalid Message Length", |
256 | }; |
257 | |
258 | static const char **bgpnotify_minor[] = { |
259 | NULL((void *)0), bgpnotify_minor_msg, bgpnotify_minor_open, bgpnotify_minor_update, |
260 | bgpnotify_minor_holdtime, bgpnotify_minor_fsm, bgpnotify_minor_cease, |
261 | bgpnotify_minor_err, |
262 | }; |
263 | static const int bgpnotify_minor_siz[] = { |
264 | 0, |
265 | sizeof(bgpnotify_minor_msg)/sizeof(bgpnotify_minor_msg[0]), |
266 | sizeof(bgpnotify_minor_open)/sizeof(bgpnotify_minor_open[0]), |
267 | sizeof(bgpnotify_minor_update)/sizeof(bgpnotify_minor_update[0]), |
268 | sizeof(bgpnotify_minor_holdtime)/sizeof(bgpnotify_minor_holdtime[0]), |
269 | sizeof(bgpnotify_minor_fsm)/sizeof(bgpnotify_minor_fsm[0]), |
270 | sizeof(bgpnotify_minor_cease)/sizeof(bgpnotify_minor_cease[0]), |
271 | sizeof(bgpnotify_minor_err)/sizeof(bgpnotify_minor_err[0]), |
272 | }; |
273 | |
274 | static const char *bgpattr_origin[] = { |
275 | "IGP", "EGP", "INCOMPLETE", |
276 | }; |
277 | #define bgp_attr_origin(x)num_or_str(bgpattr_origin, sizeof(bgpattr_origin)/sizeof(bgpattr_origin [0]), (x)) \ |
278 | num_or_str(bgpattr_origin, \ |
279 | sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x)) |
280 | |
281 | static const char *bgpattr_type[] = { |
282 | NULL((void *)0), "ORIGIN", "AS_PATH", "NEXT_HOP", |
283 | "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR", |
284 | "COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA", |
285 | "ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI", |
286 | "EXTD_COMMUNITIES", "AS4_PATH", "AGGREGATOR4", NULL((void *)0), NULL((void *)0), NULL((void *)0), |
287 | NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), |
288 | "LARGE_COMMUNITIES", |
289 | }; |
290 | #define bgp_attr_type(x)num_or_str(bgpattr_type, sizeof(bgpattr_type)/sizeof(bgpattr_type [0]), (x)) \ |
291 | num_or_str(bgpattr_type, \ |
292 | sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x)) |
293 | |
294 | /* Subsequent address family identifier, RFC2283 section 7 */ |
295 | static const char *bgpattr_nlri_safi[] = { |
296 | "Reserved", "Unicast", "Multicast", "Unicast+Multicast", |
297 | "labeled Unicast", /* MPLS BGP RFC3107 */ |
298 | 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 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
302 | /* 64-66: MPLS BGP RFC3107 */ |
303 | "Tunnel", "VPLS", "MDT", |
304 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
305 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
306 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
307 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
308 | /* 128-129: RFC4364 + RFC6513 */ |
309 | "L3VPN Unicast", "L3VPN Multicast", |
310 | }; |
311 | #define bgp_attr_nlri_safi(x)num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (x)) \ |
312 | num_or_str(bgpattr_nlri_safi, \ |
313 | sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x)) |
314 | |
315 | /* well-known community */ |
316 | #define BGP_COMMUNITY_NO_EXPORT0xffffff01 0xffffff01 |
317 | #define BGP_COMMUNITY_NO_ADVERT0xffffff02 0xffffff02 |
318 | #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED0xffffff03 0xffffff03 |
319 | #define BGP_COMMUNITY_NO_PEER0xffffff04 0xffffff04 |
320 | |
321 | static const char *afnumber[] = AFNUM_NAME_STR{ "Reserved", "IPv4", "IPv6", "NSAP", "HDLC", "BBN 1822", "802" , "E.163", "E.164", "F.69", "X.121", "IPX", "Appletalk", "Decnet IV" , "Banyan Vines", "E.164 with NSAP subaddress", "DNS", "AS Number" , "XTP over IPv4", "XTP over IPv6", "XTP native mode", "Fibre Channel WWPN" , "Fibre Channel WWNN", "GWID" }; |
322 | #define af_name(x)(((x) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof(afnumber )/sizeof(afnumber[0]), (x))) \ |
323 | (((x) == 65535) ? afnumber[0] : \ |
324 | num_or_str(afnumber, \ |
325 | sizeof(afnumber)/sizeof(afnumber[0]), (x))) |
326 | |
327 | static const char *refreshtype[] = { |
328 | "Request", "BoRR", "EoRR" |
329 | }; |
330 | #define refresh_subtype(x)num_or_str(refreshtype, sizeof(refreshtype)/sizeof(refreshtype [0]), (x)) \ |
331 | num_or_str(refreshtype, sizeof(refreshtype)/sizeof(refreshtype[0]), (x)) |
332 | |
333 | static const char * |
334 | num_or_str(const char **table, size_t siz, int value) |
335 | { |
336 | static char buf[20]; |
337 | if (value < 0 || siz <= value || table[value] == NULL((void *)0)) { |
338 | snprintf(buf, sizeof(buf), "#%d", value); |
339 | return buf; |
340 | } else |
341 | return table[value]; |
342 | } |
343 | |
344 | static const char * |
345 | bgp_notify_minor(int major, int minor) |
346 | { |
347 | static const char **table; |
348 | int siz; |
349 | static char buf[20]; |
350 | const char *p; |
351 | |
352 | if (0 <= major |
353 | && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0]) |
354 | && bgpnotify_minor[major]) { |
355 | table = bgpnotify_minor[major]; |
356 | siz = bgpnotify_minor_siz[major]; |
357 | if (0 <= minor && minor < siz && table[minor]) |
358 | p = table[minor]; |
359 | else |
360 | p = NULL((void *)0); |
361 | } else |
362 | p = NULL((void *)0); |
363 | if (p == NULL((void *)0)) { |
364 | snprintf(buf, sizeof(buf), "#%d", minor); |
365 | return buf; |
366 | } else |
367 | return p; |
368 | } |
369 | |
370 | static int |
371 | decode_prefix4(const u_char *pd, char *buf, u_int buflen) |
372 | { |
373 | struct in_addr addr; |
374 | u_int plen; |
375 | int n; |
376 | |
377 | TCHECK(pd[0])if (!(snapend - (sizeof(pd[0])) <= snapend && (const u_char *)&(pd[0]) <= snapend - (sizeof(pd[0])))) goto trunc; |
378 | plen = pd[0]; /* |
Value stored to 'plen' is never read | |
379 | * prefix length is in bits; packet only contains |
380 | * enough bytes of address to contain this many bits |
381 | */ |
382 | plen = pd[0]; |
383 | if (32 < plen) |
384 | return -1; |
385 | memset(&addr, 0, sizeof(addr)); |
386 | TCHECK2(pd[1], (plen + 7) / 8)if (!(snapend - ((plen + 7) / 8) <= snapend && (const u_char *)&(pd[1]) <= snapend - ((plen + 7) / 8))) goto trunc; |
387 | memcpy(&addr, &pd[1], (plen + 7) / 8); |
388 | if (plen % 8) { |
389 | ((u_char *)&addr)[(plen + 7) / 8 - 1] &= |
390 | ((0xff00 >> (plen % 8)) & 0xff); |
391 | } |
392 | n = snprintf(buf, buflen, "%s/%u", getname((u_char *)&addr), plen); |
393 | if (n < 0 || n >= buflen) |
394 | return -1; |
395 | |
396 | return 1 + (plen + 7) / 8; |
397 | |
398 | trunc: |
399 | return -2; |
400 | } |
401 | |
402 | static int |
403 | decode_prefix6(const u_char *pd, char *buf, u_int buflen) |
404 | { |
405 | struct in6_addr addr; |
406 | u_int plen; |
407 | int n; |
408 | |
409 | TCHECK(pd[0])if (!(snapend - (sizeof(pd[0])) <= snapend && (const u_char *)&(pd[0]) <= snapend - (sizeof(pd[0])))) goto trunc; |
410 | plen = pd[0]; |
411 | if (128 < plen) |
412 | return -1; |
413 | |
414 | memset(&addr, 0, sizeof(addr)); |
415 | TCHECK2(pd[1], (plen + 7) / 8)if (!(snapend - ((plen + 7) / 8) <= snapend && (const u_char *)&(pd[1]) <= snapend - ((plen + 7) / 8))) goto trunc; |
416 | memcpy(&addr, &pd[1], (plen + 7) / 8); |
417 | if (plen % 8) { |
418 | addr.s6_addr__u6_addr.__u6_addr8[(plen + 7) / 8 - 1] &= |
419 | ((0xff00 >> (plen % 8)) & 0xff); |
420 | } |
421 | |
422 | n = snprintf(buf, buflen, "%s/%u", getname6((u_char *)&addr), plen); |
423 | if (n < 0 || n >= buflen) |
424 | return -1; |
425 | |
426 | return 1 + (plen + 7) / 8; |
427 | |
428 | trunc: |
429 | return -2; |
430 | } |
431 | |
432 | static int |
433 | bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len) |
434 | { |
435 | int i; |
436 | u_int16_t af; |
437 | u_int8_t safi, snpa; |
438 | int advance; |
439 | int tlen, asn_bytes; |
440 | const u_char *p; |
441 | char buf[HOST_NAME_MAX255+1 + 100]; |
442 | |
443 | p = dat; |
444 | tlen = len; |
445 | asn_bytes = 0; |
446 | |
447 | switch (attr->bgpa_type) { |
448 | case BGPTYPE_ORIGIN1: |
449 | if (len != 1) |
450 | printf(" invalid len"); |
451 | else { |
452 | TCHECK(p[0])if (!(snapend - (sizeof(p[0])) <= snapend && (const u_char *)&(p[0]) <= snapend - (sizeof(p[0])))) goto trunc; |
453 | printf(" %s", bgp_attr_origin(p[0])num_or_str(bgpattr_origin, sizeof(bgpattr_origin)/sizeof(bgpattr_origin [0]), (p[0]))); |
454 | } |
455 | break; |
456 | case BGPTYPE_AS4_PATH17: |
457 | asn_bytes = 4; |
458 | /* FALLTHROUGH */ |
459 | case BGPTYPE_AS_PATH2: |
460 | /* |
461 | * 2-byte speakers will receive AS4_PATH as well AS_PATH (2-byte). |
462 | * 4-byte speakers will only receive AS_PATH but it will be 4-byte. |
463 | * To identify which is the case, compare the length of the path |
464 | * segment value in bytes, with the path segment length from the |
465 | * message (counted in # of AS) |
466 | */ |
467 | |
468 | if (len % 2) { |
469 | printf(" invalid len"); |
470 | break; |
471 | } |
472 | if (!len) { |
473 | /* valid: local originated routes to IBGP peers */ |
474 | printf(" empty"); |
475 | break; |
476 | } |
477 | while (p < dat + len) { |
478 | TCHECK2(p[0], 2)if (!(snapend - (2) <= snapend && (const u_char *) &(p[0]) <= snapend - (2))) goto trunc; |
479 | if (asn_bytes == 0) { |
480 | if (p[1] == 0) { |
481 | /* invalid: segment contains one or more AS */ |
482 | printf(" malformed"); |
483 | break; |
484 | } |
485 | asn_bytes = (len-2)/p[1]; |
486 | } |
487 | printf("%s", |
488 | tok2str(bgp_as_path_segment_open_values, |
489 | "?", p[0])); |
490 | for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) { |
491 | TCHECK2(p[2 + i], asn_bytes)if (!(snapend - (asn_bytes) <= snapend && (const u_char *)&(p[2 + i]) <= snapend - (asn_bytes))) goto trunc; |
492 | printf("%s", i == 0 ? "" : " "); |
493 | if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i])((u_int16_t)*((const u_int8_t *)(&p[2 + i]) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&p[2 + i]) + 1))) |
494 | printf("%u%s", |
495 | EXTRACT_16BITS(&p[2 + i])((u_int16_t)*((const u_int8_t *)(&p[2 + i]) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&p[2 + i]) + 1)), |
496 | asn_bytes == 4 ? "." : ""); |
497 | if (asn_bytes == 4) |
498 | printf("%u", |
499 | EXTRACT_16BITS(&p[2 + i + 2])((u_int16_t)*((const u_int8_t *)(&p[2 + i + 2]) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&p[2 + i + 2]) + 1))); |
500 | } |
501 | printf("%s", |
502 | tok2str(bgp_as_path_segment_close_values, |
503 | "?", p[0])); |
504 | p += 2 + p[1] * asn_bytes; |
505 | } |
506 | break; |
507 | case BGPTYPE_NEXT_HOP3: |
508 | if (len != 4) |
509 | printf(" invalid len"); |
510 | else { |
511 | TCHECK2(p[0], 4)if (!(snapend - (4) <= snapend && (const u_char *) &(p[0]) <= snapend - (4))) goto trunc; |
512 | printf(" %s", getname(p)); |
513 | } |
514 | break; |
515 | case BGPTYPE_MULTI_EXIT_DISC4: |
516 | case BGPTYPE_LOCAL_PREF5: |
517 | if (len != 4) |
518 | printf(" invalid len"); |
519 | else { |
520 | TCHECK2(p[0], 4)if (!(snapend - (4) <= snapend && (const u_char *) &(p[0]) <= snapend - (4))) goto trunc; |
521 | printf(" %u", EXTRACT_32BITS(p)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p) + 3))); |
522 | } |
523 | break; |
524 | case BGPTYPE_ATOMIC_AGGREGATE6: |
525 | if (len != 0) |
526 | printf(" invalid len"); |
527 | break; |
528 | case BGPTYPE_AGGREGATOR418: |
529 | case BGPTYPE_AGGREGATOR7: |
530 | /* |
531 | * like AS_PATH/AS4_PATH, AGGREGATOR can contain |
532 | * either 2-byte or 4-byte ASN, and AGGREGATOR4 |
533 | * always contains 4-byte ASN. |
534 | */ |
535 | if (len != 6 && len != 8) { |
536 | printf(" invalid len"); |
537 | break; |
538 | } |
539 | TCHECK2(p[0], len)if (!(snapend - (len) <= snapend && (const u_char * )&(p[0]) <= snapend - (len))) goto trunc; |
540 | printf(" AS #"); |
541 | if (len == 6 || EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1))) |
542 | printf("%u%s", EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1)), len == 8 ? "." : ""); |
543 | if (len == 8) |
544 | printf("%u", EXTRACT_16BITS(p+2)((u_int16_t)*((const u_int8_t *)(p+2) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p+2) + 1))); |
545 | printf(", origin %s", getname(p+len-4)); |
546 | break; |
547 | case BGPTYPE_COMMUNITIES8: |
548 | if (len % 4) { |
549 | printf(" invalid len"); |
550 | break; |
551 | } |
552 | while (tlen>0) { |
553 | u_int32_t comm; |
554 | TCHECK2(p[0], 4)if (!(snapend - (4) <= snapend && (const u_char *) &(p[0]) <= snapend - (4))) goto trunc; |
555 | comm = EXTRACT_32BITS(p)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p) + 3)); |
556 | switch (comm) { |
557 | case BGP_COMMUNITY_NO_EXPORT0xffffff01: |
558 | printf(" NO_EXPORT"); |
559 | break; |
560 | case BGP_COMMUNITY_NO_ADVERT0xffffff02: |
561 | printf(" NO_ADVERTISE"); |
562 | break; |
563 | case BGP_COMMUNITY_NO_EXPORT_SUBCONFED0xffffff03: |
564 | printf(" NO_EXPORT_SUBCONFED"); |
565 | break; |
566 | case BGP_COMMUNITY_NO_PEER0xffffff04: |
567 | printf(" NO_PEER"); |
568 | break; |
569 | default: |
570 | printf(" %d:%d", |
571 | (comm >> 16) & 0xffff, comm & 0xffff); |
572 | break; |
573 | } |
574 | tlen -= 4; |
575 | p += 4; |
576 | } |
577 | break; |
578 | case BGPTYPE_LARGE_COMMUNITIES32: |
579 | if (len == 0 || len % 12) { |
580 | printf(" invalid len"); |
581 | break; |
582 | } |
583 | while (tlen>0) { |
584 | TCHECK2(p[0], 12)if (!(snapend - (12) <= snapend && (const u_char * )&(p[0]) <= snapend - (12))) goto trunc; |
585 | printf(" %u:%u:%u", |
586 | EXTRACT_32BITS(p)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p) + 3)), |
587 | EXTRACT_32BITS(p + 4)((u_int32_t)*((const u_int8_t *)(p + 4) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p + 4) + 1) << 16 | (u_int32_t)*( (const u_int8_t *)(p + 4) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p + 4) + 3)), |
588 | EXTRACT_32BITS(p + 8)((u_int32_t)*((const u_int8_t *)(p + 8) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p + 8) + 1) << 16 | (u_int32_t)*( (const u_int8_t *)(p + 8) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p + 8) + 3))); |
589 | tlen -= 12; |
590 | p += 12; |
591 | } |
592 | break; |
593 | case BGPTYPE_ORIGINATOR_ID9: |
594 | if (len != 4) { |
595 | printf(" invalid len"); |
596 | break; |
597 | } |
598 | TCHECK2(p[0], 4)if (!(snapend - (4) <= snapend && (const u_char *) &(p[0]) <= snapend - (4))) goto trunc; |
599 | printf("%s",getname(p)); |
600 | break; |
601 | case BGPTYPE_CLUSTER_LIST10: |
602 | if (len % 4) { |
603 | printf(" invalid len"); |
604 | break; |
605 | } |
606 | while (tlen>0) { |
607 | TCHECK2(p[0], 4)if (!(snapend - (4) <= snapend && (const u_char *) &(p[0]) <= snapend - (4))) goto trunc; |
608 | printf(" %s%s", |
609 | getname(p), |
610 | (tlen>4) ? ", " : ""); |
611 | tlen -=4; |
612 | p +=4; |
613 | } |
614 | break; |
615 | case BGPTYPE_MP_REACH_NLRI14: |
616 | TCHECK2(p[0], BGP_MP_NLRI_MINSIZE)if (!(snapend - (3) <= snapend && (const u_char *) &(p[0]) <= snapend - (3))) goto trunc; |
617 | af = EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1)); |
618 | safi = p[2]; |
619 | if (safi >= 128) |
620 | printf(" %s vendor specific %u,", af_name(af)(((af) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof( afnumber)/sizeof(afnumber[0]), (af))), safi); |
621 | else { |
622 | printf(" %s %s,", af_name(af)(((af) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof( afnumber)/sizeof(afnumber[0]), (af))), |
623 | bgp_attr_nlri_safi(safi)num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (safi))); |
624 | } |
625 | p += 3; |
626 | |
627 | if (af != AFNUM_INET1 && af != AFNUM_INET62) |
628 | break; |
629 | |
630 | TCHECK(p[0])if (!(snapend - (sizeof(p[0])) <= snapend && (const u_char *)&(p[0]) <= snapend - (sizeof(p[0])))) goto trunc; |
631 | tlen = p[0]; |
632 | if (tlen) { |
633 | printf(" nexthop"); |
634 | i = 0; |
635 | while (i < tlen) { |
636 | switch (af) { |
637 | case AFNUM_INET1: |
638 | TCHECK2(p[1+i], sizeof(struct in_addr))if (!(snapend - (sizeof(struct in_addr)) <= snapend && (const u_char *)&(p[1+i]) <= snapend - (sizeof(struct in_addr)))) goto trunc; |
639 | printf(" %s", getname(p + 1 + i)); |
640 | i += sizeof(struct in_addr); |
641 | break; |
642 | case AFNUM_INET62: |
643 | TCHECK2(p[1+i], sizeof(struct in6_addr))if (!(snapend - (sizeof(struct in6_addr)) <= snapend && (const u_char *)&(p[1+i]) <= snapend - (sizeof(struct in6_addr)))) goto trunc; |
644 | printf(" %s", getname6(p + 1 + i)); |
645 | i += sizeof(struct in6_addr); |
646 | break; |
647 | default: |
648 | printf(" (unknown af)"); |
649 | i = tlen; /*exit loop*/ |
650 | break; |
651 | } |
652 | } |
653 | printf(","); |
654 | } |
655 | p += 1 + tlen; |
656 | |
657 | TCHECK(p[0])if (!(snapend - (sizeof(p[0])) <= snapend && (const u_char *)&(p[0]) <= snapend - (sizeof(p[0])))) goto trunc; |
658 | snpa = p[0]; |
659 | p++; |
660 | if (snpa) { |
661 | printf(" %u snpa", snpa); |
662 | for (/*nothing*/; snpa > 0; snpa--) { |
663 | TCHECK(p[0])if (!(snapend - (sizeof(p[0])) <= snapend && (const u_char *)&(p[0]) <= snapend - (sizeof(p[0])))) goto trunc; |
664 | printf("(%d bytes)", p[0]); |
665 | p += p[0] + 1; |
666 | } |
667 | printf(","); |
668 | } |
669 | |
670 | printf(" NLRI"); |
671 | while (len - (p - dat) > 0) { |
672 | switch (af) { |
673 | case AFNUM_INET1: |
674 | advance = decode_prefix4(p, buf, sizeof(buf)); |
675 | break; |
676 | case AFNUM_INET62: |
677 | advance = decode_prefix6(p, buf, sizeof(buf)); |
678 | break; |
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_NLRI15: |
696 | TCHECK2(p[0], BGP_MP_NLRI_MINSIZE)if (!(snapend - (3) <= snapend && (const u_char *) &(p[0]) <= snapend - (3))) goto trunc; |
697 | af = EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1)); |
698 | safi = p[2]; |
699 | if (safi >= 128) |
700 | printf(" %s vendor specific %u,", af_name(af)(((af) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof( afnumber)/sizeof(afnumber[0]), (af))), safi); |
701 | else { |
702 | printf(" %s %s,", af_name(af)(((af) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof( afnumber)/sizeof(afnumber[0]), (af))), |
703 | bgp_attr_nlri_safi(safi)num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (safi))); |
704 | } |
705 | p += 3; |
706 | |
707 | printf(" Withdraw"); |
708 | while (len - (p - dat) > 0) { |
709 | switch (af) { |
710 | case AFNUM_INET1: |
711 | advance = decode_prefix4(p, buf, sizeof(buf)); |
712 | break; |
713 | case AFNUM_INET62: |
714 | advance = decode_prefix6(p, buf, sizeof(buf)); |
715 | break; |
716 | default: |
717 | printf(" (unknown af)"); |
718 | advance = 0; |
719 | p = dat + len; |
720 | break; |
721 | } |
722 | |
723 | if (advance <= 0) |
724 | break; |
725 | |
726 | printf(" %s", buf); |
727 | p += advance; |
728 | } |
729 | break; |
730 | default: |
731 | break; |
732 | } |
733 | return 1; |
734 | |
735 | trunc: |
736 | return 0; |
737 | } |
738 | |
739 | static void |
740 | bgp_open_capa_print(const u_char *opt, int length) |
741 | { |
742 | int i,cap_type,cap_len,tcap_len,cap_offset; |
743 | |
744 | i = 0; |
745 | while (i < length) { |
746 | TCHECK2(opt[i], 2)if (!(snapend - (2) <= snapend && (const u_char *) &(opt[i]) <= snapend - (2))) goto trunc; |
747 | |
748 | cap_type=opt[i]; |
749 | cap_len=opt[i+1]; |
750 | printf("%sCAP %s", i == 0 ? "(" : " ", /* ) */ |
751 | bgp_capcode(cap_type)num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode [0]), (cap_type))); |
752 | |
753 | /* can we print the capability? */ |
754 | TCHECK2(opt[i+2],cap_len)if (!(snapend - (cap_len) <= snapend && (const u_char *)&(opt[i+2]) <= snapend - (cap_len))) goto trunc; |
755 | i += 2; |
756 | |
757 | switch(cap_type) { |
758 | case BGP_CAPCODE_MP1: |
759 | if (cap_len != 4) { |
760 | printf(" BAD ENCODING"); |
761 | break; |
762 | } |
763 | printf(" [%s %s]", |
764 | af_name(EXTRACT_16BITS(opt+i))(((((u_int16_t)*((const u_int8_t *)(opt+i) + 0) << 8 | ( u_int16_t)*((const u_int8_t *)(opt+i) + 1))) == 65535) ? afnumber [0] : num_or_str(afnumber, sizeof(afnumber)/sizeof(afnumber[0 ]), (((u_int16_t)*((const u_int8_t *)(opt+i) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(opt+i) + 1))))), |
765 | bgp_attr_nlri_safi(opt[i+3])num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (opt[i+3]))); |
766 | break; |
767 | case BGP_CAPCODE_REFRESH2: |
768 | if (cap_len != 0) { |
769 | printf(" BAD ENCODING"); |
770 | break; |
771 | } |
772 | break; |
773 | case BGP_CAPCODE_RESTART64: |
774 | if (cap_len < 2 || (cap_len - 2) % 4) { |
775 | printf(" BAD ENCODING"); |
776 | break; |
777 | } |
778 | printf(" [%s], Time %us", |
779 | ((opt[i])&0x80) ? "R" : "none", |
780 | EXTRACT_16BITS(opt+i)((u_int16_t)*((const u_int8_t *)(opt+i) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(opt+i) + 1))&0xfff); |
781 | tcap_len=cap_len - 2; |
782 | cap_offset=2; |
783 | while(tcap_len>=4) { |
784 | printf(" (%s %s)%s", |
785 | af_name(EXTRACT_16BITS(opt+i+cap_offset))(((((u_int16_t)*((const u_int8_t *)(opt+i+cap_offset) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(opt+i+cap_offset) + 1))) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof(afnumber )/sizeof(afnumber[0]), (((u_int16_t)*((const u_int8_t *)(opt+ i+cap_offset) + 0) << 8 | (u_int16_t)*((const u_int8_t * )(opt+i+cap_offset) + 1))))), |
786 | bgp_attr_nlri_safi(opt[i+cap_offset+2])num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (opt[i+cap_offset+2])), |
787 | ((opt[i+cap_offset+3])&0x80) ? |
788 | " forwarding state preserved" : "" ); |
789 | tcap_len-=4; |
790 | cap_offset+=4; |
791 | } |
792 | break; |
793 | case BGP_CAPCODE_AS465: |
794 | if (cap_len != 4) { |
795 | printf(" BAD ENCODING"); |
796 | break; |
797 | } |
798 | printf(" #"); |
799 | if (EXTRACT_16BITS(opt+i)((u_int16_t)*((const u_int8_t *)(opt+i) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(opt+i) + 1))) |
800 | printf("%u.", |
801 | EXTRACT_16BITS(opt+i)((u_int16_t)*((const u_int8_t *)(opt+i) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(opt+i) + 1))); |
802 | printf("%u", |
803 | EXTRACT_16BITS(opt+i+2)((u_int16_t)*((const u_int8_t *)(opt+i+2) + 0) << 8 | ( u_int16_t)*((const u_int8_t *)(opt+i+2) + 1))); |
804 | break; |
805 | default: |
806 | printf(" len %d", cap_len); |
807 | break; |
808 | } |
809 | i += cap_len; |
810 | if (i + cap_len < length) |
811 | printf(","); |
812 | } |
813 | /* ( */ |
814 | printf(")"); |
815 | return; |
816 | trunc: |
817 | printf("[|BGP]"); |
818 | } |
819 | |
820 | static void |
821 | bgp_open_print(const u_char *dat, int length) |
822 | { |
823 | struct bgp_open bgpo; |
824 | struct bgp_opt bgpopt; |
825 | const u_char *opt; |
826 | int i; |
827 | |
828 | TCHECK2(dat[0], BGP_OPEN_SIZE)if (!(snapend - (29) <= snapend && (const u_char * )&(dat[0]) <= snapend - (29))) goto trunc; |
829 | memcpy(&bgpo, dat, BGP_OPEN_SIZE29); |
830 | |
831 | printf(": Version %d,", bgpo.bgpo_version); |
832 | printf(" AS #%u,", ntohs(bgpo.bgpo_myas)(__uint16_t)(__builtin_constant_p(bgpo.bgpo_myas) ? (__uint16_t )(((__uint16_t)(bgpo.bgpo_myas) & 0xffU) << 8 | ((__uint16_t )(bgpo.bgpo_myas) & 0xff00U) >> 8) : __swap16md(bgpo .bgpo_myas))); |
833 | printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)(__uint16_t)(__builtin_constant_p(bgpo.bgpo_holdtime) ? (__uint16_t )(((__uint16_t)(bgpo.bgpo_holdtime) & 0xffU) << 8 | ((__uint16_t)(bgpo.bgpo_holdtime) & 0xff00U) >> 8) : __swap16md(bgpo.bgpo_holdtime))); |
834 | printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id)); |
835 | printf(" Option length %u", bgpo.bgpo_optlen); |
836 | |
837 | /* sanity checking */ |
838 | if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE29) || (!bgpo.bgpo_optlen)) |
839 | return; |
840 | |
841 | /* ugly! */ |
842 | opt = &((const struct bgp_open *)dat)->bgpo_optlen; |
843 | opt++; |
844 | |
845 | i = 0; |
846 | while (i < bgpo.bgpo_optlen) { |
847 | TCHECK2(opt[i], BGP_OPT_SIZE)if (!(snapend - (2) <= snapend && (const u_char *) &(opt[i]) <= snapend - (2))) goto trunc; |
848 | memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE2); |
849 | if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { |
850 | printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); |
851 | break; |
852 | } |
853 | |
854 | if (i == 0) |
855 | printf(" ("); /* ) */ |
856 | else |
857 | printf(" "); |
858 | |
859 | switch(bgpopt.bgpopt_type) { |
860 | case BGP_OPT_CAP2: |
861 | bgp_open_capa_print(opt + i + BGP_OPT_SIZE2, |
862 | bgpopt.bgpopt_len); |
863 | break; |
864 | default: |
865 | printf(" (option %s, len=%u)", |
866 | bgp_opttype(bgpopt.bgpopt_type)num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type [0]), (bgpopt.bgpopt_type)), |
867 | bgpopt.bgpopt_len); |
868 | break; |
869 | } |
870 | |
871 | i += BGP_OPT_SIZE2 + bgpopt.bgpopt_len; |
872 | } |
873 | /* ( */ |
874 | printf(")"); |
875 | return; |
876 | trunc: |
877 | printf("[|BGP]"); |
878 | } |
879 | |
880 | static void |
881 | bgp_update_print(const u_char *dat, int length) |
882 | { |
883 | struct bgp bgp; |
884 | struct bgp_attr bgpa; |
885 | const u_char *p; |
886 | int len; |
887 | int i; |
888 | int newline; |
889 | |
890 | TCHECK2(dat[0], BGP_SIZE)if (!(snapend - (19) <= snapend && (const u_char * )&(dat[0]) <= snapend - (19))) goto trunc; |
891 | memcpy(&bgp, dat, BGP_SIZE19); |
892 | p = dat + BGP_SIZE19; /*XXX*/ |
893 | printf(":"); |
894 | |
895 | /* Unfeasible routes */ |
896 | len = EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1)); |
897 | if (len) { |
898 | /* |
899 | * Without keeping state from the original NLRI message, |
900 | * it's not possible to tell if this a v4 or v6 route, |
901 | * so do not try to decode it. |
902 | */ |
903 | printf(" (Withdrawn routes: %d bytes)", len); |
904 | } |
905 | p += 2 + len; |
906 | |
907 | TCHECK2(p[0], 2)if (!(snapend - (2) <= snapend && (const u_char *) &(p[0]) <= snapend - (2))) goto trunc; |
908 | len = EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1)); |
909 | |
910 | if (len == 0 && length == BGP_UPDATE_MINSIZE23) { |
911 | printf(" End-of-Rib Marker (empty NLRI)"); |
912 | return; |
913 | } |
914 | |
915 | if (len) { |
916 | /* do something more useful!*/ |
917 | i = 2; |
918 | printf(" (Path attributes:"); /* ) */ |
919 | newline = 0; |
920 | while (i < 2 + len) { |
921 | int alen, aoff; |
922 | |
923 | TCHECK2(p[i], sizeof(bgpa))if (!(snapend - (sizeof(bgpa)) <= snapend && (const u_char *)&(p[i]) <= snapend - (sizeof(bgpa)))) goto trunc; |
924 | memcpy(&bgpa, &p[i], sizeof(bgpa)); |
925 | alen = bgp_attr_len(&bgpa)(((&bgpa)->bgpa_flags & 0x10) ? (__uint16_t)(__builtin_constant_p ((&bgpa)->bgpa_len.elen) ? (__uint16_t)(((__uint16_t)( (&bgpa)->bgpa_len.elen) & 0xffU) << 8 | ((__uint16_t )((&bgpa)->bgpa_len.elen) & 0xff00U) >> 8) : __swap16md((&bgpa)->bgpa_len.elen)) : (&bgpa)-> bgpa_len.len); |
926 | aoff = bgp_attr_off(&bgpa)(((&bgpa)->bgpa_flags & 0x10) ? 4 : 3); |
927 | |
928 | if (vflag && newline) |
929 | printf("\n\t\t"); |
930 | else |
931 | printf(" "); |
932 | printf("("); /* ) */ |
933 | printf("%s", bgp_attr_type(bgpa.bgpa_type)num_or_str(bgpattr_type, sizeof(bgpattr_type)/sizeof(bgpattr_type [0]), (bgpa.bgpa_type))); |
934 | if (bgpa.bgpa_flags) { |
935 | printf("[%s%s%s%s", |
936 | bgpa.bgpa_flags & 0x80 ? "O" : "", |
937 | bgpa.bgpa_flags & 0x40 ? "T" : "", |
938 | bgpa.bgpa_flags & 0x20 ? "P" : "", |
939 | bgpa.bgpa_flags & 0x10 ? "E" : ""); |
940 | if (bgpa.bgpa_flags & 0xf) |
941 | printf("+%x", bgpa.bgpa_flags & 0xf); |
942 | printf("]"); |
943 | } |
944 | |
945 | if (!bgp_attr_print(&bgpa, &p[i + aoff], alen)) |
946 | goto trunc; |
947 | newline = 1; |
948 | |
949 | /* ( */ |
950 | printf(")"); |
951 | |
952 | i += aoff + alen; |
953 | } |
954 | |
955 | /* ( */ |
956 | printf(")"); |
957 | } |
958 | p += 2 + len; |
959 | |
960 | if (len && dat + length > p) |
961 | printf("\n\t\t"); |
962 | if (dat + length > p) { |
963 | printf("(NLRI:"); /* ) */ |
964 | while (dat + length > p) { |
965 | char buf[HOST_NAME_MAX255+1 + 100]; |
966 | i = decode_prefix4(p, buf, sizeof(buf)); |
967 | if (i == -1) { |
968 | printf(" (illegal prefix length)"); |
969 | break; |
970 | } else if (i == -2) |
971 | goto trunc; |
972 | printf(" %s", buf); |
973 | p += i; |
974 | } |
975 | |
976 | /* ( */ |
977 | printf(")"); |
978 | } |
979 | return; |
980 | trunc: |
981 | printf("[|BGP]"); |
982 | } |
983 | |
984 | static void |
985 | bgp_notification_print(const u_char *dat, int length) |
986 | { |
987 | struct bgp_notification bgpn; |
988 | u_int16_t af; |
989 | u_int8_t safi; |
990 | const u_char *p; |
991 | size_t shutdown_comm_length; |
992 | char shutstring[BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN255 + 1]; |
993 | |
994 | TCHECK2(dat[0], BGP_NOTIFICATION_SIZE)if (!(snapend - (21) <= snapend && (const u_char * )&(dat[0]) <= snapend - (21))) goto trunc; |
995 | memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE21); |
996 | |
997 | /* sanity checking */ |
998 | if (length < BGP_NOTIFICATION_SIZE21) |
999 | return; |
1000 | |
1001 | printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)num_or_str(bgpnotify_major, sizeof(bgpnotify_major)/sizeof(bgpnotify_major [0]), (bgpn.bgpn_major))); |
1002 | printf(" subcode %s", |
1003 | bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); |
1004 | |
1005 | if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE6) { |
1006 | /* |
1007 | * RFC 4486: optional maxprefix subtype of 7 bytes |
1008 | * may contain AFI, SAFI and MAXPREFIXES |
1009 | */ |
1010 | if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX1 && |
1011 | length >= BGP_NOTIFICATION_SIZE21 + 7) { |
1012 | |
1013 | p = dat + BGP_NOTIFICATION_SIZE21; |
1014 | TCHECK2(*p, 7)if (!(snapend - (7) <= snapend && (const u_char *) &(*p) <= snapend - (7))) goto trunc; |
1015 | |
1016 | af = EXTRACT_16BITS(p)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(p) + 1)); |
1017 | safi = p[2]; |
1018 | printf(" %s %s,", af_name(af)(((af) == 65535) ? afnumber[0] : num_or_str(afnumber, sizeof( afnumber)/sizeof(afnumber[0]), (af))), |
1019 | bgp_attr_nlri_safi(safi)num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (safi))); |
1020 | |
1021 | printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3)((u_int32_t)*((const u_int8_t *)(p+3) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(p+3) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(p+3) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(p+3) + 3))); |
1022 | } |
1023 | |
1024 | /* |
1025 | * RFC 8203 describes a method to send a message intended |
1026 | * for human consumption regarding the Administrative |
1027 | * Shutdown or Reset event. This is called the "Shutdown |
1028 | * Communication". The communication is UTF-8 encoded |
1029 | * and may be no longer than 128 bytes. |
1030 | */ |
1031 | if ((bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT2 || |
1032 | bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET4) && |
1033 | (length >= BGP_NOTIFICATION_SIZE21 + 1)) { |
1034 | p = dat + BGP_NOTIFICATION_SIZE21; |
1035 | TCHECK2(*p, 1)if (!(snapend - (1) <= snapend && (const u_char *) &(*p) <= snapend - (1))) goto trunc; |
1036 | shutdown_comm_length = *p; |
1037 | |
1038 | /* sanity checking */ |
1039 | if (shutdown_comm_length == 0) |
1040 | return; |
1041 | if (shutdown_comm_length > |
1042 | BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN255) |
1043 | goto trunc; |
1044 | if (length < (shutdown_comm_length + 1 + |
1045 | BGP_NOTIFICATION_SIZE21)) |
1046 | goto trunc; |
1047 | TCHECK2(*(p+1), shutdown_comm_length)if (!(snapend - (shutdown_comm_length) <= snapend && (const u_char *)&(*(p+1)) <= snapend - (shutdown_comm_length ))) goto trunc; |
1048 | |
1049 | /* a proper shutdown communication */ |
1050 | printf(", Shutdown Communication [len %zu]: \"", |
1051 | shutdown_comm_length); |
1052 | memset(shutstring, 0, sizeof(shutstring)); |
1053 | memcpy(shutstring, p+1, shutdown_comm_length); |
1054 | safeputs(shutstring); |
1055 | printf("\""); |
1056 | } |
1057 | } |
1058 | |
1059 | return; |
1060 | |
1061 | trunc: |
1062 | printf("[|BGP]"); |
1063 | } |
1064 | |
1065 | static void |
1066 | bgp_route_refresh_print(const u_char *dat, int length) |
1067 | { |
1068 | const struct bgp_route_refresh *bgp_route_refresh_header; |
1069 | |
1070 | TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE)if (!(snapend - (23) <= snapend && (const u_char * )&(dat[0]) <= snapend - (23))) goto trunc; |
1071 | |
1072 | /* sanity checking */ |
1073 | if (length<BGP_ROUTE_REFRESH_SIZE23) |
1074 | return; |
1075 | |
1076 | bgp_route_refresh_header = (const struct bgp_route_refresh *)dat; |
1077 | |
1078 | printf(" %s (%s %s)", |
1079 | refresh_subtype(bgp_route_refresh_header->subtype)num_or_str(refreshtype, sizeof(refreshtype)/sizeof(refreshtype [0]), (bgp_route_refresh_header->subtype)), |
1080 | af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi))(((((u_int16_t)*((const u_int8_t *)(&bgp_route_refresh_header ->afi) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(& bgp_route_refresh_header->afi) + 1))) == 65535) ? afnumber [0] : num_or_str(afnumber, sizeof(afnumber)/sizeof(afnumber[0 ]), (((u_int16_t)*((const u_int8_t *)(&bgp_route_refresh_header ->afi) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(& bgp_route_refresh_header->afi) + 1))))), |
1081 | bgp_attr_nlri_safi(bgp_route_refresh_header->safi)num_or_str(bgpattr_nlri_safi, sizeof(bgpattr_nlri_safi)/sizeof (bgpattr_nlri_safi[0]), (bgp_route_refresh_header->safi))); |
1082 | |
1083 | return; |
1084 | trunc: |
1085 | printf("[|BGP]"); |
1086 | } |
1087 | |
1088 | static int |
1089 | bgp_header_print(const u_char *dat, int length) |
1090 | { |
1091 | struct bgp bgp; |
1092 | |
1093 | TCHECK2(dat[0], BGP_SIZE)if (!(snapend - (19) <= snapend && (const u_char * )&(dat[0]) <= snapend - (19))) goto trunc; |
1094 | memcpy(&bgp, dat, BGP_SIZE19); |
1095 | printf("(%s", bgp_type(bgp.bgp_type)num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (bgp. bgp_type))); /* ) */ |
1096 | |
1097 | switch (bgp.bgp_type) { |
1098 | case BGP_OPEN1: |
1099 | bgp_open_print(dat, length); |
1100 | break; |
1101 | case BGP_UPDATE2: |
1102 | bgp_update_print(dat, length); |
1103 | break; |
1104 | case BGP_NOTIFICATION3: |
1105 | bgp_notification_print(dat, length); |
1106 | break; |
1107 | case BGP_KEEPALIVE4: |
1108 | break; |
1109 | case BGP_ROUTE_REFRESH5: |
1110 | bgp_route_refresh_print(dat, length); |
1111 | default: |
1112 | TCHECK2(*dat, length)if (!(snapend - (length) <= snapend && (const u_char *)&(*dat) <= snapend - (length))) goto trunc; |
1113 | break; |
1114 | } |
1115 | |
1116 | /* ( */ |
1117 | printf(")"); |
1118 | return 1; |
1119 | trunc: |
1120 | printf("[|BGP]"); |
1121 | return 0; |
1122 | } |
1123 | |
1124 | void |
1125 | bgp_print(const u_char *dat, int length) |
1126 | { |
1127 | const u_char *p; |
1128 | const u_char *ep; |
1129 | const u_char *start; |
1130 | const u_char marker[] = { |
1131 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
1132 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
1133 | }; |
1134 | struct bgp bgp; |
1135 | u_int16_t hlen; |
1136 | int newline; |
1137 | |
1138 | ep = dat + length; |
1139 | if (snapend < dat + length) |
1140 | ep = snapend; |
1141 | |
1142 | printf(": BGP"); |
1143 | |
1144 | p = dat; |
1145 | newline = 0; |
1146 | start = p; |
1147 | while (p < ep) { |
1148 | if (!TTEST2(p[0], 1)(snapend - (1) <= snapend && (const u_char *)& (p[0]) <= snapend - (1))) |
1149 | break; |
1150 | if (p[0] != 0xff) { |
1151 | p++; |
1152 | continue; |
1153 | } |
1154 | |
1155 | if (!TTEST2(p[0], sizeof(marker))(snapend - (sizeof(marker)) <= snapend && (const u_char *)&(p[0]) <= snapend - (sizeof(marker)))) |
1156 | break; |
1157 | if (memcmp(p, marker, sizeof(marker)) != 0) { |
1158 | p++; |
1159 | continue; |
1160 | } |
1161 | |
1162 | /* found BGP header */ |
1163 | TCHECK2(p[0], BGP_SIZE)if (!(snapend - (19) <= snapend && (const u_char * )&(p[0]) <= snapend - (19))) goto trunc; /*XXX*/ |
1164 | memcpy(&bgp, p, BGP_SIZE19); |
1165 | |
1166 | if (start != p) |
1167 | printf(" [|BGP]"); |
1168 | |
1169 | hlen = ntohs(bgp.bgp_len)(__uint16_t)(__builtin_constant_p(bgp.bgp_len) ? (__uint16_t) (((__uint16_t)(bgp.bgp_len) & 0xffU) << 8 | ((__uint16_t )(bgp.bgp_len) & 0xff00U) >> 8) : __swap16md(bgp.bgp_len )); |
1170 | if (vflag && newline) |
1171 | printf("\n\t"); |
1172 | else |
1173 | printf(" "); |
1174 | if (hlen < BGP_SIZE19) { |
1175 | printf("\n[|BGP Bogus header length %u < %u]", |
1176 | hlen, BGP_SIZE19); |
1177 | break; |
1178 | } |
1179 | if (TTEST2(p[0], hlen)(snapend - (hlen) <= snapend && (const u_char *)& (p[0]) <= snapend - (hlen))) { |
1180 | if (!bgp_header_print(p, hlen)) |
1181 | return; |
1182 | newline = 1; |
1183 | p += hlen; |
1184 | start = p; |
1185 | } else { |
1186 | printf("[|BGP %s]", bgp_type(bgp.bgp_type)num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (bgp. bgp_type))); |
1187 | break; |
1188 | } |
1189 | } |
1190 | |
1191 | return; |
1192 | |
1193 | trunc: |
1194 | printf(" [|BGP]"); |
1195 | } |