4.2. Корректировка контрольной суммы
Преобразования NAT выполняются для каждого пакета и могут приводить к значительным расходам вычислительных ресурсов при необходимости корректировки одной или нескольких контрольных сумм в дополнение к простой замене полей. К счастью существует приведенный ниже алгоритм, делающий корректировку контрольных сумм заголовков IP, TCP, UDP и ICMP очень простой и эффективной. Поскольку все эти заголовки используют арифметику дополнения до 1, достаточно рассчитать разность между адресами до и после трансляции и добавить полученное значение к контрольной сумме. Приведенный ниже алгоритм применим только для случаев четного смещения (т. е., поле optr должно начинаться с четного октета от начала заголовка) и четной длины (т. е., поля olen и nlen должны иметь четные значения). Ниже приведен вариант реализации алгоритма на языке C.
void checksumadjust(unsigned char *chksum, unsigned char *optr,
int olen, unsigned char *nptr, int nlen)
/* Допущения: unsigned char имеет размер 8 битов, long - 32 бита.
- chksum указывает контрольную сумму пакета
- optr указывает старые данные в пакете
- nptr указывает новые данные в пакете
*/
{
long x, old, new;
x=chksum[0]*256+chksum[1];
x=~x & 0xFFFF;
while (olen)
{
old=optr[0]*256+optr[1]; optr+=2;
x-=old & 0xffff;
if (x<=0) { x--; x&=0xffff; }
olen-=2;
}
while (nlen)
{
new=nptr[0]*256+nptr[1]; nptr+=2;
x+=new & 0xffff;
if (x & 0x10000) { x++; x&=0xffff; }
nlen-=2;
}
x=~x & 0xFFFF;
chksum[0]=x/256; chksum[1]=x & 0xff;
}