247 lines
7.9 KiB
C
247 lines
7.9 KiB
C
|
|
/************************************************************************/
|
||
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||
|
|
/************************************************************************/
|
||
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||
|
|
/* 1996, All Rights Reserved. */
|
||
|
|
/* */
|
||
|
|
/* PROPRIETARY AND CONFIDENTIAL */
|
||
|
|
/* */
|
||
|
|
/* MODULE NAME : checksum.c */
|
||
|
|
/* PRODUCT(S) : Lean-T Stack */
|
||
|
|
/* */
|
||
|
|
/* MODULE DESCRIPTION : */
|
||
|
|
/* This module implements the computation of checksum */
|
||
|
|
/* using the algorithm defined in Annex B of the ISO 8073 */
|
||
|
|
/* or in the ISO 8473. */
|
||
|
|
/* */
|
||
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||
|
|
/* */
|
||
|
|
/* checksum_insert */
|
||
|
|
/* checksum_verified */
|
||
|
|
/* */
|
||
|
|
/* */
|
||
|
|
/* MODIFICATION LOG : */
|
||
|
|
/* Date Who Rev Comments */
|
||
|
|
/* -------- --- ------ ------------------------------------------- */
|
||
|
|
/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */
|
||
|
|
/* 05/12/97 JRB 03 ch*_verified chk c0. Was checking c1 twice. */
|
||
|
|
/* Clean up data types. */
|
||
|
|
/* Clarify casting computing x,y in ch*_insert. */
|
||
|
|
/* 05/07/97 JRB 02 Changed non-ANSI "%hu" to "%u". */
|
||
|
|
/* 06/17/96 EJV 01 Created */
|
||
|
|
/************************************************************************/
|
||
|
|
#if 0
|
||
|
|
/* this file is not neccessary when printf will be replaced with slog */
|
||
|
|
#include <stdio.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include "glbtypes.h"
|
||
|
|
#include "checksum.h"
|
||
|
|
|
||
|
|
|
||
|
|
static ST_VOID get_checksum_c0_c1 (ST_UCHAR *buf, ST_UINT16 buf_len,
|
||
|
|
ST_UCHAR *pC0, ST_UCHAR *pC1);
|
||
|
|
|
||
|
|
|
||
|
|
/************************************************************************/
|
||
|
|
/* checksum_insert */
|
||
|
|
/*----------------------------------------------------------------------*/
|
||
|
|
/* This function computes and inserts the 2 byte checksum into a PDU */
|
||
|
|
/* buffer at specified position (and position+1). */
|
||
|
|
/* The checksum algorithm is described in ISO 8473 (CLNP) and */
|
||
|
|
/* ISO 8073 (Transport protocol). */
|
||
|
|
/* Note that the maximum len of TPDU in ISO 8073 is 8192 bytes. */
|
||
|
|
/* */
|
||
|
|
/* Parameters: */
|
||
|
|
/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/
|
||
|
|
/* will be computed. */
|
||
|
|
/* ST_UINT16 buf_len Length of the buffer (PDU). */
|
||
|
|
/* ST_UINT16 position Position of checksum's first byte in buf*/
|
||
|
|
/* (position=0 if checksum is the first */
|
||
|
|
/* byte in buffer). */
|
||
|
|
/* */
|
||
|
|
/* Return: */
|
||
|
|
/* ST_VOID none */
|
||
|
|
/************************************************************************/
|
||
|
|
ST_VOID checksum_insert (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position)
|
||
|
|
{
|
||
|
|
ST_UCHAR c0, c1;
|
||
|
|
ST_LONG x, y; /* the checksum's first and second byte */
|
||
|
|
ST_UINT16 sum_pos; /* this is the position of checksum first byte */
|
||
|
|
/* in the PDU as specified by algorithm, first */
|
||
|
|
/* byte position is 1 not 0. */
|
||
|
|
|
||
|
|
sum_pos = position+1;
|
||
|
|
|
||
|
|
/* make sure the checksum bytes are cleared */
|
||
|
|
buf [position] = buf [position+1] = 0;
|
||
|
|
|
||
|
|
get_checksum_c0_c1 (buf, buf_len, &c0, &c1);
|
||
|
|
|
||
|
|
#if 0
|
||
|
|
/* LIZ substitute the printf with slogging */
|
||
|
|
printf ("\n Checksum computation: c0=0x%2.2X=%u, c1=0x%2.2X=%u",
|
||
|
|
(ST_UINT) c0, (ST_UINT) c0, (ST_UINT) c1, (ST_UINT) c1);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
x = ((ST_LONG) (buf_len-sum_pos) * (ST_LONG) c0 - (ST_LONG) c1) % 255L;
|
||
|
|
y = ((ST_LONG) c1 - (ST_LONG) (buf_len-sum_pos+1) * (ST_LONG) c0) % 255L;
|
||
|
|
|
||
|
|
buf [position] = (ST_UCHAR) (x <= 0L ? x+255L : x);
|
||
|
|
buf [position+1] = (ST_UCHAR) (y <= 0L ? y+255L : y);
|
||
|
|
|
||
|
|
#if 0
|
||
|
|
/* LIZ substitute the printf with slogging */
|
||
|
|
printf ("\n Checksum computation: buf[%u]=%u, buf[%u]=%u",
|
||
|
|
position, (ST_UINT) buf[position],
|
||
|
|
position+1,(ST_UINT) buf[position+1]);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/************************************************************************/
|
||
|
|
/* checksum_verified */
|
||
|
|
/*----------------------------------------------------------------------*/
|
||
|
|
/* This function verifies the checksum of a PDU. */
|
||
|
|
/* The checksum algorithm is described in ISO 8473 (CLNP) and */
|
||
|
|
/* ISO 8073 (Transport protocol). */
|
||
|
|
/* Note that the maximum len of TPDU in ISO 8073 is 8192 bytes. */
|
||
|
|
/* */
|
||
|
|
/* Parameters: */
|
||
|
|
/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/
|
||
|
|
/* will be computed. */
|
||
|
|
/* ST_UINT16 buf_len Length of the buffer (PDU). */
|
||
|
|
/* ST_UINT16 position Position of checksum's first byte in buf*/
|
||
|
|
/* (position=0 if checksum is the first */
|
||
|
|
/* byte in buffer), used only for CLNP. */
|
||
|
|
/* ST_BOOLEAN clnp_csum If SD_TRUE the CLNP checksum will be */
|
||
|
|
/* verified, if SD_FALSE the Transport Prot. */
|
||
|
|
/* checksum will be verified. */
|
||
|
|
/* */
|
||
|
|
/* Return: */
|
||
|
|
/* ST_BOOLEAN SD_TRUE if verification of checksum is */
|
||
|
|
/* successful; */
|
||
|
|
/* SD_FALSE if verification failed. */
|
||
|
|
/************************************************************************/
|
||
|
|
ST_BOOLEAN checksum_verified (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position,
|
||
|
|
ST_BOOLEAN clnp_csum)
|
||
|
|
{
|
||
|
|
ST_BOOLEAN checksum_correct;
|
||
|
|
ST_UCHAR c0, c1;
|
||
|
|
|
||
|
|
checksum_correct = SD_FALSE;
|
||
|
|
|
||
|
|
if (clnp_csum)
|
||
|
|
{
|
||
|
|
if (buf [position] != 0 && buf [position+1] != 0)
|
||
|
|
{
|
||
|
|
/* if both bytes in checksum are not 0 then we have to compute the */
|
||
|
|
/* checksum */
|
||
|
|
|
||
|
|
get_checksum_c0_c1 (buf, buf_len, &c0, &c1);
|
||
|
|
|
||
|
|
#if 0
|
||
|
|
/* LIZ substitute the printf with slogging */
|
||
|
|
printf ("\n Checksum verification: c0=0x%2.2X=%u, c1=0x%2.2X=%u",
|
||
|
|
(ST_UINT) c0, (ST_UINT) c0, (ST_UINT) c1, (ST_UINT) c1);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (c0 == 0 && c1 == 0)
|
||
|
|
checksum_correct = SD_TRUE;
|
||
|
|
}
|
||
|
|
else if (buf [position] == 0 && buf [position+1] == 0)
|
||
|
|
{
|
||
|
|
/* if both bytes in checksum are 0 then the checksum should be */
|
||
|
|
/* ignored, and is considered as correct. */
|
||
|
|
|
||
|
|
checksum_correct = SD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* if one byte (but not both bytes) in checksum is 0 then the */
|
||
|
|
/* checksum is invalid. */
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* transport protocol checksum */
|
||
|
|
|
||
|
|
get_checksum_c0_c1 (buf, buf_len, &c0, &c1);
|
||
|
|
|
||
|
|
if (c0 == 0 && c1 == 0)
|
||
|
|
checksum_correct = SD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (checksum_correct);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/************************************************************************/
|
||
|
|
/* get_checksum_c0_c1 */
|
||
|
|
/*----------------------------------------------------------------------*/
|
||
|
|
/* This function computes the checksum values C0 and C1 described in */
|
||
|
|
/* ISO 8473 (CLNP) and ISO 8073 (Transport protocol). */
|
||
|
|
/* Note that the maximum len of TPDU in ISO 8073 is 8192 bytes. */
|
||
|
|
/* To avoid overflow of long values c0 or c1 when the buffer len is */
|
||
|
|
/* greater then 4096 the values c0 and c1 are computed in two stages. */
|
||
|
|
/* */
|
||
|
|
/* Parameters: */
|
||
|
|
/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/
|
||
|
|
/* will be computed. */
|
||
|
|
/* ST_UINT16 buf_len Length of the buffer (TPDU). */
|
||
|
|
/* ST_UCHAR *pC0 Pointer where to return the computed C0.*/
|
||
|
|
/* ST_UCHAR *pC1 Pointer where to return the computed C1.*/
|
||
|
|
/* */
|
||
|
|
/* Return: */
|
||
|
|
/* ST_VOID none */
|
||
|
|
/************************************************************************/
|
||
|
|
static ST_VOID get_checksum_c0_c1 (ST_UCHAR *buf, ST_UINT16 buf_len,
|
||
|
|
ST_UCHAR *pC0, ST_UCHAR *pC1)
|
||
|
|
{
|
||
|
|
ST_ULONG c0, c1;
|
||
|
|
|
||
|
|
c0 = c1 = 0L;
|
||
|
|
|
||
|
|
while (buf_len-- > 0)
|
||
|
|
{
|
||
|
|
c0 = c0 + (ST_ULONG) *(buf++);
|
||
|
|
c1 = c1 + c0;
|
||
|
|
|
||
|
|
/* if the buf_len > 4096 there is risk of overflowing, so we take */
|
||
|
|
/* modulus at 4096 bytes to bring the c0 and c1 numbers down */
|
||
|
|
|
||
|
|
if (buf_len == 4096)
|
||
|
|
{
|
||
|
|
c0 = c0 % 255L;
|
||
|
|
c1 = c1 % 255L;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
*pC0 = (ST_UCHAR) (c0 % 255L);
|
||
|
|
*pC1 = (ST_UCHAR) (c1 % 255L);
|
||
|
|
|
||
|
|
/* the code below can substitute the code above if long 32-bit values */
|
||
|
|
/* are not available with given compiler. */
|
||
|
|
#if 0
|
||
|
|
ST_UINT16 c0,c1;
|
||
|
|
c0 = c1 = 0;
|
||
|
|
while (buf_len-- > 0)
|
||
|
|
{
|
||
|
|
c0 += (ST_UINT16) *(buf++);
|
||
|
|
if (c0 >= 255)
|
||
|
|
{
|
||
|
|
++c0; /* this two lines are equvalen to mod 255 */
|
||
|
|
c0 &= 0x00ff;
|
||
|
|
}
|
||
|
|
c1 += c0;
|
||
|
|
if (c1 >= 255)
|
||
|
|
{
|
||
|
|
++c1;
|
||
|
|
c1 &= 0x00ff;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
*pC0 = (ST_UCHAR) c0;
|
||
|
|
*pC1 = (ST_UCHAR) c1;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|