Outer IP packet structure not recognized

Asked by Ashok Kumar on 2015-05-06

Hi Didier,
                  When I am trying to compress the stream of TCP/IP packets that are read using raw socket it gave me "the outer IP packet is not correct (bad checksum)" trace on the console leading my packet to go uncompressed. How could I make this TCP packet recognizable.

IP packet <DestAddr=192.168.0.30, SourceAddr=172.16.0.25, SourcePort=2425, DestPort=1256,
             Protocol=6 ToS=0, Size=1500>

#05:19:27:923309#CE: Compressing the IP packet...
[net_pkt.c:75 net_pkt_parse()] outer IP header: 1500 bytes
[net_pkt.c:77 net_pkt_parse()] outer IP header: version 4
[net_pkt.c:82 net_pkt_parse()] outer IP header: next header is of type 6
[net_pkt.c:87 net_pkt_parse()] outer IP header: next layer is of type 6
[rohc_comp.c:4608 c_get_profile_from_packet()] try to find the best profile for packet with transport protocol 6
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP/RTP' (0x0001)
[c_generic.c:715 c_generic_check_profile()] the outer IP packet is not correct (bad checksum)
[rohc_comp.c:4632 c_get_profile_from_packet()] skip profile 'IP/UDP' (0x0002) because it does not match packet
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/UDP-Lite' (0x0008)
[rohc_comp.c:4621 c_get_profile_from_packet()] skip disabled profile 'IP/ESP' (0x0003)
[c_generic.c:715 c_generic_check_profile()] the outer IP packet is not correct (bad checksum)
[rohc_comp.c:4632 c_get_profile_from_packet()] skip profile 'IP/TCP' (0x0006) because it does not match packet
[c_generic.c:715 c_generic_check_profile()] the outer IP packet is not correct (bad checksum)
[rohc_comp.c:4632 c_get_profile_from_packet()] skip profile 'IP-only' (0x0004) because it does not match packet
[rohc_comp.c:4813 rohc_comp_find_ctxt()] using profile 'Uncompressed' (0x0000)
[rohc_comp.c:4843 rohc_comp_find_ctxt()] using context CID = 0
[rohc_comp.c:1435 rohc_compress4()] compress the packet #6
[c_uncompressed.c:643 uncompressed_code_packet()] build normal packet
[c_uncompressed.c:807 uncompressed_code_normal_packet()] code normal packet (CID = 0)
[c_uncompressed.c:826 uncompressed_code_normal_packet()] small CID 0 encoded on 0 byte(s)
[c_uncompressed.c:832 uncompressed_code_normal_packet()] header length = 0, payload length = 1500
[rohc_comp.c:1563 rohc_compress4()] copy full 1499-byte payload
[rohc_comp.c:1573 rohc_compress4()] ROHC size = 1500 bytes (header = 1, payload = 1499), output buffer size = 2500
#05:19:27:924377#luchar_ComStatus=0
#05:19:27:924438#CE: ROHC packet after compression: 1500

Question information

Language:
English Edit question
Status:
Solved
For:
rohc Edit question
Assignee:
No assignee Edit question
Solved by:
Didier Barvaux
Solved:
2015-08-03
Last query:
2015-08-03
Last reply:
2015-06-03

Hello,

> When I am trying to compress the stream of TCP/IP packets that
> are read using raw socket it gave me "the outer IP packet is not
> correct (bad checksum)" trace on the console leading my packet
> to go uncompressed. How could I make this TCP packet recognizable.

The simplest solution is to make the IP checksum correct.

If you're the one that created the packet, did you verified whether the IP checksum was correctly computed or not? A tool such as Wireshark may help you. If you're not the one that created the packet, the emitter seems to be faulty.

Another possibility is that the wrong IP checksum is caused by checksum offloading. Was the packet created by the local host on which your program runs?

Regards,
Didier

Ashok Kumar (ashokkm-9) said : #2

