trema/trema-edge

View on GitHub
src/lib/packet_info.c

Summary

Maintainability
Test Coverage
/*
 * Copyright (C) 2008-2013 NEC Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


#include <assert.h>
#include "checks.h"
#include "packet_info.h"
#include "wrapper.h"


void
free_packet_info( buffer *buf ) {
  die_if_NULL( buf );
  die_if_NULL( buf->user_data );

  xfree( buf->user_data );
  buf->user_data = NULL;
  buf->user_data_free_function = NULL;
}


void
calloc_packet_info( buffer *buf ) {
  die_if_NULL( buf );

  if ( buf->user_data != NULL && buf->user_data_free_function != NULL ) {
    ( *buf->user_data_free_function )( buf );
    assert( buf->user_data == NULL );
    assert( buf->user_data_free_function == NULL );
  }

  void *user_data = xcalloc( 1, sizeof( packet_info ) );
  assert( user_data != NULL );

  memset( user_data, 0, sizeof( packet_info ) );

  buf->user_data = user_data;
  buf->user_data_free_function = free_packet_info;
}


void
copy_packet_info( buffer *dst, const buffer *src ) {
  die_if_NULL( src );
  die_if_NULL( dst );
  
  if ( src->user_data == NULL ) {
    return;
  }
  calloc_packet_info( dst );
  memcpy( dst->user_data, src->user_data, sizeof( packet_info ) );

  packet_info *info = ( packet_info* ) dst->user_data;
  ssize_t offset = ( ( char * ) dst->data - ( char * ) src->data);

  if(info->l2_header      != NULL) info->l2_header      = ( char * ) info->l2_header      + offset;
  if(info->l2_payload     != NULL) info->l2_payload     = ( char * ) info->l2_payload     + offset;
  if(info->l3_header      != NULL) info->l3_header      = ( char * ) info->l3_header      + offset;
  if(info->l3_payload     != NULL) info->l3_payload     = ( char * ) info->l3_payload     + offset;
  if(info->l4_header      != NULL) info->l4_header      = ( char * ) info->l4_header      + offset;
  if(info->l4_payload     != NULL) info->l4_payload     = ( char * ) info->l4_payload     + offset;
  if(info->l2_vlan_header != NULL) info->l2_vlan_header = ( char * ) info->l2_vlan_header + offset;
  if(info->l2_pbb_header  != NULL) info->l2_pbb_header  = ( char * ) info->l2_pbb_header  + offset;
  if(info->l2_mpls_header != NULL) info->l2_mpls_header = ( char * ) info->l2_mpls_header + offset;
}


packet_info
get_packet_info( const buffer *frame ) {
  die_if_NULL( frame );

  packet_info info;

  if ( frame->user_data != NULL ) {
    info = *( packet_info * ) frame->user_data;
  }
  else {
    memset( &info, 0, sizeof( info ) );
  }

  return info;
}


static bool
if_packet_type( const buffer *frame, const uint32_t type ) {
  die_if_NULL( frame );
  packet_info packet_info = get_packet_info( frame );
  return ( ( packet_info.format & type ) == type );
}


bool
packet_type_eth_dix( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, ETH_DIX );
}


bool
packet_type_eth_vtag( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, ETH_8021Q );
}


bool
packet_type_eth_raw( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, ETH_8023_RAW );
}


bool
packet_type_eth_llc( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, ETH_8023_LLC );
}


bool
packet_type_ether( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, ETH_DIX ) |
           if_packet_type( frame, ETH_8023_RAW ) |
           if_packet_type( frame, ETH_8023_LLC ) |
           if_packet_type( frame, ETH_8023_SNAP ) );
}


bool
packet_type_eth_snap( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, ETH_8023_SNAP );
}


bool
packet_type_eth_mpls( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, MPLS );
}


bool
packet_type_eth_pbb( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, PBB );
}


bool
packet_type_arp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_ARP );
}


bool
packet_type_ipv4( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV4 );
}


bool
packet_type_ipv6( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV6 );
}


bool
packet_type_lldp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_LLDP );
}


bool
packet_type_icmpv4( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_ICMPV4 );
}


bool
packet_type_icmpv6( const buffer *frame) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_ICMPV6 );
}


bool
packet_type_igmp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IGMP );
}


bool
packet_type_ipv4_tcp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV4 | TP_TCP );
}


bool
packet_type_ipv6_tcp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV6 | TP_TCP );
}


bool
packet_type_ipv4_udp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV4 | TP_UDP );
}


bool
packet_type_ipv6_udp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV6 | TP_UDP );
}


bool
packet_type_ipv4_sctp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV4 | TP_SCTP );
}


bool
packet_type_ipv6_sctp( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV6 | TP_SCTP );
}


bool
packet_type_ipv4_etherip( const buffer *frame ) {
  die_if_NULL( frame );
  return if_packet_type( frame, NW_IPV4 | TP_ETHERIP );
}


static bool
if_arp_opcode( const buffer *frame, const uint32_t opcode ) {
  die_if_NULL( frame );
  packet_info packet_info = get_packet_info( frame );
  return ( packet_info.arp_ar_op == opcode );
}


bool
packet_type_arp_request( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_ARP ) &
           if_arp_opcode( frame, ARP_OP_REQUEST ) );
}


bool
packet_type_arp_reply( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_ARP ) &
           if_arp_opcode( frame, ARP_OP_REPLY ) );
}


static bool
if_icmpv4_type( const buffer *frame, const uint32_t type ) {
  die_if_NULL( frame );
  packet_info packet_info = get_packet_info( frame );
  return ( packet_info.icmpv4_type == type );
}


bool
packet_type_icmpv4_echo_reply( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_ICMPV4 ) &
           if_icmpv4_type( frame, ICMP_TYPE_ECHOREP ) );
}


bool
packet_type_icmpv4_dst_unreach( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_ICMPV4 ) &
           if_icmpv4_type( frame, ICMP_TYPE_UNREACH ) );
}


bool
packet_type_icmpv4_redirect( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_ICMPV4 ) &
           if_icmpv4_type( frame, ICMP_TYPE_REDIRECT ) );
}


bool
packet_type_icmpv4_echo_request( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_ICMPV4 ) &
           if_icmpv4_type( frame, ICMP_TYPE_ECHOREQ ) );
}


static bool
if_igmp_type( const buffer *frame, const uint32_t type ) {
  die_if_NULL( frame );
  packet_info packet_info = get_packet_info( frame );
  return ( packet_info.igmp_type == type );
}


bool
packet_type_igmp_membership_query( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_IGMP ) &
           if_igmp_type( frame, IGMP_TYPE_MEMBERSHIP_QUERY ) );
}


bool
packet_type_igmp_v1_membership_report( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_IGMP ) &
           if_igmp_type( frame, IGMP_TYPE_V1_MEMBERSHIP_REPORT ) );
}

bool
packet_type_igmp_v2_membership_report( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_IGMP ) &
           if_igmp_type( frame, IGMP_TYPE_V2_MEMBERSHIP_REPORT ) );
}


bool
packet_type_igmp_v2_leave_group( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_IGMP ) &
           if_igmp_type( frame, IGMP_TYPE_V2_LEAVE_GROUP ) );
}


bool
packet_type_igmp_v3_membership_report( const buffer *frame ) {
  die_if_NULL( frame );
  return ( if_packet_type( frame, NW_IGMP ) &
           if_igmp_type( frame, IGMP_TYPE_V3_MEMBERSHIP_REPORT ) );
}


/*
 * Local variables:
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * End:
 */