Почему моя программа чтения пакетов возвращает неверные данные? - PullRequest
0 голосов
/ 28 ноября 2011

Я написал программу чтения пакетов, которая использует libpcap для чтения файла захвата.Он читает файл захвата и загружает захваченные данные в базу данных MySQL.Иногда кажется, что он работает нормально, а в других он возвращает недопустимые данные (например, IP-адрес источника и получателя будет одинаковым, все порты TCP являются ненужными).Я запускаю это под виртуальным RHEL 5. Вот мой код (извините, если он довольно длинный или излишне запутанный, это моя первая попытка сделать это).

#include <arpa/inet.h>
#include <net/ethernet.h>

#include <netinet/ether.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#include "npc_tcp.h"
#include "npc_udp.h"

#include <ftw.h>
#include <pcap.h>
#include <stdio.h>
#include <sys/stat.h>
#include <regex.h>
#include <string.h>
#include <time.h>

const int IPTYPE_TCP = 6;
const int IPTYPE_UDP = 17;

struct cap_data {
  char ts[64];
  u_int16_t ether_type;
  u_int16_t proto;
  char *srcip;
  char *dstip;
  char *srcmac;
  u_int16_t srcport;
  u_int16_t dstport;
  u_int8_t flags;
  u_int capsize;
};

int main(int argc, char **argv) {

  //pcap
  struct cap_data data;
  struct pcap_pkthdr pkthdr;
  const u_char *packet;
  pcap_t *handle;
  char *fname = argv[1];
  printf("%s\n", fname);
  char errbuf[PCAP_ERRBUF_SIZE]; 
  handle = pcap_open_offline(fname, errbuf);
  char buf[1000];

  while (packet = pcap_next(handle, &pkthdr)) {

    int ether_flag;
    struct ether_header *ether;    
    u_short ether_type;           

    ether = (struct ether_header *) packet;
    data.ether_type = ntohs(ether->ether_type);

    ether_flag = 1;

    if (ether_flag) {
      if (data.ether_type == ETHERTYPE_IP) {
        struct ip *ip_hdr;
        u_int length = pkthdr.len;

        ip_hdr = (struct ip *)(packet + sizeof(struct ether_header));

      data.proto = ip_hdr->ip_p;
      data.dstip = inet_ntoa(ip_hdr->ip_dst);
      data.srcip = inet_ntoa(ip_hdr->ip_src);

      if (data.proto == IPTYPE_TCP) {
        struct tcphdr *tcp;
        tcp = (struct tcphdr*)(packet + sizeof(struct ether_header) + 
                sizeof(struct ip));

        data.srcport = tcp->th_sport;
        data.dstport = tcp->th_dport;

        printf("%s %u   %s %u\n\n", inet_ntoa(ip_hdr->ip_src), tcp->th_sport, inet_ntoa(ip_hdr->ip_dst), tcp->th_dport);

      } else if (data.proto == IPTYPE_UDP) {
        struct udphdr *udp;
        udp = (struct udphdr *)(packet + sizeof(struct ether_header) + 
                sizeof(struct ip));
        data.srcport = udp->uh_sport;
        data.dstport = udp->uh_dport;

        printf("%s %u   %s %u\n\n", inet_ntoa(ip_hdr->ip_src), udp->uh_sport, inet_ntoa(ip_hdr->ip_dst), udp->uh_dport);

        }
      }
    }
  }//while

  pcap_close(handle);

  return 0;
} 

ОБНОВЛЕНИЕ:

Это выводит ..

source ip      port   dest ip       port

66.68.236.207 30151     66.68.236.207 47873

172.22.162.235 60920    172.22.162.235 36175

67.207.28.150 23007     67.207.28.150 22038

172.22.162.235 60920    172.22.162.235 36175

67.207.28.151 22038     67.207.28.151 23007

65.55.87.43 20480       65.55.87.43 21764

67.207.28.150 23007     67.207.28.150 22038

Адреса не должны быть одинаковыми, а номера портов также неверны.

Я не знаю, с чего начать поиск ошибок, как мой код(по крайней мере для меня) выглядит правильно.Любая помощь, советы или советы будут с благодарностью.Спасибо:)

Ответы [ 2 ]

1 голос
/ 01 января 2012

Две проблемы:

  1. inet_ntoa возвращает указатель на статический буфер.
    При вызове его дважды в одном и том же printf он перезаписывает один и тот же буфер.Таким образом, вы в конечном итоге печатаете одни и те же данные.
    Вместо этого используйте inet_ntop и присваивайте каждому вызову отдельный буфер.

  2. Вы должны использовать ntohs () для преобразования портов вхост-заказ перед печатью.

0 голосов
/ 01 января 2012

Что произойдет, если сразу после звонка pcap_open_offline() вы выполните

if (pcap_datalink(handle) != DLT_EN10MB) {
  fprintf(stderr, "This program handles only Ethernet captures\n");
  return 2;
}
...