Hi Didier,
                  The following is the figure showing the test scenario,

               ............ ping 192.168.0.30 ............ Wired connection ............ ............
  | Host M/C-1 | ----------------------> | Linux/ARM | <-----------------> | Linux/ARM | -------------------> |Host M/C-2|
          ............ Ethernet ............ ............ Ethernet ............
         172.16.0.25 Application instance 1 Application instance 2 192.168.0.30
                                                                        running on running on
                                                                  Target platform 1 Target platform 2

Here I am trying to send ICMP/IP packet from Host M/C-1 to Host M/C-2 using ping. These host machines are connected to target platform through Ethernet.Application instance are running on the target platform. A wired connection exist between these platforms making end-to-end connection between the host machines possible. I used the following APIs of your library ROHC-1.7.0 in my source code:

1.COMPRESSOR

                compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX, gen_random_num, NULL);
                if(compressor == NULL)
                {
                        rohc_comp_free(compressor);
                }

                if(!rohc_comp_set_traces_cb2(compressor, print_rohc_traces,NULL))
                {
                        printf("CE: Failed to set the callback for traces on compressor\n");
                        rohc_comp_free(compressor);
                }

                if(!rohc_comp_enable_profiles(compressor, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_UDP, ROHC_PROFILE_IP, ROHC_PROFILE_TCP, -1))
                {
                        rohc_comp_free(compressor);
                }

               struct rohc_buf rohcBuf_IpPacket = rohc_buf_init_full(&luchar_Buffer[sizeof(IP_Packet)], ((IP_Packet*)luchar_Buffer)->int_data_size, 0);
               unsigned char rohc_Combuffer[BUFFER_SIZE];
               struct rohc_buf rohc_Compacket = rohc_buf_init_empty(rohc_Combuffer, BUFFER_SIZE);
               luchar_RohcComStatus = rohc_compress4(compressor, rohcBuf_IpPacket, &rohc_Compacket);
               if(luchar_RohcComStatus!= ROHC_STATUS_OK)
               {
                         rohc_comp_free(compressor);
               }

2.DE-COMPRESSOR

           decompressor=rohc_decomp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX, ROHC_U_MODE);
            if(decompressor == NULL)
            {
                    rohc_decomp_free(decompressor);
            }

            if(!rohc_decomp_set_traces_cb2(decompressor,print_rohc_traces,NULL))
            {
                    rohc_decomp_free(decompressor);
            }
            if(!rohc_decomp_enable_profiles(decompressor, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_UDP, ROHC_PROFILE_IP, ROHC_PROFILE_TCP, -1))
            {
                    rohc_decomp_free(decompressor);
            }
            struct rohc_buf rohc_packet = rohc_buf_init_full(&luchar_Buffer[sizeof(LLCDataInd)+sizeof(CL_D_pdu)], ((LLCDataInd*) luchar_Buffer)->uint16_Size - sizeof(CL_D_pdu), 0);
             unsigned char rohc_Decombuffer[BUFFER_SIZE];
             struct rohc_buf rohc_Decompacket = rohc_buf_init_empty(rohc_Decombuffer, BUFFER_SIZE);
             luchar_RohcDecStatus = rohc_decompress3(decompressor, rohc_packet, &rohc_Decompacket,
rcvd_feedback, feedback_send);
             if(luchar_RohcDecStatus != ROHC_STATUS_OK)
             {
                   rohc_decomp_free(decompressor);
            }

I had captured these ICMP/IP packets sent from M/C-1 to Target Platform-1 using Wireshark and observed that the checksum field of these IP packet headers are found to be correct and containing a value. This indicates there is no checksum offloading. The IP packets received in the target platfrom-1 running the application is not compressing these IP packets saying checksum incorrect in the debug prints but there seems to be no checksum error as per wireshark log. Then the application chooses Uncompressed profile and sends the packets uncompressed to Target Platform-2. Application running on the platform-2 receives this Uncompressed profiled packet and sends to M/C-2 via Ethernet. M/C-2 captured these received packets using Wireshark, its checksum field is also found to be correct.So, the thing is that actual ICMP packets does not seems to contain checksum error but the application is treating them as error. Wireshark logs are with me, if u want to have a look I can attach. Please, help me to sort out this issue. Thanks in advance....

