blob: d413e5b26122aa5ce334981b0074f76c31fa1b53 [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{
Lou Berger056f3762013-04-10 12:30:04 -0700206 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
Chris Caputo228da422009-07-18 05:44:03 +0000207 hash_free (cluster_hash);
208 cluster_hash = NULL;
209}
David Lamparter6b0655a2014-06-04 06:53:35 +0200210
paul718e3742002-12-13 20:15:29 +0000211/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700212static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000213
paul94f2b392005-06-28 12:44:16 +0000214static void
paul718e3742002-12-13 20:15:29 +0000215transit_free (struct transit *transit)
216{
217 if (transit->val)
218 XFREE (MTYPE_TRANSIT_VAL, transit->val);
219 XFREE (MTYPE_TRANSIT, transit);
220}
221
Paul Jakma923de652007-04-29 18:25:17 +0000222
paul94f2b392005-06-28 12:44:16 +0000223static void *
Paul Jakma923de652007-04-29 18:25:17 +0000224transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000225{
226 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000227 return p;
paul718e3742002-12-13 20:15:29 +0000228}
229
paul94f2b392005-06-28 12:44:16 +0000230static struct transit *
paul718e3742002-12-13 20:15:29 +0000231transit_intern (struct transit *transit)
232{
233 struct transit *find;
234
235 find = hash_get (transit_hash, transit, transit_hash_alloc);
236 if (find != transit)
237 transit_free (transit);
238 find->refcnt++;
239
240 return find;
241}
242
243void
244transit_unintern (struct transit *transit)
245{
paul718e3742002-12-13 20:15:29 +0000246 if (transit->refcnt)
247 transit->refcnt--;
248
249 if (transit->refcnt == 0)
250 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400251 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000252 transit_free (transit);
253 }
254}
255
paul94f2b392005-06-28 12:44:16 +0000256static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000257transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000258{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700259 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000260
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700261 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000262}
263
paul94f2b392005-06-28 12:44:16 +0000264static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100265transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000266{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100267 const struct transit * transit1 = p1;
268 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000269
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100270 return (transit1->length == transit2->length &&
271 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000272}
273
paul94f2b392005-06-28 12:44:16 +0000274static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800275transit_init (void)
paul718e3742002-12-13 20:15:29 +0000276{
277 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
278}
Chris Caputo228da422009-07-18 05:44:03 +0000279
280static void
281transit_finish (void)
282{
Lou Berger056f3762013-04-10 12:30:04 -0700283 hash_clean (transit_hash, (void (*)(void *))transit_free);
Chris Caputo228da422009-07-18 05:44:03 +0000284 hash_free (transit_hash);
285 transit_hash = NULL;
286}
David Lamparter6b0655a2014-06-04 06:53:35 +0200287
paul718e3742002-12-13 20:15:29 +0000288/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700289static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000290
Paul Jakmafb982c22007-05-04 20:15:47 +0000291static struct attr_extra *
292bgp_attr_extra_new (void)
293{
294 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
295}
296
297void
298bgp_attr_extra_free (struct attr *attr)
299{
300 if (attr->extra)
301 {
302 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
303 attr->extra = NULL;
304 }
305}
306
307struct attr_extra *
308bgp_attr_extra_get (struct attr *attr)
309{
310 if (!attr->extra)
311 attr->extra = bgp_attr_extra_new();
312 return attr->extra;
313}
314
315/* Shallow copy of an attribute
316 * Though, not so shallow that it doesn't copy the contents
317 * of the attr_extra pointed to by 'extra'
318 */
319void
320bgp_attr_dup (struct attr *new, struct attr *orig)
321{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000322 struct attr_extra *extra = new->extra;
323
Paul Jakmafb982c22007-05-04 20:15:47 +0000324 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000325 /* if caller provided attr_extra space, use it in any case.
326 *
327 * This is neccesary even if orig->extra equals NULL, because otherwise
328 * memory may be later allocated on the heap by bgp_attr_extra_get.
329 *
330 * That memory would eventually be leaked, because the caller must not
331 * call bgp_attr_extra_free if he provided attr_extra on the stack.
332 */
333 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000334 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000335 new->extra = extra;
336 memset(new->extra, 0, sizeof(struct attr_extra));
337 if (orig->extra)
338 *new->extra = *orig->extra;
339 }
340 else if (orig->extra)
341 {
342 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000343 *new->extra = *orig->extra;
344 }
345}
346
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000347unsigned long int
348attr_count (void)
349{
350 return attrhash->count;
351}
352
353unsigned long int
354attr_unknown_count (void)
355{
356 return transit_hash->count;
357}
358
paul718e3742002-12-13 20:15:29 +0000359unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000360attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000361{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000362 const struct attr *attr = (struct attr *) p;
363 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700364 uint32_t key = 0;
365#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000366
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700367 MIX(attr->origin);
368 MIX(attr->nexthop.s_addr);
369 MIX(attr->med);
370 MIX(attr->local_pref);
371
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000372 key += attr->origin;
373 key += attr->nexthop.s_addr;
374 key += attr->med;
375 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000376
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000377 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000378 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000379 MIX(extra->aggregator_as);
380 MIX(extra->aggregator_addr.s_addr);
381 MIX(extra->weight);
382 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000383 MIX(extra->originator_id.s_addr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000384 }
385
paul718e3742002-12-13 20:15:29 +0000386 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700387 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000388 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700389 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000390
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000391 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000392 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000393 if (extra->ecommunity)
394 MIX(ecommunity_hash_make (extra->ecommunity));
395 if (extra->cluster)
396 MIX(cluster_hash_key_make (extra->cluster));
397 if (extra->transit)
398 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000399
400#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000401 MIX(extra->mp_nexthop_len);
402 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
403 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
paul718e3742002-12-13 20:15:29 +0000404#endif /* HAVE_IPV6 */
Paul Jakmafb982c22007-05-04 20:15:47 +0000405 }
paul718e3742002-12-13 20:15:29 +0000406
407 return key;
408}
409
410int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100411attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000412{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100413 const struct attr * attr1 = p1;
414 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000415
paul718e3742002-12-13 20:15:29 +0000416 if (attr1->flag == attr2->flag
417 && attr1->origin == attr2->origin
418 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000419 && attr1->aspath == attr2->aspath
420 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000421 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000422 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000423 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100424 const struct attr_extra *ae1 = attr1->extra;
425 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000426
427 if (ae1 && ae2
428 && ae1->aggregator_as == ae2->aggregator_as
429 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
430 && ae1->weight == ae2->weight
431#ifdef HAVE_IPV6
432 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
433 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
434 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
435#endif /* HAVE_IPV6 */
436 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
437 && ae1->ecommunity == ae2->ecommunity
438 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000439 && ae1->transit == ae2->transit
440 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000441 return 1;
442 else if (ae1 || ae2)
443 return 0;
444 /* neither attribute has extra attributes, so they're same */
445 return 1;
446 }
paul718e3742002-12-13 20:15:29 +0000447 else
448 return 0;
449}
450
paul94f2b392005-06-28 12:44:16 +0000451static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100452attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000453{
454 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
455}
456
Lou Berger056f3762013-04-10 12:30:04 -0700457/*
458 * special for hash_clean below
459 */
460static void
461attr_vfree (void *attr)
462{
463 bgp_attr_extra_free ((struct attr *)attr);
464 XFREE (MTYPE_ATTR, attr);
465}
466
paul94f2b392005-06-28 12:44:16 +0000467static void
Chris Caputo228da422009-07-18 05:44:03 +0000468attrhash_finish (void)
469{
Lou Berger056f3762013-04-10 12:30:04 -0700470 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000471 hash_free (attrhash);
472 attrhash = NULL;
473}
474
475static void
paul718e3742002-12-13 20:15:29 +0000476attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
477{
478 struct attr *attr = backet->data;
479
480 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
481 inet_ntoa (attr->nexthop), VTY_NEWLINE);
482}
483
484void
485attr_show_all (struct vty *vty)
486{
487 hash_iterate (attrhash,
488 (void (*)(struct hash_backet *, void *))
489 attr_show_all_iterator,
490 vty);
491}
492
paul94f2b392005-06-28 12:44:16 +0000493static void *
Paul Jakma923de652007-04-29 18:25:17 +0000494bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000495{
Paul Jakma923de652007-04-29 18:25:17 +0000496 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000497 struct attr *attr;
498
499 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
500 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000501 if (val->extra)
502 {
503 attr->extra = bgp_attr_extra_new ();
504 *attr->extra = *val->extra;
505 }
paul718e3742002-12-13 20:15:29 +0000506 attr->refcnt = 0;
507 return attr;
508}
509
510/* Internet argument attribute. */
511struct attr *
512bgp_attr_intern (struct attr *attr)
513{
514 struct attr *find;
515
516 /* Intern referenced strucutre. */
517 if (attr->aspath)
518 {
519 if (! attr->aspath->refcnt)
520 attr->aspath = aspath_intern (attr->aspath);
521 else
522 attr->aspath->refcnt++;
523 }
524 if (attr->community)
525 {
526 if (! attr->community->refcnt)
527 attr->community = community_intern (attr->community);
528 else
529 attr->community->refcnt++;
530 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000531 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000532 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000533 struct attr_extra *attre = attr->extra;
534
535 if (attre->ecommunity)
536 {
537 if (! attre->ecommunity->refcnt)
538 attre->ecommunity = ecommunity_intern (attre->ecommunity);
539 else
540 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000541
Paul Jakmafb982c22007-05-04 20:15:47 +0000542 }
543 if (attre->cluster)
544 {
545 if (! attre->cluster->refcnt)
546 attre->cluster = cluster_intern (attre->cluster);
547 else
548 attre->cluster->refcnt++;
549 }
550 if (attre->transit)
551 {
552 if (! attre->transit->refcnt)
553 attre->transit = transit_intern (attre->transit);
554 else
555 attre->transit->refcnt++;
556 }
paul718e3742002-12-13 20:15:29 +0000557 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000558
paul718e3742002-12-13 20:15:29 +0000559 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
560 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000561
paul718e3742002-12-13 20:15:29 +0000562 return find;
563}
564
Paul Jakma03e214c2007-04-29 18:31:07 +0000565
paul718e3742002-12-13 20:15:29 +0000566/* Make network statement's attribute. */
567struct attr *
568bgp_attr_default_set (struct attr *attr, u_char origin)
569{
570 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000571 bgp_attr_extra_get (attr);
572
paul718e3742002-12-13 20:15:29 +0000573 attr->origin = origin;
574 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
575 attr->aspath = aspath_empty ();
576 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000577 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000578 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
579#ifdef HAVE_IPV6
Paul Jakmafb982c22007-05-04 20:15:47 +0000580 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000581#endif
Paul Jakma03e214c2007-04-29 18:31:07 +0000582
paul718e3742002-12-13 20:15:29 +0000583 return attr;
584}
585
Paul Jakma03e214c2007-04-29 18:31:07 +0000586
paul718e3742002-12-13 20:15:29 +0000587/* Make network statement's attribute. */
588struct attr *
589bgp_attr_default_intern (u_char origin)
590{
591 struct attr attr;
592 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000593
Paul Jakma03e214c2007-04-29 18:31:07 +0000594 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000595
596 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000597 bgp_attr_extra_free (&attr);
598
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000599 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000600 return new;
601}
602
603struct attr *
604bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
605 struct aspath *aspath,
606 struct community *community, int as_set)
607{
608 struct attr attr;
609 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000610 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000611
612 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000613 memset (&attre, 0, sizeof (struct attr_extra));
614 attr.extra = &attre;
615
paul718e3742002-12-13 20:15:29 +0000616 /* Origin attribute. */
617 attr.origin = origin;
618 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
619
620 /* AS path attribute. */
621 if (aspath)
622 attr.aspath = aspath_intern (aspath);
623 else
624 attr.aspath = aspath_empty ();
625 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
626
627 /* Next hop attribute. */
628 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
629
630 if (community)
631 {
632 attr.community = community;
633 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
634 }
635
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000636 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000637#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000638 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000639#endif
640 if (! as_set)
641 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
642 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
643 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000644 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000645 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000646 attre.aggregator_as = bgp->as;
647 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000648
649 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000650
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000651 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000652 return new;
653}
654
Paul Jakmab881c702010-11-23 16:35:42 +0000655/* Unintern just the sub-components of the attr, but not the attr */
656void
657bgp_attr_unintern_sub (struct attr *attr)
658{
659 /* aspath refcount shoud be decrement. */
660 if (attr->aspath)
661 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000662 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000663
664 if (attr->community)
665 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000666 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000667
668 if (attr->extra)
669 {
670 if (attr->extra->ecommunity)
671 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000672 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000673
674 if (attr->extra->cluster)
675 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000676 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000677
678 if (attr->extra->transit)
679 transit_unintern (attr->extra->transit);
680 }
681}
682
paul718e3742002-12-13 20:15:29 +0000683/* Free bgp attribute and aspath. */
684void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000685bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000686{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000687 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000688 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000689 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000690 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000691
paul718e3742002-12-13 20:15:29 +0000692 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000693 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000694
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000695 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000696
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000697 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000698 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000699 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000700 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000701 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000702
paul718e3742002-12-13 20:15:29 +0000703 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000704 if (attr->refcnt == 0)
705 {
706 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000707 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000708 bgp_attr_extra_free (attr);
709 XFREE (MTYPE_ATTR, attr);
710 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000711 }
712
Paul Jakmab881c702010-11-23 16:35:42 +0000713 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000714}
715
716void
717bgp_attr_flush (struct attr *attr)
718{
719 if (attr->aspath && ! attr->aspath->refcnt)
720 aspath_free (attr->aspath);
721 if (attr->community && ! attr->community->refcnt)
722 community_free (attr->community);
Paul Jakmafb982c22007-05-04 20:15:47 +0000723 if (attr->extra)
724 {
725 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000726
Paul Jakmafb982c22007-05-04 20:15:47 +0000727 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000728 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000729 if (attre->cluster && ! attre->cluster->refcnt)
730 cluster_free (attre->cluster);
731 if (attre->transit && ! attre->transit->refcnt)
732 transit_free (attre->transit);
733 }
paul718e3742002-12-13 20:15:29 +0000734}
735
Paul Jakmab881c702010-11-23 16:35:42 +0000736/* Implement draft-scudder-idr-optional-transitive behaviour and
737 * avoid resetting sessions for malformed attributes which are
738 * are partial/optional and hence where the error likely was not
739 * introduced by the sending neighbour.
740 */
741static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000742bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
743 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000744{
Paul Jakma835315b2012-01-18 12:28:30 +0000745 struct peer *const peer = args->peer;
746 const u_int8_t flags = args->flags;
747 /* startp and length must be special-cased, as whether or not to
748 * send the attribute data with the NOTIFY depends on the error,
749 * the caller therefore signals this with the seperate length argument
750 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000751 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000752
Paul Jakmab881c702010-11-23 16:35:42 +0000753 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000754 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000755 {
756 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000757 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000758 return BGP_ATTR_PARSE_ERROR;
759
760 }
761
Paul Jakmabd471fe2012-03-15 11:30:00 +0000762 /* Adjust the stream getp to the end of the attribute, in case we can
763 * still proceed but the caller hasn't read all the attribute.
764 */
765 stream_set_getp (BGP_INPUT (peer),
766 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
767 + args->total);
768
Paul Jakma835315b2012-01-18 12:28:30 +0000769 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100770 /* where an attribute is relatively inconsequential, e.g. it does not
771 * affect route selection, and can be safely ignored, then any such
772 * attributes which are malformed should just be ignored and the route
773 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000774 */
775 case BGP_ATTR_AS4_AGGREGATOR:
776 case BGP_ATTR_AGGREGATOR:
777 case BGP_ATTR_ATOMIC_AGGREGATE:
778 return BGP_ATTR_PARSE_PROCEED;
779
780 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100781 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000782 */
783 case BGP_ATTR_ORIGIN:
784 case BGP_ATTR_AS_PATH:
785 case BGP_ATTR_NEXT_HOP:
786 case BGP_ATTR_MULTI_EXIT_DISC:
787 case BGP_ATTR_LOCAL_PREF:
788 case BGP_ATTR_COMMUNITIES:
789 case BGP_ATTR_ORIGINATOR_ID:
790 case BGP_ATTR_CLUSTER_LIST:
791 case BGP_ATTR_MP_REACH_NLRI:
792 case BGP_ATTR_MP_UNREACH_NLRI:
793 case BGP_ATTR_EXT_COMMUNITIES:
794 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000795 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000796 return BGP_ATTR_PARSE_ERROR;
797 }
798
799 /* Partial optional attributes that are malformed should not cause
800 * the whole session to be reset. Instead treat it as a withdrawal
801 * of the routes, if possible.
802 */
Paul Jakma835315b2012-01-18 12:28:30 +0000803 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
804 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
805 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000806 return BGP_ATTR_PARSE_WITHDRAW;
807
808 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200809 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000810}
811
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400812/* Find out what is wrong with the path attribute flag bits and log the error.
813 "Flag bits" here stand for Optional, Transitive and Partial, but not for
814 Extended Length. Checking O/T/P bits at once implies, that the attribute
815 being diagnosed is defined by RFC as either a "well-known" or an "optional,
816 non-transitive" attribute. */
817static void
Paul Jakma835315b2012-01-18 12:28:30 +0000818bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
819 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400820)
821{
822 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000823 u_char real_flags = args->flags;
824 const u_int8_t attr_code = args->type;
825
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400826 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
827 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
828 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
829 if
830 (
831 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
832 CHECK_FLAG (real_flags, attr_flag_str[i].key)
833 )
834 {
Paul Jakma835315b2012-01-18 12:28:30 +0000835 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400836 LOOKUP (attr_str, attr_code),
837 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
838 attr_flag_str[i].str);
839 seen = 1;
840 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100841 if (!seen)
842 {
843 zlog (args->peer->log, LOG_DEBUG,
844 "Strange, %s called for attr %s, but no problem found with flags"
845 " (real flags 0x%x, desired 0x%x)",
846 __func__, LOOKUP (attr_str, attr_code),
847 real_flags, desired_flags);
848 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400849}
850
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000851/* Required flags for attributes. EXTLEN will be masked off when testing,
852 * as will PARTIAL for optional+transitive attributes.
853 */
854const u_int8_t attr_flags_values [] = {
855 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
856 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
857 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
858 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
859 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
860 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
861 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
862 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
863 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
864 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
865 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
866 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
867 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
868 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
869 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
870};
871static const size_t attr_flags_values_max =
872 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
873
874static int
Paul Jakma835315b2012-01-18 12:28:30 +0000875bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000876{
877 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +0000878 const u_int8_t flags = args->flags;
879 const u_int8_t attr_code = args->type;
880 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000881
882 /* there may be attributes we don't know about */
883 if (attr_code > attr_flags_values_max)
884 return 0;
885 if (attr_flags_values[attr_code] == 0)
886 return 0;
887
888 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
889 * 1."
890 */
891 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
892 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
893 {
894 zlog (peer->log, LOG_ERR,
895 "%s well-known attributes must have transitive flag set (%x)",
896 LOOKUP (attr_str, attr_code), flags);
897 return 1;
898 }
899
900 /* "For well-known attributes and for optional non-transitive attributes,
901 * the Partial bit MUST be set to 0."
902 */
903 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
904 {
905 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
906 {
907 zlog (peer->log, LOG_ERR,
908 "%s well-known attribute "
909 "must NOT have the partial flag set (%x)",
910 LOOKUP (attr_str, attr_code), flags);
911 return 1;
912 }
913 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
914 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
915 {
916 zlog (peer->log, LOG_ERR,
917 "%s optional + transitive attribute "
918 "must NOT have the partial flag set (%x)",
919 LOOKUP (attr_str, attr_code), flags);
920 return 1;
921 }
922 }
923
924 /* Optional transitive attributes may go through speakers that don't
925 * reocgnise them and set the Partial bit.
926 */
927 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
928 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
929 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
930
Paul Jakma683f2b82012-03-23 14:58:45 +0000931 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000932 == attr_flags_values[attr_code])
933 return 0;
934
Paul Jakma835315b2012-01-18 12:28:30 +0000935 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000936 return 1;
937}
938
paul718e3742002-12-13 20:15:29 +0000939/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +0000940static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000941bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000942{
Paul Jakma835315b2012-01-18 12:28:30 +0000943 struct peer *const peer = args->peer;
944 struct attr *const attr = args->attr;
945 const bgp_size_t length = args->length;
946
paul718e3742002-12-13 20:15:29 +0000947 /* If any recognized attribute has Attribute Length that conflicts
948 with the expected length (based on the attribute type code), then
949 the Error Subcode is set to Attribute Length Error. The Data
950 field contains the erroneous attribute (type, length and
951 value). */
952 if (length != 1)
953 {
954 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
955 length);
Paul Jakma835315b2012-01-18 12:28:30 +0000956 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000957 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +0000958 args->total);
paul718e3742002-12-13 20:15:29 +0000959 }
960
961 /* Fetch origin attribute. */
962 attr->origin = stream_getc (BGP_INPUT (peer));
963
964 /* If the ORIGIN attribute has an undefined value, then the Error
965 Subcode is set to Invalid Origin Attribute. The Data field
966 contains the unrecognized attribute (type, length and value). */
967 if ((attr->origin != BGP_ORIGIN_IGP)
968 && (attr->origin != BGP_ORIGIN_EGP)
969 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
970 {
971 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
972 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +0000973 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +0000974 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +0000975 args->total);
paul718e3742002-12-13 20:15:29 +0000976 }
977
978 /* Set oring attribute flag. */
979 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
980
981 return 0;
982}
Paul Jakmaab005292010-11-27 22:48:34 +0000983
984/* Parse AS path information. This function is wrapper of
985 aspath_parse. */
986static int
Paul Jakma835315b2012-01-18 12:28:30 +0000987bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +0000988{
Paul Jakma835315b2012-01-18 12:28:30 +0000989 struct attr *const attr = args->attr;
990 struct peer *const peer = args->peer;
991 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +0000992
Paul Jakmaab005292010-11-27 22:48:34 +0000993 /*
994 * peer with AS4 => will get 4Byte ASnums
995 * otherwise, will get 16 Bit
996 */
997 attr->aspath = aspath_parse (peer->ibuf, length,
998 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
999
1000 /* In case of IBGP, length will be zero. */
1001 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001002 {
Paul Jakmab881c702010-11-23 16:35:42 +00001003 zlog (peer->log, LOG_ERR,
1004 "Malformed AS path from %s, length is %d",
1005 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001006 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001007 }
Chris Hallcddb8112010-08-09 22:31:37 +04001008
Paul Jakmaab005292010-11-27 22:48:34 +00001009 /* Set aspath attribute flag. */
1010 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001011
Paul Jakmab881c702010-11-23 16:35:42 +00001012 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001013}
1014
Paul Jakmab881c702010-11-23 16:35:42 +00001015static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001016bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001017{
1018 /* These checks were part of bgp_attr_aspath, but with
1019 * as4 we should to check aspath things when
1020 * aspath synthesizing with as4_path has already taken place.
1021 * Otherwise we check ASPATH and use the synthesized thing, and that is
1022 * not right.
1023 * So do the checks later, i.e. here
1024 */
1025 struct bgp *bgp = peer->bgp;
1026 struct aspath *aspath;
1027
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001028 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001029 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1030 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001031 {
1032 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
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;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001036 }
1037
paul718e3742002-12-13 20:15:29 +00001038 /* First AS check for EBGP. */
1039 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1040 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001041 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001042 && ! aspath_firstas_check (attr->aspath, peer->as))
1043 {
1044 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001045 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001046 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1047 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1048 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001049 }
1050 }
1051
1052 /* local-as prepend */
1053 if (peer->change_local_as &&
1054 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1055 {
1056 aspath = aspath_dup (attr->aspath);
1057 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001058 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001059 attr->aspath = aspath_intern (aspath);
1060 }
1061
Paul Jakmab881c702010-11-23 16:35:42 +00001062 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001063}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001064
Paul Jakmaab005292010-11-27 22:48:34 +00001065/* Parse AS4 path information. This function is another wrapper of
1066 aspath_parse. */
1067static int
Paul Jakma835315b2012-01-18 12:28:30 +00001068bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001069{
Paul Jakma835315b2012-01-18 12:28:30 +00001070 struct peer *const peer = args->peer;
1071 struct attr *const attr = args->attr;
1072 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001073
Paul Jakmaab005292010-11-27 22:48:34 +00001074 *as4_path = aspath_parse (peer->ibuf, length, 1);
1075
Paul Jakmab881c702010-11-23 16:35:42 +00001076 /* In case of IBGP, length will be zero. */
1077 if (!*as4_path)
1078 {
1079 zlog (peer->log, LOG_ERR,
1080 "Malformed AS4 path from %s, length is %d",
1081 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001082 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001083 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001084 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001085 }
1086
Paul Jakmaab005292010-11-27 22:48:34 +00001087 /* Set aspath attribute flag. */
1088 if (as4_path)
1089 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1090
Paul Jakmab881c702010-11-23 16:35:42 +00001091 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001092}
1093
paul718e3742002-12-13 20:15:29 +00001094/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001095static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001096bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001097{
Paul Jakma835315b2012-01-18 12:28:30 +00001098 struct peer *const peer = args->peer;
1099 struct attr *const attr = args->attr;
1100 const bgp_size_t length = args->length;
1101
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001102 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001103
paul718e3742002-12-13 20:15:29 +00001104 /* Check nexthop attribute length. */
1105 if (length != 4)
1106 {
1107 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1108 length);
1109
Paul Jakma835315b2012-01-18 12:28:30 +00001110 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001111 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001112 args->total);
paul718e3742002-12-13 20:15:29 +00001113 }
1114
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001115 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1116 attribute must result in a NOTIFICATION message (this is implemented below).
1117 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1118 logged locally (this is implemented somewhere else). The UPDATE message
1119 gets ignored in any of these cases. */
1120 nexthop_n = stream_get_ipv4 (peer->ibuf);
1121 nexthop_h = ntohl (nexthop_n);
1122 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1123 {
1124 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001125 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001126 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001127 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001128 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001129 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001130 }
1131
1132 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001133 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1134
Paul Jakmab881c702010-11-23 16:35:42 +00001135 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001136}
1137
1138/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001139static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001140bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001141{
Paul Jakma835315b2012-01-18 12:28:30 +00001142 struct peer *const peer = args->peer;
1143 struct attr *const attr = args->attr;
1144 const bgp_size_t length = args->length;
1145
paul718e3742002-12-13 20:15:29 +00001146 /* Length check. */
1147 if (length != 4)
1148 {
1149 zlog (peer->log, LOG_ERR,
1150 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001151
Paul Jakma835315b2012-01-18 12:28:30 +00001152 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001153 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001154 args->total);
paul718e3742002-12-13 20:15:29 +00001155 }
1156
1157 attr->med = stream_getl (peer->ibuf);
1158
1159 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1160
Paul Jakmab881c702010-11-23 16:35:42 +00001161 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001162}
1163
1164/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001165static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001166bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001167{
Paul Jakma835315b2012-01-18 12:28:30 +00001168 struct peer *const peer = args->peer;
1169 struct attr *const attr = args->attr;
1170 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001171
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001172 /* Length check. */
1173 if (length != 4)
1174 {
Paul Jakma835315b2012-01-18 12:28:30 +00001175 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1176 length);
1177 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001178 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001179 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001180 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001181
paul718e3742002-12-13 20:15:29 +00001182 /* If it is contained in an UPDATE message that is received from an
1183 external peer, then this attribute MUST be ignored by the
1184 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001185 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001186 {
paul9985f832005-02-09 15:51:56 +00001187 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001188 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001189 }
1190
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001191 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001192
1193 /* Set atomic aggregate flag. */
1194 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1195
Paul Jakmab881c702010-11-23 16:35:42 +00001196 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001197}
1198
1199/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001200static int
Paul Jakma835315b2012-01-18 12:28:30 +00001201bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001202{
Paul Jakma835315b2012-01-18 12:28:30 +00001203 struct peer *const peer = args->peer;
1204 struct attr *const attr = args->attr;
1205 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001206
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001207 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001208 if (length != 0)
1209 {
Paul Jakma835315b2012-01-18 12:28:30 +00001210 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1211 length);
1212 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001213 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001214 args->total);
paul718e3742002-12-13 20:15:29 +00001215 }
1216
1217 /* Set atomic aggregate flag. */
1218 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1219
Paul Jakmab881c702010-11-23 16:35:42 +00001220 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001221}
1222
1223/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001224static int
Paul Jakma835315b2012-01-18 12:28:30 +00001225bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001226{
Paul Jakma835315b2012-01-18 12:28:30 +00001227 struct peer *const peer = args->peer;
1228 struct attr *const attr = args->attr;
1229 const bgp_size_t length = args->length;
1230
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001231 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001232 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001233
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001234 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001235 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001236 wantedlen = 8;
1237
1238 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001239 {
Paul Jakma835315b2012-01-18 12:28:30 +00001240 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1241 wantedlen, length);
1242 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001243 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001244 args->total);
paul718e3742002-12-13 20:15:29 +00001245 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001246
1247 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1248 attre->aggregator_as = stream_getl (peer->ibuf);
1249 else
1250 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001251 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001252
1253 /* Set atomic aggregate flag. */
1254 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1255
Paul Jakmab881c702010-11-23 16:35:42 +00001256 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001257}
1258
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001259/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001260static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001261bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1262 as_t *as4_aggregator_as,
1263 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001264{
Paul Jakma835315b2012-01-18 12:28:30 +00001265 struct peer *const peer = args->peer;
1266 struct attr *const attr = args->attr;
1267 const bgp_size_t length = args->length;
1268
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001269 if (length != 8)
1270 {
Paul Jakma835315b2012-01-18 12:28:30 +00001271 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1272 length);
1273 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001274 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001275 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001276 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001277
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001278 *as4_aggregator_as = stream_getl (peer->ibuf);
1279 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1280
1281 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1282
Paul Jakmab881c702010-11-23 16:35:42 +00001283 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001284}
1285
1286/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1287 */
Paul Jakmab881c702010-11-23 16:35:42 +00001288static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001289bgp_attr_munge_as4_attrs (struct peer *const peer,
1290 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001291 struct aspath *as4_path, as_t as4_aggregator,
1292 struct in_addr *as4_aggregator_addr)
1293{
1294 int ignore_as4_path = 0;
1295 struct aspath *newpath;
1296 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001297
1298 if (!attr->aspath)
1299 {
1300 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1301 * checked that all well-known, mandatory attributes were present.
1302 *
1303 * Can only be a problem with peer itself - hard error
1304 */
1305 return BGP_ATTR_PARSE_ERROR;
1306 }
1307
Paul Jakmab881c702010-11-23 16:35:42 +00001308 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001309 {
1310 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1311 * if given.
1312 * It is worth a warning though, because the peer really
1313 * should not send them
1314 */
1315 if (BGP_DEBUG(as4, AS4))
1316 {
1317 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1318 zlog_debug ("[AS4] %s %s AS4_PATH",
1319 peer->host, "AS4 capable peer, yet it sent");
1320
1321 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1322 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1323 peer->host, "AS4 capable peer, yet it sent");
1324 }
1325
Paul Jakmab881c702010-11-23 16:35:42 +00001326 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001327 }
1328
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001329 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1330 * because that may override AS4_PATH
1331 */
1332 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1333 {
Paul Jakmab881c702010-11-23 16:35:42 +00001334 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001335 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001336 assert (attre);
1337
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001338 /* received both.
1339 * if the as_number in aggregator is not AS_TRANS,
1340 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1341 * and the Aggregator shall be taken as
1342 * info on the aggregating node, and the AS_PATH
1343 * shall be taken as the AS_PATH
1344 * otherwise
1345 * the Aggregator shall be ignored and the
1346 * AS4_AGGREGATOR shall be taken as the
1347 * Aggregating node and the AS_PATH is to be
1348 * constructed "as in all other cases"
1349 */
Paul Jakmab881c702010-11-23 16:35:42 +00001350 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001351 {
1352 /* ignore */
1353 if ( BGP_DEBUG(as4, AS4))
1354 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1355 " send AGGREGATOR != AS_TRANS and"
1356 " AS4_AGGREGATOR, so ignore"
1357 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1358 ignore_as4_path = 1;
1359 }
1360 else
1361 {
1362 /* "New_aggregator shall be taken as aggregator" */
1363 attre->aggregator_as = as4_aggregator;
1364 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1365 }
1366 }
1367 else
1368 {
1369 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1370 * That is bogus - but reading the conditions
1371 * we have to handle AS4_AGGREGATOR as if it were
1372 * AGGREGATOR in that case
1373 */
1374 if ( BGP_DEBUG(as4, AS4))
1375 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1376 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1377 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001378 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001379 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1380 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1381 }
1382 }
1383
1384 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001385 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001386 {
Paul Jakma055086f2014-09-23 15:23:01 +01001387 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1388 aspath_unintern (&attr->aspath);
1389 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001390 }
Paul Jakmab881c702010-11-23 16:35:42 +00001391 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001392}
1393
paul718e3742002-12-13 20:15:29 +00001394/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001395static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001396bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001397{
Paul Jakma835315b2012-01-18 12:28:30 +00001398 struct peer *const peer = args->peer;
1399 struct attr *const attr = args->attr;
1400 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001401
paul718e3742002-12-13 20:15:29 +00001402 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001403 {
1404 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001405 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001406 }
Paul Jakma0c466382010-12-05 17:17:26 +00001407
1408 attr->community =
1409 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1410
1411 /* XXX: fix community_parse to use stream API and remove this */
1412 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001413
Paul Jakma0c466382010-12-05 17:17:26 +00001414 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001415 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001416 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001417 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001418
paul718e3742002-12-13 20:15:29 +00001419 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1420
Paul Jakmab881c702010-11-23 16:35:42 +00001421 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001422}
1423
1424/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001425static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001426bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001427{
Paul Jakma835315b2012-01-18 12:28:30 +00001428 struct peer *const peer = args->peer;
1429 struct attr *const attr = args->attr;
1430 const bgp_size_t length = args->length;
1431
Denis Ovsienkod595b562011-09-30 15:08:54 +04001432 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001433 if (length != 4)
1434 {
1435 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1436
Paul Jakma835315b2012-01-18 12:28:30 +00001437 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001438 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001439 args->total);
paul718e3742002-12-13 20:15:29 +00001440 }
1441
Paul Jakmafb982c22007-05-04 20:15:47 +00001442 (bgp_attr_extra_get (attr))->originator_id.s_addr
1443 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001444
1445 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1446
Paul Jakmab881c702010-11-23 16:35:42 +00001447 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001448}
1449
1450/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001451static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001452bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001453{
Paul Jakma835315b2012-01-18 12:28:30 +00001454 struct peer *const peer = args->peer;
1455 struct attr *const attr = args->attr;
1456 const bgp_size_t length = args->length;
1457
paul718e3742002-12-13 20:15:29 +00001458 /* Check length. */
1459 if (length % 4)
1460 {
1461 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1462
Paul Jakma835315b2012-01-18 12:28:30 +00001463 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1464 args->total);
paul718e3742002-12-13 20:15:29 +00001465 }
1466
Paul Jakmafb982c22007-05-04 20:15:47 +00001467 (bgp_attr_extra_get (attr))->cluster
1468 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001469
1470 /* XXX: Fix cluster_parse to use stream API and then remove this */
1471 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001472
1473 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1474
Paul Jakmab881c702010-11-23 16:35:42 +00001475 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001476}
1477
1478/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001479int
Paul Jakma835315b2012-01-18 12:28:30 +00001480bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1481 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001482{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001483 afi_t afi;
1484 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001485 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001486 size_t start;
paul718e3742002-12-13 20:15:29 +00001487 int ret;
1488 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001489 struct peer *const peer = args->peer;
1490 struct attr *const attr = args->attr;
1491 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001492 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001493
paul718e3742002-12-13 20:15:29 +00001494 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001495 s = BGP_INPUT(peer);
1496 start = stream_get_getp(s);
1497
1498 /* safe to read statically sized header? */
1499#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001500#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001501 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001502 {
1503 zlog_info ("%s: %s sent invalid length, %lu",
1504 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001505 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001506 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001507
paul718e3742002-12-13 20:15:29 +00001508 /* Load AFI, SAFI. */
1509 afi = stream_getw (s);
1510 safi = stream_getc (s);
1511
1512 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001513 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001514
Paul Jakma03292802008-06-07 20:37:10 +00001515 if (LEN_LEFT < attre->mp_nexthop_len)
1516 {
1517 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1518 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001519 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001520 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001521
paul718e3742002-12-13 20:15:29 +00001522 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001523 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001524 {
1525 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001526 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001527 /* Probably needed for RFC 2283 */
1528 if (attr->nexthop.s_addr == 0)
1529 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001530 break;
1531 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001532 stream_getl (s); /* RD high */
1533 stream_getl (s); /* RD low */
1534 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001535 break;
1536#ifdef HAVE_IPV6
1537 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001538 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001539 break;
1540 case 32:
Paul Jakmafb982c22007-05-04 20:15:47 +00001541 stream_get (&attre->mp_nexthop_global, s, 16);
1542 stream_get (&attre->mp_nexthop_local, s, 16);
1543 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001544 {
1545 char buf1[INET6_ADDRSTRLEN];
1546 char buf2[INET6_ADDRSTRLEN];
1547
1548 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001549 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 +00001550 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001551 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001552 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001553 buf2, INET6_ADDRSTRLEN));
1554
Paul Jakmafb982c22007-05-04 20:15:47 +00001555 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001556 }
1557 break;
1558#endif /* HAVE_IPV6 */
1559 default:
Paul Jakma03292802008-06-07 20:37:10 +00001560 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1561 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001562 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001563 }
1564
Paul Jakma03292802008-06-07 20:37:10 +00001565 if (!LEN_LEFT)
1566 {
1567 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1568 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001569 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001570 }
paul718e3742002-12-13 20:15:29 +00001571
Paul Jakma6e4ab122007-04-10 19:36:48 +00001572 {
1573 u_char val;
1574 if ((val = stream_getc (s)))
1575 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1576 peer->host, val);
1577 }
1578
1579 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001580 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001581 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001582 {
1583 zlog_info ("%s: (%s) Failed to read NLRI",
1584 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001585 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001586 }
paul718e3742002-12-13 20:15:29 +00001587
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001588 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001589 {
1590 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
Paul Jakma03292802008-06-07 20:37:10 +00001591 if (ret < 0)
1592 {
1593 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1594 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001595 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001596 }
paul718e3742002-12-13 20:15:29 +00001597 }
1598
1599 mp_update->afi = afi;
1600 mp_update->safi = safi;
1601 mp_update->nlri = stream_pnt (s);
1602 mp_update->length = nlri_len;
1603
paul9985f832005-02-09 15:51:56 +00001604 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001605
David Lamparterdaefeb82014-12-08 17:42:12 +01001606 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1607
Paul Jakmab881c702010-11-23 16:35:42 +00001608 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001609#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001610}
1611
1612/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001613int
Paul Jakma835315b2012-01-18 12:28:30 +00001614bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001615 struct bgp_nlri *mp_withdraw)
1616{
1617 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001618 afi_t afi;
1619 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001620 u_int16_t withdraw_len;
1621 int ret;
Paul Jakma835315b2012-01-18 12:28:30 +00001622 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001623 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001624 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001625
1626 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001627
1628#define BGP_MP_UNREACH_MIN_SIZE 3
1629 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001630 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001631
paul718e3742002-12-13 20:15:29 +00001632 afi = stream_getw (s);
1633 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001634
1635 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001636
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001637 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001638 {
1639 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1640 if (ret < 0)
David Lamparterf57000c2014-06-04 01:01:10 +02001641 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001642 }
1643
1644 mp_withdraw->afi = afi;
1645 mp_withdraw->safi = safi;
1646 mp_withdraw->nlri = stream_pnt (s);
1647 mp_withdraw->length = withdraw_len;
1648
paul9985f832005-02-09 15:51:56 +00001649 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001650
David Lamparterdaefeb82014-12-08 17:42:12 +01001651 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1652
Paul Jakmab881c702010-11-23 16:35:42 +00001653 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001654}
1655
1656/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001657static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001658bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001659{
Paul Jakma835315b2012-01-18 12:28:30 +00001660 struct peer *const peer = args->peer;
1661 struct attr *const attr = args->attr;
1662 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001663
paul718e3742002-12-13 20:15:29 +00001664 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001665 {
1666 if (attr->extra)
1667 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001668 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001669 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001670 }
Paul Jakma0c466382010-12-05 17:17:26 +00001671
1672 (bgp_attr_extra_get (attr))->ecommunity =
1673 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1674 /* XXX: fix ecommunity_parse to use stream API */
1675 stream_forward_getp (peer->ibuf, length);
1676
1677 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001678 return bgp_attr_malformed (args,
1679 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1680 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001681
paul718e3742002-12-13 20:15:29 +00001682 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1683
Paul Jakmab881c702010-11-23 16:35:42 +00001684 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001685}
1686
1687/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001688static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001689bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001690{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001691 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001692 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001693 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001694 struct peer *const peer = args->peer;
1695 struct attr *const attr = args->attr;
1696 u_char *const startp = args->startp;
1697 const u_char type = args->type;
1698 const u_char flag = args->flags;
1699 const bgp_size_t length = args->length;
1700
paul718e3742002-12-13 20:15:29 +00001701
hassof4184462005-02-01 20:13:16 +00001702 if (BGP_DEBUG (normal, NORMAL))
1703 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1704 peer->host, type, length);
1705
paul718e3742002-12-13 20:15:29 +00001706 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001707 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001708 "Unknown attribute type %d length %d is received", type, length);
1709
1710 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001711 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001712
paul718e3742002-12-13 20:15:29 +00001713 /* If any of the mandatory well-known attributes are not recognized,
1714 then the Error Subcode is set to Unrecognized Well-known
1715 Attribute. The Data field contains the unrecognized attribute
1716 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001717 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001718 {
Paul Jakma835315b2012-01-18 12:28:30 +00001719 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001720 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001721 args->total);
paul718e3742002-12-13 20:15:29 +00001722 }
1723
1724 /* Unrecognized non-transitive optional attributes must be quietly
1725 ignored and not passed along to other BGP peers. */
1726 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001727 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001728
1729 /* If a path with recognized transitive optional attribute is
1730 accepted and passed along to other BGP peers and the Partial bit
1731 in the Attribute Flags octet is set to 1 by some previous AS, it
1732 is not set back to 0 by the current AS. */
1733 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1734
1735 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001736 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001737 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001738
Paul Jakmafb982c22007-05-04 20:15:47 +00001739 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001740
1741 if (transit->val)
1742 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1743 transit->length + total);
1744 else
1745 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1746
1747 memcpy (transit->val + transit->length, startp, total);
1748 transit->length += total;
1749
Paul Jakmab881c702010-11-23 16:35:42 +00001750 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001751}
1752
Paul Jakma055086f2014-09-23 15:23:01 +01001753/* Well-known attribute check. */
1754static int
1755bgp_attr_check (struct peer *peer, struct attr *attr)
1756{
1757 u_char type = 0;
1758
Paul Jakmaaed1b552014-10-21 16:59:01 +01001759 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
1760 * empty UPDATE. */
1761 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
1762 return BGP_ATTR_PARSE_PROCEED;
1763
1764 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
1765 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
1766 are present, it should. Check for any other attribute being present
1767 instead.
1768 */
1769 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
1770 return BGP_ATTR_PARSE_PROCEED;
1771
Paul Jakma055086f2014-09-23 15:23:01 +01001772 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
1773 type = BGP_ATTR_ORIGIN;
1774
1775 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
1776 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001777
1778 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
1779 * NLRI is empty. We can't easily check NLRI empty here though.
1780 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00001781 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
1782 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01001783 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01001784
Paul Jakma055086f2014-09-23 15:23:01 +01001785 if (peer->sort == BGP_PEER_IBGP
1786 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
1787 type = BGP_ATTR_LOCAL_PREF;
1788
1789 if (type)
1790 {
1791 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01001792 "%s Missing well-known attribute %d / %s",
1793 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01001794 bgp_notify_send_with_data (peer,
1795 BGP_NOTIFY_UPDATE_ERR,
1796 BGP_NOTIFY_UPDATE_MISS_ATTR,
1797 &type, 1);
1798 return BGP_ATTR_PARSE_ERROR;
1799 }
1800 return BGP_ATTR_PARSE_PROCEED;
1801}
1802
paul718e3742002-12-13 20:15:29 +00001803/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00001804 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00001805bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00001806bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1807 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1808{
1809 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00001810 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001811 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00001812 bgp_size_t length;
1813 u_char *startp, *endp;
1814 u_char *attr_endp;
1815 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001816 /* we need the as4_path only until we have synthesized the as_path with it */
1817 /* same goes for as4_aggregator */
1818 struct aspath *as4_path = NULL;
1819 as_t as4_aggregator = 0;
1820 struct in_addr as4_aggregator_addr = { 0 };
paul718e3742002-12-13 20:15:29 +00001821
1822 /* Initialize bitmap. */
1823 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1824
1825 /* End pointer of BGP attribute. */
1826 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00001827
paul718e3742002-12-13 20:15:29 +00001828 /* Get attributes to the end of attribute length. */
1829 while (BGP_INPUT_PNT (peer) < endp)
1830 {
1831 /* Check remaining length check.*/
1832 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1833 {
gdtc29fdba2004-12-09 14:46:46 +00001834 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00001835 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001836 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001837 peer->host,
1838 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00001839
1840 bgp_notify_send (peer,
1841 BGP_NOTIFY_UPDATE_ERR,
1842 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001843 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001844 }
1845
1846 /* Fetch attribute flag and type. */
1847 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04001848 /* "The lower-order four bits of the Attribute Flags octet are
1849 unused. They MUST be zero when sent and MUST be ignored when
1850 received." */
1851 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00001852 type = stream_getc (BGP_INPUT (peer));
1853
Paul Jakma370b64a2007-12-22 16:49:52 +00001854 /* Check whether Extended-Length applies and is in bounds */
1855 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1856 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1857 {
1858 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001859 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00001860 peer->host,
1861 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1862
1863 bgp_notify_send (peer,
1864 BGP_NOTIFY_UPDATE_ERR,
1865 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001866 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00001867 }
Paul Jakma835315b2012-01-18 12:28:30 +00001868
paul718e3742002-12-13 20:15:29 +00001869 /* Check extended attribue length bit. */
1870 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1871 length = stream_getw (BGP_INPUT (peer));
1872 else
1873 length = stream_getc (BGP_INPUT (peer));
1874
1875 /* If any attribute appears more than once in the UPDATE
1876 message, then the Error Subcode is set to Malformed Attribute
1877 List. */
1878
1879 if (CHECK_BITMAP (seen, type))
1880 {
1881 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001882 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00001883 peer->host, type);
1884
1885 bgp_notify_send (peer,
1886 BGP_NOTIFY_UPDATE_ERR,
1887 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00001888 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001889 }
1890
1891 /* Set type to bitmap to check duplicate attribute. `type' is
1892 unsigned char so it never overflow bitmap range. */
1893
1894 SET_BITMAP (seen, type);
1895
1896 /* Overflow check. */
1897 attr_endp = BGP_INPUT_PNT (peer) + length;
1898
1899 if (attr_endp > endp)
1900 {
1901 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04001902 "%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 +00001903 bgp_notify_send (peer,
1904 BGP_NOTIFY_UPDATE_ERR,
1905 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00001906 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001907 }
Paul Jakma835315b2012-01-18 12:28:30 +00001908
1909 struct bgp_attr_parser_args attr_args = {
1910 .peer = peer,
1911 .length = length,
1912 .attr = attr,
1913 .type = type,
1914 .flags = flag,
1915 .startp = startp,
1916 .total = attr_endp - startp,
1917 };
1918
1919
1920 /* If any recognized attribute has Attribute Flags that conflict
1921 with the Attribute Type Code, then the Error Subcode is set to
1922 Attribute Flags Error. The Data field contains the erroneous
1923 attribute (type, length and value). */
1924 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01001925 {
1926 bgp_attr_parse_ret_t ret;
1927 ret = bgp_attr_malformed (&attr_args,
1928 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1929 attr_args.total);
1930 if (ret == BGP_ATTR_PARSE_PROCEED)
1931 continue;
1932 return ret;
1933 }
paul718e3742002-12-13 20:15:29 +00001934
1935 /* OK check attribute and store it's value. */
1936 switch (type)
1937 {
1938 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00001939 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00001940 break;
1941 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001942 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00001943 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001944 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00001945 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001946 break;
paul718e3742002-12-13 20:15:29 +00001947 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00001948 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00001949 break;
1950 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00001951 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00001952 break;
1953 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00001954 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00001955 break;
1956 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00001957 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00001958 break;
1959 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001960 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00001961 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001962 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00001963 ret = bgp_attr_as4_aggregator (&attr_args,
1964 &as4_aggregator,
1965 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001966 break;
paul718e3742002-12-13 20:15:29 +00001967 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001968 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00001969 break;
1970 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00001971 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00001972 break;
1973 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00001974 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00001975 break;
1976 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001977 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00001978 break;
1979 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00001980 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00001981 break;
1982 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00001983 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00001984 break;
1985 default:
Paul Jakma835315b2012-01-18 12:28:30 +00001986 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00001987 break;
1988 }
Paul Jakmab881c702010-11-23 16:35:42 +00001989
David Lamparterf57000c2014-06-04 01:01:10 +02001990 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
1991 {
1992 bgp_notify_send (peer,
1993 BGP_NOTIFY_UPDATE_ERR,
1994 BGP_NOTIFY_UPDATE_MAL_ATTR);
1995 ret = BGP_ATTR_PARSE_ERROR;
1996 }
1997
Paul Jakmab881c702010-11-23 16:35:42 +00001998 /* If hard error occured immediately return to the caller. */
1999 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002000 {
2001 zlog (peer->log, LOG_WARNING,
2002 "%s: Attribute %s, parse error",
2003 peer->host,
2004 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002005 if (as4_path)
2006 aspath_unintern (&as4_path);
2007 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002008 }
Paul Jakmab881c702010-11-23 16:35:42 +00002009 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2010 {
2011
2012 zlog (peer->log, LOG_WARNING,
2013 "%s: Attribute %s, parse error - treating as withdrawal",
2014 peer->host,
2015 LOOKUP (attr_str, type));
2016 if (as4_path)
2017 aspath_unintern (&as4_path);
2018 return ret;
2019 }
2020
paul718e3742002-12-13 20:15:29 +00002021 /* Check the fetched length. */
2022 if (BGP_INPUT_PNT (peer) != attr_endp)
2023 {
2024 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002025 "%s: BGP attribute %s, fetch error",
2026 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002027 bgp_notify_send (peer,
2028 BGP_NOTIFY_UPDATE_ERR,
2029 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002030 if (as4_path)
2031 aspath_unintern (&as4_path);
2032 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002033 }
2034 }
paul718e3742002-12-13 20:15:29 +00002035 /* Check final read pointer is same as end pointer. */
2036 if (BGP_INPUT_PNT (peer) != endp)
2037 {
2038 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002039 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002040 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002041 bgp_notify_send (peer,
2042 BGP_NOTIFY_UPDATE_ERR,
2043 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002044 if (as4_path)
2045 aspath_unintern (&as4_path);
2046 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002047 }
Paul Jakma055086f2014-09-23 15:23:01 +01002048
2049 /* Check all mandatory well-known attributes are present */
2050 {
2051 bgp_attr_parse_ret_t ret;
2052 if ((ret = bgp_attr_check (peer, attr)) < 0)
2053 {
2054 if (as4_path)
2055 aspath_unintern (&as4_path);
2056 return ret;
2057 }
2058 }
2059
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002060 /*
2061 * At this place we can see whether we got AS4_PATH and/or
2062 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2063 * We can not do this before we've read all attributes because
2064 * the as4 handling does not say whether AS4_PATH has to be sent
2065 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2066 * in relationship to AGGREGATOR.
2067 * So, to be defensive, we are not relying on any order and read
2068 * all attributes first, including these 32bit ones, and now,
2069 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002070 *
2071 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2072 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002073 */
David Lamparterf57000c2014-06-04 01:01:10 +02002074 /* actually... this doesn't ever return failure currently, but
2075 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002076 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2077 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002078 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002079 {
David Lamparterf57000c2014-06-04 01:01:10 +02002080 bgp_notify_send (peer,
2081 BGP_NOTIFY_UPDATE_ERR,
2082 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002083 if (as4_path)
2084 aspath_unintern (&as4_path);
2085 return BGP_ATTR_PARSE_ERROR;
2086 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002087
2088 /* At this stage, we have done all fiddling with as4, and the
2089 * resulting info is in attr->aggregator resp. attr->aspath
2090 * so we can chuck as4_aggregator and as4_path alltogether in
2091 * order to save memory
2092 */
Paul Jakmab881c702010-11-23 16:35:42 +00002093 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002094 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002095 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002096 /* The flag that we got this is still there, but that does not
2097 * do any trouble
2098 */
2099 }
2100 /*
2101 * The "rest" of the code does nothing with as4_aggregator.
2102 * there is no memory attached specifically which is not part
2103 * of the attr.
2104 * so ignoring just means do nothing.
2105 */
2106 /*
2107 * Finally do the checks on the aspath we did not do yet
2108 * because we waited for a potentially synthesized aspath.
2109 */
Paul Jakmab881c702010-11-23 16:35:42 +00002110 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002111 {
Paul Jakma835315b2012-01-18 12:28:30 +00002112 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002113 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002114 return ret;
2115 }
2116
paul718e3742002-12-13 20:15:29 +00002117 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002118 if (attr->extra && attr->extra->transit)
2119 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002120
Paul Jakmab881c702010-11-23 16:35:42 +00002121 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002122}
2123
paul718e3742002-12-13 20:15:29 +00002124int stream_put_prefix (struct stream *, struct prefix *);
2125
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002126size_t
2127bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2128 struct attr *attr)
2129{
2130 size_t sizep;
2131
2132 /* Set extended bit always to encode the attribute length as 2 bytes */
2133 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2134 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2135 sizep = stream_get_endp (s);
2136 stream_putw (s, 0); /* Marker: Attribute length. */
2137 stream_putw (s, afi); /* AFI */
2138 stream_putc (s, safi); /* SAFI */
2139
2140 /* Nexthop */
2141 switch (afi)
2142 {
2143 case AFI_IP:
2144 switch (safi)
2145 {
2146 case SAFI_UNICAST:
2147 case SAFI_MULTICAST:
2148 stream_putc (s, 4);
2149 stream_put_ipv4 (s, attr->nexthop.s_addr);
2150 break;
2151 case SAFI_MPLS_VPN:
2152 stream_putc (s, 12);
2153 stream_putl (s, 0);
2154 stream_putl (s, 0);
2155 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2156 break;
2157 default:
2158 break;
2159 }
2160 break;
2161#ifdef HAVE_IPV6
2162 case AFI_IP6:
2163 switch (safi)
2164 {
2165 case SAFI_UNICAST:
2166 case SAFI_MULTICAST:
2167 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002168 struct attr_extra *attre = attr->extra;
2169
2170 assert (attr->extra);
2171 stream_putc (s, attre->mp_nexthop_len);
2172 stream_put (s, &attre->mp_nexthop_global, 16);
2173 if (attre->mp_nexthop_len == 32)
2174 stream_put (s, &attre->mp_nexthop_local, 16);
2175 }
2176 default:
2177 break;
2178 }
2179 break;
2180#endif /*HAVE_IPV6*/
2181 default:
2182 break;
2183 }
2184
2185 /* SNPA */
2186 stream_putc (s, 0);
2187 return sizep;
2188}
2189
2190void
2191bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2192 struct prefix *p, struct prefix_rd *prd,
2193 u_char *tag)
2194{
2195 switch (safi)
2196 {
2197 case SAFI_MPLS_VPN:
2198 /* Tag, RD, Prefix write. */
2199 stream_putc (s, p->prefixlen + 88);
2200 stream_put (s, tag, 3);
2201 stream_put (s, prd->val, 8);
2202 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2203 break;
2204 default:
2205 /* Prefix write. */
2206 stream_put_prefix (s, p);
2207 break;
2208 }
2209}
2210
2211void
2212bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2213{
2214 /* Set MP attribute length. Don't count the (2) bytes used to encode
2215 the attr length */
2216 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2217}
2218
paul718e3742002-12-13 20:15:29 +00002219/* Make attribute packet. */
2220bgp_size_t
2221bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002222 struct stream *s, struct attr *attr,
2223 struct prefix *p, afi_t afi, safi_t safi,
2224 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002225{
paulfe69a502005-09-10 16:55:02 +00002226 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002227 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002228 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002229 int send_as4_path = 0;
2230 int send_as4_aggregator = 0;
2231 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002232 size_t mpattrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +00002233
2234 if (! bgp)
2235 bgp = bgp_get_default ();
2236
2237 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002238 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002239
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002240 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2241 {
2242 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2243 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2244 bgp_packet_mpattr_end(s, mpattrlen_pos);
2245 }
2246
paul718e3742002-12-13 20:15:29 +00002247 /* Origin attribute. */
2248 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2249 stream_putc (s, BGP_ATTR_ORIGIN);
2250 stream_putc (s, 1);
2251 stream_putc (s, attr->origin);
2252
2253 /* AS path attribute. */
2254
2255 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002256 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002257 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002258 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002259 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002260 {
2261 aspath = aspath_dup (attr->aspath);
2262
2263 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2264 {
2265 /* Strip the confed info, and then stuff our path CONFED_ID
2266 on the front */
2267 aspath = aspath_delete_confed_seq (aspath);
2268 aspath = aspath_add_seq (aspath, bgp->confed_id);
2269 }
2270 else
2271 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002272 if (peer->change_local_as) {
2273 /* If replace-as is specified, we only use the change_local_as when
2274 advertising routes. */
2275 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2276 aspath = aspath_add_seq (aspath, peer->local_as);
2277 }
paul718e3742002-12-13 20:15:29 +00002278 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002279 } else {
2280 aspath = aspath_add_seq (aspath, peer->local_as);
2281 }
paul718e3742002-12-13 20:15:29 +00002282 }
2283 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002284 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002285 {
2286 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2287 aspath = aspath_dup (attr->aspath);
2288 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2289 }
2290 else
2291 aspath = attr->aspath;
2292
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002293 /* If peer is not AS4 capable, then:
2294 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2295 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2296 * types are in it (i.e. exclude them if they are there)
2297 * AND do this only if there is at least one asnum > 65535 in the path!
2298 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2299 * all ASnums > 65535 to BGP_AS_TRANS
2300 */
paul718e3742002-12-13 20:15:29 +00002301
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002302 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2303 stream_putc (s, BGP_ATTR_AS_PATH);
2304 aspath_sizep = stream_get_endp (s);
2305 stream_putw (s, 0);
2306 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2307
2308 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2309 * in the path
2310 */
2311 if (!use32bit && aspath_has_as4 (aspath))
2312 send_as4_path = 1; /* we'll do this later, at the correct place */
2313
paul718e3742002-12-13 20:15:29 +00002314 /* Nexthop attribute. */
2315 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2316 {
2317 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2318 stream_putc (s, BGP_ATTR_NEXT_HOP);
2319 stream_putc (s, 4);
2320 if (safi == SAFI_MPLS_VPN)
2321 {
2322 if (attr->nexthop.s_addr == 0)
2323 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2324 else
2325 stream_put_ipv4 (s, attr->nexthop.s_addr);
2326 }
2327 else
2328 stream_put_ipv4 (s, attr->nexthop.s_addr);
2329 }
2330
2331 /* MED attribute. */
2332 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2333 {
2334 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2335 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2336 stream_putc (s, 4);
2337 stream_putl (s, attr->med);
2338 }
2339
2340 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002341 if (peer->sort == BGP_PEER_IBGP ||
2342 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002343 {
2344 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2345 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2346 stream_putc (s, 4);
2347 stream_putl (s, attr->local_pref);
2348 }
2349
2350 /* Atomic aggregate. */
2351 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2352 {
2353 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2354 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2355 stream_putc (s, 0);
2356 }
2357
2358 /* Aggregator. */
2359 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2360 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002361 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002362
2363 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002364 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2365 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002366
2367 if (use32bit)
2368 {
2369 /* AS4 capable peer */
2370 stream_putc (s, 8);
2371 stream_putl (s, attr->extra->aggregator_as);
2372 }
2373 else
2374 {
2375 /* 2-byte AS peer */
2376 stream_putc (s, 6);
2377
2378 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2379 if ( attr->extra->aggregator_as > 65535 )
2380 {
2381 stream_putw (s, BGP_AS_TRANS);
2382
2383 /* we have to send AS4_AGGREGATOR, too.
2384 * we'll do that later in order to send attributes in ascending
2385 * order.
2386 */
2387 send_as4_aggregator = 1;
2388 }
2389 else
2390 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2391 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002392 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002393 }
2394
2395 /* Community attribute. */
2396 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2397 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2398 {
2399 if (attr->community->size * 4 > 255)
2400 {
2401 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2402 stream_putc (s, BGP_ATTR_COMMUNITIES);
2403 stream_putw (s, attr->community->size * 4);
2404 }
2405 else
2406 {
2407 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2408 stream_putc (s, BGP_ATTR_COMMUNITIES);
2409 stream_putc (s, attr->community->size * 4);
2410 }
2411 stream_put (s, attr->community->val, attr->community->size * 4);
2412 }
2413
2414 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002415 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002416 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002417 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002418 {
2419 /* Originator ID. */
2420 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2421 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2422 stream_putc (s, 4);
2423
2424 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002425 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002426 else
2427 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002428
2429 /* Cluster list. */
2430 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2431 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2432
Paul Jakma9eda90c2007-08-30 13:36:17 +00002433 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002434 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002435 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002436 /* If this peer configuration's parent BGP has cluster_id. */
2437 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2438 stream_put_in_addr (s, &bgp->cluster_id);
2439 else
2440 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002441 stream_put (s, attr->extra->cluster->list,
2442 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002443 }
2444 else
2445 {
2446 stream_putc (s, 4);
2447 /* If this peer configuration's parent BGP has cluster_id. */
2448 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2449 stream_put_in_addr (s, &bgp->cluster_id);
2450 else
2451 stream_put_in_addr (s, &bgp->router_id);
2452 }
2453 }
2454
paul718e3742002-12-13 20:15:29 +00002455 /* Extended Communities attribute. */
2456 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2457 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2458 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002459 struct attr_extra *attre = attr->extra;
2460
2461 assert (attre);
2462
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002463 if (peer->sort == BGP_PEER_IBGP
2464 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002465 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002466 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002467 {
2468 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2469 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002470 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002471 }
2472 else
2473 {
2474 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2475 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002476 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002477 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002478 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002479 }
2480 else
2481 {
paul5228ad22004-06-04 17:58:18 +00002482 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002483 int tbit;
2484 int ecom_tr_size = 0;
2485 int i;
2486
Paul Jakmafb982c22007-05-04 20:15:47 +00002487 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002488 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002489 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002490 tbit = *pnt;
2491
2492 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2493 continue;
2494
2495 ecom_tr_size++;
2496 }
2497
2498 if (ecom_tr_size)
2499 {
2500 if (ecom_tr_size * 8 > 255)
2501 {
2502 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2503 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2504 stream_putw (s, ecom_tr_size * 8);
2505 }
2506 else
2507 {
2508 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2509 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2510 stream_putc (s, ecom_tr_size * 8);
2511 }
2512
Paul Jakmafb982c22007-05-04 20:15:47 +00002513 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002514 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002515 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002516 tbit = *pnt;
2517
2518 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2519 continue;
2520
2521 stream_put (s, pnt, 8);
2522 }
2523 }
paul718e3742002-12-13 20:15:29 +00002524 }
paul718e3742002-12-13 20:15:29 +00002525 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002526
2527 if ( send_as4_path )
2528 {
2529 /* If the peer is NOT As4 capable, AND */
2530 /* there are ASnums > 65535 in path THEN
2531 * give out AS4_PATH */
2532
2533 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2534 * path segments!
2535 * Hm, I wonder... confederation things *should* only be at
2536 * the beginning of an aspath, right? Then we should use
2537 * aspath_delete_confed_seq for this, because it is already
2538 * there! (JK)
2539 * Folks, talk to me: what is reasonable here!?
2540 */
2541 aspath = aspath_delete_confed_seq (aspath);
2542
2543 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2544 stream_putc (s, BGP_ATTR_AS4_PATH);
2545 aspath_sizep = stream_get_endp (s);
2546 stream_putw (s, 0);
2547 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2548 }
2549
2550 if (aspath != attr->aspath)
2551 aspath_free (aspath);
2552
2553 if ( send_as4_aggregator )
2554 {
2555 assert (attr->extra);
2556
2557 /* send AS4_AGGREGATOR, at this place */
2558 /* this section of code moved here in order to ensure the correct
2559 * *ascending* order of attributes
2560 */
2561 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2562 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2563 stream_putc (s, 8);
2564 stream_putl (s, attr->extra->aggregator_as);
2565 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2566 }
Paul Jakma41367172007-08-06 15:24:51 +00002567
paul718e3742002-12-13 20:15:29 +00002568 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002569 if (attr->extra && attr->extra->transit)
2570 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002571
2572 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002573 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002574}
2575
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002576size_t
2577bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002578{
paul718e3742002-12-13 20:15:29 +00002579 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002580
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002581 /* Set extended bit always to encode the attribute length as 2 bytes */
2582 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002583 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2584
paul9985f832005-02-09 15:51:56 +00002585 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002586 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002587
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002588 stream_putw (s, afi);
2589 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
2590 stream_putc (s, safi);
2591 return attrlen_pnt;
2592}
paul718e3742002-12-13 20:15:29 +00002593
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002594void
2595bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2596 afi_t afi, safi_t safi, struct prefix_rd *prd,
2597 u_char *tag)
2598{
paul718e3742002-12-13 20:15:29 +00002599 if (safi == SAFI_MPLS_VPN)
2600 {
paul718e3742002-12-13 20:15:29 +00002601 stream_putc (s, p->prefixlen + 88);
2602 stream_put (s, tag, 3);
2603 stream_put (s, prd->val, 8);
2604 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2605 }
2606 else
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002607 stream_put_prefix (s, p);
2608}
paul718e3742002-12-13 20:15:29 +00002609
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002610void
2611bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2612{
2613 bgp_size_t size;
paul718e3742002-12-13 20:15:29 +00002614
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002615 /* Set MP attribute length. Don't count the (2) bytes used to encode
2616 the attr length */
2617 size = stream_get_endp (s) - attrlen_pnt - 2;
2618 stream_putw_at (s, attrlen_pnt, size);
paul718e3742002-12-13 20:15:29 +00002619}
2620
2621/* Initialization of attribute. */
2622void
paulfe69a502005-09-10 16:55:02 +00002623bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002624{
paul718e3742002-12-13 20:15:29 +00002625 aspath_init ();
2626 attrhash_init ();
2627 community_init ();
2628 ecommunity_init ();
2629 cluster_init ();
2630 transit_init ();
2631}
2632
Chris Caputo228da422009-07-18 05:44:03 +00002633void
2634bgp_attr_finish (void)
2635{
2636 aspath_finish ();
2637 attrhash_finish ();
2638 community_finish ();
2639 ecommunity_finish ();
2640 cluster_finish ();
2641 transit_finish ();
2642}
2643
paul718e3742002-12-13 20:15:29 +00002644/* Make attribute packet. */
2645void
paula3845922003-10-18 01:30:50 +00002646bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2647 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00002648{
2649 unsigned long cp;
2650 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002651 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00002652 struct aspath *aspath;
2653
2654 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002655 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002656
2657 /* Place holder of length. */
2658 stream_putw (s, 0);
2659
2660 /* Origin attribute. */
2661 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2662 stream_putc (s, BGP_ATTR_ORIGIN);
2663 stream_putc (s, 1);
2664 stream_putc (s, attr->origin);
2665
2666 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002667
2668 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2669 stream_putc (s, BGP_ATTR_AS_PATH);
2670 aspath_lenp = stream_get_endp (s);
2671 stream_putw (s, 0);
2672
2673 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00002674
2675 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00002676 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2677 if(prefix != NULL
2678#ifdef HAVE_IPV6
2679 && prefix->family != AF_INET6
2680#endif /* HAVE_IPV6 */
2681 )
2682 {
2683 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2684 stream_putc (s, BGP_ATTR_NEXT_HOP);
2685 stream_putc (s, 4);
2686 stream_put_ipv4 (s, attr->nexthop.s_addr);
2687 }
paul718e3742002-12-13 20:15:29 +00002688
2689 /* MED attribute. */
2690 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2691 {
2692 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2693 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2694 stream_putc (s, 4);
2695 stream_putl (s, attr->med);
2696 }
2697
2698 /* Local preference. */
2699 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2700 {
2701 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2702 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2703 stream_putc (s, 4);
2704 stream_putl (s, attr->local_pref);
2705 }
2706
2707 /* Atomic aggregate. */
2708 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2709 {
2710 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2711 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2712 stream_putc (s, 0);
2713 }
2714
2715 /* Aggregator. */
2716 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2717 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002718 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00002719 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2720 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002721 stream_putc (s, 8);
2722 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00002723 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002724 }
2725
2726 /* Community attribute. */
2727 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2728 {
2729 if (attr->community->size * 4 > 255)
2730 {
2731 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2732 stream_putc (s, BGP_ATTR_COMMUNITIES);
2733 stream_putw (s, attr->community->size * 4);
2734 }
2735 else
2736 {
2737 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2738 stream_putc (s, BGP_ATTR_COMMUNITIES);
2739 stream_putc (s, attr->community->size * 4);
2740 }
2741 stream_put (s, attr->community->val, attr->community->size * 4);
2742 }
2743
paula3845922003-10-18 01:30:50 +00002744#ifdef HAVE_IPV6
2745 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002746 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2747 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00002748 {
2749 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00002750 struct attr_extra *attre = attr->extra;
2751
paula3845922003-10-18 01:30:50 +00002752 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2753 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00002754 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00002755
2756 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00002757 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00002758 stream_putw(s, AFI_IP6); /* AFI */
2759 stream_putc(s, SAFI_UNICAST); /* SAFI */
2760
2761 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00002762 stream_putc(s, attre->mp_nexthop_len);
2763 stream_put(s, &attre->mp_nexthop_global, 16);
2764 if (attre->mp_nexthop_len == 32)
2765 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00002766
2767 /* SNPA */
2768 stream_putc(s, 0);
2769
2770 /* Prefix */
2771 stream_put_prefix(s, prefix);
2772
2773 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00002774 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00002775 }
2776#endif /* HAVE_IPV6 */
2777
paul718e3742002-12-13 20:15:29 +00002778 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002779 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00002780 stream_putw_at (s, cp, len);
2781}