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

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

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