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

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

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