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

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

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