Annotation of embedaddon/quagga/bgpd/bgp_attr.c, revision 1.1.1.2
1.1 misho 1: /* BGP attributes management routines.
2: Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3:
4: This file is part of GNU Zebra.
5:
6: GNU Zebra is free software; you can redistribute it and/or modify it
7: under the terms of the GNU General Public License as published by the
8: Free Software Foundation; either version 2, or (at your option) any
9: later version.
10:
11: GNU Zebra is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Zebra; see the file COPYING. If not, write to the Free
18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19: 02111-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"
31: #include "jhash.h"
32:
33: #include "bgpd/bgpd.h"
34: #include "bgpd/bgp_attr.h"
35: #include "bgpd/bgp_route.h"
36: #include "bgpd/bgp_aspath.h"
37: #include "bgpd/bgp_community.h"
38: #include "bgpd/bgp_debug.h"
39: #include "bgpd/bgp_packet.h"
40: #include "bgpd/bgp_ecommunity.h"
41:
42: /* Attribute strings for logging. */
43: static const struct message attr_str [] =
44: {
45: { BGP_ATTR_ORIGIN, "ORIGIN" },
46: { BGP_ATTR_AS_PATH, "AS_PATH" },
47: { BGP_ATTR_NEXT_HOP, "NEXT_HOP" },
48: { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
49: { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" },
50: { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
51: { BGP_ATTR_AGGREGATOR, "AGGREGATOR" },
52: { BGP_ATTR_COMMUNITIES, "COMMUNITY" },
53: { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" },
1.1.1.2 ! misho 54: { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" },
1.1 misho 55: { BGP_ATTR_DPA, "DPA" },
56: { BGP_ATTR_ADVERTISER, "ADVERTISER"} ,
57: { BGP_ATTR_RCID_PATH, "RCID_PATH" },
58: { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
59: { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
60: { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
61: { BGP_ATTR_AS4_PATH, "AS4_PATH" },
62: { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
63: { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
64: };
65: static const int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]);
1.1.1.2 ! misho 66:
! 67: static const struct message attr_flag_str[] =
! 68: {
! 69: { BGP_ATTR_FLAG_OPTIONAL, "Optional" },
! 70: { BGP_ATTR_FLAG_TRANS, "Transitive" },
! 71: { BGP_ATTR_FLAG_PARTIAL, "Partial" },
! 72: /* bgp_attr_flags_diagnose() relies on this bit being last in this list */
! 73: { BGP_ATTR_FLAG_EXTLEN, "Extended Length" },
! 74: };
! 75: static const size_t attr_flag_str_max =
! 76: sizeof (attr_flag_str) / sizeof (attr_flag_str[0]);
1.1 misho 77:
78: static struct hash *cluster_hash;
79:
80: static void *
81: cluster_hash_alloc (void *p)
82: {
83: struct cluster_list * val = (struct cluster_list *) p;
84: struct cluster_list *cluster;
85:
86: cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
87: cluster->length = val->length;
88:
89: if (cluster->length)
90: {
91: cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
92: memcpy (cluster->list, val->list, val->length);
93: }
94: else
95: cluster->list = NULL;
96:
97: cluster->refcnt = 0;
98:
99: return cluster;
100: }
101:
102: /* Cluster list related functions. */
103: static struct cluster_list *
104: cluster_parse (struct in_addr * pnt, int length)
105: {
106: struct cluster_list tmp;
107: struct cluster_list *cluster;
108:
109: tmp.length = length;
110: tmp.list = pnt;
111:
112: cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
113: cluster->refcnt++;
114: return cluster;
115: }
116:
117: int
118: cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
119: {
120: int i;
121:
122: for (i = 0; i < cluster->length / 4; i++)
123: if (cluster->list[i].s_addr == originator.s_addr)
124: return 1;
125: return 0;
126: }
127:
128: static unsigned int
129: cluster_hash_key_make (void *p)
130: {
131: const struct cluster_list *cluster = p;
132:
133: return jhash(cluster->list, cluster->length, 0);
134: }
135:
136: static int
137: cluster_hash_cmp (const void *p1, const void *p2)
138: {
139: const struct cluster_list * cluster1 = p1;
140: const struct cluster_list * cluster2 = p2;
141:
142: return (cluster1->length == cluster2->length &&
143: memcmp (cluster1->list, cluster2->list, cluster1->length) == 0);
144: }
145:
146: static void
147: cluster_free (struct cluster_list *cluster)
148: {
149: if (cluster->list)
150: XFREE (MTYPE_CLUSTER_VAL, cluster->list);
151: XFREE (MTYPE_CLUSTER, cluster);
152: }
153:
154: #if 0
155: static struct cluster_list *
156: cluster_dup (struct cluster_list *cluster)
157: {
158: struct cluster_list *new;
159:
160: new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
161: new->length = cluster->length;
162:
163: if (cluster->length)
164: {
165: new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
166: memcpy (new->list, cluster->list, cluster->length);
167: }
168: else
169: new->list = NULL;
170:
171: return new;
172: }
173: #endif
174:
175: static struct cluster_list *
176: cluster_intern (struct cluster_list *cluster)
177: {
178: struct cluster_list *find;
179:
180: find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
181: find->refcnt++;
182:
183: return find;
184: }
185:
186: void
187: cluster_unintern (struct cluster_list *cluster)
188: {
189: if (cluster->refcnt)
190: cluster->refcnt--;
191:
192: if (cluster->refcnt == 0)
193: {
1.1.1.2 ! misho 194: hash_release (cluster_hash, cluster);
1.1 misho 195: cluster_free (cluster);
196: }
197: }
198:
199: static void
200: cluster_init (void)
201: {
202: cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
203: }
204:
205: static void
206: cluster_finish (void)
207: {
208: hash_free (cluster_hash);
209: cluster_hash = NULL;
210: }
211:
212: /* Unknown transit attribute. */
213: static struct hash *transit_hash;
214:
215: static void
216: transit_free (struct transit *transit)
217: {
218: if (transit->val)
219: XFREE (MTYPE_TRANSIT_VAL, transit->val);
220: XFREE (MTYPE_TRANSIT, transit);
221: }
222:
223:
224: static void *
225: transit_hash_alloc (void *p)
226: {
227: /* Transit structure is already allocated. */
228: return p;
229: }
230:
231: static struct transit *
232: transit_intern (struct transit *transit)
233: {
234: struct transit *find;
235:
236: find = hash_get (transit_hash, transit, transit_hash_alloc);
237: if (find != transit)
238: transit_free (transit);
239: find->refcnt++;
240:
241: return find;
242: }
243:
244: void
245: transit_unintern (struct transit *transit)
246: {
247: if (transit->refcnt)
248: transit->refcnt--;
249:
250: if (transit->refcnt == 0)
251: {
1.1.1.2 ! misho 252: hash_release (transit_hash, transit);
1.1 misho 253: transit_free (transit);
254: }
255: }
256:
257: static unsigned int
258: transit_hash_key_make (void *p)
259: {
260: const struct transit * transit = p;
261:
262: return jhash(transit->val, transit->length, 0);
263: }
264:
265: static int
266: transit_hash_cmp (const void *p1, const void *p2)
267: {
268: const struct transit * transit1 = p1;
269: const struct transit * transit2 = p2;
270:
271: return (transit1->length == transit2->length &&
272: memcmp (transit1->val, transit2->val, transit1->length) == 0);
273: }
274:
275: static void
276: transit_init (void)
277: {
278: transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
279: }
280:
281: static void
282: transit_finish (void)
283: {
284: hash_free (transit_hash);
285: transit_hash = NULL;
286: }
287:
288: /* Attribute hash routines. */
289: static struct hash *attrhash;
290:
291: static struct attr_extra *
292: bgp_attr_extra_new (void)
293: {
294: return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
295: }
296:
297: void
298: bgp_attr_extra_free (struct attr *attr)
299: {
300: if (attr->extra)
301: {
302: XFREE (MTYPE_ATTR_EXTRA, attr->extra);
303: attr->extra = NULL;
304: }
305: }
306:
307: struct attr_extra *
308: bgp_attr_extra_get (struct attr *attr)
309: {
310: if (!attr->extra)
311: attr->extra = bgp_attr_extra_new();
312: return attr->extra;
313: }
314:
315: /* Shallow copy of an attribute
316: * Though, not so shallow that it doesn't copy the contents
317: * of the attr_extra pointed to by 'extra'
318: */
319: void
320: bgp_attr_dup (struct attr *new, struct attr *orig)
321: {
322: *new = *orig;
323: if (orig->extra)
324: {
325: new->extra = bgp_attr_extra_new();
326: *new->extra = *orig->extra;
327: }
328: }
329:
330: unsigned long int
331: attr_count (void)
332: {
333: return attrhash->count;
334: }
335:
336: unsigned long int
337: attr_unknown_count (void)
338: {
339: return transit_hash->count;
340: }
341:
342: unsigned int
343: attrhash_key_make (void *p)
344: {
345: const struct attr * attr = (struct attr *) p;
346: uint32_t key = 0;
347: #define MIX(val) key = jhash_1word(val, key)
348:
349: MIX(attr->origin);
350: MIX(attr->nexthop.s_addr);
351: MIX(attr->med);
352: MIX(attr->local_pref);
353:
354: key += attr->origin;
355: key += attr->nexthop.s_addr;
356: key += attr->med;
357: key += attr->local_pref;
358:
359: if (attr->extra)
360: {
361: MIX(attr->extra->aggregator_as);
362: MIX(attr->extra->aggregator_addr.s_addr);
363: MIX(attr->extra->weight);
364: MIX(attr->extra->mp_nexthop_global_in.s_addr);
365: }
366:
367: if (attr->aspath)
368: MIX(aspath_key_make (attr->aspath));
369: if (attr->community)
370: MIX(community_hash_make (attr->community));
371:
372: if (attr->extra)
373: {
374: if (attr->extra->ecommunity)
375: MIX(ecommunity_hash_make (attr->extra->ecommunity));
376: if (attr->extra->cluster)
377: MIX(cluster_hash_key_make (attr->extra->cluster));
378: if (attr->extra->transit)
379: MIX(transit_hash_key_make (attr->extra->transit));
380:
381: #ifdef HAVE_IPV6
382: MIX(attr->extra->mp_nexthop_len);
383: key = jhash(attr->extra->mp_nexthop_global.s6_addr, 16, key);
384: key = jhash(attr->extra->mp_nexthop_local.s6_addr, 16, key);
385: #endif /* HAVE_IPV6 */
386: }
387:
388: return key;
389: }
390:
391: int
392: attrhash_cmp (const void *p1, const void *p2)
393: {
394: const struct attr * attr1 = p1;
395: const struct attr * attr2 = p2;
396:
397: if (attr1->flag == attr2->flag
398: && attr1->origin == attr2->origin
399: && attr1->nexthop.s_addr == attr2->nexthop.s_addr
400: && attr1->aspath == attr2->aspath
401: && attr1->community == attr2->community
402: && attr1->med == attr2->med
403: && attr1->local_pref == attr2->local_pref)
404: {
405: const struct attr_extra *ae1 = attr1->extra;
406: const struct attr_extra *ae2 = attr2->extra;
407:
408: if (ae1 && ae2
409: && ae1->aggregator_as == ae2->aggregator_as
410: && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
411: && ae1->weight == ae2->weight
412: #ifdef HAVE_IPV6
413: && ae1->mp_nexthop_len == ae2->mp_nexthop_len
414: && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
415: && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
416: #endif /* HAVE_IPV6 */
417: && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
418: && ae1->ecommunity == ae2->ecommunity
419: && ae1->cluster == ae2->cluster
420: && ae1->transit == ae2->transit)
421: return 1;
422: else if (ae1 || ae2)
423: return 0;
424: /* neither attribute has extra attributes, so they're same */
425: return 1;
426: }
427: else
428: return 0;
429: }
430:
431: static void
432: attrhash_init (void)
433: {
434: attrhash = hash_create (attrhash_key_make, attrhash_cmp);
435: }
436:
437: static void
438: attrhash_finish (void)
439: {
440: hash_free (attrhash);
441: attrhash = NULL;
442: }
443:
444: static void
445: attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
446: {
447: struct attr *attr = backet->data;
448:
449: vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt,
450: inet_ntoa (attr->nexthop), VTY_NEWLINE);
451: }
452:
453: void
454: attr_show_all (struct vty *vty)
455: {
456: hash_iterate (attrhash,
457: (void (*)(struct hash_backet *, void *))
458: attr_show_all_iterator,
459: vty);
460: }
461:
462: static void *
463: bgp_attr_hash_alloc (void *p)
464: {
465: struct attr * val = (struct attr *) p;
466: struct attr *attr;
467:
468: attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
469: *attr = *val;
470: if (val->extra)
471: {
472: attr->extra = bgp_attr_extra_new ();
473: *attr->extra = *val->extra;
474: }
475: attr->refcnt = 0;
476: return attr;
477: }
478:
479: /* Internet argument attribute. */
480: struct attr *
481: bgp_attr_intern (struct attr *attr)
482: {
483: struct attr *find;
484:
485: /* Intern referenced strucutre. */
486: if (attr->aspath)
487: {
488: if (! attr->aspath->refcnt)
489: attr->aspath = aspath_intern (attr->aspath);
490: else
491: attr->aspath->refcnt++;
492: }
493: if (attr->community)
494: {
495: if (! attr->community->refcnt)
496: attr->community = community_intern (attr->community);
497: else
498: attr->community->refcnt++;
499: }
500: if (attr->extra)
501: {
502: struct attr_extra *attre = attr->extra;
503:
504: if (attre->ecommunity)
505: {
506: if (! attre->ecommunity->refcnt)
507: attre->ecommunity = ecommunity_intern (attre->ecommunity);
508: else
509: attre->ecommunity->refcnt++;
510:
511: }
512: if (attre->cluster)
513: {
514: if (! attre->cluster->refcnt)
515: attre->cluster = cluster_intern (attre->cluster);
516: else
517: attre->cluster->refcnt++;
518: }
519: if (attre->transit)
520: {
521: if (! attre->transit->refcnt)
522: attre->transit = transit_intern (attre->transit);
523: else
524: attre->transit->refcnt++;
525: }
526: }
527:
528: find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
529: find->refcnt++;
530:
531: return find;
532: }
533:
534:
535: /* Make network statement's attribute. */
536: struct attr *
537: bgp_attr_default_set (struct attr *attr, u_char origin)
538: {
539: memset (attr, 0, sizeof (struct attr));
540: bgp_attr_extra_get (attr);
541:
542: attr->origin = origin;
543: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
544: attr->aspath = aspath_empty ();
545: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
546: attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
547: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
548: #ifdef HAVE_IPV6
549: attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
550: #endif
551:
552: return attr;
553: }
554:
555:
556: /* Make network statement's attribute. */
557: struct attr *
558: bgp_attr_default_intern (u_char origin)
559: {
560: struct attr attr;
561: struct attr *new;
562:
563: memset (&attr, 0, sizeof (struct attr));
1.1.1.2 ! misho 564: bgp_attr_extra_get (&attr);
1.1 misho 565:
566: bgp_attr_default_set(&attr, origin);
567:
568: new = bgp_attr_intern (&attr);
569: bgp_attr_extra_free (&attr);
570:
571: aspath_unintern (&new->aspath);
572: return new;
573: }
574:
575: struct attr *
576: bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
577: struct aspath *aspath,
578: struct community *community, int as_set)
579: {
580: struct attr attr;
581: struct attr *new;
582: struct attr_extra *attre;
583:
584: memset (&attr, 0, sizeof (struct attr));
585: attre = bgp_attr_extra_get (&attr);
586:
587: /* Origin attribute. */
588: attr.origin = origin;
589: attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
590:
591: /* AS path attribute. */
592: if (aspath)
593: attr.aspath = aspath_intern (aspath);
594: else
595: attr.aspath = aspath_empty ();
596: attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
597:
598: /* Next hop attribute. */
599: attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
600:
601: if (community)
602: {
603: attr.community = community;
604: attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
605: }
606:
607: attre->weight = BGP_ATTR_DEFAULT_WEIGHT;
608: #ifdef HAVE_IPV6
609: attre->mp_nexthop_len = IPV6_MAX_BYTELEN;
610: #endif
611: if (! as_set)
612: attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
613: attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
614: if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
615: attre->aggregator_as = bgp->confed_id;
616: else
617: attre->aggregator_as = bgp->as;
618: attre->aggregator_addr = bgp->router_id;
619:
620: new = bgp_attr_intern (&attr);
621: bgp_attr_extra_free (&attr);
622:
623: aspath_unintern (&new->aspath);
624: return new;
625: }
626:
627: /* Unintern just the sub-components of the attr, but not the attr */
628: void
629: bgp_attr_unintern_sub (struct attr *attr)
630: {
631: /* aspath refcount shoud be decrement. */
632: if (attr->aspath)
633: aspath_unintern (&attr->aspath);
634: UNSET_FLAG(attr->flag, BGP_ATTR_AS_PATH);
635:
636: if (attr->community)
637: community_unintern (&attr->community);
638: UNSET_FLAG(attr->flag, BGP_ATTR_COMMUNITIES);
639:
640: if (attr->extra)
641: {
642: if (attr->extra->ecommunity)
643: ecommunity_unintern (&attr->extra->ecommunity);
644: UNSET_FLAG(attr->flag, BGP_ATTR_EXT_COMMUNITIES);
645:
646: if (attr->extra->cluster)
647: cluster_unintern (attr->extra->cluster);
648: UNSET_FLAG(attr->flag, BGP_ATTR_CLUSTER_LIST);
649:
650: if (attr->extra->transit)
651: transit_unintern (attr->extra->transit);
652: }
653: }
654:
655: /* Free bgp attribute and aspath. */
656: void
657: bgp_attr_unintern (struct attr **attr)
658: {
659: struct attr *ret;
660: struct attr tmp;
661:
662: /* Decrement attribute reference. */
663: (*attr)->refcnt--;
664:
665: tmp = *(*attr);
666:
667: if ((*attr)->extra)
668: {
669: tmp.extra = bgp_attr_extra_new ();
670: memcpy (tmp.extra, (*attr)->extra, sizeof (struct attr_extra));
671: }
672:
673: /* If reference becomes zero then free attribute object. */
674: if ((*attr)->refcnt == 0)
675: {
676: ret = hash_release (attrhash, *attr);
677: assert (ret != NULL);
678: bgp_attr_extra_free (*attr);
679: XFREE (MTYPE_ATTR, *attr);
680: *attr = NULL;
681: }
682:
683: bgp_attr_unintern_sub (&tmp);
1.1.1.2 ! misho 684: bgp_attr_extra_free (&tmp);
1.1 misho 685: }
686:
687: void
688: bgp_attr_flush (struct attr *attr)
689: {
690: if (attr->aspath && ! attr->aspath->refcnt)
691: aspath_free (attr->aspath);
692: if (attr->community && ! attr->community->refcnt)
693: community_free (attr->community);
694: if (attr->extra)
695: {
696: struct attr_extra *attre = attr->extra;
697:
698: if (attre->ecommunity && ! attre->ecommunity->refcnt)
699: ecommunity_free (&attre->ecommunity);
700: if (attre->cluster && ! attre->cluster->refcnt)
701: cluster_free (attre->cluster);
702: if (attre->transit && ! attre->transit->refcnt)
703: transit_free (attre->transit);
704: }
705: }
706:
707: /* Implement draft-scudder-idr-optional-transitive behaviour and
708: * avoid resetting sessions for malformed attributes which are
709: * are partial/optional and hence where the error likely was not
710: * introduced by the sending neighbour.
711: */
712: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 713: bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode,
! 714: bgp_size_t length)
1.1 misho 715: {
1.1.1.2 ! misho 716: struct peer *const peer = args->peer;
! 717: const u_int8_t flags = args->flags;
! 718: /* startp and length must be special-cased, as whether or not to
! 719: * send the attribute data with the NOTIFY depends on the error,
! 720: * the caller therefore signals this with the seperate length argument
! 721: */
! 722: u_char *notify_datap = (length > 0 ? args->startp : NULL);
! 723:
1.1 misho 724: /* Only relax error handling for eBGP peers */
725: if (peer_sort (peer) != BGP_PEER_EBGP)
726: {
727: bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1.1.1.2 ! misho 728: notify_datap, length);
1.1 misho 729: return BGP_ATTR_PARSE_ERROR;
730:
731: }
732:
1.1.1.2 ! misho 733: /* Adjust the stream getp to the end of the attribute, in case we can
! 734: * still proceed but the caller hasn't read all the attribute.
! 735: */
! 736: stream_set_getp (BGP_INPUT (peer),
! 737: (args->startp - STREAM_DATA (BGP_INPUT (peer)))
! 738: + args->total);
! 739:
! 740: switch (args->type) {
! 741: /* where an attribute is relatively inconsequential, e.g. it does not
! 742: * affect route selection, and can be safely ignored, then any such
! 743: * attributes which are malformed should just be ignored and the route
! 744: * processed as normal.
1.1 misho 745: */
746: case BGP_ATTR_AS4_AGGREGATOR:
747: case BGP_ATTR_AGGREGATOR:
748: case BGP_ATTR_ATOMIC_AGGREGATE:
749: return BGP_ATTR_PARSE_PROCEED;
750:
751: /* Core attributes, particularly ones which may influence route
1.1.1.2 ! misho 752: * selection, should always cause session resets
1.1 misho 753: */
754: case BGP_ATTR_ORIGIN:
755: case BGP_ATTR_AS_PATH:
756: case BGP_ATTR_NEXT_HOP:
757: case BGP_ATTR_MULTI_EXIT_DISC:
758: case BGP_ATTR_LOCAL_PREF:
759: case BGP_ATTR_COMMUNITIES:
760: case BGP_ATTR_ORIGINATOR_ID:
761: case BGP_ATTR_CLUSTER_LIST:
762: case BGP_ATTR_MP_REACH_NLRI:
763: case BGP_ATTR_MP_UNREACH_NLRI:
764: case BGP_ATTR_EXT_COMMUNITIES:
765: bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1.1.1.2 ! misho 766: notify_datap, length);
1.1 misho 767: return BGP_ATTR_PARSE_ERROR;
768: }
769:
770: /* Partial optional attributes that are malformed should not cause
771: * the whole session to be reset. Instead treat it as a withdrawal
772: * of the routes, if possible.
773: */
1.1.1.2 ! misho 774: if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)
! 775: && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
! 776: && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
1.1 misho 777: return BGP_ATTR_PARSE_WITHDRAW;
778:
779: /* default to reset */
780: return BGP_ATTR_PARSE_ERROR;
781: }
782:
1.1.1.2 ! misho 783: /* Find out what is wrong with the path attribute flag bits and log the error.
! 784: "Flag bits" here stand for Optional, Transitive and Partial, but not for
! 785: Extended Length. Checking O/T/P bits at once implies, that the attribute
! 786: being diagnosed is defined by RFC as either a "well-known" or an "optional,
! 787: non-transitive" attribute. */
! 788: static void
! 789: bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
! 790: u_int8_t desired_flags /* how RFC says it must be */
! 791: )
! 792: {
! 793: u_char seen = 0, i;
! 794: u_char real_flags = args->flags;
! 795: const u_int8_t attr_code = args->type;
! 796:
! 797: desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
! 798: real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
! 799: for (i = 0; i <= 2; i++) /* O,T,P, but not E */
! 800: if
! 801: (
! 802: CHECK_FLAG (desired_flags, attr_flag_str[i].key) !=
! 803: CHECK_FLAG (real_flags, attr_flag_str[i].key)
! 804: )
! 805: {
! 806: zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
! 807: LOOKUP (attr_str, attr_code),
! 808: CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
! 809: attr_flag_str[i].str);
! 810: seen = 1;
! 811: }
! 812: if (!seen)
! 813: {
! 814: zlog (args->peer->log, LOG_DEBUG,
! 815: "Strange, %s called for attr %s, but no problem found with flags"
! 816: " (real flags 0x%x, desired 0x%x)",
! 817: __func__, LOOKUP (attr_str, attr_code),
! 818: real_flags, desired_flags);
! 819: }
! 820: }
! 821:
! 822: /* Required flags for attributes. EXTLEN will be masked off when testing,
! 823: * as will PARTIAL for optional+transitive attributes.
! 824: */
! 825: const u_int8_t attr_flags_values [] = {
! 826: [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
! 827: [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
! 828: [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
! 829: [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
! 830: [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
! 831: [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
! 832: [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
! 833: [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
! 834: [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
! 835: [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
! 836: [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
! 837: [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
! 838: [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
! 839: [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
! 840: [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
! 841: };
! 842: static const size_t attr_flags_values_max =
! 843: sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
1.1 misho 844:
1.1.1.2 ! misho 845: static int
! 846: bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
! 847: {
! 848: u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
! 849: const u_int8_t flags = args->flags;
! 850: const u_int8_t attr_code = args->type;
! 851: struct peer *const peer = args->peer;
! 852:
! 853: /* there may be attributes we don't know about */
! 854: if (attr_code > attr_flags_values_max)
! 855: return 0;
! 856: if (attr_flags_values[attr_code] == 0)
! 857: return 0;
! 858:
! 859: /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to
! 860: * 1."
! 861: */
! 862: if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
! 863: && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
1.1 misho 864: {
1.1.1.2 ! misho 865: zlog (peer->log, LOG_ERR,
! 866: "%s well-known attributes must have transitive flag set (%x)",
! 867: LOOKUP (attr_str, attr_code), flags);
! 868: return 1;
! 869: }
! 870:
! 871: /* "For well-known attributes and for optional non-transitive attributes,
! 872: * the Partial bit MUST be set to 0."
! 873: */
! 874: if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL))
! 875: {
! 876: if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
! 877: {
! 878: zlog (peer->log, LOG_ERR,
! 879: "%s well-known attribute "
! 880: "must NOT have the partial flag set (%x)",
! 881: LOOKUP (attr_str, attr_code), flags);
! 882: return 1;
! 883: }
! 884: if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
! 885: && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
! 886: {
! 887: zlog (peer->log, LOG_ERR,
! 888: "%s optional + transitive attribute "
! 889: "must NOT have the partial flag set (%x)",
! 890: LOOKUP (attr_str, attr_code), flags);
! 891: return 1;
! 892: }
1.1 misho 893: }
1.1.1.2 ! misho 894:
! 895: /* Optional transitive attributes may go through speakers that don't
! 896: * reocgnise them and set the Partial bit.
! 897: */
! 898: if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
! 899: && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
! 900: SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL);
! 901:
! 902: if ((flags & ~mask)
! 903: == attr_flags_values[attr_code])
! 904: return 0;
! 905:
! 906: bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]);
! 907: return 1;
! 908: }
1.1 misho 909:
1.1.1.2 ! misho 910: /* Get origin attribute of the update message. */
! 911: static bgp_attr_parse_ret_t
! 912: bgp_attr_origin (struct bgp_attr_parser_args *args)
! 913: {
! 914: struct peer *const peer = args->peer;
! 915: struct attr *const attr = args->attr;
! 916: const bgp_size_t length = args->length;
! 917:
1.1 misho 918: /* If any recognized attribute has Attribute Length that conflicts
919: with the expected length (based on the attribute type code), then
920: the Error Subcode is set to Attribute Length Error. The Data
921: field contains the erroneous attribute (type, length and
922: value). */
923: if (length != 1)
924: {
925: zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
926: length);
1.1.1.2 ! misho 927: return bgp_attr_malformed (args,
1.1 misho 928: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 929: args->total);
1.1 misho 930: }
931:
932: /* Fetch origin attribute. */
933: attr->origin = stream_getc (BGP_INPUT (peer));
934:
935: /* If the ORIGIN attribute has an undefined value, then the Error
936: Subcode is set to Invalid Origin Attribute. The Data field
937: contains the unrecognized attribute (type, length and value). */
938: if ((attr->origin != BGP_ORIGIN_IGP)
939: && (attr->origin != BGP_ORIGIN_EGP)
940: && (attr->origin != BGP_ORIGIN_INCOMPLETE))
941: {
942: zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
943: attr->origin);
1.1.1.2 ! misho 944: return bgp_attr_malformed (args,
1.1 misho 945: BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1.1.1.2 ! misho 946: args->total);
1.1 misho 947: }
948:
949: /* Set oring attribute flag. */
950: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
951:
952: return 0;
953: }
954:
955: /* Parse AS path information. This function is wrapper of
956: aspath_parse. */
957: static int
1.1.1.2 ! misho 958: bgp_attr_aspath (struct bgp_attr_parser_args *args)
1.1 misho 959: {
1.1.1.2 ! misho 960: struct attr *const attr = args->attr;
! 961: struct peer *const peer = args->peer;
! 962: const bgp_size_t length = args->length;
! 963:
1.1 misho 964: /*
965: * peer with AS4 => will get 4Byte ASnums
966: * otherwise, will get 16 Bit
967: */
968: attr->aspath = aspath_parse (peer->ibuf, length,
969: CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
970:
971: /* In case of IBGP, length will be zero. */
972: if (! attr->aspath)
973: {
974: zlog (peer->log, LOG_ERR,
975: "Malformed AS path from %s, length is %d",
976: peer->host, length);
1.1.1.2 ! misho 977: return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
1.1 misho 978: }
979:
980: /* Set aspath attribute flag. */
981: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
982:
983: return BGP_ATTR_PARSE_PROCEED;
984: }
985:
986: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 987: bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
1.1 misho 988: {
989: /* These checks were part of bgp_attr_aspath, but with
990: * as4 we should to check aspath things when
991: * aspath synthesizing with as4_path has already taken place.
992: * Otherwise we check ASPATH and use the synthesized thing, and that is
993: * not right.
994: * So do the checks later, i.e. here
995: */
996: struct bgp *bgp = peer->bgp;
997: struct aspath *aspath;
998:
999: bgp = peer->bgp;
1000:
1001: /* Confederation sanity check. */
1002: if ((peer_sort (peer) == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
1003: (peer_sort (peer) == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
1004: {
1005: zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
1.1.1.2 ! misho 1006: bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
! 1007: BGP_NOTIFY_UPDATE_MAL_AS_PATH);
! 1008: return BGP_ATTR_PARSE_ERROR;
1.1 misho 1009: }
1010:
1011: /* First AS check for EBGP. */
1012: if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
1013: {
1014: if (peer_sort (peer) == BGP_PEER_EBGP
1015: && ! aspath_firstas_check (attr->aspath, peer->as))
1016: {
1017: zlog (peer->log, LOG_ERR,
1018: "%s incorrect first AS (must be %u)", peer->host, peer->as);
1.1.1.2 ! misho 1019: bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
! 1020: BGP_NOTIFY_UPDATE_MAL_AS_PATH);
! 1021: return BGP_ATTR_PARSE_ERROR;
1.1 misho 1022: }
1023: }
1024:
1025: /* local-as prepend */
1026: if (peer->change_local_as &&
1027: ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
1028: {
1029: aspath = aspath_dup (attr->aspath);
1030: aspath = aspath_add_seq (aspath, peer->change_local_as);
1031: aspath_unintern (&attr->aspath);
1032: attr->aspath = aspath_intern (aspath);
1033: }
1034:
1035: return BGP_ATTR_PARSE_PROCEED;
1036: }
1037:
1038: /* Parse AS4 path information. This function is another wrapper of
1039: aspath_parse. */
1040: static int
1.1.1.2 ! misho 1041: bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
1.1 misho 1042: {
1.1.1.2 ! misho 1043: struct peer *const peer = args->peer;
! 1044: struct attr *const attr = args->attr;
! 1045: const bgp_size_t length = args->length;
! 1046:
1.1 misho 1047: *as4_path = aspath_parse (peer->ibuf, length, 1);
1048:
1049: /* In case of IBGP, length will be zero. */
1050: if (!*as4_path)
1051: {
1052: zlog (peer->log, LOG_ERR,
1053: "Malformed AS4 path from %s, length is %d",
1054: peer->host, length);
1.1.1.2 ! misho 1055: return bgp_attr_malformed (args,
1.1 misho 1056: BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1.1.1.2 ! misho 1057: 0);
1.1 misho 1058: }
1059:
1060: /* Set aspath attribute flag. */
1061: if (as4_path)
1062: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
1063:
1064: return BGP_ATTR_PARSE_PROCEED;
1065: }
1066:
1067: /* Nexthop attribute. */
1068: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1069: bgp_attr_nexthop (struct bgp_attr_parser_args *args)
1.1 misho 1070: {
1.1.1.2 ! misho 1071: struct peer *const peer = args->peer;
! 1072: struct attr *const attr = args->attr;
! 1073: const bgp_size_t length = args->length;
! 1074:
! 1075: in_addr_t nexthop_h, nexthop_n;
1.1 misho 1076:
1077: /* Check nexthop attribute length. */
1078: if (length != 4)
1079: {
1080: zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
1081: length);
1082:
1.1.1.2 ! misho 1083: return bgp_attr_malformed (args,
1.1 misho 1084: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 1085: args->total);
1.1 misho 1086: }
1087:
1.1.1.2 ! misho 1088: /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
! 1089: attribute must result in a NOTIFICATION message (this is implemented below).
! 1090: At the same time, semantically incorrect NEXT_HOP is more likely to be just
! 1091: logged locally (this is implemented somewhere else). The UPDATE message
! 1092: gets ignored in any of these cases. */
! 1093: nexthop_n = stream_get_ipv4 (peer->ibuf);
! 1094: nexthop_h = ntohl (nexthop_n);
! 1095: if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h))
! 1096: {
! 1097: char buf[INET_ADDRSTRLEN];
! 1098: inet_ntop (AF_INET, &nexthop_h, buf, INET_ADDRSTRLEN);
! 1099: zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
! 1100: return bgp_attr_malformed (args,
! 1101: BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
! 1102: args->total);
! 1103: }
! 1104:
! 1105: attr->nexthop.s_addr = nexthop_n;
1.1 misho 1106: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1107:
1108: return BGP_ATTR_PARSE_PROCEED;
1109: }
1110:
1111: /* MED atrribute. */
1112: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1113: bgp_attr_med (struct bgp_attr_parser_args *args)
1.1 misho 1114: {
1.1.1.2 ! misho 1115: struct peer *const peer = args->peer;
! 1116: struct attr *const attr = args->attr;
! 1117: const bgp_size_t length = args->length;
! 1118:
1.1 misho 1119: /* Length check. */
1120: if (length != 4)
1121: {
1122: zlog (peer->log, LOG_ERR,
1123: "MED attribute length isn't four [%d]", length);
1124:
1.1.1.2 ! misho 1125: return bgp_attr_malformed (args,
1.1 misho 1126: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 1127: args->total);
1.1 misho 1128: }
1129:
1130: attr->med = stream_getl (peer->ibuf);
1131:
1132: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1133:
1134: return BGP_ATTR_PARSE_PROCEED;
1135: }
1136:
1137: /* Local preference attribute. */
1138: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1139: bgp_attr_local_pref (struct bgp_attr_parser_args *args)
1.1 misho 1140: {
1.1.1.2 ! misho 1141: struct peer *const peer = args->peer;
! 1142: struct attr *const attr = args->attr;
! 1143: const bgp_size_t length = args->length;
! 1144:
! 1145: /* Length check. */
! 1146: if (length != 4)
! 1147: {
! 1148: zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
! 1149: length);
! 1150: return bgp_attr_malformed (args,
! 1151: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
! 1152: args->total);
! 1153: }
1.1 misho 1154:
1155: /* If it is contained in an UPDATE message that is received from an
1156: external peer, then this attribute MUST be ignored by the
1157: receiving speaker. */
1158: if (peer_sort (peer) == BGP_PEER_EBGP)
1159: {
1160: stream_forward_getp (peer->ibuf, length);
1161: return BGP_ATTR_PARSE_PROCEED;
1162: }
1163:
1.1.1.2 ! misho 1164: attr->local_pref = stream_getl (peer->ibuf);
1.1 misho 1165:
1166: /* Set atomic aggregate flag. */
1167: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1168:
1169: return BGP_ATTR_PARSE_PROCEED;
1170: }
1171:
1172: /* Atomic aggregate. */
1173: static int
1.1.1.2 ! misho 1174: bgp_attr_atomic (struct bgp_attr_parser_args *args)
1.1 misho 1175: {
1.1.1.2 ! misho 1176: struct peer *const peer = args->peer;
! 1177: struct attr *const attr = args->attr;
! 1178: const bgp_size_t length = args->length;
! 1179:
1.1 misho 1180: /* Length check. */
1181: if (length != 0)
1182: {
1.1.1.2 ! misho 1183: zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
! 1184: length);
! 1185: return bgp_attr_malformed (args,
1.1 misho 1186: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 1187: args->total);
1.1 misho 1188: }
1189:
1190: /* Set atomic aggregate flag. */
1191: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1192:
1193: return BGP_ATTR_PARSE_PROCEED;
1194: }
1195:
1196: /* Aggregator attribute */
1197: static int
1.1.1.2 ! misho 1198: bgp_attr_aggregator (struct bgp_attr_parser_args *args)
1.1 misho 1199: {
1.1.1.2 ! misho 1200: struct peer *const peer = args->peer;
! 1201: struct attr *const attr = args->attr;
! 1202: const bgp_size_t length = args->length;
! 1203:
1.1 misho 1204: int wantedlen = 6;
1205: struct attr_extra *attre = bgp_attr_extra_get (attr);
1206:
1207: /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1208: if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1209: wantedlen = 8;
1210:
1211: if (length != wantedlen)
1212: {
1.1.1.2 ! misho 1213: zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
! 1214: wantedlen, length);
! 1215: return bgp_attr_malformed (args,
1.1 misho 1216: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 1217: args->total);
1.1 misho 1218: }
1219:
1220: if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
1221: attre->aggregator_as = stream_getl (peer->ibuf);
1222: else
1223: attre->aggregator_as = stream_getw (peer->ibuf);
1224: attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
1225:
1226: /* Set atomic aggregate flag. */
1227: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1228:
1229: return BGP_ATTR_PARSE_PROCEED;
1230: }
1231:
1232: /* New Aggregator attribute */
1233: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1234: bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
! 1235: as_t *as4_aggregator_as,
! 1236: struct in_addr *as4_aggregator_addr)
! 1237: {
! 1238: struct peer *const peer = args->peer;
! 1239: struct attr *const attr = args->attr;
! 1240: const bgp_size_t length = args->length;
! 1241:
1.1 misho 1242: if (length != 8)
1243: {
1.1.1.2 ! misho 1244: zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
! 1245: length);
! 1246: return bgp_attr_malformed (args,
1.1 misho 1247: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 1248: 0);
1.1 misho 1249: }
1.1.1.2 ! misho 1250:
1.1 misho 1251: *as4_aggregator_as = stream_getl (peer->ibuf);
1252: as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
1253:
1254: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
1255:
1256: return BGP_ATTR_PARSE_PROCEED;
1257: }
1258:
1259: /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1260: */
1261: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1262: bgp_attr_munge_as4_attrs (struct peer *const peer,
! 1263: struct attr *const attr,
1.1 misho 1264: struct aspath *as4_path, as_t as4_aggregator,
1265: struct in_addr *as4_aggregator_addr)
1266: {
1267: int ignore_as4_path = 0;
1268: struct aspath *newpath;
1269: struct attr_extra *attre = attr->extra;
1270:
1271: if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
1272: {
1273: /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1274: * if given.
1275: * It is worth a warning though, because the peer really
1276: * should not send them
1277: */
1278: if (BGP_DEBUG(as4, AS4))
1279: {
1280: if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
1281: zlog_debug ("[AS4] %s %s AS4_PATH",
1282: peer->host, "AS4 capable peer, yet it sent");
1283:
1284: if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
1285: zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
1286: peer->host, "AS4 capable peer, yet it sent");
1287: }
1288:
1289: return BGP_ATTR_PARSE_PROCEED;
1290: }
1291:
1292: /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1293: * because that may override AS4_PATH
1294: */
1295: if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
1296: {
1297: if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
1298: {
1299: assert (attre);
1300:
1301: /* received both.
1302: * if the as_number in aggregator is not AS_TRANS,
1303: * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1304: * and the Aggregator shall be taken as
1305: * info on the aggregating node, and the AS_PATH
1306: * shall be taken as the AS_PATH
1307: * otherwise
1308: * the Aggregator shall be ignored and the
1309: * AS4_AGGREGATOR shall be taken as the
1310: * Aggregating node and the AS_PATH is to be
1311: * constructed "as in all other cases"
1312: */
1313: if (attre->aggregator_as != BGP_AS_TRANS)
1314: {
1315: /* ignore */
1316: if ( BGP_DEBUG(as4, AS4))
1317: zlog_debug ("[AS4] %s BGP not AS4 capable peer"
1318: " send AGGREGATOR != AS_TRANS and"
1319: " AS4_AGGREGATOR, so ignore"
1320: " AS4_AGGREGATOR and AS4_PATH", peer->host);
1321: ignore_as4_path = 1;
1322: }
1323: else
1324: {
1325: /* "New_aggregator shall be taken as aggregator" */
1326: attre->aggregator_as = as4_aggregator;
1327: attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
1328: }
1329: }
1330: else
1331: {
1332: /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1333: * That is bogus - but reading the conditions
1334: * we have to handle AS4_AGGREGATOR as if it were
1335: * AGGREGATOR in that case
1336: */
1337: if ( BGP_DEBUG(as4, AS4))
1338: zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
1339: " AS4_AGGREGATOR but no AGGREGATOR, will take"
1340: " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
1341: (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
1342: /* sweep it under the carpet and simulate a "good" AGGREGATOR */
1343: attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
1344: }
1345: }
1346:
1347: /* need to reconcile NEW_AS_PATH and AS_PATH */
1348: if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
1349: {
1350: newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
1351: aspath_unintern (&attr->aspath);
1352: attr->aspath = aspath_intern (newpath);
1353: }
1354: return BGP_ATTR_PARSE_PROCEED;
1355: }
1356:
1357: /* Community attribute. */
1358: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1359: bgp_attr_community (struct bgp_attr_parser_args *args)
1.1 misho 1360: {
1.1.1.2 ! misho 1361: struct peer *const peer = args->peer;
! 1362: struct attr *const attr = args->attr;
! 1363: const bgp_size_t length = args->length;
1.1 misho 1364:
1365: if (length == 0)
1366: {
1367: attr->community = NULL;
1368: return BGP_ATTR_PARSE_PROCEED;
1369: }
1370:
1371: attr->community =
1372: community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length);
1373:
1374: /* XXX: fix community_parse to use stream API and remove this */
1375: stream_forward_getp (peer->ibuf, length);
1376:
1377: if (!attr->community)
1.1.1.2 ! misho 1378: return bgp_attr_malformed (args,
1.1 misho 1379: BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
1.1.1.2 ! misho 1380: args->total);
1.1 misho 1381:
1382: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1383:
1384: return BGP_ATTR_PARSE_PROCEED;
1385: }
1386:
1387: /* Originator ID attribute. */
1388: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1389: bgp_attr_originator_id (struct bgp_attr_parser_args *args)
1.1 misho 1390: {
1.1.1.2 ! misho 1391: struct peer *const peer = args->peer;
! 1392: struct attr *const attr = args->attr;
! 1393: const bgp_size_t length = args->length;
! 1394:
! 1395: /* Length check. */
1.1 misho 1396: if (length != 4)
1397: {
1398: zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
1399:
1.1.1.2 ! misho 1400: return bgp_attr_malformed (args,
1.1 misho 1401: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1.1.1.2 ! misho 1402: args->total);
1.1 misho 1403: }
1404:
1405: (bgp_attr_extra_get (attr))->originator_id.s_addr
1406: = stream_get_ipv4 (peer->ibuf);
1407:
1408: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1409:
1410: return BGP_ATTR_PARSE_PROCEED;
1411: }
1412:
1413: /* Cluster list attribute. */
1414: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1415: bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
1.1 misho 1416: {
1.1.1.2 ! misho 1417: struct peer *const peer = args->peer;
! 1418: struct attr *const attr = args->attr;
! 1419: const bgp_size_t length = args->length;
! 1420:
1.1 misho 1421: /* Check length. */
1422: if (length % 4)
1423: {
1424: zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
1425:
1.1.1.2 ! misho 1426: return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
! 1427: args->total);
1.1 misho 1428: }
1429:
1430: (bgp_attr_extra_get (attr))->cluster
1431: = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
1432:
1433: /* XXX: Fix cluster_parse to use stream API and then remove this */
1434: stream_forward_getp (peer->ibuf, length);
1435:
1436: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
1437:
1438: return BGP_ATTR_PARSE_PROCEED;
1439: }
1440:
1441: /* Multiprotocol reachability information parse. */
1442: int
1.1.1.2 ! misho 1443: bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
! 1444: struct bgp_nlri *mp_update)
1.1 misho 1445: {
1446: afi_t afi;
1447: safi_t safi;
1448: bgp_size_t nlri_len;
1449: size_t start;
1450: int ret;
1451: struct stream *s;
1.1.1.2 ! misho 1452: struct peer *const peer = args->peer;
! 1453: struct attr *const attr = args->attr;
! 1454: const bgp_size_t length = args->length;
1.1 misho 1455: struct attr_extra *attre = bgp_attr_extra_get(attr);
1456:
1457: /* Set end of packet. */
1458: s = BGP_INPUT(peer);
1459: start = stream_get_getp(s);
1460:
1461: /* safe to read statically sized header? */
1462: #define BGP_MP_REACH_MIN_SIZE 5
1463: #define LEN_LEFT (length - (stream_get_getp(s) - start))
1464: if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE))
1465: {
1466: zlog_info ("%s: %s sent invalid length, %lu",
1467: __func__, peer->host, (unsigned long)length);
1468: return BGP_ATTR_PARSE_ERROR;
1469: }
1470:
1471: /* Load AFI, SAFI. */
1472: afi = stream_getw (s);
1473: safi = stream_getc (s);
1474:
1475: /* Get nexthop length. */
1476: attre->mp_nexthop_len = stream_getc (s);
1477:
1478: if (LEN_LEFT < attre->mp_nexthop_len)
1479: {
1480: zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute",
1481: __func__, peer->host, attre->mp_nexthop_len);
1482: return BGP_ATTR_PARSE_ERROR;
1483: }
1484:
1485: /* Nexthop length check. */
1486: switch (attre->mp_nexthop_len)
1487: {
1488: case 4:
1489: stream_get (&attre->mp_nexthop_global_in, s, 4);
1490: /* Probably needed for RFC 2283 */
1491: if (attr->nexthop.s_addr == 0)
1492: memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
1493: break;
1494: case 12:
1.1.1.2 ! misho 1495: stream_getl (s); /* RD high */
! 1496: stream_getl (s); /* RD low */
! 1497: stream_get (&attre->mp_nexthop_global_in, s, 4);
1.1 misho 1498: break;
1499: #ifdef HAVE_IPV6
1500: case 16:
1501: stream_get (&attre->mp_nexthop_global, s, 16);
1502: break;
1503: case 32:
1504: stream_get (&attre->mp_nexthop_global, s, 16);
1505: stream_get (&attre->mp_nexthop_local, s, 16);
1506: if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
1507: {
1508: char buf1[INET6_ADDRSTRLEN];
1509: char buf2[INET6_ADDRSTRLEN];
1510:
1511: if (BGP_DEBUG (update, UPDATE_IN))
1512: zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
1513: inet_ntop (AF_INET6, &attre->mp_nexthop_global,
1514: buf1, INET6_ADDRSTRLEN),
1515: inet_ntop (AF_INET6, &attre->mp_nexthop_local,
1516: buf2, INET6_ADDRSTRLEN));
1517:
1518: attre->mp_nexthop_len = 16;
1519: }
1520: break;
1521: #endif /* HAVE_IPV6 */
1522: default:
1523: zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d",
1524: __func__, peer->host, attre->mp_nexthop_len);
1525: return BGP_ATTR_PARSE_ERROR;
1526: }
1527:
1528: if (!LEN_LEFT)
1529: {
1530: zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
1531: __func__, peer->host);
1532: return BGP_ATTR_PARSE_ERROR;
1533: }
1534:
1535: {
1536: u_char val;
1537: if ((val = stream_getc (s)))
1538: zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field",
1539: peer->host, val);
1540: }
1541:
1542: /* must have nrli_len, what is left of the attribute */
1543: nlri_len = LEN_LEFT;
1544: if ((!nlri_len) || (nlri_len > STREAM_READABLE(s)))
1545: {
1546: zlog_info ("%s: (%s) Failed to read NLRI",
1547: __func__, peer->host);
1548: return BGP_ATTR_PARSE_ERROR;
1549: }
1550:
1.1.1.2 ! misho 1551: if (safi != SAFI_MPLS_LABELED_VPN)
1.1 misho 1552: {
1553: ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
1554: if (ret < 0)
1555: {
1556: zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
1557: __func__, peer->host);
1558: return BGP_ATTR_PARSE_ERROR;
1559: }
1560: }
1561:
1562: mp_update->afi = afi;
1563: mp_update->safi = safi;
1564: mp_update->nlri = stream_pnt (s);
1565: mp_update->length = nlri_len;
1566:
1567: stream_forward_getp (s, nlri_len);
1568:
1569: return BGP_ATTR_PARSE_PROCEED;
1570: #undef LEN_LEFT
1571: }
1572:
1573: /* Multiprotocol unreachable parse */
1574: int
1.1.1.2 ! misho 1575: bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
1.1 misho 1576: struct bgp_nlri *mp_withdraw)
1577: {
1578: struct stream *s;
1579: afi_t afi;
1580: safi_t safi;
1581: u_int16_t withdraw_len;
1582: int ret;
1.1.1.2 ! misho 1583: struct peer *const peer = args->peer;
! 1584: const bgp_size_t length = args->length;
1.1 misho 1585:
1586: s = peer->ibuf;
1587:
1588: #define BGP_MP_UNREACH_MIN_SIZE 3
1589: if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
1590: return BGP_ATTR_PARSE_ERROR;
1591:
1592: afi = stream_getw (s);
1593: safi = stream_getc (s);
1594:
1595: withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
1596:
1.1.1.2 ! misho 1597: if (safi != SAFI_MPLS_LABELED_VPN)
1.1 misho 1598: {
1599: ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
1600: if (ret < 0)
1601: return BGP_ATTR_PARSE_ERROR;
1602: }
1603:
1604: mp_withdraw->afi = afi;
1605: mp_withdraw->safi = safi;
1606: mp_withdraw->nlri = stream_pnt (s);
1607: mp_withdraw->length = withdraw_len;
1608:
1609: stream_forward_getp (s, withdraw_len);
1610:
1611: return BGP_ATTR_PARSE_PROCEED;
1612: }
1613:
1614: /* Extended Community attribute. */
1615: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1616: bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
1.1 misho 1617: {
1.1.1.2 ! misho 1618: struct peer *const peer = args->peer;
! 1619: struct attr *const attr = args->attr;
! 1620: const bgp_size_t length = args->length;
1.1 misho 1621:
1622: if (length == 0)
1623: {
1624: if (attr->extra)
1625: attr->extra->ecommunity = NULL;
1626: /* Empty extcomm doesn't seem to be invalid per se */
1627: return BGP_ATTR_PARSE_PROCEED;
1628: }
1629:
1630: (bgp_attr_extra_get (attr))->ecommunity =
1631: ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
1632: /* XXX: fix ecommunity_parse to use stream API */
1633: stream_forward_getp (peer->ibuf, length);
1634:
1635: if (!attr->extra->ecommunity)
1.1.1.2 ! misho 1636: return bgp_attr_malformed (args,
! 1637: BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
! 1638: args->total);
1.1 misho 1639:
1640: attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1641:
1642: return BGP_ATTR_PARSE_PROCEED;
1643: }
1644:
1645: /* BGP unknown attribute treatment. */
1646: static bgp_attr_parse_ret_t
1.1.1.2 ! misho 1647: bgp_attr_unknown (struct bgp_attr_parser_args *args)
1.1 misho 1648: {
1649: bgp_size_t total;
1650: struct transit *transit;
1651: struct attr_extra *attre;
1.1.1.2 ! misho 1652: struct peer *const peer = args->peer;
! 1653: struct attr *const attr = args->attr;
! 1654: u_char *const startp = args->startp;
! 1655: const u_char type = args->type;
! 1656: const u_char flag = args->flags;
! 1657: const bgp_size_t length = args->length;
! 1658:
1.1 misho 1659:
1660: if (BGP_DEBUG (normal, NORMAL))
1661: zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
1662: peer->host, type, length);
1663:
1664: if (BGP_DEBUG (events, EVENTS))
1665: zlog (peer->log, LOG_DEBUG,
1666: "Unknown attribute type %d length %d is received", type, length);
1667:
1668: /* Forward read pointer of input stream. */
1669: stream_forward_getp (peer->ibuf, length);
1670:
1671: /* If any of the mandatory well-known attributes are not recognized,
1672: then the Error Subcode is set to Unrecognized Well-known
1673: Attribute. The Data field contains the unrecognized attribute
1674: (type, length and value). */
1675: if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
1676: {
1.1.1.2 ! misho 1677: return bgp_attr_malformed (args,
1.1 misho 1678: BGP_NOTIFY_UPDATE_UNREC_ATTR,
1.1.1.2 ! misho 1679: args->total);
1.1 misho 1680: }
1681:
1682: /* Unrecognized non-transitive optional attributes must be quietly
1683: ignored and not passed along to other BGP peers. */
1684: if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
1685: return BGP_ATTR_PARSE_PROCEED;
1686:
1687: /* If a path with recognized transitive optional attribute is
1688: accepted and passed along to other BGP peers and the Partial bit
1689: in the Attribute Flags octet is set to 1 by some previous AS, it
1690: is not set back to 0 by the current AS. */
1691: SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
1692:
1693: /* Store transitive attribute to the end of attr->transit. */
1694: if (! ((attre = bgp_attr_extra_get(attr))->transit) )
1695: attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
1696:
1697: transit = attre->transit;
1698:
1699: if (transit->val)
1700: transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val,
1701: transit->length + total);
1702: else
1703: transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
1704:
1705: memcpy (transit->val + transit->length, startp, total);
1706: transit->length += total;
1707:
1708: return BGP_ATTR_PARSE_PROCEED;
1709: }
1710:
1711: /* Read attribute of update packet. This function is called from
1712: bgp_update() in bgpd.c. */
1713: bgp_attr_parse_ret_t
1714: bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
1715: struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
1716: {
1717: int ret;
1718: u_char flag = 0;
1719: u_char type = 0;
1720: bgp_size_t length;
1721: u_char *startp, *endp;
1722: u_char *attr_endp;
1723: u_char seen[BGP_ATTR_BITMAP_SIZE];
1724: /* we need the as4_path only until we have synthesized the as_path with it */
1725: /* same goes for as4_aggregator */
1726: struct aspath *as4_path = NULL;
1727: as_t as4_aggregator = 0;
1728: struct in_addr as4_aggregator_addr = { 0 };
1729:
1730: /* Initialize bitmap. */
1731: memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
1732:
1733: /* End pointer of BGP attribute. */
1734: endp = BGP_INPUT_PNT (peer) + size;
1735:
1736: /* Get attributes to the end of attribute length. */
1737: while (BGP_INPUT_PNT (peer) < endp)
1738: {
1739: /* Check remaining length check.*/
1740: if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
1741: {
1742: /* XXX warning: long int format, int arg (arg 5) */
1743: zlog (peer->log, LOG_WARNING,
1744: "%s: error BGP attribute length %lu is smaller than min len",
1745: peer->host,
1746: (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1747:
1748: bgp_notify_send (peer,
1749: BGP_NOTIFY_UPDATE_ERR,
1750: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1751: return BGP_ATTR_PARSE_ERROR;
1752: }
1753:
1754: /* Fetch attribute flag and type. */
1755: startp = BGP_INPUT_PNT (peer);
1.1.1.2 ! misho 1756: /* "The lower-order four bits of the Attribute Flags octet are
! 1757: unused. They MUST be zero when sent and MUST be ignored when
! 1758: received." */
! 1759: flag = 0xF0 & stream_getc (BGP_INPUT (peer));
1.1 misho 1760: type = stream_getc (BGP_INPUT (peer));
1761:
1762: /* Check whether Extended-Length applies and is in bounds */
1763: if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
1764: && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
1765: {
1766: zlog (peer->log, LOG_WARNING,
1767: "%s: Extended length set, but just %lu bytes of attr header",
1768: peer->host,
1769: (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
1770:
1771: bgp_notify_send (peer,
1772: BGP_NOTIFY_UPDATE_ERR,
1773: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1774: return BGP_ATTR_PARSE_ERROR;
1775: }
1.1.1.2 ! misho 1776:
1.1 misho 1777: /* Check extended attribue length bit. */
1778: if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
1779: length = stream_getw (BGP_INPUT (peer));
1780: else
1781: length = stream_getc (BGP_INPUT (peer));
1782:
1783: /* If any attribute appears more than once in the UPDATE
1784: message, then the Error Subcode is set to Malformed Attribute
1785: List. */
1786:
1787: if (CHECK_BITMAP (seen, type))
1788: {
1789: zlog (peer->log, LOG_WARNING,
1790: "%s: error BGP attribute type %d appears twice in a message",
1791: peer->host, type);
1792:
1793: bgp_notify_send (peer,
1794: BGP_NOTIFY_UPDATE_ERR,
1795: BGP_NOTIFY_UPDATE_MAL_ATTR);
1796: return BGP_ATTR_PARSE_ERROR;
1797: }
1798:
1799: /* Set type to bitmap to check duplicate attribute. `type' is
1800: unsigned char so it never overflow bitmap range. */
1801:
1802: SET_BITMAP (seen, type);
1803:
1804: /* Overflow check. */
1805: attr_endp = BGP_INPUT_PNT (peer) + length;
1806:
1807: if (attr_endp > endp)
1808: {
1809: zlog (peer->log, LOG_WARNING,
1810: "%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);
1811: bgp_notify_send (peer,
1812: BGP_NOTIFY_UPDATE_ERR,
1813: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1814: return BGP_ATTR_PARSE_ERROR;
1815: }
1.1.1.2 ! misho 1816:
! 1817: struct bgp_attr_parser_args attr_args = {
! 1818: .peer = peer,
! 1819: .length = length,
! 1820: .attr = attr,
! 1821: .type = type,
! 1822: .flags = flag,
! 1823: .startp = startp,
! 1824: .total = attr_endp - startp,
! 1825: };
! 1826:
! 1827:
! 1828: /* If any recognized attribute has Attribute Flags that conflict
! 1829: with the Attribute Type Code, then the Error Subcode is set to
! 1830: Attribute Flags Error. The Data field contains the erroneous
! 1831: attribute (type, length and value). */
! 1832: if (bgp_attr_flag_invalid (&attr_args))
! 1833: {
! 1834: bgp_attr_parse_ret_t ret;
! 1835: ret = bgp_attr_malformed (&attr_args,
! 1836: BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
! 1837: attr_args.total);
! 1838: if (ret == BGP_ATTR_PARSE_PROCEED)
! 1839: continue;
! 1840: return ret;
! 1841: }
1.1 misho 1842:
1843: /* OK check attribute and store it's value. */
1844: switch (type)
1845: {
1846: case BGP_ATTR_ORIGIN:
1.1.1.2 ! misho 1847: ret = bgp_attr_origin (&attr_args);
1.1 misho 1848: break;
1849: case BGP_ATTR_AS_PATH:
1.1.1.2 ! misho 1850: ret = bgp_attr_aspath (&attr_args);
1.1 misho 1851: break;
1852: case BGP_ATTR_AS4_PATH:
1.1.1.2 ! misho 1853: ret = bgp_attr_as4_path (&attr_args, &as4_path);
1.1 misho 1854: break;
1855: case BGP_ATTR_NEXT_HOP:
1.1.1.2 ! misho 1856: ret = bgp_attr_nexthop (&attr_args);
1.1 misho 1857: break;
1858: case BGP_ATTR_MULTI_EXIT_DISC:
1.1.1.2 ! misho 1859: ret = bgp_attr_med (&attr_args);
1.1 misho 1860: break;
1861: case BGP_ATTR_LOCAL_PREF:
1.1.1.2 ! misho 1862: ret = bgp_attr_local_pref (&attr_args);
1.1 misho 1863: break;
1864: case BGP_ATTR_ATOMIC_AGGREGATE:
1.1.1.2 ! misho 1865: ret = bgp_attr_atomic (&attr_args);
1.1 misho 1866: break;
1867: case BGP_ATTR_AGGREGATOR:
1.1.1.2 ! misho 1868: ret = bgp_attr_aggregator (&attr_args);
1.1 misho 1869: break;
1870: case BGP_ATTR_AS4_AGGREGATOR:
1.1.1.2 ! misho 1871: ret = bgp_attr_as4_aggregator (&attr_args,
! 1872: &as4_aggregator,
1.1 misho 1873: &as4_aggregator_addr);
1874: break;
1875: case BGP_ATTR_COMMUNITIES:
1.1.1.2 ! misho 1876: ret = bgp_attr_community (&attr_args);
1.1 misho 1877: break;
1878: case BGP_ATTR_ORIGINATOR_ID:
1.1.1.2 ! misho 1879: ret = bgp_attr_originator_id (&attr_args);
1.1 misho 1880: break;
1881: case BGP_ATTR_CLUSTER_LIST:
1.1.1.2 ! misho 1882: ret = bgp_attr_cluster_list (&attr_args);
1.1 misho 1883: break;
1884: case BGP_ATTR_MP_REACH_NLRI:
1.1.1.2 ! misho 1885: ret = bgp_mp_reach_parse (&attr_args, mp_update);
1.1 misho 1886: break;
1887: case BGP_ATTR_MP_UNREACH_NLRI:
1.1.1.2 ! misho 1888: ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw);
1.1 misho 1889: break;
1890: case BGP_ATTR_EXT_COMMUNITIES:
1.1.1.2 ! misho 1891: ret = bgp_attr_ext_communities (&attr_args);
1.1 misho 1892: break;
1893: default:
1.1.1.2 ! misho 1894: ret = bgp_attr_unknown (&attr_args);
1.1 misho 1895: break;
1896: }
1897:
1898: /* If hard error occured immediately return to the caller. */
1899: if (ret == BGP_ATTR_PARSE_ERROR)
1900: {
1901: zlog (peer->log, LOG_WARNING,
1902: "%s: Attribute %s, parse error",
1903: peer->host,
1904: LOOKUP (attr_str, type));
1905: bgp_notify_send (peer,
1906: BGP_NOTIFY_UPDATE_ERR,
1907: BGP_NOTIFY_UPDATE_MAL_ATTR);
1908: if (as4_path)
1909: aspath_unintern (&as4_path);
1910: return ret;
1911: }
1912: if (ret == BGP_ATTR_PARSE_WITHDRAW)
1913: {
1914:
1915: zlog (peer->log, LOG_WARNING,
1916: "%s: Attribute %s, parse error - treating as withdrawal",
1917: peer->host,
1918: LOOKUP (attr_str, type));
1919: if (as4_path)
1920: aspath_unintern (&as4_path);
1921: return ret;
1922: }
1923:
1924: /* Check the fetched length. */
1925: if (BGP_INPUT_PNT (peer) != attr_endp)
1926: {
1927: zlog (peer->log, LOG_WARNING,
1928: "%s: BGP attribute %s, fetch error",
1929: peer->host, LOOKUP (attr_str, type));
1930: bgp_notify_send (peer,
1931: BGP_NOTIFY_UPDATE_ERR,
1932: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1933: if (as4_path)
1934: aspath_unintern (&as4_path);
1935: return BGP_ATTR_PARSE_ERROR;
1936: }
1937: }
1938:
1939: /* Check final read pointer is same as end pointer. */
1940: if (BGP_INPUT_PNT (peer) != endp)
1941: {
1942: zlog (peer->log, LOG_WARNING,
1943: "%s: BGP attribute %s, length mismatch",
1944: peer->host, LOOKUP (attr_str, type));
1945: bgp_notify_send (peer,
1946: BGP_NOTIFY_UPDATE_ERR,
1947: BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
1948: if (as4_path)
1949: aspath_unintern (&as4_path);
1950: return BGP_ATTR_PARSE_ERROR;
1951: }
1952:
1953: /*
1954: * At this place we can see whether we got AS4_PATH and/or
1955: * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
1956: * We can not do this before we've read all attributes because
1957: * the as4 handling does not say whether AS4_PATH has to be sent
1958: * after AS_PATH or not - and when AS4_AGGREGATOR will be send
1959: * in relationship to AGGREGATOR.
1960: * So, to be defensive, we are not relying on any order and read
1961: * all attributes first, including these 32bit ones, and now,
1962: * afterwards, we look what and if something is to be done for as4.
1963: */
1.1.1.2 ! misho 1964: if (bgp_attr_munge_as4_attrs (peer, attr, as4_path,
1.1 misho 1965: as4_aggregator, &as4_aggregator_addr))
1966: {
1967: if (as4_path)
1968: aspath_unintern (&as4_path);
1969: return BGP_ATTR_PARSE_ERROR;
1970: }
1971:
1972: /* At this stage, we have done all fiddling with as4, and the
1973: * resulting info is in attr->aggregator resp. attr->aspath
1974: * so we can chuck as4_aggregator and as4_path alltogether in
1975: * order to save memory
1976: */
1977: if (as4_path)
1978: {
1979: aspath_unintern (&as4_path); /* unintern - it is in the hash */
1980: /* The flag that we got this is still there, but that does not
1981: * do any trouble
1982: */
1983: }
1984: /*
1985: * The "rest" of the code does nothing with as4_aggregator.
1986: * there is no memory attached specifically which is not part
1987: * of the attr.
1988: * so ignoring just means do nothing.
1989: */
1990: /*
1991: * Finally do the checks on the aspath we did not do yet
1992: * because we waited for a potentially synthesized aspath.
1993: */
1994: if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
1995: {
1.1.1.2 ! misho 1996: ret = bgp_attr_aspath_check (peer, attr);
1.1 misho 1997: if (ret != BGP_ATTR_PARSE_PROCEED)
1998: return ret;
1999: }
2000:
2001: /* Finally intern unknown attribute. */
2002: if (attr->extra && attr->extra->transit)
2003: attr->extra->transit = transit_intern (attr->extra->transit);
2004:
2005: return BGP_ATTR_PARSE_PROCEED;
2006: }
2007:
2008: /* Well-known attribute check. */
2009: int
2010: bgp_attr_check (struct peer *peer, struct attr *attr)
2011: {
2012: u_char type = 0;
2013:
2014: if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
2015: type = BGP_ATTR_ORIGIN;
2016:
2017: if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
2018: type = BGP_ATTR_AS_PATH;
2019:
2020: if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
2021: type = BGP_ATTR_NEXT_HOP;
2022:
2023: if (peer_sort (peer) == BGP_PEER_IBGP
2024: && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
2025: type = BGP_ATTR_LOCAL_PREF;
2026:
2027: if (type)
2028: {
2029: zlog (peer->log, LOG_WARNING,
2030: "%s Missing well-known attribute %d.",
2031: peer->host, type);
2032: bgp_notify_send_with_data (peer,
2033: BGP_NOTIFY_UPDATE_ERR,
2034: BGP_NOTIFY_UPDATE_MISS_ATTR,
2035: &type, 1);
2036: return BGP_ATTR_PARSE_ERROR;
2037: }
2038: return BGP_ATTR_PARSE_PROCEED;
2039: }
2040:
2041: int stream_put_prefix (struct stream *, struct prefix *);
2042:
2043: /* Make attribute packet. */
2044: bgp_size_t
2045: bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
2046: struct stream *s, struct attr *attr, struct prefix *p,
2047: afi_t afi, safi_t safi, struct peer *from,
2048: struct prefix_rd *prd, u_char *tag)
2049: {
2050: size_t cp;
2051: size_t aspath_sizep;
2052: struct aspath *aspath;
2053: int send_as4_path = 0;
2054: int send_as4_aggregator = 0;
2055: int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
2056:
2057: if (! bgp)
2058: bgp = bgp_get_default ();
2059:
2060: /* Remember current pointer. */
2061: cp = stream_get_endp (s);
2062:
2063: /* Origin attribute. */
2064: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2065: stream_putc (s, BGP_ATTR_ORIGIN);
2066: stream_putc (s, 1);
2067: stream_putc (s, attr->origin);
2068:
2069: /* AS path attribute. */
2070:
2071: /* If remote-peer is EBGP */
2072: if (peer_sort (peer) == BGP_PEER_EBGP
2073: && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
2074: || attr->aspath->segments == NULL)
2075: && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
2076: {
2077: aspath = aspath_dup (attr->aspath);
2078:
2079: if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
2080: {
2081: /* Strip the confed info, and then stuff our path CONFED_ID
2082: on the front */
2083: aspath = aspath_delete_confed_seq (aspath);
2084: aspath = aspath_add_seq (aspath, bgp->confed_id);
2085: }
2086: else
2087: {
2088: aspath = aspath_add_seq (aspath, peer->local_as);
2089: if (peer->change_local_as)
2090: aspath = aspath_add_seq (aspath, peer->change_local_as);
2091: }
2092: }
2093: else if (peer_sort (peer) == BGP_PEER_CONFED)
2094: {
2095: /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
2096: aspath = aspath_dup (attr->aspath);
2097: aspath = aspath_add_confed_seq (aspath, peer->local_as);
2098: }
2099: else
2100: aspath = attr->aspath;
2101:
2102: /* If peer is not AS4 capable, then:
2103: * - send the created AS_PATH out as AS4_PATH (optional, transitive),
2104: * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
2105: * types are in it (i.e. exclude them if they are there)
2106: * AND do this only if there is at least one asnum > 65535 in the path!
2107: * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
2108: * all ASnums > 65535 to BGP_AS_TRANS
2109: */
2110:
2111: stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2112: stream_putc (s, BGP_ATTR_AS_PATH);
2113: aspath_sizep = stream_get_endp (s);
2114: stream_putw (s, 0);
2115: stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
2116:
2117: /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
2118: * in the path
2119: */
2120: if (!use32bit && aspath_has_as4 (aspath))
2121: send_as4_path = 1; /* we'll do this later, at the correct place */
2122:
2123: /* Nexthop attribute. */
2124: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
2125: {
2126: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2127: stream_putc (s, BGP_ATTR_NEXT_HOP);
2128: stream_putc (s, 4);
2129: if (safi == SAFI_MPLS_VPN)
2130: {
2131: if (attr->nexthop.s_addr == 0)
2132: stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
2133: else
2134: stream_put_ipv4 (s, attr->nexthop.s_addr);
2135: }
2136: else
2137: stream_put_ipv4 (s, attr->nexthop.s_addr);
2138: }
2139:
2140: /* MED attribute. */
2141: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2142: {
2143: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2144: stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2145: stream_putc (s, 4);
2146: stream_putl (s, attr->med);
2147: }
2148:
2149: /* Local preference. */
2150: if (peer_sort (peer) == BGP_PEER_IBGP ||
2151: peer_sort (peer) == BGP_PEER_CONFED)
2152: {
2153: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2154: stream_putc (s, BGP_ATTR_LOCAL_PREF);
2155: stream_putc (s, 4);
2156: stream_putl (s, attr->local_pref);
2157: }
2158:
2159: /* Atomic aggregate. */
2160: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2161: {
2162: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2163: stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2164: stream_putc (s, 0);
2165: }
2166:
2167: /* Aggregator. */
2168: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2169: {
2170: assert (attr->extra);
2171:
2172: /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
2173: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2174: stream_putc (s, BGP_ATTR_AGGREGATOR);
2175:
2176: if (use32bit)
2177: {
2178: /* AS4 capable peer */
2179: stream_putc (s, 8);
2180: stream_putl (s, attr->extra->aggregator_as);
2181: }
2182: else
2183: {
2184: /* 2-byte AS peer */
2185: stream_putc (s, 6);
2186:
2187: /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
2188: if ( attr->extra->aggregator_as > 65535 )
2189: {
2190: stream_putw (s, BGP_AS_TRANS);
2191:
2192: /* we have to send AS4_AGGREGATOR, too.
2193: * we'll do that later in order to send attributes in ascending
2194: * order.
2195: */
2196: send_as4_aggregator = 1;
2197: }
2198: else
2199: stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
2200: }
2201: stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2202: }
2203:
2204: /* Community attribute. */
2205: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
2206: && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
2207: {
2208: if (attr->community->size * 4 > 255)
2209: {
2210: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2211: stream_putc (s, BGP_ATTR_COMMUNITIES);
2212: stream_putw (s, attr->community->size * 4);
2213: }
2214: else
2215: {
2216: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2217: stream_putc (s, BGP_ATTR_COMMUNITIES);
2218: stream_putc (s, attr->community->size * 4);
2219: }
2220: stream_put (s, attr->community->val, attr->community->size * 4);
2221: }
2222:
2223: /* Route Reflector. */
2224: if (peer_sort (peer) == BGP_PEER_IBGP
2225: && from
2226: && peer_sort (from) == BGP_PEER_IBGP)
2227: {
2228: /* Originator ID. */
2229: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2230: stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
2231: stream_putc (s, 4);
2232:
2233: if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
2234: stream_put_in_addr (s, &attr->extra->originator_id);
2235: else
2236: stream_put_in_addr (s, &from->remote_id);
2237:
2238: /* Cluster list. */
2239: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2240: stream_putc (s, BGP_ATTR_CLUSTER_LIST);
2241:
2242: if (attr->extra && attr->extra->cluster)
2243: {
2244: stream_putc (s, attr->extra->cluster->length + 4);
2245: /* If this peer configuration's parent BGP has cluster_id. */
2246: if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2247: stream_put_in_addr (s, &bgp->cluster_id);
2248: else
2249: stream_put_in_addr (s, &bgp->router_id);
2250: stream_put (s, attr->extra->cluster->list,
2251: attr->extra->cluster->length);
2252: }
2253: else
2254: {
2255: stream_putc (s, 4);
2256: /* If this peer configuration's parent BGP has cluster_id. */
2257: if (bgp->config & BGP_CONFIG_CLUSTER_ID)
2258: stream_put_in_addr (s, &bgp->cluster_id);
2259: else
2260: stream_put_in_addr (s, &bgp->router_id);
2261: }
2262: }
2263:
2264: #ifdef HAVE_IPV6
2265: /* If p is IPv6 address put it into attribute. */
2266: if (p->family == AF_INET6)
2267: {
2268: unsigned long sizep;
2269: struct attr_extra *attre = attr->extra;
2270:
2271: assert (attr->extra);
2272:
2273: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2274: stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2275: sizep = stream_get_endp (s);
2276: stream_putc (s, 0); /* Marker: Attribute length. */
2277: stream_putw (s, AFI_IP6); /* AFI */
2278: stream_putc (s, safi); /* SAFI */
2279:
2280: stream_putc (s, attre->mp_nexthop_len);
2281:
2282: if (attre->mp_nexthop_len == 16)
2283: stream_put (s, &attre->mp_nexthop_global, 16);
2284: else if (attre->mp_nexthop_len == 32)
2285: {
2286: stream_put (s, &attre->mp_nexthop_global, 16);
2287: stream_put (s, &attre->mp_nexthop_local, 16);
2288: }
2289:
2290: /* SNPA */
2291: stream_putc (s, 0);
2292:
2293: /* Prefix write. */
2294: stream_put_prefix (s, p);
2295:
2296: /* Set MP attribute length. */
2297: stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
2298: }
2299: #endif /* HAVE_IPV6 */
2300:
2301: if (p->family == AF_INET && safi == SAFI_MULTICAST)
2302: {
2303: unsigned long sizep;
2304:
2305: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2306: stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2307: sizep = stream_get_endp (s);
2308: stream_putc (s, 0); /* Marker: Attribute Length. */
2309: stream_putw (s, AFI_IP); /* AFI */
2310: stream_putc (s, SAFI_MULTICAST); /* SAFI */
2311:
2312: stream_putc (s, 4);
2313: stream_put_ipv4 (s, attr->nexthop.s_addr);
2314:
2315: /* SNPA */
2316: stream_putc (s, 0);
2317:
2318: /* Prefix write. */
2319: stream_put_prefix (s, p);
2320:
2321: /* Set MP attribute length. */
2322: stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
2323: }
2324:
2325: if (p->family == AF_INET && safi == SAFI_MPLS_VPN)
2326: {
2327: unsigned long sizep;
2328:
2329: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2330: stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
2331: sizep = stream_get_endp (s);
2332: stream_putc (s, 0); /* Length of this attribute. */
2333: stream_putw (s, AFI_IP); /* AFI */
1.1.1.2 ! misho 2334: stream_putc (s, SAFI_MPLS_LABELED_VPN); /* SAFI */
1.1 misho 2335:
2336: stream_putc (s, 12);
2337: stream_putl (s, 0);
2338: stream_putl (s, 0);
2339: stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
2340:
2341: /* SNPA */
2342: stream_putc (s, 0);
2343:
2344: /* Tag, RD, Prefix write. */
2345: stream_putc (s, p->prefixlen + 88);
2346: stream_put (s, tag, 3);
2347: stream_put (s, prd->val, 8);
2348: stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2349:
2350: /* Set MP attribute length. */
2351: stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
2352: }
2353:
2354: /* Extended Communities attribute. */
2355: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
2356: && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
2357: {
2358: struct attr_extra *attre = attr->extra;
2359:
2360: assert (attre);
2361:
2362: if (peer_sort (peer) == BGP_PEER_IBGP
2363: || peer_sort (peer) == BGP_PEER_CONFED)
2364: {
2365: if (attre->ecommunity->size * 8 > 255)
2366: {
2367: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2368: stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2369: stream_putw (s, attre->ecommunity->size * 8);
2370: }
2371: else
2372: {
2373: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2374: stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2375: stream_putc (s, attre->ecommunity->size * 8);
2376: }
2377: stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8);
2378: }
2379: else
2380: {
2381: u_int8_t *pnt;
2382: int tbit;
2383: int ecom_tr_size = 0;
2384: int i;
2385:
2386: for (i = 0; i < attre->ecommunity->size; i++)
2387: {
2388: pnt = attre->ecommunity->val + (i * 8);
2389: tbit = *pnt;
2390:
2391: if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2392: continue;
2393:
2394: ecom_tr_size++;
2395: }
2396:
2397: if (ecom_tr_size)
2398: {
2399: if (ecom_tr_size * 8 > 255)
2400: {
2401: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2402: stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2403: stream_putw (s, ecom_tr_size * 8);
2404: }
2405: else
2406: {
2407: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2408: stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
2409: stream_putc (s, ecom_tr_size * 8);
2410: }
2411:
2412: for (i = 0; i < attre->ecommunity->size; i++)
2413: {
2414: pnt = attre->ecommunity->val + (i * 8);
2415: tbit = *pnt;
2416:
2417: if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
2418: continue;
2419:
2420: stream_put (s, pnt, 8);
2421: }
2422: }
2423: }
2424: }
2425:
2426: if ( send_as4_path )
2427: {
2428: /* If the peer is NOT As4 capable, AND */
2429: /* there are ASnums > 65535 in path THEN
2430: * give out AS4_PATH */
2431:
2432: /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
2433: * path segments!
2434: * Hm, I wonder... confederation things *should* only be at
2435: * the beginning of an aspath, right? Then we should use
2436: * aspath_delete_confed_seq for this, because it is already
2437: * there! (JK)
2438: * Folks, talk to me: what is reasonable here!?
2439: */
2440: aspath = aspath_delete_confed_seq (aspath);
2441:
2442: stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
2443: stream_putc (s, BGP_ATTR_AS4_PATH);
2444: aspath_sizep = stream_get_endp (s);
2445: stream_putw (s, 0);
2446: stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
2447: }
2448:
2449: if (aspath != attr->aspath)
2450: aspath_free (aspath);
2451:
2452: if ( send_as4_aggregator )
2453: {
2454: assert (attr->extra);
2455:
2456: /* send AS4_AGGREGATOR, at this place */
2457: /* this section of code moved here in order to ensure the correct
2458: * *ascending* order of attributes
2459: */
2460: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2461: stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
2462: stream_putc (s, 8);
2463: stream_putl (s, attr->extra->aggregator_as);
2464: stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2465: }
2466:
2467: /* Unknown transit attribute. */
2468: if (attr->extra && attr->extra->transit)
2469: stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
2470:
2471: /* Return total size of attribute. */
2472: return stream_get_endp (s) - cp;
2473: }
2474:
2475: bgp_size_t
2476: bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p,
2477: afi_t afi, safi_t safi, struct prefix_rd *prd,
2478: u_char *tag)
2479: {
2480: unsigned long cp;
2481: unsigned long attrlen_pnt;
2482: bgp_size_t size;
2483:
2484: cp = stream_get_endp (s);
2485:
2486: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2487: stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
2488:
2489: attrlen_pnt = stream_get_endp (s);
2490: stream_putc (s, 0); /* Length of this attribute. */
2491:
2492: stream_putw (s, family2afi (p->family));
2493:
2494: if (safi == SAFI_MPLS_VPN)
2495: {
2496: /* SAFI */
1.1.1.2 ! misho 2497: stream_putc (s, SAFI_MPLS_LABELED_VPN);
1.1 misho 2498:
2499: /* prefix. */
2500: stream_putc (s, p->prefixlen + 88);
2501: stream_put (s, tag, 3);
2502: stream_put (s, prd->val, 8);
2503: stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
2504: }
2505: else
2506: {
2507: /* SAFI */
2508: stream_putc (s, safi);
2509:
2510: /* prefix */
2511: stream_put_prefix (s, p);
2512: }
2513:
2514: /* Set MP attribute length. */
2515: size = stream_get_endp (s) - attrlen_pnt - 1;
2516: stream_putc_at (s, attrlen_pnt, size);
2517:
2518: return stream_get_endp (s) - cp;
2519: }
2520:
2521: /* Initialization of attribute. */
2522: void
2523: bgp_attr_init (void)
2524: {
2525: aspath_init ();
2526: attrhash_init ();
2527: community_init ();
2528: ecommunity_init ();
2529: cluster_init ();
2530: transit_init ();
2531: }
2532:
2533: void
2534: bgp_attr_finish (void)
2535: {
2536: aspath_finish ();
2537: attrhash_finish ();
2538: community_finish ();
2539: ecommunity_finish ();
2540: cluster_finish ();
2541: transit_finish ();
2542: }
2543:
2544: /* Make attribute packet. */
2545: void
2546: bgp_dump_routes_attr (struct stream *s, struct attr *attr,
2547: struct prefix *prefix)
2548: {
2549: unsigned long cp;
2550: unsigned long len;
2551: size_t aspath_lenp;
2552: struct aspath *aspath;
2553:
2554: /* Remember current pointer. */
2555: cp = stream_get_endp (s);
2556:
2557: /* Place holder of length. */
2558: stream_putw (s, 0);
2559:
2560: /* Origin attribute. */
2561: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2562: stream_putc (s, BGP_ATTR_ORIGIN);
2563: stream_putc (s, 1);
2564: stream_putc (s, attr->origin);
2565:
2566: aspath = attr->aspath;
2567:
2568: stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2569: stream_putc (s, BGP_ATTR_AS_PATH);
2570: aspath_lenp = stream_get_endp (s);
2571: stream_putw (s, 0);
2572:
2573: stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
2574:
2575: /* Nexthop attribute. */
2576: /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
2577: if(prefix != NULL
2578: #ifdef HAVE_IPV6
2579: && prefix->family != AF_INET6
2580: #endif /* HAVE_IPV6 */
2581: )
2582: {
2583: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2584: stream_putc (s, BGP_ATTR_NEXT_HOP);
2585: stream_putc (s, 4);
2586: stream_put_ipv4 (s, attr->nexthop.s_addr);
2587: }
2588:
2589: /* MED attribute. */
2590: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
2591: {
2592: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
2593: stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
2594: stream_putc (s, 4);
2595: stream_putl (s, attr->med);
2596: }
2597:
2598: /* Local preference. */
2599: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
2600: {
2601: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2602: stream_putc (s, BGP_ATTR_LOCAL_PREF);
2603: stream_putc (s, 4);
2604: stream_putl (s, attr->local_pref);
2605: }
2606:
2607: /* Atomic aggregate. */
2608: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
2609: {
2610: stream_putc (s, BGP_ATTR_FLAG_TRANS);
2611: stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
2612: stream_putc (s, 0);
2613: }
2614:
2615: /* Aggregator. */
2616: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
2617: {
2618: assert (attr->extra);
2619: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2620: stream_putc (s, BGP_ATTR_AGGREGATOR);
2621: stream_putc (s, 8);
2622: stream_putl (s, attr->extra->aggregator_as);
2623: stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
2624: }
2625:
2626: /* Community attribute. */
2627: if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
2628: {
2629: if (attr->community->size * 4 > 255)
2630: {
2631: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
2632: stream_putc (s, BGP_ATTR_COMMUNITIES);
2633: stream_putw (s, attr->community->size * 4);
2634: }
2635: else
2636: {
2637: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
2638: stream_putc (s, BGP_ATTR_COMMUNITIES);
2639: stream_putc (s, attr->community->size * 4);
2640: }
2641: stream_put (s, attr->community->val, attr->community->size * 4);
2642: }
2643:
2644: #ifdef HAVE_IPV6
2645: /* Add a MP_NLRI attribute to dump the IPv6 next hop */
2646: if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
2647: (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) )
2648: {
2649: int sizep;
2650: struct attr_extra *attre = attr->extra;
2651:
2652: stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
2653: stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
2654: sizep = stream_get_endp (s);
2655:
2656: /* MP header */
2657: stream_putc (s, 0); /* Marker: Attribute length. */
2658: stream_putw(s, AFI_IP6); /* AFI */
2659: stream_putc(s, SAFI_UNICAST); /* SAFI */
2660:
2661: /* Next hop */
2662: stream_putc(s, attre->mp_nexthop_len);
2663: stream_put(s, &attre->mp_nexthop_global, 16);
2664: if (attre->mp_nexthop_len == 32)
2665: stream_put(s, &attre->mp_nexthop_local, 16);
2666:
2667: /* SNPA */
2668: stream_putc(s, 0);
2669:
2670: /* Prefix */
2671: stream_put_prefix(s, prefix);
2672:
2673: /* Set MP attribute length. */
2674: stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
2675: }
2676: #endif /* HAVE_IPV6 */
2677:
2678: /* Return total size of attribute. */
2679: len = stream_get_endp (s) - cp - 2;
2680: stream_putw_at (s, cp, len);
2681: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>