blob: 6aab50af4cfb75f714db3808fed85f593ac09548 [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"
Lou Bergerc3741782016-01-12 13:42:01 -050042#include "table.h"
43#include "bgp_encap_types.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020044
paul718e3742002-12-13 20:15:29 +000045/* Attribute strings for logging. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -070046static const struct message attr_str [] =
paul718e3742002-12-13 20:15:29 +000047{
48 { BGP_ATTR_ORIGIN, "ORIGIN" },
49 { BGP_ATTR_AS_PATH, "AS_PATH" },
50 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
51 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
52 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
53 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
54 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
55 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
56 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
Denis Ovsienkof8627ff2011-10-10 16:52:20 +040057 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
paul718e3742002-12-13 20:15:29 +000058 { BGP_ATTR_DPA, "DPA" },
59 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
60 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
61 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
62 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000063 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
64 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
65 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
66 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
Lou Bergerc3741782016-01-12 13:42:01 -050067 { BGP_ATTR_ENCAP, "ENCAP" },
paul718e3742002-12-13 20:15:29 +000068};
Balaji.G837d16c2012-09-26 14:09:10 +053069static const int attr_str_max = array_size(attr_str);
Denis Ovsienkoafcb7672011-10-23 22:32:44 +040070
71static const struct message attr_flag_str[] =
72{
73 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
74 { BGP_ATTR_FLAG_TRANS, "Transitive" },
75 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
76 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
77 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
78};
David Lamparter6b0655a2014-06-04 06:53:35 +020079
Stephen Hemminger9bddac42009-05-15 09:59:51 -070080static struct hash *cluster_hash;
paul718e3742002-12-13 20:15:29 +000081
paul94f2b392005-06-28 12:44:16 +000082static void *
Paul Jakma923de652007-04-29 18:25:17 +000083cluster_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +000084{
Paul Jakma923de652007-04-29 18:25:17 +000085 struct cluster_list * val = (struct cluster_list *) p;
paul718e3742002-12-13 20:15:29 +000086 struct cluster_list *cluster;
87
88 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
89 cluster->length = val->length;
90
91 if (cluster->length)
92 {
93 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
94 memcpy (cluster->list, val->list, val->length);
95 }
96 else
97 cluster->list = NULL;
98
99 cluster->refcnt = 0;
100
101 return cluster;
102}
103
104/* Cluster list related functions. */
paul94f2b392005-06-28 12:44:16 +0000105static struct cluster_list *
paul5228ad22004-06-04 17:58:18 +0000106cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +0000107{
108 struct cluster_list tmp;
109 struct cluster_list *cluster;
110
111 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +0000112 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +0000113
114 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
115 cluster->refcnt++;
116 return cluster;
117}
118
119int
120cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
121{
122 int i;
123
124 for (i = 0; i < cluster->length / 4; i++)
125 if (cluster->list[i].s_addr == originator.s_addr)
126 return 1;
127 return 0;
128}
129
paul94f2b392005-06-28 12:44:16 +0000130static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000131cluster_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000132{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700133 const struct cluster_list *cluster = p;
paul718e3742002-12-13 20:15:29 +0000134
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700135 return jhash(cluster->list, cluster->length, 0);
paul718e3742002-12-13 20:15:29 +0000136}
137
paul94f2b392005-06-28 12:44:16 +0000138static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100139cluster_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000140{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100141 const struct cluster_list * cluster1 = p1;
142 const struct cluster_list * cluster2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000143
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100144 return (cluster1->length == cluster2->length &&
145 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000146}
147
paul94f2b392005-06-28 12:44:16 +0000148static void
paul718e3742002-12-13 20:15:29 +0000149cluster_free (struct cluster_list *cluster)
150{
151 if (cluster->list)
152 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
153 XFREE (MTYPE_CLUSTER, cluster);
154}
155
Chris Caputo228da422009-07-18 05:44:03 +0000156#if 0
paul94f2b392005-06-28 12:44:16 +0000157static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000158cluster_dup (struct cluster_list *cluster)
159{
160 struct cluster_list *new;
161
Stephen Hemminger393deb92008-08-18 14:13:29 -0700162 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
paul718e3742002-12-13 20:15:29 +0000163 new->length = cluster->length;
164
165 if (cluster->length)
166 {
167 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
168 memcpy (new->list, cluster->list, cluster->length);
169 }
170 else
171 new->list = NULL;
172
173 return new;
174}
Chris Caputo228da422009-07-18 05:44:03 +0000175#endif
paul718e3742002-12-13 20:15:29 +0000176
paul94f2b392005-06-28 12:44:16 +0000177static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000178cluster_intern (struct cluster_list *cluster)
179{
180 struct cluster_list *find;
181
182 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
183 find->refcnt++;
184
185 return find;
186}
187
188void
189cluster_unintern (struct cluster_list *cluster)
190{
paul718e3742002-12-13 20:15:29 +0000191 if (cluster->refcnt)
192 cluster->refcnt--;
193
194 if (cluster->refcnt == 0)
195 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400196 hash_release (cluster_hash, cluster);
paul718e3742002-12-13 20:15:29 +0000197 cluster_free (cluster);
198 }
199}
200
paul94f2b392005-06-28 12:44:16 +0000201static void
202cluster_init (void)
paul718e3742002-12-13 20:15:29 +0000203{
204 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
205}
Chris Caputo228da422009-07-18 05:44:03 +0000206
207static void
208cluster_finish (void)
209{
Lou Berger056f3762013-04-10 12:30:04 -0700210 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
Chris Caputo228da422009-07-18 05:44:03 +0000211 hash_free (cluster_hash);
212 cluster_hash = NULL;
213}
David Lamparter6b0655a2014-06-04 06:53:35 +0200214
Lou Bergerc3741782016-01-12 13:42:01 -0500215struct bgp_attr_encap_subtlv *
216encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
217{
218 struct bgp_attr_encap_subtlv *new;
219 struct bgp_attr_encap_subtlv *tail;
220 struct bgp_attr_encap_subtlv *p;
221
222 for (p = orig, tail = new = NULL; p; p = p->next) {
223 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
224 if (tail) {
225 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
226 tail = tail->next;
227 } else {
228 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
229 }
230 assert(tail);
231 memcpy(tail, p, size);
232 tail->next = NULL;
233 }
234
235 return new;
236}
237
238static void
239encap_free(struct bgp_attr_encap_subtlv *p)
240{
241 struct bgp_attr_encap_subtlv *next;
242 while (p) {
243 next = p->next;
244 p->next = NULL;
245 XFREE(MTYPE_ENCAP_TLV, p);
246 p = next;
247 }
248}
249
250void
251bgp_attr_flush_encap(struct attr *attr)
252{
253 if (!attr || !attr->extra)
254 return;
255
256 if (attr->extra->encap_subtlvs) {
257 encap_free(attr->extra->encap_subtlvs);
258 attr->extra->encap_subtlvs = NULL;
259 }
260}
261
262/*
263 * Compare encap sub-tlv chains
264 *
265 * 1 = equivalent
266 * 0 = not equivalent
267 *
268 * This algorithm could be made faster if needed
269 */
270static int
271encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
272{
273 struct bgp_attr_encap_subtlv *p;
274 struct bgp_attr_encap_subtlv *q;
275
276 if (!h1 && !h2)
277 return 1;
278 if (h1 && !h2)
279 return 0;
280 if (!h1 && h2)
281 return 0;
282 if (h1 == h2)
283 return 1;
284
285 for (p = h1; p; p = p->next) {
286 for (q = h2; q; q = q->next) {
287 if ((p->type == q->type) &&
288 (p->length == q->length) &&
289 !memcmp(p->value, q->value, p->length)) {
290
291 break;
292 }
293 }
294 if (!q)
295 return 0;
296 }
297
298 for (p = h2; p; p = p->next) {
299 for (q = h1; 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 return 1;
312}
313
paul718e3742002-12-13 20:15:29 +0000314/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700315static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000316
paul94f2b392005-06-28 12:44:16 +0000317static void
paul718e3742002-12-13 20:15:29 +0000318transit_free (struct transit *transit)
319{
320 if (transit->val)
321 XFREE (MTYPE_TRANSIT_VAL, transit->val);
322 XFREE (MTYPE_TRANSIT, transit);
323}
324
Paul Jakma923de652007-04-29 18:25:17 +0000325
paul94f2b392005-06-28 12:44:16 +0000326static void *
Paul Jakma923de652007-04-29 18:25:17 +0000327transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000328{
329 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000330 return p;
paul718e3742002-12-13 20:15:29 +0000331}
332
paul94f2b392005-06-28 12:44:16 +0000333static struct transit *
paul718e3742002-12-13 20:15:29 +0000334transit_intern (struct transit *transit)
335{
336 struct transit *find;
337
338 find = hash_get (transit_hash, transit, transit_hash_alloc);
339 if (find != transit)
340 transit_free (transit);
341 find->refcnt++;
342
343 return find;
344}
345
346void
347transit_unintern (struct transit *transit)
348{
paul718e3742002-12-13 20:15:29 +0000349 if (transit->refcnt)
350 transit->refcnt--;
351
352 if (transit->refcnt == 0)
353 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400354 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000355 transit_free (transit);
356 }
357}
358
paul94f2b392005-06-28 12:44:16 +0000359static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000360transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000361{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700362 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000363
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700364 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000365}
366
paul94f2b392005-06-28 12:44:16 +0000367static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100368transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000369{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100370 const struct transit * transit1 = p1;
371 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000372
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100373 return (transit1->length == transit2->length &&
374 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000375}
376
paul94f2b392005-06-28 12:44:16 +0000377static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800378transit_init (void)
paul718e3742002-12-13 20:15:29 +0000379{
380 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
381}
Chris Caputo228da422009-07-18 05:44:03 +0000382
383static void
384transit_finish (void)
385{
Lou Berger056f3762013-04-10 12:30:04 -0700386 hash_clean (transit_hash, (void (*)(void *))transit_free);
Chris Caputo228da422009-07-18 05:44:03 +0000387 hash_free (transit_hash);
388 transit_hash = NULL;
389}
David Lamparter6b0655a2014-06-04 06:53:35 +0200390
paul718e3742002-12-13 20:15:29 +0000391/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700392static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000393
Paul Jakmafb982c22007-05-04 20:15:47 +0000394static struct attr_extra *
395bgp_attr_extra_new (void)
396{
397 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
398}
399
400void
401bgp_attr_extra_free (struct attr *attr)
402{
403 if (attr->extra)
404 {
Lou Bergerc3741782016-01-12 13:42:01 -0500405 if (attr->extra->encap_subtlvs) {
406 encap_free(attr->extra->encap_subtlvs);
407 attr->extra->encap_subtlvs = NULL;
408 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000409 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
410 attr->extra = NULL;
411 }
412}
413
414struct attr_extra *
415bgp_attr_extra_get (struct attr *attr)
416{
417 if (!attr->extra)
418 attr->extra = bgp_attr_extra_new();
419 return attr->extra;
420}
421
422/* Shallow copy of an attribute
423 * Though, not so shallow that it doesn't copy the contents
424 * of the attr_extra pointed to by 'extra'
425 */
426void
427bgp_attr_dup (struct attr *new, struct attr *orig)
428{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000429 struct attr_extra *extra = new->extra;
430
Paul Jakmafb982c22007-05-04 20:15:47 +0000431 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000432 /* if caller provided attr_extra space, use it in any case.
433 *
434 * This is neccesary even if orig->extra equals NULL, because otherwise
435 * memory may be later allocated on the heap by bgp_attr_extra_get.
436 *
437 * That memory would eventually be leaked, because the caller must not
438 * call bgp_attr_extra_free if he provided attr_extra on the stack.
439 */
440 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000441 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000442 new->extra = extra;
443 memset(new->extra, 0, sizeof(struct attr_extra));
Lou Bergerc3741782016-01-12 13:42:01 -0500444 if (orig->extra) {
Christian Frankea0de1d12012-12-07 16:35:00 +0000445 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500446 if (orig->extra->encap_subtlvs) {
447 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
448 }
449 }
Christian Frankea0de1d12012-12-07 16:35:00 +0000450 }
451 else if (orig->extra)
452 {
453 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000454 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500455 if (orig->extra->encap_subtlvs) {
456 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
457 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000458 }
459}
460
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000461unsigned long int
462attr_count (void)
463{
464 return attrhash->count;
465}
466
467unsigned long int
468attr_unknown_count (void)
469{
470 return transit_hash->count;
471}
472
paul718e3742002-12-13 20:15:29 +0000473unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000474attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000475{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000476 const struct attr *attr = (struct attr *) p;
477 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700478 uint32_t key = 0;
479#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000480
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700481 MIX(attr->origin);
482 MIX(attr->nexthop.s_addr);
483 MIX(attr->med);
484 MIX(attr->local_pref);
485
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000486 key += attr->origin;
487 key += attr->nexthop.s_addr;
488 key += attr->med;
489 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000490
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000491 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000492 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000493 MIX(extra->aggregator_as);
494 MIX(extra->aggregator_addr.s_addr);
495 MIX(extra->weight);
496 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000497 MIX(extra->originator_id.s_addr);
Piotr Chytła605aa332015-12-01 10:03:54 -0500498 MIX(extra->tag);
Paul Jakmafb982c22007-05-04 20:15:47 +0000499 }
500
paul718e3742002-12-13 20:15:29 +0000501 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700502 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000503 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700504 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000505
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000506 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000507 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000508 if (extra->ecommunity)
509 MIX(ecommunity_hash_make (extra->ecommunity));
510 if (extra->cluster)
511 MIX(cluster_hash_key_make (extra->cluster));
512 if (extra->transit)
513 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000514
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000515 MIX(extra->mp_nexthop_len);
516 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
517 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
Paul Jakmafb982c22007-05-04 20:15:47 +0000518 }
paul718e3742002-12-13 20:15:29 +0000519
520 return key;
521}
522
523int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100524attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000525{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100526 const struct attr * attr1 = p1;
527 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000528
paul718e3742002-12-13 20:15:29 +0000529 if (attr1->flag == attr2->flag
530 && attr1->origin == attr2->origin
531 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000532 && attr1->aspath == attr2->aspath
533 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000534 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000535 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000536 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100537 const struct attr_extra *ae1 = attr1->extra;
538 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000539
540 if (ae1 && ae2
541 && ae1->aggregator_as == ae2->aggregator_as
542 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
543 && ae1->weight == ae2->weight
Piotr Chytła605aa332015-12-01 10:03:54 -0500544 && ae1->tag == ae2->tag
Paul Jakmafb982c22007-05-04 20:15:47 +0000545 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
546 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
547 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
Paul Jakmafb982c22007-05-04 20:15:47 +0000548 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
549 && ae1->ecommunity == ae2->ecommunity
550 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000551 && ae1->transit == ae2->transit
Lou Bergerc3741782016-01-12 13:42:01 -0500552 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
553 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000554 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000555 return 1;
556 else if (ae1 || ae2)
557 return 0;
558 /* neither attribute has extra attributes, so they're same */
559 return 1;
560 }
paul718e3742002-12-13 20:15:29 +0000561 else
562 return 0;
563}
564
paul94f2b392005-06-28 12:44:16 +0000565static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100566attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000567{
568 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
569}
570
Lou Berger056f3762013-04-10 12:30:04 -0700571/*
572 * special for hash_clean below
573 */
574static void
575attr_vfree (void *attr)
576{
577 bgp_attr_extra_free ((struct attr *)attr);
578 XFREE (MTYPE_ATTR, attr);
579}
580
paul94f2b392005-06-28 12:44:16 +0000581static void
Chris Caputo228da422009-07-18 05:44:03 +0000582attrhash_finish (void)
583{
Lou Berger056f3762013-04-10 12:30:04 -0700584 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000585 hash_free (attrhash);
586 attrhash = NULL;
587}
588
589static void
paul718e3742002-12-13 20:15:29 +0000590attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
591{
592 struct attr *attr = backet->data;
593
594 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
595 inet_ntoa (attr->nexthop), VTY_NEWLINE);
596}
597
598void
599attr_show_all (struct vty *vty)
600{
601 hash_iterate (attrhash,
602 (void (*)(struct hash_backet *, void *))
603 attr_show_all_iterator,
604 vty);
605}
606
paul94f2b392005-06-28 12:44:16 +0000607static void *
Paul Jakma923de652007-04-29 18:25:17 +0000608bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000609{
Paul Jakma923de652007-04-29 18:25:17 +0000610 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000611 struct attr *attr;
612
613 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
614 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000615 if (val->extra)
616 {
617 attr->extra = bgp_attr_extra_new ();
618 *attr->extra = *val->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500619
620 if (attr->extra->encap_subtlvs) {
621 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
622 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000623 }
paul718e3742002-12-13 20:15:29 +0000624 attr->refcnt = 0;
625 return attr;
626}
627
628/* Internet argument attribute. */
629struct attr *
630bgp_attr_intern (struct attr *attr)
631{
632 struct attr *find;
633
634 /* Intern referenced strucutre. */
635 if (attr->aspath)
636 {
637 if (! attr->aspath->refcnt)
638 attr->aspath = aspath_intern (attr->aspath);
639 else
640 attr->aspath->refcnt++;
641 }
642 if (attr->community)
643 {
644 if (! attr->community->refcnt)
645 attr->community = community_intern (attr->community);
646 else
647 attr->community->refcnt++;
648 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000649 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000650 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000651 struct attr_extra *attre = attr->extra;
652
653 if (attre->ecommunity)
654 {
655 if (! attre->ecommunity->refcnt)
656 attre->ecommunity = ecommunity_intern (attre->ecommunity);
657 else
658 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000659
Paul Jakmafb982c22007-05-04 20:15:47 +0000660 }
661 if (attre->cluster)
662 {
663 if (! attre->cluster->refcnt)
664 attre->cluster = cluster_intern (attre->cluster);
665 else
666 attre->cluster->refcnt++;
667 }
668 if (attre->transit)
669 {
670 if (! attre->transit->refcnt)
671 attre->transit = transit_intern (attre->transit);
672 else
673 attre->transit->refcnt++;
674 }
paul718e3742002-12-13 20:15:29 +0000675 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000676
paul718e3742002-12-13 20:15:29 +0000677 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
678 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000679
paul718e3742002-12-13 20:15:29 +0000680 return find;
681}
682
Paul Jakma03e214c2007-04-29 18:31:07 +0000683
paul718e3742002-12-13 20:15:29 +0000684/* Make network statement's attribute. */
685struct attr *
686bgp_attr_default_set (struct attr *attr, u_char origin)
687{
688 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000689 bgp_attr_extra_get (attr);
690
paul718e3742002-12-13 20:15:29 +0000691 attr->origin = origin;
692 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
693 attr->aspath = aspath_empty ();
694 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000695 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
Piotr Chytła605aa332015-12-01 10:03:54 -0500696 attr->extra->tag = 0;
paul718e3742002-12-13 20:15:29 +0000697 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
Paul Jakmafb982c22007-05-04 20:15:47 +0000698 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
Paul Jakma03e214c2007-04-29 18:31:07 +0000699
paul718e3742002-12-13 20:15:29 +0000700 return attr;
701}
702
Paul Jakma03e214c2007-04-29 18:31:07 +0000703
paul718e3742002-12-13 20:15:29 +0000704/* Make network statement's attribute. */
705struct attr *
706bgp_attr_default_intern (u_char origin)
707{
708 struct attr attr;
709 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000710
Lou Bergerc3741782016-01-12 13:42:01 -0500711 memset (&attr, 0, sizeof (struct attr));
712 bgp_attr_extra_get (&attr);
713
Paul Jakma03e214c2007-04-29 18:31:07 +0000714 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000715
716 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000717 bgp_attr_extra_free (&attr);
718
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000719 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000720 return new;
721}
722
Daniel Walton76a72802015-05-19 17:47:24 -0700723/* Create the attributes for an aggregate */
paul718e3742002-12-13 20:15:29 +0000724struct attr *
725bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
726 struct aspath *aspath,
Daniel Waltonf2eb9ca2015-05-19 17:47:21 -0700727 struct community *community, int as_set,
728 u_char atomic_aggregate)
paul718e3742002-12-13 20:15:29 +0000729{
730 struct attr attr;
731 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000732 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000733
734 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000735 memset (&attre, 0, sizeof (struct attr_extra));
736 attr.extra = &attre;
737
paul718e3742002-12-13 20:15:29 +0000738 /* Origin attribute. */
739 attr.origin = origin;
740 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
741
742 /* AS path attribute. */
743 if (aspath)
744 attr.aspath = aspath_intern (aspath);
745 else
746 attr.aspath = aspath_empty ();
747 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
748
749 /* Next hop attribute. */
750 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
751
752 if (community)
753 {
754 attr.community = community;
755 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
756 }
757
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000758 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000759 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
Lou Berger205e6742016-01-12 13:42:11 -0500760
Daniel Waltonf2eb9ca2015-05-19 17:47:21 -0700761 if (! as_set || atomic_aggregate)
paul718e3742002-12-13 20:15:29 +0000762 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
763 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
764 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000765 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000766 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000767 attre.aggregator_as = bgp->as;
768 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000769
770 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000771
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000772 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000773 return new;
774}
775
Paul Jakmab881c702010-11-23 16:35:42 +0000776/* Unintern just the sub-components of the attr, but not the attr */
777void
778bgp_attr_unintern_sub (struct attr *attr)
779{
780 /* aspath refcount shoud be decrement. */
781 if (attr->aspath)
782 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000783 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000784
785 if (attr->community)
786 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000787 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000788
789 if (attr->extra)
790 {
791 if (attr->extra->ecommunity)
792 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000793 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000794
795 if (attr->extra->cluster)
796 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000797 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000798
799 if (attr->extra->transit)
800 transit_unintern (attr->extra->transit);
801 }
802}
803
paul718e3742002-12-13 20:15:29 +0000804/* Free bgp attribute and aspath. */
805void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000806bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000807{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000808 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000809 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000810 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000811 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000812
paul718e3742002-12-13 20:15:29 +0000813 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000814 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000815
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000816 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000817
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000818 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000819 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000820 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000821 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000822 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000823
paul718e3742002-12-13 20:15:29 +0000824 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000825 if (attr->refcnt == 0)
826 {
827 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000828 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000829 bgp_attr_extra_free (attr);
830 XFREE (MTYPE_ATTR, attr);
831 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000832 }
833
Paul Jakmab881c702010-11-23 16:35:42 +0000834 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000835}
836
837void
838bgp_attr_flush (struct attr *attr)
839{
840 if (attr->aspath && ! attr->aspath->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500841 {
842 aspath_free (attr->aspath);
843 attr->aspath = NULL;
844 }
paul718e3742002-12-13 20:15:29 +0000845 if (attr->community && ! attr->community->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500846 {
847 community_free (attr->community);
848 attr->community = NULL;
849 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000850 if (attr->extra)
851 {
852 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000853
Paul Jakmafb982c22007-05-04 20:15:47 +0000854 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000855 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000856 if (attre->cluster && ! attre->cluster->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500857 {
858 cluster_free (attre->cluster);
859 attre->cluster = NULL;
860 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000861 if (attre->transit && ! attre->transit->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500862 {
863 transit_free (attre->transit);
864 attre->transit = NULL;
865 }
Lou Bergerc3741782016-01-12 13:42:01 -0500866 encap_free(attre->encap_subtlvs);
867 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000868 }
paul718e3742002-12-13 20:15:29 +0000869}
870
Paul Jakmab881c702010-11-23 16:35:42 +0000871/* Implement draft-scudder-idr-optional-transitive behaviour and
872 * avoid resetting sessions for malformed attributes which are
873 * are partial/optional and hence where the error likely was not
874 * introduced by the sending neighbour.
875 */
876static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000877bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
878 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000879{
Paul Jakma835315b2012-01-18 12:28:30 +0000880 struct peer *const peer = args->peer;
881 const u_int8_t flags = args->flags;
882 /* startp and length must be special-cased, as whether or not to
883 * send the attribute data with the NOTIFY depends on the error,
884 * the caller therefore signals this with the seperate length argument
885 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000886 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000887
Paul Jakmab881c702010-11-23 16:35:42 +0000888 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000889 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000890 {
891 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000892 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000893 return BGP_ATTR_PARSE_ERROR;
894
895 }
896
Paul Jakmabd471fe2012-03-15 11:30:00 +0000897 /* Adjust the stream getp to the end of the attribute, in case we can
898 * still proceed but the caller hasn't read all the attribute.
899 */
900 stream_set_getp (BGP_INPUT (peer),
901 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
902 + args->total);
903
Paul Jakma835315b2012-01-18 12:28:30 +0000904 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100905 /* where an attribute is relatively inconsequential, e.g. it does not
906 * affect route selection, and can be safely ignored, then any such
907 * attributes which are malformed should just be ignored and the route
908 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000909 */
910 case BGP_ATTR_AS4_AGGREGATOR:
911 case BGP_ATTR_AGGREGATOR:
912 case BGP_ATTR_ATOMIC_AGGREGATE:
913 return BGP_ATTR_PARSE_PROCEED;
914
915 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100916 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000917 */
918 case BGP_ATTR_ORIGIN:
919 case BGP_ATTR_AS_PATH:
920 case BGP_ATTR_NEXT_HOP:
921 case BGP_ATTR_MULTI_EXIT_DISC:
922 case BGP_ATTR_LOCAL_PREF:
923 case BGP_ATTR_COMMUNITIES:
924 case BGP_ATTR_ORIGINATOR_ID:
925 case BGP_ATTR_CLUSTER_LIST:
926 case BGP_ATTR_MP_REACH_NLRI:
927 case BGP_ATTR_MP_UNREACH_NLRI:
928 case BGP_ATTR_EXT_COMMUNITIES:
929 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000930 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000931 return BGP_ATTR_PARSE_ERROR;
932 }
933
934 /* Partial optional attributes that are malformed should not cause
935 * the whole session to be reset. Instead treat it as a withdrawal
936 * of the routes, if possible.
937 */
Paul Jakma835315b2012-01-18 12:28:30 +0000938 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
939 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
940 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000941 return BGP_ATTR_PARSE_WITHDRAW;
942
943 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200944 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000945}
946
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400947/* Find out what is wrong with the path attribute flag bits and log the error.
948 "Flag bits" here stand for Optional, Transitive and Partial, but not for
949 Extended Length. Checking O/T/P bits at once implies, that the attribute
950 being diagnosed is defined by RFC as either a "well-known" or an "optional,
951 non-transitive" attribute. */
952static void
Paul Jakma835315b2012-01-18 12:28:30 +0000953bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
954 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400955)
956{
957 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000958 u_char real_flags = args->flags;
959 const u_int8_t attr_code = args->type;
960
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400961 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
962 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
963 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
964 if
965 (
966 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
967 CHECK_FLAG (real_flags, attr_flag_str[i].key)
968 )
969 {
Paul Jakma835315b2012-01-18 12:28:30 +0000970 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400971 LOOKUP (attr_str, attr_code),
972 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
973 attr_flag_str[i].str);
974 seen = 1;
975 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100976 if (!seen)
977 {
978 zlog (args->peer->log, LOG_DEBUG,
979 "Strange, %s called for attr %s, but no problem found with flags"
980 " (real flags 0x%x, desired 0x%x)",
981 __func__, LOOKUP (attr_str, attr_code),
982 real_flags, desired_flags);
983 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400984}
985
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000986/* Required flags for attributes. EXTLEN will be masked off when testing,
987 * as will PARTIAL for optional+transitive attributes.
988 */
989const u_int8_t attr_flags_values [] = {
990 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
991 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
992 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
993 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
994 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
995 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
996 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
997 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
998 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
999 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1000 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1001 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1002 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1003 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1004 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1005};
Christian Franke0d8b32a2016-06-14 20:07:00 +02001006static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001007
1008static int
Paul Jakma835315b2012-01-18 12:28:30 +00001009bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001010{
1011 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +00001012 const u_int8_t flags = args->flags;
1013 const u_int8_t attr_code = args->type;
1014 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001015
1016 /* there may be attributes we don't know about */
1017 if (attr_code > attr_flags_values_max)
1018 return 0;
1019 if (attr_flags_values[attr_code] == 0)
1020 return 0;
1021
1022 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1023 * 1."
1024 */
1025 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1026 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1027 {
1028 zlog (peer->log, LOG_ERR,
1029 "%s well-known attributes must have transitive flag set (%x)",
1030 LOOKUP (attr_str, attr_code), flags);
1031 return 1;
1032 }
1033
1034 /* "For well-known attributes and for optional non-transitive attributes,
1035 * the Partial bit MUST be set to 0."
1036 */
1037 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1038 {
1039 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1040 {
1041 zlog (peer->log, LOG_ERR,
1042 "%s well-known attribute "
1043 "must NOT have the partial flag set (%x)",
1044 LOOKUP (attr_str, attr_code), flags);
1045 return 1;
1046 }
1047 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1048 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1049 {
1050 zlog (peer->log, LOG_ERR,
1051 "%s optional + transitive attribute "
1052 "must NOT have the partial flag set (%x)",
1053 LOOKUP (attr_str, attr_code), flags);
1054 return 1;
1055 }
1056 }
1057
1058 /* Optional transitive attributes may go through speakers that don't
1059 * reocgnise them and set the Partial bit.
1060 */
1061 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1062 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1063 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1064
Paul Jakma683f2b82012-03-23 14:58:45 +00001065 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001066 == attr_flags_values[attr_code])
1067 return 0;
1068
Paul Jakma835315b2012-01-18 12:28:30 +00001069 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001070 return 1;
1071}
1072
paul718e3742002-12-13 20:15:29 +00001073/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001074static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001075bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001076{
Paul Jakma835315b2012-01-18 12:28:30 +00001077 struct peer *const peer = args->peer;
1078 struct attr *const attr = args->attr;
1079 const bgp_size_t length = args->length;
1080
paul718e3742002-12-13 20:15:29 +00001081 /* If any recognized attribute has Attribute Length that conflicts
1082 with the expected length (based on the attribute type code), then
1083 the Error Subcode is set to Attribute Length Error. The Data
1084 field contains the erroneous attribute (type, length and
1085 value). */
1086 if (length != 1)
1087 {
1088 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1089 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001090 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001091 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001092 args->total);
paul718e3742002-12-13 20:15:29 +00001093 }
1094
1095 /* Fetch origin attribute. */
1096 attr->origin = stream_getc (BGP_INPUT (peer));
1097
1098 /* If the ORIGIN attribute has an undefined value, then the Error
1099 Subcode is set to Invalid Origin Attribute. The Data field
1100 contains the unrecognized attribute (type, length and value). */
1101 if ((attr->origin != BGP_ORIGIN_IGP)
1102 && (attr->origin != BGP_ORIGIN_EGP)
1103 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1104 {
1105 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1106 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001107 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001108 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001109 args->total);
paul718e3742002-12-13 20:15:29 +00001110 }
1111
1112 /* Set oring attribute flag. */
1113 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1114
1115 return 0;
1116}
Paul Jakmaab005292010-11-27 22:48:34 +00001117
1118/* Parse AS path information. This function is wrapper of
1119 aspath_parse. */
1120static int
Paul Jakma835315b2012-01-18 12:28:30 +00001121bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001122{
Paul Jakma835315b2012-01-18 12:28:30 +00001123 struct attr *const attr = args->attr;
1124 struct peer *const peer = args->peer;
1125 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001126
Paul Jakmaab005292010-11-27 22:48:34 +00001127 /*
1128 * peer with AS4 => will get 4Byte ASnums
1129 * otherwise, will get 16 Bit
1130 */
1131 attr->aspath = aspath_parse (peer->ibuf, length,
1132 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1133
1134 /* In case of IBGP, length will be zero. */
1135 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001136 {
Paul Jakmab881c702010-11-23 16:35:42 +00001137 zlog (peer->log, LOG_ERR,
1138 "Malformed AS path from %s, length is %d",
1139 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001140 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001141 }
Chris Hallcddb8112010-08-09 22:31:37 +04001142
Paul Jakmaab005292010-11-27 22:48:34 +00001143 /* Set aspath attribute flag. */
1144 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001145
Paul Jakmab881c702010-11-23 16:35:42 +00001146 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001147}
1148
Paul Jakmab881c702010-11-23 16:35:42 +00001149static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001150bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001151{
1152 /* These checks were part of bgp_attr_aspath, but with
1153 * as4 we should to check aspath things when
1154 * aspath synthesizing with as4_path has already taken place.
1155 * Otherwise we check ASPATH and use the synthesized thing, and that is
1156 * not right.
1157 * So do the checks later, i.e. here
1158 */
1159 struct bgp *bgp = peer->bgp;
1160 struct aspath *aspath;
1161
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001162 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001163 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1164 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001165 {
1166 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001167 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1168 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1169 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001170 }
1171
paul718e3742002-12-13 20:15:29 +00001172 /* First AS check for EBGP. */
1173 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1174 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001175 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001176 && ! aspath_firstas_check (attr->aspath, peer->as))
1177 {
1178 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001179 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001180 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1181 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1182 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001183 }
1184 }
1185
1186 /* local-as prepend */
1187 if (peer->change_local_as &&
1188 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1189 {
1190 aspath = aspath_dup (attr->aspath);
1191 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001192 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001193 attr->aspath = aspath_intern (aspath);
1194 }
1195
Paul Jakmab881c702010-11-23 16:35:42 +00001196 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001197}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001198
Paul Jakmaab005292010-11-27 22:48:34 +00001199/* Parse AS4 path information. This function is another wrapper of
1200 aspath_parse. */
1201static int
Paul Jakma835315b2012-01-18 12:28:30 +00001202bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001203{
Paul Jakma835315b2012-01-18 12:28:30 +00001204 struct peer *const peer = args->peer;
1205 struct attr *const attr = args->attr;
1206 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001207
Paul Jakmaab005292010-11-27 22:48:34 +00001208 *as4_path = aspath_parse (peer->ibuf, length, 1);
1209
Paul Jakmab881c702010-11-23 16:35:42 +00001210 /* In case of IBGP, length will be zero. */
1211 if (!*as4_path)
1212 {
1213 zlog (peer->log, LOG_ERR,
1214 "Malformed AS4 path from %s, length is %d",
1215 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001216 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001217 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001218 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001219 }
1220
Paul Jakmaab005292010-11-27 22:48:34 +00001221 /* Set aspath attribute flag. */
1222 if (as4_path)
1223 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1224
Paul Jakmab881c702010-11-23 16:35:42 +00001225 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001226}
1227
paul718e3742002-12-13 20:15:29 +00001228/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001229static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001230bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001231{
Paul Jakma835315b2012-01-18 12:28:30 +00001232 struct peer *const peer = args->peer;
1233 struct attr *const attr = args->attr;
1234 const bgp_size_t length = args->length;
1235
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001236 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001237
paul718e3742002-12-13 20:15:29 +00001238 /* Check nexthop attribute length. */
1239 if (length != 4)
1240 {
1241 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1242 length);
1243
Paul Jakma835315b2012-01-18 12:28:30 +00001244 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001245 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001246 args->total);
paul718e3742002-12-13 20:15:29 +00001247 }
1248
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001249 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1250 attribute must result in a NOTIFICATION message (this is implemented below).
1251 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1252 logged locally (this is implemented somewhere else). The UPDATE message
1253 gets ignored in any of these cases. */
1254 nexthop_n = stream_get_ipv4 (peer->ibuf);
1255 nexthop_h = ntohl (nexthop_n);
Lou Bergerf53585d2016-05-17 07:10:36 -04001256 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1257 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001258 {
1259 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001260 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001261 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001262 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001263 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001264 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001265 }
1266
1267 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001268 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1269
Paul Jakmab881c702010-11-23 16:35:42 +00001270 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001271}
1272
1273/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001274static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001275bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001276{
Paul Jakma835315b2012-01-18 12:28:30 +00001277 struct peer *const peer = args->peer;
1278 struct attr *const attr = args->attr;
1279 const bgp_size_t length = args->length;
1280
paul718e3742002-12-13 20:15:29 +00001281 /* Length check. */
1282 if (length != 4)
1283 {
1284 zlog (peer->log, LOG_ERR,
1285 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001286
Paul Jakma835315b2012-01-18 12:28:30 +00001287 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001288 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001289 args->total);
paul718e3742002-12-13 20:15:29 +00001290 }
1291
1292 attr->med = stream_getl (peer->ibuf);
1293
1294 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1295
Paul Jakmab881c702010-11-23 16:35:42 +00001296 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001297}
1298
1299/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001300static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001301bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001302{
Paul Jakma835315b2012-01-18 12:28:30 +00001303 struct peer *const peer = args->peer;
1304 struct attr *const attr = args->attr;
1305 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001306
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001307 /* Length check. */
1308 if (length != 4)
1309 {
Paul Jakma835315b2012-01-18 12:28:30 +00001310 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1311 length);
1312 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001313 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001314 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001315 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001316
paul718e3742002-12-13 20:15:29 +00001317 /* If it is contained in an UPDATE message that is received from an
1318 external peer, then this attribute MUST be ignored by the
1319 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001320 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001321 {
paul9985f832005-02-09 15:51:56 +00001322 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001323 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001324 }
1325
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001326 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001327
1328 /* Set atomic aggregate flag. */
1329 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1330
Paul Jakmab881c702010-11-23 16:35:42 +00001331 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001332}
1333
1334/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001335static int
Paul Jakma835315b2012-01-18 12:28:30 +00001336bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001337{
Paul Jakma835315b2012-01-18 12:28:30 +00001338 struct peer *const peer = args->peer;
1339 struct attr *const attr = args->attr;
1340 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001341
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001342 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001343 if (length != 0)
1344 {
Paul Jakma835315b2012-01-18 12:28:30 +00001345 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1346 length);
1347 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001348 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001349 args->total);
paul718e3742002-12-13 20:15:29 +00001350 }
1351
1352 /* Set atomic aggregate flag. */
1353 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1354
Paul Jakmab881c702010-11-23 16:35:42 +00001355 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001356}
1357
1358/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001359static int
Paul Jakma835315b2012-01-18 12:28:30 +00001360bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001361{
Paul Jakma835315b2012-01-18 12:28:30 +00001362 struct peer *const peer = args->peer;
1363 struct attr *const attr = args->attr;
1364 const bgp_size_t length = args->length;
1365
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001366 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001367 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001368
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001369 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001370 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001371 wantedlen = 8;
1372
1373 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001374 {
Paul Jakma835315b2012-01-18 12:28:30 +00001375 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1376 wantedlen, 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 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001381
1382 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1383 attre->aggregator_as = stream_getl (peer->ibuf);
1384 else
1385 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001386 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001387
1388 /* Set atomic aggregate flag. */
1389 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1390
Paul Jakmab881c702010-11-23 16:35:42 +00001391 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001392}
1393
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001394/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001395static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001396bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1397 as_t *as4_aggregator_as,
1398 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001399{
Paul Jakma835315b2012-01-18 12:28:30 +00001400 struct peer *const peer = args->peer;
1401 struct attr *const attr = args->attr;
1402 const bgp_size_t length = args->length;
1403
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001404 if (length != 8)
1405 {
Paul Jakma835315b2012-01-18 12:28:30 +00001406 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1407 length);
1408 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001409 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001410 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001411 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001412
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001413 *as4_aggregator_as = stream_getl (peer->ibuf);
1414 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1415
1416 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1417
Paul Jakmab881c702010-11-23 16:35:42 +00001418 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001419}
1420
1421/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1422 */
Paul Jakmab881c702010-11-23 16:35:42 +00001423static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001424bgp_attr_munge_as4_attrs (struct peer *const peer,
1425 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001426 struct aspath *as4_path, as_t as4_aggregator,
1427 struct in_addr *as4_aggregator_addr)
1428{
1429 int ignore_as4_path = 0;
1430 struct aspath *newpath;
1431 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001432
1433 if (!attr->aspath)
1434 {
1435 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1436 * checked that all well-known, mandatory attributes were present.
1437 *
1438 * Can only be a problem with peer itself - hard error
1439 */
1440 return BGP_ATTR_PARSE_ERROR;
1441 }
1442
Paul Jakmab881c702010-11-23 16:35:42 +00001443 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001444 {
1445 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1446 * if given.
1447 * It is worth a warning though, because the peer really
1448 * should not send them
1449 */
1450 if (BGP_DEBUG(as4, AS4))
1451 {
1452 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1453 zlog_debug ("[AS4] %s %s AS4_PATH",
1454 peer->host, "AS4 capable peer, yet it sent");
1455
1456 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1457 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1458 peer->host, "AS4 capable peer, yet it sent");
1459 }
1460
Paul Jakmab881c702010-11-23 16:35:42 +00001461 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001462 }
1463
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001464 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1465 * because that may override AS4_PATH
1466 */
1467 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1468 {
Paul Jakmab881c702010-11-23 16:35:42 +00001469 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001470 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001471 assert (attre);
1472
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001473 /* received both.
1474 * if the as_number in aggregator is not AS_TRANS,
1475 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1476 * and the Aggregator shall be taken as
1477 * info on the aggregating node, and the AS_PATH
1478 * shall be taken as the AS_PATH
1479 * otherwise
1480 * the Aggregator shall be ignored and the
1481 * AS4_AGGREGATOR shall be taken as the
1482 * Aggregating node and the AS_PATH is to be
1483 * constructed "as in all other cases"
1484 */
Paul Jakmab881c702010-11-23 16:35:42 +00001485 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001486 {
1487 /* ignore */
1488 if ( BGP_DEBUG(as4, AS4))
1489 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1490 " send AGGREGATOR != AS_TRANS and"
1491 " AS4_AGGREGATOR, so ignore"
1492 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1493 ignore_as4_path = 1;
1494 }
1495 else
1496 {
1497 /* "New_aggregator shall be taken as aggregator" */
1498 attre->aggregator_as = as4_aggregator;
1499 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1500 }
1501 }
1502 else
1503 {
1504 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1505 * That is bogus - but reading the conditions
1506 * we have to handle AS4_AGGREGATOR as if it were
1507 * AGGREGATOR in that case
1508 */
1509 if ( BGP_DEBUG(as4, AS4))
1510 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1511 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1512 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001513 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001514 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1515 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1516 }
1517 }
1518
1519 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001520 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001521 {
Paul Jakma055086f2014-09-23 15:23:01 +01001522 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1523 aspath_unintern (&attr->aspath);
1524 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001525 }
Paul Jakmab881c702010-11-23 16:35:42 +00001526 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001527}
1528
paul718e3742002-12-13 20:15:29 +00001529/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001530static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001531bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001532{
Paul Jakma835315b2012-01-18 12:28:30 +00001533 struct peer *const peer = args->peer;
1534 struct attr *const attr = args->attr;
1535 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001536
paul718e3742002-12-13 20:15:29 +00001537 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001538 {
1539 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001540 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001541 }
Paul Jakma0c466382010-12-05 17:17:26 +00001542
1543 attr->community =
1544 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1545
1546 /* XXX: fix community_parse to use stream API and remove this */
1547 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001548
Paul Jakma0c466382010-12-05 17:17:26 +00001549 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001550 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001551 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001552 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001553
paul718e3742002-12-13 20:15:29 +00001554 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1555
Paul Jakmab881c702010-11-23 16:35:42 +00001556 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001557}
1558
1559/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001560static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001561bgp_attr_originator_id (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;
1566
Denis Ovsienkod595b562011-09-30 15:08:54 +04001567 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001568 if (length != 4)
1569 {
1570 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1571
Paul Jakma835315b2012-01-18 12:28:30 +00001572 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001573 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001574 args->total);
paul718e3742002-12-13 20:15:29 +00001575 }
1576
Paul Jakmafb982c22007-05-04 20:15:47 +00001577 (bgp_attr_extra_get (attr))->originator_id.s_addr
1578 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001579
1580 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1581
Paul Jakmab881c702010-11-23 16:35:42 +00001582 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001583}
1584
1585/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001586static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001587bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001588{
Paul Jakma835315b2012-01-18 12:28:30 +00001589 struct peer *const peer = args->peer;
1590 struct attr *const attr = args->attr;
1591 const bgp_size_t length = args->length;
1592
paul718e3742002-12-13 20:15:29 +00001593 /* Check length. */
1594 if (length % 4)
1595 {
1596 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1597
Paul Jakma835315b2012-01-18 12:28:30 +00001598 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1599 args->total);
paul718e3742002-12-13 20:15:29 +00001600 }
1601
Paul Jakmafb982c22007-05-04 20:15:47 +00001602 (bgp_attr_extra_get (attr))->cluster
1603 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001604
1605 /* XXX: Fix cluster_parse to use stream API and then remove this */
1606 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001607
1608 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1609
Paul Jakmab881c702010-11-23 16:35:42 +00001610 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001611}
1612
1613/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001614int
Paul Jakma835315b2012-01-18 12:28:30 +00001615bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1616 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001617{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001618 afi_t afi;
1619 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001620 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001621 size_t start;
paul718e3742002-12-13 20:15:29 +00001622 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001623 struct peer *const peer = args->peer;
1624 struct attr *const attr = args->attr;
1625 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001626 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001627
paul718e3742002-12-13 20:15:29 +00001628 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001629 s = BGP_INPUT(peer);
1630 start = stream_get_getp(s);
1631
1632 /* safe to read statically sized header? */
1633#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001634#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001635 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001636 {
1637 zlog_info ("%s: %s sent invalid length, %lu",
1638 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001639 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001640 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001641
paul718e3742002-12-13 20:15:29 +00001642 /* Load AFI, SAFI. */
1643 afi = stream_getw (s);
1644 safi = stream_getc (s);
1645
1646 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001647 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001648
Paul Jakma03292802008-06-07 20:37:10 +00001649 if (LEN_LEFT < attre->mp_nexthop_len)
1650 {
1651 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1652 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001653 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001654 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001655
paul718e3742002-12-13 20:15:29 +00001656 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001657 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001658 {
1659 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001660 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001661 /* Probably needed for RFC 2283 */
1662 if (attr->nexthop.s_addr == 0)
1663 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001664 break;
1665 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001666 stream_getl (s); /* RD high */
1667 stream_getl (s); /* RD low */
1668 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001669 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001670 case 24:
1671 {
1672 u_int32_t rd_high __attribute__((unused));
1673 u_int32_t rd_low __attribute__((unused));
1674
1675 rd_high = stream_getl (s);
1676 rd_low = stream_getl (s);
1677 }
1678 /* fall through */
paul718e3742002-12-13 20:15:29 +00001679 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001680 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001681 break;
1682 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001683 case 48:
1684 if (attre->mp_nexthop_len == 48) {
1685 u_int32_t rd_high __attribute__((unused));
1686 u_int32_t rd_low __attribute__((unused));
1687
1688 rd_high = stream_getl (s);
1689 rd_low = stream_getl (s);
1690 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001691 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001692
1693 if (attre->mp_nexthop_len == 48) {
1694 u_int32_t rd_high __attribute__((unused));
1695 u_int32_t rd_low __attribute__((unused));
1696
1697 rd_high = stream_getl (s);
1698 rd_low = stream_getl (s);
1699 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001700 stream_get (&attre->mp_nexthop_local, s, 16);
1701 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001702 {
1703 char buf1[INET6_ADDRSTRLEN];
1704 char buf2[INET6_ADDRSTRLEN];
1705
1706 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001707 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 +00001708 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001709 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001710 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001711 buf2, INET6_ADDRSTRLEN));
1712
Paul Jakmafb982c22007-05-04 20:15:47 +00001713 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001714 }
1715 break;
paul718e3742002-12-13 20:15:29 +00001716 default:
Paul Jakma03292802008-06-07 20:37:10 +00001717 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1718 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001719 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001720 }
1721
Paul Jakma03292802008-06-07 20:37:10 +00001722 if (!LEN_LEFT)
1723 {
1724 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1725 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001726 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001727 }
paul718e3742002-12-13 20:15:29 +00001728
Paul Jakma6e4ab122007-04-10 19:36:48 +00001729 {
1730 u_char val;
1731 if ((val = stream_getc (s)))
1732 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1733 peer->host, val);
1734 }
1735
1736 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001737 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001738 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001739 {
1740 zlog_info ("%s: (%s) Failed to read NLRI",
1741 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001742 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001743 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001744
paul718e3742002-12-13 20:15:29 +00001745 mp_update->afi = afi;
1746 mp_update->safi = safi;
1747 mp_update->nlri = stream_pnt (s);
1748 mp_update->length = nlri_len;
1749
paul9985f832005-02-09 15:51:56 +00001750 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001751
David Lamparterdaefeb82014-12-08 17:42:12 +01001752 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1753
Paul Jakmab881c702010-11-23 16:35:42 +00001754 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001755#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001756}
1757
1758/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001759int
Paul Jakma835315b2012-01-18 12:28:30 +00001760bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001761 struct bgp_nlri *mp_withdraw)
1762{
1763 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001764 afi_t afi;
1765 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001766 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001767 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001768 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001769 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001770
1771 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001772
1773#define BGP_MP_UNREACH_MIN_SIZE 3
1774 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001775 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001776
paul718e3742002-12-13 20:15:29 +00001777 afi = stream_getw (s);
1778 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001779
1780 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001781
paul718e3742002-12-13 20:15:29 +00001782 mp_withdraw->afi = afi;
1783 mp_withdraw->safi = safi;
1784 mp_withdraw->nlri = stream_pnt (s);
1785 mp_withdraw->length = withdraw_len;
1786
paul9985f832005-02-09 15:51:56 +00001787 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001788
David Lamparterdaefeb82014-12-08 17:42:12 +01001789 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1790
Paul Jakmab881c702010-11-23 16:35:42 +00001791 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001792}
1793
1794/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001795static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001796bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001797{
Paul Jakma835315b2012-01-18 12:28:30 +00001798 struct peer *const peer = args->peer;
1799 struct attr *const attr = args->attr;
1800 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001801
paul718e3742002-12-13 20:15:29 +00001802 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001803 {
1804 if (attr->extra)
1805 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001806 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001807 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001808 }
Paul Jakma0c466382010-12-05 17:17:26 +00001809
1810 (bgp_attr_extra_get (attr))->ecommunity =
1811 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1812 /* XXX: fix ecommunity_parse to use stream API */
1813 stream_forward_getp (peer->ibuf, length);
1814
1815 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001816 return bgp_attr_malformed (args,
1817 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1818 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001819
paul718e3742002-12-13 20:15:29 +00001820 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1821
Paul Jakmab881c702010-11-23 16:35:42 +00001822 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001823}
1824
Lou Bergerc3741782016-01-12 13:42:01 -05001825/* Parse Tunnel Encap attribute in an UPDATE */
1826static int
1827bgp_attr_encap(
1828 uint8_t type,
1829 struct peer *peer, /* IN */
1830 bgp_size_t length, /* IN: attr's length field */
1831 struct attr *attr, /* IN: caller already allocated */
1832 u_char flag, /* IN: attr's flags field */
1833 u_char *startp)
1834{
1835 bgp_size_t total;
1836 struct attr_extra *attre = NULL;
1837 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1838 uint16_t tunneltype;
1839
1840 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1841
1842 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1843 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1844 {
1845 zlog (peer->log, LOG_ERR,
1846 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1847 bgp_notify_send_with_data (peer,
1848 BGP_NOTIFY_UPDATE_ERR,
1849 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1850 startp, total);
1851 return -1;
1852 }
1853
1854 if (BGP_ATTR_ENCAP == type) {
1855 /* read outer TLV type and length */
1856 uint16_t tlv_length;
1857
1858 if (length < 4) {
1859 zlog (peer->log, LOG_ERR,
1860 "Tunnel Encap attribute not long enough to contain outer T,L");
1861 bgp_notify_send_with_data(peer,
1862 BGP_NOTIFY_UPDATE_ERR,
1863 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1864 startp, total);
1865 return -1;
1866 }
1867 tunneltype = stream_getw (BGP_INPUT (peer));
1868 tlv_length = stream_getw (BGP_INPUT (peer));
1869 length -= 4;
1870
1871 if (tlv_length != length) {
1872 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1873 __func__, tlv_length, length);
1874 }
1875 }
1876
1877 while (length >= 4) {
Donald Sharp985c3552016-03-10 20:16:47 -05001878 uint16_t subtype = 0;
1879 uint16_t sublength = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05001880 struct bgp_attr_encap_subtlv *tlv;
1881
Lou Berger298cc2f2016-01-12 13:42:02 -05001882 if (BGP_ATTR_ENCAP == type) {
1883 subtype = stream_getc (BGP_INPUT (peer));
1884 sublength = stream_getc (BGP_INPUT (peer));
1885 length -= 2;
1886 }
Lou Bergerc3741782016-01-12 13:42:01 -05001887
1888 if (sublength > length) {
1889 zlog (peer->log, LOG_ERR,
1890 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1891 sublength, length);
1892 bgp_notify_send_with_data (peer,
1893 BGP_NOTIFY_UPDATE_ERR,
1894 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1895 startp, total);
1896 return -1;
1897 }
1898
1899 /* alloc and copy sub-tlv */
1900 /* TBD make sure these are freed when attributes are released */
1901 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1902 tlv->type = subtype;
1903 tlv->length = sublength;
1904 stream_get(tlv->value, peer->ibuf, sublength);
1905 length -= sublength;
1906
1907 /* attach tlv to encap chain */
1908 if (!attre) {
1909 attre = bgp_attr_extra_get(attr);
1910 if (BGP_ATTR_ENCAP == type) {
1911 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1912 stlv_last = stlv_last->next);
1913 if (stlv_last) {
1914 stlv_last->next = tlv;
1915 } else {
1916 attre->encap_subtlvs = tlv;
1917 }
1918 }
1919 } else {
1920 stlv_last->next = tlv;
1921 }
1922 stlv_last = tlv;
1923 }
1924
1925 if (attre && (BGP_ATTR_ENCAP == type)) {
1926 attre->encap_tunneltype = tunneltype;
1927 }
1928
1929 if (length) {
1930 /* spurious leftover data */
1931 zlog (peer->log, LOG_ERR,
1932 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1933 bgp_notify_send_with_data (peer,
1934 BGP_NOTIFY_UPDATE_ERR,
1935 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1936 startp, total);
1937 return -1;
1938 }
1939
1940 return 0;
1941}
1942
paul718e3742002-12-13 20:15:29 +00001943/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001944static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001945bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001946{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001947 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001948 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001949 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001950 struct peer *const peer = args->peer;
1951 struct attr *const attr = args->attr;
1952 u_char *const startp = args->startp;
1953 const u_char type = args->type;
1954 const u_char flag = args->flags;
1955 const bgp_size_t length = args->length;
1956
paul718e3742002-12-13 20:15:29 +00001957
hassof4184462005-02-01 20:13:16 +00001958 if (BGP_DEBUG (normal, NORMAL))
1959 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1960 peer->host, type, length);
1961
paul718e3742002-12-13 20:15:29 +00001962 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001963 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001964 "Unknown attribute type %d length %d is received", type, length);
1965
1966 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001967 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001968
paul718e3742002-12-13 20:15:29 +00001969 /* If any of the mandatory well-known attributes are not recognized,
1970 then the Error Subcode is set to Unrecognized Well-known
1971 Attribute. The Data field contains the unrecognized attribute
1972 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001973 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001974 {
Paul Jakma835315b2012-01-18 12:28:30 +00001975 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001976 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001977 args->total);
paul718e3742002-12-13 20:15:29 +00001978 }
1979
1980 /* Unrecognized non-transitive optional attributes must be quietly
1981 ignored and not passed along to other BGP peers. */
1982 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001983 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001984
1985 /* If a path with recognized transitive optional attribute is
1986 accepted and passed along to other BGP peers and the Partial bit
1987 in the Attribute Flags octet is set to 1 by some previous AS, it
1988 is not set back to 0 by the current AS. */
1989 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1990
1991 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001992 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001993 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001994
Paul Jakmafb982c22007-05-04 20:15:47 +00001995 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001996
1997 if (transit->val)
1998 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1999 transit->length + total);
2000 else
2001 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2002
2003 memcpy (transit->val + transit->length, startp, total);
2004 transit->length += total;
2005
Paul Jakmab881c702010-11-23 16:35:42 +00002006 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002007}
2008
Paul Jakma055086f2014-09-23 15:23:01 +01002009/* Well-known attribute check. */
2010static int
2011bgp_attr_check (struct peer *peer, struct attr *attr)
2012{
2013 u_char type = 0;
2014
Paul Jakmaaed1b552014-10-21 16:59:01 +01002015 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2016 * empty UPDATE. */
2017 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2018 return BGP_ATTR_PARSE_PROCEED;
2019
2020 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2021 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2022 are present, it should. Check for any other attribute being present
2023 instead.
2024 */
2025 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2026 return BGP_ATTR_PARSE_PROCEED;
2027
Paul Jakma055086f2014-09-23 15:23:01 +01002028 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2029 type = BGP_ATTR_ORIGIN;
2030
2031 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2032 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002033
2034 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2035 * NLRI is empty. We can't easily check NLRI empty here though.
2036 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002037 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2038 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002039 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002040
Paul Jakma055086f2014-09-23 15:23:01 +01002041 if (peer->sort == BGP_PEER_IBGP
2042 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2043 type = BGP_ATTR_LOCAL_PREF;
2044
2045 if (type)
2046 {
2047 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002048 "%s Missing well-known attribute %d / %s",
2049 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002050 bgp_notify_send_with_data (peer,
2051 BGP_NOTIFY_UPDATE_ERR,
2052 BGP_NOTIFY_UPDATE_MISS_ATTR,
2053 &type, 1);
2054 return BGP_ATTR_PARSE_ERROR;
2055 }
2056 return BGP_ATTR_PARSE_PROCEED;
2057}
2058
paul718e3742002-12-13 20:15:29 +00002059/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002060 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002061bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002062bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2063 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2064{
2065 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002066 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002067 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002068 bgp_size_t length;
2069 u_char *startp, *endp;
2070 u_char *attr_endp;
2071 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002072 /* we need the as4_path only until we have synthesized the as_path with it */
2073 /* same goes for as4_aggregator */
2074 struct aspath *as4_path = NULL;
2075 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002076 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002077
2078 /* Initialize bitmap. */
2079 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2080
2081 /* End pointer of BGP attribute. */
2082 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002083
paul718e3742002-12-13 20:15:29 +00002084 /* Get attributes to the end of attribute length. */
2085 while (BGP_INPUT_PNT (peer) < endp)
2086 {
2087 /* Check remaining length check.*/
2088 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2089 {
gdtc29fdba2004-12-09 14:46:46 +00002090 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002091 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002092 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002093 peer->host,
2094 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002095
2096 bgp_notify_send (peer,
2097 BGP_NOTIFY_UPDATE_ERR,
2098 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002099 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002100 }
2101
2102 /* Fetch attribute flag and type. */
2103 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002104 /* "The lower-order four bits of the Attribute Flags octet are
2105 unused. They MUST be zero when sent and MUST be ignored when
2106 received." */
2107 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002108 type = stream_getc (BGP_INPUT (peer));
2109
Paul Jakma370b64a2007-12-22 16:49:52 +00002110 /* Check whether Extended-Length applies and is in bounds */
2111 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2112 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2113 {
2114 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002115 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002116 peer->host,
2117 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2118
2119 bgp_notify_send (peer,
2120 BGP_NOTIFY_UPDATE_ERR,
2121 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002122 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002123 }
Paul Jakma835315b2012-01-18 12:28:30 +00002124
paul718e3742002-12-13 20:15:29 +00002125 /* Check extended attribue length bit. */
2126 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2127 length = stream_getw (BGP_INPUT (peer));
2128 else
2129 length = stream_getc (BGP_INPUT (peer));
2130
2131 /* If any attribute appears more than once in the UPDATE
2132 message, then the Error Subcode is set to Malformed Attribute
2133 List. */
2134
2135 if (CHECK_BITMAP (seen, type))
2136 {
2137 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002138 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002139 peer->host, type);
2140
2141 bgp_notify_send (peer,
2142 BGP_NOTIFY_UPDATE_ERR,
2143 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002144 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002145 }
2146
2147 /* Set type to bitmap to check duplicate attribute. `type' is
2148 unsigned char so it never overflow bitmap range. */
2149
2150 SET_BITMAP (seen, type);
2151
2152 /* Overflow check. */
2153 attr_endp = BGP_INPUT_PNT (peer) + length;
2154
2155 if (attr_endp > endp)
2156 {
2157 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002158 "%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 -07002159 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);
2160 bgp_notify_send_with_data (peer,
2161 BGP_NOTIFY_UPDATE_ERR,
2162 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2163 startp, attr_endp - startp);
Paul Jakmab881c702010-11-23 16:35:42 +00002164 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002165 }
Paul Jakma835315b2012-01-18 12:28:30 +00002166
2167 struct bgp_attr_parser_args attr_args = {
2168 .peer = peer,
2169 .length = length,
2170 .attr = attr,
2171 .type = type,
2172 .flags = flag,
2173 .startp = startp,
2174 .total = attr_endp - startp,
2175 };
2176
2177
2178 /* If any recognized attribute has Attribute Flags that conflict
2179 with the Attribute Type Code, then the Error Subcode is set to
2180 Attribute Flags Error. The Data field contains the erroneous
2181 attribute (type, length and value). */
2182 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002183 {
2184 bgp_attr_parse_ret_t ret;
2185 ret = bgp_attr_malformed (&attr_args,
2186 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2187 attr_args.total);
2188 if (ret == BGP_ATTR_PARSE_PROCEED)
2189 continue;
2190 return ret;
2191 }
paul718e3742002-12-13 20:15:29 +00002192
2193 /* OK check attribute and store it's value. */
2194 switch (type)
2195 {
2196 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002197 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002198 break;
2199 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002200 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002201 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002202 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002203 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002204 break;
paul718e3742002-12-13 20:15:29 +00002205 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002206 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002207 break;
2208 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002209 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002210 break;
2211 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002212 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002213 break;
2214 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002215 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002216 break;
2217 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002218 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002219 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002220 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002221 ret = bgp_attr_as4_aggregator (&attr_args,
2222 &as4_aggregator,
2223 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002224 break;
paul718e3742002-12-13 20:15:29 +00002225 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002226 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002227 break;
2228 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002229 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002230 break;
2231 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002232 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002233 break;
2234 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002235 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002236 break;
2237 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002238 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002239 break;
2240 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002241 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002242 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002243 case BGP_ATTR_ENCAP:
2244 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2245 break;
paul718e3742002-12-13 20:15:29 +00002246 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002247 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002248 break;
2249 }
Paul Jakmab881c702010-11-23 16:35:42 +00002250
David Lamparterf57000c2014-06-04 01:01:10 +02002251 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2252 {
2253 bgp_notify_send (peer,
2254 BGP_NOTIFY_UPDATE_ERR,
2255 BGP_NOTIFY_UPDATE_MAL_ATTR);
2256 ret = BGP_ATTR_PARSE_ERROR;
2257 }
2258
Paul Jakmab881c702010-11-23 16:35:42 +00002259 /* If hard error occured immediately return to the caller. */
2260 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002261 {
2262 zlog (peer->log, LOG_WARNING,
2263 "%s: Attribute %s, parse error",
2264 peer->host,
2265 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002266 if (as4_path)
2267 aspath_unintern (&as4_path);
2268 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002269 }
Paul Jakmab881c702010-11-23 16:35:42 +00002270 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2271 {
2272
2273 zlog (peer->log, LOG_WARNING,
2274 "%s: Attribute %s, parse error - treating as withdrawal",
2275 peer->host,
2276 LOOKUP (attr_str, type));
2277 if (as4_path)
2278 aspath_unintern (&as4_path);
2279 return ret;
2280 }
2281
paul718e3742002-12-13 20:15:29 +00002282 /* Check the fetched length. */
2283 if (BGP_INPUT_PNT (peer) != attr_endp)
2284 {
2285 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002286 "%s: BGP attribute %s, fetch error",
2287 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002288 bgp_notify_send (peer,
2289 BGP_NOTIFY_UPDATE_ERR,
2290 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002291 if (as4_path)
2292 aspath_unintern (&as4_path);
2293 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002294 }
2295 }
paul718e3742002-12-13 20:15:29 +00002296 /* Check final read pointer is same as end pointer. */
2297 if (BGP_INPUT_PNT (peer) != endp)
2298 {
2299 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002300 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002301 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002302 bgp_notify_send (peer,
2303 BGP_NOTIFY_UPDATE_ERR,
2304 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002305 if (as4_path)
2306 aspath_unintern (&as4_path);
2307 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002308 }
Paul Jakma055086f2014-09-23 15:23:01 +01002309
2310 /* Check all mandatory well-known attributes are present */
2311 {
2312 bgp_attr_parse_ret_t ret;
2313 if ((ret = bgp_attr_check (peer, attr)) < 0)
2314 {
2315 if (as4_path)
2316 aspath_unintern (&as4_path);
2317 return ret;
2318 }
2319 }
2320
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002321 /*
2322 * At this place we can see whether we got AS4_PATH and/or
2323 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2324 * We can not do this before we've read all attributes because
2325 * the as4 handling does not say whether AS4_PATH has to be sent
2326 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2327 * in relationship to AGGREGATOR.
2328 * So, to be defensive, we are not relying on any order and read
2329 * all attributes first, including these 32bit ones, and now,
2330 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002331 *
2332 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2333 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002334 */
David Lamparterf57000c2014-06-04 01:01:10 +02002335 /* actually... this doesn't ever return failure currently, but
2336 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002337 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2338 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002339 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002340 {
David Lamparterf57000c2014-06-04 01:01:10 +02002341 bgp_notify_send (peer,
2342 BGP_NOTIFY_UPDATE_ERR,
2343 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002344 if (as4_path)
2345 aspath_unintern (&as4_path);
2346 return BGP_ATTR_PARSE_ERROR;
2347 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002348
2349 /* At this stage, we have done all fiddling with as4, and the
2350 * resulting info is in attr->aggregator resp. attr->aspath
2351 * so we can chuck as4_aggregator and as4_path alltogether in
2352 * order to save memory
2353 */
Paul Jakmab881c702010-11-23 16:35:42 +00002354 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002355 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002356 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002357 /* The flag that we got this is still there, but that does not
2358 * do any trouble
2359 */
2360 }
2361 /*
2362 * The "rest" of the code does nothing with as4_aggregator.
2363 * there is no memory attached specifically which is not part
2364 * of the attr.
2365 * so ignoring just means do nothing.
2366 */
2367 /*
2368 * Finally do the checks on the aspath we did not do yet
2369 * because we waited for a potentially synthesized aspath.
2370 */
Paul Jakmab881c702010-11-23 16:35:42 +00002371 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002372 {
Paul Jakma835315b2012-01-18 12:28:30 +00002373 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002374 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002375 return ret;
2376 }
2377
paul718e3742002-12-13 20:15:29 +00002378 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002379 if (attr->extra && attr->extra->transit)
2380 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002381
Paul Jakmab881c702010-11-23 16:35:42 +00002382 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002383}
2384
paul718e3742002-12-13 20:15:29 +00002385int stream_put_prefix (struct stream *, struct prefix *);
2386
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002387size_t
2388bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2389 struct attr *attr)
2390{
2391 size_t sizep;
2392
2393 /* Set extended bit always to encode the attribute length as 2 bytes */
2394 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2395 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2396 sizep = stream_get_endp (s);
2397 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002398
2399 stream_putw (s, afi);
2400 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002401
2402 /* Nexthop */
2403 switch (afi)
2404 {
2405 case AFI_IP:
2406 switch (safi)
2407 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002408 case SAFI_MULTICAST:
2409 stream_putc (s, 4);
2410 stream_put_ipv4 (s, attr->nexthop.s_addr);
2411 break;
2412 case SAFI_MPLS_VPN:
2413 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002414 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002415 stream_putl (s, 0);
2416 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2417 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002418 case SAFI_ENCAP:
2419 stream_putc (s, 4);
2420 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2421 break;
Lou Berger050defe2016-01-12 13:41:59 -05002422 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002423 default:
2424 break;
2425 }
2426 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002427 case AFI_IP6:
2428 switch (safi)
2429 {
2430 case SAFI_UNICAST:
2431 case SAFI_MULTICAST:
2432 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002433 struct attr_extra *attre = attr->extra;
2434
2435 assert (attr->extra);
2436 stream_putc (s, attre->mp_nexthop_len);
2437 stream_put (s, &attre->mp_nexthop_global, 16);
2438 if (attre->mp_nexthop_len == 32)
2439 stream_put (s, &attre->mp_nexthop_local, 16);
2440 }
Lou Berger050defe2016-01-12 13:41:59 -05002441 break;
2442 case SAFI_MPLS_VPN:
2443 {
2444 struct attr_extra *attre = attr->extra;
2445
2446 assert (attr->extra);
2447 if (attre->mp_nexthop_len == 16) {
2448 stream_putc (s, 24);
2449 stream_putl (s, 0); /* RD = 0, per RFC */
2450 stream_putl (s, 0);
2451 stream_put (s, &attre->mp_nexthop_global, 16);
2452 } else if (attre->mp_nexthop_len == 32) {
2453 stream_putc (s, 48);
2454 stream_putl (s, 0); /* RD = 0, per RFC */
2455 stream_putl (s, 0);
2456 stream_put (s, &attre->mp_nexthop_global, 16);
2457 stream_putl (s, 0); /* RD = 0, per RFC */
2458 stream_putl (s, 0);
2459 stream_put (s, &attre->mp_nexthop_local, 16);
2460 }
2461 }
2462 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002463 case SAFI_ENCAP:
2464 assert (attr->extra);
2465 stream_putc (s, 16);
2466 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2467 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002468 default:
2469 break;
2470 }
2471 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002472 default:
2473 break;
2474 }
2475
2476 /* SNPA */
2477 stream_putc (s, 0);
2478 return sizep;
2479}
2480
2481void
2482bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2483 struct prefix *p, struct prefix_rd *prd,
2484 u_char *tag)
2485{
Lou Berger050defe2016-01-12 13:41:59 -05002486 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002487 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002488 /* Tag, RD, Prefix write. */
2489 stream_putc (s, p->prefixlen + 88);
2490 stream_put (s, tag, 3);
2491 stream_put (s, prd->val, 8);
2492 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002493 }
Lou Berger050defe2016-01-12 13:41:59 -05002494 else
2495 stream_put_prefix (s, p);
2496}
2497
2498size_t
2499bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2500{
2501 int size = PSIZE (p->prefixlen);
2502 if (safi == SAFI_MPLS_VPN)
2503 size += 88;
2504 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002505}
2506
Lou Bergerc3741782016-01-12 13:42:01 -05002507/*
2508 * Encodes the tunnel encapsulation attribute
2509 */
2510static void
2511bgp_packet_mpattr_tea(
2512 struct bgp *bgp,
2513 struct peer *peer,
2514 struct stream *s,
2515 struct attr *attr,
2516 uint8_t attrtype)
2517{
2518 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002519 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002520 struct bgp_attr_encap_subtlv *subtlvs;
2521 struct bgp_attr_encap_subtlv *st;
2522 const char *attrname;
2523
2524 if (!attr || !attr->extra)
2525 return;
2526
2527 switch (attrtype) {
2528 case BGP_ATTR_ENCAP:
2529 attrname = "Tunnel Encap";
2530 subtlvs = attr->extra->encap_subtlvs;
2531
2532 /*
2533 * The tunnel encap attr has an "outer" tlv.
2534 * T = tunneltype,
2535 * L = total length of subtlvs,
2536 * V = concatenated subtlvs.
2537 */
2538 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002539 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002540 break;
2541
2542 default:
2543 assert(0);
2544 }
2545
2546
Lou Berger298cc2f2016-01-12 13:42:02 -05002547 /* if no tlvs, don't make attr */
2548 if (subtlvs == NULL)
2549 return;
2550
Lou Bergerc3741782016-01-12 13:42:01 -05002551 /* compute attr length */
2552 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002553 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002554 }
2555
Lou Bergerc3741782016-01-12 13:42:01 -05002556 if (attrlenfield > 0xffff) {
2557 zlog (peer->log, LOG_ERR,
2558 "%s attribute is too long (length=%d), can't send it",
2559 attrname,
2560 attrlenfield);
2561 return;
2562 }
2563
2564 if (attrlenfield > 0xff) {
2565 /* 2-octet length field */
2566 stream_putc (s,
2567 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2568 stream_putc (s, attrtype);
2569 stream_putw (s, attrlenfield & 0xffff);
2570 } else {
2571 /* 1-octet length field */
2572 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2573 stream_putc (s, attrtype);
2574 stream_putc (s, attrlenfield & 0xff);
2575 }
2576
2577 if (attrtype == BGP_ATTR_ENCAP) {
2578 /* write outer T+L */
2579 stream_putw(s, attr->extra->encap_tunneltype);
2580 stream_putw(s, attrlenfield - 4);
2581 }
2582
2583 /* write each sub-tlv */
2584 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002585 if (attrtype == BGP_ATTR_ENCAP) {
2586 stream_putc (s, st->type);
2587 stream_putc (s, st->length);
2588 }
Lou Bergerc3741782016-01-12 13:42:01 -05002589 stream_put (s, st->value, st->length);
2590 }
2591}
2592
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002593void
2594bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2595{
2596 /* Set MP attribute length. Don't count the (2) bytes used to encode
2597 the attr length */
2598 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2599}
2600
paul718e3742002-12-13 20:15:29 +00002601/* Make attribute packet. */
2602bgp_size_t
2603bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002604 struct stream *s, struct attr *attr,
2605 struct prefix *p, afi_t afi, safi_t safi,
2606 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002607{
paulfe69a502005-09-10 16:55:02 +00002608 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002609 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002610 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002611 int send_as4_path = 0;
2612 int send_as4_aggregator = 0;
2613 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002614
2615 if (! bgp)
2616 bgp = bgp_get_default ();
2617
2618 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002619 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002620
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002621 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2622 {
Lou Berger050defe2016-01-12 13:41:59 -05002623 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002624 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2625 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2626 bgp_packet_mpattr_end(s, mpattrlen_pos);
2627 }
2628
paul718e3742002-12-13 20:15:29 +00002629 /* Origin attribute. */
2630 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2631 stream_putc (s, BGP_ATTR_ORIGIN);
2632 stream_putc (s, 1);
2633 stream_putc (s, attr->origin);
2634
2635 /* AS path attribute. */
2636
2637 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002638 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002639 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002640 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002641 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002642 {
2643 aspath = aspath_dup (attr->aspath);
2644
2645 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2646 {
2647 /* Strip the confed info, and then stuff our path CONFED_ID
2648 on the front */
2649 aspath = aspath_delete_confed_seq (aspath);
2650 aspath = aspath_add_seq (aspath, bgp->confed_id);
2651 }
2652 else
2653 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002654 if (peer->change_local_as) {
2655 /* If replace-as is specified, we only use the change_local_as when
2656 advertising routes. */
2657 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2658 aspath = aspath_add_seq (aspath, peer->local_as);
2659 }
paul718e3742002-12-13 20:15:29 +00002660 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002661 } else {
2662 aspath = aspath_add_seq (aspath, peer->local_as);
2663 }
paul718e3742002-12-13 20:15:29 +00002664 }
2665 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002666 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002667 {
2668 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2669 aspath = aspath_dup (attr->aspath);
2670 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2671 }
2672 else
2673 aspath = attr->aspath;
2674
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002675 /* If peer is not AS4 capable, then:
2676 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2677 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2678 * types are in it (i.e. exclude them if they are there)
2679 * AND do this only if there is at least one asnum > 65535 in the path!
2680 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2681 * all ASnums > 65535 to BGP_AS_TRANS
2682 */
paul718e3742002-12-13 20:15:29 +00002683
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002684 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2685 stream_putc (s, BGP_ATTR_AS_PATH);
2686 aspath_sizep = stream_get_endp (s);
2687 stream_putw (s, 0);
2688 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2689
2690 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2691 * in the path
2692 */
2693 if (!use32bit && aspath_has_as4 (aspath))
2694 send_as4_path = 1; /* we'll do this later, at the correct place */
2695
paul718e3742002-12-13 20:15:29 +00002696 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002697 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2698 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002699 {
2700 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2701 stream_putc (s, BGP_ATTR_NEXT_HOP);
2702 stream_putc (s, 4);
2703 if (safi == SAFI_MPLS_VPN)
2704 {
2705 if (attr->nexthop.s_addr == 0)
2706 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2707 else
2708 stream_put_ipv4 (s, attr->nexthop.s_addr);
2709 }
2710 else
2711 stream_put_ipv4 (s, attr->nexthop.s_addr);
2712 }
2713
2714 /* MED attribute. */
2715 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2716 {
2717 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2718 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2719 stream_putc (s, 4);
2720 stream_putl (s, attr->med);
2721 }
2722
2723 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002724 if (peer->sort == BGP_PEER_IBGP ||
2725 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002726 {
2727 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2728 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2729 stream_putc (s, 4);
2730 stream_putl (s, attr->local_pref);
2731 }
2732
2733 /* Atomic aggregate. */
2734 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2735 {
2736 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2737 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2738 stream_putc (s, 0);
2739 }
2740
2741 /* Aggregator. */
2742 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2743 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002744 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002745
2746 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002747 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2748 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002749
2750 if (use32bit)
2751 {
2752 /* AS4 capable peer */
2753 stream_putc (s, 8);
2754 stream_putl (s, attr->extra->aggregator_as);
2755 }
2756 else
2757 {
2758 /* 2-byte AS peer */
2759 stream_putc (s, 6);
2760
2761 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2762 if ( attr->extra->aggregator_as > 65535 )
2763 {
2764 stream_putw (s, BGP_AS_TRANS);
2765
2766 /* we have to send AS4_AGGREGATOR, too.
2767 * we'll do that later in order to send attributes in ascending
2768 * order.
2769 */
2770 send_as4_aggregator = 1;
2771 }
2772 else
2773 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2774 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002775 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002776 }
2777
2778 /* Community attribute. */
2779 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2780 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2781 {
2782 if (attr->community->size * 4 > 255)
2783 {
2784 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2785 stream_putc (s, BGP_ATTR_COMMUNITIES);
2786 stream_putw (s, attr->community->size * 4);
2787 }
2788 else
2789 {
2790 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2791 stream_putc (s, BGP_ATTR_COMMUNITIES);
2792 stream_putc (s, attr->community->size * 4);
2793 }
2794 stream_put (s, attr->community->val, attr->community->size * 4);
2795 }
2796
2797 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002798 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002799 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002800 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002801 {
2802 /* Originator ID. */
2803 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2804 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2805 stream_putc (s, 4);
2806
2807 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002808 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002809 else
2810 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002811
2812 /* Cluster list. */
2813 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2814 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2815
Paul Jakma9eda90c2007-08-30 13:36:17 +00002816 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002817 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002818 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002819 /* If this peer configuration's parent BGP has cluster_id. */
2820 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2821 stream_put_in_addr (s, &bgp->cluster_id);
2822 else
2823 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002824 stream_put (s, attr->extra->cluster->list,
2825 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002826 }
2827 else
2828 {
2829 stream_putc (s, 4);
2830 /* If this peer configuration's parent BGP has cluster_id. */
2831 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2832 stream_put_in_addr (s, &bgp->cluster_id);
2833 else
2834 stream_put_in_addr (s, &bgp->router_id);
2835 }
2836 }
2837
paul718e3742002-12-13 20:15:29 +00002838 /* Extended Communities attribute. */
2839 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2840 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2841 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002842 struct attr_extra *attre = attr->extra;
2843
2844 assert (attre);
2845
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002846 if (peer->sort == BGP_PEER_IBGP
2847 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002848 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002849 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002850 {
2851 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2852 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002853 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002854 }
2855 else
2856 {
2857 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2858 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002859 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002860 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002861 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002862 }
2863 else
2864 {
paul5228ad22004-06-04 17:58:18 +00002865 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002866 int tbit;
2867 int ecom_tr_size = 0;
2868 int i;
2869
Paul Jakmafb982c22007-05-04 20:15:47 +00002870 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002871 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002872 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002873 tbit = *pnt;
2874
2875 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2876 continue;
2877
2878 ecom_tr_size++;
2879 }
2880
2881 if (ecom_tr_size)
2882 {
2883 if (ecom_tr_size * 8 > 255)
2884 {
2885 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2886 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2887 stream_putw (s, ecom_tr_size * 8);
2888 }
2889 else
2890 {
2891 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2892 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2893 stream_putc (s, ecom_tr_size * 8);
2894 }
2895
Paul Jakmafb982c22007-05-04 20:15:47 +00002896 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002897 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002898 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002899 tbit = *pnt;
2900
2901 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2902 continue;
2903
2904 stream_put (s, pnt, 8);
2905 }
2906 }
paul718e3742002-12-13 20:15:29 +00002907 }
paul718e3742002-12-13 20:15:29 +00002908 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002909
2910 if ( send_as4_path )
2911 {
2912 /* If the peer is NOT As4 capable, AND */
2913 /* there are ASnums > 65535 in path THEN
2914 * give out AS4_PATH */
2915
2916 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2917 * path segments!
2918 * Hm, I wonder... confederation things *should* only be at
2919 * the beginning of an aspath, right? Then we should use
2920 * aspath_delete_confed_seq for this, because it is already
2921 * there! (JK)
2922 * Folks, talk to me: what is reasonable here!?
2923 */
2924 aspath = aspath_delete_confed_seq (aspath);
2925
2926 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2927 stream_putc (s, BGP_ATTR_AS4_PATH);
2928 aspath_sizep = stream_get_endp (s);
2929 stream_putw (s, 0);
2930 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2931 }
2932
2933 if (aspath != attr->aspath)
2934 aspath_free (aspath);
2935
2936 if ( send_as4_aggregator )
2937 {
2938 assert (attr->extra);
2939
2940 /* send AS4_AGGREGATOR, at this place */
2941 /* this section of code moved here in order to ensure the correct
2942 * *ascending* order of attributes
2943 */
2944 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2945 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2946 stream_putc (s, 8);
2947 stream_putl (s, attr->extra->aggregator_as);
2948 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2949 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002950
2951 if ((afi == AFI_IP || afi == AFI_IP6) &&
2952 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2953 {
2954 /* Tunnel Encap attribute */
2955 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2956 }
2957
paul718e3742002-12-13 20:15:29 +00002958 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002959 if (attr->extra && attr->extra->transit)
2960 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002961
2962 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002963 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002964}
2965
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002966size_t
2967bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002968{
paul718e3742002-12-13 20:15:29 +00002969 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002970
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002971 /* Set extended bit always to encode the attribute length as 2 bytes */
2972 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002973 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2974
paul9985f832005-02-09 15:51:56 +00002975 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002976 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002977
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002978 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002979 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002980 return attrlen_pnt;
2981}
paul718e3742002-12-13 20:15:29 +00002982
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002983void
2984bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2985 afi_t afi, safi_t safi, struct prefix_rd *prd,
2986 u_char *tag)
2987{
Lou Berger050defe2016-01-12 13:41:59 -05002988 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002989}
paul718e3742002-12-13 20:15:29 +00002990
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002991void
2992bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2993{
Lou Berger050defe2016-01-12 13:41:59 -05002994 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002995}
2996
2997/* Initialization of attribute. */
2998void
paulfe69a502005-09-10 16:55:02 +00002999bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00003000{
paul718e3742002-12-13 20:15:29 +00003001 aspath_init ();
3002 attrhash_init ();
3003 community_init ();
3004 ecommunity_init ();
3005 cluster_init ();
3006 transit_init ();
3007}
3008
Chris Caputo228da422009-07-18 05:44:03 +00003009void
3010bgp_attr_finish (void)
3011{
3012 aspath_finish ();
3013 attrhash_finish ();
3014 community_finish ();
3015 ecommunity_finish ();
3016 cluster_finish ();
3017 transit_finish ();
3018}
3019
paul718e3742002-12-13 20:15:29 +00003020/* Make attribute packet. */
3021void
paula3845922003-10-18 01:30:50 +00003022bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3023 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003024{
3025 unsigned long cp;
3026 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003027 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003028 struct aspath *aspath;
3029
3030 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003031 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003032
3033 /* Place holder of length. */
3034 stream_putw (s, 0);
3035
3036 /* Origin attribute. */
3037 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3038 stream_putc (s, BGP_ATTR_ORIGIN);
3039 stream_putc (s, 1);
3040 stream_putc (s, attr->origin);
3041
3042 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003043
3044 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3045 stream_putc (s, BGP_ATTR_AS_PATH);
3046 aspath_lenp = stream_get_endp (s);
3047 stream_putw (s, 0);
3048
3049 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003050
3051 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003052 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3053 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003054 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003055 )
3056 {
3057 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3058 stream_putc (s, BGP_ATTR_NEXT_HOP);
3059 stream_putc (s, 4);
3060 stream_put_ipv4 (s, attr->nexthop.s_addr);
3061 }
paul718e3742002-12-13 20:15:29 +00003062
3063 /* MED attribute. */
3064 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3065 {
3066 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3067 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3068 stream_putc (s, 4);
3069 stream_putl (s, attr->med);
3070 }
3071
3072 /* Local preference. */
3073 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3074 {
3075 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3076 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3077 stream_putc (s, 4);
3078 stream_putl (s, attr->local_pref);
3079 }
3080
3081 /* Atomic aggregate. */
3082 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3083 {
3084 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3085 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3086 stream_putc (s, 0);
3087 }
3088
3089 /* Aggregator. */
3090 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3091 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003092 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003093 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3094 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003095 stream_putc (s, 8);
3096 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003097 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003098 }
3099
3100 /* Community attribute. */
3101 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3102 {
3103 if (attr->community->size * 4 > 255)
3104 {
3105 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3106 stream_putc (s, BGP_ATTR_COMMUNITIES);
3107 stream_putw (s, attr->community->size * 4);
3108 }
3109 else
3110 {
3111 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3112 stream_putc (s, BGP_ATTR_COMMUNITIES);
3113 stream_putc (s, attr->community->size * 4);
3114 }
3115 stream_put (s, attr->community->val, attr->community->size * 4);
3116 }
3117
paula3845922003-10-18 01:30:50 +00003118 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003119 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3120 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003121 {
3122 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003123 struct attr_extra *attre = attr->extra;
3124
paula3845922003-10-18 01:30:50 +00003125 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3126 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003127 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003128
3129 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003130 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003131 stream_putw(s, AFI_IP6); /* AFI */
3132 stream_putc(s, SAFI_UNICAST); /* SAFI */
3133
3134 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003135 stream_putc(s, attre->mp_nexthop_len);
3136 stream_put(s, &attre->mp_nexthop_global, 16);
3137 if (attre->mp_nexthop_len == 32)
3138 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003139
3140 /* SNPA */
3141 stream_putc(s, 0);
3142
3143 /* Prefix */
3144 stream_put_prefix(s, prefix);
3145
3146 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003147 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003148 }
paula3845922003-10-18 01:30:50 +00003149
paul718e3742002-12-13 20:15:29 +00003150 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003151 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003152 stream_putw_at (s, cp, len);
3153}