blob: 3f0910319f3d7acb59f9ddaf0f18d9561da15477 [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};
David Lamparter6b0655a2014-06-04 06:53:35 +020075
Stephen Hemminger9bddac42009-05-15 09:59:51 -070076static struct hash *cluster_hash;
paul718e3742002-12-13 20:15:29 +000077
paul94f2b392005-06-28 12:44:16 +000078static void *
Paul Jakma923de652007-04-29 18:25:17 +000079cluster_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +000080{
Paul Jakma923de652007-04-29 18:25:17 +000081 struct cluster_list * val = (struct cluster_list *) p;
paul718e3742002-12-13 20:15:29 +000082 struct cluster_list *cluster;
83
84 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
85 cluster->length = val->length;
86
87 if (cluster->length)
88 {
89 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
90 memcpy (cluster->list, val->list, val->length);
91 }
92 else
93 cluster->list = NULL;
94
95 cluster->refcnt = 0;
96
97 return cluster;
98}
99
100/* Cluster list related functions. */
paul94f2b392005-06-28 12:44:16 +0000101static struct cluster_list *
paul5228ad22004-06-04 17:58:18 +0000102cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +0000103{
104 struct cluster_list tmp;
105 struct cluster_list *cluster;
106
107 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +0000108 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +0000109
110 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
111 cluster->refcnt++;
112 return cluster;
113}
114
115int
116cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
117{
118 int i;
119
120 for (i = 0; i < cluster->length / 4; i++)
121 if (cluster->list[i].s_addr == originator.s_addr)
122 return 1;
123 return 0;
124}
125
paul94f2b392005-06-28 12:44:16 +0000126static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000127cluster_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000128{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700129 const struct cluster_list *cluster = p;
paul718e3742002-12-13 20:15:29 +0000130
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700131 return jhash(cluster->list, cluster->length, 0);
paul718e3742002-12-13 20:15:29 +0000132}
133
paul94f2b392005-06-28 12:44:16 +0000134static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100135cluster_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000136{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100137 const struct cluster_list * cluster1 = p1;
138 const struct cluster_list * cluster2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000139
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100140 return (cluster1->length == cluster2->length &&
141 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000142}
143
paul94f2b392005-06-28 12:44:16 +0000144static void
paul718e3742002-12-13 20:15:29 +0000145cluster_free (struct cluster_list *cluster)
146{
147 if (cluster->list)
148 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
149 XFREE (MTYPE_CLUSTER, cluster);
150}
151
Chris Caputo228da422009-07-18 05:44:03 +0000152#if 0
paul94f2b392005-06-28 12:44:16 +0000153static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000154cluster_dup (struct cluster_list *cluster)
155{
156 struct cluster_list *new;
157
Stephen Hemminger393deb92008-08-18 14:13:29 -0700158 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
paul718e3742002-12-13 20:15:29 +0000159 new->length = cluster->length;
160
161 if (cluster->length)
162 {
163 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
164 memcpy (new->list, cluster->list, cluster->length);
165 }
166 else
167 new->list = NULL;
168
169 return new;
170}
Chris Caputo228da422009-07-18 05:44:03 +0000171#endif
paul718e3742002-12-13 20:15:29 +0000172
paul94f2b392005-06-28 12:44:16 +0000173static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000174cluster_intern (struct cluster_list *cluster)
175{
176 struct cluster_list *find;
177
178 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
179 find->refcnt++;
180
181 return find;
182}
183
184void
185cluster_unintern (struct cluster_list *cluster)
186{
paul718e3742002-12-13 20:15:29 +0000187 if (cluster->refcnt)
188 cluster->refcnt--;
189
190 if (cluster->refcnt == 0)
191 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400192 hash_release (cluster_hash, cluster);
paul718e3742002-12-13 20:15:29 +0000193 cluster_free (cluster);
194 }
195}
196
paul94f2b392005-06-28 12:44:16 +0000197static void
198cluster_init (void)
paul718e3742002-12-13 20:15:29 +0000199{
200 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
201}
Chris Caputo228da422009-07-18 05:44:03 +0000202
203static void
204cluster_finish (void)
205{
206 hash_free (cluster_hash);
207 cluster_hash = NULL;
208}
David Lamparter6b0655a2014-06-04 06:53:35 +0200209
paul718e3742002-12-13 20:15:29 +0000210/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700211static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000212
paul94f2b392005-06-28 12:44:16 +0000213static void
paul718e3742002-12-13 20:15:29 +0000214transit_free (struct transit *transit)
215{
216 if (transit->val)
217 XFREE (MTYPE_TRANSIT_VAL, transit->val);
218 XFREE (MTYPE_TRANSIT, transit);
219}
220
Paul Jakma923de652007-04-29 18:25:17 +0000221
paul94f2b392005-06-28 12:44:16 +0000222static void *
Paul Jakma923de652007-04-29 18:25:17 +0000223transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000224{
225 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000226 return p;
paul718e3742002-12-13 20:15:29 +0000227}
228
paul94f2b392005-06-28 12:44:16 +0000229static struct transit *
paul718e3742002-12-13 20:15:29 +0000230transit_intern (struct transit *transit)
231{
232 struct transit *find;
233
234 find = hash_get (transit_hash, transit, transit_hash_alloc);
235 if (find != transit)
236 transit_free (transit);
237 find->refcnt++;
238
239 return find;
240}
241
242void
243transit_unintern (struct transit *transit)
244{
paul718e3742002-12-13 20:15:29 +0000245 if (transit->refcnt)
246 transit->refcnt--;
247
248 if (transit->refcnt == 0)
249 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400250 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000251 transit_free (transit);
252 }
253}
254
paul94f2b392005-06-28 12:44:16 +0000255static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000256transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000257{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700258 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000259
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700260 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000261}
262
paul94f2b392005-06-28 12:44:16 +0000263static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100264transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000265{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100266 const struct transit * transit1 = p1;
267 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000268
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100269 return (transit1->length == transit2->length &&
270 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000271}
272
paul94f2b392005-06-28 12:44:16 +0000273static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800274transit_init (void)
paul718e3742002-12-13 20:15:29 +0000275{
276 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
277}
Chris Caputo228da422009-07-18 05:44:03 +0000278
279static void
280transit_finish (void)
281{
282 hash_free (transit_hash);
283 transit_hash = NULL;
284}
David Lamparter6b0655a2014-06-04 06:53:35 +0200285
paul718e3742002-12-13 20:15:29 +0000286/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700287static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000288
Paul Jakmafb982c22007-05-04 20:15:47 +0000289static struct attr_extra *
290bgp_attr_extra_new (void)
291{
292 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
293}
294
295void
296bgp_attr_extra_free (struct attr *attr)
297{
298 if (attr->extra)
299 {
300 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
301 attr->extra = NULL;
302 }
303}
304
305struct attr_extra *
306bgp_attr_extra_get (struct attr *attr)
307{
308 if (!attr->extra)
309 attr->extra = bgp_attr_extra_new();
310 return attr->extra;
311}
312
313/* Shallow copy of an attribute
314 * Though, not so shallow that it doesn't copy the contents
315 * of the attr_extra pointed to by 'extra'
316 */
317void
318bgp_attr_dup (struct attr *new, struct attr *orig)
319{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000320 struct attr_extra *extra = new->extra;
321
Paul Jakmafb982c22007-05-04 20:15:47 +0000322 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000323 /* if caller provided attr_extra space, use it in any case.
324 *
325 * This is neccesary even if orig->extra equals NULL, because otherwise
326 * memory may be later allocated on the heap by bgp_attr_extra_get.
327 *
328 * That memory would eventually be leaked, because the caller must not
329 * call bgp_attr_extra_free if he provided attr_extra on the stack.
330 */
331 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000332 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000333 new->extra = extra;
334 memset(new->extra, 0, sizeof(struct attr_extra));
335 if (orig->extra)
336 *new->extra = *orig->extra;
337 }
338 else if (orig->extra)
339 {
340 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000341 *new->extra = *orig->extra;
342 }
343}
344
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000345unsigned long int
346attr_count (void)
347{
348 return attrhash->count;
349}
350
351unsigned long int
352attr_unknown_count (void)
353{
354 return transit_hash->count;
355}
356
paul718e3742002-12-13 20:15:29 +0000357unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000358attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000359{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000360 const struct attr *attr = (struct attr *) p;
361 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700362 uint32_t key = 0;
363#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000364
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700365 MIX(attr->origin);
366 MIX(attr->nexthop.s_addr);
367 MIX(attr->med);
368 MIX(attr->local_pref);
369
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000370 key += attr->origin;
371 key += attr->nexthop.s_addr;
372 key += attr->med;
373 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000374
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000375 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000376 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000377 MIX(extra->aggregator_as);
378 MIX(extra->aggregator_addr.s_addr);
379 MIX(extra->weight);
380 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000381 MIX(extra->originator_id.s_addr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000382 }
383
paul718e3742002-12-13 20:15:29 +0000384 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700385 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000386 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700387 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000388
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000389 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000390 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000391 if (extra->ecommunity)
392 MIX(ecommunity_hash_make (extra->ecommunity));
393 if (extra->cluster)
394 MIX(cluster_hash_key_make (extra->cluster));
395 if (extra->transit)
396 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000397
398#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000399 MIX(extra->mp_nexthop_len);
400 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
401 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
paul718e3742002-12-13 20:15:29 +0000402#endif /* HAVE_IPV6 */
Paul Jakmafb982c22007-05-04 20:15:47 +0000403 }
paul718e3742002-12-13 20:15:29 +0000404
405 return key;
406}
407
408int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100409attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000410{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100411 const struct attr * attr1 = p1;
412 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000413
paul718e3742002-12-13 20:15:29 +0000414 if (attr1->flag == attr2->flag
415 && attr1->origin == attr2->origin
416 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000417 && attr1->aspath == attr2->aspath
418 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000419 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000420 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000421 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100422 const struct attr_extra *ae1 = attr1->extra;
423 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000424
425 if (ae1 && ae2
426 && ae1->aggregator_as == ae2->aggregator_as
427 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
428 && ae1->weight == ae2->weight
429#ifdef HAVE_IPV6
430 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
431 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
432 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
433#endif /* HAVE_IPV6 */
434 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
435 && ae1->ecommunity == ae2->ecommunity
436 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000437 && ae1->transit == ae2->transit
438 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000439 return 1;
440 else if (ae1 || ae2)
441 return 0;
442 /* neither attribute has extra attributes, so they're same */
443 return 1;
444 }
paul718e3742002-12-13 20:15:29 +0000445 else
446 return 0;
447}
448
paul94f2b392005-06-28 12:44:16 +0000449static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100450attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000451{
452 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
453}
454
paul94f2b392005-06-28 12:44:16 +0000455static void
Chris Caputo228da422009-07-18 05:44:03 +0000456attrhash_finish (void)
457{
458 hash_free (attrhash);
459 attrhash = NULL;
460}
461
462static void
paul718e3742002-12-13 20:15:29 +0000463attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
464{
465 struct attr *attr = backet->data;
466
467 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
468 inet_ntoa (attr->nexthop), VTY_NEWLINE);
469}
470
471void
472attr_show_all (struct vty *vty)
473{
474 hash_iterate (attrhash,
475 (void (*)(struct hash_backet *, void *))
476 attr_show_all_iterator,
477 vty);
478}
479
paul94f2b392005-06-28 12:44:16 +0000480static void *
Paul Jakma923de652007-04-29 18:25:17 +0000481bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000482{
Paul Jakma923de652007-04-29 18:25:17 +0000483 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000484 struct attr *attr;
485
486 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
487 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000488 if (val->extra)
489 {
490 attr->extra = bgp_attr_extra_new ();
491 *attr->extra = *val->extra;
492 }
paul718e3742002-12-13 20:15:29 +0000493 attr->refcnt = 0;
494 return attr;
495}
496
497/* Internet argument attribute. */
498struct attr *
499bgp_attr_intern (struct attr *attr)
500{
501 struct attr *find;
502
503 /* Intern referenced strucutre. */
504 if (attr->aspath)
505 {
506 if (! attr->aspath->refcnt)
507 attr->aspath = aspath_intern (attr->aspath);
508 else
509 attr->aspath->refcnt++;
510 }
511 if (attr->community)
512 {
513 if (! attr->community->refcnt)
514 attr->community = community_intern (attr->community);
515 else
516 attr->community->refcnt++;
517 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000518 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000519 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000520 struct attr_extra *attre = attr->extra;
521
522 if (attre->ecommunity)
523 {
524 if (! attre->ecommunity->refcnt)
525 attre->ecommunity = ecommunity_intern (attre->ecommunity);
526 else
527 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000528
Paul Jakmafb982c22007-05-04 20:15:47 +0000529 }
530 if (attre->cluster)
531 {
532 if (! attre->cluster->refcnt)
533 attre->cluster = cluster_intern (attre->cluster);
534 else
535 attre->cluster->refcnt++;
536 }
537 if (attre->transit)
538 {
539 if (! attre->transit->refcnt)
540 attre->transit = transit_intern (attre->transit);
541 else
542 attre->transit->refcnt++;
543 }
paul718e3742002-12-13 20:15:29 +0000544 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000545
paul718e3742002-12-13 20:15:29 +0000546 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
547 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000548
paul718e3742002-12-13 20:15:29 +0000549 return find;
550}
551
Paul Jakma03e214c2007-04-29 18:31:07 +0000552
paul718e3742002-12-13 20:15:29 +0000553/* Make network statement's attribute. */
554struct attr *
555bgp_attr_default_set (struct attr *attr, u_char origin)
556{
557 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000558 bgp_attr_extra_get (attr);
559
paul718e3742002-12-13 20:15:29 +0000560 attr->origin = origin;
561 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
562 attr->aspath = aspath_empty ();
563 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000564 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000565 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
566#ifdef HAVE_IPV6
Paul Jakmafb982c22007-05-04 20:15:47 +0000567 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000568#endif
Paul Jakma03e214c2007-04-29 18:31:07 +0000569
paul718e3742002-12-13 20:15:29 +0000570 return attr;
571}
572
Paul Jakma03e214c2007-04-29 18:31:07 +0000573
paul718e3742002-12-13 20:15:29 +0000574/* Make network statement's attribute. */
575struct attr *
576bgp_attr_default_intern (u_char origin)
577{
578 struct attr attr;
579 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000580
Paul Jakma03e214c2007-04-29 18:31:07 +0000581 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000582
583 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000584 bgp_attr_extra_free (&attr);
585
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000586 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000587 return new;
588}
589
590struct attr *
591bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
592 struct aspath *aspath,
593 struct community *community, int as_set)
594{
595 struct attr attr;
596 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000597 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000598
599 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000600 memset (&attre, 0, sizeof (struct attr_extra));
601 attr.extra = &attre;
602
paul718e3742002-12-13 20:15:29 +0000603 /* Origin attribute. */
604 attr.origin = origin;
605 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
606
607 /* AS path attribute. */
608 if (aspath)
609 attr.aspath = aspath_intern (aspath);
610 else
611 attr.aspath = aspath_empty ();
612 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
613
614 /* Next hop attribute. */
615 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
616
617 if (community)
618 {
619 attr.community = community;
620 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
621 }
622
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000623 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000624#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000625 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000626#endif
627 if (! as_set)
628 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
629 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
630 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000631 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000632 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000633 attre.aggregator_as = bgp->as;
634 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000635
636 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000637
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000638 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000639 return new;
640}
641
Paul Jakmab881c702010-11-23 16:35:42 +0000642/* Unintern just the sub-components of the attr, but not the attr */
643void
644bgp_attr_unintern_sub (struct attr *attr)
645{
646 /* aspath refcount shoud be decrement. */
647 if (attr->aspath)
648 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000649 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000650
651 if (attr->community)
652 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000653 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000654
655 if (attr->extra)
656 {
657 if (attr->extra->ecommunity)
658 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000659 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000660
661 if (attr->extra->cluster)
662 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000663 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000664
665 if (attr->extra->transit)
666 transit_unintern (attr->extra->transit);
667 }
668}
669
paul718e3742002-12-13 20:15:29 +0000670/* Free bgp attribute and aspath. */
671void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000672bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000673{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000674 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000675 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000676 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000677 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000678
paul718e3742002-12-13 20:15:29 +0000679 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000680 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000681
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000682 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000683
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000684 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000685 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000686 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000687 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000688 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000689
paul718e3742002-12-13 20:15:29 +0000690 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000691 if (attr->refcnt == 0)
692 {
693 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000694 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000695 bgp_attr_extra_free (attr);
696 XFREE (MTYPE_ATTR, attr);
697 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000698 }
699
Paul Jakmab881c702010-11-23 16:35:42 +0000700 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000701}
702
703void
704bgp_attr_flush (struct attr *attr)
705{
706 if (attr->aspath && ! attr->aspath->refcnt)
707 aspath_free (attr->aspath);
708 if (attr->community && ! attr->community->refcnt)
709 community_free (attr->community);
Paul Jakmafb982c22007-05-04 20:15:47 +0000710 if (attr->extra)
711 {
712 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000713
Paul Jakmafb982c22007-05-04 20:15:47 +0000714 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000715 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000716 if (attre->cluster && ! attre->cluster->refcnt)
717 cluster_free (attre->cluster);
718 if (attre->transit && ! attre->transit->refcnt)
719 transit_free (attre->transit);
720 }
paul718e3742002-12-13 20:15:29 +0000721}
722
Paul Jakmab881c702010-11-23 16:35:42 +0000723/* Implement draft-scudder-idr-optional-transitive behaviour and
724 * avoid resetting sessions for malformed attributes which are
725 * are partial/optional and hence where the error likely was not
726 * introduced by the sending neighbour.
727 */
728static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000729bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
730 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000731{
Paul Jakma835315b2012-01-18 12:28:30 +0000732 struct peer *const peer = args->peer;
733 const u_int8_t flags = args->flags;
734 /* startp and length must be special-cased, as whether or not to
735 * send the attribute data with the NOTIFY depends on the error,
736 * the caller therefore signals this with the seperate length argument
737 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000738 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000739
Paul Jakmab881c702010-11-23 16:35:42 +0000740 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000741 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000742 {
743 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000744 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000745 return BGP_ATTR_PARSE_ERROR;
746
747 }
748
Paul Jakmabd471fe2012-03-15 11:30:00 +0000749 /* Adjust the stream getp to the end of the attribute, in case we can
750 * still proceed but the caller hasn't read all the attribute.
751 */
752 stream_set_getp (BGP_INPUT (peer),
753 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
754 + args->total);
755
Paul Jakma835315b2012-01-18 12:28:30 +0000756 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100757 /* where an attribute is relatively inconsequential, e.g. it does not
758 * affect route selection, and can be safely ignored, then any such
759 * attributes which are malformed should just be ignored and the route
760 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000761 */
762 case BGP_ATTR_AS4_AGGREGATOR:
763 case BGP_ATTR_AGGREGATOR:
764 case BGP_ATTR_ATOMIC_AGGREGATE:
765 return BGP_ATTR_PARSE_PROCEED;
766
767 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100768 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000769 */
770 case BGP_ATTR_ORIGIN:
771 case BGP_ATTR_AS_PATH:
772 case BGP_ATTR_NEXT_HOP:
773 case BGP_ATTR_MULTI_EXIT_DISC:
774 case BGP_ATTR_LOCAL_PREF:
775 case BGP_ATTR_COMMUNITIES:
776 case BGP_ATTR_ORIGINATOR_ID:
777 case BGP_ATTR_CLUSTER_LIST:
778 case BGP_ATTR_MP_REACH_NLRI:
779 case BGP_ATTR_MP_UNREACH_NLRI:
780 case BGP_ATTR_EXT_COMMUNITIES:
781 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000782 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000783 return BGP_ATTR_PARSE_ERROR;
784 }
785
786 /* Partial optional attributes that are malformed should not cause
787 * the whole session to be reset. Instead treat it as a withdrawal
788 * of the routes, if possible.
789 */
Paul Jakma835315b2012-01-18 12:28:30 +0000790 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
791 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
792 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000793 return BGP_ATTR_PARSE_WITHDRAW;
794
795 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200796 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000797}
798
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400799/* Find out what is wrong with the path attribute flag bits and log the error.
800 "Flag bits" here stand for Optional, Transitive and Partial, but not for
801 Extended Length. Checking O/T/P bits at once implies, that the attribute
802 being diagnosed is defined by RFC as either a "well-known" or an "optional,
803 non-transitive" attribute. */
804static void
Paul Jakma835315b2012-01-18 12:28:30 +0000805bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
806 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400807)
808{
809 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000810 u_char real_flags = args->flags;
811 const u_int8_t attr_code = args->type;
812
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400813 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
814 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
815 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
816 if
817 (
818 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
819 CHECK_FLAG (real_flags, attr_flag_str[i].key)
820 )
821 {
Paul Jakma835315b2012-01-18 12:28:30 +0000822 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400823 LOOKUP (attr_str, attr_code),
824 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
825 attr_flag_str[i].str);
826 seen = 1;
827 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100828 if (!seen)
829 {
830 zlog (args->peer->log, LOG_DEBUG,
831 "Strange, %s called for attr %s, but no problem found with flags"
832 " (real flags 0x%x, desired 0x%x)",
833 __func__, LOOKUP (attr_str, attr_code),
834 real_flags, desired_flags);
835 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400836}
837
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000838/* Required flags for attributes. EXTLEN will be masked off when testing,
839 * as will PARTIAL for optional+transitive attributes.
840 */
841const u_int8_t attr_flags_values [] = {
842 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
843 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
844 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
845 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
846 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
847 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
848 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
849 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
850 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
851 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
852 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
853 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
854 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
855 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
856 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
857};
858static const size_t attr_flags_values_max =
859 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
860
861static int
Paul Jakma835315b2012-01-18 12:28:30 +0000862bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000863{
864 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +0000865 const u_int8_t flags = args->flags;
866 const u_int8_t attr_code = args->type;
867 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000868
869 /* there may be attributes we don't know about */
870 if (attr_code > attr_flags_values_max)
871 return 0;
872 if (attr_flags_values[attr_code] == 0)
873 return 0;
874
875 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
876 * 1."
877 */
878 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
879 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
880 {
881 zlog (peer->log, LOG_ERR,
882 "%s well-known attributes must have transitive flag set (%x)",
883 LOOKUP (attr_str, attr_code), flags);
884 return 1;
885 }
886
887 /* "For well-known attributes and for optional non-transitive attributes,
888 * the Partial bit MUST be set to 0."
889 */
890 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
891 {
892 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
893 {
894 zlog (peer->log, LOG_ERR,
895 "%s well-known attribute "
896 "must NOT have the partial flag set (%x)",
897 LOOKUP (attr_str, attr_code), flags);
898 return 1;
899 }
900 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
901 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
902 {
903 zlog (peer->log, LOG_ERR,
904 "%s optional + transitive attribute "
905 "must NOT have the partial flag set (%x)",
906 LOOKUP (attr_str, attr_code), flags);
907 return 1;
908 }
909 }
910
911 /* Optional transitive attributes may go through speakers that don't
912 * reocgnise them and set the Partial bit.
913 */
914 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
915 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
916 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
917
Paul Jakma683f2b82012-03-23 14:58:45 +0000918 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000919 == attr_flags_values[attr_code])
920 return 0;
921
Paul Jakma835315b2012-01-18 12:28:30 +0000922 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000923 return 1;
924}
925
paul718e3742002-12-13 20:15:29 +0000926/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +0000927static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000928bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000929{
Paul Jakma835315b2012-01-18 12:28:30 +0000930 struct peer *const peer = args->peer;
931 struct attr *const attr = args->attr;
932 const bgp_size_t length = args->length;
933
paul718e3742002-12-13 20:15:29 +0000934 /* If any recognized attribute has Attribute Length that conflicts
935 with the expected length (based on the attribute type code), then
936 the Error Subcode is set to Attribute Length Error. The Data
937 field contains the erroneous attribute (type, length and
938 value). */
939 if (length != 1)
940 {
941 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
942 length);
Paul Jakma835315b2012-01-18 12:28:30 +0000943 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000944 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +0000945 args->total);
paul718e3742002-12-13 20:15:29 +0000946 }
947
948 /* Fetch origin attribute. */
949 attr->origin = stream_getc (BGP_INPUT (peer));
950
951 /* If the ORIGIN attribute has an undefined value, then the Error
952 Subcode is set to Invalid Origin Attribute. The Data field
953 contains the unrecognized attribute (type, length and value). */
954 if ((attr->origin != BGP_ORIGIN_IGP)
955 && (attr->origin != BGP_ORIGIN_EGP)
956 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
957 {
958 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
959 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +0000960 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000961 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +0000962 args->total);
paul718e3742002-12-13 20:15:29 +0000963 }
964
965 /* Set oring attribute flag. */
966 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
967
968 return 0;
969}
Paul Jakmaab005292010-11-27 22:48:34 +0000970
971/* Parse AS path information. This function is wrapper of
972 aspath_parse. */
973static int
Paul Jakma835315b2012-01-18 12:28:30 +0000974bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000975{
Paul Jakma835315b2012-01-18 12:28:30 +0000976 struct attr *const attr = args->attr;
977 struct peer *const peer = args->peer;
978 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +0000979
Paul Jakmaab005292010-11-27 22:48:34 +0000980 /*
981 * peer with AS4 => will get 4Byte ASnums
982 * otherwise, will get 16 Bit
983 */
984 attr->aspath = aspath_parse (peer->ibuf, length,
985 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
986
987 /* In case of IBGP, length will be zero. */
988 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +0000989 {
Paul Jakmab881c702010-11-23 16:35:42 +0000990 zlog (peer->log, LOG_ERR,
991 "Malformed AS path from %s, length is %d",
992 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +0000993 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +0000994 }
Chris Hallcddb8112010-08-09 22:31:37 +0400995
Paul Jakmaab005292010-11-27 22:48:34 +0000996 /* Set aspath attribute flag. */
997 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +0000998
Paul Jakmab881c702010-11-23 16:35:42 +0000999 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001000}
1001
Paul Jakmab881c702010-11-23 16:35:42 +00001002static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001003bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001004{
1005 /* These checks were part of bgp_attr_aspath, but with
1006 * as4 we should to check aspath things when
1007 * aspath synthesizing with as4_path has already taken place.
1008 * Otherwise we check ASPATH and use the synthesized thing, and that is
1009 * not right.
1010 * So do the checks later, i.e. here
1011 */
1012 struct bgp *bgp = peer->bgp;
1013 struct aspath *aspath;
1014
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001015 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001016 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1017 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001018 {
1019 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001020 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1021 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1022 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001023 }
1024
paul718e3742002-12-13 20:15:29 +00001025 /* First AS check for EBGP. */
1026 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1027 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001028 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001029 && ! aspath_firstas_check (attr->aspath, peer->as))
1030 {
1031 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001032 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001033 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1034 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1035 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001036 }
1037 }
1038
1039 /* local-as prepend */
1040 if (peer->change_local_as &&
1041 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1042 {
1043 aspath = aspath_dup (attr->aspath);
1044 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001045 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001046 attr->aspath = aspath_intern (aspath);
1047 }
1048
Paul Jakmab881c702010-11-23 16:35:42 +00001049 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001050}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001051
Paul Jakmaab005292010-11-27 22:48:34 +00001052/* Parse AS4 path information. This function is another wrapper of
1053 aspath_parse. */
1054static int
Paul Jakma835315b2012-01-18 12:28:30 +00001055bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001056{
Paul Jakma835315b2012-01-18 12:28:30 +00001057 struct peer *const peer = args->peer;
1058 struct attr *const attr = args->attr;
1059 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001060
Paul Jakmaab005292010-11-27 22:48:34 +00001061 *as4_path = aspath_parse (peer->ibuf, length, 1);
1062
Paul Jakmab881c702010-11-23 16:35:42 +00001063 /* In case of IBGP, length will be zero. */
1064 if (!*as4_path)
1065 {
1066 zlog (peer->log, LOG_ERR,
1067 "Malformed AS4 path from %s, length is %d",
1068 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001069 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001070 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001071 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001072 }
1073
Paul Jakmaab005292010-11-27 22:48:34 +00001074 /* Set aspath attribute flag. */
1075 if (as4_path)
1076 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1077
Paul Jakmab881c702010-11-23 16:35:42 +00001078 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001079}
1080
paul718e3742002-12-13 20:15:29 +00001081/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001082static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001083bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001084{
Paul Jakma835315b2012-01-18 12:28:30 +00001085 struct peer *const peer = args->peer;
1086 struct attr *const attr = args->attr;
1087 const bgp_size_t length = args->length;
1088
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001089 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001090
paul718e3742002-12-13 20:15:29 +00001091 /* Check nexthop attribute length. */
1092 if (length != 4)
1093 {
1094 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1095 length);
1096
Paul Jakma835315b2012-01-18 12:28:30 +00001097 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001098 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001099 args->total);
paul718e3742002-12-13 20:15:29 +00001100 }
1101
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001102 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1103 attribute must result in a NOTIFICATION message (this is implemented below).
1104 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1105 logged locally (this is implemented somewhere else). The UPDATE message
1106 gets ignored in any of these cases. */
1107 nexthop_n = stream_get_ipv4 (peer->ibuf);
1108 nexthop_h = ntohl (nexthop_n);
1109 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1110 {
1111 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001112 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001113 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001114 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001115 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001116 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001117 }
1118
1119 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001120 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1121
Paul Jakmab881c702010-11-23 16:35:42 +00001122 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001123}
1124
1125/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001126static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001127bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001128{
Paul Jakma835315b2012-01-18 12:28:30 +00001129 struct peer *const peer = args->peer;
1130 struct attr *const attr = args->attr;
1131 const bgp_size_t length = args->length;
1132
paul718e3742002-12-13 20:15:29 +00001133 /* Length check. */
1134 if (length != 4)
1135 {
1136 zlog (peer->log, LOG_ERR,
1137 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001138
Paul Jakma835315b2012-01-18 12:28:30 +00001139 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001140 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001141 args->total);
paul718e3742002-12-13 20:15:29 +00001142 }
1143
1144 attr->med = stream_getl (peer->ibuf);
1145
1146 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1147
Paul Jakmab881c702010-11-23 16:35:42 +00001148 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001149}
1150
1151/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001152static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001153bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001154{
Paul Jakma835315b2012-01-18 12:28:30 +00001155 struct peer *const peer = args->peer;
1156 struct attr *const attr = args->attr;
1157 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001158
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001159 /* Length check. */
1160 if (length != 4)
1161 {
Paul Jakma835315b2012-01-18 12:28:30 +00001162 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1163 length);
1164 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001165 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001166 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001167 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001168
paul718e3742002-12-13 20:15:29 +00001169 /* If it is contained in an UPDATE message that is received from an
1170 external peer, then this attribute MUST be ignored by the
1171 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001172 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001173 {
paul9985f832005-02-09 15:51:56 +00001174 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001175 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001176 }
1177
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001178 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001179
1180 /* Set atomic aggregate flag. */
1181 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1182
Paul Jakmab881c702010-11-23 16:35:42 +00001183 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001184}
1185
1186/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001187static int
Paul Jakma835315b2012-01-18 12:28:30 +00001188bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001189{
Paul Jakma835315b2012-01-18 12:28:30 +00001190 struct peer *const peer = args->peer;
1191 struct attr *const attr = args->attr;
1192 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001193
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001194 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001195 if (length != 0)
1196 {
Paul Jakma835315b2012-01-18 12:28:30 +00001197 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1198 length);
1199 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001200 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001201 args->total);
paul718e3742002-12-13 20:15:29 +00001202 }
1203
1204 /* Set atomic aggregate flag. */
1205 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1206
Paul Jakmab881c702010-11-23 16:35:42 +00001207 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001208}
1209
1210/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001211static int
Paul Jakma835315b2012-01-18 12:28:30 +00001212bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001213{
Paul Jakma835315b2012-01-18 12:28:30 +00001214 struct peer *const peer = args->peer;
1215 struct attr *const attr = args->attr;
1216 const bgp_size_t length = args->length;
1217
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001218 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001219 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001220
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001221 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001222 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001223 wantedlen = 8;
1224
1225 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001226 {
Paul Jakma835315b2012-01-18 12:28:30 +00001227 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1228 wantedlen, length);
1229 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001230 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001231 args->total);
paul718e3742002-12-13 20:15:29 +00001232 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001233
1234 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1235 attre->aggregator_as = stream_getl (peer->ibuf);
1236 else
1237 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001238 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001239
1240 /* Set atomic aggregate flag. */
1241 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1242
Paul Jakmab881c702010-11-23 16:35:42 +00001243 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001244}
1245
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001246/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001247static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001248bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1249 as_t *as4_aggregator_as,
1250 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001251{
Paul Jakma835315b2012-01-18 12:28:30 +00001252 struct peer *const peer = args->peer;
1253 struct attr *const attr = args->attr;
1254 const bgp_size_t length = args->length;
1255
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001256 if (length != 8)
1257 {
Paul Jakma835315b2012-01-18 12:28:30 +00001258 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1259 length);
1260 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001261 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001262 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001263 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001264
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001265 *as4_aggregator_as = stream_getl (peer->ibuf);
1266 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1267
1268 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1269
Paul Jakmab881c702010-11-23 16:35:42 +00001270 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001271}
1272
1273/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1274 */
Paul Jakmab881c702010-11-23 16:35:42 +00001275static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001276bgp_attr_munge_as4_attrs (struct peer *const peer,
1277 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001278 struct aspath *as4_path, as_t as4_aggregator,
1279 struct in_addr *as4_aggregator_addr)
1280{
1281 int ignore_as4_path = 0;
1282 struct aspath *newpath;
1283 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001284
1285 if (!attr->aspath)
1286 {
1287 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1288 * checked that all well-known, mandatory attributes were present.
1289 *
1290 * Can only be a problem with peer itself - hard error
1291 */
1292 return BGP_ATTR_PARSE_ERROR;
1293 }
1294
Paul Jakmab881c702010-11-23 16:35:42 +00001295 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001296 {
1297 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1298 * if given.
1299 * It is worth a warning though, because the peer really
1300 * should not send them
1301 */
1302 if (BGP_DEBUG(as4, AS4))
1303 {
1304 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1305 zlog_debug ("[AS4] %s %s AS4_PATH",
1306 peer->host, "AS4 capable peer, yet it sent");
1307
1308 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1309 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1310 peer->host, "AS4 capable peer, yet it sent");
1311 }
1312
Paul Jakmab881c702010-11-23 16:35:42 +00001313 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001314 }
1315
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001316 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1317 * because that may override AS4_PATH
1318 */
1319 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1320 {
Paul Jakmab881c702010-11-23 16:35:42 +00001321 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001322 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001323 assert (attre);
1324
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001325 /* received both.
1326 * if the as_number in aggregator is not AS_TRANS,
1327 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1328 * and the Aggregator shall be taken as
1329 * info on the aggregating node, and the AS_PATH
1330 * shall be taken as the AS_PATH
1331 * otherwise
1332 * the Aggregator shall be ignored and the
1333 * AS4_AGGREGATOR shall be taken as the
1334 * Aggregating node and the AS_PATH is to be
1335 * constructed "as in all other cases"
1336 */
Paul Jakmab881c702010-11-23 16:35:42 +00001337 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001338 {
1339 /* ignore */
1340 if ( BGP_DEBUG(as4, AS4))
1341 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1342 " send AGGREGATOR != AS_TRANS and"
1343 " AS4_AGGREGATOR, so ignore"
1344 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1345 ignore_as4_path = 1;
1346 }
1347 else
1348 {
1349 /* "New_aggregator shall be taken as aggregator" */
1350 attre->aggregator_as = as4_aggregator;
1351 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1352 }
1353 }
1354 else
1355 {
1356 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1357 * That is bogus - but reading the conditions
1358 * we have to handle AS4_AGGREGATOR as if it were
1359 * AGGREGATOR in that case
1360 */
1361 if ( BGP_DEBUG(as4, AS4))
1362 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1363 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1364 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001365 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001366 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1367 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1368 }
1369 }
1370
1371 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001372 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001373 {
Paul Jakma055086f2014-09-23 15:23:01 +01001374 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1375 aspath_unintern (&attr->aspath);
1376 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001377 }
Paul Jakmab881c702010-11-23 16:35:42 +00001378 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001379}
1380
paul718e3742002-12-13 20:15:29 +00001381/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001382static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001383bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001384{
Paul Jakma835315b2012-01-18 12:28:30 +00001385 struct peer *const peer = args->peer;
1386 struct attr *const attr = args->attr;
1387 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001388
paul718e3742002-12-13 20:15:29 +00001389 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001390 {
1391 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001392 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001393 }
Paul Jakma0c466382010-12-05 17:17:26 +00001394
1395 attr->community =
1396 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1397
1398 /* XXX: fix community_parse to use stream API and remove this */
1399 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001400
Paul Jakma0c466382010-12-05 17:17:26 +00001401 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001402 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001403 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001404 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001405
paul718e3742002-12-13 20:15:29 +00001406 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1407
Paul Jakmab881c702010-11-23 16:35:42 +00001408 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001409}
1410
1411/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001412static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001413bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001414{
Paul Jakma835315b2012-01-18 12:28:30 +00001415 struct peer *const peer = args->peer;
1416 struct attr *const attr = args->attr;
1417 const bgp_size_t length = args->length;
1418
Denis Ovsienkod595b562011-09-30 15:08:54 +04001419 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001420 if (length != 4)
1421 {
1422 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1423
Paul Jakma835315b2012-01-18 12:28:30 +00001424 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001425 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001426 args->total);
paul718e3742002-12-13 20:15:29 +00001427 }
1428
Paul Jakmafb982c22007-05-04 20:15:47 +00001429 (bgp_attr_extra_get (attr))->originator_id.s_addr
1430 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001431
1432 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1433
Paul Jakmab881c702010-11-23 16:35:42 +00001434 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001435}
1436
1437/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001438static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001439bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001440{
Paul Jakma835315b2012-01-18 12:28:30 +00001441 struct peer *const peer = args->peer;
1442 struct attr *const attr = args->attr;
1443 const bgp_size_t length = args->length;
1444
paul718e3742002-12-13 20:15:29 +00001445 /* Check length. */
1446 if (length % 4)
1447 {
1448 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1449
Paul Jakma835315b2012-01-18 12:28:30 +00001450 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1451 args->total);
paul718e3742002-12-13 20:15:29 +00001452 }
1453
Paul Jakmafb982c22007-05-04 20:15:47 +00001454 (bgp_attr_extra_get (attr))->cluster
1455 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001456
1457 /* XXX: Fix cluster_parse to use stream API and then remove this */
1458 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001459
1460 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1461
Paul Jakmab881c702010-11-23 16:35:42 +00001462 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001463}
1464
1465/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001466int
Paul Jakma835315b2012-01-18 12:28:30 +00001467bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1468 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001469{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001470 afi_t afi;
1471 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001472 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001473 size_t start;
paul718e3742002-12-13 20:15:29 +00001474 int ret;
1475 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001476 struct peer *const peer = args->peer;
1477 struct attr *const attr = args->attr;
1478 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001479 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001480
paul718e3742002-12-13 20:15:29 +00001481 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001482 s = BGP_INPUT(peer);
1483 start = stream_get_getp(s);
1484
1485 /* safe to read statically sized header? */
1486#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001487#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001488 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001489 {
1490 zlog_info ("%s: %s sent invalid length, %lu",
1491 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001492 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001493 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001494
paul718e3742002-12-13 20:15:29 +00001495 /* Load AFI, SAFI. */
1496 afi = stream_getw (s);
1497 safi = stream_getc (s);
1498
1499 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001500 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001501
Paul Jakma03292802008-06-07 20:37:10 +00001502 if (LEN_LEFT < attre->mp_nexthop_len)
1503 {
1504 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1505 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001506 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001507 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001508
paul718e3742002-12-13 20:15:29 +00001509 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001510 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001511 {
1512 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001513 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001514 /* Probably needed for RFC 2283 */
1515 if (attr->nexthop.s_addr == 0)
1516 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001517 break;
1518 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001519 stream_getl (s); /* RD high */
1520 stream_getl (s); /* RD low */
1521 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001522 break;
1523#ifdef HAVE_IPV6
1524 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001525 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001526 break;
1527 case 32:
Paul Jakmafb982c22007-05-04 20:15:47 +00001528 stream_get (&attre->mp_nexthop_global, s, 16);
1529 stream_get (&attre->mp_nexthop_local, s, 16);
1530 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001531 {
1532 char buf1[INET6_ADDRSTRLEN];
1533 char buf2[INET6_ADDRSTRLEN];
1534
1535 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001536 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 +00001537 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001538 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001539 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001540 buf2, INET6_ADDRSTRLEN));
1541
Paul Jakmafb982c22007-05-04 20:15:47 +00001542 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001543 }
1544 break;
1545#endif /* HAVE_IPV6 */
1546 default:
Paul Jakma03292802008-06-07 20:37:10 +00001547 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1548 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001549 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001550 }
1551
Paul Jakma03292802008-06-07 20:37:10 +00001552 if (!LEN_LEFT)
1553 {
1554 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1555 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001556 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001557 }
paul718e3742002-12-13 20:15:29 +00001558
Paul Jakma6e4ab122007-04-10 19:36:48 +00001559 {
1560 u_char val;
1561 if ((val = stream_getc (s)))
1562 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1563 peer->host, val);
1564 }
1565
1566 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001567 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001568 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001569 {
1570 zlog_info ("%s: (%s) Failed to read NLRI",
1571 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001572 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001573 }
paul718e3742002-12-13 20:15:29 +00001574
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001575 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001576 {
1577 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
Paul Jakma03292802008-06-07 20:37:10 +00001578 if (ret < 0)
1579 {
1580 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1581 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001582 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001583 }
paul718e3742002-12-13 20:15:29 +00001584 }
1585
1586 mp_update->afi = afi;
1587 mp_update->safi = safi;
1588 mp_update->nlri = stream_pnt (s);
1589 mp_update->length = nlri_len;
1590
paul9985f832005-02-09 15:51:56 +00001591 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001592
David Lamparterdaefeb82014-12-08 17:42:12 +01001593 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1594
Paul Jakmab881c702010-11-23 16:35:42 +00001595 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001596#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001597}
1598
1599/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001600int
Paul Jakma835315b2012-01-18 12:28:30 +00001601bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001602 struct bgp_nlri *mp_withdraw)
1603{
1604 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001605 afi_t afi;
1606 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001607 u_int16_t withdraw_len;
1608 int ret;
Paul Jakma835315b2012-01-18 12:28:30 +00001609 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001610 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001611 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001612
1613 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001614
1615#define BGP_MP_UNREACH_MIN_SIZE 3
1616 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001617 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001618
paul718e3742002-12-13 20:15:29 +00001619 afi = stream_getw (s);
1620 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001621
1622 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001623
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001624 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001625 {
1626 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1627 if (ret < 0)
David Lamparterf57000c2014-06-04 01:01:10 +02001628 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001629 }
1630
1631 mp_withdraw->afi = afi;
1632 mp_withdraw->safi = safi;
1633 mp_withdraw->nlri = stream_pnt (s);
1634 mp_withdraw->length = withdraw_len;
1635
paul9985f832005-02-09 15:51:56 +00001636 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001637
David Lamparterdaefeb82014-12-08 17:42:12 +01001638 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1639
Paul Jakmab881c702010-11-23 16:35:42 +00001640 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001641}
1642
1643/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001644static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001645bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001646{
Paul Jakma835315b2012-01-18 12:28:30 +00001647 struct peer *const peer = args->peer;
1648 struct attr *const attr = args->attr;
1649 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001650
paul718e3742002-12-13 20:15:29 +00001651 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001652 {
1653 if (attr->extra)
1654 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001655 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001656 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001657 }
Paul Jakma0c466382010-12-05 17:17:26 +00001658
1659 (bgp_attr_extra_get (attr))->ecommunity =
1660 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1661 /* XXX: fix ecommunity_parse to use stream API */
1662 stream_forward_getp (peer->ibuf, length);
1663
1664 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001665 return bgp_attr_malformed (args,
1666 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1667 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001668
paul718e3742002-12-13 20:15:29 +00001669 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1670
Paul Jakmab881c702010-11-23 16:35:42 +00001671 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001672}
1673
1674/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001675static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001676bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001677{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001678 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001679 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001680 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001681 struct peer *const peer = args->peer;
1682 struct attr *const attr = args->attr;
1683 u_char *const startp = args->startp;
1684 const u_char type = args->type;
1685 const u_char flag = args->flags;
1686 const bgp_size_t length = args->length;
1687
paul718e3742002-12-13 20:15:29 +00001688
hassof4184462005-02-01 20:13:16 +00001689 if (BGP_DEBUG (normal, NORMAL))
1690 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1691 peer->host, type, length);
1692
paul718e3742002-12-13 20:15:29 +00001693 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001694 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001695 "Unknown attribute type %d length %d is received", type, length);
1696
1697 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001698 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001699
paul718e3742002-12-13 20:15:29 +00001700 /* If any of the mandatory well-known attributes are not recognized,
1701 then the Error Subcode is set to Unrecognized Well-known
1702 Attribute. The Data field contains the unrecognized attribute
1703 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001704 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001705 {
Paul Jakma835315b2012-01-18 12:28:30 +00001706 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001707 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001708 args->total);
paul718e3742002-12-13 20:15:29 +00001709 }
1710
1711 /* Unrecognized non-transitive optional attributes must be quietly
1712 ignored and not passed along to other BGP peers. */
1713 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001714 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001715
1716 /* If a path with recognized transitive optional attribute is
1717 accepted and passed along to other BGP peers and the Partial bit
1718 in the Attribute Flags octet is set to 1 by some previous AS, it
1719 is not set back to 0 by the current AS. */
1720 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1721
1722 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001723 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001724 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001725
Paul Jakmafb982c22007-05-04 20:15:47 +00001726 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001727
1728 if (transit->val)
1729 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1730 transit->length + total);
1731 else
1732 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1733
1734 memcpy (transit->val + transit->length, startp, total);
1735 transit->length += total;
1736
Paul Jakmab881c702010-11-23 16:35:42 +00001737 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001738}
1739
Paul Jakma055086f2014-09-23 15:23:01 +01001740/* Well-known attribute check. */
1741static int
1742bgp_attr_check (struct peer *peer, struct attr *attr)
1743{
1744 u_char type = 0;
1745
Paul Jakmaaed1b552014-10-21 16:59:01 +01001746 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
1747 * empty UPDATE. */
1748 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
1749 return BGP_ATTR_PARSE_PROCEED;
1750
1751 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
1752 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
1753 are present, it should. Check for any other attribute being present
1754 instead.
1755 */
1756 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
1757 return BGP_ATTR_PARSE_PROCEED;
1758
Paul Jakma055086f2014-09-23 15:23:01 +01001759 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1760 type = BGP_ATTR_ORIGIN;
1761
1762 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1763 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001764
1765 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
1766 * NLRI is empty. We can't easily check NLRI empty here though.
1767 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00001768 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
1769 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01001770 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001771
Paul Jakma055086f2014-09-23 15:23:01 +01001772 if (peer->sort == BGP_PEER_IBGP
1773 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1774 type = BGP_ATTR_LOCAL_PREF;
1775
1776 if (type)
1777 {
1778 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01001779 "%s Missing well-known attribute %d / %s",
1780 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01001781 bgp_notify_send_with_data (peer,
1782 BGP_NOTIFY_UPDATE_ERR,
1783 BGP_NOTIFY_UPDATE_MISS_ATTR,
1784 &type, 1);
1785 return BGP_ATTR_PARSE_ERROR;
1786 }
1787 return BGP_ATTR_PARSE_PROCEED;
1788}
1789
paul718e3742002-12-13 20:15:29 +00001790/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00001791 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00001792bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00001793bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1794 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1795{
1796 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00001797 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001798 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00001799 bgp_size_t length;
1800 u_char *startp, *endp;
1801 u_char *attr_endp;
1802 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001803 /* we need the as4_path only until we have synthesized the as_path with it */
1804 /* same goes for as4_aggregator */
1805 struct aspath *as4_path = NULL;
1806 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07001807 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00001808
1809 /* Initialize bitmap. */
1810 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1811
1812 /* End pointer of BGP attribute. */
1813 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00001814
paul718e3742002-12-13 20:15:29 +00001815 /* Get attributes to the end of attribute length. */
1816 while (BGP_INPUT_PNT (peer) < endp)
1817 {
1818 /* Check remaining length check.*/
1819 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1820 {
gdtc29fdba2004-12-09 14:46:46 +00001821 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00001822 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001823 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001824 peer->host,
1825 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00001826
1827 bgp_notify_send (peer,
1828 BGP_NOTIFY_UPDATE_ERR,
1829 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001830 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001831 }
1832
1833 /* Fetch attribute flag and type. */
1834 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04001835 /* "The lower-order four bits of the Attribute Flags octet are
1836 unused. They MUST be zero when sent and MUST be ignored when
1837 received." */
1838 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00001839 type = stream_getc (BGP_INPUT (peer));
1840
Paul Jakma370b64a2007-12-22 16:49:52 +00001841 /* Check whether Extended-Length applies and is in bounds */
1842 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1843 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1844 {
1845 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001846 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00001847 peer->host,
1848 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1849
1850 bgp_notify_send (peer,
1851 BGP_NOTIFY_UPDATE_ERR,
1852 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001853 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00001854 }
Paul Jakma835315b2012-01-18 12:28:30 +00001855
paul718e3742002-12-13 20:15:29 +00001856 /* Check extended attribue length bit. */
1857 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1858 length = stream_getw (BGP_INPUT (peer));
1859 else
1860 length = stream_getc (BGP_INPUT (peer));
1861
1862 /* If any attribute appears more than once in the UPDATE
1863 message, then the Error Subcode is set to Malformed Attribute
1864 List. */
1865
1866 if (CHECK_BITMAP (seen, type))
1867 {
1868 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001869 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00001870 peer->host, type);
1871
1872 bgp_notify_send (peer,
1873 BGP_NOTIFY_UPDATE_ERR,
1874 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00001875 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001876 }
1877
1878 /* Set type to bitmap to check duplicate attribute. `type' is
1879 unsigned char so it never overflow bitmap range. */
1880
1881 SET_BITMAP (seen, type);
1882
1883 /* Overflow check. */
1884 attr_endp = BGP_INPUT_PNT (peer) + length;
1885
1886 if (attr_endp > endp)
1887 {
1888 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001889 "%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 +00001890 bgp_notify_send (peer,
1891 BGP_NOTIFY_UPDATE_ERR,
1892 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001893 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001894 }
Paul Jakma835315b2012-01-18 12:28:30 +00001895
1896 struct bgp_attr_parser_args attr_args = {
1897 .peer = peer,
1898 .length = length,
1899 .attr = attr,
1900 .type = type,
1901 .flags = flag,
1902 .startp = startp,
1903 .total = attr_endp - startp,
1904 };
1905
1906
1907 /* If any recognized attribute has Attribute Flags that conflict
1908 with the Attribute Type Code, then the Error Subcode is set to
1909 Attribute Flags Error. The Data field contains the erroneous
1910 attribute (type, length and value). */
1911 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01001912 {
1913 bgp_attr_parse_ret_t ret;
1914 ret = bgp_attr_malformed (&attr_args,
1915 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1916 attr_args.total);
1917 if (ret == BGP_ATTR_PARSE_PROCEED)
1918 continue;
1919 return ret;
1920 }
paul718e3742002-12-13 20:15:29 +00001921
1922 /* OK check attribute and store it's value. */
1923 switch (type)
1924 {
1925 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00001926 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00001927 break;
1928 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001929 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00001930 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001931 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001932 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001933 break;
paul718e3742002-12-13 20:15:29 +00001934 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00001935 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00001936 break;
1937 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00001938 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00001939 break;
1940 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00001941 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00001942 break;
1943 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00001944 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00001945 break;
1946 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001947 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00001948 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001949 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001950 ret = bgp_attr_as4_aggregator (&attr_args,
1951 &as4_aggregator,
1952 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001953 break;
paul718e3742002-12-13 20:15:29 +00001954 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001955 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00001956 break;
1957 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00001958 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00001959 break;
1960 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00001961 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00001962 break;
1963 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001964 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00001965 break;
1966 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001967 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00001968 break;
1969 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001970 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00001971 break;
1972 default:
Paul Jakma835315b2012-01-18 12:28:30 +00001973 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00001974 break;
1975 }
Paul Jakmab881c702010-11-23 16:35:42 +00001976
David Lamparterf57000c2014-06-04 01:01:10 +02001977 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
1978 {
1979 bgp_notify_send (peer,
1980 BGP_NOTIFY_UPDATE_ERR,
1981 BGP_NOTIFY_UPDATE_MAL_ATTR);
1982 ret = BGP_ATTR_PARSE_ERROR;
1983 }
1984
Paul Jakmab881c702010-11-23 16:35:42 +00001985 /* If hard error occured immediately return to the caller. */
1986 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00001987 {
1988 zlog (peer->log, LOG_WARNING,
1989 "%s: Attribute %s, parse error",
1990 peer->host,
1991 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00001992 if (as4_path)
1993 aspath_unintern (&as4_path);
1994 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001995 }
Paul Jakmab881c702010-11-23 16:35:42 +00001996 if (ret == BGP_ATTR_PARSE_WITHDRAW)
1997 {
1998
1999 zlog (peer->log, LOG_WARNING,
2000 "%s: Attribute %s, parse error - treating as withdrawal",
2001 peer->host,
2002 LOOKUP (attr_str, type));
2003 if (as4_path)
2004 aspath_unintern (&as4_path);
2005 return ret;
2006 }
2007
paul718e3742002-12-13 20:15:29 +00002008 /* Check the fetched length. */
2009 if (BGP_INPUT_PNT (peer) != attr_endp)
2010 {
2011 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002012 "%s: BGP attribute %s, fetch error",
2013 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002014 bgp_notify_send (peer,
2015 BGP_NOTIFY_UPDATE_ERR,
2016 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002017 if (as4_path)
2018 aspath_unintern (&as4_path);
2019 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002020 }
2021 }
paul718e3742002-12-13 20:15:29 +00002022 /* Check final read pointer is same as end pointer. */
2023 if (BGP_INPUT_PNT (peer) != endp)
2024 {
2025 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002026 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002027 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002028 bgp_notify_send (peer,
2029 BGP_NOTIFY_UPDATE_ERR,
2030 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002031 if (as4_path)
2032 aspath_unintern (&as4_path);
2033 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002034 }
Paul Jakma055086f2014-09-23 15:23:01 +01002035
2036 /* Check all mandatory well-known attributes are present */
2037 {
2038 bgp_attr_parse_ret_t ret;
2039 if ((ret = bgp_attr_check (peer, attr)) < 0)
2040 {
2041 if (as4_path)
2042 aspath_unintern (&as4_path);
2043 return ret;
2044 }
2045 }
2046
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002047 /*
2048 * At this place we can see whether we got AS4_PATH and/or
2049 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2050 * We can not do this before we've read all attributes because
2051 * the as4 handling does not say whether AS4_PATH has to be sent
2052 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2053 * in relationship to AGGREGATOR.
2054 * So, to be defensive, we are not relying on any order and read
2055 * all attributes first, including these 32bit ones, and now,
2056 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002057 *
2058 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2059 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002060 */
David Lamparterf57000c2014-06-04 01:01:10 +02002061 /* actually... this doesn't ever return failure currently, but
2062 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002063 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2064 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002065 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002066 {
David Lamparterf57000c2014-06-04 01:01:10 +02002067 bgp_notify_send (peer,
2068 BGP_NOTIFY_UPDATE_ERR,
2069 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002070 if (as4_path)
2071 aspath_unintern (&as4_path);
2072 return BGP_ATTR_PARSE_ERROR;
2073 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002074
2075 /* At this stage, we have done all fiddling with as4, and the
2076 * resulting info is in attr->aggregator resp. attr->aspath
2077 * so we can chuck as4_aggregator and as4_path alltogether in
2078 * order to save memory
2079 */
Paul Jakmab881c702010-11-23 16:35:42 +00002080 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002081 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002082 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002083 /* The flag that we got this is still there, but that does not
2084 * do any trouble
2085 */
2086 }
2087 /*
2088 * The "rest" of the code does nothing with as4_aggregator.
2089 * there is no memory attached specifically which is not part
2090 * of the attr.
2091 * so ignoring just means do nothing.
2092 */
2093 /*
2094 * Finally do the checks on the aspath we did not do yet
2095 * because we waited for a potentially synthesized aspath.
2096 */
Paul Jakmab881c702010-11-23 16:35:42 +00002097 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002098 {
Paul Jakma835315b2012-01-18 12:28:30 +00002099 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002100 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002101 return ret;
2102 }
2103
paul718e3742002-12-13 20:15:29 +00002104 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002105 if (attr->extra && attr->extra->transit)
2106 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002107
Paul Jakmab881c702010-11-23 16:35:42 +00002108 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002109}
2110
paul718e3742002-12-13 20:15:29 +00002111int stream_put_prefix (struct stream *, struct prefix *);
2112
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002113size_t
2114bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2115 struct attr *attr)
2116{
2117 size_t sizep;
2118
2119 /* Set extended bit always to encode the attribute length as 2 bytes */
2120 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2121 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2122 sizep = stream_get_endp (s);
2123 stream_putw (s, 0); /* Marker: Attribute length. */
2124 stream_putw (s, afi); /* AFI */
2125 stream_putc (s, safi); /* SAFI */
2126
2127 /* Nexthop */
2128 switch (afi)
2129 {
2130 case AFI_IP:
2131 switch (safi)
2132 {
2133 case SAFI_UNICAST:
2134 case SAFI_MULTICAST:
2135 stream_putc (s, 4);
2136 stream_put_ipv4 (s, attr->nexthop.s_addr);
2137 break;
2138 case SAFI_MPLS_VPN:
2139 stream_putc (s, 12);
2140 stream_putl (s, 0);
2141 stream_putl (s, 0);
2142 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2143 break;
2144 default:
2145 break;
2146 }
2147 break;
2148#ifdef HAVE_IPV6
2149 case AFI_IP6:
2150 switch (safi)
2151 {
2152 case SAFI_UNICAST:
2153 case SAFI_MULTICAST:
2154 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002155 struct attr_extra *attre = attr->extra;
2156
2157 assert (attr->extra);
2158 stream_putc (s, attre->mp_nexthop_len);
2159 stream_put (s, &attre->mp_nexthop_global, 16);
2160 if (attre->mp_nexthop_len == 32)
2161 stream_put (s, &attre->mp_nexthop_local, 16);
2162 }
2163 default:
2164 break;
2165 }
2166 break;
2167#endif /*HAVE_IPV6*/
2168 default:
2169 break;
2170 }
2171
2172 /* SNPA */
2173 stream_putc (s, 0);
2174 return sizep;
2175}
2176
2177void
2178bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2179 struct prefix *p, struct prefix_rd *prd,
2180 u_char *tag)
2181{
2182 switch (safi)
2183 {
2184 case SAFI_MPLS_VPN:
2185 /* Tag, RD, Prefix write. */
2186 stream_putc (s, p->prefixlen + 88);
2187 stream_put (s, tag, 3);
2188 stream_put (s, prd->val, 8);
2189 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2190 break;
2191 default:
2192 /* Prefix write. */
2193 stream_put_prefix (s, p);
2194 break;
2195 }
2196}
2197
2198void
2199bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2200{
2201 /* Set MP attribute length. Don't count the (2) bytes used to encode
2202 the attr length */
2203 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2204}
2205
paul718e3742002-12-13 20:15:29 +00002206/* Make attribute packet. */
2207bgp_size_t
2208bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002209 struct stream *s, struct attr *attr,
2210 struct prefix *p, afi_t afi, safi_t safi,
2211 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002212{
paulfe69a502005-09-10 16:55:02 +00002213 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002214 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002215 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002216 int send_as4_path = 0;
2217 int send_as4_aggregator = 0;
2218 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002219 size_t mpattrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +00002220
2221 if (! bgp)
2222 bgp = bgp_get_default ();
2223
2224 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002225 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002226
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002227 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2228 {
2229 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2230 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2231 bgp_packet_mpattr_end(s, mpattrlen_pos);
2232 }
2233
paul718e3742002-12-13 20:15:29 +00002234 /* Origin attribute. */
2235 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2236 stream_putc (s, BGP_ATTR_ORIGIN);
2237 stream_putc (s, 1);
2238 stream_putc (s, attr->origin);
2239
2240 /* AS path attribute. */
2241
2242 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002243 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002244 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002245 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002246 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002247 {
2248 aspath = aspath_dup (attr->aspath);
2249
2250 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2251 {
2252 /* Strip the confed info, and then stuff our path CONFED_ID
2253 on the front */
2254 aspath = aspath_delete_confed_seq (aspath);
2255 aspath = aspath_add_seq (aspath, bgp->confed_id);
2256 }
2257 else
2258 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002259 if (peer->change_local_as) {
2260 /* If replace-as is specified, we only use the change_local_as when
2261 advertising routes. */
2262 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2263 aspath = aspath_add_seq (aspath, peer->local_as);
2264 }
paul718e3742002-12-13 20:15:29 +00002265 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002266 } else {
2267 aspath = aspath_add_seq (aspath, peer->local_as);
2268 }
paul718e3742002-12-13 20:15:29 +00002269 }
2270 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002271 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002272 {
2273 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2274 aspath = aspath_dup (attr->aspath);
2275 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2276 }
2277 else
2278 aspath = attr->aspath;
2279
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002280 /* If peer is not AS4 capable, then:
2281 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2282 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2283 * types are in it (i.e. exclude them if they are there)
2284 * AND do this only if there is at least one asnum > 65535 in the path!
2285 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2286 * all ASnums > 65535 to BGP_AS_TRANS
2287 */
paul718e3742002-12-13 20:15:29 +00002288
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002289 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2290 stream_putc (s, BGP_ATTR_AS_PATH);
2291 aspath_sizep = stream_get_endp (s);
2292 stream_putw (s, 0);
2293 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2294
2295 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2296 * in the path
2297 */
2298 if (!use32bit && aspath_has_as4 (aspath))
2299 send_as4_path = 1; /* we'll do this later, at the correct place */
2300
paul718e3742002-12-13 20:15:29 +00002301 /* Nexthop attribute. */
2302 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2303 {
2304 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2305 stream_putc (s, BGP_ATTR_NEXT_HOP);
2306 stream_putc (s, 4);
2307 if (safi == SAFI_MPLS_VPN)
2308 {
2309 if (attr->nexthop.s_addr == 0)
2310 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2311 else
2312 stream_put_ipv4 (s, attr->nexthop.s_addr);
2313 }
2314 else
2315 stream_put_ipv4 (s, attr->nexthop.s_addr);
2316 }
2317
2318 /* MED attribute. */
2319 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2320 {
2321 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2322 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2323 stream_putc (s, 4);
2324 stream_putl (s, attr->med);
2325 }
2326
2327 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002328 if (peer->sort == BGP_PEER_IBGP ||
2329 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002330 {
2331 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2332 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2333 stream_putc (s, 4);
2334 stream_putl (s, attr->local_pref);
2335 }
2336
2337 /* Atomic aggregate. */
2338 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2339 {
2340 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2341 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2342 stream_putc (s, 0);
2343 }
2344
2345 /* Aggregator. */
2346 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2347 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002348 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002349
2350 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002351 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2352 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002353
2354 if (use32bit)
2355 {
2356 /* AS4 capable peer */
2357 stream_putc (s, 8);
2358 stream_putl (s, attr->extra->aggregator_as);
2359 }
2360 else
2361 {
2362 /* 2-byte AS peer */
2363 stream_putc (s, 6);
2364
2365 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2366 if ( attr->extra->aggregator_as > 65535 )
2367 {
2368 stream_putw (s, BGP_AS_TRANS);
2369
2370 /* we have to send AS4_AGGREGATOR, too.
2371 * we'll do that later in order to send attributes in ascending
2372 * order.
2373 */
2374 send_as4_aggregator = 1;
2375 }
2376 else
2377 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2378 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002379 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002380 }
2381
2382 /* Community attribute. */
2383 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2384 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2385 {
2386 if (attr->community->size * 4 > 255)
2387 {
2388 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2389 stream_putc (s, BGP_ATTR_COMMUNITIES);
2390 stream_putw (s, attr->community->size * 4);
2391 }
2392 else
2393 {
2394 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2395 stream_putc (s, BGP_ATTR_COMMUNITIES);
2396 stream_putc (s, attr->community->size * 4);
2397 }
2398 stream_put (s, attr->community->val, attr->community->size * 4);
2399 }
2400
2401 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002402 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002403 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002404 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002405 {
2406 /* Originator ID. */
2407 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2408 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2409 stream_putc (s, 4);
2410
2411 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002412 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002413 else
2414 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002415
2416 /* Cluster list. */
2417 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2418 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2419
Paul Jakma9eda90c2007-08-30 13:36:17 +00002420 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002421 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002422 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002423 /* If this peer configuration's parent BGP has cluster_id. */
2424 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2425 stream_put_in_addr (s, &bgp->cluster_id);
2426 else
2427 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002428 stream_put (s, attr->extra->cluster->list,
2429 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002430 }
2431 else
2432 {
2433 stream_putc (s, 4);
2434 /* If this peer configuration's parent BGP has cluster_id. */
2435 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2436 stream_put_in_addr (s, &bgp->cluster_id);
2437 else
2438 stream_put_in_addr (s, &bgp->router_id);
2439 }
2440 }
2441
paul718e3742002-12-13 20:15:29 +00002442 /* Extended Communities attribute. */
2443 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2444 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2445 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002446 struct attr_extra *attre = attr->extra;
2447
2448 assert (attre);
2449
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002450 if (peer->sort == BGP_PEER_IBGP
2451 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002452 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002453 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002454 {
2455 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2456 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002457 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002458 }
2459 else
2460 {
2461 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2462 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002463 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002464 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002465 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002466 }
2467 else
2468 {
paul5228ad22004-06-04 17:58:18 +00002469 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002470 int tbit;
2471 int ecom_tr_size = 0;
2472 int i;
2473
Paul Jakmafb982c22007-05-04 20:15:47 +00002474 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002475 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002476 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002477 tbit = *pnt;
2478
2479 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2480 continue;
2481
2482 ecom_tr_size++;
2483 }
2484
2485 if (ecom_tr_size)
2486 {
2487 if (ecom_tr_size * 8 > 255)
2488 {
2489 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2490 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2491 stream_putw (s, ecom_tr_size * 8);
2492 }
2493 else
2494 {
2495 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2496 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2497 stream_putc (s, ecom_tr_size * 8);
2498 }
2499
Paul Jakmafb982c22007-05-04 20:15:47 +00002500 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002501 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002502 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002503 tbit = *pnt;
2504
2505 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2506 continue;
2507
2508 stream_put (s, pnt, 8);
2509 }
2510 }
paul718e3742002-12-13 20:15:29 +00002511 }
paul718e3742002-12-13 20:15:29 +00002512 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002513
2514 if ( send_as4_path )
2515 {
2516 /* If the peer is NOT As4 capable, AND */
2517 /* there are ASnums > 65535 in path THEN
2518 * give out AS4_PATH */
2519
2520 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2521 * path segments!
2522 * Hm, I wonder... confederation things *should* only be at
2523 * the beginning of an aspath, right? Then we should use
2524 * aspath_delete_confed_seq for this, because it is already
2525 * there! (JK)
2526 * Folks, talk to me: what is reasonable here!?
2527 */
2528 aspath = aspath_delete_confed_seq (aspath);
2529
2530 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2531 stream_putc (s, BGP_ATTR_AS4_PATH);
2532 aspath_sizep = stream_get_endp (s);
2533 stream_putw (s, 0);
2534 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2535 }
2536
2537 if (aspath != attr->aspath)
2538 aspath_free (aspath);
2539
2540 if ( send_as4_aggregator )
2541 {
2542 assert (attr->extra);
2543
2544 /* send AS4_AGGREGATOR, at this place */
2545 /* this section of code moved here in order to ensure the correct
2546 * *ascending* order of attributes
2547 */
2548 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2549 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2550 stream_putc (s, 8);
2551 stream_putl (s, attr->extra->aggregator_as);
2552 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2553 }
Paul Jakma41367172007-08-06 15:24:51 +00002554
paul718e3742002-12-13 20:15:29 +00002555 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002556 if (attr->extra && attr->extra->transit)
2557 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002558
2559 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002560 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002561}
2562
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002563size_t
2564bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002565{
paul718e3742002-12-13 20:15:29 +00002566 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002567
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002568 /* Set extended bit always to encode the attribute length as 2 bytes */
2569 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002570 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2571
paul9985f832005-02-09 15:51:56 +00002572 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002573 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002574
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002575 stream_putw (s, afi);
2576 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
2577 stream_putc (s, safi);
2578 return attrlen_pnt;
2579}
paul718e3742002-12-13 20:15:29 +00002580
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002581void
2582bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2583 afi_t afi, safi_t safi, struct prefix_rd *prd,
2584 u_char *tag)
2585{
paul718e3742002-12-13 20:15:29 +00002586 if (safi == SAFI_MPLS_VPN)
2587 {
paul718e3742002-12-13 20:15:29 +00002588 stream_putc (s, p->prefixlen + 88);
2589 stream_put (s, tag, 3);
2590 stream_put (s, prd->val, 8);
2591 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2592 }
2593 else
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002594 stream_put_prefix (s, p);
2595}
paul718e3742002-12-13 20:15:29 +00002596
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002597void
2598bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2599{
2600 bgp_size_t size;
paul718e3742002-12-13 20:15:29 +00002601
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002602 /* Set MP attribute length. Don't count the (2) bytes used to encode
2603 the attr length */
2604 size = stream_get_endp (s) - attrlen_pnt - 2;
2605 stream_putw_at (s, attrlen_pnt, size);
paul718e3742002-12-13 20:15:29 +00002606}
2607
2608/* Initialization of attribute. */
2609void
paulfe69a502005-09-10 16:55:02 +00002610bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002611{
paul718e3742002-12-13 20:15:29 +00002612 aspath_init ();
2613 attrhash_init ();
2614 community_init ();
2615 ecommunity_init ();
2616 cluster_init ();
2617 transit_init ();
2618}
2619
Chris Caputo228da422009-07-18 05:44:03 +00002620void
2621bgp_attr_finish (void)
2622{
2623 aspath_finish ();
2624 attrhash_finish ();
2625 community_finish ();
2626 ecommunity_finish ();
2627 cluster_finish ();
2628 transit_finish ();
2629}
2630
paul718e3742002-12-13 20:15:29 +00002631/* Make attribute packet. */
2632void
paula3845922003-10-18 01:30:50 +00002633bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2634 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00002635{
2636 unsigned long cp;
2637 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002638 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00002639 struct aspath *aspath;
2640
2641 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002642 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002643
2644 /* Place holder of length. */
2645 stream_putw (s, 0);
2646
2647 /* Origin attribute. */
2648 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2649 stream_putc (s, BGP_ATTR_ORIGIN);
2650 stream_putc (s, 1);
2651 stream_putc (s, attr->origin);
2652
2653 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002654
2655 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2656 stream_putc (s, BGP_ATTR_AS_PATH);
2657 aspath_lenp = stream_get_endp (s);
2658 stream_putw (s, 0);
2659
2660 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00002661
2662 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00002663 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2664 if(prefix != NULL
2665#ifdef HAVE_IPV6
2666 && prefix->family != AF_INET6
2667#endif /* HAVE_IPV6 */
2668 )
2669 {
2670 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2671 stream_putc (s, BGP_ATTR_NEXT_HOP);
2672 stream_putc (s, 4);
2673 stream_put_ipv4 (s, attr->nexthop.s_addr);
2674 }
paul718e3742002-12-13 20:15:29 +00002675
2676 /* MED attribute. */
2677 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2678 {
2679 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2680 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2681 stream_putc (s, 4);
2682 stream_putl (s, attr->med);
2683 }
2684
2685 /* Local preference. */
2686 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2687 {
2688 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2689 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2690 stream_putc (s, 4);
2691 stream_putl (s, attr->local_pref);
2692 }
2693
2694 /* Atomic aggregate. */
2695 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2696 {
2697 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2698 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2699 stream_putc (s, 0);
2700 }
2701
2702 /* Aggregator. */
2703 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2704 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002705 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00002706 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2707 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002708 stream_putc (s, 8);
2709 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00002710 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002711 }
2712
2713 /* Community attribute. */
2714 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2715 {
2716 if (attr->community->size * 4 > 255)
2717 {
2718 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2719 stream_putc (s, BGP_ATTR_COMMUNITIES);
2720 stream_putw (s, attr->community->size * 4);
2721 }
2722 else
2723 {
2724 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2725 stream_putc (s, BGP_ATTR_COMMUNITIES);
2726 stream_putc (s, attr->community->size * 4);
2727 }
2728 stream_put (s, attr->community->val, attr->community->size * 4);
2729 }
2730
paula3845922003-10-18 01:30:50 +00002731#ifdef HAVE_IPV6
2732 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002733 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2734 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00002735 {
2736 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00002737 struct attr_extra *attre = attr->extra;
2738
paula3845922003-10-18 01:30:50 +00002739 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2740 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00002741 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00002742
2743 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00002744 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00002745 stream_putw(s, AFI_IP6); /* AFI */
2746 stream_putc(s, SAFI_UNICAST); /* SAFI */
2747
2748 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002749 stream_putc(s, attre->mp_nexthop_len);
2750 stream_put(s, &attre->mp_nexthop_global, 16);
2751 if (attre->mp_nexthop_len == 32)
2752 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00002753
2754 /* SNPA */
2755 stream_putc(s, 0);
2756
2757 /* Prefix */
2758 stream_put_prefix(s, prefix);
2759
2760 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00002761 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00002762 }
2763#endif /* HAVE_IPV6 */
2764
paul718e3742002-12-13 20:15:29 +00002765 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002766 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00002767 stream_putw_at (s, cp, len);
2768}