Example #1
0
buffer*
create_event_forward_operation_reply( enum efi_event_type type, enum efi_result result, list_element *service_list ) {
  buffer *buf = alloc_buffer_with_length( sizeof( event_forward_operation_reply ) + MESSENGER_SERVICE_NAME_LENGTH );
  event_forward_operation_reply *rep = append_back_buffer( buf, sizeof( event_forward_operation_reply ) );
  memset( rep, 0, sizeof( event_forward_operation_reply ) );

  rep->type = ( uint8_t ) type;
  rep->result = ( uint8_t ) result;

  size_t reply_head_offset = sizeof( event_forward_operation_reply );
  uint32_t n_services = 0;
  if ( service_list != NULL ) {
    for ( list_element *e = service_list; e != NULL; e = e->next ) {
      const size_t len = strlen( e->data );
      char *dst = append_back_buffer( buf, len + 1 );
      rep = ( event_forward_operation_reply * )( dst - reply_head_offset );
      reply_head_offset += len + 1;
      strcpy( dst, e->data );
      dst[ len ] = '\0';
      ++n_services;
    }
  }

  rep->n_services = htonl( n_services );
  return buf;
}
Example #2
0
buffer *
create_pcap_packet( void* pcap_header, size_t pcap_len, void* dump_header, size_t dump_len, void* data, size_t data_len ) {
  size_t length = pcap_len + dump_len + data_len;
  assert( length != 0 );
  assert( pcap_header != NULL && dump_header != NULL );

  buffer *buf = alloc_buffer_with_length( length );
  assert( buf != NULL );

  if ( pcap_header != NULL && pcap_len > 0 ) {
    void *d = append_back_buffer( buf, pcap_len );
    assert( d != NULL );
    memcpy( d, pcap_header, pcap_len );
  }

  if ( dump_header != NULL && dump_len > 0 ) {
    void *d = append_back_buffer( buf, dump_len );
    assert( d != NULL );
    memcpy( d, dump_header, dump_len );
  }

  if ( data != NULL && data_len > 0 ) {
    void *d = append_back_buffer( buf, data_len );
    assert( d != NULL );
    memcpy( d, data, data_len );
  }

  return buf;
}
Example #3
0
static buffer *
create_openflow_application_message( uint64_t *datapath_id, buffer *data ) {
  openflow_service_header_t *message;
  buffer *buf;
  void *append;
  size_t append_len = 0;

  if ( data != NULL ) {
     append_len = data->length;
  }
  buf = alloc_buffer_with_length( sizeof( openflow_service_header_t ) + append_len );
  message = append_back_buffer( buf, sizeof( openflow_service_header_t ) );
  if ( datapath_id == NULL ) {
    message->datapath_id = ~0U; // FIXME: defined invalid datapath_id
  }
  else {
    message->datapath_id = htonll( *datapath_id );
  }
  message->service_name_length = htons( 0 );
  // TODO: append ipaddress and port
  if ( append_len > 0 ) {
    append = append_back_buffer( buf, append_len );
    memcpy( append, data->data, append_len );
  }

  return buf;
}
Example #4
0
static void
read_stdin( int fd, void *data ) {
  UNUSED( data );

  char buf[ 1024 ];
  memset( buf, '\0', sizeof( buf ) );
  ssize_t ret = read( fd, buf, sizeof( buf ) );
  if ( ret < 0 ) {
    if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) {
      return;
    }

    set_readable( fd, false );

    error( "Read error ( errno = %s [%d] ).", strerror( errno ), errno );
    return;
  }
  else if ( ret == 0 ) {
    return;
  }

  if ( stdin_read_buffer == NULL ) {
    set_readable( fd, false );

    error( "Read buffer is not allocated yet" );
    return;
  }

  char *p = append_back_buffer( stdin_read_buffer, ( size_t ) ret );
  memcpy( p, buf, ( size_t ) ret );
  char *lf = find_character( stdin_read_buffer->data, stdin_read_buffer->length, '\n' );
  while ( lf != NULL ) {
    size_t length = ( size_t ) ( lf - ( char * ) stdin_read_buffer->data );
    if ( length > 0 ) {
      buffer *string = alloc_buffer_with_length( length );
      p = append_back_buffer( string, length );
      memcpy( p, stdin_read_buffer->data, length );
      relay_string( string );
      free_buffer( string );
      remove_front_buffer( stdin_read_buffer, length + 1 );
    }
    else {
      if ( stdin_read_buffer->length > 0 ) {
        remove_front_buffer( stdin_read_buffer, 1 );
      }
    }
    if ( stdin_read_buffer->length == 0 ) {
      break;
    }
    lf = find_character( stdin_read_buffer->data, stdin_read_buffer->length, '\n' );
  }

  // truncate head room manually
  buffer *truncated = duplicate_buffer( stdin_read_buffer );
  free_buffer( stdin_read_buffer );
  stdin_read_buffer = truncated;
}
Example #5
0
static void
recv_syslog_message( int fd, void *data ) {
  UNUSED( data );

  char buf[ 1024 ];
  ssize_t ret = read( fd, buf, sizeof( buf ) );

  if ( ret < 0 ) {
    if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) {
      return;
    }

    error( "Receive error ( errno = %s [%d] ).", strerror( errno ), errno );

    set_readable( fd, false );
    delete_fd_handler( fd );
    return;
  }

  buffer *message = alloc_buffer_with_length( ( size_t ) ret );
  void *p = append_back_buffer( message, ( size_t ) ret );
  memcpy( p, buf, ( size_t ) ret );

  relay_syslog_message( message );

  free_buffer( message );
}
Example #6
0
static void
handle_delete_filter_request( const messenger_context_handle *handle, delete_packetin_filter_request *request ) {
  assert( handle != NULL );
  assert( request != NULL );

  buffer *buf = alloc_buffer_with_length( sizeof( delete_packetin_filter_reply ) );
  delete_packetin_filter_reply *reply = append_back_buffer( buf, sizeof( delete_packetin_filter_reply ) );
  reply->status = PACKETIN_FILTER_OPERATION_SUCCEEDED;
  reply->n_deleted = 0;

  struct ofp_match match;
  ntoh_match( &match, &request->criteria.match );
  uint16_t priority = ntohs( request->criteria.priority );
  if ( request->flags & PACKETIN_FILTER_FLAG_MATCH_STRICT ) {
    int n_deleted = delete_packetin_match_entry( match, priority, request->criteria.service_name );
    reply->n_deleted += ( uint32_t ) n_deleted;
  }
  else {
    map_match_table( match, delete_filter_walker, buf );
  }
  reply->n_deleted = htonl( reply->n_deleted );

  bool ret = send_reply_message( handle, MESSENGER_DELETE_PACKETIN_FILTER_REPLY, buf->data, buf->length );
  free_buffer( buf );
  if ( ret == false ) {
    error( "Failed to send a dump filter reply." );
  }
}
Example #7
0
/*
 * Creates a Vendor Request message. This message can be used
 * to facilitate sending of vendor-defined arbitrary data.
 *
 * @overload initialize
 *   @example
 *     Vendor.new
 *
 * @overload initialize(options)
 *   @example
 *     Vendor.new(
 *       :vendor => 0x3000,
 *       :data => "deadbeef".unpack( "C*" ),
 *       :transaction_id => 123
 *     )
 *
 *   @param [Hash] options
 *     the options to create a message with.
 *   @option options [Number] :xid
 *   @option options [Number] :transaction_id
 *     an unsigned 32bit integer number associated with this message.
 *     if not specified, an auto-generated value is set.
 *   @option options [Number] :vendor
 *     the vendor identifier. If MSB is zero low order bytes are IEEE OUI. Otherwise defined by openflow.
 *   @option options [Array] :data
 *     a String that holds vendor's defined arbitrary length data.
 *
 * @raise [ArgumentError] if transaction ID is not an unsigned 32-bit integer.
 * @raise [ArgumentError] if user data is not an array of bytes.
 * @raise [TypeError] if options is not a hash.
 * @return [Vendor]
 */
