@kuzko

Как прочитать заголовок PCAP пакета c/c++?

Я пытаюсь понять как прочитать IP Source и Destination из заголовка и данные из pcap файла
#include <string>
#include <iostream>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <sys/types.h>
using namespace std;

#define ETHER_ADDR_LEN 6
#define SIZE_ETHERNET 14


 struct sniff_ethernet {
    u_char ether_dhost[ETHER_ADDR_LEN]; /* Адрес назначения */
    u_char ether_shost[ETHER_ADDR_LEN]; /* Адрес источника */
    u_short ether_type;
 };

 /* IP header */
 struct sniff_ip {
    u_char ip_vhl;  /* версия << 4 | длина заголовка >> 2 */
    u_char ip_tos;  /* тип службы */
    u_short ip_len;  /* общая длина */
    u_short ip_id;  /* идентефикатор */
    u_short ip_off;  /* поле фрагмента смещения */
    #define IP_RF 0x8000  /* reserved флаг фрагмента */
    #define IP_DF 0x4000  /* dont флаг фрагмента */
    #define IP_MF 0x2000  /* more флаг фрагмента */
    #define IP_OFFMASK 0x1fff /* маска для битов фрагмента */
    u_char ip_ttl;  /* время жизни */
    u_char ip_p;  /* протокол */
    u_short ip_sum;  /* контрольная сумма */
   // struct in_addr ip_src,ip_dst; /* адрес источника и адрес назначения */
    struct in_addr ip_src,ip_dst;
 };
 #define IP_HL(ip)  (((ip)->ip_vhl) & 0x0f)
 #define IP_V(ip)  (((ip)->ip_vhl) >> 4)

int main(int argc, char *argv[])
{
  pcap_t *pcap;
  char errbuf[PCAP_ERRBUF_SIZE];
  struct sniff_ethernet *ethernet; /* Заголовок Ethernet */
  const struct sniff_ip *ip; /* Заголовок IP */
  struct pcap_pkthdr *header;
  const u_char *data;
  u_int packetCount = 0;

  if(argc != 2)
  {
    printf("usage: %s filename", argv[0]);
    return -1;
  }
  
  if ((pcap = pcap_open_offline(argv[1],errbuf )) == NULL)
  {
    fprintf(stderr,"\nUnable to open the file %s.\n", argv[1]);
    return -1;
  }

  while (int returnValue = pcap_next_ex(pcap, &header, &data) >= 0)
  {
    printf("Packet # %i\n", ++packetCount);
    printf("Packet size: %d bytes\n", header->len);

    ethernet = (struct sniff_ethernet*)(data);
    ip = (struct sniff_ip*)(data + SIZE_ETHERNET);
    printf("src address: %s dest address: %s \n",  inet_ntoa(ip->ip_src),  inet_ntoa(ip->ip_dst));
    
    printf("ETH\tsource: %s", (char *) ether_ntoa((struct ether_addr *) & ethernet->ether_shost));
    printf(" dest: %s\n", (char *) ether_ntoa((struct ether_addr *) & ethernet->ether_dhost));


    if (header->len != header->caplen)
      printf("Warning! Capture size different than packet size: %ld bytes\n", header->len);

    printf("Epoch Time: %d:%d seconds\n", header->ts.tv_sec, header->ts.tv_usec);

    for (u_int i = 0; (i < header->caplen); i++)
    {
      if ((i % 16) == 0) printf("\n");
      printf("%.2x ", data[i]);
    }
    printf("\n\n");
  }
}


IP адреса Source и Destination выводятся одинаковыми и не совпадают с информацией из Wireshark. Не могу понять в чем ошибка.

Например выводится:
src address: 15.210.194.66 dest address: 15.210.194.66

А должно быть:
src address: 172.30.255.18 dest address: 224.0.0.5
  • Вопрос задан
  • 678 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
IP адреса Source и Destination выводятся одинаковыми

Из man inet_ntoa:

The string is returned in a statically allocated buffer,
which subsequent calls will overwrite.


С вот таким изменением твой код у меня работает как ожидалось:
printf("src address: %s ",  inet_ntoa(ip->ip_src));
printf("dest address: %s\n",  inet_ntoa(ip->ip_dst));


Подозреваю, что совсем левые IP могут лезть из не-IP кадров. Проверяй поле протокола в ethernet заголовке перед тем как начинать разбор IP-заголовка.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы