2016-05-20 3 views
3

пытался исправить этот код на некоторое время без везения, пробовал различные варианты реализацию, которые рассчитывают контрольную сумму заголовка IPv4, однако их выход сильно отличается от моей программы выхода:IPv4, то, что я упускаю

Функция я украл из Linux kernel сделать это:

static inline uint16_t ip_fast_csum(const void *iph, unsigned int ihl){ 

    unsigned int sum; 

    asm(" movl (%1), %0\n" 
     " subl $4, %2\n" 
     " jbe 2f\n" 
     " addl 4(%1), %0\n" 
     " adcl 8(%1), %0\n" 
     " adcl 12(%1), %0\n" 
     "1: adcl 16(%1), %0\n" 
     " lea 4(%1), %1\n" 
     " decl %2\n" 
     " jne  1b\n" 
     " adcl $0, %0\n" 
     " movl %0, %2\n" 
     " shrl $16, %0\n" 
     " addw %w2, %w0\n" 
     " adcl $0, %0\n" 
     " notl %0\n" 
     "2:" 
    /* Since the input registers which are loaded with iph and ihl 
     are modified, we must also specify them as outputs, or gcc 
     will assume they contain their original values. */ 
     : "=r" (sum), "=r" (iph), "=r" (ihl) 
     : "1" (iph), "2" (ihl) 
     : "memory"); 
    return (uint16_t)sum; } 

заголовок образца (байт): 45009d4326400406af6cd052ed12ac10a51

Раздел моей программы, которая вызывает выше Функция присваивает контрольную сумму в заголовок и печатает заголовок, а также контрольную сумму:

newpacket.ipheader->check = ip_fast_csum ((unsigned short *) newpacket.ipheader, IP4_HDRLEN); 
    debug(5,"newpacket checksum set to %0x\r\n",newpacket.ipheader->check); 
    uint8_t *ipbuf=(uint8_t *)newpacket.ipheader; 
    for(i=0;i<IP4_HDRLEN;i++){ 
    debug(5,"%0x",ipbuf[i]); 
    }debug(5,"\n"); 

отладки() является просто Е() обертки, Ниже приведен пример вывода:

newpacket checksum set to 6caf 
45009d4326400406af6cd052ed12ac10a51 

ScreenCap от чего Wireshark говорит мне:

wiresharkcap

Можете ли вы помочь мне и сказать мне, что я делаю неправильно?

Это функция, которую я обычно использую:

inline unsigned short csum (unsigned short *buf, int nwords) { 
    unsigned long sum; 

    for (sum = 0; nwords > 0; nwords--) 
      sum += *buf++; 
    sum = (sum >> 16) + (sum & 0xffff); 
    sum += (sum >> 16); 
    return (unsigned short) (~sum); 
} 

Спасибо заранее.

+1

[RFC 1071] (https://tools.ietf.org/html/rfc1071), [RFC 1141] (https://tools.ietf.org/html/rfc1141) и [RFC 1624] (https : //tools.ietf.org/html/rfc1624) являются источниками, которые дают вам алгоритм вычисления контрольной суммы заголовка IPv4. –

+2

Похоже, вы рассчитываете контрольную сумму IP-заголовка. Кажется, что Wireshark отображает контрольную сумму TCP-заголовка. – SergeyA

+0

Просто для расширения на @SergeyA кажется, что вы поместили контрольную сумму IP-уровня в уровень TCP. Или в более «официальных» условиях. https://en.wikipedia.org/wiki/OSI_model Вы смешиваете слой 3 и 4. – arduic

ответ

0

Просто чтобы немного увеличить @SergeyA от комментариев и меня немного больше. Если вы посмотрите на файл, который вы ссылочный above, вы заметите в комментариях для этой функции

ip_fast_csum - вычислят контрольную сумму заголовка IPv4 эффективен.

Вы не хотите вычислять контрольную сумму заголовка IPv4, для которой требуется контрольная сумма TCP. Это отдельные слои в модели OSI, найденной here. Чтобы вычислить контрольную сумму TCP, вам нужно сделать как these прекрасные люди.

Используя только код ядра, который вы хотели бы сделать ранее, здесь найдена функция, которая должна вычислять контрольную сумму TCP. Ниже я скопирую описание и заголовок.

static inline __sum16 tcp_v4_check(int len, __be32 saddr, 
            __be32 daddr, __wsum base) 
  • Вычислить (/ проверить) TCP контрольной суммы

Если же вы хотите сделать это трудный путь. Глядя в том же файле, на который вы ссылаетесь, вы можете рассчитать псевдо-заголовок для TCP-пакетов, используя эту функцию.

csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, 
       __u8 proto, __wsum sum) 

Возвращает заголовке псевдо контрольную сумму входных данных. Результат - 32 бит. развернут.

Это только заголовок псевдо, хотя оттуда нужно вычислить общую контрольную сумму, которую я ПОЛАГАТЬ (не 100% уверен) вы можете просто использовать функцию, которую вы показали ранее, чтобы вычислить, если вы подушечка заголовок псевдо описывалось ранее на него.

В стороне я не проверял этот код, но он кажется довольно точным с первого взгляда, поэтому here - это способ подсчета контрольной суммы TCP.

+0

Привет, контрольная сумма TCP в порядке, у меня есть отдельная функция, которая вычисляет it.wireshark показывает хорошую контрольную сумму tcp, поэтому я не беспокоюсь об этом, для контрольной суммы TCP нужен заголовок tcp heder + data + ip pseudo. это для контрольной суммы заголовка ipv4, которая является отдельной и строго предназначена для заголовка ipv4. https://en.wikipedia.org/wiki/IPv4_header_checksum – misterdobalina

+0

А как я ошибаюсь из представленного вами изображения и текста, который, как я думал, вы поставили контрольную сумму IP в поле TCP. Извини за это. – arduic

0

Просто хотел опубликовать это и решить этот вопрос, я решил эту проблему, попробовав множество функций, единственное, что работает, - это код Suricata IDPS.

static inline uint16_t IPV4CalculateChecksum(uint16_t *pkt, uint16_t hlen) 
{ 
    uint32_t csum = pkt[0]; 

    csum += pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[6] + pkt[7] + pkt[8] + 
     pkt[9]; 

    hlen -= 20; 
    pkt += 10; 

    if (hlen == 0) { 
     ; 
    } else if (hlen == 4) { 
     csum += pkt[0] + pkt[1]; 
    } else if (hlen == 8) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3]; 
    } else if (hlen == 12) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5]; 
    } else if (hlen == 16) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7]; 
    } else if (hlen == 20) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9]; 
    } else if (hlen == 24) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11]; 
    } else if (hlen == 28) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13]; 
    } else if (hlen == 32) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + 
      pkt[14] + pkt[15]; 
    } else if (hlen == 36) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + 
      pkt[14] + pkt[15] + pkt[16] + pkt[17]; 
    } else if (hlen == 40) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + 
      pkt[14] + pkt[15] + pkt[16] + pkt[17] + pkt[18] + pkt[19]; 
    } 

    csum = (csum >> 16) + (csum & 0x0000FFFF); 
    csum += (csum >> 16); 

    return (uint16_t) ~csum; 
} 

https://github.com/inliniac/suricata/blob/master/src/decode-ipv4.h

Я надеюсь, что это помогает другим тоже Suricata имеет отличную базу кода, хорошо написано рабочий код тоже.

Приветствуем вас и благодарим за каждого, кто пытался помочь.

Смежные вопросы