blob: a79a03cc6323195d677585ee5e3c9a67278c032f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "memory.h"
26#include "vector.h"
27#include "vty.h"
28#include "stream.h"
29#include "log.h"
30#include "hash.h"
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -070031#include "jhash.h"
Donald Sharp04907292016-01-07 10:03:01 -050032#include "filter.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_route.h"
37#include "bgpd/bgp_aspath.h"
38#include "bgpd/bgp_community.h"
39#include "bgpd/bgp_debug.h"
40#include "bgpd/bgp_packet.h"
41#include "bgpd/bgp_ecommunity.h"
Job Snijders3334bab2017-01-20 14:47:12 +000042#include "bgpd/bgp_lcommunity.h"
Lou Bergerc3741782016-01-12 13:42:01 -050043#include "table.h"
44#include "bgp_encap_types.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020045
paul718e3742002-12-13 20:15:29 +000046/* Attribute strings for logging. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -070047static const struct message attr_str [] =
paul718e3742002-12-13 20:15:29 +000048{
49 { BGP_ATTR_ORIGIN, "ORIGIN" },
50 { BGP_ATTR_AS_PATH, "AS_PATH" },
51 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
52 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
53 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
54 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
55 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
56 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
57 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
Denis Ovsienkof8627ff2011-10-10 16:52:20 +040058 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
paul718e3742002-12-13 20:15:29 +000059 { BGP_ATTR_DPA, "DPA" },
60 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
61 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
62 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
63 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000064 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
65 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
66 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
67 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
Lou Bergerc3741782016-01-12 13:42:01 -050068 { BGP_ATTR_ENCAP, "ENCAP" },
Job Snijders3334bab2017-01-20 14:47:12 +000069 { 21, ""},
70 { 22, ""},
71 { 23, ""},
72 { 24, ""},
73 { 25, ""},
74 { 26, ""},
75 { 27, ""},
76 { 28, ""},
77 { 29, ""},
78 { 30, ""},
79 { 31, ""},
80 { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" }
paul718e3742002-12-13 20:15:29 +000081};
Balaji.G837d16c2012-09-26 14:09:10 +053082static const int attr_str_max = array_size(attr_str);
Denis Ovsienkoafcb7672011-10-23 22:32:44 +040083
84static const struct message attr_flag_str[] =
85{
86 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
87 { BGP_ATTR_FLAG_TRANS, "Transitive" },
88 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
89 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
90 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
91};
David Lamparter6b0655a2014-06-04 06:53:35 +020092
Stephen Hemminger9bddac42009-05-15 09:59:51 -070093static struct hash *cluster_hash;
paul718e3742002-12-13 20:15:29 +000094
paul94f2b392005-06-28 12:44:16 +000095static void *
Paul Jakma923de652007-04-29 18:25:17 +000096cluster_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +000097{
Paul Jakma923de652007-04-29 18:25:17 +000098 struct cluster_list * val = (struct cluster_list *) p;
paul718e3742002-12-13 20:15:29 +000099 struct cluster_list *cluster;
100
101 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
102 cluster->length = val->length;
103
104 if (cluster->length)
105 {
106 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
107 memcpy (cluster->list, val->list, val->length);
108 }
109 else
110 cluster->list = NULL;
111
112 cluster->refcnt = 0;
113
114 return cluster;
115}
116
117/* Cluster list related functions. */
paul94f2b392005-06-28 12:44:16 +0000118static struct cluster_list *
paul5228ad22004-06-04 17:58:18 +0000119cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +0000120{
121 struct cluster_list tmp;
122 struct cluster_list *cluster;
123
124 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +0000125 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +0000126
127 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
128 cluster->refcnt++;
129 return cluster;
130}
131
132int
133cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
134{
135 int i;
136
137 for (i = 0; i < cluster->length / 4; i++)
138 if (cluster->list[i].s_addr == originator.s_addr)
139 return 1;
140 return 0;
141}
142
paul94f2b392005-06-28 12:44:16 +0000143static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000144cluster_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000145{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700146 const struct cluster_list *cluster = p;
paul718e3742002-12-13 20:15:29 +0000147
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700148 return jhash(cluster->list, cluster->length, 0);
paul718e3742002-12-13 20:15:29 +0000149}
150
paul94f2b392005-06-28 12:44:16 +0000151static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100152cluster_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000153{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100154 const struct cluster_list * cluster1 = p1;
155 const struct cluster_list * cluster2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000156
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100157 return (cluster1->length == cluster2->length &&
158 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000159}
160
paul94f2b392005-06-28 12:44:16 +0000161static void
paul718e3742002-12-13 20:15:29 +0000162cluster_free (struct cluster_list *cluster)
163{
164 if (cluster->list)
165 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
166 XFREE (MTYPE_CLUSTER, cluster);
167}
168
Chris Caputo228da422009-07-18 05:44:03 +0000169#if 0
paul94f2b392005-06-28 12:44:16 +0000170static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000171cluster_dup (struct cluster_list *cluster)
172{
173 struct cluster_list *new;
174
Stephen Hemminger393deb92008-08-18 14:13:29 -0700175 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
paul718e3742002-12-13 20:15:29 +0000176 new->length = cluster->length;
177
178 if (cluster->length)
179 {
180 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
181 memcpy (new->list, cluster->list, cluster->length);
182 }
183 else
184 new->list = NULL;
185
186 return new;
187}
Chris Caputo228da422009-07-18 05:44:03 +0000188#endif
paul718e3742002-12-13 20:15:29 +0000189
paul94f2b392005-06-28 12:44:16 +0000190static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000191cluster_intern (struct cluster_list *cluster)
192{
193 struct cluster_list *find;
194
195 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
196 find->refcnt++;
197
198 return find;
199}
200
201void
202cluster_unintern (struct cluster_list *cluster)
203{
paul718e3742002-12-13 20:15:29 +0000204 if (cluster->refcnt)
205 cluster->refcnt--;
206
207 if (cluster->refcnt == 0)
208 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400209 hash_release (cluster_hash, cluster);
paul718e3742002-12-13 20:15:29 +0000210 cluster_free (cluster);
211 }
212}
213
paul94f2b392005-06-28 12:44:16 +0000214static void
215cluster_init (void)
paul718e3742002-12-13 20:15:29 +0000216{
217 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
218}
Chris Caputo228da422009-07-18 05:44:03 +0000219
220static void
221cluster_finish (void)
222{
Lou Berger056f3762013-04-10 12:30:04 -0700223 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
Chris Caputo228da422009-07-18 05:44:03 +0000224 hash_free (cluster_hash);
225 cluster_hash = NULL;
226}
David Lamparter6b0655a2014-06-04 06:53:35 +0200227
Lou Bergerc3741782016-01-12 13:42:01 -0500228struct bgp_attr_encap_subtlv *
229encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
230{
231 struct bgp_attr_encap_subtlv *new;
232 struct bgp_attr_encap_subtlv *tail;
233 struct bgp_attr_encap_subtlv *p;
234
235 for (p = orig, tail = new = NULL; p; p = p->next) {
236 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
237 if (tail) {
238 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
239 tail = tail->next;
240 } else {
241 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
242 }
243 assert(tail);
244 memcpy(tail, p, size);
245 tail->next = NULL;
246 }
247
248 return new;
249}
250
251static void
252encap_free(struct bgp_attr_encap_subtlv *p)
253{
254 struct bgp_attr_encap_subtlv *next;
255 while (p) {
256 next = p->next;
257 p->next = NULL;
258 XFREE(MTYPE_ENCAP_TLV, p);
259 p = next;
260 }
261}
262
263void
264bgp_attr_flush_encap(struct attr *attr)
265{
266 if (!attr || !attr->extra)
267 return;
268
269 if (attr->extra->encap_subtlvs) {
270 encap_free(attr->extra->encap_subtlvs);
271 attr->extra->encap_subtlvs = NULL;
272 }
273}
274
275/*
276 * Compare encap sub-tlv chains
277 *
278 * 1 = equivalent
279 * 0 = not equivalent
280 *
281 * This algorithm could be made faster if needed
282 */
283static int
284encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
285{
286 struct bgp_attr_encap_subtlv *p;
287 struct bgp_attr_encap_subtlv *q;
288
289 if (!h1 && !h2)
290 return 1;
291 if (h1 && !h2)
292 return 0;
293 if (!h1 && h2)
294 return 0;
295 if (h1 == h2)
296 return 1;
297
298 for (p = h1; p; p = p->next) {
299 for (q = h2; q; q = q->next) {
300 if ((p->type == q->type) &&
301 (p->length == q->length) &&
302 !memcmp(p->value, q->value, p->length)) {
303
304 break;
305 }
306 }
307 if (!q)
308 return 0;
309 }
310
311 for (p = h2; p; p = p->next) {
312 for (q = h1; q; q = q->next) {
313 if ((p->type == q->type) &&
314 (p->length == q->length) &&
315 !memcmp(p->value, q->value, p->length)) {
316
317 break;
318 }
319 }
320 if (!q)
321 return 0;
322 }
323
324 return 1;
325}
326
paul718e3742002-12-13 20:15:29 +0000327/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700328static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000329
paul94f2b392005-06-28 12:44:16 +0000330static void
paul718e3742002-12-13 20:15:29 +0000331transit_free (struct transit *transit)
332{
333 if (transit->val)
334 XFREE (MTYPE_TRANSIT_VAL, transit->val);
335 XFREE (MTYPE_TRANSIT, transit);
336}
337
Paul Jakma923de652007-04-29 18:25:17 +0000338
paul94f2b392005-06-28 12:44:16 +0000339static void *
Paul Jakma923de652007-04-29 18:25:17 +0000340transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000341{
342 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000343 return p;
paul718e3742002-12-13 20:15:29 +0000344}
345
paul94f2b392005-06-28 12:44:16 +0000346static struct transit *
paul718e3742002-12-13 20:15:29 +0000347transit_intern (struct transit *transit)
348{
349 struct transit *find;
350
351 find = hash_get (transit_hash, transit, transit_hash_alloc);
352 if (find != transit)
353 transit_free (transit);
354 find->refcnt++;
355
356 return find;
357}
358
359void
360transit_unintern (struct transit *transit)
361{
paul718e3742002-12-13 20:15:29 +0000362 if (transit->refcnt)
363 transit->refcnt--;
364
365 if (transit->refcnt == 0)
366 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400367 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000368 transit_free (transit);
369 }
370}
371
paul94f2b392005-06-28 12:44:16 +0000372static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000373transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000374{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700375 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000376
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700377 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000378}
379
paul94f2b392005-06-28 12:44:16 +0000380static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100381transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000382{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100383 const struct transit * transit1 = p1;
384 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000385
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100386 return (transit1->length == transit2->length &&
387 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000388}
389
paul94f2b392005-06-28 12:44:16 +0000390static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800391transit_init (void)
paul718e3742002-12-13 20:15:29 +0000392{
393 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
394}
Chris Caputo228da422009-07-18 05:44:03 +0000395
396static void
397transit_finish (void)
398{
Lou Berger056f3762013-04-10 12:30:04 -0700399 hash_clean (transit_hash, (void (*)(void *))transit_free);
Chris Caputo228da422009-07-18 05:44:03 +0000400 hash_free (transit_hash);
401 transit_hash = NULL;
402}
David Lamparter6b0655a2014-06-04 06:53:35 +0200403
paul718e3742002-12-13 20:15:29 +0000404/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700405static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000406
Paul Jakmafb982c22007-05-04 20:15:47 +0000407static struct attr_extra *
408bgp_attr_extra_new (void)
409{
410 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
411}
412
413void
414bgp_attr_extra_free (struct attr *attr)
415{
416 if (attr->extra)
417 {
Lou Bergerc3741782016-01-12 13:42:01 -0500418 if (attr->extra->encap_subtlvs) {
419 encap_free(attr->extra->encap_subtlvs);
420 attr->extra->encap_subtlvs = NULL;
421 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000422 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
423 attr->extra = NULL;
424 }
425}
426
427struct attr_extra *
428bgp_attr_extra_get (struct attr *attr)
429{
430 if (!attr->extra)
431 attr->extra = bgp_attr_extra_new();
432 return attr->extra;
433}
434
435/* Shallow copy of an attribute
436 * Though, not so shallow that it doesn't copy the contents
437 * of the attr_extra pointed to by 'extra'
438 */
439void
440bgp_attr_dup (struct attr *new, struct attr *orig)
441{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000442 struct attr_extra *extra = new->extra;
443
Paul Jakmafb982c22007-05-04 20:15:47 +0000444 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000445 /* if caller provided attr_extra space, use it in any case.
446 *
447 * This is neccesary even if orig->extra equals NULL, because otherwise
448 * memory may be later allocated on the heap by bgp_attr_extra_get.
449 *
450 * That memory would eventually be leaked, because the caller must not
451 * call bgp_attr_extra_free if he provided attr_extra on the stack.
452 */
453 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000454 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000455 new->extra = extra;
456 memset(new->extra, 0, sizeof(struct attr_extra));
Lou Bergerc3741782016-01-12 13:42:01 -0500457 if (orig->extra) {
Christian Frankea0de1d12012-12-07 16:35:00 +0000458 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500459 if (orig->extra->encap_subtlvs) {
460 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
461 }
462 }
Christian Frankea0de1d12012-12-07 16:35:00 +0000463 }
464 else if (orig->extra)
465 {
466 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000467 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500468 if (orig->extra->encap_subtlvs) {
469 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
470 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000471 }
472}
473
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000474unsigned long int
475attr_count (void)
476{
477 return attrhash->count;
478}
479
480unsigned long int
481attr_unknown_count (void)
482{
483 return transit_hash->count;
484}
485
paul718e3742002-12-13 20:15:29 +0000486unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000487attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000488{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000489 const struct attr *attr = (struct attr *) p;
490 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700491 uint32_t key = 0;
492#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000493
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700494 MIX(attr->origin);
495 MIX(attr->nexthop.s_addr);
496 MIX(attr->med);
497 MIX(attr->local_pref);
498
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000499 key += attr->origin;
500 key += attr->nexthop.s_addr;
501 key += attr->med;
502 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000503
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000504 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000505 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000506 MIX(extra->aggregator_as);
507 MIX(extra->aggregator_addr.s_addr);
508 MIX(extra->weight);
509 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000510 MIX(extra->originator_id.s_addr);
Piotr Chytła605aa332015-12-01 10:03:54 -0500511 MIX(extra->tag);
Paul Jakmafb982c22007-05-04 20:15:47 +0000512 }
513
paul718e3742002-12-13 20:15:29 +0000514 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700515 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000516 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700517 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000518
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000519 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000520 {
Job Snijders3334bab2017-01-20 14:47:12 +0000521 if (extra->lcommunity)
522 MIX(lcommunity_hash_make (extra->lcommunity));
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000523 if (extra->ecommunity)
524 MIX(ecommunity_hash_make (extra->ecommunity));
525 if (extra->cluster)
526 MIX(cluster_hash_key_make (extra->cluster));
527 if (extra->transit)
528 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000529
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000530 MIX(extra->mp_nexthop_len);
531 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
532 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
Paul Jakmafb982c22007-05-04 20:15:47 +0000533 }
paul718e3742002-12-13 20:15:29 +0000534
535 return key;
536}
537
538int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100539attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000540{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100541 const struct attr * attr1 = p1;
542 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000543
paul718e3742002-12-13 20:15:29 +0000544 if (attr1->flag == attr2->flag
545 && attr1->origin == attr2->origin
546 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000547 && attr1->aspath == attr2->aspath
548 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000549 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000550 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000551 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100552 const struct attr_extra *ae1 = attr1->extra;
553 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000554
555 if (ae1 && ae2
556 && ae1->aggregator_as == ae2->aggregator_as
557 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
558 && ae1->weight == ae2->weight
Piotr Chytła605aa332015-12-01 10:03:54 -0500559 && ae1->tag == ae2->tag
Paul Jakmafb982c22007-05-04 20:15:47 +0000560 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
561 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
562 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
Paul Jakmafb982c22007-05-04 20:15:47 +0000563 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
564 && ae1->ecommunity == ae2->ecommunity
Job Snijders3334bab2017-01-20 14:47:12 +0000565 && ae1->lcommunity == ae2->lcommunity
Paul Jakmafb982c22007-05-04 20:15:47 +0000566 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000567 && ae1->transit == ae2->transit
Lou Bergerc3741782016-01-12 13:42:01 -0500568 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
569 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000570 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000571 return 1;
572 else if (ae1 || ae2)
573 return 0;
574 /* neither attribute has extra attributes, so they're same */
575 return 1;
576 }
paul718e3742002-12-13 20:15:29 +0000577 else
578 return 0;
579}
580
paul94f2b392005-06-28 12:44:16 +0000581static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100582attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000583{
584 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
585}
586
Lou Berger056f3762013-04-10 12:30:04 -0700587/*
588 * special for hash_clean below
589 */
590static void
591attr_vfree (void *attr)
592{
593 bgp_attr_extra_free ((struct attr *)attr);
594 XFREE (MTYPE_ATTR, attr);
595}
596
paul94f2b392005-06-28 12:44:16 +0000597static void
Chris Caputo228da422009-07-18 05:44:03 +0000598attrhash_finish (void)
599{
Lou Berger056f3762013-04-10 12:30:04 -0700600 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000601 hash_free (attrhash);
602 attrhash = NULL;
603}
604
605static void
paul718e3742002-12-13 20:15:29 +0000606attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
607{
608 struct attr *attr = backet->data;
609
610 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
611 inet_ntoa (attr->nexthop), VTY_NEWLINE);
612}
613
614void
615attr_show_all (struct vty *vty)
616{
617 hash_iterate (attrhash,
618 (void (*)(struct hash_backet *, void *))
619 attr_show_all_iterator,
620 vty);
621}
622
paul94f2b392005-06-28 12:44:16 +0000623static void *
Paul Jakma923de652007-04-29 18:25:17 +0000624bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000625{
Paul Jakma923de652007-04-29 18:25:17 +0000626 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000627 struct attr *attr;
628
629 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
630 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000631 if (val->extra)
632 {
633 attr->extra = bgp_attr_extra_new ();
634 *attr->extra = *val->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500635
636 if (attr->extra->encap_subtlvs) {
637 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
638 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000639 }
paul718e3742002-12-13 20:15:29 +0000640 attr->refcnt = 0;
641 return attr;
642}
643
644/* Internet argument attribute. */
645struct attr *
646bgp_attr_intern (struct attr *attr)
647{
648 struct attr *find;
649
650 /* Intern referenced strucutre. */
651 if (attr->aspath)
652 {
653 if (! attr->aspath->refcnt)
654 attr->aspath = aspath_intern (attr->aspath);
655 else
656 attr->aspath->refcnt++;
657 }
658 if (attr->community)
659 {
660 if (! attr->community->refcnt)
661 attr->community = community_intern (attr->community);
662 else
663 attr->community->refcnt++;
664 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000665 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000666 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000667 struct attr_extra *attre = attr->extra;
668
669 if (attre->ecommunity)
670 {
671 if (! attre->ecommunity->refcnt)
672 attre->ecommunity = ecommunity_intern (attre->ecommunity);
673 else
674 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000675
Paul Jakmafb982c22007-05-04 20:15:47 +0000676 }
Job Snijders3334bab2017-01-20 14:47:12 +0000677 if (attre->lcommunity)
678 {
679 if (! attre->lcommunity->refcnt)
680 attre->lcommunity = lcommunity_intern (attre->lcommunity);
681 else
682 attre->lcommunity->refcnt++;
683 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000684 if (attre->cluster)
685 {
686 if (! attre->cluster->refcnt)
687 attre->cluster = cluster_intern (attre->cluster);
688 else
689 attre->cluster->refcnt++;
690 }
691 if (attre->transit)
692 {
693 if (! attre->transit->refcnt)
694 attre->transit = transit_intern (attre->transit);
695 else
696 attre->transit->refcnt++;
697 }
paul718e3742002-12-13 20:15:29 +0000698 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000699
paul718e3742002-12-13 20:15:29 +0000700 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
701 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000702
paul718e3742002-12-13 20:15:29 +0000703 return find;
704}
705
Paul Jakma03e214c2007-04-29 18:31:07 +0000706
paul718e3742002-12-13 20:15:29 +0000707/* Make network statement's attribute. */
708struct attr *
709bgp_attr_default_set (struct attr *attr, u_char origin)
710{
711 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000712 bgp_attr_extra_get (attr);
713
paul718e3742002-12-13 20:15:29 +0000714 attr->origin = origin;
715 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
716 attr->aspath = aspath_empty ();
717 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000718 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
Piotr Chytła605aa332015-12-01 10:03:54 -0500719 attr->extra->tag = 0;
paul718e3742002-12-13 20:15:29 +0000720 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
Paul Jakmafb982c22007-05-04 20:15:47 +0000721 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
Paul Jakma03e214c2007-04-29 18:31:07 +0000722
paul718e3742002-12-13 20:15:29 +0000723 return attr;
724}
725
Paul Jakma03e214c2007-04-29 18:31:07 +0000726
paul718e3742002-12-13 20:15:29 +0000727/* Make network statement's attribute. */
728struct attr *
729bgp_attr_default_intern (u_char origin)
730{
731 struct attr attr;
732 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000733
Lou Bergerc3741782016-01-12 13:42:01 -0500734 memset (&attr, 0, sizeof (struct attr));
735 bgp_attr_extra_get (&attr);
736
Paul Jakma03e214c2007-04-29 18:31:07 +0000737 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000738
739 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000740 bgp_attr_extra_free (&attr);
741
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000742 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000743 return new;
744}
745
Daniel Walton76a72802015-05-19 17:47:24 -0700746/* Create the attributes for an aggregate */
paul718e3742002-12-13 20:15:29 +0000747struct attr *
748bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
749 struct aspath *aspath,
Daniel Waltonf2eb9ca2015-05-19 17:47:21 -0700750 struct community *community, int as_set,
751 u_char atomic_aggregate)
paul718e3742002-12-13 20:15:29 +0000752{
753 struct attr attr;
754 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000755 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000756
757 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000758 memset (&attre, 0, sizeof (struct attr_extra));
759 attr.extra = &attre;
760
paul718e3742002-12-13 20:15:29 +0000761 /* Origin attribute. */
762 attr.origin = origin;
763 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
764
765 /* AS path attribute. */
766 if (aspath)
767 attr.aspath = aspath_intern (aspath);
768 else
769 attr.aspath = aspath_empty ();
770 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
771
772 /* Next hop attribute. */
773 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
774
775 if (community)
776 {
777 attr.community = community;
778 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
779 }
780
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000781 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000782 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
Lou Berger205e6742016-01-12 13:42:11 -0500783
Daniel Waltonf2eb9ca2015-05-19 17:47:21 -0700784 if (! as_set || atomic_aggregate)
paul718e3742002-12-13 20:15:29 +0000785 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
786 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
787 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000788 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000789 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000790 attre.aggregator_as = bgp->as;
791 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000792
793 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000794
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000795 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000796 return new;
797}
798
Paul Jakmab881c702010-11-23 16:35:42 +0000799/* Unintern just the sub-components of the attr, but not the attr */
800void
801bgp_attr_unintern_sub (struct attr *attr)
802{
803 /* aspath refcount shoud be decrement. */
804 if (attr->aspath)
805 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000806 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000807
808 if (attr->community)
809 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000810 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000811
812 if (attr->extra)
813 {
814 if (attr->extra->ecommunity)
815 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000816 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Job Snijders3334bab2017-01-20 14:47:12 +0000817
818 if (attr->extra->lcommunity)
819 lcommunity_unintern (&attr->extra->lcommunity);
820 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000821
822 if (attr->extra->cluster)
823 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000824 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000825
826 if (attr->extra->transit)
827 transit_unintern (attr->extra->transit);
828 }
829}
830
paul718e3742002-12-13 20:15:29 +0000831/* Free bgp attribute and aspath. */
832void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000833bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000834{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000835 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000836 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000837 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000838 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000839
paul718e3742002-12-13 20:15:29 +0000840 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000841 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000842
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000843 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000844
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000845 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000846 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000847 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000848 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000849 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000850
paul718e3742002-12-13 20:15:29 +0000851 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000852 if (attr->refcnt == 0)
853 {
854 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000855 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000856 bgp_attr_extra_free (attr);
857 XFREE (MTYPE_ATTR, attr);
858 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000859 }
860
Paul Jakmab881c702010-11-23 16:35:42 +0000861 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000862}
863
864void
865bgp_attr_flush (struct attr *attr)
866{
867 if (attr->aspath && ! attr->aspath->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500868 {
869 aspath_free (attr->aspath);
870 attr->aspath = NULL;
871 }
paul718e3742002-12-13 20:15:29 +0000872 if (attr->community && ! attr->community->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500873 {
874 community_free (attr->community);
875 attr->community = NULL;
876 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000877 if (attr->extra)
878 {
879 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000880
Paul Jakmafb982c22007-05-04 20:15:47 +0000881 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000882 ecommunity_free (&attre->ecommunity);
Job Snijders3334bab2017-01-20 14:47:12 +0000883 if (attre->lcommunity && ! attre->lcommunity->refcnt)
884 lcommunity_free (&attre->lcommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000885 if (attre->cluster && ! attre->cluster->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500886 {
887 cluster_free (attre->cluster);
888 attre->cluster = NULL;
889 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000890 if (attre->transit && ! attre->transit->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500891 {
892 transit_free (attre->transit);
893 attre->transit = NULL;
894 }
Lou Bergerc3741782016-01-12 13:42:01 -0500895 encap_free(attre->encap_subtlvs);
896 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000897 }
paul718e3742002-12-13 20:15:29 +0000898}
899
Paul Jakmab881c702010-11-23 16:35:42 +0000900/* Implement draft-scudder-idr-optional-transitive behaviour and
901 * avoid resetting sessions for malformed attributes which are
902 * are partial/optional and hence where the error likely was not
903 * introduced by the sending neighbour.
904 */
905static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000906bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
907 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000908{
Paul Jakma835315b2012-01-18 12:28:30 +0000909 struct peer *const peer = args->peer;
910 const u_int8_t flags = args->flags;
911 /* startp and length must be special-cased, as whether or not to
912 * send the attribute data with the NOTIFY depends on the error,
913 * the caller therefore signals this with the seperate length argument
914 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000915 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000916
Paul Jakmab881c702010-11-23 16:35:42 +0000917 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000918 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000919 {
920 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000921 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000922 return BGP_ATTR_PARSE_ERROR;
923
924 }
925
Paul Jakmabd471fe2012-03-15 11:30:00 +0000926 /* Adjust the stream getp to the end of the attribute, in case we can
927 * still proceed but the caller hasn't read all the attribute.
928 */
929 stream_set_getp (BGP_INPUT (peer),
930 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
931 + args->total);
932
Paul Jakma835315b2012-01-18 12:28:30 +0000933 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100934 /* where an attribute is relatively inconsequential, e.g. it does not
935 * affect route selection, and can be safely ignored, then any such
936 * attributes which are malformed should just be ignored and the route
937 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000938 */
939 case BGP_ATTR_AS4_AGGREGATOR:
940 case BGP_ATTR_AGGREGATOR:
941 case BGP_ATTR_ATOMIC_AGGREGATE:
942 return BGP_ATTR_PARSE_PROCEED;
943
944 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100945 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000946 */
947 case BGP_ATTR_ORIGIN:
948 case BGP_ATTR_AS_PATH:
949 case BGP_ATTR_NEXT_HOP:
950 case BGP_ATTR_MULTI_EXIT_DISC:
951 case BGP_ATTR_LOCAL_PREF:
952 case BGP_ATTR_COMMUNITIES:
953 case BGP_ATTR_ORIGINATOR_ID:
954 case BGP_ATTR_CLUSTER_LIST:
955 case BGP_ATTR_MP_REACH_NLRI:
956 case BGP_ATTR_MP_UNREACH_NLRI:
957 case BGP_ATTR_EXT_COMMUNITIES:
958 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000959 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000960 return BGP_ATTR_PARSE_ERROR;
961 }
962
963 /* Partial optional attributes that are malformed should not cause
964 * the whole session to be reset. Instead treat it as a withdrawal
965 * of the routes, if possible.
966 */
Paul Jakma835315b2012-01-18 12:28:30 +0000967 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
968 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
969 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000970 return BGP_ATTR_PARSE_WITHDRAW;
971
972 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200973 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000974}
975
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400976/* Find out what is wrong with the path attribute flag bits and log the error.
977 "Flag bits" here stand for Optional, Transitive and Partial, but not for
978 Extended Length. Checking O/T/P bits at once implies, that the attribute
979 being diagnosed is defined by RFC as either a "well-known" or an "optional,
980 non-transitive" attribute. */
981static void
Paul Jakma835315b2012-01-18 12:28:30 +0000982bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
983 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400984)
985{
986 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000987 u_char real_flags = args->flags;
988 const u_int8_t attr_code = args->type;
989
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400990 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
991 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
992 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
993 if
994 (
995 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
996 CHECK_FLAG (real_flags, attr_flag_str[i].key)
997 )
998 {
Paul Jakma835315b2012-01-18 12:28:30 +0000999 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +04001000 LOOKUP (attr_str, attr_code),
1001 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
1002 attr_flag_str[i].str);
1003 seen = 1;
1004 }
Paul Jakmafa5831e2012-03-27 11:54:04 +01001005 if (!seen)
1006 {
1007 zlog (args->peer->log, LOG_DEBUG,
1008 "Strange, %s called for attr %s, but no problem found with flags"
1009 " (real flags 0x%x, desired 0x%x)",
1010 __func__, LOOKUP (attr_str, attr_code),
1011 real_flags, desired_flags);
1012 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +04001013}
1014
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001015/* Required flags for attributes. EXTLEN will be masked off when testing,
1016 * as will PARTIAL for optional+transitive attributes.
1017 */
1018const u_int8_t attr_flags_values [] = {
1019 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1020 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1021 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1022 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1023 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1024 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1025 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1026 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1027 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1028 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1029 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1030 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1031 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1032 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1033 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
Job Snijders3334bab2017-01-20 14:47:12 +00001034 [BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001035};
Christian Franke0d8b32a2016-06-14 20:07:00 +02001036static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001037
1038static int
Paul Jakma835315b2012-01-18 12:28:30 +00001039bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001040{
1041 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +00001042 const u_int8_t flags = args->flags;
1043 const u_int8_t attr_code = args->type;
1044 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001045
1046 /* there may be attributes we don't know about */
1047 if (attr_code > attr_flags_values_max)
1048 return 0;
1049 if (attr_flags_values[attr_code] == 0)
1050 return 0;
1051
1052 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1053 * 1."
1054 */
1055 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1056 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1057 {
1058 zlog (peer->log, LOG_ERR,
1059 "%s well-known attributes must have transitive flag set (%x)",
1060 LOOKUP (attr_str, attr_code), flags);
1061 return 1;
1062 }
1063
1064 /* "For well-known attributes and for optional non-transitive attributes,
1065 * the Partial bit MUST be set to 0."
1066 */
1067 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1068 {
1069 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1070 {
1071 zlog (peer->log, LOG_ERR,
1072 "%s well-known attribute "
1073 "must NOT have the partial flag set (%x)",
1074 LOOKUP (attr_str, attr_code), flags);
1075 return 1;
1076 }
1077 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1078 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1079 {
1080 zlog (peer->log, LOG_ERR,
1081 "%s optional + transitive attribute "
1082 "must NOT have the partial flag set (%x)",
1083 LOOKUP (attr_str, attr_code), flags);
1084 return 1;
1085 }
1086 }
1087
1088 /* Optional transitive attributes may go through speakers that don't
1089 * reocgnise them and set the Partial bit.
1090 */
1091 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1092 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1093 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1094
Paul Jakma683f2b82012-03-23 14:58:45 +00001095 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001096 == attr_flags_values[attr_code])
1097 return 0;
1098
Paul Jakma835315b2012-01-18 12:28:30 +00001099 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001100 return 1;
1101}
1102
paul718e3742002-12-13 20:15:29 +00001103/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001104static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001105bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001106{
Paul Jakma835315b2012-01-18 12:28:30 +00001107 struct peer *const peer = args->peer;
1108 struct attr *const attr = args->attr;
1109 const bgp_size_t length = args->length;
1110
paul718e3742002-12-13 20:15:29 +00001111 /* If any recognized attribute has Attribute Length that conflicts
1112 with the expected length (based on the attribute type code), then
1113 the Error Subcode is set to Attribute Length Error. The Data
1114 field contains the erroneous attribute (type, length and
1115 value). */
1116 if (length != 1)
1117 {
1118 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1119 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001120 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001121 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001122 args->total);
paul718e3742002-12-13 20:15:29 +00001123 }
1124
1125 /* Fetch origin attribute. */
1126 attr->origin = stream_getc (BGP_INPUT (peer));
1127
1128 /* If the ORIGIN attribute has an undefined value, then the Error
1129 Subcode is set to Invalid Origin Attribute. The Data field
1130 contains the unrecognized attribute (type, length and value). */
1131 if ((attr->origin != BGP_ORIGIN_IGP)
1132 && (attr->origin != BGP_ORIGIN_EGP)
1133 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1134 {
1135 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1136 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001137 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001138 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001139 args->total);
paul718e3742002-12-13 20:15:29 +00001140 }
1141
1142 /* Set oring attribute flag. */
1143 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1144
1145 return 0;
1146}
Paul Jakmaab005292010-11-27 22:48:34 +00001147
1148/* Parse AS path information. This function is wrapper of
1149 aspath_parse. */
1150static int
Paul Jakma835315b2012-01-18 12:28:30 +00001151bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001152{
Paul Jakma835315b2012-01-18 12:28:30 +00001153 struct attr *const attr = args->attr;
1154 struct peer *const peer = args->peer;
1155 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001156
Paul Jakmaab005292010-11-27 22:48:34 +00001157 /*
1158 * peer with AS4 => will get 4Byte ASnums
1159 * otherwise, will get 16 Bit
1160 */
1161 attr->aspath = aspath_parse (peer->ibuf, length,
1162 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1163
1164 /* In case of IBGP, length will be zero. */
1165 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001166 {
Paul Jakmab881c702010-11-23 16:35:42 +00001167 zlog (peer->log, LOG_ERR,
1168 "Malformed AS path from %s, length is %d",
1169 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001170 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001171 }
Chris Hallcddb8112010-08-09 22:31:37 +04001172
Paul Jakmaab005292010-11-27 22:48:34 +00001173 /* Set aspath attribute flag. */
1174 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001175
Paul Jakmab881c702010-11-23 16:35:42 +00001176 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001177}
1178
Paul Jakmab881c702010-11-23 16:35:42 +00001179static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001180bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001181{
1182 /* These checks were part of bgp_attr_aspath, but with
1183 * as4 we should to check aspath things when
1184 * aspath synthesizing with as4_path has already taken place.
1185 * Otherwise we check ASPATH and use the synthesized thing, and that is
1186 * not right.
1187 * So do the checks later, i.e. here
1188 */
1189 struct bgp *bgp = peer->bgp;
1190 struct aspath *aspath;
1191
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001192 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001193 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1194 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001195 {
1196 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001197 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1198 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1199 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001200 }
1201
paul718e3742002-12-13 20:15:29 +00001202 /* First AS check for EBGP. */
1203 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1204 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001205 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001206 && ! aspath_firstas_check (attr->aspath, peer->as))
1207 {
1208 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001209 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001210 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1211 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1212 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001213 }
1214 }
1215
1216 /* local-as prepend */
1217 if (peer->change_local_as &&
1218 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1219 {
1220 aspath = aspath_dup (attr->aspath);
1221 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001222 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001223 attr->aspath = aspath_intern (aspath);
1224 }
1225
Paul Jakmab881c702010-11-23 16:35:42 +00001226 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001227}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001228
Paul Jakmaab005292010-11-27 22:48:34 +00001229/* Parse AS4 path information. This function is another wrapper of
1230 aspath_parse. */
1231static int
Paul Jakma835315b2012-01-18 12:28:30 +00001232bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001233{
Paul Jakma835315b2012-01-18 12:28:30 +00001234 struct peer *const peer = args->peer;
1235 struct attr *const attr = args->attr;
1236 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001237
Paul Jakmaab005292010-11-27 22:48:34 +00001238 *as4_path = aspath_parse (peer->ibuf, length, 1);
1239
Paul Jakmab881c702010-11-23 16:35:42 +00001240 /* In case of IBGP, length will be zero. */
1241 if (!*as4_path)
1242 {
1243 zlog (peer->log, LOG_ERR,
1244 "Malformed AS4 path from %s, length is %d",
1245 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001246 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001247 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001248 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001249 }
1250
Paul Jakmaab005292010-11-27 22:48:34 +00001251 /* Set aspath attribute flag. */
1252 if (as4_path)
1253 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1254
Paul Jakmab881c702010-11-23 16:35:42 +00001255 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001256}
1257
paul718e3742002-12-13 20:15:29 +00001258/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001259static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001260bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001261{
Paul Jakma835315b2012-01-18 12:28:30 +00001262 struct peer *const peer = args->peer;
1263 struct attr *const attr = args->attr;
1264 const bgp_size_t length = args->length;
1265
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001266 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001267
paul718e3742002-12-13 20:15:29 +00001268 /* Check nexthop attribute length. */
1269 if (length != 4)
1270 {
1271 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1272 length);
1273
Paul Jakma835315b2012-01-18 12:28:30 +00001274 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001275 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001276 args->total);
paul718e3742002-12-13 20:15:29 +00001277 }
1278
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001279 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1280 attribute must result in a NOTIFICATION message (this is implemented below).
1281 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1282 logged locally (this is implemented somewhere else). The UPDATE message
1283 gets ignored in any of these cases. */
1284 nexthop_n = stream_get_ipv4 (peer->ibuf);
1285 nexthop_h = ntohl (nexthop_n);
Lou Bergerf53585d2016-05-17 07:10:36 -04001286 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1287 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001288 {
1289 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001290 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001291 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001292 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001293 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001294 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001295 }
1296
1297 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001298 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1299
Paul Jakmab881c702010-11-23 16:35:42 +00001300 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001301}
1302
1303/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001304static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001305bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001306{
Paul Jakma835315b2012-01-18 12:28:30 +00001307 struct peer *const peer = args->peer;
1308 struct attr *const attr = args->attr;
1309 const bgp_size_t length = args->length;
1310
paul718e3742002-12-13 20:15:29 +00001311 /* Length check. */
1312 if (length != 4)
1313 {
1314 zlog (peer->log, LOG_ERR,
1315 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001316
Paul Jakma835315b2012-01-18 12:28:30 +00001317 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001318 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001319 args->total);
paul718e3742002-12-13 20:15:29 +00001320 }
1321
1322 attr->med = stream_getl (peer->ibuf);
1323
1324 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1325
Paul Jakmab881c702010-11-23 16:35:42 +00001326 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001327}
1328
1329/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001330static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001331bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001332{
Paul Jakma835315b2012-01-18 12:28:30 +00001333 struct peer *const peer = args->peer;
1334 struct attr *const attr = args->attr;
1335 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001336
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001337 /* Length check. */
1338 if (length != 4)
1339 {
Paul Jakma835315b2012-01-18 12:28:30 +00001340 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1341 length);
1342 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001343 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001344 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001345 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001346
paul718e3742002-12-13 20:15:29 +00001347 /* If it is contained in an UPDATE message that is received from an
1348 external peer, then this attribute MUST be ignored by the
1349 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001350 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001351 {
paul9985f832005-02-09 15:51:56 +00001352 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001353 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001354 }
1355
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001356 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001357
1358 /* Set atomic aggregate flag. */
1359 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1360
Paul Jakmab881c702010-11-23 16:35:42 +00001361 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001362}
1363
1364/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001365static int
Paul Jakma835315b2012-01-18 12:28:30 +00001366bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001367{
Paul Jakma835315b2012-01-18 12:28:30 +00001368 struct peer *const peer = args->peer;
1369 struct attr *const attr = args->attr;
1370 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001371
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001372 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001373 if (length != 0)
1374 {
Paul Jakma835315b2012-01-18 12:28:30 +00001375 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1376 length);
1377 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001378 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001379 args->total);
paul718e3742002-12-13 20:15:29 +00001380 }
1381
1382 /* Set atomic aggregate flag. */
1383 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1384
Paul Jakmab881c702010-11-23 16:35:42 +00001385 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001386}
1387
1388/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001389static int
Paul Jakma835315b2012-01-18 12:28:30 +00001390bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001391{
Paul Jakma835315b2012-01-18 12:28:30 +00001392 struct peer *const peer = args->peer;
1393 struct attr *const attr = args->attr;
1394 const bgp_size_t length = args->length;
1395
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001396 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001397 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001398
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001399 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001400 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001401 wantedlen = 8;
1402
1403 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001404 {
Paul Jakma835315b2012-01-18 12:28:30 +00001405 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1406 wantedlen, length);
1407 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001408 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001409 args->total);
paul718e3742002-12-13 20:15:29 +00001410 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001411
1412 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1413 attre->aggregator_as = stream_getl (peer->ibuf);
1414 else
1415 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001416 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001417
1418 /* Set atomic aggregate flag. */
1419 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1420
Paul Jakmab881c702010-11-23 16:35:42 +00001421 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001422}
1423
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001424/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001425static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001426bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1427 as_t *as4_aggregator_as,
1428 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001429{
Paul Jakma835315b2012-01-18 12:28:30 +00001430 struct peer *const peer = args->peer;
1431 struct attr *const attr = args->attr;
1432 const bgp_size_t length = args->length;
1433
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001434 if (length != 8)
1435 {
Paul Jakma835315b2012-01-18 12:28:30 +00001436 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1437 length);
1438 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001439 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001440 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001441 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001442
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001443 *as4_aggregator_as = stream_getl (peer->ibuf);
1444 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1445
1446 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1447
Paul Jakmab881c702010-11-23 16:35:42 +00001448 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001449}
1450
1451/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1452 */
Paul Jakmab881c702010-11-23 16:35:42 +00001453static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001454bgp_attr_munge_as4_attrs (struct peer *const peer,
1455 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001456 struct aspath *as4_path, as_t as4_aggregator,
1457 struct in_addr *as4_aggregator_addr)
1458{
1459 int ignore_as4_path = 0;
1460 struct aspath *newpath;
1461 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001462
1463 if (!attr->aspath)
1464 {
1465 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1466 * checked that all well-known, mandatory attributes were present.
1467 *
1468 * Can only be a problem with peer itself - hard error
1469 */
1470 return BGP_ATTR_PARSE_ERROR;
1471 }
1472
Paul Jakmab881c702010-11-23 16:35:42 +00001473 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001474 {
1475 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1476 * if given.
1477 * It is worth a warning though, because the peer really
1478 * should not send them
1479 */
1480 if (BGP_DEBUG(as4, AS4))
1481 {
1482 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1483 zlog_debug ("[AS4] %s %s AS4_PATH",
1484 peer->host, "AS4 capable peer, yet it sent");
1485
1486 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1487 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1488 peer->host, "AS4 capable peer, yet it sent");
1489 }
1490
Paul Jakmab881c702010-11-23 16:35:42 +00001491 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001492 }
1493
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001494 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1495 * because that may override AS4_PATH
1496 */
1497 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1498 {
Paul Jakmab881c702010-11-23 16:35:42 +00001499 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001500 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001501 assert (attre);
1502
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001503 /* received both.
1504 * if the as_number in aggregator is not AS_TRANS,
1505 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1506 * and the Aggregator shall be taken as
1507 * info on the aggregating node, and the AS_PATH
1508 * shall be taken as the AS_PATH
1509 * otherwise
1510 * the Aggregator shall be ignored and the
1511 * AS4_AGGREGATOR shall be taken as the
1512 * Aggregating node and the AS_PATH is to be
1513 * constructed "as in all other cases"
1514 */
Paul Jakmab881c702010-11-23 16:35:42 +00001515 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001516 {
1517 /* ignore */
1518 if ( BGP_DEBUG(as4, AS4))
1519 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1520 " send AGGREGATOR != AS_TRANS and"
1521 " AS4_AGGREGATOR, so ignore"
1522 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1523 ignore_as4_path = 1;
1524 }
1525 else
1526 {
1527 /* "New_aggregator shall be taken as aggregator" */
1528 attre->aggregator_as = as4_aggregator;
1529 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1530 }
1531 }
1532 else
1533 {
1534 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1535 * That is bogus - but reading the conditions
1536 * we have to handle AS4_AGGREGATOR as if it were
1537 * AGGREGATOR in that case
1538 */
1539 if ( BGP_DEBUG(as4, AS4))
1540 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1541 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1542 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001543 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001544 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1545 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1546 }
1547 }
1548
1549 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001550 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001551 {
Paul Jakma055086f2014-09-23 15:23:01 +01001552 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1553 aspath_unintern (&attr->aspath);
1554 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001555 }
Paul Jakmab881c702010-11-23 16:35:42 +00001556 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001557}
1558
paul718e3742002-12-13 20:15:29 +00001559/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001560static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001561bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001562{
Paul Jakma835315b2012-01-18 12:28:30 +00001563 struct peer *const peer = args->peer;
1564 struct attr *const attr = args->attr;
1565 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001566
paul718e3742002-12-13 20:15:29 +00001567 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001568 {
1569 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001570 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001571 }
Paul Jakma0c466382010-12-05 17:17:26 +00001572
1573 attr->community =
1574 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1575
1576 /* XXX: fix community_parse to use stream API and remove this */
1577 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001578
Paul Jakma0c466382010-12-05 17:17:26 +00001579 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001580 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001581 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001582 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001583
paul718e3742002-12-13 20:15:29 +00001584 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1585
Paul Jakmab881c702010-11-23 16:35:42 +00001586 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001587}
1588
1589/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001590static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001591bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001592{
Paul Jakma835315b2012-01-18 12:28:30 +00001593 struct peer *const peer = args->peer;
1594 struct attr *const attr = args->attr;
1595 const bgp_size_t length = args->length;
1596
Denis Ovsienkod595b562011-09-30 15:08:54 +04001597 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001598 if (length != 4)
1599 {
1600 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1601
Paul Jakma835315b2012-01-18 12:28:30 +00001602 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001603 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001604 args->total);
paul718e3742002-12-13 20:15:29 +00001605 }
1606
Paul Jakmafb982c22007-05-04 20:15:47 +00001607 (bgp_attr_extra_get (attr))->originator_id.s_addr
1608 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001609
1610 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1611
Paul Jakmab881c702010-11-23 16:35:42 +00001612 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001613}
1614
1615/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001616static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001617bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001618{
Paul Jakma835315b2012-01-18 12:28:30 +00001619 struct peer *const peer = args->peer;
1620 struct attr *const attr = args->attr;
1621 const bgp_size_t length = args->length;
1622
paul718e3742002-12-13 20:15:29 +00001623 /* Check length. */
1624 if (length % 4)
1625 {
1626 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1627
Paul Jakma835315b2012-01-18 12:28:30 +00001628 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1629 args->total);
paul718e3742002-12-13 20:15:29 +00001630 }
1631
Paul Jakmafb982c22007-05-04 20:15:47 +00001632 (bgp_attr_extra_get (attr))->cluster
1633 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001634
1635 /* XXX: Fix cluster_parse to use stream API and then remove this */
1636 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001637
1638 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1639
Paul Jakmab881c702010-11-23 16:35:42 +00001640 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001641}
1642
1643/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001644int
Paul Jakma835315b2012-01-18 12:28:30 +00001645bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1646 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001647{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001648 afi_t afi;
1649 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001650 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001651 size_t start;
paul718e3742002-12-13 20:15:29 +00001652 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001653 struct peer *const peer = args->peer;
1654 struct attr *const attr = args->attr;
1655 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001656 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001657
paul718e3742002-12-13 20:15:29 +00001658 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001659 s = BGP_INPUT(peer);
1660 start = stream_get_getp(s);
1661
1662 /* safe to read statically sized header? */
1663#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001664#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001665 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001666 {
1667 zlog_info ("%s: %s sent invalid length, %lu",
1668 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001669 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001670 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001671
paul718e3742002-12-13 20:15:29 +00001672 /* Load AFI, SAFI. */
1673 afi = stream_getw (s);
1674 safi = stream_getc (s);
1675
1676 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001677 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001678
Paul Jakma03292802008-06-07 20:37:10 +00001679 if (LEN_LEFT < attre->mp_nexthop_len)
1680 {
1681 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1682 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001683 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001684 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001685
paul718e3742002-12-13 20:15:29 +00001686 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001687 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001688 {
1689 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001690 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001691 /* Probably needed for RFC 2283 */
1692 if (attr->nexthop.s_addr == 0)
1693 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001694 break;
1695 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001696 stream_getl (s); /* RD high */
1697 stream_getl (s); /* RD low */
1698 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001699 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001700 case 24:
1701 {
1702 u_int32_t rd_high __attribute__((unused));
1703 u_int32_t rd_low __attribute__((unused));
1704
1705 rd_high = stream_getl (s);
1706 rd_low = stream_getl (s);
1707 }
1708 /* fall through */
paul718e3742002-12-13 20:15:29 +00001709 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001710 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001711 break;
1712 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001713 case 48:
1714 if (attre->mp_nexthop_len == 48) {
1715 u_int32_t rd_high __attribute__((unused));
1716 u_int32_t rd_low __attribute__((unused));
1717
1718 rd_high = stream_getl (s);
1719 rd_low = stream_getl (s);
1720 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001721 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001722
1723 if (attre->mp_nexthop_len == 48) {
1724 u_int32_t rd_high __attribute__((unused));
1725 u_int32_t rd_low __attribute__((unused));
1726
1727 rd_high = stream_getl (s);
1728 rd_low = stream_getl (s);
1729 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001730 stream_get (&attre->mp_nexthop_local, s, 16);
1731 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001732 {
1733 char buf1[INET6_ADDRSTRLEN];
1734 char buf2[INET6_ADDRSTRLEN];
1735
1736 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001737 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
Paul Jakmafb982c22007-05-04 20:15:47 +00001738 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001739 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001740 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001741 buf2, INET6_ADDRSTRLEN));
1742
Paul Jakmafb982c22007-05-04 20:15:47 +00001743 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001744 }
1745 break;
paul718e3742002-12-13 20:15:29 +00001746 default:
Paul Jakma03292802008-06-07 20:37:10 +00001747 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1748 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001749 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001750 }
1751
Paul Jakma03292802008-06-07 20:37:10 +00001752 if (!LEN_LEFT)
1753 {
1754 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1755 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001756 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001757 }
paul718e3742002-12-13 20:15:29 +00001758
Paul Jakma6e4ab122007-04-10 19:36:48 +00001759 {
1760 u_char val;
1761 if ((val = stream_getc (s)))
1762 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1763 peer->host, val);
1764 }
1765
1766 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001767 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001768 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001769 {
1770 zlog_info ("%s: (%s) Failed to read NLRI",
1771 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001772 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001773 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001774
paul718e3742002-12-13 20:15:29 +00001775 mp_update->afi = afi;
1776 mp_update->safi = safi;
1777 mp_update->nlri = stream_pnt (s);
1778 mp_update->length = nlri_len;
1779
paul9985f832005-02-09 15:51:56 +00001780 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001781
David Lamparterdaefeb82014-12-08 17:42:12 +01001782 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1783
Paul Jakmab881c702010-11-23 16:35:42 +00001784 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001785#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001786}
1787
1788/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001789int
Paul Jakma835315b2012-01-18 12:28:30 +00001790bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001791 struct bgp_nlri *mp_withdraw)
1792{
1793 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001794 afi_t afi;
1795 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001796 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001797 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001798 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001799 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001800
1801 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001802
1803#define BGP_MP_UNREACH_MIN_SIZE 3
1804 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001805 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001806
paul718e3742002-12-13 20:15:29 +00001807 afi = stream_getw (s);
1808 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001809
1810 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001811
paul718e3742002-12-13 20:15:29 +00001812 mp_withdraw->afi = afi;
1813 mp_withdraw->safi = safi;
1814 mp_withdraw->nlri = stream_pnt (s);
1815 mp_withdraw->length = withdraw_len;
1816
paul9985f832005-02-09 15:51:56 +00001817 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001818
David Lamparterdaefeb82014-12-08 17:42:12 +01001819 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1820
Paul Jakmab881c702010-11-23 16:35:42 +00001821 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001822}
1823
Job Snijders3334bab2017-01-20 14:47:12 +00001824/* Large Community attribute. */
1825static bgp_attr_parse_ret_t
1826bgp_attr_large_community (struct bgp_attr_parser_args *args)
1827{
1828 struct peer *const peer = args->peer;
1829 struct attr *const attr = args->attr;
1830 const bgp_size_t length = args->length;
1831
1832 if (length == 0)
1833 {
1834 if (attr->extra)
1835 attr->extra->lcommunity = NULL;
1836 /* Empty extcomm doesn't seem to be invalid per se */
1837 return BGP_ATTR_PARSE_PROCEED;
1838 }
1839
1840 (bgp_attr_extra_get (attr))->lcommunity =
1841 lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1842 /* XXX: fix ecommunity_parse to use stream API */
1843 stream_forward_getp (peer->ibuf, length);
1844
1845 if (attr->extra && !attr->extra->lcommunity)
1846 return bgp_attr_malformed (args,
1847 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1848 args->total);
1849
1850 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
1851
1852 return BGP_ATTR_PARSE_PROCEED;
1853}
1854
paul718e3742002-12-13 20:15:29 +00001855/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001856static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001857bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001858{
Paul Jakma835315b2012-01-18 12:28:30 +00001859 struct peer *const peer = args->peer;
1860 struct attr *const attr = args->attr;
1861 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001862
paul718e3742002-12-13 20:15:29 +00001863 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001864 {
1865 if (attr->extra)
1866 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001867 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001868 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001869 }
Paul Jakma0c466382010-12-05 17:17:26 +00001870
1871 (bgp_attr_extra_get (attr))->ecommunity =
1872 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1873 /* XXX: fix ecommunity_parse to use stream API */
1874 stream_forward_getp (peer->ibuf, length);
1875
Job Snijders3334bab2017-01-20 14:47:12 +00001876 if (attr->extra && !attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001877 return bgp_attr_malformed (args,
1878 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1879 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001880
paul718e3742002-12-13 20:15:29 +00001881 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1882
Paul Jakmab881c702010-11-23 16:35:42 +00001883 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001884}
1885
Lou Bergerc3741782016-01-12 13:42:01 -05001886/* Parse Tunnel Encap attribute in an UPDATE */
1887static int
1888bgp_attr_encap(
1889 uint8_t type,
1890 struct peer *peer, /* IN */
1891 bgp_size_t length, /* IN: attr's length field */
1892 struct attr *attr, /* IN: caller already allocated */
1893 u_char flag, /* IN: attr's flags field */
1894 u_char *startp)
1895{
1896 bgp_size_t total;
1897 struct attr_extra *attre = NULL;
1898 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1899 uint16_t tunneltype;
1900
1901 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1902
1903 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1904 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1905 {
1906 zlog (peer->log, LOG_ERR,
1907 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1908 bgp_notify_send_with_data (peer,
1909 BGP_NOTIFY_UPDATE_ERR,
1910 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1911 startp, total);
1912 return -1;
1913 }
1914
1915 if (BGP_ATTR_ENCAP == type) {
1916 /* read outer TLV type and length */
1917 uint16_t tlv_length;
1918
1919 if (length < 4) {
1920 zlog (peer->log, LOG_ERR,
1921 "Tunnel Encap attribute not long enough to contain outer T,L");
1922 bgp_notify_send_with_data(peer,
1923 BGP_NOTIFY_UPDATE_ERR,
1924 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1925 startp, total);
1926 return -1;
1927 }
1928 tunneltype = stream_getw (BGP_INPUT (peer));
1929 tlv_length = stream_getw (BGP_INPUT (peer));
1930 length -= 4;
1931
1932 if (tlv_length != length) {
1933 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1934 __func__, tlv_length, length);
1935 }
1936 }
1937
1938 while (length >= 4) {
Donald Sharp985c3552016-03-10 20:16:47 -05001939 uint16_t subtype = 0;
1940 uint16_t sublength = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05001941 struct bgp_attr_encap_subtlv *tlv;
1942
Lou Berger298cc2f2016-01-12 13:42:02 -05001943 if (BGP_ATTR_ENCAP == type) {
1944 subtype = stream_getc (BGP_INPUT (peer));
1945 sublength = stream_getc (BGP_INPUT (peer));
1946 length -= 2;
1947 }
Lou Bergerc3741782016-01-12 13:42:01 -05001948
1949 if (sublength > length) {
1950 zlog (peer->log, LOG_ERR,
1951 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1952 sublength, length);
1953 bgp_notify_send_with_data (peer,
1954 BGP_NOTIFY_UPDATE_ERR,
1955 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1956 startp, total);
1957 return -1;
1958 }
1959
1960 /* alloc and copy sub-tlv */
1961 /* TBD make sure these are freed when attributes are released */
1962 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1963 tlv->type = subtype;
1964 tlv->length = sublength;
1965 stream_get(tlv->value, peer->ibuf, sublength);
1966 length -= sublength;
1967
1968 /* attach tlv to encap chain */
1969 if (!attre) {
1970 attre = bgp_attr_extra_get(attr);
1971 if (BGP_ATTR_ENCAP == type) {
1972 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1973 stlv_last = stlv_last->next);
1974 if (stlv_last) {
1975 stlv_last->next = tlv;
1976 } else {
1977 attre->encap_subtlvs = tlv;
1978 }
1979 }
1980 } else {
1981 stlv_last->next = tlv;
1982 }
1983 stlv_last = tlv;
1984 }
1985
1986 if (attre && (BGP_ATTR_ENCAP == type)) {
1987 attre->encap_tunneltype = tunneltype;
1988 }
1989
1990 if (length) {
1991 /* spurious leftover data */
1992 zlog (peer->log, LOG_ERR,
1993 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1994 bgp_notify_send_with_data (peer,
1995 BGP_NOTIFY_UPDATE_ERR,
1996 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1997 startp, total);
1998 return -1;
1999 }
2000
2001 return 0;
2002}
2003
paul718e3742002-12-13 20:15:29 +00002004/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00002005static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00002006bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00002007{
Paul Jakma8794e8d2012-02-13 13:53:07 +00002008 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00002009 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00002010 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00002011 struct peer *const peer = args->peer;
2012 struct attr *const attr = args->attr;
2013 u_char *const startp = args->startp;
2014 const u_char type = args->type;
2015 const u_char flag = args->flags;
2016 const bgp_size_t length = args->length;
2017
paul718e3742002-12-13 20:15:29 +00002018
hassof4184462005-02-01 20:13:16 +00002019 if (BGP_DEBUG (normal, NORMAL))
2020 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
2021 peer->host, type, length);
2022
paul718e3742002-12-13 20:15:29 +00002023 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00002024 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00002025 "Unknown attribute type %d length %d is received", type, length);
2026
2027 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00002028 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00002029
paul718e3742002-12-13 20:15:29 +00002030 /* If any of the mandatory well-known attributes are not recognized,
2031 then the Error Subcode is set to Unrecognized Well-known
2032 Attribute. The Data field contains the unrecognized attribute
2033 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00002034 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00002035 {
Paul Jakma835315b2012-01-18 12:28:30 +00002036 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00002037 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00002038 args->total);
paul718e3742002-12-13 20:15:29 +00002039 }
2040
2041 /* Unrecognized non-transitive optional attributes must be quietly
2042 ignored and not passed along to other BGP peers. */
2043 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00002044 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002045
2046 /* If a path with recognized transitive optional attribute is
2047 accepted and passed along to other BGP peers and the Partial bit
2048 in the Attribute Flags octet is set to 1 by some previous AS, it
2049 is not set back to 0 by the current AS. */
2050 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2051
2052 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002053 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07002054 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00002055
Paul Jakmafb982c22007-05-04 20:15:47 +00002056 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00002057
2058 if (transit->val)
2059 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2060 transit->length + total);
2061 else
2062 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2063
2064 memcpy (transit->val + transit->length, startp, total);
2065 transit->length += total;
2066
Paul Jakmab881c702010-11-23 16:35:42 +00002067 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002068}
2069
Paul Jakma055086f2014-09-23 15:23:01 +01002070/* Well-known attribute check. */
2071static int
2072bgp_attr_check (struct peer *peer, struct attr *attr)
2073{
2074 u_char type = 0;
2075
Paul Jakmaaed1b552014-10-21 16:59:01 +01002076 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2077 * empty UPDATE. */
2078 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2079 return BGP_ATTR_PARSE_PROCEED;
2080
2081 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2082 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2083 are present, it should. Check for any other attribute being present
2084 instead.
2085 */
2086 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2087 return BGP_ATTR_PARSE_PROCEED;
2088
Paul Jakma055086f2014-09-23 15:23:01 +01002089 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2090 type = BGP_ATTR_ORIGIN;
2091
2092 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2093 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002094
2095 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2096 * NLRI is empty. We can't easily check NLRI empty here though.
2097 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002098 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2099 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002100 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002101
Paul Jakma055086f2014-09-23 15:23:01 +01002102 if (peer->sort == BGP_PEER_IBGP
2103 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2104 type = BGP_ATTR_LOCAL_PREF;
2105
2106 if (type)
2107 {
2108 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002109 "%s Missing well-known attribute %d / %s",
2110 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002111 bgp_notify_send_with_data (peer,
2112 BGP_NOTIFY_UPDATE_ERR,
2113 BGP_NOTIFY_UPDATE_MISS_ATTR,
2114 &type, 1);
2115 return BGP_ATTR_PARSE_ERROR;
2116 }
2117 return BGP_ATTR_PARSE_PROCEED;
2118}
2119
paul718e3742002-12-13 20:15:29 +00002120/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002121 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002122bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002123bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2124 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2125{
2126 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002127 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002128 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002129 bgp_size_t length;
2130 u_char *startp, *endp;
2131 u_char *attr_endp;
2132 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002133 /* we need the as4_path only until we have synthesized the as_path with it */
2134 /* same goes for as4_aggregator */
2135 struct aspath *as4_path = NULL;
2136 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002137 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002138
2139 /* Initialize bitmap. */
2140 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2141
2142 /* End pointer of BGP attribute. */
2143 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002144
paul718e3742002-12-13 20:15:29 +00002145 /* Get attributes to the end of attribute length. */
2146 while (BGP_INPUT_PNT (peer) < endp)
2147 {
2148 /* Check remaining length check.*/
2149 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2150 {
gdtc29fdba2004-12-09 14:46:46 +00002151 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002152 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002153 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002154 peer->host,
2155 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002156
2157 bgp_notify_send (peer,
2158 BGP_NOTIFY_UPDATE_ERR,
2159 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002160 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002161 }
2162
2163 /* Fetch attribute flag and type. */
2164 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002165 /* "The lower-order four bits of the Attribute Flags octet are
2166 unused. They MUST be zero when sent and MUST be ignored when
2167 received." */
2168 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002169 type = stream_getc (BGP_INPUT (peer));
2170
Paul Jakma370b64a2007-12-22 16:49:52 +00002171 /* Check whether Extended-Length applies and is in bounds */
2172 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2173 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2174 {
2175 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002176 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002177 peer->host,
2178 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2179
2180 bgp_notify_send (peer,
2181 BGP_NOTIFY_UPDATE_ERR,
2182 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002183 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002184 }
Paul Jakma835315b2012-01-18 12:28:30 +00002185
paul718e3742002-12-13 20:15:29 +00002186 /* Check extended attribue length bit. */
2187 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2188 length = stream_getw (BGP_INPUT (peer));
2189 else
2190 length = stream_getc (BGP_INPUT (peer));
2191
2192 /* If any attribute appears more than once in the UPDATE
2193 message, then the Error Subcode is set to Malformed Attribute
2194 List. */
2195
2196 if (CHECK_BITMAP (seen, type))
2197 {
2198 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002199 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002200 peer->host, type);
2201
2202 bgp_notify_send (peer,
2203 BGP_NOTIFY_UPDATE_ERR,
2204 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002205 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002206 }
2207
2208 /* Set type to bitmap to check duplicate attribute. `type' is
2209 unsigned char so it never overflow bitmap range. */
2210
2211 SET_BITMAP (seen, type);
2212
2213 /* Overflow check. */
2214 attr_endp = BGP_INPUT_PNT (peer) + length;
2215
2216 if (attr_endp > endp)
2217 {
2218 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002219 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp);
Daniel Waltonc6969872015-05-19 18:03:43 -07002220 zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp);
2221 bgp_notify_send_with_data (peer,
2222 BGP_NOTIFY_UPDATE_ERR,
2223 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2224 startp, attr_endp - startp);
Paul Jakmab881c702010-11-23 16:35:42 +00002225 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002226 }
Paul Jakma835315b2012-01-18 12:28:30 +00002227
2228 struct bgp_attr_parser_args attr_args = {
2229 .peer = peer,
2230 .length = length,
2231 .attr = attr,
2232 .type = type,
2233 .flags = flag,
2234 .startp = startp,
2235 .total = attr_endp - startp,
2236 };
2237
2238
2239 /* If any recognized attribute has Attribute Flags that conflict
2240 with the Attribute Type Code, then the Error Subcode is set to
2241 Attribute Flags Error. The Data field contains the erroneous
2242 attribute (type, length and value). */
2243 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002244 {
2245 bgp_attr_parse_ret_t ret;
2246 ret = bgp_attr_malformed (&attr_args,
2247 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2248 attr_args.total);
2249 if (ret == BGP_ATTR_PARSE_PROCEED)
2250 continue;
2251 return ret;
2252 }
paul718e3742002-12-13 20:15:29 +00002253
2254 /* OK check attribute and store it's value. */
2255 switch (type)
2256 {
2257 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002258 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002259 break;
2260 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002261 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002262 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002263 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002264 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002265 break;
paul718e3742002-12-13 20:15:29 +00002266 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002267 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002268 break;
2269 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002270 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002271 break;
2272 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002273 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002274 break;
2275 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002276 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002277 break;
2278 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002279 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002280 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002281 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002282 ret = bgp_attr_as4_aggregator (&attr_args,
2283 &as4_aggregator,
2284 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002285 break;
paul718e3742002-12-13 20:15:29 +00002286 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002287 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002288 break;
Job Snijders3334bab2017-01-20 14:47:12 +00002289 case BGP_ATTR_LARGE_COMMUNITIES:
2290 ret = bgp_attr_large_community (&attr_args);
2291 break;
paul718e3742002-12-13 20:15:29 +00002292 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002293 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002294 break;
2295 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002296 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002297 break;
2298 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002299 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002300 break;
2301 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002302 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002303 break;
2304 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002305 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002306 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002307 case BGP_ATTR_ENCAP:
2308 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2309 break;
paul718e3742002-12-13 20:15:29 +00002310 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002311 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002312 break;
2313 }
Paul Jakmab881c702010-11-23 16:35:42 +00002314
David Lamparterf57000c2014-06-04 01:01:10 +02002315 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2316 {
2317 bgp_notify_send (peer,
2318 BGP_NOTIFY_UPDATE_ERR,
2319 BGP_NOTIFY_UPDATE_MAL_ATTR);
2320 ret = BGP_ATTR_PARSE_ERROR;
2321 }
2322
Paul Jakmab881c702010-11-23 16:35:42 +00002323 /* If hard error occured immediately return to the caller. */
2324 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002325 {
2326 zlog (peer->log, LOG_WARNING,
2327 "%s: Attribute %s, parse error",
2328 peer->host,
2329 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002330 if (as4_path)
2331 aspath_unintern (&as4_path);
2332 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002333 }
Paul Jakmab881c702010-11-23 16:35:42 +00002334 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2335 {
2336
2337 zlog (peer->log, LOG_WARNING,
2338 "%s: Attribute %s, parse error - treating as withdrawal",
2339 peer->host,
2340 LOOKUP (attr_str, type));
2341 if (as4_path)
2342 aspath_unintern (&as4_path);
2343 return ret;
2344 }
2345
paul718e3742002-12-13 20:15:29 +00002346 /* Check the fetched length. */
2347 if (BGP_INPUT_PNT (peer) != attr_endp)
2348 {
2349 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002350 "%s: BGP attribute %s, fetch error",
2351 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002352 bgp_notify_send (peer,
2353 BGP_NOTIFY_UPDATE_ERR,
2354 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002355 if (as4_path)
2356 aspath_unintern (&as4_path);
2357 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002358 }
2359 }
paul718e3742002-12-13 20:15:29 +00002360 /* Check final read pointer is same as end pointer. */
2361 if (BGP_INPUT_PNT (peer) != endp)
2362 {
2363 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002364 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002365 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002366 bgp_notify_send (peer,
2367 BGP_NOTIFY_UPDATE_ERR,
2368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002369 if (as4_path)
2370 aspath_unintern (&as4_path);
2371 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002372 }
Paul Jakma055086f2014-09-23 15:23:01 +01002373
2374 /* Check all mandatory well-known attributes are present */
2375 {
2376 bgp_attr_parse_ret_t ret;
2377 if ((ret = bgp_attr_check (peer, attr)) < 0)
2378 {
2379 if (as4_path)
2380 aspath_unintern (&as4_path);
2381 return ret;
2382 }
2383 }
2384
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002385 /*
2386 * At this place we can see whether we got AS4_PATH and/or
2387 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2388 * We can not do this before we've read all attributes because
2389 * the as4 handling does not say whether AS4_PATH has to be sent
2390 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2391 * in relationship to AGGREGATOR.
2392 * So, to be defensive, we are not relying on any order and read
2393 * all attributes first, including these 32bit ones, and now,
2394 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002395 *
2396 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2397 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002398 */
David Lamparterf57000c2014-06-04 01:01:10 +02002399 /* actually... this doesn't ever return failure currently, but
2400 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002401 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2402 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002403 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002404 {
David Lamparterf57000c2014-06-04 01:01:10 +02002405 bgp_notify_send (peer,
2406 BGP_NOTIFY_UPDATE_ERR,
2407 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002408 if (as4_path)
2409 aspath_unintern (&as4_path);
2410 return BGP_ATTR_PARSE_ERROR;
2411 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002412
2413 /* At this stage, we have done all fiddling with as4, and the
2414 * resulting info is in attr->aggregator resp. attr->aspath
2415 * so we can chuck as4_aggregator and as4_path alltogether in
2416 * order to save memory
2417 */
Paul Jakmab881c702010-11-23 16:35:42 +00002418 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002419 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002420 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002421 /* The flag that we got this is still there, but that does not
2422 * do any trouble
2423 */
2424 }
2425 /*
2426 * The "rest" of the code does nothing with as4_aggregator.
2427 * there is no memory attached specifically which is not part
2428 * of the attr.
2429 * so ignoring just means do nothing.
2430 */
2431 /*
2432 * Finally do the checks on the aspath we did not do yet
2433 * because we waited for a potentially synthesized aspath.
2434 */
Paul Jakmab881c702010-11-23 16:35:42 +00002435 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002436 {
Paul Jakma835315b2012-01-18 12:28:30 +00002437 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002438 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002439 return ret;
2440 }
2441
paul718e3742002-12-13 20:15:29 +00002442 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002443 if (attr->extra && attr->extra->transit)
2444 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002445
Paul Jakmab881c702010-11-23 16:35:42 +00002446 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002447}
2448
paul718e3742002-12-13 20:15:29 +00002449int stream_put_prefix (struct stream *, struct prefix *);
2450
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002451size_t
2452bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2453 struct attr *attr)
2454{
2455 size_t sizep;
2456
2457 /* Set extended bit always to encode the attribute length as 2 bytes */
2458 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2459 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2460 sizep = stream_get_endp (s);
2461 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002462
2463 stream_putw (s, afi);
2464 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002465
2466 /* Nexthop */
2467 switch (afi)
2468 {
2469 case AFI_IP:
2470 switch (safi)
2471 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002472 case SAFI_MULTICAST:
2473 stream_putc (s, 4);
2474 stream_put_ipv4 (s, attr->nexthop.s_addr);
2475 break;
2476 case SAFI_MPLS_VPN:
2477 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002478 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002479 stream_putl (s, 0);
2480 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2481 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002482 case SAFI_ENCAP:
2483 stream_putc (s, 4);
2484 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2485 break;
Lou Berger050defe2016-01-12 13:41:59 -05002486 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002487 default:
2488 break;
2489 }
2490 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002491 case AFI_IP6:
2492 switch (safi)
2493 {
2494 case SAFI_UNICAST:
2495 case SAFI_MULTICAST:
2496 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002497 struct attr_extra *attre = attr->extra;
2498
2499 assert (attr->extra);
2500 stream_putc (s, attre->mp_nexthop_len);
2501 stream_put (s, &attre->mp_nexthop_global, 16);
2502 if (attre->mp_nexthop_len == 32)
2503 stream_put (s, &attre->mp_nexthop_local, 16);
2504 }
Lou Berger050defe2016-01-12 13:41:59 -05002505 break;
2506 case SAFI_MPLS_VPN:
2507 {
2508 struct attr_extra *attre = attr->extra;
2509
2510 assert (attr->extra);
2511 if (attre->mp_nexthop_len == 16) {
2512 stream_putc (s, 24);
2513 stream_putl (s, 0); /* RD = 0, per RFC */
2514 stream_putl (s, 0);
2515 stream_put (s, &attre->mp_nexthop_global, 16);
2516 } else if (attre->mp_nexthop_len == 32) {
2517 stream_putc (s, 48);
2518 stream_putl (s, 0); /* RD = 0, per RFC */
2519 stream_putl (s, 0);
2520 stream_put (s, &attre->mp_nexthop_global, 16);
2521 stream_putl (s, 0); /* RD = 0, per RFC */
2522 stream_putl (s, 0);
2523 stream_put (s, &attre->mp_nexthop_local, 16);
2524 }
2525 }
2526 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002527 case SAFI_ENCAP:
2528 assert (attr->extra);
2529 stream_putc (s, 16);
2530 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2531 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002532 default:
2533 break;
2534 }
2535 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002536 default:
2537 break;
2538 }
2539
2540 /* SNPA */
2541 stream_putc (s, 0);
2542 return sizep;
2543}
2544
2545void
2546bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2547 struct prefix *p, struct prefix_rd *prd,
2548 u_char *tag)
2549{
Lou Berger050defe2016-01-12 13:41:59 -05002550 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002551 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002552 /* Tag, RD, Prefix write. */
2553 stream_putc (s, p->prefixlen + 88);
2554 stream_put (s, tag, 3);
2555 stream_put (s, prd->val, 8);
2556 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002557 }
Lou Berger050defe2016-01-12 13:41:59 -05002558 else
2559 stream_put_prefix (s, p);
2560}
2561
2562size_t
2563bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2564{
2565 int size = PSIZE (p->prefixlen);
2566 if (safi == SAFI_MPLS_VPN)
2567 size += 88;
2568 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002569}
2570
Lou Bergerc3741782016-01-12 13:42:01 -05002571/*
2572 * Encodes the tunnel encapsulation attribute
2573 */
2574static void
2575bgp_packet_mpattr_tea(
2576 struct bgp *bgp,
2577 struct peer *peer,
2578 struct stream *s,
2579 struct attr *attr,
2580 uint8_t attrtype)
2581{
2582 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002583 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002584 struct bgp_attr_encap_subtlv *subtlvs;
2585 struct bgp_attr_encap_subtlv *st;
2586 const char *attrname;
2587
2588 if (!attr || !attr->extra)
2589 return;
2590
2591 switch (attrtype) {
2592 case BGP_ATTR_ENCAP:
2593 attrname = "Tunnel Encap";
2594 subtlvs = attr->extra->encap_subtlvs;
2595
2596 /*
2597 * The tunnel encap attr has an "outer" tlv.
2598 * T = tunneltype,
2599 * L = total length of subtlvs,
2600 * V = concatenated subtlvs.
2601 */
2602 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002603 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002604 break;
2605
2606 default:
2607 assert(0);
2608 }
2609
2610
Lou Berger298cc2f2016-01-12 13:42:02 -05002611 /* if no tlvs, don't make attr */
2612 if (subtlvs == NULL)
2613 return;
2614
Lou Bergerc3741782016-01-12 13:42:01 -05002615 /* compute attr length */
2616 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002617 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002618 }
2619
Lou Bergerc3741782016-01-12 13:42:01 -05002620 if (attrlenfield > 0xffff) {
2621 zlog (peer->log, LOG_ERR,
2622 "%s attribute is too long (length=%d), can't send it",
2623 attrname,
2624 attrlenfield);
2625 return;
2626 }
2627
2628 if (attrlenfield > 0xff) {
2629 /* 2-octet length field */
2630 stream_putc (s,
2631 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2632 stream_putc (s, attrtype);
2633 stream_putw (s, attrlenfield & 0xffff);
2634 } else {
2635 /* 1-octet length field */
2636 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2637 stream_putc (s, attrtype);
2638 stream_putc (s, attrlenfield & 0xff);
2639 }
2640
2641 if (attrtype == BGP_ATTR_ENCAP) {
2642 /* write outer T+L */
2643 stream_putw(s, attr->extra->encap_tunneltype);
2644 stream_putw(s, attrlenfield - 4);
2645 }
2646
2647 /* write each sub-tlv */
2648 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002649 if (attrtype == BGP_ATTR_ENCAP) {
2650 stream_putc (s, st->type);
2651 stream_putc (s, st->length);
2652 }
Lou Bergerc3741782016-01-12 13:42:01 -05002653 stream_put (s, st->value, st->length);
2654 }
2655}
2656
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002657void
2658bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2659{
2660 /* Set MP attribute length. Don't count the (2) bytes used to encode
2661 the attr length */
2662 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2663}
2664
paul718e3742002-12-13 20:15:29 +00002665/* Make attribute packet. */
2666bgp_size_t
2667bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002668 struct stream *s, struct attr *attr,
2669 struct prefix *p, afi_t afi, safi_t safi,
2670 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002671{
paulfe69a502005-09-10 16:55:02 +00002672 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002673 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002674 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002675 int send_as4_path = 0;
2676 int send_as4_aggregator = 0;
2677 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002678
2679 if (! bgp)
2680 bgp = bgp_get_default ();
2681
2682 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002683 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002684
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002685 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2686 {
Lou Berger050defe2016-01-12 13:41:59 -05002687 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002688 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2689 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2690 bgp_packet_mpattr_end(s, mpattrlen_pos);
2691 }
2692
paul718e3742002-12-13 20:15:29 +00002693 /* Origin attribute. */
2694 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2695 stream_putc (s, BGP_ATTR_ORIGIN);
2696 stream_putc (s, 1);
2697 stream_putc (s, attr->origin);
2698
2699 /* AS path attribute. */
2700
2701 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002702 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002703 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002704 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002705 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002706 {
2707 aspath = aspath_dup (attr->aspath);
2708
2709 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2710 {
2711 /* Strip the confed info, and then stuff our path CONFED_ID
2712 on the front */
2713 aspath = aspath_delete_confed_seq (aspath);
2714 aspath = aspath_add_seq (aspath, bgp->confed_id);
2715 }
2716 else
2717 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002718 if (peer->change_local_as) {
2719 /* If replace-as is specified, we only use the change_local_as when
2720 advertising routes. */
2721 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2722 aspath = aspath_add_seq (aspath, peer->local_as);
2723 }
paul718e3742002-12-13 20:15:29 +00002724 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002725 } else {
2726 aspath = aspath_add_seq (aspath, peer->local_as);
2727 }
paul718e3742002-12-13 20:15:29 +00002728 }
2729 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002730 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002731 {
2732 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2733 aspath = aspath_dup (attr->aspath);
2734 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2735 }
2736 else
2737 aspath = attr->aspath;
2738
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002739 /* If peer is not AS4 capable, then:
2740 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2741 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2742 * types are in it (i.e. exclude them if they are there)
2743 * AND do this only if there is at least one asnum > 65535 in the path!
2744 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2745 * all ASnums > 65535 to BGP_AS_TRANS
2746 */
paul718e3742002-12-13 20:15:29 +00002747
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002748 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2749 stream_putc (s, BGP_ATTR_AS_PATH);
2750 aspath_sizep = stream_get_endp (s);
2751 stream_putw (s, 0);
2752 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2753
2754 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2755 * in the path
2756 */
2757 if (!use32bit && aspath_has_as4 (aspath))
2758 send_as4_path = 1; /* we'll do this later, at the correct place */
2759
paul718e3742002-12-13 20:15:29 +00002760 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002761 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2762 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002763 {
2764 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2765 stream_putc (s, BGP_ATTR_NEXT_HOP);
2766 stream_putc (s, 4);
2767 if (safi == SAFI_MPLS_VPN)
2768 {
2769 if (attr->nexthop.s_addr == 0)
2770 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2771 else
2772 stream_put_ipv4 (s, attr->nexthop.s_addr);
2773 }
2774 else
2775 stream_put_ipv4 (s, attr->nexthop.s_addr);
2776 }
2777
2778 /* MED attribute. */
2779 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2780 {
2781 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2782 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2783 stream_putc (s, 4);
2784 stream_putl (s, attr->med);
2785 }
2786
2787 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002788 if (peer->sort == BGP_PEER_IBGP ||
2789 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002790 {
2791 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2792 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2793 stream_putc (s, 4);
2794 stream_putl (s, attr->local_pref);
2795 }
2796
2797 /* Atomic aggregate. */
2798 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2799 {
2800 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2801 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2802 stream_putc (s, 0);
2803 }
2804
2805 /* Aggregator. */
2806 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2807 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002808 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002809
2810 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002811 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2812 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002813
2814 if (use32bit)
2815 {
2816 /* AS4 capable peer */
2817 stream_putc (s, 8);
2818 stream_putl (s, attr->extra->aggregator_as);
2819 }
2820 else
2821 {
2822 /* 2-byte AS peer */
2823 stream_putc (s, 6);
2824
2825 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2826 if ( attr->extra->aggregator_as > 65535 )
2827 {
2828 stream_putw (s, BGP_AS_TRANS);
2829
2830 /* we have to send AS4_AGGREGATOR, too.
2831 * we'll do that later in order to send attributes in ascending
2832 * order.
2833 */
2834 send_as4_aggregator = 1;
2835 }
2836 else
2837 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2838 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002839 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002840 }
2841
2842 /* Community attribute. */
2843 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2844 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2845 {
2846 if (attr->community->size * 4 > 255)
2847 {
2848 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2849 stream_putc (s, BGP_ATTR_COMMUNITIES);
2850 stream_putw (s, attr->community->size * 4);
2851 }
2852 else
2853 {
2854 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2855 stream_putc (s, BGP_ATTR_COMMUNITIES);
2856 stream_putc (s, attr->community->size * 4);
2857 }
2858 stream_put (s, attr->community->val, attr->community->size * 4);
2859 }
2860
Job Snijders3334bab2017-01-20 14:47:12 +00002861 /*
2862 * Large Community attribute.
2863 */
2864 if (attr->extra &&
2865 CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)
2866 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)))
2867 {
2868 if (attr->extra->lcommunity->size * 12 > 255)
2869 {
2870 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2871 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
2872 stream_putw (s, attr->extra->lcommunity->size * 12);
2873 }
2874 else
2875 {
2876 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2877 stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
2878 stream_putc (s, attr->extra->lcommunity->size * 12);
2879 }
2880 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
2881 }
2882
paul718e3742002-12-13 20:15:29 +00002883 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002884 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002885 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002886 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002887 {
2888 /* Originator ID. */
2889 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2890 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2891 stream_putc (s, 4);
2892
2893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002894 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002895 else
2896 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002897
2898 /* Cluster list. */
2899 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2900 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2901
Paul Jakma9eda90c2007-08-30 13:36:17 +00002902 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002903 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002904 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002905 /* If this peer configuration's parent BGP has cluster_id. */
2906 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2907 stream_put_in_addr (s, &bgp->cluster_id);
2908 else
2909 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002910 stream_put (s, attr->extra->cluster->list,
2911 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002912 }
2913 else
2914 {
2915 stream_putc (s, 4);
2916 /* If this peer configuration's parent BGP has cluster_id. */
2917 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2918 stream_put_in_addr (s, &bgp->cluster_id);
2919 else
2920 stream_put_in_addr (s, &bgp->router_id);
2921 }
2922 }
2923
paul718e3742002-12-13 20:15:29 +00002924 /* Extended Communities attribute. */
2925 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2926 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2927 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002928 struct attr_extra *attre = attr->extra;
2929
2930 assert (attre);
2931
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002932 if (peer->sort == BGP_PEER_IBGP
2933 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002934 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002935 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002936 {
2937 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2938 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002939 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002940 }
2941 else
2942 {
2943 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2944 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002945 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002946 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002947 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002948 }
2949 else
2950 {
paul5228ad22004-06-04 17:58:18 +00002951 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002952 int tbit;
2953 int ecom_tr_size = 0;
2954 int i;
2955
Paul Jakmafb982c22007-05-04 20:15:47 +00002956 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002957 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002958 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002959 tbit = *pnt;
2960
2961 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2962 continue;
2963
2964 ecom_tr_size++;
2965 }
2966
2967 if (ecom_tr_size)
2968 {
2969 if (ecom_tr_size * 8 > 255)
2970 {
2971 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2972 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2973 stream_putw (s, ecom_tr_size * 8);
2974 }
2975 else
2976 {
2977 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2978 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2979 stream_putc (s, ecom_tr_size * 8);
2980 }
2981
Paul Jakmafb982c22007-05-04 20:15:47 +00002982 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002983 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002984 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002985 tbit = *pnt;
2986
2987 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2988 continue;
2989
2990 stream_put (s, pnt, 8);
2991 }
2992 }
paul718e3742002-12-13 20:15:29 +00002993 }
paul718e3742002-12-13 20:15:29 +00002994 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002995
2996 if ( send_as4_path )
2997 {
2998 /* If the peer is NOT As4 capable, AND */
2999 /* there are ASnums > 65535 in path THEN
3000 * give out AS4_PATH */
3001
3002 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3003 * path segments!
3004 * Hm, I wonder... confederation things *should* only be at
3005 * the beginning of an aspath, right? Then we should use
3006 * aspath_delete_confed_seq for this, because it is already
3007 * there! (JK)
3008 * Folks, talk to me: what is reasonable here!?
3009 */
3010 aspath = aspath_delete_confed_seq (aspath);
3011
3012 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
3013 stream_putc (s, BGP_ATTR_AS4_PATH);
3014 aspath_sizep = stream_get_endp (s);
3015 stream_putw (s, 0);
3016 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
3017 }
3018
3019 if (aspath != attr->aspath)
3020 aspath_free (aspath);
3021
3022 if ( send_as4_aggregator )
3023 {
3024 assert (attr->extra);
3025
3026 /* send AS4_AGGREGATOR, at this place */
3027 /* this section of code moved here in order to ensure the correct
3028 * *ascending* order of attributes
3029 */
3030 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3031 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
3032 stream_putc (s, 8);
3033 stream_putl (s, attr->extra->aggregator_as);
3034 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
3035 }
Lou Berger298cc2f2016-01-12 13:42:02 -05003036
3037 if ((afi == AFI_IP || afi == AFI_IP6) &&
3038 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
3039 {
3040 /* Tunnel Encap attribute */
3041 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
3042 }
3043
paul718e3742002-12-13 20:15:29 +00003044 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00003045 if (attr->extra && attr->extra->transit)
3046 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00003047
3048 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003049 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00003050}
3051
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003052size_t
3053bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00003054{
paul718e3742002-12-13 20:15:29 +00003055 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00003056
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003057 /* Set extended bit always to encode the attribute length as 2 bytes */
3058 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00003059 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
3060
paul9985f832005-02-09 15:51:56 +00003061 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003062 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00003063
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003064 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05003065 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003066 return attrlen_pnt;
3067}
paul718e3742002-12-13 20:15:29 +00003068
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003069void
3070bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
3071 afi_t afi, safi_t safi, struct prefix_rd *prd,
3072 u_char *tag)
3073{
Lou Berger050defe2016-01-12 13:41:59 -05003074 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003075}
paul718e3742002-12-13 20:15:29 +00003076
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003077void
3078bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
3079{
Lou Berger050defe2016-01-12 13:41:59 -05003080 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00003081}
3082
3083/* Initialization of attribute. */
3084void
paulfe69a502005-09-10 16:55:02 +00003085bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00003086{
paul718e3742002-12-13 20:15:29 +00003087 aspath_init ();
3088 attrhash_init ();
3089 community_init ();
3090 ecommunity_init ();
Job Snijders3334bab2017-01-20 14:47:12 +00003091 lcommunity_init ();
paul718e3742002-12-13 20:15:29 +00003092 cluster_init ();
3093 transit_init ();
3094}
3095
Chris Caputo228da422009-07-18 05:44:03 +00003096void
3097bgp_attr_finish (void)
3098{
3099 aspath_finish ();
3100 attrhash_finish ();
3101 community_finish ();
3102 ecommunity_finish ();
Job Snijders3334bab2017-01-20 14:47:12 +00003103 lcommunity_finish ();
Chris Caputo228da422009-07-18 05:44:03 +00003104 cluster_finish ();
3105 transit_finish ();
3106}
3107
paul718e3742002-12-13 20:15:29 +00003108/* Make attribute packet. */
3109void
paula3845922003-10-18 01:30:50 +00003110bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3111 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003112{
3113 unsigned long cp;
3114 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003115 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003116 struct aspath *aspath;
3117
3118 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003119 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003120
3121 /* Place holder of length. */
3122 stream_putw (s, 0);
3123
3124 /* Origin attribute. */
3125 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3126 stream_putc (s, BGP_ATTR_ORIGIN);
3127 stream_putc (s, 1);
3128 stream_putc (s, attr->origin);
3129
3130 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003131
3132 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3133 stream_putc (s, BGP_ATTR_AS_PATH);
3134 aspath_lenp = stream_get_endp (s);
3135 stream_putw (s, 0);
3136
3137 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003138
3139 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003140 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3141 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003142 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003143 )
3144 {
3145 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3146 stream_putc (s, BGP_ATTR_NEXT_HOP);
3147 stream_putc (s, 4);
3148 stream_put_ipv4 (s, attr->nexthop.s_addr);
3149 }
paul718e3742002-12-13 20:15:29 +00003150
3151 /* MED attribute. */
3152 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3153 {
3154 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3155 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3156 stream_putc (s, 4);
3157 stream_putl (s, attr->med);
3158 }
3159
3160 /* Local preference. */
3161 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3162 {
3163 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3164 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3165 stream_putc (s, 4);
3166 stream_putl (s, attr->local_pref);
3167 }
3168
3169 /* Atomic aggregate. */
3170 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3171 {
3172 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3173 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3174 stream_putc (s, 0);
3175 }
3176
3177 /* Aggregator. */
3178 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3179 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003180 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003181 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3182 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003183 stream_putc (s, 8);
3184 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003185 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003186 }
3187
3188 /* Community attribute. */
3189 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3190 {
3191 if (attr->community->size * 4 > 255)
3192 {
3193 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3194 stream_putc (s, BGP_ATTR_COMMUNITIES);
3195 stream_putw (s, attr->community->size * 4);
3196 }
3197 else
3198 {
3199 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3200 stream_putc (s, BGP_ATTR_COMMUNITIES);
3201 stream_putc (s, attr->community->size * 4);
3202 }
3203 stream_put (s, attr->community->val, attr->community->size * 4);
3204 }
3205
Job Snijders3334bab2017-01-20 14:47:12 +00003206 /* Large Community attribute. */
3207 if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))
3208 {
3209 if (attr->extra->lcommunity->size * 12 > 255)
3210 {
3211 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3212 stream_putc (s, BGP_ATTR_COMMUNITIES);
3213 stream_putw (s, attr->extra->lcommunity->size * 12);
3214 }
3215 else
3216 {
3217 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3218 stream_putc (s, BGP_ATTR_COMMUNITIES);
3219 stream_putc (s, attr->extra->lcommunity->size * 12);
3220 }
3221
3222 stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3223 }
3224
paula3845922003-10-18 01:30:50 +00003225 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003226 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3227 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003228 {
3229 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003230 struct attr_extra *attre = attr->extra;
3231
paula3845922003-10-18 01:30:50 +00003232 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3233 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003234 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003235
3236 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003237 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003238 stream_putw(s, AFI_IP6); /* AFI */
3239 stream_putc(s, SAFI_UNICAST); /* SAFI */
3240
3241 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003242 stream_putc(s, attre->mp_nexthop_len);
3243 stream_put(s, &attre->mp_nexthop_global, 16);
3244 if (attre->mp_nexthop_len == 32)
3245 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003246
3247 /* SNPA */
3248 stream_putc(s, 0);
3249
3250 /* Prefix */
3251 stream_put_prefix(s, prefix);
3252
3253 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003254 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003255 }
paula3845922003-10-18 01:30:50 +00003256
paul718e3742002-12-13 20:15:29 +00003257 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003258 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003259 stream_putw_at (s, cp, len);
3260}