blob: 616f779250e318315bc777c7c57db5b93cc904d1 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP attributes management routines.
2 Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "memory.h"
26#include "vector.h"
27#include "vty.h"
28#include "stream.h"
29#include "log.h"
30#include "hash.h"
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -070031#include "jhash.h"
Donald Sharp04907292016-01-07 10:03:01 -050032#include "filter.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_route.h"
37#include "bgpd/bgp_aspath.h"
38#include "bgpd/bgp_community.h"
39#include "bgpd/bgp_debug.h"
40#include "bgpd/bgp_packet.h"
41#include "bgpd/bgp_ecommunity.h"
Lou Bergerc3741782016-01-12 13:42:01 -050042#include "table.h"
43#include "bgp_encap_types.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020044
paul718e3742002-12-13 20:15:29 +000045/* Attribute strings for logging. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -070046static const struct message attr_str [] =
paul718e3742002-12-13 20:15:29 +000047{
48 { BGP_ATTR_ORIGIN, "ORIGIN" },
49 { BGP_ATTR_AS_PATH, "AS_PATH" },
50 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
51 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
52 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
53 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
54 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
55 { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
56 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
Denis Ovsienkof8627ff2011-10-10 16:52:20 +040057 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
paul718e3742002-12-13 20:15:29 +000058 { BGP_ATTR_DPA, "DPA" },
59 { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
60 { BGP_ATTR_RCID_PATH, "RCID_PATH" },
61 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
62 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000063 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
64 { BGP_ATTR_AS4_PATH, "AS4_PATH" },
65 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
66 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
Lou Bergerc3741782016-01-12 13:42:01 -050067 { BGP_ATTR_ENCAP, "ENCAP" },
paul718e3742002-12-13 20:15:29 +000068};
Balaji.G837d16c2012-09-26 14:09:10 +053069static const int attr_str_max = array_size(attr_str);
Denis Ovsienkoafcb7672011-10-23 22:32:44 +040070
71static const struct message attr_flag_str[] =
72{
73 { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
74 { BGP_ATTR_FLAG_TRANS, "Transitive" },
75 { BGP_ATTR_FLAG_PARTIAL, "Partial" },
76 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
77 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
78};
David Lamparter6b0655a2014-06-04 06:53:35 +020079
Stephen Hemminger9bddac42009-05-15 09:59:51 -070080static struct hash *cluster_hash;
paul718e3742002-12-13 20:15:29 +000081
paul94f2b392005-06-28 12:44:16 +000082static void *
Paul Jakma923de652007-04-29 18:25:17 +000083cluster_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +000084{
Paul Jakma923de652007-04-29 18:25:17 +000085 struct cluster_list * val = (struct cluster_list *) p;
paul718e3742002-12-13 20:15:29 +000086 struct cluster_list *cluster;
87
88 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
89 cluster->length = val->length;
90
91 if (cluster->length)
92 {
93 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
94 memcpy (cluster->list, val->list, val->length);
95 }
96 else
97 cluster->list = NULL;
98
99 cluster->refcnt = 0;
100
101 return cluster;
102}
103
104/* Cluster list related functions. */
paul94f2b392005-06-28 12:44:16 +0000105static struct cluster_list *
paul5228ad22004-06-04 17:58:18 +0000106cluster_parse (struct in_addr * pnt, int length)
paul718e3742002-12-13 20:15:29 +0000107{
108 struct cluster_list tmp;
109 struct cluster_list *cluster;
110
111 tmp.length = length;
paul5228ad22004-06-04 17:58:18 +0000112 tmp.list = pnt;
paul718e3742002-12-13 20:15:29 +0000113
114 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
115 cluster->refcnt++;
116 return cluster;
117}
118
119int
120cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
121{
122 int i;
123
124 for (i = 0; i < cluster->length / 4; i++)
125 if (cluster->list[i].s_addr == originator.s_addr)
126 return 1;
127 return 0;
128}
129
paul94f2b392005-06-28 12:44:16 +0000130static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000131cluster_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000132{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700133 const struct cluster_list *cluster = p;
paul718e3742002-12-13 20:15:29 +0000134
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700135 return jhash(cluster->list, cluster->length, 0);
paul718e3742002-12-13 20:15:29 +0000136}
137
paul94f2b392005-06-28 12:44:16 +0000138static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100139cluster_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000140{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100141 const struct cluster_list * cluster1 = p1;
142 const struct cluster_list * cluster2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000143
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100144 return (cluster1->length == cluster2->length &&
145 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000146}
147
paul94f2b392005-06-28 12:44:16 +0000148static void
paul718e3742002-12-13 20:15:29 +0000149cluster_free (struct cluster_list *cluster)
150{
151 if (cluster->list)
152 XFREE (MTYPE_CLUSTER_VAL, cluster->list);
153 XFREE (MTYPE_CLUSTER, cluster);
154}
155
Chris Caputo228da422009-07-18 05:44:03 +0000156#if 0
paul94f2b392005-06-28 12:44:16 +0000157static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000158cluster_dup (struct cluster_list *cluster)
159{
160 struct cluster_list *new;
161
Stephen Hemminger393deb92008-08-18 14:13:29 -0700162 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
paul718e3742002-12-13 20:15:29 +0000163 new->length = cluster->length;
164
165 if (cluster->length)
166 {
167 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
168 memcpy (new->list, cluster->list, cluster->length);
169 }
170 else
171 new->list = NULL;
172
173 return new;
174}
Chris Caputo228da422009-07-18 05:44:03 +0000175#endif
paul718e3742002-12-13 20:15:29 +0000176
paul94f2b392005-06-28 12:44:16 +0000177static struct cluster_list *
paul718e3742002-12-13 20:15:29 +0000178cluster_intern (struct cluster_list *cluster)
179{
180 struct cluster_list *find;
181
182 find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
183 find->refcnt++;
184
185 return find;
186}
187
188void
189cluster_unintern (struct cluster_list *cluster)
190{
paul718e3742002-12-13 20:15:29 +0000191 if (cluster->refcnt)
192 cluster->refcnt--;
193
194 if (cluster->refcnt == 0)
195 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400196 hash_release (cluster_hash, cluster);
paul718e3742002-12-13 20:15:29 +0000197 cluster_free (cluster);
198 }
199}
200
paul94f2b392005-06-28 12:44:16 +0000201static void
202cluster_init (void)
paul718e3742002-12-13 20:15:29 +0000203{
204 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
205}
Chris Caputo228da422009-07-18 05:44:03 +0000206
207static void
208cluster_finish (void)
209{
Lou Berger056f3762013-04-10 12:30:04 -0700210 hash_clean (cluster_hash, (void (*)(void *))cluster_free);
Chris Caputo228da422009-07-18 05:44:03 +0000211 hash_free (cluster_hash);
212 cluster_hash = NULL;
213}
David Lamparter6b0655a2014-06-04 06:53:35 +0200214
Lou Bergerc3741782016-01-12 13:42:01 -0500215struct bgp_attr_encap_subtlv *
216encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
217{
218 struct bgp_attr_encap_subtlv *new;
219 struct bgp_attr_encap_subtlv *tail;
220 struct bgp_attr_encap_subtlv *p;
221
222 for (p = orig, tail = new = NULL; p; p = p->next) {
223 int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length;
224 if (tail) {
225 tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
226 tail = tail->next;
227 } else {
228 tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
229 }
230 assert(tail);
231 memcpy(tail, p, size);
232 tail->next = NULL;
233 }
234
235 return new;
236}
237
238static void
239encap_free(struct bgp_attr_encap_subtlv *p)
240{
241 struct bgp_attr_encap_subtlv *next;
242 while (p) {
243 next = p->next;
244 p->next = NULL;
245 XFREE(MTYPE_ENCAP_TLV, p);
246 p = next;
247 }
248}
249
250void
251bgp_attr_flush_encap(struct attr *attr)
252{
253 if (!attr || !attr->extra)
254 return;
255
256 if (attr->extra->encap_subtlvs) {
257 encap_free(attr->extra->encap_subtlvs);
258 attr->extra->encap_subtlvs = NULL;
259 }
260}
261
262/*
263 * Compare encap sub-tlv chains
264 *
265 * 1 = equivalent
266 * 0 = not equivalent
267 *
268 * This algorithm could be made faster if needed
269 */
270static int
271encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
272{
273 struct bgp_attr_encap_subtlv *p;
274 struct bgp_attr_encap_subtlv *q;
275
276 if (!h1 && !h2)
277 return 1;
278 if (h1 && !h2)
279 return 0;
280 if (!h1 && h2)
281 return 0;
282 if (h1 == h2)
283 return 1;
284
285 for (p = h1; p; p = p->next) {
286 for (q = h2; q; q = q->next) {
287 if ((p->type == q->type) &&
288 (p->length == q->length) &&
289 !memcmp(p->value, q->value, p->length)) {
290
291 break;
292 }
293 }
294 if (!q)
295 return 0;
296 }
297
298 for (p = h2; p; p = p->next) {
299 for (q = h1; q; q = q->next) {
300 if ((p->type == q->type) &&
301 (p->length == q->length) &&
302 !memcmp(p->value, q->value, p->length)) {
303
304 break;
305 }
306 }
307 if (!q)
308 return 0;
309 }
310
311 return 1;
312}
313
paul718e3742002-12-13 20:15:29 +0000314/* Unknown transit attribute. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700315static struct hash *transit_hash;
paul718e3742002-12-13 20:15:29 +0000316
paul94f2b392005-06-28 12:44:16 +0000317static void
paul718e3742002-12-13 20:15:29 +0000318transit_free (struct transit *transit)
319{
320 if (transit->val)
321 XFREE (MTYPE_TRANSIT_VAL, transit->val);
322 XFREE (MTYPE_TRANSIT, transit);
323}
324
Paul Jakma923de652007-04-29 18:25:17 +0000325
paul94f2b392005-06-28 12:44:16 +0000326static void *
Paul Jakma923de652007-04-29 18:25:17 +0000327transit_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000328{
329 /* Transit structure is already allocated. */
Paul Jakma923de652007-04-29 18:25:17 +0000330 return p;
paul718e3742002-12-13 20:15:29 +0000331}
332
paul94f2b392005-06-28 12:44:16 +0000333static struct transit *
paul718e3742002-12-13 20:15:29 +0000334transit_intern (struct transit *transit)
335{
336 struct transit *find;
337
338 find = hash_get (transit_hash, transit, transit_hash_alloc);
339 if (find != transit)
340 transit_free (transit);
341 find->refcnt++;
342
343 return find;
344}
345
346void
347transit_unintern (struct transit *transit)
348{
paul718e3742002-12-13 20:15:29 +0000349 if (transit->refcnt)
350 transit->refcnt--;
351
352 if (transit->refcnt == 0)
353 {
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400354 hash_release (transit_hash, transit);
paul718e3742002-12-13 20:15:29 +0000355 transit_free (transit);
356 }
357}
358
paul94f2b392005-06-28 12:44:16 +0000359static unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000360transit_hash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000361{
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700362 const struct transit * transit = p;
paul718e3742002-12-13 20:15:29 +0000363
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700364 return jhash(transit->val, transit->length, 0);
paul718e3742002-12-13 20:15:29 +0000365}
366
paul94f2b392005-06-28 12:44:16 +0000367static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100368transit_hash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000369{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100370 const struct transit * transit1 = p1;
371 const struct transit * transit2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000372
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100373 return (transit1->length == transit2->length &&
374 memcmp (transit1->val, transit2->val, transit1->length) == 0);
paul718e3742002-12-13 20:15:29 +0000375}
376
paul94f2b392005-06-28 12:44:16 +0000377static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800378transit_init (void)
paul718e3742002-12-13 20:15:29 +0000379{
380 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
381}
Chris Caputo228da422009-07-18 05:44:03 +0000382
383static void
384transit_finish (void)
385{
Lou Berger056f3762013-04-10 12:30:04 -0700386 hash_clean (transit_hash, (void (*)(void *))transit_free);
Chris Caputo228da422009-07-18 05:44:03 +0000387 hash_free (transit_hash);
388 transit_hash = NULL;
389}
David Lamparter6b0655a2014-06-04 06:53:35 +0200390
paul718e3742002-12-13 20:15:29 +0000391/* Attribute hash routines. */
Stephen Hemminger9bddac42009-05-15 09:59:51 -0700392static struct hash *attrhash;
paul718e3742002-12-13 20:15:29 +0000393
Paul Jakmafb982c22007-05-04 20:15:47 +0000394static struct attr_extra *
395bgp_attr_extra_new (void)
396{
397 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
398}
399
400void
401bgp_attr_extra_free (struct attr *attr)
402{
403 if (attr->extra)
404 {
Lou Bergerc3741782016-01-12 13:42:01 -0500405 if (attr->extra->encap_subtlvs) {
406 encap_free(attr->extra->encap_subtlvs);
407 attr->extra->encap_subtlvs = NULL;
408 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000409 XFREE (MTYPE_ATTR_EXTRA, attr->extra);
410 attr->extra = NULL;
411 }
412}
413
414struct attr_extra *
415bgp_attr_extra_get (struct attr *attr)
416{
417 if (!attr->extra)
418 attr->extra = bgp_attr_extra_new();
419 return attr->extra;
420}
421
422/* Shallow copy of an attribute
423 * Though, not so shallow that it doesn't copy the contents
424 * of the attr_extra pointed to by 'extra'
425 */
426void
427bgp_attr_dup (struct attr *new, struct attr *orig)
428{
Jorge Boncompte [DTI2]558d1fe2012-05-07 16:53:05 +0000429 struct attr_extra *extra = new->extra;
430
Paul Jakmafb982c22007-05-04 20:15:47 +0000431 *new = *orig;
Christian Frankea0de1d12012-12-07 16:35:00 +0000432 /* if caller provided attr_extra space, use it in any case.
433 *
434 * This is neccesary even if orig->extra equals NULL, because otherwise
435 * memory may be later allocated on the heap by bgp_attr_extra_get.
436 *
437 * That memory would eventually be leaked, because the caller must not
438 * call bgp_attr_extra_free if he provided attr_extra on the stack.
439 */
440 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000441 {
Christian Frankea0de1d12012-12-07 16:35:00 +0000442 new->extra = extra;
443 memset(new->extra, 0, sizeof(struct attr_extra));
Lou Bergerc3741782016-01-12 13:42:01 -0500444 if (orig->extra) {
Christian Frankea0de1d12012-12-07 16:35:00 +0000445 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500446 if (orig->extra->encap_subtlvs) {
447 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
448 }
449 }
Christian Frankea0de1d12012-12-07 16:35:00 +0000450 }
451 else if (orig->extra)
452 {
453 new->extra = bgp_attr_extra_new();
Paul Jakmafb982c22007-05-04 20:15:47 +0000454 *new->extra = *orig->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500455 if (orig->extra->encap_subtlvs) {
456 new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
457 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000458 }
459}
460
Paul Jakmacbdfbaa2006-03-30 13:20:48 +0000461unsigned long int
462attr_count (void)
463{
464 return attrhash->count;
465}
466
467unsigned long int
468attr_unknown_count (void)
469{
470 return transit_hash->count;
471}
472
paul718e3742002-12-13 20:15:29 +0000473unsigned int
Paul Jakma923de652007-04-29 18:25:17 +0000474attrhash_key_make (void *p)
paul718e3742002-12-13 20:15:29 +0000475{
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000476 const struct attr *attr = (struct attr *) p;
477 const struct attr_extra *extra = attr->extra;
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700478 uint32_t key = 0;
479#define MIX(val) key = jhash_1word(val, key)
paul718e3742002-12-13 20:15:29 +0000480
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700481 MIX(attr->origin);
482 MIX(attr->nexthop.s_addr);
483 MIX(attr->med);
484 MIX(attr->local_pref);
485
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000486 key += attr->origin;
487 key += attr->nexthop.s_addr;
488 key += attr->med;
489 key += attr->local_pref;
Paul Jakmafb982c22007-05-04 20:15:47 +0000490
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000491 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000492 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000493 MIX(extra->aggregator_as);
494 MIX(extra->aggregator_addr.s_addr);
495 MIX(extra->weight);
496 MIX(extra->mp_nexthop_global_in.s_addr);
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000497 MIX(extra->originator_id.s_addr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000498 }
499
paul718e3742002-12-13 20:15:29 +0000500 if (attr->aspath)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700501 MIX(aspath_key_make (attr->aspath));
paul718e3742002-12-13 20:15:29 +0000502 if (attr->community)
Stephen Hemmingerc8e7b892010-08-27 14:12:54 -0700503 MIX(community_hash_make (attr->community));
Paul Jakmafb982c22007-05-04 20:15:47 +0000504
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000505 if (extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000506 {
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000507 if (extra->ecommunity)
508 MIX(ecommunity_hash_make (extra->ecommunity));
509 if (extra->cluster)
510 MIX(cluster_hash_key_make (extra->cluster));
511 if (extra->transit)
512 MIX(transit_hash_key_make (extra->transit));
paul718e3742002-12-13 20:15:29 +0000513
Jorge Boncompte [DTI2]7fb0cd82012-05-07 16:52:58 +0000514 MIX(extra->mp_nexthop_len);
515 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key);
516 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key);
Paul Jakmafb982c22007-05-04 20:15:47 +0000517 }
paul718e3742002-12-13 20:15:29 +0000518
519 return key;
520}
521
522int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100523attrhash_cmp (const void *p1, const void *p2)
paul718e3742002-12-13 20:15:29 +0000524{
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100525 const struct attr * attr1 = p1;
526 const struct attr * attr2 = p2;
Paul Jakma923de652007-04-29 18:25:17 +0000527
paul718e3742002-12-13 20:15:29 +0000528 if (attr1->flag == attr2->flag
529 && attr1->origin == attr2->origin
530 && attr1->nexthop.s_addr == attr2->nexthop.s_addr
paul718e3742002-12-13 20:15:29 +0000531 && attr1->aspath == attr2->aspath
532 && attr1->community == attr2->community
Paul Jakmafb982c22007-05-04 20:15:47 +0000533 && attr1->med == attr2->med
Paul Jakmac8f3fe32010-12-05 20:28:02 +0000534 && attr1->local_pref == attr2->local_pref)
Paul Jakmafb982c22007-05-04 20:15:47 +0000535 {
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100536 const struct attr_extra *ae1 = attr1->extra;
537 const struct attr_extra *ae2 = attr2->extra;
Paul Jakmafb982c22007-05-04 20:15:47 +0000538
539 if (ae1 && ae2
540 && ae1->aggregator_as == ae2->aggregator_as
541 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
542 && ae1->weight == ae2->weight
Paul Jakmafb982c22007-05-04 20:15:47 +0000543 && ae1->mp_nexthop_len == ae2->mp_nexthop_len
544 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
545 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
Paul Jakmafb982c22007-05-04 20:15:47 +0000546 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
547 && ae1->ecommunity == ae2->ecommunity
548 && ae1->cluster == ae2->cluster
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000549 && ae1->transit == ae2->transit
Lou Bergerc3741782016-01-12 13:42:01 -0500550 && (ae1->encap_tunneltype == ae2->encap_tunneltype)
551 && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
Pradosh Mohapatra689bb662013-09-07 07:13:37 +0000552 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
Paul Jakmafb982c22007-05-04 20:15:47 +0000553 return 1;
554 else if (ae1 || ae2)
555 return 0;
556 /* neither attribute has extra attributes, so they're same */
557 return 1;
558 }
paul718e3742002-12-13 20:15:29 +0000559 else
560 return 0;
561}
562
paul94f2b392005-06-28 12:44:16 +0000563static void
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100564attrhash_init (void)
paul718e3742002-12-13 20:15:29 +0000565{
566 attrhash = hash_create (attrhash_key_make, attrhash_cmp);
567}
568
Lou Berger056f3762013-04-10 12:30:04 -0700569/*
570 * special for hash_clean below
571 */
572static void
573attr_vfree (void *attr)
574{
575 bgp_attr_extra_free ((struct attr *)attr);
576 XFREE (MTYPE_ATTR, attr);
577}
578
paul94f2b392005-06-28 12:44:16 +0000579static void
Chris Caputo228da422009-07-18 05:44:03 +0000580attrhash_finish (void)
581{
Lou Berger056f3762013-04-10 12:30:04 -0700582 hash_clean(attrhash, attr_vfree);
Chris Caputo228da422009-07-18 05:44:03 +0000583 hash_free (attrhash);
584 attrhash = NULL;
585}
586
587static void
paul718e3742002-12-13 20:15:29 +0000588attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
589{
590 struct attr *attr = backet->data;
591
592 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
593 inet_ntoa (attr->nexthop), VTY_NEWLINE);
594}
595
596void
597attr_show_all (struct vty *vty)
598{
599 hash_iterate (attrhash,
600 (void (*)(struct hash_backet *, void *))
601 attr_show_all_iterator,
602 vty);
603}
604
paul94f2b392005-06-28 12:44:16 +0000605static void *
Paul Jakma923de652007-04-29 18:25:17 +0000606bgp_attr_hash_alloc (void *p)
paul718e3742002-12-13 20:15:29 +0000607{
Paul Jakma923de652007-04-29 18:25:17 +0000608 struct attr * val = (struct attr *) p;
paul718e3742002-12-13 20:15:29 +0000609 struct attr *attr;
610
611 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
612 *attr = *val;
Paul Jakmafb982c22007-05-04 20:15:47 +0000613 if (val->extra)
614 {
615 attr->extra = bgp_attr_extra_new ();
616 *attr->extra = *val->extra;
Lou Bergerc3741782016-01-12 13:42:01 -0500617
618 if (attr->extra->encap_subtlvs) {
619 attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
620 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000621 }
paul718e3742002-12-13 20:15:29 +0000622 attr->refcnt = 0;
623 return attr;
624}
625
626/* Internet argument attribute. */
627struct attr *
628bgp_attr_intern (struct attr *attr)
629{
630 struct attr *find;
631
632 /* Intern referenced strucutre. */
633 if (attr->aspath)
634 {
635 if (! attr->aspath->refcnt)
636 attr->aspath = aspath_intern (attr->aspath);
637 else
638 attr->aspath->refcnt++;
639 }
640 if (attr->community)
641 {
642 if (! attr->community->refcnt)
643 attr->community = community_intern (attr->community);
644 else
645 attr->community->refcnt++;
646 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000647 if (attr->extra)
paul718e3742002-12-13 20:15:29 +0000648 {
Paul Jakmafb982c22007-05-04 20:15:47 +0000649 struct attr_extra *attre = attr->extra;
650
651 if (attre->ecommunity)
652 {
653 if (! attre->ecommunity->refcnt)
654 attre->ecommunity = ecommunity_intern (attre->ecommunity);
655 else
656 attre->ecommunity->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000657
Paul Jakmafb982c22007-05-04 20:15:47 +0000658 }
659 if (attre->cluster)
660 {
661 if (! attre->cluster->refcnt)
662 attre->cluster = cluster_intern (attre->cluster);
663 else
664 attre->cluster->refcnt++;
665 }
666 if (attre->transit)
667 {
668 if (! attre->transit->refcnt)
669 attre->transit = transit_intern (attre->transit);
670 else
671 attre->transit->refcnt++;
672 }
paul718e3742002-12-13 20:15:29 +0000673 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000674
paul718e3742002-12-13 20:15:29 +0000675 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
676 find->refcnt++;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000677
paul718e3742002-12-13 20:15:29 +0000678 return find;
679}
680
Paul Jakma03e214c2007-04-29 18:31:07 +0000681
paul718e3742002-12-13 20:15:29 +0000682/* Make network statement's attribute. */
683struct attr *
684bgp_attr_default_set (struct attr *attr, u_char origin)
685{
686 memset (attr, 0, sizeof (struct attr));
Paul Jakmafb982c22007-05-04 20:15:47 +0000687 bgp_attr_extra_get (attr);
688
paul718e3742002-12-13 20:15:29 +0000689 attr->origin = origin;
690 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
691 attr->aspath = aspath_empty ();
692 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
Paul Jakmafb982c22007-05-04 20:15:47 +0000693 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
paul718e3742002-12-13 20:15:29 +0000694 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
Paul Jakmafb982c22007-05-04 20:15:47 +0000695 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
Paul Jakma03e214c2007-04-29 18:31:07 +0000696
paul718e3742002-12-13 20:15:29 +0000697 return attr;
698}
699
Paul Jakma03e214c2007-04-29 18:31:07 +0000700
paul718e3742002-12-13 20:15:29 +0000701/* Make network statement's attribute. */
702struct attr *
703bgp_attr_default_intern (u_char origin)
704{
705 struct attr attr;
706 struct attr *new;
Jorge Boncompte [DTI2]e16a4132012-05-07 16:52:57 +0000707
Lou Bergerc3741782016-01-12 13:42:01 -0500708 memset (&attr, 0, sizeof (struct attr));
709 bgp_attr_extra_get (&attr);
710
Paul Jakma03e214c2007-04-29 18:31:07 +0000711 bgp_attr_default_set(&attr, origin);
paul718e3742002-12-13 20:15:29 +0000712
713 new = bgp_attr_intern (&attr);
Paul Jakmafb982c22007-05-04 20:15:47 +0000714 bgp_attr_extra_free (&attr);
715
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000716 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000717 return new;
718}
719
Daniel Walton76a72802015-05-19 17:47:24 -0700720/* Create the attributes for an aggregate */
paul718e3742002-12-13 20:15:29 +0000721struct attr *
722bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
723 struct aspath *aspath,
724 struct community *community, int as_set)
725{
726 struct attr attr;
727 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000728 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000729
730 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000731 memset (&attre, 0, sizeof (struct attr_extra));
732 attr.extra = &attre;
733
paul718e3742002-12-13 20:15:29 +0000734 /* Origin attribute. */
735 attr.origin = origin;
736 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
737
738 /* AS path attribute. */
739 if (aspath)
740 attr.aspath = aspath_intern (aspath);
741 else
742 attr.aspath = aspath_empty ();
743 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
744
745 /* Next hop attribute. */
746 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
747
748 if (community)
749 {
750 attr.community = community;
751 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
752 }
753
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000754 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000755 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
Lou Berger205e6742016-01-12 13:42:11 -0500756
paul718e3742002-12-13 20:15:29 +0000757 if (! as_set)
758 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
759 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
760 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000761 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000762 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000763 attre.aggregator_as = bgp->as;
764 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000765
766 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000767
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000768 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000769 return new;
770}
771
Paul Jakmab881c702010-11-23 16:35:42 +0000772/* Unintern just the sub-components of the attr, but not the attr */
773void
774bgp_attr_unintern_sub (struct attr *attr)
775{
776 /* aspath refcount shoud be decrement. */
777 if (attr->aspath)
778 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000779 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000780
781 if (attr->community)
782 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000783 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000784
785 if (attr->extra)
786 {
787 if (attr->extra->ecommunity)
788 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000789 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000790
791 if (attr->extra->cluster)
792 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000793 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000794
795 if (attr->extra->transit)
796 transit_unintern (attr->extra->transit);
797 }
798}
799
paul718e3742002-12-13 20:15:29 +0000800/* Free bgp attribute and aspath. */
801void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000802bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000803{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000804 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000805 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000806 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000807 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000808
paul718e3742002-12-13 20:15:29 +0000809 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000810 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000811
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000812 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000813
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000814 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000815 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000816 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000817 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000818 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000819
paul718e3742002-12-13 20:15:29 +0000820 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000821 if (attr->refcnt == 0)
822 {
823 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000824 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000825 bgp_attr_extra_free (attr);
826 XFREE (MTYPE_ATTR, attr);
827 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000828 }
829
Paul Jakmab881c702010-11-23 16:35:42 +0000830 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000831}
832
833void
834bgp_attr_flush (struct attr *attr)
835{
836 if (attr->aspath && ! attr->aspath->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500837 {
838 aspath_free (attr->aspath);
839 attr->aspath = NULL;
840 }
paul718e3742002-12-13 20:15:29 +0000841 if (attr->community && ! attr->community->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500842 {
843 community_free (attr->community);
844 attr->community = NULL;
845 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000846 if (attr->extra)
847 {
848 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000849
Paul Jakmafb982c22007-05-04 20:15:47 +0000850 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000851 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000852 if (attre->cluster && ! attre->cluster->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500853 {
854 cluster_free (attre->cluster);
855 attre->cluster = NULL;
856 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000857 if (attre->transit && ! attre->transit->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500858 {
859 transit_free (attre->transit);
860 attre->transit = NULL;
861 }
Lou Bergerc3741782016-01-12 13:42:01 -0500862 encap_free(attre->encap_subtlvs);
863 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000864 }
paul718e3742002-12-13 20:15:29 +0000865}
866
Paul Jakmab881c702010-11-23 16:35:42 +0000867/* Implement draft-scudder-idr-optional-transitive behaviour and
868 * avoid resetting sessions for malformed attributes which are
869 * are partial/optional and hence where the error likely was not
870 * introduced by the sending neighbour.
871 */
872static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000873bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
874 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000875{
Paul Jakma835315b2012-01-18 12:28:30 +0000876 struct peer *const peer = args->peer;
877 const u_int8_t flags = args->flags;
878 /* startp and length must be special-cased, as whether or not to
879 * send the attribute data with the NOTIFY depends on the error,
880 * the caller therefore signals this with the seperate length argument
881 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000882 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000883
Paul Jakmab881c702010-11-23 16:35:42 +0000884 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000885 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000886 {
887 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000888 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000889 return BGP_ATTR_PARSE_ERROR;
890
891 }
892
Paul Jakmabd471fe2012-03-15 11:30:00 +0000893 /* Adjust the stream getp to the end of the attribute, in case we can
894 * still proceed but the caller hasn't read all the attribute.
895 */
896 stream_set_getp (BGP_INPUT (peer),
897 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
898 + args->total);
899
Paul Jakma835315b2012-01-18 12:28:30 +0000900 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100901 /* where an attribute is relatively inconsequential, e.g. it does not
902 * affect route selection, and can be safely ignored, then any such
903 * attributes which are malformed should just be ignored and the route
904 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000905 */
906 case BGP_ATTR_AS4_AGGREGATOR:
907 case BGP_ATTR_AGGREGATOR:
908 case BGP_ATTR_ATOMIC_AGGREGATE:
909 return BGP_ATTR_PARSE_PROCEED;
910
911 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100912 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000913 */
914 case BGP_ATTR_ORIGIN:
915 case BGP_ATTR_AS_PATH:
916 case BGP_ATTR_NEXT_HOP:
917 case BGP_ATTR_MULTI_EXIT_DISC:
918 case BGP_ATTR_LOCAL_PREF:
919 case BGP_ATTR_COMMUNITIES:
920 case BGP_ATTR_ORIGINATOR_ID:
921 case BGP_ATTR_CLUSTER_LIST:
922 case BGP_ATTR_MP_REACH_NLRI:
923 case BGP_ATTR_MP_UNREACH_NLRI:
924 case BGP_ATTR_EXT_COMMUNITIES:
925 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000926 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000927 return BGP_ATTR_PARSE_ERROR;
928 }
929
930 /* Partial optional attributes that are malformed should not cause
931 * the whole session to be reset. Instead treat it as a withdrawal
932 * of the routes, if possible.
933 */
Paul Jakma835315b2012-01-18 12:28:30 +0000934 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
935 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
936 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000937 return BGP_ATTR_PARSE_WITHDRAW;
938
939 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200940 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000941}
942
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400943/* Find out what is wrong with the path attribute flag bits and log the error.
944 "Flag bits" here stand for Optional, Transitive and Partial, but not for
945 Extended Length. Checking O/T/P bits at once implies, that the attribute
946 being diagnosed is defined by RFC as either a "well-known" or an "optional,
947 non-transitive" attribute. */
948static void
Paul Jakma835315b2012-01-18 12:28:30 +0000949bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
950 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400951)
952{
953 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000954 u_char real_flags = args->flags;
955 const u_int8_t attr_code = args->type;
956
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400957 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
958 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
959 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
960 if
961 (
962 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
963 CHECK_FLAG (real_flags, attr_flag_str[i].key)
964 )
965 {
Paul Jakma835315b2012-01-18 12:28:30 +0000966 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400967 LOOKUP (attr_str, attr_code),
968 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
969 attr_flag_str[i].str);
970 seen = 1;
971 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100972 if (!seen)
973 {
974 zlog (args->peer->log, LOG_DEBUG,
975 "Strange, %s called for attr %s, but no problem found with flags"
976 " (real flags 0x%x, desired 0x%x)",
977 __func__, LOOKUP (attr_str, attr_code),
978 real_flags, desired_flags);
979 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400980}
981
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000982/* Required flags for attributes. EXTLEN will be masked off when testing,
983 * as will PARTIAL for optional+transitive attributes.
984 */
985const u_int8_t attr_flags_values [] = {
986 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
987 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
988 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
989 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
990 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
991 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
992 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
993 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
994 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
995 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
996 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
997 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
998 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
999 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1000 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1001};
1002static const size_t attr_flags_values_max =
1003 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
1004
1005static int
Paul Jakma835315b2012-01-18 12:28:30 +00001006bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001007{
1008 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +00001009 const u_int8_t flags = args->flags;
1010 const u_int8_t attr_code = args->type;
1011 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001012
1013 /* there may be attributes we don't know about */
1014 if (attr_code > attr_flags_values_max)
1015 return 0;
1016 if (attr_flags_values[attr_code] == 0)
1017 return 0;
1018
1019 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1020 * 1."
1021 */
1022 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1023 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1024 {
1025 zlog (peer->log, LOG_ERR,
1026 "%s well-known attributes must have transitive flag set (%x)",
1027 LOOKUP (attr_str, attr_code), flags);
1028 return 1;
1029 }
1030
1031 /* "For well-known attributes and for optional non-transitive attributes,
1032 * the Partial bit MUST be set to 0."
1033 */
1034 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1035 {
1036 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1037 {
1038 zlog (peer->log, LOG_ERR,
1039 "%s well-known attribute "
1040 "must NOT have the partial flag set (%x)",
1041 LOOKUP (attr_str, attr_code), flags);
1042 return 1;
1043 }
1044 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1045 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1046 {
1047 zlog (peer->log, LOG_ERR,
1048 "%s optional + transitive attribute "
1049 "must NOT have the partial flag set (%x)",
1050 LOOKUP (attr_str, attr_code), flags);
1051 return 1;
1052 }
1053 }
1054
1055 /* Optional transitive attributes may go through speakers that don't
1056 * reocgnise them and set the Partial bit.
1057 */
1058 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1059 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1060 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1061
Paul Jakma683f2b82012-03-23 14:58:45 +00001062 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001063 == attr_flags_values[attr_code])
1064 return 0;
1065
Paul Jakma835315b2012-01-18 12:28:30 +00001066 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001067 return 1;
1068}
1069
paul718e3742002-12-13 20:15:29 +00001070/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001071static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001072bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001073{
Paul Jakma835315b2012-01-18 12:28:30 +00001074 struct peer *const peer = args->peer;
1075 struct attr *const attr = args->attr;
1076 const bgp_size_t length = args->length;
1077
paul718e3742002-12-13 20:15:29 +00001078 /* If any recognized attribute has Attribute Length that conflicts
1079 with the expected length (based on the attribute type code), then
1080 the Error Subcode is set to Attribute Length Error. The Data
1081 field contains the erroneous attribute (type, length and
1082 value). */
1083 if (length != 1)
1084 {
1085 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1086 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001087 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001088 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001089 args->total);
paul718e3742002-12-13 20:15:29 +00001090 }
1091
1092 /* Fetch origin attribute. */
1093 attr->origin = stream_getc (BGP_INPUT (peer));
1094
1095 /* If the ORIGIN attribute has an undefined value, then the Error
1096 Subcode is set to Invalid Origin Attribute. The Data field
1097 contains the unrecognized attribute (type, length and value). */
1098 if ((attr->origin != BGP_ORIGIN_IGP)
1099 && (attr->origin != BGP_ORIGIN_EGP)
1100 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1101 {
1102 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1103 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001104 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001105 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001106 args->total);
paul718e3742002-12-13 20:15:29 +00001107 }
1108
1109 /* Set oring attribute flag. */
1110 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1111
1112 return 0;
1113}
Paul Jakmaab005292010-11-27 22:48:34 +00001114
1115/* Parse AS path information. This function is wrapper of
1116 aspath_parse. */
1117static int
Paul Jakma835315b2012-01-18 12:28:30 +00001118bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001119{
Paul Jakma835315b2012-01-18 12:28:30 +00001120 struct attr *const attr = args->attr;
1121 struct peer *const peer = args->peer;
1122 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001123
Paul Jakmaab005292010-11-27 22:48:34 +00001124 /*
1125 * peer with AS4 => will get 4Byte ASnums
1126 * otherwise, will get 16 Bit
1127 */
1128 attr->aspath = aspath_parse (peer->ibuf, length,
1129 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1130
1131 /* In case of IBGP, length will be zero. */
1132 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001133 {
Paul Jakmab881c702010-11-23 16:35:42 +00001134 zlog (peer->log, LOG_ERR,
1135 "Malformed AS path from %s, length is %d",
1136 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001137 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001138 }
Chris Hallcddb8112010-08-09 22:31:37 +04001139
Paul Jakmaab005292010-11-27 22:48:34 +00001140 /* Set aspath attribute flag. */
1141 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001142
Paul Jakmab881c702010-11-23 16:35:42 +00001143 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001144}
1145
Paul Jakmab881c702010-11-23 16:35:42 +00001146static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001147bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001148{
1149 /* These checks were part of bgp_attr_aspath, but with
1150 * as4 we should to check aspath things when
1151 * aspath synthesizing with as4_path has already taken place.
1152 * Otherwise we check ASPATH and use the synthesized thing, and that is
1153 * not right.
1154 * So do the checks later, i.e. here
1155 */
1156 struct bgp *bgp = peer->bgp;
1157 struct aspath *aspath;
1158
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001159 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001160 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1161 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001162 {
1163 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001164 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1165 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1166 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001167 }
1168
paul718e3742002-12-13 20:15:29 +00001169 /* First AS check for EBGP. */
1170 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1171 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001172 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001173 && ! aspath_firstas_check (attr->aspath, peer->as))
1174 {
1175 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001176 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001177 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1178 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1179 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001180 }
1181 }
1182
1183 /* local-as prepend */
1184 if (peer->change_local_as &&
1185 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1186 {
1187 aspath = aspath_dup (attr->aspath);
1188 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001189 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001190 attr->aspath = aspath_intern (aspath);
1191 }
1192
Paul Jakmab881c702010-11-23 16:35:42 +00001193 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001194}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001195
Paul Jakmaab005292010-11-27 22:48:34 +00001196/* Parse AS4 path information. This function is another wrapper of
1197 aspath_parse. */
1198static int
Paul Jakma835315b2012-01-18 12:28:30 +00001199bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001200{
Paul Jakma835315b2012-01-18 12:28:30 +00001201 struct peer *const peer = args->peer;
1202 struct attr *const attr = args->attr;
1203 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001204
Paul Jakmaab005292010-11-27 22:48:34 +00001205 *as4_path = aspath_parse (peer->ibuf, length, 1);
1206
Paul Jakmab881c702010-11-23 16:35:42 +00001207 /* In case of IBGP, length will be zero. */
1208 if (!*as4_path)
1209 {
1210 zlog (peer->log, LOG_ERR,
1211 "Malformed AS4 path from %s, length is %d",
1212 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001213 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001214 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001215 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001216 }
1217
Paul Jakmaab005292010-11-27 22:48:34 +00001218 /* Set aspath attribute flag. */
1219 if (as4_path)
1220 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1221
Paul Jakmab881c702010-11-23 16:35:42 +00001222 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001223}
1224
paul718e3742002-12-13 20:15:29 +00001225/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001226static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001227bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001228{
Paul Jakma835315b2012-01-18 12:28:30 +00001229 struct peer *const peer = args->peer;
1230 struct attr *const attr = args->attr;
1231 const bgp_size_t length = args->length;
1232
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001233 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001234
paul718e3742002-12-13 20:15:29 +00001235 /* Check nexthop attribute length. */
1236 if (length != 4)
1237 {
1238 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1239 length);
1240
Paul Jakma835315b2012-01-18 12:28:30 +00001241 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001242 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001243 args->total);
paul718e3742002-12-13 20:15:29 +00001244 }
1245
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001246 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1247 attribute must result in a NOTIFICATION message (this is implemented below).
1248 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1249 logged locally (this is implemented somewhere else). The UPDATE message
1250 gets ignored in any of these cases. */
1251 nexthop_n = stream_get_ipv4 (peer->ibuf);
1252 nexthop_h = ntohl (nexthop_n);
Lou Bergerf53585d2016-05-17 07:10:36 -04001253 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1254 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001255 {
1256 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001257 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001258 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001259 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001260 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001261 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001262 }
1263
1264 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001265 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1266
Paul Jakmab881c702010-11-23 16:35:42 +00001267 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001268}
1269
1270/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001271static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001272bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001273{
Paul Jakma835315b2012-01-18 12:28:30 +00001274 struct peer *const peer = args->peer;
1275 struct attr *const attr = args->attr;
1276 const bgp_size_t length = args->length;
1277
paul718e3742002-12-13 20:15:29 +00001278 /* Length check. */
1279 if (length != 4)
1280 {
1281 zlog (peer->log, LOG_ERR,
1282 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001283
Paul Jakma835315b2012-01-18 12:28:30 +00001284 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001285 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001286 args->total);
paul718e3742002-12-13 20:15:29 +00001287 }
1288
1289 attr->med = stream_getl (peer->ibuf);
1290
1291 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1292
Paul Jakmab881c702010-11-23 16:35:42 +00001293 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001294}
1295
1296/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001297static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001298bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001299{
Paul Jakma835315b2012-01-18 12:28:30 +00001300 struct peer *const peer = args->peer;
1301 struct attr *const attr = args->attr;
1302 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001303
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001304 /* Length check. */
1305 if (length != 4)
1306 {
Paul Jakma835315b2012-01-18 12:28:30 +00001307 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1308 length);
1309 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001310 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001311 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001312 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001313
paul718e3742002-12-13 20:15:29 +00001314 /* If it is contained in an UPDATE message that is received from an
1315 external peer, then this attribute MUST be ignored by the
1316 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001317 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001318 {
paul9985f832005-02-09 15:51:56 +00001319 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001320 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001321 }
1322
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001323 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001324
1325 /* Set atomic aggregate flag. */
1326 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1327
Paul Jakmab881c702010-11-23 16:35:42 +00001328 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001329}
1330
1331/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001332static int
Paul Jakma835315b2012-01-18 12:28:30 +00001333bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001334{
Paul Jakma835315b2012-01-18 12:28:30 +00001335 struct peer *const peer = args->peer;
1336 struct attr *const attr = args->attr;
1337 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001338
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001339 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001340 if (length != 0)
1341 {
Paul Jakma835315b2012-01-18 12:28:30 +00001342 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1343 length);
1344 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001345 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001346 args->total);
paul718e3742002-12-13 20:15:29 +00001347 }
1348
1349 /* Set atomic aggregate flag. */
1350 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1351
Paul Jakmab881c702010-11-23 16:35:42 +00001352 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001353}
1354
1355/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001356static int
Paul Jakma835315b2012-01-18 12:28:30 +00001357bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001358{
Paul Jakma835315b2012-01-18 12:28:30 +00001359 struct peer *const peer = args->peer;
1360 struct attr *const attr = args->attr;
1361 const bgp_size_t length = args->length;
1362
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001363 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001364 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001365
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001366 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001367 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001368 wantedlen = 8;
1369
1370 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001371 {
Paul Jakma835315b2012-01-18 12:28:30 +00001372 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1373 wantedlen, length);
1374 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001375 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001376 args->total);
paul718e3742002-12-13 20:15:29 +00001377 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001378
1379 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1380 attre->aggregator_as = stream_getl (peer->ibuf);
1381 else
1382 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001383 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001384
1385 /* Set atomic aggregate flag. */
1386 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1387
Paul Jakmab881c702010-11-23 16:35:42 +00001388 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001389}
1390
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001391/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001392static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001393bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1394 as_t *as4_aggregator_as,
1395 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001396{
Paul Jakma835315b2012-01-18 12:28:30 +00001397 struct peer *const peer = args->peer;
1398 struct attr *const attr = args->attr;
1399 const bgp_size_t length = args->length;
1400
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001401 if (length != 8)
1402 {
Paul Jakma835315b2012-01-18 12:28:30 +00001403 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1404 length);
1405 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001406 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001407 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001408 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001409
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001410 *as4_aggregator_as = stream_getl (peer->ibuf);
1411 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1412
1413 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1414
Paul Jakmab881c702010-11-23 16:35:42 +00001415 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001416}
1417
1418/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1419 */
Paul Jakmab881c702010-11-23 16:35:42 +00001420static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001421bgp_attr_munge_as4_attrs (struct peer *const peer,
1422 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001423 struct aspath *as4_path, as_t as4_aggregator,
1424 struct in_addr *as4_aggregator_addr)
1425{
1426 int ignore_as4_path = 0;
1427 struct aspath *newpath;
1428 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001429
1430 if (!attr->aspath)
1431 {
1432 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1433 * checked that all well-known, mandatory attributes were present.
1434 *
1435 * Can only be a problem with peer itself - hard error
1436 */
1437 return BGP_ATTR_PARSE_ERROR;
1438 }
1439
Paul Jakmab881c702010-11-23 16:35:42 +00001440 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001441 {
1442 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1443 * if given.
1444 * It is worth a warning though, because the peer really
1445 * should not send them
1446 */
1447 if (BGP_DEBUG(as4, AS4))
1448 {
1449 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1450 zlog_debug ("[AS4] %s %s AS4_PATH",
1451 peer->host, "AS4 capable peer, yet it sent");
1452
1453 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1454 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1455 peer->host, "AS4 capable peer, yet it sent");
1456 }
1457
Paul Jakmab881c702010-11-23 16:35:42 +00001458 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001459 }
1460
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001461 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1462 * because that may override AS4_PATH
1463 */
1464 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1465 {
Paul Jakmab881c702010-11-23 16:35:42 +00001466 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001467 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001468 assert (attre);
1469
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001470 /* received both.
1471 * if the as_number in aggregator is not AS_TRANS,
1472 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1473 * and the Aggregator shall be taken as
1474 * info on the aggregating node, and the AS_PATH
1475 * shall be taken as the AS_PATH
1476 * otherwise
1477 * the Aggregator shall be ignored and the
1478 * AS4_AGGREGATOR shall be taken as the
1479 * Aggregating node and the AS_PATH is to be
1480 * constructed "as in all other cases"
1481 */
Paul Jakmab881c702010-11-23 16:35:42 +00001482 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001483 {
1484 /* ignore */
1485 if ( BGP_DEBUG(as4, AS4))
1486 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1487 " send AGGREGATOR != AS_TRANS and"
1488 " AS4_AGGREGATOR, so ignore"
1489 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1490 ignore_as4_path = 1;
1491 }
1492 else
1493 {
1494 /* "New_aggregator shall be taken as aggregator" */
1495 attre->aggregator_as = as4_aggregator;
1496 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1497 }
1498 }
1499 else
1500 {
1501 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1502 * That is bogus - but reading the conditions
1503 * we have to handle AS4_AGGREGATOR as if it were
1504 * AGGREGATOR in that case
1505 */
1506 if ( BGP_DEBUG(as4, AS4))
1507 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1508 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1509 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001510 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001511 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1512 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1513 }
1514 }
1515
1516 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001517 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001518 {
Paul Jakma055086f2014-09-23 15:23:01 +01001519 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1520 aspath_unintern (&attr->aspath);
1521 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001522 }
Paul Jakmab881c702010-11-23 16:35:42 +00001523 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001524}
1525
paul718e3742002-12-13 20:15:29 +00001526/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001527static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001528bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001529{
Paul Jakma835315b2012-01-18 12:28:30 +00001530 struct peer *const peer = args->peer;
1531 struct attr *const attr = args->attr;
1532 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001533
paul718e3742002-12-13 20:15:29 +00001534 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001535 {
1536 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001537 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001538 }
Paul Jakma0c466382010-12-05 17:17:26 +00001539
1540 attr->community =
1541 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1542
1543 /* XXX: fix community_parse to use stream API and remove this */
1544 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001545
Paul Jakma0c466382010-12-05 17:17:26 +00001546 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001547 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001548 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001549 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001550
paul718e3742002-12-13 20:15:29 +00001551 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1552
Paul Jakmab881c702010-11-23 16:35:42 +00001553 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001554}
1555
1556/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001557static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001558bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001559{
Paul Jakma835315b2012-01-18 12:28:30 +00001560 struct peer *const peer = args->peer;
1561 struct attr *const attr = args->attr;
1562 const bgp_size_t length = args->length;
1563
Denis Ovsienkod595b562011-09-30 15:08:54 +04001564 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001565 if (length != 4)
1566 {
1567 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1568
Paul Jakma835315b2012-01-18 12:28:30 +00001569 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001570 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001571 args->total);
paul718e3742002-12-13 20:15:29 +00001572 }
1573
Paul Jakmafb982c22007-05-04 20:15:47 +00001574 (bgp_attr_extra_get (attr))->originator_id.s_addr
1575 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001576
1577 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1578
Paul Jakmab881c702010-11-23 16:35:42 +00001579 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001580}
1581
1582/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001583static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001584bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001585{
Paul Jakma835315b2012-01-18 12:28:30 +00001586 struct peer *const peer = args->peer;
1587 struct attr *const attr = args->attr;
1588 const bgp_size_t length = args->length;
1589
paul718e3742002-12-13 20:15:29 +00001590 /* Check length. */
1591 if (length % 4)
1592 {
1593 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1594
Paul Jakma835315b2012-01-18 12:28:30 +00001595 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1596 args->total);
paul718e3742002-12-13 20:15:29 +00001597 }
1598
Paul Jakmafb982c22007-05-04 20:15:47 +00001599 (bgp_attr_extra_get (attr))->cluster
1600 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001601
1602 /* XXX: Fix cluster_parse to use stream API and then remove this */
1603 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001604
1605 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1606
Paul Jakmab881c702010-11-23 16:35:42 +00001607 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001608}
1609
1610/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001611int
Paul Jakma835315b2012-01-18 12:28:30 +00001612bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1613 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001614{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001615 afi_t afi;
1616 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001617 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001618 size_t start;
paul718e3742002-12-13 20:15:29 +00001619 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001620 struct peer *const peer = args->peer;
1621 struct attr *const attr = args->attr;
1622 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001623 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001624
paul718e3742002-12-13 20:15:29 +00001625 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001626 s = BGP_INPUT(peer);
1627 start = stream_get_getp(s);
1628
1629 /* safe to read statically sized header? */
1630#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001631#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001632 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001633 {
1634 zlog_info ("%s: %s sent invalid length, %lu",
1635 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001636 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001637 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001638
paul718e3742002-12-13 20:15:29 +00001639 /* Load AFI, SAFI. */
1640 afi = stream_getw (s);
1641 safi = stream_getc (s);
1642
1643 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001644 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001645
Paul Jakma03292802008-06-07 20:37:10 +00001646 if (LEN_LEFT < attre->mp_nexthop_len)
1647 {
1648 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1649 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001650 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001651 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001652
paul718e3742002-12-13 20:15:29 +00001653 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001654 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001655 {
1656 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001657 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001658 /* Probably needed for RFC 2283 */
1659 if (attr->nexthop.s_addr == 0)
1660 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001661 break;
1662 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001663 stream_getl (s); /* RD high */
1664 stream_getl (s); /* RD low */
1665 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001666 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001667 case 24:
1668 {
1669 u_int32_t rd_high __attribute__((unused));
1670 u_int32_t rd_low __attribute__((unused));
1671
1672 rd_high = stream_getl (s);
1673 rd_low = stream_getl (s);
1674 }
1675 /* fall through */
paul718e3742002-12-13 20:15:29 +00001676 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001677 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001678 break;
1679 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001680 case 48:
1681 if (attre->mp_nexthop_len == 48) {
1682 u_int32_t rd_high __attribute__((unused));
1683 u_int32_t rd_low __attribute__((unused));
1684
1685 rd_high = stream_getl (s);
1686 rd_low = stream_getl (s);
1687 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001688 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001689
1690 if (attre->mp_nexthop_len == 48) {
1691 u_int32_t rd_high __attribute__((unused));
1692 u_int32_t rd_low __attribute__((unused));
1693
1694 rd_high = stream_getl (s);
1695 rd_low = stream_getl (s);
1696 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001697 stream_get (&attre->mp_nexthop_local, s, 16);
1698 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001699 {
1700 char buf1[INET6_ADDRSTRLEN];
1701 char buf2[INET6_ADDRSTRLEN];
1702
1703 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001704 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 +00001705 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001706 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001707 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001708 buf2, INET6_ADDRSTRLEN));
1709
Paul Jakmafb982c22007-05-04 20:15:47 +00001710 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001711 }
1712 break;
paul718e3742002-12-13 20:15:29 +00001713 default:
Paul Jakma03292802008-06-07 20:37:10 +00001714 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1715 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001716 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001717 }
1718
Paul Jakma03292802008-06-07 20:37:10 +00001719 if (!LEN_LEFT)
1720 {
1721 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1722 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001723 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001724 }
paul718e3742002-12-13 20:15:29 +00001725
Paul Jakma6e4ab122007-04-10 19:36:48 +00001726 {
1727 u_char val;
1728 if ((val = stream_getc (s)))
1729 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1730 peer->host, val);
1731 }
1732
1733 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001734 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001735 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001736 {
1737 zlog_info ("%s: (%s) Failed to read NLRI",
1738 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001739 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001740 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001741
paul718e3742002-12-13 20:15:29 +00001742 mp_update->afi = afi;
1743 mp_update->safi = safi;
1744 mp_update->nlri = stream_pnt (s);
1745 mp_update->length = nlri_len;
1746
paul9985f832005-02-09 15:51:56 +00001747 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001748
David Lamparterdaefeb82014-12-08 17:42:12 +01001749 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1750
Paul Jakmab881c702010-11-23 16:35:42 +00001751 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001752#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001753}
1754
1755/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001756int
Paul Jakma835315b2012-01-18 12:28:30 +00001757bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001758 struct bgp_nlri *mp_withdraw)
1759{
1760 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001761 afi_t afi;
1762 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001763 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001764 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001765 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001766 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001767
1768 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001769
1770#define BGP_MP_UNREACH_MIN_SIZE 3
1771 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001772 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001773
paul718e3742002-12-13 20:15:29 +00001774 afi = stream_getw (s);
1775 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001776
1777 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001778
paul718e3742002-12-13 20:15:29 +00001779 mp_withdraw->afi = afi;
1780 mp_withdraw->safi = safi;
1781 mp_withdraw->nlri = stream_pnt (s);
1782 mp_withdraw->length = withdraw_len;
1783
paul9985f832005-02-09 15:51:56 +00001784 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001785
David Lamparterdaefeb82014-12-08 17:42:12 +01001786 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1787
Paul Jakmab881c702010-11-23 16:35:42 +00001788 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001789}
1790
1791/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001792static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001793bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001794{
Paul Jakma835315b2012-01-18 12:28:30 +00001795 struct peer *const peer = args->peer;
1796 struct attr *const attr = args->attr;
1797 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001798
paul718e3742002-12-13 20:15:29 +00001799 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001800 {
1801 if (attr->extra)
1802 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001803 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001804 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001805 }
Paul Jakma0c466382010-12-05 17:17:26 +00001806
1807 (bgp_attr_extra_get (attr))->ecommunity =
1808 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1809 /* XXX: fix ecommunity_parse to use stream API */
1810 stream_forward_getp (peer->ibuf, length);
1811
1812 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001813 return bgp_attr_malformed (args,
1814 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1815 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001816
paul718e3742002-12-13 20:15:29 +00001817 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1818
Paul Jakmab881c702010-11-23 16:35:42 +00001819 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001820}
1821
Lou Bergerc3741782016-01-12 13:42:01 -05001822/* Parse Tunnel Encap attribute in an UPDATE */
1823static int
1824bgp_attr_encap(
1825 uint8_t type,
1826 struct peer *peer, /* IN */
1827 bgp_size_t length, /* IN: attr's length field */
1828 struct attr *attr, /* IN: caller already allocated */
1829 u_char flag, /* IN: attr's flags field */
1830 u_char *startp)
1831{
1832 bgp_size_t total;
1833 struct attr_extra *attre = NULL;
1834 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1835 uint16_t tunneltype;
1836
1837 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1838
1839 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1840 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1841 {
1842 zlog (peer->log, LOG_ERR,
1843 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1844 bgp_notify_send_with_data (peer,
1845 BGP_NOTIFY_UPDATE_ERR,
1846 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1847 startp, total);
1848 return -1;
1849 }
1850
1851 if (BGP_ATTR_ENCAP == type) {
1852 /* read outer TLV type and length */
1853 uint16_t tlv_length;
1854
1855 if (length < 4) {
1856 zlog (peer->log, LOG_ERR,
1857 "Tunnel Encap attribute not long enough to contain outer T,L");
1858 bgp_notify_send_with_data(peer,
1859 BGP_NOTIFY_UPDATE_ERR,
1860 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1861 startp, total);
1862 return -1;
1863 }
1864 tunneltype = stream_getw (BGP_INPUT (peer));
1865 tlv_length = stream_getw (BGP_INPUT (peer));
1866 length -= 4;
1867
1868 if (tlv_length != length) {
1869 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1870 __func__, tlv_length, length);
1871 }
1872 }
1873
1874 while (length >= 4) {
Donald Sharp985c3552016-03-10 20:16:47 -05001875 uint16_t subtype = 0;
1876 uint16_t sublength = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05001877 struct bgp_attr_encap_subtlv *tlv;
1878
Lou Berger298cc2f2016-01-12 13:42:02 -05001879 if (BGP_ATTR_ENCAP == type) {
1880 subtype = stream_getc (BGP_INPUT (peer));
1881 sublength = stream_getc (BGP_INPUT (peer));
1882 length -= 2;
1883 }
Lou Bergerc3741782016-01-12 13:42:01 -05001884
1885 if (sublength > length) {
1886 zlog (peer->log, LOG_ERR,
1887 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1888 sublength, length);
1889 bgp_notify_send_with_data (peer,
1890 BGP_NOTIFY_UPDATE_ERR,
1891 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1892 startp, total);
1893 return -1;
1894 }
1895
1896 /* alloc and copy sub-tlv */
1897 /* TBD make sure these are freed when attributes are released */
1898 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1899 tlv->type = subtype;
1900 tlv->length = sublength;
1901 stream_get(tlv->value, peer->ibuf, sublength);
1902 length -= sublength;
1903
1904 /* attach tlv to encap chain */
1905 if (!attre) {
1906 attre = bgp_attr_extra_get(attr);
1907 if (BGP_ATTR_ENCAP == type) {
1908 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1909 stlv_last = stlv_last->next);
1910 if (stlv_last) {
1911 stlv_last->next = tlv;
1912 } else {
1913 attre->encap_subtlvs = tlv;
1914 }
1915 }
1916 } else {
1917 stlv_last->next = tlv;
1918 }
1919 stlv_last = tlv;
1920 }
1921
1922 if (attre && (BGP_ATTR_ENCAP == type)) {
1923 attre->encap_tunneltype = tunneltype;
1924 }
1925
1926 if (length) {
1927 /* spurious leftover data */
1928 zlog (peer->log, LOG_ERR,
1929 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1930 bgp_notify_send_with_data (peer,
1931 BGP_NOTIFY_UPDATE_ERR,
1932 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1933 startp, total);
1934 return -1;
1935 }
1936
1937 return 0;
1938}
1939
paul718e3742002-12-13 20:15:29 +00001940/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001941static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001942bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001943{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001944 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001945 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001946 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001947 struct peer *const peer = args->peer;
1948 struct attr *const attr = args->attr;
1949 u_char *const startp = args->startp;
1950 const u_char type = args->type;
1951 const u_char flag = args->flags;
1952 const bgp_size_t length = args->length;
1953
paul718e3742002-12-13 20:15:29 +00001954
hassof4184462005-02-01 20:13:16 +00001955 if (BGP_DEBUG (normal, NORMAL))
1956 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1957 peer->host, type, length);
1958
paul718e3742002-12-13 20:15:29 +00001959 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001960 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001961 "Unknown attribute type %d length %d is received", type, length);
1962
1963 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001964 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001965
paul718e3742002-12-13 20:15:29 +00001966 /* If any of the mandatory well-known attributes are not recognized,
1967 then the Error Subcode is set to Unrecognized Well-known
1968 Attribute. The Data field contains the unrecognized attribute
1969 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001970 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001971 {
Paul Jakma835315b2012-01-18 12:28:30 +00001972 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001973 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001974 args->total);
paul718e3742002-12-13 20:15:29 +00001975 }
1976
1977 /* Unrecognized non-transitive optional attributes must be quietly
1978 ignored and not passed along to other BGP peers. */
1979 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001980 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001981
1982 /* If a path with recognized transitive optional attribute is
1983 accepted and passed along to other BGP peers and the Partial bit
1984 in the Attribute Flags octet is set to 1 by some previous AS, it
1985 is not set back to 0 by the current AS. */
1986 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1987
1988 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001989 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001990 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001991
Paul Jakmafb982c22007-05-04 20:15:47 +00001992 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001993
1994 if (transit->val)
1995 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1996 transit->length + total);
1997 else
1998 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1999
2000 memcpy (transit->val + transit->length, startp, total);
2001 transit->length += total;
2002
Paul Jakmab881c702010-11-23 16:35:42 +00002003 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002004}
2005
Paul Jakma055086f2014-09-23 15:23:01 +01002006/* Well-known attribute check. */
2007static int
2008bgp_attr_check (struct peer *peer, struct attr *attr)
2009{
2010 u_char type = 0;
2011
Paul Jakmaaed1b552014-10-21 16:59:01 +01002012 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2013 * empty UPDATE. */
2014 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2015 return BGP_ATTR_PARSE_PROCEED;
2016
2017 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2018 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2019 are present, it should. Check for any other attribute being present
2020 instead.
2021 */
2022 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2023 return BGP_ATTR_PARSE_PROCEED;
2024
Paul Jakma055086f2014-09-23 15:23:01 +01002025 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2026 type = BGP_ATTR_ORIGIN;
2027
2028 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2029 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002030
2031 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2032 * NLRI is empty. We can't easily check NLRI empty here though.
2033 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002034 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2035 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002036 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002037
Paul Jakma055086f2014-09-23 15:23:01 +01002038 if (peer->sort == BGP_PEER_IBGP
2039 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2040 type = BGP_ATTR_LOCAL_PREF;
2041
2042 if (type)
2043 {
2044 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002045 "%s Missing well-known attribute %d / %s",
2046 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002047 bgp_notify_send_with_data (peer,
2048 BGP_NOTIFY_UPDATE_ERR,
2049 BGP_NOTIFY_UPDATE_MISS_ATTR,
2050 &type, 1);
2051 return BGP_ATTR_PARSE_ERROR;
2052 }
2053 return BGP_ATTR_PARSE_PROCEED;
2054}
2055
paul718e3742002-12-13 20:15:29 +00002056/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002057 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002058bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002059bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2060 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2061{
2062 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002063 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002064 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002065 bgp_size_t length;
2066 u_char *startp, *endp;
2067 u_char *attr_endp;
2068 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002069 /* we need the as4_path only until we have synthesized the as_path with it */
2070 /* same goes for as4_aggregator */
2071 struct aspath *as4_path = NULL;
2072 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002073 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002074
2075 /* Initialize bitmap. */
2076 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2077
2078 /* End pointer of BGP attribute. */
2079 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002080
paul718e3742002-12-13 20:15:29 +00002081 /* Get attributes to the end of attribute length. */
2082 while (BGP_INPUT_PNT (peer) < endp)
2083 {
2084 /* Check remaining length check.*/
2085 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2086 {
gdtc29fdba2004-12-09 14:46:46 +00002087 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002088 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002089 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002090 peer->host,
2091 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002092
2093 bgp_notify_send (peer,
2094 BGP_NOTIFY_UPDATE_ERR,
2095 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002096 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002097 }
2098
2099 /* Fetch attribute flag and type. */
2100 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002101 /* "The lower-order four bits of the Attribute Flags octet are
2102 unused. They MUST be zero when sent and MUST be ignored when
2103 received." */
2104 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002105 type = stream_getc (BGP_INPUT (peer));
2106
Paul Jakma370b64a2007-12-22 16:49:52 +00002107 /* Check whether Extended-Length applies and is in bounds */
2108 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2109 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2110 {
2111 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002112 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002113 peer->host,
2114 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2115
2116 bgp_notify_send (peer,
2117 BGP_NOTIFY_UPDATE_ERR,
2118 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002119 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002120 }
Paul Jakma835315b2012-01-18 12:28:30 +00002121
paul718e3742002-12-13 20:15:29 +00002122 /* Check extended attribue length bit. */
2123 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2124 length = stream_getw (BGP_INPUT (peer));
2125 else
2126 length = stream_getc (BGP_INPUT (peer));
2127
2128 /* If any attribute appears more than once in the UPDATE
2129 message, then the Error Subcode is set to Malformed Attribute
2130 List. */
2131
2132 if (CHECK_BITMAP (seen, type))
2133 {
2134 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002135 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002136 peer->host, type);
2137
2138 bgp_notify_send (peer,
2139 BGP_NOTIFY_UPDATE_ERR,
2140 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002141 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002142 }
2143
2144 /* Set type to bitmap to check duplicate attribute. `type' is
2145 unsigned char so it never overflow bitmap range. */
2146
2147 SET_BITMAP (seen, type);
2148
2149 /* Overflow check. */
2150 attr_endp = BGP_INPUT_PNT (peer) + length;
2151
2152 if (attr_endp > endp)
2153 {
2154 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002155 "%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 +00002156 bgp_notify_send (peer,
2157 BGP_NOTIFY_UPDATE_ERR,
2158 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002159 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002160 }
Paul Jakma835315b2012-01-18 12:28:30 +00002161
2162 struct bgp_attr_parser_args attr_args = {
2163 .peer = peer,
2164 .length = length,
2165 .attr = attr,
2166 .type = type,
2167 .flags = flag,
2168 .startp = startp,
2169 .total = attr_endp - startp,
2170 };
2171
2172
2173 /* If any recognized attribute has Attribute Flags that conflict
2174 with the Attribute Type Code, then the Error Subcode is set to
2175 Attribute Flags Error. The Data field contains the erroneous
2176 attribute (type, length and value). */
2177 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002178 {
2179 bgp_attr_parse_ret_t ret;
2180 ret = bgp_attr_malformed (&attr_args,
2181 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2182 attr_args.total);
2183 if (ret == BGP_ATTR_PARSE_PROCEED)
2184 continue;
2185 return ret;
2186 }
paul718e3742002-12-13 20:15:29 +00002187
2188 /* OK check attribute and store it's value. */
2189 switch (type)
2190 {
2191 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002192 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002193 break;
2194 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002195 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002196 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002197 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002198 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002199 break;
paul718e3742002-12-13 20:15:29 +00002200 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002201 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002202 break;
2203 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002204 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002205 break;
2206 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002207 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002208 break;
2209 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002210 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002211 break;
2212 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002213 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002214 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002215 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002216 ret = bgp_attr_as4_aggregator (&attr_args,
2217 &as4_aggregator,
2218 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002219 break;
paul718e3742002-12-13 20:15:29 +00002220 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002221 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002222 break;
2223 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002224 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002225 break;
2226 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002227 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002228 break;
2229 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002230 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002231 break;
2232 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002233 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002234 break;
2235 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002236 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002237 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002238 case BGP_ATTR_ENCAP:
2239 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2240 break;
paul718e3742002-12-13 20:15:29 +00002241 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002242 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002243 break;
2244 }
Paul Jakmab881c702010-11-23 16:35:42 +00002245
David Lamparterf57000c2014-06-04 01:01:10 +02002246 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2247 {
2248 bgp_notify_send (peer,
2249 BGP_NOTIFY_UPDATE_ERR,
2250 BGP_NOTIFY_UPDATE_MAL_ATTR);
2251 ret = BGP_ATTR_PARSE_ERROR;
2252 }
2253
Paul Jakmab881c702010-11-23 16:35:42 +00002254 /* If hard error occured immediately return to the caller. */
2255 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002256 {
2257 zlog (peer->log, LOG_WARNING,
2258 "%s: Attribute %s, parse error",
2259 peer->host,
2260 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002261 if (as4_path)
2262 aspath_unintern (&as4_path);
2263 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002264 }
Paul Jakmab881c702010-11-23 16:35:42 +00002265 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2266 {
2267
2268 zlog (peer->log, LOG_WARNING,
2269 "%s: Attribute %s, parse error - treating as withdrawal",
2270 peer->host,
2271 LOOKUP (attr_str, type));
2272 if (as4_path)
2273 aspath_unintern (&as4_path);
2274 return ret;
2275 }
2276
paul718e3742002-12-13 20:15:29 +00002277 /* Check the fetched length. */
2278 if (BGP_INPUT_PNT (peer) != attr_endp)
2279 {
2280 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002281 "%s: BGP attribute %s, fetch error",
2282 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002283 bgp_notify_send (peer,
2284 BGP_NOTIFY_UPDATE_ERR,
2285 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002286 if (as4_path)
2287 aspath_unintern (&as4_path);
2288 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002289 }
2290 }
paul718e3742002-12-13 20:15:29 +00002291 /* Check final read pointer is same as end pointer. */
2292 if (BGP_INPUT_PNT (peer) != endp)
2293 {
2294 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002295 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002296 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002297 bgp_notify_send (peer,
2298 BGP_NOTIFY_UPDATE_ERR,
2299 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002300 if (as4_path)
2301 aspath_unintern (&as4_path);
2302 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002303 }
Paul Jakma055086f2014-09-23 15:23:01 +01002304
2305 /* Check all mandatory well-known attributes are present */
2306 {
2307 bgp_attr_parse_ret_t ret;
2308 if ((ret = bgp_attr_check (peer, attr)) < 0)
2309 {
2310 if (as4_path)
2311 aspath_unintern (&as4_path);
2312 return ret;
2313 }
2314 }
2315
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002316 /*
2317 * At this place we can see whether we got AS4_PATH and/or
2318 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2319 * We can not do this before we've read all attributes because
2320 * the as4 handling does not say whether AS4_PATH has to be sent
2321 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2322 * in relationship to AGGREGATOR.
2323 * So, to be defensive, we are not relying on any order and read
2324 * all attributes first, including these 32bit ones, and now,
2325 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002326 *
2327 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2328 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002329 */
David Lamparterf57000c2014-06-04 01:01:10 +02002330 /* actually... this doesn't ever return failure currently, but
2331 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002332 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2333 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002334 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002335 {
David Lamparterf57000c2014-06-04 01:01:10 +02002336 bgp_notify_send (peer,
2337 BGP_NOTIFY_UPDATE_ERR,
2338 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002339 if (as4_path)
2340 aspath_unintern (&as4_path);
2341 return BGP_ATTR_PARSE_ERROR;
2342 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002343
2344 /* At this stage, we have done all fiddling with as4, and the
2345 * resulting info is in attr->aggregator resp. attr->aspath
2346 * so we can chuck as4_aggregator and as4_path alltogether in
2347 * order to save memory
2348 */
Paul Jakmab881c702010-11-23 16:35:42 +00002349 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002350 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002351 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002352 /* The flag that we got this is still there, but that does not
2353 * do any trouble
2354 */
2355 }
2356 /*
2357 * The "rest" of the code does nothing with as4_aggregator.
2358 * there is no memory attached specifically which is not part
2359 * of the attr.
2360 * so ignoring just means do nothing.
2361 */
2362 /*
2363 * Finally do the checks on the aspath we did not do yet
2364 * because we waited for a potentially synthesized aspath.
2365 */
Paul Jakmab881c702010-11-23 16:35:42 +00002366 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002367 {
Paul Jakma835315b2012-01-18 12:28:30 +00002368 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002369 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002370 return ret;
2371 }
2372
paul718e3742002-12-13 20:15:29 +00002373 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002374 if (attr->extra && attr->extra->transit)
2375 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002376
Paul Jakmab881c702010-11-23 16:35:42 +00002377 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002378}
2379
paul718e3742002-12-13 20:15:29 +00002380int stream_put_prefix (struct stream *, struct prefix *);
2381
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002382size_t
2383bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2384 struct attr *attr)
2385{
2386 size_t sizep;
2387
2388 /* Set extended bit always to encode the attribute length as 2 bytes */
2389 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2390 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2391 sizep = stream_get_endp (s);
2392 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002393
2394 stream_putw (s, afi);
2395 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002396
2397 /* Nexthop */
2398 switch (afi)
2399 {
2400 case AFI_IP:
2401 switch (safi)
2402 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002403 case SAFI_MULTICAST:
2404 stream_putc (s, 4);
2405 stream_put_ipv4 (s, attr->nexthop.s_addr);
2406 break;
2407 case SAFI_MPLS_VPN:
2408 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002409 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002410 stream_putl (s, 0);
2411 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2412 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002413 case SAFI_ENCAP:
2414 stream_putc (s, 4);
2415 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2416 break;
Lou Berger050defe2016-01-12 13:41:59 -05002417 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002418 default:
2419 break;
2420 }
2421 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002422 case AFI_IP6:
2423 switch (safi)
2424 {
2425 case SAFI_UNICAST:
2426 case SAFI_MULTICAST:
2427 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002428 struct attr_extra *attre = attr->extra;
2429
2430 assert (attr->extra);
2431 stream_putc (s, attre->mp_nexthop_len);
2432 stream_put (s, &attre->mp_nexthop_global, 16);
2433 if (attre->mp_nexthop_len == 32)
2434 stream_put (s, &attre->mp_nexthop_local, 16);
2435 }
Lou Berger050defe2016-01-12 13:41:59 -05002436 break;
2437 case SAFI_MPLS_VPN:
2438 {
2439 struct attr_extra *attre = attr->extra;
2440
2441 assert (attr->extra);
2442 if (attre->mp_nexthop_len == 16) {
2443 stream_putc (s, 24);
2444 stream_putl (s, 0); /* RD = 0, per RFC */
2445 stream_putl (s, 0);
2446 stream_put (s, &attre->mp_nexthop_global, 16);
2447 } else if (attre->mp_nexthop_len == 32) {
2448 stream_putc (s, 48);
2449 stream_putl (s, 0); /* RD = 0, per RFC */
2450 stream_putl (s, 0);
2451 stream_put (s, &attre->mp_nexthop_global, 16);
2452 stream_putl (s, 0); /* RD = 0, per RFC */
2453 stream_putl (s, 0);
2454 stream_put (s, &attre->mp_nexthop_local, 16);
2455 }
2456 }
2457 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002458 case SAFI_ENCAP:
2459 assert (attr->extra);
2460 stream_putc (s, 16);
2461 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2462 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002463 default:
2464 break;
2465 }
2466 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002467 default:
2468 break;
2469 }
2470
2471 /* SNPA */
2472 stream_putc (s, 0);
2473 return sizep;
2474}
2475
2476void
2477bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2478 struct prefix *p, struct prefix_rd *prd,
2479 u_char *tag)
2480{
Lou Berger050defe2016-01-12 13:41:59 -05002481 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002482 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002483 /* Tag, RD, Prefix write. */
2484 stream_putc (s, p->prefixlen + 88);
2485 stream_put (s, tag, 3);
2486 stream_put (s, prd->val, 8);
2487 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002488 }
Lou Berger050defe2016-01-12 13:41:59 -05002489 else
2490 stream_put_prefix (s, p);
2491}
2492
2493size_t
2494bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2495{
2496 int size = PSIZE (p->prefixlen);
2497 if (safi == SAFI_MPLS_VPN)
2498 size += 88;
2499 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002500}
2501
Lou Bergerc3741782016-01-12 13:42:01 -05002502/*
2503 * Encodes the tunnel encapsulation attribute
2504 */
2505static void
2506bgp_packet_mpattr_tea(
2507 struct bgp *bgp,
2508 struct peer *peer,
2509 struct stream *s,
2510 struct attr *attr,
2511 uint8_t attrtype)
2512{
2513 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002514 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002515 struct bgp_attr_encap_subtlv *subtlvs;
2516 struct bgp_attr_encap_subtlv *st;
2517 const char *attrname;
2518
2519 if (!attr || !attr->extra)
2520 return;
2521
2522 switch (attrtype) {
2523 case BGP_ATTR_ENCAP:
2524 attrname = "Tunnel Encap";
2525 subtlvs = attr->extra->encap_subtlvs;
2526
2527 /*
2528 * The tunnel encap attr has an "outer" tlv.
2529 * T = tunneltype,
2530 * L = total length of subtlvs,
2531 * V = concatenated subtlvs.
2532 */
2533 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002534 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002535 break;
2536
2537 default:
2538 assert(0);
2539 }
2540
2541
Lou Berger298cc2f2016-01-12 13:42:02 -05002542 /* if no tlvs, don't make attr */
2543 if (subtlvs == NULL)
2544 return;
2545
Lou Bergerc3741782016-01-12 13:42:01 -05002546 /* compute attr length */
2547 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002548 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002549 }
2550
Lou Bergerc3741782016-01-12 13:42:01 -05002551 if (attrlenfield > 0xffff) {
2552 zlog (peer->log, LOG_ERR,
2553 "%s attribute is too long (length=%d), can't send it",
2554 attrname,
2555 attrlenfield);
2556 return;
2557 }
2558
2559 if (attrlenfield > 0xff) {
2560 /* 2-octet length field */
2561 stream_putc (s,
2562 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2563 stream_putc (s, attrtype);
2564 stream_putw (s, attrlenfield & 0xffff);
2565 } else {
2566 /* 1-octet length field */
2567 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2568 stream_putc (s, attrtype);
2569 stream_putc (s, attrlenfield & 0xff);
2570 }
2571
2572 if (attrtype == BGP_ATTR_ENCAP) {
2573 /* write outer T+L */
2574 stream_putw(s, attr->extra->encap_tunneltype);
2575 stream_putw(s, attrlenfield - 4);
2576 }
2577
2578 /* write each sub-tlv */
2579 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002580 if (attrtype == BGP_ATTR_ENCAP) {
2581 stream_putc (s, st->type);
2582 stream_putc (s, st->length);
2583 }
Lou Bergerc3741782016-01-12 13:42:01 -05002584 stream_put (s, st->value, st->length);
2585 }
2586}
2587
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002588void
2589bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2590{
2591 /* Set MP attribute length. Don't count the (2) bytes used to encode
2592 the attr length */
2593 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2594}
2595
paul718e3742002-12-13 20:15:29 +00002596/* Make attribute packet. */
2597bgp_size_t
2598bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002599 struct stream *s, struct attr *attr,
2600 struct prefix *p, afi_t afi, safi_t safi,
2601 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002602{
paulfe69a502005-09-10 16:55:02 +00002603 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002604 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002605 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002606 int send_as4_path = 0;
2607 int send_as4_aggregator = 0;
2608 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002609
2610 if (! bgp)
2611 bgp = bgp_get_default ();
2612
2613 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002614 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002615
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002616 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2617 {
Lou Berger050defe2016-01-12 13:41:59 -05002618 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002619 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2620 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2621 bgp_packet_mpattr_end(s, mpattrlen_pos);
2622 }
2623
paul718e3742002-12-13 20:15:29 +00002624 /* Origin attribute. */
2625 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2626 stream_putc (s, BGP_ATTR_ORIGIN);
2627 stream_putc (s, 1);
2628 stream_putc (s, attr->origin);
2629
2630 /* AS path attribute. */
2631
2632 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002633 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002634 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002635 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002636 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002637 {
2638 aspath = aspath_dup (attr->aspath);
2639
2640 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2641 {
2642 /* Strip the confed info, and then stuff our path CONFED_ID
2643 on the front */
2644 aspath = aspath_delete_confed_seq (aspath);
2645 aspath = aspath_add_seq (aspath, bgp->confed_id);
2646 }
2647 else
2648 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002649 if (peer->change_local_as) {
2650 /* If replace-as is specified, we only use the change_local_as when
2651 advertising routes. */
2652 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2653 aspath = aspath_add_seq (aspath, peer->local_as);
2654 }
paul718e3742002-12-13 20:15:29 +00002655 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002656 } else {
2657 aspath = aspath_add_seq (aspath, peer->local_as);
2658 }
paul718e3742002-12-13 20:15:29 +00002659 }
2660 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002661 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002662 {
2663 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2664 aspath = aspath_dup (attr->aspath);
2665 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2666 }
2667 else
2668 aspath = attr->aspath;
2669
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002670 /* If peer is not AS4 capable, then:
2671 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2672 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2673 * types are in it (i.e. exclude them if they are there)
2674 * AND do this only if there is at least one asnum > 65535 in the path!
2675 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2676 * all ASnums > 65535 to BGP_AS_TRANS
2677 */
paul718e3742002-12-13 20:15:29 +00002678
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002679 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2680 stream_putc (s, BGP_ATTR_AS_PATH);
2681 aspath_sizep = stream_get_endp (s);
2682 stream_putw (s, 0);
2683 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2684
2685 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2686 * in the path
2687 */
2688 if (!use32bit && aspath_has_as4 (aspath))
2689 send_as4_path = 1; /* we'll do this later, at the correct place */
2690
paul718e3742002-12-13 20:15:29 +00002691 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002692 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2693 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002694 {
2695 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2696 stream_putc (s, BGP_ATTR_NEXT_HOP);
2697 stream_putc (s, 4);
2698 if (safi == SAFI_MPLS_VPN)
2699 {
2700 if (attr->nexthop.s_addr == 0)
2701 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2702 else
2703 stream_put_ipv4 (s, attr->nexthop.s_addr);
2704 }
2705 else
2706 stream_put_ipv4 (s, attr->nexthop.s_addr);
2707 }
2708
2709 /* MED attribute. */
2710 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2711 {
2712 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2713 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2714 stream_putc (s, 4);
2715 stream_putl (s, attr->med);
2716 }
2717
2718 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002719 if (peer->sort == BGP_PEER_IBGP ||
2720 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002721 {
2722 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2723 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2724 stream_putc (s, 4);
2725 stream_putl (s, attr->local_pref);
2726 }
2727
2728 /* Atomic aggregate. */
2729 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2730 {
2731 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2732 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2733 stream_putc (s, 0);
2734 }
2735
2736 /* Aggregator. */
2737 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2738 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002739 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002740
2741 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002742 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2743 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002744
2745 if (use32bit)
2746 {
2747 /* AS4 capable peer */
2748 stream_putc (s, 8);
2749 stream_putl (s, attr->extra->aggregator_as);
2750 }
2751 else
2752 {
2753 /* 2-byte AS peer */
2754 stream_putc (s, 6);
2755
2756 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2757 if ( attr->extra->aggregator_as > 65535 )
2758 {
2759 stream_putw (s, BGP_AS_TRANS);
2760
2761 /* we have to send AS4_AGGREGATOR, too.
2762 * we'll do that later in order to send attributes in ascending
2763 * order.
2764 */
2765 send_as4_aggregator = 1;
2766 }
2767 else
2768 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2769 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002770 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002771 }
2772
2773 /* Community attribute. */
2774 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2775 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2776 {
2777 if (attr->community->size * 4 > 255)
2778 {
2779 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2780 stream_putc (s, BGP_ATTR_COMMUNITIES);
2781 stream_putw (s, attr->community->size * 4);
2782 }
2783 else
2784 {
2785 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2786 stream_putc (s, BGP_ATTR_COMMUNITIES);
2787 stream_putc (s, attr->community->size * 4);
2788 }
2789 stream_put (s, attr->community->val, attr->community->size * 4);
2790 }
2791
2792 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002793 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002794 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002795 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002796 {
2797 /* Originator ID. */
2798 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2799 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2800 stream_putc (s, 4);
2801
2802 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002803 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002804 else
2805 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002806
2807 /* Cluster list. */
2808 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2809 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2810
Paul Jakma9eda90c2007-08-30 13:36:17 +00002811 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002812 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002813 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002814 /* If this peer configuration's parent BGP has cluster_id. */
2815 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2816 stream_put_in_addr (s, &bgp->cluster_id);
2817 else
2818 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002819 stream_put (s, attr->extra->cluster->list,
2820 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002821 }
2822 else
2823 {
2824 stream_putc (s, 4);
2825 /* If this peer configuration's parent BGP has cluster_id. */
2826 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2827 stream_put_in_addr (s, &bgp->cluster_id);
2828 else
2829 stream_put_in_addr (s, &bgp->router_id);
2830 }
2831 }
2832
paul718e3742002-12-13 20:15:29 +00002833 /* Extended Communities attribute. */
2834 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2835 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2836 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002837 struct attr_extra *attre = attr->extra;
2838
2839 assert (attre);
2840
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002841 if (peer->sort == BGP_PEER_IBGP
2842 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002843 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002844 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002845 {
2846 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2847 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002848 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002849 }
2850 else
2851 {
2852 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2853 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002854 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002855 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002856 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002857 }
2858 else
2859 {
paul5228ad22004-06-04 17:58:18 +00002860 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002861 int tbit;
2862 int ecom_tr_size = 0;
2863 int i;
2864
Paul Jakmafb982c22007-05-04 20:15:47 +00002865 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002866 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002867 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002868 tbit = *pnt;
2869
2870 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2871 continue;
2872
2873 ecom_tr_size++;
2874 }
2875
2876 if (ecom_tr_size)
2877 {
2878 if (ecom_tr_size * 8 > 255)
2879 {
2880 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2881 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2882 stream_putw (s, ecom_tr_size * 8);
2883 }
2884 else
2885 {
2886 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2887 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2888 stream_putc (s, ecom_tr_size * 8);
2889 }
2890
Paul Jakmafb982c22007-05-04 20:15:47 +00002891 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002892 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002893 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002894 tbit = *pnt;
2895
2896 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2897 continue;
2898
2899 stream_put (s, pnt, 8);
2900 }
2901 }
paul718e3742002-12-13 20:15:29 +00002902 }
paul718e3742002-12-13 20:15:29 +00002903 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002904
2905 if ( send_as4_path )
2906 {
2907 /* If the peer is NOT As4 capable, AND */
2908 /* there are ASnums > 65535 in path THEN
2909 * give out AS4_PATH */
2910
2911 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2912 * path segments!
2913 * Hm, I wonder... confederation things *should* only be at
2914 * the beginning of an aspath, right? Then we should use
2915 * aspath_delete_confed_seq for this, because it is already
2916 * there! (JK)
2917 * Folks, talk to me: what is reasonable here!?
2918 */
2919 aspath = aspath_delete_confed_seq (aspath);
2920
2921 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2922 stream_putc (s, BGP_ATTR_AS4_PATH);
2923 aspath_sizep = stream_get_endp (s);
2924 stream_putw (s, 0);
2925 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2926 }
2927
2928 if (aspath != attr->aspath)
2929 aspath_free (aspath);
2930
2931 if ( send_as4_aggregator )
2932 {
2933 assert (attr->extra);
2934
2935 /* send AS4_AGGREGATOR, at this place */
2936 /* this section of code moved here in order to ensure the correct
2937 * *ascending* order of attributes
2938 */
2939 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2940 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2941 stream_putc (s, 8);
2942 stream_putl (s, attr->extra->aggregator_as);
2943 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2944 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002945
2946 if ((afi == AFI_IP || afi == AFI_IP6) &&
2947 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2948 {
2949 /* Tunnel Encap attribute */
2950 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2951 }
2952
paul718e3742002-12-13 20:15:29 +00002953 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002954 if (attr->extra && attr->extra->transit)
2955 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002956
2957 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002958 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002959}
2960
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002961size_t
2962bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002963{
paul718e3742002-12-13 20:15:29 +00002964 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002965
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002966 /* Set extended bit always to encode the attribute length as 2 bytes */
2967 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002968 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2969
paul9985f832005-02-09 15:51:56 +00002970 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002971 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002972
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002973 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002974 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002975 return attrlen_pnt;
2976}
paul718e3742002-12-13 20:15:29 +00002977
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002978void
2979bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2980 afi_t afi, safi_t safi, struct prefix_rd *prd,
2981 u_char *tag)
2982{
Lou Berger050defe2016-01-12 13:41:59 -05002983 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002984}
paul718e3742002-12-13 20:15:29 +00002985
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002986void
2987bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2988{
Lou Berger050defe2016-01-12 13:41:59 -05002989 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002990}
2991
2992/* Initialization of attribute. */
2993void
paulfe69a502005-09-10 16:55:02 +00002994bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002995{
paul718e3742002-12-13 20:15:29 +00002996 aspath_init ();
2997 attrhash_init ();
2998 community_init ();
2999 ecommunity_init ();
3000 cluster_init ();
3001 transit_init ();
3002}
3003
Chris Caputo228da422009-07-18 05:44:03 +00003004void
3005bgp_attr_finish (void)
3006{
3007 aspath_finish ();
3008 attrhash_finish ();
3009 community_finish ();
3010 ecommunity_finish ();
3011 cluster_finish ();
3012 transit_finish ();
3013}
3014
paul718e3742002-12-13 20:15:29 +00003015/* Make attribute packet. */
3016void
paula3845922003-10-18 01:30:50 +00003017bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3018 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003019{
3020 unsigned long cp;
3021 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003022 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003023 struct aspath *aspath;
3024
3025 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003026 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003027
3028 /* Place holder of length. */
3029 stream_putw (s, 0);
3030
3031 /* Origin attribute. */
3032 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3033 stream_putc (s, BGP_ATTR_ORIGIN);
3034 stream_putc (s, 1);
3035 stream_putc (s, attr->origin);
3036
3037 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003038
3039 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3040 stream_putc (s, BGP_ATTR_AS_PATH);
3041 aspath_lenp = stream_get_endp (s);
3042 stream_putw (s, 0);
3043
3044 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003045
3046 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003047 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3048 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003049 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003050 )
3051 {
3052 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3053 stream_putc (s, BGP_ATTR_NEXT_HOP);
3054 stream_putc (s, 4);
3055 stream_put_ipv4 (s, attr->nexthop.s_addr);
3056 }
paul718e3742002-12-13 20:15:29 +00003057
3058 /* MED attribute. */
3059 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3060 {
3061 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3062 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3063 stream_putc (s, 4);
3064 stream_putl (s, attr->med);
3065 }
3066
3067 /* Local preference. */
3068 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3069 {
3070 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3071 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3072 stream_putc (s, 4);
3073 stream_putl (s, attr->local_pref);
3074 }
3075
3076 /* Atomic aggregate. */
3077 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3078 {
3079 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3080 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3081 stream_putc (s, 0);
3082 }
3083
3084 /* Aggregator. */
3085 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3086 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003087 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003088 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3089 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003090 stream_putc (s, 8);
3091 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003092 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003093 }
3094
3095 /* Community attribute. */
3096 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3097 {
3098 if (attr->community->size * 4 > 255)
3099 {
3100 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3101 stream_putc (s, BGP_ATTR_COMMUNITIES);
3102 stream_putw (s, attr->community->size * 4);
3103 }
3104 else
3105 {
3106 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3107 stream_putc (s, BGP_ATTR_COMMUNITIES);
3108 stream_putc (s, attr->community->size * 4);
3109 }
3110 stream_put (s, attr->community->val, attr->community->size * 4);
3111 }
3112
paula3845922003-10-18 01:30:50 +00003113 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003114 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3115 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003116 {
3117 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003118 struct attr_extra *attre = attr->extra;
3119
paula3845922003-10-18 01:30:50 +00003120 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3121 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003122 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003123
3124 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003125 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003126 stream_putw(s, AFI_IP6); /* AFI */
3127 stream_putc(s, SAFI_UNICAST); /* SAFI */
3128
3129 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003130 stream_putc(s, attre->mp_nexthop_len);
3131 stream_put(s, &attre->mp_nexthop_global, 16);
3132 if (attre->mp_nexthop_len == 32)
3133 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003134
3135 /* SNPA */
3136 stream_putc(s, 0);
3137
3138 /* Prefix */
3139 stream_put_prefix(s, prefix);
3140
3141 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003142 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003143 }
paula3845922003-10-18 01:30:50 +00003144
paul718e3742002-12-13 20:15:29 +00003145 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003146 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003147 stream_putw_at (s, cp, len);
3148}