static VALUE
vendor_init( int argc, VALUE *argv, VALUE self ) {
  buffer *vendor = NULL;
  Data_Get_Struct( self, buffer, vendor );
  VALUE options = Qnil;

  if ( rb_scan_args( argc, argv, "01", &options ) == 0 ) {
    set_xid( vendor, get_transaction_id() );
  }
  else {
    if ( options == Qnil ) {
      set_xid( vendor, get_transaction_id() );
    }
    else {
      if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) {
        Check_Type( options, T_HASH );
        VALUE tmp = Qnil;
        VALUE xid = Qnil;

        tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) );
        if ( tmp != Qnil ) {
          xid = tmp;
        }
        tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) );
        if ( tmp != Qnil ) {
          xid = tmp;
        }

        if ( xid != Qnil ) {
          validate_xid( xid );
          set_xid( vendor, ( uint32_t ) NUM2UINT( xid ) );
        }
        else {
          set_xid( vendor, get_transaction_id() );
        }

        tmp = rb_hash_aref( options, ID2SYM( rb_intern( "vendor" ) ) );
        if ( tmp != Qnil ) {
          ( ( struct ofp_vendor_header * ) ( vendor->data ) )->vendor = htonl( ( uint32_t ) NUM2UINT( tmp ) );
        }

        tmp = rb_hash_aref( options, ID2SYM( rb_intern( "data" ) ) );
        if ( tmp != Qnil ) {
          Check_Type( tmp, T_ARRAY );
          uint16_t length = ( uint16_t ) RARRAY_LEN( tmp );
          append_back_buffer( vendor, length );
          set_length( vendor, length );
          uint8_t *data = ( uint8_t * ) ( ( char * ) vendor->data + sizeof( struct ofp_vendor_header ) );
          int i;
          for ( i = 0; i < length; i++ ) {
            data[ i ] = ( uint8_t ) FIX2INT( RARRAY_PTR( tmp )[ i ] );
          }
        }
      }
    }
  }

  return self;
}
Example #8
0
static VALUE
vendor_stats_request_alloc( VALUE klass ) {
  uint16_t length = 128;
  buffer *body = alloc_buffer_with_length( length );
  void *p = append_back_buffer( body, length );
  memset( p, 0xaf, length );
  buffer *vendor_stats_request = create_vendor_stats_request( MY_TRANSACTION_ID, VENDOR_STATS_FLAG, VENDOR_ID, body );
  return Data_Wrap_Struct( klass, NULL, free_buffer, vendor_stats_request );
}
Example #9
0
File: ether.c Project: n-tada/trema
void
fill_ether_padding( buffer *buf ) {
  assert( buf != NULL );

  if ( buf->length + ETH_FCS_LENGTH < ETH_MINIMUM_LENGTH ) {
    size_t padding_length = ETH_MINIMUM_LENGTH - buf->length - ETH_FCS_LENGTH;
    debug( "Adding %u octets padding ( original frame length = %u ).", buf->length, padding_length );
    append_back_buffer( buf, padding_length );
  }
}
Example #10
0
static void
receive_frame( int fd, void *user_data ) {
  UNUSED( fd );

  ether_device *device = user_data;
  assert( device != NULL );

  if ( !device->status.up ) {
    return;
  }

  if ( get_max_packet_buffers_length( device->recv_queue ) <= get_packet_buffers_length( device->recv_queue ) ) {
    warn( "Receive queue is full ( device = %s, usage = %u/%u ).", device->name,
          get_packet_buffers_length( device->recv_queue ), get_max_packet_buffers_length( device->recv_queue ) );
    return;
  }

  unsigned int count = 0;
  const unsigned int max_queue_length = get_max_packet_buffers_length( device->recv_queue );
  const unsigned int max_loop_count = max_queue_length < 256 ? max_queue_length : 256;
  while ( count < max_loop_count ) {
    buffer *frame = get_buffer_from_free_buffers( device->recv_queue );
    if ( frame == NULL ) {
      warn( "Failed to retrieve a receive buffer ( device = %s, queue usage = %u/%u ).", device->name,
            get_packet_buffers_length( device->recv_queue ), max_queue_length );
      frame = device->recv_buffer; // Use recv_buffer as a trash.
    }
    append_back_buffer( frame, device->mtu );

    ssize_t length = recv( device->fd, frame->data, frame->length, MSG_DONTWAIT );
    assert( length != 0 );
    if ( length < 0 ) {
      if ( frame != device->recv_buffer ) {
        mark_packet_buffer_as_used( device->recv_queue, frame );
      }
      if ( ( errno == EINTR ) || ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) || ( errno == ENETDOWN ) ) {
        break;
      }
      char error_string[ ERROR_STRING_SIZE ];
      error( "Receive error ( device = %s, errno = %s [%d] ).",
             device->name, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno );
      break;
    }
    if ( frame != device->recv_buffer ) {
      frame->length = ( size_t ) length;
      enqueue_packet_buffer( device->recv_queue, frame );
    }
    else {
      reset_buffer( frame );
    }
    count++;
  }

  handle_received_frames( device );
}
Example #11
0
static void
recv_from_secure_channel( int fd, void *user_data ) {
  UNUSED( fd );
  UNUSED( user_data );

  // all queued messages should be processed before receiving new messages from remote
  if ( recv_queue->length > 0 ) {
    return;
  }

  if ( fragment_buf == NULL ) {
    fragment_buf = alloc_buffer_with_length( RECEIVE_BUFFFER_SIZE );
  }

  size_t remaining_length = RECEIVE_BUFFFER_SIZE - fragment_buf->length;
  char *recv_buf = ( char * ) fragment_buf->data + fragment_buf->length;
  ssize_t recv_length = read( connection.fd, recv_buf, remaining_length );
  if ( recv_length < 0 ) {
    if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) {
      return;
    }
    error( "Receive error ( errno = %s [%d] ).", strerror( errno ), errno );
    return;
  }
  if ( recv_length == 0 ) {
    debug( "Connection closed by peer." );
    disconnected();
    reconnect( NULL );
    return;
  }
  fragment_buf->length += ( size_t ) recv_length;

  size_t read_total = 0;
  while ( fragment_buf->length >= sizeof( struct ofp_header ) ) {
    struct ofp_header *header = fragment_buf->data;
    uint16_t message_length = ntohs( header->length );
    if ( message_length > fragment_buf->length ) {
      break;
    }
    buffer *message = alloc_buffer_with_length( message_length );
    char *p = append_back_buffer( message, message_length );
    memcpy( p, fragment_buf->data, message_length );
    remove_front_buffer( fragment_buf, message_length );
    enqueue_message( recv_queue, message );
    read_total += message_length;
  }

  // remove headroom manually for next call
  if ( read_total > 0 ) {
    memmove( ( char * ) fragment_buf->data - read_total, fragment_buf->data, fragment_buf->length );
    fragment_buf->data = ( char * ) fragment_buf->data - read_total;
  }

  while ( recv_message_from_secure_channel() == true );
}
Example #12
0
File: error.c Project: nhst/trema
/*
 * @overload initialize(transaction_id=nil, type=OFPET_HELLO_FAILED, code=OFPHFC_INCOMPATIBLE, user_data=nil)
 *
 * @param [Number] transaction_id
 *   a positive number, not recently attached to any previous pending commands to
 *   guarantee message integrity auto-generated if not specified.
 *
 * @param [Number] type
 *   a command or action that failed. Defaults to +OFPET_HELLO_FAILED+ if 
 *   not specified.
 *
 * @param [Number] code
 *   the reason of the failed type error. Defaults to +OFPHFC_INCOMPATIBLE+ if 
 *   not specified.
 *
 * @param [String] user_data
 *   a more user friendly explanation of the error. Defaults to nil if not 
 *   specified.
 *
 * @example Instantiate with type and code
 *   Error.new(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE)
 *
 * @example Instantiate with transaction_id, type and code.
 *   Error.new(1234, OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR)
 *
 * @example Instantiate with transaction_id, type, code, user_data
 *   Error.new(6789, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_EMERG_TIMEOUT, "this is a test") 
 *
 * @raise [ArgumentError] if transaction id is negative.
 * @raise [ArgumentError] if user data is not a string.
 *
 * @return [Error] 
 *   an object that encapsulates the +OFPT_ERROR+ openflow message.
 */
