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