]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/bgp/attrs.c
Merge branch 'master' into int-new
[thirdparty/bird.git] / proto / bgp / attrs.c
1 /*
2 * BIRD -- BGP Attributes
3 *
4 * (c) 2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #undef LOCAL_DEBUG
10
11 #include <stdlib.h>
12
13 #include "nest/bird.h"
14 #include "nest/iface.h"
15 #include "nest/protocol.h"
16 #include "nest/route.h"
17 #include "nest/attrs.h"
18 #include "conf/conf.h"
19 #include "lib/resource.h"
20 #include "lib/string.h"
21 #include "lib/unaligned.h"
22
23 #include "bgp.h"
24
25 /*
26 * UPDATE message error handling
27 *
28 * All checks from RFC 4271 6.3 are done as specified with these exceptions:
29 * - The semantic check of an IP address from NEXT_HOP attribute is missing.
30 * - Checks of some optional attribute values are missing.
31 * - Syntactic and semantic checks of NLRIs (done in DECODE_PREFIX())
32 * are probably inadequate.
33 *
34 * Loop detection based on AS_PATH causes updates to be withdrawn. RFC
35 * 4271 does not explicitly specifiy the behavior in that case.
36 *
37 * Loop detection related to route reflection (based on ORIGINATOR_ID
38 * and CLUSTER_LIST) causes updates to be withdrawn. RFC 4456 8
39 * specifies that such updates should be ignored, but that is generally
40 * a bad idea.
41 *
42 * Error checking of optional transitive attributes is done according to
43 * draft-ietf-idr-optional-transitive-03, but errors are handled always
44 * as withdraws.
45 *
46 * Unexpected AS_CONFED_* segments in AS_PATH are logged and removed,
47 * but unknown segments cause a session drop with Malformed AS_PATH
48 * error (see validate_path()). The behavior in such case is not
49 * explicitly specified by RFC 4271. RFC 5065 specifies that
50 * inconsistent AS_CONFED_* segments should cause a session drop, but
51 * implementations that pass invalid AS_CONFED_* segments are
52 * widespread.
53 *
54 * Error handling of AS4_* attributes is done as specified by
55 * draft-ietf-idr-rfc4893bis-03. There are several possible
56 * inconsistencies between AGGREGATOR and AS4_AGGREGATOR that are not
57 * handled by that draft, these are logged and ignored (see
58 * bgp_reconstruct_4b_attrs()).
59 */
60
61
62 static byte bgp_mandatory_attrs[] = { BA_ORIGIN, BA_AS_PATH
63 #ifndef IPV6
64 ,BA_NEXT_HOP
65 #endif
66 };
67
68 struct attr_desc {
69 char *name;
70 int expected_length;
71 int expected_flags;
72 int type;
73 int allow_in_ebgp;
74 int (*validate)(struct bgp_proto *p, byte *attr, int len);
75 void (*format)(eattr *ea, byte *buf, int buflen);
76 };
77
78 #define IGNORE -1
79 #define WITHDRAW -2
80
81 static int
82 bgp_check_origin(struct bgp_proto *p UNUSED, byte *a, int len UNUSED)
83 {
84 if (*a > 2)
85 return 6;
86 return 0;
87 }
88
89 static void
90 bgp_format_origin(eattr *a, byte *buf, int buflen UNUSED)
91 {
92 static char *bgp_origin_names[] = { "IGP", "EGP", "Incomplete" };
93
94 bsprintf(buf, bgp_origin_names[a->u.data]);
95 }
96
97 static int
98 path_segment_contains(byte *p, int bs, u32 asn)
99 {
100 int i;
101 int len = p[1];
102 p += 2;
103
104 for(i=0; i<len; i++)
105 {
106 u32 asn2 = (bs == 4) ? get_u32(p) : get_u16(p);
107 if (asn2 == asn)
108 return 1;
109 p += bs;
110 }
111
112 return 0;
113 }
114
115 /* Validates path attribute, removes AS_CONFED_* segments, and also returns path length */
116 static int
117 validate_path(struct bgp_proto *p, int as_path, int bs, byte *idata, uint *ilength)
118 {
119 int res = 0;
120 u8 *a, *dst;
121 int len, plen;
122
123 dst = a = idata;
124 len = *ilength;
125
126 while (len)
127 {
128 if (len < 2)
129 return -1;
130
131 plen = 2 + bs * a[1];
132 if (len < plen)
133 return -1;
134
135 if (a[1] == 0)
136 {
137 log(L_WARN "%s: %s_PATH attribute contains empty segment, skipping it",
138 p->p.name, as_path ? "AS" : "AS4");
139 goto skip;
140 }
141
142 switch (a[0])
143 {
144 case AS_PATH_SET:
145 res++;
146 break;
147
148 case AS_PATH_SEQUENCE:
149 res += a[1];
150 break;
151
152 case AS_PATH_CONFED_SEQUENCE:
153 case AS_PATH_CONFED_SET:
154 if (as_path && path_segment_contains(a, bs, p->remote_as))
155 {
156 log(L_WARN "%s: AS_CONFED_* segment with peer ASN found, misconfigured confederation?", p->p.name);
157 return -1;
158 }
159
160 log(L_WARN "%s: %s_PATH attribute contains AS_CONFED_* segment, skipping segment",
161 p->p.name, as_path ? "AS" : "AS4");
162 goto skip;
163
164 default:
165 return -1;
166 }
167
168 if (dst != a)
169 memmove(dst, a, plen);
170 dst += plen;
171
172 skip:
173 len -= plen;
174 a += plen;
175 }
176
177 *ilength = dst - idata;
178 return res;
179 }
180
181 static inline int
182 validate_as_path(struct bgp_proto *p, byte *a, int *len)
183 {
184 return validate_path(p, 1, p->as4_session ? 4 : 2, a, len);
185 }
186
187 static inline int
188 validate_as4_path(struct bgp_proto *p, struct adata *path)
189 {
190 return validate_path(p, 0, 4, path->data, &path->length);
191 }
192
193 static int
194 bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a UNUSED6, int len UNUSED6)
195 {
196 #ifdef IPV6
197 return IGNORE;
198 #else
199 ip_addr addr;
200
201 memcpy(&addr, a, len);
202 ipa_ntoh(addr);
203 if (ipa_classify(addr) & IADDR_HOST)
204 return 0;
205 else
206 return 8;
207 #endif
208 }
209
210 static void
211 bgp_format_next_hop(eattr *a, byte *buf, int buflen UNUSED)
212 {
213 ip_addr *ipp = (ip_addr *) a->u.ptr->data;
214 #ifdef IPV6
215 /* in IPv6, we might have two addresses in NEXT HOP */
216 if ((a->u.ptr->length == NEXT_HOP_LENGTH) && ipa_nonzero(ipp[1]))
217 {
218 bsprintf(buf, "%I %I", ipp[0], ipp[1]);
219 return;
220 }
221 #endif
222
223 bsprintf(buf, "%I", ipp[0]);
224 }
225
226 static int
227 bgp_check_aggregator(struct bgp_proto *p, byte *a UNUSED, int len)
228 {
229 int exp_len = p->as4_session ? 8 : 6;
230
231 return (len == exp_len) ? 0 : WITHDRAW;
232 }
233
234 static void
235 bgp_format_aggregator(eattr *a, byte *buf, int buflen UNUSED)
236 {
237 struct adata *ad = a->u.ptr;
238 byte *data = ad->data;
239 u32 as;
240
241 as = get_u32(data);
242 data += 4;
243
244 bsprintf(buf, "%d.%d.%d.%d AS%u", data[0], data[1], data[2], data[3], as);
245 }
246
247 static int
248 bgp_check_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
249 {
250 return ((len % 4) == 0) ? 0 : WITHDRAW;
251 }
252
253 static int
254 bgp_check_cluster_list(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
255 {
256 return ((len % 4) == 0) ? 0 : 5;
257 }
258
259 static void
260 bgp_format_cluster_list(eattr *a, byte *buf, int buflen)
261 {
262 /* Truncates cluster lists larger than buflen, probably not a problem */
263 int_set_format(a->u.ptr, 0, -1, buf, buflen);
264 }
265
266 static int
267 bgp_check_reach_nlri(struct bgp_proto *p UNUSED, byte *a UNUSED, int len UNUSED)
268 {
269 #ifdef IPV6
270 p->mp_reach_start = a;
271 p->mp_reach_len = len;
272 #endif
273 return IGNORE;
274 }
275
276 static int
277 bgp_check_unreach_nlri(struct bgp_proto *p UNUSED, byte *a UNUSED, int len UNUSED)
278 {
279 #ifdef IPV6
280 p->mp_unreach_start = a;
281 p->mp_unreach_len = len;
282 #endif
283 return IGNORE;
284 }
285
286 static int
287 bgp_check_ext_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
288 {
289 return ((len % 8) == 0) ? 0 : WITHDRAW;
290 }
291
292 static int
293 bgp_check_large_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
294 {
295 return ((len % 12) == 0) ? 0 : WITHDRAW;
296 }
297
298
299 static struct attr_desc bgp_attr_table[] = {
300 { NULL, -1, 0, 0, 0, /* Undefined */
301 NULL, NULL },
302 { "origin", 1, BAF_TRANSITIVE, EAF_TYPE_INT, 1, /* BA_ORIGIN */
303 bgp_check_origin, bgp_format_origin },
304 { "as_path", -1, BAF_TRANSITIVE, EAF_TYPE_AS_PATH, 1, /* BA_AS_PATH */
305 NULL, NULL }, /* is checked by validate_as_path() as a special case */
306 { "next_hop", 4, BAF_TRANSITIVE, EAF_TYPE_IP_ADDRESS, 1, /* BA_NEXT_HOP */
307 bgp_check_next_hop, bgp_format_next_hop },
308 { "med", 4, BAF_OPTIONAL, EAF_TYPE_INT, 1, /* BA_MULTI_EXIT_DISC */
309 NULL, NULL },
310 { "local_pref", 4, BAF_TRANSITIVE, EAF_TYPE_INT, 0, /* BA_LOCAL_PREF */
311 NULL, NULL },
312 { "atomic_aggr", 0, BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_ATOMIC_AGGR */
313 NULL, NULL },
314 { "aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AGGREGATOR */
315 bgp_check_aggregator, bgp_format_aggregator },
316 { "community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_INT_SET, 1, /* BA_COMMUNITY */
317 bgp_check_community, NULL },
318 { "originator_id", 4, BAF_OPTIONAL, EAF_TYPE_ROUTER_ID, 0, /* BA_ORIGINATOR_ID */
319 NULL, NULL },
320 { "cluster_list", -1, BAF_OPTIONAL, EAF_TYPE_INT_SET, 0, /* BA_CLUSTER_LIST */
321 bgp_check_cluster_list, bgp_format_cluster_list },
322 { .name = NULL }, /* BA_DPA */
323 { .name = NULL }, /* BA_ADVERTISER */
324 { .name = NULL }, /* BA_RCID_PATH */
325 { "mp_reach_nlri", -1, BAF_OPTIONAL, EAF_TYPE_OPAQUE, 1, /* BA_MP_REACH_NLRI */
326 bgp_check_reach_nlri, NULL },
327 { "mp_unreach_nlri", -1, BAF_OPTIONAL, EAF_TYPE_OPAQUE, 1, /* BA_MP_UNREACH_NLRI */
328 bgp_check_unreach_nlri, NULL },
329 { "ext_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_EC_SET, 1, /* BA_EXT_COMMUNITY */
330 bgp_check_ext_community, NULL },
331 { "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
332 NULL, NULL },
333 { "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */
334 NULL, NULL },
335 [BA_LARGE_COMMUNITY] =
336 { "large_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_LC_SET, 1,
337 bgp_check_large_community, NULL }
338 };
339
340 /* BA_AS4_PATH is type EAF_TYPE_OPAQUE and not type EAF_TYPE_AS_PATH.
341 * It does not matter as this attribute does not appear on routes in the routing table.
342 */
343
344 #define ATTR_KNOWN(code) ((code) < ARRAY_SIZE(bgp_attr_table) && bgp_attr_table[code].name)
345
346 static inline struct adata *
347 bgp_alloc_adata(struct linpool *pool, unsigned len)
348 {
349 struct adata *ad = lp_alloc(pool, sizeof(struct adata) + len);
350 ad->length = len;
351 return ad;
352 }
353
354 static void
355 bgp_set_attr(eattr *e, unsigned attr, uintptr_t val)
356 {
357 ASSERT(ATTR_KNOWN(attr));
358 e->id = EA_CODE(EAP_BGP, attr);
359 e->type = bgp_attr_table[attr].type;
360 e->flags = bgp_attr_table[attr].expected_flags;
361 if (e->type & EAF_EMBEDDED)
362 e->u.data = val;
363 else
364 e->u.ptr = (struct adata *) val;
365 }
366
367 static byte *
368 bgp_set_attr_wa(eattr *e, struct linpool *pool, unsigned attr, unsigned len)
369 {
370 struct adata *ad = bgp_alloc_adata(pool, len);
371 bgp_set_attr(e, attr, (uintptr_t) ad);
372 return ad->data;
373 }
374
375 void
376 bgp_attach_attr(ea_list **to, struct linpool *pool, unsigned attr, uintptr_t val)
377 {
378 ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
379 a->next = *to;
380 *to = a;
381 a->flags = EALF_SORTED;
382 a->count = 1;
383 bgp_set_attr(a->attrs, attr, val);
384 }
385
386 byte *
387 bgp_attach_attr_wa(ea_list **to, struct linpool *pool, unsigned attr, unsigned len)
388 {
389 struct adata *ad = bgp_alloc_adata(pool, len);
390 bgp_attach_attr(to, pool, attr, (uintptr_t) ad);
391 return ad->data;
392 }
393
394 static int
395 bgp_encode_attr_hdr(byte *dst, uint flags, unsigned code, int len)
396 {
397 int wlen;
398
399 DBG("\tAttribute %02x (%d bytes, flags %02x)\n", code, len, flags);
400
401 if (len < 256)
402 {
403 *dst++ = flags;
404 *dst++ = code;
405 *dst++ = len;
406 wlen = 3;
407 }
408 else
409 {
410 *dst++ = flags | BAF_EXT_LEN;
411 *dst++ = code;
412 put_u16(dst, len);
413 wlen = 4;
414 }
415
416 return wlen;
417 }
418
419 static void
420 aggregator_convert_to_old(struct adata *aggr, byte *dst, int *new_used)
421 {
422 byte *src = aggr->data;
423 *new_used = 0;
424
425 u32 as = get_u32(src);
426 if (as > 0xFFFF)
427 {
428 as = AS_TRANS;
429 *new_used = 1;
430 }
431 put_u16(dst, as);
432
433 /* Copy IPv4 address */
434 memcpy(dst + 2, src + 4, 4);
435 }
436
437 static void
438 aggregator_convert_to_new(struct adata *aggr, byte *dst)
439 {
440 byte *src = aggr->data;
441
442 u32 as = get_u16(src);
443 put_u32(dst, as);
444
445 /* Copy IPv4 address */
446 memcpy(dst + 4, src + 2, 4);
447 }
448
449 static int
450 bgp_get_attr_len(eattr *a)
451 {
452 int len;
453 if (ATTR_KNOWN(EA_ID(a->id)))
454 {
455 int code = EA_ID(a->id);
456 struct attr_desc *desc = &bgp_attr_table[code];
457 len = desc->expected_length;
458 if (len < 0)
459 {
460 ASSERT(!(a->type & EAF_EMBEDDED));
461 len = a->u.ptr->length;
462 }
463 }
464 else
465 {
466 ASSERT((a->type & EAF_TYPE_MASK) == EAF_TYPE_OPAQUE);
467 len = a->u.ptr->length;
468 }
469
470 return len;
471 }
472
473 #define ADVANCE(w, r, l) do { r -= l; w += l; } while (0)
474
475 /**
476 * bgp_encode_attrs - encode BGP attributes
477 * @p: BGP instance
478 * @w: buffer
479 * @attrs: a list of extended attributes
480 * @remains: remaining space in the buffer
481 *
482 * The bgp_encode_attrs() function takes a list of extended attributes
483 * and converts it to its BGP representation (a part of an Update message).
484 *
485 * Result: Length of the attribute block generated or -1 if not enough space.
486 */
487 uint
488 bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
489 {
490 uint i, code, type, flags;
491 byte *start = w;
492 int len, rv;
493
494 for(i=0; i<attrs->count; i++)
495 {
496 eattr *a = &attrs->attrs[i];
497 ASSERT(EA_PROTO(a->id) == EAP_BGP);
498 code = EA_ID(a->id);
499
500 #ifdef IPV6
501 /* When talking multiprotocol BGP, the NEXT_HOP attributes are used only temporarily. */
502 if (code == BA_NEXT_HOP)
503 continue;
504 #endif
505
506 /* When AS4-aware BGP speaker is talking to non-AS4-aware BGP speaker,
507 * we have to convert our 4B AS_PATH to 2B AS_PATH and send our AS_PATH
508 * as optional AS4_PATH attribute.
509 */
510 if ((code == BA_AS_PATH) && (! p->as4_session))
511 {
512 len = a->u.ptr->length;
513
514 if (remains < (len + 4))
515 goto err_no_buffer;
516
517 /* Using temporary buffer because don't know a length of created attr
518 * and therefore a length of a header. Perhaps i should better always
519 * use BAF_EXT_LEN. */
520
521 byte buf[len];
522 int new_used;
523 int nl = as_path_convert_to_old(a->u.ptr, buf, &new_used);
524
525 DBG("BGP: Encoding old AS_PATH\n");
526 rv = bgp_encode_attr_hdr(w, BAF_TRANSITIVE, BA_AS_PATH, nl);
527 ADVANCE(w, remains, rv);
528 memcpy(w, buf, nl);
529 ADVANCE(w, remains, nl);
530
531 if (! new_used)
532 continue;
533
534 if (remains < (len + 4))
535 goto err_no_buffer;
536
537 /* We should discard AS_CONFED_SEQUENCE or AS_CONFED_SET path segments
538 * here but we don't support confederations and such paths we already
539 * discarded in bgp_check_as_path().
540 */
541
542 DBG("BGP: Encoding AS4_PATH\n");
543 rv = bgp_encode_attr_hdr(w, BAF_OPTIONAL | BAF_TRANSITIVE, BA_AS4_PATH, len);
544 ADVANCE(w, remains, rv);
545 memcpy(w, a->u.ptr->data, len);
546 ADVANCE(w, remains, len);
547
548 continue;
549 }
550
551 /* The same issue with AGGREGATOR attribute */
552 if ((code == BA_AGGREGATOR) && (! p->as4_session))
553 {
554 int new_used;
555
556 len = 6;
557 if (remains < (len + 3))
558 goto err_no_buffer;
559
560 rv = bgp_encode_attr_hdr(w, BAF_OPTIONAL | BAF_TRANSITIVE, BA_AGGREGATOR, len);
561 ADVANCE(w, remains, rv);
562 aggregator_convert_to_old(a->u.ptr, w, &new_used);
563 ADVANCE(w, remains, len);
564
565 if (! new_used)
566 continue;
567
568 len = 8;
569 if (remains < (len + 3))
570 goto err_no_buffer;
571
572 rv = bgp_encode_attr_hdr(w, BAF_OPTIONAL | BAF_TRANSITIVE, BA_AS4_AGGREGATOR, len);
573 ADVANCE(w, remains, rv);
574 memcpy(w, a->u.ptr->data, len);
575 ADVANCE(w, remains, len);
576
577 continue;
578 }
579
580 /* Standard path continues here ... */
581
582 type = a->type & EAF_TYPE_MASK;
583 flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
584 len = bgp_get_attr_len(a);
585
586 /* Skip empty sets */
587 if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET) || (type == EAF_TYPE_LC_SET)) && (len == 0))
588 continue;
589
590 if (remains < len + 4)
591 goto err_no_buffer;
592
593 rv = bgp_encode_attr_hdr(w, flags, code, len);
594 ADVANCE(w, remains, rv);
595
596 switch (type)
597 {
598 case EAF_TYPE_INT:
599 case EAF_TYPE_ROUTER_ID:
600 if (len == 4)
601 put_u32(w, a->u.data);
602 else
603 *w = a->u.data;
604 break;
605 case EAF_TYPE_IP_ADDRESS:
606 {
607 ip_addr ip = *(ip_addr *)a->u.ptr->data;
608 ipa_hton(ip);
609 memcpy(w, &ip, len);
610 break;
611 }
612 case EAF_TYPE_INT_SET:
613 case EAF_TYPE_LC_SET:
614 case EAF_TYPE_EC_SET:
615 {
616 u32 *z = int_set_get_data(a->u.ptr);
617 int i;
618 for(i=0; i<len; i+=4)
619 put_u32(w+i, *z++);
620 break;
621 }
622 case EAF_TYPE_OPAQUE:
623 case EAF_TYPE_AS_PATH:
624 memcpy(w, a->u.ptr->data, len);
625 break;
626 default:
627 bug("bgp_encode_attrs: unknown attribute type %02x", a->type);
628 }
629 ADVANCE(w, remains, len);
630 }
631 return w - start;
632
633 err_no_buffer:
634 return -1;
635 }
636
637 /*
638 static void
639 bgp_init_prefix(struct fib_node *N)
640 {
641 struct bgp_prefix *p = (struct bgp_prefix *) N;
642 p->bucket_node.next = NULL;
643 }
644 */
645
646 static int
647 bgp_compare_u32(const u32 *x, const u32 *y)
648 {
649 return (*x < *y) ? -1 : (*x > *y) ? 1 : 0;
650 }
651
652 static inline void
653 bgp_normalize_int_set(u32 *dest, u32 *src, unsigned cnt)
654 {
655 memcpy(dest, src, sizeof(u32) * cnt);
656 qsort(dest, cnt, sizeof(u32), (int(*)(const void *, const void *)) bgp_compare_u32);
657 }
658
659 static int
660 bgp_compare_ec(const u32 *xp, const u32 *yp)
661 {
662 u64 x = ec_get(xp, 0);
663 u64 y = ec_get(yp, 0);
664 return (x < y) ? -1 : (x > y) ? 1 : 0;
665 }
666
667 static inline void
668 bgp_normalize_ec_set(struct adata *ad, u32 *src, int internal)
669 {
670 u32 *dst = int_set_get_data(ad);
671
672 /* Remove non-transitive communities (EC_TBIT active) on external sessions */
673 if (! internal)
674 {
675 int len = int_set_get_size(ad);
676 u32 *t = dst;
677 int i;
678
679 for (i=0; i < len; i += 2)
680 {
681 if (src[i] & EC_TBIT)
682 continue;
683
684 *t++ = src[i];
685 *t++ = src[i+1];
686 }
687
688 ad->length = (t - dst) * 4;
689 }
690 else
691 memcpy(dst, src, ad->length);
692
693 qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec);
694 }
695
696 static int
697 bgp_compare_lc(const u32 *x, const u32 *y)
698 {
699 if (x[0] != y[0])
700 return (x[0] > y[0]) ? 1 : -1;
701 if (x[1] != y[1])
702 return (x[1] > y[1]) ? 1 : -1;
703 if (x[2] != y[2])
704 return (x[2] > y[2]) ? 1 : -1;
705 return 0;
706 }
707
708 static inline void
709 bgp_normalize_lc_set(u32 *dest, u32 *src, unsigned cnt)
710 {
711 memcpy(dest, src, LCOMM_LENGTH * cnt);
712 qsort(dest, cnt, LCOMM_LENGTH, (int(*)(const void *, const void *)) bgp_compare_lc);
713 }
714
715 static void
716 bgp_rehash_buckets(struct bgp_proto *p)
717 {
718 struct bgp_bucket **old = p->bucket_hash;
719 struct bgp_bucket **new;
720 unsigned oldn = p->hash_size;
721 unsigned i, e, mask;
722 struct bgp_bucket *b;
723
724 p->hash_size = p->hash_limit;
725 DBG("BGP: Rehashing bucket table from %d to %d\n", oldn, p->hash_size);
726 p->hash_limit *= 4;
727 if (p->hash_limit >= 65536)
728 p->hash_limit = ~0;
729 new = p->bucket_hash = mb_allocz(p->p.pool, p->hash_size * sizeof(struct bgp_bucket *));
730 mask = p->hash_size - 1;
731 for (i=0; i<oldn; i++)
732 while (b = old[i])
733 {
734 old[i] = b->hash_next;
735 e = b->hash & mask;
736 b->hash_next = new[e];
737 if (b->hash_next)
738 b->hash_next->hash_prev = b;
739 b->hash_prev = NULL;
740 new[e] = b;
741 }
742 mb_free(old);
743 }
744
745 static struct bgp_bucket *
746 bgp_new_bucket(struct bgp_proto *p, ea_list *new, unsigned hash)
747 {
748 struct bgp_bucket *b;
749 unsigned ea_size = sizeof(ea_list) + new->count * sizeof(eattr);
750 unsigned ea_size_aligned = BIRD_ALIGN(ea_size, CPU_STRUCT_ALIGN);
751 unsigned size = sizeof(struct bgp_bucket) + ea_size_aligned;
752 unsigned i;
753 byte *dest;
754 unsigned index = hash & (p->hash_size - 1);
755
756 /* Gather total size of non-inline attributes */
757 for (i=0; i<new->count; i++)
758 {
759 eattr *a = &new->attrs[i];
760 if (!(a->type & EAF_EMBEDDED))
761 size += BIRD_ALIGN(sizeof(struct adata) + a->u.ptr->length, CPU_STRUCT_ALIGN);
762 }
763
764 /* Create the bucket and hash it */
765 b = mb_alloc(p->p.pool, size);
766 b->hash_next = p->bucket_hash[index];
767 if (b->hash_next)
768 b->hash_next->hash_prev = b;
769 p->bucket_hash[index] = b;
770 b->hash_prev = NULL;
771 b->hash = hash;
772 add_tail(&p->bucket_queue, &b->send_node);
773 init_list(&b->prefixes);
774 memcpy(b->eattrs, new, ea_size);
775 dest = ((byte *)b->eattrs) + ea_size_aligned;
776
777 /* Copy values of non-inline attributes */
778 for (i=0; i<new->count; i++)
779 {
780 eattr *a = &b->eattrs->attrs[i];
781 if (!(a->type & EAF_EMBEDDED))
782 {
783 struct adata *oa = a->u.ptr;
784 struct adata *na = (struct adata *) dest;
785 memcpy(na, oa, sizeof(struct adata) + oa->length);
786 a->u.ptr = na;
787 dest += BIRD_ALIGN(sizeof(struct adata) + na->length, CPU_STRUCT_ALIGN);
788 }
789 }
790
791 /* If needed, rehash */
792 p->hash_count++;
793 if (p->hash_count > p->hash_limit)
794 bgp_rehash_buckets(p);
795
796 return b;
797 }
798
799 static struct bgp_bucket *
800 bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
801 {
802 ea_list *new;
803 unsigned i, cnt, hash, code;
804 eattr *a, *d;
805 u32 seen = 0;
806 struct bgp_bucket *b;
807
808 /* Merge the attribute list */
809 new = alloca(ea_scan(attrs));
810 ea_merge(attrs, new);
811 ea_sort(new);
812
813 /* Normalize attributes */
814 d = new->attrs;
815 cnt = new->count;
816 new->count = 0;
817 for(i=0; i<cnt; i++)
818 {
819 a = &new->attrs[i];
820 if (EA_PROTO(a->id) != EAP_BGP)
821 continue;
822 code = EA_ID(a->id);
823 if (ATTR_KNOWN(code))
824 {
825 if (!bgp_attr_table[code].allow_in_ebgp && !p->is_internal)
826 continue;
827 /* The flags might have been zero if the attr was added by filters */
828 a->flags = (a->flags & BAF_PARTIAL) | bgp_attr_table[code].expected_flags;
829 if (code < 32)
830 seen |= 1 << code;
831 }
832 else
833 {
834 /* Don't re-export unknown non-transitive attributes */
835 if (!(a->flags & BAF_TRANSITIVE))
836 continue;
837 }
838 *d = *a;
839 if ((d->type & EAF_ORIGINATED) && !originate && (d->flags & BAF_TRANSITIVE) && (d->flags & BAF_OPTIONAL))
840 d->flags |= BAF_PARTIAL;
841 switch (d->type & EAF_TYPE_MASK)
842 {
843 case EAF_TYPE_INT_SET:
844 {
845 struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
846 z->length = d->u.ptr->length;
847 bgp_normalize_int_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / 4);
848 d->u.ptr = z;
849 break;
850 }
851 case EAF_TYPE_EC_SET:
852 {
853 struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
854 z->length = d->u.ptr->length;
855 bgp_normalize_ec_set(z, (u32 *) d->u.ptr->data, p->is_internal);
856 d->u.ptr = z;
857 break;
858 }
859 case EAF_TYPE_LC_SET:
860 {
861 struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
862 z->length = d->u.ptr->length;
863 bgp_normalize_lc_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / LCOMM_LENGTH);
864 d->u.ptr = z;
865 break;
866 }
867 default: ;
868 }
869 d++;
870 new->count++;
871 }
872
873 /* Hash */
874 hash = ea_hash(new);
875 for(b=p->bucket_hash[hash & (p->hash_size - 1)]; b; b=b->hash_next)
876 if (b->hash == hash && ea_same(b->eattrs, new))
877 {
878 DBG("Found bucket.\n");
879 return b;
880 }
881
882 /* Ensure that there are all mandatory attributes */
883 for(i=0; i<ARRAY_SIZE(bgp_mandatory_attrs); i++)
884 if (!(seen & (1 << bgp_mandatory_attrs[i])))
885 {
886 log(L_ERR "%s: Mandatory attribute %s missing in route %I/%d", p->p.name, bgp_attr_table[bgp_mandatory_attrs[i]].name, n->n.prefix, n->n.pxlen);
887 return NULL;
888 }
889
890 /* Check if next hop is valid */
891 a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP));
892 if (!a || ipa_equal(p->cf->remote_ip, *(ip_addr *)a->u.ptr->data))
893 {
894 log(L_ERR "%s: Invalid NEXT_HOP attribute in route %I/%d", p->p.name, n->n.prefix, n->n.pxlen);
895 return NULL;
896 }
897
898 /* Create new bucket */
899 DBG("Creating bucket.\n");
900 return bgp_new_bucket(p, new, hash);
901 }
902
903 void
904 bgp_free_bucket(struct bgp_proto *p, struct bgp_bucket *buck)
905 {
906 if (buck->hash_next)
907 buck->hash_next->hash_prev = buck->hash_prev;
908 if (buck->hash_prev)
909 buck->hash_prev->hash_next = buck->hash_next;
910 else
911 p->bucket_hash[buck->hash & (p->hash_size-1)] = buck->hash_next;
912 mb_free(buck);
913 }
914
915
916 /* Prefix hash table */
917
918 #define PXH_KEY(n1) n1->n.prefix, n1->n.pxlen, n1->path_id
919 #define PXH_NEXT(n) n->next
920 #define PXH_EQ(p1,l1,i1,p2,l2,i2) ipa_equal(p1, p2) && l1 == l2 && i1 == i2
921 #define PXH_FN(p,l,i) ipa_hash32(p) ^ u32_hash((l << 16) ^ i)
922
923 #define PXH_REHASH bgp_pxh_rehash
924 #define PXH_PARAMS /8, *2, 2, 2, 8, 20
925
926
927 HASH_DEFINE_REHASH_FN(PXH, struct bgp_prefix)
928
929 void
930 bgp_init_prefix_table(struct bgp_proto *p, u32 order)
931 {
932 HASH_INIT(p->prefix_hash, p->p.pool, order);
933
934 p->prefix_slab = sl_new(p->p.pool, sizeof(struct bgp_prefix));
935 }
936
937 static struct bgp_prefix *
938 bgp_get_prefix(struct bgp_proto *p, ip_addr prefix, int pxlen, u32 path_id)
939 {
940 struct bgp_prefix *bp = HASH_FIND(p->prefix_hash, PXH, prefix, pxlen, path_id);
941
942 if (bp)
943 return bp;
944
945 bp = sl_alloc(p->prefix_slab);
946 bp->n.prefix = prefix;
947 bp->n.pxlen = pxlen;
948 bp->path_id = path_id;
949 bp->bucket_node.next = NULL;
950
951 HASH_INSERT2(p->prefix_hash, PXH, p->p.pool, bp);
952
953 return bp;
954 }
955
956 void
957 bgp_free_prefix(struct bgp_proto *p, struct bgp_prefix *bp)
958 {
959 HASH_REMOVE2(p->prefix_hash, PXH, p->p.pool, bp);
960 sl_free(p->prefix_slab, bp);
961 }
962
963
964 void
965 bgp_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
966 {
967 struct bgp_proto *p = (struct bgp_proto *) P;
968 struct bgp_bucket *buck;
969 struct bgp_prefix *px;
970 rte *key;
971 u32 path_id;
972
973 DBG("BGP: Got route %I/%d %s\n", n->n.prefix, n->n.pxlen, new ? "up" : "down");
974
975 if (new)
976 {
977 key = new;
978 buck = bgp_get_bucket(p, n, attrs, new->attrs->source != RTS_BGP);
979 if (!buck) /* Inconsistent attribute list */
980 return;
981 }
982 else
983 {
984 key = old;
985 if (!(buck = p->withdraw_bucket))
986 {
987 buck = p->withdraw_bucket = mb_alloc(P->pool, sizeof(struct bgp_bucket));
988 init_list(&buck->prefixes);
989 }
990 }
991 path_id = p->add_path_tx ? key->attrs->src->global_id : 0;
992 px = bgp_get_prefix(p, n->n.prefix, n->n.pxlen, path_id);
993 if (px->bucket_node.next)
994 {
995 DBG("\tRemoving old entry.\n");
996 rem_node(&px->bucket_node);
997 }
998 add_tail(&buck->prefixes, &px->bucket_node);
999 bgp_schedule_packet(p->conn, PKT_UPDATE);
1000 }
1001
1002 static int
1003 bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *pool)
1004 {
1005 ea_list *ea = lp_alloc(pool, sizeof(ea_list) + 4*sizeof(eattr));
1006 rta *rta = e->attrs;
1007 byte *z;
1008
1009 ea->next = *attrs;
1010 *attrs = ea;
1011 ea->flags = EALF_SORTED;
1012 ea->count = 4;
1013
1014 bgp_set_attr(ea->attrs, BA_ORIGIN,
1015 ((rta->source == RTS_OSPF_EXT1) || (rta->source == RTS_OSPF_EXT2)) ? ORIGIN_INCOMPLETE : ORIGIN_IGP);
1016
1017 if (p->is_internal)
1018 bgp_set_attr_wa(ea->attrs+1, pool, BA_AS_PATH, 0);
1019 else
1020 {
1021 z = bgp_set_attr_wa(ea->attrs+1, pool, BA_AS_PATH, 6);
1022 z[0] = AS_PATH_SEQUENCE;
1023 z[1] = 1; /* 1 AS */
1024 put_u32(z+2, p->local_as);
1025 }
1026
1027 /* iBGP -> use gw, eBGP multi-hop -> use source_addr,
1028 eBGP single-hop -> use gw if on the same iface */
1029 z = bgp_set_attr_wa(ea->attrs+2, pool, BA_NEXT_HOP, NEXT_HOP_LENGTH);
1030 if (p->cf->next_hop_self ||
1031 rta->dest != RTD_ROUTER ||
1032 ipa_equal(rta->gw, IPA_NONE) ||
1033 ipa_is_link_local(rta->gw) ||
1034 (!p->is_internal && !p->cf->next_hop_keep &&
1035 (!p->neigh || (rta->iface != p->neigh->iface))))
1036 set_next_hop(z, p->source_addr);
1037 else
1038 set_next_hop(z, rta->gw);
1039
1040 bgp_set_attr(ea->attrs+3, BA_LOCAL_PREF, p->cf->default_local_pref);
1041
1042 return 0; /* Leave decision to the filters */
1043 }
1044
1045
1046 static inline int
1047 bgp_as_path_loopy(struct bgp_proto *p, rta *a)
1048 {
1049 int num = p->cf->allow_local_as + 1;
1050 eattr *e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1051 return (e && (num > 0) && as_path_contains(e->u.ptr, p->local_as, num));
1052 }
1053
1054 static inline int
1055 bgp_originator_id_loopy(struct bgp_proto *p, rta *a)
1056 {
1057 eattr *e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID));
1058 return (e && (e->u.data == p->local_id));
1059 }
1060
1061 static inline int
1062 bgp_cluster_list_loopy(struct bgp_proto *p, rta *a)
1063 {
1064 eattr *e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_CLUSTER_LIST));
1065 return (e && p->rr_client && int_set_contains(e->u.ptr, p->rr_cluster_id));
1066 }
1067
1068
1069 static inline void
1070 bgp_path_prepend(rte *e, ea_list **attrs, struct linpool *pool, u32 as)
1071 {
1072 eattr *a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1073 bgp_attach_attr(attrs, pool, BA_AS_PATH, (uintptr_t) as_path_prepend(pool, a->u.ptr, as));
1074 }
1075
1076 static inline void
1077 bgp_cluster_list_prepend(rte *e, ea_list **attrs, struct linpool *pool, u32 cid)
1078 {
1079 eattr *a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_CLUSTER_LIST));
1080 bgp_attach_attr(attrs, pool, BA_CLUSTER_LIST, (uintptr_t) int_set_add(pool, a ? a->u.ptr : NULL, cid));
1081 }
1082
1083 static int
1084 bgp_update_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *pool, int rr)
1085 {
1086 eattr *a;
1087
1088 if (!p->is_internal && !p->rs_client)
1089 {
1090 bgp_path_prepend(e, attrs, pool, p->local_as);
1091
1092 /* The MULTI_EXIT_DISC attribute received from a neighboring AS MUST NOT be
1093 * propagated to other neighboring ASes.
1094 * Perhaps it would be better to undefine it.
1095 */
1096 a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
1097 if (a)
1098 bgp_attach_attr(attrs, pool, BA_MULTI_EXIT_DISC, 0);
1099 }
1100
1101 /* iBGP -> keep next_hop, eBGP multi-hop -> use source_addr,
1102 * eBGP single-hop -> keep next_hop if on the same iface.
1103 * If the next_hop is zero (i.e. link-local), keep only if on the same iface.
1104 *
1105 * Note that same-iface-check uses iface from route, which is based on gw.
1106 */
1107 a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
1108 if (a && !p->cf->next_hop_self &&
1109 (p->cf->next_hop_keep ||
1110 (p->is_internal && ipa_nonzero(*((ip_addr *) a->u.ptr->data))) ||
1111 (p->neigh && (e->attrs->iface == p->neigh->iface))))
1112 {
1113 /* Leave the original next hop attribute, will check later where does it point */
1114 }
1115 else
1116 {
1117 /* Need to create new one */
1118 byte *b = bgp_attach_attr_wa(attrs, pool, BA_NEXT_HOP, NEXT_HOP_LENGTH);
1119 set_next_hop(b, p->source_addr);
1120 }
1121
1122 if (rr)
1123 {
1124 /* Handling route reflection, RFC 4456 */
1125 struct bgp_proto *src = (struct bgp_proto *) e->attrs->src->proto;
1126
1127 a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID));
1128 if (!a)
1129 bgp_attach_attr(attrs, pool, BA_ORIGINATOR_ID, src->remote_id);
1130
1131 /* We attach proper cluster ID according to whether the route is entering or leaving the cluster */
1132 bgp_cluster_list_prepend(e, attrs, pool, src->rr_client ? src->rr_cluster_id : p->rr_cluster_id);
1133
1134 /* Two RR clients with different cluster ID, hmmm */
1135 if (src->rr_client && p->rr_client && (src->rr_cluster_id != p->rr_cluster_id))
1136 bgp_cluster_list_prepend(e, attrs, pool, p->rr_cluster_id);
1137 }
1138
1139 return 0; /* Leave decision to the filters */
1140 }
1141
1142 static int
1143 bgp_community_filter(struct bgp_proto *p, rte *e)
1144 {
1145 eattr *a;
1146 struct adata *d;
1147
1148 /* Check if we aren't forbidden to export the route by communities */
1149 a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_COMMUNITY));
1150 if (a)
1151 {
1152 d = a->u.ptr;
1153 if (int_set_contains(d, BGP_COMM_NO_ADVERTISE))
1154 {
1155 DBG("\tNO_ADVERTISE\n");
1156 return 1;
1157 }
1158 if (!p->is_internal &&
1159 (int_set_contains(d, BGP_COMM_NO_EXPORT) ||
1160 int_set_contains(d, BGP_COMM_NO_EXPORT_SUBCONFED)))
1161 {
1162 DBG("\tNO_EXPORT\n");
1163 return 1;
1164 }
1165 }
1166
1167 return 0;
1168 }
1169
1170 int
1171 bgp_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
1172 {
1173 rte *e = *new;
1174 struct bgp_proto *p = (struct bgp_proto *) P;
1175 struct bgp_proto *new_bgp = (e->attrs->src->proto->proto == &proto_bgp) ?
1176 (struct bgp_proto *) e->attrs->src->proto : NULL;
1177
1178 if (p == new_bgp) /* Poison reverse updates */
1179 return -1;
1180 if (new_bgp)
1181 {
1182 /* We should check here for cluster list loop, because the receiving BGP instance
1183 might have different cluster ID */
1184 if (bgp_cluster_list_loopy(p, e->attrs))
1185 return -1;
1186
1187 if (p->cf->interpret_communities && bgp_community_filter(p, e))
1188 return -1;
1189
1190 if (p->local_as == new_bgp->local_as && p->is_internal && new_bgp->is_internal)
1191 {
1192 /* Redistribution of internal routes with IBGP */
1193 if (p->rr_client || new_bgp->rr_client)
1194 /* Route reflection, RFC 4456 */
1195 return bgp_update_attrs(p, e, attrs, pool, 1);
1196 else
1197 return -1;
1198 }
1199 else
1200 return bgp_update_attrs(p, e, attrs, pool, 0);
1201 }
1202 else
1203 return bgp_create_attrs(p, e, attrs, pool);
1204 }
1205
1206 static inline u32
1207 bgp_get_neighbor(rte *r)
1208 {
1209 eattr *e = ea_find(r->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1210 u32 as;
1211
1212 if (e && as_path_get_first(e->u.ptr, &as))
1213 return as;
1214 else
1215 return ((struct bgp_proto *) r->attrs->src->proto)->remote_as;
1216 }
1217
1218 static inline int
1219 rte_resolvable(rte *rt)
1220 {
1221 int rd = rt->attrs->dest;
1222 return (rd == RTD_ROUTER) || (rd == RTD_DEVICE) || (rd == RTD_MULTIPATH);
1223 }
1224
1225 int
1226 bgp_rte_better(rte *new, rte *old)
1227 {
1228 struct bgp_proto *new_bgp = (struct bgp_proto *) new->attrs->src->proto;
1229 struct bgp_proto *old_bgp = (struct bgp_proto *) old->attrs->src->proto;
1230 eattr *x, *y;
1231 u32 n, o;
1232
1233 /* Skip suppressed routes (see bgp_rte_recalculate()) */
1234 n = new->u.bgp.suppressed;
1235 o = old->u.bgp.suppressed;
1236 if (n > o)
1237 return 0;
1238 if (n < o)
1239 return 1;
1240
1241 /* RFC 4271 9.1.2.1. Route resolvability test */
1242 n = rte_resolvable(new);
1243 o = rte_resolvable(old);
1244 if (n > o)
1245 return 1;
1246 if (n < o)
1247 return 0;
1248
1249 /* Start with local preferences */
1250 x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
1251 y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
1252 n = x ? x->u.data : new_bgp->cf->default_local_pref;
1253 o = y ? y->u.data : old_bgp->cf->default_local_pref;
1254 if (n > o)
1255 return 1;
1256 if (n < o)
1257 return 0;
1258
1259 /* RFC 4271 9.1.2.2. a) Use AS path lengths */
1260 if (new_bgp->cf->compare_path_lengths || old_bgp->cf->compare_path_lengths)
1261 {
1262 x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1263 y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1264 n = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
1265 o = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
1266 if (n < o)
1267 return 1;
1268 if (n > o)
1269 return 0;
1270 }
1271
1272 /* RFC 4271 9.1.2.2. b) Use origins */
1273 x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGIN));
1274 y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGIN));
1275 n = x ? x->u.data : ORIGIN_INCOMPLETE;
1276 o = y ? y->u.data : ORIGIN_INCOMPLETE;
1277 if (n < o)
1278 return 1;
1279 if (n > o)
1280 return 0;
1281
1282 /* RFC 4271 9.1.2.2. c) Compare MED's */
1283 /* Proper RFC 4271 path selection cannot be interpreted as finding
1284 * the best path in some ordering. It is implemented partially in
1285 * bgp_rte_recalculate() when deterministic_med option is
1286 * active. Without that option, the behavior is just an
1287 * approximation, which in specific situations may lead to
1288 * persistent routing loops, because it is nondeterministic - it
1289 * depends on the order in which routes appeared. But it is also the
1290 * same behavior as used by default in Cisco routers, so it is
1291 * probably not a big issue.
1292 */
1293 if (new_bgp->cf->med_metric || old_bgp->cf->med_metric ||
1294 (bgp_get_neighbor(new) == bgp_get_neighbor(old)))
1295 {
1296 x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
1297 y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
1298 n = x ? x->u.data : new_bgp->cf->default_med;
1299 o = y ? y->u.data : old_bgp->cf->default_med;
1300 if (n < o)
1301 return 1;
1302 if (n > o)
1303 return 0;
1304 }
1305
1306 /* RFC 4271 9.1.2.2. d) Prefer external peers */
1307 if (new_bgp->is_internal > old_bgp->is_internal)
1308 return 0;
1309 if (new_bgp->is_internal < old_bgp->is_internal)
1310 return 1;
1311
1312 /* RFC 4271 9.1.2.2. e) Compare IGP metrics */
1313 n = new_bgp->cf->igp_metric ? new->attrs->igp_metric : 0;
1314 o = old_bgp->cf->igp_metric ? old->attrs->igp_metric : 0;
1315 if (n < o)
1316 return 1;
1317 if (n > o)
1318 return 0;
1319
1320 /* RFC 4271 9.1.2.2. f) Compare BGP identifiers */
1321 /* RFC 4456 9. a) Use ORIGINATOR_ID instead of local neighor ID */
1322 x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID));
1323 y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID));
1324 n = x ? x->u.data : new_bgp->remote_id;
1325 o = y ? y->u.data : old_bgp->remote_id;
1326
1327 /* RFC 5004 - prefer older routes */
1328 /* (if both are external and from different peer) */
1329 if ((new_bgp->cf->prefer_older || old_bgp->cf->prefer_older) &&
1330 !new_bgp->is_internal && n != o)
1331 return 0;
1332
1333 /* rest of RFC 4271 9.1.2.2. f) */
1334 if (n < o)
1335 return 1;
1336 if (n > o)
1337 return 0;
1338
1339 /* RFC 4456 9. b) Compare cluster list lengths */
1340 x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_CLUSTER_LIST));
1341 y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_CLUSTER_LIST));
1342 n = x ? int_set_get_size(x->u.ptr) : 0;
1343 o = y ? int_set_get_size(y->u.ptr) : 0;
1344 if (n < o)
1345 return 1;
1346 if (n > o)
1347 return 0;
1348
1349 /* RFC 4271 9.1.2.2. g) Compare peer IP adresses */
1350 return (ipa_compare(new_bgp->cf->remote_ip, old_bgp->cf->remote_ip) < 0);
1351 }
1352
1353
1354 int
1355 bgp_rte_mergable(rte *pri, rte *sec)
1356 {
1357 struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->attrs->src->proto;
1358 struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->attrs->src->proto;
1359 eattr *x, *y;
1360 u32 p, s;
1361
1362 /* Skip suppressed routes (see bgp_rte_recalculate()) */
1363 if (pri->u.bgp.suppressed != sec->u.bgp.suppressed)
1364 return 0;
1365
1366 /* RFC 4271 9.1.2.1. Route resolvability test */
1367 if (!rte_resolvable(sec))
1368 return 0;
1369
1370 /* Start with local preferences */
1371 x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
1372 y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
1373 p = x ? x->u.data : pri_bgp->cf->default_local_pref;
1374 s = y ? y->u.data : sec_bgp->cf->default_local_pref;
1375 if (p != s)
1376 return 0;
1377
1378 /* RFC 4271 9.1.2.2. a) Use AS path lengths */
1379 if (pri_bgp->cf->compare_path_lengths || sec_bgp->cf->compare_path_lengths)
1380 {
1381 x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1382 y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1383 p = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
1384 s = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
1385
1386 if (p != s)
1387 return 0;
1388
1389 // if (DELTA(p, s) > pri_bgp->cf->relax_multipath)
1390 // return 0;
1391 }
1392
1393 /* RFC 4271 9.1.2.2. b) Use origins */
1394 x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGIN));
1395 y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGIN));
1396 p = x ? x->u.data : ORIGIN_INCOMPLETE;
1397 s = y ? y->u.data : ORIGIN_INCOMPLETE;
1398 if (p != s)
1399 return 0;
1400
1401 /* RFC 4271 9.1.2.2. c) Compare MED's */
1402 if (pri_bgp->cf->med_metric || sec_bgp->cf->med_metric ||
1403 (bgp_get_neighbor(pri) == bgp_get_neighbor(sec)))
1404 {
1405 x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
1406 y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
1407 p = x ? x->u.data : pri_bgp->cf->default_med;
1408 s = y ? y->u.data : sec_bgp->cf->default_med;
1409 if (p != s)
1410 return 0;
1411 }
1412
1413 /* RFC 4271 9.1.2.2. d) Prefer external peers */
1414 if (pri_bgp->is_internal != sec_bgp->is_internal)
1415 return 0;
1416
1417 /* RFC 4271 9.1.2.2. e) Compare IGP metrics */
1418 p = pri_bgp->cf->igp_metric ? pri->attrs->igp_metric : 0;
1419 s = sec_bgp->cf->igp_metric ? sec->attrs->igp_metric : 0;
1420 if (p != s)
1421 return 0;
1422
1423 /* Remaining criteria are ignored */
1424
1425 return 1;
1426 }
1427
1428
1429
1430 static inline int
1431 same_group(rte *r, u32 lpref, u32 lasn)
1432 {
1433 return (r->pref == lpref) && (bgp_get_neighbor(r) == lasn);
1434 }
1435
1436 static inline int
1437 use_deterministic_med(rte *r)
1438 {
1439 struct proto *P = r->attrs->src->proto;
1440 return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
1441 }
1442
1443 int
1444 bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
1445 {
1446 rte *r, *s;
1447 rte *key = new ? new : old;
1448 u32 lpref = key->pref;
1449 u32 lasn = bgp_get_neighbor(key);
1450 int old_is_group_best = 0;
1451
1452 /*
1453 * Proper RFC 4271 path selection is a bit complicated, it cannot be
1454 * implemented just by rte_better(), because it is not a linear
1455 * ordering. But it can be splitted to two levels, where the lower
1456 * level chooses the best routes in each group of routes from the
1457 * same neighboring AS and higher level chooses the best route (with
1458 * a slightly different ordering) between the best-in-group routes.
1459 *
1460 * When deterministic_med is disabled, we just ignore this issue and
1461 * choose the best route by bgp_rte_better() alone. If enabled, the
1462 * lower level of the route selection is done here (for the group
1463 * to which the changed route belongs), all routes in group are
1464 * marked as suppressed, just chosen best-in-group is not.
1465 *
1466 * Global best route selection then implements higher level by
1467 * choosing between non-suppressed routes (as they are always
1468 * preferred over suppressed routes). Routes from BGP protocols
1469 * that do not set deterministic_med are just never suppressed. As
1470 * they do not participate in the lower level selection, it is OK
1471 * that this fn is not called for them.
1472 *
1473 * The idea is simple, the implementation is more problematic,
1474 * mostly because of optimizations in rte_recalculate() that
1475 * avoids full recalculation in most cases.
1476 *
1477 * We can assume that at least one of new, old is non-NULL and both
1478 * are from the same protocol with enabled deterministic_med. We
1479 * group routes by both neighbor AS (lasn) and preference (lpref),
1480 * because bgp_rte_better() does not handle preference itself.
1481 */
1482
1483 /* If new and old are from different groups, we just process that
1484 as two independent events */
1485 if (new && old && !same_group(old, lpref, lasn))
1486 {
1487 int i1, i2;
1488 i1 = bgp_rte_recalculate(table, net, NULL, old, old_best);
1489 i2 = bgp_rte_recalculate(table, net, new, NULL, old_best);
1490 return i1 || i2;
1491 }
1492
1493 /*
1494 * We could find the best-in-group and then make some shortcuts like
1495 * in rte_recalculate, but as we would have to walk through all
1496 * net->routes just to find it, it is probably not worth. So we
1497 * just have two simpler fast cases that use just the old route.
1498 * We also set suppressed flag to avoid using it in bgp_rte_better().
1499 */
1500
1501 if (new)
1502 new->u.bgp.suppressed = 1;
1503
1504 if (old)
1505 {
1506 old_is_group_best = !old->u.bgp.suppressed;
1507 old->u.bgp.suppressed = 1;
1508 int new_is_better = new && bgp_rte_better(new, old);
1509
1510 /* The first case - replace not best with worse (or remove not best) */
1511 if (!old_is_group_best && !new_is_better)
1512 return 0;
1513
1514 /* The second case - replace the best with better */
1515 if (old_is_group_best && new_is_better)
1516 {
1517 /* new is best-in-group, the see discussion below - this is
1518 a special variant of NBG && OBG. From OBG we can deduce
1519 that same_group(old_best) iff (old == old_best) */
1520 new->u.bgp.suppressed = 0;
1521 return (old == old_best);
1522 }
1523 }
1524
1525 /* The default case - find a new best-in-group route */
1526 r = new; /* new may not be in the list */
1527 for (s=net->routes; rte_is_valid(s); s=s->next)
1528 if (use_deterministic_med(s) && same_group(s, lpref, lasn))
1529 {
1530 s->u.bgp.suppressed = 1;
1531 if (!r || bgp_rte_better(s, r))
1532 r = s;
1533 }
1534
1535 /* Simple case - the last route in group disappears */
1536 if (!r)
1537 return 0;
1538
1539 /* Found best-in-group */
1540 r->u.bgp.suppressed = 0;
1541
1542 /*
1543 * There are generally two reasons why we have to force
1544 * recalculation (return 1): First, the new route may be wrongfully
1545 * chosen to be the best in the first case check in
1546 * rte_recalculate(), this may happen only if old_best is from the
1547 * same group. Second, another (different than new route)
1548 * best-in-group is chosen and that may be the proper best (although
1549 * rte_recalculate() without ignore that possibility).
1550 *
1551 * There are three possible cases according to whether the old route
1552 * was the best in group (OBG, stored in old_is_group_best) and
1553 * whether the new route is the best in group (NBG, tested by r == new).
1554 * These cases work even if old or new is NULL.
1555 *
1556 * NBG -> new is a possible candidate for the best route, so we just
1557 * check for the first reason using same_group().
1558 *
1559 * !NBG && OBG -> Second reason applies, return 1
1560 *
1561 * !NBG && !OBG -> Best in group does not change, old != old_best,
1562 * rte_better(new, old_best) is false and therefore
1563 * the first reason does not apply, return 0
1564 */
1565
1566 if (r == new)
1567 return old_best && same_group(old_best, lpref, lasn);
1568 else
1569 return old_is_group_best;
1570 }
1571
1572 static struct adata *
1573 bgp_aggregator_convert_to_new(struct adata *old, struct linpool *pool)
1574 {
1575 struct adata *newa = lp_alloc(pool, sizeof(struct adata) + 8);
1576 newa->length = 8;
1577 aggregator_convert_to_new(old, newa->data);
1578 return newa;
1579 }
1580
1581
1582 /* Take last req_as ASNs from path old2 (in 2B format), convert to 4B format
1583 * and append path old4 (in 4B format).
1584 */
1585 static struct adata *
1586 bgp_merge_as_paths(struct adata *old2, struct adata *old4, int req_as, struct linpool *pool)
1587 {
1588 byte buf[old2->length * 2];
1589
1590 int ol = as_path_convert_to_new(old2, buf, req_as);
1591 int nl = ol + (old4 ? old4->length : 0);
1592
1593 struct adata *newa = lp_alloc(pool, sizeof(struct adata) + nl);
1594 newa->length = nl;
1595 memcpy(newa->data, buf, ol);
1596 if (old4) memcpy(newa->data + ol, old4->data, old4->length);
1597
1598 return newa;
1599 }
1600
1601 static int
1602 as4_aggregator_valid(struct adata *aggr)
1603 {
1604 return aggr->length == 8;
1605 }
1606
1607
1608 /* Reconstruct 4B AS_PATH and AGGREGATOR according to RFC 4893 4.2.3 */
1609 static void
1610 bgp_reconstruct_4b_atts(struct bgp_proto *p, rta *a, struct linpool *pool)
1611 {
1612 eattr *p2 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1613 eattr *p4 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS4_PATH));
1614 eattr *a2 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AGGREGATOR));
1615 eattr *a4 =ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS4_AGGREGATOR));
1616 int a4_removed = 0;
1617
1618 if (a4 && !as4_aggregator_valid(a4->u.ptr))
1619 {
1620 log(L_WARN "%s: AS4_AGGREGATOR attribute is invalid, skipping attribute", p->p.name);
1621 a4 = NULL;
1622 a4_removed = 1;
1623 }
1624
1625 if (a2)
1626 {
1627 u32 a2_as = get_u16(a2->u.ptr->data);
1628
1629 if (a4)
1630 {
1631 if (a2_as != AS_TRANS)
1632 {
1633 /* Routes were aggregated by old router and therefore AS4_PATH
1634 * and AS4_AGGREGATOR is invalid
1635 *
1636 * Convert AS_PATH and AGGREGATOR to 4B format and finish.
1637 */
1638
1639 a2->u.ptr = bgp_aggregator_convert_to_new(a2->u.ptr, pool);
1640 p2->u.ptr = bgp_merge_as_paths(p2->u.ptr, NULL, AS_PATH_MAXLEN, pool);
1641
1642 return;
1643 }
1644 else
1645 {
1646 /* Common case, use AS4_AGGREGATOR attribute */
1647 a2->u.ptr = a4->u.ptr;
1648 }
1649 }
1650 else
1651 {
1652 /* Common case, use old AGGREGATOR attribute */
1653 a2->u.ptr = bgp_aggregator_convert_to_new(a2->u.ptr, pool);
1654
1655 if ((a2_as == AS_TRANS) && !a4_removed)
1656 log(L_WARN "%s: AGGREGATOR attribute contain AS_TRANS, but AS4_AGGREGATOR is missing", p->p.name);
1657 }
1658 }
1659 else
1660 if (a4)
1661 log(L_WARN "%s: AS4_AGGREGATOR attribute received, but AGGREGATOR attribute is missing", p->p.name);
1662
1663 int p2_len = as_path_getlen_int(p2->u.ptr, 2);
1664 int p4_len = p4 ? validate_as4_path(p, p4->u.ptr) : -1;
1665
1666 if (p4 && (p4_len < 0))
1667 log(L_WARN "%s: AS4_PATH attribute is malformed, skipping attribute", p->p.name);
1668
1669 if ((p4_len <= 0) || (p2_len < p4_len))
1670 p2->u.ptr = bgp_merge_as_paths(p2->u.ptr, NULL, AS_PATH_MAXLEN, pool);
1671 else
1672 p2->u.ptr = bgp_merge_as_paths(p2->u.ptr, p4->u.ptr, p2_len - p4_len, pool);
1673 }
1674
1675 static void
1676 bgp_remove_as4_attrs(struct bgp_proto *p, rta *a)
1677 {
1678 unsigned id1 = EA_CODE(EAP_BGP, BA_AS4_PATH);
1679 unsigned id2 = EA_CODE(EAP_BGP, BA_AS4_AGGREGATOR);
1680 ea_list **el = &(a->eattrs);
1681
1682 /* We know that ea_lists constructed in bgp_decode attrs have one attribute per ea_list struct */
1683 while (*el != NULL)
1684 {
1685 unsigned fid = (*el)->attrs[0].id;
1686
1687 if ((fid == id1) || (fid == id2))
1688 {
1689 *el = (*el)->next;
1690 if (p->as4_session)
1691 log(L_WARN "%s: Unexpected AS4_* attributes received", p->p.name);
1692 }
1693 else
1694 el = &((*el)->next);
1695 }
1696 }
1697
1698 /**
1699 * bgp_decode_attrs - check and decode BGP attributes
1700 * @conn: connection
1701 * @attr: start of attribute block
1702 * @len: length of attribute block
1703 * @pool: linear pool to make all the allocations in
1704 * @mandatory: 1 iff presence of mandatory attributes has to be checked
1705 *
1706 * This function takes a BGP attribute block (a part of an Update message), checks
1707 * its consistency and converts it to a list of BIRD route attributes represented
1708 * by a &rta.
1709 */
1710 struct rta *
1711 bgp_decode_attrs(struct bgp_conn *conn, byte *attr, uint len, struct linpool *pool, int mandatory)
1712 {
1713 struct bgp_proto *bgp = conn->bgp;
1714 rta *a = lp_alloc(pool, sizeof(struct rta));
1715 uint flags, code, l, i, type;
1716 int errcode;
1717 byte *z, *attr_start;
1718 byte seen[256/8];
1719 ea_list *ea;
1720 struct adata *ad;
1721 int withdraw = 0;
1722
1723 bzero(a, sizeof(rta));
1724 a->source = RTS_BGP;
1725 a->scope = SCOPE_UNIVERSE;
1726 a->cast = RTC_UNICAST;
1727 /* a->dest = RTD_ROUTER; -- set in bgp_set_next_hop() */
1728 a->from = bgp->cf->remote_ip;
1729
1730 /* Parse the attributes */
1731 bzero(seen, sizeof(seen));
1732 DBG("BGP: Parsing attributes\n");
1733 while (len)
1734 {
1735 if (len < 2)
1736 goto malformed;
1737 attr_start = attr;
1738 flags = *attr++;
1739 code = *attr++;
1740 len -= 2;
1741 if (flags & BAF_EXT_LEN)
1742 {
1743 if (len < 2)
1744 goto malformed;
1745 l = get_u16(attr);
1746 attr += 2;
1747 len -= 2;
1748 }
1749 else
1750 {
1751 if (len < 1)
1752 goto malformed;
1753 l = *attr++;
1754 len--;
1755 }
1756 if (l > len)
1757 goto malformed;
1758 len -= l;
1759 z = attr;
1760 attr += l;
1761 DBG("Attr %02x %02x %d\n", code, flags, l);
1762 if (seen[code/8] & (1 << (code%8)))
1763 goto malformed;
1764 if (ATTR_KNOWN(code))
1765 {
1766 struct attr_desc *desc = &bgp_attr_table[code];
1767 if (desc->expected_length >= 0 && desc->expected_length != (int) l)
1768 { errcode = 5; goto err; }
1769 if ((desc->expected_flags ^ flags) & (BAF_OPTIONAL | BAF_TRANSITIVE))
1770 { errcode = 4; goto err; }
1771 if (!desc->allow_in_ebgp && !bgp->is_internal)
1772 continue;
1773 if (desc->validate)
1774 {
1775 errcode = desc->validate(bgp, z, l);
1776 if (errcode > 0)
1777 goto err;
1778 if (errcode == IGNORE)
1779 continue;
1780 if (errcode <= WITHDRAW)
1781 {
1782 log(L_WARN "%s: Attribute %s is malformed, withdrawing update",
1783 bgp->p.name, desc->name);
1784 withdraw = 1;
1785 }
1786 }
1787 else if (code == BA_AS_PATH)
1788 {
1789 /* Special case as it might also trim the attribute */
1790 if (validate_as_path(bgp, z, &l) < 0)
1791 { errcode = 11; goto err; }
1792 }
1793 type = desc->type;
1794 }
1795 else /* Unknown attribute */
1796 {
1797 if (!(flags & BAF_OPTIONAL))
1798 { errcode = 2; goto err; }
1799 type = EAF_TYPE_OPAQUE;
1800 }
1801
1802 // Only OPTIONAL and TRANSITIVE attributes may have non-zero PARTIAL flag
1803 // if (!((flags & BAF_OPTIONAL) && (flags & BAF_TRANSITIVE)) && (flags & BAF_PARTIAL))
1804 // { errcode = 4; goto err; }
1805
1806 seen[code/8] |= (1 << (code%8));
1807 ea = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
1808 ea->next = a->eattrs;
1809 a->eattrs = ea;
1810 ea->flags = 0;
1811 ea->count = 1;
1812 ea->attrs[0].id = EA_CODE(EAP_BGP, code);
1813 ea->attrs[0].flags = flags;
1814 ea->attrs[0].type = type;
1815 if (type & EAF_EMBEDDED)
1816 ad = NULL;
1817 else
1818 {
1819 ad = lp_alloc(pool, sizeof(struct adata) + l);
1820 ea->attrs[0].u.ptr = ad;
1821 ad->length = l;
1822 memcpy(ad->data, z, l);
1823 }
1824 switch (type)
1825 {
1826 case EAF_TYPE_ROUTER_ID:
1827 case EAF_TYPE_INT:
1828 if (l == 1)
1829 ea->attrs[0].u.data = *z;
1830 else
1831 ea->attrs[0].u.data = get_u32(z);
1832 break;
1833 case EAF_TYPE_IP_ADDRESS:
1834 ipa_ntoh(*(ip_addr *)ad->data);
1835 break;
1836 case EAF_TYPE_INT_SET:
1837 case EAF_TYPE_LC_SET:
1838 case EAF_TYPE_EC_SET:
1839 {
1840 u32 *z = (u32 *) ad->data;
1841 for(i=0; i<ad->length/4; i++)
1842 z[i] = ntohl(z[i]);
1843 break;
1844 }
1845 }
1846 }
1847
1848 if (withdraw)
1849 goto withdraw;
1850
1851 #ifdef IPV6
1852 /* If we received MP_REACH_NLRI we should check mandatory attributes */
1853 if (bgp->mp_reach_len != 0)
1854 mandatory = 1;
1855 #endif
1856
1857 /* If there is no (reachability) NLRI, we should exit now */
1858 if (! mandatory)
1859 return a;
1860
1861 /* Check if all mandatory attributes are present */
1862 for(i=0; i < ARRAY_SIZE(bgp_mandatory_attrs); i++)
1863 {
1864 code = bgp_mandatory_attrs[i];
1865 if (!(seen[code/8] & (1 << (code%8))))
1866 {
1867 bgp_error(conn, 3, 3, &bgp_mandatory_attrs[i], 1);
1868 return NULL;
1869 }
1870 }
1871
1872 /* When receiving attributes from non-AS4-aware BGP speaker,
1873 * we have to reconstruct 4B AS_PATH and AGGREGATOR attributes
1874 */
1875 if (! bgp->as4_session)
1876 bgp_reconstruct_4b_atts(bgp, a, pool);
1877
1878 bgp_remove_as4_attrs(bgp, a);
1879
1880 /* If the AS path attribute contains our AS, reject the routes */
1881 if (bgp_as_path_loopy(bgp, a))
1882 goto withdraw;
1883
1884 /* Two checks for IBGP loops caused by route reflection, RFC 4456 */
1885 if (bgp_originator_id_loopy(bgp, a) ||
1886 bgp_cluster_list_loopy(bgp, a))
1887 goto withdraw;
1888
1889 /* If there's no local preference, define one */
1890 if (!(seen[0] & (1 << BA_LOCAL_PREF)))
1891 bgp_attach_attr(&a->eattrs, pool, BA_LOCAL_PREF, bgp->cf->default_local_pref);
1892
1893 return a;
1894
1895 withdraw:
1896 return NULL;
1897
1898 malformed:
1899 bgp_error(conn, 3, 1, NULL, 0);
1900 return NULL;
1901
1902 err:
1903 bgp_error(conn, 3, errcode, attr_start, z+l-attr_start);
1904 return NULL;
1905 }
1906
1907 int
1908 bgp_get_attr(eattr *a, byte *buf, int buflen)
1909 {
1910 uint i = EA_ID(a->id);
1911 struct attr_desc *d;
1912 int len;
1913
1914 if (ATTR_KNOWN(i))
1915 {
1916 d = &bgp_attr_table[i];
1917 len = bsprintf(buf, "%s", d->name);
1918 buf += len;
1919 if (d->format)
1920 {
1921 *buf++ = ':';
1922 *buf++ = ' ';
1923 d->format(a, buf, buflen - len - 2);
1924 return GA_FULL;
1925 }
1926 return GA_NAME;
1927 }
1928 bsprintf(buf, "%02x%s", i, (a->flags & BAF_TRANSITIVE) ? " [t]" : "");
1929 return GA_NAME;
1930 }
1931
1932 void
1933 bgp_init_bucket_table(struct bgp_proto *p)
1934 {
1935 p->hash_size = 256;
1936 p->hash_limit = p->hash_size * 4;
1937 p->bucket_hash = mb_allocz(p->p.pool, p->hash_size * sizeof(struct bgp_bucket *));
1938 init_list(&p->bucket_queue);
1939 p->withdraw_bucket = NULL;
1940 // fib_init(&p->prefix_fib, p->p.pool, sizeof(struct bgp_prefix), 0, bgp_init_prefix);
1941 }
1942
1943 void
1944 bgp_get_route_info(rte *e, byte *buf, ea_list *attrs)
1945 {
1946 eattr *p = ea_find(attrs, EA_CODE(EAP_BGP, BA_AS_PATH));
1947 eattr *o = ea_find(attrs, EA_CODE(EAP_BGP, BA_ORIGIN));
1948 u32 origas;
1949
1950 buf += bsprintf(buf, " (%d", e->pref);
1951
1952 if (e->u.bgp.suppressed)
1953 buf += bsprintf(buf, "-");
1954
1955 if (e->attrs->hostentry)
1956 {
1957 if (!rte_resolvable(e))
1958 buf += bsprintf(buf, "/-");
1959 else if (e->attrs->igp_metric >= IGP_METRIC_UNKNOWN)
1960 buf += bsprintf(buf, "/?");
1961 else
1962 buf += bsprintf(buf, "/%d", e->attrs->igp_metric);
1963 }
1964 buf += bsprintf(buf, ") [");
1965
1966 if (p && as_path_get_last(p->u.ptr, &origas))
1967 buf += bsprintf(buf, "AS%u", origas);
1968 if (o)
1969 buf += bsprintf(buf, "%c", "ie?"[o->u.data]);
1970 strcpy(buf, "]");
1971 }