Annotation of embedaddon/quagga/bgpd/bgp_open.c, revision 1.1

1.1     ! misho       1: /* BGP open message handling
        !             2:    Copyright (C) 1998, 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 "stream.h"
        !            26: #include "thread.h"
        !            27: #include "log.h"
        !            28: #include "command.h"
        !            29: #include "memory.h"
        !            30: 
        !            31: #include "bgpd/bgpd.h"
        !            32: #include "bgpd/bgp_attr.h"
        !            33: #include "bgpd/bgp_debug.h"
        !            34: #include "bgpd/bgp_fsm.h"
        !            35: #include "bgpd/bgp_packet.h"
        !            36: #include "bgpd/bgp_open.h"
        !            37: #include "bgpd/bgp_aspath.h"
        !            38: #include "bgpd/bgp_vty.h"
        !            39: 
        !            40: /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
        !            41:    negotiate remote peer supports extentions or not. But if
        !            42:    remote-peer doesn't supports negotiation process itself.  We would
        !            43:    like to do manual configuration.
        !            44: 
        !            45:    So there is many configurable point.  First of all we want set each
        !            46:    peer whether we send capability negotiation to the peer or not.
        !            47:    Next, if we send capability to the peer we want to set my capabilty
        !            48:    inforation at each peer. */
        !            49: 
        !            50: void
        !            51: bgp_capability_vty_out (struct vty *vty, struct peer *peer)
        !            52: {
        !            53:   char *pnt;
        !            54:   char *end;
        !            55:   struct capability_mp_data mpc;
        !            56:   struct capability_header *hdr;
        !            57: 
        !            58:   pnt = peer->notify.data;
        !            59:   end = pnt + peer->notify.length;
        !            60:   
        !            61:   while (pnt < end)
        !            62:     {
        !            63:       if (pnt + sizeof (struct capability_mp_data) + 2 > end)
        !            64:        return;
        !            65:       
        !            66:       hdr = (struct capability_header *)pnt;
        !            67:       if (pnt + hdr->length + 2 > end)
        !            68:        return;
        !            69: 
        !            70:       memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
        !            71: 
        !            72:       if (hdr->code == CAPABILITY_CODE_MP)
        !            73:        {
        !            74:          vty_out (vty, "  Capability error for: Multi protocol ");
        !            75: 
        !            76:          switch (ntohs (mpc.afi))
        !            77:            {
        !            78:            case AFI_IP:
        !            79:              vty_out (vty, "AFI IPv4, ");
        !            80:              break;
        !            81:            case AFI_IP6:
        !            82:              vty_out (vty, "AFI IPv6, ");
        !            83:              break;
        !            84:            default:
        !            85:              vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
        !            86:              break;
        !            87:            }
        !            88:          switch (mpc.safi)
        !            89:            {
        !            90:            case SAFI_UNICAST:
        !            91:              vty_out (vty, "SAFI Unicast");
        !            92:              break;
        !            93:            case SAFI_MULTICAST:
        !            94:              vty_out (vty, "SAFI Multicast");
        !            95:              break;
        !            96:            case SAFI_UNICAST_MULTICAST:
        !            97:              vty_out (vty, "SAFI Unicast Multicast");
        !            98:              break;
        !            99:            case BGP_SAFI_VPNV4:
        !           100:              vty_out (vty, "SAFI MPLS-VPN");
        !           101:              break;
        !           102:            default:
        !           103:              vty_out (vty, "SAFI Unknown %d ", mpc.safi);
        !           104:              break;
        !           105:            }
        !           106:          vty_out (vty, "%s", VTY_NEWLINE);
        !           107:        }
        !           108:       else if (hdr->code >= 128)
        !           109:        vty_out (vty, "  Capability error: vendor specific capability code %d",
        !           110:                 hdr->code);
        !           111:       else
        !           112:        vty_out (vty, "  Capability error: unknown capability code %d", 
        !           113:                 hdr->code);
        !           114: 
        !           115:       pnt += hdr->length + 2;
        !           116:     }
        !           117: }
        !           118: 
        !           119: static void 
        !           120: bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
        !           121: {
        !           122:   mpc->afi = stream_getw (s);
        !           123:   mpc->reserved = stream_getc (s);
        !           124:   mpc->safi = stream_getc (s);
        !           125: }
        !           126: 
        !           127: int
        !           128: bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
        !           129: {
        !           130:   /* VPNvX are AFI specific */
        !           131:   if ((afi == AFI_IP6 && *safi == BGP_SAFI_VPNV4)
        !           132:       || (afi == AFI_IP && *safi == BGP_SAFI_VPNV6))
        !           133:     {
        !           134:       zlog_warn ("Invalid afi/safi combination (%u/%u)", afi, *safi);
        !           135:       return 0;
        !           136:     }
        !           137:   
        !           138:   switch (afi)
        !           139:     {
        !           140:       case AFI_IP:
        !           141: #ifdef HAVE_IPV6
        !           142:       case AFI_IP6:
        !           143: #endif
        !           144:         switch (*safi)
        !           145:           {
        !           146:             /* BGP VPNvX SAFI isn't contigious with others, remap */
        !           147:             case BGP_SAFI_VPNV4:
        !           148:             case BGP_SAFI_VPNV6:
        !           149:               *safi = SAFI_MPLS_VPN;
        !           150:             case SAFI_UNICAST:
        !           151:             case SAFI_MULTICAST:
        !           152:             case SAFI_MPLS_VPN:
        !           153:               return 1;
        !           154:           }
        !           155:     }
        !           156:   zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
        !           157:   
        !           158:   return 0;
        !           159: }
        !           160: 
        !           161: /* Set negotiated capability value. */
        !           162: static int
        !           163: bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
        !           164: {
        !           165:   struct capability_mp_data mpc;
        !           166:   struct stream *s = BGP_INPUT (peer);
        !           167:   
        !           168:   bgp_capability_mp_data (s, &mpc);
        !           169:   
        !           170:   if (BGP_DEBUG (normal, NORMAL))
        !           171:     zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
        !           172:                peer->host, mpc.afi, mpc.safi);
        !           173:   
        !           174:   if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
        !           175:     return -1;
        !           176:    
        !           177:   /* Now safi remapped, and afi/safi are valid array indices */
        !           178:   peer->afc_recv[mpc.afi][mpc.safi] = 1;
        !           179:   
        !           180:   if (peer->afc[mpc.afi][mpc.safi])
        !           181:     peer->afc_nego[mpc.afi][mpc.safi] = 1;
        !           182:   else 
        !           183:     return -1;
        !           184: 
        !           185:   return 0;
        !           186: }
        !           187: 
        !           188: static void
        !           189: bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
        !           190:                                u_char type, u_char mode)
        !           191: {
        !           192:   if (BGP_DEBUG (normal, NORMAL))
        !           193:     zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
        !           194:               peer->host, afi, safi, type, mode);
        !           195: }
        !           196: 
        !           197: static const struct message orf_type_str[] =
        !           198: {
        !           199:   { ORF_TYPE_PREFIX,           "Prefixlist"            },
        !           200:   { ORF_TYPE_PREFIX_OLD,       "Prefixlist (old)"      },
        !           201: };
        !           202: static const int orf_type_str_max
        !           203:        = sizeof(orf_type_str)/sizeof(orf_type_str[0]);
        !           204: 
        !           205: static const struct message orf_mode_str[] =
        !           206: {
        !           207:   { ORF_MODE_RECEIVE,  "Receive"       },
        !           208:   { ORF_MODE_SEND,     "Send"          },
        !           209:   { ORF_MODE_BOTH,     "Both"          },
        !           210: };
        !           211: static const int orf_mode_str_max
        !           212:         = sizeof(orf_mode_str)/sizeof(orf_mode_str[0]);
        !           213: 
        !           214: static int
        !           215: bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
        !           216: {
        !           217:   struct stream *s = BGP_INPUT (peer);
        !           218:   struct capability_orf_entry entry;
        !           219:   afi_t afi;
        !           220:   safi_t safi;
        !           221:   u_char type;
        !           222:   u_char mode;
        !           223:   u_int16_t sm_cap = 0; /* capability send-mode receive */
        !           224:   u_int16_t rm_cap = 0; /* capability receive-mode receive */ 
        !           225:   int i;
        !           226: 
        !           227:   /* ORF Entry header */
        !           228:   bgp_capability_mp_data (s, &entry.mpc);
        !           229:   entry.num = stream_getc (s);
        !           230:   afi = entry.mpc.afi;
        !           231:   safi = entry.mpc.safi;
        !           232:   
        !           233:   if (BGP_DEBUG (normal, NORMAL))
        !           234:     zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
        !           235:                peer->host, entry.mpc.afi, entry.mpc.safi);
        !           236: 
        !           237:   /* Check AFI and SAFI. */
        !           238:   if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
        !           239:     {
        !           240:       zlog_info ("%s Addr-family %d/%d not supported."
        !           241:                  " Ignoring the ORF capability",
        !           242:                  peer->host, entry.mpc.afi, entry.mpc.safi);
        !           243:       return 0;
        !           244:     }
        !           245:   
        !           246:   /* validate number field */
        !           247:   if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
        !           248:     {
        !           249:       zlog_info ("%s ORF Capability entry length error,"
        !           250:                  " Cap length %u, num %u",
        !           251:                  peer->host, hdr->length, entry.num);
        !           252:       bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
        !           253:       return -1;
        !           254:     }
        !           255: 
        !           256:   for (i = 0 ; i < entry.num ; i++)
        !           257:     {
        !           258:       type = stream_getc(s);
        !           259:       mode = stream_getc(s);
        !           260:       
        !           261:       /* ORF Mode error check */
        !           262:       switch (mode)
        !           263:         {
        !           264:           case ORF_MODE_BOTH:
        !           265:           case ORF_MODE_SEND:
        !           266:           case ORF_MODE_RECEIVE:
        !           267:             break;
        !           268:           default:
        !           269:            bgp_capability_orf_not_support (peer, afi, safi, type, mode);
        !           270:            continue;
        !           271:        }
        !           272:       /* ORF Type and afi/safi error checks */
        !           273:       /* capcode versus type */
        !           274:       switch (hdr->code)
        !           275:         {
        !           276:           case CAPABILITY_CODE_ORF:
        !           277:             switch (type)
        !           278:               {
        !           279:                 case ORF_TYPE_PREFIX:
        !           280:                   break;
        !           281:                 default:
        !           282:                   bgp_capability_orf_not_support (peer, afi, safi, type, mode);
        !           283:                   continue;
        !           284:               }
        !           285:             break;
        !           286:           case CAPABILITY_CODE_ORF_OLD:
        !           287:             switch (type)
        !           288:               {
        !           289:                 case ORF_TYPE_PREFIX_OLD:
        !           290:                   break;
        !           291:                 default:
        !           292:                   bgp_capability_orf_not_support (peer, afi, safi, type, mode);
        !           293:                   continue;
        !           294:               }
        !           295:             break;
        !           296:           default:
        !           297:             bgp_capability_orf_not_support (peer, afi, safi, type, mode);
        !           298:             continue;
        !           299:         }
        !           300:                 
        !           301:       /* AFI vs SAFI */
        !           302:       if (!((afi == AFI_IP && safi == SAFI_UNICAST)
        !           303:             || (afi == AFI_IP && safi == SAFI_MULTICAST)
        !           304:             || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
        !           305:         {
        !           306:           bgp_capability_orf_not_support (peer, afi, safi, type, mode);
        !           307:           continue;
        !           308:         }
        !           309:       
        !           310:       if (BGP_DEBUG (normal, NORMAL))
        !           311:         zlog_debug ("%s OPEN has %s ORF capability"
        !           312:                     " as %s for afi/safi: %d/%d",
        !           313:                     peer->host, LOOKUP (orf_type_str, type),
        !           314:                     LOOKUP (orf_mode_str, mode),
        !           315:                     entry.mpc.afi, safi);
        !           316: 
        !           317:       if (hdr->code == CAPABILITY_CODE_ORF)
        !           318:        {
        !           319:           sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
        !           320:           rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
        !           321:        }
        !           322:       else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
        !           323:        {
        !           324:           sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
        !           325:           rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
        !           326:        }
        !           327:       else
        !           328:        {
        !           329:          bgp_capability_orf_not_support (peer, afi, safi, type, mode);
        !           330:          continue;
        !           331:        }
        !           332: 
        !           333:       switch (mode)
        !           334:        {
        !           335:          case ORF_MODE_BOTH:
        !           336:            SET_FLAG (peer->af_cap[afi][safi], sm_cap);
        !           337:            SET_FLAG (peer->af_cap[afi][safi], rm_cap);
        !           338:            break;
        !           339:          case ORF_MODE_SEND:
        !           340:            SET_FLAG (peer->af_cap[afi][safi], sm_cap);
        !           341:            break;
        !           342:          case ORF_MODE_RECEIVE:
        !           343:            SET_FLAG (peer->af_cap[afi][safi], rm_cap);
        !           344:            break;
        !           345:        }
        !           346:     }
        !           347:   return 0;
        !           348: }
        !           349: 
        !           350: static int
        !           351: bgp_capability_orf (struct peer *peer, struct capability_header *hdr)
        !           352: {
        !           353:   struct stream *s = BGP_INPUT (peer);
        !           354:   size_t end = stream_get_getp (s) + hdr->length;
        !           355:   
        !           356:   assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end);
        !           357:   
        !           358:   /* We must have at least one ORF entry, as the caller has already done
        !           359:    * minimum length validation for the capability code - for ORF there must
        !           360:    * at least one ORF entry (header and unknown number of pairs of bytes).
        !           361:    */
        !           362:   do
        !           363:     {
        !           364:       if (bgp_capability_orf_entry (peer, hdr) == -1)
        !           365:         return -1;
        !           366:     } 
        !           367:   while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end);
        !           368:   
        !           369:   return 0;
        !           370: }
        !           371: 
        !           372: static int
        !           373: bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
        !           374: {
        !           375:   struct stream *s = BGP_INPUT (peer);
        !           376:   u_int16_t restart_flag_time;
        !           377:   int restart_bit = 0;
        !           378:   size_t end = stream_get_getp (s) + caphdr->length;
        !           379: 
        !           380:   SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
        !           381:   restart_flag_time = stream_getw(s);
        !           382:   if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
        !           383:     restart_bit = 1;
        !           384:   UNSET_FLAG (restart_flag_time, 0xF000);
        !           385:   peer->v_gr_restart = restart_flag_time;
        !           386: 
        !           387:   if (BGP_DEBUG (normal, NORMAL))
        !           388:     {
        !           389:       zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
        !           390:       zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
        !           391:                   peer->host, restart_bit ? " " : " not ",
        !           392:                   peer->v_gr_restart);
        !           393:     }
        !           394: 
        !           395:   while (stream_get_getp (s) + 4 < end)
        !           396:     {
        !           397:       afi_t afi = stream_getw (s);
        !           398:       safi_t safi = stream_getc (s);
        !           399:       u_char flag = stream_getc (s);
        !           400:       
        !           401:       if (!bgp_afi_safi_valid_indices (afi, &safi))
        !           402:         {
        !           403:           if (BGP_DEBUG (normal, NORMAL))
        !           404:             zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
        !           405:                         " Ignore the Graceful Restart capability",
        !           406:                         peer->host, afi, safi);
        !           407:         }
        !           408:       else if (!peer->afc[afi][safi])
        !           409:         {
        !           410:           if (BGP_DEBUG (normal, NORMAL))
        !           411:             zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
        !           412:                         " Ignore the Graceful Restart capability",
        !           413:                         peer->host, afi, safi);
        !           414:         }
        !           415:       else
        !           416:         {
        !           417:           if (BGP_DEBUG (normal, NORMAL))
        !           418:             zlog_debug ("%s Address family %s is%spreserved", peer->host,
        !           419:                         afi_safi_print (afi, safi),
        !           420:                         CHECK_FLAG (peer->af_cap[afi][safi],
        !           421:                                     PEER_CAP_RESTART_AF_PRESERVE_RCV)
        !           422:                         ? " " : " not ");
        !           423: 
        !           424:           SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
        !           425:           if (CHECK_FLAG (flag, RESTART_F_BIT))
        !           426:             SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
        !           427:           
        !           428:         }
        !           429:     }
        !           430:   return 0;
        !           431: }
        !           432: 
        !           433: static as_t
        !           434: bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
        !           435: {
        !           436:   as_t as4 = stream_getl (BGP_INPUT(peer));
        !           437:   
        !           438:   if (BGP_DEBUG (as4, AS4))
        !           439:     zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
        !           440:                 peer->host, as4);
        !           441:   SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
        !           442:   
        !           443:   return as4;
        !           444: }
        !           445: 
        !           446: static const struct message capcode_str[] =
        !           447: {
        !           448:   { CAPABILITY_CODE_MP,                        "MultiProtocol Extensions"      },
        !           449:   { CAPABILITY_CODE_REFRESH,           "Route Refresh"                 },
        !           450:   { CAPABILITY_CODE_ORF,               "Cooperative Route Filtering"   },
        !           451:   { CAPABILITY_CODE_RESTART,           "Graceful Restart"              },
        !           452:   { CAPABILITY_CODE_AS4,               "4-octet AS number"             },
        !           453:   { CAPABILITY_CODE_DYNAMIC,           "Dynamic"                       },
        !           454:   { CAPABILITY_CODE_REFRESH_OLD,       "Route Refresh (Old)"           },
        !           455:   { CAPABILITY_CODE_ORF_OLD,           "ORF (Old)"                     },
        !           456: };
        !           457: static const int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]);
        !           458: 
        !           459: /* Minimum sizes for length field of each cap (so not inc. the header) */
        !           460: static const size_t cap_minsizes[] = 
        !           461: {
        !           462:   [CAPABILITY_CODE_MP]         = sizeof (struct capability_mp_data),
        !           463:   [CAPABILITY_CODE_REFRESH]    = CAPABILITY_CODE_REFRESH_LEN,
        !           464:   [CAPABILITY_CODE_ORF]                = sizeof (struct capability_orf_entry),
        !           465:   [CAPABILITY_CODE_RESTART]    = sizeof (struct capability_gr),
        !           466:   [CAPABILITY_CODE_AS4]                = CAPABILITY_CODE_AS4_LEN,
        !           467:   [CAPABILITY_CODE_DYNAMIC]    = CAPABILITY_CODE_DYNAMIC_LEN,
        !           468:   [CAPABILITY_CODE_REFRESH_OLD]        = CAPABILITY_CODE_REFRESH_LEN,
        !           469:   [CAPABILITY_CODE_ORF_OLD]    = sizeof (struct capability_orf_entry),
        !           470: };
        !           471: 
        !           472: /* Parse given capability.
        !           473:  * XXX: This is reading into a stream, but not using stream API
        !           474:  */
        !           475: static int
        !           476: bgp_capability_parse (struct peer *peer, size_t length, u_char **error)
        !           477: {
        !           478:   int ret;
        !           479:   struct stream *s = BGP_INPUT (peer);
        !           480:   size_t end = stream_get_getp (s) + length;
        !           481:   
        !           482:   assert (STREAM_READABLE (s) >= length);
        !           483:   
        !           484:   while (stream_get_getp (s) < end)
        !           485:     {
        !           486:       size_t start;
        !           487:       u_char *sp = stream_pnt (s);
        !           488:       struct capability_header caphdr;
        !           489:       
        !           490:       /* We need at least capability code and capability length. */
        !           491:       if (stream_get_getp(s) + 2 > end)
        !           492:        {
        !           493:          zlog_info ("%s Capability length error (< header)", peer->host);
        !           494:          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
        !           495:          return -1;
        !           496:        }
        !           497:       
        !           498:       caphdr.code = stream_getc (s);
        !           499:       caphdr.length = stream_getc (s);
        !           500:       start = stream_get_getp (s);
        !           501:       
        !           502:       /* Capability length check sanity check. */
        !           503:       if (start + caphdr.length > end)
        !           504:        {
        !           505:          zlog_info ("%s Capability length error (< length)", peer->host);
        !           506:          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
        !           507:          return -1;
        !           508:        }
        !           509:       
        !           510:       if (BGP_DEBUG (normal, NORMAL))
        !           511:        zlog_debug ("%s OPEN has %s capability (%u), length %u",
        !           512:                   peer->host,
        !           513:                   LOOKUP (capcode_str, caphdr.code),
        !           514:                   caphdr.code, caphdr.length);
        !           515:       
        !           516:       /* Length sanity check, type-specific, for known capabilities */
        !           517:       switch (caphdr.code)
        !           518:         {
        !           519:           case CAPABILITY_CODE_MP:
        !           520:           case CAPABILITY_CODE_REFRESH:
        !           521:           case CAPABILITY_CODE_REFRESH_OLD:
        !           522:           case CAPABILITY_CODE_ORF:
        !           523:           case CAPABILITY_CODE_ORF_OLD:
        !           524:           case CAPABILITY_CODE_RESTART:
        !           525:           case CAPABILITY_CODE_AS4:
        !           526:           case CAPABILITY_CODE_DYNAMIC:
        !           527:               /* Check length. */
        !           528:               if (caphdr.length < cap_minsizes[caphdr.code])
        !           529:                 {
        !           530:                   zlog_info ("%s %s Capability length error: got %u,"
        !           531:                              " expected at least %u",
        !           532:                              peer->host, 
        !           533:                              LOOKUP (capcode_str, caphdr.code),
        !           534:                              caphdr.length, 
        !           535:                             (unsigned) cap_minsizes[caphdr.code]);
        !           536:                   bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
        !           537:                   return -1;
        !           538:                 }
        !           539:           /* we deliberately ignore unknown codes, see below */
        !           540:           default:
        !           541:             break;
        !           542:         }
        !           543:       
        !           544:       switch (caphdr.code)
        !           545:         {
        !           546:           case CAPABILITY_CODE_MP:
        !           547:             {
        !           548:               /* Ignore capability when override-capability is set. */
        !           549:               if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
        !           550:                 {
        !           551:                   /* Set negotiated value. */
        !           552:                   ret = bgp_capability_mp (peer, &caphdr);
        !           553: 
        !           554:                   /* Unsupported Capability. */
        !           555:                   if (ret < 0)
        !           556:                     {
        !           557:                       /* Store return data. */
        !           558:                       memcpy (*error, sp, caphdr.length + 2);
        !           559:                       *error += caphdr.length + 2;
        !           560:                     }
        !           561:                 }
        !           562:             }
        !           563:             break;
        !           564:           case CAPABILITY_CODE_REFRESH:
        !           565:           case CAPABILITY_CODE_REFRESH_OLD:
        !           566:             {
        !           567:               /* BGP refresh capability */
        !           568:               if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
        !           569:                 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
        !           570:               else
        !           571:                 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
        !           572:             }
        !           573:             break;
        !           574:           case CAPABILITY_CODE_ORF:
        !           575:           case CAPABILITY_CODE_ORF_OLD:
        !           576:             if (bgp_capability_orf (peer, &caphdr))
        !           577:               return -1;
        !           578:             break;
        !           579:           case CAPABILITY_CODE_RESTART:
        !           580:             if (bgp_capability_restart (peer, &caphdr))
        !           581:               return -1;
        !           582:             break;
        !           583:           case CAPABILITY_CODE_DYNAMIC:
        !           584:             SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
        !           585:             break;
        !           586:           case CAPABILITY_CODE_AS4:
        !           587:               /* Already handled as a special-case parsing of the capabilities
        !           588:                * at the beginning of OPEN processing. So we care not a jot
        !           589:                * for the value really, only error case.
        !           590:                */
        !           591:               if (!bgp_capability_as4 (peer, &caphdr))
        !           592:                 return -1;
        !           593:               break;            
        !           594:           default:
        !           595:             if (caphdr.code > 128)
        !           596:               {
        !           597:                 /* We don't send Notification for unknown vendor specific
        !           598:                    capabilities.  It seems reasonable for now...  */
        !           599:                 zlog_warn ("%s Vendor specific capability %d",
        !           600:                            peer->host, caphdr.code);
        !           601:               }
        !           602:             else
        !           603:               {
        !           604:                 zlog_warn ("%s unrecognized capability code: %d - ignored",
        !           605:                            peer->host, caphdr.code);
        !           606:                 memcpy (*error, sp, caphdr.length + 2);
        !           607:                 *error += caphdr.length + 2;
        !           608:               }
        !           609:           }
        !           610:       if (stream_get_getp(s) != (start + caphdr.length))
        !           611:         {
        !           612:           if (stream_get_getp(s) > (start + caphdr.length))
        !           613:             zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
        !           614:                        peer->host, LOOKUP (capcode_str, caphdr.code),
        !           615:                        caphdr.length);
        !           616:           stream_set_getp (s, start + caphdr.length);
        !           617:         }
        !           618:     }
        !           619:   return 0;
        !           620: }
        !           621: 
        !           622: static int
        !           623: bgp_auth_parse (struct peer *peer, size_t length)
        !           624: {
        !           625:   bgp_notify_send (peer, 
        !           626:                   BGP_NOTIFY_OPEN_ERR, 
        !           627:                   BGP_NOTIFY_OPEN_AUTH_FAILURE); 
        !           628:   return -1;
        !           629: }
        !           630: 
        !           631: static int
        !           632: strict_capability_same (struct peer *peer)
        !           633: {
        !           634:   int i, j;
        !           635: 
        !           636:   for (i = AFI_IP; i < AFI_MAX; i++)
        !           637:     for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
        !           638:       if (peer->afc[i][j] != peer->afc_nego[i][j])
        !           639:        return 0;
        !           640:   return 1;
        !           641: }
        !           642: 
        !           643: /* peek into option, stores ASN to *as4 if the AS4 capability was found.
        !           644:  * Returns  0 if no as4 found, as4cap value otherwise.
        !           645:  */
        !           646: as_t
        !           647: peek_for_as4_capability (struct peer *peer, u_char length)
        !           648: {
        !           649:   struct stream *s = BGP_INPUT (peer);
        !           650:   size_t orig_getp = stream_get_getp (s);
        !           651:   size_t end = orig_getp + length;
        !           652:   as_t as4 = 0;
        !           653:   
        !           654:   /* The full capability parser will better flag the error.. */
        !           655:   if (STREAM_READABLE(s) < length)
        !           656:     return 0;
        !           657: 
        !           658:   if (BGP_DEBUG (as4, AS4))
        !           659:     zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
        !           660:                 " peeking for as4",
        !           661:                peer->host, length);
        !           662:   /* the error cases we DONT handle, we ONLY try to read as4 out of
        !           663:    * correctly formatted options.
        !           664:    */
        !           665:   while (stream_get_getp(s) < end) 
        !           666:     {
        !           667:       u_char opt_type;
        !           668:       u_char opt_length;
        !           669:       
        !           670:       /* Check the length. */
        !           671:       if (stream_get_getp (s) + 2 > end)
        !           672:         goto end;
        !           673:       
        !           674:       /* Fetch option type and length. */
        !           675:       opt_type = stream_getc (s);
        !           676:       opt_length = stream_getc (s);
        !           677:       
        !           678:       /* Option length check. */
        !           679:       if (stream_get_getp (s) + opt_length > end)
        !           680:         goto end;
        !           681:       
        !           682:       if (opt_type == BGP_OPEN_OPT_CAP)
        !           683:         {
        !           684:           unsigned long capd_start = stream_get_getp (s);
        !           685:           unsigned long capd_end = capd_start + opt_length;
        !           686:           
        !           687:           assert (capd_end <= end);
        !           688:           
        !           689:          while (stream_get_getp (s) < capd_end)
        !           690:            {
        !           691:              struct capability_header hdr;
        !           692:              
        !           693:              if (stream_get_getp (s) + 2 > capd_end)
        !           694:                 goto end;
        !           695:               
        !           696:               hdr.code = stream_getc (s);
        !           697:               hdr.length = stream_getc (s);
        !           698:               
        !           699:              if ((stream_get_getp(s) +  hdr.length) > capd_end)
        !           700:                goto end;
        !           701: 
        !           702:              if (hdr.code == CAPABILITY_CODE_AS4)
        !           703:                {
        !           704:                  if (hdr.length != CAPABILITY_CODE_AS4_LEN)
        !           705:                    goto end;
        !           706:                   
        !           707:                  if (BGP_DEBUG (as4, AS4))
        !           708:                    zlog_info ("[AS4] found AS4 capability, about to parse");
        !           709:                  as4 = bgp_capability_as4 (peer, &hdr);
        !           710:                  
        !           711:                  goto end;
        !           712:                 }
        !           713:               stream_forward_getp (s, hdr.length);
        !           714:            }
        !           715:        }
        !           716:     }
        !           717: 
        !           718: end:
        !           719:   stream_set_getp (s, orig_getp);
        !           720:   return as4;
        !           721: }
        !           722: 
        !           723: /* Parse open option */
        !           724: int
        !           725: bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
        !           726: {
        !           727:   int ret;
        !           728:   u_char *error;
        !           729:   u_char error_data[BGP_MAX_PACKET_SIZE];
        !           730:   struct stream *s = BGP_INPUT(peer);
        !           731:   size_t end = stream_get_getp (s) + length;
        !           732: 
        !           733:   ret = 0;
        !           734:   error = error_data;
        !           735: 
        !           736:   if (BGP_DEBUG (normal, NORMAL))
        !           737:     zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
        !           738:               peer->host, length);
        !           739:   
        !           740:   while (stream_get_getp(s) < end)
        !           741:     {
        !           742:       u_char opt_type;
        !           743:       u_char opt_length;
        !           744:       
        !           745:       /* Must have at least an OPEN option header */
        !           746:       if (STREAM_READABLE(s) < 2)
        !           747:        {
        !           748:          zlog_info ("%s Option length error", peer->host);
        !           749:          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
        !           750:          return -1;
        !           751:        }
        !           752: 
        !           753:       /* Fetch option type and length. */
        !           754:       opt_type = stream_getc (s);
        !           755:       opt_length = stream_getc (s);
        !           756:       
        !           757:       /* Option length check. */
        !           758:       if (STREAM_READABLE (s) < opt_length)
        !           759:        {
        !           760:          zlog_info ("%s Option length error", peer->host);
        !           761:          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
        !           762:          return -1;
        !           763:        }
        !           764: 
        !           765:       if (BGP_DEBUG (normal, NORMAL))
        !           766:        zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
        !           767:                   peer->host, opt_type,
        !           768:                   opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
        !           769:                   opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
        !           770:                   opt_length);
        !           771:   
        !           772:       switch (opt_type)
        !           773:        {
        !           774:        case BGP_OPEN_OPT_AUTH:
        !           775:          ret = bgp_auth_parse (peer, opt_length);
        !           776:          break;
        !           777:        case BGP_OPEN_OPT_CAP:
        !           778:          ret = bgp_capability_parse (peer, opt_length, &error);
        !           779:          *capability = 1;
        !           780:          break;
        !           781:        default:
        !           782:          bgp_notify_send (peer, 
        !           783:                           BGP_NOTIFY_OPEN_ERR, 
        !           784:                           BGP_NOTIFY_OPEN_UNSUP_PARAM); 
        !           785:          ret = -1;
        !           786:          break;
        !           787:        }
        !           788: 
        !           789:       /* Parse error.  To accumulate all unsupported capability codes,
        !           790:          bgp_capability_parse does not return -1 when encounter
        !           791:          unsupported capability code.  To detect that, please check
        !           792:          error and erro_data pointer, like below.  */
        !           793:       if (ret < 0)
        !           794:        return -1;
        !           795:     }
        !           796: 
        !           797:   /* All OPEN option is parsed.  Check capability when strict compare
        !           798:      flag is enabled.*/
        !           799:   if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
        !           800:     {
        !           801:       /* If Unsupported Capability exists. */
        !           802:       if (error != error_data)
        !           803:        {
        !           804:          bgp_notify_send_with_data (peer, 
        !           805:                                     BGP_NOTIFY_OPEN_ERR, 
        !           806:                                     BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
        !           807:                                     error_data, error - error_data);
        !           808:          return -1;
        !           809:        }
        !           810: 
        !           811:       /* Check local capability does not negotiated with remote
        !           812:          peer. */
        !           813:       if (! strict_capability_same (peer))
        !           814:        {
        !           815:          bgp_notify_send (peer, 
        !           816:                           BGP_NOTIFY_OPEN_ERR, 
        !           817:                           BGP_NOTIFY_OPEN_UNSUP_CAPBL);
        !           818:          return -1;
        !           819:        }
        !           820:     }
        !           821: 
        !           822:   /* Check there is no common capability send Unsupported Capability
        !           823:      error. */
        !           824:   if (*capability && ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
        !           825:     {
        !           826:       if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] 
        !           827:          && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
        !           828:          && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
        !           829:          && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
        !           830:          && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
        !           831:        {
        !           832:          plog_err (peer->log, "%s [Error] No common capability", peer->host);
        !           833: 
        !           834:          if (error != error_data)
        !           835: 
        !           836:            bgp_notify_send_with_data (peer, 
        !           837:                                       BGP_NOTIFY_OPEN_ERR, 
        !           838:                                       BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
        !           839:                                       error_data, error - error_data);
        !           840:          else
        !           841:            bgp_notify_send (peer, 
        !           842:                             BGP_NOTIFY_OPEN_ERR, 
        !           843:                             BGP_NOTIFY_OPEN_UNSUP_CAPBL);
        !           844:          return -1;
        !           845:        }
        !           846:     }
        !           847:   return 0;
        !           848: }
        !           849: 
        !           850: static void
        !           851: bgp_open_capability_orf (struct stream *s, struct peer *peer,
        !           852:                          afi_t afi, safi_t safi, u_char code)
        !           853: {
        !           854:   u_char cap_len;
        !           855:   u_char orf_len;
        !           856:   unsigned long capp;
        !           857:   unsigned long orfp;
        !           858:   unsigned long numberp;
        !           859:   int number_of_orfs = 0;
        !           860: 
        !           861:   if (safi == SAFI_MPLS_VPN)
        !           862:     safi = BGP_SAFI_VPNV4;
        !           863: 
        !           864:   stream_putc (s, BGP_OPEN_OPT_CAP);
        !           865:   capp = stream_get_endp (s);           /* Set Capability Len Pointer */
        !           866:   stream_putc (s, 0);                   /* Capability Length */
        !           867:   stream_putc (s, code);                /* Capability Code */
        !           868:   orfp = stream_get_endp (s);           /* Set ORF Len Pointer */
        !           869:   stream_putc (s, 0);                   /* ORF Length */
        !           870:   stream_putw (s, afi);
        !           871:   stream_putc (s, 0);
        !           872:   stream_putc (s, safi);
        !           873:   numberp = stream_get_endp (s);        /* Set Number Pointer */
        !           874:   stream_putc (s, 0);                   /* Number of ORFs */
        !           875: 
        !           876:   /* Address Prefix ORF */
        !           877:   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
        !           878:       || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
        !           879:     {
        !           880:       stream_putc (s, (code == CAPABILITY_CODE_ORF ?
        !           881:                   ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
        !           882: 
        !           883:       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
        !           884:          && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
        !           885:        {
        !           886:          SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
        !           887:          SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
        !           888:          stream_putc (s, ORF_MODE_BOTH);
        !           889:        }
        !           890:       else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
        !           891:        {
        !           892:          SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
        !           893:          stream_putc (s, ORF_MODE_SEND);
        !           894:        }
        !           895:       else
        !           896:        {
        !           897:          SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
        !           898:          stream_putc (s, ORF_MODE_RECEIVE);
        !           899:        }
        !           900:       number_of_orfs++;
        !           901:     }
        !           902: 
        !           903:   /* Total Number of ORFs. */
        !           904:   stream_putc_at (s, numberp, number_of_orfs);
        !           905: 
        !           906:   /* Total ORF Len. */
        !           907:   orf_len = stream_get_endp (s) - orfp - 1;
        !           908:   stream_putc_at (s, orfp, orf_len);
        !           909: 
        !           910:   /* Total Capability Len. */
        !           911:   cap_len = stream_get_endp (s) - capp - 1;
        !           912:   stream_putc_at (s, capp, cap_len);
        !           913: }
        !           914: 
        !           915: /* Fill in capability open option to the packet. */
        !           916: void
        !           917: bgp_open_capability (struct stream *s, struct peer *peer)
        !           918: {
        !           919:   u_char len;
        !           920:   unsigned long cp;
        !           921:   afi_t afi;
        !           922:   safi_t safi;
        !           923:   as_t local_as;
        !           924: 
        !           925:   /* Remember current pointer for Opt Parm Len. */
        !           926:   cp = stream_get_endp (s);
        !           927: 
        !           928:   /* Opt Parm Len. */
        !           929:   stream_putc (s, 0);
        !           930: 
        !           931:   /* Do not send capability. */
        !           932:   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) 
        !           933:       || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
        !           934:     return;
        !           935: 
        !           936:   /* IPv4 unicast. */
        !           937:   if (peer->afc[AFI_IP][SAFI_UNICAST])
        !           938:     {
        !           939:       peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
        !           940:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !           941:       stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        !           942:       stream_putc (s, CAPABILITY_CODE_MP);
        !           943:       stream_putc (s, CAPABILITY_CODE_MP_LEN);
        !           944:       stream_putw (s, AFI_IP);
        !           945:       stream_putc (s, 0);
        !           946:       stream_putc (s, SAFI_UNICAST);
        !           947:     }
        !           948:   /* IPv4 multicast. */
        !           949:   if (peer->afc[AFI_IP][SAFI_MULTICAST])
        !           950:     {
        !           951:       peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
        !           952:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !           953:       stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        !           954:       stream_putc (s, CAPABILITY_CODE_MP);
        !           955:       stream_putc (s, CAPABILITY_CODE_MP_LEN);
        !           956:       stream_putw (s, AFI_IP);
        !           957:       stream_putc (s, 0);
        !           958:       stream_putc (s, SAFI_MULTICAST);
        !           959:     }
        !           960:   /* IPv4 VPN */
        !           961:   if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
        !           962:     {
        !           963:       peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
        !           964:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !           965:       stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        !           966:       stream_putc (s, CAPABILITY_CODE_MP);
        !           967:       stream_putc (s, CAPABILITY_CODE_MP_LEN);
        !           968:       stream_putw (s, AFI_IP);
        !           969:       stream_putc (s, 0);
        !           970:       stream_putc (s, BGP_SAFI_VPNV4);
        !           971:     }
        !           972: #ifdef HAVE_IPV6
        !           973:   /* IPv6 unicast. */
        !           974:   if (peer->afc[AFI_IP6][SAFI_UNICAST])
        !           975:     {
        !           976:       peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
        !           977:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !           978:       stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        !           979:       stream_putc (s, CAPABILITY_CODE_MP);
        !           980:       stream_putc (s, CAPABILITY_CODE_MP_LEN);
        !           981:       stream_putw (s, AFI_IP6);
        !           982:       stream_putc (s, 0);
        !           983:       stream_putc (s, SAFI_UNICAST);
        !           984:     }
        !           985:   /* IPv6 multicast. */
        !           986:   if (peer->afc[AFI_IP6][SAFI_MULTICAST])
        !           987:     {
        !           988:       peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
        !           989:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !           990:       stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
        !           991:       stream_putc (s, CAPABILITY_CODE_MP);
        !           992:       stream_putc (s, CAPABILITY_CODE_MP_LEN);
        !           993:       stream_putw (s, AFI_IP6);
        !           994:       stream_putc (s, 0);
        !           995:       stream_putc (s, SAFI_MULTICAST);
        !           996:     }
        !           997: #endif /* HAVE_IPV6 */
        !           998: 
        !           999:   /* Route refresh. */
        !          1000:   SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
        !          1001:   stream_putc (s, BGP_OPEN_OPT_CAP);
        !          1002:   stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
        !          1003:   stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
        !          1004:   stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
        !          1005:   stream_putc (s, BGP_OPEN_OPT_CAP);
        !          1006:   stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
        !          1007:   stream_putc (s, CAPABILITY_CODE_REFRESH);
        !          1008:   stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
        !          1009: 
        !          1010:   /* AS4 */
        !          1011:   SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
        !          1012:   stream_putc (s, BGP_OPEN_OPT_CAP);
        !          1013:   stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
        !          1014:   stream_putc (s, CAPABILITY_CODE_AS4);
        !          1015:   stream_putc (s, CAPABILITY_CODE_AS4_LEN);
        !          1016:   if ( peer->change_local_as )
        !          1017:     local_as = peer->change_local_as;
        !          1018:   else
        !          1019:     local_as = peer->local_as;
        !          1020:   stream_putl (s, local_as );
        !          1021: 
        !          1022:   /* ORF capability. */
        !          1023:   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
        !          1024:     for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
        !          1025:       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
        !          1026:          || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
        !          1027:        {
        !          1028:          bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
        !          1029:          bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
        !          1030:        }
        !          1031: 
        !          1032:   /* Dynamic capability. */
        !          1033:   if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
        !          1034:     {
        !          1035:       SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
        !          1036:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !          1037:       stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
        !          1038:       stream_putc (s, CAPABILITY_CODE_DYNAMIC);
        !          1039:       stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
        !          1040:     }
        !          1041: 
        !          1042:   /* Graceful restart capability */
        !          1043:   if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
        !          1044:     {
        !          1045:       SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
        !          1046:       stream_putc (s, BGP_OPEN_OPT_CAP);
        !          1047:       stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
        !          1048:       stream_putc (s, CAPABILITY_CODE_RESTART);
        !          1049:       stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
        !          1050:       stream_putw (s, peer->bgp->restart_time);
        !          1051:      }
        !          1052: 
        !          1053:   /* Total Opt Parm Len. */
        !          1054:   len = stream_get_endp (s) - cp - 1;
        !          1055:   stream_putc_at (s, cp, len);
        !          1056: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>