blob: 3b96bb24f4f10dddbd84bbbabe28466f037ef2d2 [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);
Piotr Chytła605aa332015-12-01 10:03:54 -0500498 MIX(extra->tag);
Paul Jakmafb982c22007-05-04 20:15:47 +0000499 }
500
paul718e3742002-12-13 20:15:29 +0000501 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700502 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000503 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700504 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000505
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000506 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000507 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000508 if (extra->ecommunity)
509 MIX(ecommunity_hash_make (extra->ecommunity));
510 if (extra->cluster)
511 MIX(cluster_hash_key_make (extra->cluster));
512 if (extra->transit)
513 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000514
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);
Paul Jakmafb982c22007-05-04 20:15:47 +0000518 }
paul718e3742002-12-13 20:15:29 +0000519
520 return key;
521}
522
523int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100524attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000525{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100526 const struct attr * attr1 = p1;
527 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000528
paul718e3742002-12-13 20:15:29 +0000529 if (attr1->flag == attr2->flag
530 && attr1->origin == attr2->origin
531 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000532 && attr1->aspath == attr2->aspath
533 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000534 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000535 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000536 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100537 const struct attr_extra *ae1 = attr1->extra;
538 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000539
540 if (ae1 && ae2
541 && ae1->aggregator_as == ae2->aggregator_as
542 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
543 && ae1->weight == ae2->weight
Piotr Chytła605aa332015-12-01 10:03:54 -0500544 && ae1->tag == ae2->tag
Paul Jakmafb982c22007-05-04 20:15:47 +0000545 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
546 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
547 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
Paul Jakmafb982c22007-05-04 20:15:47 +0000548 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
549 && ae1->ecommunity == ae2->ecommunity
550 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000551 && ae1->transit == ae2->transit
Lou Bergerc3741782016-01-12 13:42:01 -0500552 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
553 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000554 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000555 return 1;
556 else if (ae1 || ae2)
557 return 0;
558 /* neither attribute has extra attributes, so they're same */
559 return 1;
560 }
paul718e3742002-12-13 20:15:29 +0000561 else
562 return 0;
563}
564
paul94f2b392005-06-28 12:44:16 +0000565static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100566attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000567{
568 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
569}
570
Lou Berger056f3762013-04-10 12:30:04 -0700571/*
572 * special for hash_clean below
573 */
574static void
575attr_vfree (void *attr)
576{
577 bgp_attr_extra_free ((struct attr *)attr);
578 XFREE (MTYPE_ATTR, attr);
579}
580
paul94f2b392005-06-28 12:44:16 +0000581static void
Chris Caputo228da422009-07-18 05:44:03 +0000582attrhash_finish (void)
583{
Lou Berger056f3762013-04-10 12:30:04 -0700584 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000585 hash_free (attrhash);
586 attrhash = NULL;
587}
588
589static void
paul718e3742002-12-13 20:15:29 +0000590attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
591{
592 struct attr *attr = backet->data;
593
594 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
595 inet_ntoa (attr->nexthop), VTY_NEWLINE);
596}
597
598void
599attr_show_all (struct vty *vty)
600{
601 hash_iterate (attrhash,
602 (void (*)(struct hash_backet *, void *))
603 attr_show_all_iterator,
604 vty);
605}
606
paul94f2b392005-06-28 12:44:16 +0000607static void *
Paul Jakma923de652007-04-29 18:25:17 +0000608bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000609{
Paul Jakma923de652007-04-29 18:25:17 +0000610 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000611 struct attr *attr;
612
613 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
614 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000615 if (val->extra)
616 {
617 attr->extra = bgp_attr_extra_new ();
618 *attr->extra = *val->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500619
620 if (attr->extra->encap_subtlvs) {
621 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
622 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000623 }
paul718e3742002-12-13 20:15:29 +0000624 attr->refcnt = 0;
625 return attr;
626}
627
628/* Internet argument attribute. */
629struct attr *
630bgp_attr_intern (struct attr *attr)
631{
632 struct attr *find;
633
634 /* Intern referenced strucutre. */
635 if (attr->aspath)
636 {
637 if (! attr->aspath->refcnt)
638 attr->aspath = aspath_intern (attr->aspath);
639 else
640 attr->aspath->refcnt++;
641 }
642 if (attr->community)
643 {
644 if (! attr->community->refcnt)
645 attr->community = community_intern (attr->community);
646 else
647 attr->community->refcnt++;
648 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000649 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000650 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000651 struct attr_extra *attre = attr->extra;
652
653 if (attre->ecommunity)
654 {
655 if (! attre->ecommunity->refcnt)
656 attre->ecommunity = ecommunity_intern (attre->ecommunity);
657 else
658 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000659
Paul Jakmafb982c22007-05-04 20:15:47 +0000660 }
661 if (attre->cluster)
662 {
663 if (! attre->cluster->refcnt)
664 attre->cluster = cluster_intern (attre->cluster);
665 else
666 attre->cluster->refcnt++;
667 }
668 if (attre->transit)
669 {
670 if (! attre->transit->refcnt)
671 attre->transit = transit_intern (attre->transit);
672 else
673 attre->transit->refcnt++;
674 }
paul718e3742002-12-13 20:15:29 +0000675 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000676
paul718e3742002-12-13 20:15:29 +0000677 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
678 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000679
paul718e3742002-12-13 20:15:29 +0000680 return find;
681}
682
Paul Jakma03e214c2007-04-29 18:31:07 +0000683
paul718e3742002-12-13 20:15:29 +0000684/* Make network statement's attribute. */
685struct attr *
686bgp_attr_default_set (struct attr *attr, u_char origin)
687{
688 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000689 bgp_attr_extra_get (attr);
690
paul718e3742002-12-13 20:15:29 +0000691 attr->origin = origin;
692 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
693 attr->aspath = aspath_empty ();
694 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000695 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
Piotr Chytła605aa332015-12-01 10:03:54 -0500696 attr->extra->tag = 0;
paul718e3742002-12-13 20:15:29 +0000697 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
Paul Jakmafb982c22007-05-04 20:15:47 +0000698 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
Paul Jakma03e214c2007-04-29 18:31:07 +0000699
paul718e3742002-12-13 20:15:29 +0000700 return attr;
701}
702
Paul Jakma03e214c2007-04-29 18:31:07 +0000703
paul718e3742002-12-13 20:15:29 +0000704/* Make network statement's attribute. */
705struct attr *
706bgp_attr_default_intern (u_char origin)
707{
708 struct attr attr;
709 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000710
Lou Bergerc3741782016-01-12 13:42:01 -0500711 memset (&attr, 0, sizeof (struct attr));
712 bgp_attr_extra_get (&attr);
713
Paul Jakma03e214c2007-04-29 18:31:07 +0000714 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000715
716 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000717 bgp_attr_extra_free (&attr);
718
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000719 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000720 return new;
721}
722
Daniel Walton76a72802015-05-19 17:47:24 -0700723/* Create the attributes for an aggregate */
paul718e3742002-12-13 20:15:29 +0000724struct attr *
725bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
726 struct aspath *aspath,
Daniel Waltonf2eb9ca2015-05-19 17:47:21 -0700727 struct community *community, int as_set,
728 u_char atomic_aggregate)
paul718e3742002-12-13 20:15:29 +0000729{
730 struct attr attr;
731 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000732 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000733
734 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000735 memset (&attre, 0, sizeof (struct attr_extra));
736 attr.extra = &attre;
737
paul718e3742002-12-13 20:15:29 +0000738 /* Origin attribute. */
739 attr.origin = origin;
740 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
741
742 /* AS path attribute. */
743 if (aspath)
744 attr.aspath = aspath_intern (aspath);
745 else
746 attr.aspath = aspath_empty ();
747 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
748
749 /* Next hop attribute. */
750 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
751
752 if (community)
753 {
754 attr.community = community;
755 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
756 }
757
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000758 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000759 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
Lou Berger205e6742016-01-12 13:42:11 -0500760
Daniel Waltonf2eb9ca2015-05-19 17:47:21 -0700761 if (! as_set || atomic_aggregate)
paul718e3742002-12-13 20:15:29 +0000762 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
763 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
764 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000765 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000766 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000767 attre.aggregator_as = bgp->as;
768 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000769
770 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000771
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000772 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000773 return new;
774}
775
Paul Jakmab881c702010-11-23 16:35:42 +0000776/* Unintern just the sub-components of the attr, but not the attr */
777void
778bgp_attr_unintern_sub (struct attr *attr)
779{
780 /* aspath refcount shoud be decrement. */
781 if (attr->aspath)
782 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000783 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000784
785 if (attr->community)
786 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000787 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000788
789 if (attr->extra)
790 {
791 if (attr->extra->ecommunity)
792 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000793 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000794
795 if (attr->extra->cluster)
796 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000797 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000798
799 if (attr->extra->transit)
800 transit_unintern (attr->extra->transit);
801 }
802}
803
paul718e3742002-12-13 20:15:29 +0000804/* Free bgp attribute and aspath. */
805void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000806bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000807{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000808 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000809 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000810 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000811 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000812
paul718e3742002-12-13 20:15:29 +0000813 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000814 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000815
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000816 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000817
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000818 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000819 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000820 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000821 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000822 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000823
paul718e3742002-12-13 20:15:29 +0000824 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000825 if (attr->refcnt == 0)
826 {
827 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000828 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000829 bgp_attr_extra_free (attr);
830 XFREE (MTYPE_ATTR, attr);
831 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000832 }
833
Paul Jakmab881c702010-11-23 16:35:42 +0000834 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000835}
836
837void
838bgp_attr_flush (struct attr *attr)
839{
840 if (attr->aspath && ! attr->aspath->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500841 {
842 aspath_free (attr->aspath);
843 attr->aspath = NULL;
844 }
paul718e3742002-12-13 20:15:29 +0000845 if (attr->community && ! attr->community->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500846 {
847 community_free (attr->community);
848 attr->community = NULL;
849 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000850 if (attr->extra)
851 {
852 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000853
Paul Jakmafb982c22007-05-04 20:15:47 +0000854 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000855 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000856 if (attre->cluster && ! attre->cluster->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500857 {
858 cluster_free (attre->cluster);
859 attre->cluster = NULL;
860 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000861 if (attre->transit && ! attre->transit->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500862 {
863 transit_free (attre->transit);
864 attre->transit = NULL;
865 }
Lou Bergerc3741782016-01-12 13:42:01 -0500866 encap_free(attre->encap_subtlvs);
867 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000868 }
paul718e3742002-12-13 20:15:29 +0000869}
870
Paul Jakmab881c702010-11-23 16:35:42 +0000871/* Implement draft-scudder-idr-optional-transitive behaviour and
872 * avoid resetting sessions for malformed attributes which are
873 * are partial/optional and hence where the error likely was not
874 * introduced by the sending neighbour.
875 */
876static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000877bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
878 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000879{
Paul Jakma835315b2012-01-18 12:28:30 +0000880 struct peer *const peer = args->peer;
881 const u_int8_t flags = args->flags;
882 /* startp and length must be special-cased, as whether or not to
883 * send the attribute data with the NOTIFY depends on the error,
884 * the caller therefore signals this with the seperate length argument
885 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000886 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000887
Paul Jakmab881c702010-11-23 16:35:42 +0000888 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000889 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000890 {
891 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000892 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000893 return BGP_ATTR_PARSE_ERROR;
894
895 }
896
Paul Jakmabd471fe2012-03-15 11:30:00 +0000897 /* Adjust the stream getp to the end of the attribute, in case we can
898 * still proceed but the caller hasn't read all the attribute.
899 */
900 stream_set_getp (BGP_INPUT (peer),
901 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
902 + args->total);
903
Paul Jakma835315b2012-01-18 12:28:30 +0000904 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100905 /* where an attribute is relatively inconsequential, e.g. it does not
906 * affect route selection, and can be safely ignored, then any such
907 * attributes which are malformed should just be ignored and the route
908 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000909 */
910 case BGP_ATTR_AS4_AGGREGATOR:
911 case BGP_ATTR_AGGREGATOR:
912 case BGP_ATTR_ATOMIC_AGGREGATE:
913 return BGP_ATTR_PARSE_PROCEED;
914
915 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100916 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000917 */
918 case BGP_ATTR_ORIGIN:
919 case BGP_ATTR_AS_PATH:
920 case BGP_ATTR_NEXT_HOP:
921 case BGP_ATTR_MULTI_EXIT_DISC:
922 case BGP_ATTR_LOCAL_PREF:
923 case BGP_ATTR_COMMUNITIES:
924 case BGP_ATTR_ORIGINATOR_ID:
925 case BGP_ATTR_CLUSTER_LIST:
926 case BGP_ATTR_MP_REACH_NLRI:
927 case BGP_ATTR_MP_UNREACH_NLRI:
928 case BGP_ATTR_EXT_COMMUNITIES:
929 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000930 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000931 return BGP_ATTR_PARSE_ERROR;
932 }
933
934 /* Partial optional attributes that are malformed should not cause
935 * the whole session to be reset. Instead treat it as a withdrawal
936 * of the routes, if possible.
937 */
Paul Jakma835315b2012-01-18 12:28:30 +0000938 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
939 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
940 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000941 return BGP_ATTR_PARSE_WITHDRAW;
942
943 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200944 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000945}
946
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400947/* Find out what is wrong with the path attribute flag bits and log the error.
948 "Flag bits" here stand for Optional, Transitive and Partial, but not for
949 Extended Length. Checking O/T/P bits at once implies, that the attribute
950 being diagnosed is defined by RFC as either a "well-known" or an "optional,
951 non-transitive" attribute. */
952static void
Paul Jakma835315b2012-01-18 12:28:30 +0000953bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
954 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400955)
956{
957 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000958 u_char real_flags = args->flags;
959 const u_int8_t attr_code = args->type;
960
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400961 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
962 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
963 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
964 if
965 (
966 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
967 CHECK_FLAG (real_flags, attr_flag_str[i].key)
968 )
969 {
Paul Jakma835315b2012-01-18 12:28:30 +0000970 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400971 LOOKUP (attr_str, attr_code),
972 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
973 attr_flag_str[i].str);
974 seen = 1;
975 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100976 if (!seen)
977 {
978 zlog (args->peer->log, LOG_DEBUG,
979 "Strange, %s called for attr %s, but no problem found with flags"
980 " (real flags 0x%x, desired 0x%x)",
981 __func__, LOOKUP (attr_str, attr_code),
982 real_flags, desired_flags);
983 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400984}
985
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000986/* Required flags for attributes. EXTLEN will be masked off when testing,
987 * as will PARTIAL for optional+transitive attributes.
988 */
989const u_int8_t attr_flags_values [] = {
990 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
991 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
992 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
993 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
994 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
995 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
996 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
997 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
998 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
999 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1000 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1001 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1002 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1003 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1004 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1005};
1006static const size_t attr_flags_values_max =
1007 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
1008
1009static int
Paul Jakma835315b2012-01-18 12:28:30 +00001010bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001011{
1012 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +00001013 const u_int8_t flags = args->flags;
1014 const u_int8_t attr_code = args->type;
1015 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001016
1017 /* there may be attributes we don't know about */
1018 if (attr_code > attr_flags_values_max)
1019 return 0;
1020 if (attr_flags_values[attr_code] == 0)
1021 return 0;
1022
1023 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1024 * 1."
1025 */
1026 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1027 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1028 {
1029 zlog (peer->log, LOG_ERR,
1030 "%s well-known attributes must have transitive flag set (%x)",
1031 LOOKUP (attr_str, attr_code), flags);
1032 return 1;
1033 }
1034
1035 /* "For well-known attributes and for optional non-transitive attributes,
1036 * the Partial bit MUST be set to 0."
1037 */
1038 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1039 {
1040 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1041 {
1042 zlog (peer->log, LOG_ERR,
1043 "%s well-known attribute "
1044 "must NOT have the partial flag set (%x)",
1045 LOOKUP (attr_str, attr_code), flags);
1046 return 1;
1047 }
1048 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1049 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1050 {
1051 zlog (peer->log, LOG_ERR,
1052 "%s optional + transitive attribute "
1053 "must NOT have the partial flag set (%x)",
1054 LOOKUP (attr_str, attr_code), flags);
1055 return 1;
1056 }
1057 }
1058
1059 /* Optional transitive attributes may go through speakers that don't
1060 * reocgnise them and set the Partial bit.
1061 */
1062 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1063 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1064 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1065
Paul Jakma683f2b82012-03-23 14:58:45 +00001066 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001067 == attr_flags_values[attr_code])
1068 return 0;
1069
Paul Jakma835315b2012-01-18 12:28:30 +00001070 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001071 return 1;
1072}
1073
paul718e3742002-12-13 20:15:29 +00001074/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001075static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001076bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001077{
Paul Jakma835315b2012-01-18 12:28:30 +00001078 struct peer *const peer = args->peer;
1079 struct attr *const attr = args->attr;
1080 const bgp_size_t length = args->length;
1081
paul718e3742002-12-13 20:15:29 +00001082 /* If any recognized attribute has Attribute Length that conflicts
1083 with the expected length (based on the attribute type code), then
1084 the Error Subcode is set to Attribute Length Error. The Data
1085 field contains the erroneous attribute (type, length and
1086 value). */
1087 if (length != 1)
1088 {
1089 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1090 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001091 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001092 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001093 args->total);
paul718e3742002-12-13 20:15:29 +00001094 }
1095
1096 /* Fetch origin attribute. */
1097 attr->origin = stream_getc (BGP_INPUT (peer));
1098
1099 /* If the ORIGIN attribute has an undefined value, then the Error
1100 Subcode is set to Invalid Origin Attribute. The Data field
1101 contains the unrecognized attribute (type, length and value). */
1102 if ((attr->origin != BGP_ORIGIN_IGP)
1103 && (attr->origin != BGP_ORIGIN_EGP)
1104 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1105 {
1106 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1107 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001108 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001109 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001110 args->total);
paul718e3742002-12-13 20:15:29 +00001111 }
1112
1113 /* Set oring attribute flag. */
1114 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1115
1116 return 0;
1117}
Paul Jakmaab005292010-11-27 22:48:34 +00001118
1119/* Parse AS path information. This function is wrapper of
1120 aspath_parse. */
1121static int
Paul Jakma835315b2012-01-18 12:28:30 +00001122bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001123{
Paul Jakma835315b2012-01-18 12:28:30 +00001124 struct attr *const attr = args->attr;
1125 struct peer *const peer = args->peer;
1126 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001127
Paul Jakmaab005292010-11-27 22:48:34 +00001128 /*
1129 * peer with AS4 => will get 4Byte ASnums
1130 * otherwise, will get 16 Bit
1131 */
1132 attr->aspath = aspath_parse (peer->ibuf, length,
1133 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1134
1135 /* In case of IBGP, length will be zero. */
1136 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001137 {
Paul Jakmab881c702010-11-23 16:35:42 +00001138 zlog (peer->log, LOG_ERR,
1139 "Malformed AS path from %s, length is %d",
1140 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001141 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001142 }
Chris Hallcddb8112010-08-09 22:31:37 +04001143
Paul Jakmaab005292010-11-27 22:48:34 +00001144 /* Set aspath attribute flag. */
1145 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001146
Paul Jakmab881c702010-11-23 16:35:42 +00001147 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001148}
1149
Paul Jakmab881c702010-11-23 16:35:42 +00001150static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001151bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001152{
1153 /* These checks were part of bgp_attr_aspath, but with
1154 * as4 we should to check aspath things when
1155 * aspath synthesizing with as4_path has already taken place.
1156 * Otherwise we check ASPATH and use the synthesized thing, and that is
1157 * not right.
1158 * So do the checks later, i.e. here
1159 */
1160 struct bgp *bgp = peer->bgp;
1161 struct aspath *aspath;
1162
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001163 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001164 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1165 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001166 {
1167 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001168 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1169 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1170 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001171 }
1172
paul718e3742002-12-13 20:15:29 +00001173 /* First AS check for EBGP. */
1174 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1175 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001176 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001177 && ! aspath_firstas_check (attr->aspath, peer->as))
1178 {
1179 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001180 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001181 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1182 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1183 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001184 }
1185 }
1186
1187 /* local-as prepend */
1188 if (peer->change_local_as &&
1189 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1190 {
1191 aspath = aspath_dup (attr->aspath);
1192 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001193 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001194 attr->aspath = aspath_intern (aspath);
1195 }
1196
Paul Jakmab881c702010-11-23 16:35:42 +00001197 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001198}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001199
Paul Jakmaab005292010-11-27 22:48:34 +00001200/* Parse AS4 path information. This function is another wrapper of
1201 aspath_parse. */
1202static int
Paul Jakma835315b2012-01-18 12:28:30 +00001203bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001204{
Paul Jakma835315b2012-01-18 12:28:30 +00001205 struct peer *const peer = args->peer;
1206 struct attr *const attr = args->attr;
1207 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001208
Paul Jakmaab005292010-11-27 22:48:34 +00001209 *as4_path = aspath_parse (peer->ibuf, length, 1);
1210
Paul Jakmab881c702010-11-23 16:35:42 +00001211 /* In case of IBGP, length will be zero. */
1212 if (!*as4_path)
1213 {
1214 zlog (peer->log, LOG_ERR,
1215 "Malformed AS4 path from %s, length is %d",
1216 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001217 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001218 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001219 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001220 }
1221
Paul Jakmaab005292010-11-27 22:48:34 +00001222 /* Set aspath attribute flag. */
1223 if (as4_path)
1224 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1225
Paul Jakmab881c702010-11-23 16:35:42 +00001226 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001227}
1228
paul718e3742002-12-13 20:15:29 +00001229/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001230static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001231bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001232{
Paul Jakma835315b2012-01-18 12:28:30 +00001233 struct peer *const peer = args->peer;
1234 struct attr *const attr = args->attr;
1235 const bgp_size_t length = args->length;
1236
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001237 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001238
paul718e3742002-12-13 20:15:29 +00001239 /* Check nexthop attribute length. */
1240 if (length != 4)
1241 {
1242 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1243 length);
1244
Paul Jakma835315b2012-01-18 12:28:30 +00001245 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001246 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001247 args->total);
paul718e3742002-12-13 20:15:29 +00001248 }
1249
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001250 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1251 attribute must result in a NOTIFICATION message (this is implemented below).
1252 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1253 logged locally (this is implemented somewhere else). The UPDATE message
1254 gets ignored in any of these cases. */
1255 nexthop_n = stream_get_ipv4 (peer->ibuf);
1256 nexthop_h = ntohl (nexthop_n);
Lou Bergerf53585d2016-05-17 07:10:36 -04001257 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1258 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001259 {
1260 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001261 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001262 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001263 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001264 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001265 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001266 }
1267
1268 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001269 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1270
Paul Jakmab881c702010-11-23 16:35:42 +00001271 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001272}
1273
1274/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001275static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001276bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001277{
Paul Jakma835315b2012-01-18 12:28:30 +00001278 struct peer *const peer = args->peer;
1279 struct attr *const attr = args->attr;
1280 const bgp_size_t length = args->length;
1281
paul718e3742002-12-13 20:15:29 +00001282 /* Length check. */
1283 if (length != 4)
1284 {
1285 zlog (peer->log, LOG_ERR,
1286 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001287
Paul Jakma835315b2012-01-18 12:28:30 +00001288 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001289 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001290 args->total);
paul718e3742002-12-13 20:15:29 +00001291 }
1292
1293 attr->med = stream_getl (peer->ibuf);
1294
1295 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1296
Paul Jakmab881c702010-11-23 16:35:42 +00001297 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001298}
1299
1300/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001301static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001302bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001303{
Paul Jakma835315b2012-01-18 12:28:30 +00001304 struct peer *const peer = args->peer;
1305 struct attr *const attr = args->attr;
1306 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001307
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001308 /* Length check. */
1309 if (length != 4)
1310 {
Paul Jakma835315b2012-01-18 12:28:30 +00001311 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1312 length);
1313 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001314 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001315 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001316 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001317
paul718e3742002-12-13 20:15:29 +00001318 /* If it is contained in an UPDATE message that is received from an
1319 external peer, then this attribute MUST be ignored by the
1320 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001321 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001322 {
paul9985f832005-02-09 15:51:56 +00001323 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001324 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001325 }
1326
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001327 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001328
1329 /* Set atomic aggregate flag. */
1330 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1331
Paul Jakmab881c702010-11-23 16:35:42 +00001332 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001333}
1334
1335/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001336static int
Paul Jakma835315b2012-01-18 12:28:30 +00001337bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001338{
Paul Jakma835315b2012-01-18 12:28:30 +00001339 struct peer *const peer = args->peer;
1340 struct attr *const attr = args->attr;
1341 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001342
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001343 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001344 if (length != 0)
1345 {
Paul Jakma835315b2012-01-18 12:28:30 +00001346 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1347 length);
1348 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001349 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001350 args->total);
paul718e3742002-12-13 20:15:29 +00001351 }
1352
1353 /* Set atomic aggregate flag. */
1354 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1355
Paul Jakmab881c702010-11-23 16:35:42 +00001356 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001357}
1358
1359/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001360static int
Paul Jakma835315b2012-01-18 12:28:30 +00001361bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001362{
Paul Jakma835315b2012-01-18 12:28:30 +00001363 struct peer *const peer = args->peer;
1364 struct attr *const attr = args->attr;
1365 const bgp_size_t length = args->length;
1366
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001367 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001368 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001369
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001370 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001371 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001372 wantedlen = 8;
1373
1374 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001375 {
Paul Jakma835315b2012-01-18 12:28:30 +00001376 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1377 wantedlen, length);
1378 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001379 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001380 args->total);
paul718e3742002-12-13 20:15:29 +00001381 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001382
1383 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1384 attre->aggregator_as = stream_getl (peer->ibuf);
1385 else
1386 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001387 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001388
1389 /* Set atomic aggregate flag. */
1390 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1391
Paul Jakmab881c702010-11-23 16:35:42 +00001392 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001393}
1394
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001395/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001396static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001397bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1398 as_t *as4_aggregator_as,
1399 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001400{
Paul Jakma835315b2012-01-18 12:28:30 +00001401 struct peer *const peer = args->peer;
1402 struct attr *const attr = args->attr;
1403 const bgp_size_t length = args->length;
1404
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001405 if (length != 8)
1406 {
Paul Jakma835315b2012-01-18 12:28:30 +00001407 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1408 length);
1409 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001410 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001411 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001412 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001413
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001414 *as4_aggregator_as = stream_getl (peer->ibuf);
1415 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1416
1417 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1418
Paul Jakmab881c702010-11-23 16:35:42 +00001419 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001420}
1421
1422/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1423 */
Paul Jakmab881c702010-11-23 16:35:42 +00001424static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001425bgp_attr_munge_as4_attrs (struct peer *const peer,
1426 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001427 struct aspath *as4_path, as_t as4_aggregator,
1428 struct in_addr *as4_aggregator_addr)
1429{
1430 int ignore_as4_path = 0;
1431 struct aspath *newpath;
1432 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001433
1434 if (!attr->aspath)
1435 {
1436 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1437 * checked that all well-known, mandatory attributes were present.
1438 *
1439 * Can only be a problem with peer itself - hard error
1440 */
1441 return BGP_ATTR_PARSE_ERROR;
1442 }
1443
Paul Jakmab881c702010-11-23 16:35:42 +00001444 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001445 {
1446 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1447 * if given.
1448 * It is worth a warning though, because the peer really
1449 * should not send them
1450 */
1451 if (BGP_DEBUG(as4, AS4))
1452 {
1453 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1454 zlog_debug ("[AS4] %s %s AS4_PATH",
1455 peer->host, "AS4 capable peer, yet it sent");
1456
1457 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1458 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1459 peer->host, "AS4 capable peer, yet it sent");
1460 }
1461
Paul Jakmab881c702010-11-23 16:35:42 +00001462 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001463 }
1464
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001465 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1466 * because that may override AS4_PATH
1467 */
1468 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1469 {
Paul Jakmab881c702010-11-23 16:35:42 +00001470 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001471 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001472 assert (attre);
1473
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001474 /* received both.
1475 * if the as_number in aggregator is not AS_TRANS,
1476 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1477 * and the Aggregator shall be taken as
1478 * info on the aggregating node, and the AS_PATH
1479 * shall be taken as the AS_PATH
1480 * otherwise
1481 * the Aggregator shall be ignored and the
1482 * AS4_AGGREGATOR shall be taken as the
1483 * Aggregating node and the AS_PATH is to be
1484 * constructed "as in all other cases"
1485 */
Paul Jakmab881c702010-11-23 16:35:42 +00001486 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001487 {
1488 /* ignore */
1489 if ( BGP_DEBUG(as4, AS4))
1490 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1491 " send AGGREGATOR != AS_TRANS and"
1492 " AS4_AGGREGATOR, so ignore"
1493 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1494 ignore_as4_path = 1;
1495 }
1496 else
1497 {
1498 /* "New_aggregator shall be taken as aggregator" */
1499 attre->aggregator_as = as4_aggregator;
1500 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1501 }
1502 }
1503 else
1504 {
1505 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1506 * That is bogus - but reading the conditions
1507 * we have to handle AS4_AGGREGATOR as if it were
1508 * AGGREGATOR in that case
1509 */
1510 if ( BGP_DEBUG(as4, AS4))
1511 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1512 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1513 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001514 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001515 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1516 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1517 }
1518 }
1519
1520 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001521 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001522 {
Paul Jakma055086f2014-09-23 15:23:01 +01001523 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1524 aspath_unintern (&attr->aspath);
1525 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001526 }
Paul Jakmab881c702010-11-23 16:35:42 +00001527 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001528}
1529
paul718e3742002-12-13 20:15:29 +00001530/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001531static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001532bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001533{
Paul Jakma835315b2012-01-18 12:28:30 +00001534 struct peer *const peer = args->peer;
1535 struct attr *const attr = args->attr;
1536 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001537
paul718e3742002-12-13 20:15:29 +00001538 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001539 {
1540 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001541 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001542 }
Paul Jakma0c466382010-12-05 17:17:26 +00001543
1544 attr->community =
1545 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1546
1547 /* XXX: fix community_parse to use stream API and remove this */
1548 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001549
Paul Jakma0c466382010-12-05 17:17:26 +00001550 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001551 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001552 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001553 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001554
paul718e3742002-12-13 20:15:29 +00001555 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1556
Paul Jakmab881c702010-11-23 16:35:42 +00001557 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001558}
1559
1560/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001561static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001562bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001563{
Paul Jakma835315b2012-01-18 12:28:30 +00001564 struct peer *const peer = args->peer;
1565 struct attr *const attr = args->attr;
1566 const bgp_size_t length = args->length;
1567
Denis Ovsienkod595b562011-09-30 15:08:54 +04001568 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001569 if (length != 4)
1570 {
1571 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1572
Paul Jakma835315b2012-01-18 12:28:30 +00001573 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001574 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001575 args->total);
paul718e3742002-12-13 20:15:29 +00001576 }
1577
Paul Jakmafb982c22007-05-04 20:15:47 +00001578 (bgp_attr_extra_get (attr))->originator_id.s_addr
1579 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001580
1581 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1582
Paul Jakmab881c702010-11-23 16:35:42 +00001583 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001584}
1585
1586/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001587static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001588bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001589{
Paul Jakma835315b2012-01-18 12:28:30 +00001590 struct peer *const peer = args->peer;
1591 struct attr *const attr = args->attr;
1592 const bgp_size_t length = args->length;
1593
paul718e3742002-12-13 20:15:29 +00001594 /* Check length. */
1595 if (length % 4)
1596 {
1597 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1598
Paul Jakma835315b2012-01-18 12:28:30 +00001599 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1600 args->total);
paul718e3742002-12-13 20:15:29 +00001601 }
1602
Paul Jakmafb982c22007-05-04 20:15:47 +00001603 (bgp_attr_extra_get (attr))->cluster
1604 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001605
1606 /* XXX: Fix cluster_parse to use stream API and then remove this */
1607 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001608
1609 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1610
Paul Jakmab881c702010-11-23 16:35:42 +00001611 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001612}
1613
1614/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001615int
Paul Jakma835315b2012-01-18 12:28:30 +00001616bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1617 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001618{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001619 afi_t afi;
1620 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001621 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001622 size_t start;
paul718e3742002-12-13 20:15:29 +00001623 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001624 struct peer *const peer = args->peer;
1625 struct attr *const attr = args->attr;
1626 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001627 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001628
paul718e3742002-12-13 20:15:29 +00001629 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001630 s = BGP_INPUT(peer);
1631 start = stream_get_getp(s);
1632
1633 /* safe to read statically sized header? */
1634#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001635#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001636 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001637 {
1638 zlog_info ("%s: %s sent invalid length, %lu",
1639 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001640 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001641 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001642
paul718e3742002-12-13 20:15:29 +00001643 /* Load AFI, SAFI. */
1644 afi = stream_getw (s);
1645 safi = stream_getc (s);
1646
1647 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001648 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001649
Paul Jakma03292802008-06-07 20:37:10 +00001650 if (LEN_LEFT < attre->mp_nexthop_len)
1651 {
1652 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1653 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001654 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001655 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001656
paul718e3742002-12-13 20:15:29 +00001657 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001658 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001659 {
1660 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001661 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001662 /* Probably needed for RFC 2283 */
1663 if (attr->nexthop.s_addr == 0)
1664 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001665 break;
1666 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001667 stream_getl (s); /* RD high */
1668 stream_getl (s); /* RD low */
1669 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001670 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001671 case 24:
1672 {
1673 u_int32_t rd_high __attribute__((unused));
1674 u_int32_t rd_low __attribute__((unused));
1675
1676 rd_high = stream_getl (s);
1677 rd_low = stream_getl (s);
1678 }
1679 /* fall through */
paul718e3742002-12-13 20:15:29 +00001680 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001681 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001682 break;
1683 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001684 case 48:
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_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001693
1694 if (attre->mp_nexthop_len == 48) {
1695 u_int32_t rd_high __attribute__((unused));
1696 u_int32_t rd_low __attribute__((unused));
1697
1698 rd_high = stream_getl (s);
1699 rd_low = stream_getl (s);
1700 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001701 stream_get (&attre->mp_nexthop_local, s, 16);
1702 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001703 {
1704 char buf1[INET6_ADDRSTRLEN];
1705 char buf2[INET6_ADDRSTRLEN];
1706
1707 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001708 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 +00001709 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001710 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001711 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001712 buf2, INET6_ADDRSTRLEN));
1713
Paul Jakmafb982c22007-05-04 20:15:47 +00001714 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001715 }
1716 break;
paul718e3742002-12-13 20:15:29 +00001717 default:
Paul Jakma03292802008-06-07 20:37:10 +00001718 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1719 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001720 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001721 }
1722
Paul Jakma03292802008-06-07 20:37:10 +00001723 if (!LEN_LEFT)
1724 {
1725 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1726 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001727 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001728 }
paul718e3742002-12-13 20:15:29 +00001729
Paul Jakma6e4ab122007-04-10 19:36:48 +00001730 {
1731 u_char val;
1732 if ((val = stream_getc (s)))
1733 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1734 peer->host, val);
1735 }
1736
1737 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001738 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001739 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001740 {
1741 zlog_info ("%s: (%s) Failed to read NLRI",
1742 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001743 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001744 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001745
paul718e3742002-12-13 20:15:29 +00001746 mp_update->afi = afi;
1747 mp_update->safi = safi;
1748 mp_update->nlri = stream_pnt (s);
1749 mp_update->length = nlri_len;
1750
paul9985f832005-02-09 15:51:56 +00001751 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001752
David Lamparterdaefeb82014-12-08 17:42:12 +01001753 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1754
Paul Jakmab881c702010-11-23 16:35:42 +00001755 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001756#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001757}
1758
1759/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001760int
Paul Jakma835315b2012-01-18 12:28:30 +00001761bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001762 struct bgp_nlri *mp_withdraw)
1763{
1764 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001765 afi_t afi;
1766 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001767 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001768 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001769 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001770 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001771
1772 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001773
1774#define BGP_MP_UNREACH_MIN_SIZE 3
1775 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001776 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001777
paul718e3742002-12-13 20:15:29 +00001778 afi = stream_getw (s);
1779 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001780
1781 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001782
paul718e3742002-12-13 20:15:29 +00001783 mp_withdraw->afi = afi;
1784 mp_withdraw->safi = safi;
1785 mp_withdraw->nlri = stream_pnt (s);
1786 mp_withdraw->length = withdraw_len;
1787
paul9985f832005-02-09 15:51:56 +00001788 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001789
David Lamparterdaefeb82014-12-08 17:42:12 +01001790 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1791
Paul Jakmab881c702010-11-23 16:35:42 +00001792 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001793}
1794
1795/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001796static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001797bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001798{
Paul Jakma835315b2012-01-18 12:28:30 +00001799 struct peer *const peer = args->peer;
1800 struct attr *const attr = args->attr;
1801 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001802
paul718e3742002-12-13 20:15:29 +00001803 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001804 {
1805 if (attr->extra)
1806 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001807 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001808 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001809 }
Paul Jakma0c466382010-12-05 17:17:26 +00001810
1811 (bgp_attr_extra_get (attr))->ecommunity =
1812 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1813 /* XXX: fix ecommunity_parse to use stream API */
1814 stream_forward_getp (peer->ibuf, length);
1815
1816 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001817 return bgp_attr_malformed (args,
1818 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1819 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001820
paul718e3742002-12-13 20:15:29 +00001821 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1822
Paul Jakmab881c702010-11-23 16:35:42 +00001823 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001824}
1825
Lou Bergerc3741782016-01-12 13:42:01 -05001826/* Parse Tunnel Encap attribute in an UPDATE */
1827static int
1828bgp_attr_encap(
1829 uint8_t type,
1830 struct peer *peer, /* IN */
1831 bgp_size_t length, /* IN: attr's length field */
1832 struct attr *attr, /* IN: caller already allocated */
1833 u_char flag, /* IN: attr's flags field */
1834 u_char *startp)
1835{
1836 bgp_size_t total;
1837 struct attr_extra *attre = NULL;
1838 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1839 uint16_t tunneltype;
1840
1841 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1842
1843 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1844 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1845 {
1846 zlog (peer->log, LOG_ERR,
1847 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1848 bgp_notify_send_with_data (peer,
1849 BGP_NOTIFY_UPDATE_ERR,
1850 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1851 startp, total);
1852 return -1;
1853 }
1854
1855 if (BGP_ATTR_ENCAP == type) {
1856 /* read outer TLV type and length */
1857 uint16_t tlv_length;
1858
1859 if (length < 4) {
1860 zlog (peer->log, LOG_ERR,
1861 "Tunnel Encap attribute not long enough to contain outer T,L");
1862 bgp_notify_send_with_data(peer,
1863 BGP_NOTIFY_UPDATE_ERR,
1864 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1865 startp, total);
1866 return -1;
1867 }
1868 tunneltype = stream_getw (BGP_INPUT (peer));
1869 tlv_length = stream_getw (BGP_INPUT (peer));
1870 length -= 4;
1871
1872 if (tlv_length != length) {
1873 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1874 __func__, tlv_length, length);
1875 }
1876 }
1877
1878 while (length >= 4) {
Donald Sharp985c3552016-03-10 20:16:47 -05001879 uint16_t subtype = 0;
1880 uint16_t sublength = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05001881 struct bgp_attr_encap_subtlv *tlv;
1882
Lou Berger298cc2f2016-01-12 13:42:02 -05001883 if (BGP_ATTR_ENCAP == type) {
1884 subtype = stream_getc (BGP_INPUT (peer));
1885 sublength = stream_getc (BGP_INPUT (peer));
1886 length -= 2;
1887 }
Lou Bergerc3741782016-01-12 13:42:01 -05001888
1889 if (sublength > length) {
1890 zlog (peer->log, LOG_ERR,
1891 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1892 sublength, length);
1893 bgp_notify_send_with_data (peer,
1894 BGP_NOTIFY_UPDATE_ERR,
1895 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1896 startp, total);
1897 return -1;
1898 }
1899
1900 /* alloc and copy sub-tlv */
1901 /* TBD make sure these are freed when attributes are released */
1902 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1903 tlv->type = subtype;
1904 tlv->length = sublength;
1905 stream_get(tlv->value, peer->ibuf, sublength);
1906 length -= sublength;
1907
1908 /* attach tlv to encap chain */
1909 if (!attre) {
1910 attre = bgp_attr_extra_get(attr);
1911 if (BGP_ATTR_ENCAP == type) {
1912 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1913 stlv_last = stlv_last->next);
1914 if (stlv_last) {
1915 stlv_last->next = tlv;
1916 } else {
1917 attre->encap_subtlvs = tlv;
1918 }
1919 }
1920 } else {
1921 stlv_last->next = tlv;
1922 }
1923 stlv_last = tlv;
1924 }
1925
1926 if (attre && (BGP_ATTR_ENCAP == type)) {
1927 attre->encap_tunneltype = tunneltype;
1928 }
1929
1930 if (length) {
1931 /* spurious leftover data */
1932 zlog (peer->log, LOG_ERR,
1933 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1934 bgp_notify_send_with_data (peer,
1935 BGP_NOTIFY_UPDATE_ERR,
1936 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1937 startp, total);
1938 return -1;
1939 }
1940
1941 return 0;
1942}
1943
paul718e3742002-12-13 20:15:29 +00001944/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001945static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001946bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001947{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001948 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001949 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001950 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001951 struct peer *const peer = args->peer;
1952 struct attr *const attr = args->attr;
1953 u_char *const startp = args->startp;
1954 const u_char type = args->type;
1955 const u_char flag = args->flags;
1956 const bgp_size_t length = args->length;
1957
paul718e3742002-12-13 20:15:29 +00001958
hassof4184462005-02-01 20:13:16 +00001959 if (BGP_DEBUG (normal, NORMAL))
1960 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1961 peer->host, type, length);
1962
paul718e3742002-12-13 20:15:29 +00001963 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001964 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001965 "Unknown attribute type %d length %d is received", type, length);
1966
1967 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001968 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001969
paul718e3742002-12-13 20:15:29 +00001970 /* If any of the mandatory well-known attributes are not recognized,
1971 then the Error Subcode is set to Unrecognized Well-known
1972 Attribute. The Data field contains the unrecognized attribute
1973 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001974 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001975 {
Paul Jakma835315b2012-01-18 12:28:30 +00001976 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001977 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001978 args->total);
paul718e3742002-12-13 20:15:29 +00001979 }
1980
1981 /* Unrecognized non-transitive optional attributes must be quietly
1982 ignored and not passed along to other BGP peers. */
1983 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001984 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001985
1986 /* If a path with recognized transitive optional attribute is
1987 accepted and passed along to other BGP peers and the Partial bit
1988 in the Attribute Flags octet is set to 1 by some previous AS, it
1989 is not set back to 0 by the current AS. */
1990 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1991
1992 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001993 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001994 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001995
Paul Jakmafb982c22007-05-04 20:15:47 +00001996 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001997
1998 if (transit->val)
1999 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
2000 transit->length + total);
2001 else
2002 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
2003
2004 memcpy (transit->val + transit->length, startp, total);
2005 transit->length += total;
2006
Paul Jakmab881c702010-11-23 16:35:42 +00002007 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002008}
2009
Paul Jakma055086f2014-09-23 15:23:01 +01002010/* Well-known attribute check. */
2011static int
2012bgp_attr_check (struct peer *peer, struct attr *attr)
2013{
2014 u_char type = 0;
2015
Paul Jakmaaed1b552014-10-21 16:59:01 +01002016 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2017 * empty UPDATE. */
2018 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2019 return BGP_ATTR_PARSE_PROCEED;
2020
2021 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2022 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2023 are present, it should. Check for any other attribute being present
2024 instead.
2025 */
2026 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2027 return BGP_ATTR_PARSE_PROCEED;
2028
Paul Jakma055086f2014-09-23 15:23:01 +01002029 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2030 type = BGP_ATTR_ORIGIN;
2031
2032 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2033 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002034
2035 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2036 * NLRI is empty. We can't easily check NLRI empty here though.
2037 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002038 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2039 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002040 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002041
Paul Jakma055086f2014-09-23 15:23:01 +01002042 if (peer->sort == BGP_PEER_IBGP
2043 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2044 type = BGP_ATTR_LOCAL_PREF;
2045
2046 if (type)
2047 {
2048 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002049 "%s Missing well-known attribute %d / %s",
2050 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002051 bgp_notify_send_with_data (peer,
2052 BGP_NOTIFY_UPDATE_ERR,
2053 BGP_NOTIFY_UPDATE_MISS_ATTR,
2054 &type, 1);
2055 return BGP_ATTR_PARSE_ERROR;
2056 }
2057 return BGP_ATTR_PARSE_PROCEED;
2058}
2059
paul718e3742002-12-13 20:15:29 +00002060/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002061 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002062bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002063bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2064 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2065{
2066 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002067 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002068 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002069 bgp_size_t length;
2070 u_char *startp, *endp;
2071 u_char *attr_endp;
2072 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002073 /* we need the as4_path only until we have synthesized the as_path with it */
2074 /* same goes for as4_aggregator */
2075 struct aspath *as4_path = NULL;
2076 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002077 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002078
2079 /* Initialize bitmap. */
2080 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2081
2082 /* End pointer of BGP attribute. */
2083 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002084
paul718e3742002-12-13 20:15:29 +00002085 /* Get attributes to the end of attribute length. */
2086 while (BGP_INPUT_PNT (peer) < endp)
2087 {
2088 /* Check remaining length check.*/
2089 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2090 {
gdtc29fdba2004-12-09 14:46:46 +00002091 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002092 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002093 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002094 peer->host,
2095 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002096
2097 bgp_notify_send (peer,
2098 BGP_NOTIFY_UPDATE_ERR,
2099 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002100 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002101 }
2102
2103 /* Fetch attribute flag and type. */
2104 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002105 /* "The lower-order four bits of the Attribute Flags octet are
2106 unused. They MUST be zero when sent and MUST be ignored when
2107 received." */
2108 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002109 type = stream_getc (BGP_INPUT (peer));
2110
Paul Jakma370b64a2007-12-22 16:49:52 +00002111 /* Check whether Extended-Length applies and is in bounds */
2112 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2113 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2114 {
2115 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002116 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002117 peer->host,
2118 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2119
2120 bgp_notify_send (peer,
2121 BGP_NOTIFY_UPDATE_ERR,
2122 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002123 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002124 }
Paul Jakma835315b2012-01-18 12:28:30 +00002125
paul718e3742002-12-13 20:15:29 +00002126 /* Check extended attribue length bit. */
2127 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2128 length = stream_getw (BGP_INPUT (peer));
2129 else
2130 length = stream_getc (BGP_INPUT (peer));
2131
2132 /* If any attribute appears more than once in the UPDATE
2133 message, then the Error Subcode is set to Malformed Attribute
2134 List. */
2135
2136 if (CHECK_BITMAP (seen, type))
2137 {
2138 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002139 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002140 peer->host, type);
2141
2142 bgp_notify_send (peer,
2143 BGP_NOTIFY_UPDATE_ERR,
2144 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002145 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002146 }
2147
2148 /* Set type to bitmap to check duplicate attribute. `type' is
2149 unsigned char so it never overflow bitmap range. */
2150
2151 SET_BITMAP (seen, type);
2152
2153 /* Overflow check. */
2154 attr_endp = BGP_INPUT_PNT (peer) + length;
2155
2156 if (attr_endp > endp)
2157 {
2158 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002159 "%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 +00002160 bgp_notify_send (peer,
2161 BGP_NOTIFY_UPDATE_ERR,
2162 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002163 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002164 }
Paul Jakma835315b2012-01-18 12:28:30 +00002165
2166 struct bgp_attr_parser_args attr_args = {
2167 .peer = peer,
2168 .length = length,
2169 .attr = attr,
2170 .type = type,
2171 .flags = flag,
2172 .startp = startp,
2173 .total = attr_endp - startp,
2174 };
2175
2176
2177 /* If any recognized attribute has Attribute Flags that conflict
2178 with the Attribute Type Code, then the Error Subcode is set to
2179 Attribute Flags Error. The Data field contains the erroneous
2180 attribute (type, length and value). */
2181 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002182 {
2183 bgp_attr_parse_ret_t ret;
2184 ret = bgp_attr_malformed (&attr_args,
2185 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2186 attr_args.total);
2187 if (ret == BGP_ATTR_PARSE_PROCEED)
2188 continue;
2189 return ret;
2190 }
paul718e3742002-12-13 20:15:29 +00002191
2192 /* OK check attribute and store it's value. */
2193 switch (type)
2194 {
2195 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002196 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002197 break;
2198 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002199 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002200 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002201 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002202 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002203 break;
paul718e3742002-12-13 20:15:29 +00002204 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002205 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002206 break;
2207 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002208 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002209 break;
2210 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002211 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002212 break;
2213 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002214 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002215 break;
2216 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002217 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002218 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002219 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002220 ret = bgp_attr_as4_aggregator (&attr_args,
2221 &as4_aggregator,
2222 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002223 break;
paul718e3742002-12-13 20:15:29 +00002224 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002225 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002226 break;
2227 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002228 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002229 break;
2230 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002231 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002232 break;
2233 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002234 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002235 break;
2236 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002237 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002238 break;
2239 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002240 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002241 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002242 case BGP_ATTR_ENCAP:
2243 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2244 break;
paul718e3742002-12-13 20:15:29 +00002245 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002246 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002247 break;
2248 }
Paul Jakmab881c702010-11-23 16:35:42 +00002249
David Lamparterf57000c2014-06-04 01:01:10 +02002250 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2251 {
2252 bgp_notify_send (peer,
2253 BGP_NOTIFY_UPDATE_ERR,
2254 BGP_NOTIFY_UPDATE_MAL_ATTR);
2255 ret = BGP_ATTR_PARSE_ERROR;
2256 }
2257
Paul Jakmab881c702010-11-23 16:35:42 +00002258 /* If hard error occured immediately return to the caller. */
2259 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002260 {
2261 zlog (peer->log, LOG_WARNING,
2262 "%s: Attribute %s, parse error",
2263 peer->host,
2264 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002265 if (as4_path)
2266 aspath_unintern (&as4_path);
2267 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002268 }
Paul Jakmab881c702010-11-23 16:35:42 +00002269 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2270 {
2271
2272 zlog (peer->log, LOG_WARNING,
2273 "%s: Attribute %s, parse error - treating as withdrawal",
2274 peer->host,
2275 LOOKUP (attr_str, type));
2276 if (as4_path)
2277 aspath_unintern (&as4_path);
2278 return ret;
2279 }
2280
paul718e3742002-12-13 20:15:29 +00002281 /* Check the fetched length. */
2282 if (BGP_INPUT_PNT (peer) != attr_endp)
2283 {
2284 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002285 "%s: BGP attribute %s, fetch error",
2286 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002287 bgp_notify_send (peer,
2288 BGP_NOTIFY_UPDATE_ERR,
2289 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002290 if (as4_path)
2291 aspath_unintern (&as4_path);
2292 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002293 }
2294 }
paul718e3742002-12-13 20:15:29 +00002295 /* Check final read pointer is same as end pointer. */
2296 if (BGP_INPUT_PNT (peer) != endp)
2297 {
2298 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002299 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002300 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002301 bgp_notify_send (peer,
2302 BGP_NOTIFY_UPDATE_ERR,
2303 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002304 if (as4_path)
2305 aspath_unintern (&as4_path);
2306 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002307 }
Paul Jakma055086f2014-09-23 15:23:01 +01002308
2309 /* Check all mandatory well-known attributes are present */
2310 {
2311 bgp_attr_parse_ret_t ret;
2312 if ((ret = bgp_attr_check (peer, attr)) < 0)
2313 {
2314 if (as4_path)
2315 aspath_unintern (&as4_path);
2316 return ret;
2317 }
2318 }
2319
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002320 /*
2321 * At this place we can see whether we got AS4_PATH and/or
2322 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2323 * We can not do this before we've read all attributes because
2324 * the as4 handling does not say whether AS4_PATH has to be sent
2325 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2326 * in relationship to AGGREGATOR.
2327 * So, to be defensive, we are not relying on any order and read
2328 * all attributes first, including these 32bit ones, and now,
2329 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002330 *
2331 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2332 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002333 */
David Lamparterf57000c2014-06-04 01:01:10 +02002334 /* actually... this doesn't ever return failure currently, but
2335 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002336 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2337 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002338 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002339 {
David Lamparterf57000c2014-06-04 01:01:10 +02002340 bgp_notify_send (peer,
2341 BGP_NOTIFY_UPDATE_ERR,
2342 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002343 if (as4_path)
2344 aspath_unintern (&as4_path);
2345 return BGP_ATTR_PARSE_ERROR;
2346 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002347
2348 /* At this stage, we have done all fiddling with as4, and the
2349 * resulting info is in attr->aggregator resp. attr->aspath
2350 * so we can chuck as4_aggregator and as4_path alltogether in
2351 * order to save memory
2352 */
Paul Jakmab881c702010-11-23 16:35:42 +00002353 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002354 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002355 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002356 /* The flag that we got this is still there, but that does not
2357 * do any trouble
2358 */
2359 }
2360 /*
2361 * The "rest" of the code does nothing with as4_aggregator.
2362 * there is no memory attached specifically which is not part
2363 * of the attr.
2364 * so ignoring just means do nothing.
2365 */
2366 /*
2367 * Finally do the checks on the aspath we did not do yet
2368 * because we waited for a potentially synthesized aspath.
2369 */
Paul Jakmab881c702010-11-23 16:35:42 +00002370 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002371 {
Paul Jakma835315b2012-01-18 12:28:30 +00002372 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002373 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002374 return ret;
2375 }
2376
paul718e3742002-12-13 20:15:29 +00002377 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002378 if (attr->extra && attr->extra->transit)
2379 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002380
Paul Jakmab881c702010-11-23 16:35:42 +00002381 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002382}
2383
paul718e3742002-12-13 20:15:29 +00002384int stream_put_prefix (struct stream *, struct prefix *);
2385
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002386size_t
2387bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2388 struct attr *attr)
2389{
2390 size_t sizep;
2391
2392 /* Set extended bit always to encode the attribute length as 2 bytes */
2393 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2394 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2395 sizep = stream_get_endp (s);
2396 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002397
2398 stream_putw (s, afi);
2399 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002400
2401 /* Nexthop */
2402 switch (afi)
2403 {
2404 case AFI_IP:
2405 switch (safi)
2406 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002407 case SAFI_MULTICAST:
2408 stream_putc (s, 4);
2409 stream_put_ipv4 (s, attr->nexthop.s_addr);
2410 break;
2411 case SAFI_MPLS_VPN:
2412 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002413 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002414 stream_putl (s, 0);
2415 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2416 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002417 case SAFI_ENCAP:
2418 stream_putc (s, 4);
2419 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2420 break;
Lou Berger050defe2016-01-12 13:41:59 -05002421 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002422 default:
2423 break;
2424 }
2425 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002426 case AFI_IP6:
2427 switch (safi)
2428 {
2429 case SAFI_UNICAST:
2430 case SAFI_MULTICAST:
2431 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002432 struct attr_extra *attre = attr->extra;
2433
2434 assert (attr->extra);
2435 stream_putc (s, attre->mp_nexthop_len);
2436 stream_put (s, &attre->mp_nexthop_global, 16);
2437 if (attre->mp_nexthop_len == 32)
2438 stream_put (s, &attre->mp_nexthop_local, 16);
2439 }
Lou Berger050defe2016-01-12 13:41:59 -05002440 break;
2441 case SAFI_MPLS_VPN:
2442 {
2443 struct attr_extra *attre = attr->extra;
2444
2445 assert (attr->extra);
2446 if (attre->mp_nexthop_len == 16) {
2447 stream_putc (s, 24);
2448 stream_putl (s, 0); /* RD = 0, per RFC */
2449 stream_putl (s, 0);
2450 stream_put (s, &attre->mp_nexthop_global, 16);
2451 } else if (attre->mp_nexthop_len == 32) {
2452 stream_putc (s, 48);
2453 stream_putl (s, 0); /* RD = 0, per RFC */
2454 stream_putl (s, 0);
2455 stream_put (s, &attre->mp_nexthop_global, 16);
2456 stream_putl (s, 0); /* RD = 0, per RFC */
2457 stream_putl (s, 0);
2458 stream_put (s, &attre->mp_nexthop_local, 16);
2459 }
2460 }
2461 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002462 case SAFI_ENCAP:
2463 assert (attr->extra);
2464 stream_putc (s, 16);
2465 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2466 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002467 default:
2468 break;
2469 }
2470 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002471 default:
2472 break;
2473 }
2474
2475 /* SNPA */
2476 stream_putc (s, 0);
2477 return sizep;
2478}
2479
2480void
2481bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2482 struct prefix *p, struct prefix_rd *prd,
2483 u_char *tag)
2484{
Lou Berger050defe2016-01-12 13:41:59 -05002485 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002486 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002487 /* Tag, RD, Prefix write. */
2488 stream_putc (s, p->prefixlen + 88);
2489 stream_put (s, tag, 3);
2490 stream_put (s, prd->val, 8);
2491 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002492 }
Lou Berger050defe2016-01-12 13:41:59 -05002493 else
2494 stream_put_prefix (s, p);
2495}
2496
2497size_t
2498bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2499{
2500 int size = PSIZE (p->prefixlen);
2501 if (safi == SAFI_MPLS_VPN)
2502 size += 88;
2503 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002504}
2505
Lou Bergerc3741782016-01-12 13:42:01 -05002506/*
2507 * Encodes the tunnel encapsulation attribute
2508 */
2509static void
2510bgp_packet_mpattr_tea(
2511 struct bgp *bgp,
2512 struct peer *peer,
2513 struct stream *s,
2514 struct attr *attr,
2515 uint8_t attrtype)
2516{
2517 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002518 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002519 struct bgp_attr_encap_subtlv *subtlvs;
2520 struct bgp_attr_encap_subtlv *st;
2521 const char *attrname;
2522
2523 if (!attr || !attr->extra)
2524 return;
2525
2526 switch (attrtype) {
2527 case BGP_ATTR_ENCAP:
2528 attrname = "Tunnel Encap";
2529 subtlvs = attr->extra->encap_subtlvs;
2530
2531 /*
2532 * The tunnel encap attr has an "outer" tlv.
2533 * T = tunneltype,
2534 * L = total length of subtlvs,
2535 * V = concatenated subtlvs.
2536 */
2537 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002538 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002539 break;
2540
2541 default:
2542 assert(0);
2543 }
2544
2545
Lou Berger298cc2f2016-01-12 13:42:02 -05002546 /* if no tlvs, don't make attr */
2547 if (subtlvs == NULL)
2548 return;
2549
Lou Bergerc3741782016-01-12 13:42:01 -05002550 /* compute attr length */
2551 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002552 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002553 }
2554
Lou Bergerc3741782016-01-12 13:42:01 -05002555 if (attrlenfield > 0xffff) {
2556 zlog (peer->log, LOG_ERR,
2557 "%s attribute is too long (length=%d), can't send it",
2558 attrname,
2559 attrlenfield);
2560 return;
2561 }
2562
2563 if (attrlenfield > 0xff) {
2564 /* 2-octet length field */
2565 stream_putc (s,
2566 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2567 stream_putc (s, attrtype);
2568 stream_putw (s, attrlenfield & 0xffff);
2569 } else {
2570 /* 1-octet length field */
2571 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2572 stream_putc (s, attrtype);
2573 stream_putc (s, attrlenfield & 0xff);
2574 }
2575
2576 if (attrtype == BGP_ATTR_ENCAP) {
2577 /* write outer T+L */
2578 stream_putw(s, attr->extra->encap_tunneltype);
2579 stream_putw(s, attrlenfield - 4);
2580 }
2581
2582 /* write each sub-tlv */
2583 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002584 if (attrtype == BGP_ATTR_ENCAP) {
2585 stream_putc (s, st->type);
2586 stream_putc (s, st->length);
2587 }
Lou Bergerc3741782016-01-12 13:42:01 -05002588 stream_put (s, st->value, st->length);
2589 }
2590}
2591
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002592void
2593bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2594{
2595 /* Set MP attribute length. Don't count the (2) bytes used to encode
2596 the attr length */
2597 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2598}
2599
paul718e3742002-12-13 20:15:29 +00002600/* Make attribute packet. */
2601bgp_size_t
2602bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002603 struct stream *s, struct attr *attr,
2604 struct prefix *p, afi_t afi, safi_t safi,
2605 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002606{
paulfe69a502005-09-10 16:55:02 +00002607 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002608 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002609 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002610 int send_as4_path = 0;
2611 int send_as4_aggregator = 0;
2612 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002613
2614 if (! bgp)
2615 bgp = bgp_get_default ();
2616
2617 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002618 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002619
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002620 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2621 {
Lou Berger050defe2016-01-12 13:41:59 -05002622 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002623 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2624 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2625 bgp_packet_mpattr_end(s, mpattrlen_pos);
2626 }
2627
paul718e3742002-12-13 20:15:29 +00002628 /* Origin attribute. */
2629 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2630 stream_putc (s, BGP_ATTR_ORIGIN);
2631 stream_putc (s, 1);
2632 stream_putc (s, attr->origin);
2633
2634 /* AS path attribute. */
2635
2636 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002637 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002638 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002639 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002640 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002641 {
2642 aspath = aspath_dup (attr->aspath);
2643
2644 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2645 {
2646 /* Strip the confed info, and then stuff our path CONFED_ID
2647 on the front */
2648 aspath = aspath_delete_confed_seq (aspath);
2649 aspath = aspath_add_seq (aspath, bgp->confed_id);
2650 }
2651 else
2652 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002653 if (peer->change_local_as) {
2654 /* If replace-as is specified, we only use the change_local_as when
2655 advertising routes. */
2656 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2657 aspath = aspath_add_seq (aspath, peer->local_as);
2658 }
paul718e3742002-12-13 20:15:29 +00002659 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002660 } else {
2661 aspath = aspath_add_seq (aspath, peer->local_as);
2662 }
paul718e3742002-12-13 20:15:29 +00002663 }
2664 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002665 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002666 {
2667 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2668 aspath = aspath_dup (attr->aspath);
2669 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2670 }
2671 else
2672 aspath = attr->aspath;
2673
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002674 /* If peer is not AS4 capable, then:
2675 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2676 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2677 * types are in it (i.e. exclude them if they are there)
2678 * AND do this only if there is at least one asnum > 65535 in the path!
2679 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2680 * all ASnums > 65535 to BGP_AS_TRANS
2681 */
paul718e3742002-12-13 20:15:29 +00002682
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002683 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2684 stream_putc (s, BGP_ATTR_AS_PATH);
2685 aspath_sizep = stream_get_endp (s);
2686 stream_putw (s, 0);
2687 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2688
2689 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2690 * in the path
2691 */
2692 if (!use32bit && aspath_has_as4 (aspath))
2693 send_as4_path = 1; /* we'll do this later, at the correct place */
2694
paul718e3742002-12-13 20:15:29 +00002695 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002696 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2697 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002698 {
2699 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2700 stream_putc (s, BGP_ATTR_NEXT_HOP);
2701 stream_putc (s, 4);
2702 if (safi == SAFI_MPLS_VPN)
2703 {
2704 if (attr->nexthop.s_addr == 0)
2705 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2706 else
2707 stream_put_ipv4 (s, attr->nexthop.s_addr);
2708 }
2709 else
2710 stream_put_ipv4 (s, attr->nexthop.s_addr);
2711 }
2712
2713 /* MED attribute. */
2714 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2715 {
2716 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2717 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2718 stream_putc (s, 4);
2719 stream_putl (s, attr->med);
2720 }
2721
2722 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002723 if (peer->sort == BGP_PEER_IBGP ||
2724 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002725 {
2726 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2727 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2728 stream_putc (s, 4);
2729 stream_putl (s, attr->local_pref);
2730 }
2731
2732 /* Atomic aggregate. */
2733 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2734 {
2735 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2736 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2737 stream_putc (s, 0);
2738 }
2739
2740 /* Aggregator. */
2741 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2742 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002743 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002744
2745 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002746 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2747 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002748
2749 if (use32bit)
2750 {
2751 /* AS4 capable peer */
2752 stream_putc (s, 8);
2753 stream_putl (s, attr->extra->aggregator_as);
2754 }
2755 else
2756 {
2757 /* 2-byte AS peer */
2758 stream_putc (s, 6);
2759
2760 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2761 if ( attr->extra->aggregator_as > 65535 )
2762 {
2763 stream_putw (s, BGP_AS_TRANS);
2764
2765 /* we have to send AS4_AGGREGATOR, too.
2766 * we'll do that later in order to send attributes in ascending
2767 * order.
2768 */
2769 send_as4_aggregator = 1;
2770 }
2771 else
2772 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2773 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002774 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002775 }
2776
2777 /* Community attribute. */
2778 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2779 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2780 {
2781 if (attr->community->size * 4 > 255)
2782 {
2783 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2784 stream_putc (s, BGP_ATTR_COMMUNITIES);
2785 stream_putw (s, attr->community->size * 4);
2786 }
2787 else
2788 {
2789 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2790 stream_putc (s, BGP_ATTR_COMMUNITIES);
2791 stream_putc (s, attr->community->size * 4);
2792 }
2793 stream_put (s, attr->community->val, attr->community->size * 4);
2794 }
2795
2796 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002797 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002798 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002799 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002800 {
2801 /* Originator ID. */
2802 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2803 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2804 stream_putc (s, 4);
2805
2806 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002807 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002808 else
2809 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002810
2811 /* Cluster list. */
2812 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2813 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2814
Paul Jakma9eda90c2007-08-30 13:36:17 +00002815 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002816 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002817 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002818 /* If this peer configuration's parent BGP has cluster_id. */
2819 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2820 stream_put_in_addr (s, &bgp->cluster_id);
2821 else
2822 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002823 stream_put (s, attr->extra->cluster->list,
2824 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002825 }
2826 else
2827 {
2828 stream_putc (s, 4);
2829 /* If this peer configuration's parent BGP has cluster_id. */
2830 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2831 stream_put_in_addr (s, &bgp->cluster_id);
2832 else
2833 stream_put_in_addr (s, &bgp->router_id);
2834 }
2835 }
2836
paul718e3742002-12-13 20:15:29 +00002837 /* Extended Communities attribute. */
2838 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2839 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2840 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002841 struct attr_extra *attre = attr->extra;
2842
2843 assert (attre);
2844
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002845 if (peer->sort == BGP_PEER_IBGP
2846 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002847 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002848 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002849 {
2850 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2851 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002852 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002853 }
2854 else
2855 {
2856 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2857 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002858 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002859 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002860 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002861 }
2862 else
2863 {
paul5228ad22004-06-04 17:58:18 +00002864 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002865 int tbit;
2866 int ecom_tr_size = 0;
2867 int i;
2868
Paul Jakmafb982c22007-05-04 20:15:47 +00002869 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002870 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002871 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002872 tbit = *pnt;
2873
2874 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2875 continue;
2876
2877 ecom_tr_size++;
2878 }
2879
2880 if (ecom_tr_size)
2881 {
2882 if (ecom_tr_size * 8 > 255)
2883 {
2884 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2885 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2886 stream_putw (s, ecom_tr_size * 8);
2887 }
2888 else
2889 {
2890 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2891 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2892 stream_putc (s, ecom_tr_size * 8);
2893 }
2894
Paul Jakmafb982c22007-05-04 20:15:47 +00002895 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002896 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002897 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002898 tbit = *pnt;
2899
2900 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2901 continue;
2902
2903 stream_put (s, pnt, 8);
2904 }
2905 }
paul718e3742002-12-13 20:15:29 +00002906 }
paul718e3742002-12-13 20:15:29 +00002907 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002908
2909 if ( send_as4_path )
2910 {
2911 /* If the peer is NOT As4 capable, AND */
2912 /* there are ASnums > 65535 in path THEN
2913 * give out AS4_PATH */
2914
2915 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2916 * path segments!
2917 * Hm, I wonder... confederation things *should* only be at
2918 * the beginning of an aspath, right? Then we should use
2919 * aspath_delete_confed_seq for this, because it is already
2920 * there! (JK)
2921 * Folks, talk to me: what is reasonable here!?
2922 */
2923 aspath = aspath_delete_confed_seq (aspath);
2924
2925 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2926 stream_putc (s, BGP_ATTR_AS4_PATH);
2927 aspath_sizep = stream_get_endp (s);
2928 stream_putw (s, 0);
2929 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2930 }
2931
2932 if (aspath != attr->aspath)
2933 aspath_free (aspath);
2934
2935 if ( send_as4_aggregator )
2936 {
2937 assert (attr->extra);
2938
2939 /* send AS4_AGGREGATOR, at this place */
2940 /* this section of code moved here in order to ensure the correct
2941 * *ascending* order of attributes
2942 */
2943 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2944 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2945 stream_putc (s, 8);
2946 stream_putl (s, attr->extra->aggregator_as);
2947 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2948 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002949
2950 if ((afi == AFI_IP || afi == AFI_IP6) &&
2951 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2952 {
2953 /* Tunnel Encap attribute */
2954 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2955 }
2956
paul718e3742002-12-13 20:15:29 +00002957 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002958 if (attr->extra && attr->extra->transit)
2959 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002960
2961 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002962 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002963}
2964
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002965size_t
2966bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002967{
paul718e3742002-12-13 20:15:29 +00002968 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002969
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002970 /* Set extended bit always to encode the attribute length as 2 bytes */
2971 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002972 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2973
paul9985f832005-02-09 15:51:56 +00002974 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002975 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002976
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002977 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002978 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002979 return attrlen_pnt;
2980}
paul718e3742002-12-13 20:15:29 +00002981
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002982void
2983bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2984 afi_t afi, safi_t safi, struct prefix_rd *prd,
2985 u_char *tag)
2986{
Lou Berger050defe2016-01-12 13:41:59 -05002987 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002988}
paul718e3742002-12-13 20:15:29 +00002989
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002990void
2991bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2992{
Lou Berger050defe2016-01-12 13:41:59 -05002993 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002994}
2995
2996/* Initialization of attribute. */
2997void
paulfe69a502005-09-10 16:55:02 +00002998bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002999{
paul718e3742002-12-13 20:15:29 +00003000 aspath_init ();
3001 attrhash_init ();
3002 community_init ();
3003 ecommunity_init ();
3004 cluster_init ();
3005 transit_init ();
3006}
3007
Chris Caputo228da422009-07-18 05:44:03 +00003008void
3009bgp_attr_finish (void)
3010{
3011 aspath_finish ();
3012 attrhash_finish ();
3013 community_finish ();
3014 ecommunity_finish ();
3015 cluster_finish ();
3016 transit_finish ();
3017}
3018
paul718e3742002-12-13 20:15:29 +00003019/* Make attribute packet. */
3020void
paula3845922003-10-18 01:30:50 +00003021bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3022 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003023{
3024 unsigned long cp;
3025 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003026 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003027 struct aspath *aspath;
3028
3029 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003030 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003031
3032 /* Place holder of length. */
3033 stream_putw (s, 0);
3034
3035 /* Origin attribute. */
3036 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3037 stream_putc (s, BGP_ATTR_ORIGIN);
3038 stream_putc (s, 1);
3039 stream_putc (s, attr->origin);
3040
3041 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003042
3043 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3044 stream_putc (s, BGP_ATTR_AS_PATH);
3045 aspath_lenp = stream_get_endp (s);
3046 stream_putw (s, 0);
3047
3048 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003049
3050 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003051 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3052 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003053 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003054 )
3055 {
3056 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3057 stream_putc (s, BGP_ATTR_NEXT_HOP);
3058 stream_putc (s, 4);
3059 stream_put_ipv4 (s, attr->nexthop.s_addr);
3060 }
paul718e3742002-12-13 20:15:29 +00003061
3062 /* MED attribute. */
3063 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3064 {
3065 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3066 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3067 stream_putc (s, 4);
3068 stream_putl (s, attr->med);
3069 }
3070
3071 /* Local preference. */
3072 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3073 {
3074 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3075 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3076 stream_putc (s, 4);
3077 stream_putl (s, attr->local_pref);
3078 }
3079
3080 /* Atomic aggregate. */
3081 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3082 {
3083 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3084 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3085 stream_putc (s, 0);
3086 }
3087
3088 /* Aggregator. */
3089 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3090 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003091 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003092 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3093 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003094 stream_putc (s, 8);
3095 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003096 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003097 }
3098
3099 /* Community attribute. */
3100 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3101 {
3102 if (attr->community->size * 4 > 255)
3103 {
3104 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3105 stream_putc (s, BGP_ATTR_COMMUNITIES);
3106 stream_putw (s, attr->community->size * 4);
3107 }
3108 else
3109 {
3110 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3111 stream_putc (s, BGP_ATTR_COMMUNITIES);
3112 stream_putc (s, attr->community->size * 4);
3113 }
3114 stream_put (s, attr->community->val, attr->community->size * 4);
3115 }
3116
paula3845922003-10-18 01:30:50 +00003117 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003118 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3119 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003120 {
3121 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003122 struct attr_extra *attre = attr->extra;
3123
paula3845922003-10-18 01:30:50 +00003124 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3125 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003126 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003127
3128 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003129 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003130 stream_putw(s, AFI_IP6); /* AFI */
3131 stream_putc(s, SAFI_UNICAST); /* SAFI */
3132
3133 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003134 stream_putc(s, attre->mp_nexthop_len);
3135 stream_put(s, &attre->mp_nexthop_global, 16);
3136 if (attre->mp_nexthop_len == 32)
3137 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003138
3139 /* SNPA */
3140 stream_putc(s, 0);
3141
3142 /* Prefix */
3143 stream_put_prefix(s, prefix);
3144
3145 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003146 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003147 }
paula3845922003-10-18 01:30:50 +00003148
paul718e3742002-12-13 20:15:29 +00003149 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003150 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003151 stream_putw_at (s, cp, len);
3152}