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