blob: be316daa6ff1d428fac930cf6f28888c47faa39b [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"
paul718e3742002-12-13 20:15:29 +000032
33#include "bgpd/bgpd.h"
34#include "bgpd/bgp_attr.h"
35#include "bgpd/bgp_route.h"
36#include "bgpd/bgp_aspath.h"
37#include "bgpd/bgp_community.h"
38#include "bgpd/bgp_debug.h"
39#include "bgpd/bgp_packet.h"
40#include "bgpd/bgp_ecommunity.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020041
paul718e3742002-12-13 20:15:29 +000042/* Attribute strings for logging. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -070043static const struct message attr_str [] =
paul718e3742002-12-13 20:15:29 +000044{
45 { BGP_ATTR_ORIGIN, "ORIGIN" },
46 { BGP_ATTR_AS_PATH, "AS_PATH" },
47 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
48 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
49 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
50 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
51 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
52 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
53 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
Denis Ovsienkof8627ff2011-10-10 16:52:20 +040054 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
paul718e3742002-12-13 20:15:29 +000055 { BGP_ATTR_DPA, "DPA" },
56 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
57 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
58 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
59 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000060 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
61 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
62 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
63 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
paul718e3742002-12-13 20:15:29 +000064};
Balaji.G837d16c2012-09-26 14:09:10 +053065static const int attr_str_max = array_size(attr_str);
Denis Ovsienkoafcb7672011-10-23 22:32:44 +040066
67static const struct message attr_flag_str[] =
68{
69 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
70 { BGP_ATTR_FLAG_TRANS, "Transitive" },
71 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
72 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
73 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
74};
Balaji.G837d16c2012-09-26 14:09:10 +053075static const size_t attr_flag_str_max = array_size(attr_flag_str);
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{
207 hash_free (cluster_hash);
208 cluster_hash = NULL;
209}
David Lamparter6b0655a2014-06-04 06:53:35 +0200210
paul718e3742002-12-13 20:15:29 +0000211/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700212static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000213
paul94f2b392005-06-28 12:44:16 +0000214static void
paul718e3742002-12-13 20:15:29 +0000215transit_free (struct transit *transit)
216{
217 if (transit->val)
218 XFREE (MTYPE_TRANSIT_VAL, transit->val);
219 XFREE (MTYPE_TRANSIT, transit);
220}
221
Paul Jakma923de652007-04-29 18:25:17 +0000222
paul94f2b392005-06-28 12:44:16 +0000223static void *
Paul Jakma923de652007-04-29 18:25:17 +0000224transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000225{
226 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000227 return p;
paul718e3742002-12-13 20:15:29 +0000228}
229
paul94f2b392005-06-28 12:44:16 +0000230static struct transit *
paul718e3742002-12-13 20:15:29 +0000231transit_intern (struct transit *transit)
232{
233 struct transit *find;
234
235 find = hash_get (transit_hash, transit, transit_hash_alloc);
236 if (find != transit)
237 transit_free (transit);
238 find->refcnt++;
239
240 return find;
241}
242
243void
244transit_unintern (struct transit *transit)
245{
paul718e3742002-12-13 20:15:29 +0000246 if (transit->refcnt)
247 transit->refcnt--;
248
249 if (transit->refcnt == 0)
250 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400251 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000252 transit_free (transit);
253 }
254}
255
paul94f2b392005-06-28 12:44:16 +0000256static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000257transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000258{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700259 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000260
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700261 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000262}
263
paul94f2b392005-06-28 12:44:16 +0000264static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100265transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000266{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100267 const struct transit * transit1 = p1;
268 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000269
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100270 return (transit1->length == transit2->length &&
271 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000272}
273
paul94f2b392005-06-28 12:44:16 +0000274static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800275transit_init (void)
paul718e3742002-12-13 20:15:29 +0000276{
277 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
278}
Chris Caputo228da422009-07-18 05:44:03 +0000279
280static void
281transit_finish (void)
282{
283 hash_free (transit_hash);
284 transit_hash = NULL;
285}
David Lamparter6b0655a2014-06-04 06:53:35 +0200286
paul718e3742002-12-13 20:15:29 +0000287/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700288static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000289
Paul Jakmafb982c22007-05-04 20:15:47 +0000290static struct attr_extra *
291bgp_attr_extra_new (void)
292{
293 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
294}
295
296void
297bgp_attr_extra_free (struct attr *attr)
298{
299 if (attr->extra)
300 {
301 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
302 attr->extra = NULL;
303 }
304}
305
306struct attr_extra *
307bgp_attr_extra_get (struct attr *attr)
308{
309 if (!attr->extra)
310 attr->extra = bgp_attr_extra_new();
311 return attr->extra;
312}
313
314/* Shallow copy of an attribute
315 * Though, not so shallow that it doesn't copy the contents
316 * of the attr_extra pointed to by 'extra'
317 */
318void
319bgp_attr_dup (struct attr *new, struct attr *orig)
320{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000321 struct attr_extra *extra = new->extra;
322
Paul Jakmafb982c22007-05-04 20:15:47 +0000323 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000324 /* if caller provided attr_extra space, use it in any case.
325 *
326 * This is neccesary even if orig->extra equals NULL, because otherwise
327 * memory may be later allocated on the heap by bgp_attr_extra_get.
328 *
329 * That memory would eventually be leaked, because the caller must not
330 * call bgp_attr_extra_free if he provided attr_extra on the stack.
331 */
332 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000333 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000334 new->extra = extra;
335 memset(new->extra, 0, sizeof(struct attr_extra));
336 if (orig->extra)
337 *new->extra = *orig->extra;
338 }
339 else if (orig->extra)
340 {
341 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000342 *new->extra = *orig->extra;
343 }
344}
345
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000346unsigned long int
347attr_count (void)
348{
349 return attrhash->count;
350}
351
352unsigned long int
353attr_unknown_count (void)
354{
355 return transit_hash->count;
356}
357
paul718e3742002-12-13 20:15:29 +0000358unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000359attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000360{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000361 const struct attr *attr = (struct attr *) p;
362 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700363 uint32_t key = 0;
364#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000365
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700366 MIX(attr->origin);
367 MIX(attr->nexthop.s_addr);
368 MIX(attr->med);
369 MIX(attr->local_pref);
370
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000371 key += attr->origin;
372 key += attr->nexthop.s_addr;
373 key += attr->med;
374 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000375
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000376 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000377 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000378 MIX(extra->aggregator_as);
379 MIX(extra->aggregator_addr.s_addr);
380 MIX(extra->weight);
381 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000382 MIX(extra->originator_id.s_addr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000383 }
384
paul718e3742002-12-13 20:15:29 +0000385 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700386 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000387 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700388 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000389
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000390 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000391 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000392 if (extra->ecommunity)
393 MIX(ecommunity_hash_make (extra->ecommunity));
394 if (extra->cluster)
395 MIX(cluster_hash_key_make (extra->cluster));
396 if (extra->transit)
397 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000398
399#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000400 MIX(extra->mp_nexthop_len);
401 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
402 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
paul718e3742002-12-13 20:15:29 +0000403#endif /* HAVE_IPV6 */
Paul Jakmafb982c22007-05-04 20:15:47 +0000404 }
paul718e3742002-12-13 20:15:29 +0000405
406 return key;
407}
408
409int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100410attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000411{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100412 const struct attr * attr1 = p1;
413 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000414
paul718e3742002-12-13 20:15:29 +0000415 if (attr1->flag == attr2->flag
416 && attr1->origin == attr2->origin
417 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000418 && attr1->aspath == attr2->aspath
419 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000420 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000421 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000422 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100423 const struct attr_extra *ae1 = attr1->extra;
424 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000425
426 if (ae1 && ae2
427 && ae1->aggregator_as == ae2->aggregator_as
428 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
429 && ae1->weight == ae2->weight
430#ifdef HAVE_IPV6
431 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
432 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
433 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
434#endif /* HAVE_IPV6 */
435 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
436 && ae1->ecommunity == ae2->ecommunity
437 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000438 && ae1->transit == ae2->transit
439 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000440 return 1;
441 else if (ae1 || ae2)
442 return 0;
443 /* neither attribute has extra attributes, so they're same */
444 return 1;
445 }
paul718e3742002-12-13 20:15:29 +0000446 else
447 return 0;
448}
449
paul94f2b392005-06-28 12:44:16 +0000450static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100451attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000452{
453 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
454}
455
paul94f2b392005-06-28 12:44:16 +0000456static void
Chris Caputo228da422009-07-18 05:44:03 +0000457attrhash_finish (void)
458{
459 hash_free (attrhash);
460 attrhash = NULL;
461}
462
463static void
paul718e3742002-12-13 20:15:29 +0000464attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
465{
466 struct attr *attr = backet->data;
467
468 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
469 inet_ntoa (attr->nexthop), VTY_NEWLINE);
470}
471
472void
473attr_show_all (struct vty *vty)
474{
475 hash_iterate (attrhash,
476 (void (*)(struct hash_backet *, void *))
477 attr_show_all_iterator,
478 vty);
479}
480
paul94f2b392005-06-28 12:44:16 +0000481static void *
Paul Jakma923de652007-04-29 18:25:17 +0000482bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000483{
Paul Jakma923de652007-04-29 18:25:17 +0000484 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000485 struct attr *attr;
486
487 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
488 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000489 if (val->extra)
490 {
491 attr->extra = bgp_attr_extra_new ();
492 *attr->extra = *val->extra;
493 }
paul718e3742002-12-13 20:15:29 +0000494 attr->refcnt = 0;
495 return attr;
496}
497
498/* Internet argument attribute. */
499struct attr *
500bgp_attr_intern (struct attr *attr)
501{
502 struct attr *find;
503
504 /* Intern referenced strucutre. */
505 if (attr->aspath)
506 {
507 if (! attr->aspath->refcnt)
508 attr->aspath = aspath_intern (attr->aspath);
509 else
510 attr->aspath->refcnt++;
511 }
512 if (attr->community)
513 {
514 if (! attr->community->refcnt)
515 attr->community = community_intern (attr->community);
516 else
517 attr->community->refcnt++;
518 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000519 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000520 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000521 struct attr_extra *attre = attr->extra;
522
523 if (attre->ecommunity)
524 {
525 if (! attre->ecommunity->refcnt)
526 attre->ecommunity = ecommunity_intern (attre->ecommunity);
527 else
528 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000529
Paul Jakmafb982c22007-05-04 20:15:47 +0000530 }
531 if (attre->cluster)
532 {
533 if (! attre->cluster->refcnt)
534 attre->cluster = cluster_intern (attre->cluster);
535 else
536 attre->cluster->refcnt++;
537 }
538 if (attre->transit)
539 {
540 if (! attre->transit->refcnt)
541 attre->transit = transit_intern (attre->transit);
542 else
543 attre->transit->refcnt++;
544 }
paul718e3742002-12-13 20:15:29 +0000545 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000546
paul718e3742002-12-13 20:15:29 +0000547 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
548 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000549
paul718e3742002-12-13 20:15:29 +0000550 return find;
551}
552
Paul Jakma03e214c2007-04-29 18:31:07 +0000553
paul718e3742002-12-13 20:15:29 +0000554/* Make network statement's attribute. */
555struct attr *
556bgp_attr_default_set (struct attr *attr, u_char origin)
557{
558 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000559 bgp_attr_extra_get (attr);
560
paul718e3742002-12-13 20:15:29 +0000561 attr->origin = origin;
562 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
563 attr->aspath = aspath_empty ();
564 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000565 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000566 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
567#ifdef HAVE_IPV6
Paul Jakmafb982c22007-05-04 20:15:47 +0000568 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000569#endif
Paul Jakma03e214c2007-04-29 18:31:07 +0000570
paul718e3742002-12-13 20:15:29 +0000571 return attr;
572}
573
Paul Jakma03e214c2007-04-29 18:31:07 +0000574
paul718e3742002-12-13 20:15:29 +0000575/* Make network statement's attribute. */
576struct attr *
577bgp_attr_default_intern (u_char origin)
578{
579 struct attr attr;
580 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000581
Paul Jakma03e214c2007-04-29 18:31:07 +0000582 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000583
584 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000585 bgp_attr_extra_free (&attr);
586
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000587 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000588 return new;
589}
590
591struct attr *
592bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
593 struct aspath *aspath,
594 struct community *community, int as_set)
595{
596 struct attr attr;
597 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000598 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000599
600 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000601 memset (&attre, 0, sizeof (struct attr_extra));
602 attr.extra = &attre;
603
paul718e3742002-12-13 20:15:29 +0000604 /* Origin attribute. */
605 attr.origin = origin;
606 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
607
608 /* AS path attribute. */
609 if (aspath)
610 attr.aspath = aspath_intern (aspath);
611 else
612 attr.aspath = aspath_empty ();
613 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
614
615 /* Next hop attribute. */
616 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
617
618 if (community)
619 {
620 attr.community = community;
621 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
622 }
623
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000624 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000625#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000626 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000627#endif
628 if (! as_set)
629 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
630 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
631 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000632 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000633 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000634 attre.aggregator_as = bgp->as;
635 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000636
637 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000638
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000639 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000640 return new;
641}
642
Paul Jakmab881c702010-11-23 16:35:42 +0000643/* Unintern just the sub-components of the attr, but not the attr */
644void
645bgp_attr_unintern_sub (struct attr *attr)
646{
647 /* aspath refcount shoud be decrement. */
648 if (attr->aspath)
649 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000650 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000651
652 if (attr->community)
653 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000654 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000655
656 if (attr->extra)
657 {
658 if (attr->extra->ecommunity)
659 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000660 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000661
662 if (attr->extra->cluster)
663 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000664 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000665
666 if (attr->extra->transit)
667 transit_unintern (attr->extra->transit);
668 }
669}
670
paul718e3742002-12-13 20:15:29 +0000671/* Free bgp attribute and aspath. */
672void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000673bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000674{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000675 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000676 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000677 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000678 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000679
paul718e3742002-12-13 20:15:29 +0000680 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000681 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000682
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000683 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000684
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000685 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000686 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000687 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000688 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000689 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000690
paul718e3742002-12-13 20:15:29 +0000691 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000692 if (attr->refcnt == 0)
693 {
694 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000695 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000696 bgp_attr_extra_free (attr);
697 XFREE (MTYPE_ATTR, attr);
698 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000699 }
700
Paul Jakmab881c702010-11-23 16:35:42 +0000701 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000702}
703
704void
705bgp_attr_flush (struct attr *attr)
706{
707 if (attr->aspath && ! attr->aspath->refcnt)
708 aspath_free (attr->aspath);
709 if (attr->community && ! attr->community->refcnt)
710 community_free (attr->community);
Paul Jakmafb982c22007-05-04 20:15:47 +0000711 if (attr->extra)
712 {
713 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000714
Paul Jakmafb982c22007-05-04 20:15:47 +0000715 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000716 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000717 if (attre->cluster && ! attre->cluster->refcnt)
718 cluster_free (attre->cluster);
719 if (attre->transit && ! attre->transit->refcnt)
720 transit_free (attre->transit);
721 }
paul718e3742002-12-13 20:15:29 +0000722}
723
Paul Jakmab881c702010-11-23 16:35:42 +0000724/* Implement draft-scudder-idr-optional-transitive behaviour and
725 * avoid resetting sessions for malformed attributes which are
726 * are partial/optional and hence where the error likely was not
727 * introduced by the sending neighbour.
728 */
729static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000730bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
731 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000732{
Paul Jakma835315b2012-01-18 12:28:30 +0000733 struct peer *const peer = args->peer;
734 const u_int8_t flags = args->flags;
735 /* startp and length must be special-cased, as whether or not to
736 * send the attribute data with the NOTIFY depends on the error,
737 * the caller therefore signals this with the seperate length argument
738 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000739 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000740
Paul Jakmab881c702010-11-23 16:35:42 +0000741 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000742 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000743 {
744 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000745 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000746 return BGP_ATTR_PARSE_ERROR;
747
748 }
749
Paul Jakmabd471fe2012-03-15 11:30:00 +0000750 /* Adjust the stream getp to the end of the attribute, in case we can
751 * still proceed but the caller hasn't read all the attribute.
752 */
753 stream_set_getp (BGP_INPUT (peer),
754 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
755 + args->total);
756
Paul Jakma835315b2012-01-18 12:28:30 +0000757 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100758 /* where an attribute is relatively inconsequential, e.g. it does not
759 * affect route selection, and can be safely ignored, then any such
760 * attributes which are malformed should just be ignored and the route
761 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000762 */
763 case BGP_ATTR_AS4_AGGREGATOR:
764 case BGP_ATTR_AGGREGATOR:
765 case BGP_ATTR_ATOMIC_AGGREGATE:
766 return BGP_ATTR_PARSE_PROCEED;
767
768 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100769 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000770 */
771 case BGP_ATTR_ORIGIN:
772 case BGP_ATTR_AS_PATH:
773 case BGP_ATTR_NEXT_HOP:
774 case BGP_ATTR_MULTI_EXIT_DISC:
775 case BGP_ATTR_LOCAL_PREF:
776 case BGP_ATTR_COMMUNITIES:
777 case BGP_ATTR_ORIGINATOR_ID:
778 case BGP_ATTR_CLUSTER_LIST:
779 case BGP_ATTR_MP_REACH_NLRI:
780 case BGP_ATTR_MP_UNREACH_NLRI:
781 case BGP_ATTR_EXT_COMMUNITIES:
782 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000783 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000784 return BGP_ATTR_PARSE_ERROR;
785 }
786
787 /* Partial optional attributes that are malformed should not cause
788 * the whole session to be reset. Instead treat it as a withdrawal
789 * of the routes, if possible.
790 */
Paul Jakma835315b2012-01-18 12:28:30 +0000791 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
792 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
793 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000794 return BGP_ATTR_PARSE_WITHDRAW;
795
796 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200797 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000798}
799
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400800/* Find out what is wrong with the path attribute flag bits and log the error.
801 "Flag bits" here stand for Optional, Transitive and Partial, but not for
802 Extended Length. Checking O/T/P bits at once implies, that the attribute
803 being diagnosed is defined by RFC as either a "well-known" or an "optional,
804 non-transitive" attribute. */
805static void
Paul Jakma835315b2012-01-18 12:28:30 +0000806bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
807 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400808)
809{
810 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000811 u_char real_flags = args->flags;
812 const u_int8_t attr_code = args->type;
813
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400814 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
815 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
816 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
817 if
818 (
819 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
820 CHECK_FLAG (real_flags, attr_flag_str[i].key)
821 )
822 {
Paul Jakma835315b2012-01-18 12:28:30 +0000823 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400824 LOOKUP (attr_str, attr_code),
825 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
826 attr_flag_str[i].str);
827 seen = 1;
828 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100829 if (!seen)
830 {
831 zlog (args->peer->log, LOG_DEBUG,
832 "Strange, %s called for attr %s, but no problem found with flags"
833 " (real flags 0x%x, desired 0x%x)",
834 __func__, LOOKUP (attr_str, attr_code),
835 real_flags, desired_flags);
836 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400837}
838
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000839/* Required flags for attributes. EXTLEN will be masked off when testing,
840 * as will PARTIAL for optional+transitive attributes.
841 */
842const u_int8_t attr_flags_values [] = {
843 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
844 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
845 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
846 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
847 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
848 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
849 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
850 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
851 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
852 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
853 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
854 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
855 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
856 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
857 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
858};
859static const size_t attr_flags_values_max =
860 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
861
862static int
Paul Jakma835315b2012-01-18 12:28:30 +0000863bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000864{
865 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +0000866 const u_int8_t flags = args->flags;
867 const u_int8_t attr_code = args->type;
868 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000869
870 /* there may be attributes we don't know about */
871 if (attr_code > attr_flags_values_max)
872 return 0;
873 if (attr_flags_values[attr_code] == 0)
874 return 0;
875
876 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
877 * 1."
878 */
879 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
880 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
881 {
882 zlog (peer->log, LOG_ERR,
883 "%s well-known attributes must have transitive flag set (%x)",
884 LOOKUP (attr_str, attr_code), flags);
885 return 1;
886 }
887
888 /* "For well-known attributes and for optional non-transitive attributes,
889 * the Partial bit MUST be set to 0."
890 */
891 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
892 {
893 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
894 {
895 zlog (peer->log, LOG_ERR,
896 "%s well-known attribute "
897 "must NOT have the partial flag set (%x)",
898 LOOKUP (attr_str, attr_code), flags);
899 return 1;
900 }
901 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
902 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
903 {
904 zlog (peer->log, LOG_ERR,
905 "%s optional + transitive attribute "
906 "must NOT have the partial flag set (%x)",
907 LOOKUP (attr_str, attr_code), flags);
908 return 1;
909 }
910 }
911
912 /* Optional transitive attributes may go through speakers that don't
913 * reocgnise them and set the Partial bit.
914 */
915 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
916 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
917 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
918
Paul Jakma683f2b82012-03-23 14:58:45 +0000919 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000920 == attr_flags_values[attr_code])
921 return 0;
922
Paul Jakma835315b2012-01-18 12:28:30 +0000923 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000924 return 1;
925}
926
paul718e3742002-12-13 20:15:29 +0000927/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +0000928static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000929bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000930{
Paul Jakma835315b2012-01-18 12:28:30 +0000931 struct peer *const peer = args->peer;
932 struct attr *const attr = args->attr;
933 const bgp_size_t length = args->length;
934
paul718e3742002-12-13 20:15:29 +0000935 /* If any recognized attribute has Attribute Length that conflicts
936 with the expected length (based on the attribute type code), then
937 the Error Subcode is set to Attribute Length Error. The Data
938 field contains the erroneous attribute (type, length and
939 value). */
940 if (length != 1)
941 {
942 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
943 length);
Paul Jakma835315b2012-01-18 12:28:30 +0000944 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000945 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +0000946 args->total);
paul718e3742002-12-13 20:15:29 +0000947 }
948
949 /* Fetch origin attribute. */
950 attr->origin = stream_getc (BGP_INPUT (peer));
951
952 /* If the ORIGIN attribute has an undefined value, then the Error
953 Subcode is set to Invalid Origin Attribute. The Data field
954 contains the unrecognized attribute (type, length and value). */
955 if ((attr->origin != BGP_ORIGIN_IGP)
956 && (attr->origin != BGP_ORIGIN_EGP)
957 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
958 {
959 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
960 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +0000961 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000962 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +0000963 args->total);
paul718e3742002-12-13 20:15:29 +0000964 }
965
966 /* Set oring attribute flag. */
967 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
968
969 return 0;
970}
Paul Jakmaab005292010-11-27 22:48:34 +0000971
972/* Parse AS path information. This function is wrapper of
973 aspath_parse. */
974static int
Paul Jakma835315b2012-01-18 12:28:30 +0000975bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000976{
Paul Jakma835315b2012-01-18 12:28:30 +0000977 struct attr *const attr = args->attr;
978 struct peer *const peer = args->peer;
979 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +0000980
Paul Jakmaab005292010-11-27 22:48:34 +0000981 /*
982 * peer with AS4 => will get 4Byte ASnums
983 * otherwise, will get 16 Bit
984 */
985 attr->aspath = aspath_parse (peer->ibuf, length,
986 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
987
988 /* In case of IBGP, length will be zero. */
989 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +0000990 {
Paul Jakmab881c702010-11-23 16:35:42 +0000991 zlog (peer->log, LOG_ERR,
992 "Malformed AS path from %s, length is %d",
993 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +0000994 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +0000995 }
Chris Hallcddb8112010-08-09 22:31:37 +0400996
Paul Jakmaab005292010-11-27 22:48:34 +0000997 /* Set aspath attribute flag. */
998 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +0000999
Paul Jakmab881c702010-11-23 16:35:42 +00001000 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001001}
1002
Paul Jakmab881c702010-11-23 16:35:42 +00001003static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001004bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001005{
1006 /* These checks were part of bgp_attr_aspath, but with
1007 * as4 we should to check aspath things when
1008 * aspath synthesizing with as4_path has already taken place.
1009 * Otherwise we check ASPATH and use the synthesized thing, and that is
1010 * not right.
1011 * So do the checks later, i.e. here
1012 */
1013 struct bgp *bgp = peer->bgp;
1014 struct aspath *aspath;
1015
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001016 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001017 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1018 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001019 {
1020 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001021 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1022 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1023 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001024 }
1025
paul718e3742002-12-13 20:15:29 +00001026 /* First AS check for EBGP. */
1027 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1028 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001029 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001030 && ! aspath_firstas_check (attr->aspath, peer->as))
1031 {
1032 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001033 "%s incorrect first AS (must be %u)", peer->host, peer->as);
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;
paul718e3742002-12-13 20:15:29 +00001037 }
1038 }
1039
1040 /* local-as prepend */
1041 if (peer->change_local_as &&
1042 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1043 {
1044 aspath = aspath_dup (attr->aspath);
1045 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001046 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001047 attr->aspath = aspath_intern (aspath);
1048 }
1049
Paul Jakmab881c702010-11-23 16:35:42 +00001050 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001051}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001052
Paul Jakmaab005292010-11-27 22:48:34 +00001053/* Parse AS4 path information. This function is another wrapper of
1054 aspath_parse. */
1055static int
Paul Jakma835315b2012-01-18 12:28:30 +00001056bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001057{
Paul Jakma835315b2012-01-18 12:28:30 +00001058 struct peer *const peer = args->peer;
1059 struct attr *const attr = args->attr;
1060 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001061
Paul Jakmaab005292010-11-27 22:48:34 +00001062 *as4_path = aspath_parse (peer->ibuf, length, 1);
1063
Paul Jakmab881c702010-11-23 16:35:42 +00001064 /* In case of IBGP, length will be zero. */
1065 if (!*as4_path)
1066 {
1067 zlog (peer->log, LOG_ERR,
1068 "Malformed AS4 path from %s, length is %d",
1069 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001070 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001071 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001072 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001073 }
1074
Paul Jakmaab005292010-11-27 22:48:34 +00001075 /* Set aspath attribute flag. */
1076 if (as4_path)
1077 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1078
Paul Jakmab881c702010-11-23 16:35:42 +00001079 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001080}
1081
paul718e3742002-12-13 20:15:29 +00001082/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001083static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001084bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001085{
Paul Jakma835315b2012-01-18 12:28:30 +00001086 struct peer *const peer = args->peer;
1087 struct attr *const attr = args->attr;
1088 const bgp_size_t length = args->length;
1089
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001090 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001091
paul718e3742002-12-13 20:15:29 +00001092 /* Check nexthop attribute length. */
1093 if (length != 4)
1094 {
1095 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1096 length);
1097
Paul Jakma835315b2012-01-18 12:28:30 +00001098 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001099 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001100 args->total);
paul718e3742002-12-13 20:15:29 +00001101 }
1102
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001103 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1104 attribute must result in a NOTIFICATION message (this is implemented below).
1105 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1106 logged locally (this is implemented somewhere else). The UPDATE message
1107 gets ignored in any of these cases. */
1108 nexthop_n = stream_get_ipv4 (peer->ibuf);
1109 nexthop_h = ntohl (nexthop_n);
1110 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1111 {
1112 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001113 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001114 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001115 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001116 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001117 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001118 }
1119
1120 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001121 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1122
Paul Jakmab881c702010-11-23 16:35:42 +00001123 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001124}
1125
1126/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001127static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001128bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001129{
Paul Jakma835315b2012-01-18 12:28:30 +00001130 struct peer *const peer = args->peer;
1131 struct attr *const attr = args->attr;
1132 const bgp_size_t length = args->length;
1133
paul718e3742002-12-13 20:15:29 +00001134 /* Length check. */
1135 if (length != 4)
1136 {
1137 zlog (peer->log, LOG_ERR,
1138 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001139
Paul Jakma835315b2012-01-18 12:28:30 +00001140 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001141 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001142 args->total);
paul718e3742002-12-13 20:15:29 +00001143 }
1144
1145 attr->med = stream_getl (peer->ibuf);
1146
1147 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1148
Paul Jakmab881c702010-11-23 16:35:42 +00001149 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001150}
1151
1152/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001153static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001154bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001155{
Paul Jakma835315b2012-01-18 12:28:30 +00001156 struct peer *const peer = args->peer;
1157 struct attr *const attr = args->attr;
1158 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001159
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001160 /* Length check. */
1161 if (length != 4)
1162 {
Paul Jakma835315b2012-01-18 12:28:30 +00001163 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1164 length);
1165 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001166 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001167 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001168 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001169
paul718e3742002-12-13 20:15:29 +00001170 /* If it is contained in an UPDATE message that is received from an
1171 external peer, then this attribute MUST be ignored by the
1172 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001173 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001174 {
paul9985f832005-02-09 15:51:56 +00001175 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001176 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001177 }
1178
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001179 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001180
1181 /* Set atomic aggregate flag. */
1182 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1183
Paul Jakmab881c702010-11-23 16:35:42 +00001184 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001185}
1186
1187/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001188static int
Paul Jakma835315b2012-01-18 12:28:30 +00001189bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001190{
Paul Jakma835315b2012-01-18 12:28:30 +00001191 struct peer *const peer = args->peer;
1192 struct attr *const attr = args->attr;
1193 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001194
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001195 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001196 if (length != 0)
1197 {
Paul Jakma835315b2012-01-18 12:28:30 +00001198 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1199 length);
1200 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001201 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001202 args->total);
paul718e3742002-12-13 20:15:29 +00001203 }
1204
1205 /* Set atomic aggregate flag. */
1206 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1207
Paul Jakmab881c702010-11-23 16:35:42 +00001208 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001209}
1210
1211/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001212static int
Paul Jakma835315b2012-01-18 12:28:30 +00001213bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001214{
Paul Jakma835315b2012-01-18 12:28:30 +00001215 struct peer *const peer = args->peer;
1216 struct attr *const attr = args->attr;
1217 const bgp_size_t length = args->length;
1218
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001219 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001220 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001221
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001222 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001223 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001224 wantedlen = 8;
1225
1226 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001227 {
Paul Jakma835315b2012-01-18 12:28:30 +00001228 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1229 wantedlen, length);
1230 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001231 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001232 args->total);
paul718e3742002-12-13 20:15:29 +00001233 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001234
1235 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1236 attre->aggregator_as = stream_getl (peer->ibuf);
1237 else
1238 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001239 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001240
1241 /* Set atomic aggregate flag. */
1242 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1243
Paul Jakmab881c702010-11-23 16:35:42 +00001244 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001245}
1246
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001247/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001248static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001249bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1250 as_t *as4_aggregator_as,
1251 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001252{
Paul Jakma835315b2012-01-18 12:28:30 +00001253 struct peer *const peer = args->peer;
1254 struct attr *const attr = args->attr;
1255 const bgp_size_t length = args->length;
1256
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001257 if (length != 8)
1258 {
Paul Jakma835315b2012-01-18 12:28:30 +00001259 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1260 length);
1261 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001262 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001263 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001264 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001265
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001266 *as4_aggregator_as = stream_getl (peer->ibuf);
1267 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1268
1269 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1270
Paul Jakmab881c702010-11-23 16:35:42 +00001271 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001272}
1273
1274/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1275 */
Paul Jakmab881c702010-11-23 16:35:42 +00001276static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001277bgp_attr_munge_as4_attrs (struct peer *const peer,
1278 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001279 struct aspath *as4_path, as_t as4_aggregator,
1280 struct in_addr *as4_aggregator_addr)
1281{
1282 int ignore_as4_path = 0;
1283 struct aspath *newpath;
1284 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001285
1286 if (!attr->aspath)
1287 {
1288 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1289 * checked that all well-known, mandatory attributes were present.
1290 *
1291 * Can only be a problem with peer itself - hard error
1292 */
1293 return BGP_ATTR_PARSE_ERROR;
1294 }
1295
Paul Jakmab881c702010-11-23 16:35:42 +00001296 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001297 {
1298 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1299 * if given.
1300 * It is worth a warning though, because the peer really
1301 * should not send them
1302 */
1303 if (BGP_DEBUG(as4, AS4))
1304 {
1305 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1306 zlog_debug ("[AS4] %s %s AS4_PATH",
1307 peer->host, "AS4 capable peer, yet it sent");
1308
1309 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1310 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1311 peer->host, "AS4 capable peer, yet it sent");
1312 }
1313
Paul Jakmab881c702010-11-23 16:35:42 +00001314 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001315 }
1316
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001317 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1318 * because that may override AS4_PATH
1319 */
1320 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1321 {
Paul Jakmab881c702010-11-23 16:35:42 +00001322 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001323 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001324 assert (attre);
1325
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001326 /* received both.
1327 * if the as_number in aggregator is not AS_TRANS,
1328 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1329 * and the Aggregator shall be taken as
1330 * info on the aggregating node, and the AS_PATH
1331 * shall be taken as the AS_PATH
1332 * otherwise
1333 * the Aggregator shall be ignored and the
1334 * AS4_AGGREGATOR shall be taken as the
1335 * Aggregating node and the AS_PATH is to be
1336 * constructed "as in all other cases"
1337 */
Paul Jakmab881c702010-11-23 16:35:42 +00001338 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001339 {
1340 /* ignore */
1341 if ( BGP_DEBUG(as4, AS4))
1342 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1343 " send AGGREGATOR != AS_TRANS and"
1344 " AS4_AGGREGATOR, so ignore"
1345 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1346 ignore_as4_path = 1;
1347 }
1348 else
1349 {
1350 /* "New_aggregator shall be taken as aggregator" */
1351 attre->aggregator_as = as4_aggregator;
1352 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1353 }
1354 }
1355 else
1356 {
1357 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1358 * That is bogus - but reading the conditions
1359 * we have to handle AS4_AGGREGATOR as if it were
1360 * AGGREGATOR in that case
1361 */
1362 if ( BGP_DEBUG(as4, AS4))
1363 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1364 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1365 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001366 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001367 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1368 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1369 }
1370 }
1371
1372 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001373 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001374 {
Paul Jakma055086f2014-09-23 15:23:01 +01001375 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1376 aspath_unintern (&attr->aspath);
1377 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001378 }
Paul Jakmab881c702010-11-23 16:35:42 +00001379 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001380}
1381
paul718e3742002-12-13 20:15:29 +00001382/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001383static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001384bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001385{
Paul Jakma835315b2012-01-18 12:28:30 +00001386 struct peer *const peer = args->peer;
1387 struct attr *const attr = args->attr;
1388 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001389
paul718e3742002-12-13 20:15:29 +00001390 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001391 {
1392 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001393 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001394 }
Paul Jakma0c466382010-12-05 17:17:26 +00001395
1396 attr->community =
1397 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1398
1399 /* XXX: fix community_parse to use stream API and remove this */
1400 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001401
Paul Jakma0c466382010-12-05 17:17:26 +00001402 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001403 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001404 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001405 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001406
paul718e3742002-12-13 20:15:29 +00001407 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1408
Paul Jakmab881c702010-11-23 16:35:42 +00001409 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001410}
1411
1412/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001413static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001414bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001415{
Paul Jakma835315b2012-01-18 12:28:30 +00001416 struct peer *const peer = args->peer;
1417 struct attr *const attr = args->attr;
1418 const bgp_size_t length = args->length;
1419
Denis Ovsienkod595b562011-09-30 15:08:54 +04001420 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001421 if (length != 4)
1422 {
1423 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1424
Paul Jakma835315b2012-01-18 12:28:30 +00001425 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001426 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001427 args->total);
paul718e3742002-12-13 20:15:29 +00001428 }
1429
Paul Jakmafb982c22007-05-04 20:15:47 +00001430 (bgp_attr_extra_get (attr))->originator_id.s_addr
1431 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001432
1433 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1434
Paul Jakmab881c702010-11-23 16:35:42 +00001435 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001436}
1437
1438/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001439static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001440bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001441{
Paul Jakma835315b2012-01-18 12:28:30 +00001442 struct peer *const peer = args->peer;
1443 struct attr *const attr = args->attr;
1444 const bgp_size_t length = args->length;
1445
paul718e3742002-12-13 20:15:29 +00001446 /* Check length. */
1447 if (length % 4)
1448 {
1449 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1450
Paul Jakma835315b2012-01-18 12:28:30 +00001451 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1452 args->total);
paul718e3742002-12-13 20:15:29 +00001453 }
1454
Paul Jakmafb982c22007-05-04 20:15:47 +00001455 (bgp_attr_extra_get (attr))->cluster
1456 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001457
1458 /* XXX: Fix cluster_parse to use stream API and then remove this */
1459 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001460
1461 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1462
Paul Jakmab881c702010-11-23 16:35:42 +00001463 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001464}
1465
1466/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001467int
Paul Jakma835315b2012-01-18 12:28:30 +00001468bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1469 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001470{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001471 afi_t afi;
1472 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001473 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001474 size_t start;
paul718e3742002-12-13 20:15:29 +00001475 int ret;
1476 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001477 struct peer *const peer = args->peer;
1478 struct attr *const attr = args->attr;
1479 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001480 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001481
paul718e3742002-12-13 20:15:29 +00001482 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001483 s = BGP_INPUT(peer);
1484 start = stream_get_getp(s);
1485
1486 /* safe to read statically sized header? */
1487#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001488#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001489 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001490 {
1491 zlog_info ("%s: %s sent invalid length, %lu",
1492 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001493 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001494 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001495
paul718e3742002-12-13 20:15:29 +00001496 /* Load AFI, SAFI. */
1497 afi = stream_getw (s);
1498 safi = stream_getc (s);
1499
1500 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001501 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001502
Paul Jakma03292802008-06-07 20:37:10 +00001503 if (LEN_LEFT < attre->mp_nexthop_len)
1504 {
1505 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1506 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001507 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001508 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001509
paul718e3742002-12-13 20:15:29 +00001510 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001511 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001512 {
1513 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001514 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001515 /* Probably needed for RFC 2283 */
1516 if (attr->nexthop.s_addr == 0)
1517 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001518 break;
1519 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001520 stream_getl (s); /* RD high */
1521 stream_getl (s); /* RD low */
1522 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001523 break;
1524#ifdef HAVE_IPV6
1525 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001526 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001527 break;
1528 case 32:
Paul Jakmafb982c22007-05-04 20:15:47 +00001529 stream_get (&attre->mp_nexthop_global, s, 16);
1530 stream_get (&attre->mp_nexthop_local, s, 16);
1531 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001532 {
1533 char buf1[INET6_ADDRSTRLEN];
1534 char buf2[INET6_ADDRSTRLEN];
1535
1536 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001537 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 +00001538 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001539 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001540 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001541 buf2, INET6_ADDRSTRLEN));
1542
Paul Jakmafb982c22007-05-04 20:15:47 +00001543 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001544 }
1545 break;
1546#endif /* HAVE_IPV6 */
1547 default:
Paul Jakma03292802008-06-07 20:37:10 +00001548 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1549 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001550 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001551 }
1552
Paul Jakma03292802008-06-07 20:37:10 +00001553 if (!LEN_LEFT)
1554 {
1555 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1556 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001557 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001558 }
paul718e3742002-12-13 20:15:29 +00001559
Paul Jakma6e4ab122007-04-10 19:36:48 +00001560 {
1561 u_char val;
1562 if ((val = stream_getc (s)))
1563 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1564 peer->host, val);
1565 }
1566
1567 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001568 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001569 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001570 {
1571 zlog_info ("%s: (%s) Failed to read NLRI",
1572 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001573 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001574 }
paul718e3742002-12-13 20:15:29 +00001575
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001576 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001577 {
1578 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
Paul Jakma03292802008-06-07 20:37:10 +00001579 if (ret < 0)
1580 {
1581 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1582 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001583 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001584 }
paul718e3742002-12-13 20:15:29 +00001585 }
1586
1587 mp_update->afi = afi;
1588 mp_update->safi = safi;
1589 mp_update->nlri = stream_pnt (s);
1590 mp_update->length = nlri_len;
1591
paul9985f832005-02-09 15:51:56 +00001592 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001593
David Lamparterdaefeb82014-12-08 17:42:12 +01001594 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1595
Paul Jakmab881c702010-11-23 16:35:42 +00001596 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001597#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001598}
1599
1600/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001601int
Paul Jakma835315b2012-01-18 12:28:30 +00001602bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001603 struct bgp_nlri *mp_withdraw)
1604{
1605 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001606 afi_t afi;
1607 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001608 u_int16_t withdraw_len;
1609 int ret;
Paul Jakma835315b2012-01-18 12:28:30 +00001610 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001611 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001612 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001613
1614 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001615
1616#define BGP_MP_UNREACH_MIN_SIZE 3
1617 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001618 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001619
paul718e3742002-12-13 20:15:29 +00001620 afi = stream_getw (s);
1621 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001622
1623 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001624
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001625 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001626 {
1627 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1628 if (ret < 0)
David Lamparterf57000c2014-06-04 01:01:10 +02001629 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001630 }
1631
1632 mp_withdraw->afi = afi;
1633 mp_withdraw->safi = safi;
1634 mp_withdraw->nlri = stream_pnt (s);
1635 mp_withdraw->length = withdraw_len;
1636
paul9985f832005-02-09 15:51:56 +00001637 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001638
David Lamparterdaefeb82014-12-08 17:42:12 +01001639 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1640
Paul Jakmab881c702010-11-23 16:35:42 +00001641 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001642}
1643
1644/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001645static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001646bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001647{
Paul Jakma835315b2012-01-18 12:28:30 +00001648 struct peer *const peer = args->peer;
1649 struct attr *const attr = args->attr;
1650 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001651
paul718e3742002-12-13 20:15:29 +00001652 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001653 {
1654 if (attr->extra)
1655 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001656 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001657 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001658 }
Paul Jakma0c466382010-12-05 17:17:26 +00001659
1660 (bgp_attr_extra_get (attr))->ecommunity =
1661 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1662 /* XXX: fix ecommunity_parse to use stream API */
1663 stream_forward_getp (peer->ibuf, length);
1664
1665 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001666 return bgp_attr_malformed (args,
1667 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1668 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001669
paul718e3742002-12-13 20:15:29 +00001670 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1671
Paul Jakmab881c702010-11-23 16:35:42 +00001672 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001673}
1674
1675/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001676static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001677bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001678{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001679 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001680 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001681 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001682 struct peer *const peer = args->peer;
1683 struct attr *const attr = args->attr;
1684 u_char *const startp = args->startp;
1685 const u_char type = args->type;
1686 const u_char flag = args->flags;
1687 const bgp_size_t length = args->length;
1688
paul718e3742002-12-13 20:15:29 +00001689
hassof4184462005-02-01 20:13:16 +00001690 if (BGP_DEBUG (normal, NORMAL))
1691 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1692 peer->host, type, length);
1693
paul718e3742002-12-13 20:15:29 +00001694 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001695 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001696 "Unknown attribute type %d length %d is received", type, length);
1697
1698 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001699 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001700
paul718e3742002-12-13 20:15:29 +00001701 /* If any of the mandatory well-known attributes are not recognized,
1702 then the Error Subcode is set to Unrecognized Well-known
1703 Attribute. The Data field contains the unrecognized attribute
1704 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001705 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001706 {
Paul Jakma835315b2012-01-18 12:28:30 +00001707 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001708 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001709 args->total);
paul718e3742002-12-13 20:15:29 +00001710 }
1711
1712 /* Unrecognized non-transitive optional attributes must be quietly
1713 ignored and not passed along to other BGP peers. */
1714 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001715 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001716
1717 /* If a path with recognized transitive optional attribute is
1718 accepted and passed along to other BGP peers and the Partial bit
1719 in the Attribute Flags octet is set to 1 by some previous AS, it
1720 is not set back to 0 by the current AS. */
1721 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1722
1723 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001724 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001725 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001726
Paul Jakmafb982c22007-05-04 20:15:47 +00001727 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001728
1729 if (transit->val)
1730 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1731 transit->length + total);
1732 else
1733 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1734
1735 memcpy (transit->val + transit->length, startp, total);
1736 transit->length += total;
1737
Paul Jakmab881c702010-11-23 16:35:42 +00001738 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001739}
1740
Paul Jakma055086f2014-09-23 15:23:01 +01001741/* Well-known attribute check. */
1742static int
1743bgp_attr_check (struct peer *peer, struct attr *attr)
1744{
1745 u_char type = 0;
1746
Paul Jakmaaed1b552014-10-21 16:59:01 +01001747 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
1748 * empty UPDATE. */
1749 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
1750 return BGP_ATTR_PARSE_PROCEED;
1751
1752 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
1753 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
1754 are present, it should. Check for any other attribute being present
1755 instead.
1756 */
1757 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
1758 return BGP_ATTR_PARSE_PROCEED;
1759
Paul Jakma055086f2014-09-23 15:23:01 +01001760 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1761 type = BGP_ATTR_ORIGIN;
1762
1763 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1764 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001765
1766 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
1767 * NLRI is empty. We can't easily check NLRI empty here though.
1768 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00001769 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
1770 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01001771 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001772
Paul Jakma055086f2014-09-23 15:23:01 +01001773 if (peer->sort == BGP_PEER_IBGP
1774 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1775 type = BGP_ATTR_LOCAL_PREF;
1776
1777 if (type)
1778 {
1779 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01001780 "%s Missing well-known attribute %d / %s",
1781 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01001782 bgp_notify_send_with_data (peer,
1783 BGP_NOTIFY_UPDATE_ERR,
1784 BGP_NOTIFY_UPDATE_MISS_ATTR,
1785 &type, 1);
1786 return BGP_ATTR_PARSE_ERROR;
1787 }
1788 return BGP_ATTR_PARSE_PROCEED;
1789}
1790
paul718e3742002-12-13 20:15:29 +00001791/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00001792 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00001793bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00001794bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1795 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1796{
1797 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00001798 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001799 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00001800 bgp_size_t length;
1801 u_char *startp, *endp;
1802 u_char *attr_endp;
1803 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001804 /* we need the as4_path only until we have synthesized the as_path with it */
1805 /* same goes for as4_aggregator */
1806 struct aspath *as4_path = NULL;
1807 as_t as4_aggregator = 0;
1808 struct in_addr as4_aggregator_addr = { 0 };
paul718e3742002-12-13 20:15:29 +00001809
1810 /* Initialize bitmap. */
1811 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1812
1813 /* End pointer of BGP attribute. */
1814 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00001815
paul718e3742002-12-13 20:15:29 +00001816 /* Get attributes to the end of attribute length. */
1817 while (BGP_INPUT_PNT (peer) < endp)
1818 {
1819 /* Check remaining length check.*/
1820 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1821 {
gdtc29fdba2004-12-09 14:46:46 +00001822 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00001823 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001824 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001825 peer->host,
1826 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00001827
1828 bgp_notify_send (peer,
1829 BGP_NOTIFY_UPDATE_ERR,
1830 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001831 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001832 }
1833
1834 /* Fetch attribute flag and type. */
1835 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04001836 /* "The lower-order four bits of the Attribute Flags octet are
1837 unused. They MUST be zero when sent and MUST be ignored when
1838 received." */
1839 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00001840 type = stream_getc (BGP_INPUT (peer));
1841
Paul Jakma370b64a2007-12-22 16:49:52 +00001842 /* Check whether Extended-Length applies and is in bounds */
1843 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1844 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1845 {
1846 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001847 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00001848 peer->host,
1849 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1850
1851 bgp_notify_send (peer,
1852 BGP_NOTIFY_UPDATE_ERR,
1853 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001854 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00001855 }
Paul Jakma835315b2012-01-18 12:28:30 +00001856
paul718e3742002-12-13 20:15:29 +00001857 /* Check extended attribue length bit. */
1858 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1859 length = stream_getw (BGP_INPUT (peer));
1860 else
1861 length = stream_getc (BGP_INPUT (peer));
1862
1863 /* If any attribute appears more than once in the UPDATE
1864 message, then the Error Subcode is set to Malformed Attribute
1865 List. */
1866
1867 if (CHECK_BITMAP (seen, type))
1868 {
1869 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001870 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00001871 peer->host, type);
1872
1873 bgp_notify_send (peer,
1874 BGP_NOTIFY_UPDATE_ERR,
1875 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00001876 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001877 }
1878
1879 /* Set type to bitmap to check duplicate attribute. `type' is
1880 unsigned char so it never overflow bitmap range. */
1881
1882 SET_BITMAP (seen, type);
1883
1884 /* Overflow check. */
1885 attr_endp = BGP_INPUT_PNT (peer) + length;
1886
1887 if (attr_endp > endp)
1888 {
1889 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001890 "%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 +00001891 bgp_notify_send (peer,
1892 BGP_NOTIFY_UPDATE_ERR,
1893 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001894 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001895 }
Paul Jakma835315b2012-01-18 12:28:30 +00001896
1897 struct bgp_attr_parser_args attr_args = {
1898 .peer = peer,
1899 .length = length,
1900 .attr = attr,
1901 .type = type,
1902 .flags = flag,
1903 .startp = startp,
1904 .total = attr_endp - startp,
1905 };
1906
1907
1908 /* If any recognized attribute has Attribute Flags that conflict
1909 with the Attribute Type Code, then the Error Subcode is set to
1910 Attribute Flags Error. The Data field contains the erroneous
1911 attribute (type, length and value). */
1912 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01001913 {
1914 bgp_attr_parse_ret_t ret;
1915 ret = bgp_attr_malformed (&attr_args,
1916 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1917 attr_args.total);
1918 if (ret == BGP_ATTR_PARSE_PROCEED)
1919 continue;
1920 return ret;
1921 }
paul718e3742002-12-13 20:15:29 +00001922
1923 /* OK check attribute and store it's value. */
1924 switch (type)
1925 {
1926 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00001927 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00001928 break;
1929 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001930 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00001931 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001932 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001933 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001934 break;
paul718e3742002-12-13 20:15:29 +00001935 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00001936 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00001937 break;
1938 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00001939 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00001940 break;
1941 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00001942 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00001943 break;
1944 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00001945 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00001946 break;
1947 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001948 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00001949 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001950 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001951 ret = bgp_attr_as4_aggregator (&attr_args,
1952 &as4_aggregator,
1953 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001954 break;
paul718e3742002-12-13 20:15:29 +00001955 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001956 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00001957 break;
1958 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00001959 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00001960 break;
1961 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00001962 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00001963 break;
1964 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001965 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00001966 break;
1967 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001968 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00001969 break;
1970 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001971 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00001972 break;
1973 default:
Paul Jakma835315b2012-01-18 12:28:30 +00001974 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00001975 break;
1976 }
Paul Jakmab881c702010-11-23 16:35:42 +00001977
David Lamparterf57000c2014-06-04 01:01:10 +02001978 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
1979 {
1980 bgp_notify_send (peer,
1981 BGP_NOTIFY_UPDATE_ERR,
1982 BGP_NOTIFY_UPDATE_MAL_ATTR);
1983 ret = BGP_ATTR_PARSE_ERROR;
1984 }
1985
Paul Jakmab881c702010-11-23 16:35:42 +00001986 /* If hard error occured immediately return to the caller. */
1987 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00001988 {
1989 zlog (peer->log, LOG_WARNING,
1990 "%s: Attribute %s, parse error",
1991 peer->host,
1992 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00001993 if (as4_path)
1994 aspath_unintern (&as4_path);
1995 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001996 }
Paul Jakmab881c702010-11-23 16:35:42 +00001997 if (ret == BGP_ATTR_PARSE_WITHDRAW)
1998 {
1999
2000 zlog (peer->log, LOG_WARNING,
2001 "%s: Attribute %s, parse error - treating as withdrawal",
2002 peer->host,
2003 LOOKUP (attr_str, type));
2004 if (as4_path)
2005 aspath_unintern (&as4_path);
2006 return ret;
2007 }
2008
paul718e3742002-12-13 20:15:29 +00002009 /* Check the fetched length. */
2010 if (BGP_INPUT_PNT (peer) != attr_endp)
2011 {
2012 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002013 "%s: BGP attribute %s, fetch error",
2014 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002015 bgp_notify_send (peer,
2016 BGP_NOTIFY_UPDATE_ERR,
2017 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002018 if (as4_path)
2019 aspath_unintern (&as4_path);
2020 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002021 }
2022 }
paul718e3742002-12-13 20:15:29 +00002023 /* Check final read pointer is same as end pointer. */
2024 if (BGP_INPUT_PNT (peer) != endp)
2025 {
2026 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002027 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002028 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002029 bgp_notify_send (peer,
2030 BGP_NOTIFY_UPDATE_ERR,
2031 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002032 if (as4_path)
2033 aspath_unintern (&as4_path);
2034 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002035 }
Paul Jakma055086f2014-09-23 15:23:01 +01002036
2037 /* Check all mandatory well-known attributes are present */
2038 {
2039 bgp_attr_parse_ret_t ret;
2040 if ((ret = bgp_attr_check (peer, attr)) < 0)
2041 {
2042 if (as4_path)
2043 aspath_unintern (&as4_path);
2044 return ret;
2045 }
2046 }
2047
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002048 /*
2049 * At this place we can see whether we got AS4_PATH and/or
2050 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2051 * We can not do this before we've read all attributes because
2052 * the as4 handling does not say whether AS4_PATH has to be sent
2053 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2054 * in relationship to AGGREGATOR.
2055 * So, to be defensive, we are not relying on any order and read
2056 * all attributes first, including these 32bit ones, and now,
2057 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002058 *
2059 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2060 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002061 */
David Lamparterf57000c2014-06-04 01:01:10 +02002062 /* actually... this doesn't ever return failure currently, but
2063 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002064 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2065 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002066 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002067 {
David Lamparterf57000c2014-06-04 01:01:10 +02002068 bgp_notify_send (peer,
2069 BGP_NOTIFY_UPDATE_ERR,
2070 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002071 if (as4_path)
2072 aspath_unintern (&as4_path);
2073 return BGP_ATTR_PARSE_ERROR;
2074 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002075
2076 /* At this stage, we have done all fiddling with as4, and the
2077 * resulting info is in attr->aggregator resp. attr->aspath
2078 * so we can chuck as4_aggregator and as4_path alltogether in
2079 * order to save memory
2080 */
Paul Jakmab881c702010-11-23 16:35:42 +00002081 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002082 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002083 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002084 /* The flag that we got this is still there, but that does not
2085 * do any trouble
2086 */
2087 }
2088 /*
2089 * The "rest" of the code does nothing with as4_aggregator.
2090 * there is no memory attached specifically which is not part
2091 * of the attr.
2092 * so ignoring just means do nothing.
2093 */
2094 /*
2095 * Finally do the checks on the aspath we did not do yet
2096 * because we waited for a potentially synthesized aspath.
2097 */
Paul Jakmab881c702010-11-23 16:35:42 +00002098 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002099 {
Paul Jakma835315b2012-01-18 12:28:30 +00002100 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002101 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002102 return ret;
2103 }
2104
paul718e3742002-12-13 20:15:29 +00002105 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002106 if (attr->extra && attr->extra->transit)
2107 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002108
Paul Jakmab881c702010-11-23 16:35:42 +00002109 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002110}
2111
paul718e3742002-12-13 20:15:29 +00002112int stream_put_prefix (struct stream *, struct prefix *);
2113
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002114size_t
2115bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2116 struct attr *attr)
2117{
2118 size_t sizep;
2119
2120 /* Set extended bit always to encode the attribute length as 2 bytes */
2121 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2122 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2123 sizep = stream_get_endp (s);
2124 stream_putw (s, 0); /* Marker: Attribute length. */
2125 stream_putw (s, afi); /* AFI */
2126 stream_putc (s, safi); /* SAFI */
2127
2128 /* Nexthop */
2129 switch (afi)
2130 {
2131 case AFI_IP:
2132 switch (safi)
2133 {
2134 case SAFI_UNICAST:
2135 case SAFI_MULTICAST:
2136 stream_putc (s, 4);
2137 stream_put_ipv4 (s, attr->nexthop.s_addr);
2138 break;
2139 case SAFI_MPLS_VPN:
2140 stream_putc (s, 12);
2141 stream_putl (s, 0);
2142 stream_putl (s, 0);
2143 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2144 break;
2145 default:
2146 break;
2147 }
2148 break;
2149#ifdef HAVE_IPV6
2150 case AFI_IP6:
2151 switch (safi)
2152 {
2153 case SAFI_UNICAST:
2154 case SAFI_MULTICAST:
2155 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002156 struct attr_extra *attre = attr->extra;
2157
2158 assert (attr->extra);
2159 stream_putc (s, attre->mp_nexthop_len);
2160 stream_put (s, &attre->mp_nexthop_global, 16);
2161 if (attre->mp_nexthop_len == 32)
2162 stream_put (s, &attre->mp_nexthop_local, 16);
2163 }
2164 default:
2165 break;
2166 }
2167 break;
2168#endif /*HAVE_IPV6*/
2169 default:
2170 break;
2171 }
2172
2173 /* SNPA */
2174 stream_putc (s, 0);
2175 return sizep;
2176}
2177
2178void
2179bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2180 struct prefix *p, struct prefix_rd *prd,
2181 u_char *tag)
2182{
2183 switch (safi)
2184 {
2185 case SAFI_MPLS_VPN:
2186 /* Tag, RD, Prefix write. */
2187 stream_putc (s, p->prefixlen + 88);
2188 stream_put (s, tag, 3);
2189 stream_put (s, prd->val, 8);
2190 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2191 break;
2192 default:
2193 /* Prefix write. */
2194 stream_put_prefix (s, p);
2195 break;
2196 }
2197}
2198
2199void
2200bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2201{
2202 /* Set MP attribute length. Don't count the (2) bytes used to encode
2203 the attr length */
2204 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2205}
2206
paul718e3742002-12-13 20:15:29 +00002207/* Make attribute packet. */
2208bgp_size_t
2209bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002210 struct stream *s, struct attr *attr,
2211 struct prefix *p, afi_t afi, safi_t safi,
2212 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002213{
paulfe69a502005-09-10 16:55:02 +00002214 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002215 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002216 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002217 int send_as4_path = 0;
2218 int send_as4_aggregator = 0;
2219 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002220 size_t mpattrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +00002221
2222 if (! bgp)
2223 bgp = bgp_get_default ();
2224
2225 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002226 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002227
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002228 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2229 {
2230 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2231 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2232 bgp_packet_mpattr_end(s, mpattrlen_pos);
2233 }
2234
paul718e3742002-12-13 20:15:29 +00002235 /* Origin attribute. */
2236 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2237 stream_putc (s, BGP_ATTR_ORIGIN);
2238 stream_putc (s, 1);
2239 stream_putc (s, attr->origin);
2240
2241 /* AS path attribute. */
2242
2243 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002244 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002245 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002246 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002247 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002248 {
2249 aspath = aspath_dup (attr->aspath);
2250
2251 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2252 {
2253 /* Strip the confed info, and then stuff our path CONFED_ID
2254 on the front */
2255 aspath = aspath_delete_confed_seq (aspath);
2256 aspath = aspath_add_seq (aspath, bgp->confed_id);
2257 }
2258 else
2259 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002260 if (peer->change_local_as) {
2261 /* If replace-as is specified, we only use the change_local_as when
2262 advertising routes. */
2263 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2264 aspath = aspath_add_seq (aspath, peer->local_as);
2265 }
paul718e3742002-12-13 20:15:29 +00002266 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002267 } else {
2268 aspath = aspath_add_seq (aspath, peer->local_as);
2269 }
paul718e3742002-12-13 20:15:29 +00002270 }
2271 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002272 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002273 {
2274 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2275 aspath = aspath_dup (attr->aspath);
2276 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2277 }
2278 else
2279 aspath = attr->aspath;
2280
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002281 /* If peer is not AS4 capable, then:
2282 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2283 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2284 * types are in it (i.e. exclude them if they are there)
2285 * AND do this only if there is at least one asnum > 65535 in the path!
2286 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2287 * all ASnums > 65535 to BGP_AS_TRANS
2288 */
paul718e3742002-12-13 20:15:29 +00002289
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002290 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2291 stream_putc (s, BGP_ATTR_AS_PATH);
2292 aspath_sizep = stream_get_endp (s);
2293 stream_putw (s, 0);
2294 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2295
2296 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2297 * in the path
2298 */
2299 if (!use32bit && aspath_has_as4 (aspath))
2300 send_as4_path = 1; /* we'll do this later, at the correct place */
2301
paul718e3742002-12-13 20:15:29 +00002302 /* Nexthop attribute. */
2303 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2304 {
2305 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2306 stream_putc (s, BGP_ATTR_NEXT_HOP);
2307 stream_putc (s, 4);
2308 if (safi == SAFI_MPLS_VPN)
2309 {
2310 if (attr->nexthop.s_addr == 0)
2311 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2312 else
2313 stream_put_ipv4 (s, attr->nexthop.s_addr);
2314 }
2315 else
2316 stream_put_ipv4 (s, attr->nexthop.s_addr);
2317 }
2318
2319 /* MED attribute. */
2320 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2321 {
2322 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2323 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2324 stream_putc (s, 4);
2325 stream_putl (s, attr->med);
2326 }
2327
2328 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002329 if (peer->sort == BGP_PEER_IBGP ||
2330 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002331 {
2332 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2333 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2334 stream_putc (s, 4);
2335 stream_putl (s, attr->local_pref);
2336 }
2337
2338 /* Atomic aggregate. */
2339 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2340 {
2341 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2342 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2343 stream_putc (s, 0);
2344 }
2345
2346 /* Aggregator. */
2347 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2348 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002349 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002350
2351 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002352 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2353 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002354
2355 if (use32bit)
2356 {
2357 /* AS4 capable peer */
2358 stream_putc (s, 8);
2359 stream_putl (s, attr->extra->aggregator_as);
2360 }
2361 else
2362 {
2363 /* 2-byte AS peer */
2364 stream_putc (s, 6);
2365
2366 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2367 if ( attr->extra->aggregator_as > 65535 )
2368 {
2369 stream_putw (s, BGP_AS_TRANS);
2370
2371 /* we have to send AS4_AGGREGATOR, too.
2372 * we'll do that later in order to send attributes in ascending
2373 * order.
2374 */
2375 send_as4_aggregator = 1;
2376 }
2377 else
2378 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2379 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002380 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002381 }
2382
2383 /* Community attribute. */
2384 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2385 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2386 {
2387 if (attr->community->size * 4 > 255)
2388 {
2389 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2390 stream_putc (s, BGP_ATTR_COMMUNITIES);
2391 stream_putw (s, attr->community->size * 4);
2392 }
2393 else
2394 {
2395 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2396 stream_putc (s, BGP_ATTR_COMMUNITIES);
2397 stream_putc (s, attr->community->size * 4);
2398 }
2399 stream_put (s, attr->community->val, attr->community->size * 4);
2400 }
2401
2402 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002403 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002404 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002405 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002406 {
2407 /* Originator ID. */
2408 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2409 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2410 stream_putc (s, 4);
2411
2412 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002413 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002414 else
2415 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002416
2417 /* Cluster list. */
2418 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2419 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2420
Paul Jakma9eda90c2007-08-30 13:36:17 +00002421 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002422 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002423 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002424 /* If this peer configuration's parent BGP has cluster_id. */
2425 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2426 stream_put_in_addr (s, &bgp->cluster_id);
2427 else
2428 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002429 stream_put (s, attr->extra->cluster->list,
2430 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002431 }
2432 else
2433 {
2434 stream_putc (s, 4);
2435 /* If this peer configuration's parent BGP has cluster_id. */
2436 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2437 stream_put_in_addr (s, &bgp->cluster_id);
2438 else
2439 stream_put_in_addr (s, &bgp->router_id);
2440 }
2441 }
2442
paul718e3742002-12-13 20:15:29 +00002443 /* Extended Communities attribute. */
2444 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2445 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2446 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002447 struct attr_extra *attre = attr->extra;
2448
2449 assert (attre);
2450
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002451 if (peer->sort == BGP_PEER_IBGP
2452 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002453 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002454 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002455 {
2456 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2457 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002458 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002459 }
2460 else
2461 {
2462 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2463 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002464 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002465 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002466 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002467 }
2468 else
2469 {
paul5228ad22004-06-04 17:58:18 +00002470 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002471 int tbit;
2472 int ecom_tr_size = 0;
2473 int i;
2474
Paul Jakmafb982c22007-05-04 20:15:47 +00002475 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002476 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002477 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002478 tbit = *pnt;
2479
2480 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2481 continue;
2482
2483 ecom_tr_size++;
2484 }
2485
2486 if (ecom_tr_size)
2487 {
2488 if (ecom_tr_size * 8 > 255)
2489 {
2490 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2491 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2492 stream_putw (s, ecom_tr_size * 8);
2493 }
2494 else
2495 {
2496 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2497 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2498 stream_putc (s, ecom_tr_size * 8);
2499 }
2500
Paul Jakmafb982c22007-05-04 20:15:47 +00002501 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002502 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002503 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002504 tbit = *pnt;
2505
2506 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2507 continue;
2508
2509 stream_put (s, pnt, 8);
2510 }
2511 }
paul718e3742002-12-13 20:15:29 +00002512 }
paul718e3742002-12-13 20:15:29 +00002513 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002514
2515 if ( send_as4_path )
2516 {
2517 /* If the peer is NOT As4 capable, AND */
2518 /* there are ASnums > 65535 in path THEN
2519 * give out AS4_PATH */
2520
2521 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2522 * path segments!
2523 * Hm, I wonder... confederation things *should* only be at
2524 * the beginning of an aspath, right? Then we should use
2525 * aspath_delete_confed_seq for this, because it is already
2526 * there! (JK)
2527 * Folks, talk to me: what is reasonable here!?
2528 */
2529 aspath = aspath_delete_confed_seq (aspath);
2530
2531 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2532 stream_putc (s, BGP_ATTR_AS4_PATH);
2533 aspath_sizep = stream_get_endp (s);
2534 stream_putw (s, 0);
2535 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2536 }
2537
2538 if (aspath != attr->aspath)
2539 aspath_free (aspath);
2540
2541 if ( send_as4_aggregator )
2542 {
2543 assert (attr->extra);
2544
2545 /* send AS4_AGGREGATOR, at this place */
2546 /* this section of code moved here in order to ensure the correct
2547 * *ascending* order of attributes
2548 */
2549 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2550 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2551 stream_putc (s, 8);
2552 stream_putl (s, attr->extra->aggregator_as);
2553 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2554 }
Paul Jakma41367172007-08-06 15:24:51 +00002555
paul718e3742002-12-13 20:15:29 +00002556 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002557 if (attr->extra && attr->extra->transit)
2558 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002559
2560 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002561 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002562}
2563
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002564size_t
2565bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002566{
paul718e3742002-12-13 20:15:29 +00002567 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002568
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002569 /* Set extended bit always to encode the attribute length as 2 bytes */
2570 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002571 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2572
paul9985f832005-02-09 15:51:56 +00002573 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002574 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002575
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002576 stream_putw (s, afi);
2577 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
2578 stream_putc (s, safi);
2579 return attrlen_pnt;
2580}
paul718e3742002-12-13 20:15:29 +00002581
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002582void
2583bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2584 afi_t afi, safi_t safi, struct prefix_rd *prd,
2585 u_char *tag)
2586{
paul718e3742002-12-13 20:15:29 +00002587 if (safi == SAFI_MPLS_VPN)
2588 {
paul718e3742002-12-13 20:15:29 +00002589 stream_putc (s, p->prefixlen + 88);
2590 stream_put (s, tag, 3);
2591 stream_put (s, prd->val, 8);
2592 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2593 }
2594 else
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002595 stream_put_prefix (s, p);
2596}
paul718e3742002-12-13 20:15:29 +00002597
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002598void
2599bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2600{
2601 bgp_size_t size;
paul718e3742002-12-13 20:15:29 +00002602
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002603 /* Set MP attribute length. Don't count the (2) bytes used to encode
2604 the attr length */
2605 size = stream_get_endp (s) - attrlen_pnt - 2;
2606 stream_putw_at (s, attrlen_pnt, size);
paul718e3742002-12-13 20:15:29 +00002607}
2608
2609/* Initialization of attribute. */
2610void
paulfe69a502005-09-10 16:55:02 +00002611bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002612{
paul718e3742002-12-13 20:15:29 +00002613 aspath_init ();
2614 attrhash_init ();
2615 community_init ();
2616 ecommunity_init ();
2617 cluster_init ();
2618 transit_init ();
2619}
2620
Chris Caputo228da422009-07-18 05:44:03 +00002621void
2622bgp_attr_finish (void)
2623{
2624 aspath_finish ();
2625 attrhash_finish ();
2626 community_finish ();
2627 ecommunity_finish ();
2628 cluster_finish ();
2629 transit_finish ();
2630}
2631
paul718e3742002-12-13 20:15:29 +00002632/* Make attribute packet. */
2633void
paula3845922003-10-18 01:30:50 +00002634bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2635 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00002636{
2637 unsigned long cp;
2638 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002639 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00002640 struct aspath *aspath;
2641
2642 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002643 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002644
2645 /* Place holder of length. */
2646 stream_putw (s, 0);
2647
2648 /* Origin attribute. */
2649 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2650 stream_putc (s, BGP_ATTR_ORIGIN);
2651 stream_putc (s, 1);
2652 stream_putc (s, attr->origin);
2653
2654 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002655
2656 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2657 stream_putc (s, BGP_ATTR_AS_PATH);
2658 aspath_lenp = stream_get_endp (s);
2659 stream_putw (s, 0);
2660
2661 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00002662
2663 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00002664 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2665 if(prefix != NULL
2666#ifdef HAVE_IPV6
2667 && prefix->family != AF_INET6
2668#endif /* HAVE_IPV6 */
2669 )
2670 {
2671 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2672 stream_putc (s, BGP_ATTR_NEXT_HOP);
2673 stream_putc (s, 4);
2674 stream_put_ipv4 (s, attr->nexthop.s_addr);
2675 }
paul718e3742002-12-13 20:15:29 +00002676
2677 /* MED attribute. */
2678 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2679 {
2680 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2681 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2682 stream_putc (s, 4);
2683 stream_putl (s, attr->med);
2684 }
2685
2686 /* Local preference. */
2687 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2688 {
2689 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2690 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2691 stream_putc (s, 4);
2692 stream_putl (s, attr->local_pref);
2693 }
2694
2695 /* Atomic aggregate. */
2696 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2697 {
2698 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2699 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2700 stream_putc (s, 0);
2701 }
2702
2703 /* Aggregator. */
2704 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2705 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002706 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00002707 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2708 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002709 stream_putc (s, 8);
2710 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00002711 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002712 }
2713
2714 /* Community attribute. */
2715 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2716 {
2717 if (attr->community->size * 4 > 255)
2718 {
2719 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2720 stream_putc (s, BGP_ATTR_COMMUNITIES);
2721 stream_putw (s, attr->community->size * 4);
2722 }
2723 else
2724 {
2725 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2726 stream_putc (s, BGP_ATTR_COMMUNITIES);
2727 stream_putc (s, attr->community->size * 4);
2728 }
2729 stream_put (s, attr->community->val, attr->community->size * 4);
2730 }
2731
paula3845922003-10-18 01:30:50 +00002732#ifdef HAVE_IPV6
2733 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002734 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2735 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00002736 {
2737 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00002738 struct attr_extra *attre = attr->extra;
2739
paula3845922003-10-18 01:30:50 +00002740 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2741 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00002742 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00002743
2744 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00002745 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00002746 stream_putw(s, AFI_IP6); /* AFI */
2747 stream_putc(s, SAFI_UNICAST); /* SAFI */
2748
2749 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002750 stream_putc(s, attre->mp_nexthop_len);
2751 stream_put(s, &attre->mp_nexthop_global, 16);
2752 if (attre->mp_nexthop_len == 32)
2753 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00002754
2755 /* SNPA */
2756 stream_putc(s, 0);
2757
2758 /* Prefix */
2759 stream_put_prefix(s, prefix);
2760
2761 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00002762 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00002763 }
2764#endif /* HAVE_IPV6 */
2765
paul718e3742002-12-13 20:15:29 +00002766 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002767 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00002768 stream_putw_at (s, cp, len);
2769}