static VALUE
error_new( int argc, VALUE *argv, VALUE klass ) {
  buffer *data = NULL;
  uint32_t xid = get_transaction_id();
  VALUE xid_r;
  VALUE user_data;
  VALUE type_r;
  VALUE code_r;
  uint16_t type;
  uint16_t code;

  switch ( argc ) {
    case 2:
      // type, code specified.
      rb_scan_args( argc, argv, "02", &type_r, &code_r );
      type = ( uint16_t ) NUM2UINT( type_r );
      code = ( uint16_t ) NUM2UINT( code_r );
      break;
    case 3:
      // transaction id, type, code specified.
      rb_scan_args( argc, argv, "03", &xid_r, &type_r, &code_r );
      if ( NUM2INT( xid_r ) < 0 ) {
        rb_raise( rb_eArgError, "Transaction ID must be >= 0" );
      }
      xid = ( uint32_t ) NUM2UINT( xid_r );
      type = ( uint16_t ) NUM2UINT( type_r );
      code = ( uint16_t ) NUM2UINT( code_r );
      break;
    case 4:
      rb_scan_args( argc, argv, "04", &xid_r, &type_r, &code_r, &user_data );
      if ( NUM2INT( xid_r ) < 0 ) {
        rb_raise( rb_eArgError, "Transaction ID must be >= 0" );
      }
      if ( rb_obj_is_kind_of( user_data, rb_cString ) == Qfalse ) {
        rb_raise( rb_eArgError, "User data must be a string" );
      }
      xid = ( uint32_t ) NUM2UINT( xid_r );
      type = ( uint16_t ) NUM2UINT( type_r );
      code = ( uint16_t ) NUM2UINT( code_r );
      uint16_t length = ( u_int16_t ) RSTRING_LEN( user_data );
      data = alloc_buffer_with_length( length );
      void *p = append_back_buffer( data, length );
      memcpy( p, RSTRING_PTR( user_data ), length );
      break;
    default:
      type = OFPET_HELLO_FAILED;
      code = OFPHFC_INCOMPATIBLE;
      break;
  }
  buffer *error = create_error( xid, type, code, data );
  if ( data != NULL ) {
    free_buffer( data );
  }
  return Data_Wrap_Struct( klass, NULL, free_buffer, error );
}
Example #13
0
static void
relay_string( buffer *string ) {
  // retrieve current time
  struct timespec now;
  if ( clock_gettime( CLOCK_REALTIME, &now ) == -1 ) {
    error( "Failed to retrieve system-wide real-time clock ( %s [%d] ).", strerror( errno ), errno );
    return;
  }

  // allocate buffer
  char *service_name = xstrdup( get_trema_name() );
  uint16_t service_name_length = ( uint16_t ) ( strlen( service_name ) + 1 );
  size_t buffer_length = sizeof( message_dump_header ) + service_name_length + sizeof( syslog_dump_header ) + string->length + 1;
  buffer *buf = alloc_buffer_with_length( buffer_length );

  // syslog_dump_header + service_name
  message_dump_header *mdh = append_back_buffer( buf, sizeof( message_dump_header ) );
  mdh->sent_time.sec = htonl( ( uint32_t ) now.tv_sec );
  mdh->sent_time.nsec = htonl( ( uint32_t ) now.tv_nsec );
  mdh->app_name_length = htons( 0 );
  mdh->service_name_length = htons( service_name_length );
  mdh->data_length = htonl( ( uint32_t ) ( sizeof( text_dump_header ) + string->length + 1 ) );
  void *svn = append_back_buffer( buf, service_name_length );
  memcpy( svn, service_name, service_name_length );
  xfree( service_name );

  // text_dump_header
  text_dump_header *tdh = append_back_buffer( buf, sizeof( text_dump_header ) );
  tdh->sent_time.sec = htonl( ( uint32_t ) now.tv_sec );
  tdh->sent_time.nsec = htonl( ( uint32_t ) now.tv_nsec );

  // message
  void *p = append_back_buffer( buf, string->length + 1 );
  memset( p, '\0', string->length + 1 );
  memcpy( p, string->data, string->length );

  bool ret = send_message( dump_service_name, MESSENGER_DUMP_TEXT, buf->data, buf->length );
  if ( !ret ) {
    error( "Failed to relay syslog message." );
  }
  free_buffer( buf );
}
Example #14
0
void
test_fill_ether_padding_succeeds_if_length_is_less_than_ETH_MINIMUM_LENGTH() {
  buffer *buffer = alloc_buffer_with_length( ( size_t ) ETH_MINIMUM_LENGTH - ETH_FCS_LENGTH - 1 );
  append_back_buffer( buffer, ETH_MINIMUM_LENGTH - ETH_FCS_LENGTH - 1 );

  fill_ether_padding( buffer );

  assert_int_equal ( ( int ) buffer->length, ETH_MINIMUM_LENGTH - ETH_FCS_LENGTH );

  free_buffer( buffer );
}
Example #15
0
static void
service_recv( uint16_t message_type, void *data, size_t data_len ) {
  buffer *buf;
  void *msg;

  buf = alloc_buffer_with_length( data_len );

  msg = append_back_buffer( buf, data_len );
  memcpy( msg, data, data_len );

  service_recv_from_application( message_type, buf );
}
Example #16
0
uint16_t
fill_ether_padding( buffer *buf ) {
  die_if_NULL( buf );
  size_t padding_length = 0;

  if ( buf->length + ETH_FCS_LENGTH < ETH_MINIMUM_LENGTH ) {
    padding_length = ETH_MINIMUM_LENGTH - buf->length - ETH_FCS_LENGTH;
    debug( "Adding %u octets padding ( original frame length = %u ).", 
           buf->length, padding_length );
    append_back_buffer( buf, padding_length );
  }
  return ( uint16_t ) padding_length;
}
Example #17
0
static buffer *
setup_dummy_ether_packet( size_t length ) {
  buffer *ether_buffer = alloc_buffer_with_length( length );
  alloc_packet( ether_buffer );
  append_back_buffer( ether_buffer, length );
  packet_info( ether_buffer )->l2_data.eth = ether_buffer->data;

  memcpy( ( char * ) packet_info( ether_buffer )->l2_data.eth->macda, macda, ETH_ADDRLEN );
  memcpy( ( char * ) packet_info( ether_buffer )->l2_data.eth->macsa, macsa, ETH_ADDRLEN );
  packet_info( ether_buffer )->l2_data.eth->type = htons( ETH_ETHTYPE_ARP );

  return ether_buffer;
}
Example #18
0
VALUE
echo_init( int argc, VALUE *argv, VALUE self ) {
  buffer *echo = NULL;
  Data_Get_Struct( self, buffer, echo );
  VALUE options = Qnil;

  if ( rb_scan_args( argc, argv, "01", &options ) == 0 ) {
    set_xid( echo, get_transaction_id() );
  }
  else {
    if ( options == Qnil ) {
      set_xid( echo, get_transaction_id() );
    }
    else if ( rb_obj_is_kind_of( options, rb_cInteger ) == Qtrue ) {
      validate_xid( options );
      set_xid( echo, ( uint32_t ) NUM2UINT( options ) );
    }
    else {
      Check_Type( options, T_HASH );
      VALUE tmp = Qnil;
      VALUE xid = Qnil;

      tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) );
      if ( tmp != Qnil ) {
        xid = tmp;
      }
      tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) );
      if ( tmp != Qnil ) {
        xid = tmp;
      }
      if ( xid != Qnil ) {
        validate_xid( xid );
        set_xid( echo, ( uint32_t ) NUM2UINT( xid ) );
      }
      else {
        set_xid( echo, get_transaction_id() );
      }

      VALUE user_data = rb_hash_aref( options, ID2SYM( rb_intern( "user_data" ) ) );
      if ( user_data != Qnil ) {
        Check_Type( user_data, T_STRING );
        uint16_t length = ( uint16_t ) RSTRING_LEN( user_data );
        append_back_buffer( echo, length );
        set_length( echo, ( uint16_t ) ( sizeof( struct ofp_header ) + length ) );
        memcpy( ( char * ) echo->data + sizeof( struct ofp_header ), RSTRING_PTR( user_data ), length );
      }
    }
  }

  return self;
}
Example #19
0
/*
 * @overload initialize(options)
 *   @example
 *     Error.new(
 *       :type => OFPET_BAD_REQUEST,
 *       :code => OFPBRC_BAD_TYPE,
 *     )
 *     Error.new(
 *       :type => OFPET_BAD_REQUEST,
 *       :code => OFPBRC_BAD_TYPE,
 *       :transcation_id => 123
 *     )
 *     Error.new(
 *       :type => OFPET_BAD_REQUEST,
 *       :code => OFPBRC_BAD_TYPE,
 *       :transcation_id => 123
 *       :data => "Error!!"
 *     )
 *   @param [Hash] options
 *     the options to create a message with.
 *   @option options [Number] :type
 *     a command or action that failed.
 *   @option options [Number] :code
 *     the reason of the failed type error.
 *   @option options [String] :data
 *     a more user friendly explanation of the error. Defaults to nil
 *     if not specified.
 *   @option options [Number] :xid
 *   @option options [Number] :transaction_id
 *     An unsigned 32bit integer number associated with this message.
 *     If not specified, an auto-generated value is set.
 *   @raise [ArgumentError] if transaction ID is not an unsigned 32bit integer.
 *   @raise [ArgumentError] if type and code are not supplied.
 *   @raise [ArgumentError] if user data is not a string.
 *   @raise [TypeError] if options is not a hash.
 *   @return [Error]
 */
