Вычисление контрольной суммы для эхо-запроса ICMP в Python - PullRequest
1 голос
/ 18 марта 2019

Я пытаюсь реализовать ping-сервер в Python, и в качестве справки я использую исходный код Pyping: https://github.com/Akhavi/pyping/blob/master/pyping/core.py

Я не могу понять Calculate_checksum функция, которая была реализована для вычисления контрольной суммы эхо-запроса ICMP.Это было реализовано следующим образом:

def calculate_checksum(source_string):

    countTo = (int(len(source_string) / 2)) * 2
    sum = 0
    count = 0

    # Handle bytes in pairs (decoding as short ints)
    loByte = 0
    hiByte = 0
    while count < countTo:
        if (sys.byteorder == "little"):
            loByte = source_string[count]
            hiByte = source_string[count + 1]
        else:
            loByte = source_string[count + 1]
            hiByte = source_string[count]
        sum = sum + (ord(hiByte) * 256 + ord(loByte))
        count += 2

    # Handle last byte if applicable (odd-number of bytes)
    # Endianness should be irrelevant in this case
    if countTo < len(source_string): # Check for odd length
        loByte = source_string[len(source_string) - 1]
        sum += ord(loByte)

    sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
                      # uses signed ints, but overflow is unlikely in ping)

    sum = (sum >> 16) + (sum & 0xffff)  # Add high 16 bits to low 16 bits
    sum += (sum >> 16)                  # Add carry from above (if any)
    answer = ~sum & 0xffff              # Invert and truncate to 16 bits
    answer = socket.htons(answer)

    return answer

sum & = 0xffffffff используется для усечения суммы до 32 бит.Однако, что происходит с дополнительным битом (33-й бит).Разве это не должно быть добавлено к сумме как перенос?Кроме того, я не могу понять код после этого.

Я прочитал документацию RFC1071 (http://www.faqs.org/rfcs/rfc1071.html), которая объясняет, как реализовать контрольную сумму, но я не смог понятьмного.

Любая помощь будет оценена. Спасибо!

1 Ответ

0 голосов
/ 18 марта 2019

Я наконец-то смог выяснить работу функции Calculate_checksum , и я попытался объяснить это ниже.

Расчет контрольной суммы выполняется следующим образом (согласно RFC1071 ):

Давайте рассмотрим пример.

Если контрольная сумма должна быть вычислена по последовательности октетов [A, B, C, D, E], то будут созданы пары [A, B] и [C, D] с оставшимся октетом E. Пары [a, b] могут быть вычислены следующим образом:

a * 256 + b , где a и b - октеты

Скажите, если a равно 11001010, а b равно 00010001, a * 256 + b = 1100101000010001, что дает нам объединенные результаты октетов.

Таким образом, сумма дополнения 1 вычисляется следующим образом:

sum = [A + B] + '[C + D] +' E, где + 'представляет дополнение 1 дополнение

Теперь вернемся к коду, все перед строкой sum & = 0xffffffff вычисляет сумму дополнения 1, которую мы вычислили ранее.


сумма & = 0xffffffff

используется для усечения суммы до 32 бит, хотя превышение суммы в пинге маловероятно, поскольку размер source_string не очень велик

(source_string = заголовок (8 байт) + полезная нагрузка (переменная длина)).


сумма = (сумма >> 16) + (сумма и 0xffff)

Этот фрагмент кода реализован для случая, когда сумма больше 16 бит. Сумма разбита на 2 части:

(сумма >> 16): 16 битов высшего порядка

(sum & 0xffff): младшие 16 битов

и затем эти две части добавляются. Конечный результат может быть на 16 бит больше, чем на 16 бит


сумма + = (сумма >> 16)

Эта строка используется в том случае, если итоговая сумма, полученная в результате предыдущего вычисления, длиннее 16 битов и используется для выполнения переноса, аналогично предыдущей строке.


Наконец, дополнение 1 вычисляется и усекается до 16 бит. Функция socket.htons () используется для поддержания порядка байтов, отправляемых в сеть на основе архитектуры вашего устройства (с прямым и прямым порядком байтов).

...