1. Home
  2. Docs
  3. Examples
  4. ICMP Checksum Calculation

ICMP Checksum Calculation

While GUARDARA makes difficult or time consuming tasks quick and easy, sometimes, you may not be able to do everything in a straightforward way using the built-in components. For example, the ICMP protocol utilizes a checksum value in order to detect data corruption. In this example, we discuss the challenge of calculating the ICMP checksum and a possible implementation of the checksum calculation using a Transform.

Challenge

The challenge with ICMP is that the checksum (marked with dark red below) is not at the beginning or end, but it is within the “protected” are (marked light red below).

The ICMP checksum is calculated by having NULL bytes set for the checksum field during the calculation. The resulting checksum is then written to this area. Using the built-in Hash field (assuming it supported IPv4 checksum calculation) to calculate the checksum would result in an Exception, because because support fields, such as the Hash field work on the rendered value of Group fields. If the Hash field was a child of the Group for which we wanted to calculate the checksum, rendering the Group would result in recursion. It’s a chicken and egg kind of a problem, as the parent Group‘s rendered value depends on the value of the child fields; therefore we have to find another solution.

As per the above, we will use a Transform to implement the checksum calculation. We can apply the transform to the target Group to dynamically calculate the checksum for each test case.

Please note, GUARDARA has a built-in transform named IPv4 Checksum that can be used to calculate the ICMP checksum. However, should you find yourself in a similar situation you may find the instructions below useful.

The below section discusses the implementation of a custom transform capable of calculating and setting a valid ICMP checksum for an ICMP message.

Implementation

In order to create the transform skeleton, issue the following SDK command.

guardara extension -e transform -o create

Properties and Skeleton

Even though the position of the checksum is fixed relative to the start of the block, in this example, we will expose a numeric parameter for users to be able to define the starting offset of the checksum field, with the default value set to 2. (counting from 0)

The properties.json file should look like below.

{
    "name": "icmpchecksum",
    "description": "ICMP Checksum Calculator",
    "properties": {
        "index": {
            "title": "Checksum Index",
            "description": "The position of the first byte of the checksum within the block.",
            "type": "integer"
        }
    }
}

The skeleton.json file should look like, as shown below.

{
    "name": "icmpchecksum",
    "parameters": {
        "index": 2
    }
}

Transform

The transform.py, that contains the actual implementation is shown below.

import struct
from guardara.sdk.transform.transform import TransformInterface

class transform(TransformInterface):

    @staticmethod
    def calculate_checksum(value):
        """
        The checksum is the 16-bit one's complement of the one's
        complement sum of the ICMP message starting with the ICMP Type.
        For computing the checksum, the checksum field should be zero.
        If the total length is odd, the received data is padded with 
        one octet of zeros for computing the checksum. This checksum 
        maybe replaced in the future.
        """
        if (len(value) % 2):
            value += "\x00"
        sum = 0
        for i in range(0, len(value), 2):
            a = ord(value[i]) 
            b = ord(value[i+1])
            sum = sum + (a+(b << 8)) sum = sum + (sum >> 16)
        sum = ~sum & 0xffff
        return struct.pack("<H", sum)

    @staticmethod
    def ensure_zero(value, index):
        """
        Make sure the bytes at index and index + 1 are NULL before checksum
        calculation.
        """
        value = list(map(ord, value))
        value[index] = 0
        value[index + 1] = 0
        return "".join(list(map(chr, value)))

    @staticmethod
    def transform(value, params=None):
        """
        Transform entry point.
        """
        value = transform.ensure_zero(value, params.get('index'))
        checksum = transform.calculate_checksum(value)
        value = list(map(ord, value))
        checksum = list(checksum)
        value[params.get('index')] = checksum[0]
        value[params.get('index') + 1] = checksum[1]
        value = "".join(list(map(chr, value)))
        return value

Deploying the Transform

First, the newly created transform has to be packaged using the SDK as shown below.

guardara extension -e transform -o package -n icmpchecksum

The resulting file named icmpchecksum.fl is the deployable extension package. This package can be deployed by importing it in GUARDARA Manager under Settings > Inventory, by clicking the Add button.

Using the Transform

Open your message template using the Message Template Designer and select the group or field you would like to apply the transform to. On the properties panel, open the Transform section. You will see that the recently added Transform is now available to use. Select the transform, configure it as appropriate and click the “Add” button to apply the transform.

Was this article helpful to you? Yes No