Ashok Kumar (ashokkm-9) said : #3

Hi Didier,
                   The problem is solved and the reason for aforementioned checksum error is due to hardware problem in the target platform. By the way of fine working of ROHC application on ICMP/IP packets I came across an error with TCP/IP packet. Here when a TCP packet is lost, the application seems to abort immediately as shown below

wbhdr_cl: rfc4996.c:438: d_ip_id_lsb: Assertion `ip_id_offset == value' failed.

Actually it should proceed even though some packets are lost (which can be captured later during TCP retransmission), right?? Any suggestions.......

Ashok Kumar (ashokkm-9) said : #4

Hi,
      Did anyone came across the same issue while using TCP profile and is there any solution??

       rfc4996.c:438: d_ip_id_lsb: Assertion `ip_id_offset == value' failed.

Launchpad Janitor (janitor) said : #5

This question was expired because it remained in the 'Open' state without activity for the last 15 days.

Hello,

The problem is fixed in the master branch of the GIT repository:

    commit fec385d17a3668be928c1b4ad914bd2dc3bcd78f
    Author: Didier Barvaux <email address hidden>
    Date: Sun Dec 14 00:44:51 2014 +0100

        First batch of fixes for bugs #1219419 and 1400690

        * do not copy more than 6 bytes of TCP options in context
          TODO: add non-reg test
        * fix W-LSB for innermost IP-ID

See https://github.com/didier-barvaux/rohc/commit/fec385d17a3668be928c1b4ad914bd2dc3bcd78f

You may follow the instructions at https://rohc-lib.org/wiki/doku.php?id=library-install-sources#native_build_on_unix-like_systems to build a ROHC library from Git. Let me know if it solves your problem.

Regards,
Didier

(change question status)

Ashok Kumar (ashokkm-9) said : #8

Hi,
      I installed the latest version of ROHC from Git as per the instruction given in the link and also enabled non-regression test. Then I used the following code which deliberately takes the fifth packet to de-compressor without being compressed and the error its created also shown

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<netdb.h>

#include<netinet/ip_icmp.h>
#include<netinet/udp.h>
#include<netinet/tcp.h>
#include<netinet/ip.h>
#include<netinet/if_ether.h>
#include<net/ethernet.h>
#include<netinet/in.h>

#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

#include<stdarg.h>
#include<rohc/rohc.h>
#include<rohc/rohc_comp.h>
#include<rohc/rohc_decomp.h>
#include<rohc/rohc_time.h>

#define BUFFER_SIZE 65536

//void PrintData(unsigned char* ,int);
static int gen_random_num(const struct rohc_comp *const comp, void *const user_context);
static void print_rohc_traces(void *const priv_ctxt,const rohc_trace_level_t level,const rohc_trace_entity_t entity,
                              const int profile,const char *const format,...);
int raw_sock,i,j;
FILE *logfile;
struct sockaddr_in source,dest;

