blob: f34e649332e6bfb801ae8f65628ac087d82ac975 [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
720struct attr *
721bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
722 struct aspath *aspath,
723 struct community *community, int as_set)
724{
725 struct attr attr;
726 struct attr *new;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000727 struct attr_extra attre;
paul718e3742002-12-13 20:15:29 +0000728
729 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000730 memset (&attre, 0, sizeof (struct attr_extra));
731 attr.extra = &attre;
732
paul718e3742002-12-13 20:15:29 +0000733 /* Origin attribute. */
734 attr.origin = origin;
735 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
736
737 /* AS path attribute. */
738 if (aspath)
739 attr.aspath = aspath_intern (aspath);
740 else
741 attr.aspath = aspath_empty ();
742 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
743
744 /* Next hop attribute. */
745 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
746
747 if (community)
748 {
749 attr.community = community;
750 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
751 }
752
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000753 attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000754 attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
Lou Berger205e6742016-01-12 13:42:11 -0500755
paul718e3742002-12-13 20:15:29 +0000756 if (! as_set)
757 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
758 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
759 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000760 attre.aggregator_as = bgp->confed_id;
paul718e3742002-12-13 20:15:29 +0000761 else
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000762 attre.aggregator_as = bgp->as;
763 attre.aggregator_addr = bgp->router_id;
paul718e3742002-12-13 20:15:29 +0000764
765 new = bgp_attr_intern (&attr);
Jorge Boncompte [DTI2]938ef3a2012-05-07 16:52:59 +0000766
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000767 aspath_unintern (&new->aspath);
paul718e3742002-12-13 20:15:29 +0000768 return new;
769}
770
Paul Jakmab881c702010-11-23 16:35:42 +0000771/* Unintern just the sub-components of the attr, but not the attr */
772void
773bgp_attr_unintern_sub (struct attr *attr)
774{
775 /* aspath refcount shoud be decrement. */
776 if (attr->aspath)
777 aspath_unintern (&attr->aspath);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000778 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH));
Paul Jakmab881c702010-11-23 16:35:42 +0000779
780 if (attr->community)
781 community_unintern (&attr->community);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000782 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000783
784 if (attr->extra)
785 {
786 if (attr->extra->ecommunity)
787 ecommunity_unintern (&attr->extra->ecommunity);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000788 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
Paul Jakmab881c702010-11-23 16:35:42 +0000789
790 if (attr->extra->cluster)
791 cluster_unintern (attr->extra->cluster);
Jorge Boncompte [DTI2]d92a2f32013-07-31 16:36:08 +0000792 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
Paul Jakmab881c702010-11-23 16:35:42 +0000793
794 if (attr->extra->transit)
795 transit_unintern (attr->extra->transit);
796 }
797}
798
paul718e3742002-12-13 20:15:29 +0000799/* Free bgp attribute and aspath. */
800void
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000801bgp_attr_unintern (struct attr **pattr)
paul718e3742002-12-13 20:15:29 +0000802{
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000803 struct attr *attr = *pattr;
paul718e3742002-12-13 20:15:29 +0000804 struct attr *ret;
Paul Jakmab881c702010-11-23 16:35:42 +0000805 struct attr tmp;
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000806 struct attr_extra tmp_extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000807
paul718e3742002-12-13 20:15:29 +0000808 /* Decrement attribute reference. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000809 attr->refcnt--;
Paul Jakmab881c702010-11-23 16:35:42 +0000810
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000811 tmp = *attr;
Paul Jakmab881c702010-11-23 16:35:42 +0000812
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000813 if (attr->extra)
Paul Jakmafb982c22007-05-04 20:15:47 +0000814 {
Jorge Boncompte [DTI2]b9f1dca2012-05-07 16:53:01 +0000815 tmp.extra = &tmp_extra;
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000816 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra));
Paul Jakmafb982c22007-05-04 20:15:47 +0000817 }
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000818
paul718e3742002-12-13 20:15:29 +0000819 /* If reference becomes zero then free attribute object. */
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000820 if (attr->refcnt == 0)
821 {
822 ret = hash_release (attrhash, attr);
paul718e3742002-12-13 20:15:29 +0000823 assert (ret != NULL);
Jorge Boncompte [DTI2]1a2fd702012-05-07 16:53:00 +0000824 bgp_attr_extra_free (attr);
825 XFREE (MTYPE_ATTR, attr);
826 *pattr = NULL;
paul718e3742002-12-13 20:15:29 +0000827 }
828
Paul Jakmab881c702010-11-23 16:35:42 +0000829 bgp_attr_unintern_sub (&tmp);
paul718e3742002-12-13 20:15:29 +0000830}
831
832void
833bgp_attr_flush (struct attr *attr)
834{
835 if (attr->aspath && ! attr->aspath->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500836 {
837 aspath_free (attr->aspath);
838 attr->aspath = NULL;
839 }
paul718e3742002-12-13 20:15:29 +0000840 if (attr->community && ! attr->community->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500841 {
842 community_free (attr->community);
843 attr->community = NULL;
844 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000845 if (attr->extra)
846 {
847 struct attr_extra *attre = attr->extra;
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000848
Paul Jakmafb982c22007-05-04 20:15:47 +0000849 if (attre->ecommunity && ! attre->ecommunity->refcnt)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000850 ecommunity_free (&attre->ecommunity);
Paul Jakmafb982c22007-05-04 20:15:47 +0000851 if (attre->cluster && ! attre->cluster->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500852 {
853 cluster_free (attre->cluster);
854 attre->cluster = NULL;
855 }
Paul Jakmafb982c22007-05-04 20:15:47 +0000856 if (attre->transit && ! attre->transit->refcnt)
Lou Berger370b7e52016-02-04 21:29:49 -0500857 {
858 transit_free (attre->transit);
859 attre->transit = NULL;
860 }
Lou Bergerc3741782016-01-12 13:42:01 -0500861 encap_free(attre->encap_subtlvs);
862 attre->encap_subtlvs = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000863 }
paul718e3742002-12-13 20:15:29 +0000864}
865
Paul Jakmab881c702010-11-23 16:35:42 +0000866/* Implement draft-scudder-idr-optional-transitive behaviour and
867 * avoid resetting sessions for malformed attributes which are
868 * are partial/optional and hence where the error likely was not
869 * introduced by the sending neighbour.
870 */
871static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +0000872bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
873 bgp_size_t length)
Paul Jakmab881c702010-11-23 16:35:42 +0000874{
Paul Jakma835315b2012-01-18 12:28:30 +0000875 struct peer *const peer = args->peer;
876 const u_int8_t flags = args->flags;
877 /* startp and length must be special-cased, as whether or not to
878 * send the attribute data with the NOTIFY depends on the error,
879 * the caller therefore signals this with the seperate length argument
880 */
Paul Jakmabd471fe2012-03-15 11:30:00 +0000881 u_char *notify_datap = (length > 0 ? args->startp : NULL);
Paul Jakma835315b2012-01-18 12:28:30 +0000882
Paul Jakmab881c702010-11-23 16:35:42 +0000883 /* Only relax error handling for eBGP peers */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000884 if (peer->sort != BGP_PEER_EBGP)
Paul Jakmab881c702010-11-23 16:35:42 +0000885 {
886 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000887 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000888 return BGP_ATTR_PARSE_ERROR;
889
890 }
891
Paul Jakmabd471fe2012-03-15 11:30:00 +0000892 /* Adjust the stream getp to the end of the attribute, in case we can
893 * still proceed but the caller hasn't read all the attribute.
894 */
895 stream_set_getp (BGP_INPUT (peer),
896 (args->startp - STREAM_DATA (BGP_INPUT (peer)))
897 + args->total);
898
Paul Jakma835315b2012-01-18 12:28:30 +0000899 switch (args->type) {
Paul Jakmafa61e162012-03-25 21:31:47 +0100900 /* where an attribute is relatively inconsequential, e.g. it does not
901 * affect route selection, and can be safely ignored, then any such
902 * attributes which are malformed should just be ignored and the route
903 * processed as normal.
Paul Jakmab881c702010-11-23 16:35:42 +0000904 */
905 case BGP_ATTR_AS4_AGGREGATOR:
906 case BGP_ATTR_AGGREGATOR:
907 case BGP_ATTR_ATOMIC_AGGREGATE:
908 return BGP_ATTR_PARSE_PROCEED;
909
910 /* Core attributes, particularly ones which may influence route
Paul Jakmafa61e162012-03-25 21:31:47 +0100911 * selection, should always cause session resets
Paul Jakmab881c702010-11-23 16:35:42 +0000912 */
913 case BGP_ATTR_ORIGIN:
914 case BGP_ATTR_AS_PATH:
915 case BGP_ATTR_NEXT_HOP:
916 case BGP_ATTR_MULTI_EXIT_DISC:
917 case BGP_ATTR_LOCAL_PREF:
918 case BGP_ATTR_COMMUNITIES:
919 case BGP_ATTR_ORIGINATOR_ID:
920 case BGP_ATTR_CLUSTER_LIST:
921 case BGP_ATTR_MP_REACH_NLRI:
922 case BGP_ATTR_MP_UNREACH_NLRI:
923 case BGP_ATTR_EXT_COMMUNITIES:
924 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
Paul Jakmabd471fe2012-03-15 11:30:00 +0000925 notify_datap, length);
Paul Jakmab881c702010-11-23 16:35:42 +0000926 return BGP_ATTR_PARSE_ERROR;
927 }
928
929 /* Partial optional attributes that are malformed should not cause
930 * the whole session to be reset. Instead treat it as a withdrawal
931 * of the routes, if possible.
932 */
Paul Jakma835315b2012-01-18 12:28:30 +0000933 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
934 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
935 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
Paul Jakmab881c702010-11-23 16:35:42 +0000936 return BGP_ATTR_PARSE_WITHDRAW;
937
938 /* default to reset */
David Lamparterf57000c2014-06-04 01:01:10 +0200939 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakmab881c702010-11-23 16:35:42 +0000940}
941
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400942/* Find out what is wrong with the path attribute flag bits and log the error.
943 "Flag bits" here stand for Optional, Transitive and Partial, but not for
944 Extended Length. Checking O/T/P bits at once implies, that the attribute
945 being diagnosed is defined by RFC as either a "well-known" or an "optional,
946 non-transitive" attribute. */
947static void
Paul Jakma835315b2012-01-18 12:28:30 +0000948bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
949 u_int8_t desired_flags /* how RFC says it must be */
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400950)
951{
952 u_char seen = 0, i;
Paul Jakma835315b2012-01-18 12:28:30 +0000953 u_char real_flags = args->flags;
954 const u_int8_t attr_code = args->type;
955
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400956 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
957 real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
958 for (i = 0; i <= 2; i++) /* O,T,P, but not E */
959 if
960 (
961 CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
962 CHECK_FLAG (real_flags, attr_flag_str[i].key)
963 )
964 {
Paul Jakma835315b2012-01-18 12:28:30 +0000965 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400966 LOOKUP (attr_str, attr_code),
967 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
968 attr_flag_str[i].str);
969 seen = 1;
970 }
Paul Jakmafa5831e2012-03-27 11:54:04 +0100971 if (!seen)
972 {
973 zlog (args->peer->log, LOG_DEBUG,
974 "Strange, %s called for attr %s, but no problem found with flags"
975 " (real flags 0x%x, desired 0x%x)",
976 __func__, LOOKUP (attr_str, attr_code),
977 real_flags, desired_flags);
978 }
Denis Ovsienkoafcb7672011-10-23 22:32:44 +0400979}
980
Paul Jakma3ecab4c2012-01-17 13:31:33 +0000981/* Required flags for attributes. EXTLEN will be masked off when testing,
982 * as will PARTIAL for optional+transitive attributes.
983 */
984const u_int8_t attr_flags_values [] = {
985 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
986 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
987 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
988 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
989 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
990 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
991 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
992 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
993 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
994 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
995 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
996 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
997 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
998 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
999 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1000};
1001static const size_t attr_flags_values_max =
1002 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
1003
1004static int
Paul Jakma835315b2012-01-18 12:28:30 +00001005bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001006{
1007 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
Paul Jakma835315b2012-01-18 12:28:30 +00001008 const u_int8_t flags = args->flags;
1009 const u_int8_t attr_code = args->type;
1010 struct peer *const peer = args->peer;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001011
1012 /* there may be attributes we don't know about */
1013 if (attr_code > attr_flags_values_max)
1014 return 0;
1015 if (attr_flags_values[attr_code] == 0)
1016 return 0;
1017
1018 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
1019 * 1."
1020 */
1021 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
1022 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1023 {
1024 zlog (peer->log, LOG_ERR,
1025 "%s well-known attributes must have transitive flag set (%x)",
1026 LOOKUP (attr_str, attr_code), flags);
1027 return 1;
1028 }
1029
1030 /* "For well-known attributes and for optional non-transitive attributes,
1031 * the Partial bit MUST be set to 0."
1032 */
1033 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1034 {
1035 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
1036 {
1037 zlog (peer->log, LOG_ERR,
1038 "%s well-known attribute "
1039 "must NOT have the partial flag set (%x)",
1040 LOOKUP (attr_str, attr_code), flags);
1041 return 1;
1042 }
1043 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1044 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1045 {
1046 zlog (peer->log, LOG_ERR,
1047 "%s optional + transitive attribute "
1048 "must NOT have the partial flag set (%x)",
1049 LOOKUP (attr_str, attr_code), flags);
1050 return 1;
1051 }
1052 }
1053
1054 /* Optional transitive attributes may go through speakers that don't
1055 * reocgnise them and set the Partial bit.
1056 */
1057 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
1058 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
1059 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
1060
Paul Jakma683f2b82012-03-23 14:58:45 +00001061 if ((flags & ~mask)
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001062 == attr_flags_values[attr_code])
1063 return 0;
1064
Paul Jakma835315b2012-01-18 12:28:30 +00001065 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001066 return 1;
1067}
1068
paul718e3742002-12-13 20:15:29 +00001069/* Get origin attribute of the update message. */
Paul Jakmab881c702010-11-23 16:35:42 +00001070static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001071bgp_attr_origin (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001072{
Paul Jakma835315b2012-01-18 12:28:30 +00001073 struct peer *const peer = args->peer;
1074 struct attr *const attr = args->attr;
1075 const bgp_size_t length = args->length;
1076
paul718e3742002-12-13 20:15:29 +00001077 /* If any recognized attribute has Attribute Length that conflicts
1078 with the expected length (based on the attribute type code), then
1079 the Error Subcode is set to Attribute Length Error. The Data
1080 field contains the erroneous attribute (type, length and
1081 value). */
1082 if (length != 1)
1083 {
1084 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
1085 length);
Paul Jakma835315b2012-01-18 12:28:30 +00001086 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001087 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001088 args->total);
paul718e3742002-12-13 20:15:29 +00001089 }
1090
1091 /* Fetch origin attribute. */
1092 attr->origin = stream_getc (BGP_INPUT (peer));
1093
1094 /* If the ORIGIN attribute has an undefined value, then the Error
1095 Subcode is set to Invalid Origin Attribute. The Data field
1096 contains the unrecognized attribute (type, length and value). */
1097 if ((attr->origin != BGP_ORIGIN_IGP)
1098 && (attr->origin != BGP_ORIGIN_EGP)
1099 && (attr->origin != BGP_ORIGIN_INCOMPLETE))
1100 {
1101 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
1102 attr->origin);
Paul Jakma835315b2012-01-18 12:28:30 +00001103 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001104 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
Paul Jakma835315b2012-01-18 12:28:30 +00001105 args->total);
paul718e3742002-12-13 20:15:29 +00001106 }
1107
1108 /* Set oring attribute flag. */
1109 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
1110
1111 return 0;
1112}
Paul Jakmaab005292010-11-27 22:48:34 +00001113
1114/* Parse AS path information. This function is wrapper of
1115 aspath_parse. */
1116static int
Paul Jakma835315b2012-01-18 12:28:30 +00001117bgp_attr_aspath (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001118{
Paul Jakma835315b2012-01-18 12:28:30 +00001119 struct attr *const attr = args->attr;
1120 struct peer *const peer = args->peer;
1121 const bgp_size_t length = args->length;
Paul Jakma83a9a222012-01-08 14:15:03 +00001122
Paul Jakmaab005292010-11-27 22:48:34 +00001123 /*
1124 * peer with AS4 => will get 4Byte ASnums
1125 * otherwise, will get 16 Bit
1126 */
1127 attr->aspath = aspath_parse (peer->ibuf, length,
1128 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
1129
1130 /* In case of IBGP, length will be zero. */
1131 if (! attr->aspath)
paul718e3742002-12-13 20:15:29 +00001132 {
Paul Jakmab881c702010-11-23 16:35:42 +00001133 zlog (peer->log, LOG_ERR,
1134 "Malformed AS path from %s, length is %d",
1135 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001136 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
Paul Jakmaab005292010-11-27 22:48:34 +00001137 }
Chris Hallcddb8112010-08-09 22:31:37 +04001138
Paul Jakmaab005292010-11-27 22:48:34 +00001139 /* Set aspath attribute flag. */
1140 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
paul718e3742002-12-13 20:15:29 +00001141
Paul Jakmab881c702010-11-23 16:35:42 +00001142 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001143}
1144
Paul Jakmab881c702010-11-23 16:35:42 +00001145static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001146bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001147{
1148 /* These checks were part of bgp_attr_aspath, but with
1149 * as4 we should to check aspath things when
1150 * aspath synthesizing with as4_path has already taken place.
1151 * Otherwise we check ASPATH and use the synthesized thing, and that is
1152 * not right.
1153 * So do the checks later, i.e. here
1154 */
1155 struct bgp *bgp = peer->bgp;
1156 struct aspath *aspath;
1157
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001158 /* Confederation sanity check. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001159 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1160 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001161 {
1162 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
Paul Jakma835315b2012-01-18 12:28:30 +00001163 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1164 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1165 return BGP_ATTR_PARSE_ERROR;
Vasilis Tsiligiannisca87e1d2009-07-20 01:28:35 +03001166 }
1167
paul718e3742002-12-13 20:15:29 +00001168 /* First AS check for EBGP. */
1169 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1170 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001171 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00001172 && ! aspath_firstas_check (attr->aspath, peer->as))
1173 {
1174 zlog (peer->log, LOG_ERR,
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001175 "%s incorrect first AS (must be %u)", peer->host, peer->as);
Paul Jakma835315b2012-01-18 12:28:30 +00001176 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1177 BGP_NOTIFY_UPDATE_MAL_AS_PATH);
1178 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00001179 }
1180 }
1181
1182 /* local-as prepend */
1183 if (peer->change_local_as &&
1184 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1185 {
1186 aspath = aspath_dup (attr->aspath);
1187 aspath = aspath_add_seq (aspath, peer->change_local_as);
Paul Jakmaf6f434b2010-11-23 21:28:03 +00001188 aspath_unintern (&attr->aspath);
paul718e3742002-12-13 20:15:29 +00001189 attr->aspath = aspath_intern (aspath);
1190 }
1191
Paul Jakmab881c702010-11-23 16:35:42 +00001192 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001193}
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001194
Paul Jakmaab005292010-11-27 22:48:34 +00001195/* Parse AS4 path information. This function is another wrapper of
1196 aspath_parse. */
1197static int
Paul Jakma835315b2012-01-18 12:28:30 +00001198bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
Paul Jakmaab005292010-11-27 22:48:34 +00001199{
Paul Jakma835315b2012-01-18 12:28:30 +00001200 struct peer *const peer = args->peer;
1201 struct attr *const attr = args->attr;
1202 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001203
Paul Jakmaab005292010-11-27 22:48:34 +00001204 *as4_path = aspath_parse (peer->ibuf, length, 1);
1205
Paul Jakmab881c702010-11-23 16:35:42 +00001206 /* In case of IBGP, length will be zero. */
1207 if (!*as4_path)
1208 {
1209 zlog (peer->log, LOG_ERR,
1210 "Malformed AS4 path from %s, length is %d",
1211 peer->host, length);
Paul Jakma835315b2012-01-18 12:28:30 +00001212 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001213 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
Paul Jakma835315b2012-01-18 12:28:30 +00001214 0);
Paul Jakmab881c702010-11-23 16:35:42 +00001215 }
1216
Paul Jakmaab005292010-11-27 22:48:34 +00001217 /* Set aspath attribute flag. */
1218 if (as4_path)
1219 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1220
Paul Jakmab881c702010-11-23 16:35:42 +00001221 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001222}
1223
paul718e3742002-12-13 20:15:29 +00001224/* Nexthop attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001225static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001226bgp_attr_nexthop (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001227{
Paul Jakma835315b2012-01-18 12:28:30 +00001228 struct peer *const peer = args->peer;
1229 struct attr *const attr = args->attr;
1230 const bgp_size_t length = args->length;
1231
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001232 in_addr_t nexthop_h, nexthop_n;
paul718e3742002-12-13 20:15:29 +00001233
paul718e3742002-12-13 20:15:29 +00001234 /* Check nexthop attribute length. */
1235 if (length != 4)
1236 {
1237 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1238 length);
1239
Paul Jakma835315b2012-01-18 12:28:30 +00001240 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001241 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001242 args->total);
paul718e3742002-12-13 20:15:29 +00001243 }
1244
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001245 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
1246 attribute must result in a NOTIFICATION message (this is implemented below).
1247 At the same time, semantically incorrect NEXT_HOP is more likely to be just
1248 logged locally (this is implemented somewhere else). The UPDATE message
1249 gets ignored in any of these cases. */
1250 nexthop_n = stream_get_ipv4 (peer->ibuf);
1251 nexthop_h = ntohl (nexthop_n);
1252 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1253 {
1254 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001255 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001256 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001257 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001258 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001259 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001260 }
1261
1262 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001263 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1264
Paul Jakmab881c702010-11-23 16:35:42 +00001265 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001266}
1267
1268/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001269static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001270bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001271{
Paul Jakma835315b2012-01-18 12:28:30 +00001272 struct peer *const peer = args->peer;
1273 struct attr *const attr = args->attr;
1274 const bgp_size_t length = args->length;
1275
paul718e3742002-12-13 20:15:29 +00001276 /* Length check. */
1277 if (length != 4)
1278 {
1279 zlog (peer->log, LOG_ERR,
1280 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001281
Paul Jakma835315b2012-01-18 12:28:30 +00001282 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001283 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001284 args->total);
paul718e3742002-12-13 20:15:29 +00001285 }
1286
1287 attr->med = stream_getl (peer->ibuf);
1288
1289 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1290
Paul Jakmab881c702010-11-23 16:35:42 +00001291 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001292}
1293
1294/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001295static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001296bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001297{
Paul Jakma835315b2012-01-18 12:28:30 +00001298 struct peer *const peer = args->peer;
1299 struct attr *const attr = args->attr;
1300 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001301
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001302 /* Length check. */
1303 if (length != 4)
1304 {
Paul Jakma835315b2012-01-18 12:28:30 +00001305 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1306 length);
1307 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001308 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001309 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001310 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001311
paul718e3742002-12-13 20:15:29 +00001312 /* If it is contained in an UPDATE message that is received from an
1313 external peer, then this attribute MUST be ignored by the
1314 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001315 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001316 {
paul9985f832005-02-09 15:51:56 +00001317 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001318 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001319 }
1320
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001321 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001322
1323 /* Set atomic aggregate flag. */
1324 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1325
Paul Jakmab881c702010-11-23 16:35:42 +00001326 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001327}
1328
1329/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001330static int
Paul Jakma835315b2012-01-18 12:28:30 +00001331bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001332{
Paul Jakma835315b2012-01-18 12:28:30 +00001333 struct peer *const peer = args->peer;
1334 struct attr *const attr = args->attr;
1335 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001336
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001337 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001338 if (length != 0)
1339 {
Paul Jakma835315b2012-01-18 12:28:30 +00001340 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1341 length);
1342 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001343 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001344 args->total);
paul718e3742002-12-13 20:15:29 +00001345 }
1346
1347 /* Set atomic aggregate flag. */
1348 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1349
Paul Jakmab881c702010-11-23 16:35:42 +00001350 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001351}
1352
1353/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001354static int
Paul Jakma835315b2012-01-18 12:28:30 +00001355bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001356{
Paul Jakma835315b2012-01-18 12:28:30 +00001357 struct peer *const peer = args->peer;
1358 struct attr *const attr = args->attr;
1359 const bgp_size_t length = args->length;
1360
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001361 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001362 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001363
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001364 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001365 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001366 wantedlen = 8;
1367
1368 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001369 {
Paul Jakma835315b2012-01-18 12:28:30 +00001370 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1371 wantedlen, length);
1372 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001373 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001374 args->total);
paul718e3742002-12-13 20:15:29 +00001375 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001376
1377 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1378 attre->aggregator_as = stream_getl (peer->ibuf);
1379 else
1380 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001381 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001382
1383 /* Set atomic aggregate flag. */
1384 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1385
Paul Jakmab881c702010-11-23 16:35:42 +00001386 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001387}
1388
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001389/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001390static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001391bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1392 as_t *as4_aggregator_as,
1393 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001394{
Paul Jakma835315b2012-01-18 12:28:30 +00001395 struct peer *const peer = args->peer;
1396 struct attr *const attr = args->attr;
1397 const bgp_size_t length = args->length;
1398
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001399 if (length != 8)
1400 {
Paul Jakma835315b2012-01-18 12:28:30 +00001401 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1402 length);
1403 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001404 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001405 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001406 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001407
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001408 *as4_aggregator_as = stream_getl (peer->ibuf);
1409 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1410
1411 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1412
Paul Jakmab881c702010-11-23 16:35:42 +00001413 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001414}
1415
1416/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1417 */
Paul Jakmab881c702010-11-23 16:35:42 +00001418static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001419bgp_attr_munge_as4_attrs (struct peer *const peer,
1420 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001421 struct aspath *as4_path, as_t as4_aggregator,
1422 struct in_addr *as4_aggregator_addr)
1423{
1424 int ignore_as4_path = 0;
1425 struct aspath *newpath;
1426 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001427
1428 if (!attr->aspath)
1429 {
1430 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1431 * checked that all well-known, mandatory attributes were present.
1432 *
1433 * Can only be a problem with peer itself - hard error
1434 */
1435 return BGP_ATTR_PARSE_ERROR;
1436 }
1437
Paul Jakmab881c702010-11-23 16:35:42 +00001438 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001439 {
1440 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1441 * if given.
1442 * It is worth a warning though, because the peer really
1443 * should not send them
1444 */
1445 if (BGP_DEBUG(as4, AS4))
1446 {
1447 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1448 zlog_debug ("[AS4] %s %s AS4_PATH",
1449 peer->host, "AS4 capable peer, yet it sent");
1450
1451 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1452 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1453 peer->host, "AS4 capable peer, yet it sent");
1454 }
1455
Paul Jakmab881c702010-11-23 16:35:42 +00001456 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001457 }
1458
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001459 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1460 * because that may override AS4_PATH
1461 */
1462 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1463 {
Paul Jakmab881c702010-11-23 16:35:42 +00001464 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001465 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001466 assert (attre);
1467
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001468 /* received both.
1469 * if the as_number in aggregator is not AS_TRANS,
1470 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1471 * and the Aggregator shall be taken as
1472 * info on the aggregating node, and the AS_PATH
1473 * shall be taken as the AS_PATH
1474 * otherwise
1475 * the Aggregator shall be ignored and the
1476 * AS4_AGGREGATOR shall be taken as the
1477 * Aggregating node and the AS_PATH is to be
1478 * constructed "as in all other cases"
1479 */
Paul Jakmab881c702010-11-23 16:35:42 +00001480 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001481 {
1482 /* ignore */
1483 if ( BGP_DEBUG(as4, AS4))
1484 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1485 " send AGGREGATOR != AS_TRANS and"
1486 " AS4_AGGREGATOR, so ignore"
1487 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1488 ignore_as4_path = 1;
1489 }
1490 else
1491 {
1492 /* "New_aggregator shall be taken as aggregator" */
1493 attre->aggregator_as = as4_aggregator;
1494 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1495 }
1496 }
1497 else
1498 {
1499 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1500 * That is bogus - but reading the conditions
1501 * we have to handle AS4_AGGREGATOR as if it were
1502 * AGGREGATOR in that case
1503 */
1504 if ( BGP_DEBUG(as4, AS4))
1505 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1506 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1507 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001508 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001509 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1510 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1511 }
1512 }
1513
1514 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001515 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001516 {
Paul Jakma055086f2014-09-23 15:23:01 +01001517 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1518 aspath_unintern (&attr->aspath);
1519 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001520 }
Paul Jakmab881c702010-11-23 16:35:42 +00001521 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001522}
1523
paul718e3742002-12-13 20:15:29 +00001524/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001525static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001526bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001527{
Paul Jakma835315b2012-01-18 12:28:30 +00001528 struct peer *const peer = args->peer;
1529 struct attr *const attr = args->attr;
1530 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001531
paul718e3742002-12-13 20:15:29 +00001532 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001533 {
1534 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001535 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001536 }
Paul Jakma0c466382010-12-05 17:17:26 +00001537
1538 attr->community =
1539 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1540
1541 /* XXX: fix community_parse to use stream API and remove this */
1542 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001543
Paul Jakma0c466382010-12-05 17:17:26 +00001544 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001545 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001546 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001547 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001548
paul718e3742002-12-13 20:15:29 +00001549 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1550
Paul Jakmab881c702010-11-23 16:35:42 +00001551 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001552}
1553
1554/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001555static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001556bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001557{
Paul Jakma835315b2012-01-18 12:28:30 +00001558 struct peer *const peer = args->peer;
1559 struct attr *const attr = args->attr;
1560 const bgp_size_t length = args->length;
1561
Denis Ovsienkod595b562011-09-30 15:08:54 +04001562 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001563 if (length != 4)
1564 {
1565 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1566
Paul Jakma835315b2012-01-18 12:28:30 +00001567 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001568 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001569 args->total);
paul718e3742002-12-13 20:15:29 +00001570 }
1571
Paul Jakmafb982c22007-05-04 20:15:47 +00001572 (bgp_attr_extra_get (attr))->originator_id.s_addr
1573 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001574
1575 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1576
Paul Jakmab881c702010-11-23 16:35:42 +00001577 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001578}
1579
1580/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001581static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001582bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001583{
Paul Jakma835315b2012-01-18 12:28:30 +00001584 struct peer *const peer = args->peer;
1585 struct attr *const attr = args->attr;
1586 const bgp_size_t length = args->length;
1587
paul718e3742002-12-13 20:15:29 +00001588 /* Check length. */
1589 if (length % 4)
1590 {
1591 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1592
Paul Jakma835315b2012-01-18 12:28:30 +00001593 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1594 args->total);
paul718e3742002-12-13 20:15:29 +00001595 }
1596
Paul Jakmafb982c22007-05-04 20:15:47 +00001597 (bgp_attr_extra_get (attr))->cluster
1598 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001599
1600 /* XXX: Fix cluster_parse to use stream API and then remove this */
1601 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001602
1603 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1604
Paul Jakmab881c702010-11-23 16:35:42 +00001605 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001606}
1607
1608/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001609int
Paul Jakma835315b2012-01-18 12:28:30 +00001610bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1611 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001612{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001613 afi_t afi;
1614 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001615 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001616 size_t start;
paul718e3742002-12-13 20:15:29 +00001617 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001618 struct peer *const peer = args->peer;
1619 struct attr *const attr = args->attr;
1620 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001621 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001622
paul718e3742002-12-13 20:15:29 +00001623 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001624 s = BGP_INPUT(peer);
1625 start = stream_get_getp(s);
1626
1627 /* safe to read statically sized header? */
1628#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001629#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001630 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001631 {
1632 zlog_info ("%s: %s sent invalid length, %lu",
1633 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001634 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001635 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001636
paul718e3742002-12-13 20:15:29 +00001637 /* Load AFI, SAFI. */
1638 afi = stream_getw (s);
1639 safi = stream_getc (s);
1640
1641 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001642 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001643
Paul Jakma03292802008-06-07 20:37:10 +00001644 if (LEN_LEFT < attre->mp_nexthop_len)
1645 {
1646 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1647 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001648 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001649 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001650
paul718e3742002-12-13 20:15:29 +00001651 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001652 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001653 {
1654 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001655 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001656 /* Probably needed for RFC 2283 */
1657 if (attr->nexthop.s_addr == 0)
1658 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001659 break;
1660 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001661 stream_getl (s); /* RD high */
1662 stream_getl (s); /* RD low */
1663 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001664 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001665 case 24:
1666 {
1667 u_int32_t rd_high __attribute__((unused));
1668 u_int32_t rd_low __attribute__((unused));
1669
1670 rd_high = stream_getl (s);
1671 rd_low = stream_getl (s);
1672 }
1673 /* fall through */
paul718e3742002-12-13 20:15:29 +00001674 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001675 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001676 break;
1677 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001678 case 48:
1679 if (attre->mp_nexthop_len == 48) {
1680 u_int32_t rd_high __attribute__((unused));
1681 u_int32_t rd_low __attribute__((unused));
1682
1683 rd_high = stream_getl (s);
1684 rd_low = stream_getl (s);
1685 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001686 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001687
1688 if (attre->mp_nexthop_len == 48) {
1689 u_int32_t rd_high __attribute__((unused));
1690 u_int32_t rd_low __attribute__((unused));
1691
1692 rd_high = stream_getl (s);
1693 rd_low = stream_getl (s);
1694 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001695 stream_get (&attre->mp_nexthop_local, s, 16);
1696 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001697 {
1698 char buf1[INET6_ADDRSTRLEN];
1699 char buf2[INET6_ADDRSTRLEN];
1700
1701 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001702 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 +00001703 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001704 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001705 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001706 buf2, INET6_ADDRSTRLEN));
1707
Paul Jakmafb982c22007-05-04 20:15:47 +00001708 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001709 }
1710 break;
paul718e3742002-12-13 20:15:29 +00001711 default:
Paul Jakma03292802008-06-07 20:37:10 +00001712 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1713 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001714 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001715 }
1716
Paul Jakma03292802008-06-07 20:37:10 +00001717 if (!LEN_LEFT)
1718 {
1719 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1720 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001721 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001722 }
paul718e3742002-12-13 20:15:29 +00001723
Paul Jakma6e4ab122007-04-10 19:36:48 +00001724 {
1725 u_char val;
1726 if ((val = stream_getc (s)))
1727 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1728 peer->host, val);
1729 }
1730
1731 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001732 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001733 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001734 {
1735 zlog_info ("%s: (%s) Failed to read NLRI",
1736 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001737 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001738 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001739
paul718e3742002-12-13 20:15:29 +00001740 mp_update->afi = afi;
1741 mp_update->safi = safi;
1742 mp_update->nlri = stream_pnt (s);
1743 mp_update->length = nlri_len;
1744
paul9985f832005-02-09 15:51:56 +00001745 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001746
David Lamparterdaefeb82014-12-08 17:42:12 +01001747 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1748
Paul Jakmab881c702010-11-23 16:35:42 +00001749 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001750#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001751}
1752
1753/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001754int
Paul Jakma835315b2012-01-18 12:28:30 +00001755bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001756 struct bgp_nlri *mp_withdraw)
1757{
1758 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001759 afi_t afi;
1760 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001761 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001762 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001763 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001764 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001765
1766 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001767
1768#define BGP_MP_UNREACH_MIN_SIZE 3
1769 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001770 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001771
paul718e3742002-12-13 20:15:29 +00001772 afi = stream_getw (s);
1773 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001774
1775 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001776
paul718e3742002-12-13 20:15:29 +00001777 mp_withdraw->afi = afi;
1778 mp_withdraw->safi = safi;
1779 mp_withdraw->nlri = stream_pnt (s);
1780 mp_withdraw->length = withdraw_len;
1781
paul9985f832005-02-09 15:51:56 +00001782 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001783
David Lamparterdaefeb82014-12-08 17:42:12 +01001784 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1785
Paul Jakmab881c702010-11-23 16:35:42 +00001786 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001787}
1788
1789/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001790static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001791bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001792{
Paul Jakma835315b2012-01-18 12:28:30 +00001793 struct peer *const peer = args->peer;
1794 struct attr *const attr = args->attr;
1795 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001796
paul718e3742002-12-13 20:15:29 +00001797 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001798 {
1799 if (attr->extra)
1800 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001801 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001802 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001803 }
Paul Jakma0c466382010-12-05 17:17:26 +00001804
1805 (bgp_attr_extra_get (attr))->ecommunity =
1806 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1807 /* XXX: fix ecommunity_parse to use stream API */
1808 stream_forward_getp (peer->ibuf, length);
1809
1810 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001811 return bgp_attr_malformed (args,
1812 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1813 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001814
paul718e3742002-12-13 20:15:29 +00001815 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1816
Paul Jakmab881c702010-11-23 16:35:42 +00001817 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001818}
1819
Lou Bergerc3741782016-01-12 13:42:01 -05001820/* Parse Tunnel Encap attribute in an UPDATE */
1821static int
1822bgp_attr_encap(
1823 uint8_t type,
1824 struct peer *peer, /* IN */
1825 bgp_size_t length, /* IN: attr's length field */
1826 struct attr *attr, /* IN: caller already allocated */
1827 u_char flag, /* IN: attr's flags field */
1828 u_char *startp)
1829{
1830 bgp_size_t total;
1831 struct attr_extra *attre = NULL;
1832 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1833 uint16_t tunneltype;
1834
1835 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1836
1837 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1838 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1839 {
1840 zlog (peer->log, LOG_ERR,
1841 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1842 bgp_notify_send_with_data (peer,
1843 BGP_NOTIFY_UPDATE_ERR,
1844 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1845 startp, total);
1846 return -1;
1847 }
1848
1849 if (BGP_ATTR_ENCAP == type) {
1850 /* read outer TLV type and length */
1851 uint16_t tlv_length;
1852
1853 if (length < 4) {
1854 zlog (peer->log, LOG_ERR,
1855 "Tunnel Encap attribute not long enough to contain outer T,L");
1856 bgp_notify_send_with_data(peer,
1857 BGP_NOTIFY_UPDATE_ERR,
1858 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1859 startp, total);
1860 return -1;
1861 }
1862 tunneltype = stream_getw (BGP_INPUT (peer));
1863 tlv_length = stream_getw (BGP_INPUT (peer));
1864 length -= 4;
1865
1866 if (tlv_length != length) {
1867 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1868 __func__, tlv_length, length);
1869 }
1870 }
1871
1872 while (length >= 4) {
1873 uint16_t subtype;
1874 uint16_t sublength;
1875 struct bgp_attr_encap_subtlv *tlv;
1876
Lou Berger298cc2f2016-01-12 13:42:02 -05001877 if (BGP_ATTR_ENCAP == type) {
1878 subtype = stream_getc (BGP_INPUT (peer));
1879 sublength = stream_getc (BGP_INPUT (peer));
1880 length -= 2;
1881 }
Lou Bergerc3741782016-01-12 13:42:01 -05001882
1883 if (sublength > length) {
1884 zlog (peer->log, LOG_ERR,
1885 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1886 sublength, length);
1887 bgp_notify_send_with_data (peer,
1888 BGP_NOTIFY_UPDATE_ERR,
1889 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1890 startp, total);
1891 return -1;
1892 }
1893
1894 /* alloc and copy sub-tlv */
1895 /* TBD make sure these are freed when attributes are released */
1896 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1897 tlv->type = subtype;
1898 tlv->length = sublength;
1899 stream_get(tlv->value, peer->ibuf, sublength);
1900 length -= sublength;
1901
1902 /* attach tlv to encap chain */
1903 if (!attre) {
1904 attre = bgp_attr_extra_get(attr);
1905 if (BGP_ATTR_ENCAP == type) {
1906 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1907 stlv_last = stlv_last->next);
1908 if (stlv_last) {
1909 stlv_last->next = tlv;
1910 } else {
1911 attre->encap_subtlvs = tlv;
1912 }
1913 }
1914 } else {
1915 stlv_last->next = tlv;
1916 }
1917 stlv_last = tlv;
1918 }
1919
1920 if (attre && (BGP_ATTR_ENCAP == type)) {
1921 attre->encap_tunneltype = tunneltype;
1922 }
1923
1924 if (length) {
1925 /* spurious leftover data */
1926 zlog (peer->log, LOG_ERR,
1927 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1928 bgp_notify_send_with_data (peer,
1929 BGP_NOTIFY_UPDATE_ERR,
1930 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1931 startp, total);
1932 return -1;
1933 }
1934
1935 return 0;
1936}
1937
paul718e3742002-12-13 20:15:29 +00001938/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001939static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001940bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001941{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001942 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001943 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001944 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001945 struct peer *const peer = args->peer;
1946 struct attr *const attr = args->attr;
1947 u_char *const startp = args->startp;
1948 const u_char type = args->type;
1949 const u_char flag = args->flags;
1950 const bgp_size_t length = args->length;
1951
paul718e3742002-12-13 20:15:29 +00001952
hassof4184462005-02-01 20:13:16 +00001953 if (BGP_DEBUG (normal, NORMAL))
1954 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1955 peer->host, type, length);
1956
paul718e3742002-12-13 20:15:29 +00001957 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001958 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001959 "Unknown attribute type %d length %d is received", type, length);
1960
1961 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001962 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001963
paul718e3742002-12-13 20:15:29 +00001964 /* If any of the mandatory well-known attributes are not recognized,
1965 then the Error Subcode is set to Unrecognized Well-known
1966 Attribute. The Data field contains the unrecognized attribute
1967 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001968 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001969 {
Paul Jakma835315b2012-01-18 12:28:30 +00001970 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001971 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001972 args->total);
paul718e3742002-12-13 20:15:29 +00001973 }
1974
1975 /* Unrecognized non-transitive optional attributes must be quietly
1976 ignored and not passed along to other BGP peers. */
1977 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001978 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001979
1980 /* If a path with recognized transitive optional attribute is
1981 accepted and passed along to other BGP peers and the Partial bit
1982 in the Attribute Flags octet is set to 1 by some previous AS, it
1983 is not set back to 0 by the current AS. */
1984 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1985
1986 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001987 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001988 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001989
Paul Jakmafb982c22007-05-04 20:15:47 +00001990 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001991
1992 if (transit->val)
1993 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1994 transit->length + total);
1995 else
1996 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1997
1998 memcpy (transit->val + transit->length, startp, total);
1999 transit->length += total;
2000
Paul Jakmab881c702010-11-23 16:35:42 +00002001 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002002}
2003
Paul Jakma055086f2014-09-23 15:23:01 +01002004/* Well-known attribute check. */
2005static int
2006bgp_attr_check (struct peer *peer, struct attr *attr)
2007{
2008 u_char type = 0;
2009
Paul Jakmaaed1b552014-10-21 16:59:01 +01002010 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2011 * empty UPDATE. */
2012 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2013 return BGP_ATTR_PARSE_PROCEED;
2014
2015 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2016 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2017 are present, it should. Check for any other attribute being present
2018 instead.
2019 */
2020 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2021 return BGP_ATTR_PARSE_PROCEED;
2022
Paul Jakma055086f2014-09-23 15:23:01 +01002023 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2024 type = BGP_ATTR_ORIGIN;
2025
2026 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2027 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002028
2029 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2030 * NLRI is empty. We can't easily check NLRI empty here though.
2031 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002032 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2033 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002034 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002035
Paul Jakma055086f2014-09-23 15:23:01 +01002036 if (peer->sort == BGP_PEER_IBGP
2037 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2038 type = BGP_ATTR_LOCAL_PREF;
2039
2040 if (type)
2041 {
2042 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002043 "%s Missing well-known attribute %d / %s",
2044 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002045 bgp_notify_send_with_data (peer,
2046 BGP_NOTIFY_UPDATE_ERR,
2047 BGP_NOTIFY_UPDATE_MISS_ATTR,
2048 &type, 1);
2049 return BGP_ATTR_PARSE_ERROR;
2050 }
2051 return BGP_ATTR_PARSE_PROCEED;
2052}
2053
paul718e3742002-12-13 20:15:29 +00002054/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002055 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002056bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002057bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2058 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2059{
2060 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002061 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002062 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002063 bgp_size_t length;
2064 u_char *startp, *endp;
2065 u_char *attr_endp;
2066 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002067 /* we need the as4_path only until we have synthesized the as_path with it */
2068 /* same goes for as4_aggregator */
2069 struct aspath *as4_path = NULL;
2070 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002071 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002072
2073 /* Initialize bitmap. */
2074 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2075
2076 /* End pointer of BGP attribute. */
2077 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002078
paul718e3742002-12-13 20:15:29 +00002079 /* Get attributes to the end of attribute length. */
2080 while (BGP_INPUT_PNT (peer) < endp)
2081 {
2082 /* Check remaining length check.*/
2083 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2084 {
gdtc29fdba2004-12-09 14:46:46 +00002085 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002086 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002087 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002088 peer->host,
2089 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002090
2091 bgp_notify_send (peer,
2092 BGP_NOTIFY_UPDATE_ERR,
2093 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002094 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002095 }
2096
2097 /* Fetch attribute flag and type. */
2098 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002099 /* "The lower-order four bits of the Attribute Flags octet are
2100 unused. They MUST be zero when sent and MUST be ignored when
2101 received." */
2102 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002103 type = stream_getc (BGP_INPUT (peer));
2104
Paul Jakma370b64a2007-12-22 16:49:52 +00002105 /* Check whether Extended-Length applies and is in bounds */
2106 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2107 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2108 {
2109 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002110 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002111 peer->host,
2112 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2113
2114 bgp_notify_send (peer,
2115 BGP_NOTIFY_UPDATE_ERR,
2116 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002117 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002118 }
Paul Jakma835315b2012-01-18 12:28:30 +00002119
paul718e3742002-12-13 20:15:29 +00002120 /* Check extended attribue length bit. */
2121 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2122 length = stream_getw (BGP_INPUT (peer));
2123 else
2124 length = stream_getc (BGP_INPUT (peer));
2125
2126 /* If any attribute appears more than once in the UPDATE
2127 message, then the Error Subcode is set to Malformed Attribute
2128 List. */
2129
2130 if (CHECK_BITMAP (seen, type))
2131 {
2132 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002133 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002134 peer->host, type);
2135
2136 bgp_notify_send (peer,
2137 BGP_NOTIFY_UPDATE_ERR,
2138 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002139 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002140 }
2141
2142 /* Set type to bitmap to check duplicate attribute. `type' is
2143 unsigned char so it never overflow bitmap range. */
2144
2145 SET_BITMAP (seen, type);
2146
2147 /* Overflow check. */
2148 attr_endp = BGP_INPUT_PNT (peer) + length;
2149
2150 if (attr_endp > endp)
2151 {
2152 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002153 "%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 +00002154 bgp_notify_send (peer,
2155 BGP_NOTIFY_UPDATE_ERR,
2156 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002157 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002158 }
Paul Jakma835315b2012-01-18 12:28:30 +00002159
2160 struct bgp_attr_parser_args attr_args = {
2161 .peer = peer,
2162 .length = length,
2163 .attr = attr,
2164 .type = type,
2165 .flags = flag,
2166 .startp = startp,
2167 .total = attr_endp - startp,
2168 };
2169
2170
2171 /* If any recognized attribute has Attribute Flags that conflict
2172 with the Attribute Type Code, then the Error Subcode is set to
2173 Attribute Flags Error. The Data field contains the erroneous
2174 attribute (type, length and value). */
2175 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002176 {
2177 bgp_attr_parse_ret_t ret;
2178 ret = bgp_attr_malformed (&attr_args,
2179 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2180 attr_args.total);
2181 if (ret == BGP_ATTR_PARSE_PROCEED)
2182 continue;
2183 return ret;
2184 }
paul718e3742002-12-13 20:15:29 +00002185
2186 /* OK check attribute and store it's value. */
2187 switch (type)
2188 {
2189 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002190 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002191 break;
2192 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002193 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002194 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002195 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002196 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002197 break;
paul718e3742002-12-13 20:15:29 +00002198 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002199 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002200 break;
2201 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002202 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002203 break;
2204 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002205 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002206 break;
2207 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002208 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002209 break;
2210 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002211 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002212 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002213 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002214 ret = bgp_attr_as4_aggregator (&attr_args,
2215 &as4_aggregator,
2216 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002217 break;
paul718e3742002-12-13 20:15:29 +00002218 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002219 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002220 break;
2221 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002222 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002223 break;
2224 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002225 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002226 break;
2227 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002228 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002229 break;
2230 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002231 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002232 break;
2233 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002234 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002235 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002236 case BGP_ATTR_ENCAP:
2237 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2238 break;
paul718e3742002-12-13 20:15:29 +00002239 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002240 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002241 break;
2242 }
Paul Jakmab881c702010-11-23 16:35:42 +00002243
David Lamparterf57000c2014-06-04 01:01:10 +02002244 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2245 {
2246 bgp_notify_send (peer,
2247 BGP_NOTIFY_UPDATE_ERR,
2248 BGP_NOTIFY_UPDATE_MAL_ATTR);
2249 ret = BGP_ATTR_PARSE_ERROR;
2250 }
2251
Paul Jakmab881c702010-11-23 16:35:42 +00002252 /* If hard error occured immediately return to the caller. */
2253 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002254 {
2255 zlog (peer->log, LOG_WARNING,
2256 "%s: Attribute %s, parse error",
2257 peer->host,
2258 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002259 if (as4_path)
2260 aspath_unintern (&as4_path);
2261 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002262 }
Paul Jakmab881c702010-11-23 16:35:42 +00002263 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2264 {
2265
2266 zlog (peer->log, LOG_WARNING,
2267 "%s: Attribute %s, parse error - treating as withdrawal",
2268 peer->host,
2269 LOOKUP (attr_str, type));
2270 if (as4_path)
2271 aspath_unintern (&as4_path);
2272 return ret;
2273 }
2274
paul718e3742002-12-13 20:15:29 +00002275 /* Check the fetched length. */
2276 if (BGP_INPUT_PNT (peer) != attr_endp)
2277 {
2278 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002279 "%s: BGP attribute %s, fetch error",
2280 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002281 bgp_notify_send (peer,
2282 BGP_NOTIFY_UPDATE_ERR,
2283 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002284 if (as4_path)
2285 aspath_unintern (&as4_path);
2286 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002287 }
2288 }
paul718e3742002-12-13 20:15:29 +00002289 /* Check final read pointer is same as end pointer. */
2290 if (BGP_INPUT_PNT (peer) != endp)
2291 {
2292 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002293 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002294 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002295 bgp_notify_send (peer,
2296 BGP_NOTIFY_UPDATE_ERR,
2297 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002298 if (as4_path)
2299 aspath_unintern (&as4_path);
2300 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002301 }
Paul Jakma055086f2014-09-23 15:23:01 +01002302
2303 /* Check all mandatory well-known attributes are present */
2304 {
2305 bgp_attr_parse_ret_t ret;
2306 if ((ret = bgp_attr_check (peer, attr)) < 0)
2307 {
2308 if (as4_path)
2309 aspath_unintern (&as4_path);
2310 return ret;
2311 }
2312 }
2313
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002314 /*
2315 * At this place we can see whether we got AS4_PATH and/or
2316 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2317 * We can not do this before we've read all attributes because
2318 * the as4 handling does not say whether AS4_PATH has to be sent
2319 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2320 * in relationship to AGGREGATOR.
2321 * So, to be defensive, we are not relying on any order and read
2322 * all attributes first, including these 32bit ones, and now,
2323 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002324 *
2325 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2326 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002327 */
David Lamparterf57000c2014-06-04 01:01:10 +02002328 /* actually... this doesn't ever return failure currently, but
2329 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002330 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2331 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002332 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002333 {
David Lamparterf57000c2014-06-04 01:01:10 +02002334 bgp_notify_send (peer,
2335 BGP_NOTIFY_UPDATE_ERR,
2336 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002337 if (as4_path)
2338 aspath_unintern (&as4_path);
2339 return BGP_ATTR_PARSE_ERROR;
2340 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002341
2342 /* At this stage, we have done all fiddling with as4, and the
2343 * resulting info is in attr->aggregator resp. attr->aspath
2344 * so we can chuck as4_aggregator and as4_path alltogether in
2345 * order to save memory
2346 */
Paul Jakmab881c702010-11-23 16:35:42 +00002347 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002348 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002349 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002350 /* The flag that we got this is still there, but that does not
2351 * do any trouble
2352 */
2353 }
2354 /*
2355 * The "rest" of the code does nothing with as4_aggregator.
2356 * there is no memory attached specifically which is not part
2357 * of the attr.
2358 * so ignoring just means do nothing.
2359 */
2360 /*
2361 * Finally do the checks on the aspath we did not do yet
2362 * because we waited for a potentially synthesized aspath.
2363 */
Paul Jakmab881c702010-11-23 16:35:42 +00002364 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002365 {
Paul Jakma835315b2012-01-18 12:28:30 +00002366 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002367 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002368 return ret;
2369 }
2370
paul718e3742002-12-13 20:15:29 +00002371 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002372 if (attr->extra && attr->extra->transit)
2373 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002374
Paul Jakmab881c702010-11-23 16:35:42 +00002375 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002376}
2377
paul718e3742002-12-13 20:15:29 +00002378int stream_put_prefix (struct stream *, struct prefix *);
2379
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002380size_t
2381bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2382 struct attr *attr)
2383{
2384 size_t sizep;
2385
2386 /* Set extended bit always to encode the attribute length as 2 bytes */
2387 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2388 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2389 sizep = stream_get_endp (s);
2390 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002391
2392 stream_putw (s, afi);
2393 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002394
2395 /* Nexthop */
2396 switch (afi)
2397 {
2398 case AFI_IP:
2399 switch (safi)
2400 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002401 case SAFI_MULTICAST:
2402 stream_putc (s, 4);
2403 stream_put_ipv4 (s, attr->nexthop.s_addr);
2404 break;
2405 case SAFI_MPLS_VPN:
2406 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002407 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002408 stream_putl (s, 0);
2409 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2410 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002411 case SAFI_ENCAP:
2412 stream_putc (s, 4);
2413 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2414 break;
Lou Berger050defe2016-01-12 13:41:59 -05002415 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002416 default:
2417 break;
2418 }
2419 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002420 case AFI_IP6:
2421 switch (safi)
2422 {
2423 case SAFI_UNICAST:
2424 case SAFI_MULTICAST:
2425 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002426 struct attr_extra *attre = attr->extra;
2427
2428 assert (attr->extra);
2429 stream_putc (s, attre->mp_nexthop_len);
2430 stream_put (s, &attre->mp_nexthop_global, 16);
2431 if (attre->mp_nexthop_len == 32)
2432 stream_put (s, &attre->mp_nexthop_local, 16);
2433 }
Lou Berger050defe2016-01-12 13:41:59 -05002434 break;
2435 case SAFI_MPLS_VPN:
2436 {
2437 struct attr_extra *attre = attr->extra;
2438
2439 assert (attr->extra);
2440 if (attre->mp_nexthop_len == 16) {
2441 stream_putc (s, 24);
2442 stream_putl (s, 0); /* RD = 0, per RFC */
2443 stream_putl (s, 0);
2444 stream_put (s, &attre->mp_nexthop_global, 16);
2445 } else if (attre->mp_nexthop_len == 32) {
2446 stream_putc (s, 48);
2447 stream_putl (s, 0); /* RD = 0, per RFC */
2448 stream_putl (s, 0);
2449 stream_put (s, &attre->mp_nexthop_global, 16);
2450 stream_putl (s, 0); /* RD = 0, per RFC */
2451 stream_putl (s, 0);
2452 stream_put (s, &attre->mp_nexthop_local, 16);
2453 }
2454 }
2455 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002456 case SAFI_ENCAP:
2457 assert (attr->extra);
2458 stream_putc (s, 16);
2459 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2460 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002461 default:
2462 break;
2463 }
2464 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002465 default:
2466 break;
2467 }
2468
2469 /* SNPA */
2470 stream_putc (s, 0);
2471 return sizep;
2472}
2473
2474void
2475bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2476 struct prefix *p, struct prefix_rd *prd,
2477 u_char *tag)
2478{
Lou Berger050defe2016-01-12 13:41:59 -05002479 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002480 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002481 /* Tag, RD, Prefix write. */
2482 stream_putc (s, p->prefixlen + 88);
2483 stream_put (s, tag, 3);
2484 stream_put (s, prd->val, 8);
2485 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002486 }
Lou Berger050defe2016-01-12 13:41:59 -05002487 else
2488 stream_put_prefix (s, p);
2489}
2490
2491size_t
2492bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2493{
2494 int size = PSIZE (p->prefixlen);
2495 if (safi == SAFI_MPLS_VPN)
2496 size += 88;
2497 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002498}
2499
Lou Bergerc3741782016-01-12 13:42:01 -05002500/*
2501 * Encodes the tunnel encapsulation attribute
2502 */
2503static void
2504bgp_packet_mpattr_tea(
2505 struct bgp *bgp,
2506 struct peer *peer,
2507 struct stream *s,
2508 struct attr *attr,
2509 uint8_t attrtype)
2510{
2511 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002512 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002513 struct bgp_attr_encap_subtlv *subtlvs;
2514 struct bgp_attr_encap_subtlv *st;
2515 const char *attrname;
2516
2517 if (!attr || !attr->extra)
2518 return;
2519
2520 switch (attrtype) {
2521 case BGP_ATTR_ENCAP:
2522 attrname = "Tunnel Encap";
2523 subtlvs = attr->extra->encap_subtlvs;
2524
2525 /*
2526 * The tunnel encap attr has an "outer" tlv.
2527 * T = tunneltype,
2528 * L = total length of subtlvs,
2529 * V = concatenated subtlvs.
2530 */
2531 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002532 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002533 break;
2534
2535 default:
2536 assert(0);
2537 }
2538
2539
Lou Berger298cc2f2016-01-12 13:42:02 -05002540 /* if no tlvs, don't make attr */
2541 if (subtlvs == NULL)
2542 return;
2543
Lou Bergerc3741782016-01-12 13:42:01 -05002544 /* compute attr length */
2545 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002546 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002547 }
2548
Lou Bergerc3741782016-01-12 13:42:01 -05002549 if (attrlenfield > 0xffff) {
2550 zlog (peer->log, LOG_ERR,
2551 "%s attribute is too long (length=%d), can't send it",
2552 attrname,
2553 attrlenfield);
2554 return;
2555 }
2556
2557 if (attrlenfield > 0xff) {
2558 /* 2-octet length field */
2559 stream_putc (s,
2560 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2561 stream_putc (s, attrtype);
2562 stream_putw (s, attrlenfield & 0xffff);
2563 } else {
2564 /* 1-octet length field */
2565 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2566 stream_putc (s, attrtype);
2567 stream_putc (s, attrlenfield & 0xff);
2568 }
2569
2570 if (attrtype == BGP_ATTR_ENCAP) {
2571 /* write outer T+L */
2572 stream_putw(s, attr->extra->encap_tunneltype);
2573 stream_putw(s, attrlenfield - 4);
2574 }
2575
2576 /* write each sub-tlv */
2577 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002578 if (attrtype == BGP_ATTR_ENCAP) {
2579 stream_putc (s, st->type);
2580 stream_putc (s, st->length);
2581 }
Lou Bergerc3741782016-01-12 13:42:01 -05002582 stream_put (s, st->value, st->length);
2583 }
2584}
2585
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002586void
2587bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2588{
2589 /* Set MP attribute length. Don't count the (2) bytes used to encode
2590 the attr length */
2591 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2592}
2593
paul718e3742002-12-13 20:15:29 +00002594/* Make attribute packet. */
2595bgp_size_t
2596bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002597 struct stream *s, struct attr *attr,
2598 struct prefix *p, afi_t afi, safi_t safi,
2599 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002600{
paulfe69a502005-09-10 16:55:02 +00002601 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002602 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002603 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002604 int send_as4_path = 0;
2605 int send_as4_aggregator = 0;
2606 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002607
2608 if (! bgp)
2609 bgp = bgp_get_default ();
2610
2611 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002612 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002613
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002614 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2615 {
Lou Berger050defe2016-01-12 13:41:59 -05002616 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002617 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2618 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2619 bgp_packet_mpattr_end(s, mpattrlen_pos);
2620 }
2621
paul718e3742002-12-13 20:15:29 +00002622 /* Origin attribute. */
2623 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2624 stream_putc (s, BGP_ATTR_ORIGIN);
2625 stream_putc (s, 1);
2626 stream_putc (s, attr->origin);
2627
2628 /* AS path attribute. */
2629
2630 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002631 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002632 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002633 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002634 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002635 {
2636 aspath = aspath_dup (attr->aspath);
2637
2638 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2639 {
2640 /* Strip the confed info, and then stuff our path CONFED_ID
2641 on the front */
2642 aspath = aspath_delete_confed_seq (aspath);
2643 aspath = aspath_add_seq (aspath, bgp->confed_id);
2644 }
2645 else
2646 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002647 if (peer->change_local_as) {
2648 /* If replace-as is specified, we only use the change_local_as when
2649 advertising routes. */
2650 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2651 aspath = aspath_add_seq (aspath, peer->local_as);
2652 }
paul718e3742002-12-13 20:15:29 +00002653 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002654 } else {
2655 aspath = aspath_add_seq (aspath, peer->local_as);
2656 }
paul718e3742002-12-13 20:15:29 +00002657 }
2658 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002659 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002660 {
2661 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2662 aspath = aspath_dup (attr->aspath);
2663 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2664 }
2665 else
2666 aspath = attr->aspath;
2667
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002668 /* If peer is not AS4 capable, then:
2669 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2670 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2671 * types are in it (i.e. exclude them if they are there)
2672 * AND do this only if there is at least one asnum > 65535 in the path!
2673 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2674 * all ASnums > 65535 to BGP_AS_TRANS
2675 */
paul718e3742002-12-13 20:15:29 +00002676
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002677 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2678 stream_putc (s, BGP_ATTR_AS_PATH);
2679 aspath_sizep = stream_get_endp (s);
2680 stream_putw (s, 0);
2681 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2682
2683 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2684 * in the path
2685 */
2686 if (!use32bit && aspath_has_as4 (aspath))
2687 send_as4_path = 1; /* we'll do this later, at the correct place */
2688
paul718e3742002-12-13 20:15:29 +00002689 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002690 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2691 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002692 {
2693 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2694 stream_putc (s, BGP_ATTR_NEXT_HOP);
2695 stream_putc (s, 4);
2696 if (safi == SAFI_MPLS_VPN)
2697 {
2698 if (attr->nexthop.s_addr == 0)
2699 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2700 else
2701 stream_put_ipv4 (s, attr->nexthop.s_addr);
2702 }
2703 else
2704 stream_put_ipv4 (s, attr->nexthop.s_addr);
2705 }
2706
2707 /* MED attribute. */
2708 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2709 {
2710 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2711 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2712 stream_putc (s, 4);
2713 stream_putl (s, attr->med);
2714 }
2715
2716 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002717 if (peer->sort == BGP_PEER_IBGP ||
2718 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002719 {
2720 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2721 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2722 stream_putc (s, 4);
2723 stream_putl (s, attr->local_pref);
2724 }
2725
2726 /* Atomic aggregate. */
2727 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2728 {
2729 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2730 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2731 stream_putc (s, 0);
2732 }
2733
2734 /* Aggregator. */
2735 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2736 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002737 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002738
2739 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002740 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2741 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002742
2743 if (use32bit)
2744 {
2745 /* AS4 capable peer */
2746 stream_putc (s, 8);
2747 stream_putl (s, attr->extra->aggregator_as);
2748 }
2749 else
2750 {
2751 /* 2-byte AS peer */
2752 stream_putc (s, 6);
2753
2754 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2755 if ( attr->extra->aggregator_as > 65535 )
2756 {
2757 stream_putw (s, BGP_AS_TRANS);
2758
2759 /* we have to send AS4_AGGREGATOR, too.
2760 * we'll do that later in order to send attributes in ascending
2761 * order.
2762 */
2763 send_as4_aggregator = 1;
2764 }
2765 else
2766 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2767 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002768 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002769 }
2770
2771 /* Community attribute. */
2772 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2773 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2774 {
2775 if (attr->community->size * 4 > 255)
2776 {
2777 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2778 stream_putc (s, BGP_ATTR_COMMUNITIES);
2779 stream_putw (s, attr->community->size * 4);
2780 }
2781 else
2782 {
2783 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2784 stream_putc (s, BGP_ATTR_COMMUNITIES);
2785 stream_putc (s, attr->community->size * 4);
2786 }
2787 stream_put (s, attr->community->val, attr->community->size * 4);
2788 }
2789
2790 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002791 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002792 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002793 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002794 {
2795 /* Originator ID. */
2796 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2797 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2798 stream_putc (s, 4);
2799
2800 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002801 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002802 else
2803 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002804
2805 /* Cluster list. */
2806 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2807 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2808
Paul Jakma9eda90c2007-08-30 13:36:17 +00002809 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002810 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002811 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002812 /* If this peer configuration's parent BGP has cluster_id. */
2813 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2814 stream_put_in_addr (s, &bgp->cluster_id);
2815 else
2816 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002817 stream_put (s, attr->extra->cluster->list,
2818 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002819 }
2820 else
2821 {
2822 stream_putc (s, 4);
2823 /* If this peer configuration's parent BGP has cluster_id. */
2824 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2825 stream_put_in_addr (s, &bgp->cluster_id);
2826 else
2827 stream_put_in_addr (s, &bgp->router_id);
2828 }
2829 }
2830
paul718e3742002-12-13 20:15:29 +00002831 /* Extended Communities attribute. */
2832 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2833 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2834 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002835 struct attr_extra *attre = attr->extra;
2836
2837 assert (attre);
2838
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002839 if (peer->sort == BGP_PEER_IBGP
2840 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002841 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002842 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002843 {
2844 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2845 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002846 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002847 }
2848 else
2849 {
2850 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2851 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002852 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002853 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002854 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002855 }
2856 else
2857 {
paul5228ad22004-06-04 17:58:18 +00002858 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002859 int tbit;
2860 int ecom_tr_size = 0;
2861 int i;
2862
Paul Jakmafb982c22007-05-04 20:15:47 +00002863 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002864 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002865 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002866 tbit = *pnt;
2867
2868 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2869 continue;
2870
2871 ecom_tr_size++;
2872 }
2873
2874 if (ecom_tr_size)
2875 {
2876 if (ecom_tr_size * 8 > 255)
2877 {
2878 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2879 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2880 stream_putw (s, ecom_tr_size * 8);
2881 }
2882 else
2883 {
2884 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2885 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2886 stream_putc (s, ecom_tr_size * 8);
2887 }
2888
Paul Jakmafb982c22007-05-04 20:15:47 +00002889 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002890 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002891 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002892 tbit = *pnt;
2893
2894 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2895 continue;
2896
2897 stream_put (s, pnt, 8);
2898 }
2899 }
paul718e3742002-12-13 20:15:29 +00002900 }
paul718e3742002-12-13 20:15:29 +00002901 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002902
2903 if ( send_as4_path )
2904 {
2905 /* If the peer is NOT As4 capable, AND */
2906 /* there are ASnums > 65535 in path THEN
2907 * give out AS4_PATH */
2908
2909 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2910 * path segments!
2911 * Hm, I wonder... confederation things *should* only be at
2912 * the beginning of an aspath, right? Then we should use
2913 * aspath_delete_confed_seq for this, because it is already
2914 * there! (JK)
2915 * Folks, talk to me: what is reasonable here!?
2916 */
2917 aspath = aspath_delete_confed_seq (aspath);
2918
2919 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2920 stream_putc (s, BGP_ATTR_AS4_PATH);
2921 aspath_sizep = stream_get_endp (s);
2922 stream_putw (s, 0);
2923 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2924 }
2925
2926 if (aspath != attr->aspath)
2927 aspath_free (aspath);
2928
2929 if ( send_as4_aggregator )
2930 {
2931 assert (attr->extra);
2932
2933 /* send AS4_AGGREGATOR, at this place */
2934 /* this section of code moved here in order to ensure the correct
2935 * *ascending* order of attributes
2936 */
2937 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2938 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2939 stream_putc (s, 8);
2940 stream_putl (s, attr->extra->aggregator_as);
2941 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2942 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002943
2944 if ((afi == AFI_IP || afi == AFI_IP6) &&
2945 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2946 {
2947 /* Tunnel Encap attribute */
2948 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2949 }
2950
paul718e3742002-12-13 20:15:29 +00002951 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002952 if (attr->extra && attr->extra->transit)
2953 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002954
2955 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002956 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002957}
2958
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002959size_t
2960bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002961{
paul718e3742002-12-13 20:15:29 +00002962 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002963
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002964 /* Set extended bit always to encode the attribute length as 2 bytes */
2965 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002966 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2967
paul9985f832005-02-09 15:51:56 +00002968 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002969 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002970
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002971 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002972 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002973 return attrlen_pnt;
2974}
paul718e3742002-12-13 20:15:29 +00002975
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002976void
2977bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2978 afi_t afi, safi_t safi, struct prefix_rd *prd,
2979 u_char *tag)
2980{
Lou Berger050defe2016-01-12 13:41:59 -05002981 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002982}
paul718e3742002-12-13 20:15:29 +00002983
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002984void
2985bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2986{
Lou Berger050defe2016-01-12 13:41:59 -05002987 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002988}
2989
2990/* Initialization of attribute. */
2991void
paulfe69a502005-09-10 16:55:02 +00002992bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002993{
paul718e3742002-12-13 20:15:29 +00002994 aspath_init ();
2995 attrhash_init ();
2996 community_init ();
2997 ecommunity_init ();
2998 cluster_init ();
2999 transit_init ();
3000}
3001
Chris Caputo228da422009-07-18 05:44:03 +00003002void
3003bgp_attr_finish (void)
3004{
3005 aspath_finish ();
3006 attrhash_finish ();
3007 community_finish ();
3008 ecommunity_finish ();
3009 cluster_finish ();
3010 transit_finish ();
3011}
3012
paul718e3742002-12-13 20:15:29 +00003013/* Make attribute packet. */
3014void
paula3845922003-10-18 01:30:50 +00003015bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3016 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003017{
3018 unsigned long cp;
3019 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003020 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003021 struct aspath *aspath;
3022
3023 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003024 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003025
3026 /* Place holder of length. */
3027 stream_putw (s, 0);
3028
3029 /* Origin attribute. */
3030 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3031 stream_putc (s, BGP_ATTR_ORIGIN);
3032 stream_putc (s, 1);
3033 stream_putc (s, attr->origin);
3034
3035 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003036
3037 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3038 stream_putc (s, BGP_ATTR_AS_PATH);
3039 aspath_lenp = stream_get_endp (s);
3040 stream_putw (s, 0);
3041
3042 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003043
3044 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003045 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3046 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003047 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003048 )
3049 {
3050 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3051 stream_putc (s, BGP_ATTR_NEXT_HOP);
3052 stream_putc (s, 4);
3053 stream_put_ipv4 (s, attr->nexthop.s_addr);
3054 }
paul718e3742002-12-13 20:15:29 +00003055
3056 /* MED attribute. */
3057 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3058 {
3059 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3060 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3061 stream_putc (s, 4);
3062 stream_putl (s, attr->med);
3063 }
3064
3065 /* Local preference. */
3066 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3067 {
3068 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3069 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3070 stream_putc (s, 4);
3071 stream_putl (s, attr->local_pref);
3072 }
3073
3074 /* Atomic aggregate. */
3075 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3076 {
3077 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3078 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3079 stream_putc (s, 0);
3080 }
3081
3082 /* Aggregator. */
3083 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3084 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003085 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003086 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3087 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003088 stream_putc (s, 8);
3089 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003090 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003091 }
3092
3093 /* Community attribute. */
3094 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3095 {
3096 if (attr->community->size * 4 > 255)
3097 {
3098 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3099 stream_putc (s, BGP_ATTR_COMMUNITIES);
3100 stream_putw (s, attr->community->size * 4);
3101 }
3102 else
3103 {
3104 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3105 stream_putc (s, BGP_ATTR_COMMUNITIES);
3106 stream_putc (s, attr->community->size * 4);
3107 }
3108 stream_put (s, attr->community->val, attr->community->size * 4);
3109 }
3110
paula3845922003-10-18 01:30:50 +00003111 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003112 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3113 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003114 {
3115 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003116 struct attr_extra *attre = attr->extra;
3117
paula3845922003-10-18 01:30:50 +00003118 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3119 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003120 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003121
3122 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003123 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003124 stream_putw(s, AFI_IP6); /* AFI */
3125 stream_putc(s, SAFI_UNICAST); /* SAFI */
3126
3127 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003128 stream_putc(s, attre->mp_nexthop_len);
3129 stream_put(s, &attre->mp_nexthop_global, 16);
3130 if (attre->mp_nexthop_len == 32)
3131 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003132
3133 /* SNPA */
3134 stream_putc(s, 0);
3135
3136 /* Prefix */
3137 stream_put_prefix(s, prefix);
3138
3139 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003140 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003141 }
paula3845922003-10-18 01:30:50 +00003142
paul718e3742002-12-13 20:15:29 +00003143 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003144 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003145 stream_putw_at (s, cp, len);
3146}