blob: 6b06a8dedbb4cc56700b8dd57edf274be048514c [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2019 Ericsson Telecom AB
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
///////////////////////////////////////////////////////////////////////////////
//
// File: NDP_EncDec.cc
// Rev: R1B
// Prodnr: CNL 113 632
// Updated: 2009-02-25
// Contact: http://ttcn.ericsson.se
// Reference: RFC 4861
#include "NDP_Types.hh"
namespace NDP__Types {
#define Get_MSB_NDP(val) (((val) & 0xff00) >> 8)
#define Get_LSB_NDP(val) ((val) & 0x00ff)
// copied from IP protocol module
General__Types::OCT2
Calculate_cksum(const unsigned char *ptr, int datalen)
{
unsigned long sum = 0;
unsigned char ret[2];
// Log_function_name_on_enter();
for (int i = 0; i <= datalen - 2; i = i + 2)
sum += (ptr[i + 1] << 8) + ptr[i];
if (datalen % 2) // datalen is odd
{
sum += ptr[datalen - 1] << 8;
}
sum = (sum & 0xFFFF) + (sum >> 16);
sum = (sum & 0xFFFF) + (sum >> 16);
sum = ~sum;
ret[0] = Get_LSB_NDP(sum);
ret[1] = Get_MSB_NDP(sum);
return OCTETSTRING(2, &ret[0]);
}
OCTETSTRING f__enc__PDU__NDP(const PDU__NDP& pdu,
const OCTETSTRING& srcaddr, // from IPv6 header
const OCTETSTRING& dstaddr) //, from IPv6 header
{
TTCN_Buffer buf;
pdu.encode(PDU__NDP_descr_, buf, TTCN_EncDec::CT_RAW);
OCTETSTRING ret_val(buf.get_len(), buf.get_data());
// if user gave checksum field as '0000'O then calculate actual checksum, otherwise use what user gave
if (oct2int(substr(ret_val,2,2)) == 0)
{
//generate pseudo header for checksum calculation
OCTETSTRING PseudoHeader;
PseudoHeader = srcaddr + dstaddr + int2oct(ret_val.lengthof(),4) + int2oct (0,3) + int2oct(58,1);
// RFC 4443 2 -> "The Next Header value used in the pseudo-header is 58. ('3A'O
// calculate checksum
OCTETSTRING CHECKSUM = Calculate_cksum ( (const unsigned char *) (PseudoHeader + ret_val),
ret_val.lengthof() + 40 ); // 40 is pseudoheader length
ret_val = substr(ret_val,0,2) + CHECKSUM + substr(ret_val,4,ret_val.lengthof()- 4);
}
return ret_val;
}
BOOLEAN f__NDP__verify__checksum
(
const OCTETSTRING& stream,
const OCTETSTRING& srcaddr, // from IPv6 header
const OCTETSTRING& dstaddr // from IPv6 header
)
{
OCTETSTRING PseudoHeader;
PseudoHeader = srcaddr + dstaddr + int2oct(stream.lengthof(),4) + int2oct (0,3) + int2oct(58,1);
// stream with checksum field as 0000
OCTETSTRING stream_w_zero_checksum;
stream_w_zero_checksum = substr(stream,0,2) + int2oct(0,2) + substr(stream,4,stream.lengthof()- 4);
// calculate checksum
OCTETSTRING CHECKSUM = Calculate_cksum ( (const unsigned char *) (PseudoHeader + stream_w_zero_checksum),
stream_w_zero_checksum.lengthof() + 40 );
OCTETSTRING RECEIVED_CHECKSUM = substr(stream,2,2);
if (CHECKSUM != RECEIVED_CHECKSUM)
{
TTCN_warning("Incorrect checksum received! \n Expected checksum: %x %x \n Received checksum: %x %x ",
((const unsigned char *)CHECKSUM)[0],
((const unsigned char *)CHECKSUM)[1],
((const unsigned char *) RECEIVED_CHECKSUM)[0],
((const unsigned char *) RECEIVED_CHECKSUM)[1]
);
return FALSE;
}
else
{
return TRUE;
}
}
} // end of namespace PMIP__Types