int main(int argc, char **argv)
{
 int saddr_size, data_size;
 int count = 0;
 struct sockaddr saddr;
 struct in_addr in;
 struct rohc_comp *compressor;
 struct rohc_decomp *decompressor;
 struct rohc_buf *rcvd_feedback = NULL;
 struct rohc_buf *feedback_send = NULL;
 struct rohc_ts rohc_ts;
 int ret;
 unsigned char luchar_RohcDecStatus, luchar_RohcComStatus;
 unsigned int seed;
 size_t i;
 rohc_status_t status;

 unsigned short iphdrlen;
 unsigned int ip_packet_len, rohc_packet_len;
 unsigned char BUFFER[BUFFER_SIZE], rohc_packet[BUFFER_SIZE], op_packet[BUFFER_SIZE];

 printf("\n Creating ROHC compressor......\n\n");
 compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX, gen_random_num, NULL);
 if(compressor == NULL)
 {
  printf("Failed creating compressor!!\n");
  rohc_comp_free(compressor);
 }

 if(!rohc_comp_set_traces_cb2(compressor, NULL,NULL))//if(!rohc_comp_set_traces_cb2(compressor, print_rohc_traces,NULL))
 {
  printf( "Failed to set the compressor callback random numbers!!\n");
  rohc_comp_free(compressor);
 }

 printf("Enabling compressor profiles");
 if(!rohc_comp_enable_profiles(compressor, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_IP, ROHC_PROFILE_UDP, ROHC_PROFILE_TCP, -1))
        {
  printf("Failed to enable the Compressor profiles\n");
  rohc_comp_free(compressor);
 }

 printf("\n Creating ROHC Decompressor.....");
 decompressor=rohc_decomp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX, ROHC_U_MODE);
 if(decompressor == NULL)
 {
  printf("Failed creating decompressor!!\n");
  rohc_decomp_free(decompressor);
 }

 if(!rohc_decomp_set_traces_cb2(decompressor,NULL,NULL))//if(!rohc_decomp_set_traces_cb2(decompressor,print_rohc_traces,NULL))
 {
  printf("Failed to set callback traces for decompressor!!\n");
  rohc_decomp_free(decompressor);
 }

 if(!rohc_decomp_enable_profiles(decompressor, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_IP, ROHC_PROFILE_UDP, ROHC_PROFILE_TCP, -1))
        {
  printf("Failed to enable the De-compressor profiles\n");
  rohc_decomp_free(decompressor);
 }

 logfile=fopen("log.txt","w");
 if(logfile == NULL)
 {
  printf("Unable to create file\n");
 }

 raw_sock = socket(AF_PACKET , SOCK_RAW , htons(ETH_P_ALL));
 //setsockopt(raw_sock , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 );

 if(raw_sock < 0)
 {
  perror("\n Socket error-try with sudo");
  return 1;
 }
 while(1)
 {
  saddr_size = sizeof(saddr);
  data_size = recvfrom(raw_sock, BUFFER, BUFFER_SIZE, 0, &saddr, &saddr_size);
  if(data_size < 0)
  {
   printf("\n Error of recvfrom(), failed to get packets");
   return 1;
  }

  struct iphdr *iph = (struct iphdr*)(BUFFER + sizeof(struct ethhdr));
  iphdrlen = iph->ihl*4;
  memset(&source, 0, sizeof(source));
  source.sin_addr.s_addr = iph->saddr;
  memset(&dest, 0, sizeof(dest));
  dest.sin_addr.s_addr = iph->daddr;

  if((((unsigned int)iph->protocol)==6||((unsigned int)iph->protocol)==17)&&(strcmp(inet_ntoa(dest.sin_addr),"172.16.18.134")==0))
  {

   count++;

   int ethhdr_size = sizeof(struct ethhdr);
   struct rohc_buf rohcBuf_IpPacket = rohc_buf_init_full(&BUFFER[ethhdr_size], data_size-ethhdr_size , 0);
      unsigned char rohc_Combuffer[BUFFER_SIZE];
      struct rohc_buf rohc_Compacket = rohc_buf_init_empty(rohc_Combuffer, BUFFER_SIZE);
   if(count!=5)
   {
    printf("\n Compressing the TCP/IP packet...\n\n");
    luchar_RohcComStatus = rohc_compress4(compressor, rohcBuf_IpPacket, &rohc_Compacket);
       if(luchar_RohcComStatus!= ROHC_STATUS_OK)
    {
     printf( "Compression of TCP/IP packet failed\n");
     rohc_comp_free(compressor);
     return 1;
    }
    printf("IP packet size=%d ROHC packet size =%d\n", data_size-sizeof(struct ethhdr),rohc_Compacket.len);
   }

   //if(count!=5)
   //{
    printf("\n Decompressing the TCP/IP packet....\n");
    struct rohc_buf rohc_packet = rohc_buf_init_full(rohc_Combuffer,rohc_Compacket.len, 0);
    unsigned char rohc_Decombuffer[BUFFER_SIZE];
    struct rohc_buf rohc_Decompacket = rohc_buf_init_empty(rohc_Decombuffer, BUFFER_SIZE);

    luchar_RohcDecStatus = rohc_decompress3(decompressor, rohc_packet, &rohc_Decompacket,
      rcvd_feedback, feedback_send);
    if(luchar_RohcDecStatus != ROHC_STATUS_OK)
       {
     printf("Decompression TCP/IP packet failed\n");
              rohc_decomp_free(decompressor);
       }
    printf("ROHC packet size=%d IP packet size=%d\n", rohc_Compacket.len,rohc_Decompacket.len);
   //}

  }
  else
  {
   //printf("IP packet received of protocol number:%d\r",(unsigned int)iph->protocol);
  }
  usleep(0);
 }
 close(raw_sock);
 printf("\n Finished");
 printf("\n Destroy the Compressor and Decompressor");
 rohc_comp_free(compressor);
 rohc_decomp_free(decompressor);
 return 0;
}

