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