Ссылки. RFC 1071 Computing the Internet Checksum RFC 768 UDP RFC: 791 IP RFC: 793 Transmission Control Protocol Стивенс. TCP/IP http://rsdn.ru/Forum/Message.aspx?mid=510500&only=1 http://rsdn.ru/forum/Message.aspx?mid=875609&only=1 http://www.codeproject.com/cpp/checksum32.asp Общее. Поле контрольной суммы — это 16-битное дополнение суммы всех 16- битных слов сегмента (заголовка и/или данных). Алгоритм вычисления одинаков для IP, UDP, TCP, ICMP протоколов, различаются только входные данные. Если сегмент содержит нечетное количество октетов, подлежащих учету в контрольной сумме, последний октет будет дополнен нулями справа с тем, чтобы образовать для предоставления контрольной сумме 16-битное слово. Возникший при таком выравнивании октет не передается вместе с сегментом по сети. Перед вычислением контрольной суммы поле этой суммы заполняется нулями. Реализация на С в виде функции. /* На входе – адрес буфера usBuf; количество байт в буфере iSize Возвращается – подсчитанная CRC */ unsigned short CalculateChecksum(unsigned short *usBuf, int iSize) { unsigned long usChksum=0; while (iSize>1) { usChksum+=*usBuf++; iSize-=sizeof(unsigned short); } if (iSize) usChksum+=*(unsigned char*)usBuf; usChksum=(usChksum >> 16) + (usChksum & 0xffff); usChksum+=(usChksum >> 16); return (unsigned short)(~usChksum); } Данная функция работает с четным и нечетным количеством байт. Контрольная сумма для IP-заголовка. Контрольная сумма заголовка (header checksum) рассчитывается только для IP заголовка. Она не включает в себя данные, которые следуют за заголовком. ICMP, IGMP, UDP и TCP имеют контрольные суммы в своих собственных заголовках, которые охватывают их заголовки и данные. Расчет производится по вышеприведенному алгоритму. При отправке, не забываем перед вычислением обнулить поле CRC в заголовке! При получении сумма считается по тому же алгоритму. Так как контрольная сумма, рассчитанная приемником, содержит в себе контрольную сумму, сохраненную отправителем, контрольная сумма приемника состоит из битов равных 0, если в заголовке ничего не было изменено при передаче. Если в результате не получились все нулевые биты (ошибка контрольной суммы), IP отбрасывает принятую датаграмму. Сообщение об ошибке не генерируется. Теперь задача верхних уровней каким-либо образом определить, что датаграмма отсутствует, и обеспечить повторную передачу. Контрольная сумма для UDP. Контрольная сумма UDP охватывает UDP заголовок и UDP данные. Расчет по приведенному алгоритму, но есть нюансы. Во-первых, UDP датаграмма может состоять из нечетного количества байт, тогда как при расчете контрольной суммы складываются 16-битные слова. При этом в конец датаграммы добавляются нулевые байты заполнения, если это необходимо для расчета контрольной суммы. (Байты заполнения не передаются.) Во-вторых, в UDP ( и TCP) существуют 12-байтовые псевдозаголовки (в UDP датаграммах и TCP сегментах) только для расчета контрольной суммы. Псевдозаголовки содержат в себе определенные поля из IP заголовка. Все это сделано для двойной проверки того, что данные достигли того пункта назначения, которому предназначались (IP не принимает датаграммы, которые не адресованы для данного хоста, и не сможет передать UDP датаграммы, предназначенные для другого верхнего уровня). На рисунке показан псевдозаголовок и UDP датаграмма. Псевдозаголовок и UDP заголовок Часть IP заголовка преобразованная в псевдозаголовок и UDP заголовок. Обратите внимание на то, что длина UDP датаграммы, при расчете контрольной суммы, появляется дважды. При отправке, что бы не выделять дополнительно память для псевдозаголовка, сделаем следующее. 1. Сначала формируется IP заголовок, кроме следующих полейКонтрольная сумма (Header Checksum); Время жизни (Time To Live). Их заполним так: Контрольная сумма := Длина UDP; Время жизни := 0х00 2. Теперь формируем UDP-заголовок (кроме контрольной суммы, она забита нулями). 3. Теперь необходимости в отдельном псевдозаголовке нет – его роль выполняет часть IPзаголовка. Контрольная сумма UDP считается теперь - часть IP-заголовка + UDPзаголовок + UDP данные. 4. UDP заполнено. Ставим Время жизни в IP заголовок, и считаем Контрольную сумму IP заголовка. При приеме аналогично. Контрольная сумма := Длина UDP; Время жизни := 0х00, Расчет контрольной суммы. Если рассчитанная контрольная сумма равна 0, она хранится как все единичные биты (65535), эти значения эквивалентны в арифметике с поразрядным дополнением (дополнение единицы) (ones-complement). Если переданная контрольная сумма равна 0, это означает, что отправитель не рассчитал контрольную сумму. Несмотря на то, что для контрольная сумма UDP - необязательный параметр, она должна рассчитываться всегда. В конце 1980-х годов некоторые производители компьютеров стали по умолчанию отключать расчет контрольной суммы UDP, чтобы увеличить скорость работы сетевой файловой системы (NFS - Network File System), которая использует UDP. Это может быть допустимым в одной локальной сети, где рассчитывается циклический избыточный код для фреймов на канальном уровне (фреймы Ethernet или Token ring), с помощью которого можно определить повреждение фрейма, когда датаграмма проходит через маршрутизаторы. Поверите Вы или нет, но существуют маршрутизаторы, у которых есть ошибки в программном или аппаратном обеспечении и которые изменяют биты в датаграммах, которые они маршрутизируют. Эти ошибки не могут быть выявлены в UDP датаграммах, если отключена опция контрольной суммы. Также необходимо отметить, что некоторые протоколы канального уровня (например, SLIP) не имеют каких-либо форм расчета контрольной суммы для данных в канале.