components/quagga/patches/40-bgp-capab-cleanup.patch
changeset 641 719d637aca9f
parent 640 4afec94b6313
child 642 817474c3c772
equal deleted inserted replaced
640:4afec94b6313 641:719d637aca9f
     1 commit 6d58272b4cf96f0daa846210dd2104877900f921
       
     2 Author: Paul Jakma <[email protected]>
       
     3 Date:   Mon Aug 6 15:21:45 2007 +0000
       
     4 
       
     5     [bgpd] cleanup, compact and consolidate capability parsing code
       
     6     
       
     7     2007-07-26 Paul Jakma <[email protected]>
       
     8     
       
     9     	* (general) Clean up and compact capability parsing slightly.
       
    10     	  Consolidate validation of length and logging of generic TLV, and
       
    11     	  memcpy of capability data, thus removing such from cap specifc
       
    12     	  code (not always present or correct).
       
    13     	* bgp_open.h: Add structures for the generic capability TLV header
       
    14     	  and for the data formats of the various specific capabilities we
       
    15     	  support.  Hence remove the badly named, or else misdefined, struct
       
    16     	  capability.
       
    17     	* bgp_open.c: (bgp_capability_vty_out) Use struct capability_mp_data.
       
    18     	  Do the length checks *before* memcpy()'ing based on that length
       
    19     	  (stored capability - should have been validated anyway on input,
       
    20     	  but..).
       
    21     	  (bgp_afi_safi_valid_indices) new function to validate (afi,safi)
       
    22     	  which is about to be used as index into arrays, consolidates
       
    23     	  several instances of same, at least one of which appeared to be
       
    24     	  incomplete..
       
    25     	  (bgp_capability_mp) Much condensed.
       
    26     	  (bgp_capability_orf_entry) New, process one ORF entry
       
    27     	  (bgp_capability_orf) Condensed. Fixed to process all ORF entries.
       
    28     	  (bgp_capability_restart) Condensed, and fixed to use a
       
    29     	  cap-specific type, rather than abusing capability_mp.
       
    30     	  (struct message capcode_str) added to aid generic logging.
       
    31     	  (size_t cap_minsizes[]) added to aid generic validation of
       
    32     	  capability length field.
       
    33     	  (bgp_capability_parse) Generic logging and validation of TLV
       
    34     	  consolidated here. Code compacted as much as possible.
       
    35     	* bgp_packet.c: (bgp_open_receive) Capability parsers now use
       
    36     	  streams, so no more need here to manually fudge the input stream
       
    37     	  getp.
       
    38     	  (bgp_capability_msg_parse) use struct capability_mp_data. Validate
       
    39     	  lengths /before/ memcpy. Use bgp_afi_safi_valid_indices.
       
    40     	  (bgp_capability_receive) Exported for use by test harness.
       
    41     	* bgp_vty.c: (bgp_show_summary) fix conversion warning
       
    42     	  (bgp_show_peer) ditto
       
    43     	* bgp_debug.h: Fix storage 'extern' after type 'const'.
       
    44             * lib/log.c: (mes_lookup) warning about code not being in
       
    45               same-number array slot should be debug, not warning. E.g. BGP
       
    46               has several discontigious number spaces, allocating from
       
    47               different parts of a space is not uncommon (e.g. IANA
       
    48               assigned versus vendor-assigned code points in some number
       
    49               space).
       
    50 
       
    51 --- bgpd/bgp_debug.h
       
    52 +++ bgpd/bgp_debug.h
       
    53 @@ -110,7 +110,7 @@ extern unsigned long term_bgp_debug_zebra;
       
    54  #define BGP_DEBUG(a, b)		(term_bgp_debug_ ## a & BGP_DEBUG_ ## b)
       
    55  #define CONF_BGP_DEBUG(a, b)    (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
       
    56  
       
    57 -const extern char *bgp_type_str[];
       
    58 +extern const char *bgp_type_str[];
       
    59  
       
    60  extern int bgp_dump_attr (struct peer *, struct attr *, char *, size_t);
       
    61  extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *);
       
    62 diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
       
    63 index e44bd2a..d4f7cdf 100644
       
    64 --- bgpd/bgp_open.c
       
    65 +++ bgpd/bgp_open.c
       
    66 @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
       
    67  #include "thread.h"
       
    68  #include "log.h"
       
    69  #include "command.h"
       
    70 +#include "memory.h"
       
    71  
       
    72  #include "bgpd/bgpd.h"
       
    73  #include "bgpd/bgp_attr.h"
       
    74 @@ -50,25 +51,28 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer)
       
    75  {
       
    76    char *pnt;
       
    77    char *end;
       
    78 -  struct capability cap;
       
    79 +  struct capability_mp_data mpc;
       
    80 +  struct capability_header *hdr;
       
    81  
       
    82    pnt = peer->notify.data;
       
    83    end = pnt + peer->notify.length;
       
    84 -
       
    85 +  
       
    86    while (pnt < end)
       
    87      {
       
    88 -      memcpy(&cap, pnt, sizeof(struct capability));
       
    89 -
       
    90 -      if (pnt + 2 > end)
       
    91 +      if (pnt + sizeof (struct capability_mp_data) + 2 > end)
       
    92  	return;
       
    93 -      if (pnt + (cap.length + 2) > end)
       
    94 +      
       
    95 +      hdr = (struct capability_header *)pnt;
       
    96 +      if (pnt + hdr->length + 2 > end)
       
    97  	return;
       
    98  
       
    99 -      if (cap.code == CAPABILITY_CODE_MP)
       
   100 +      memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
       
   101 +
       
   102 +      if (hdr->code == CAPABILITY_CODE_MP)
       
   103  	{
       
   104  	  vty_out (vty, "  Capability error for: Multi protocol ");
       
   105  
       
   106 -	  switch (ntohs (cap.mpc.afi))
       
   107 +	  switch (ntohs (mpc.afi))
       
   108  	    {
       
   109  	    case AFI_IP:
       
   110  	      vty_out (vty, "AFI IPv4, ");
       
   111 @@ -77,10 +81,10 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer)
       
   112  	      vty_out (vty, "AFI IPv6, ");
       
   113  	      break;
       
   114  	    default:
       
   115 -	      vty_out (vty, "AFI Unknown %d, ", ntohs (cap.mpc.afi));
       
   116 +	      vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
       
   117  	      break;
       
   118  	    }
       
   119 -	  switch (cap.mpc.safi)
       
   120 +	  switch (mpc.safi)
       
   121  	    {
       
   122  	    case SAFI_UNICAST:
       
   123  	      vty_out (vty, "SAFI Unicast");
       
   124 @@ -95,88 +99,87 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer)
       
   125  	      vty_out (vty, "SAFI MPLS-VPN");
       
   126  	      break;
       
   127  	    default:
       
   128 -	      vty_out (vty, "SAFI Unknown %d ", cap.mpc.safi);
       
   129 +	      vty_out (vty, "SAFI Unknown %d ", mpc.safi);
       
   130  	      break;
       
   131  	    }
       
   132  	  vty_out (vty, "%s", VTY_NEWLINE);
       
   133  	}
       
   134 -      else if (cap.code >= 128)
       
   135 +      else if (hdr->code >= 128)
       
   136  	vty_out (vty, "  Capability error: vendor specific capability code %d",
       
   137 -		 cap.code);
       
   138 +		 hdr->code);
       
   139        else
       
   140  	vty_out (vty, "  Capability error: unknown capability code %d", 
       
   141 -		 cap.code);
       
   142 +		 hdr->code);
       
   143  
       
   144 -      pnt += cap.length + 2;
       
   145 +      pnt += hdr->length + 2;
       
   146      }
       
   147  }
       
   148  
       
   149 -/* Set negotiated capability value. */
       
   150 -static int
       
   151 -bgp_capability_mp (struct peer *peer, struct capability *cap)
       
   152 +static void 
       
   153 +bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
       
   154  {
       
   155 -  if (ntohs (cap->mpc.afi) == AFI_IP)
       
   156 -    {
       
   157 -      if (cap->mpc.safi == SAFI_UNICAST)
       
   158 -	{
       
   159 -	  peer->afc_recv[AFI_IP][SAFI_UNICAST] = 1;
       
   160 -
       
   161 -	  if (peer->afc[AFI_IP][SAFI_UNICAST])
       
   162 -	    peer->afc_nego[AFI_IP][SAFI_UNICAST] = 1;
       
   163 -	  else
       
   164 -	    return -1;
       
   165 -	}
       
   166 -      else if (cap->mpc.safi == SAFI_MULTICAST) 
       
   167 -	{
       
   168 -	  peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 1;
       
   169 -
       
   170 -	  if (peer->afc[AFI_IP][SAFI_MULTICAST])
       
   171 -	    peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 1;
       
   172 -	  else
       
   173 -	    return -1;
       
   174 -	}
       
   175 -      else if (cap->mpc.safi == BGP_SAFI_VPNV4)
       
   176 -	{
       
   177 -	  peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 1;
       
   178 +  mpc->afi = stream_getw (s);
       
   179 +  mpc->reserved = stream_getc (s);
       
   180 +  mpc->safi = stream_getc (s);
       
   181 +}
       
   182  
       
   183 -	  if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
       
   184 -	    peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 1;
       
   185 -	  else
       
   186 -	    return -1;
       
   187 -	}
       
   188 -      else
       
   189 -	return -1;
       
   190 -    }
       
   191 -#ifdef HAVE_IPV6
       
   192 -  else if (ntohs (cap->mpc.afi) == AFI_IP6)
       
   193 +int
       
   194 +bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
       
   195 +{
       
   196 +  /* VPNvX are AFI specific */
       
   197 +  if ((afi == AFI_IP6 && *safi == BGP_SAFI_VPNV4)
       
   198 +      || (afi == AFI_IP && *safi == BGP_SAFI_VPNV6))
       
   199      {
       
   200 -      if (cap->mpc.safi == SAFI_UNICAST)
       
   201 -	{
       
   202 -	  peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 1;
       
   203 -
       
   204 -	  if (peer->afc[AFI_IP6][SAFI_UNICAST])
       
   205 -	    peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 1;
       
   206 -	  else
       
   207 -	    return -1;
       
   208 -	}
       
   209 -      else if (cap->mpc.safi == SAFI_MULTICAST)
       
   210 -	{
       
   211 -	  peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 1;
       
   212 -
       
   213 -	  if (peer->afc[AFI_IP6][SAFI_MULTICAST])
       
   214 -	    peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 1;
       
   215 -	  else
       
   216 -	    return -1;
       
   217 -	}
       
   218 -      else
       
   219 -	return -1;
       
   220 +      zlog_warn ("Invalid afi/safi combination (%u/%u)", afi, *safi);
       
   221 +      return 0;
       
   222      }
       
   223 -#endif /* HAVE_IPV6 */
       
   224 -  else
       
   225 +  
       
   226 +  switch (afi)
       
   227      {
       
   228 -      /* Unknown Address Family. */
       
   229 -      return -1;
       
   230 +      case AFI_IP:
       
   231 +#ifdef HAVE_IPV6
       
   232 +      case AFI_IP6:
       
   233 +#endif
       
   234 +        switch (*safi)
       
   235 +          {
       
   236 +            /* BGP VPNvX SAFI isn't contigious with others, remap */
       
   237 +            case BGP_SAFI_VPNV4:
       
   238 +            case BGP_SAFI_VPNV6:
       
   239 +              *safi = SAFI_MPLS_VPN;
       
   240 +            case SAFI_UNICAST:
       
   241 +            case SAFI_MULTICAST:
       
   242 +            case SAFI_MPLS_VPN:
       
   243 +              return 1;
       
   244 +          }
       
   245      }
       
   246 +  zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
       
   247 +  
       
   248 +  return 0;
       
   249 +}
       
   250 +
       
   251 +/* Set negotiated capability value. */
       
   252 +static int
       
   253 +bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
       
   254 +{
       
   255 +  struct capability_mp_data mpc;
       
   256 +  struct stream *s = BGP_INPUT (peer);
       
   257 +  
       
   258 +  bgp_capability_mp_data (s, &mpc);
       
   259 +  
       
   260 +  if (BGP_DEBUG (normal, NORMAL))
       
   261 +    zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
       
   262 +               peer->host, mpc.afi, mpc.safi);
       
   263 +  
       
   264 +  if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
       
   265 +    return -1;
       
   266 +   
       
   267 +  /* Now safi remapped, and afi/safi are valid array indices */
       
   268 +  peer->afc_recv[mpc.afi][mpc.safi] = 1;
       
   269 +  
       
   270 +  if (peer->afc[mpc.afi][mpc.safi])
       
   271 +    peer->afc_nego[mpc.safi][mpc.safi] = 1;
       
   272 +  else 
       
   273 +    return -1;
       
   274  
       
   275    return 0;
       
   276  }
       
   277 @@ -190,98 +193,133 @@ bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
       
   278  	       peer->host, afi, safi, type, mode);
       
   279  }
       
   280  
       
   281 +static struct message orf_type_str[] =
       
   282 +{
       
   283 +  { ORF_TYPE_PREFIX,		"Prefixlist"		},
       
   284 +  { ORF_TYPE_PREFIX_OLD,	"Prefixlist (old)"	},
       
   285 +};
       
   286 +static int orf_type_str_max = sizeof(orf_type_str)/sizeof(orf_type_str[0]);
       
   287 +
       
   288 +static struct message orf_mode_str[] =
       
   289 +{
       
   290 +  { ORF_MODE_RECEIVE,	"Receive"	},
       
   291 +  { ORF_MODE_SEND,	"Send"		},
       
   292 +  { ORF_MODE_BOTH,	"Both"		},
       
   293 +};
       
   294 +static int orf_mode_str_max = sizeof(orf_mode_str)/sizeof(orf_mode_str[0]);
       
   295 +
       
   296  static int
       
   297 -bgp_capability_orf (struct peer *peer, struct capability *cap,
       
   298 -		    u_char *pnt)
       
   299 +bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
       
   300  {
       
   301 -  afi_t afi = ntohs(cap->mpc.afi);
       
   302 -  safi_t safi = cap->mpc.safi;
       
   303 -  u_char number_of_orfs;
       
   304 +  struct stream *s = BGP_INPUT (peer);
       
   305 +  struct capability_orf_entry entry;
       
   306 +  afi_t afi;
       
   307 +  safi_t safi;
       
   308    u_char type;
       
   309    u_char mode;
       
   310    u_int16_t sm_cap = 0; /* capability send-mode receive */
       
   311    u_int16_t rm_cap = 0; /* capability receive-mode receive */ 
       
   312    int i;
       
   313  
       
   314 -  /* Check length. */
       
   315 -  if (cap->length < 7)
       
   316 -    {
       
   317 -      zlog_info ("%s ORF Capability length error %d",
       
   318 -		 peer->host, cap->length);
       
   319 -		 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   320 -      return -1;
       
   321 -    }
       
   322 -
       
   323 +  /* ORF Entry header */
       
   324 +  bgp_capability_mp_data (s, &entry.mpc);
       
   325 +  entry.num = stream_getc (s);
       
   326 +  afi = entry.mpc.afi;
       
   327 +  safi = entry.mpc.safi;
       
   328 +  
       
   329    if (BGP_DEBUG (normal, NORMAL))
       
   330 -    zlog_debug ("%s OPEN has ORF CAP(%s) for afi/safi: %u/%u",
       
   331 -	       peer->host, (cap->code == CAPABILITY_CODE_ORF ?
       
   332 -                       "new" : "old"), afi, safi);
       
   333 +    zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
       
   334 +	        peer->host, entry.mpc.afi, entry.mpc.safi);
       
   335  
       
   336    /* Check AFI and SAFI. */
       
   337 -  if ((afi != AFI_IP && afi != AFI_IP6)
       
   338 -      || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
       
   339 -	  && safi != BGP_SAFI_VPNV4))
       
   340 +  if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
       
   341 +    {
       
   342 +      zlog_info ("%s Addr-family %d/%d not supported."
       
   343 +                 " Ignoring the ORF capability",
       
   344 +                 peer->host, entry.mpc.afi, entry.mpc.safi);
       
   345 +      return 0;
       
   346 +    }
       
   347 +  
       
   348 +  /* validate number field */
       
   349 +  if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
       
   350      {
       
   351 -      zlog_info ("%s Addr-family %d/%d not supported. Ignoring the ORF capability",
       
   352 -                 peer->host, afi, safi);
       
   353 +      zlog_info ("%s ORF Capability entry length error,"
       
   354 +                 " Cap length %u, num %u",
       
   355 +                 peer->host, hdr->length, entry.num);
       
   356 +      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   357        return -1;
       
   358      }
       
   359  
       
   360 -  number_of_orfs = *pnt++;
       
   361 -
       
   362 -  for (i = 0 ; i < number_of_orfs ; i++)
       
   363 +  for (i = 0 ; i < entry.num ; i++)
       
   364      {
       
   365 -      type = *pnt++;
       
   366 -      mode = *pnt++;
       
   367 -
       
   368 +      type = stream_getc(s);
       
   369 +      mode = stream_getc(s);
       
   370 +      
       
   371        /* ORF Mode error check */
       
   372 -      if (mode != ORF_MODE_BOTH && mode != ORF_MODE_SEND
       
   373 -	  && mode != ORF_MODE_RECEIVE)
       
   374 -	{
       
   375 -	  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   376 -	  continue;
       
   377 +      switch (mode)
       
   378 +        {
       
   379 +          case ORF_MODE_BOTH:
       
   380 +          case ORF_MODE_SEND:
       
   381 +          case ORF_MODE_RECEIVE:
       
   382 +            break;
       
   383 +          default:
       
   384 +	    bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   385 +	    continue;
       
   386  	}
       
   387 +      /* ORF Type and afi/safi error checks */
       
   388 +      /* capcode versus type */
       
   389 +      switch (hdr->code)
       
   390 +        {
       
   391 +          case CAPABILITY_CODE_ORF:
       
   392 +            switch (type)
       
   393 +              {
       
   394 +                case ORF_TYPE_PREFIX:
       
   395 +                  break;
       
   396 +                default:
       
   397 +                  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   398 +                  continue;
       
   399 +              }
       
   400 +            break;
       
   401 +          case CAPABILITY_CODE_ORF_OLD:
       
   402 +            switch (type)
       
   403 +              {
       
   404 +                case ORF_TYPE_PREFIX_OLD:
       
   405 +                  break;
       
   406 +                default:
       
   407 +                  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   408 +                  continue;
       
   409 +              }
       
   410 +            break;
       
   411 +          default:
       
   412 +            bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   413 +            continue;
       
   414 +        }
       
   415 +                
       
   416 +      /* AFI vs SAFI */
       
   417 +      if (!((afi == AFI_IP && safi == SAFI_UNICAST)
       
   418 +            || (afi == AFI_IP && safi == SAFI_MULTICAST)
       
   419 +            || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
       
   420 +        {
       
   421 +          bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   422 +          continue;
       
   423 +        }
       
   424 +      
       
   425 +      if (BGP_DEBUG (normal, NORMAL))
       
   426 +        zlog_debug ("%s OPEN has %s ORF capability"
       
   427 +                    " as %s for afi/safi: %d/%d",
       
   428 +                    peer->host, LOOKUP (orf_type_str, type),
       
   429 +                    LOOKUP (orf_mode_str, mode),
       
   430 +                    entry.mpc.afi, safi);
       
   431  
       
   432 -      /* ORF Type and afi/safi error check */
       
   433 -      if (cap->code == CAPABILITY_CODE_ORF)
       
   434 +      if (hdr->code == CAPABILITY_CODE_ORF)
       
   435  	{
       
   436 -	  if (type == ORF_TYPE_PREFIX &&
       
   437 -	      ((afi == AFI_IP && safi == SAFI_UNICAST)
       
   438 -		|| (afi == AFI_IP && safi == SAFI_MULTICAST)
       
   439 -		|| (afi == AFI_IP6 && safi == SAFI_UNICAST)))
       
   440 -	    {
       
   441 -	      sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
       
   442 -	      rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
       
   443 -	      if (BGP_DEBUG (normal, NORMAL))
       
   444 -		zlog_debug ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d",
       
   445 -			   peer->host, ORF_TYPE_PREFIX, (mode == ORF_MODE_SEND ? "SEND" :
       
   446 -			   mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi);
       
   447 -	    }
       
   448 -	  else
       
   449 -	    {
       
   450 -	      bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   451 -	      continue;
       
   452 -	    }
       
   453 +          sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
       
   454 +          rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
       
   455  	}
       
   456 -      else if (cap->code == CAPABILITY_CODE_ORF_OLD)
       
   457 +      else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
       
   458  	{
       
   459 -	  if (type == ORF_TYPE_PREFIX_OLD &&
       
   460 -	      ((afi == AFI_IP && safi == SAFI_UNICAST)
       
   461 -		|| (afi == AFI_IP && safi == SAFI_MULTICAST)
       
   462 -		|| (afi == AFI_IP6 && safi == SAFI_UNICAST)))
       
   463 -	    {
       
   464 -	      sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
       
   465 -	      rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
       
   466 -	      if (BGP_DEBUG (normal, NORMAL))
       
   467 -		zlog_debug ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d",
       
   468 -			   peer->host, ORF_TYPE_PREFIX_OLD, (mode == ORF_MODE_SEND ? "SEND" :
       
   469 -			   mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi);
       
   470 -	    }
       
   471 -	  else
       
   472 -	    {
       
   473 -	      bgp_capability_orf_not_support (peer, afi, safi, type, mode);
       
   474 -	      continue;
       
   475 -	    }
       
   476 +          sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
       
   477 +          rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
       
   478  	}
       
   479        else
       
   480  	{
       
   481 @@ -306,206 +344,258 @@ bgp_capability_orf (struct peer *peer, struct capability *cap,
       
   482    return 0;
       
   483  }
       
   484  
       
   485 -/* Parse given capability. */
       
   486  static int
       
   487 -bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
       
   488 -		      u_char **error)
       
   489 +bgp_capability_orf (struct peer *peer, struct capability_header *hdr)
       
   490  {
       
   491 -  int ret;
       
   492 -  u_char *end;
       
   493 -  struct capability cap;
       
   494 -
       
   495 -  end = pnt + length;
       
   496 -
       
   497 -  while (pnt < end)
       
   498 +  struct stream *s = BGP_INPUT (peer);
       
   499 +  size_t end = stream_get_getp (s) + hdr->length;
       
   500 +  
       
   501 +  assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end);
       
   502 +  
       
   503 +  /* We must have at least one ORF entry, as the caller has already done
       
   504 +   * minimum length validation for the capability code - for ORF there must
       
   505 +   * at least one ORF entry (header and unknown number of pairs of bytes).
       
   506 +   */
       
   507 +  do
       
   508      {
       
   509 -      afi_t afi;
       
   510 -      safi_t safi;
       
   511 +      if (bgp_capability_orf_entry (peer, hdr) == -1)
       
   512 +        return -1;
       
   513 +    } 
       
   514 +  while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end);
       
   515 +  
       
   516 +  return 0;
       
   517 +}
       
   518  
       
   519 -      /* Fetch structure to the byte stream. */
       
   520 -      memcpy (&cap, pnt, sizeof (struct capability));
       
   521 +static int
       
   522 +bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
       
   523 +{
       
   524 +  struct stream *s = BGP_INPUT (peer);
       
   525 +  u_int16_t restart_flag_time;
       
   526 +  int restart_bit = 0;
       
   527 +  size_t end = stream_get_getp (s) + caphdr->length;
       
   528 +
       
   529 +  SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
       
   530 +  restart_flag_time = stream_getw(s);
       
   531 +  if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
       
   532 +    restart_bit = 1;
       
   533 +  UNSET_FLAG (restart_flag_time, 0xF000);
       
   534 +  peer->v_gr_restart = restart_flag_time;
       
   535  
       
   536 -      afi = ntohs(cap.mpc.afi);
       
   537 -      safi = cap.mpc.safi;
       
   538 +  if (BGP_DEBUG (normal, NORMAL))
       
   539 +    {
       
   540 +      zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
       
   541 +      zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
       
   542 +                  peer->host, restart_bit ? " " : " not ",
       
   543 +                  peer->v_gr_restart);
       
   544 +    }
       
   545  
       
   546 -      if (BGP_DEBUG (normal, NORMAL))
       
   547 -	zlog_debug ("%s OPEN has CAPABILITY code: %d, length %d",
       
   548 -		   peer->host, cap.code, cap.length);
       
   549 +  while (stream_get_getp (s) + 4 < end)
       
   550 +    {
       
   551 +      afi_t afi = stream_getw (s);
       
   552 +      safi_t safi = stream_getc (s);
       
   553 +      u_char flag = stream_getc (s);
       
   554 +      
       
   555 +      if (!bgp_afi_safi_valid_indices (afi, &safi))
       
   556 +        {
       
   557 +          if (BGP_DEBUG (normal, NORMAL))
       
   558 +            zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
       
   559 +                        " Ignore the Graceful Restart capability",
       
   560 +                        peer->host, afi, safi);
       
   561 +        }
       
   562 +      else if (!peer->afc[afi][safi])
       
   563 +        {
       
   564 +          if (BGP_DEBUG (normal, NORMAL))
       
   565 +            zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
       
   566 +                        " Ignore the Graceful Restart capability",
       
   567 +                        peer->host, afi, safi);
       
   568 +        }
       
   569 +      else
       
   570 +        {
       
   571 +          if (BGP_DEBUG (normal, NORMAL))
       
   572 +            zlog_debug ("%s Address family %s is%spreserved", peer->host,
       
   573 +                        afi_safi_print (afi, safi),
       
   574 +                        CHECK_FLAG (peer->af_cap[afi][safi],
       
   575 +                                    PEER_CAP_RESTART_AF_PRESERVE_RCV)
       
   576 +                        ? " " : " not ");
       
   577 +
       
   578 +          SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
       
   579 +          if (CHECK_FLAG (flag, RESTART_F_BIT))
       
   580 +            SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
       
   581 +          
       
   582 +        }
       
   583 +    }
       
   584 +  return 0;
       
   585 +}
       
   586  
       
   587 +static struct message capcode_str[] =
       
   588 +{
       
   589 +  { 0,	""},
       
   590 +  { CAPABILITY_CODE_MP,			"MultiProtocol Extensions"	},
       
   591 +  { CAPABILITY_CODE_REFRESH,		"Route Refresh"			},
       
   592 +  { CAPABILITY_CODE_ORF,		"Cooperative Route Filtering" 	},
       
   593 +  { CAPABILITY_CODE_RESTART,		"Graceful Restart"		},
       
   594 +  { CAPABILITY_CODE_AS4,		"4-octet AS number"		},
       
   595 +  { CAPABILITY_CODE_DYNAMIC,		"Dynamic"			},
       
   596 +  { CAPABILITY_CODE_REFRESH_OLD,	"Route Refresh (Old)"		},
       
   597 +  { CAPABILITY_CODE_ORF_OLD,		"ORF (Old)"			},
       
   598 +};
       
   599 +int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]);
       
   600 +
       
   601 +/* Minimum sizes for length field of each cap (so not inc. the header) */
       
   602 +static size_t cap_minsizes[] = 
       
   603 +{
       
   604 +  [CAPABILITY_CODE_MP]		= sizeof (struct capability_mp_data),
       
   605 +  [CAPABILITY_CODE_REFRESH]	= CAPABILITY_CODE_REFRESH_LEN,
       
   606 +  [CAPABILITY_CODE_ORF]		= sizeof (struct capability_orf_entry),
       
   607 +  [CAPABILITY_CODE_RESTART]	= sizeof (struct capability_gr) - 2,
       
   608 +  [CAPABILITY_CODE_AS4]		= CAPABILITY_CODE_AS4_LEN,
       
   609 +  [CAPABILITY_CODE_DYNAMIC]	= CAPABILITY_CODE_DYNAMIC_LEN,
       
   610 +  [CAPABILITY_CODE_REFRESH_OLD]	= CAPABILITY_CODE_REFRESH_LEN,
       
   611 +  [CAPABILITY_CODE_ORF_OLD]	= sizeof (struct capability_orf_entry),
       
   612 +};
       
   613 +
       
   614 +/* Parse given capability.
       
   615 + * XXX: This is reading into a stream, but not using stream API
       
   616 + */
       
   617 +static int
       
   618 +bgp_capability_parse (struct peer *peer, size_t length, u_char **error)
       
   619 +{
       
   620 +  int ret;
       
   621 +  struct stream *s = BGP_INPUT (peer);
       
   622 +  size_t end = stream_get_getp (s) + length;
       
   623 +  
       
   624 +  assert (STREAM_READABLE (s) >= length);
       
   625 +  
       
   626 +  while (stream_get_getp (s) < end)
       
   627 +    {
       
   628 +      size_t start;
       
   629 +      u_char *sp = stream_pnt (s);
       
   630 +      struct capability_header caphdr;
       
   631 +      
       
   632        /* We need at least capability code and capability length. */
       
   633 -      if (pnt + 2 > end)
       
   634 +      if (stream_get_getp(s) + 2 > end)
       
   635  	{
       
   636 -	  zlog_info ("%s Capability length error", peer->host);
       
   637 +	  zlog_info ("%s Capability length error (< header)", peer->host);
       
   638  	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   639  	  return -1;
       
   640  	}
       
   641 -
       
   642 -      /* Capability length check. */
       
   643 -      if (pnt + (cap.length + 2) > end)
       
   644 +      
       
   645 +      caphdr.code = stream_getc (s);
       
   646 +      caphdr.length = stream_getc (s);
       
   647 +      start = stream_get_getp (s);
       
   648 +      
       
   649 +      /* Capability length check sanity check. */
       
   650 +      if (start + caphdr.length > end)
       
   651  	{
       
   652 -	  zlog_info ("%s Capability length error", peer->host);
       
   653 +	  zlog_info ("%s Capability length error (< length)", peer->host);
       
   654  	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   655  	  return -1;
       
   656  	}
       
   657 -
       
   658 -      /* We know MP Capability Code. */
       
   659 -      if (cap.code == CAPABILITY_CODE_MP)
       
   660 -	{
       
   661 -	  if (BGP_DEBUG (normal, NORMAL))
       
   662 -	    zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
       
   663 -		       peer->host, afi, safi);
       
   664 -
       
   665 -	  /* Ignore capability when override-capability is set. */
       
   666 -	  if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
       
   667 -	    {
       
   668 -	      /* Set negotiated value. */
       
   669 -	      ret = bgp_capability_mp (peer, &cap);
       
   670 -
       
   671 -	      /* Unsupported Capability. */
       
   672 -	      if (ret < 0)
       
   673 -		{
       
   674 -		  /* Store return data. */
       
   675 -		  memcpy (*error, &cap, cap.length + 2);
       
   676 -		  *error += cap.length + 2;
       
   677 -		}
       
   678 -	    }
       
   679 -	}
       
   680 -      else if (cap.code == CAPABILITY_CODE_REFRESH
       
   681 -	       || cap.code == CAPABILITY_CODE_REFRESH_OLD)
       
   682 -	{
       
   683 -	  /* Check length. */
       
   684 -	  if (cap.length != CAPABILITY_CODE_REFRESH_LEN)
       
   685 -	    {
       
   686 -	      zlog_info ("%s Route Refresh Capability length error %d",
       
   687 -			 peer->host, cap.length);
       
   688 -	      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   689 -	      return -1;
       
   690 -	    }
       
   691 -
       
   692 -	  if (BGP_DEBUG (normal, NORMAL))
       
   693 -	    zlog_debug ("%s OPEN has ROUTE-REFRESH capability(%s) for all address-families",
       
   694 -		       peer->host,
       
   695 -		       cap.code == CAPABILITY_CODE_REFRESH_OLD ? "old" : "new");
       
   696 -
       
   697 -	  /* BGP refresh capability */
       
   698 -	  if (cap.code == CAPABILITY_CODE_REFRESH_OLD)
       
   699 -	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
       
   700 -	  else
       
   701 -	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
       
   702 -	}
       
   703 -      else if (cap.code == CAPABILITY_CODE_ORF
       
   704 -	       || cap.code == CAPABILITY_CODE_ORF_OLD)
       
   705 -	bgp_capability_orf (peer, &cap, pnt + sizeof (struct capability));
       
   706 -      else if (cap.code == CAPABILITY_CODE_RESTART)
       
   707 -       {
       
   708 -         struct graceful_restart_af graf;
       
   709 -         u_int16_t restart_flag_time;
       
   710 -         int restart_bit = 0;
       
   711 -         u_char *restart_pnt;
       
   712 -         u_char *restart_end;
       
   713 -
       
   714 -         /* Check length. */
       
   715 -         if (cap.length < CAPABILITY_CODE_RESTART_LEN)
       
   716 -           {
       
   717 -             zlog_info ("%s Graceful Restart Capability length error %d",
       
   718 -                        peer->host, cap.length);
       
   719 -             bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   720 -             return -1;
       
   721 -           }
       
   722 -
       
   723 -         SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
       
   724 -         restart_flag_time = ntohs(cap.mpc.afi);
       
   725 -         if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
       
   726 -           restart_bit = 1;
       
   727 -         UNSET_FLAG (restart_flag_time, 0xF000);
       
   728 -	 peer->v_gr_restart = restart_flag_time;
       
   729 -
       
   730 -         if (BGP_DEBUG (normal, NORMAL))
       
   731 -           {
       
   732 -             zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
       
   733 -             zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
       
   734 -                        peer->host, restart_bit ? " " : " not ",
       
   735 -			peer->v_gr_restart);
       
   736 -           }
       
   737 -
       
   738 -         restart_pnt = pnt + 4;
       
   739 -         restart_end = pnt + cap.length + 2;
       
   740 -
       
   741 -         while (restart_pnt < restart_end)
       
   742 -           {
       
   743 -             memcpy (&graf, restart_pnt, sizeof (struct graceful_restart_af));
       
   744 -
       
   745 -             afi = ntohs(graf.afi);
       
   746 -             safi = graf.safi;
       
   747 -
       
   748 -             if (CHECK_FLAG (graf.flag, RESTART_F_BIT))
       
   749 -		SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
       
   750 -
       
   751 -             if (strcmp (afi_safi_print (afi, safi), "Unknown") == 0)
       
   752 -               {
       
   753 -                  if (BGP_DEBUG (normal, NORMAL))
       
   754 -                    zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported. I gnore the Graceful Restart capability",
       
   755 -                               peer->host, afi, safi);
       
   756 -               }
       
   757 -             else if (! peer->afc[afi][safi])
       
   758 -               {
       
   759 -                  if (BGP_DEBUG (normal, NORMAL))
       
   760 -                     zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled. Ignore the Graceful Restart capability",
       
   761 -                                peer->host, afi, safi);
       
   762 -               }
       
   763 -             else
       
   764 -               {
       
   765 -                 if (BGP_DEBUG (normal, NORMAL))
       
   766 -                   zlog_debug ("%s Address family %s is%spreserved", peer->host,
       
   767 -			       afi_safi_print (afi, safi),
       
   768 -			       CHECK_FLAG (peer->af_cap[afi][safi],
       
   769 -			       PEER_CAP_RESTART_AF_PRESERVE_RCV)
       
   770 -			       ? " " : " not ");
       
   771 -
       
   772 -                   SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
       
   773 -               }
       
   774 -             restart_pnt += 4;
       
   775 -           }
       
   776 -       }
       
   777 -      else if (cap.code == CAPABILITY_CODE_DYNAMIC)
       
   778 -	{
       
   779 -	  /* Check length. */
       
   780 -	  if (cap.length != CAPABILITY_CODE_DYNAMIC_LEN)
       
   781 -	    {
       
   782 -	      zlog_info ("%s Dynamic Capability length error %d",
       
   783 -			 peer->host, cap.length);
       
   784 -	      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   785 -	      return -1;
       
   786 -	    }
       
   787 -
       
   788 -	  if (BGP_DEBUG (normal, NORMAL))
       
   789 -	    zlog_debug ("%s OPEN has DYNAMIC capability", peer->host);
       
   790 -
       
   791 -	  SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
       
   792 -	}
       
   793 - 
       
   794 -      else if (cap.code > 128)
       
   795 -	{
       
   796 -	  /* We don't send Notification for unknown vendor specific
       
   797 -	     capabilities.  It seems reasonable for now...  */
       
   798 -	  zlog_warn ("%s Vendor specific capability %d",
       
   799 -		     peer->host, cap.code);
       
   800 -	}
       
   801 -      else
       
   802 -	{
       
   803 -	  zlog_warn ("%s unrecognized capability code: %d - ignored",
       
   804 -		     peer->host, cap.code);
       
   805 -	  memcpy (*error, &cap, cap.length + 2);
       
   806 -	  *error += cap.length + 2;
       
   807 -	}
       
   808 -
       
   809 -      pnt += cap.length + 2;
       
   810 +      
       
   811 +      if (BGP_DEBUG (normal, NORMAL))
       
   812 +	zlog_debug ("%s OPEN has %s capability (%u), length %u",
       
   813 +		   peer->host,
       
   814 +		   LOOKUP (capcode_str, caphdr.code),
       
   815 +		   caphdr.code, caphdr.length);
       
   816 +      
       
   817 +      /* Length sanity check, type-specific, for known capabilities */
       
   818 +      switch (caphdr.code)
       
   819 +        {
       
   820 +          case CAPABILITY_CODE_MP:
       
   821 +          case CAPABILITY_CODE_REFRESH:
       
   822 +          case CAPABILITY_CODE_REFRESH_OLD:
       
   823 +          case CAPABILITY_CODE_ORF:
       
   824 +          case CAPABILITY_CODE_ORF_OLD:
       
   825 +          case CAPABILITY_CODE_RESTART:
       
   826 +          case CAPABILITY_CODE_DYNAMIC:
       
   827 +              /* Check length. */
       
   828 +              if (caphdr.length < cap_minsizes[caphdr.code])
       
   829 +                {
       
   830 +                  zlog_info ("%s %s Capability length error: got %u,"
       
   831 +                             " expected at least %u",
       
   832 +                             peer->host, 
       
   833 +                             LOOKUP (capcode_str, caphdr.code),
       
   834 +                             caphdr.length, cap_minsizes[caphdr.code]);
       
   835 +                  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   836 +                  return -1;
       
   837 +                }
       
   838 +          /* we deliberately ignore unknown codes, see below */
       
   839 +          default:
       
   840 +            break;
       
   841 +        }
       
   842 +      
       
   843 +      switch (caphdr.code)
       
   844 +        {
       
   845 +          case CAPABILITY_CODE_MP:
       
   846 +            {
       
   847 +              /* Ignore capability when override-capability is set. */
       
   848 +              if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
       
   849 +                {
       
   850 +                  /* Set negotiated value. */
       
   851 +                  ret = bgp_capability_mp (peer, &caphdr);
       
   852 +
       
   853 +                  /* Unsupported Capability. */
       
   854 +                  if (ret < 0)
       
   855 +                    {
       
   856 +                      /* Store return data. */
       
   857 +                      memcpy (*error, sp, caphdr.length + 2);
       
   858 +                      *error += caphdr.length + 2;
       
   859 +                    }
       
   860 +                }
       
   861 +            }
       
   862 +            break;
       
   863 +          case CAPABILITY_CODE_REFRESH:
       
   864 +          case CAPABILITY_CODE_REFRESH_OLD:
       
   865 +            {
       
   866 +              /* BGP refresh capability */
       
   867 +              if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
       
   868 +                SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
       
   869 +              else
       
   870 +                SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
       
   871 +            }
       
   872 +            break;
       
   873 +          case CAPABILITY_CODE_ORF:
       
   874 +          case CAPABILITY_CODE_ORF_OLD:
       
   875 +            if (bgp_capability_orf (peer, &caphdr))
       
   876 +              return -1;
       
   877 +            break;
       
   878 +          case CAPABILITY_CODE_RESTART:
       
   879 +            if (bgp_capability_restart (peer, &caphdr))
       
   880 +              return -1;
       
   881 +            break;
       
   882 +          case CAPABILITY_CODE_DYNAMIC:
       
   883 +            SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
       
   884 +            break;
       
   885 +          default:
       
   886 +            if (caphdr.code > 128)
       
   887 +              {
       
   888 +                /* We don't send Notification for unknown vendor specific
       
   889 +                   capabilities.  It seems reasonable for now...  */
       
   890 +                zlog_warn ("%s Vendor specific capability %d",
       
   891 +                           peer->host, caphdr.code);
       
   892 +              }
       
   893 +            else
       
   894 +              {
       
   895 +                zlog_warn ("%s unrecognized capability code: %d - ignored",
       
   896 +                           peer->host, caphdr.code);
       
   897 +                memcpy (*error, sp, caphdr.length + 2);
       
   898 +                *error += caphdr.length + 2;
       
   899 +              }
       
   900 +          }
       
   901 +      if (stream_get_getp(s) != (start + caphdr.length))
       
   902 +        {
       
   903 +          if (stream_get_getp(s) > (start + caphdr.length))
       
   904 +            zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
       
   905 +                       peer->host, LOOKUP (capcode_str, caphdr.code),
       
   906 +                       caphdr.length);
       
   907 +          stream_set_getp (s, start + caphdr.length);
       
   908 +        }
       
   909      }
       
   910    return 0;
       
   911  }
       
   912  
       
   913  static int
       
   914 -bgp_auth_parse (struct peer *peer, u_char *pnt, size_t length)
       
   915 +bgp_auth_parse (struct peer *peer, size_t length)
       
   916  {
       
   917    bgp_notify_send (peer, 
       
   918  		   BGP_NOTIFY_OPEN_ERR, 
       
   919 @@ -530,30 +620,25 @@ int
       
   920  bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
       
   921  {
       
   922    int ret;
       
   923 -  u_char *end;
       
   924 -  u_char opt_type;
       
   925 -  u_char opt_length;
       
   926 -  u_char *pnt;
       
   927    u_char *error;
       
   928    u_char error_data[BGP_MAX_PACKET_SIZE];
       
   929 -
       
   930 -  /* Fetch pointer. */
       
   931 -  pnt = stream_pnt (peer->ibuf);
       
   932 +  struct stream *s = BGP_INPUT(peer);
       
   933 +  size_t end = stream_get_getp (s) + length;
       
   934  
       
   935    ret = 0;
       
   936 -  opt_type = 0;
       
   937 -  opt_length = 0;
       
   938 -  end = pnt + length;
       
   939    error = error_data;
       
   940  
       
   941    if (BGP_DEBUG (normal, NORMAL))
       
   942      zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
       
   943  	       peer->host, length);
       
   944    
       
   945 -  while (pnt < end) 
       
   946 +  while (stream_get_getp(s) < end)
       
   947      {
       
   948 -      /* Check the length. */
       
   949 -      if (pnt + 2 > end)
       
   950 +      u_char opt_type;
       
   951 +      u_char opt_length;
       
   952 +      
       
   953 +      /* Must have at least an OPEN option header */
       
   954 +      if (STREAM_READABLE(s) < 2)
       
   955  	{
       
   956  	  zlog_info ("%s Option length error", peer->host);
       
   957  	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   958 @@ -561,11 +646,11 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
       
   959  	}
       
   960  
       
   961        /* Fetch option type and length. */
       
   962 -      opt_type = *pnt++;
       
   963 -      opt_length = *pnt++;
       
   964 +      opt_type = stream_getc (s);
       
   965 +      opt_length = stream_getc (s);
       
   966        
       
   967        /* Option length check. */
       
   968 -      if (pnt + opt_length > end)
       
   969 +      if (STREAM_READABLE (s) < opt_length)
       
   970  	{
       
   971  	  zlog_info ("%s Option length error", peer->host);
       
   972  	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
   973 @@ -582,10 +667,10 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
       
   974        switch (opt_type)
       
   975  	{
       
   976  	case BGP_OPEN_OPT_AUTH:
       
   977 -	  ret = bgp_auth_parse (peer, pnt, opt_length);
       
   978 +	  ret = bgp_auth_parse (peer, opt_length);
       
   979  	  break;
       
   980  	case BGP_OPEN_OPT_CAP:
       
   981 -	  ret = bgp_capability_parse (peer, pnt, opt_length, &error);
       
   982 +	  ret = bgp_capability_parse (peer, opt_length, &error);
       
   983  	  *capability = 1;
       
   984  	  break;
       
   985  	default:
       
   986 @@ -602,9 +687,6 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
       
   987           error and erro_data pointer, like below.  */
       
   988        if (ret < 0)
       
   989  	return -1;
       
   990 -
       
   991 -      /* Forward pointer. */
       
   992 -      pnt += opt_length;
       
   993      }
       
   994  
       
   995    /* All OPEN option is parsed.  Check capability when strict compare
       
   996 diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
       
   997 index 7515d3f..436eb01 100644
       
   998 --- bgpd/bgp_open.h
       
   999 +++ bgpd/bgp_open.h
       
  1000 @@ -21,21 +21,32 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
       
  1001  #ifndef _QUAGGA_BGP_OPEN_H
       
  1002  #define _QUAGGA_BGP_OPEN_H
       
  1003  
       
  1004 -/* MP Capability information. */
       
  1005 -struct capability_mp
       
  1006 +/* Standard header for capability TLV */
       
  1007 +struct capability_header
       
  1008 +{
       
  1009 +  u_char code;
       
  1010 +  u_char length;
       
  1011 +};
       
  1012 +
       
  1013 +/* Generic MP capability data */
       
  1014 +struct capability_mp_data
       
  1015  {
       
  1016    u_int16_t afi;
       
  1017    u_char reserved;
       
  1018    u_char safi;
       
  1019  };
       
  1020  
       
  1021 -/* BGP open message capability. */
       
  1022 -struct capability
       
  1023 +#pragma pack(1)
       
  1024 +struct capability_orf_entry 
       
  1025  {
       
  1026 -  u_char code;
       
  1027 -  u_char length;
       
  1028 -  struct capability_mp mpc;
       
  1029 -};
       
  1030 +  struct capability_mp_data mpc;
       
  1031 +  u_char num;
       
  1032 +  struct {
       
  1033 +    u_char type;
       
  1034 +    u_char mode;
       
  1035 +  } orfs[];
       
  1036 +} __attribute__ ((packed));
       
  1037 +#pragma pack()
       
  1038  
       
  1039  struct graceful_restart_af
       
  1040  {
       
  1041 @@ -44,12 +55,18 @@ struct graceful_restart_af
       
  1042    u_char flag;
       
  1043  };
       
  1044  
       
  1045 +struct capability_gr
       
  1046 +{
       
  1047 +  u_int16_t restart_flag_time;
       
  1048 +  struct graceful_restart_af gr[];
       
  1049 +};
       
  1050 +
       
  1051  /* Capability Code */
       
  1052  #define CAPABILITY_CODE_MP              1 /* Multiprotocol Extensions */
       
  1053  #define CAPABILITY_CODE_REFRESH         2 /* Route Refresh Capability */
       
  1054  #define CAPABILITY_CODE_ORF             3 /* Cooperative Route Filtering Capability */
       
  1055  #define CAPABILITY_CODE_RESTART        64 /* Graceful Restart Capability */
       
  1056 -#define CAPABILITY_CODE_4BYTE_AS       65 /* 4-octet AS number Capability */
       
  1057 +#define CAPABILITY_CODE_AS4            65 /* 4-octet AS number Capability */
       
  1058  #define CAPABILITY_CODE_DYNAMIC        66 /* Dynamic Capability */
       
  1059  #define CAPABILITY_CODE_REFRESH_OLD   128 /* Route Refresh Capability(cisco) */
       
  1060  #define CAPABILITY_CODE_ORF_OLD       130 /* Cooperative Route Filtering Capability(cisco) */
       
  1061 @@ -59,6 +76,7 @@ struct graceful_restart_af
       
  1062  #define CAPABILITY_CODE_REFRESH_LEN     0
       
  1063  #define CAPABILITY_CODE_DYNAMIC_LEN     0
       
  1064  #define CAPABILITY_CODE_RESTART_LEN     2 /* Receiving only case */
       
  1065 +#define CAPABILITY_CODE_AS4_LEN         4
       
  1066  
       
  1067  /* Cooperative Route Filtering Capability.  */
       
  1068  
       
  1069 @@ -82,5 +100,6 @@ struct graceful_restart_af
       
  1070  extern int bgp_open_option_parse (struct peer *, u_char, int *);
       
  1071  extern void bgp_open_capability (struct stream *, struct peer *);
       
  1072  extern void bgp_capability_vty_out (struct vty *, struct peer *);
       
  1073 +extern int bgp_afi_safi_valid_indices (afi_t, safi_t *);
       
  1074  
       
  1075  #endif /* _QUAGGA_BGP_OPEN_H */
       
  1076 diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
       
  1077 index 2653201..17ac1f7 100644
       
  1078 --- bgpd/bgp_packet.c
       
  1079 +++ bgpd/bgp_packet.c
       
  1080 @@ -1371,8 +1371,6 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
       
  1081        ret = bgp_open_option_parse (peer, optlen, &capability);
       
  1082        if (ret < 0)
       
  1083  	return ret;
       
  1084 -
       
  1085 -      stream_forward_getp (peer->ibuf, optlen);
       
  1086      }
       
  1087    else
       
  1088      {
       
  1089 @@ -1991,7 +1989,8 @@ static int
       
  1090  bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
       
  1091  {
       
  1092    u_char *end;
       
  1093 -  struct capability cap;
       
  1094 +  struct capability_mp_data mpc;
       
  1095 +  struct capability_header *hdr;
       
  1096    u_char action;
       
  1097    struct bgp *bgp;
       
  1098    afi_t afi;
       
  1099 @@ -2001,7 +2000,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
       
  1100    end = pnt + length;
       
  1101  
       
  1102    while (pnt < end)
       
  1103 -    {
       
  1104 +    {      
       
  1105        /* We need at least action, capability code and capability length. */
       
  1106        if (pnt + 3 > end)
       
  1107          {
       
  1108 @@ -2009,12 +2008,9 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
       
  1109            bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
  1110            return -1;
       
  1111          }
       
  1112 -
       
  1113        action = *pnt;
       
  1114 -
       
  1115 -      /* Fetch structure to the byte stream. */
       
  1116 -      memcpy (&cap, pnt + 1, sizeof (struct capability));
       
  1117 -
       
  1118 +      hdr = (struct capability_header *)(pnt + 1);
       
  1119 +      
       
  1120        /* Action value check.  */
       
  1121        if (action != CAPABILITY_ACTION_SET
       
  1122  	  && action != CAPABILITY_ACTION_UNSET)
       
  1123 @@ -2027,77 +2023,77 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
       
  1124  
       
  1125        if (BGP_DEBUG (normal, NORMAL))
       
  1126  	zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
       
  1127 -		   peer->host, action, cap.code, cap.length);
       
  1128 +		   peer->host, action, hdr->code, hdr->length);
       
  1129  
       
  1130        /* Capability length check. */
       
  1131 -      if (pnt + (cap.length + 3) > end)
       
  1132 +      if ((pnt + hdr->length + 3) > end)
       
  1133          {
       
  1134            zlog_info ("%s Capability length error", peer->host);
       
  1135            bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
       
  1136            return -1;
       
  1137          }
       
  1138  
       
  1139 +      /* Fetch structure to the byte stream. */
       
  1140 +      memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
       
  1141 +
       
  1142        /* We know MP Capability Code. */
       
  1143 -      if (cap.code == CAPABILITY_CODE_MP)
       
  1144 +      if (hdr->code == CAPABILITY_CODE_MP)
       
  1145          {
       
  1146 -	  afi = ntohs (cap.mpc.afi);
       
  1147 -	  safi = cap.mpc.safi;
       
  1148 +	  afi = ntohs (mpc.afi);
       
  1149 +	  safi = mpc.safi;
       
  1150  
       
  1151            /* Ignore capability when override-capability is set. */
       
  1152            if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
       
  1153  	    continue;
       
  1154 -
       
  1155 +          
       
  1156 +          if (!bgp_afi_safi_valid_indices (afi, &safi))
       
  1157 +            {
       
  1158 +              if (BGP_DEBUG (normal, NORMAL))
       
  1159 +                zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid",
       
  1160 +                            peer->host, afi, safi);
       
  1161 +              continue;
       
  1162 +            }
       
  1163 +          
       
  1164  	  /* Address family check.  */
       
  1165 -	  if ((afi == AFI_IP 
       
  1166 -	       || afi == AFI_IP6)
       
  1167 -	      && (safi == SAFI_UNICAST 
       
  1168 -		  || safi == SAFI_MULTICAST 
       
  1169 -		  || safi == BGP_SAFI_VPNV4))
       
  1170 -	    {
       
  1171 -	      if (BGP_DEBUG (normal, NORMAL))
       
  1172 -		zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
       
  1173 -			   peer->host,
       
  1174 -			   action == CAPABILITY_ACTION_SET 
       
  1175 -			   ? "Advertising" : "Removing",
       
  1176 -			   ntohs(cap.mpc.afi) , cap.mpc.safi);
       
  1177 -		  
       
  1178 -	      /* Adjust safi code. */
       
  1179 -	      if (safi == BGP_SAFI_VPNV4)
       
  1180 -		safi = SAFI_MPLS_VPN;
       
  1181 -	      
       
  1182 -	      if (action == CAPABILITY_ACTION_SET)
       
  1183 -		{
       
  1184 -		  peer->afc_recv[afi][safi] = 1;
       
  1185 -		  if (peer->afc[afi][safi])
       
  1186 -		    {
       
  1187 -		      peer->afc_nego[afi][safi] = 1;
       
  1188 -		      bgp_announce_route (peer, afi, safi);
       
  1189 -		    }
       
  1190 -		}
       
  1191 -	      else
       
  1192 -		{
       
  1193 -		  peer->afc_recv[afi][safi] = 0;
       
  1194 -		  peer->afc_nego[afi][safi] = 0;
       
  1195 -
       
  1196 -		  if (peer_active_nego (peer))
       
  1197 -		    bgp_clear_route (peer, afi, safi);
       
  1198 -		  else
       
  1199 -		    BGP_EVENT_ADD (peer, BGP_Stop);
       
  1200 -		} 
       
  1201 -	    }
       
  1202 +          if (BGP_DEBUG (normal, NORMAL))
       
  1203 +            zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
       
  1204 +                       peer->host,
       
  1205 +                       action == CAPABILITY_ACTION_SET 
       
  1206 +                       ? "Advertising" : "Removing",
       
  1207 +                       ntohs(mpc.afi) , mpc.safi);
       
  1208 +              
       
  1209 +          if (action == CAPABILITY_ACTION_SET)
       
  1210 +            {
       
  1211 +              peer->afc_recv[afi][safi] = 1;
       
  1212 +              if (peer->afc[afi][safi])
       
  1213 +                {
       
  1214 +                  peer->afc_nego[afi][safi] = 1;
       
  1215 +                  bgp_announce_route (peer, afi, safi);
       
  1216 +                }
       
  1217 +            }
       
  1218 +          else
       
  1219 +            {
       
  1220 +              peer->afc_recv[afi][safi] = 0;
       
  1221 +              peer->afc_nego[afi][safi] = 0;
       
  1222 +
       
  1223 +              if (peer_active_nego (peer))
       
  1224 +                bgp_clear_route (peer, afi, safi);
       
  1225 +              else
       
  1226 +                BGP_EVENT_ADD (peer, BGP_Stop);
       
  1227 +            }
       
  1228          }
       
  1229        else
       
  1230          {
       
  1231            zlog_warn ("%s unrecognized capability code: %d - ignored",
       
  1232 -                     peer->host, cap.code);
       
  1233 +                     peer->host, hdr->code);
       
  1234          }
       
  1235 -      pnt += cap.length + 3;
       
  1236 +      pnt += hdr->length + 3;
       
  1237      }
       
  1238    return 0;
       
  1239  }
       
  1240  
       
  1241  /* Dynamic Capability is received. */
       
  1242 -static void
       
  1243 +int
       
  1244  bgp_capability_receive (struct peer *peer, bgp_size_t size)
       
  1245  {
       
  1246    u_char *pnt;
       
  1247 @@ -2130,7 +2126,7 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
       
  1248      }
       
  1249  
       
  1250    /* Parse packet. */
       
  1251 -  ret = bgp_capability_msg_parse (peer, pnt, size);
       
  1252 +  return bgp_capability_msg_parse (peer, pnt, size);
       
  1253  }
       
  1254  
       
  1255  /* BGP read utility function. */
       
  1256 diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
       
  1257 index 1e21c74..3eeb5f9 100644
       
  1258 --- bgpd/bgp_vty.c
       
  1259 +++ bgpd/bgp_vty.c
       
  1260 @@ -6681,14 +6681,14 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
       
  1261  
       
  1262  	  vty_out (vty, "4 ");
       
  1263  
       
  1264 -	  vty_out (vty, "%5d %7d %7d %8d %4d %4ld ",
       
  1265 +	  vty_out (vty, "%5d %7d %7d %8d %4d %4lu ",
       
  1266  		   peer->as,
       
  1267  		   peer->open_in + peer->update_in + peer->keepalive_in
       
  1268  		   + peer->notify_in + peer->refresh_in + peer->dynamic_cap_in,
       
  1269  		   peer->open_out + peer->update_out + peer->keepalive_out
       
  1270  		   + peer->notify_out + peer->refresh_out
       
  1271  		   + peer->dynamic_cap_out,
       
  1272 -		   0, 0, peer->obuf->count);
       
  1273 +		   0, 0, (unsigned long)peer->obuf->count);
       
  1274  
       
  1275  	  vty_out (vty, "%8s", 
       
  1276  		   peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
       
  1277 @@ -7403,7 +7403,7 @@ bgp_show_peer (struct vty *vty, struct peer *p)
       
  1278    /* Packet counts. */
       
  1279    vty_out (vty, "  Message statistics:%s", VTY_NEWLINE);
       
  1280    vty_out (vty, "    Inq depth is 0%s", VTY_NEWLINE);
       
  1281 -  vty_out (vty, "    Outq depth is %ld%s", p->obuf->count, VTY_NEWLINE);
       
  1282 +  vty_out (vty, "    Outq depth is %lu%s", (unsigned long)p->obuf->count, VTY_NEWLINE);
       
  1283    vty_out (vty, "                         Sent       Rcvd%s", VTY_NEWLINE);
       
  1284    vty_out (vty, "    Opens:         %10d %10d%s", p->open_out, p->open_in, VTY_NEWLINE);
       
  1285    vty_out (vty, "    Notifications: %10d %10d%s", p->notify_out, p->notify_in, VTY_NEWLINE);
       
  1286 diff --git a/lib/log.c b/lib/log.c
       
  1287 index cbf76af..ff47cae 100644
       
  1288 --- lib/log.c
       
  1289 +++ lib/log.c
       
  1290 @@ -769,7 +769,7 @@ mes_lookup (struct message *meslist, int max, int index)
       
  1291        {
       
  1292  	if (meslist->key == index)
       
  1293  	  {
       
  1294 -	    zlog_warn("message index %d [%s] found in position %d (max is %d)",
       
  1295 +	    zlog_debug ("message index %d [%s] found in position %d (max is %d)",
       
  1296  		      index, meslist->str, i, max);
       
  1297  	    return meslist->str;
       
  1298  	  }