Notice : 内容無保証。禁無断転載。リンク不自由。

cksum

#include <iostream>

using std::cout ;
using std::endl ;

//

static const int   _ONE_ = 1 ;
#define    isNetworkByteOrderCPU() (*((char*)(&_ONE_)) == 0)

//

unsigned short cksum(
    unsigned short*    buf,
    unsigned int   nBytes,     // バイト数
    unsigned short sum0 = 0    // 途中までの計算結果があればここに。(擬似ヘッダ部分の合計とかを想定)
){
    unsigned long  sum = 0 ;

    if (nBytes & 1) {                          // バイト数が奇数のとき
        sum = ((unsigned char*)buf)[nBytes-1] ;    // 最後の1バイトで初期化しておく

        if (isNetworkByteOrderCPU()){
            sum <<= 8 ;
        }

        nBytes-- ;
    }

    sum += sum0 ;

    unsigned int nWords = nBytes / 2 ;
    while(nWords--){
        sum += *buf++ ; // BUGS : オーバーフローのチェック無し。
                        // (TCP/UDP/IP では問題無い。)
    }

    sum = (sum >> 16) + (sum & 0xffff) ;
    sum = (sum >> 16) + (sum & 0xffff) ;

    return ~sum ;
}

//

#define    BufSize 1024
char   buf[2+BufSize] ;    // 最初の2バイトがチェックサムフィールドだと思いねぇ。

int main(void){
    int i = 0 ;

    for (i=2 ; i<2+BufSize ; i++){
        buf[i] = i-2 ;
    }

    unsigned short checkSum = 0 ;

    // チェックサムの計算

    *(unsigned short*)buf = 0 ;
    checkSum = cksum((unsigned short*)buf, 2+BufSize) ;

    // チェックサムの格納
    *(unsigned short*)buf = checkSum ;

    // チェックサムの検証
    checkSum = cksum((unsigned short*)buf, 2+BufSize) ;

    if (checkSum != 0){    // 正しければ 0に戻る。
        cout <<
            "NG : i=" << (void*)i <<
            ", checkSum =" << (void*)checkSum <<
        endl ;
    }

    if (checkSum == 0){
        cout << "OK" << endl ;
    }

    return 0 ;
}