DaniWeb IT Discussion Community

DaniWeb IT Discussion Community (http://www.daniweb.com/forums/)
-   Pascal and Delphi (http://www.daniweb.com/forums/forum124.html)
-   -   C++ to Delphi CheckSum code (http://www.daniweb.com/forums/thread124488.html)

rayman341 May 16th, 2008 1:20 am
C++ to Delphi CheckSum code
 
typedef struct iphdr
{
u_char ip_hl:4, /* header length */
ip_v:4; /* version */
u_char ip_tos; /* type of service */
short ip_len; /* total length */
u_short ip_id; /* identification */
short ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
} iphdr, *iphdr_ptr;


VOID RecalculateIPChecksum (
iphdr_ptr pIpHeader
)
{
unsigned short word16;
unsigned int sum = 0;
unsigned int i = 0;
PUCHAR buff;

// Initialize checksum to zero
pIpHeader->ip_sum = 0;
buff = (PUCHAR)pIpHeader;

// Calculate IP header checksum
for (i = 0; i < pIpHeader->ip_hl*sizeof(DWORD); i=i+2)
{
word16 = ((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
sum = sum+word16;
}

// keep only the last 16 bits of the 32 bit calculated sum and add the carries
while (sum>>16)
sum = (sum & 0xFFFF)+(sum >> 16);

// Take the one's complement of sum
sum = ~sum;

pIpHeader->ip_sum = htons((unsigned short) sum);
}

Duoas May 16th, 2008 10:15 am
Re: C++ to Delphi CheckSum code
 
That C code is a mess. And it is dangerous because it uses bitfields (which C++ does not guarantee to be packed in any specific order -- so results vary by compiler!).

Alas, why don't programmers stp usng stpd shrt nonsns nms.

Anyway:
uses
  SysUtils,  // for PByteArray
  Winsock;  // for htons()

const
  IP_DF = $4000;  // don't fragment flag
  IP_MF = $2000;  // more fragments flag

type
  in_addr = record ... end;  // you must fill this in

  iphdr_ptr = ^iphdr;
  iphdr = packed record
    ip_hl__ip_v: byte;      // header length, version: four bits each
    ip_tos:      byte;      // type of service
    ip_len:      shortint;  // total length
    ip_id:      word;      // identification
    ip_off:      shortint;  // fragment offset field
    ip_ttl:      byte;      // time to live
    ip_p:        byte;      // protocol
    ip_sum:      word;      // checksum
    ip_src:      in_addr;  // source address
    ip_dst:      in_addr    // destination address
    end;

procedure RecalculateIPChecksum( pIpHeader: iphdr_ptr );
  var
    sum:    longword;
    i:      longword;
    buff:  PByteArray;  // see note 1
  begin
  sum := 0;
  i  := 0;

  // Initialize checksum to zero
  pIpHeader^.ip_sum := 0;
  buff := pIpHeader;

  // Calculate IP header checksum
  while i < (pIpHeader^.ip_hl__ip_v and $F) *sizeof( longword ) do  // see note 2
    begin
    inc( sum, (buff[ i ] shl 8) +buff[ i +1 ] );
    inc( i, 2 )
    end;

  // Keep only the last 16 bits of the 32 bit calculated sum and add the carries
  while (sum shr 16) <> 0 do
    sum := (sum and $FFFF) +(sum shr 16);

  // Take the one's complement of sum
  sum := sum xor $FFFFFFFF;

  // ...and store it in network order
  pIpHeader^.ip_sum := htons( sum )
  end;

The above code presumes the following:
  1. typedef unsigned char* PUCHAR;
  2. bitfields are packed in MS VC++ order [1], meaning that ip_hl is in the lower four bits and ip_v is in the upper four bits. If this is not the case you will need to change that and $F to shr 4.

Enjoy!

rayman341 May 16th, 2008 10:26 am
Re: C++ to Delphi CheckSum code
 
Thank you so much. This gives me a lot of help with other peaces of code.

Ray


All times are GMT -4. The time now is 11:18 pm.

Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC