blob: a25ea76401042401d86e1538133a57751d185ba9 [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"
David Lamparter6b0655a2014-06-04 06:53:35 +020042
paul718e3742002-12-13 20:15:29 +000043/* Attribute strings for logging. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -070044static const struct message attr_str [] =
paul718e3742002-12-13 20:15:29 +000045{
46 { BGP_ATTR_ORIGIN, "ORIGIN" },
47 { BGP_ATTR_AS_PATH, "AS_PATH" },
48 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
49 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
50 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
51 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
52 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
53 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
54 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
Denis Ovsienkof8627ff2011-10-10 16:52:20 +040055 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
paul718e3742002-12-13 20:15:29 +000056 { BGP_ATTR_DPA, "DPA" },
57 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
58 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
59 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
60 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000061 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
62 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
63 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
64 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
paul718e3742002-12-13 20:15:29 +000065};
Balaji.G837d16c2012-09-26 14:09:10 +053066static const int attr_str_max = array_size(attr_str);
Denis Ovsienkoafcb7672011-10-23 22:32:44 +040067
68static const struct message attr_flag_str[] =
69{
70 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
71 { BGP_ATTR_FLAG_TRANS, "Transitive" },
72 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
73 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
74 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
75};
David Lamparter6b0655a2014-06-04 06:53:35 +020076
Stephen Hemminger9bddac42009-05-15 09:59:51 -070077static struct hash *cluster_hash;
paul718e3742002-12-13 20:15:29 +000078
paul94f2b392005-06-28 12:44:16 +000079static void *
Paul Jakma923de652007-04-29 18:25:17 +000080cluster_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +000081{
Paul Jakma923de652007-04-29 18:25:17 +000082 struct cluster_list * val = (struct cluster_list *) p;
paul718e3742002-12-13 20:15:29 +000083 struct cluster_list *cluster;
84
85 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
86 cluster->length = val->length;
87
88 if (cluster->length)
89 {
90 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
91 memcpy (cluster->list, val->list, val->length);
92 }
93 else
94 cluster->list = NULL;
95
96 cluster->refcnt = 0;
97
98 return cluster;
99}
100
101/* Cluster list related functions. */
paul94f2b392005-06-28 12:44:16 +0000102static struct cluster_list *
paul5228ad22004-06-04 17:58:18 +0000103cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +0000104{
105 struct cluster_list tmp;
106 struct cluster_list *cluster;
107
108 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +0000109 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +0000110
111 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
112 cluster->refcnt++;
113 return cluster;
114}
115
116int
117cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
118{
119 int i;
120
121 for (i = 0; i < cluster->length / 4; i++)
122 if (cluster->list[i].s_addr == originator.s_addr)
123 return 1;
124 return 0;
125}
126
paul94f2b392005-06-28 12:44:16 +0000127static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000128cluster_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000129{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700130 const struct cluster_list *cluster = p;
paul718e3742002-12-13 20:15:29 +0000131
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700132 return jhash(cluster->list, cluster->length, 0);
paul718e3742002-12-13 20:15:29 +0000133}
134
paul94f2b392005-06-28 12:44:16 +0000135static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100136cluster_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000137{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100138 const struct cluster_list * cluster1 = p1;
139 const struct cluster_list * cluster2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000140
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100141 return (cluster1->length == cluster2->length &&
142 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000143}
144
paul94f2b392005-06-28 12:44:16 +0000145static void
paul718e3742002-12-13 20:15:29 +0000146cluster_free (struct cluster_list *cluster)
147{
148 if (cluster->list)
149 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
150 XFREE (MTYPE_CLUSTER, cluster);
151}
152
Chris Caputo228da422009-07-18 05:44:03 +0000153#if 0
paul94f2b392005-06-28 12:44:16 +0000154static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000155cluster_dup (struct cluster_list *cluster)
156{
157 struct cluster_list *new;
158
Stephen Hemminger393deb92008-08-18 14:13:29 -0700159 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
paul718e3742002-12-13 20:15:29 +0000160 new->length = cluster->length;
161
162 if (cluster->length)
163 {
164 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
165 memcpy (new->list, cluster->list, cluster->length);
166 }
167 else
168 new->list = NULL;
169
170 return new;
171}
Chris Caputo228da422009-07-18 05:44:03 +0000172#endif
paul718e3742002-12-13 20:15:29 +0000173
paul94f2b392005-06-28 12:44:16 +0000174static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000175cluster_intern (struct cluster_list *cluster)
176{
177 struct cluster_list *find;
178
179 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
180 find->refcnt++;
181
182 return find;
183}
184
185void
186cluster_unintern (struct cluster_list *cluster)
187{
paul718e3742002-12-13 20:15:29 +0000188 if (cluster->refcnt)
189 cluster->refcnt--;
190
191 if (cluster->refcnt == 0)
192 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400193 hash_release (cluster_hash, cluster);
paul718e3742002-12-13 20:15:29 +0000194 cluster_free (cluster);
195 }
196}
197
paul94f2b392005-06-28 12:44:16 +0000198static void
199cluster_init (void)
paul718e3742002-12-13 20:15:29 +0000200{
201 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
202}
Chris Caputo228da422009-07-18 05:44:03 +0000203
204static void
205cluster_finish (void)
206{
Lou Berger056f3762013-04-10 12:30:04 -0700207 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
Chris Caputo228da422009-07-18 05:44:03 +0000208 hash_free (cluster_hash);
209 cluster_hash = NULL;
210}
David Lamparter6b0655a2014-06-04 06:53:35 +0200211
paul718e3742002-12-13 20:15:29 +0000212/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700213static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000214
paul94f2b392005-06-28 12:44:16 +0000215static void
paul718e3742002-12-13 20:15:29 +0000216transit_free (struct transit *transit)
217{
218 if (transit->val)
219 XFREE (MTYPE_TRANSIT_VAL, transit->val);
220 XFREE (MTYPE_TRANSIT, transit);
221}
222
Paul Jakma923de652007-04-29 18:25:17 +0000223
paul94f2b392005-06-28 12:44:16 +0000224static void *
Paul Jakma923de652007-04-29 18:25:17 +0000225transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000226{
227 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000228 return p;
paul718e3742002-12-13 20:15:29 +0000229}
230
paul94f2b392005-06-28 12:44:16 +0000231static struct transit *
paul718e3742002-12-13 20:15:29 +0000232transit_intern (struct transit *transit)
233{
234 struct transit *find;
235
236 find = hash_get (transit_hash, transit, transit_hash_alloc);
237 if (find != transit)
238 transit_free (transit);
239 find->refcnt++;
240
241 return find;
242}
243
244void
245transit_unintern (struct transit *transit)
246{
paul718e3742002-12-13 20:15:29 +0000247 if (transit->refcnt)
248 transit->refcnt--;
249
250 if (transit->refcnt == 0)
251 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400252 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000253 transit_free (transit);
254 }
255}
256
paul94f2b392005-06-28 12:44:16 +0000257static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000258transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000259{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700260 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000261
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700262 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000263}
264
paul94f2b392005-06-28 12:44:16 +0000265static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100266transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000267{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100268 const struct transit * transit1 = p1;
269 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000270
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100271 return (transit1->length == transit2->length &&
272 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000273}
274
paul94f2b392005-06-28 12:44:16 +0000275static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800276transit_init (void)
paul718e3742002-12-13 20:15:29 +0000277{
278 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
279}
Chris Caputo228da422009-07-18 05:44:03 +0000280
281static void
282transit_finish (void)
283{
Lou Berger056f3762013-04-10 12:30:04 -0700284 hash_clean (transit_hash, (void (*)(void *))transit_free);
Chris Caputo228da422009-07-18 05:44:03 +0000285 hash_free (transit_hash);
286 transit_hash = NULL;
287}
David Lamparter6b0655a2014-06-04 06:53:35 +0200288
paul718e3742002-12-13 20:15:29 +0000289/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700290static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000291
Paul Jakmafb982c22007-05-04 20:15:47 +0000292static struct attr_extra *
293bgp_attr_extra_new (void)
294{
295 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
296}
297
298void
299bgp_attr_extra_free (struct attr *attr)
300{
301 if (attr->extra)
302 {
303 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
304 attr->extra = NULL;
305 }
306}
307
308struct attr_extra *
309bgp_attr_extra_get (struct attr *attr)
310{
311 if (!attr->extra)
312 attr->extra = bgp_attr_extra_new();
313 return attr->extra;
314}
315
316/* Shallow copy of an attribute
317 * Though, not so shallow that it doesn't copy the contents
318 * of the attr_extra pointed to by 'extra'
319 */
320void
321bgp_attr_dup (struct attr *new, struct attr *orig)
322{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000323 struct attr_extra *extra = new->extra;
324
Paul Jakmafb982c22007-05-04 20:15:47 +0000325 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000326 /* if caller provided attr_extra space, use it in any case.
327 *
328 * This is neccesary even if orig->extra equals NULL, because otherwise
329 * memory may be later allocated on the heap by bgp_attr_extra_get.
330 *
331 * That memory would eventually be leaked, because the caller must not
332 * call bgp_attr_extra_free if he provided attr_extra on the stack.
333 */
334 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000335 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000336 new->extra = extra;
337 memset(new->extra, 0, sizeof(struct attr_extra));
338 if (orig->extra)
339 *new->extra = *orig->extra;
340 }
341 else if (orig->extra)
342 {
343 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000344 *new->extra = *orig->extra;
345 }
346}
347
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000348unsigned long int
349attr_count (void)
350{
351 return attrhash->count;
352}
353
354unsigned long int
355attr_unknown_count (void)
356{
357 return transit_hash->count;
358}
359
paul718e3742002-12-13 20:15:29 +0000360unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000361attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000362{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000363 const struct attr *attr = (struct attr *) p;
364 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700365 uint32_t key = 0;
366#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000367
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700368 MIX(attr->origin);
369 MIX(attr->nexthop.s_addr);
370 MIX(attr->med);
371 MIX(attr->local_pref);
372
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000373 key += attr->origin;
374 key += attr->nexthop.s_addr;
375 key += attr->med;
376 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000377
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000378 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000379 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000380 MIX(extra->aggregator_as);
381 MIX(extra->aggregator_addr.s_addr);
382 MIX(extra->weight);
383 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000384 MIX(extra->originator_id.s_addr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000385 }
386
paul718e3742002-12-13 20:15:29 +0000387 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700388 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000389 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700390 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000391
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000392 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000393 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000394 if (extra->ecommunity)
395 MIX(ecommunity_hash_make (extra->ecommunity));
396 if (extra->cluster)
397 MIX(cluster_hash_key_make (extra->cluster));
398 if (extra->transit)
399 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000400
401#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000402 MIX(extra->mp_nexthop_len);
403 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
404 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
paul718e3742002-12-13 20:15:29 +0000405#endif /* HAVE_IPV6 */
Paul Jakmafb982c22007-05-04 20:15:47 +0000406 }
paul718e3742002-12-13 20:15:29 +0000407
408 return key;
409}
410
411int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100412attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000413{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100414 const struct attr * attr1 = p1;
415 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000416
paul718e3742002-12-13 20:15:29 +0000417 if (attr1->flag == attr2->flag
418 && attr1->origin == attr2->origin
419 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000420 && attr1->aspath == attr2->aspath
421 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000422 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000423 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000424 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100425 const struct attr_extra *ae1 = attr1->extra;
426 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000427
428 if (ae1 && ae2
429 && ae1->aggregator_as == ae2->aggregator_as
430 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
431 && ae1->weight == ae2->weight
432#ifdef HAVE_IPV6
433 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
434 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
435 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
436#endif /* HAVE_IPV6 */
437 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
438 && ae1->ecommunity == ae2->ecommunity
439 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000440 && ae1->transit == ae2->transit
441 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000442 return 1;
443 else if (ae1 || ae2)
444 return 0;
445 /* neither attribute has extra attributes, so they're same */
446 return 1;
447 }
paul718e3742002-12-13 20:15:29 +0000448 else
449 return 0;
450}
451
paul94f2b392005-06-28 12:44:16 +0000452static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100453attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000454{
455 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
456}
457
Lou Berger056f3762013-04-10 12:30:04 -0700458/*
459 * special for hash_clean below
460 */
461static void
462attr_vfree (void *attr)
463{
464 bgp_attr_extra_free ((struct attr *)attr);
465 XFREE (MTYPE_ATTR, attr);
466}
467
paul94f2b392005-06-28 12:44:16 +0000468static void
Chris Caputo228da422009-07-18 05:44:03 +0000469attrhash_finish (void)
470{
Lou Berger056f3762013-04-10 12:30:04 -0700471 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000472 hash_free (attrhash);
473 attrhash = NULL;
474}
475
476static void
paul718e3742002-12-13 20:15:29 +0000477attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
478{
479 struct attr *attr = backet->data;
480
481 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
482 inet_ntoa (attr->nexthop), VTY_NEWLINE);
483}
484
485void
486attr_show_all (struct vty *vty)
487{
488 hash_iterate (attrhash,
489 (void (*)(struct hash_backet *, void *))
490 attr_show_all_iterator,
491 vty);
492}
493
paul94f2b392005-06-28 12:44:16 +0000494static void *
Paul Jakma923de652007-04-29 18:25:17 +0000495bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000496{
Paul Jakma923de652007-04-29 18:25:17 +0000497 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000498 struct attr *attr;
499
500 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
501 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000502 if (val->extra)
503 {
504 attr->extra = bgp_attr_extra_new ();
505 *attr->extra = *val->extra;
506 }
paul718e3742002-12-13 20:15:29 +0000507 attr->refcnt = 0;
508 return attr;
509}
510
511/* Internet argument attribute. */
512struct attr *
513bgp_attr_intern (struct attr *attr)
514{
515 struct attr *find;
516
517 /* Intern referenced strucutre. */
518 if (attr->aspath)
519 {
520 if (! attr->aspath->refcnt)
521 attr->aspath = aspath_intern (attr->aspath);
522 else
523 attr->aspath->refcnt++;
524 }
525 if (attr->community)
526 {
527 if (! attr->community->refcnt)
528 attr->community = community_intern (attr->community);
529 else
530 attr->community->refcnt++;
531 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000532 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000533 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000534 struct attr_extra *attre = attr->extra;
535
536 if (attre->ecommunity)
537 {
538 if (! attre->ecommunity->refcnt)
539 attre->ecommunity = ecommunity_intern (attre->ecommunity);
540 else
541 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000542
Paul Jakmafb982c22007-05-04 20:15:47 +0000543 }
544 if (attre->cluster)
545 {
546 if (! attre->cluster->refcnt)
547 attre->cluster = cluster_intern (attre->cluster);
548 else
549 attre->cluster->refcnt++;
550 }
551 if (attre->transit)
552 {
553 if (! attre->transit->refcnt)
554 attre->transit = transit_intern (attre->transit);
555 else
556 attre->transit->refcnt++;
557 }
paul718e3742002-12-13 20:15:29 +0000558 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000559
paul718e3742002-12-13 20:15:29 +0000560 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
561 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000562
paul718e3742002-12-13 20:15:29 +0000563 return find;
564}
565
Paul Jakma03e214c2007-04-29 18:31:07 +0000566
paul718e3742002-12-13 20:15:29 +0000567/* Make network statement's attribute. */
568struct attr *
569bgp_attr_default_set (struct attr *attr, u_char origin)
570{
571 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000572 bgp_attr_extra_get (attr);
573
paul718e3742002-12-13 20:15:29 +0000574 attr->origin = origin;
575 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
576 attr->aspath = aspath_empty ();
577 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000578 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000579 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
580#ifdef HAVE_IPV6
Paul Jakmafb982c22007-05-04 20:15:47 +0000581 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000582#endif
Paul Jakma03e214c2007-04-29 18:31:07 +0000583
paul718e3742002-12-13 20:15:29 +0000584 return attr;
585}
586
Paul Jakma03e214c2007-04-29 18:31:07 +0000587
paul718e3742002-12-13 20:15:29 +0000588/* Make network statement's attribute. */
589struct attr *
590bgp_attr_default_intern (u_char origin)
591{
592 struct attr attr;
593 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000594
Paul Jakma03e214c2007-04-29 18:31:07 +0000595 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000596
597 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000598 bgp_attr_extra_free (&attr);
599
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000600 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000601 return new;
602}
603
604struct attr *
605bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
606 struct aspath *aspath,
607 struct community *community, int as_set)
608{
609 struct attr attr;
610 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000611 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000612
613 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000614 memset (&attre, 0, sizeof (struct attr_extra));
615 attr.extra = &attre;
616
paul718e3742002-12-13 20:15:29 +0000617 /* Origin attribute. */
618 attr.origin = origin;
619 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
620
621 /* AS path attribute. */
622 if (aspath)
623 attr.aspath = aspath_intern (aspath);
624 else
625 attr.aspath = aspath_empty ();
626 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
627
628 /* Next hop attribute. */
629 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
630
631 if (community)
632 {
633 attr.community = community;
634 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
635 }
636
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000637 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000638#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000639 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000640#endif
641 if (! as_set)
642 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
643 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
644 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000645 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000646 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000647 attre.aggregator_as = bgp->as;
648 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000649
650 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000651
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000652 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000653 return new;
654}
655
Paul Jakmab881c702010-11-23 16:35:42 +0000656/* Unintern just the sub-components of the attr, but not the attr */
657void
658bgp_attr_unintern_sub (struct attr *attr)
659{
660 /* aspath refcount shoud be decrement. */
661 if (attr->aspath)
662 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000663 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000664
665 if (attr->community)
666 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000667 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000668
669 if (attr->extra)
670 {
671 if (attr->extra->ecommunity)
672 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000673 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000674
675 if (attr->extra->cluster)
676 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000677 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000678
679 if (attr->extra->transit)
680 transit_unintern (attr->extra->transit);
681 }
682}
683
paul718e3742002-12-13 20:15:29 +0000684/* Free bgp attribute and aspath. */
685void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000686bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000687{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000688 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000689 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000690 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000691 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000692
paul718e3742002-12-13 20:15:29 +0000693 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000694 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000695
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000696 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000697
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000698 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000699 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000700 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000701 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000702 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000703
paul718e3742002-12-13 20:15:29 +0000704 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000705 if (attr->refcnt == 0)
706 {
707 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000708 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000709 bgp_attr_extra_free (attr);
710 XFREE (MTYPE_ATTR, attr);
711 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000712 }
713
Paul Jakmab881c702010-11-23 16:35:42 +0000714 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000715}
716
717void
718bgp_attr_flush (struct attr *attr)
719{
720 if (attr->aspath && ! attr->aspath->refcnt)
721 aspath_free (attr->aspath);
722 if (attr->community && ! attr->community->refcnt)
723 community_free (attr->community);
Paul Jakmafb982c22007-05-04 20:15:47 +0000724 if (attr->extra)
725 {
726 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000727
Paul Jakmafb982c22007-05-04 20:15:47 +0000728 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000729 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000730 if (attre->cluster && ! attre->cluster->refcnt)
731 cluster_free (attre->cluster);
732 if (attre->transit && ! attre->transit->refcnt)
733 transit_free (attre->transit);
734 }
paul718e3742002-12-13 20:15:29 +0000735}
736
Paul Jakmab881c702010-11-23 16:35:42 +0000737/* Implement draft-scudder-idr-optional-transitive behaviour and
738 * avoid resetting sessions for malformed attributes which are
739 * are partial/optional and hence where the error likely was not
740 * introduced by the sending neighbour.
741 */
742static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000743bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
744 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000745{
Paul Jakma835315b2012-01-18 12:28:30 +0000746 struct peer *const peer = args->peer;
747 const u_int8_t flags = args->flags;
748 /* startp and length must be special-cased, as whether or not to
749 * send the attribute data with the NOTIFY depends on the error,
750 * the caller therefore signals this with the seperate length argument
751 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000752 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000753
Paul Jakmab881c702010-11-23 16:35:42 +0000754 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000755 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000756 {
757 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000758 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000759 return BGP_ATTR_PARSE_ERROR;
760
761 }
762
Paul Jakmabd471fe2012-03-15 11:30:00 +0000763 /* Adjust the stream getp to the end of the attribute, in case we can
764 * still proceed but the caller hasn't read all the attribute.
765 */
766 stream_set_getp (BGP_INPUT (peer),
767 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
768 + args->total);
769
Paul Jakma835315b2012-01-18 12:28:30 +0000770 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100771 /* where an attribute is relatively inconsequential, e.g. it does not
772 * affect route selection, and can be safely ignored, then any such
773 * attributes which are malformed should just be ignored and the route
774 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000775 */
776 case BGP_ATTR_AS4_AGGREGATOR:
777 case BGP_ATTR_AGGREGATOR:
778 case BGP_ATTR_ATOMIC_AGGREGATE:
779 return BGP_ATTR_PARSE_PROCEED;
780
781 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100782 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000783 */
784 case BGP_ATTR_ORIGIN:
785 case BGP_ATTR_AS_PATH:
786 case BGP_ATTR_NEXT_HOP:
787 case BGP_ATTR_MULTI_EXIT_DISC:
788 case BGP_ATTR_LOCAL_PREF:
789 case BGP_ATTR_COMMUNITIES:
790 case BGP_ATTR_ORIGINATOR_ID:
791 case BGP_ATTR_CLUSTER_LIST:
792 case BGP_ATTR_MP_REACH_NLRI:
793 case BGP_ATTR_MP_UNREACH_NLRI:
794 case BGP_ATTR_EXT_COMMUNITIES:
795 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000796 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000797 return BGP_ATTR_PARSE_ERROR;
798 }
799
800 /* Partial optional attributes that are malformed should not cause
801 * the whole session to be reset. Instead treat it as a withdrawal
802 * of the routes, if possible.
803 */
Paul Jakma835315b2012-01-18 12:28:30 +0000804 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
805 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
806 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000807 return BGP_ATTR_PARSE_WITHDRAW;
808
809 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200810 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000811}
812
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400813/* Find out what is wrong with the path attribute flag bits and log the error.
814 "Flag bits" here stand for Optional, Transitive and Partial, but not for
815 Extended Length. Checking O/T/P bits at once implies, that the attribute
816 being diagnosed is defined by RFC as either a "well-known" or an "optional,
817 non-transitive" attribute. */
818static void
Paul Jakma835315b2012-01-18 12:28:30 +0000819bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
820 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400821)
822{
823 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000824 u_char real_flags = args->flags;
825 const u_int8_t attr_code = args->type;
826
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400827 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
828 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
829 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
830 if
831 (
832 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
833 CHECK_FLAG (real_flags, attr_flag_str[i].key)
834 )
835 {
Paul Jakma835315b2012-01-18 12:28:30 +0000836 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400837 LOOKUP (attr_str, attr_code),
838 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
839 attr_flag_str[i].str);
840 seen = 1;
841 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100842 if (!seen)
843 {
844 zlog (args->peer->log, LOG_DEBUG,
845 "Strange, %s called for attr %s, but no problem found with flags"
846 " (real flags 0x%x, desired 0x%x)",
847 __func__, LOOKUP (attr_str, attr_code),
848 real_flags, desired_flags);
849 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400850}
851
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000852/* Required flags for attributes. EXTLEN will be masked off when testing,
853 * as will PARTIAL for optional+transitive attributes.
854 */
855const u_int8_t attr_flags_values [] = {
856 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
857 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
858 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
859 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
860 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
861 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
862 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
863 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
864 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
865 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
866 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
867 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
868 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
869 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
870 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
871};
872static const size_t attr_flags_values_max =
873 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
874
875static int
Paul Jakma835315b2012-01-18 12:28:30 +0000876bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000877{
878 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +0000879 const u_int8_t flags = args->flags;
880 const u_int8_t attr_code = args->type;
881 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000882
883 /* there may be attributes we don't know about */
884 if (attr_code > attr_flags_values_max)
885 return 0;
886 if (attr_flags_values[attr_code] == 0)
887 return 0;
888
889 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
890 * 1."
891 */
892 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
893 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
894 {
895 zlog (peer->log, LOG_ERR,
896 "%s well-known attributes must have transitive flag set (%x)",
897 LOOKUP (attr_str, attr_code), flags);
898 return 1;
899 }
900
901 /* "For well-known attributes and for optional non-transitive attributes,
902 * the Partial bit MUST be set to 0."
903 */
904 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
905 {
906 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
907 {
908 zlog (peer->log, LOG_ERR,
909 "%s well-known attribute "
910 "must NOT have the partial flag set (%x)",
911 LOOKUP (attr_str, attr_code), flags);
912 return 1;
913 }
914 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
915 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
916 {
917 zlog (peer->log, LOG_ERR,
918 "%s optional + transitive attribute "
919 "must NOT have the partial flag set (%x)",
920 LOOKUP (attr_str, attr_code), flags);
921 return 1;
922 }
923 }
924
925 /* Optional transitive attributes may go through speakers that don't
926 * reocgnise them and set the Partial bit.
927 */
928 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
929 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
930 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
931
Paul Jakma683f2b82012-03-23 14:58:45 +0000932 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000933 == attr_flags_values[attr_code])
934 return 0;
935
Paul Jakma835315b2012-01-18 12:28:30 +0000936 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000937 return 1;
938}
939
paul718e3742002-12-13 20:15:29 +0000940/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +0000941static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000942bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000943{
Paul Jakma835315b2012-01-18 12:28:30 +0000944 struct peer *const peer = args->peer;
945 struct attr *const attr = args->attr;
946 const bgp_size_t length = args->length;
947
paul718e3742002-12-13 20:15:29 +0000948 /* If any recognized attribute has Attribute Length that conflicts
949 with the expected length (based on the attribute type code), then
950 the Error Subcode is set to Attribute Length Error. The Data
951 field contains the erroneous attribute (type, length and
952 value). */
953 if (length != 1)
954 {
955 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
956 length);
Paul Jakma835315b2012-01-18 12:28:30 +0000957 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000958 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +0000959 args->total);
paul718e3742002-12-13 20:15:29 +0000960 }
961
962 /* Fetch origin attribute. */
963 attr->origin = stream_getc (BGP_INPUT (peer));
964
965 /* If the ORIGIN attribute has an undefined value, then the Error
966 Subcode is set to Invalid Origin Attribute. The Data field
967 contains the unrecognized attribute (type, length and value). */
968 if ((attr->origin != BGP_ORIGIN_IGP)
969 && (attr->origin != BGP_ORIGIN_EGP)
970 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
971 {
972 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
973 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +0000974 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000975 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +0000976 args->total);
paul718e3742002-12-13 20:15:29 +0000977 }
978
979 /* Set oring attribute flag. */
980 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
981
982 return 0;
983}
Paul Jakmaab005292010-11-27 22:48:34 +0000984
985/* Parse AS path information. This function is wrapper of
986 aspath_parse. */
987static int
Paul Jakma835315b2012-01-18 12:28:30 +0000988bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000989{
Paul Jakma835315b2012-01-18 12:28:30 +0000990 struct attr *const attr = args->attr;
991 struct peer *const peer = args->peer;
992 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +0000993
Paul Jakmaab005292010-11-27 22:48:34 +0000994 /*
995 * peer with AS4 => will get 4Byte ASnums
996 * otherwise, will get 16 Bit
997 */
998 attr->aspath = aspath_parse (peer->ibuf, length,
999 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1000
1001 /* In case of IBGP, length will be zero. */
1002 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001003 {
Paul Jakmab881c702010-11-23 16:35:42 +00001004 zlog (peer->log, LOG_ERR,
1005 "Malformed AS path from %s, length is %d",
1006 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001007 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001008 }
Chris Hallcddb8112010-08-09 22:31:37 +04001009
Paul Jakmaab005292010-11-27 22:48:34 +00001010 /* Set aspath attribute flag. */
1011 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001012
Paul Jakmab881c702010-11-23 16:35:42 +00001013 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001014}
1015
Paul Jakmab881c702010-11-23 16:35:42 +00001016static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001017bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001018{
1019 /* These checks were part of bgp_attr_aspath, but with
1020 * as4 we should to check aspath things when
1021 * aspath synthesizing with as4_path has already taken place.
1022 * Otherwise we check ASPATH and use the synthesized thing, and that is
1023 * not right.
1024 * So do the checks later, i.e. here
1025 */
1026 struct bgp *bgp = peer->bgp;
1027 struct aspath *aspath;
1028
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001029 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001030 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1031 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001032 {
1033 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001034 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1035 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1036 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001037 }
1038
paul718e3742002-12-13 20:15:29 +00001039 /* First AS check for EBGP. */
1040 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1041 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001042 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001043 && ! aspath_firstas_check (attr->aspath, peer->as))
1044 {
1045 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001046 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001047 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1048 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1049 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001050 }
1051 }
1052
1053 /* local-as prepend */
1054 if (peer->change_local_as &&
1055 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1056 {
1057 aspath = aspath_dup (attr->aspath);
1058 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001059 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001060 attr->aspath = aspath_intern (aspath);
1061 }
1062
Paul Jakmab881c702010-11-23 16:35:42 +00001063 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001064}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001065
Paul Jakmaab005292010-11-27 22:48:34 +00001066/* Parse AS4 path information. This function is another wrapper of
1067 aspath_parse. */
1068static int
Paul Jakma835315b2012-01-18 12:28:30 +00001069bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001070{
Paul Jakma835315b2012-01-18 12:28:30 +00001071 struct peer *const peer = args->peer;
1072 struct attr *const attr = args->attr;
1073 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001074
Paul Jakmaab005292010-11-27 22:48:34 +00001075 *as4_path = aspath_parse (peer->ibuf, length, 1);
1076
Paul Jakmab881c702010-11-23 16:35:42 +00001077 /* In case of IBGP, length will be zero. */
1078 if (!*as4_path)
1079 {
1080 zlog (peer->log, LOG_ERR,
1081 "Malformed AS4 path from %s, length is %d",
1082 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001083 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001084 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001085 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001086 }
1087
Paul Jakmaab005292010-11-27 22:48:34 +00001088 /* Set aspath attribute flag. */
1089 if (as4_path)
1090 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1091
Paul Jakmab881c702010-11-23 16:35:42 +00001092 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001093}
1094
paul718e3742002-12-13 20:15:29 +00001095/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001096static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001097bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001098{
Paul Jakma835315b2012-01-18 12:28:30 +00001099 struct peer *const peer = args->peer;
1100 struct attr *const attr = args->attr;
1101 const bgp_size_t length = args->length;
1102
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001103 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001104
paul718e3742002-12-13 20:15:29 +00001105 /* Check nexthop attribute length. */
1106 if (length != 4)
1107 {
1108 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1109 length);
1110
Paul Jakma835315b2012-01-18 12:28:30 +00001111 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001112 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001113 args->total);
paul718e3742002-12-13 20:15:29 +00001114 }
1115
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001116 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1117 attribute must result in a NOTIFICATION message (this is implemented below).
1118 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1119 logged locally (this is implemented somewhere else). The UPDATE message
1120 gets ignored in any of these cases. */
1121 nexthop_n = stream_get_ipv4 (peer->ibuf);
1122 nexthop_h = ntohl (nexthop_n);
1123 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1124 {
1125 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001126 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001127 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001128 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001129 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001130 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001131 }
1132
1133 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001134 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1135
Paul Jakmab881c702010-11-23 16:35:42 +00001136 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001137}
1138
1139/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001140static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001141bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001142{
Paul Jakma835315b2012-01-18 12:28:30 +00001143 struct peer *const peer = args->peer;
1144 struct attr *const attr = args->attr;
1145 const bgp_size_t length = args->length;
1146
paul718e3742002-12-13 20:15:29 +00001147 /* Length check. */
1148 if (length != 4)
1149 {
1150 zlog (peer->log, LOG_ERR,
1151 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001152
Paul Jakma835315b2012-01-18 12:28:30 +00001153 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001154 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001155 args->total);
paul718e3742002-12-13 20:15:29 +00001156 }
1157
1158 attr->med = stream_getl (peer->ibuf);
1159
1160 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1161
Paul Jakmab881c702010-11-23 16:35:42 +00001162 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001163}
1164
1165/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001166static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001167bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001168{
Paul Jakma835315b2012-01-18 12:28:30 +00001169 struct peer *const peer = args->peer;
1170 struct attr *const attr = args->attr;
1171 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001172
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001173 /* Length check. */
1174 if (length != 4)
1175 {
Paul Jakma835315b2012-01-18 12:28:30 +00001176 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1177 length);
1178 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001179 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001180 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001181 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001182
paul718e3742002-12-13 20:15:29 +00001183 /* If it is contained in an UPDATE message that is received from an
1184 external peer, then this attribute MUST be ignored by the
1185 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001186 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001187 {
paul9985f832005-02-09 15:51:56 +00001188 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001189 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001190 }
1191
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001192 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001193
1194 /* Set atomic aggregate flag. */
1195 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1196
Paul Jakmab881c702010-11-23 16:35:42 +00001197 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001198}
1199
1200/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001201static int
Paul Jakma835315b2012-01-18 12:28:30 +00001202bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001203{
Paul Jakma835315b2012-01-18 12:28:30 +00001204 struct peer *const peer = args->peer;
1205 struct attr *const attr = args->attr;
1206 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001207
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001208 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001209 if (length != 0)
1210 {
Paul Jakma835315b2012-01-18 12:28:30 +00001211 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1212 length);
1213 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001214 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001215 args->total);
paul718e3742002-12-13 20:15:29 +00001216 }
1217
1218 /* Set atomic aggregate flag. */
1219 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1220
Paul Jakmab881c702010-11-23 16:35:42 +00001221 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001222}
1223
1224/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001225static int
Paul Jakma835315b2012-01-18 12:28:30 +00001226bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001227{
Paul Jakma835315b2012-01-18 12:28:30 +00001228 struct peer *const peer = args->peer;
1229 struct attr *const attr = args->attr;
1230 const bgp_size_t length = args->length;
1231
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001232 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001233 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001234
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001235 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001236 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001237 wantedlen = 8;
1238
1239 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001240 {
Paul Jakma835315b2012-01-18 12:28:30 +00001241 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1242 wantedlen, length);
1243 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001244 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001245 args->total);
paul718e3742002-12-13 20:15:29 +00001246 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001247
1248 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1249 attre->aggregator_as = stream_getl (peer->ibuf);
1250 else
1251 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001252 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001253
1254 /* Set atomic aggregate flag. */
1255 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1256
Paul Jakmab881c702010-11-23 16:35:42 +00001257 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001258}
1259
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001260/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001261static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001262bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1263 as_t *as4_aggregator_as,
1264 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001265{
Paul Jakma835315b2012-01-18 12:28:30 +00001266 struct peer *const peer = args->peer;
1267 struct attr *const attr = args->attr;
1268 const bgp_size_t length = args->length;
1269
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001270 if (length != 8)
1271 {
Paul Jakma835315b2012-01-18 12:28:30 +00001272 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1273 length);
1274 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001275 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001276 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001277 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001278
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001279 *as4_aggregator_as = stream_getl (peer->ibuf);
1280 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1281
1282 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1283
Paul Jakmab881c702010-11-23 16:35:42 +00001284 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001285}
1286
1287/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1288 */
Paul Jakmab881c702010-11-23 16:35:42 +00001289static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001290bgp_attr_munge_as4_attrs (struct peer *const peer,
1291 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001292 struct aspath *as4_path, as_t as4_aggregator,
1293 struct in_addr *as4_aggregator_addr)
1294{
1295 int ignore_as4_path = 0;
1296 struct aspath *newpath;
1297 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001298
1299 if (!attr->aspath)
1300 {
1301 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1302 * checked that all well-known, mandatory attributes were present.
1303 *
1304 * Can only be a problem with peer itself - hard error
1305 */
1306 return BGP_ATTR_PARSE_ERROR;
1307 }
1308
Paul Jakmab881c702010-11-23 16:35:42 +00001309 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001310 {
1311 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1312 * if given.
1313 * It is worth a warning though, because the peer really
1314 * should not send them
1315 */
1316 if (BGP_DEBUG(as4, AS4))
1317 {
1318 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1319 zlog_debug ("[AS4] %s %s AS4_PATH",
1320 peer->host, "AS4 capable peer, yet it sent");
1321
1322 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1323 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1324 peer->host, "AS4 capable peer, yet it sent");
1325 }
1326
Paul Jakmab881c702010-11-23 16:35:42 +00001327 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001328 }
1329
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001330 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1331 * because that may override AS4_PATH
1332 */
1333 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1334 {
Paul Jakmab881c702010-11-23 16:35:42 +00001335 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001336 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001337 assert (attre);
1338
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001339 /* received both.
1340 * if the as_number in aggregator is not AS_TRANS,
1341 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1342 * and the Aggregator shall be taken as
1343 * info on the aggregating node, and the AS_PATH
1344 * shall be taken as the AS_PATH
1345 * otherwise
1346 * the Aggregator shall be ignored and the
1347 * AS4_AGGREGATOR shall be taken as the
1348 * Aggregating node and the AS_PATH is to be
1349 * constructed "as in all other cases"
1350 */
Paul Jakmab881c702010-11-23 16:35:42 +00001351 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001352 {
1353 /* ignore */
1354 if ( BGP_DEBUG(as4, AS4))
1355 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1356 " send AGGREGATOR != AS_TRANS and"
1357 " AS4_AGGREGATOR, so ignore"
1358 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1359 ignore_as4_path = 1;
1360 }
1361 else
1362 {
1363 /* "New_aggregator shall be taken as aggregator" */
1364 attre->aggregator_as = as4_aggregator;
1365 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1366 }
1367 }
1368 else
1369 {
1370 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1371 * That is bogus - but reading the conditions
1372 * we have to handle AS4_AGGREGATOR as if it were
1373 * AGGREGATOR in that case
1374 */
1375 if ( BGP_DEBUG(as4, AS4))
1376 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1377 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1378 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001379 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001380 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1381 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1382 }
1383 }
1384
1385 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001386 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001387 {
Paul Jakma055086f2014-09-23 15:23:01 +01001388 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1389 aspath_unintern (&attr->aspath);
1390 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001391 }
Paul Jakmab881c702010-11-23 16:35:42 +00001392 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001393}
1394
paul718e3742002-12-13 20:15:29 +00001395/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001396static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001397bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001398{
Paul Jakma835315b2012-01-18 12:28:30 +00001399 struct peer *const peer = args->peer;
1400 struct attr *const attr = args->attr;
1401 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001402
paul718e3742002-12-13 20:15:29 +00001403 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001404 {
1405 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001406 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001407 }
Paul Jakma0c466382010-12-05 17:17:26 +00001408
1409 attr->community =
1410 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1411
1412 /* XXX: fix community_parse to use stream API and remove this */
1413 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001414
Paul Jakma0c466382010-12-05 17:17:26 +00001415 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001416 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001417 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001418 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001419
paul718e3742002-12-13 20:15:29 +00001420 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1421
Paul Jakmab881c702010-11-23 16:35:42 +00001422 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001423}
1424
1425/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001426static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001427bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001428{
Paul Jakma835315b2012-01-18 12:28:30 +00001429 struct peer *const peer = args->peer;
1430 struct attr *const attr = args->attr;
1431 const bgp_size_t length = args->length;
1432
Denis Ovsienkod595b562011-09-30 15:08:54 +04001433 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001434 if (length != 4)
1435 {
1436 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1437
Paul Jakma835315b2012-01-18 12:28:30 +00001438 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001439 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001440 args->total);
paul718e3742002-12-13 20:15:29 +00001441 }
1442
Paul Jakmafb982c22007-05-04 20:15:47 +00001443 (bgp_attr_extra_get (attr))->originator_id.s_addr
1444 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001445
1446 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1447
Paul Jakmab881c702010-11-23 16:35:42 +00001448 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001449}
1450
1451/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001452static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001453bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001454{
Paul Jakma835315b2012-01-18 12:28:30 +00001455 struct peer *const peer = args->peer;
1456 struct attr *const attr = args->attr;
1457 const bgp_size_t length = args->length;
1458
paul718e3742002-12-13 20:15:29 +00001459 /* Check length. */
1460 if (length % 4)
1461 {
1462 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1463
Paul Jakma835315b2012-01-18 12:28:30 +00001464 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1465 args->total);
paul718e3742002-12-13 20:15:29 +00001466 }
1467
Paul Jakmafb982c22007-05-04 20:15:47 +00001468 (bgp_attr_extra_get (attr))->cluster
1469 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001470
1471 /* XXX: Fix cluster_parse to use stream API and then remove this */
1472 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001473
1474 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1475
Paul Jakmab881c702010-11-23 16:35:42 +00001476 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001477}
1478
1479/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001480int
Paul Jakma835315b2012-01-18 12:28:30 +00001481bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1482 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001483{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001484 afi_t afi;
1485 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001486 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001487 size_t start;
paul718e3742002-12-13 20:15:29 +00001488 int ret;
1489 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001490 struct peer *const peer = args->peer;
1491 struct attr *const attr = args->attr;
1492 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001493 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001494
paul718e3742002-12-13 20:15:29 +00001495 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001496 s = BGP_INPUT(peer);
1497 start = stream_get_getp(s);
1498
1499 /* safe to read statically sized header? */
1500#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001501#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001502 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001503 {
1504 zlog_info ("%s: %s sent invalid length, %lu",
1505 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001506 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001507 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001508
paul718e3742002-12-13 20:15:29 +00001509 /* Load AFI, SAFI. */
1510 afi = stream_getw (s);
1511 safi = stream_getc (s);
1512
1513 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001514 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001515
Paul Jakma03292802008-06-07 20:37:10 +00001516 if (LEN_LEFT < attre->mp_nexthop_len)
1517 {
1518 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1519 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001520 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001521 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001522
paul718e3742002-12-13 20:15:29 +00001523 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001524 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001525 {
1526 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001527 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001528 /* Probably needed for RFC 2283 */
1529 if (attr->nexthop.s_addr == 0)
1530 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001531 break;
1532 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001533 stream_getl (s); /* RD high */
1534 stream_getl (s); /* RD low */
1535 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001536 break;
1537#ifdef HAVE_IPV6
Lou Berger9da04bc2016-01-12 13:41:55 -05001538 case 24:
1539 {
1540 u_int32_t rd_high __attribute__((unused));
1541 u_int32_t rd_low __attribute__((unused));
1542
1543 rd_high = stream_getl (s);
1544 rd_low = stream_getl (s);
1545 }
1546 /* fall through */
paul718e3742002-12-13 20:15:29 +00001547 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001548 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001549 break;
1550 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001551 case 48:
1552 if (attre->mp_nexthop_len == 48) {
1553 u_int32_t rd_high __attribute__((unused));
1554 u_int32_t rd_low __attribute__((unused));
1555
1556 rd_high = stream_getl (s);
1557 rd_low = stream_getl (s);
1558 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001559 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001560
1561 if (attre->mp_nexthop_len == 48) {
1562 u_int32_t rd_high __attribute__((unused));
1563 u_int32_t rd_low __attribute__((unused));
1564
1565 rd_high = stream_getl (s);
1566 rd_low = stream_getl (s);
1567 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001568 stream_get (&attre->mp_nexthop_local, s, 16);
1569 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001570 {
1571 char buf1[INET6_ADDRSTRLEN];
1572 char buf2[INET6_ADDRSTRLEN];
1573
1574 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001575 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 +00001576 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001577 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001578 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001579 buf2, INET6_ADDRSTRLEN));
1580
Paul Jakmafb982c22007-05-04 20:15:47 +00001581 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001582 }
1583 break;
1584#endif /* HAVE_IPV6 */
1585 default:
Paul Jakma03292802008-06-07 20:37:10 +00001586 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1587 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001588 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001589 }
1590
Paul Jakma03292802008-06-07 20:37:10 +00001591 if (!LEN_LEFT)
1592 {
1593 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1594 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001595 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001596 }
paul718e3742002-12-13 20:15:29 +00001597
Paul Jakma6e4ab122007-04-10 19:36:48 +00001598 {
1599 u_char val;
1600 if ((val = stream_getc (s)))
1601 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1602 peer->host, val);
1603 }
1604
1605 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001606 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001607 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001608 {
1609 zlog_info ("%s: (%s) Failed to read NLRI",
1610 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001611 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001612 }
paul718e3742002-12-13 20:15:29 +00001613
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001614 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001615 {
Lou Berger050defe2016-01-12 13:41:59 -05001616 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s), nlri_len);
Paul Jakma03292802008-06-07 20:37:10 +00001617 if (ret < 0)
1618 {
1619 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1620 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001621 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001622 }
paul718e3742002-12-13 20:15:29 +00001623 }
1624
1625 mp_update->afi = afi;
1626 mp_update->safi = safi;
1627 mp_update->nlri = stream_pnt (s);
1628 mp_update->length = nlri_len;
1629
paul9985f832005-02-09 15:51:56 +00001630 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001631
David Lamparterdaefeb82014-12-08 17:42:12 +01001632 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1633
Paul Jakmab881c702010-11-23 16:35:42 +00001634 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001635#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001636}
1637
1638/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001639int
Paul Jakma835315b2012-01-18 12:28:30 +00001640bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001641 struct bgp_nlri *mp_withdraw)
1642{
1643 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001644 afi_t afi;
1645 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001646 u_int16_t withdraw_len;
1647 int ret;
Paul Jakma835315b2012-01-18 12:28:30 +00001648 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001649 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001650 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001651
1652 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001653
1654#define BGP_MP_UNREACH_MIN_SIZE 3
1655 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001656 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001657
paul718e3742002-12-13 20:15:29 +00001658 afi = stream_getw (s);
1659 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001660
1661 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001662
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001663 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001664 {
Lou Berger050defe2016-01-12 13:41:59 -05001665 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s), withdraw_len);
paul718e3742002-12-13 20:15:29 +00001666 if (ret < 0)
David Lamparterf57000c2014-06-04 01:01:10 +02001667 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001668 }
1669
1670 mp_withdraw->afi = afi;
1671 mp_withdraw->safi = safi;
1672 mp_withdraw->nlri = stream_pnt (s);
1673 mp_withdraw->length = withdraw_len;
1674
paul9985f832005-02-09 15:51:56 +00001675 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001676
David Lamparterdaefeb82014-12-08 17:42:12 +01001677 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1678
Paul Jakmab881c702010-11-23 16:35:42 +00001679 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001680}
1681
1682/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001683static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001684bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001685{
Paul Jakma835315b2012-01-18 12:28:30 +00001686 struct peer *const peer = args->peer;
1687 struct attr *const attr = args->attr;
1688 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001689
paul718e3742002-12-13 20:15:29 +00001690 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001691 {
1692 if (attr->extra)
1693 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001694 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001695 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001696 }
Paul Jakma0c466382010-12-05 17:17:26 +00001697
1698 (bgp_attr_extra_get (attr))->ecommunity =
1699 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1700 /* XXX: fix ecommunity_parse to use stream API */
1701 stream_forward_getp (peer->ibuf, length);
1702
1703 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001704 return bgp_attr_malformed (args,
1705 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1706 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001707
paul718e3742002-12-13 20:15:29 +00001708 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1709
Paul Jakmab881c702010-11-23 16:35:42 +00001710 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001711}
1712
1713/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001714static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001715bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001716{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001717 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001718 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001719 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001720 struct peer *const peer = args->peer;
1721 struct attr *const attr = args->attr;
1722 u_char *const startp = args->startp;
1723 const u_char type = args->type;
1724 const u_char flag = args->flags;
1725 const bgp_size_t length = args->length;
1726
paul718e3742002-12-13 20:15:29 +00001727
hassof4184462005-02-01 20:13:16 +00001728 if (BGP_DEBUG (normal, NORMAL))
1729 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1730 peer->host, type, length);
1731
paul718e3742002-12-13 20:15:29 +00001732 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001733 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001734 "Unknown attribute type %d length %d is received", type, length);
1735
1736 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001737 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001738
paul718e3742002-12-13 20:15:29 +00001739 /* If any of the mandatory well-known attributes are not recognized,
1740 then the Error Subcode is set to Unrecognized Well-known
1741 Attribute. The Data field contains the unrecognized attribute
1742 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001743 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001744 {
Paul Jakma835315b2012-01-18 12:28:30 +00001745 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001746 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001747 args->total);
paul718e3742002-12-13 20:15:29 +00001748 }
1749
1750 /* Unrecognized non-transitive optional attributes must be quietly
1751 ignored and not passed along to other BGP peers. */
1752 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001753 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001754
1755 /* If a path with recognized transitive optional attribute is
1756 accepted and passed along to other BGP peers and the Partial bit
1757 in the Attribute Flags octet is set to 1 by some previous AS, it
1758 is not set back to 0 by the current AS. */
1759 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1760
1761 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001762 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001763 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001764
Paul Jakmafb982c22007-05-04 20:15:47 +00001765 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001766
1767 if (transit->val)
1768 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1769 transit->length + total);
1770 else
1771 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1772
1773 memcpy (transit->val + transit->length, startp, total);
1774 transit->length += total;
1775
Paul Jakmab881c702010-11-23 16:35:42 +00001776 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001777}
1778
Paul Jakma055086f2014-09-23 15:23:01 +01001779/* Well-known attribute check. */
1780static int
1781bgp_attr_check (struct peer *peer, struct attr *attr)
1782{
1783 u_char type = 0;
1784
Paul Jakmaaed1b552014-10-21 16:59:01 +01001785 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
1786 * empty UPDATE. */
1787 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
1788 return BGP_ATTR_PARSE_PROCEED;
1789
1790 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
1791 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
1792 are present, it should. Check for any other attribute being present
1793 instead.
1794 */
1795 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
1796 return BGP_ATTR_PARSE_PROCEED;
1797
Paul Jakma055086f2014-09-23 15:23:01 +01001798 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1799 type = BGP_ATTR_ORIGIN;
1800
1801 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1802 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001803
1804 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
1805 * NLRI is empty. We can't easily check NLRI empty here though.
1806 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00001807 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
1808 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01001809 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001810
Paul Jakma055086f2014-09-23 15:23:01 +01001811 if (peer->sort == BGP_PEER_IBGP
1812 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1813 type = BGP_ATTR_LOCAL_PREF;
1814
1815 if (type)
1816 {
1817 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01001818 "%s Missing well-known attribute %d / %s",
1819 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01001820 bgp_notify_send_with_data (peer,
1821 BGP_NOTIFY_UPDATE_ERR,
1822 BGP_NOTIFY_UPDATE_MISS_ATTR,
1823 &type, 1);
1824 return BGP_ATTR_PARSE_ERROR;
1825 }
1826 return BGP_ATTR_PARSE_PROCEED;
1827}
1828
paul718e3742002-12-13 20:15:29 +00001829/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00001830 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00001831bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00001832bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1833 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1834{
1835 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00001836 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001837 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00001838 bgp_size_t length;
1839 u_char *startp, *endp;
1840 u_char *attr_endp;
1841 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001842 /* we need the as4_path only until we have synthesized the as_path with it */
1843 /* same goes for as4_aggregator */
1844 struct aspath *as4_path = NULL;
1845 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07001846 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00001847
1848 /* Initialize bitmap. */
1849 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1850
1851 /* End pointer of BGP attribute. */
1852 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00001853
paul718e3742002-12-13 20:15:29 +00001854 /* Get attributes to the end of attribute length. */
1855 while (BGP_INPUT_PNT (peer) < endp)
1856 {
1857 /* Check remaining length check.*/
1858 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1859 {
gdtc29fdba2004-12-09 14:46:46 +00001860 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00001861 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001862 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001863 peer->host,
1864 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00001865
1866 bgp_notify_send (peer,
1867 BGP_NOTIFY_UPDATE_ERR,
1868 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001869 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001870 }
1871
1872 /* Fetch attribute flag and type. */
1873 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04001874 /* "The lower-order four bits of the Attribute Flags octet are
1875 unused. They MUST be zero when sent and MUST be ignored when
1876 received." */
1877 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00001878 type = stream_getc (BGP_INPUT (peer));
1879
Paul Jakma370b64a2007-12-22 16:49:52 +00001880 /* Check whether Extended-Length applies and is in bounds */
1881 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1882 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1883 {
1884 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001885 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00001886 peer->host,
1887 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1888
1889 bgp_notify_send (peer,
1890 BGP_NOTIFY_UPDATE_ERR,
1891 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001892 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00001893 }
Paul Jakma835315b2012-01-18 12:28:30 +00001894
paul718e3742002-12-13 20:15:29 +00001895 /* Check extended attribue length bit. */
1896 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1897 length = stream_getw (BGP_INPUT (peer));
1898 else
1899 length = stream_getc (BGP_INPUT (peer));
1900
1901 /* If any attribute appears more than once in the UPDATE
1902 message, then the Error Subcode is set to Malformed Attribute
1903 List. */
1904
1905 if (CHECK_BITMAP (seen, type))
1906 {
1907 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001908 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00001909 peer->host, type);
1910
1911 bgp_notify_send (peer,
1912 BGP_NOTIFY_UPDATE_ERR,
1913 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00001914 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001915 }
1916
1917 /* Set type to bitmap to check duplicate attribute. `type' is
1918 unsigned char so it never overflow bitmap range. */
1919
1920 SET_BITMAP (seen, type);
1921
1922 /* Overflow check. */
1923 attr_endp = BGP_INPUT_PNT (peer) + length;
1924
1925 if (attr_endp > endp)
1926 {
1927 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001928 "%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 +00001929 bgp_notify_send (peer,
1930 BGP_NOTIFY_UPDATE_ERR,
1931 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001932 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001933 }
Paul Jakma835315b2012-01-18 12:28:30 +00001934
1935 struct bgp_attr_parser_args attr_args = {
1936 .peer = peer,
1937 .length = length,
1938 .attr = attr,
1939 .type = type,
1940 .flags = flag,
1941 .startp = startp,
1942 .total = attr_endp - startp,
1943 };
1944
1945
1946 /* If any recognized attribute has Attribute Flags that conflict
1947 with the Attribute Type Code, then the Error Subcode is set to
1948 Attribute Flags Error. The Data field contains the erroneous
1949 attribute (type, length and value). */
1950 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01001951 {
1952 bgp_attr_parse_ret_t ret;
1953 ret = bgp_attr_malformed (&attr_args,
1954 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1955 attr_args.total);
1956 if (ret == BGP_ATTR_PARSE_PROCEED)
1957 continue;
1958 return ret;
1959 }
paul718e3742002-12-13 20:15:29 +00001960
1961 /* OK check attribute and store it's value. */
1962 switch (type)
1963 {
1964 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00001965 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00001966 break;
1967 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001968 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00001969 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001970 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001971 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001972 break;
paul718e3742002-12-13 20:15:29 +00001973 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00001974 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00001975 break;
1976 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00001977 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00001978 break;
1979 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00001980 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00001981 break;
1982 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00001983 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00001984 break;
1985 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001986 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00001987 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001988 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001989 ret = bgp_attr_as4_aggregator (&attr_args,
1990 &as4_aggregator,
1991 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001992 break;
paul718e3742002-12-13 20:15:29 +00001993 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001994 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00001995 break;
1996 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00001997 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00001998 break;
1999 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002000 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002001 break;
2002 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002003 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002004 break;
2005 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002006 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002007 break;
2008 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002009 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002010 break;
2011 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002012 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002013 break;
2014 }
Paul Jakmab881c702010-11-23 16:35:42 +00002015
David Lamparterf57000c2014-06-04 01:01:10 +02002016 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2017 {
2018 bgp_notify_send (peer,
2019 BGP_NOTIFY_UPDATE_ERR,
2020 BGP_NOTIFY_UPDATE_MAL_ATTR);
2021 ret = BGP_ATTR_PARSE_ERROR;
2022 }
2023
Paul Jakmab881c702010-11-23 16:35:42 +00002024 /* If hard error occured immediately return to the caller. */
2025 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002026 {
2027 zlog (peer->log, LOG_WARNING,
2028 "%s: Attribute %s, parse error",
2029 peer->host,
2030 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002031 if (as4_path)
2032 aspath_unintern (&as4_path);
2033 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002034 }
Paul Jakmab881c702010-11-23 16:35:42 +00002035 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2036 {
2037
2038 zlog (peer->log, LOG_WARNING,
2039 "%s: Attribute %s, parse error - treating as withdrawal",
2040 peer->host,
2041 LOOKUP (attr_str, type));
2042 if (as4_path)
2043 aspath_unintern (&as4_path);
2044 return ret;
2045 }
2046
paul718e3742002-12-13 20:15:29 +00002047 /* Check the fetched length. */
2048 if (BGP_INPUT_PNT (peer) != attr_endp)
2049 {
2050 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002051 "%s: BGP attribute %s, fetch error",
2052 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002053 bgp_notify_send (peer,
2054 BGP_NOTIFY_UPDATE_ERR,
2055 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002056 if (as4_path)
2057 aspath_unintern (&as4_path);
2058 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002059 }
2060 }
paul718e3742002-12-13 20:15:29 +00002061 /* Check final read pointer is same as end pointer. */
2062 if (BGP_INPUT_PNT (peer) != endp)
2063 {
2064 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002065 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002066 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002067 bgp_notify_send (peer,
2068 BGP_NOTIFY_UPDATE_ERR,
2069 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002070 if (as4_path)
2071 aspath_unintern (&as4_path);
2072 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002073 }
Paul Jakma055086f2014-09-23 15:23:01 +01002074
2075 /* Check all mandatory well-known attributes are present */
2076 {
2077 bgp_attr_parse_ret_t ret;
2078 if ((ret = bgp_attr_check (peer, attr)) < 0)
2079 {
2080 if (as4_path)
2081 aspath_unintern (&as4_path);
2082 return ret;
2083 }
2084 }
2085
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002086 /*
2087 * At this place we can see whether we got AS4_PATH and/or
2088 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2089 * We can not do this before we've read all attributes because
2090 * the as4 handling does not say whether AS4_PATH has to be sent
2091 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2092 * in relationship to AGGREGATOR.
2093 * So, to be defensive, we are not relying on any order and read
2094 * all attributes first, including these 32bit ones, and now,
2095 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002096 *
2097 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2098 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002099 */
David Lamparterf57000c2014-06-04 01:01:10 +02002100 /* actually... this doesn't ever return failure currently, but
2101 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002102 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2103 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002104 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002105 {
David Lamparterf57000c2014-06-04 01:01:10 +02002106 bgp_notify_send (peer,
2107 BGP_NOTIFY_UPDATE_ERR,
2108 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002109 if (as4_path)
2110 aspath_unintern (&as4_path);
2111 return BGP_ATTR_PARSE_ERROR;
2112 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002113
2114 /* At this stage, we have done all fiddling with as4, and the
2115 * resulting info is in attr->aggregator resp. attr->aspath
2116 * so we can chuck as4_aggregator and as4_path alltogether in
2117 * order to save memory
2118 */
Paul Jakmab881c702010-11-23 16:35:42 +00002119 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002120 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002121 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002122 /* The flag that we got this is still there, but that does not
2123 * do any trouble
2124 */
2125 }
2126 /*
2127 * The "rest" of the code does nothing with as4_aggregator.
2128 * there is no memory attached specifically which is not part
2129 * of the attr.
2130 * so ignoring just means do nothing.
2131 */
2132 /*
2133 * Finally do the checks on the aspath we did not do yet
2134 * because we waited for a potentially synthesized aspath.
2135 */
Paul Jakmab881c702010-11-23 16:35:42 +00002136 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002137 {
Paul Jakma835315b2012-01-18 12:28:30 +00002138 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002139 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002140 return ret;
2141 }
2142
paul718e3742002-12-13 20:15:29 +00002143 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002144 if (attr->extra && attr->extra->transit)
2145 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002146
Paul Jakmab881c702010-11-23 16:35:42 +00002147 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002148}
2149
paul718e3742002-12-13 20:15:29 +00002150int stream_put_prefix (struct stream *, struct prefix *);
2151
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002152size_t
2153bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2154 struct attr *attr)
2155{
2156 size_t sizep;
2157
2158 /* Set extended bit always to encode the attribute length as 2 bytes */
2159 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2160 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2161 sizep = stream_get_endp (s);
2162 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002163
2164 stream_putw (s, afi);
2165 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002166
2167 /* Nexthop */
2168 switch (afi)
2169 {
2170 case AFI_IP:
2171 switch (safi)
2172 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002173 case SAFI_MULTICAST:
2174 stream_putc (s, 4);
2175 stream_put_ipv4 (s, attr->nexthop.s_addr);
2176 break;
2177 case SAFI_MPLS_VPN:
2178 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002179 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002180 stream_putl (s, 0);
2181 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2182 break;
Lou Berger050defe2016-01-12 13:41:59 -05002183 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002184 default:
2185 break;
2186 }
2187 break;
2188#ifdef HAVE_IPV6
2189 case AFI_IP6:
2190 switch (safi)
2191 {
2192 case SAFI_UNICAST:
2193 case SAFI_MULTICAST:
2194 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002195 struct attr_extra *attre = attr->extra;
2196
2197 assert (attr->extra);
2198 stream_putc (s, attre->mp_nexthop_len);
2199 stream_put (s, &attre->mp_nexthop_global, 16);
2200 if (attre->mp_nexthop_len == 32)
2201 stream_put (s, &attre->mp_nexthop_local, 16);
2202 }
Lou Berger050defe2016-01-12 13:41:59 -05002203 break;
2204 case SAFI_MPLS_VPN:
2205 {
2206 struct attr_extra *attre = attr->extra;
2207
2208 assert (attr->extra);
2209 if (attre->mp_nexthop_len == 16) {
2210 stream_putc (s, 24);
2211 stream_putl (s, 0); /* RD = 0, per RFC */
2212 stream_putl (s, 0);
2213 stream_put (s, &attre->mp_nexthop_global, 16);
2214 } else if (attre->mp_nexthop_len == 32) {
2215 stream_putc (s, 48);
2216 stream_putl (s, 0); /* RD = 0, per RFC */
2217 stream_putl (s, 0);
2218 stream_put (s, &attre->mp_nexthop_global, 16);
2219 stream_putl (s, 0); /* RD = 0, per RFC */
2220 stream_putl (s, 0);
2221 stream_put (s, &attre->mp_nexthop_local, 16);
2222 }
2223 }
2224 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002225 default:
2226 break;
2227 }
2228 break;
2229#endif /*HAVE_IPV6*/
2230 default:
2231 break;
2232 }
2233
2234 /* SNPA */
2235 stream_putc (s, 0);
2236 return sizep;
2237}
2238
2239void
2240bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2241 struct prefix *p, struct prefix_rd *prd,
2242 u_char *tag)
2243{
Lou Berger050defe2016-01-12 13:41:59 -05002244 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002245 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002246 /* Tag, RD, Prefix write. */
2247 stream_putc (s, p->prefixlen + 88);
2248 stream_put (s, tag, 3);
2249 stream_put (s, prd->val, 8);
2250 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002251 }
Lou Berger050defe2016-01-12 13:41:59 -05002252 else
2253 stream_put_prefix (s, p);
2254}
2255
2256size_t
2257bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2258{
2259 int size = PSIZE (p->prefixlen);
2260 if (safi == SAFI_MPLS_VPN)
2261 size += 88;
2262 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002263}
2264
2265void
2266bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2267{
2268 /* Set MP attribute length. Don't count the (2) bytes used to encode
2269 the attr length */
2270 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2271}
2272
paul718e3742002-12-13 20:15:29 +00002273/* Make attribute packet. */
2274bgp_size_t
2275bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002276 struct stream *s, struct attr *attr,
2277 struct prefix *p, afi_t afi, safi_t safi,
2278 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002279{
paulfe69a502005-09-10 16:55:02 +00002280 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002281 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002282 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002283 int send_as4_path = 0;
2284 int send_as4_aggregator = 0;
2285 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002286
2287 if (! bgp)
2288 bgp = bgp_get_default ();
2289
2290 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002291 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002292
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002293 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2294 {
Lou Berger050defe2016-01-12 13:41:59 -05002295 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002296 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2297 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2298 bgp_packet_mpattr_end(s, mpattrlen_pos);
2299 }
2300
paul718e3742002-12-13 20:15:29 +00002301 /* Origin attribute. */
2302 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2303 stream_putc (s, BGP_ATTR_ORIGIN);
2304 stream_putc (s, 1);
2305 stream_putc (s, attr->origin);
2306
2307 /* AS path attribute. */
2308
2309 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002310 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002311 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002312 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002313 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002314 {
2315 aspath = aspath_dup (attr->aspath);
2316
2317 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2318 {
2319 /* Strip the confed info, and then stuff our path CONFED_ID
2320 on the front */
2321 aspath = aspath_delete_confed_seq (aspath);
2322 aspath = aspath_add_seq (aspath, bgp->confed_id);
2323 }
2324 else
2325 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002326 if (peer->change_local_as) {
2327 /* If replace-as is specified, we only use the change_local_as when
2328 advertising routes. */
2329 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2330 aspath = aspath_add_seq (aspath, peer->local_as);
2331 }
paul718e3742002-12-13 20:15:29 +00002332 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002333 } else {
2334 aspath = aspath_add_seq (aspath, peer->local_as);
2335 }
paul718e3742002-12-13 20:15:29 +00002336 }
2337 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002338 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002339 {
2340 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2341 aspath = aspath_dup (attr->aspath);
2342 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2343 }
2344 else
2345 aspath = attr->aspath;
2346
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002347 /* If peer is not AS4 capable, then:
2348 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2349 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2350 * types are in it (i.e. exclude them if they are there)
2351 * AND do this only if there is at least one asnum > 65535 in the path!
2352 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2353 * all ASnums > 65535 to BGP_AS_TRANS
2354 */
paul718e3742002-12-13 20:15:29 +00002355
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002356 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2357 stream_putc (s, BGP_ATTR_AS_PATH);
2358 aspath_sizep = stream_get_endp (s);
2359 stream_putw (s, 0);
2360 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2361
2362 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2363 * in the path
2364 */
2365 if (!use32bit && aspath_has_as4 (aspath))
2366 send_as4_path = 1; /* we'll do this later, at the correct place */
2367
paul718e3742002-12-13 20:15:29 +00002368 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002369 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2370 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002371 {
2372 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2373 stream_putc (s, BGP_ATTR_NEXT_HOP);
2374 stream_putc (s, 4);
2375 if (safi == SAFI_MPLS_VPN)
2376 {
2377 if (attr->nexthop.s_addr == 0)
2378 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2379 else
2380 stream_put_ipv4 (s, attr->nexthop.s_addr);
2381 }
2382 else
2383 stream_put_ipv4 (s, attr->nexthop.s_addr);
2384 }
2385
2386 /* MED attribute. */
2387 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2388 {
2389 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2390 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2391 stream_putc (s, 4);
2392 stream_putl (s, attr->med);
2393 }
2394
2395 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002396 if (peer->sort == BGP_PEER_IBGP ||
2397 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002398 {
2399 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2400 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2401 stream_putc (s, 4);
2402 stream_putl (s, attr->local_pref);
2403 }
2404
2405 /* Atomic aggregate. */
2406 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2407 {
2408 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2409 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2410 stream_putc (s, 0);
2411 }
2412
2413 /* Aggregator. */
2414 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2415 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002416 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002417
2418 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002419 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2420 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002421
2422 if (use32bit)
2423 {
2424 /* AS4 capable peer */
2425 stream_putc (s, 8);
2426 stream_putl (s, attr->extra->aggregator_as);
2427 }
2428 else
2429 {
2430 /* 2-byte AS peer */
2431 stream_putc (s, 6);
2432
2433 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2434 if ( attr->extra->aggregator_as > 65535 )
2435 {
2436 stream_putw (s, BGP_AS_TRANS);
2437
2438 /* we have to send AS4_AGGREGATOR, too.
2439 * we'll do that later in order to send attributes in ascending
2440 * order.
2441 */
2442 send_as4_aggregator = 1;
2443 }
2444 else
2445 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2446 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002447 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002448 }
2449
2450 /* Community attribute. */
2451 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2452 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2453 {
2454 if (attr->community->size * 4 > 255)
2455 {
2456 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2457 stream_putc (s, BGP_ATTR_COMMUNITIES);
2458 stream_putw (s, attr->community->size * 4);
2459 }
2460 else
2461 {
2462 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2463 stream_putc (s, BGP_ATTR_COMMUNITIES);
2464 stream_putc (s, attr->community->size * 4);
2465 }
2466 stream_put (s, attr->community->val, attr->community->size * 4);
2467 }
2468
2469 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002470 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002471 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002472 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002473 {
2474 /* Originator ID. */
2475 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2476 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2477 stream_putc (s, 4);
2478
2479 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002480 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002481 else
2482 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002483
2484 /* Cluster list. */
2485 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2486 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2487
Paul Jakma9eda90c2007-08-30 13:36:17 +00002488 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002489 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002490 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002491 /* If this peer configuration's parent BGP has cluster_id. */
2492 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2493 stream_put_in_addr (s, &bgp->cluster_id);
2494 else
2495 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002496 stream_put (s, attr->extra->cluster->list,
2497 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002498 }
2499 else
2500 {
2501 stream_putc (s, 4);
2502 /* If this peer configuration's parent BGP has cluster_id. */
2503 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2504 stream_put_in_addr (s, &bgp->cluster_id);
2505 else
2506 stream_put_in_addr (s, &bgp->router_id);
2507 }
2508 }
2509
paul718e3742002-12-13 20:15:29 +00002510 /* Extended Communities attribute. */
2511 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2512 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2513 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002514 struct attr_extra *attre = attr->extra;
2515
2516 assert (attre);
2517
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002518 if (peer->sort == BGP_PEER_IBGP
2519 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002520 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002521 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002522 {
2523 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2524 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002525 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002526 }
2527 else
2528 {
2529 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2530 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002531 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002532 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002533 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002534 }
2535 else
2536 {
paul5228ad22004-06-04 17:58:18 +00002537 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002538 int tbit;
2539 int ecom_tr_size = 0;
2540 int i;
2541
Paul Jakmafb982c22007-05-04 20:15:47 +00002542 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002543 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002544 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002545 tbit = *pnt;
2546
2547 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2548 continue;
2549
2550 ecom_tr_size++;
2551 }
2552
2553 if (ecom_tr_size)
2554 {
2555 if (ecom_tr_size * 8 > 255)
2556 {
2557 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2558 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2559 stream_putw (s, ecom_tr_size * 8);
2560 }
2561 else
2562 {
2563 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2564 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2565 stream_putc (s, ecom_tr_size * 8);
2566 }
2567
Paul Jakmafb982c22007-05-04 20:15:47 +00002568 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002569 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002570 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002571 tbit = *pnt;
2572
2573 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2574 continue;
2575
2576 stream_put (s, pnt, 8);
2577 }
2578 }
paul718e3742002-12-13 20:15:29 +00002579 }
paul718e3742002-12-13 20:15:29 +00002580 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002581
2582 if ( send_as4_path )
2583 {
2584 /* If the peer is NOT As4 capable, AND */
2585 /* there are ASnums > 65535 in path THEN
2586 * give out AS4_PATH */
2587
2588 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2589 * path segments!
2590 * Hm, I wonder... confederation things *should* only be at
2591 * the beginning of an aspath, right? Then we should use
2592 * aspath_delete_confed_seq for this, because it is already
2593 * there! (JK)
2594 * Folks, talk to me: what is reasonable here!?
2595 */
2596 aspath = aspath_delete_confed_seq (aspath);
2597
2598 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2599 stream_putc (s, BGP_ATTR_AS4_PATH);
2600 aspath_sizep = stream_get_endp (s);
2601 stream_putw (s, 0);
2602 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2603 }
2604
2605 if (aspath != attr->aspath)
2606 aspath_free (aspath);
2607
2608 if ( send_as4_aggregator )
2609 {
2610 assert (attr->extra);
2611
2612 /* send AS4_AGGREGATOR, at this place */
2613 /* this section of code moved here in order to ensure the correct
2614 * *ascending* order of attributes
2615 */
2616 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2617 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2618 stream_putc (s, 8);
2619 stream_putl (s, attr->extra->aggregator_as);
2620 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2621 }
Paul Jakma41367172007-08-06 15:24:51 +00002622
paul718e3742002-12-13 20:15:29 +00002623 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002624 if (attr->extra && attr->extra->transit)
2625 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002626
2627 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002628 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002629}
2630
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002631size_t
2632bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002633{
paul718e3742002-12-13 20:15:29 +00002634 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002635
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002636 /* Set extended bit always to encode the attribute length as 2 bytes */
2637 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002638 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2639
paul9985f832005-02-09 15:51:56 +00002640 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002641 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002642
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002643 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002644 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002645 return attrlen_pnt;
2646}
paul718e3742002-12-13 20:15:29 +00002647
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002648void
2649bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2650 afi_t afi, safi_t safi, struct prefix_rd *prd,
2651 u_char *tag)
2652{
Lou Berger050defe2016-01-12 13:41:59 -05002653 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002654}
paul718e3742002-12-13 20:15:29 +00002655
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002656void
2657bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2658{
Lou Berger050defe2016-01-12 13:41:59 -05002659 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002660}
2661
2662/* Initialization of attribute. */
2663void
paulfe69a502005-09-10 16:55:02 +00002664bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002665{
paul718e3742002-12-13 20:15:29 +00002666 aspath_init ();
2667 attrhash_init ();
2668 community_init ();
2669 ecommunity_init ();
2670 cluster_init ();
2671 transit_init ();
2672}
2673
Chris Caputo228da422009-07-18 05:44:03 +00002674void
2675bgp_attr_finish (void)
2676{
2677 aspath_finish ();
2678 attrhash_finish ();
2679 community_finish ();
2680 ecommunity_finish ();
2681 cluster_finish ();
2682 transit_finish ();
2683}
2684
paul718e3742002-12-13 20:15:29 +00002685/* Make attribute packet. */
2686void
paula3845922003-10-18 01:30:50 +00002687bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2688 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00002689{
2690 unsigned long cp;
2691 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002692 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00002693 struct aspath *aspath;
2694
2695 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002696 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002697
2698 /* Place holder of length. */
2699 stream_putw (s, 0);
2700
2701 /* Origin attribute. */
2702 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2703 stream_putc (s, BGP_ATTR_ORIGIN);
2704 stream_putc (s, 1);
2705 stream_putc (s, attr->origin);
2706
2707 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002708
2709 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2710 stream_putc (s, BGP_ATTR_AS_PATH);
2711 aspath_lenp = stream_get_endp (s);
2712 stream_putw (s, 0);
2713
2714 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00002715
2716 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00002717 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2718 if(prefix != NULL
2719#ifdef HAVE_IPV6
2720 && prefix->family != AF_INET6
2721#endif /* HAVE_IPV6 */
2722 )
2723 {
2724 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2725 stream_putc (s, BGP_ATTR_NEXT_HOP);
2726 stream_putc (s, 4);
2727 stream_put_ipv4 (s, attr->nexthop.s_addr);
2728 }
paul718e3742002-12-13 20:15:29 +00002729
2730 /* MED attribute. */
2731 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2732 {
2733 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2734 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2735 stream_putc (s, 4);
2736 stream_putl (s, attr->med);
2737 }
2738
2739 /* Local preference. */
2740 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2741 {
2742 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2743 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2744 stream_putc (s, 4);
2745 stream_putl (s, attr->local_pref);
2746 }
2747
2748 /* Atomic aggregate. */
2749 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2750 {
2751 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2752 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2753 stream_putc (s, 0);
2754 }
2755
2756 /* Aggregator. */
2757 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2758 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002759 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00002760 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2761 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002762 stream_putc (s, 8);
2763 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00002764 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002765 }
2766
2767 /* Community attribute. */
2768 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2769 {
2770 if (attr->community->size * 4 > 255)
2771 {
2772 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2773 stream_putc (s, BGP_ATTR_COMMUNITIES);
2774 stream_putw (s, attr->community->size * 4);
2775 }
2776 else
2777 {
2778 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2779 stream_putc (s, BGP_ATTR_COMMUNITIES);
2780 stream_putc (s, attr->community->size * 4);
2781 }
2782 stream_put (s, attr->community->val, attr->community->size * 4);
2783 }
2784
paula3845922003-10-18 01:30:50 +00002785#ifdef HAVE_IPV6
2786 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002787 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2788 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00002789 {
2790 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00002791 struct attr_extra *attre = attr->extra;
2792
paula3845922003-10-18 01:30:50 +00002793 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2794 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00002795 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00002796
2797 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00002798 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00002799 stream_putw(s, AFI_IP6); /* AFI */
2800 stream_putc(s, SAFI_UNICAST); /* SAFI */
2801
2802 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002803 stream_putc(s, attre->mp_nexthop_len);
2804 stream_put(s, &attre->mp_nexthop_global, 16);
2805 if (attre->mp_nexthop_len == 32)
2806 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00002807
2808 /* SNPA */
2809 stream_putc(s, 0);
2810
2811 /* Prefix */
2812 stream_put_prefix(s, prefix);
2813
2814 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00002815 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00002816 }
2817#endif /* HAVE_IPV6 */
2818
paul718e3742002-12-13 20:15:29 +00002819 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002820 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00002821 stream_putw_at (s, cp, len);
2822}