blob: ce8f8a0801bc70169db612d06d4cbc89aa90b4a0 [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
1538 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001539 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001540 break;
1541 case 32:
Paul Jakmafb982c22007-05-04 20:15:47 +00001542 stream_get (&attre->mp_nexthop_global, s, 16);
1543 stream_get (&attre->mp_nexthop_local, s, 16);
1544 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001545 {
1546 char buf1[INET6_ADDRSTRLEN];
1547 char buf2[INET6_ADDRSTRLEN];
1548
1549 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001550 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 +00001551 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001552 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001553 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001554 buf2, INET6_ADDRSTRLEN));
1555
Paul Jakmafb982c22007-05-04 20:15:47 +00001556 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001557 }
1558 break;
1559#endif /* HAVE_IPV6 */
1560 default:
Paul Jakma03292802008-06-07 20:37:10 +00001561 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1562 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001563 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001564 }
1565
Paul Jakma03292802008-06-07 20:37:10 +00001566 if (!LEN_LEFT)
1567 {
1568 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1569 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001570 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001571 }
paul718e3742002-12-13 20:15:29 +00001572
Paul Jakma6e4ab122007-04-10 19:36:48 +00001573 {
1574 u_char val;
1575 if ((val = stream_getc (s)))
1576 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1577 peer->host, val);
1578 }
1579
1580 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001581 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001582 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001583 {
1584 zlog_info ("%s: (%s) Failed to read NLRI",
1585 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001586 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001587 }
paul718e3742002-12-13 20:15:29 +00001588
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001589 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001590 {
1591 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
Paul Jakma03292802008-06-07 20:37:10 +00001592 if (ret < 0)
1593 {
1594 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1595 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001596 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001597 }
paul718e3742002-12-13 20:15:29 +00001598 }
1599
1600 mp_update->afi = afi;
1601 mp_update->safi = safi;
1602 mp_update->nlri = stream_pnt (s);
1603 mp_update->length = nlri_len;
1604
paul9985f832005-02-09 15:51:56 +00001605 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001606
David Lamparterdaefeb82014-12-08 17:42:12 +01001607 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1608
Paul Jakmab881c702010-11-23 16:35:42 +00001609 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001610#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001611}
1612
1613/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001614int
Paul Jakma835315b2012-01-18 12:28:30 +00001615bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001616 struct bgp_nlri *mp_withdraw)
1617{
1618 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001619 afi_t afi;
1620 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001621 u_int16_t withdraw_len;
1622 int ret;
Paul Jakma835315b2012-01-18 12:28:30 +00001623 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001624 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001625 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001626
1627 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001628
1629#define BGP_MP_UNREACH_MIN_SIZE 3
1630 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001631 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001632
paul718e3742002-12-13 20:15:29 +00001633 afi = stream_getw (s);
1634 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001635
1636 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001637
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001638 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001639 {
1640 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1641 if (ret < 0)
David Lamparterf57000c2014-06-04 01:01:10 +02001642 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001643 }
1644
1645 mp_withdraw->afi = afi;
1646 mp_withdraw->safi = safi;
1647 mp_withdraw->nlri = stream_pnt (s);
1648 mp_withdraw->length = withdraw_len;
1649
paul9985f832005-02-09 15:51:56 +00001650 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001651
David Lamparterdaefeb82014-12-08 17:42:12 +01001652 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1653
Paul Jakmab881c702010-11-23 16:35:42 +00001654 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001655}
1656
1657/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001658static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001659bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001660{
Paul Jakma835315b2012-01-18 12:28:30 +00001661 struct peer *const peer = args->peer;
1662 struct attr *const attr = args->attr;
1663 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001664
paul718e3742002-12-13 20:15:29 +00001665 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001666 {
1667 if (attr->extra)
1668 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001669 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001670 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001671 }
Paul Jakma0c466382010-12-05 17:17:26 +00001672
1673 (bgp_attr_extra_get (attr))->ecommunity =
1674 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1675 /* XXX: fix ecommunity_parse to use stream API */
1676 stream_forward_getp (peer->ibuf, length);
1677
1678 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001679 return bgp_attr_malformed (args,
1680 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1681 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001682
paul718e3742002-12-13 20:15:29 +00001683 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1684
Paul Jakmab881c702010-11-23 16:35:42 +00001685 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001686}
1687
1688/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001689static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001690bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001691{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001692 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001693 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001694 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001695 struct peer *const peer = args->peer;
1696 struct attr *const attr = args->attr;
1697 u_char *const startp = args->startp;
1698 const u_char type = args->type;
1699 const u_char flag = args->flags;
1700 const bgp_size_t length = args->length;
1701
paul718e3742002-12-13 20:15:29 +00001702
hassof4184462005-02-01 20:13:16 +00001703 if (BGP_DEBUG (normal, NORMAL))
1704 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1705 peer->host, type, length);
1706
paul718e3742002-12-13 20:15:29 +00001707 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001708 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001709 "Unknown attribute type %d length %d is received", type, length);
1710
1711 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001712 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001713
paul718e3742002-12-13 20:15:29 +00001714 /* If any of the mandatory well-known attributes are not recognized,
1715 then the Error Subcode is set to Unrecognized Well-known
1716 Attribute. The Data field contains the unrecognized attribute
1717 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001718 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001719 {
Paul Jakma835315b2012-01-18 12:28:30 +00001720 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001721 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001722 args->total);
paul718e3742002-12-13 20:15:29 +00001723 }
1724
1725 /* Unrecognized non-transitive optional attributes must be quietly
1726 ignored and not passed along to other BGP peers. */
1727 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001728 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001729
1730 /* If a path with recognized transitive optional attribute is
1731 accepted and passed along to other BGP peers and the Partial bit
1732 in the Attribute Flags octet is set to 1 by some previous AS, it
1733 is not set back to 0 by the current AS. */
1734 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1735
1736 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001737 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001738 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001739
Paul Jakmafb982c22007-05-04 20:15:47 +00001740 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001741
1742 if (transit->val)
1743 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1744 transit->length + total);
1745 else
1746 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1747
1748 memcpy (transit->val + transit->length, startp, total);
1749 transit->length += total;
1750
Paul Jakmab881c702010-11-23 16:35:42 +00001751 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001752}
1753
Paul Jakma055086f2014-09-23 15:23:01 +01001754/* Well-known attribute check. */
1755static int
1756bgp_attr_check (struct peer *peer, struct attr *attr)
1757{
1758 u_char type = 0;
1759
Paul Jakmaaed1b552014-10-21 16:59:01 +01001760 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
1761 * empty UPDATE. */
1762 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
1763 return BGP_ATTR_PARSE_PROCEED;
1764
1765 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
1766 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
1767 are present, it should. Check for any other attribute being present
1768 instead.
1769 */
1770 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
1771 return BGP_ATTR_PARSE_PROCEED;
1772
Paul Jakma055086f2014-09-23 15:23:01 +01001773 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1774 type = BGP_ATTR_ORIGIN;
1775
1776 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1777 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001778
1779 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
1780 * NLRI is empty. We can't easily check NLRI empty here though.
1781 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00001782 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
1783 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01001784 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001785
Paul Jakma055086f2014-09-23 15:23:01 +01001786 if (peer->sort == BGP_PEER_IBGP
1787 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1788 type = BGP_ATTR_LOCAL_PREF;
1789
1790 if (type)
1791 {
1792 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01001793 "%s Missing well-known attribute %d / %s",
1794 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01001795 bgp_notify_send_with_data (peer,
1796 BGP_NOTIFY_UPDATE_ERR,
1797 BGP_NOTIFY_UPDATE_MISS_ATTR,
1798 &type, 1);
1799 return BGP_ATTR_PARSE_ERROR;
1800 }
1801 return BGP_ATTR_PARSE_PROCEED;
1802}
1803
paul718e3742002-12-13 20:15:29 +00001804/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00001805 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00001806bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00001807bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1808 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1809{
1810 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00001811 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001812 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00001813 bgp_size_t length;
1814 u_char *startp, *endp;
1815 u_char *attr_endp;
1816 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001817 /* we need the as4_path only until we have synthesized the as_path with it */
1818 /* same goes for as4_aggregator */
1819 struct aspath *as4_path = NULL;
1820 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07001821 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00001822
1823 /* Initialize bitmap. */
1824 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1825
1826 /* End pointer of BGP attribute. */
1827 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00001828
paul718e3742002-12-13 20:15:29 +00001829 /* Get attributes to the end of attribute length. */
1830 while (BGP_INPUT_PNT (peer) < endp)
1831 {
1832 /* Check remaining length check.*/
1833 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1834 {
gdtc29fdba2004-12-09 14:46:46 +00001835 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00001836 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001837 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001838 peer->host,
1839 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00001840
1841 bgp_notify_send (peer,
1842 BGP_NOTIFY_UPDATE_ERR,
1843 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001844 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001845 }
1846
1847 /* Fetch attribute flag and type. */
1848 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04001849 /* "The lower-order four bits of the Attribute Flags octet are
1850 unused. They MUST be zero when sent and MUST be ignored when
1851 received." */
1852 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00001853 type = stream_getc (BGP_INPUT (peer));
1854
Paul Jakma370b64a2007-12-22 16:49:52 +00001855 /* Check whether Extended-Length applies and is in bounds */
1856 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1857 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1858 {
1859 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001860 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00001861 peer->host,
1862 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1863
1864 bgp_notify_send (peer,
1865 BGP_NOTIFY_UPDATE_ERR,
1866 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001867 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00001868 }
Paul Jakma835315b2012-01-18 12:28:30 +00001869
paul718e3742002-12-13 20:15:29 +00001870 /* Check extended attribue length bit. */
1871 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1872 length = stream_getw (BGP_INPUT (peer));
1873 else
1874 length = stream_getc (BGP_INPUT (peer));
1875
1876 /* If any attribute appears more than once in the UPDATE
1877 message, then the Error Subcode is set to Malformed Attribute
1878 List. */
1879
1880 if (CHECK_BITMAP (seen, type))
1881 {
1882 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001883 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00001884 peer->host, type);
1885
1886 bgp_notify_send (peer,
1887 BGP_NOTIFY_UPDATE_ERR,
1888 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00001889 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001890 }
1891
1892 /* Set type to bitmap to check duplicate attribute. `type' is
1893 unsigned char so it never overflow bitmap range. */
1894
1895 SET_BITMAP (seen, type);
1896
1897 /* Overflow check. */
1898 attr_endp = BGP_INPUT_PNT (peer) + length;
1899
1900 if (attr_endp > endp)
1901 {
1902 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001903 "%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 +00001904 bgp_notify_send (peer,
1905 BGP_NOTIFY_UPDATE_ERR,
1906 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001907 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001908 }
Paul Jakma835315b2012-01-18 12:28:30 +00001909
1910 struct bgp_attr_parser_args attr_args = {
1911 .peer = peer,
1912 .length = length,
1913 .attr = attr,
1914 .type = type,
1915 .flags = flag,
1916 .startp = startp,
1917 .total = attr_endp - startp,
1918 };
1919
1920
1921 /* If any recognized attribute has Attribute Flags that conflict
1922 with the Attribute Type Code, then the Error Subcode is set to
1923 Attribute Flags Error. The Data field contains the erroneous
1924 attribute (type, length and value). */
1925 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01001926 {
1927 bgp_attr_parse_ret_t ret;
1928 ret = bgp_attr_malformed (&attr_args,
1929 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1930 attr_args.total);
1931 if (ret == BGP_ATTR_PARSE_PROCEED)
1932 continue;
1933 return ret;
1934 }
paul718e3742002-12-13 20:15:29 +00001935
1936 /* OK check attribute and store it's value. */
1937 switch (type)
1938 {
1939 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00001940 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00001941 break;
1942 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001943 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00001944 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001945 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001946 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001947 break;
paul718e3742002-12-13 20:15:29 +00001948 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00001949 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00001950 break;
1951 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00001952 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00001953 break;
1954 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00001955 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00001956 break;
1957 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00001958 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00001959 break;
1960 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001961 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00001962 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001963 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001964 ret = bgp_attr_as4_aggregator (&attr_args,
1965 &as4_aggregator,
1966 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001967 break;
paul718e3742002-12-13 20:15:29 +00001968 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001969 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00001970 break;
1971 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00001972 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00001973 break;
1974 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00001975 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00001976 break;
1977 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001978 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00001979 break;
1980 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001981 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00001982 break;
1983 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001984 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00001985 break;
1986 default:
Paul Jakma835315b2012-01-18 12:28:30 +00001987 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00001988 break;
1989 }
Paul Jakmab881c702010-11-23 16:35:42 +00001990
David Lamparterf57000c2014-06-04 01:01:10 +02001991 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
1992 {
1993 bgp_notify_send (peer,
1994 BGP_NOTIFY_UPDATE_ERR,
1995 BGP_NOTIFY_UPDATE_MAL_ATTR);
1996 ret = BGP_ATTR_PARSE_ERROR;
1997 }
1998
Paul Jakmab881c702010-11-23 16:35:42 +00001999 /* If hard error occured immediately return to the caller. */
2000 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002001 {
2002 zlog (peer->log, LOG_WARNING,
2003 "%s: Attribute %s, parse error",
2004 peer->host,
2005 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002006 if (as4_path)
2007 aspath_unintern (&as4_path);
2008 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002009 }
Paul Jakmab881c702010-11-23 16:35:42 +00002010 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2011 {
2012
2013 zlog (peer->log, LOG_WARNING,
2014 "%s: Attribute %s, parse error - treating as withdrawal",
2015 peer->host,
2016 LOOKUP (attr_str, type));
2017 if (as4_path)
2018 aspath_unintern (&as4_path);
2019 return ret;
2020 }
2021
paul718e3742002-12-13 20:15:29 +00002022 /* Check the fetched length. */
2023 if (BGP_INPUT_PNT (peer) != attr_endp)
2024 {
2025 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002026 "%s: BGP attribute %s, fetch error",
2027 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002028 bgp_notify_send (peer,
2029 BGP_NOTIFY_UPDATE_ERR,
2030 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002031 if (as4_path)
2032 aspath_unintern (&as4_path);
2033 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002034 }
2035 }
paul718e3742002-12-13 20:15:29 +00002036 /* Check final read pointer is same as end pointer. */
2037 if (BGP_INPUT_PNT (peer) != endp)
2038 {
2039 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002040 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002041 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002042 bgp_notify_send (peer,
2043 BGP_NOTIFY_UPDATE_ERR,
2044 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002045 if (as4_path)
2046 aspath_unintern (&as4_path);
2047 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002048 }
Paul Jakma055086f2014-09-23 15:23:01 +01002049
2050 /* Check all mandatory well-known attributes are present */
2051 {
2052 bgp_attr_parse_ret_t ret;
2053 if ((ret = bgp_attr_check (peer, attr)) < 0)
2054 {
2055 if (as4_path)
2056 aspath_unintern (&as4_path);
2057 return ret;
2058 }
2059 }
2060
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002061 /*
2062 * At this place we can see whether we got AS4_PATH and/or
2063 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2064 * We can not do this before we've read all attributes because
2065 * the as4 handling does not say whether AS4_PATH has to be sent
2066 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2067 * in relationship to AGGREGATOR.
2068 * So, to be defensive, we are not relying on any order and read
2069 * all attributes first, including these 32bit ones, and now,
2070 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002071 *
2072 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2073 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002074 */
David Lamparterf57000c2014-06-04 01:01:10 +02002075 /* actually... this doesn't ever return failure currently, but
2076 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002077 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2078 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002079 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002080 {
David Lamparterf57000c2014-06-04 01:01:10 +02002081 bgp_notify_send (peer,
2082 BGP_NOTIFY_UPDATE_ERR,
2083 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002084 if (as4_path)
2085 aspath_unintern (&as4_path);
2086 return BGP_ATTR_PARSE_ERROR;
2087 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002088
2089 /* At this stage, we have done all fiddling with as4, and the
2090 * resulting info is in attr->aggregator resp. attr->aspath
2091 * so we can chuck as4_aggregator and as4_path alltogether in
2092 * order to save memory
2093 */
Paul Jakmab881c702010-11-23 16:35:42 +00002094 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002095 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002096 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002097 /* The flag that we got this is still there, but that does not
2098 * do any trouble
2099 */
2100 }
2101 /*
2102 * The "rest" of the code does nothing with as4_aggregator.
2103 * there is no memory attached specifically which is not part
2104 * of the attr.
2105 * so ignoring just means do nothing.
2106 */
2107 /*
2108 * Finally do the checks on the aspath we did not do yet
2109 * because we waited for a potentially synthesized aspath.
2110 */
Paul Jakmab881c702010-11-23 16:35:42 +00002111 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002112 {
Paul Jakma835315b2012-01-18 12:28:30 +00002113 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002114 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002115 return ret;
2116 }
2117
paul718e3742002-12-13 20:15:29 +00002118 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002119 if (attr->extra && attr->extra->transit)
2120 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002121
Paul Jakmab881c702010-11-23 16:35:42 +00002122 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002123}
2124
paul718e3742002-12-13 20:15:29 +00002125int stream_put_prefix (struct stream *, struct prefix *);
2126
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002127size_t
2128bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2129 struct attr *attr)
2130{
2131 size_t sizep;
2132
2133 /* Set extended bit always to encode the attribute length as 2 bytes */
2134 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2135 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2136 sizep = stream_get_endp (s);
2137 stream_putw (s, 0); /* Marker: Attribute length. */
2138 stream_putw (s, afi); /* AFI */
2139 stream_putc (s, safi); /* SAFI */
2140
2141 /* Nexthop */
2142 switch (afi)
2143 {
2144 case AFI_IP:
2145 switch (safi)
2146 {
2147 case SAFI_UNICAST:
2148 case SAFI_MULTICAST:
2149 stream_putc (s, 4);
2150 stream_put_ipv4 (s, attr->nexthop.s_addr);
2151 break;
2152 case SAFI_MPLS_VPN:
2153 stream_putc (s, 12);
2154 stream_putl (s, 0);
2155 stream_putl (s, 0);
2156 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2157 break;
2158 default:
2159 break;
2160 }
2161 break;
2162#ifdef HAVE_IPV6
2163 case AFI_IP6:
2164 switch (safi)
2165 {
2166 case SAFI_UNICAST:
2167 case SAFI_MULTICAST:
2168 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002169 struct attr_extra *attre = attr->extra;
2170
2171 assert (attr->extra);
2172 stream_putc (s, attre->mp_nexthop_len);
2173 stream_put (s, &attre->mp_nexthop_global, 16);
2174 if (attre->mp_nexthop_len == 32)
2175 stream_put (s, &attre->mp_nexthop_local, 16);
2176 }
2177 default:
2178 break;
2179 }
2180 break;
2181#endif /*HAVE_IPV6*/
2182 default:
2183 break;
2184 }
2185
2186 /* SNPA */
2187 stream_putc (s, 0);
2188 return sizep;
2189}
2190
2191void
2192bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2193 struct prefix *p, struct prefix_rd *prd,
2194 u_char *tag)
2195{
2196 switch (safi)
2197 {
2198 case SAFI_MPLS_VPN:
2199 /* Tag, RD, Prefix write. */
2200 stream_putc (s, p->prefixlen + 88);
2201 stream_put (s, tag, 3);
2202 stream_put (s, prd->val, 8);
2203 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2204 break;
2205 default:
2206 /* Prefix write. */
2207 stream_put_prefix (s, p);
2208 break;
2209 }
2210}
2211
2212void
2213bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2214{
2215 /* Set MP attribute length. Don't count the (2) bytes used to encode
2216 the attr length */
2217 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2218}
2219
paul718e3742002-12-13 20:15:29 +00002220/* Make attribute packet. */
2221bgp_size_t
2222bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002223 struct stream *s, struct attr *attr,
2224 struct prefix *p, afi_t afi, safi_t safi,
2225 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002226{
paulfe69a502005-09-10 16:55:02 +00002227 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002228 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002229 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002230 int send_as4_path = 0;
2231 int send_as4_aggregator = 0;
2232 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002233 size_t mpattrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +00002234
2235 if (! bgp)
2236 bgp = bgp_get_default ();
2237
2238 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002239 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002240
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002241 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2242 {
2243 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2244 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2245 bgp_packet_mpattr_end(s, mpattrlen_pos);
2246 }
2247
paul718e3742002-12-13 20:15:29 +00002248 /* Origin attribute. */
2249 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2250 stream_putc (s, BGP_ATTR_ORIGIN);
2251 stream_putc (s, 1);
2252 stream_putc (s, attr->origin);
2253
2254 /* AS path attribute. */
2255
2256 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002257 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002258 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002259 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002260 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002261 {
2262 aspath = aspath_dup (attr->aspath);
2263
2264 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2265 {
2266 /* Strip the confed info, and then stuff our path CONFED_ID
2267 on the front */
2268 aspath = aspath_delete_confed_seq (aspath);
2269 aspath = aspath_add_seq (aspath, bgp->confed_id);
2270 }
2271 else
2272 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002273 if (peer->change_local_as) {
2274 /* If replace-as is specified, we only use the change_local_as when
2275 advertising routes. */
2276 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2277 aspath = aspath_add_seq (aspath, peer->local_as);
2278 }
paul718e3742002-12-13 20:15:29 +00002279 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002280 } else {
2281 aspath = aspath_add_seq (aspath, peer->local_as);
2282 }
paul718e3742002-12-13 20:15:29 +00002283 }
2284 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002285 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002286 {
2287 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2288 aspath = aspath_dup (attr->aspath);
2289 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2290 }
2291 else
2292 aspath = attr->aspath;
2293
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002294 /* If peer is not AS4 capable, then:
2295 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2296 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2297 * types are in it (i.e. exclude them if they are there)
2298 * AND do this only if there is at least one asnum > 65535 in the path!
2299 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2300 * all ASnums > 65535 to BGP_AS_TRANS
2301 */
paul718e3742002-12-13 20:15:29 +00002302
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002303 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2304 stream_putc (s, BGP_ATTR_AS_PATH);
2305 aspath_sizep = stream_get_endp (s);
2306 stream_putw (s, 0);
2307 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2308
2309 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2310 * in the path
2311 */
2312 if (!use32bit && aspath_has_as4 (aspath))
2313 send_as4_path = 1; /* we'll do this later, at the correct place */
2314
paul718e3742002-12-13 20:15:29 +00002315 /* Nexthop attribute. */
2316 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2317 {
2318 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2319 stream_putc (s, BGP_ATTR_NEXT_HOP);
2320 stream_putc (s, 4);
2321 if (safi == SAFI_MPLS_VPN)
2322 {
2323 if (attr->nexthop.s_addr == 0)
2324 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2325 else
2326 stream_put_ipv4 (s, attr->nexthop.s_addr);
2327 }
2328 else
2329 stream_put_ipv4 (s, attr->nexthop.s_addr);
2330 }
2331
2332 /* MED attribute. */
2333 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2334 {
2335 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2336 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2337 stream_putc (s, 4);
2338 stream_putl (s, attr->med);
2339 }
2340
2341 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002342 if (peer->sort == BGP_PEER_IBGP ||
2343 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002344 {
2345 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2346 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2347 stream_putc (s, 4);
2348 stream_putl (s, attr->local_pref);
2349 }
2350
2351 /* Atomic aggregate. */
2352 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2353 {
2354 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2355 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2356 stream_putc (s, 0);
2357 }
2358
2359 /* Aggregator. */
2360 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2361 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002362 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002363
2364 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002365 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2366 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002367
2368 if (use32bit)
2369 {
2370 /* AS4 capable peer */
2371 stream_putc (s, 8);
2372 stream_putl (s, attr->extra->aggregator_as);
2373 }
2374 else
2375 {
2376 /* 2-byte AS peer */
2377 stream_putc (s, 6);
2378
2379 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2380 if ( attr->extra->aggregator_as > 65535 )
2381 {
2382 stream_putw (s, BGP_AS_TRANS);
2383
2384 /* we have to send AS4_AGGREGATOR, too.
2385 * we'll do that later in order to send attributes in ascending
2386 * order.
2387 */
2388 send_as4_aggregator = 1;
2389 }
2390 else
2391 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2392 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002393 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002394 }
2395
2396 /* Community attribute. */
2397 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2398 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2399 {
2400 if (attr->community->size * 4 > 255)
2401 {
2402 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2403 stream_putc (s, BGP_ATTR_COMMUNITIES);
2404 stream_putw (s, attr->community->size * 4);
2405 }
2406 else
2407 {
2408 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2409 stream_putc (s, BGP_ATTR_COMMUNITIES);
2410 stream_putc (s, attr->community->size * 4);
2411 }
2412 stream_put (s, attr->community->val, attr->community->size * 4);
2413 }
2414
2415 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002416 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002417 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002418 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002419 {
2420 /* Originator ID. */
2421 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2422 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2423 stream_putc (s, 4);
2424
2425 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002426 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002427 else
2428 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002429
2430 /* Cluster list. */
2431 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2432 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2433
Paul Jakma9eda90c2007-08-30 13:36:17 +00002434 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002435 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002436 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002437 /* If this peer configuration's parent BGP has cluster_id. */
2438 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2439 stream_put_in_addr (s, &bgp->cluster_id);
2440 else
2441 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002442 stream_put (s, attr->extra->cluster->list,
2443 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002444 }
2445 else
2446 {
2447 stream_putc (s, 4);
2448 /* If this peer configuration's parent BGP has cluster_id. */
2449 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2450 stream_put_in_addr (s, &bgp->cluster_id);
2451 else
2452 stream_put_in_addr (s, &bgp->router_id);
2453 }
2454 }
2455
paul718e3742002-12-13 20:15:29 +00002456 /* Extended Communities attribute. */
2457 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2458 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2459 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002460 struct attr_extra *attre = attr->extra;
2461
2462 assert (attre);
2463
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002464 if (peer->sort == BGP_PEER_IBGP
2465 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002466 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002467 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002468 {
2469 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2470 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002471 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002472 }
2473 else
2474 {
2475 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2476 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002477 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002478 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002479 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002480 }
2481 else
2482 {
paul5228ad22004-06-04 17:58:18 +00002483 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002484 int tbit;
2485 int ecom_tr_size = 0;
2486 int i;
2487
Paul Jakmafb982c22007-05-04 20:15:47 +00002488 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002489 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002490 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002491 tbit = *pnt;
2492
2493 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2494 continue;
2495
2496 ecom_tr_size++;
2497 }
2498
2499 if (ecom_tr_size)
2500 {
2501 if (ecom_tr_size * 8 > 255)
2502 {
2503 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2504 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2505 stream_putw (s, ecom_tr_size * 8);
2506 }
2507 else
2508 {
2509 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2510 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2511 stream_putc (s, ecom_tr_size * 8);
2512 }
2513
Paul Jakmafb982c22007-05-04 20:15:47 +00002514 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002515 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002516 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002517 tbit = *pnt;
2518
2519 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2520 continue;
2521
2522 stream_put (s, pnt, 8);
2523 }
2524 }
paul718e3742002-12-13 20:15:29 +00002525 }
paul718e3742002-12-13 20:15:29 +00002526 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002527
2528 if ( send_as4_path )
2529 {
2530 /* If the peer is NOT As4 capable, AND */
2531 /* there are ASnums > 65535 in path THEN
2532 * give out AS4_PATH */
2533
2534 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2535 * path segments!
2536 * Hm, I wonder... confederation things *should* only be at
2537 * the beginning of an aspath, right? Then we should use
2538 * aspath_delete_confed_seq for this, because it is already
2539 * there! (JK)
2540 * Folks, talk to me: what is reasonable here!?
2541 */
2542 aspath = aspath_delete_confed_seq (aspath);
2543
2544 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2545 stream_putc (s, BGP_ATTR_AS4_PATH);
2546 aspath_sizep = stream_get_endp (s);
2547 stream_putw (s, 0);
2548 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2549 }
2550
2551 if (aspath != attr->aspath)
2552 aspath_free (aspath);
2553
2554 if ( send_as4_aggregator )
2555 {
2556 assert (attr->extra);
2557
2558 /* send AS4_AGGREGATOR, at this place */
2559 /* this section of code moved here in order to ensure the correct
2560 * *ascending* order of attributes
2561 */
2562 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2563 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2564 stream_putc (s, 8);
2565 stream_putl (s, attr->extra->aggregator_as);
2566 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2567 }
Paul Jakma41367172007-08-06 15:24:51 +00002568
paul718e3742002-12-13 20:15:29 +00002569 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002570 if (attr->extra && attr->extra->transit)
2571 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002572
2573 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002574 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002575}
2576
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002577size_t
2578bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002579{
paul718e3742002-12-13 20:15:29 +00002580 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002581
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002582 /* Set extended bit always to encode the attribute length as 2 bytes */
2583 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002584 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2585
paul9985f832005-02-09 15:51:56 +00002586 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002587 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002588
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002589 stream_putw (s, afi);
2590 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
2591 stream_putc (s, safi);
2592 return attrlen_pnt;
2593}
paul718e3742002-12-13 20:15:29 +00002594
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002595void
2596bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2597 afi_t afi, safi_t safi, struct prefix_rd *prd,
2598 u_char *tag)
2599{
paul718e3742002-12-13 20:15:29 +00002600 if (safi == SAFI_MPLS_VPN)
2601 {
paul718e3742002-12-13 20:15:29 +00002602 stream_putc (s, p->prefixlen + 88);
2603 stream_put (s, tag, 3);
2604 stream_put (s, prd->val, 8);
2605 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2606 }
2607 else
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002608 stream_put_prefix (s, p);
2609}
paul718e3742002-12-13 20:15:29 +00002610
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002611void
2612bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2613{
2614 bgp_size_t size;
paul718e3742002-12-13 20:15:29 +00002615
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002616 /* Set MP attribute length. Don't count the (2) bytes used to encode
2617 the attr length */
2618 size = stream_get_endp (s) - attrlen_pnt - 2;
2619 stream_putw_at (s, attrlen_pnt, size);
paul718e3742002-12-13 20:15:29 +00002620}
2621
2622/* Initialization of attribute. */
2623void
paulfe69a502005-09-10 16:55:02 +00002624bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002625{
paul718e3742002-12-13 20:15:29 +00002626 aspath_init ();
2627 attrhash_init ();
2628 community_init ();
2629 ecommunity_init ();
2630 cluster_init ();
2631 transit_init ();
2632}
2633
Chris Caputo228da422009-07-18 05:44:03 +00002634void
2635bgp_attr_finish (void)
2636{
2637 aspath_finish ();
2638 attrhash_finish ();
2639 community_finish ();
2640 ecommunity_finish ();
2641 cluster_finish ();
2642 transit_finish ();
2643}
2644
paul718e3742002-12-13 20:15:29 +00002645/* Make attribute packet. */
2646void
paula3845922003-10-18 01:30:50 +00002647bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2648 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00002649{
2650 unsigned long cp;
2651 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002652 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00002653 struct aspath *aspath;
2654
2655 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002656 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002657
2658 /* Place holder of length. */
2659 stream_putw (s, 0);
2660
2661 /* Origin attribute. */
2662 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2663 stream_putc (s, BGP_ATTR_ORIGIN);
2664 stream_putc (s, 1);
2665 stream_putc (s, attr->origin);
2666
2667 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002668
2669 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2670 stream_putc (s, BGP_ATTR_AS_PATH);
2671 aspath_lenp = stream_get_endp (s);
2672 stream_putw (s, 0);
2673
2674 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00002675
2676 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00002677 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2678 if(prefix != NULL
2679#ifdef HAVE_IPV6
2680 && prefix->family != AF_INET6
2681#endif /* HAVE_IPV6 */
2682 )
2683 {
2684 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2685 stream_putc (s, BGP_ATTR_NEXT_HOP);
2686 stream_putc (s, 4);
2687 stream_put_ipv4 (s, attr->nexthop.s_addr);
2688 }
paul718e3742002-12-13 20:15:29 +00002689
2690 /* MED attribute. */
2691 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2692 {
2693 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2694 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2695 stream_putc (s, 4);
2696 stream_putl (s, attr->med);
2697 }
2698
2699 /* Local preference. */
2700 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2701 {
2702 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2703 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2704 stream_putc (s, 4);
2705 stream_putl (s, attr->local_pref);
2706 }
2707
2708 /* Atomic aggregate. */
2709 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2710 {
2711 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2712 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2713 stream_putc (s, 0);
2714 }
2715
2716 /* Aggregator. */
2717 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2718 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002719 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00002720 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2721 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002722 stream_putc (s, 8);
2723 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00002724 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002725 }
2726
2727 /* Community attribute. */
2728 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2729 {
2730 if (attr->community->size * 4 > 255)
2731 {
2732 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2733 stream_putc (s, BGP_ATTR_COMMUNITIES);
2734 stream_putw (s, attr->community->size * 4);
2735 }
2736 else
2737 {
2738 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2739 stream_putc (s, BGP_ATTR_COMMUNITIES);
2740 stream_putc (s, attr->community->size * 4);
2741 }
2742 stream_put (s, attr->community->val, attr->community->size * 4);
2743 }
2744
paula3845922003-10-18 01:30:50 +00002745#ifdef HAVE_IPV6
2746 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002747 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2748 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00002749 {
2750 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00002751 struct attr_extra *attre = attr->extra;
2752
paula3845922003-10-18 01:30:50 +00002753 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2754 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00002755 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00002756
2757 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00002758 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00002759 stream_putw(s, AFI_IP6); /* AFI */
2760 stream_putc(s, SAFI_UNICAST); /* SAFI */
2761
2762 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002763 stream_putc(s, attre->mp_nexthop_len);
2764 stream_put(s, &attre->mp_nexthop_global, 16);
2765 if (attre->mp_nexthop_len == 32)
2766 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00002767
2768 /* SNPA */
2769 stream_putc(s, 0);
2770
2771 /* Prefix */
2772 stream_put_prefix(s, prefix);
2773
2774 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00002775 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00002776 }
2777#endif /* HAVE_IPV6 */
2778
paul718e3742002-12-13 20:15:29 +00002779 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002780 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00002781 stream_putw_at (s, cp, len);
2782}