blob: 54ff54446913a23c97525bb4d60a39f708c9afc2 [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);
Lou Bergerf53585d2016-05-17 07:10:36 -04001252 if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
1253 && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001254 {
1255 char buf[INET_ADDRSTRLEN];
David Lamparterbb02b822014-06-04 01:01:00 +02001256 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001257 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
Paul Jakma835315b2012-01-18 12:28:30 +00001258 return bgp_attr_malformed (args,
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001259 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
Paul Jakma835315b2012-01-18 12:28:30 +00001260 args->total);
Denis Ovsienkobc3443e2011-09-22 12:48:14 +04001261 }
1262
1263 attr->nexthop.s_addr = nexthop_n;
paul718e3742002-12-13 20:15:29 +00001264 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1265
Paul Jakmab881c702010-11-23 16:35:42 +00001266 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001267}
1268
1269/* MED atrribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001270static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001271bgp_attr_med (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001272{
Paul Jakma835315b2012-01-18 12:28:30 +00001273 struct peer *const peer = args->peer;
1274 struct attr *const attr = args->attr;
1275 const bgp_size_t length = args->length;
1276
paul718e3742002-12-13 20:15:29 +00001277 /* Length check. */
1278 if (length != 4)
1279 {
1280 zlog (peer->log, LOG_ERR,
1281 "MED attribute length isn't four [%d]", length);
Paul Jakmab881c702010-11-23 16:35:42 +00001282
Paul Jakma835315b2012-01-18 12:28:30 +00001283 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001284 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001285 args->total);
paul718e3742002-12-13 20:15:29 +00001286 }
1287
1288 attr->med = stream_getl (peer->ibuf);
1289
1290 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1291
Paul Jakmab881c702010-11-23 16:35:42 +00001292 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001293}
1294
1295/* Local preference attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001296static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001297bgp_attr_local_pref (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001298{
Paul Jakma835315b2012-01-18 12:28:30 +00001299 struct peer *const peer = args->peer;
1300 struct attr *const attr = args->attr;
1301 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001302
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001303 /* Length check. */
1304 if (length != 4)
1305 {
Paul Jakma835315b2012-01-18 12:28:30 +00001306 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
1307 length);
1308 return bgp_attr_malformed (args,
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001309 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001310 args->total);
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001311 }
Denis Ovsienko0ea968d2011-09-19 16:30:47 +04001312
paul718e3742002-12-13 20:15:29 +00001313 /* If it is contained in an UPDATE message that is received from an
1314 external peer, then this attribute MUST be ignored by the
1315 receiving speaker. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00001316 if (peer->sort == BGP_PEER_EBGP)
paul718e3742002-12-13 20:15:29 +00001317 {
paul9985f832005-02-09 15:51:56 +00001318 stream_forward_getp (peer->ibuf, length);
Paul Jakmab881c702010-11-23 16:35:42 +00001319 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001320 }
1321
Denis Ovsienkoa624cae2011-10-08 13:54:48 +04001322 attr->local_pref = stream_getl (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001323
1324 /* Set atomic aggregate flag. */
1325 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1326
Paul Jakmab881c702010-11-23 16:35:42 +00001327 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001328}
1329
1330/* Atomic aggregate. */
paul94f2b392005-06-28 12:44:16 +00001331static int
Paul Jakma835315b2012-01-18 12:28:30 +00001332bgp_attr_atomic (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001333{
Paul Jakma835315b2012-01-18 12:28:30 +00001334 struct peer *const peer = args->peer;
1335 struct attr *const attr = args->attr;
1336 const bgp_size_t length = args->length;
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001337
Denis Ovsienko9eba2ad2011-09-20 14:43:50 +04001338 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001339 if (length != 0)
1340 {
Paul Jakma835315b2012-01-18 12:28:30 +00001341 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1342 length);
1343 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001344 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001345 args->total);
paul718e3742002-12-13 20:15:29 +00001346 }
1347
1348 /* Set atomic aggregate flag. */
1349 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1350
Paul Jakmab881c702010-11-23 16:35:42 +00001351 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001352}
1353
1354/* Aggregator attribute */
paul94f2b392005-06-28 12:44:16 +00001355static int
Paul Jakma835315b2012-01-18 12:28:30 +00001356bgp_attr_aggregator (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001357{
Paul Jakma835315b2012-01-18 12:28:30 +00001358 struct peer *const peer = args->peer;
1359 struct attr *const attr = args->attr;
1360 const bgp_size_t length = args->length;
1361
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001362 int wantedlen = 6;
Paul Jakmafb982c22007-05-04 20:15:47 +00001363 struct attr_extra *attre = bgp_attr_extra_get (attr);
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001364
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001365 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
Paul Jakmab881c702010-11-23 16:35:42 +00001366 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001367 wantedlen = 8;
1368
1369 if (length != wantedlen)
paul718e3742002-12-13 20:15:29 +00001370 {
Paul Jakma835315b2012-01-18 12:28:30 +00001371 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
1372 wantedlen, length);
1373 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001374 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001375 args->total);
paul718e3742002-12-13 20:15:29 +00001376 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001377
1378 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1379 attre->aggregator_as = stream_getl (peer->ibuf);
1380 else
1381 attre->aggregator_as = stream_getw (peer->ibuf);
Paul Jakmafb982c22007-05-04 20:15:47 +00001382 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001383
1384 /* Set atomic aggregate flag. */
1385 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1386
Paul Jakmab881c702010-11-23 16:35:42 +00001387 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001388}
1389
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001390/* New Aggregator attribute */
Paul Jakmab881c702010-11-23 16:35:42 +00001391static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001392bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
1393 as_t *as4_aggregator_as,
1394 struct in_addr *as4_aggregator_addr)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001395{
Paul Jakma835315b2012-01-18 12:28:30 +00001396 struct peer *const peer = args->peer;
1397 struct attr *const attr = args->attr;
1398 const bgp_size_t length = args->length;
1399
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001400 if (length != 8)
1401 {
Paul Jakma835315b2012-01-18 12:28:30 +00001402 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
1403 length);
1404 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001405 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001406 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001407 }
Paul Jakma3ecab4c2012-01-17 13:31:33 +00001408
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001409 *as4_aggregator_as = stream_getl (peer->ibuf);
1410 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1411
1412 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1413
Paul Jakmab881c702010-11-23 16:35:42 +00001414 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001415}
1416
1417/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1418 */
Paul Jakmab881c702010-11-23 16:35:42 +00001419static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001420bgp_attr_munge_as4_attrs (struct peer *const peer,
1421 struct attr *const attr,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001422 struct aspath *as4_path, as_t as4_aggregator,
1423 struct in_addr *as4_aggregator_addr)
1424{
1425 int ignore_as4_path = 0;
1426 struct aspath *newpath;
1427 struct attr_extra *attre = attr->extra;
Paul Jakma055086f2014-09-23 15:23:01 +01001428
1429 if (!attr->aspath)
1430 {
1431 /* NULL aspath shouldn't be possible as bgp_attr_parse should have
1432 * checked that all well-known, mandatory attributes were present.
1433 *
1434 * Can only be a problem with peer itself - hard error
1435 */
1436 return BGP_ATTR_PARSE_ERROR;
1437 }
1438
Paul Jakmab881c702010-11-23 16:35:42 +00001439 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001440 {
1441 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1442 * if given.
1443 * It is worth a warning though, because the peer really
1444 * should not send them
1445 */
1446 if (BGP_DEBUG(as4, AS4))
1447 {
1448 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1449 zlog_debug ("[AS4] %s %s AS4_PATH",
1450 peer->host, "AS4 capable peer, yet it sent");
1451
1452 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1453 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1454 peer->host, "AS4 capable peer, yet it sent");
1455 }
1456
Paul Jakmab881c702010-11-23 16:35:42 +00001457 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001458 }
1459
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001460 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1461 * because that may override AS4_PATH
1462 */
1463 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1464 {
Paul Jakmab881c702010-11-23 16:35:42 +00001465 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001466 {
Paul Jakma370b64a2007-12-22 16:49:52 +00001467 assert (attre);
1468
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001469 /* received both.
1470 * if the as_number in aggregator is not AS_TRANS,
1471 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1472 * and the Aggregator shall be taken as
1473 * info on the aggregating node, and the AS_PATH
1474 * shall be taken as the AS_PATH
1475 * otherwise
1476 * the Aggregator shall be ignored and the
1477 * AS4_AGGREGATOR shall be taken as the
1478 * Aggregating node and the AS_PATH is to be
1479 * constructed "as in all other cases"
1480 */
Paul Jakmab881c702010-11-23 16:35:42 +00001481 if (attre->aggregator_as != BGP_AS_TRANS)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001482 {
1483 /* ignore */
1484 if ( BGP_DEBUG(as4, AS4))
1485 zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1486 " send AGGREGATOR != AS_TRANS and"
1487 " AS4_AGGREGATOR, so ignore"
1488 " AS4_AGGREGATOR and AS4_PATH", peer->host);
1489 ignore_as4_path = 1;
1490 }
1491 else
1492 {
1493 /* "New_aggregator shall be taken as aggregator" */
1494 attre->aggregator_as = as4_aggregator;
1495 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1496 }
1497 }
1498 else
1499 {
1500 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1501 * That is bogus - but reading the conditions
1502 * we have to handle AS4_AGGREGATOR as if it were
1503 * AGGREGATOR in that case
1504 */
1505 if ( BGP_DEBUG(as4, AS4))
1506 zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1507 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1508 " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
Paul Jakma370b64a2007-12-22 16:49:52 +00001509 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001510 /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1511 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1512 }
1513 }
1514
1515 /* need to reconcile NEW_AS_PATH and AS_PATH */
Paul Jakmab881c702010-11-23 16:35:42 +00001516 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001517 {
Paul Jakma055086f2014-09-23 15:23:01 +01001518 newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1519 aspath_unintern (&attr->aspath);
1520 attr->aspath = aspath_intern (newpath);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001521 }
Paul Jakmab881c702010-11-23 16:35:42 +00001522 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001523}
1524
paul718e3742002-12-13 20:15:29 +00001525/* Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001526static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001527bgp_attr_community (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001528{
Paul Jakma835315b2012-01-18 12:28:30 +00001529 struct peer *const peer = args->peer;
1530 struct attr *const attr = args->attr;
1531 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001532
paul718e3742002-12-13 20:15:29 +00001533 if (length == 0)
Paul Jakmab2ceea12007-09-07 14:24:55 +00001534 {
1535 attr->community = NULL;
Paul Jakmab881c702010-11-23 16:35:42 +00001536 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmab2ceea12007-09-07 14:24:55 +00001537 }
Paul Jakma0c466382010-12-05 17:17:26 +00001538
1539 attr->community =
1540 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1541
1542 /* XXX: fix community_parse to use stream API and remove this */
1543 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001544
Paul Jakma0c466382010-12-05 17:17:26 +00001545 if (!attr->community)
Paul Jakma835315b2012-01-18 12:28:30 +00001546 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001547 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001548 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001549
paul718e3742002-12-13 20:15:29 +00001550 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1551
Paul Jakmab881c702010-11-23 16:35:42 +00001552 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001553}
1554
1555/* Originator ID attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001556static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001557bgp_attr_originator_id (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001558{
Paul Jakma835315b2012-01-18 12:28:30 +00001559 struct peer *const peer = args->peer;
1560 struct attr *const attr = args->attr;
1561 const bgp_size_t length = args->length;
1562
Denis Ovsienkod595b562011-09-30 15:08:54 +04001563 /* Length check. */
paul718e3742002-12-13 20:15:29 +00001564 if (length != 4)
1565 {
1566 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1567
Paul Jakma835315b2012-01-18 12:28:30 +00001568 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001569 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
Paul Jakma835315b2012-01-18 12:28:30 +00001570 args->total);
paul718e3742002-12-13 20:15:29 +00001571 }
1572
Paul Jakmafb982c22007-05-04 20:15:47 +00001573 (bgp_attr_extra_get (attr))->originator_id.s_addr
1574 = stream_get_ipv4 (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001575
1576 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1577
Paul Jakmab881c702010-11-23 16:35:42 +00001578 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001579}
1580
1581/* Cluster list attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001582static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001583bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001584{
Paul Jakma835315b2012-01-18 12:28:30 +00001585 struct peer *const peer = args->peer;
1586 struct attr *const attr = args->attr;
1587 const bgp_size_t length = args->length;
1588
paul718e3742002-12-13 20:15:29 +00001589 /* Check length. */
1590 if (length % 4)
1591 {
1592 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1593
Paul Jakma835315b2012-01-18 12:28:30 +00001594 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1595 args->total);
paul718e3742002-12-13 20:15:29 +00001596 }
1597
Paul Jakmafb982c22007-05-04 20:15:47 +00001598 (bgp_attr_extra_get (attr))->cluster
1599 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
Paul Jakmab881c702010-11-23 16:35:42 +00001600
1601 /* XXX: Fix cluster_parse to use stream API and then remove this */
1602 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001603
1604 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1605
Paul Jakmab881c702010-11-23 16:35:42 +00001606 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001607}
1608
1609/* Multiprotocol reachability information parse. */
Paul Jakma03292802008-06-07 20:37:10 +00001610int
Paul Jakma835315b2012-01-18 12:28:30 +00001611bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
1612 struct bgp_nlri *mp_update)
paul718e3742002-12-13 20:15:29 +00001613{
Michael Lambert4c9641b2010-07-22 13:20:55 -04001614 afi_t afi;
1615 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001616 bgp_size_t nlri_len;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001617 size_t start;
paul718e3742002-12-13 20:15:29 +00001618 struct stream *s;
Paul Jakma835315b2012-01-18 12:28:30 +00001619 struct peer *const peer = args->peer;
1620 struct attr *const attr = args->attr;
1621 const bgp_size_t length = args->length;
Paul Jakmafb982c22007-05-04 20:15:47 +00001622 struct attr_extra *attre = bgp_attr_extra_get(attr);
Paul Jakma835315b2012-01-18 12:28:30 +00001623
paul718e3742002-12-13 20:15:29 +00001624 /* Set end of packet. */
Paul Jakma6e4ab122007-04-10 19:36:48 +00001625 s = BGP_INPUT(peer);
1626 start = stream_get_getp(s);
1627
1628 /* safe to read statically sized header? */
1629#define BGP_MP_REACH_MIN_SIZE 5
Paul Jakma03292802008-06-07 20:37:10 +00001630#define LEN_LEFT (length - (stream_get_getp(s) - start))
Paul Jakma6e4ab122007-04-10 19:36:48 +00001631 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
Paul Jakma03292802008-06-07 20:37:10 +00001632 {
1633 zlog_info ("%s: %s sent invalid length, %lu",
1634 __func__, peer->host, (unsigned long)length);
David Lamparterf57000c2014-06-04 01:01:10 +02001635 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001636 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001637
paul718e3742002-12-13 20:15:29 +00001638 /* Load AFI, SAFI. */
1639 afi = stream_getw (s);
1640 safi = stream_getc (s);
1641
1642 /* Get nexthop length. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001643 attre->mp_nexthop_len = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001644
Paul Jakma03292802008-06-07 20:37:10 +00001645 if (LEN_LEFT < attre->mp_nexthop_len)
1646 {
1647 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1648 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001649 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001650 }
Paul Jakma6e4ab122007-04-10 19:36:48 +00001651
paul718e3742002-12-13 20:15:29 +00001652 /* Nexthop length check. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001653 switch (attre->mp_nexthop_len)
paul718e3742002-12-13 20:15:29 +00001654 {
1655 case 4:
Paul Jakmafb982c22007-05-04 20:15:47 +00001656 stream_get (&attre->mp_nexthop_global_in, s, 4);
Michael Lambert66bed4f2009-07-28 11:26:14 -04001657 /* Probably needed for RFC 2283 */
1658 if (attr->nexthop.s_addr == 0)
1659 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
paul718e3742002-12-13 20:15:29 +00001660 break;
1661 case 12:
Stephen Hemminger9206f9e2011-12-18 19:43:40 +04001662 stream_getl (s); /* RD high */
1663 stream_getl (s); /* RD low */
1664 stream_get (&attre->mp_nexthop_global_in, s, 4);
paul718e3742002-12-13 20:15:29 +00001665 break;
Lou Berger9da04bc2016-01-12 13:41:55 -05001666 case 24:
1667 {
1668 u_int32_t rd_high __attribute__((unused));
1669 u_int32_t rd_low __attribute__((unused));
1670
1671 rd_high = stream_getl (s);
1672 rd_low = stream_getl (s);
1673 }
1674 /* fall through */
paul718e3742002-12-13 20:15:29 +00001675 case 16:
Paul Jakmafb982c22007-05-04 20:15:47 +00001676 stream_get (&attre->mp_nexthop_global, s, 16);
paul718e3742002-12-13 20:15:29 +00001677 break;
1678 case 32:
Lou Berger9da04bc2016-01-12 13:41:55 -05001679 case 48:
1680 if (attre->mp_nexthop_len == 48) {
1681 u_int32_t rd_high __attribute__((unused));
1682 u_int32_t rd_low __attribute__((unused));
1683
1684 rd_high = stream_getl (s);
1685 rd_low = stream_getl (s);
1686 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001687 stream_get (&attre->mp_nexthop_global, s, 16);
Lou Berger9da04bc2016-01-12 13:41:55 -05001688
1689 if (attre->mp_nexthop_len == 48) {
1690 u_int32_t rd_high __attribute__((unused));
1691 u_int32_t rd_low __attribute__((unused));
1692
1693 rd_high = stream_getl (s);
1694 rd_low = stream_getl (s);
1695 }
Paul Jakmafb982c22007-05-04 20:15:47 +00001696 stream_get (&attre->mp_nexthop_local, s, 16);
1697 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
paul718e3742002-12-13 20:15:29 +00001698 {
1699 char buf1[INET6_ADDRSTRLEN];
1700 char buf2[INET6_ADDRSTRLEN];
1701
1702 if (BGP_DEBUG (update, UPDATE_IN))
ajs557865c2004-12-08 19:59:11 +00001703 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 +00001704 inet_ntop (AF_INET6, &attre->mp_nexthop_global,
paul718e3742002-12-13 20:15:29 +00001705 buf1, INET6_ADDRSTRLEN),
Paul Jakmafb982c22007-05-04 20:15:47 +00001706 inet_ntop (AF_INET6, &attre->mp_nexthop_local,
paul718e3742002-12-13 20:15:29 +00001707 buf2, INET6_ADDRSTRLEN));
1708
Paul Jakmafb982c22007-05-04 20:15:47 +00001709 attre->mp_nexthop_len = 16;
paul718e3742002-12-13 20:15:29 +00001710 }
1711 break;
paul718e3742002-12-13 20:15:29 +00001712 default:
Paul Jakma03292802008-06-07 20:37:10 +00001713 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1714 __func__, peer->host, attre->mp_nexthop_len);
David Lamparterf57000c2014-06-04 01:01:10 +02001715 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
paul718e3742002-12-13 20:15:29 +00001716 }
1717
Paul Jakma03292802008-06-07 20:37:10 +00001718 if (!LEN_LEFT)
1719 {
1720 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1721 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001722 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001723 }
paul718e3742002-12-13 20:15:29 +00001724
Paul Jakma6e4ab122007-04-10 19:36:48 +00001725 {
1726 u_char val;
1727 if ((val = stream_getc (s)))
1728 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1729 peer->host, val);
1730 }
1731
1732 /* must have nrli_len, what is left of the attribute */
Paul Jakma03292802008-06-07 20:37:10 +00001733 nlri_len = LEN_LEFT;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001734 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
Paul Jakma03292802008-06-07 20:37:10 +00001735 {
1736 zlog_info ("%s: (%s) Failed to read NLRI",
1737 __func__, peer->host);
David Lamparterf57000c2014-06-04 01:01:10 +02001738 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma03292802008-06-07 20:37:10 +00001739 }
Paul Jakma18ab08b2016-01-27 16:37:33 +00001740
paul718e3742002-12-13 20:15:29 +00001741 mp_update->afi = afi;
1742 mp_update->safi = safi;
1743 mp_update->nlri = stream_pnt (s);
1744 mp_update->length = nlri_len;
1745
paul9985f832005-02-09 15:51:56 +00001746 stream_forward_getp (s, nlri_len);
paul718e3742002-12-13 20:15:29 +00001747
David Lamparterdaefeb82014-12-08 17:42:12 +01001748 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
1749
Paul Jakmab881c702010-11-23 16:35:42 +00001750 return BGP_ATTR_PARSE_PROCEED;
Paul Jakma03292802008-06-07 20:37:10 +00001751#undef LEN_LEFT
paul718e3742002-12-13 20:15:29 +00001752}
1753
1754/* Multiprotocol unreachable parse */
Paul Jakma03292802008-06-07 20:37:10 +00001755int
Paul Jakma835315b2012-01-18 12:28:30 +00001756bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
paul718e3742002-12-13 20:15:29 +00001757 struct bgp_nlri *mp_withdraw)
1758{
1759 struct stream *s;
Michael Lambert4c9641b2010-07-22 13:20:55 -04001760 afi_t afi;
1761 safi_t safi;
paul718e3742002-12-13 20:15:29 +00001762 u_int16_t withdraw_len;
Paul Jakma835315b2012-01-18 12:28:30 +00001763 struct peer *const peer = args->peer;
David Lamparterdaefeb82014-12-08 17:42:12 +01001764 struct attr *const attr = args->attr;
Paul Jakma835315b2012-01-18 12:28:30 +00001765 const bgp_size_t length = args->length;
paul718e3742002-12-13 20:15:29 +00001766
1767 s = peer->ibuf;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001768
1769#define BGP_MP_UNREACH_MIN_SIZE 3
1770 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
David Lamparterf57000c2014-06-04 01:01:10 +02001771 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
Paul Jakma6e4ab122007-04-10 19:36:48 +00001772
paul718e3742002-12-13 20:15:29 +00001773 afi = stream_getw (s);
1774 safi = stream_getc (s);
Paul Jakma6e4ab122007-04-10 19:36:48 +00001775
1776 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
paul718e3742002-12-13 20:15:29 +00001777
paul718e3742002-12-13 20:15:29 +00001778 mp_withdraw->afi = afi;
1779 mp_withdraw->safi = safi;
1780 mp_withdraw->nlri = stream_pnt (s);
1781 mp_withdraw->length = withdraw_len;
1782
paul9985f832005-02-09 15:51:56 +00001783 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001784
David Lamparterdaefeb82014-12-08 17:42:12 +01001785 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
1786
Paul Jakmab881c702010-11-23 16:35:42 +00001787 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001788}
1789
1790/* Extended Community attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001791static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001792bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001793{
Paul Jakma835315b2012-01-18 12:28:30 +00001794 struct peer *const peer = args->peer;
1795 struct attr *const attr = args->attr;
1796 const bgp_size_t length = args->length;
Paul Jakmab881c702010-11-23 16:35:42 +00001797
paul718e3742002-12-13 20:15:29 +00001798 if (length == 0)
Paul Jakmafb982c22007-05-04 20:15:47 +00001799 {
1800 if (attr->extra)
1801 attr->extra->ecommunity = NULL;
Paul Jakma0c466382010-12-05 17:17:26 +00001802 /* Empty extcomm doesn't seem to be invalid per se */
Paul Jakmab881c702010-11-23 16:35:42 +00001803 return BGP_ATTR_PARSE_PROCEED;
Paul Jakmafb982c22007-05-04 20:15:47 +00001804 }
Paul Jakma0c466382010-12-05 17:17:26 +00001805
1806 (bgp_attr_extra_get (attr))->ecommunity =
1807 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1808 /* XXX: fix ecommunity_parse to use stream API */
1809 stream_forward_getp (peer->ibuf, length);
1810
1811 if (!attr->extra->ecommunity)
Paul Jakma835315b2012-01-18 12:28:30 +00001812 return bgp_attr_malformed (args,
1813 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1814 args->total);
Paul Jakma0c466382010-12-05 17:17:26 +00001815
paul718e3742002-12-13 20:15:29 +00001816 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1817
Paul Jakmab881c702010-11-23 16:35:42 +00001818 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001819}
1820
Lou Bergerc3741782016-01-12 13:42:01 -05001821/* Parse Tunnel Encap attribute in an UPDATE */
1822static int
1823bgp_attr_encap(
1824 uint8_t type,
1825 struct peer *peer, /* IN */
1826 bgp_size_t length, /* IN: attr's length field */
1827 struct attr *attr, /* IN: caller already allocated */
1828 u_char flag, /* IN: attr's flags field */
1829 u_char *startp)
1830{
1831 bgp_size_t total;
1832 struct attr_extra *attre = NULL;
1833 struct bgp_attr_encap_subtlv *stlv_last = NULL;
1834 uint16_t tunneltype;
1835
1836 total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
1837
1838 if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
1839 || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
1840 {
1841 zlog (peer->log, LOG_ERR,
1842 "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
1843 bgp_notify_send_with_data (peer,
1844 BGP_NOTIFY_UPDATE_ERR,
1845 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
1846 startp, total);
1847 return -1;
1848 }
1849
1850 if (BGP_ATTR_ENCAP == type) {
1851 /* read outer TLV type and length */
1852 uint16_t tlv_length;
1853
1854 if (length < 4) {
1855 zlog (peer->log, LOG_ERR,
1856 "Tunnel Encap attribute not long enough to contain outer T,L");
1857 bgp_notify_send_with_data(peer,
1858 BGP_NOTIFY_UPDATE_ERR,
1859 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1860 startp, total);
1861 return -1;
1862 }
1863 tunneltype = stream_getw (BGP_INPUT (peer));
1864 tlv_length = stream_getw (BGP_INPUT (peer));
1865 length -= 4;
1866
1867 if (tlv_length != length) {
1868 zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
1869 __func__, tlv_length, length);
1870 }
1871 }
1872
1873 while (length >= 4) {
Donald Sharp985c3552016-03-10 20:16:47 -05001874 uint16_t subtype = 0;
1875 uint16_t sublength = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05001876 struct bgp_attr_encap_subtlv *tlv;
1877
Lou Berger298cc2f2016-01-12 13:42:02 -05001878 if (BGP_ATTR_ENCAP == type) {
1879 subtype = stream_getc (BGP_INPUT (peer));
1880 sublength = stream_getc (BGP_INPUT (peer));
1881 length -= 2;
1882 }
Lou Bergerc3741782016-01-12 13:42:01 -05001883
1884 if (sublength > length) {
1885 zlog (peer->log, LOG_ERR,
1886 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
1887 sublength, length);
1888 bgp_notify_send_with_data (peer,
1889 BGP_NOTIFY_UPDATE_ERR,
1890 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1891 startp, total);
1892 return -1;
1893 }
1894
1895 /* alloc and copy sub-tlv */
1896 /* TBD make sure these are freed when attributes are released */
1897 tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength);
1898 tlv->type = subtype;
1899 tlv->length = sublength;
1900 stream_get(tlv->value, peer->ibuf, sublength);
1901 length -= sublength;
1902
1903 /* attach tlv to encap chain */
1904 if (!attre) {
1905 attre = bgp_attr_extra_get(attr);
1906 if (BGP_ATTR_ENCAP == type) {
1907 for (stlv_last = attre->encap_subtlvs; stlv_last && stlv_last->next;
1908 stlv_last = stlv_last->next);
1909 if (stlv_last) {
1910 stlv_last->next = tlv;
1911 } else {
1912 attre->encap_subtlvs = tlv;
1913 }
1914 }
1915 } else {
1916 stlv_last->next = tlv;
1917 }
1918 stlv_last = tlv;
1919 }
1920
1921 if (attre && (BGP_ATTR_ENCAP == type)) {
1922 attre->encap_tunneltype = tunneltype;
1923 }
1924
1925 if (length) {
1926 /* spurious leftover data */
1927 zlog (peer->log, LOG_ERR,
1928 "Tunnel Encap attribute length is bad: %d leftover octets", length);
1929 bgp_notify_send_with_data (peer,
1930 BGP_NOTIFY_UPDATE_ERR,
1931 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1932 startp, total);
1933 return -1;
1934 }
1935
1936 return 0;
1937}
1938
paul718e3742002-12-13 20:15:29 +00001939/* BGP unknown attribute treatment. */
Paul Jakmab881c702010-11-23 16:35:42 +00001940static bgp_attr_parse_ret_t
Paul Jakma835315b2012-01-18 12:28:30 +00001941bgp_attr_unknown (struct bgp_attr_parser_args *args)
paul718e3742002-12-13 20:15:29 +00001942{
Paul Jakma8794e8d2012-02-13 13:53:07 +00001943 bgp_size_t total = args->total;
paul718e3742002-12-13 20:15:29 +00001944 struct transit *transit;
Paul Jakmafb982c22007-05-04 20:15:47 +00001945 struct attr_extra *attre;
Paul Jakma835315b2012-01-18 12:28:30 +00001946 struct peer *const peer = args->peer;
1947 struct attr *const attr = args->attr;
1948 u_char *const startp = args->startp;
1949 const u_char type = args->type;
1950 const u_char flag = args->flags;
1951 const bgp_size_t length = args->length;
1952
paul718e3742002-12-13 20:15:29 +00001953
hassof4184462005-02-01 20:13:16 +00001954 if (BGP_DEBUG (normal, NORMAL))
1955 zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1956 peer->host, type, length);
1957
paul718e3742002-12-13 20:15:29 +00001958 if (BGP_DEBUG (events, EVENTS))
ajs557865c2004-12-08 19:59:11 +00001959 zlog (peer->log, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001960 "Unknown attribute type %d length %d is received", type, length);
1961
1962 /* Forward read pointer of input stream. */
paul9985f832005-02-09 15:51:56 +00001963 stream_forward_getp (peer->ibuf, length);
paul718e3742002-12-13 20:15:29 +00001964
paul718e3742002-12-13 20:15:29 +00001965 /* If any of the mandatory well-known attributes are not recognized,
1966 then the Error Subcode is set to Unrecognized Well-known
1967 Attribute. The Data field contains the unrecognized attribute
1968 (type, length and value). */
Paul Jakmab881c702010-11-23 16:35:42 +00001969 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
paul718e3742002-12-13 20:15:29 +00001970 {
Paul Jakma835315b2012-01-18 12:28:30 +00001971 return bgp_attr_malformed (args,
Paul Jakmab881c702010-11-23 16:35:42 +00001972 BGP_NOTIFY_UPDATE_UNREC_ATTR,
Paul Jakma835315b2012-01-18 12:28:30 +00001973 args->total);
paul718e3742002-12-13 20:15:29 +00001974 }
1975
1976 /* Unrecognized non-transitive optional attributes must be quietly
1977 ignored and not passed along to other BGP peers. */
1978 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
Paul Jakmab881c702010-11-23 16:35:42 +00001979 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00001980
1981 /* If a path with recognized transitive optional attribute is
1982 accepted and passed along to other BGP peers and the Partial bit
1983 in the Attribute Flags octet is set to 1 by some previous AS, it
1984 is not set back to 0 by the current AS. */
1985 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1986
1987 /* Store transitive attribute to the end of attr->transit. */
Paul Jakmafb982c22007-05-04 20:15:47 +00001988 if (! ((attre = bgp_attr_extra_get(attr))->transit) )
Stephen Hemminger393deb92008-08-18 14:13:29 -07001989 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
paul718e3742002-12-13 20:15:29 +00001990
Paul Jakmafb982c22007-05-04 20:15:47 +00001991 transit = attre->transit;
paul718e3742002-12-13 20:15:29 +00001992
1993 if (transit->val)
1994 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1995 transit->length + total);
1996 else
1997 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1998
1999 memcpy (transit->val + transit->length, startp, total);
2000 transit->length += total;
2001
Paul Jakmab881c702010-11-23 16:35:42 +00002002 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002003}
2004
Paul Jakma055086f2014-09-23 15:23:01 +01002005/* Well-known attribute check. */
2006static int
2007bgp_attr_check (struct peer *peer, struct attr *attr)
2008{
2009 u_char type = 0;
2010
Paul Jakmaaed1b552014-10-21 16:59:01 +01002011 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2012 * empty UPDATE. */
2013 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
2014 return BGP_ATTR_PARSE_PROCEED;
2015
2016 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2017 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2018 are present, it should. Check for any other attribute being present
2019 instead.
2020 */
2021 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI))
2022 return BGP_ATTR_PARSE_PROCEED;
2023
Paul Jakma055086f2014-09-23 15:23:01 +01002024 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2025 type = BGP_ATTR_ORIGIN;
2026
2027 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2028 type = BGP_ATTR_AS_PATH;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002029
2030 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and
2031 * NLRI is empty. We can't easily check NLRI empty here though.
2032 */
Paul Jakma1a211cb2014-11-01 17:21:47 +00002033 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
2034 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI)))
Paul Jakma055086f2014-09-23 15:23:01 +01002035 type = BGP_ATTR_NEXT_HOP;
Paul Jakmaaed1b552014-10-21 16:59:01 +01002036
Paul Jakma055086f2014-09-23 15:23:01 +01002037 if (peer->sort == BGP_PEER_IBGP
2038 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2039 type = BGP_ATTR_LOCAL_PREF;
2040
2041 if (type)
2042 {
2043 zlog (peer->log, LOG_WARNING,
Paul Jakmaaed1b552014-10-21 16:59:01 +01002044 "%s Missing well-known attribute %d / %s",
2045 peer->host, type, LOOKUP (attr_str, type));
Paul Jakma055086f2014-09-23 15:23:01 +01002046 bgp_notify_send_with_data (peer,
2047 BGP_NOTIFY_UPDATE_ERR,
2048 BGP_NOTIFY_UPDATE_MISS_ATTR,
2049 &type, 1);
2050 return BGP_ATTR_PARSE_ERROR;
2051 }
2052 return BGP_ATTR_PARSE_PROCEED;
2053}
2054
paul718e3742002-12-13 20:15:29 +00002055/* Read attribute of update packet. This function is called from
Andrew Certain8b366b92012-11-07 23:50:08 +00002056 bgp_update_receive() in bgp_packet.c. */
Paul Jakmab881c702010-11-23 16:35:42 +00002057bgp_attr_parse_ret_t
paul718e3742002-12-13 20:15:29 +00002058bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2059 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
2060{
2061 int ret;
Paul Jakmab881c702010-11-23 16:35:42 +00002062 u_char flag = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002063 u_char type = 0;
paul718e3742002-12-13 20:15:29 +00002064 bgp_size_t length;
2065 u_char *startp, *endp;
2066 u_char *attr_endp;
2067 u_char seen[BGP_ATTR_BITMAP_SIZE];
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002068 /* we need the as4_path only until we have synthesized the as_path with it */
2069 /* same goes for as4_aggregator */
2070 struct aspath *as4_path = NULL;
2071 as_t as4_aggregator = 0;
David Lamparter5181a022015-09-15 03:00:09 -07002072 struct in_addr as4_aggregator_addr = { .s_addr = 0 };
paul718e3742002-12-13 20:15:29 +00002073
2074 /* Initialize bitmap. */
2075 memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
2076
2077 /* End pointer of BGP attribute. */
2078 endp = BGP_INPUT_PNT (peer) + size;
Paul Jakmab881c702010-11-23 16:35:42 +00002079
paul718e3742002-12-13 20:15:29 +00002080 /* Get attributes to the end of attribute length. */
2081 while (BGP_INPUT_PNT (peer) < endp)
2082 {
2083 /* Check remaining length check.*/
2084 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
2085 {
gdtc29fdba2004-12-09 14:46:46 +00002086 /* XXX warning: long int format, int arg (arg 5) */
paul718e3742002-12-13 20:15:29 +00002087 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002088 "%s: error BGP attribute length %lu is smaller than min len",
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002089 peer->host,
2090 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
paul718e3742002-12-13 20:15:29 +00002091
2092 bgp_notify_send (peer,
2093 BGP_NOTIFY_UPDATE_ERR,
2094 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002095 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002096 }
2097
2098 /* Fetch attribute flag and type. */
2099 startp = BGP_INPUT_PNT (peer);
Denis Ovsienko2d42e682011-09-27 15:35:39 +04002100 /* "The lower-order four bits of the Attribute Flags octet are
2101 unused. They MUST be zero when sent and MUST be ignored when
2102 received." */
2103 flag = 0xF0 & stream_getc (BGP_INPUT (peer));
paul718e3742002-12-13 20:15:29 +00002104 type = stream_getc (BGP_INPUT (peer));
2105
Paul Jakma370b64a2007-12-22 16:49:52 +00002106 /* Check whether Extended-Length applies and is in bounds */
2107 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
2108 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
2109 {
2110 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002111 "%s: Extended length set, but just %lu bytes of attr header",
Paul Jakma370b64a2007-12-22 16:49:52 +00002112 peer->host,
2113 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
2114
2115 bgp_notify_send (peer,
2116 BGP_NOTIFY_UPDATE_ERR,
2117 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002118 return BGP_ATTR_PARSE_ERROR;
Paul Jakma370b64a2007-12-22 16:49:52 +00002119 }
Paul Jakma835315b2012-01-18 12:28:30 +00002120
paul718e3742002-12-13 20:15:29 +00002121 /* Check extended attribue length bit. */
2122 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
2123 length = stream_getw (BGP_INPUT (peer));
2124 else
2125 length = stream_getc (BGP_INPUT (peer));
2126
2127 /* If any attribute appears more than once in the UPDATE
2128 message, then the Error Subcode is set to Malformed Attribute
2129 List. */
2130
2131 if (CHECK_BITMAP (seen, type))
2132 {
2133 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002134 "%s: error BGP attribute type %d appears twice in a message",
paul718e3742002-12-13 20:15:29 +00002135 peer->host, type);
2136
2137 bgp_notify_send (peer,
2138 BGP_NOTIFY_UPDATE_ERR,
2139 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002140 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002141 }
2142
2143 /* Set type to bitmap to check duplicate attribute. `type' is
2144 unsigned char so it never overflow bitmap range. */
2145
2146 SET_BITMAP (seen, type);
2147
2148 /* Overflow check. */
2149 attr_endp = BGP_INPUT_PNT (peer) + length;
2150
2151 if (attr_endp > endp)
2152 {
2153 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002154 "%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 +00002155 bgp_notify_send (peer,
2156 BGP_NOTIFY_UPDATE_ERR,
2157 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002158 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002159 }
Paul Jakma835315b2012-01-18 12:28:30 +00002160
2161 struct bgp_attr_parser_args attr_args = {
2162 .peer = peer,
2163 .length = length,
2164 .attr = attr,
2165 .type = type,
2166 .flags = flag,
2167 .startp = startp,
2168 .total = attr_endp - startp,
2169 };
2170
2171
2172 /* If any recognized attribute has Attribute Flags that conflict
2173 with the Attribute Type Code, then the Error Subcode is set to
2174 Attribute Flags Error. The Data field contains the erroneous
2175 attribute (type, length and value). */
2176 if (bgp_attr_flag_invalid (&attr_args))
Paul Jakmafa61e162012-03-25 21:31:47 +01002177 {
2178 bgp_attr_parse_ret_t ret;
2179 ret = bgp_attr_malformed (&attr_args,
2180 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
2181 attr_args.total);
2182 if (ret == BGP_ATTR_PARSE_PROCEED)
2183 continue;
2184 return ret;
2185 }
paul718e3742002-12-13 20:15:29 +00002186
2187 /* OK check attribute and store it's value. */
2188 switch (type)
2189 {
2190 case BGP_ATTR_ORIGIN:
Paul Jakma835315b2012-01-18 12:28:30 +00002191 ret = bgp_attr_origin (&attr_args);
paul718e3742002-12-13 20:15:29 +00002192 break;
2193 case BGP_ATTR_AS_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002194 ret = bgp_attr_aspath (&attr_args);
paul718e3742002-12-13 20:15:29 +00002195 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002196 case BGP_ATTR_AS4_PATH:
Paul Jakma835315b2012-01-18 12:28:30 +00002197 ret = bgp_attr_as4_path (&attr_args, &as4_path);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002198 break;
paul718e3742002-12-13 20:15:29 +00002199 case BGP_ATTR_NEXT_HOP:
Paul Jakma835315b2012-01-18 12:28:30 +00002200 ret = bgp_attr_nexthop (&attr_args);
paul718e3742002-12-13 20:15:29 +00002201 break;
2202 case BGP_ATTR_MULTI_EXIT_DISC:
Paul Jakma835315b2012-01-18 12:28:30 +00002203 ret = bgp_attr_med (&attr_args);
paul718e3742002-12-13 20:15:29 +00002204 break;
2205 case BGP_ATTR_LOCAL_PREF:
Paul Jakma835315b2012-01-18 12:28:30 +00002206 ret = bgp_attr_local_pref (&attr_args);
paul718e3742002-12-13 20:15:29 +00002207 break;
2208 case BGP_ATTR_ATOMIC_AGGREGATE:
Paul Jakma835315b2012-01-18 12:28:30 +00002209 ret = bgp_attr_atomic (&attr_args);
paul718e3742002-12-13 20:15:29 +00002210 break;
2211 case BGP_ATTR_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002212 ret = bgp_attr_aggregator (&attr_args);
paul718e3742002-12-13 20:15:29 +00002213 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002214 case BGP_ATTR_AS4_AGGREGATOR:
Paul Jakma835315b2012-01-18 12:28:30 +00002215 ret = bgp_attr_as4_aggregator (&attr_args,
2216 &as4_aggregator,
2217 &as4_aggregator_addr);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002218 break;
paul718e3742002-12-13 20:15:29 +00002219 case BGP_ATTR_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002220 ret = bgp_attr_community (&attr_args);
paul718e3742002-12-13 20:15:29 +00002221 break;
2222 case BGP_ATTR_ORIGINATOR_ID:
Paul Jakma835315b2012-01-18 12:28:30 +00002223 ret = bgp_attr_originator_id (&attr_args);
paul718e3742002-12-13 20:15:29 +00002224 break;
2225 case BGP_ATTR_CLUSTER_LIST:
Paul Jakma835315b2012-01-18 12:28:30 +00002226 ret = bgp_attr_cluster_list (&attr_args);
paul718e3742002-12-13 20:15:29 +00002227 break;
2228 case BGP_ATTR_MP_REACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002229 ret = bgp_mp_reach_parse (&attr_args, mp_update);
paul718e3742002-12-13 20:15:29 +00002230 break;
2231 case BGP_ATTR_MP_UNREACH_NLRI:
Paul Jakma835315b2012-01-18 12:28:30 +00002232 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
paul718e3742002-12-13 20:15:29 +00002233 break;
2234 case BGP_ATTR_EXT_COMMUNITIES:
Paul Jakma835315b2012-01-18 12:28:30 +00002235 ret = bgp_attr_ext_communities (&attr_args);
paul718e3742002-12-13 20:15:29 +00002236 break;
Lou Bergerc3741782016-01-12 13:42:01 -05002237 case BGP_ATTR_ENCAP:
2238 ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
2239 break;
paul718e3742002-12-13 20:15:29 +00002240 default:
Paul Jakma835315b2012-01-18 12:28:30 +00002241 ret = bgp_attr_unknown (&attr_args);
paul718e3742002-12-13 20:15:29 +00002242 break;
2243 }
Paul Jakmab881c702010-11-23 16:35:42 +00002244
David Lamparterf57000c2014-06-04 01:01:10 +02002245 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS)
2246 {
2247 bgp_notify_send (peer,
2248 BGP_NOTIFY_UPDATE_ERR,
2249 BGP_NOTIFY_UPDATE_MAL_ATTR);
2250 ret = BGP_ATTR_PARSE_ERROR;
2251 }
2252
Paul Jakmab881c702010-11-23 16:35:42 +00002253 /* If hard error occured immediately return to the caller. */
2254 if (ret == BGP_ATTR_PARSE_ERROR)
Paul Jakma6e4ab122007-04-10 19:36:48 +00002255 {
2256 zlog (peer->log, LOG_WARNING,
2257 "%s: Attribute %s, parse error",
2258 peer->host,
2259 LOOKUP (attr_str, type));
Paul Jakmab881c702010-11-23 16:35:42 +00002260 if (as4_path)
2261 aspath_unintern (&as4_path);
2262 return ret;
Paul Jakma6e4ab122007-04-10 19:36:48 +00002263 }
Paul Jakmab881c702010-11-23 16:35:42 +00002264 if (ret == BGP_ATTR_PARSE_WITHDRAW)
2265 {
2266
2267 zlog (peer->log, LOG_WARNING,
2268 "%s: Attribute %s, parse error - treating as withdrawal",
2269 peer->host,
2270 LOOKUP (attr_str, type));
2271 if (as4_path)
2272 aspath_unintern (&as4_path);
2273 return ret;
2274 }
2275
paul718e3742002-12-13 20:15:29 +00002276 /* Check the fetched length. */
2277 if (BGP_INPUT_PNT (peer) != attr_endp)
2278 {
2279 zlog (peer->log, LOG_WARNING,
Paul Jakma6e4ab122007-04-10 19:36:48 +00002280 "%s: BGP attribute %s, fetch error",
2281 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002282 bgp_notify_send (peer,
2283 BGP_NOTIFY_UPDATE_ERR,
2284 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002285 if (as4_path)
2286 aspath_unintern (&as4_path);
2287 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002288 }
2289 }
paul718e3742002-12-13 20:15:29 +00002290 /* Check final read pointer is same as end pointer. */
2291 if (BGP_INPUT_PNT (peer) != endp)
2292 {
2293 zlog (peer->log, LOG_WARNING,
heasleyd68ab102011-07-12 20:09:18 +04002294 "%s: BGP attribute %s, length mismatch",
Paul Jakma6e4ab122007-04-10 19:36:48 +00002295 peer->host, LOOKUP (attr_str, type));
paul718e3742002-12-13 20:15:29 +00002296 bgp_notify_send (peer,
2297 BGP_NOTIFY_UPDATE_ERR,
2298 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
Paul Jakmab881c702010-11-23 16:35:42 +00002299 if (as4_path)
2300 aspath_unintern (&as4_path);
2301 return BGP_ATTR_PARSE_ERROR;
paul718e3742002-12-13 20:15:29 +00002302 }
Paul Jakma055086f2014-09-23 15:23:01 +01002303
2304 /* Check all mandatory well-known attributes are present */
2305 {
2306 bgp_attr_parse_ret_t ret;
2307 if ((ret = bgp_attr_check (peer, attr)) < 0)
2308 {
2309 if (as4_path)
2310 aspath_unintern (&as4_path);
2311 return ret;
2312 }
2313 }
2314
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002315 /*
2316 * At this place we can see whether we got AS4_PATH and/or
2317 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2318 * We can not do this before we've read all attributes because
2319 * the as4 handling does not say whether AS4_PATH has to be sent
2320 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2321 * in relationship to AGGREGATOR.
2322 * So, to be defensive, we are not relying on any order and read
2323 * all attributes first, including these 32bit ones, and now,
2324 * afterwards, we look what and if something is to be done for as4.
Paul Jakmaaed1b552014-10-21 16:59:01 +01002325 *
2326 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2327 * MP_UNREACH_NLRI.
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002328 */
David Lamparterf57000c2014-06-04 01:01:10 +02002329 /* actually... this doesn't ever return failure currently, but
2330 * better safe than sorry */
Paul Jakmaaed1b552014-10-21 16:59:01 +01002331 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))
2332 && bgp_attr_munge_as4_attrs (peer, attr, as4_path,
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002333 as4_aggregator, &as4_aggregator_addr))
Paul Jakmab881c702010-11-23 16:35:42 +00002334 {
David Lamparterf57000c2014-06-04 01:01:10 +02002335 bgp_notify_send (peer,
2336 BGP_NOTIFY_UPDATE_ERR,
2337 BGP_NOTIFY_UPDATE_MAL_ATTR);
Paul Jakmab881c702010-11-23 16:35:42 +00002338 if (as4_path)
2339 aspath_unintern (&as4_path);
2340 return BGP_ATTR_PARSE_ERROR;
2341 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002342
2343 /* At this stage, we have done all fiddling with as4, and the
2344 * resulting info is in attr->aggregator resp. attr->aspath
2345 * so we can chuck as4_aggregator and as4_path alltogether in
2346 * order to save memory
2347 */
Paul Jakmab881c702010-11-23 16:35:42 +00002348 if (as4_path)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002349 {
Paul Jakmaf6f434b2010-11-23 21:28:03 +00002350 aspath_unintern (&as4_path); /* unintern - it is in the hash */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002351 /* The flag that we got this is still there, but that does not
2352 * do any trouble
2353 */
2354 }
2355 /*
2356 * The "rest" of the code does nothing with as4_aggregator.
2357 * there is no memory attached specifically which is not part
2358 * of the attr.
2359 * so ignoring just means do nothing.
2360 */
2361 /*
2362 * Finally do the checks on the aspath we did not do yet
2363 * because we waited for a potentially synthesized aspath.
2364 */
Paul Jakmab881c702010-11-23 16:35:42 +00002365 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002366 {
Paul Jakma835315b2012-01-18 12:28:30 +00002367 ret = bgp_attr_aspath_check (peer, attr);
Paul Jakmab881c702010-11-23 16:35:42 +00002368 if (ret != BGP_ATTR_PARSE_PROCEED)
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002369 return ret;
2370 }
2371
paul718e3742002-12-13 20:15:29 +00002372 /* Finally intern unknown attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002373 if (attr->extra && attr->extra->transit)
2374 attr->extra->transit = transit_intern (attr->extra->transit);
paul718e3742002-12-13 20:15:29 +00002375
Paul Jakmab881c702010-11-23 16:35:42 +00002376 return BGP_ATTR_PARSE_PROCEED;
paul718e3742002-12-13 20:15:29 +00002377}
2378
paul718e3742002-12-13 20:15:29 +00002379int stream_put_prefix (struct stream *, struct prefix *);
2380
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002381size_t
2382bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi,
2383 struct attr *attr)
2384{
2385 size_t sizep;
2386
2387 /* Set extended bit always to encode the attribute length as 2 bytes */
2388 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2389 stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2390 sizep = stream_get_endp (s);
2391 stream_putw (s, 0); /* Marker: Attribute length. */
Lou Berger050defe2016-01-12 13:41:59 -05002392
2393 stream_putw (s, afi);
2394 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002395
2396 /* Nexthop */
2397 switch (afi)
2398 {
2399 case AFI_IP:
2400 switch (safi)
2401 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002402 case SAFI_MULTICAST:
2403 stream_putc (s, 4);
2404 stream_put_ipv4 (s, attr->nexthop.s_addr);
2405 break;
2406 case SAFI_MPLS_VPN:
2407 stream_putc (s, 12);
Lou Berger050defe2016-01-12 13:41:59 -05002408 stream_putl (s, 0); /* RD = 0, per RFC */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002409 stream_putl (s, 0);
2410 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2411 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002412 case SAFI_ENCAP:
2413 stream_putc (s, 4);
2414 stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2415 break;
Lou Berger050defe2016-01-12 13:41:59 -05002416 case SAFI_UNICAST: /* invalid for IPv4 */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002417 default:
2418 break;
2419 }
2420 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002421 case AFI_IP6:
2422 switch (safi)
2423 {
2424 case SAFI_UNICAST:
2425 case SAFI_MULTICAST:
2426 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002427 struct attr_extra *attre = attr->extra;
2428
2429 assert (attr->extra);
2430 stream_putc (s, attre->mp_nexthop_len);
2431 stream_put (s, &attre->mp_nexthop_global, 16);
2432 if (attre->mp_nexthop_len == 32)
2433 stream_put (s, &attre->mp_nexthop_local, 16);
2434 }
Lou Berger050defe2016-01-12 13:41:59 -05002435 break;
2436 case SAFI_MPLS_VPN:
2437 {
2438 struct attr_extra *attre = attr->extra;
2439
2440 assert (attr->extra);
2441 if (attre->mp_nexthop_len == 16) {
2442 stream_putc (s, 24);
2443 stream_putl (s, 0); /* RD = 0, per RFC */
2444 stream_putl (s, 0);
2445 stream_put (s, &attre->mp_nexthop_global, 16);
2446 } else if (attre->mp_nexthop_len == 32) {
2447 stream_putc (s, 48);
2448 stream_putl (s, 0); /* RD = 0, per RFC */
2449 stream_putl (s, 0);
2450 stream_put (s, &attre->mp_nexthop_global, 16);
2451 stream_putl (s, 0); /* RD = 0, per RFC */
2452 stream_putl (s, 0);
2453 stream_put (s, &attre->mp_nexthop_local, 16);
2454 }
2455 }
2456 break;
Lou Berger298cc2f2016-01-12 13:42:02 -05002457 case SAFI_ENCAP:
2458 assert (attr->extra);
2459 stream_putc (s, 16);
2460 stream_put (s, &attr->extra->mp_nexthop_global, 16);
2461 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002462 default:
2463 break;
2464 }
2465 break;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002466 default:
2467 break;
2468 }
2469
2470 /* SNPA */
2471 stream_putc (s, 0);
2472 return sizep;
2473}
2474
2475void
2476bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
2477 struct prefix *p, struct prefix_rd *prd,
2478 u_char *tag)
2479{
Lou Berger050defe2016-01-12 13:41:59 -05002480 if (safi == SAFI_MPLS_VPN)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002481 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002482 /* Tag, RD, Prefix write. */
2483 stream_putc (s, p->prefixlen + 88);
2484 stream_put (s, tag, 3);
2485 stream_put (s, prd->val, 8);
2486 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002487 }
Lou Berger050defe2016-01-12 13:41:59 -05002488 else
2489 stream_put_prefix (s, p);
2490}
2491
2492size_t
2493bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
2494{
2495 int size = PSIZE (p->prefixlen);
2496 if (safi == SAFI_MPLS_VPN)
2497 size += 88;
2498 return size;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002499}
2500
Lou Bergerc3741782016-01-12 13:42:01 -05002501/*
2502 * Encodes the tunnel encapsulation attribute
2503 */
2504static void
2505bgp_packet_mpattr_tea(
2506 struct bgp *bgp,
2507 struct peer *peer,
2508 struct stream *s,
2509 struct attr *attr,
2510 uint8_t attrtype)
2511{
2512 unsigned int attrlenfield = 0;
Lou Berger298cc2f2016-01-12 13:42:02 -05002513 unsigned int attrhdrlen = 0;
Lou Bergerc3741782016-01-12 13:42:01 -05002514 struct bgp_attr_encap_subtlv *subtlvs;
2515 struct bgp_attr_encap_subtlv *st;
2516 const char *attrname;
2517
2518 if (!attr || !attr->extra)
2519 return;
2520
2521 switch (attrtype) {
2522 case BGP_ATTR_ENCAP:
2523 attrname = "Tunnel Encap";
2524 subtlvs = attr->extra->encap_subtlvs;
2525
2526 /*
2527 * The tunnel encap attr has an "outer" tlv.
2528 * T = tunneltype,
2529 * L = total length of subtlvs,
2530 * V = concatenated subtlvs.
2531 */
2532 attrlenfield = 2 + 2; /* T + L */
Lou Berger298cc2f2016-01-12 13:42:02 -05002533 attrhdrlen = 1 + 1; /* subTLV T + L */
Lou Bergerc3741782016-01-12 13:42:01 -05002534 break;
2535
2536 default:
2537 assert(0);
2538 }
2539
2540
Lou Berger298cc2f2016-01-12 13:42:02 -05002541 /* if no tlvs, don't make attr */
2542 if (subtlvs == NULL)
2543 return;
2544
Lou Bergerc3741782016-01-12 13:42:01 -05002545 /* compute attr length */
2546 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002547 attrlenfield += (attrhdrlen + st->length);
Lou Bergerc3741782016-01-12 13:42:01 -05002548 }
2549
Lou Bergerc3741782016-01-12 13:42:01 -05002550 if (attrlenfield > 0xffff) {
2551 zlog (peer->log, LOG_ERR,
2552 "%s attribute is too long (length=%d), can't send it",
2553 attrname,
2554 attrlenfield);
2555 return;
2556 }
2557
2558 if (attrlenfield > 0xff) {
2559 /* 2-octet length field */
2560 stream_putc (s,
2561 BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2562 stream_putc (s, attrtype);
2563 stream_putw (s, attrlenfield & 0xffff);
2564 } else {
2565 /* 1-octet length field */
2566 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
2567 stream_putc (s, attrtype);
2568 stream_putc (s, attrlenfield & 0xff);
2569 }
2570
2571 if (attrtype == BGP_ATTR_ENCAP) {
2572 /* write outer T+L */
2573 stream_putw(s, attr->extra->encap_tunneltype);
2574 stream_putw(s, attrlenfield - 4);
2575 }
2576
2577 /* write each sub-tlv */
2578 for (st = subtlvs; st; st = st->next) {
Lou Berger298cc2f2016-01-12 13:42:02 -05002579 if (attrtype == BGP_ATTR_ENCAP) {
2580 stream_putc (s, st->type);
2581 stream_putc (s, st->length);
2582 }
Lou Bergerc3741782016-01-12 13:42:01 -05002583 stream_put (s, st->value, st->length);
2584 }
2585}
2586
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002587void
2588bgp_packet_mpattr_end (struct stream *s, size_t sizep)
2589{
2590 /* Set MP attribute length. Don't count the (2) bytes used to encode
2591 the attr length */
2592 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2);
2593}
2594
paul718e3742002-12-13 20:15:29 +00002595/* Make attribute packet. */
2596bgp_size_t
2597bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002598 struct stream *s, struct attr *attr,
2599 struct prefix *p, afi_t afi, safi_t safi,
2600 struct peer *from, struct prefix_rd *prd, u_char *tag)
paul718e3742002-12-13 20:15:29 +00002601{
paulfe69a502005-09-10 16:55:02 +00002602 size_t cp;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002603 size_t aspath_sizep;
paul718e3742002-12-13 20:15:29 +00002604 struct aspath *aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002605 int send_as4_path = 0;
2606 int send_as4_aggregator = 0;
2607 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
paul718e3742002-12-13 20:15:29 +00002608
2609 if (! bgp)
2610 bgp = bgp_get_default ();
2611
2612 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00002613 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002614
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002615 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST))
2616 {
Lou Berger050defe2016-01-12 13:41:59 -05002617 size_t mpattrlen_pos = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002618 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr);
2619 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag);
2620 bgp_packet_mpattr_end(s, mpattrlen_pos);
2621 }
2622
paul718e3742002-12-13 20:15:29 +00002623 /* Origin attribute. */
2624 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2625 stream_putc (s, BGP_ATTR_ORIGIN);
2626 stream_putc (s, 1);
2627 stream_putc (s, attr->origin);
2628
2629 /* AS path attribute. */
2630
2631 /* If remote-peer is EBGP */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002632 if (peer->sort == BGP_PEER_EBGP
paul718e3742002-12-13 20:15:29 +00002633 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
paulfe69a502005-09-10 16:55:02 +00002634 || attr->aspath->segments == NULL)
paulfee0f4c2004-09-13 05:12:46 +00002635 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
paul718e3742002-12-13 20:15:29 +00002636 {
2637 aspath = aspath_dup (attr->aspath);
2638
2639 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2640 {
2641 /* Strip the confed info, and then stuff our path CONFED_ID
2642 on the front */
2643 aspath = aspath_delete_confed_seq (aspath);
2644 aspath = aspath_add_seq (aspath, bgp->confed_id);
2645 }
2646 else
2647 {
Andrew Certain9d3f9702012-11-07 23:50:07 +00002648 if (peer->change_local_as) {
2649 /* If replace-as is specified, we only use the change_local_as when
2650 advertising routes. */
2651 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
2652 aspath = aspath_add_seq (aspath, peer->local_as);
2653 }
paul718e3742002-12-13 20:15:29 +00002654 aspath = aspath_add_seq (aspath, peer->change_local_as);
Andrew Certain9d3f9702012-11-07 23:50:07 +00002655 } else {
2656 aspath = aspath_add_seq (aspath, peer->local_as);
2657 }
paul718e3742002-12-13 20:15:29 +00002658 }
2659 }
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002660 else if (peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002661 {
2662 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2663 aspath = aspath_dup (attr->aspath);
2664 aspath = aspath_add_confed_seq (aspath, peer->local_as);
2665 }
2666 else
2667 aspath = attr->aspath;
2668
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002669 /* If peer is not AS4 capable, then:
2670 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2671 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2672 * types are in it (i.e. exclude them if they are there)
2673 * AND do this only if there is at least one asnum > 65535 in the path!
2674 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2675 * all ASnums > 65535 to BGP_AS_TRANS
2676 */
paul718e3742002-12-13 20:15:29 +00002677
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002678 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2679 stream_putc (s, BGP_ATTR_AS_PATH);
2680 aspath_sizep = stream_get_endp (s);
2681 stream_putw (s, 0);
2682 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2683
2684 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2685 * in the path
2686 */
2687 if (!use32bit && aspath_has_as4 (aspath))
2688 send_as4_path = 1; /* we'll do this later, at the correct place */
2689
paul718e3742002-12-13 20:15:29 +00002690 /* Nexthop attribute. */
Lou Berger050defe2016-01-12 13:41:59 -05002691 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP &&
2692 safi == SAFI_UNICAST) /* only write NH attr for unicast safi */
paul718e3742002-12-13 20:15:29 +00002693 {
2694 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2695 stream_putc (s, BGP_ATTR_NEXT_HOP);
2696 stream_putc (s, 4);
2697 if (safi == SAFI_MPLS_VPN)
2698 {
2699 if (attr->nexthop.s_addr == 0)
2700 stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2701 else
2702 stream_put_ipv4 (s, attr->nexthop.s_addr);
2703 }
2704 else
2705 stream_put_ipv4 (s, attr->nexthop.s_addr);
2706 }
2707
2708 /* MED attribute. */
2709 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2710 {
2711 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2712 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2713 stream_putc (s, 4);
2714 stream_putl (s, attr->med);
2715 }
2716
2717 /* Local preference. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002718 if (peer->sort == BGP_PEER_IBGP ||
2719 peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002720 {
2721 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2722 stream_putc (s, BGP_ATTR_LOCAL_PREF);
2723 stream_putc (s, 4);
2724 stream_putl (s, attr->local_pref);
2725 }
2726
2727 /* Atomic aggregate. */
2728 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2729 {
2730 stream_putc (s, BGP_ATTR_FLAG_TRANS);
2731 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2732 stream_putc (s, 0);
2733 }
2734
2735 /* Aggregator. */
2736 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2737 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002738 assert (attr->extra);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002739
2740 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
paul718e3742002-12-13 20:15:29 +00002741 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2742 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002743
2744 if (use32bit)
2745 {
2746 /* AS4 capable peer */
2747 stream_putc (s, 8);
2748 stream_putl (s, attr->extra->aggregator_as);
2749 }
2750 else
2751 {
2752 /* 2-byte AS peer */
2753 stream_putc (s, 6);
2754
2755 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2756 if ( attr->extra->aggregator_as > 65535 )
2757 {
2758 stream_putw (s, BGP_AS_TRANS);
2759
2760 /* we have to send AS4_AGGREGATOR, too.
2761 * we'll do that later in order to send attributes in ascending
2762 * order.
2763 */
2764 send_as4_aggregator = 1;
2765 }
2766 else
2767 stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2768 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002769 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00002770 }
2771
2772 /* Community attribute. */
2773 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2774 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2775 {
2776 if (attr->community->size * 4 > 255)
2777 {
2778 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2779 stream_putc (s, BGP_ATTR_COMMUNITIES);
2780 stream_putw (s, attr->community->size * 4);
2781 }
2782 else
2783 {
2784 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2785 stream_putc (s, BGP_ATTR_COMMUNITIES);
2786 stream_putc (s, attr->community->size * 4);
2787 }
2788 stream_put (s, attr->community->val, attr->community->size * 4);
2789 }
2790
2791 /* Route Reflector. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002792 if (peer->sort == BGP_PEER_IBGP
paul718e3742002-12-13 20:15:29 +00002793 && from
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002794 && from->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002795 {
2796 /* Originator ID. */
2797 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2798 stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2799 stream_putc (s, 4);
2800
2801 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
Paul Jakmafb982c22007-05-04 20:15:47 +00002802 stream_put_in_addr (s, &attr->extra->originator_id);
Paul Jakma34c3f812006-05-12 23:25:37 +00002803 else
2804 stream_put_in_addr (s, &from->remote_id);
paul718e3742002-12-13 20:15:29 +00002805
2806 /* Cluster list. */
2807 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2808 stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2809
Paul Jakma9eda90c2007-08-30 13:36:17 +00002810 if (attr->extra && attr->extra->cluster)
paul718e3742002-12-13 20:15:29 +00002811 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002812 stream_putc (s, attr->extra->cluster->length + 4);
paul718e3742002-12-13 20:15:29 +00002813 /* If this peer configuration's parent BGP has cluster_id. */
2814 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2815 stream_put_in_addr (s, &bgp->cluster_id);
2816 else
2817 stream_put_in_addr (s, &bgp->router_id);
Paul Jakmafb982c22007-05-04 20:15:47 +00002818 stream_put (s, attr->extra->cluster->list,
2819 attr->extra->cluster->length);
paul718e3742002-12-13 20:15:29 +00002820 }
2821 else
2822 {
2823 stream_putc (s, 4);
2824 /* If this peer configuration's parent BGP has cluster_id. */
2825 if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2826 stream_put_in_addr (s, &bgp->cluster_id);
2827 else
2828 stream_put_in_addr (s, &bgp->router_id);
2829 }
2830 }
2831
paul718e3742002-12-13 20:15:29 +00002832 /* Extended Communities attribute. */
2833 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2834 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2835 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002836 struct attr_extra *attre = attr->extra;
2837
2838 assert (attre);
2839
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002840 if (peer->sort == BGP_PEER_IBGP
2841 || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +00002842 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002843 if (attre->ecommunity->size * 8 > 255)
hasso4372df72004-05-20 10:20:02 +00002844 {
2845 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2846 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002847 stream_putw (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002848 }
2849 else
2850 {
2851 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2852 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
Paul Jakmafb982c22007-05-04 20:15:47 +00002853 stream_putc (s, attre->ecommunity->size * 8);
hasso4372df72004-05-20 10:20:02 +00002854 }
Paul Jakmafb982c22007-05-04 20:15:47 +00002855 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
paul718e3742002-12-13 20:15:29 +00002856 }
2857 else
2858 {
paul5228ad22004-06-04 17:58:18 +00002859 u_int8_t *pnt;
hasso4372df72004-05-20 10:20:02 +00002860 int tbit;
2861 int ecom_tr_size = 0;
2862 int i;
2863
Paul Jakmafb982c22007-05-04 20:15:47 +00002864 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002865 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002866 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002867 tbit = *pnt;
2868
2869 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2870 continue;
2871
2872 ecom_tr_size++;
2873 }
2874
2875 if (ecom_tr_size)
2876 {
2877 if (ecom_tr_size * 8 > 255)
2878 {
2879 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2880 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2881 stream_putw (s, ecom_tr_size * 8);
2882 }
2883 else
2884 {
2885 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2886 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2887 stream_putc (s, ecom_tr_size * 8);
2888 }
2889
Paul Jakmafb982c22007-05-04 20:15:47 +00002890 for (i = 0; i < attre->ecommunity->size; i++)
hasso4372df72004-05-20 10:20:02 +00002891 {
Paul Jakmafb982c22007-05-04 20:15:47 +00002892 pnt = attre->ecommunity->val + (i * 8);
hasso4372df72004-05-20 10:20:02 +00002893 tbit = *pnt;
2894
2895 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2896 continue;
2897
2898 stream_put (s, pnt, 8);
2899 }
2900 }
paul718e3742002-12-13 20:15:29 +00002901 }
paul718e3742002-12-13 20:15:29 +00002902 }
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002903
2904 if ( send_as4_path )
2905 {
2906 /* If the peer is NOT As4 capable, AND */
2907 /* there are ASnums > 65535 in path THEN
2908 * give out AS4_PATH */
2909
2910 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2911 * path segments!
2912 * Hm, I wonder... confederation things *should* only be at
2913 * the beginning of an aspath, right? Then we should use
2914 * aspath_delete_confed_seq for this, because it is already
2915 * there! (JK)
2916 * Folks, talk to me: what is reasonable here!?
2917 */
2918 aspath = aspath_delete_confed_seq (aspath);
2919
2920 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2921 stream_putc (s, BGP_ATTR_AS4_PATH);
2922 aspath_sizep = stream_get_endp (s);
2923 stream_putw (s, 0);
2924 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2925 }
2926
2927 if (aspath != attr->aspath)
2928 aspath_free (aspath);
2929
2930 if ( send_as4_aggregator )
2931 {
2932 assert (attr->extra);
2933
2934 /* send AS4_AGGREGATOR, at this place */
2935 /* this section of code moved here in order to ensure the correct
2936 * *ascending* order of attributes
2937 */
2938 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2939 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2940 stream_putc (s, 8);
2941 stream_putl (s, attr->extra->aggregator_as);
2942 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2943 }
Lou Berger298cc2f2016-01-12 13:42:02 -05002944
2945 if ((afi == AFI_IP || afi == AFI_IP6) &&
2946 (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
2947 {
2948 /* Tunnel Encap attribute */
2949 bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
2950 }
2951
paul718e3742002-12-13 20:15:29 +00002952 /* Unknown transit attribute. */
Paul Jakmafb982c22007-05-04 20:15:47 +00002953 if (attr->extra && attr->extra->transit)
2954 stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
paul718e3742002-12-13 20:15:29 +00002955
2956 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00002957 return stream_get_endp (s) - cp;
paul718e3742002-12-13 20:15:29 +00002958}
2959
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002960size_t
2961bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
paul718e3742002-12-13 20:15:29 +00002962{
paul718e3742002-12-13 20:15:29 +00002963 unsigned long attrlen_pnt;
paul718e3742002-12-13 20:15:29 +00002964
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002965 /* Set extended bit always to encode the attribute length as 2 bytes */
2966 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
paul718e3742002-12-13 20:15:29 +00002967 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2968
paul9985f832005-02-09 15:51:56 +00002969 attrlen_pnt = stream_get_endp (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002970 stream_putw (s, 0); /* Length of this attribute. */
paul718e3742002-12-13 20:15:29 +00002971
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002972 stream_putw (s, afi);
Lou Berger050defe2016-01-12 13:41:59 -05002973 stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002974 return attrlen_pnt;
2975}
paul718e3742002-12-13 20:15:29 +00002976
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002977void
2978bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
2979 afi_t afi, safi_t safi, struct prefix_rd *prd,
2980 u_char *tag)
2981{
Lou Berger050defe2016-01-12 13:41:59 -05002982 bgp_packet_mpattr_prefix (s, afi, safi, p, prd, tag);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002983}
paul718e3742002-12-13 20:15:29 +00002984
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00002985void
2986bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
2987{
Lou Berger050defe2016-01-12 13:41:59 -05002988 bgp_packet_mpattr_end (s, attrlen_pnt);
paul718e3742002-12-13 20:15:29 +00002989}
2990
2991/* Initialization of attribute. */
2992void
paulfe69a502005-09-10 16:55:02 +00002993bgp_attr_init (void)
paul718e3742002-12-13 20:15:29 +00002994{
paul718e3742002-12-13 20:15:29 +00002995 aspath_init ();
2996 attrhash_init ();
2997 community_init ();
2998 ecommunity_init ();
2999 cluster_init ();
3000 transit_init ();
3001}
3002
Chris Caputo228da422009-07-18 05:44:03 +00003003void
3004bgp_attr_finish (void)
3005{
3006 aspath_finish ();
3007 attrhash_finish ();
3008 community_finish ();
3009 ecommunity_finish ();
3010 cluster_finish ();
3011 transit_finish ();
3012}
3013
paul718e3742002-12-13 20:15:29 +00003014/* Make attribute packet. */
3015void
paula3845922003-10-18 01:30:50 +00003016bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3017 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +00003018{
3019 unsigned long cp;
3020 unsigned long len;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003021 size_t aspath_lenp;
paul718e3742002-12-13 20:15:29 +00003022 struct aspath *aspath;
3023
3024 /* Remember current pointer. */
paul9985f832005-02-09 15:51:56 +00003025 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00003026
3027 /* Place holder of length. */
3028 stream_putw (s, 0);
3029
3030 /* Origin attribute. */
3031 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3032 stream_putc (s, BGP_ATTR_ORIGIN);
3033 stream_putc (s, 1);
3034 stream_putc (s, attr->origin);
3035
3036 aspath = attr->aspath;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003037
3038 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3039 stream_putc (s, BGP_ATTR_AS_PATH);
3040 aspath_lenp = stream_get_endp (s);
3041 stream_putw (s, 0);
3042
3043 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
paul718e3742002-12-13 20:15:29 +00003044
3045 /* Nexthop attribute. */
paula3845922003-10-18 01:30:50 +00003046 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3047 if(prefix != NULL
paula3845922003-10-18 01:30:50 +00003048 && prefix->family != AF_INET6
paula3845922003-10-18 01:30:50 +00003049 )
3050 {
3051 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3052 stream_putc (s, BGP_ATTR_NEXT_HOP);
3053 stream_putc (s, 4);
3054 stream_put_ipv4 (s, attr->nexthop.s_addr);
3055 }
paul718e3742002-12-13 20:15:29 +00003056
3057 /* MED attribute. */
3058 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
3059 {
3060 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
3061 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
3062 stream_putc (s, 4);
3063 stream_putl (s, attr->med);
3064 }
3065
3066 /* Local preference. */
3067 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
3068 {
3069 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3070 stream_putc (s, BGP_ATTR_LOCAL_PREF);
3071 stream_putc (s, 4);
3072 stream_putl (s, attr->local_pref);
3073 }
3074
3075 /* Atomic aggregate. */
3076 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
3077 {
3078 stream_putc (s, BGP_ATTR_FLAG_TRANS);
3079 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
3080 stream_putc (s, 0);
3081 }
3082
3083 /* Aggregator. */
3084 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
3085 {
Paul Jakmafb982c22007-05-04 20:15:47 +00003086 assert (attr->extra);
paul718e3742002-12-13 20:15:29 +00003087 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3088 stream_putc (s, BGP_ATTR_AGGREGATOR);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00003089 stream_putc (s, 8);
3090 stream_putl (s, attr->extra->aggregator_as);
Paul Jakmafb982c22007-05-04 20:15:47 +00003091 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
paul718e3742002-12-13 20:15:29 +00003092 }
3093
3094 /* Community attribute. */
3095 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
3096 {
3097 if (attr->community->size * 4 > 255)
3098 {
3099 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3100 stream_putc (s, BGP_ATTR_COMMUNITIES);
3101 stream_putw (s, attr->community->size * 4);
3102 }
3103 else
3104 {
3105 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3106 stream_putc (s, BGP_ATTR_COMMUNITIES);
3107 stream_putc (s, attr->community->size * 4);
3108 }
3109 stream_put (s, attr->community->val, attr->community->size * 4);
3110 }
3111
paula3845922003-10-18 01:30:50 +00003112 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003113 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
3114 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
paula3845922003-10-18 01:30:50 +00003115 {
3116 int sizep;
Paul Jakmafb982c22007-05-04 20:15:47 +00003117 struct attr_extra *attre = attr->extra;
3118
paula3845922003-10-18 01:30:50 +00003119 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
3120 stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
paul9985f832005-02-09 15:51:56 +00003121 sizep = stream_get_endp (s);
paula3845922003-10-18 01:30:50 +00003122
3123 /* MP header */
Paul Jakmafb982c22007-05-04 20:15:47 +00003124 stream_putc (s, 0); /* Marker: Attribute length. */
paula3845922003-10-18 01:30:50 +00003125 stream_putw(s, AFI_IP6); /* AFI */
3126 stream_putc(s, SAFI_UNICAST); /* SAFI */
3127
3128 /* Next hop */
Paul Jakmafb982c22007-05-04 20:15:47 +00003129 stream_putc(s, attre->mp_nexthop_len);
3130 stream_put(s, &attre->mp_nexthop_global, 16);
3131 if (attre->mp_nexthop_len == 32)
3132 stream_put(s, &attre->mp_nexthop_local, 16);
paula3845922003-10-18 01:30:50 +00003133
3134 /* SNPA */
3135 stream_putc(s, 0);
3136
3137 /* Prefix */
3138 stream_put_prefix(s, prefix);
3139
3140 /* Set MP attribute length. */
paul9985f832005-02-09 15:51:56 +00003141 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
paula3845922003-10-18 01:30:50 +00003142 }
paula3845922003-10-18 01:30:50 +00003143
paul718e3742002-12-13 20:15:29 +00003144 /* Return total size of attribute. */
paul9985f832005-02-09 15:51:56 +00003145 len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +00003146 stream_putw_at (s, cp, len);
3147}