blob: 5dc118be650a348bd0a9689d1b09d2ab3724cf22 [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
Lou Berger298cc2f2016-01-12 13:42:02 -05001894 if (BGP_ATTR_ENCAP == type) {
1895 subtype = stream_getc (BGP_INPUT (peer));
1896 sublength = stream_getc (BGP_INPUT (peer));
1897 length -= 2;
1898 }
Lou Bergerc3741782016-01-12 13:42:01 -05001899
1900 if (sublength > length) {
1901 zlog (peer->log, LOG_ERR,
1902 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1903 sublength, length);
1904 bgp_notify_send_with_data (peer,
1905 BGP_NOTIFY_UPDATE_ERR,
1906 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1907 startp, total);
1908 return -1;
1909 }
1910
1911 /* alloc and copy sub-tlv */
1912 /* TBD make sure these are freed when attributes are released */
1913 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1914 tlv->type = subtype;
1915 tlv->length = sublength;
1916 stream_get(tlv->value, peer->ibuf, sublength);
1917 length -= sublength;
1918
1919 /* attach tlv to encap chain */
1920 if (!attre) {
1921 attre = bgp_attr_extra_get(attr);
1922 if (BGP_ATTR_ENCAP == type) {
1923 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1924 stlv_last = stlv_last->next);
1925 if (stlv_last) {
1926 stlv_last->next = tlv;
1927 } else {
1928 attre->encap_subtlvs = tlv;
1929 }
1930 }
1931 } else {
1932 stlv_last->next = tlv;
1933 }
1934 stlv_last = tlv;
1935 }
1936
1937 if (attre && (BGP_ATTR_ENCAP == type)) {
1938 attre->encap_tunneltype = tunneltype;
1939 }
1940
1941 if (length) {
1942 /* spurious leftover data */
1943 zlog (peer->log, LOG_ERR,
1944 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1945 bgp_notify_send_with_data (peer,
1946 BGP_NOTIFY_UPDATE_ERR,
1947 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1948 startp, total);
1949 return -1;
1950 }
1951
1952 return 0;
1953}
1954
paul718e3742002-12-13 20:15:29 +00001955/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001956static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001957bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001958{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001959 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001960 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001961 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001962 struct peer *const peer = args->peer;
1963 struct attr *const attr = args->attr;
1964 u_char *const startp = args->startp;
1965 const u_char type = args->type;
1966 const u_char flag = args->flags;
1967 const bgp_size_t length = args->length;
1968
paul718e3742002-12-13 20:15:29 +00001969
hassof4184462005-02-01 20:13:16 +00001970 if (BGP_DEBUG (normal, NORMAL))
1971 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1972 peer->host, type, length);
1973
paul718e3742002-12-13 20:15:29 +00001974 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001975 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001976 "Unknown attribute type %d length %d is received", type, length);
1977
1978 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001979 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001980
paul718e3742002-12-13 20:15:29 +00001981 /* If any of the mandatory well-known attributes are not recognized,
1982 then the Error Subcode is set to Unrecognized Well-known
1983 Attribute. The Data field contains the unrecognized attribute
1984 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001985 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001986 {
Paul Jakma835315b2012-01-18 12:28:30 +00001987 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001988 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001989 args->total);
paul718e3742002-12-13 20:15:29 +00001990 }
1991
1992 /* Unrecognized non-transitive optional attributes must be quietly
1993 ignored and not passed along to other BGP peers. */
1994 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001995 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001996
1997 /* If a path with recognized transitive optional attribute is
1998 accepted and passed along to other BGP peers and the Partial bit
1999 in the Attribute Flags octet is set to 1 by some previous AS, it
2000 is not set back to 0 by the current AS. */
2001 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
2002
2003 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002004 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07002005 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00002006
Paul Jakmafb982c22007-05-04 20:15:47 +00002007 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00002008
2009 if (transit->val)
2010 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2011 transit->length + total);
2012 else
2013 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2014
2015 memcpy (transit->val + transit->length, startp, total);
2016 transit->length += total;
2017
Paul Jakmab881c702010-11-23 16:35:42 +00002018 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002019}
2020
Paul Jakma055086f2014-09-23 15:23:01 +01002021/* Well-known attribute check. */
2022static int
2023bgp_attr_check (struct peer *peer, struct attr *attr)
2024{
2025 u_char type = 0;
2026
Paul Jakmaaed1b552014-10-21 16:59:01 +01002027 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2028 * empty UPDATE. */
2029 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2030 return BGP_ATTR_PARSE_PROCEED;
2031
2032 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2033 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2034 are present, it should. Check for any other attribute being present
2035 instead.
2036 */
2037 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2038 return BGP_ATTR_PARSE_PROCEED;
2039
Paul Jakma055086f2014-09-23 15:23:01 +01002040 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2041 type = BGP_ATTR_ORIGIN;
2042
2043 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2044 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002045
2046 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2047 * NLRI is empty. We can't easily check NLRI empty here though.
2048 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002049 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2050 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002051 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002052
Paul Jakma055086f2014-09-23 15:23:01 +01002053 if (peer->sort == BGP_PEER_IBGP
2054 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2055 type = BGP_ATTR_LOCAL_PREF;
2056
2057 if (type)
2058 {
2059 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002060 "%s Missing well-known attribute %d / %s",
2061 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002062 bgp_notify_send_with_data (peer,
2063 BGP_NOTIFY_UPDATE_ERR,
2064 BGP_NOTIFY_UPDATE_MISS_ATTR,
2065 &type, 1);
2066 return BGP_ATTR_PARSE_ERROR;
2067 }
2068 return BGP_ATTR_PARSE_PROCEED;
2069}
2070
paul718e3742002-12-13 20:15:29 +00002071/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002072 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002073bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002074bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2075 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2076{
2077 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002078 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002079 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002080 bgp_size_t length;
2081 u_char *startp, *endp;
2082 u_char *attr_endp;
2083 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002084 /* we need the as4_path only until we have synthesized the as_path with it */
2085 /* same goes for as4_aggregator */
2086 struct aspath *as4_path = NULL;
2087 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002088 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002089
2090 /* Initialize bitmap. */
2091 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2092
2093 /* End pointer of BGP attribute. */
2094 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002095
paul718e3742002-12-13 20:15:29 +00002096 /* Get attributes to the end of attribute length. */
2097 while (BGP_INPUT_PNT (peer) < endp)
2098 {
2099 /* Check remaining length check.*/
2100 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2101 {
gdtc29fdba2004-12-09 14:46:46 +00002102 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002103 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002104 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002105 peer->host,
2106 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002107
2108 bgp_notify_send (peer,
2109 BGP_NOTIFY_UPDATE_ERR,
2110 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002111 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002112 }
2113
2114 /* Fetch attribute flag and type. */
2115 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002116 /* "The lower-order four bits of the Attribute Flags octet are
2117 unused. They MUST be zero when sent and MUST be ignored when
2118 received." */
2119 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002120 type = stream_getc (BGP_INPUT (peer));
2121
Paul Jakma370b64a2007-12-22 16:49:52 +00002122 /* Check whether Extended-Length applies and is in bounds */
2123 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2124 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2125 {
2126 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002127 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002128 peer->host,
2129 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2130
2131 bgp_notify_send (peer,
2132 BGP_NOTIFY_UPDATE_ERR,
2133 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002134 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002135 }
Paul Jakma835315b2012-01-18 12:28:30 +00002136
paul718e3742002-12-13 20:15:29 +00002137 /* Check extended attribue length bit. */
2138 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2139 length = stream_getw (BGP_INPUT (peer));
2140 else
2141 length = stream_getc (BGP_INPUT (peer));
2142
2143 /* If any attribute appears more than once in the UPDATE
2144 message, then the Error Subcode is set to Malformed Attribute
2145 List. */
2146
2147 if (CHECK_BITMAP (seen, type))
2148 {
2149 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002150 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002151 peer->host, type);
2152
2153 bgp_notify_send (peer,
2154 BGP_NOTIFY_UPDATE_ERR,
2155 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002156 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002157 }
2158
2159 /* Set type to bitmap to check duplicate attribute. `type' is
2160 unsigned char so it never overflow bitmap range. */
2161
2162 SET_BITMAP (seen, type);
2163
2164 /* Overflow check. */
2165 attr_endp = BGP_INPUT_PNT (peer) + length;
2166
2167 if (attr_endp > endp)
2168 {
2169 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002170 "%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 +00002171 bgp_notify_send (peer,
2172 BGP_NOTIFY_UPDATE_ERR,
2173 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002174 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002175 }
Paul Jakma835315b2012-01-18 12:28:30 +00002176
2177 struct bgp_attr_parser_args attr_args = {
2178 .peer = peer,
2179 .length = length,
2180 .attr = attr,
2181 .type = type,
2182 .flags = flag,
2183 .startp = startp,
2184 .total = attr_endp - startp,
2185 };
2186
2187
2188 /* If any recognized attribute has Attribute Flags that conflict
2189 with the Attribute Type Code, then the Error Subcode is set to
2190 Attribute Flags Error. The Data field contains the erroneous
2191 attribute (type, length and value). */
2192 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002193 {
2194 bgp_attr_parse_ret_t ret;
2195 ret = bgp_attr_malformed (&attr_args,
2196 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2197 attr_args.total);
2198 if (ret == BGP_ATTR_PARSE_PROCEED)
2199 continue;
2200 return ret;
2201 }
paul718e3742002-12-13 20:15:29 +00002202
2203 /* OK check attribute and store it's value. */
2204 switch (type)
2205 {
2206 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002207 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002208 break;
2209 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002210 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002211 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002212 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002213 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002214 break;
paul718e3742002-12-13 20:15:29 +00002215 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002216 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002217 break;
2218 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002219 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002220 break;
2221 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002222 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002223 break;
2224 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002225 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002226 break;
2227 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002228 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002229 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002230 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002231 ret = bgp_attr_as4_aggregator (&attr_args,
2232 &as4_aggregator,
2233 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002234 break;
paul718e3742002-12-13 20:15:29 +00002235 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002236 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002237 break;
2238 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002239 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002240 break;
2241 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002242 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002243 break;
2244 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002245 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002246 break;
2247 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002248 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002249 break;
2250 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002251 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002252 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002253 case BGP_ATTR_ENCAP:
2254 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2255 break;
paul718e3742002-12-13 20:15:29 +00002256 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002257 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002258 break;
2259 }
Paul Jakmab881c702010-11-23 16:35:42 +00002260
David Lamparterf57000c2014-06-04 01:01:10 +02002261 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2262 {
2263 bgp_notify_send (peer,
2264 BGP_NOTIFY_UPDATE_ERR,
2265 BGP_NOTIFY_UPDATE_MAL_ATTR);
2266 ret = BGP_ATTR_PARSE_ERROR;
2267 }
2268
Paul Jakmab881c702010-11-23 16:35:42 +00002269 /* If hard error occured immediately return to the caller. */
2270 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002271 {
2272 zlog (peer->log, LOG_WARNING,
2273 "%s: Attribute %s, parse error",
2274 peer->host,
2275 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002276 if (as4_path)
2277 aspath_unintern (&as4_path);
2278 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002279 }
Paul Jakmab881c702010-11-23 16:35:42 +00002280 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2281 {
2282
2283 zlog (peer->log, LOG_WARNING,
2284 "%s: Attribute %s, parse error - treating as withdrawal",
2285 peer->host,
2286 LOOKUP (attr_str, type));
2287 if (as4_path)
2288 aspath_unintern (&as4_path);
2289 return ret;
2290 }
2291
paul718e3742002-12-13 20:15:29 +00002292 /* Check the fetched length. */
2293 if (BGP_INPUT_PNT (peer) != attr_endp)
2294 {
2295 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002296 "%s: BGP attribute %s, fetch error",
2297 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002298 bgp_notify_send (peer,
2299 BGP_NOTIFY_UPDATE_ERR,
2300 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002301 if (as4_path)
2302 aspath_unintern (&as4_path);
2303 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002304 }
2305 }
paul718e3742002-12-13 20:15:29 +00002306 /* Check final read pointer is same as end pointer. */
2307 if (BGP_INPUT_PNT (peer) != endp)
2308 {
2309 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002310 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002311 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002312 bgp_notify_send (peer,
2313 BGP_NOTIFY_UPDATE_ERR,
2314 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002315 if (as4_path)
2316 aspath_unintern (&as4_path);
2317 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002318 }
Paul Jakma055086f2014-09-23 15:23:01 +01002319
2320 /* Check all mandatory well-known attributes are present */
2321 {
2322 bgp_attr_parse_ret_t ret;
2323 if ((ret = bgp_attr_check (peer, attr)) < 0)
2324 {
2325 if (as4_path)
2326 aspath_unintern (&as4_path);
2327 return ret;
2328 }
2329 }
2330
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002331 /*
2332 * At this place we can see whether we got AS4_PATH and/or
2333 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2334 * We can not do this before we've read all attributes because
2335 * the as4 handling does not say whether AS4_PATH has to be sent
2336 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2337 * in relationship to AGGREGATOR.
2338 * So, to be defensive, we are not relying on any order and read
2339 * all attributes first, including these 32bit ones, and now,
2340 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002341 *
2342 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2343 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002344 */
David Lamparterf57000c2014-06-04 01:01:10 +02002345 /* actually... this doesn't ever return failure currently, but
2346 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002347 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2348 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002349 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002350 {
David Lamparterf57000c2014-06-04 01:01:10 +02002351 bgp_notify_send (peer,
2352 BGP_NOTIFY_UPDATE_ERR,
2353 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002354 if (as4_path)
2355 aspath_unintern (&as4_path);
2356 return BGP_ATTR_PARSE_ERROR;
2357 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002358
2359 /* At this stage, we have done all fiddling with as4, and the
2360 * resulting info is in attr->aggregator resp. attr->aspath
2361 * so we can chuck as4_aggregator and as4_path alltogether in
2362 * order to save memory
2363 */
Paul Jakmab881c702010-11-23 16:35:42 +00002364 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002365 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002366 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002367 /* The flag that we got this is still there, but that does not
2368 * do any trouble
2369 */
2370 }
2371 /*
2372 * The "rest" of the code does nothing with as4_aggregator.
2373 * there is no memory attached specifically which is not part
2374 * of the attr.
2375 * so ignoring just means do nothing.
2376 */
2377 /*
2378 * Finally do the checks on the aspath we did not do yet
2379 * because we waited for a potentially synthesized aspath.
2380 */
Paul Jakmab881c702010-11-23 16:35:42 +00002381 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002382 {
Paul Jakma835315b2012-01-18 12:28:30 +00002383 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002384 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002385 return ret;
2386 }
2387
paul718e3742002-12-13 20:15:29 +00002388 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002389 if (attr->extra && attr->extra->transit)
2390 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002391
Paul Jakmab881c702010-11-23 16:35:42 +00002392 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002393}
2394
paul718e3742002-12-13 20:15:29 +00002395int stream_put_prefix (struct stream *, struct prefix *);
2396
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002397size_t
2398bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2399 struct attr *attr)
2400{
2401 size_t sizep;
2402
2403 /* Set extended bit always to encode the attribute length as 2 bytes */
2404 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2405 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2406 sizep = stream_get_endp (s);
2407 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002408
2409 stream_putw (s, afi);
2410 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002411
2412 /* Nexthop */
2413 switch (afi)
2414 {
2415 case AFI_IP:
2416 switch (safi)
2417 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002418 case SAFI_MULTICAST:
2419 stream_putc (s, 4);
2420 stream_put_ipv4 (s, attr->nexthop.s_addr);
2421 break;
2422 case SAFI_MPLS_VPN:
2423 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002424 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002425 stream_putl (s, 0);
2426 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2427 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002428 case SAFI_ENCAP:
2429 stream_putc (s, 4);
2430 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2431 break;
Lou Berger050defe2016-01-12 13:41:59 -05002432 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002433 default:
2434 break;
2435 }
2436 break;
2437#ifdef HAVE_IPV6
2438 case AFI_IP6:
2439 switch (safi)
2440 {
2441 case SAFI_UNICAST:
2442 case SAFI_MULTICAST:
2443 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002444 struct attr_extra *attre = attr->extra;
2445
2446 assert (attr->extra);
2447 stream_putc (s, attre->mp_nexthop_len);
2448 stream_put (s, &attre->mp_nexthop_global, 16);
2449 if (attre->mp_nexthop_len == 32)
2450 stream_put (s, &attre->mp_nexthop_local, 16);
2451 }
Lou Berger050defe2016-01-12 13:41:59 -05002452 break;
2453 case SAFI_MPLS_VPN:
2454 {
2455 struct attr_extra *attre = attr->extra;
2456
2457 assert (attr->extra);
2458 if (attre->mp_nexthop_len == 16) {
2459 stream_putc (s, 24);
2460 stream_putl (s, 0); /* RD = 0, per RFC */
2461 stream_putl (s, 0);
2462 stream_put (s, &attre->mp_nexthop_global, 16);
2463 } else if (attre->mp_nexthop_len == 32) {
2464 stream_putc (s, 48);
2465 stream_putl (s, 0); /* RD = 0, per RFC */
2466 stream_putl (s, 0);
2467 stream_put (s, &attre->mp_nexthop_global, 16);
2468 stream_putl (s, 0); /* RD = 0, per RFC */
2469 stream_putl (s, 0);
2470 stream_put (s, &attre->mp_nexthop_local, 16);
2471 }
2472 }
2473 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002474 case SAFI_ENCAP:
2475 assert (attr->extra);
2476 stream_putc (s, 16);
2477 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2478 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002479 default:
2480 break;
2481 }
2482 break;
2483#endif /*HAVE_IPV6*/
2484 default:
2485 break;
2486 }
2487
2488 /* SNPA */
2489 stream_putc (s, 0);
2490 return sizep;
2491}
2492
2493void
2494bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2495 struct prefix *p, struct prefix_rd *prd,
2496 u_char *tag)
2497{
Lou Berger050defe2016-01-12 13:41:59 -05002498 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002499 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002500 /* Tag, RD, Prefix write. */
2501 stream_putc (s, p->prefixlen + 88);
2502 stream_put (s, tag, 3);
2503 stream_put (s, prd->val, 8);
2504 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002505 }
Lou Berger050defe2016-01-12 13:41:59 -05002506 else
2507 stream_put_prefix (s, p);
2508}
2509
2510size_t
2511bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2512{
2513 int size = PSIZE (p->prefixlen);
2514 if (safi == SAFI_MPLS_VPN)
2515 size += 88;
2516 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002517}
2518
Lou Bergerc3741782016-01-12 13:42:01 -05002519/*
2520 * Encodes the tunnel encapsulation attribute
2521 */
2522static void
2523bgp_packet_mpattr_tea(
2524 struct bgp *bgp,
2525 struct peer *peer,
2526 struct stream *s,
2527 struct attr *attr,
2528 uint8_t attrtype)
2529{
2530 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002531 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002532 struct bgp_attr_encap_subtlv *subtlvs;
2533 struct bgp_attr_encap_subtlv *st;
2534 const char *attrname;
2535
2536 if (!attr || !attr->extra)
2537 return;
2538
2539 switch (attrtype) {
2540 case BGP_ATTR_ENCAP:
2541 attrname = "Tunnel Encap";
2542 subtlvs = attr->extra->encap_subtlvs;
2543
2544 /*
2545 * The tunnel encap attr has an "outer" tlv.
2546 * T = tunneltype,
2547 * L = total length of subtlvs,
2548 * V = concatenated subtlvs.
2549 */
2550 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002551 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002552 break;
2553
2554 default:
2555 assert(0);
2556 }
2557
2558
Lou Berger298cc2f2016-01-12 13:42:02 -05002559 /* if no tlvs, don't make attr */
2560 if (subtlvs == NULL)
2561 return;
2562
Lou Bergerc3741782016-01-12 13:42:01 -05002563 /* compute attr length */
2564 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002565 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002566 }
2567
Lou Bergerc3741782016-01-12 13:42:01 -05002568 if (attrlenfield > 0xffff) {
2569 zlog (peer->log, LOG_ERR,
2570 "%s attribute is too long (length=%d), can't send it",
2571 attrname,
2572 attrlenfield);
2573 return;
2574 }
2575
2576 if (attrlenfield > 0xff) {
2577 /* 2-octet length field */
2578 stream_putc (s,
2579 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2580 stream_putc (s, attrtype);
2581 stream_putw (s, attrlenfield & 0xffff);
2582 } else {
2583 /* 1-octet length field */
2584 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2585 stream_putc (s, attrtype);
2586 stream_putc (s, attrlenfield & 0xff);
2587 }
2588
2589 if (attrtype == BGP_ATTR_ENCAP) {
2590 /* write outer T+L */
2591 stream_putw(s, attr->extra->encap_tunneltype);
2592 stream_putw(s, attrlenfield - 4);
2593 }
2594
2595 /* write each sub-tlv */
2596 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002597 if (attrtype == BGP_ATTR_ENCAP) {
2598 stream_putc (s, st->type);
2599 stream_putc (s, st->length);
2600 }
Lou Bergerc3741782016-01-12 13:42:01 -05002601 stream_put (s, st->value, st->length);
2602 }
2603}
2604
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002605void
2606bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2607{
2608 /* Set MP attribute length. Don't count the (2) bytes used to encode
2609 the attr length */
2610 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2611}
2612
paul718e3742002-12-13 20:15:29 +00002613/* Make attribute packet. */
2614bgp_size_t
2615bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002616 struct stream *s, struct attr *attr,
2617 struct prefix *p, afi_t afi, safi_t safi,
2618 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002619{
paulfe69a502005-09-10 16:55:02 +00002620 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002621 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002622 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002623 int send_as4_path = 0;
2624 int send_as4_aggregator = 0;
2625 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002626
2627 if (! bgp)
2628 bgp = bgp_get_default ();
2629
2630 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002631 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002632
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002633 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2634 {
Lou Berger050defe2016-01-12 13:41:59 -05002635 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002636 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2637 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2638 bgp_packet_mpattr_end(s, mpattrlen_pos);
2639 }
2640
paul718e3742002-12-13 20:15:29 +00002641 /* Origin attribute. */
2642 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2643 stream_putc (s, BGP_ATTR_ORIGIN);
2644 stream_putc (s, 1);
2645 stream_putc (s, attr->origin);
2646
2647 /* AS path attribute. */
2648
2649 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002650 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002651 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002652 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002653 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002654 {
2655 aspath = aspath_dup (attr->aspath);
2656
2657 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2658 {
2659 /* Strip the confed info, and then stuff our path CONFED_ID
2660 on the front */
2661 aspath = aspath_delete_confed_seq (aspath);
2662 aspath = aspath_add_seq (aspath, bgp->confed_id);
2663 }
2664 else
2665 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002666 if (peer->change_local_as) {
2667 /* If replace-as is specified, we only use the change_local_as when
2668 advertising routes. */
2669 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2670 aspath = aspath_add_seq (aspath, peer->local_as);
2671 }
paul718e3742002-12-13 20:15:29 +00002672 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002673 } else {
2674 aspath = aspath_add_seq (aspath, peer->local_as);
2675 }
paul718e3742002-12-13 20:15:29 +00002676 }
2677 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002678 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002679 {
2680 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2681 aspath = aspath_dup (attr->aspath);
2682 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2683 }
2684 else
2685 aspath = attr->aspath;
2686
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002687 /* If peer is not AS4 capable, then:
2688 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2689 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2690 * types are in it (i.e. exclude them if they are there)
2691 * AND do this only if there is at least one asnum > 65535 in the path!
2692 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2693 * all ASnums > 65535 to BGP_AS_TRANS
2694 */
paul718e3742002-12-13 20:15:29 +00002695
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002696 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2697 stream_putc (s, BGP_ATTR_AS_PATH);
2698 aspath_sizep = stream_get_endp (s);
2699 stream_putw (s, 0);
2700 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2701
2702 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2703 * in the path
2704 */
2705 if (!use32bit && aspath_has_as4 (aspath))
2706 send_as4_path = 1; /* we'll do this later, at the correct place */
2707
paul718e3742002-12-13 20:15:29 +00002708 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002709 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2710 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002711 {
2712 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2713 stream_putc (s, BGP_ATTR_NEXT_HOP);
2714 stream_putc (s, 4);
2715 if (safi == SAFI_MPLS_VPN)
2716 {
2717 if (attr->nexthop.s_addr == 0)
2718 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2719 else
2720 stream_put_ipv4 (s, attr->nexthop.s_addr);
2721 }
2722 else
2723 stream_put_ipv4 (s, attr->nexthop.s_addr);
2724 }
2725
2726 /* MED attribute. */
2727 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2728 {
2729 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2730 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2731 stream_putc (s, 4);
2732 stream_putl (s, attr->med);
2733 }
2734
2735 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002736 if (peer->sort == BGP_PEER_IBGP ||
2737 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002738 {
2739 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2740 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2741 stream_putc (s, 4);
2742 stream_putl (s, attr->local_pref);
2743 }
2744
2745 /* Atomic aggregate. */
2746 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2747 {
2748 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2749 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2750 stream_putc (s, 0);
2751 }
2752
2753 /* Aggregator. */
2754 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2755 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002756 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002757
2758 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002759 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2760 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002761
2762 if (use32bit)
2763 {
2764 /* AS4 capable peer */
2765 stream_putc (s, 8);
2766 stream_putl (s, attr->extra->aggregator_as);
2767 }
2768 else
2769 {
2770 /* 2-byte AS peer */
2771 stream_putc (s, 6);
2772
2773 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2774 if ( attr->extra->aggregator_as > 65535 )
2775 {
2776 stream_putw (s, BGP_AS_TRANS);
2777
2778 /* we have to send AS4_AGGREGATOR, too.
2779 * we'll do that later in order to send attributes in ascending
2780 * order.
2781 */
2782 send_as4_aggregator = 1;
2783 }
2784 else
2785 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2786 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002787 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002788 }
2789
2790 /* Community attribute. */
2791 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2792 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2793 {
2794 if (attr->community->size * 4 > 255)
2795 {
2796 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2797 stream_putc (s, BGP_ATTR_COMMUNITIES);
2798 stream_putw (s, attr->community->size * 4);
2799 }
2800 else
2801 {
2802 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2803 stream_putc (s, BGP_ATTR_COMMUNITIES);
2804 stream_putc (s, attr->community->size * 4);
2805 }
2806 stream_put (s, attr->community->val, attr->community->size * 4);
2807 }
2808
2809 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002810 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002811 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002812 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002813 {
2814 /* Originator ID. */
2815 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2816 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2817 stream_putc (s, 4);
2818
2819 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002820 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002821 else
2822 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002823
2824 /* Cluster list. */
2825 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2826 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2827
Paul Jakma9eda90c2007-08-30 13:36:17 +00002828 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002829 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002830 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002831 /* If this peer configuration's parent BGP has cluster_id. */
2832 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2833 stream_put_in_addr (s, &bgp->cluster_id);
2834 else
2835 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002836 stream_put (s, attr->extra->cluster->list,
2837 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002838 }
2839 else
2840 {
2841 stream_putc (s, 4);
2842 /* If this peer configuration's parent BGP has cluster_id. */
2843 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2844 stream_put_in_addr (s, &bgp->cluster_id);
2845 else
2846 stream_put_in_addr (s, &bgp->router_id);
2847 }
2848 }
2849
paul718e3742002-12-13 20:15:29 +00002850 /* Extended Communities attribute. */
2851 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2852 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2853 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002854 struct attr_extra *attre = attr->extra;
2855
2856 assert (attre);
2857
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002858 if (peer->sort == BGP_PEER_IBGP
2859 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002860 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002861 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002862 {
2863 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2864 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002865 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002866 }
2867 else
2868 {
2869 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2870 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002871 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002872 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002873 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002874 }
2875 else
2876 {
paul5228ad22004-06-04 17:58:18 +00002877 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002878 int tbit;
2879 int ecom_tr_size = 0;
2880 int i;
2881
Paul Jakmafb982c22007-05-04 20:15:47 +00002882 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002883 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002884 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002885 tbit = *pnt;
2886
2887 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2888 continue;
2889
2890 ecom_tr_size++;
2891 }
2892
2893 if (ecom_tr_size)
2894 {
2895 if (ecom_tr_size * 8 > 255)
2896 {
2897 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2898 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2899 stream_putw (s, ecom_tr_size * 8);
2900 }
2901 else
2902 {
2903 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2904 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2905 stream_putc (s, ecom_tr_size * 8);
2906 }
2907
Paul Jakmafb982c22007-05-04 20:15:47 +00002908 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002909 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002910 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002911 tbit = *pnt;
2912
2913 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2914 continue;
2915
2916 stream_put (s, pnt, 8);
2917 }
2918 }
paul718e3742002-12-13 20:15:29 +00002919 }
paul718e3742002-12-13 20:15:29 +00002920 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002921
2922 if ( send_as4_path )
2923 {
2924 /* If the peer is NOT As4 capable, AND */
2925 /* there are ASnums > 65535 in path THEN
2926 * give out AS4_PATH */
2927
2928 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2929 * path segments!
2930 * Hm, I wonder... confederation things *should* only be at
2931 * the beginning of an aspath, right? Then we should use
2932 * aspath_delete_confed_seq for this, because it is already
2933 * there! (JK)
2934 * Folks, talk to me: what is reasonable here!?
2935 */
2936 aspath = aspath_delete_confed_seq (aspath);
2937
2938 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2939 stream_putc (s, BGP_ATTR_AS4_PATH);
2940 aspath_sizep = stream_get_endp (s);
2941 stream_putw (s, 0);
2942 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2943 }
2944
2945 if (aspath != attr->aspath)
2946 aspath_free (aspath);
2947
2948 if ( send_as4_aggregator )
2949 {
2950 assert (attr->extra);
2951
2952 /* send AS4_AGGREGATOR, at this place */
2953 /* this section of code moved here in order to ensure the correct
2954 * *ascending* order of attributes
2955 */
2956 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2957 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2958 stream_putc (s, 8);
2959 stream_putl (s, attr->extra->aggregator_as);
2960 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2961 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002962
2963 if ((afi == AFI_IP || afi == AFI_IP6) &&
2964 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2965 {
2966 /* Tunnel Encap attribute */
2967 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2968 }
2969
paul718e3742002-12-13 20:15:29 +00002970 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002971 if (attr->extra && attr->extra->transit)
2972 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002973
2974 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002975 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002976}
2977
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002978size_t
2979bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002980{
paul718e3742002-12-13 20:15:29 +00002981 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002982
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002983 /* Set extended bit always to encode the attribute length as 2 bytes */
2984 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002985 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2986
paul9985f832005-02-09 15:51:56 +00002987 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002988 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002989
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002990 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002991 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002992 return attrlen_pnt;
2993}
paul718e3742002-12-13 20:15:29 +00002994
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002995void
2996bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2997 afi_t afi, safi_t safi, struct prefix_rd *prd,
2998 u_char *tag)
2999{
Lou Berger050defe2016-01-12 13:41:59 -05003000 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003001}
paul718e3742002-12-13 20:15:29 +00003002
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00003003void
3004bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
3005{
Lou Berger050defe2016-01-12 13:41:59 -05003006 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00003007}
3008
3009/* Initialization of attribute. */
3010void
paulfe69a502005-09-10 16:55:02 +00003011bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00003012{
paul718e3742002-12-13 20:15:29 +00003013 aspath_init ();
3014 attrhash_init ();
3015 community_init ();
3016 ecommunity_init ();
3017 cluster_init ();
3018 transit_init ();
3019}
3020
Chris Caputo228da422009-07-18 05:44:03 +00003021void
3022bgp_attr_finish (void)
3023{
3024 aspath_finish ();
3025 attrhash_finish ();
3026 community_finish ();
3027 ecommunity_finish ();
3028 cluster_finish ();
3029 transit_finish ();
3030}
3031
paul718e3742002-12-13 20:15:29 +00003032/* Make attribute packet. */
3033void
paula3845922003-10-18 01:30:50 +00003034bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3035 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003036{
3037 unsigned long cp;
3038 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003039 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003040 struct aspath *aspath;
3041
3042 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003043 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003044
3045 /* Place holder of length. */
3046 stream_putw (s, 0);
3047
3048 /* Origin attribute. */
3049 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3050 stream_putc (s, BGP_ATTR_ORIGIN);
3051 stream_putc (s, 1);
3052 stream_putc (s, attr->origin);
3053
3054 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003055
3056 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3057 stream_putc (s, BGP_ATTR_AS_PATH);
3058 aspath_lenp = stream_get_endp (s);
3059 stream_putw (s, 0);
3060
3061 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003062
3063 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003064 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3065 if(prefix != NULL
3066#ifdef HAVE_IPV6
3067 && prefix->family != AF_INET6
3068#endif /* HAVE_IPV6 */
3069 )
3070 {
3071 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3072 stream_putc (s, BGP_ATTR_NEXT_HOP);
3073 stream_putc (s, 4);
3074 stream_put_ipv4 (s, attr->nexthop.s_addr);
3075 }
paul718e3742002-12-13 20:15:29 +00003076
3077 /* MED attribute. */
3078 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3079 {
3080 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3081 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3082 stream_putc (s, 4);
3083 stream_putl (s, attr->med);
3084 }
3085
3086 /* Local preference. */
3087 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3088 {
3089 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3090 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3091 stream_putc (s, 4);
3092 stream_putl (s, attr->local_pref);
3093 }
3094
3095 /* Atomic aggregate. */
3096 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3097 {
3098 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3099 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3100 stream_putc (s, 0);
3101 }
3102
3103 /* Aggregator. */
3104 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3105 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003106 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003107 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3108 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003109 stream_putc (s, 8);
3110 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003111 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003112 }
3113
3114 /* Community attribute. */
3115 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3116 {
3117 if (attr->community->size * 4 > 255)
3118 {
3119 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3120 stream_putc (s, BGP_ATTR_COMMUNITIES);
3121 stream_putw (s, attr->community->size * 4);
3122 }
3123 else
3124 {
3125 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3126 stream_putc (s, BGP_ATTR_COMMUNITIES);
3127 stream_putc (s, attr->community->size * 4);
3128 }
3129 stream_put (s, attr->community->val, attr->community->size * 4);
3130 }
3131
paula3845922003-10-18 01:30:50 +00003132#ifdef HAVE_IPV6
3133 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003134 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3135 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003136 {
3137 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003138 struct attr_extra *attre = attr->extra;
3139
paula3845922003-10-18 01:30:50 +00003140 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3141 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003142 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003143
3144 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003145 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003146 stream_putw(s, AFI_IP6); /* AFI */
3147 stream_putc(s, SAFI_UNICAST); /* SAFI */
3148
3149 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003150 stream_putc(s, attre->mp_nexthop_len);
3151 stream_put(s, &attre->mp_nexthop_global, 16);
3152 if (attre->mp_nexthop_len == 32)
3153 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003154
3155 /* SNPA */
3156 stream_putc(s, 0);
3157
3158 /* Prefix */
3159 stream_put_prefix(s, prefix);
3160
3161 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003162 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003163 }
3164#endif /* HAVE_IPV6 */
3165
paul718e3742002-12-13 20:15:29 +00003166 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003167 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003168 stream_putw_at (s, cp, len);
3169}