checksum issues

0

I am trying to generate the checksum of an icmpv6 package as an example. This is the function that I am using:

uint16_t checksum (uint16_t *addr, int len)
{
  int count = len;
  register uint32_t sum = 0;
  uint16_t answer = 0;

  // Sum up 2-byte values until none or only one byte left.
  while (count > 1) {
    sum += *(addr++);
    count -= 2;
  }

  // Add left-over byte, if any.
  if (count > 0) {
    sum += *(uint8_t *) addr;
  }

  // Fold 32-bit sum into 16 bits; we lose information by doing this,
  // increasing the chances of a collision.
  // sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits)
  while (sum >> 16) {
    sum = (sum & 0xffff) + (sum >> 16);
  }

  // Checksum is one's compliment of sum.
  answer = ~sum;

  return (answer);
}

and this is the variable that I am inserting:

nread = read(tun_fd,buffer,sizeof(buffer));
for(i = 8; i < 40 ; i++)
{
    buf[i-8] = buffer[i];  
    j++;
}
buf[j] = 0; j++;

buf[j] = 0; j++;

aux2 |= buffer[4] << 8;

aux2 |= buffer[5] << 0; 

buf[j] = aux2 / 256;j++;
buf[j] = aux2 % 256;j++;

buf[j] = 0;j++;
buf[j] = 0;j++;
buf[j] = 0;j++;
buf[j] = 58;j++;
buf[j] = buffer[40];j++;
buf[j] = buffer[41];j++;
buf[j] = buffer[44];j++;
buf[j] = buffer[45];j++;
buf[j] = buffer[46];j++;
buf[j] = buffer[47];j++;
buf[j] = 0;j++;
buf[j] = 0;j++;
for(i = 48; i < nread ; i++)
{
    buf[j] = buffer[i];
    j++  ;
}


printf("%i\n", checksum((uint16_t *)buf,j));

The values obtained are:

value that should be checksum 65522 and the
value that I get 57975

I'm looking for some help

    
asked by tomas lagos 15.11.2016 в 22:20
source

1 answer

1

Let's see. In this part of your code

  // Sum up 2-byte values until none or only one byte left.
  while (count > 1) {
    sum += *(addr++);
    count -= 2;
  }

  // Add left-over byte, if any.
  if (count > 0) {
    sum += *(uint8_t *) addr;
  }

You scroll past the buffer and add the value of its bytes, taking them as 16 bits , and, if there are any bytes left (the size of the buffer is odd), you add as 8 bits .

That point can give you problems, depending on the ENDIAN of the architecture in which you run it.

Try changing it to uint16_t , to see what happens.

// Add left-over byte, if any.
if (count > 0) {
  sum += *(uint16_t *) addr;
}

EDITO

If you do it as I say, I think you should manually add a \ 0 at the end of addr , so that it does not take unwanted values.

    
answered by 15.11.2016 в 22:53