static int gen_random_num(const struct rohc_comp *const comp,void *const user_context)
{
 return rand();
}

static void print_rohc_traces(void *const priv_ctxt,const rohc_trace_level_t level,const rohc_trace_entity_t entity,const int profile,
 const char *const format,...)
{
        va_list args;
        va_start(args, format);
        vfprintf(stdout, format, args);
        va_end(args);
}

sudo ./ROHCTest

 Creating ROHC compressor......

Enabling compressor profiles
 Creating ROHC Decompressor.....
 Compressing the TCP/IP packet...

IP packet size=618 ROHC packet size =617

 Decompressing the TCP/IP packet....
ROHC packet size=617 IP packet size=618

 Compressing the TCP/IP packet...

IP packet size=52 ROHC packet size =51

 Decompressing the TCP/IP packet....
ROHC packet size=51 IP packet size=52

 Compressing the TCP/IP packet...

IP packet size=593 ROHC packet size =592

 Decompressing the TCP/IP packet....
ROHC packet size=592 IP packet size=593

 Compressing the TCP/IP packet...

IP packet size=613 ROHC packet size =613

 Decompressing the TCP/IP packet....
ROHC packet size=613 IP packet size=613

 Decompressing the TCP/IP packet....
Decompression TCP/IP packet failed
ROHC packet size=0 IP packet size=0

 Compressing the TCP/IP packet...

IP packet size=52 ROHC packet size =27

 Decompressing the TCP/IP packet....
ROHCTest: rohc_decomp.c:3616: rohc_decomp_decode_cid: Assertion `0' failed.
Aborted

But it works like a champ when a compressed packet is purposely discarded in de-compressor without getting aborted...

Hello,

Your program is buggy. You use the decompressor after destroying it. You destroyed it when the decompression failed.

    luchar_RohcDecStatus = rohc_decompress3(decompressor, rohc_packet, &rohc_Decompacket,
      rcvd_feedback, feedback_send);
    if(luchar_RohcDecStatus != ROHC_STATUS_OK)
       {
     printf("Decompression TCP/IP packet failed\n");
              rohc_decomp_free(decompressor); <-------------- decompressor is destroyed but program continues using it
       }

If you comment out the rohc_decomp_free(decompressor) call, program runs fine.

Note that your handling of error is quite strange. If the creation of the decompressor fails, you free it (1st bug) and let the program continue (2nd bug). All other error cases are buggy too.

Regards,
Didier

Ashok Kumar (ashokkm-9) said : #10

Thanks Didier Barvaux, that solved my question.