File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_open.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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: #include "filter.h"
   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;
   97: 	    case SAFI_MPLS_LABELED_VPN:
   98: 	      vty_out (vty, "SAFI MPLS-labeled VPN");
   99: 	      break;
  100: 	    case SAFI_ENCAP:
  101: 	      vty_out (vty, "SAFI ENCAP");
  102: 	      break;
  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:     {
  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;
  147:     }
  148: 
  149:   zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
  150: 
  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: };
  195: static const int orf_type_str_max = array_size(orf_type_str);
  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: };
  203: static const int orf_mode_str_max = array_size(orf_mode_str);
  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 */
  238:   if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length)
  239:     {
  240:       zlog_info ("%s ORF Capability entry length error,"
  241:                  " Cap length %u, num %u",
  242:                  peer->host, hdr->length, entry.num);
  243:       bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
  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))
  351:     SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
  352:   
  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",
  360:                   peer->host,
  361:                   CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " " 
  362:                                                                    : " not ",
  363:                   peer->v_gr_restart);
  364:     }
  365: 
  366:   while (stream_get_getp (s) + 4 <= end)
  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: {
  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:   
  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: };
  435: static const int capcode_str_max = array_size(capcode_str);
  436: 
  437: /* Minimum sizes for length field of each cap (so not inc. the header) */
  438: static const size_t cap_minsizes[] = 
  439: {
  440:   [CAPABILITY_CODE_MP]		= CAPABILITY_CODE_MP_LEN,
  441:   [CAPABILITY_CODE_REFRESH]	= CAPABILITY_CODE_REFRESH_LEN,
  442:   [CAPABILITY_CODE_ORF]		= CAPABILITY_CODE_ORF_LEN,
  443:   [CAPABILITY_CODE_RESTART]	= CAPABILITY_CODE_RESTART_LEN,
  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,
  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,
  465: };
  466: 
  467: /**
  468:  * Parse given capability.
  469:  * XXX: This is reading into a stream, but not using stream API
  470:  *
  471:  * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
  472:  *                           capabilities were encountered.
  473:  */
  474: static int
  475: bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
  476: 		      u_char **error)
  477: {
  478:   int ret;
  479:   struct stream *s = BGP_INPUT (peer);
  480:   size_t end = stream_get_getp (s) + length;
  481:   
  482:   assert (STREAM_READABLE (s) >= length);
  483:   
  484:   while (stream_get_getp (s) < end)
  485:     {
  486:       size_t start;
  487:       u_char *sp = stream_pnt (s);
  488:       struct capability_header caphdr;
  489:       
  490:       /* We need at least capability code and capability length. */
  491:       if (stream_get_getp(s) + 2 > end)
  492: 	{
  493: 	  zlog_info ("%s Capability length error (< header)", peer->host);
  494: 	  bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
  495: 	  return -1;
  496: 	}
  497:       
  498:       caphdr.code = stream_getc (s);
  499:       caphdr.length = stream_getc (s);
  500:       start = stream_get_getp (s);
  501:       
  502:       /* Capability length check sanity check. */
  503:       if (start + caphdr.length > end)
  504: 	{
  505: 	  zlog_info ("%s Capability length error (< length)", peer->host);
  506: 	  bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
  507: 	  return -1;
  508: 	}
  509:       
  510:       if (BGP_DEBUG (normal, NORMAL))
  511: 	zlog_debug ("%s OPEN has %s capability (%u), length %u",
  512: 		   peer->host,
  513: 		   LOOKUP (capcode_str, caphdr.code),
  514: 		   caphdr.code, caphdr.length);
  515:       
  516:       /* Length sanity check, type-specific, for known capabilities */
  517:       switch (caphdr.code)
  518:         {
  519:           case CAPABILITY_CODE_MP:
  520:           case CAPABILITY_CODE_REFRESH:
  521:           case CAPABILITY_CODE_REFRESH_OLD:
  522:           case CAPABILITY_CODE_ORF:
  523:           case CAPABILITY_CODE_ORF_OLD:
  524:           case CAPABILITY_CODE_RESTART:
  525:           case CAPABILITY_CODE_AS4:
  526:           case CAPABILITY_CODE_DYNAMIC:
  527:               /* Check length. */
  528:               if (caphdr.length < cap_minsizes[caphdr.code])
  529:                 {
  530:                   zlog_info ("%s %s Capability length error: got %u,"
  531:                              " expected at least %u",
  532:                              peer->host, 
  533:                              LOOKUP (capcode_str, caphdr.code),
  534:                              caphdr.length, 
  535: 			     (unsigned) cap_minsizes[caphdr.code]);
  536:                   bgp_notify_send (peer, BGP_NOTIFY_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);
  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:             {
  562: 	      *mp_capability = 1;
  563: 
  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:
  592:             if (bgp_capability_orf_entry (peer, &caphdr))
  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: 
  736: /**
  737:  * Parse open option.
  738:  *
  739:  * @param[out] mp_capability @see bgp_capability_parse() for semantics.
  740:  */
  741: int
  742: bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
  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);
  766: 	  bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
  767: 	                         BGP_NOTIFY_OPEN_UNSPECIFIC);
  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);
  779: 	  bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
  780: 	                         BGP_NOTIFY_OPEN_UNSPECIFIC);
  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:
  797: 	  ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
  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: 
  840:   /* Check there are no common AFI/SAFIs and send Unsupported Capability
  841:      error. */
  842:   if (*mp_capability &&
  843:       ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
  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]
  848: 	  && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
  849: 	  && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
  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])
  853: 	{
  854: 	  plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
  855: 		    "overlap with received MP capabilities",
  856: 		    peer->host);
  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)
  886:     safi = SAFI_MPLS_LABELED_VPN;
  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;
  944:   unsigned long cp, capp, rcapp;
  945:   afi_t afi;
  946:   safi_t safi;
  947:   as_t local_as;
  948:   u_int32_t restart_time;
  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);
  995:       stream_putc (s, SAFI_MPLS_LABELED_VPN);
  996:     }
  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:     }
 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:     }
 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:     }
 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: 
 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 */
 1119:   if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
 1120:     {
 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);
 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>