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