blob: d74e0efc7f72d00f578739d4891e06d7fb4157b2 [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);
Paul Jakmafb982c22007-05-04 20:15:47 +0000498 }
499
paul718e3742002-12-13 20:15:29 +0000500 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700501 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000502 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700503 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000504
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000505 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000506 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000507 if (extra->ecommunity)
508 MIX(ecommunity_hash_make (extra->ecommunity));
509 if (extra->cluster)
510 MIX(cluster_hash_key_make (extra->cluster));
511 if (extra->transit)
512 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000513
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000514 MIX(extra->mp_nexthop_len);
515 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
516 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
Paul Jakmafb982c22007-05-04 20:15:47 +0000517 }
paul718e3742002-12-13 20:15:29 +0000518
519 return key;
520}
521
522int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100523attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000524{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100525 const struct attr * attr1 = p1;
526 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000527
paul718e3742002-12-13 20:15:29 +0000528 if (attr1->flag == attr2->flag
529 && attr1->origin == attr2->origin
530 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000531 && attr1->aspath == attr2->aspath
532 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000533 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000534 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000535 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100536 const struct attr_extra *ae1 = attr1->extra;
537 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000538
539 if (ae1 && ae2
540 && ae1->aggregator_as == ae2->aggregator_as
541 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
542 && ae1->weight == ae2->weight
Paul Jakmafb982c22007-05-04 20:15:47 +0000543 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
544 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
545 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
Paul Jakmafb982c22007-05-04 20:15:47 +0000546 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
547 && ae1->ecommunity == ae2->ecommunity
548 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000549 && ae1->transit == ae2->transit
Lou Bergerc3741782016-01-12 13:42:01 -0500550 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
551 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000552 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000553 return 1;
554 else if (ae1 || ae2)
555 return 0;
556 /* neither attribute has extra attributes, so they're same */
557 return 1;
558 }
paul718e3742002-12-13 20:15:29 +0000559 else
560 return 0;
561}
562
paul94f2b392005-06-28 12:44:16 +0000563static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100564attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000565{
566 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
567}
568
Lou Berger056f3762013-04-10 12:30:04 -0700569/*
570 * special for hash_clean below
571 */
572static void
573attr_vfree (void *attr)
574{
575 bgp_attr_extra_free ((struct attr *)attr);
576 XFREE (MTYPE_ATTR, attr);
577}
578
paul94f2b392005-06-28 12:44:16 +0000579static void
Chris Caputo228da422009-07-18 05:44:03 +0000580attrhash_finish (void)
581{
Lou Berger056f3762013-04-10 12:30:04 -0700582 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000583 hash_free (attrhash);
584 attrhash = NULL;
585}
586
587static void
paul718e3742002-12-13 20:15:29 +0000588attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
589{
590 struct attr *attr = backet->data;
591
592 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
593 inet_ntoa (attr->nexthop), VTY_NEWLINE);
594}
595
596void
597attr_show_all (struct vty *vty)
598{
599 hash_iterate (attrhash,
600 (void (*)(struct hash_backet *, void *))
601 attr_show_all_iterator,
602 vty);
603}
604
paul94f2b392005-06-28 12:44:16 +0000605static void *
Paul Jakma923de652007-04-29 18:25:17 +0000606bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000607{
Paul Jakma923de652007-04-29 18:25:17 +0000608 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000609 struct attr *attr;
610
611 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
612 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000613 if (val->extra)
614 {
615 attr->extra = bgp_attr_extra_new ();
616 *attr->extra = *val->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500617
618 if (attr->extra->encap_subtlvs) {
619 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
620 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000621 }
paul718e3742002-12-13 20:15:29 +0000622 attr->refcnt = 0;
623 return attr;
624}
625
626/* Internet argument attribute. */
627struct attr *
628bgp_attr_intern (struct attr *attr)
629{
630 struct attr *find;
631
632 /* Intern referenced strucutre. */
633 if (attr->aspath)
634 {
635 if (! attr->aspath->refcnt)
636 attr->aspath = aspath_intern (attr->aspath);
637 else
638 attr->aspath->refcnt++;
639 }
640 if (attr->community)
641 {
642 if (! attr->community->refcnt)
643 attr->community = community_intern (attr->community);
644 else
645 attr->community->refcnt++;
646 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000647 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000648 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000649 struct attr_extra *attre = attr->extra;
650
651 if (attre->ecommunity)
652 {
653 if (! attre->ecommunity->refcnt)
654 attre->ecommunity = ecommunity_intern (attre->ecommunity);
655 else
656 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000657
Paul Jakmafb982c22007-05-04 20:15:47 +0000658 }
659 if (attre->cluster)
660 {
661 if (! attre->cluster->refcnt)
662 attre->cluster = cluster_intern (attre->cluster);
663 else
664 attre->cluster->refcnt++;
665 }
666 if (attre->transit)
667 {
668 if (! attre->transit->refcnt)
669 attre->transit = transit_intern (attre->transit);
670 else
671 attre->transit->refcnt++;
672 }
paul718e3742002-12-13 20:15:29 +0000673 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000674
paul718e3742002-12-13 20:15:29 +0000675 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
676 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000677
paul718e3742002-12-13 20:15:29 +0000678 return find;
679}
680
Paul Jakma03e214c2007-04-29 18:31:07 +0000681
paul718e3742002-12-13 20:15:29 +0000682/* Make network statement's attribute. */
683struct attr *
684bgp_attr_default_set (struct attr *attr, u_char origin)
685{
686 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000687 bgp_attr_extra_get (attr);
688
paul718e3742002-12-13 20:15:29 +0000689 attr->origin = origin;
690 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
691 attr->aspath = aspath_empty ();
692 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000693 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000694 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
Paul Jakmafb982c22007-05-04 20:15:47 +0000695 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
Paul Jakma03e214c2007-04-29 18:31:07 +0000696
paul718e3742002-12-13 20:15:29 +0000697 return attr;
698}
699
Paul Jakma03e214c2007-04-29 18:31:07 +0000700
paul718e3742002-12-13 20:15:29 +0000701/* Make network statement's attribute. */
702struct attr *
703bgp_attr_default_intern (u_char origin)
704{
705 struct attr attr;
706 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000707
Lou Bergerc3741782016-01-12 13:42:01 -0500708 memset (&attr, 0, sizeof (struct attr));
709 bgp_attr_extra_get (&attr);
710
Paul Jakma03e214c2007-04-29 18:31:07 +0000711 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000712
713 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000714 bgp_attr_extra_free (&attr);
715
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000716 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000717 return new;
718}
719
720struct attr *
721bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
722 struct aspath *aspath,
723 struct community *community, int as_set)
724{
725 struct attr attr;
726 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000727 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000728
729 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000730 memset (&attre, 0, sizeof (struct attr_extra));
731 attr.extra = &attre;
732
paul718e3742002-12-13 20:15:29 +0000733 /* Origin attribute. */
734 attr.origin = origin;
735 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
736
737 /* AS path attribute. */
738 if (aspath)
739 attr.aspath = aspath_intern (aspath);
740 else
741 attr.aspath = aspath_empty ();
742 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
743
744 /* Next hop attribute. */
745 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
746
747 if (community)
748 {
749 attr.community = community;
750 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
751 }
752
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000753 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000754 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
Lou Berger205e6742016-01-12 13:42:11 -0500755
paul718e3742002-12-13 20:15:29 +0000756 if (! as_set)
757 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
758 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
759 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000760 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000761 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000762 attre.aggregator_as = bgp->as;
763 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000764
765 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000766
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000767 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000768 return new;
769}
770
Paul Jakmab881c702010-11-23 16:35:42 +0000771/* Unintern just the sub-components of the attr, but not the attr */
772void
773bgp_attr_unintern_sub (struct attr *attr)
774{
775 /* aspath refcount shoud be decrement. */
776 if (attr->aspath)
777 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000778 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000779
780 if (attr->community)
781 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000782 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000783
784 if (attr->extra)
785 {
786 if (attr->extra->ecommunity)
787 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000788 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000789
790 if (attr->extra->cluster)
791 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000792 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000793
794 if (attr->extra->transit)
795 transit_unintern (attr->extra->transit);
796 }
797}
798
paul718e3742002-12-13 20:15:29 +0000799/* Free bgp attribute and aspath. */
800void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000801bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000802{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000803 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000804 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000805 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000806 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000807
paul718e3742002-12-13 20:15:29 +0000808 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000809 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000810
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000811 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000812
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000813 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000814 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000815 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000816 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000817 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000818
paul718e3742002-12-13 20:15:29 +0000819 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000820 if (attr->refcnt == 0)
821 {
822 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000823 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000824 bgp_attr_extra_free (attr);
825 XFREE (MTYPE_ATTR, attr);
826 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000827 }
828
Paul Jakmab881c702010-11-23 16:35:42 +0000829 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000830}
831
832void
833bgp_attr_flush (struct attr *attr)
834{
835 if (attr->aspath && ! attr->aspath->refcnt)
836 aspath_free (attr->aspath);
837 if (attr->community && ! attr->community->refcnt)
838 community_free (attr->community);
Paul Jakmafb982c22007-05-04 20:15:47 +0000839 if (attr->extra)
840 {
841 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000842
Paul Jakmafb982c22007-05-04 20:15:47 +0000843 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000844 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000845 if (attre->cluster && ! attre->cluster->refcnt)
846 cluster_free (attre->cluster);
847 if (attre->transit && ! attre->transit->refcnt)
848 transit_free (attre->transit);
Lou Bergerc3741782016-01-12 13:42:01 -0500849 encap_free(attre->encap_subtlvs);
850 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000851 }
paul718e3742002-12-13 20:15:29 +0000852}
853
Paul Jakmab881c702010-11-23 16:35:42 +0000854/* Implement draft-scudder-idr-optional-transitive behaviour and
855 * avoid resetting sessions for malformed attributes which are
856 * are partial/optional and hence where the error likely was not
857 * introduced by the sending neighbour.
858 */
859static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000860bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
861 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000862{
Paul Jakma835315b2012-01-18 12:28:30 +0000863 struct peer *const peer = args->peer;
864 const u_int8_t flags = args->flags;
865 /* startp and length must be special-cased, as whether or not to
866 * send the attribute data with the NOTIFY depends on the error,
867 * the caller therefore signals this with the seperate length argument
868 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000869 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000870
Paul Jakmab881c702010-11-23 16:35:42 +0000871 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000872 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000873 {
874 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000875 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000876 return BGP_ATTR_PARSE_ERROR;
877
878 }
879
Paul Jakmabd471fe2012-03-15 11:30:00 +0000880 /* Adjust the stream getp to the end of the attribute, in case we can
881 * still proceed but the caller hasn't read all the attribute.
882 */
883 stream_set_getp (BGP_INPUT (peer),
884 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
885 + args->total);
886
Paul Jakma835315b2012-01-18 12:28:30 +0000887 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100888 /* where an attribute is relatively inconsequential, e.g. it does not
889 * affect route selection, and can be safely ignored, then any such
890 * attributes which are malformed should just be ignored and the route
891 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000892 */
893 case BGP_ATTR_AS4_AGGREGATOR:
894 case BGP_ATTR_AGGREGATOR:
895 case BGP_ATTR_ATOMIC_AGGREGATE:
896 return BGP_ATTR_PARSE_PROCEED;
897
898 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100899 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000900 */
901 case BGP_ATTR_ORIGIN:
902 case BGP_ATTR_AS_PATH:
903 case BGP_ATTR_NEXT_HOP:
904 case BGP_ATTR_MULTI_EXIT_DISC:
905 case BGP_ATTR_LOCAL_PREF:
906 case BGP_ATTR_COMMUNITIES:
907 case BGP_ATTR_ORIGINATOR_ID:
908 case BGP_ATTR_CLUSTER_LIST:
909 case BGP_ATTR_MP_REACH_NLRI:
910 case BGP_ATTR_MP_UNREACH_NLRI:
911 case BGP_ATTR_EXT_COMMUNITIES:
912 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000913 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000914 return BGP_ATTR_PARSE_ERROR;
915 }
916
917 /* Partial optional attributes that are malformed should not cause
918 * the whole session to be reset. Instead treat it as a withdrawal
919 * of the routes, if possible.
920 */
Paul Jakma835315b2012-01-18 12:28:30 +0000921 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
922 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
923 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000924 return BGP_ATTR_PARSE_WITHDRAW;
925
926 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200927 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000928}
929
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400930/* Find out what is wrong with the path attribute flag bits and log the error.
931 "Flag bits" here stand for Optional, Transitive and Partial, but not for
932 Extended Length. Checking O/T/P bits at once implies, that the attribute
933 being diagnosed is defined by RFC as either a "well-known" or an "optional,
934 non-transitive" attribute. */
935static void
Paul Jakma835315b2012-01-18 12:28:30 +0000936bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
937 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400938)
939{
940 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000941 u_char real_flags = args->flags;
942 const u_int8_t attr_code = args->type;
943
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400944 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
945 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
946 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
947 if
948 (
949 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
950 CHECK_FLAG (real_flags, attr_flag_str[i].key)
951 )
952 {
Paul Jakma835315b2012-01-18 12:28:30 +0000953 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400954 LOOKUP (attr_str, attr_code),
955 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
956 attr_flag_str[i].str);
957 seen = 1;
958 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100959 if (!seen)
960 {
961 zlog (args->peer->log, LOG_DEBUG,
962 "Strange, %s called for attr %s, but no problem found with flags"
963 " (real flags 0x%x, desired 0x%x)",
964 __func__, LOOKUP (attr_str, attr_code),
965 real_flags, desired_flags);
966 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400967}
968
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000969/* Required flags for attributes. EXTLEN will be masked off when testing,
970 * as will PARTIAL for optional+transitive attributes.
971 */
972const u_int8_t attr_flags_values [] = {
973 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
974 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
975 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
976 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
977 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
978 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
979 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
980 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
981 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
982 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
983 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
984 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
985 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
986 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
987 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
988};
989static const size_t attr_flags_values_max =
990 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
991
992static int
Paul Jakma835315b2012-01-18 12:28:30 +0000993bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000994{
995 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +0000996 const u_int8_t flags = args->flags;
997 const u_int8_t attr_code = args->type;
998 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000999
1000 /* there may be attributes we don't know about */
1001 if (attr_code > attr_flags_values_max)
1002 return 0;
1003 if (attr_flags_values[attr_code] == 0)
1004 return 0;
1005
1006 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1007 * 1."
1008 */
1009 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1010 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1011 {
1012 zlog (peer->log, LOG_ERR,
1013 "%s well-known attributes must have transitive flag set (%x)",
1014 LOOKUP (attr_str, attr_code), flags);
1015 return 1;
1016 }
1017
1018 /* "For well-known attributes and for optional non-transitive attributes,
1019 * the Partial bit MUST be set to 0."
1020 */
1021 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1022 {
1023 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1024 {
1025 zlog (peer->log, LOG_ERR,
1026 "%s well-known attribute "
1027 "must NOT have the partial flag set (%x)",
1028 LOOKUP (attr_str, attr_code), flags);
1029 return 1;
1030 }
1031 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1032 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1033 {
1034 zlog (peer->log, LOG_ERR,
1035 "%s optional + transitive attribute "
1036 "must NOT have the partial flag set (%x)",
1037 LOOKUP (attr_str, attr_code), flags);
1038 return 1;
1039 }
1040 }
1041
1042 /* Optional transitive attributes may go through speakers that don't
1043 * reocgnise them and set the Partial bit.
1044 */
1045 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1046 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1047 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1048
Paul Jakma683f2b82012-03-23 14:58:45 +00001049 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001050 == attr_flags_values[attr_code])
1051 return 0;
1052
Paul Jakma835315b2012-01-18 12:28:30 +00001053 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001054 return 1;
1055}
1056
paul718e3742002-12-13 20:15:29 +00001057/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001058static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001059bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001060{
Paul Jakma835315b2012-01-18 12:28:30 +00001061 struct peer *const peer = args->peer;
1062 struct attr *const attr = args->attr;
1063 const bgp_size_t length = args->length;
1064
paul718e3742002-12-13 20:15:29 +00001065 /* If any recognized attribute has Attribute Length that conflicts
1066 with the expected length (based on the attribute type code), then
1067 the Error Subcode is set to Attribute Length Error. The Data
1068 field contains the erroneous attribute (type, length and
1069 value). */
1070 if (length != 1)
1071 {
1072 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1073 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001074 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001075 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001076 args->total);
paul718e3742002-12-13 20:15:29 +00001077 }
1078
1079 /* Fetch origin attribute. */
1080 attr->origin = stream_getc (BGP_INPUT (peer));
1081
1082 /* If the ORIGIN attribute has an undefined value, then the Error
1083 Subcode is set to Invalid Origin Attribute. The Data field
1084 contains the unrecognized attribute (type, length and value). */
1085 if ((attr->origin != BGP_ORIGIN_IGP)
1086 && (attr->origin != BGP_ORIGIN_EGP)
1087 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1088 {
1089 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1090 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001091 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001092 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001093 args->total);
paul718e3742002-12-13 20:15:29 +00001094 }
1095
1096 /* Set oring attribute flag. */
1097 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1098
1099 return 0;
1100}
Paul Jakmaab005292010-11-27 22:48:34 +00001101
1102/* Parse AS path information. This function is wrapper of
1103 aspath_parse. */
1104static int
Paul Jakma835315b2012-01-18 12:28:30 +00001105bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001106{
Paul Jakma835315b2012-01-18 12:28:30 +00001107 struct attr *const attr = args->attr;
1108 struct peer *const peer = args->peer;
1109 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001110
Paul Jakmaab005292010-11-27 22:48:34 +00001111 /*
1112 * peer with AS4 => will get 4Byte ASnums
1113 * otherwise, will get 16 Bit
1114 */
1115 attr->aspath = aspath_parse (peer->ibuf, length,
1116 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1117
1118 /* In case of IBGP, length will be zero. */
1119 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001120 {
Paul Jakmab881c702010-11-23 16:35:42 +00001121 zlog (peer->log, LOG_ERR,
1122 "Malformed AS path from %s, length is %d",
1123 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001124 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001125 }
Chris Hallcddb8112010-08-09 22:31:37 +04001126
Paul Jakmaab005292010-11-27 22:48:34 +00001127 /* Set aspath attribute flag. */
1128 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001129
Paul Jakmab881c702010-11-23 16:35:42 +00001130 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001131}
1132
Paul Jakmab881c702010-11-23 16:35:42 +00001133static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001134bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001135{
1136 /* These checks were part of bgp_attr_aspath, but with
1137 * as4 we should to check aspath things when
1138 * aspath synthesizing with as4_path has already taken place.
1139 * Otherwise we check ASPATH and use the synthesized thing, and that is
1140 * not right.
1141 * So do the checks later, i.e. here
1142 */
1143 struct bgp *bgp = peer->bgp;
1144 struct aspath *aspath;
1145
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001146 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001147 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1148 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001149 {
1150 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001151 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1152 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1153 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001154 }
1155
paul718e3742002-12-13 20:15:29 +00001156 /* First AS check for EBGP. */
1157 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1158 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001159 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001160 && ! aspath_firstas_check (attr->aspath, peer->as))
1161 {
1162 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001163 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001164 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1165 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1166 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001167 }
1168 }
1169
1170 /* local-as prepend */
1171 if (peer->change_local_as &&
1172 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1173 {
1174 aspath = aspath_dup (attr->aspath);
1175 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001176 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001177 attr->aspath = aspath_intern (aspath);
1178 }
1179
Paul Jakmab881c702010-11-23 16:35:42 +00001180 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001181}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001182
Paul Jakmaab005292010-11-27 22:48:34 +00001183/* Parse AS4 path information. This function is another wrapper of
1184 aspath_parse. */
1185static int
Paul Jakma835315b2012-01-18 12:28:30 +00001186bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001187{
Paul Jakma835315b2012-01-18 12:28:30 +00001188 struct peer *const peer = args->peer;
1189 struct attr *const attr = args->attr;
1190 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001191
Paul Jakmaab005292010-11-27 22:48:34 +00001192 *as4_path = aspath_parse (peer->ibuf, length, 1);
1193
Paul Jakmab881c702010-11-23 16:35:42 +00001194 /* In case of IBGP, length will be zero. */
1195 if (!*as4_path)
1196 {
1197 zlog (peer->log, LOG_ERR,
1198 "Malformed AS4 path from %s, length is %d",
1199 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001200 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001201 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001202 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001203 }
1204
Paul Jakmaab005292010-11-27 22:48:34 +00001205 /* Set aspath attribute flag. */
1206 if (as4_path)
1207 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1208
Paul Jakmab881c702010-11-23 16:35:42 +00001209 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001210}
1211
paul718e3742002-12-13 20:15:29 +00001212/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001213static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001214bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001215{
Paul Jakma835315b2012-01-18 12:28:30 +00001216 struct peer *const peer = args->peer;
1217 struct attr *const attr = args->attr;
1218 const bgp_size_t length = args->length;
1219
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001220 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001221
paul718e3742002-12-13 20:15:29 +00001222 /* Check nexthop attribute length. */
1223 if (length != 4)
1224 {
1225 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1226 length);
1227
Paul Jakma835315b2012-01-18 12:28:30 +00001228 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001229 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001230 args->total);
paul718e3742002-12-13 20:15:29 +00001231 }
1232
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001233 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1234 attribute must result in a NOTIFICATION message (this is implemented below).
1235 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1236 logged locally (this is implemented somewhere else). The UPDATE message
1237 gets ignored in any of these cases. */
1238 nexthop_n = stream_get_ipv4 (peer->ibuf);
1239 nexthop_h = ntohl (nexthop_n);
1240 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1241 {
1242 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001243 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001244 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001245 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001246 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001247 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001248 }
1249
1250 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001251 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1252
Paul Jakmab881c702010-11-23 16:35:42 +00001253 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001254}
1255
1256/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001257static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001258bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001259{
Paul Jakma835315b2012-01-18 12:28:30 +00001260 struct peer *const peer = args->peer;
1261 struct attr *const attr = args->attr;
1262 const bgp_size_t length = args->length;
1263
paul718e3742002-12-13 20:15:29 +00001264 /* Length check. */
1265 if (length != 4)
1266 {
1267 zlog (peer->log, LOG_ERR,
1268 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001269
Paul Jakma835315b2012-01-18 12:28:30 +00001270 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001271 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001272 args->total);
paul718e3742002-12-13 20:15:29 +00001273 }
1274
1275 attr->med = stream_getl (peer->ibuf);
1276
1277 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1278
Paul Jakmab881c702010-11-23 16:35:42 +00001279 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001280}
1281
1282/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001283static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001284bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001285{
Paul Jakma835315b2012-01-18 12:28:30 +00001286 struct peer *const peer = args->peer;
1287 struct attr *const attr = args->attr;
1288 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001289
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001290 /* Length check. */
1291 if (length != 4)
1292 {
Paul Jakma835315b2012-01-18 12:28:30 +00001293 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1294 length);
1295 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001296 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001297 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001298 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001299
paul718e3742002-12-13 20:15:29 +00001300 /* If it is contained in an UPDATE message that is received from an
1301 external peer, then this attribute MUST be ignored by the
1302 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001303 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001304 {
paul9985f832005-02-09 15:51:56 +00001305 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001306 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001307 }
1308
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001309 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001310
1311 /* Set atomic aggregate flag. */
1312 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1313
Paul Jakmab881c702010-11-23 16:35:42 +00001314 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001315}
1316
1317/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001318static int
Paul Jakma835315b2012-01-18 12:28:30 +00001319bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001320{
Paul Jakma835315b2012-01-18 12:28:30 +00001321 struct peer *const peer = args->peer;
1322 struct attr *const attr = args->attr;
1323 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001324
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001325 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001326 if (length != 0)
1327 {
Paul Jakma835315b2012-01-18 12:28:30 +00001328 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1329 length);
1330 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001331 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001332 args->total);
paul718e3742002-12-13 20:15:29 +00001333 }
1334
1335 /* Set atomic aggregate flag. */
1336 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1337
Paul Jakmab881c702010-11-23 16:35:42 +00001338 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001339}
1340
1341/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001342static int
Paul Jakma835315b2012-01-18 12:28:30 +00001343bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001344{
Paul Jakma835315b2012-01-18 12:28:30 +00001345 struct peer *const peer = args->peer;
1346 struct attr *const attr = args->attr;
1347 const bgp_size_t length = args->length;
1348
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001349 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001350 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001351
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001352 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001353 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001354 wantedlen = 8;
1355
1356 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001357 {
Paul Jakma835315b2012-01-18 12:28:30 +00001358 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1359 wantedlen, length);
1360 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001361 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001362 args->total);
paul718e3742002-12-13 20:15:29 +00001363 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001364
1365 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1366 attre->aggregator_as = stream_getl (peer->ibuf);
1367 else
1368 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001369 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001370
1371 /* Set atomic aggregate flag. */
1372 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1373
Paul Jakmab881c702010-11-23 16:35:42 +00001374 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001375}
1376
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001377/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001378static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001379bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1380 as_t *as4_aggregator_as,
1381 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001382{
Paul Jakma835315b2012-01-18 12:28:30 +00001383 struct peer *const peer = args->peer;
1384 struct attr *const attr = args->attr;
1385 const bgp_size_t length = args->length;
1386
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001387 if (length != 8)
1388 {
Paul Jakma835315b2012-01-18 12:28:30 +00001389 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1390 length);
1391 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001392 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001393 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001394 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001395
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001396 *as4_aggregator_as = stream_getl (peer->ibuf);
1397 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1398
1399 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1400
Paul Jakmab881c702010-11-23 16:35:42 +00001401 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001402}
1403
1404/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1405 */
Paul Jakmab881c702010-11-23 16:35:42 +00001406static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001407bgp_attr_munge_as4_attrs (struct peer *const peer,
1408 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001409 struct aspath *as4_path, as_t as4_aggregator,
1410 struct in_addr *as4_aggregator_addr)
1411{
1412 int ignore_as4_path = 0;
1413 struct aspath *newpath;
1414 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001415
1416 if (!attr->aspath)
1417 {
1418 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1419 * checked that all well-known, mandatory attributes were present.
1420 *
1421 * Can only be a problem with peer itself - hard error
1422 */
1423 return BGP_ATTR_PARSE_ERROR;
1424 }
1425
Paul Jakmab881c702010-11-23 16:35:42 +00001426 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001427 {
1428 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1429 * if given.
1430 * It is worth a warning though, because the peer really
1431 * should not send them
1432 */
1433 if (BGP_DEBUG(as4, AS4))
1434 {
1435 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1436 zlog_debug ("[AS4] %s %s AS4_PATH",
1437 peer->host, "AS4 capable peer, yet it sent");
1438
1439 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1440 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1441 peer->host, "AS4 capable peer, yet it sent");
1442 }
1443
Paul Jakmab881c702010-11-23 16:35:42 +00001444 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001445 }
1446
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001447 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1448 * because that may override AS4_PATH
1449 */
1450 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1451 {
Paul Jakmab881c702010-11-23 16:35:42 +00001452 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001453 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001454 assert (attre);
1455
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001456 /* received both.
1457 * if the as_number in aggregator is not AS_TRANS,
1458 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1459 * and the Aggregator shall be taken as
1460 * info on the aggregating node, and the AS_PATH
1461 * shall be taken as the AS_PATH
1462 * otherwise
1463 * the Aggregator shall be ignored and the
1464 * AS4_AGGREGATOR shall be taken as the
1465 * Aggregating node and the AS_PATH is to be
1466 * constructed "as in all other cases"
1467 */
Paul Jakmab881c702010-11-23 16:35:42 +00001468 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001469 {
1470 /* ignore */
1471 if ( BGP_DEBUG(as4, AS4))
1472 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1473 " send AGGREGATOR != AS_TRANS and"
1474 " AS4_AGGREGATOR, so ignore"
1475 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1476 ignore_as4_path = 1;
1477 }
1478 else
1479 {
1480 /* "New_aggregator shall be taken as aggregator" */
1481 attre->aggregator_as = as4_aggregator;
1482 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1483 }
1484 }
1485 else
1486 {
1487 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1488 * That is bogus - but reading the conditions
1489 * we have to handle AS4_AGGREGATOR as if it were
1490 * AGGREGATOR in that case
1491 */
1492 if ( BGP_DEBUG(as4, AS4))
1493 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1494 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1495 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001496 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001497 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1498 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1499 }
1500 }
1501
1502 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001503 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001504 {
Paul Jakma055086f2014-09-23 15:23:01 +01001505 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1506 aspath_unintern (&attr->aspath);
1507 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001508 }
Paul Jakmab881c702010-11-23 16:35:42 +00001509 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001510}
1511
paul718e3742002-12-13 20:15:29 +00001512/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001513static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001514bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001515{
Paul Jakma835315b2012-01-18 12:28:30 +00001516 struct peer *const peer = args->peer;
1517 struct attr *const attr = args->attr;
1518 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001519
paul718e3742002-12-13 20:15:29 +00001520 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001521 {
1522 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001523 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001524 }
Paul Jakma0c466382010-12-05 17:17:26 +00001525
1526 attr->community =
1527 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1528
1529 /* XXX: fix community_parse to use stream API and remove this */
1530 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001531
Paul Jakma0c466382010-12-05 17:17:26 +00001532 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001533 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001534 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001535 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001536
paul718e3742002-12-13 20:15:29 +00001537 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1538
Paul Jakmab881c702010-11-23 16:35:42 +00001539 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001540}
1541
1542/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001543static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001544bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001545{
Paul Jakma835315b2012-01-18 12:28:30 +00001546 struct peer *const peer = args->peer;
1547 struct attr *const attr = args->attr;
1548 const bgp_size_t length = args->length;
1549
Denis Ovsienkod595b562011-09-30 15:08:54 +04001550 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001551 if (length != 4)
1552 {
1553 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1554
Paul Jakma835315b2012-01-18 12:28:30 +00001555 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001556 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001557 args->total);
paul718e3742002-12-13 20:15:29 +00001558 }
1559
Paul Jakmafb982c22007-05-04 20:15:47 +00001560 (bgp_attr_extra_get (attr))->originator_id.s_addr
1561 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001562
1563 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1564
Paul Jakmab881c702010-11-23 16:35:42 +00001565 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001566}
1567
1568/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001569static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001570bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001571{
Paul Jakma835315b2012-01-18 12:28:30 +00001572 struct peer *const peer = args->peer;
1573 struct attr *const attr = args->attr;
1574 const bgp_size_t length = args->length;
1575
paul718e3742002-12-13 20:15:29 +00001576 /* Check length. */
1577 if (length % 4)
1578 {
1579 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1580
Paul Jakma835315b2012-01-18 12:28:30 +00001581 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1582 args->total);
paul718e3742002-12-13 20:15:29 +00001583 }
1584
Paul Jakmafb982c22007-05-04 20:15:47 +00001585 (bgp_attr_extra_get (attr))->cluster
1586 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001587
1588 /* XXX: Fix cluster_parse to use stream API and then remove this */
1589 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001590
1591 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1592
Paul Jakmab881c702010-11-23 16:35:42 +00001593 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001594}
1595
1596/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001597int
Paul Jakma835315b2012-01-18 12:28:30 +00001598bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1599 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001600{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001601 afi_t afi;
1602 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001603 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001604 size_t start;
paul718e3742002-12-13 20:15:29 +00001605 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001606 struct peer *const peer = args->peer;
1607 struct attr *const attr = args->attr;
1608 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001609 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001610
paul718e3742002-12-13 20:15:29 +00001611 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001612 s = BGP_INPUT(peer);
1613 start = stream_get_getp(s);
1614
1615 /* safe to read statically sized header? */
1616#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001617#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001618 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001619 {
1620 zlog_info ("%s: %s sent invalid length, %lu",
1621 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001622 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001623 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001624
paul718e3742002-12-13 20:15:29 +00001625 /* Load AFI, SAFI. */
1626 afi = stream_getw (s);
1627 safi = stream_getc (s);
1628
1629 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001630 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001631
Paul Jakma03292802008-06-07 20:37:10 +00001632 if (LEN_LEFT < attre->mp_nexthop_len)
1633 {
1634 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1635 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001636 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001637 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001638
paul718e3742002-12-13 20:15:29 +00001639 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001640 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001641 {
1642 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001643 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001644 /* Probably needed for RFC 2283 */
1645 if (attr->nexthop.s_addr == 0)
1646 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001647 break;
1648 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001649 stream_getl (s); /* RD high */
1650 stream_getl (s); /* RD low */
1651 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001652 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001653 case 24:
1654 {
1655 u_int32_t rd_high __attribute__((unused));
1656 u_int32_t rd_low __attribute__((unused));
1657
1658 rd_high = stream_getl (s);
1659 rd_low = stream_getl (s);
1660 }
1661 /* fall through */
paul718e3742002-12-13 20:15:29 +00001662 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001663 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001664 break;
1665 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001666 case 48:
1667 if (attre->mp_nexthop_len == 48) {
1668 u_int32_t rd_high __attribute__((unused));
1669 u_int32_t rd_low __attribute__((unused));
1670
1671 rd_high = stream_getl (s);
1672 rd_low = stream_getl (s);
1673 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001674 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001675
1676 if (attre->mp_nexthop_len == 48) {
1677 u_int32_t rd_high __attribute__((unused));
1678 u_int32_t rd_low __attribute__((unused));
1679
1680 rd_high = stream_getl (s);
1681 rd_low = stream_getl (s);
1682 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001683 stream_get (&attre->mp_nexthop_local, s, 16);
1684 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001685 {
1686 char buf1[INET6_ADDRSTRLEN];
1687 char buf2[INET6_ADDRSTRLEN];
1688
1689 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001690 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 +00001691 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001692 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001693 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001694 buf2, INET6_ADDRSTRLEN));
1695
Paul Jakmafb982c22007-05-04 20:15:47 +00001696 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001697 }
1698 break;
paul718e3742002-12-13 20:15:29 +00001699 default:
Paul Jakma03292802008-06-07 20:37:10 +00001700 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1701 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001702 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001703 }
1704
Paul Jakma03292802008-06-07 20:37:10 +00001705 if (!LEN_LEFT)
1706 {
1707 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1708 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001709 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001710 }
paul718e3742002-12-13 20:15:29 +00001711
Paul Jakma6e4ab122007-04-10 19:36:48 +00001712 {
1713 u_char val;
1714 if ((val = stream_getc (s)))
1715 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1716 peer->host, val);
1717 }
1718
1719 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001720 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001721 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001722 {
1723 zlog_info ("%s: (%s) Failed to read NLRI",
1724 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001725 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001726 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001727
paul718e3742002-12-13 20:15:29 +00001728 mp_update->afi = afi;
1729 mp_update->safi = safi;
1730 mp_update->nlri = stream_pnt (s);
1731 mp_update->length = nlri_len;
1732
paul9985f832005-02-09 15:51:56 +00001733 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001734
David Lamparterdaefeb82014-12-08 17:42:12 +01001735 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1736
Paul Jakmab881c702010-11-23 16:35:42 +00001737 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001738#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001739}
1740
1741/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001742int
Paul Jakma835315b2012-01-18 12:28:30 +00001743bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001744 struct bgp_nlri *mp_withdraw)
1745{
1746 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001747 afi_t afi;
1748 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001749 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001750 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001751 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001752 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001753
1754 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001755
1756#define BGP_MP_UNREACH_MIN_SIZE 3
1757 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001758 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001759
paul718e3742002-12-13 20:15:29 +00001760 afi = stream_getw (s);
1761 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001762
1763 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001764
paul718e3742002-12-13 20:15:29 +00001765 mp_withdraw->afi = afi;
1766 mp_withdraw->safi = safi;
1767 mp_withdraw->nlri = stream_pnt (s);
1768 mp_withdraw->length = withdraw_len;
1769
paul9985f832005-02-09 15:51:56 +00001770 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001771
David Lamparterdaefeb82014-12-08 17:42:12 +01001772 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1773
Paul Jakmab881c702010-11-23 16:35:42 +00001774 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001775}
1776
1777/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001778static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001779bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001780{
Paul Jakma835315b2012-01-18 12:28:30 +00001781 struct peer *const peer = args->peer;
1782 struct attr *const attr = args->attr;
1783 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001784
paul718e3742002-12-13 20:15:29 +00001785 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001786 {
1787 if (attr->extra)
1788 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001789 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001790 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001791 }
Paul Jakma0c466382010-12-05 17:17:26 +00001792
1793 (bgp_attr_extra_get (attr))->ecommunity =
1794 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1795 /* XXX: fix ecommunity_parse to use stream API */
1796 stream_forward_getp (peer->ibuf, length);
1797
1798 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001799 return bgp_attr_malformed (args,
1800 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1801 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001802
paul718e3742002-12-13 20:15:29 +00001803 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1804
Paul Jakmab881c702010-11-23 16:35:42 +00001805 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001806}
1807
Lou Bergerc3741782016-01-12 13:42:01 -05001808/* Parse Tunnel Encap attribute in an UPDATE */
1809static int
1810bgp_attr_encap(
1811 uint8_t type,
1812 struct peer *peer, /* IN */
1813 bgp_size_t length, /* IN: attr's length field */
1814 struct attr *attr, /* IN: caller already allocated */
1815 u_char flag, /* IN: attr's flags field */
1816 u_char *startp)
1817{
1818 bgp_size_t total;
1819 struct attr_extra *attre = NULL;
1820 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1821 uint16_t tunneltype;
1822
1823 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1824
1825 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1826 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1827 {
1828 zlog (peer->log, LOG_ERR,
1829 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1830 bgp_notify_send_with_data (peer,
1831 BGP_NOTIFY_UPDATE_ERR,
1832 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1833 startp, total);
1834 return -1;
1835 }
1836
1837 if (BGP_ATTR_ENCAP == type) {
1838 /* read outer TLV type and length */
1839 uint16_t tlv_length;
1840
1841 if (length < 4) {
1842 zlog (peer->log, LOG_ERR,
1843 "Tunnel Encap attribute not long enough to contain outer T,L");
1844 bgp_notify_send_with_data(peer,
1845 BGP_NOTIFY_UPDATE_ERR,
1846 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1847 startp, total);
1848 return -1;
1849 }
1850 tunneltype = stream_getw (BGP_INPUT (peer));
1851 tlv_length = stream_getw (BGP_INPUT (peer));
1852 length -= 4;
1853
1854 if (tlv_length != length) {
1855 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1856 __func__, tlv_length, length);
1857 }
1858 }
1859
1860 while (length >= 4) {
1861 uint16_t subtype;
1862 uint16_t sublength;
1863 struct bgp_attr_encap_subtlv *tlv;
1864
Lou Berger298cc2f2016-01-12 13:42:02 -05001865 if (BGP_ATTR_ENCAP == type) {
1866 subtype = stream_getc (BGP_INPUT (peer));
1867 sublength = stream_getc (BGP_INPUT (peer));
1868 length -= 2;
1869 }
Lou Bergerc3741782016-01-12 13:42:01 -05001870
1871 if (sublength > length) {
1872 zlog (peer->log, LOG_ERR,
1873 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1874 sublength, length);
1875 bgp_notify_send_with_data (peer,
1876 BGP_NOTIFY_UPDATE_ERR,
1877 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1878 startp, total);
1879 return -1;
1880 }
1881
1882 /* alloc and copy sub-tlv */
1883 /* TBD make sure these are freed when attributes are released */
1884 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1885 tlv->type = subtype;
1886 tlv->length = sublength;
1887 stream_get(tlv->value, peer->ibuf, sublength);
1888 length -= sublength;
1889
1890 /* attach tlv to encap chain */
1891 if (!attre) {
1892 attre = bgp_attr_extra_get(attr);
1893 if (BGP_ATTR_ENCAP == type) {
1894 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1895 stlv_last = stlv_last->next);
1896 if (stlv_last) {
1897 stlv_last->next = tlv;
1898 } else {
1899 attre->encap_subtlvs = tlv;
1900 }
1901 }
1902 } else {
1903 stlv_last->next = tlv;
1904 }
1905 stlv_last = tlv;
1906 }
1907
1908 if (attre && (BGP_ATTR_ENCAP == type)) {
1909 attre->encap_tunneltype = tunneltype;
1910 }
1911
1912 if (length) {
1913 /* spurious leftover data */
1914 zlog (peer->log, LOG_ERR,
1915 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1916 bgp_notify_send_with_data (peer,
1917 BGP_NOTIFY_UPDATE_ERR,
1918 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1919 startp, total);
1920 return -1;
1921 }
1922
1923 return 0;
1924}
1925
paul718e3742002-12-13 20:15:29 +00001926/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001927static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001928bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001929{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001930 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001931 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001932 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001933 struct peer *const peer = args->peer;
1934 struct attr *const attr = args->attr;
1935 u_char *const startp = args->startp;
1936 const u_char type = args->type;
1937 const u_char flag = args->flags;
1938 const bgp_size_t length = args->length;
1939
paul718e3742002-12-13 20:15:29 +00001940
hassof4184462005-02-01 20:13:16 +00001941 if (BGP_DEBUG (normal, NORMAL))
1942 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1943 peer->host, type, length);
1944
paul718e3742002-12-13 20:15:29 +00001945 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001946 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001947 "Unknown attribute type %d length %d is received", type, length);
1948
1949 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001950 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001951
paul718e3742002-12-13 20:15:29 +00001952 /* If any of the mandatory well-known attributes are not recognized,
1953 then the Error Subcode is set to Unrecognized Well-known
1954 Attribute. The Data field contains the unrecognized attribute
1955 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001956 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001957 {
Paul Jakma835315b2012-01-18 12:28:30 +00001958 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001959 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001960 args->total);
paul718e3742002-12-13 20:15:29 +00001961 }
1962
1963 /* Unrecognized non-transitive optional attributes must be quietly
1964 ignored and not passed along to other BGP peers. */
1965 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001966 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001967
1968 /* If a path with recognized transitive optional attribute is
1969 accepted and passed along to other BGP peers and the Partial bit
1970 in the Attribute Flags octet is set to 1 by some previous AS, it
1971 is not set back to 0 by the current AS. */
1972 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1973
1974 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001975 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001976 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001977
Paul Jakmafb982c22007-05-04 20:15:47 +00001978 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001979
1980 if (transit->val)
1981 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1982 transit->length + total);
1983 else
1984 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1985
1986 memcpy (transit->val + transit->length, startp, total);
1987 transit->length += total;
1988
Paul Jakmab881c702010-11-23 16:35:42 +00001989 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001990}
1991
Paul Jakma055086f2014-09-23 15:23:01 +01001992/* Well-known attribute check. */
1993static int
1994bgp_attr_check (struct peer *peer, struct attr *attr)
1995{
1996 u_char type = 0;
1997
Paul Jakmaaed1b552014-10-21 16:59:01 +01001998 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
1999 * empty UPDATE. */
2000 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2001 return BGP_ATTR_PARSE_PROCEED;
2002
2003 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2004 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2005 are present, it should. Check for any other attribute being present
2006 instead.
2007 */
2008 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2009 return BGP_ATTR_PARSE_PROCEED;
2010
Paul Jakma055086f2014-09-23 15:23:01 +01002011 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2012 type = BGP_ATTR_ORIGIN;
2013
2014 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2015 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002016
2017 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2018 * NLRI is empty. We can't easily check NLRI empty here though.
2019 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002020 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2021 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002022 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002023
Paul Jakma055086f2014-09-23 15:23:01 +01002024 if (peer->sort == BGP_PEER_IBGP
2025 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2026 type = BGP_ATTR_LOCAL_PREF;
2027
2028 if (type)
2029 {
2030 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002031 "%s Missing well-known attribute %d / %s",
2032 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002033 bgp_notify_send_with_data (peer,
2034 BGP_NOTIFY_UPDATE_ERR,
2035 BGP_NOTIFY_UPDATE_MISS_ATTR,
2036 &type, 1);
2037 return BGP_ATTR_PARSE_ERROR;
2038 }
2039 return BGP_ATTR_PARSE_PROCEED;
2040}
2041
paul718e3742002-12-13 20:15:29 +00002042/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002043 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002044bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002045bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2046 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2047{
2048 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002049 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002050 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002051 bgp_size_t length;
2052 u_char *startp, *endp;
2053 u_char *attr_endp;
2054 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002055 /* we need the as4_path only until we have synthesized the as_path with it */
2056 /* same goes for as4_aggregator */
2057 struct aspath *as4_path = NULL;
2058 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002059 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002060
2061 /* Initialize bitmap. */
2062 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2063
2064 /* End pointer of BGP attribute. */
2065 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002066
paul718e3742002-12-13 20:15:29 +00002067 /* Get attributes to the end of attribute length. */
2068 while (BGP_INPUT_PNT (peer) < endp)
2069 {
2070 /* Check remaining length check.*/
2071 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2072 {
gdtc29fdba2004-12-09 14:46:46 +00002073 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002074 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002075 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002076 peer->host,
2077 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002078
2079 bgp_notify_send (peer,
2080 BGP_NOTIFY_UPDATE_ERR,
2081 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002082 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002083 }
2084
2085 /* Fetch attribute flag and type. */
2086 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002087 /* "The lower-order four bits of the Attribute Flags octet are
2088 unused. They MUST be zero when sent and MUST be ignored when
2089 received." */
2090 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002091 type = stream_getc (BGP_INPUT (peer));
2092
Paul Jakma370b64a2007-12-22 16:49:52 +00002093 /* Check whether Extended-Length applies and is in bounds */
2094 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2095 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2096 {
2097 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002098 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002099 peer->host,
2100 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2101
2102 bgp_notify_send (peer,
2103 BGP_NOTIFY_UPDATE_ERR,
2104 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002105 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002106 }
Paul Jakma835315b2012-01-18 12:28:30 +00002107
paul718e3742002-12-13 20:15:29 +00002108 /* Check extended attribue length bit. */
2109 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2110 length = stream_getw (BGP_INPUT (peer));
2111 else
2112 length = stream_getc (BGP_INPUT (peer));
2113
2114 /* If any attribute appears more than once in the UPDATE
2115 message, then the Error Subcode is set to Malformed Attribute
2116 List. */
2117
2118 if (CHECK_BITMAP (seen, type))
2119 {
2120 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002121 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002122 peer->host, type);
2123
2124 bgp_notify_send (peer,
2125 BGP_NOTIFY_UPDATE_ERR,
2126 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002127 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002128 }
2129
2130 /* Set type to bitmap to check duplicate attribute. `type' is
2131 unsigned char so it never overflow bitmap range. */
2132
2133 SET_BITMAP (seen, type);
2134
2135 /* Overflow check. */
2136 attr_endp = BGP_INPUT_PNT (peer) + length;
2137
2138 if (attr_endp > endp)
2139 {
2140 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002141 "%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);
paul718e3742002-12-13 20:15:29 +00002142 bgp_notify_send (peer,
2143 BGP_NOTIFY_UPDATE_ERR,
2144 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002145 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002146 }
Paul Jakma835315b2012-01-18 12:28:30 +00002147
2148 struct bgp_attr_parser_args attr_args = {
2149 .peer = peer,
2150 .length = length,
2151 .attr = attr,
2152 .type = type,
2153 .flags = flag,
2154 .startp = startp,
2155 .total = attr_endp - startp,
2156 };
2157
2158
2159 /* If any recognized attribute has Attribute Flags that conflict
2160 with the Attribute Type Code, then the Error Subcode is set to
2161 Attribute Flags Error. The Data field contains the erroneous
2162 attribute (type, length and value). */
2163 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002164 {
2165 bgp_attr_parse_ret_t ret;
2166 ret = bgp_attr_malformed (&attr_args,
2167 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2168 attr_args.total);
2169 if (ret == BGP_ATTR_PARSE_PROCEED)
2170 continue;
2171 return ret;
2172 }
paul718e3742002-12-13 20:15:29 +00002173
2174 /* OK check attribute and store it's value. */
2175 switch (type)
2176 {
2177 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002178 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002179 break;
2180 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002181 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002182 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002183 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002184 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002185 break;
paul718e3742002-12-13 20:15:29 +00002186 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002187 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002188 break;
2189 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002190 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002191 break;
2192 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002193 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002194 break;
2195 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002196 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002197 break;
2198 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002199 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002200 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002201 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002202 ret = bgp_attr_as4_aggregator (&attr_args,
2203 &as4_aggregator,
2204 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002205 break;
paul718e3742002-12-13 20:15:29 +00002206 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002207 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002208 break;
2209 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002210 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002211 break;
2212 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002213 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002214 break;
2215 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002216 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002217 break;
2218 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002219 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002220 break;
2221 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002222 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002223 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002224 case BGP_ATTR_ENCAP:
2225 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2226 break;
paul718e3742002-12-13 20:15:29 +00002227 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002228 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002229 break;
2230 }
Paul Jakmab881c702010-11-23 16:35:42 +00002231
David Lamparterf57000c2014-06-04 01:01:10 +02002232 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2233 {
2234 bgp_notify_send (peer,
2235 BGP_NOTIFY_UPDATE_ERR,
2236 BGP_NOTIFY_UPDATE_MAL_ATTR);
2237 ret = BGP_ATTR_PARSE_ERROR;
2238 }
2239
Paul Jakmab881c702010-11-23 16:35:42 +00002240 /* If hard error occured immediately return to the caller. */
2241 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002242 {
2243 zlog (peer->log, LOG_WARNING,
2244 "%s: Attribute %s, parse error",
2245 peer->host,
2246 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002247 if (as4_path)
2248 aspath_unintern (&as4_path);
2249 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002250 }
Paul Jakmab881c702010-11-23 16:35:42 +00002251 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2252 {
2253
2254 zlog (peer->log, LOG_WARNING,
2255 "%s: Attribute %s, parse error - treating as withdrawal",
2256 peer->host,
2257 LOOKUP (attr_str, type));
2258 if (as4_path)
2259 aspath_unintern (&as4_path);
2260 return ret;
2261 }
2262
paul718e3742002-12-13 20:15:29 +00002263 /* Check the fetched length. */
2264 if (BGP_INPUT_PNT (peer) != attr_endp)
2265 {
2266 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002267 "%s: BGP attribute %s, fetch error",
2268 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002269 bgp_notify_send (peer,
2270 BGP_NOTIFY_UPDATE_ERR,
2271 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002272 if (as4_path)
2273 aspath_unintern (&as4_path);
2274 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002275 }
2276 }
paul718e3742002-12-13 20:15:29 +00002277 /* Check final read pointer is same as end pointer. */
2278 if (BGP_INPUT_PNT (peer) != endp)
2279 {
2280 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002281 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002282 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002283 bgp_notify_send (peer,
2284 BGP_NOTIFY_UPDATE_ERR,
2285 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002286 if (as4_path)
2287 aspath_unintern (&as4_path);
2288 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002289 }
Paul Jakma055086f2014-09-23 15:23:01 +01002290
2291 /* Check all mandatory well-known attributes are present */
2292 {
2293 bgp_attr_parse_ret_t ret;
2294 if ((ret = bgp_attr_check (peer, attr)) < 0)
2295 {
2296 if (as4_path)
2297 aspath_unintern (&as4_path);
2298 return ret;
2299 }
2300 }
2301
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002302 /*
2303 * At this place we can see whether we got AS4_PATH and/or
2304 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2305 * We can not do this before we've read all attributes because
2306 * the as4 handling does not say whether AS4_PATH has to be sent
2307 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2308 * in relationship to AGGREGATOR.
2309 * So, to be defensive, we are not relying on any order and read
2310 * all attributes first, including these 32bit ones, and now,
2311 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002312 *
2313 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2314 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002315 */
David Lamparterf57000c2014-06-04 01:01:10 +02002316 /* actually... this doesn't ever return failure currently, but
2317 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002318 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2319 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002320 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002321 {
David Lamparterf57000c2014-06-04 01:01:10 +02002322 bgp_notify_send (peer,
2323 BGP_NOTIFY_UPDATE_ERR,
2324 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002325 if (as4_path)
2326 aspath_unintern (&as4_path);
2327 return BGP_ATTR_PARSE_ERROR;
2328 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002329
2330 /* At this stage, we have done all fiddling with as4, and the
2331 * resulting info is in attr->aggregator resp. attr->aspath
2332 * so we can chuck as4_aggregator and as4_path alltogether in
2333 * order to save memory
2334 */
Paul Jakmab881c702010-11-23 16:35:42 +00002335 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002336 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002337 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002338 /* The flag that we got this is still there, but that does not
2339 * do any trouble
2340 */
2341 }
2342 /*
2343 * The "rest" of the code does nothing with as4_aggregator.
2344 * there is no memory attached specifically which is not part
2345 * of the attr.
2346 * so ignoring just means do nothing.
2347 */
2348 /*
2349 * Finally do the checks on the aspath we did not do yet
2350 * because we waited for a potentially synthesized aspath.
2351 */
Paul Jakmab881c702010-11-23 16:35:42 +00002352 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002353 {
Paul Jakma835315b2012-01-18 12:28:30 +00002354 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002355 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002356 return ret;
2357 }
2358
paul718e3742002-12-13 20:15:29 +00002359 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002360 if (attr->extra && attr->extra->transit)
2361 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002362
Paul Jakmab881c702010-11-23 16:35:42 +00002363 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002364}
2365
paul718e3742002-12-13 20:15:29 +00002366int stream_put_prefix (struct stream *, struct prefix *);
2367
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002368size_t
2369bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2370 struct attr *attr)
2371{
2372 size_t sizep;
2373
2374 /* Set extended bit always to encode the attribute length as 2 bytes */
2375 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2376 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2377 sizep = stream_get_endp (s);
2378 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002379
2380 stream_putw (s, afi);
2381 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002382
2383 /* Nexthop */
2384 switch (afi)
2385 {
2386 case AFI_IP:
2387 switch (safi)
2388 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002389 case SAFI_MULTICAST:
2390 stream_putc (s, 4);
2391 stream_put_ipv4 (s, attr->nexthop.s_addr);
2392 break;
2393 case SAFI_MPLS_VPN:
2394 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002395 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002396 stream_putl (s, 0);
2397 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2398 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002399 case SAFI_ENCAP:
2400 stream_putc (s, 4);
2401 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2402 break;
Lou Berger050defe2016-01-12 13:41:59 -05002403 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002404 default:
2405 break;
2406 }
2407 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002408 case AFI_IP6:
2409 switch (safi)
2410 {
2411 case SAFI_UNICAST:
2412 case SAFI_MULTICAST:
2413 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002414 struct attr_extra *attre = attr->extra;
2415
2416 assert (attr->extra);
2417 stream_putc (s, attre->mp_nexthop_len);
2418 stream_put (s, &attre->mp_nexthop_global, 16);
2419 if (attre->mp_nexthop_len == 32)
2420 stream_put (s, &attre->mp_nexthop_local, 16);
2421 }
Lou Berger050defe2016-01-12 13:41:59 -05002422 break;
2423 case SAFI_MPLS_VPN:
2424 {
2425 struct attr_extra *attre = attr->extra;
2426
2427 assert (attr->extra);
2428 if (attre->mp_nexthop_len == 16) {
2429 stream_putc (s, 24);
2430 stream_putl (s, 0); /* RD = 0, per RFC */
2431 stream_putl (s, 0);
2432 stream_put (s, &attre->mp_nexthop_global, 16);
2433 } else if (attre->mp_nexthop_len == 32) {
2434 stream_putc (s, 48);
2435 stream_putl (s, 0); /* RD = 0, per RFC */
2436 stream_putl (s, 0);
2437 stream_put (s, &attre->mp_nexthop_global, 16);
2438 stream_putl (s, 0); /* RD = 0, per RFC */
2439 stream_putl (s, 0);
2440 stream_put (s, &attre->mp_nexthop_local, 16);
2441 }
2442 }
2443 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002444 case SAFI_ENCAP:
2445 assert (attr->extra);
2446 stream_putc (s, 16);
2447 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2448 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002449 default:
2450 break;
2451 }
2452 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002453 default:
2454 break;
2455 }
2456
2457 /* SNPA */
2458 stream_putc (s, 0);
2459 return sizep;
2460}
2461
2462void
2463bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2464 struct prefix *p, struct prefix_rd *prd,
2465 u_char *tag)
2466{
Lou Berger050defe2016-01-12 13:41:59 -05002467 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002468 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002469 /* Tag, RD, Prefix write. */
2470 stream_putc (s, p->prefixlen + 88);
2471 stream_put (s, tag, 3);
2472 stream_put (s, prd->val, 8);
2473 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002474 }
Lou Berger050defe2016-01-12 13:41:59 -05002475 else
2476 stream_put_prefix (s, p);
2477}
2478
2479size_t
2480bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2481{
2482 int size = PSIZE (p->prefixlen);
2483 if (safi == SAFI_MPLS_VPN)
2484 size += 88;
2485 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002486}
2487
Lou Bergerc3741782016-01-12 13:42:01 -05002488/*
2489 * Encodes the tunnel encapsulation attribute
2490 */
2491static void
2492bgp_packet_mpattr_tea(
2493 struct bgp *bgp,
2494 struct peer *peer,
2495 struct stream *s,
2496 struct attr *attr,
2497 uint8_t attrtype)
2498{
2499 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002500 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002501 struct bgp_attr_encap_subtlv *subtlvs;
2502 struct bgp_attr_encap_subtlv *st;
2503 const char *attrname;
2504
2505 if (!attr || !attr->extra)
2506 return;
2507
2508 switch (attrtype) {
2509 case BGP_ATTR_ENCAP:
2510 attrname = "Tunnel Encap";
2511 subtlvs = attr->extra->encap_subtlvs;
2512
2513 /*
2514 * The tunnel encap attr has an "outer" tlv.
2515 * T = tunneltype,
2516 * L = total length of subtlvs,
2517 * V = concatenated subtlvs.
2518 */
2519 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002520 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002521 break;
2522
2523 default:
2524 assert(0);
2525 }
2526
2527
Lou Berger298cc2f2016-01-12 13:42:02 -05002528 /* if no tlvs, don't make attr */
2529 if (subtlvs == NULL)
2530 return;
2531
Lou Bergerc3741782016-01-12 13:42:01 -05002532 /* compute attr length */
2533 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002534 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002535 }
2536
Lou Bergerc3741782016-01-12 13:42:01 -05002537 if (attrlenfield > 0xffff) {
2538 zlog (peer->log, LOG_ERR,
2539 "%s attribute is too long (length=%d), can't send it",
2540 attrname,
2541 attrlenfield);
2542 return;
2543 }
2544
2545 if (attrlenfield > 0xff) {
2546 /* 2-octet length field */
2547 stream_putc (s,
2548 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2549 stream_putc (s, attrtype);
2550 stream_putw (s, attrlenfield & 0xffff);
2551 } else {
2552 /* 1-octet length field */
2553 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2554 stream_putc (s, attrtype);
2555 stream_putc (s, attrlenfield & 0xff);
2556 }
2557
2558 if (attrtype == BGP_ATTR_ENCAP) {
2559 /* write outer T+L */
2560 stream_putw(s, attr->extra->encap_tunneltype);
2561 stream_putw(s, attrlenfield - 4);
2562 }
2563
2564 /* write each sub-tlv */
2565 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002566 if (attrtype == BGP_ATTR_ENCAP) {
2567 stream_putc (s, st->type);
2568 stream_putc (s, st->length);
2569 }
Lou Bergerc3741782016-01-12 13:42:01 -05002570 stream_put (s, st->value, st->length);
2571 }
2572}
2573
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002574void
2575bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2576{
2577 /* Set MP attribute length. Don't count the (2) bytes used to encode
2578 the attr length */
2579 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2580}
2581
paul718e3742002-12-13 20:15:29 +00002582/* Make attribute packet. */
2583bgp_size_t
2584bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002585 struct stream *s, struct attr *attr,
2586 struct prefix *p, afi_t afi, safi_t safi,
2587 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002588{
paulfe69a502005-09-10 16:55:02 +00002589 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002590 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002591 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002592 int send_as4_path = 0;
2593 int send_as4_aggregator = 0;
2594 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002595
2596 if (! bgp)
2597 bgp = bgp_get_default ();
2598
2599 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002600 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002601
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002602 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2603 {
Lou Berger050defe2016-01-12 13:41:59 -05002604 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002605 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2606 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2607 bgp_packet_mpattr_end(s, mpattrlen_pos);
2608 }
2609
paul718e3742002-12-13 20:15:29 +00002610 /* Origin attribute. */
2611 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2612 stream_putc (s, BGP_ATTR_ORIGIN);
2613 stream_putc (s, 1);
2614 stream_putc (s, attr->origin);
2615
2616 /* AS path attribute. */
2617
2618 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002619 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002620 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002621 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002622 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002623 {
2624 aspath = aspath_dup (attr->aspath);
2625
2626 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2627 {
2628 /* Strip the confed info, and then stuff our path CONFED_ID
2629 on the front */
2630 aspath = aspath_delete_confed_seq (aspath);
2631 aspath = aspath_add_seq (aspath, bgp->confed_id);
2632 }
2633 else
2634 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002635 if (peer->change_local_as) {
2636 /* If replace-as is specified, we only use the change_local_as when
2637 advertising routes. */
2638 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2639 aspath = aspath_add_seq (aspath, peer->local_as);
2640 }
paul718e3742002-12-13 20:15:29 +00002641 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002642 } else {
2643 aspath = aspath_add_seq (aspath, peer->local_as);
2644 }
paul718e3742002-12-13 20:15:29 +00002645 }
2646 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002647 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002648 {
2649 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2650 aspath = aspath_dup (attr->aspath);
2651 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2652 }
2653 else
2654 aspath = attr->aspath;
2655
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002656 /* If peer is not AS4 capable, then:
2657 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2658 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2659 * types are in it (i.e. exclude them if they are there)
2660 * AND do this only if there is at least one asnum > 65535 in the path!
2661 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2662 * all ASnums > 65535 to BGP_AS_TRANS
2663 */
paul718e3742002-12-13 20:15:29 +00002664
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002665 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2666 stream_putc (s, BGP_ATTR_AS_PATH);
2667 aspath_sizep = stream_get_endp (s);
2668 stream_putw (s, 0);
2669 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2670
2671 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2672 * in the path
2673 */
2674 if (!use32bit && aspath_has_as4 (aspath))
2675 send_as4_path = 1; /* we'll do this later, at the correct place */
2676
paul718e3742002-12-13 20:15:29 +00002677 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002678 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2679 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002680 {
2681 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2682 stream_putc (s, BGP_ATTR_NEXT_HOP);
2683 stream_putc (s, 4);
2684 if (safi == SAFI_MPLS_VPN)
2685 {
2686 if (attr->nexthop.s_addr == 0)
2687 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2688 else
2689 stream_put_ipv4 (s, attr->nexthop.s_addr);
2690 }
2691 else
2692 stream_put_ipv4 (s, attr->nexthop.s_addr);
2693 }
2694
2695 /* MED attribute. */
2696 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2697 {
2698 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2699 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2700 stream_putc (s, 4);
2701 stream_putl (s, attr->med);
2702 }
2703
2704 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002705 if (peer->sort == BGP_PEER_IBGP ||
2706 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002707 {
2708 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2709 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2710 stream_putc (s, 4);
2711 stream_putl (s, attr->local_pref);
2712 }
2713
2714 /* Atomic aggregate. */
2715 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2716 {
2717 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2718 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2719 stream_putc (s, 0);
2720 }
2721
2722 /* Aggregator. */
2723 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2724 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002725 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002726
2727 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002728 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2729 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002730
2731 if (use32bit)
2732 {
2733 /* AS4 capable peer */
2734 stream_putc (s, 8);
2735 stream_putl (s, attr->extra->aggregator_as);
2736 }
2737 else
2738 {
2739 /* 2-byte AS peer */
2740 stream_putc (s, 6);
2741
2742 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2743 if ( attr->extra->aggregator_as > 65535 )
2744 {
2745 stream_putw (s, BGP_AS_TRANS);
2746
2747 /* we have to send AS4_AGGREGATOR, too.
2748 * we'll do that later in order to send attributes in ascending
2749 * order.
2750 */
2751 send_as4_aggregator = 1;
2752 }
2753 else
2754 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2755 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002756 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002757 }
2758
2759 /* Community attribute. */
2760 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2761 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2762 {
2763 if (attr->community->size * 4 > 255)
2764 {
2765 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2766 stream_putc (s, BGP_ATTR_COMMUNITIES);
2767 stream_putw (s, attr->community->size * 4);
2768 }
2769 else
2770 {
2771 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2772 stream_putc (s, BGP_ATTR_COMMUNITIES);
2773 stream_putc (s, attr->community->size * 4);
2774 }
2775 stream_put (s, attr->community->val, attr->community->size * 4);
2776 }
2777
2778 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002779 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002780 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002781 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002782 {
2783 /* Originator ID. */
2784 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2785 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2786 stream_putc (s, 4);
2787
2788 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002789 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002790 else
2791 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002792
2793 /* Cluster list. */
2794 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2795 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2796
Paul Jakma9eda90c2007-08-30 13:36:17 +00002797 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002798 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002799 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002800 /* If this peer configuration's parent BGP has cluster_id. */
2801 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2802 stream_put_in_addr (s, &bgp->cluster_id);
2803 else
2804 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002805 stream_put (s, attr->extra->cluster->list,
2806 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002807 }
2808 else
2809 {
2810 stream_putc (s, 4);
2811 /* If this peer configuration's parent BGP has cluster_id. */
2812 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2813 stream_put_in_addr (s, &bgp->cluster_id);
2814 else
2815 stream_put_in_addr (s, &bgp->router_id);
2816 }
2817 }
2818
paul718e3742002-12-13 20:15:29 +00002819 /* Extended Communities attribute. */
2820 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2821 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2822 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002823 struct attr_extra *attre = attr->extra;
2824
2825 assert (attre);
2826
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002827 if (peer->sort == BGP_PEER_IBGP
2828 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002829 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002830 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002831 {
2832 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2833 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002834 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002835 }
2836 else
2837 {
2838 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2839 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002840 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002841 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002842 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002843 }
2844 else
2845 {
paul5228ad22004-06-04 17:58:18 +00002846 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002847 int tbit;
2848 int ecom_tr_size = 0;
2849 int i;
2850
Paul Jakmafb982c22007-05-04 20:15:47 +00002851 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002852 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002853 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002854 tbit = *pnt;
2855
2856 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2857 continue;
2858
2859 ecom_tr_size++;
2860 }
2861
2862 if (ecom_tr_size)
2863 {
2864 if (ecom_tr_size * 8 > 255)
2865 {
2866 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2867 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2868 stream_putw (s, ecom_tr_size * 8);
2869 }
2870 else
2871 {
2872 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2873 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2874 stream_putc (s, ecom_tr_size * 8);
2875 }
2876
Paul Jakmafb982c22007-05-04 20:15:47 +00002877 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002878 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002879 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002880 tbit = *pnt;
2881
2882 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2883 continue;
2884
2885 stream_put (s, pnt, 8);
2886 }
2887 }
paul718e3742002-12-13 20:15:29 +00002888 }
paul718e3742002-12-13 20:15:29 +00002889 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002890
2891 if ( send_as4_path )
2892 {
2893 /* If the peer is NOT As4 capable, AND */
2894 /* there are ASnums > 65535 in path THEN
2895 * give out AS4_PATH */
2896
2897 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2898 * path segments!
2899 * Hm, I wonder... confederation things *should* only be at
2900 * the beginning of an aspath, right? Then we should use
2901 * aspath_delete_confed_seq for this, because it is already
2902 * there! (JK)
2903 * Folks, talk to me: what is reasonable here!?
2904 */
2905 aspath = aspath_delete_confed_seq (aspath);
2906
2907 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2908 stream_putc (s, BGP_ATTR_AS4_PATH);
2909 aspath_sizep = stream_get_endp (s);
2910 stream_putw (s, 0);
2911 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2912 }
2913
2914 if (aspath != attr->aspath)
2915 aspath_free (aspath);
2916
2917 if ( send_as4_aggregator )
2918 {
2919 assert (attr->extra);
2920
2921 /* send AS4_AGGREGATOR, at this place */
2922 /* this section of code moved here in order to ensure the correct
2923 * *ascending* order of attributes
2924 */
2925 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2926 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2927 stream_putc (s, 8);
2928 stream_putl (s, attr->extra->aggregator_as);
2929 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2930 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002931
2932 if ((afi == AFI_IP || afi == AFI_IP6) &&
2933 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2934 {
2935 /* Tunnel Encap attribute */
2936 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2937 }
2938
paul718e3742002-12-13 20:15:29 +00002939 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002940 if (attr->extra && attr->extra->transit)
2941 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002942
2943 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002944 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002945}
2946
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002947size_t
2948bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002949{
paul718e3742002-12-13 20:15:29 +00002950 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002951
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002952 /* Set extended bit always to encode the attribute length as 2 bytes */
2953 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002954 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2955
paul9985f832005-02-09 15:51:56 +00002956 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002957 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002958
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002959 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002960 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002961 return attrlen_pnt;
2962}
paul718e3742002-12-13 20:15:29 +00002963
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002964void
2965bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2966 afi_t afi, safi_t safi, struct prefix_rd *prd,
2967 u_char *tag)
2968{
Lou Berger050defe2016-01-12 13:41:59 -05002969 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002970}
paul718e3742002-12-13 20:15:29 +00002971
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002972void
2973bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2974{
Lou Berger050defe2016-01-12 13:41:59 -05002975 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002976}
2977
2978/* Initialization of attribute. */
2979void
paulfe69a502005-09-10 16:55:02 +00002980bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002981{
paul718e3742002-12-13 20:15:29 +00002982 aspath_init ();
2983 attrhash_init ();
2984 community_init ();
2985 ecommunity_init ();
2986 cluster_init ();
2987 transit_init ();
2988}
2989
Chris Caputo228da422009-07-18 05:44:03 +00002990void
2991bgp_attr_finish (void)
2992{
2993 aspath_finish ();
2994 attrhash_finish ();
2995 community_finish ();
2996 ecommunity_finish ();
2997 cluster_finish ();
2998 transit_finish ();
2999}
3000
paul718e3742002-12-13 20:15:29 +00003001/* Make attribute packet. */
3002void
paula3845922003-10-18 01:30:50 +00003003bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3004 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003005{
3006 unsigned long cp;
3007 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003008 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003009 struct aspath *aspath;
3010
3011 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003012 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003013
3014 /* Place holder of length. */
3015 stream_putw (s, 0);
3016
3017 /* Origin attribute. */
3018 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3019 stream_putc (s, BGP_ATTR_ORIGIN);
3020 stream_putc (s, 1);
3021 stream_putc (s, attr->origin);
3022
3023 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003024
3025 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3026 stream_putc (s, BGP_ATTR_AS_PATH);
3027 aspath_lenp = stream_get_endp (s);
3028 stream_putw (s, 0);
3029
3030 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003031
3032 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003033 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3034 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003035 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003036 )
3037 {
3038 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3039 stream_putc (s, BGP_ATTR_NEXT_HOP);
3040 stream_putc (s, 4);
3041 stream_put_ipv4 (s, attr->nexthop.s_addr);
3042 }
paul718e3742002-12-13 20:15:29 +00003043
3044 /* MED attribute. */
3045 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3046 {
3047 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3048 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3049 stream_putc (s, 4);
3050 stream_putl (s, attr->med);
3051 }
3052
3053 /* Local preference. */
3054 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3055 {
3056 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3057 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3058 stream_putc (s, 4);
3059 stream_putl (s, attr->local_pref);
3060 }
3061
3062 /* Atomic aggregate. */
3063 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3064 {
3065 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3066 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3067 stream_putc (s, 0);
3068 }
3069
3070 /* Aggregator. */
3071 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3072 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003073 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003074 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3075 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003076 stream_putc (s, 8);
3077 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003078 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003079 }
3080
3081 /* Community attribute. */
3082 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3083 {
3084 if (attr->community->size * 4 > 255)
3085 {
3086 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3087 stream_putc (s, BGP_ATTR_COMMUNITIES);
3088 stream_putw (s, attr->community->size * 4);
3089 }
3090 else
3091 {
3092 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3093 stream_putc (s, BGP_ATTR_COMMUNITIES);
3094 stream_putc (s, attr->community->size * 4);
3095 }
3096 stream_put (s, attr->community->val, attr->community->size * 4);
3097 }
3098
paula3845922003-10-18 01:30:50 +00003099 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003100 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3101 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003102 {
3103 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003104 struct attr_extra *attre = attr->extra;
3105
paula3845922003-10-18 01:30:50 +00003106 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3107 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003108 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003109
3110 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003111 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003112 stream_putw(s, AFI_IP6); /* AFI */
3113 stream_putc(s, SAFI_UNICAST); /* SAFI */
3114
3115 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003116 stream_putc(s, attre->mp_nexthop_len);
3117 stream_put(s, &attre->mp_nexthop_global, 16);
3118 if (attre->mp_nexthop_len == 32)
3119 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003120
3121 /* SNPA */
3122 stream_putc(s, 0);
3123
3124 /* Prefix */
3125 stream_put_prefix(s, prefix);
3126
3127 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003128 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003129 }
paula3845922003-10-18 01:30:50 +00003130
paul718e3742002-12-13 20:15:29 +00003131 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003132 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003133 stream_putw_at (s, cp, len);
3134}