static VALUE
error_init( int argc, VALUE *argv, VALUE self ) {
  buffer *error = NULL;
  Data_Get_Struct( self, buffer, error );
  VALUE options;

  if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) {
    Check_Type( options, T_HASH );
    VALUE tmp = Qnil;

    tmp = rb_hash_aref( options, ID2SYM( rb_intern( "type" ) ) );
    if ( tmp != Qnil ) {
      ( ( struct ofp_error_msg * ) error->data )->type = htons( ( uint16_t ) NUM2UINT( tmp ) );
    }
    else {
      rb_raise( rb_eArgError, "Type is a mandatory option" );
    }

    tmp = rb_hash_aref( options, ID2SYM( rb_intern( "code" ) ) );
    if ( tmp != Qnil ) {
      ( ( struct ofp_error_msg * ) error->data )->code = htons( ( uint16_t ) NUM2UINT( tmp ) );
    }
    else {
      rb_raise( rb_eArgError, "Code is a mandatory option" );
    }

    VALUE xid = Qnil;
    tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) );
    if ( tmp != Qnil ) {
      xid = tmp;
    }
    tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) );
    if ( tmp != Qnil ) {
      xid = tmp;
    }
    if ( xid != Qnil ) {
      validate_xid( xid );
      set_xid( error, ( uint32_t ) NUM2UINT( xid ) );
    }
    else {
      set_xid( error, get_transaction_id() );
    }

    VALUE data = rb_hash_aref( options, ID2SYM( rb_intern( "data" ) ) );
    if ( data != Qnil ) {
      Check_Type( data, T_STRING );
      uint16_t length = ( uint16_t ) RSTRING_LEN( data );
      append_back_buffer( error, length );
      ( ( struct ofp_header * ) ( error->data ) )->length = htons( ( uint16_t ) ( offsetof( struct ofp_error_msg, data ) + length ) );
      memcpy( ( char * ) error->data + offsetof( struct ofp_error_msg, data ), RSTRING_PTR( data ), length );
    }
