コード例 #1
0
ファイル: bgp_t.c プロジェクト: strizhov/bgpmon-7.2.2
/* TEST: int BGP_addPathAttributeToUpdate(BGPMessage* msg, uint16_t type, uint16_t length, const uint8_t *value);
 *
*/
void
testBGP_addPathAttributeToUpdate()
{
    uint8_t flags1  = 0x40;
    uint8_t code1   = 0xFF;
    uint8_t flags2  = 0x50;
    uint8_t code2   = 0xF0;
    uint16_t length = 1;
    uint8_t value = 0xFF;

    BGPUpdate *update = (BGPUpdate*)bgpMessage->typeSpecific;
    CU_ASSERT(0 == BGP_addPathAttributeToUpdate(bgpMessage,flags1,code1,0,NULL));
    CU_ASSERT(-1 == BGP_addPathAttributeToUpdate(bgpMessage,flags1,code1,length,NULL));
    CU_ASSERT(0 == BGP_addPathAttributeToUpdate(bgpMessage,flags1,code1,length,&value));
    CU_ASSERT(NULL != update->pathAtts);
    if(NULL == update->pathAtts) {
        return;
    }
    CU_ASSERT(1 == update->totalPathAttsCount);
    CU_ASSERT(0x40 == update->pathAtts[0]->flags);
    CU_ASSERT(0xFF == update->pathAtts[0]->code);
    CU_ASSERT(1 == update->pathAtts[0]->length);
    CU_ASSERT(value == update->pathAtts[0]->value[0]);
    CU_ASSERT(1 == (BGP_PAL_LEN(update->pathAtts[0]->flags)));

    CU_ASSERT(0 == BGP_addPathAttributeToUpdate(bgpMessage,flags2,code2,length,&value));
    CU_ASSERT(2 == update->totalPathAttsCount);
    CU_ASSERT(0x50 == update->pathAtts[0]->flags);
    CU_ASSERT(0xF0 == update->pathAtts[0]->code);
    CU_ASSERT(1 == update->pathAtts[0]->length);
    CU_ASSERT(value == update->pathAtts[0]->value[0]);
    CU_ASSERT(2 == (BGP_PAL_LEN(update->pathAtts[0]->flags)));

    CU_ASSERT(0x40 == update->pathAtts[1]->flags);
    CU_ASSERT(0xFF == update->pathAtts[1]->code);
    CU_ASSERT(1 == update->pathAtts[1]->length);
    CU_ASSERT(value == update->pathAtts[1]->value[0]);
    CU_ASSERT(1 == (BGP_PAL_LEN(update->pathAtts[1]->flags)));

    return;
}
コード例 #2
0
ファイル: bgp.c プロジェクト: NLNOG/ring-bgpmon-core
/******************************************************************************
Name: BGP_calculateLength
Input: A pointer to the BGPMessage
Output: The number of bytes anticipated in the message
Author: Catherine Olschanowsky
******************************************************************************/
int
BGP_calculateLength(BGPMessage* msg, int asnLen)
{
  int i;
  // the first task should be too allocate enough space to hold the message,
  // but we don't know what that is.
  // so, the first thing we need to do is calculate how long the message
  // is going to turn out to be.
  int length_in_bytes = BGP_HEADER_LENGTH;
  if(msg->type == BGP_UPDATE){
    BGPUpdate *update = (BGPUpdate*)msg->typeSpecific;
    // withdrawn routes
    length_in_bytes += 2; // space for the length
    for(i=0;i<update->withdrawnRoutesCount;i++){
      length_in_bytes += 1; // for the length of this prefix
      length_in_bytes += update->withdrawnRoutes[i]->length/8;
      if(update->withdrawnRoutes[i]->length%8 != 0){
        length_in_bytes++;
      }
    }
    // path attributes
    length_in_bytes += 2; // space for the length
    for(i=0;i<update->totalPathAttsCount;i++){
      length_in_bytes += 2; // type
      length_in_bytes += BGP_PAL_LEN(update->pathAtts[i]->flags);
      length_in_bytes += update->pathAtts[i]->length; // value
      // one special case due to ASN4 versus ASN2
      if(update->pathAtts[i]->code == BGP_PATTR_AS_PATH){
        // AS_PATH is a well-known mandatory attribute that is composed
        // of a sequence of AS path segments.  Each AS path segment is
        // represented by a triple <path segment type, path segment
        // length, path segment value>.
        // The path segment type is a 1-octet length field with the
        // following values defined:
           // Value      Segment Type
           // 1         AS_SET: unordered set of ASes a route in the
                        // UPDATE message has traversed
           // 2         AS_SEQUENCE: ordered set of ASes a route in
                        // the UPDATE message has traversed
        // The path segment length is a 1-octet length field,
        // containing the number of ASes (not the number of octets) in
        // the path segment value field.
        // The path segment value field contains one or more AS
        // numbers, each encoded as a 2-octet length field.

        // the above text is taken from RFC 4271, however, this code must handle
        // AS_PATHs created by MRT and therefore, the ASes might be 4 bytes
        // this code is used to calculate the length of an AS_PATH assuming that
        // it is to be truncated from 4 bytes to 2 bytes -- I believe this is
        // only useful from the MRT module

        // we can calculate the length by looking at the path segment length
        // multiplying that value by 2 and subtracting it from the length in the
        // path attribute header
        if(asnLen == 2){
          // this has to be done for each segment
          int idz;
          for(idz = 1; idz < update->pathAtts[i]->length; ){
            length_in_bytes -= (update->pathAtts[i]->value[idz]*2);
            idz += update->pathAtts[i]->value[idz]*4 + 1;
          }
        }
      }
    }
    // nlri
    for(i=0;i<update->nlriCount;i++){
      length_in_bytes += 1;
      length_in_bytes += update->nlris[i]->length/8;
      if((update->nlris[i]->length%8) != 0){
        length_in_bytes += 1;
      }
    }
    msg->length = length_in_bytes;
  }else{
    // only updates are supported at this point
    return 0;
  }
  return length_in_bytes;
}
コード例 #3
0
ファイル: bgp.c プロジェクト: NLNOG/ring-bgpmon-core
/******************************************************************************
Name: BGP_serialize
Input: A pointer to the BGPMessage, 1 to translate asns to 2 bytes, 0 to leave 
       them as 4 byte ASNs
Output: A pointer to the binary message (note that msg->length is changed
        to reflect the number of bytes. (not including the header)
Author: Catherine Olschanowsky
******************************************************************************/
int    
BGP_serialize(uint8_t* bits,BGPMessage* msg, int asnLen)
{
  // currently only support update
  if(msg->type != BGP_UPDATE){
    return -1;
  }
  BGPUpdate *update = (BGPUpdate*)msg->typeSpecific;


  // i will keep our place in the message as we populate
  int i;
  // l will be used to hold the place of a length field 
  // this way we can add the bits for that section
  // before we know the length and then go back
  int lm,l; // lm is the main length for the whole message
  // idx is for loops that don't move us along inthe msg
  int idx,idy;

  // add in the BGP header
  for(i=0;i<16;i++){
    bits[i] = 0xFF;
  }
  lm = i;
  i+=2;
  bits[i]=msg->type;
  i+=1;

  // Add the withdrawn routes
  // skip the length for now
  l=i;
  i+=2;
  for(idx=0;idx<update->withdrawnRoutesCount;idx++){
    bits[i]=update->withdrawnRoutes[idx]->length;
    i+=1;
    for(idy=0;idy<update->withdrawnRoutes[idx]->length/8;idy++){
      bits[i]=update->withdrawnRoutes[idx]->prefix[idy];
      i+=1;      
    } 
    if(update->withdrawnRoutes[idx]->length%8 != 0){
      bits[i]=update->withdrawnRoutes[idx]->prefix[idy];
      i+=1;      
    }
  }
  // Add the length back in: the 2 is here because of the length of the length field
  BGP_ASSIGN_2BYTES(&bits[l],(uint16_t)(i-l-2));
 
  // Add in the path attributes
  l = i; // l marks the spot for the length
  i+=2;  // i is incremented to leave the length spot alone
  for(idx=0;idx<update->totalPathAttsCount;idx++){
    bits[i] = update->pathAtts[idx]->flags;
    i+=1;
    bits[i] = update->pathAtts[idx]->code;
    i+=1;

    // this is the base case.
    // For all attributes other than AS_PATH we don't mess with them
    // we are looking at
    // <type, length, value>
    // type is flags+code which we took care of above
    // this logic is to determine if we have a length of one or two
    if(update->pathAtts[idx]->code != BGP_PATTR_AS_PATH){
      // Path Attribute Length (PAL) length is 1
      if(1 == (BGP_PAL_LEN(update->pathAtts[idx]->flags))){
        bits[i] = (uint8_t)update->pathAtts[idx]->length;
        i+=1;
      }else{
        // Path Attribute Length (PAL) length is 2
        BGP_ASSIGN_2BYTES(&bits[i],update->pathAtts[idx]->length);
        i+=2;
      }
      // now that we have the length we just copy the value over
      // byte at a time
      for(idy=0;idy<update->pathAtts[idx]->length;idy++){
        bits[i] = update->pathAtts[idx]->value[idy];
        i+=1;
      }
    }else{
      // AS_PATH is a well-known mandatory attribute that is composed
      // of a sequence of AS path segments.  Each AS path segment is
      // represented by a triple <path segment type, path segment
      // length, path segment value>.
      // The path segment type is a 1-octet length field with the
      // following values defined:
         // Value      Segment Type
         // 1         AS_SET: unordered set of ASes a route in the
                      // UPDATE message has traversed
         // 2         AS_SEQUENCE: ordered set of ASes a route in
                      // the UPDATE message has traversed
      // The path segment length is a 1-octet length field,
      // containing the number of ASes (not the number of octets) in
      // the path segment value field.
      // The path segment value field contains one or more AS
      // numbers, each encoded as a 2-octet length field.

      // the above text is taken from RFC 4271, however, this code must handle
      // AS_PATHs created by MRT and therefore, the ASes might be 4 bytes
      // this code is used to calculate the length of an AS_PATH assuming that
      // it is to be truncated from 4 bytes to 2 bytes -- I believe this is
      // only useful from the MRT module

      // http://tools.ietf.org/html/rfc4893 describes how to properly handle 
      // 4 byte ASNs that cannot be reduced to 2 bytes, however, this is not
      // really needed as we have a simplified case. Either, we have 2 byte
      // ASNs that have been promoted to 4 byte ASNs within MRT (and can therefore,
      // be truncated) or we have a router that can handle 4 byte ASNs in which 
      // case we leave them be

      // we can calculate the length by looking at the path segment length
      // multiplying that value by 2 and subtracting it from the length in the
      // path attribute header
      
      // <type, length, value>
      // type is flags+code which we took care of above
      // this logic is to determine if we have a length of one or two
      // if the Path attribute length (PAL) length is 1
      int l2 = i; // hold the place for the length (l is already in use)
      if((BGP_PAL_LEN(update->pathAtts[idx]->flags)) == 1){
        i+=1;
      }else{
        i+=2;
      }
      // now we look into creating the value
      // <path segment type, path segment length, path segment value>
      for(idy = 0; idy < update->pathAtts[idx]->length; ){
        bits[i] = update->pathAtts[idx]->value[idy]; // path segment type
        i++; idy++;
        int psl = bits[i] = update->pathAtts[idx]->value[idy]; // path segment length
        i++; idy++;
        // need to translate to 2 byte asns
        if(asnLen == 2){
          int idz;
          for(idz = 0; (idz/4) < psl; ){
            uint32_t tmp;
            BGP_READ_4BYTES(tmp,update->pathAtts[idx]->value[idy+idz]);
            BGP_ASSIGN_2BYTES(&bits[i],(uint16_t)tmp);
            i+=2;
            idz+=4;
          }
          idy+=idz;
        // can keep asns at 4 bytes (just copy)
        }else{
          int idz;
          for(idz = 0; idz < psl; idz++){
            bits[i] = update->pathAtts[idx]->value[idy+idz];
            i+=1;
          }
          idy+=idz;
        }
      }
      // go back and add in the length of this path attribute
      if((BGP_PAL_LEN(update->pathAtts[idx]->flags)) == 1){
        bits[l2] = (uint8_t)(i-l2-1);
      }else{
        BGP_ASSIGN_2BYTES(&bits[l2],(uint16_t)(i-l2-2));
      }
    }
  }
  // Add the length back in: the 2 is here because of the length of the length field
  BGP_ASSIGN_2BYTES(&bits[l],(uint16_t)(i-l-2));

  // Add in the NLRI information
  for(idx=0; idx<update->nlriCount;idx++){
    bits[i] = update->nlris[idx]->length;
    i+=1;
    for(idy=0;idy<(update->nlris[idx]->length/8);idy++){
      bits[i] = update->nlris[idx]->prefix[idy];
      i+=1;
    }
    if(update->nlris[idx]->length%8 > 0){
      bits[i] = update->nlris[idx]->prefix[idy];
      i+=1;
    }
  }

  BGP_ASSIGN_2BYTES(&bits[lm],i);
  msg->length = i;
   
  return 0; 
  
}