blob: b019347bf62ce55b86fa0a9cf34947e0b17e259a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "memory.h"
26#include "vector.h"
27#include "vty.h"
28#include "stream.h"
29#include "log.h"
30#include "hash.h"
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -070031#include "jhash.h"
Donald Sharp04907292016-01-07 10:03:01 -050032#include "filter.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_route.h"
37#include "bgpd/bgp_aspath.h"
38#include "bgpd/bgp_community.h"
39#include "bgpd/bgp_debug.h"
40#include "bgpd/bgp_packet.h"
41#include "bgpd/bgp_ecommunity.h"
Lou Bergerc3741782016-01-12 13:42:01 -050042#include "table.h"
43#include "bgp_encap_types.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020044
paul718e3742002-12-13 20:15:29 +000045/* Attribute strings for logging. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -070046static const struct message attr_str [] =
paul718e3742002-12-13 20:15:29 +000047{
48 { BGP_ATTR_ORIGIN, "ORIGIN" },
49 { BGP_ATTR_AS_PATH, "AS_PATH" },
50 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
51 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
52 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
53 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
54 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
55 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
56 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
Denis Ovsienkof8627ff2011-10-10 16:52:20 +040057 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
paul718e3742002-12-13 20:15:29 +000058 { BGP_ATTR_DPA, "DPA" },
59 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
60 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
61 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
62 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000063 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
64 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
65 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
66 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
Lou Bergerc3741782016-01-12 13:42:01 -050067 { BGP_ATTR_ENCAP, "ENCAP" },
paul718e3742002-12-13 20:15:29 +000068};
Balaji.G837d16c2012-09-26 14:09:10 +053069static const int attr_str_max = array_size(attr_str);
Denis Ovsienkoafcb7672011-10-23 22:32:44 +040070
71static const struct message attr_flag_str[] =
72{
73 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
74 { BGP_ATTR_FLAG_TRANS, "Transitive" },
75 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
76 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
77 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
78};
David Lamparter6b0655a2014-06-04 06:53:35 +020079
Stephen Hemminger9bddac42009-05-15 09:59:51 -070080static struct hash *cluster_hash;
paul718e3742002-12-13 20:15:29 +000081
paul94f2b392005-06-28 12:44:16 +000082static void *
Paul Jakma923de652007-04-29 18:25:17 +000083cluster_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +000084{
Paul Jakma923de652007-04-29 18:25:17 +000085 struct cluster_list * val = (struct cluster_list *) p;
paul718e3742002-12-13 20:15:29 +000086 struct cluster_list *cluster;
87
88 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
89 cluster->length = val->length;
90
91 if (cluster->length)
92 {
93 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
94 memcpy (cluster->list, val->list, val->length);
95 }
96 else
97 cluster->list = NULL;
98
99 cluster->refcnt = 0;
100
101 return cluster;
102}
103
104/* Cluster list related functions. */
paul94f2b392005-06-28 12:44:16 +0000105static struct cluster_list *
paul5228ad22004-06-04 17:58:18 +0000106cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +0000107{
108 struct cluster_list tmp;
109 struct cluster_list *cluster;
110
111 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +0000112 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +0000113
114 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
115 cluster->refcnt++;
116 return cluster;
117}
118
119int
120cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
121{
122 int i;
123
124 for (i = 0; i < cluster->length / 4; i++)
125 if (cluster->list[i].s_addr == originator.s_addr)
126 return 1;
127 return 0;
128}
129
paul94f2b392005-06-28 12:44:16 +0000130static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000131cluster_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000132{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700133 const struct cluster_list *cluster = p;
paul718e3742002-12-13 20:15:29 +0000134
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700135 return jhash(cluster->list, cluster->length, 0);
paul718e3742002-12-13 20:15:29 +0000136}
137
paul94f2b392005-06-28 12:44:16 +0000138static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100139cluster_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000140{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100141 const struct cluster_list * cluster1 = p1;
142 const struct cluster_list * cluster2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000143
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100144 return (cluster1->length == cluster2->length &&
145 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000146}
147
paul94f2b392005-06-28 12:44:16 +0000148static void
paul718e3742002-12-13 20:15:29 +0000149cluster_free (struct cluster_list *cluster)
150{
151 if (cluster->list)
152 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
153 XFREE (MTYPE_CLUSTER, cluster);
154}
155
Chris Caputo228da422009-07-18 05:44:03 +0000156#if 0
paul94f2b392005-06-28 12:44:16 +0000157static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000158cluster_dup (struct cluster_list *cluster)
159{
160 struct cluster_list *new;
161
Stephen Hemminger393deb92008-08-18 14:13:29 -0700162 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
paul718e3742002-12-13 20:15:29 +0000163 new->length = cluster->length;
164
165 if (cluster->length)
166 {
167 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
168 memcpy (new->list, cluster->list, cluster->length);
169 }
170 else
171 new->list = NULL;
172
173 return new;
174}
Chris Caputo228da422009-07-18 05:44:03 +0000175#endif
paul718e3742002-12-13 20:15:29 +0000176
paul94f2b392005-06-28 12:44:16 +0000177static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000178cluster_intern (struct cluster_list *cluster)
179{
180 struct cluster_list *find;
181
182 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
183 find->refcnt++;
184
185 return find;
186}
187
188void
189cluster_unintern (struct cluster_list *cluster)
190{
paul718e3742002-12-13 20:15:29 +0000191 if (cluster->refcnt)
192 cluster->refcnt--;
193
194 if (cluster->refcnt == 0)
195 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400196 hash_release (cluster_hash, cluster);
paul718e3742002-12-13 20:15:29 +0000197 cluster_free (cluster);
198 }
199}
200
paul94f2b392005-06-28 12:44:16 +0000201static void
202cluster_init (void)
paul718e3742002-12-13 20:15:29 +0000203{
204 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
205}
Chris Caputo228da422009-07-18 05:44:03 +0000206
207static void
208cluster_finish (void)
209{
Lou Berger056f3762013-04-10 12:30:04 -0700210 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
Chris Caputo228da422009-07-18 05:44:03 +0000211 hash_free (cluster_hash);
212 cluster_hash = NULL;
213}
David Lamparter6b0655a2014-06-04 06:53:35 +0200214
Lou Bergerc3741782016-01-12 13:42:01 -0500215struct bgp_attr_encap_subtlv *
216encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
217{
218 struct bgp_attr_encap_subtlv *new;
219 struct bgp_attr_encap_subtlv *tail;
220 struct bgp_attr_encap_subtlv *p;
221
222 for (p = orig, tail = new = NULL; p; p = p->next) {
223 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
224 if (tail) {
225 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
226 tail = tail->next;
227 } else {
228 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
229 }
230 assert(tail);
231 memcpy(tail, p, size);
232 tail->next = NULL;
233 }
234
235 return new;
236}
237
238static void
239encap_free(struct bgp_attr_encap_subtlv *p)
240{
241 struct bgp_attr_encap_subtlv *next;
242 while (p) {
243 next = p->next;
244 p->next = NULL;
245 XFREE(MTYPE_ENCAP_TLV, p);
246 p = next;
247 }
248}
249
250void
251bgp_attr_flush_encap(struct attr *attr)
252{
253 if (!attr || !attr->extra)
254 return;
255
256 if (attr->extra->encap_subtlvs) {
257 encap_free(attr->extra->encap_subtlvs);
258 attr->extra->encap_subtlvs = NULL;
259 }
260}
261
262/*
263 * Compare encap sub-tlv chains
264 *
265 * 1 = equivalent
266 * 0 = not equivalent
267 *
268 * This algorithm could be made faster if needed
269 */
270static int
271encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
272{
273 struct bgp_attr_encap_subtlv *p;
274 struct bgp_attr_encap_subtlv *q;
275
276 if (!h1 && !h2)
277 return 1;
278 if (h1 && !h2)
279 return 0;
280 if (!h1 && h2)
281 return 0;
282 if (h1 == h2)
283 return 1;
284
285 for (p = h1; p; p = p->next) {
286 for (q = h2; q; q = q->next) {
287 if ((p->type == q->type) &&
288 (p->length == q->length) &&
289 !memcmp(p->value, q->value, p->length)) {
290
291 break;
292 }
293 }
294 if (!q)
295 return 0;
296 }
297
298 for (p = h2; p; p = p->next) {
299 for (q = h1; q; q = q->next) {
300 if ((p->type == q->type) &&
301 (p->length == q->length) &&
302 !memcmp(p->value, q->value, p->length)) {
303
304 break;
305 }
306 }
307 if (!q)
308 return 0;
309 }
310
311 return 1;
312}
313
paul718e3742002-12-13 20:15:29 +0000314/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700315static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000316
paul94f2b392005-06-28 12:44:16 +0000317static void
paul718e3742002-12-13 20:15:29 +0000318transit_free (struct transit *transit)
319{
320 if (transit->val)
321 XFREE (MTYPE_TRANSIT_VAL, transit->val);
322 XFREE (MTYPE_TRANSIT, transit);
323}
324
Paul Jakma923de652007-04-29 18:25:17 +0000325
paul94f2b392005-06-28 12:44:16 +0000326static void *
Paul Jakma923de652007-04-29 18:25:17 +0000327transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000328{
329 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000330 return p;
paul718e3742002-12-13 20:15:29 +0000331}
332
paul94f2b392005-06-28 12:44:16 +0000333static struct transit *
paul718e3742002-12-13 20:15:29 +0000334transit_intern (struct transit *transit)
335{
336 struct transit *find;
337
338 find = hash_get (transit_hash, transit, transit_hash_alloc);
339 if (find != transit)
340 transit_free (transit);
341 find->refcnt++;
342
343 return find;
344}
345
346void
347transit_unintern (struct transit *transit)
348{
paul718e3742002-12-13 20:15:29 +0000349 if (transit->refcnt)
350 transit->refcnt--;
351
352 if (transit->refcnt == 0)
353 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400354 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000355 transit_free (transit);
356 }
357}
358
paul94f2b392005-06-28 12:44:16 +0000359static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000360transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000361{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700362 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000363
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700364 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000365}
366
paul94f2b392005-06-28 12:44:16 +0000367static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100368transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000369{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100370 const struct transit * transit1 = p1;
371 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000372
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100373 return (transit1->length == transit2->length &&
374 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000375}
376
paul94f2b392005-06-28 12:44:16 +0000377static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800378transit_init (void)
paul718e3742002-12-13 20:15:29 +0000379{
380 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
381}
Chris Caputo228da422009-07-18 05:44:03 +0000382
383static void
384transit_finish (void)
385{
Lou Berger056f3762013-04-10 12:30:04 -0700386 hash_clean (transit_hash, (void (*)(void *))transit_free);
Chris Caputo228da422009-07-18 05:44:03 +0000387 hash_free (transit_hash);
388 transit_hash = NULL;
389}
David Lamparter6b0655a2014-06-04 06:53:35 +0200390
paul718e3742002-12-13 20:15:29 +0000391/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700392static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000393
Paul Jakmafb982c22007-05-04 20:15:47 +0000394static struct attr_extra *
395bgp_attr_extra_new (void)
396{
397 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
398}
399
400void
401bgp_attr_extra_free (struct attr *attr)
402{
403 if (attr->extra)
404 {
Lou Bergerc3741782016-01-12 13:42:01 -0500405 if (attr->extra->encap_subtlvs) {
406 encap_free(attr->extra->encap_subtlvs);
407 attr->extra->encap_subtlvs = NULL;
408 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000409 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
410 attr->extra = NULL;
411 }
412}
413
414struct attr_extra *
415bgp_attr_extra_get (struct attr *attr)
416{
417 if (!attr->extra)
418 attr->extra = bgp_attr_extra_new();
419 return attr->extra;
420}
421
422/* Shallow copy of an attribute
423 * Though, not so shallow that it doesn't copy the contents
424 * of the attr_extra pointed to by 'extra'
425 */
426void
427bgp_attr_dup (struct attr *new, struct attr *orig)
428{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000429 struct attr_extra *extra = new->extra;
430
Paul Jakmafb982c22007-05-04 20:15:47 +0000431 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000432 /* if caller provided attr_extra space, use it in any case.
433 *
434 * This is neccesary even if orig->extra equals NULL, because otherwise
435 * memory may be later allocated on the heap by bgp_attr_extra_get.
436 *
437 * That memory would eventually be leaked, because the caller must not
438 * call bgp_attr_extra_free if he provided attr_extra on the stack.
439 */
440 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000441 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000442 new->extra = extra;
443 memset(new->extra, 0, sizeof(struct attr_extra));
Lou Bergerc3741782016-01-12 13:42:01 -0500444 if (orig->extra) {
Christian Frankea0de1d12012-12-07 16:35:00 +0000445 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500446 if (orig->extra->encap_subtlvs) {
447 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
448 }
449 }
Christian Frankea0de1d12012-12-07 16:35:00 +0000450 }
451 else if (orig->extra)
452 {
453 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000454 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500455 if (orig->extra->encap_subtlvs) {
456 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
457 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000458 }
459}
460
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000461unsigned long int
462attr_count (void)
463{
464 return attrhash->count;
465}
466
467unsigned long int
468attr_unknown_count (void)
469{
470 return transit_hash->count;
471}
472
paul718e3742002-12-13 20:15:29 +0000473unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000474attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000475{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000476 const struct attr *attr = (struct attr *) p;
477 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700478 uint32_t key = 0;
479#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000480
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700481 MIX(attr->origin);
482 MIX(attr->nexthop.s_addr);
483 MIX(attr->med);
484 MIX(attr->local_pref);
485
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000486 key += attr->origin;
487 key += attr->nexthop.s_addr;
488 key += attr->med;
489 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000490
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000491 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000492 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000493 MIX(extra->aggregator_as);
494 MIX(extra->aggregator_addr.s_addr);
495 MIX(extra->weight);
496 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000497 MIX(extra->originator_id.s_addr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000498 }
499
paul718e3742002-12-13 20:15:29 +0000500 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700501 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000502 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700503 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000504
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000505 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000506 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000507 if (extra->ecommunity)
508 MIX(ecommunity_hash_make (extra->ecommunity));
509 if (extra->cluster)
510 MIX(cluster_hash_key_make (extra->cluster));
511 if (extra->transit)
512 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000513
514#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000515 MIX(extra->mp_nexthop_len);
516 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
517 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
paul718e3742002-12-13 20:15:29 +0000518#endif /* HAVE_IPV6 */
Paul Jakmafb982c22007-05-04 20:15:47 +0000519 }
paul718e3742002-12-13 20:15:29 +0000520
521 return key;
522}
523
524int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100525attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000526{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100527 const struct attr * attr1 = p1;
528 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000529
paul718e3742002-12-13 20:15:29 +0000530 if (attr1->flag == attr2->flag
531 && attr1->origin == attr2->origin
532 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000533 && attr1->aspath == attr2->aspath
534 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000535 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000536 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000537 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100538 const struct attr_extra *ae1 = attr1->extra;
539 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000540
541 if (ae1 && ae2
542 && ae1->aggregator_as == ae2->aggregator_as
543 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
544 && ae1->weight == ae2->weight
545#ifdef HAVE_IPV6
546 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
547 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
548 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
549#endif /* HAVE_IPV6 */
550 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
551 && ae1->ecommunity == ae2->ecommunity
552 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000553 && ae1->transit == ae2->transit
Lou Bergerc3741782016-01-12 13:42:01 -0500554 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
555 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000556 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000557 return 1;
558 else if (ae1 || ae2)
559 return 0;
560 /* neither attribute has extra attributes, so they're same */
561 return 1;
562 }
paul718e3742002-12-13 20:15:29 +0000563 else
564 return 0;
565}
566
paul94f2b392005-06-28 12:44:16 +0000567static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100568attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000569{
570 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
571}
572
Lou Berger056f3762013-04-10 12:30:04 -0700573/*
574 * special for hash_clean below
575 */
576static void
577attr_vfree (void *attr)
578{
579 bgp_attr_extra_free ((struct attr *)attr);
580 XFREE (MTYPE_ATTR, attr);
581}
582
paul94f2b392005-06-28 12:44:16 +0000583static void
Chris Caputo228da422009-07-18 05:44:03 +0000584attrhash_finish (void)
585{
Lou Berger056f3762013-04-10 12:30:04 -0700586 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000587 hash_free (attrhash);
588 attrhash = NULL;
589}
590
591static void
paul718e3742002-12-13 20:15:29 +0000592attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
593{
594 struct attr *attr = backet->data;
595
596 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
597 inet_ntoa (attr->nexthop), VTY_NEWLINE);
598}
599
600void
601attr_show_all (struct vty *vty)
602{
603 hash_iterate (attrhash,
604 (void (*)(struct hash_backet *, void *))
605 attr_show_all_iterator,
606 vty);
607}
608
paul94f2b392005-06-28 12:44:16 +0000609static void *
Paul Jakma923de652007-04-29 18:25:17 +0000610bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000611{
Paul Jakma923de652007-04-29 18:25:17 +0000612 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000613 struct attr *attr;
614
615 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
616 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000617 if (val->extra)
618 {
619 attr->extra = bgp_attr_extra_new ();
620 *attr->extra = *val->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500621
622 if (attr->extra->encap_subtlvs) {
623 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
624 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000625 }
paul718e3742002-12-13 20:15:29 +0000626 attr->refcnt = 0;
627 return attr;
628}
629
630/* Internet argument attribute. */
631struct attr *
632bgp_attr_intern (struct attr *attr)
633{
634 struct attr *find;
635
636 /* Intern referenced strucutre. */
637 if (attr->aspath)
638 {
639 if (! attr->aspath->refcnt)
640 attr->aspath = aspath_intern (attr->aspath);
641 else
642 attr->aspath->refcnt++;
643 }
644 if (attr->community)
645 {
646 if (! attr->community->refcnt)
647 attr->community = community_intern (attr->community);
648 else
649 attr->community->refcnt++;
650 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000651 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000652 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000653 struct attr_extra *attre = attr->extra;
654
655 if (attre->ecommunity)
656 {
657 if (! attre->ecommunity->refcnt)
658 attre->ecommunity = ecommunity_intern (attre->ecommunity);
659 else
660 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000661
Paul Jakmafb982c22007-05-04 20:15:47 +0000662 }
663 if (attre->cluster)
664 {
665 if (! attre->cluster->refcnt)
666 attre->cluster = cluster_intern (attre->cluster);
667 else
668 attre->cluster->refcnt++;
669 }
670 if (attre->transit)
671 {
672 if (! attre->transit->refcnt)
673 attre->transit = transit_intern (attre->transit);
674 else
675 attre->transit->refcnt++;
676 }
paul718e3742002-12-13 20:15:29 +0000677 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000678
paul718e3742002-12-13 20:15:29 +0000679 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
680 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000681
paul718e3742002-12-13 20:15:29 +0000682 return find;
683}
684
Paul Jakma03e214c2007-04-29 18:31:07 +0000685
paul718e3742002-12-13 20:15:29 +0000686/* Make network statement's attribute. */
687struct attr *
688bgp_attr_default_set (struct attr *attr, u_char origin)
689{
690 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000691 bgp_attr_extra_get (attr);
692
paul718e3742002-12-13 20:15:29 +0000693 attr->origin = origin;
694 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
695 attr->aspath = aspath_empty ();
696 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000697 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000698 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
699#ifdef HAVE_IPV6
Paul Jakmafb982c22007-05-04 20:15:47 +0000700 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000701#endif
Paul Jakma03e214c2007-04-29 18:31:07 +0000702
paul718e3742002-12-13 20:15:29 +0000703 return attr;
704}
705
Paul Jakma03e214c2007-04-29 18:31:07 +0000706
paul718e3742002-12-13 20:15:29 +0000707/* Make network statement's attribute. */
708struct attr *
709bgp_attr_default_intern (u_char origin)
710{
711 struct attr attr;
712 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000713
Lou Bergerc3741782016-01-12 13:42:01 -0500714 memset (&attr, 0, sizeof (struct attr));
715 bgp_attr_extra_get (&attr);
716
Paul Jakma03e214c2007-04-29 18:31:07 +0000717 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000718
719 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000720 bgp_attr_extra_free (&attr);
721
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000722 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000723 return new;
724}
725
726struct attr *
727bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
728 struct aspath *aspath,
729 struct community *community, int as_set)
730{
731 struct attr attr;
732 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000733 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000734
735 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000736 memset (&attre, 0, sizeof (struct attr_extra));
737 attr.extra = &attre;
738
paul718e3742002-12-13 20:15:29 +0000739 /* Origin attribute. */
740 attr.origin = origin;
741 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
742
743 /* AS path attribute. */
744 if (aspath)
745 attr.aspath = aspath_intern (aspath);
746 else
747 attr.aspath = aspath_empty ();
748 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
749
750 /* Next hop attribute. */
751 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
752
753 if (community)
754 {
755 attr.community = community;
756 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
757 }
758
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000759 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000760#ifdef HAVE_IPV6
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000761 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
paul718e3742002-12-13 20:15:29 +0000762#endif
763 if (! as_set)
764 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
765 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
766 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000767 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000768 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000769 attre.aggregator_as = bgp->as;
770 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000771
772 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000773
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000774 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000775 return new;
776}
777
Paul Jakmab881c702010-11-23 16:35:42 +0000778/* Unintern just the sub-components of the attr, but not the attr */
779void
780bgp_attr_unintern_sub (struct attr *attr)
781{
782 /* aspath refcount shoud be decrement. */
783 if (attr->aspath)
784 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000785 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000786
787 if (attr->community)
788 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000789 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000790
791 if (attr->extra)
792 {
793 if (attr->extra->ecommunity)
794 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000795 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000796
797 if (attr->extra->cluster)
798 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000799 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000800
801 if (attr->extra->transit)
802 transit_unintern (attr->extra->transit);
803 }
804}
805
paul718e3742002-12-13 20:15:29 +0000806/* Free bgp attribute and aspath. */
807void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000808bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000809{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000810 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000811 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000812 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000813 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000814
paul718e3742002-12-13 20:15:29 +0000815 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000816 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000817
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000818 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000819
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000820 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000821 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000822 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000823 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000824 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000825
paul718e3742002-12-13 20:15:29 +0000826 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000827 if (attr->refcnt == 0)
828 {
829 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000830 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000831 bgp_attr_extra_free (attr);
832 XFREE (MTYPE_ATTR, attr);
833 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000834 }
835
Paul Jakmab881c702010-11-23 16:35:42 +0000836 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000837}
838
839void
840bgp_attr_flush (struct attr *attr)
841{
842 if (attr->aspath && ! attr->aspath->refcnt)
843 aspath_free (attr->aspath);
844 if (attr->community && ! attr->community->refcnt)
845 community_free (attr->community);
Paul Jakmafb982c22007-05-04 20:15:47 +0000846 if (attr->extra)
847 {
848 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000849
Paul Jakmafb982c22007-05-04 20:15:47 +0000850 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000851 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000852 if (attre->cluster && ! attre->cluster->refcnt)
853 cluster_free (attre->cluster);
854 if (attre->transit && ! attre->transit->refcnt)
855 transit_free (attre->transit);
Lou Bergerc3741782016-01-12 13:42:01 -0500856 encap_free(attre->encap_subtlvs);
857 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000858 }
paul718e3742002-12-13 20:15:29 +0000859}
860
Paul Jakmab881c702010-11-23 16:35:42 +0000861/* Implement draft-scudder-idr-optional-transitive behaviour and
862 * avoid resetting sessions for malformed attributes which are
863 * are partial/optional and hence where the error likely was not
864 * introduced by the sending neighbour.
865 */
866static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000867bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
868 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000869{
Paul Jakma835315b2012-01-18 12:28:30 +0000870 struct peer *const peer = args->peer;
871 const u_int8_t flags = args->flags;
872 /* startp and length must be special-cased, as whether or not to
873 * send the attribute data with the NOTIFY depends on the error,
874 * the caller therefore signals this with the seperate length argument
875 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000876 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000877
Paul Jakmab881c702010-11-23 16:35:42 +0000878 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000879 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000880 {
881 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000882 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000883 return BGP_ATTR_PARSE_ERROR;
884
885 }
886
Paul Jakmabd471fe2012-03-15 11:30:00 +0000887 /* Adjust the stream getp to the end of the attribute, in case we can
888 * still proceed but the caller hasn't read all the attribute.
889 */
890 stream_set_getp (BGP_INPUT (peer),
891 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
892 + args->total);
893
Paul Jakma835315b2012-01-18 12:28:30 +0000894 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100895 /* where an attribute is relatively inconsequential, e.g. it does not
896 * affect route selection, and can be safely ignored, then any such
897 * attributes which are malformed should just be ignored and the route
898 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000899 */
900 case BGP_ATTR_AS4_AGGREGATOR:
901 case BGP_ATTR_AGGREGATOR:
902 case BGP_ATTR_ATOMIC_AGGREGATE:
903 return BGP_ATTR_PARSE_PROCEED;
904
905 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100906 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000907 */
908 case BGP_ATTR_ORIGIN:
909 case BGP_ATTR_AS_PATH:
910 case BGP_ATTR_NEXT_HOP:
911 case BGP_ATTR_MULTI_EXIT_DISC:
912 case BGP_ATTR_LOCAL_PREF:
913 case BGP_ATTR_COMMUNITIES:
914 case BGP_ATTR_ORIGINATOR_ID:
915 case BGP_ATTR_CLUSTER_LIST:
916 case BGP_ATTR_MP_REACH_NLRI:
917 case BGP_ATTR_MP_UNREACH_NLRI:
918 case BGP_ATTR_EXT_COMMUNITIES:
919 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000920 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000921 return BGP_ATTR_PARSE_ERROR;
922 }
923
924 /* Partial optional attributes that are malformed should not cause
925 * the whole session to be reset. Instead treat it as a withdrawal
926 * of the routes, if possible.
927 */
Paul Jakma835315b2012-01-18 12:28:30 +0000928 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
929 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
930 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000931 return BGP_ATTR_PARSE_WITHDRAW;
932
933 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200934 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000935}
936
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400937/* Find out what is wrong with the path attribute flag bits and log the error.
938 "Flag bits" here stand for Optional, Transitive and Partial, but not for
939 Extended Length. Checking O/T/P bits at once implies, that the attribute
940 being diagnosed is defined by RFC as either a "well-known" or an "optional,
941 non-transitive" attribute. */
942static void
Paul Jakma835315b2012-01-18 12:28:30 +0000943bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
944 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400945)
946{
947 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000948 u_char real_flags = args->flags;
949 const u_int8_t attr_code = args->type;
950
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400951 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
952 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
953 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
954 if
955 (
956 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
957 CHECK_FLAG (real_flags, attr_flag_str[i].key)
958 )
959 {
Paul Jakma835315b2012-01-18 12:28:30 +0000960 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400961 LOOKUP (attr_str, attr_code),
962 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
963 attr_flag_str[i].str);
964 seen = 1;
965 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100966 if (!seen)
967 {
968 zlog (args->peer->log, LOG_DEBUG,
969 "Strange, %s called for attr %s, but no problem found with flags"
970 " (real flags 0x%x, desired 0x%x)",
971 __func__, LOOKUP (attr_str, attr_code),
972 real_flags, desired_flags);
973 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400974}
975
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000976/* Required flags for attributes. EXTLEN will be masked off when testing,
977 * as will PARTIAL for optional+transitive attributes.
978 */
979const u_int8_t attr_flags_values [] = {
980 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
981 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
982 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
983 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
984 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
985 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
986 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
987 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
988 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
989 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
990 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
991 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
992 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
993 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
994 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
995};
996static const size_t attr_flags_values_max =
997 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
998
999static int
Paul Jakma835315b2012-01-18 12:28:30 +00001000bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001001{
1002 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +00001003 const u_int8_t flags = args->flags;
1004 const u_int8_t attr_code = args->type;
1005 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001006
1007 /* there may be attributes we don't know about */
1008 if (attr_code > attr_flags_values_max)
1009 return 0;
1010 if (attr_flags_values[attr_code] == 0)
1011 return 0;
1012
1013 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1014 * 1."
1015 */
1016 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1017 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1018 {
1019 zlog (peer->log, LOG_ERR,
1020 "%s well-known attributes must have transitive flag set (%x)",
1021 LOOKUP (attr_str, attr_code), flags);
1022 return 1;
1023 }
1024
1025 /* "For well-known attributes and for optional non-transitive attributes,
1026 * the Partial bit MUST be set to 0."
1027 */
1028 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1029 {
1030 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1031 {
1032 zlog (peer->log, LOG_ERR,
1033 "%s well-known attribute "
1034 "must NOT have the partial flag set (%x)",
1035 LOOKUP (attr_str, attr_code), flags);
1036 return 1;
1037 }
1038 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1039 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1040 {
1041 zlog (peer->log, LOG_ERR,
1042 "%s optional + transitive attribute "
1043 "must NOT have the partial flag set (%x)",
1044 LOOKUP (attr_str, attr_code), flags);
1045 return 1;
1046 }
1047 }
1048
1049 /* Optional transitive attributes may go through speakers that don't
1050 * reocgnise them and set the Partial bit.
1051 */
1052 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1053 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1054 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1055
Paul Jakma683f2b82012-03-23 14:58:45 +00001056 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001057 == attr_flags_values[attr_code])
1058 return 0;
1059
Paul Jakma835315b2012-01-18 12:28:30 +00001060 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001061 return 1;
1062}
1063
paul718e3742002-12-13 20:15:29 +00001064/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001065static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001066bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001067{
Paul Jakma835315b2012-01-18 12:28:30 +00001068 struct peer *const peer = args->peer;
1069 struct attr *const attr = args->attr;
1070 const bgp_size_t length = args->length;
1071
paul718e3742002-12-13 20:15:29 +00001072 /* If any recognized attribute has Attribute Length that conflicts
1073 with the expected length (based on the attribute type code), then
1074 the Error Subcode is set to Attribute Length Error. The Data
1075 field contains the erroneous attribute (type, length and
1076 value). */
1077 if (length != 1)
1078 {
1079 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1080 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001081 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001082 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001083 args->total);
paul718e3742002-12-13 20:15:29 +00001084 }
1085
1086 /* Fetch origin attribute. */
1087 attr->origin = stream_getc (BGP_INPUT (peer));
1088
1089 /* If the ORIGIN attribute has an undefined value, then the Error
1090 Subcode is set to Invalid Origin Attribute. The Data field
1091 contains the unrecognized attribute (type, length and value). */
1092 if ((attr->origin != BGP_ORIGIN_IGP)
1093 && (attr->origin != BGP_ORIGIN_EGP)
1094 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1095 {
1096 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1097 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001098 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001099 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001100 args->total);
paul718e3742002-12-13 20:15:29 +00001101 }
1102
1103 /* Set oring attribute flag. */
1104 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1105
1106 return 0;
1107}
Paul Jakmaab005292010-11-27 22:48:34 +00001108
1109/* Parse AS path information. This function is wrapper of
1110 aspath_parse. */
1111static int
Paul Jakma835315b2012-01-18 12:28:30 +00001112bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001113{
Paul Jakma835315b2012-01-18 12:28:30 +00001114 struct attr *const attr = args->attr;
1115 struct peer *const peer = args->peer;
1116 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001117
Paul Jakmaab005292010-11-27 22:48:34 +00001118 /*
1119 * peer with AS4 => will get 4Byte ASnums
1120 * otherwise, will get 16 Bit
1121 */
1122 attr->aspath = aspath_parse (peer->ibuf, length,
1123 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1124
1125 /* In case of IBGP, length will be zero. */
1126 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001127 {
Paul Jakmab881c702010-11-23 16:35:42 +00001128 zlog (peer->log, LOG_ERR,
1129 "Malformed AS path from %s, length is %d",
1130 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001131 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001132 }
Chris Hallcddb8112010-08-09 22:31:37 +04001133
Paul Jakmaab005292010-11-27 22:48:34 +00001134 /* Set aspath attribute flag. */
1135 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001136
Paul Jakmab881c702010-11-23 16:35:42 +00001137 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001138}
1139
Paul Jakmab881c702010-11-23 16:35:42 +00001140static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001141bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001142{
1143 /* These checks were part of bgp_attr_aspath, but with
1144 * as4 we should to check aspath things when
1145 * aspath synthesizing with as4_path has already taken place.
1146 * Otherwise we check ASPATH and use the synthesized thing, and that is
1147 * not right.
1148 * So do the checks later, i.e. here
1149 */
1150 struct bgp *bgp = peer->bgp;
1151 struct aspath *aspath;
1152
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001153 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001154 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1155 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001156 {
1157 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001158 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1159 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1160 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001161 }
1162
paul718e3742002-12-13 20:15:29 +00001163 /* First AS check for EBGP. */
1164 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1165 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001166 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001167 && ! aspath_firstas_check (attr->aspath, peer->as))
1168 {
1169 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001170 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001171 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1172 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1173 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001174 }
1175 }
1176
1177 /* local-as prepend */
1178 if (peer->change_local_as &&
1179 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1180 {
1181 aspath = aspath_dup (attr->aspath);
1182 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001183 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001184 attr->aspath = aspath_intern (aspath);
1185 }
1186
Paul Jakmab881c702010-11-23 16:35:42 +00001187 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001188}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001189
Paul Jakmaab005292010-11-27 22:48:34 +00001190/* Parse AS4 path information. This function is another wrapper of
1191 aspath_parse. */
1192static int
Paul Jakma835315b2012-01-18 12:28:30 +00001193bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001194{
Paul Jakma835315b2012-01-18 12:28:30 +00001195 struct peer *const peer = args->peer;
1196 struct attr *const attr = args->attr;
1197 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001198
Paul Jakmaab005292010-11-27 22:48:34 +00001199 *as4_path = aspath_parse (peer->ibuf, length, 1);
1200
Paul Jakmab881c702010-11-23 16:35:42 +00001201 /* In case of IBGP, length will be zero. */
1202 if (!*as4_path)
1203 {
1204 zlog (peer->log, LOG_ERR,
1205 "Malformed AS4 path from %s, length is %d",
1206 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001207 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001208 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001209 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001210 }
1211
Paul Jakmaab005292010-11-27 22:48:34 +00001212 /* Set aspath attribute flag. */
1213 if (as4_path)
1214 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1215
Paul Jakmab881c702010-11-23 16:35:42 +00001216 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001217}
1218
paul718e3742002-12-13 20:15:29 +00001219/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001220static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001221bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001222{
Paul Jakma835315b2012-01-18 12:28:30 +00001223 struct peer *const peer = args->peer;
1224 struct attr *const attr = args->attr;
1225 const bgp_size_t length = args->length;
1226
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001227 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001228
paul718e3742002-12-13 20:15:29 +00001229 /* Check nexthop attribute length. */
1230 if (length != 4)
1231 {
1232 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1233 length);
1234
Paul Jakma835315b2012-01-18 12:28:30 +00001235 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001236 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001237 args->total);
paul718e3742002-12-13 20:15:29 +00001238 }
1239
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001240 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1241 attribute must result in a NOTIFICATION message (this is implemented below).
1242 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1243 logged locally (this is implemented somewhere else). The UPDATE message
1244 gets ignored in any of these cases. */
1245 nexthop_n = stream_get_ipv4 (peer->ibuf);
1246 nexthop_h = ntohl (nexthop_n);
1247 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1248 {
1249 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001250 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001251 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001252 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001253 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001254 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001255 }
1256
1257 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001258 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1259
Paul Jakmab881c702010-11-23 16:35:42 +00001260 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001261}
1262
1263/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001264static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001265bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001266{
Paul Jakma835315b2012-01-18 12:28:30 +00001267 struct peer *const peer = args->peer;
1268 struct attr *const attr = args->attr;
1269 const bgp_size_t length = args->length;
1270
paul718e3742002-12-13 20:15:29 +00001271 /* Length check. */
1272 if (length != 4)
1273 {
1274 zlog (peer->log, LOG_ERR,
1275 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001276
Paul Jakma835315b2012-01-18 12:28:30 +00001277 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001278 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001279 args->total);
paul718e3742002-12-13 20:15:29 +00001280 }
1281
1282 attr->med = stream_getl (peer->ibuf);
1283
1284 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1285
Paul Jakmab881c702010-11-23 16:35:42 +00001286 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001287}
1288
1289/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001290static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001291bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001292{
Paul Jakma835315b2012-01-18 12:28:30 +00001293 struct peer *const peer = args->peer;
1294 struct attr *const attr = args->attr;
1295 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001296
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001297 /* Length check. */
1298 if (length != 4)
1299 {
Paul Jakma835315b2012-01-18 12:28:30 +00001300 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1301 length);
1302 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001303 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001304 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001305 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001306
paul718e3742002-12-13 20:15:29 +00001307 /* If it is contained in an UPDATE message that is received from an
1308 external peer, then this attribute MUST be ignored by the
1309 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001310 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001311 {
paul9985f832005-02-09 15:51:56 +00001312 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001313 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001314 }
1315
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001316 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001317
1318 /* Set atomic aggregate flag. */
1319 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1320
Paul Jakmab881c702010-11-23 16:35:42 +00001321 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001322}
1323
1324/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001325static int
Paul Jakma835315b2012-01-18 12:28:30 +00001326bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001327{
Paul Jakma835315b2012-01-18 12:28:30 +00001328 struct peer *const peer = args->peer;
1329 struct attr *const attr = args->attr;
1330 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001331
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001332 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001333 if (length != 0)
1334 {
Paul Jakma835315b2012-01-18 12:28:30 +00001335 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1336 length);
1337 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001338 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001339 args->total);
paul718e3742002-12-13 20:15:29 +00001340 }
1341
1342 /* Set atomic aggregate flag. */
1343 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1344
Paul Jakmab881c702010-11-23 16:35:42 +00001345 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001346}
1347
1348/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001349static int
Paul Jakma835315b2012-01-18 12:28:30 +00001350bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001351{
Paul Jakma835315b2012-01-18 12:28:30 +00001352 struct peer *const peer = args->peer;
1353 struct attr *const attr = args->attr;
1354 const bgp_size_t length = args->length;
1355
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001356 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001357 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001358
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001359 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001360 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001361 wantedlen = 8;
1362
1363 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001364 {
Paul Jakma835315b2012-01-18 12:28:30 +00001365 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1366 wantedlen, length);
1367 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001368 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001369 args->total);
paul718e3742002-12-13 20:15:29 +00001370 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001371
1372 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1373 attre->aggregator_as = stream_getl (peer->ibuf);
1374 else
1375 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001376 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001377
1378 /* Set atomic aggregate flag. */
1379 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1380
Paul Jakmab881c702010-11-23 16:35:42 +00001381 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001382}
1383
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001384/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001385static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001386bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1387 as_t *as4_aggregator_as,
1388 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001389{
Paul Jakma835315b2012-01-18 12:28:30 +00001390 struct peer *const peer = args->peer;
1391 struct attr *const attr = args->attr;
1392 const bgp_size_t length = args->length;
1393
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001394 if (length != 8)
1395 {
Paul Jakma835315b2012-01-18 12:28:30 +00001396 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1397 length);
1398 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001399 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001400 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001401 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001402
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001403 *as4_aggregator_as = stream_getl (peer->ibuf);
1404 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1405
1406 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1407
Paul Jakmab881c702010-11-23 16:35:42 +00001408 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001409}
1410
1411/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1412 */
Paul Jakmab881c702010-11-23 16:35:42 +00001413static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001414bgp_attr_munge_as4_attrs (struct peer *const peer,
1415 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001416 struct aspath *as4_path, as_t as4_aggregator,
1417 struct in_addr *as4_aggregator_addr)
1418{
1419 int ignore_as4_path = 0;
1420 struct aspath *newpath;
1421 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001422
1423 if (!attr->aspath)
1424 {
1425 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1426 * checked that all well-known, mandatory attributes were present.
1427 *
1428 * Can only be a problem with peer itself - hard error
1429 */
1430 return BGP_ATTR_PARSE_ERROR;
1431 }
1432
Paul Jakmab881c702010-11-23 16:35:42 +00001433 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001434 {
1435 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1436 * if given.
1437 * It is worth a warning though, because the peer really
1438 * should not send them
1439 */
1440 if (BGP_DEBUG(as4, AS4))
1441 {
1442 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1443 zlog_debug ("[AS4] %s %s AS4_PATH",
1444 peer->host, "AS4 capable peer, yet it sent");
1445
1446 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1447 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1448 peer->host, "AS4 capable peer, yet it sent");
1449 }
1450
Paul Jakmab881c702010-11-23 16:35:42 +00001451 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001452 }
1453
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001454 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1455 * because that may override AS4_PATH
1456 */
1457 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1458 {
Paul Jakmab881c702010-11-23 16:35:42 +00001459 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001460 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001461 assert (attre);
1462
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001463 /* received both.
1464 * if the as_number in aggregator is not AS_TRANS,
1465 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1466 * and the Aggregator shall be taken as
1467 * info on the aggregating node, and the AS_PATH
1468 * shall be taken as the AS_PATH
1469 * otherwise
1470 * the Aggregator shall be ignored and the
1471 * AS4_AGGREGATOR shall be taken as the
1472 * Aggregating node and the AS_PATH is to be
1473 * constructed "as in all other cases"
1474 */
Paul Jakmab881c702010-11-23 16:35:42 +00001475 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001476 {
1477 /* ignore */
1478 if ( BGP_DEBUG(as4, AS4))
1479 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1480 " send AGGREGATOR != AS_TRANS and"
1481 " AS4_AGGREGATOR, so ignore"
1482 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1483 ignore_as4_path = 1;
1484 }
1485 else
1486 {
1487 /* "New_aggregator shall be taken as aggregator" */
1488 attre->aggregator_as = as4_aggregator;
1489 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1490 }
1491 }
1492 else
1493 {
1494 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1495 * That is bogus - but reading the conditions
1496 * we have to handle AS4_AGGREGATOR as if it were
1497 * AGGREGATOR in that case
1498 */
1499 if ( BGP_DEBUG(as4, AS4))
1500 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1501 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1502 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001503 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001504 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1505 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1506 }
1507 }
1508
1509 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001510 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001511 {
Paul Jakma055086f2014-09-23 15:23:01 +01001512 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1513 aspath_unintern (&attr->aspath);
1514 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001515 }
Paul Jakmab881c702010-11-23 16:35:42 +00001516 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001517}
1518
paul718e3742002-12-13 20:15:29 +00001519/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001520static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001521bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001522{
Paul Jakma835315b2012-01-18 12:28:30 +00001523 struct peer *const peer = args->peer;
1524 struct attr *const attr = args->attr;
1525 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001526
paul718e3742002-12-13 20:15:29 +00001527 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001528 {
1529 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001530 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001531 }
Paul Jakma0c466382010-12-05 17:17:26 +00001532
1533 attr->community =
1534 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1535
1536 /* XXX: fix community_parse to use stream API and remove this */
1537 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001538
Paul Jakma0c466382010-12-05 17:17:26 +00001539 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001540 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001541 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001542 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001543
paul718e3742002-12-13 20:15:29 +00001544 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1545
Paul Jakmab881c702010-11-23 16:35:42 +00001546 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001547}
1548
1549/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001550static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001551bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001552{
Paul Jakma835315b2012-01-18 12:28:30 +00001553 struct peer *const peer = args->peer;
1554 struct attr *const attr = args->attr;
1555 const bgp_size_t length = args->length;
1556
Denis Ovsienkod595b562011-09-30 15:08:54 +04001557 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001558 if (length != 4)
1559 {
1560 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1561
Paul Jakma835315b2012-01-18 12:28:30 +00001562 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001563 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001564 args->total);
paul718e3742002-12-13 20:15:29 +00001565 }
1566
Paul Jakmafb982c22007-05-04 20:15:47 +00001567 (bgp_attr_extra_get (attr))->originator_id.s_addr
1568 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001569
1570 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1571
Paul Jakmab881c702010-11-23 16:35:42 +00001572 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001573}
1574
1575/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001576static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001577bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001578{
Paul Jakma835315b2012-01-18 12:28:30 +00001579 struct peer *const peer = args->peer;
1580 struct attr *const attr = args->attr;
1581 const bgp_size_t length = args->length;
1582
paul718e3742002-12-13 20:15:29 +00001583 /* Check length. */
1584 if (length % 4)
1585 {
1586 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1587
Paul Jakma835315b2012-01-18 12:28:30 +00001588 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1589 args->total);
paul718e3742002-12-13 20:15:29 +00001590 }
1591
Paul Jakmafb982c22007-05-04 20:15:47 +00001592 (bgp_attr_extra_get (attr))->cluster
1593 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001594
1595 /* XXX: Fix cluster_parse to use stream API and then remove this */
1596 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001597
1598 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1599
Paul Jakmab881c702010-11-23 16:35:42 +00001600 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001601}
1602
1603/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001604int
Paul Jakma835315b2012-01-18 12:28:30 +00001605bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1606 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001607{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001608 afi_t afi;
1609 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001610 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001611 size_t start;
paul718e3742002-12-13 20:15:29 +00001612 int ret;
1613 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001614 struct peer *const peer = args->peer;
1615 struct attr *const attr = args->attr;
1616 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001617 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001618
paul718e3742002-12-13 20:15:29 +00001619 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001620 s = BGP_INPUT(peer);
1621 start = stream_get_getp(s);
1622
1623 /* safe to read statically sized header? */
1624#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001625#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001626 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001627 {
1628 zlog_info ("%s: %s sent invalid length, %lu",
1629 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001630 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001631 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001632
paul718e3742002-12-13 20:15:29 +00001633 /* Load AFI, SAFI. */
1634 afi = stream_getw (s);
1635 safi = stream_getc (s);
1636
1637 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001638 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001639
Paul Jakma03292802008-06-07 20:37:10 +00001640 if (LEN_LEFT < attre->mp_nexthop_len)
1641 {
1642 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1643 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001644 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001645 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001646
paul718e3742002-12-13 20:15:29 +00001647 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001648 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001649 {
1650 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001651 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001652 /* Probably needed for RFC 2283 */
1653 if (attr->nexthop.s_addr == 0)
1654 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001655 break;
1656 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001657 stream_getl (s); /* RD high */
1658 stream_getl (s); /* RD low */
1659 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001660 break;
1661#ifdef HAVE_IPV6
Lou Berger9da04bc2016-01-12 13:41:55 -05001662 case 24:
1663 {
1664 u_int32_t rd_high __attribute__((unused));
1665 u_int32_t rd_low __attribute__((unused));
1666
1667 rd_high = stream_getl (s);
1668 rd_low = stream_getl (s);
1669 }
1670 /* fall through */
paul718e3742002-12-13 20:15:29 +00001671 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001672 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001673 break;
1674 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001675 case 48:
1676 if (attre->mp_nexthop_len == 48) {
1677 u_int32_t rd_high __attribute__((unused));
1678 u_int32_t rd_low __attribute__((unused));
1679
1680 rd_high = stream_getl (s);
1681 rd_low = stream_getl (s);
1682 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001683 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001684
1685 if (attre->mp_nexthop_len == 48) {
1686 u_int32_t rd_high __attribute__((unused));
1687 u_int32_t rd_low __attribute__((unused));
1688
1689 rd_high = stream_getl (s);
1690 rd_low = stream_getl (s);
1691 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001692 stream_get (&attre->mp_nexthop_local, s, 16);
1693 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001694 {
1695 char buf1[INET6_ADDRSTRLEN];
1696 char buf2[INET6_ADDRSTRLEN];
1697
1698 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001699 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 +00001700 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001701 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001702 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001703 buf2, INET6_ADDRSTRLEN));
1704
Paul Jakmafb982c22007-05-04 20:15:47 +00001705 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001706 }
1707 break;
1708#endif /* HAVE_IPV6 */
1709 default:
Paul Jakma03292802008-06-07 20:37:10 +00001710 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1711 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001712 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001713 }
1714
Paul Jakma03292802008-06-07 20:37:10 +00001715 if (!LEN_LEFT)
1716 {
1717 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1718 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001719 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001720 }
paul718e3742002-12-13 20:15:29 +00001721
Paul Jakma6e4ab122007-04-10 19:36:48 +00001722 {
1723 u_char val;
1724 if ((val = stream_getc (s)))
1725 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1726 peer->host, val);
1727 }
1728
1729 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001730 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001731 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001732 {
1733 zlog_info ("%s: (%s) Failed to read NLRI",
1734 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001735 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001736 }
paul718e3742002-12-13 20:15:29 +00001737
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001738 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001739 {
Lou Berger050defe2016-01-12 13:41:59 -05001740 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s), nlri_len);
Paul Jakma03292802008-06-07 20:37:10 +00001741 if (ret < 0)
1742 {
1743 zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1744 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001745 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001746 }
paul718e3742002-12-13 20:15:29 +00001747 }
1748
1749 mp_update->afi = afi;
1750 mp_update->safi = safi;
1751 mp_update->nlri = stream_pnt (s);
1752 mp_update->length = nlri_len;
1753
paul9985f832005-02-09 15:51:56 +00001754 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001755
David Lamparterdaefeb82014-12-08 17:42:12 +01001756 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1757
Paul Jakmab881c702010-11-23 16:35:42 +00001758 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001759#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001760}
1761
1762/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001763int
Paul Jakma835315b2012-01-18 12:28:30 +00001764bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001765 struct bgp_nlri *mp_withdraw)
1766{
1767 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001768 afi_t afi;
1769 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001770 u_int16_t withdraw_len;
1771 int ret;
Paul Jakma835315b2012-01-18 12:28:30 +00001772 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001773 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001774 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001775
1776 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001777
1778#define BGP_MP_UNREACH_MIN_SIZE 3
1779 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001780 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001781
paul718e3742002-12-13 20:15:29 +00001782 afi = stream_getw (s);
1783 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001784
1785 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001786
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001787 if (safi != SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001788 {
Lou Berger050defe2016-01-12 13:41:59 -05001789 ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s), withdraw_len);
paul718e3742002-12-13 20:15:29 +00001790 if (ret < 0)
David Lamparterf57000c2014-06-04 01:01:10 +02001791 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001792 }
1793
1794 mp_withdraw->afi = afi;
1795 mp_withdraw->safi = safi;
1796 mp_withdraw->nlri = stream_pnt (s);
1797 mp_withdraw->length = withdraw_len;
1798
paul9985f832005-02-09 15:51:56 +00001799 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001800
David Lamparterdaefeb82014-12-08 17:42:12 +01001801 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1802
Paul Jakmab881c702010-11-23 16:35:42 +00001803 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001804}
1805
1806/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001807static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001808bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001809{
Paul Jakma835315b2012-01-18 12:28:30 +00001810 struct peer *const peer = args->peer;
1811 struct attr *const attr = args->attr;
1812 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001813
paul718e3742002-12-13 20:15:29 +00001814 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001815 {
1816 if (attr->extra)
1817 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001818 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001819 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001820 }
Paul Jakma0c466382010-12-05 17:17:26 +00001821
1822 (bgp_attr_extra_get (attr))->ecommunity =
1823 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1824 /* XXX: fix ecommunity_parse to use stream API */
1825 stream_forward_getp (peer->ibuf, length);
1826
1827 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001828 return bgp_attr_malformed (args,
1829 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1830 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001831
paul718e3742002-12-13 20:15:29 +00001832 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1833
Paul Jakmab881c702010-11-23 16:35:42 +00001834 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001835}
1836
Lou Bergerc3741782016-01-12 13:42:01 -05001837/* Parse Tunnel Encap attribute in an UPDATE */
1838static int
1839bgp_attr_encap(
1840 uint8_t type,
1841 struct peer *peer, /* IN */
1842 bgp_size_t length, /* IN: attr's length field */
1843 struct attr *attr, /* IN: caller already allocated */
1844 u_char flag, /* IN: attr's flags field */
1845 u_char *startp)
1846{
1847 bgp_size_t total;
1848 struct attr_extra *attre = NULL;
1849 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1850 uint16_t tunneltype;
1851
1852 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1853
1854 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1855 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1856 {
1857 zlog (peer->log, LOG_ERR,
1858 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1859 bgp_notify_send_with_data (peer,
1860 BGP_NOTIFY_UPDATE_ERR,
1861 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1862 startp, total);
1863 return -1;
1864 }
1865
1866 if (BGP_ATTR_ENCAP == type) {
1867 /* read outer TLV type and length */
1868 uint16_t tlv_length;
1869
1870 if (length < 4) {
1871 zlog (peer->log, LOG_ERR,
1872 "Tunnel Encap attribute not long enough to contain outer T,L");
1873 bgp_notify_send_with_data(peer,
1874 BGP_NOTIFY_UPDATE_ERR,
1875 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1876 startp, total);
1877 return -1;
1878 }
1879 tunneltype = stream_getw (BGP_INPUT (peer));
1880 tlv_length = stream_getw (BGP_INPUT (peer));
1881 length -= 4;
1882
1883 if (tlv_length != length) {
1884 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1885 __func__, tlv_length, length);
1886 }
1887 }
1888
1889 while (length >= 4) {
1890 uint16_t subtype;
1891 uint16_t sublength;
1892 struct bgp_attr_encap_subtlv *tlv;
1893
1894 subtype = stream_getw (BGP_INPUT (peer));
1895 sublength = stream_getw (BGP_INPUT (peer));
1896 length -= 4;
1897
1898 if (sublength > length) {
1899 zlog (peer->log, LOG_ERR,
1900 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1901 sublength, length);
1902 bgp_notify_send_with_data (peer,
1903 BGP_NOTIFY_UPDATE_ERR,
1904 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1905 startp, total);
1906 return -1;
1907 }
1908
1909 /* alloc and copy sub-tlv */
1910 /* TBD make sure these are freed when attributes are released */
1911 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1912 tlv->type = subtype;
1913 tlv->length = sublength;
1914 stream_get(tlv->value, peer->ibuf, sublength);
1915 length -= sublength;
1916
1917 /* attach tlv to encap chain */
1918 if (!attre) {
1919 attre = bgp_attr_extra_get(attr);
1920 if (BGP_ATTR_ENCAP == type) {
1921 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1922 stlv_last = stlv_last->next);
1923 if (stlv_last) {
1924 stlv_last->next = tlv;
1925 } else {
1926 attre->encap_subtlvs = tlv;
1927 }
1928 }
1929 } else {
1930 stlv_last->next = tlv;
1931 }
1932 stlv_last = tlv;
1933 }
1934
1935 if (attre && (BGP_ATTR_ENCAP == type)) {
1936 attre->encap_tunneltype = tunneltype;
1937 }
1938
1939 if (length) {
1940 /* spurious leftover data */
1941 zlog (peer->log, LOG_ERR,
1942 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1943 bgp_notify_send_with_data (peer,
1944 BGP_NOTIFY_UPDATE_ERR,
1945 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1946 startp, total);
1947 return -1;
1948 }
1949
1950 return 0;
1951}
1952
paul718e3742002-12-13 20:15:29 +00001953/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001954static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001955bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001956{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001957 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001958 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001959 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001960 struct peer *const peer = args->peer;
1961 struct attr *const attr = args->attr;
1962 u_char *const startp = args->startp;
1963 const u_char type = args->type;
1964 const u_char flag = args->flags;
1965 const bgp_size_t length = args->length;
1966
paul718e3742002-12-13 20:15:29 +00001967
hassof4184462005-02-01 20:13:16 +00001968 if (BGP_DEBUG (normal, NORMAL))
1969 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1970 peer->host, type, length);
1971
paul718e3742002-12-13 20:15:29 +00001972 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001973 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001974 "Unknown attribute type %d length %d is received", type, length);
1975
1976 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001977 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001978
paul718e3742002-12-13 20:15:29 +00001979 /* If any of the mandatory well-known attributes are not recognized,
1980 then the Error Subcode is set to Unrecognized Well-known
1981 Attribute. The Data field contains the unrecognized attribute
1982 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001983 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001984 {
Paul Jakma835315b2012-01-18 12:28:30 +00001985 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001986 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001987 args->total);
paul718e3742002-12-13 20:15:29 +00001988 }
1989
1990 /* Unrecognized non-transitive optional attributes must be quietly
1991 ignored and not passed along to other BGP peers. */
1992 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001993 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001994
1995 /* If a path with recognized transitive optional attribute is
1996 accepted and passed along to other BGP peers and the Partial bit
1997 in the Attribute Flags octet is set to 1 by some previous AS, it
1998 is not set back to 0 by the current AS. */
1999 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2000
2001 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002002 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07002003 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00002004
Paul Jakmafb982c22007-05-04 20:15:47 +00002005 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00002006
2007 if (transit->val)
2008 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2009 transit->length + total);
2010 else
2011 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2012
2013 memcpy (transit->val + transit->length, startp, total);
2014 transit->length += total;
2015
Paul Jakmab881c702010-11-23 16:35:42 +00002016 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002017}
2018
Paul Jakma055086f2014-09-23 15:23:01 +01002019/* Well-known attribute check. */
2020static int
2021bgp_attr_check (struct peer *peer, struct attr *attr)
2022{
2023 u_char type = 0;
2024
Paul Jakmaaed1b552014-10-21 16:59:01 +01002025 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2026 * empty UPDATE. */
2027 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2028 return BGP_ATTR_PARSE_PROCEED;
2029
2030 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2031 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2032 are present, it should. Check for any other attribute being present
2033 instead.
2034 */
2035 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2036 return BGP_ATTR_PARSE_PROCEED;
2037
Paul Jakma055086f2014-09-23 15:23:01 +01002038 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2039 type = BGP_ATTR_ORIGIN;
2040
2041 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2042 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002043
2044 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2045 * NLRI is empty. We can't easily check NLRI empty here though.
2046 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002047 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2048 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002049 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002050
Paul Jakma055086f2014-09-23 15:23:01 +01002051 if (peer->sort == BGP_PEER_IBGP
2052 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2053 type = BGP_ATTR_LOCAL_PREF;
2054
2055 if (type)
2056 {
2057 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002058 "%s Missing well-known attribute %d / %s",
2059 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002060 bgp_notify_send_with_data (peer,
2061 BGP_NOTIFY_UPDATE_ERR,
2062 BGP_NOTIFY_UPDATE_MISS_ATTR,
2063 &type, 1);
2064 return BGP_ATTR_PARSE_ERROR;
2065 }
2066 return BGP_ATTR_PARSE_PROCEED;
2067}
2068
paul718e3742002-12-13 20:15:29 +00002069/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002070 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002071bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002072bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2073 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2074{
2075 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002076 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002077 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002078 bgp_size_t length;
2079 u_char *startp, *endp;
2080 u_char *attr_endp;
2081 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002082 /* we need the as4_path only until we have synthesized the as_path with it */
2083 /* same goes for as4_aggregator */
2084 struct aspath *as4_path = NULL;
2085 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002086 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002087
2088 /* Initialize bitmap. */
2089 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2090
2091 /* End pointer of BGP attribute. */
2092 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002093
paul718e3742002-12-13 20:15:29 +00002094 /* Get attributes to the end of attribute length. */
2095 while (BGP_INPUT_PNT (peer) < endp)
2096 {
2097 /* Check remaining length check.*/
2098 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2099 {
gdtc29fdba2004-12-09 14:46:46 +00002100 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002101 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002102 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002103 peer->host,
2104 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002105
2106 bgp_notify_send (peer,
2107 BGP_NOTIFY_UPDATE_ERR,
2108 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002109 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002110 }
2111
2112 /* Fetch attribute flag and type. */
2113 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002114 /* "The lower-order four bits of the Attribute Flags octet are
2115 unused. They MUST be zero when sent and MUST be ignored when
2116 received." */
2117 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002118 type = stream_getc (BGP_INPUT (peer));
2119
Paul Jakma370b64a2007-12-22 16:49:52 +00002120 /* Check whether Extended-Length applies and is in bounds */
2121 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2122 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2123 {
2124 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002125 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002126 peer->host,
2127 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2128
2129 bgp_notify_send (peer,
2130 BGP_NOTIFY_UPDATE_ERR,
2131 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002132 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002133 }
Paul Jakma835315b2012-01-18 12:28:30 +00002134
paul718e3742002-12-13 20:15:29 +00002135 /* Check extended attribue length bit. */
2136 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2137 length = stream_getw (BGP_INPUT (peer));
2138 else
2139 length = stream_getc (BGP_INPUT (peer));
2140
2141 /* If any attribute appears more than once in the UPDATE
2142 message, then the Error Subcode is set to Malformed Attribute
2143 List. */
2144
2145 if (CHECK_BITMAP (seen, type))
2146 {
2147 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002148 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002149 peer->host, type);
2150
2151 bgp_notify_send (peer,
2152 BGP_NOTIFY_UPDATE_ERR,
2153 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002154 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002155 }
2156
2157 /* Set type to bitmap to check duplicate attribute. `type' is
2158 unsigned char so it never overflow bitmap range. */
2159
2160 SET_BITMAP (seen, type);
2161
2162 /* Overflow check. */
2163 attr_endp = BGP_INPUT_PNT (peer) + length;
2164
2165 if (attr_endp > endp)
2166 {
2167 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002168 "%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 +00002169 bgp_notify_send (peer,
2170 BGP_NOTIFY_UPDATE_ERR,
2171 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002172 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002173 }
Paul Jakma835315b2012-01-18 12:28:30 +00002174
2175 struct bgp_attr_parser_args attr_args = {
2176 .peer = peer,
2177 .length = length,
2178 .attr = attr,
2179 .type = type,
2180 .flags = flag,
2181 .startp = startp,
2182 .total = attr_endp - startp,
2183 };
2184
2185
2186 /* If any recognized attribute has Attribute Flags that conflict
2187 with the Attribute Type Code, then the Error Subcode is set to
2188 Attribute Flags Error. The Data field contains the erroneous
2189 attribute (type, length and value). */
2190 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002191 {
2192 bgp_attr_parse_ret_t ret;
2193 ret = bgp_attr_malformed (&attr_args,
2194 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2195 attr_args.total);
2196 if (ret == BGP_ATTR_PARSE_PROCEED)
2197 continue;
2198 return ret;
2199 }
paul718e3742002-12-13 20:15:29 +00002200
2201 /* OK check attribute and store it's value. */
2202 switch (type)
2203 {
2204 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002205 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002206 break;
2207 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002208 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002209 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002210 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002211 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002212 break;
paul718e3742002-12-13 20:15:29 +00002213 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002214 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002215 break;
2216 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002217 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002218 break;
2219 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002220 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002221 break;
2222 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002223 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002224 break;
2225 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002226 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002227 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002228 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002229 ret = bgp_attr_as4_aggregator (&attr_args,
2230 &as4_aggregator,
2231 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002232 break;
paul718e3742002-12-13 20:15:29 +00002233 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002234 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002235 break;
2236 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002237 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002238 break;
2239 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002240 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002241 break;
2242 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002243 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002244 break;
2245 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002246 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002247 break;
2248 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002249 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002250 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002251 case BGP_ATTR_ENCAP:
2252 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2253 break;
paul718e3742002-12-13 20:15:29 +00002254 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002255 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002256 break;
2257 }
Paul Jakmab881c702010-11-23 16:35:42 +00002258
David Lamparterf57000c2014-06-04 01:01:10 +02002259 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2260 {
2261 bgp_notify_send (peer,
2262 BGP_NOTIFY_UPDATE_ERR,
2263 BGP_NOTIFY_UPDATE_MAL_ATTR);
2264 ret = BGP_ATTR_PARSE_ERROR;
2265 }
2266
Paul Jakmab881c702010-11-23 16:35:42 +00002267 /* If hard error occured immediately return to the caller. */
2268 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002269 {
2270 zlog (peer->log, LOG_WARNING,
2271 "%s: Attribute %s, parse error",
2272 peer->host,
2273 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002274 if (as4_path)
2275 aspath_unintern (&as4_path);
2276 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002277 }
Paul Jakmab881c702010-11-23 16:35:42 +00002278 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2279 {
2280
2281 zlog (peer->log, LOG_WARNING,
2282 "%s: Attribute %s, parse error - treating as withdrawal",
2283 peer->host,
2284 LOOKUP (attr_str, type));
2285 if (as4_path)
2286 aspath_unintern (&as4_path);
2287 return ret;
2288 }
2289
paul718e3742002-12-13 20:15:29 +00002290 /* Check the fetched length. */
2291 if (BGP_INPUT_PNT (peer) != attr_endp)
2292 {
2293 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002294 "%s: BGP attribute %s, fetch error",
2295 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002296 bgp_notify_send (peer,
2297 BGP_NOTIFY_UPDATE_ERR,
2298 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002299 if (as4_path)
2300 aspath_unintern (&as4_path);
2301 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002302 }
2303 }
paul718e3742002-12-13 20:15:29 +00002304 /* Check final read pointer is same as end pointer. */
2305 if (BGP_INPUT_PNT (peer) != endp)
2306 {
2307 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002308 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002309 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002310 bgp_notify_send (peer,
2311 BGP_NOTIFY_UPDATE_ERR,
2312 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002313 if (as4_path)
2314 aspath_unintern (&as4_path);
2315 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002316 }
Paul Jakma055086f2014-09-23 15:23:01 +01002317
2318 /* Check all mandatory well-known attributes are present */
2319 {
2320 bgp_attr_parse_ret_t ret;
2321 if ((ret = bgp_attr_check (peer, attr)) < 0)
2322 {
2323 if (as4_path)
2324 aspath_unintern (&as4_path);
2325 return ret;
2326 }
2327 }
2328
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002329 /*
2330 * At this place we can see whether we got AS4_PATH and/or
2331 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2332 * We can not do this before we've read all attributes because
2333 * the as4 handling does not say whether AS4_PATH has to be sent
2334 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2335 * in relationship to AGGREGATOR.
2336 * So, to be defensive, we are not relying on any order and read
2337 * all attributes first, including these 32bit ones, and now,
2338 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002339 *
2340 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2341 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002342 */
David Lamparterf57000c2014-06-04 01:01:10 +02002343 /* actually... this doesn't ever return failure currently, but
2344 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002345 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2346 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002347 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002348 {
David Lamparterf57000c2014-06-04 01:01:10 +02002349 bgp_notify_send (peer,
2350 BGP_NOTIFY_UPDATE_ERR,
2351 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002352 if (as4_path)
2353 aspath_unintern (&as4_path);
2354 return BGP_ATTR_PARSE_ERROR;
2355 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002356
2357 /* At this stage, we have done all fiddling with as4, and the
2358 * resulting info is in attr->aggregator resp. attr->aspath
2359 * so we can chuck as4_aggregator and as4_path alltogether in
2360 * order to save memory
2361 */
Paul Jakmab881c702010-11-23 16:35:42 +00002362 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002363 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002364 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002365 /* The flag that we got this is still there, but that does not
2366 * do any trouble
2367 */
2368 }
2369 /*
2370 * The "rest" of the code does nothing with as4_aggregator.
2371 * there is no memory attached specifically which is not part
2372 * of the attr.
2373 * so ignoring just means do nothing.
2374 */
2375 /*
2376 * Finally do the checks on the aspath we did not do yet
2377 * because we waited for a potentially synthesized aspath.
2378 */
Paul Jakmab881c702010-11-23 16:35:42 +00002379 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002380 {
Paul Jakma835315b2012-01-18 12:28:30 +00002381 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002382 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002383 return ret;
2384 }
2385
paul718e3742002-12-13 20:15:29 +00002386 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002387 if (attr->extra && attr->extra->transit)
2388 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002389
Paul Jakmab881c702010-11-23 16:35:42 +00002390 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002391}
2392
paul718e3742002-12-13 20:15:29 +00002393int stream_put_prefix (struct stream *, struct prefix *);
2394
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002395size_t
2396bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2397 struct attr *attr)
2398{
2399 size_t sizep;
2400
2401 /* Set extended bit always to encode the attribute length as 2 bytes */
2402 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2403 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2404 sizep = stream_get_endp (s);
2405 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002406
2407 stream_putw (s, afi);
2408 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002409
2410 /* Nexthop */
2411 switch (afi)
2412 {
2413 case AFI_IP:
2414 switch (safi)
2415 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002416 case SAFI_MULTICAST:
2417 stream_putc (s, 4);
2418 stream_put_ipv4 (s, attr->nexthop.s_addr);
2419 break;
2420 case SAFI_MPLS_VPN:
2421 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002422 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002423 stream_putl (s, 0);
2424 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2425 break;
Lou Berger050defe2016-01-12 13:41:59 -05002426 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002427 default:
2428 break;
2429 }
2430 break;
2431#ifdef HAVE_IPV6
2432 case AFI_IP6:
2433 switch (safi)
2434 {
2435 case SAFI_UNICAST:
2436 case SAFI_MULTICAST:
2437 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002438 struct attr_extra *attre = attr->extra;
2439
2440 assert (attr->extra);
2441 stream_putc (s, attre->mp_nexthop_len);
2442 stream_put (s, &attre->mp_nexthop_global, 16);
2443 if (attre->mp_nexthop_len == 32)
2444 stream_put (s, &attre->mp_nexthop_local, 16);
2445 }
Lou Berger050defe2016-01-12 13:41:59 -05002446 break;
2447 case SAFI_MPLS_VPN:
2448 {
2449 struct attr_extra *attre = attr->extra;
2450
2451 assert (attr->extra);
2452 if (attre->mp_nexthop_len == 16) {
2453 stream_putc (s, 24);
2454 stream_putl (s, 0); /* RD = 0, per RFC */
2455 stream_putl (s, 0);
2456 stream_put (s, &attre->mp_nexthop_global, 16);
2457 } else if (attre->mp_nexthop_len == 32) {
2458 stream_putc (s, 48);
2459 stream_putl (s, 0); /* RD = 0, per RFC */
2460 stream_putl (s, 0);
2461 stream_put (s, &attre->mp_nexthop_global, 16);
2462 stream_putl (s, 0); /* RD = 0, per RFC */
2463 stream_putl (s, 0);
2464 stream_put (s, &attre->mp_nexthop_local, 16);
2465 }
2466 }
2467 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002468 default:
2469 break;
2470 }
2471 break;
2472#endif /*HAVE_IPV6*/
2473 default:
2474 break;
2475 }
2476
2477 /* SNPA */
2478 stream_putc (s, 0);
2479 return sizep;
2480}
2481
2482void
2483bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2484 struct prefix *p, struct prefix_rd *prd,
2485 u_char *tag)
2486{
Lou Berger050defe2016-01-12 13:41:59 -05002487 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002488 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002489 /* Tag, RD, Prefix write. */
2490 stream_putc (s, p->prefixlen + 88);
2491 stream_put (s, tag, 3);
2492 stream_put (s, prd->val, 8);
2493 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002494 }
Lou Berger050defe2016-01-12 13:41:59 -05002495 else
2496 stream_put_prefix (s, p);
2497}
2498
2499size_t
2500bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2501{
2502 int size = PSIZE (p->prefixlen);
2503 if (safi == SAFI_MPLS_VPN)
2504 size += 88;
2505 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002506}
2507
Lou Bergerc3741782016-01-12 13:42:01 -05002508/*
2509 * Encodes the tunnel encapsulation attribute
2510 */
2511static void
2512bgp_packet_mpattr_tea(
2513 struct bgp *bgp,
2514 struct peer *peer,
2515 struct stream *s,
2516 struct attr *attr,
2517 uint8_t attrtype)
2518{
2519 unsigned int attrlenfield = 0;
2520 struct bgp_attr_encap_subtlv *subtlvs;
2521 struct bgp_attr_encap_subtlv *st;
2522 const char *attrname;
2523
2524 if (!attr || !attr->extra)
2525 return;
2526
2527 switch (attrtype) {
2528 case BGP_ATTR_ENCAP:
2529 attrname = "Tunnel Encap";
2530 subtlvs = attr->extra->encap_subtlvs;
2531
2532 /*
2533 * The tunnel encap attr has an "outer" tlv.
2534 * T = tunneltype,
2535 * L = total length of subtlvs,
2536 * V = concatenated subtlvs.
2537 */
2538 attrlenfield = 2 + 2; /* T + L */
2539 break;
2540
2541 default:
2542 assert(0);
2543 }
2544
2545
2546 /* compute attr length */
2547 for (st = subtlvs; st; st = st->next) {
2548 attrlenfield += (4 + st->length);
2549 }
2550
2551 /* if no tlvs, don't make attr */
2552 if (!attrlenfield)
2553 return;
2554
2555 if (attrlenfield > 0xffff) {
2556 zlog (peer->log, LOG_ERR,
2557 "%s attribute is too long (length=%d), can't send it",
2558 attrname,
2559 attrlenfield);
2560 return;
2561 }
2562
2563 if (attrlenfield > 0xff) {
2564 /* 2-octet length field */
2565 stream_putc (s,
2566 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2567 stream_putc (s, attrtype);
2568 stream_putw (s, attrlenfield & 0xffff);
2569 } else {
2570 /* 1-octet length field */
2571 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2572 stream_putc (s, attrtype);
2573 stream_putc (s, attrlenfield & 0xff);
2574 }
2575
2576 if (attrtype == BGP_ATTR_ENCAP) {
2577 /* write outer T+L */
2578 stream_putw(s, attr->extra->encap_tunneltype);
2579 stream_putw(s, attrlenfield - 4);
2580 }
2581
2582 /* write each sub-tlv */
2583 for (st = subtlvs; st; st = st->next) {
2584 stream_putw (s, st->type);
2585 stream_putw (s, st->length);
2586 stream_put (s, st->value, st->length);
2587 }
2588}
2589
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002590void
2591bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2592{
2593 /* Set MP attribute length. Don't count the (2) bytes used to encode
2594 the attr length */
2595 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2596}
2597
paul718e3742002-12-13 20:15:29 +00002598/* Make attribute packet. */
2599bgp_size_t
2600bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002601 struct stream *s, struct attr *attr,
2602 struct prefix *p, afi_t afi, safi_t safi,
2603 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002604{
paulfe69a502005-09-10 16:55:02 +00002605 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002606 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002607 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002608 int send_as4_path = 0;
2609 int send_as4_aggregator = 0;
2610 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002611
2612 if (! bgp)
2613 bgp = bgp_get_default ();
2614
2615 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002616 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002617
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002618 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2619 {
Lou Berger050defe2016-01-12 13:41:59 -05002620 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002621 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2622 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2623 bgp_packet_mpattr_end(s, mpattrlen_pos);
2624 }
2625
paul718e3742002-12-13 20:15:29 +00002626 /* Origin attribute. */
2627 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2628 stream_putc (s, BGP_ATTR_ORIGIN);
2629 stream_putc (s, 1);
2630 stream_putc (s, attr->origin);
2631
2632 /* AS path attribute. */
2633
2634 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002635 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002636 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002637 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002638 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002639 {
2640 aspath = aspath_dup (attr->aspath);
2641
2642 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2643 {
2644 /* Strip the confed info, and then stuff our path CONFED_ID
2645 on the front */
2646 aspath = aspath_delete_confed_seq (aspath);
2647 aspath = aspath_add_seq (aspath, bgp->confed_id);
2648 }
2649 else
2650 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002651 if (peer->change_local_as) {
2652 /* If replace-as is specified, we only use the change_local_as when
2653 advertising routes. */
2654 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2655 aspath = aspath_add_seq (aspath, peer->local_as);
2656 }
paul718e3742002-12-13 20:15:29 +00002657 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002658 } else {
2659 aspath = aspath_add_seq (aspath, peer->local_as);
2660 }
paul718e3742002-12-13 20:15:29 +00002661 }
2662 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002663 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002664 {
2665 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2666 aspath = aspath_dup (attr->aspath);
2667 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2668 }
2669 else
2670 aspath = attr->aspath;
2671
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002672 /* If peer is not AS4 capable, then:
2673 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2674 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2675 * types are in it (i.e. exclude them if they are there)
2676 * AND do this only if there is at least one asnum > 65535 in the path!
2677 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2678 * all ASnums > 65535 to BGP_AS_TRANS
2679 */
paul718e3742002-12-13 20:15:29 +00002680
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002681 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2682 stream_putc (s, BGP_ATTR_AS_PATH);
2683 aspath_sizep = stream_get_endp (s);
2684 stream_putw (s, 0);
2685 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2686
2687 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2688 * in the path
2689 */
2690 if (!use32bit && aspath_has_as4 (aspath))
2691 send_as4_path = 1; /* we'll do this later, at the correct place */
2692
paul718e3742002-12-13 20:15:29 +00002693 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002694 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2695 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002696 {
2697 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2698 stream_putc (s, BGP_ATTR_NEXT_HOP);
2699 stream_putc (s, 4);
2700 if (safi == SAFI_MPLS_VPN)
2701 {
2702 if (attr->nexthop.s_addr == 0)
2703 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2704 else
2705 stream_put_ipv4 (s, attr->nexthop.s_addr);
2706 }
2707 else
2708 stream_put_ipv4 (s, attr->nexthop.s_addr);
2709 }
2710
2711 /* MED attribute. */
2712 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2713 {
2714 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2715 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2716 stream_putc (s, 4);
2717 stream_putl (s, attr->med);
2718 }
2719
2720 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002721 if (peer->sort == BGP_PEER_IBGP ||
2722 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002723 {
2724 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2725 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2726 stream_putc (s, 4);
2727 stream_putl (s, attr->local_pref);
2728 }
2729
2730 /* Atomic aggregate. */
2731 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2732 {
2733 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2734 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2735 stream_putc (s, 0);
2736 }
2737
2738 /* Aggregator. */
2739 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2740 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002741 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002742
2743 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002744 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2745 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002746
2747 if (use32bit)
2748 {
2749 /* AS4 capable peer */
2750 stream_putc (s, 8);
2751 stream_putl (s, attr->extra->aggregator_as);
2752 }
2753 else
2754 {
2755 /* 2-byte AS peer */
2756 stream_putc (s, 6);
2757
2758 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2759 if ( attr->extra->aggregator_as > 65535 )
2760 {
2761 stream_putw (s, BGP_AS_TRANS);
2762
2763 /* we have to send AS4_AGGREGATOR, too.
2764 * we'll do that later in order to send attributes in ascending
2765 * order.
2766 */
2767 send_as4_aggregator = 1;
2768 }
2769 else
2770 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2771 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002772 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002773 }
2774
2775 /* Community attribute. */
2776 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2777 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2778 {
2779 if (attr->community->size * 4 > 255)
2780 {
2781 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2782 stream_putc (s, BGP_ATTR_COMMUNITIES);
2783 stream_putw (s, attr->community->size * 4);
2784 }
2785 else
2786 {
2787 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2788 stream_putc (s, BGP_ATTR_COMMUNITIES);
2789 stream_putc (s, attr->community->size * 4);
2790 }
2791 stream_put (s, attr->community->val, attr->community->size * 4);
2792 }
2793
2794 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002795 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002796 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002797 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002798 {
2799 /* Originator ID. */
2800 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2801 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2802 stream_putc (s, 4);
2803
2804 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002805 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002806 else
2807 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002808
2809 /* Cluster list. */
2810 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2811 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2812
Paul Jakma9eda90c2007-08-30 13:36:17 +00002813 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002814 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002815 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002816 /* If this peer configuration's parent BGP has cluster_id. */
2817 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2818 stream_put_in_addr (s, &bgp->cluster_id);
2819 else
2820 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002821 stream_put (s, attr->extra->cluster->list,
2822 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002823 }
2824 else
2825 {
2826 stream_putc (s, 4);
2827 /* If this peer configuration's parent BGP has cluster_id. */
2828 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2829 stream_put_in_addr (s, &bgp->cluster_id);
2830 else
2831 stream_put_in_addr (s, &bgp->router_id);
2832 }
2833 }
2834
paul718e3742002-12-13 20:15:29 +00002835 /* Extended Communities attribute. */
2836 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2837 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2838 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002839 struct attr_extra *attre = attr->extra;
2840
2841 assert (attre);
2842
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002843 if (peer->sort == BGP_PEER_IBGP
2844 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002845 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002846 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002847 {
2848 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2849 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002850 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002851 }
2852 else
2853 {
2854 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2855 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002856 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002857 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002858 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002859 }
2860 else
2861 {
paul5228ad22004-06-04 17:58:18 +00002862 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002863 int tbit;
2864 int ecom_tr_size = 0;
2865 int i;
2866
Paul Jakmafb982c22007-05-04 20:15:47 +00002867 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002868 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002869 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002870 tbit = *pnt;
2871
2872 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2873 continue;
2874
2875 ecom_tr_size++;
2876 }
2877
2878 if (ecom_tr_size)
2879 {
2880 if (ecom_tr_size * 8 > 255)
2881 {
2882 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2883 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2884 stream_putw (s, ecom_tr_size * 8);
2885 }
2886 else
2887 {
2888 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2889 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2890 stream_putc (s, ecom_tr_size * 8);
2891 }
2892
Paul Jakmafb982c22007-05-04 20:15:47 +00002893 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002894 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002895 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002896 tbit = *pnt;
2897
2898 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2899 continue;
2900
2901 stream_put (s, pnt, 8);
2902 }
2903 }
paul718e3742002-12-13 20:15:29 +00002904 }
paul718e3742002-12-13 20:15:29 +00002905 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002906
2907 if ( send_as4_path )
2908 {
2909 /* If the peer is NOT As4 capable, AND */
2910 /* there are ASnums > 65535 in path THEN
2911 * give out AS4_PATH */
2912
2913 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2914 * path segments!
2915 * Hm, I wonder... confederation things *should* only be at
2916 * the beginning of an aspath, right? Then we should use
2917 * aspath_delete_confed_seq for this, because it is already
2918 * there! (JK)
2919 * Folks, talk to me: what is reasonable here!?
2920 */
2921 aspath = aspath_delete_confed_seq (aspath);
2922
2923 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2924 stream_putc (s, BGP_ATTR_AS4_PATH);
2925 aspath_sizep = stream_get_endp (s);
2926 stream_putw (s, 0);
2927 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2928 }
2929
2930 if (aspath != attr->aspath)
2931 aspath_free (aspath);
2932
2933 if ( send_as4_aggregator )
2934 {
2935 assert (attr->extra);
2936
2937 /* send AS4_AGGREGATOR, at this place */
2938 /* this section of code moved here in order to ensure the correct
2939 * *ascending* order of attributes
2940 */
2941 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2942 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2943 stream_putc (s, 8);
2944 stream_putl (s, attr->extra->aggregator_as);
2945 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2946 }
Paul Jakma41367172007-08-06 15:24:51 +00002947
paul718e3742002-12-13 20:15:29 +00002948 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002949 if (attr->extra && attr->extra->transit)
2950 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002951
2952 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002953 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002954}
2955
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002956size_t
2957bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002958{
paul718e3742002-12-13 20:15:29 +00002959 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002960
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002961 /* Set extended bit always to encode the attribute length as 2 bytes */
2962 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002963 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2964
paul9985f832005-02-09 15:51:56 +00002965 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002966 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002967
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002968 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002969 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002970 return attrlen_pnt;
2971}
paul718e3742002-12-13 20:15:29 +00002972
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002973void
2974bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2975 afi_t afi, safi_t safi, struct prefix_rd *prd,
2976 u_char *tag)
2977{
Lou Berger050defe2016-01-12 13:41:59 -05002978 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002979}
paul718e3742002-12-13 20:15:29 +00002980
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002981void
2982bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2983{
Lou Berger050defe2016-01-12 13:41:59 -05002984 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002985}
2986
2987/* Initialization of attribute. */
2988void
paulfe69a502005-09-10 16:55:02 +00002989bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002990{
paul718e3742002-12-13 20:15:29 +00002991 aspath_init ();
2992 attrhash_init ();
2993 community_init ();
2994 ecommunity_init ();
2995 cluster_init ();
2996 transit_init ();
2997}
2998
Chris Caputo228da422009-07-18 05:44:03 +00002999void
3000bgp_attr_finish (void)
3001{
3002 aspath_finish ();
3003 attrhash_finish ();
3004 community_finish ();
3005 ecommunity_finish ();
3006 cluster_finish ();
3007 transit_finish ();
3008}
3009
paul718e3742002-12-13 20:15:29 +00003010/* Make attribute packet. */
3011void
paula3845922003-10-18 01:30:50 +00003012bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3013 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003014{
3015 unsigned long cp;
3016 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003017 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003018 struct aspath *aspath;
3019
3020 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003021 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003022
3023 /* Place holder of length. */
3024 stream_putw (s, 0);
3025
3026 /* Origin attribute. */
3027 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3028 stream_putc (s, BGP_ATTR_ORIGIN);
3029 stream_putc (s, 1);
3030 stream_putc (s, attr->origin);
3031
3032 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003033
3034 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3035 stream_putc (s, BGP_ATTR_AS_PATH);
3036 aspath_lenp = stream_get_endp (s);
3037 stream_putw (s, 0);
3038
3039 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003040
3041 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003042 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3043 if(prefix != NULL
3044#ifdef HAVE_IPV6
3045 && prefix->family != AF_INET6
3046#endif /* HAVE_IPV6 */
3047 )
3048 {
3049 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3050 stream_putc (s, BGP_ATTR_NEXT_HOP);
3051 stream_putc (s, 4);
3052 stream_put_ipv4 (s, attr->nexthop.s_addr);
3053 }
paul718e3742002-12-13 20:15:29 +00003054
3055 /* MED attribute. */
3056 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3057 {
3058 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3059 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3060 stream_putc (s, 4);
3061 stream_putl (s, attr->med);
3062 }
3063
3064 /* Local preference. */
3065 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3066 {
3067 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3068 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3069 stream_putc (s, 4);
3070 stream_putl (s, attr->local_pref);
3071 }
3072
3073 /* Atomic aggregate. */
3074 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3075 {
3076 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3077 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3078 stream_putc (s, 0);
3079 }
3080
3081 /* Aggregator. */
3082 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3083 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003084 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003085 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3086 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003087 stream_putc (s, 8);
3088 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003089 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003090 }
3091
3092 /* Community attribute. */
3093 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3094 {
3095 if (attr->community->size * 4 > 255)
3096 {
3097 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3098 stream_putc (s, BGP_ATTR_COMMUNITIES);
3099 stream_putw (s, attr->community->size * 4);
3100 }
3101 else
3102 {
3103 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3104 stream_putc (s, BGP_ATTR_COMMUNITIES);
3105 stream_putc (s, attr->community->size * 4);
3106 }
3107 stream_put (s, attr->community->val, attr->community->size * 4);
3108 }
3109
paula3845922003-10-18 01:30:50 +00003110#ifdef HAVE_IPV6
3111 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003112 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3113 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003114 {
3115 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003116 struct attr_extra *attre = attr->extra;
3117
paula3845922003-10-18 01:30:50 +00003118 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3119 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003120 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003121
3122 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003123 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003124 stream_putw(s, AFI_IP6); /* AFI */
3125 stream_putc(s, SAFI_UNICAST); /* SAFI */
3126
3127 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003128 stream_putc(s, attre->mp_nexthop_len);
3129 stream_put(s, &attre->mp_nexthop_global, 16);
3130 if (attre->mp_nexthop_len == 32)
3131 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003132
3133 /* SNPA */
3134 stream_putc(s, 0);
3135
3136 /* Prefix */
3137 stream_put_prefix(s, prefix);
3138
3139 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003140 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003141 }
3142#endif /* HAVE_IPV6 */
3143
paul718e3742002-12-13 20:15:29 +00003144 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003145 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003146 stream_putw_at (s, cp, len);
3147}