Example #20
0
static void
handle_dump_filter_request( const messenger_context_handle *handle, dump_packetin_filter_request *request ) {
  assert( handle != NULL );
  assert( request != NULL );

  buffer *buf = alloc_buffer_with_length( 2048 );
  dump_packetin_filter_reply *reply = append_back_buffer( buf, offsetof( dump_packetin_filter_reply, entries ) );
  reply->status = PACKETIN_FILTER_OPERATION_SUCCEEDED;
  reply->n_entries = 0;

  struct ofp_match match;
  ntoh_match( &match, &request->criteria.match );
  uint16_t priority = ntohs( request->criteria.priority );
  if ( request->flags & PACKETIN_FILTER_FLAG_MATCH_STRICT ) {
    list_element *services = lookup_match_strict_entry( match, priority );
    while ( services != NULL ) {
      if ( strcmp( services->data, request->criteria.service_name ) == 0 ) {
        packetin_filter_entry *entry = append_back_buffer( buf, sizeof( packetin_filter_entry ) );
        reply->n_entries++;
        entry->match = request->criteria.match;
        entry->priority = request->criteria.priority;
        strncpy( entry->service_name, services->data, sizeof( entry->service_name ) );
        entry->service_name[ sizeof( entry->service_name ) - 1 ] = '\0';
      }
      services = services->next;
    }
  }
  else {
    map_match_table( match, dump_filter_walker, buf );
  }
  reply->n_entries = htonl( reply->n_entries );

  bool ret = send_reply_message( handle, MESSENGER_DUMP_PACKETIN_FILTER_REPLY, buf->data, buf->length );
  free_buffer( buf );
  if ( ret == false ) {
    error( "Failed to send a dump packetin filter reply." );
  }
}
buffer *
pack_experimenter_multipart_request( VALUE options ) {
  uint32_t xid = get_transaction_id();
  VALUE r_xid = HASH_REF( options, transaction_id );
  if ( !NIL_P( r_xid ) ) {
    xid = NUM2UINT( r_xid );
  }

  uint16_t flags = 0;
  VALUE r_flags = HASH_REF( options, flags );
  if ( !NIL_P( r_flags ) ) {
    flags = ( uint16_t ) NUM2UINT( r_flags );
  }

  uint32_t experimenter = 0;
  VALUE r_experimenter = HASH_REF( options, experimenter );
  if ( !NIL_P( r_experimenter ) ) {
    experimenter = NUM2UINT( r_experimenter );
  }

  uint32_t exp_type = 0;
  VALUE r_exp_type = HASH_REF( options, exp_type );
  if ( !NIL_P( r_exp_type ) ) {
    exp_type = NUM2UINT( r_exp_type );
  }

  VALUE r_body = HASH_REF( options, user_data );
  buffer *body = NULL;
  if ( !NIL_P( r_body ) ) {
    if ( TYPE( r_body ) == T_ARRAY ) {
      uint16_t buffer_len = ( uint16_t ) RARRAY_LEN( r_body );

      body = alloc_buffer_with_length( ( size_t ) RARRAY_LEN( r_body ) );
      append_back_buffer( body, buffer_len );
      uint8_t *buf = body->data;

        
      for ( int i = 0; i < buffer_len && i < RARRAY_LEN( r_body ); i++ ) {
        buf[ i ]= ( uint8_t ) FIX2INT( rb_ary_entry( r_body , i ) );
      }
    }
    else {
      rb_raise( rb_eTypeError, "experimenter user data must be specified as an array of bytes" );
    }
  }
  buffer *experimenter_multipart_request = create_experimenter_multipart_request( xid, flags, experimenter, exp_type, body );

  return experimenter_multipart_request;
}
buffer *
create_ovs_set_flow_format( const uint32_t transaction_id, const uint32_t format ) {
  size_t length = sizeof( ovs_set_flow_format );
  buffer *message = alloc_buffer_with_length( length );
  ovs_set_flow_format *sff = append_back_buffer( message, length );
  sff->header.version = OFP_VERSION;
  sff->header.type = OFPT_VENDOR;
  sff->header.length = htons( sizeof( ovs_set_flow_format ) );
  sff->header.xid = htonl( transaction_id );
  sff->vendor = htonl( OVS_VENDOR_ID );
  sff->subtype = htonl( OVST_SET_FLOW_FORMAT );
  sff->format = htonl( format );

  return message;
}
buffer *
create_ovs_flow_mod_table_id( const uint32_t transaction_id, const uint8_t set ) {
  uint16_t length = ( uint16_t ) sizeof( ovs_flow_mod_table_id );
  buffer *buf = alloc_buffer_with_length( length );
  ovs_flow_mod_table_id *flow_mod_table_id = append_back_buffer( buf, length );

  flow_mod_table_id->header.version = OFP_VERSION;
  flow_mod_table_id->header.type = OFPT_VENDOR;
  flow_mod_table_id->header.length = htons( length );
  flow_mod_table_id->header.xid = htonl( transaction_id );
  flow_mod_table_id->vendor = ntohl( OVS_VENDOR_ID );
  flow_mod_table_id->subtype = ntohl( OVST_FLOW_MOD_TABLE_ID );
  flow_mod_table_id->set = set;

  return buf;
}
Example #24
0
buffer *
get_switches( void ) {
  assert( dpid_table != NULL );

  buffer *buf = alloc_buffer_with_length( sizeof( uint64_t ) );

  hash_iterator iter;
  hash_entry *entry;
  init_hash_iterator( dpid_table, &iter );
  while ( ( entry = iterate_hash_next( &iter ) ) != NULL ) {
    uint64_t *dpid = append_back_buffer( buf, sizeof( uint64_t ) );
    *dpid = htonll( *( uint64_t * )( entry->value ) );
  }

  return buf;
}
Example #25
0
static size_t
write_to_buffer( void *contents, size_t size, size_t nmemb, void *user_data ) {
  debug( "Writing contents ( contents = %p, size = %zu, nmemb = %zu, user_data = %p ).",
         contents, size, nmemb, user_data );

  assert( user_data != NULL );

  size_t real_size = size * nmemb;
  buffer *buf = user_data;
  void *p = append_back_buffer( buf, real_size );
  memcpy( p, contents, real_size );

  debug( "%zu bytes data is written into buffer ( buf = %p, length = %zu ).", real_size, buf, buf->length );

  return real_size;
}
Example #26
0
static void
dump_filter_walker( struct ofp_match match, uint16_t priority, void *data, void *user_data ) {
  buffer *reply_buffer = user_data;
  assert( reply_buffer != NULL );

  dump_packetin_filter_reply *reply = reply_buffer->data;
  list_element *services = data;
  while ( services != NULL ) {
    reply->n_entries++;
    packetin_filter_entry *entry = append_back_buffer( reply_buffer, sizeof( packetin_filter_entry ) );
    hton_match( &entry->match, &match );
    entry->priority = htons( priority );
    strncpy( entry->service_name, services->data, sizeof( entry->service_name ) );
    entry->service_name[ sizeof( entry->service_name ) - 1 ] = '\0';
    services = services->next;
  }
}
Example #27
0
buffer *
r_array_to_buffer( VALUE r_array ) {
  buffer *data = NULL;

  if ( !NIL_P( r_array ) ) {
    Check_Type( r_array, T_ARRAY );
    uint32_t length = ( uint32_t ) RARRAY_LEN( r_array );

    data = alloc_buffer_with_length( length );
    append_back_buffer( data, length );
    uint8_t *data_ptr = data->data;
    for ( uint32_t i = 0; i < length; i++ ) {
      data_ptr[ i ] = ( uint8_t ) FIX2INT( RARRAY_PTR( r_array ) [ i ] );
    }
  }
  return data;
}
Example #28
0
static buffer *
setup_dummy_ether_packet( size_t length, uint16_t type ) {
  buffer *buf = alloc_buffer_with_length( length );
  alloc_packet( buf );
  append_back_buffer( buf, length );
  packet_info( buf )->l2_data.eth = buf->data;
  packet_info( buf )->ethtype = type;
  ether_header_t *ether = packet_info( buf )->l2_data.eth;
  ether->type = htons( type );

  memcpy( ( char * ) ether->macda, macda, ETH_ADDRLEN );
  memcpy( ( char * ) ether->macsa, macsa, ETH_ADDRLEN );

  packet_info( buf )->l3_data.l3 = ( char * ) packet_info( buf )->l2_data.l2 + sizeof( ether_header_t );
  vlantag_header_t *vtag = ( vlantag_header_t * ) ( ( void * ) ( ether + 1 ) );
  packet_info( buf )->vtag = vtag;

  return buf;
}
Example #29
0
static void
echo_request_interval( void *user_data ) {
  struct switch_info *sw_info = user_data;

  buffer *buf = alloc_buffer();
  echo_body *body = append_back_buffer( buf, sizeof( echo_body ) );
  body->datapath_id = htonll( switch_info.datapath_id );
  struct timespec now;
  clock_gettime( CLOCK_MONOTONIC, &now );
  body->sec = htonl( ( uint32_t ) now.tv_sec );
  body->nsec = htonl( ( uint32_t ) now.tv_nsec );
  sw_info->echo_request_xid = generate_xid();

  int err = ofpmsg_send_echorequest( sw_info, sw_info->echo_request_xid, buf );
  if ( err < 0 ) {
    switch_event_disconnected( &switch_info );
    return;
  }

  switch_set_timeout( ECHO_REPLY_TIMEOUT, echo_reply_timeout, NULL );
}
Example #30
0
static VALUE
pack_experimenter( VALUE self, VALUE actions, VALUE options ) {
  VALUE r_experimenter = HASH_REF( options, experimenter );
  VALUE r_body = Qnil;

  if ( ( r_body = HASH_REF( options, body ) ) != Qnil ) {
    Check_Type( r_body, T_ARRAY );
    uint16_t length = ( uint16_t ) RARRAY_LEN( r_body );
    buffer *body = alloc_buffer_with_length( length );
    void *p = append_back_buffer( body, length );
    for ( int i = 0; i < length; i++ ) {
      ( ( uint8_t * ) p )[ i ] = ( uint8_t ) FIX2INT( RARRAY_PTR( r_body )[ i ] );
    }
    append_action_experimenter( openflow_actions_ptr( actions ), NUM2UINT( r_experimenter ), body );
    free_buffer( body );
  }
  else {
    append_action_experimenter( openflow_actions_ptr( actions ), NUM2UINT( r_experimenter ), NULL );
  }
  return self;
}