2010-01-19 9 views
1

Ниже приведена программа, которая захватывает TCP-пакеты < порт 80> и печатает информацию, связанную с заголовком, в консоли для каждого пакета. Я также включил таймер, так что после каждых 1000 миллисекунд, то есть 1 сек, частота появления различных флагов и различное количество IP-адресов Src, Ack nos и Seq nos были записаны в файл. Я работаю в ядре fedora 5. Я столкнулся со следующими проблемами:нужна помощь в отношении программы захвата пакетов

1. файл для записи в файл. Отлично работает во время некоторых исполнений, но в большинстве случаев, на том же компьютере, файл совсем не написан к.

2.Когда я выполняю эту программу в своем доме, около 30 пакетов захватываются каждую секунду. Но когда я запускаю одну и ту же программу в своей лаборатории, только 1 пакет фиксируется в секунду. (Хотя я сделать то же самое количество просмотра в обоих местах)

#define INTERVAL 1000  /* number of milliseconds to go off */ 

#include <pcap.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <sys/time.h> // for setitimer 
#include<unistd.h> // for pause 
#include <signal.h>  /* for signal */ 

/* default snap length (maximum bytes per packet to capture) */ 
#define SNAP_LEN 1518 

/* ethernet headers are always exactly 14 bytes [1] */ 
#define SIZE_ETHERNET 14 

/* Ethernet addresses are 6 bytes */ 
#define ETHER_ADDR_LEN 6 

/* Ethernet header */ 
struct sniff_ethernet { 
     u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */ 
     u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */ 
     u_short ether_type;      /* IP? ARP? RARP? etc */ 
}; 

/* IP header */ 
struct sniff_ip { 
     u_char ip_vhl;     /* version << 4 | header length >> 2 */ 
     u_char ip_tos;     /* type of service */ 
     u_short ip_len;     /* total length */ 
     u_short ip_id;     /* identification */ 
     u_short ip_off;     /* fragment offset field */ 
     #define IP_RF 0x8000   /* reserved fragment flag */ 
     #define IP_DF 0x4000   /* dont fragment flag */ 
     #define IP_MF 0x2000   /* more fragments flag */ 
     #define IP_OFFMASK 0x1fff  /* mask for fragmenting bits */ 
     u_char ip_ttl;     /* time to live */ 
     u_char ip_p;     /* protocol */ 
     u_short ip_sum;     /* checksum */ 
     struct in_addr ip_src,ip_dst; /* source and dest address */ 
}; 
#define IP_HL(ip)    (((ip)->ip_vhl) & 0x0f) 
#define IP_V(ip)    (((ip)->ip_vhl) >> 4) 

/* TCP header */ 
typedef u_int tcp_seq; 

struct sniff_tcp { 
     u_short th_sport;    /* source port */ 
     u_short th_dport;    /* destination port */ 
     tcp_seq th_seq;     /* sequence number */ 
     tcp_seq th_ack;     /* acknowledgement number */ 
     u_char th_offx2;    /* data offset, rsvd */ 
#define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4) 
     u_char th_flags; 
     #define TH_FIN 0x01 
     #define TH_SYN 0x02 
     #define TH_RST 0x04 
     #define TH_PUSH 0x08 
     #define TH_ACK 0x10 
     #define TH_URG 0x20 
     #define TH_ECE 0x40 
     #define TH_CWR 0x80 
     #define TH_FLAGS  (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) 
     u_short th_win;     /* window */ 
     u_short th_sum;     /* checksum */ 
     u_short th_urp;     /* urgent pointer */ 
}; 

u_short sport[100];int spd=0; 
u_int seq[100];int seqd=0; 
u_short win[100];int wind=0; 

FILE* urlfile; 
int count = 1,flag=0,t=0; 
float sc=0,ac=0,fc=0,pc=0,uc=0,rc=0; 

void 
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet); 

void 
print_payload(const u_char *payload, int len); 

void 
print_hex_ascii_line(const u_char *payload, int len, int offset); 



void 
print_app_usage(void); 

void DoStuff(void); 

void DoStuff(void) { 
    t++; 
    printf("Timer %d went off.########################################\n",t); 
// fprintf(urlfile,"\n hi hi"); 
    fprintf(urlfile,"\ntime %d 1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f 9:%f",t,sc/count,ac/count,fc/count,pc/count,uc/count,rc/count,(float)spd/count,(float)wind/count,(float)seqd/count); 
    printf("\ntime %d 1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f 9:%f",t,sc/count,ac/count,fc/count,pc/count,uc/count,rc/count,(float)spd/count,(float)wind/count,(float)seqd/count); 
    printf("\n a_count : %f , total_packets : %d , frequency : %f",ac,count,ac/count); 
    printf("\n r_count : %f , total_packets : %d , frequency : %f",rc,count,rc/count); 
    printf("\n p_count : %f , total_packets : %d , frequency : %f",pc,count,pc/count); 
    printf("\n s_count : %f , total_packets : %d , frequency : %f",sc,count,sc/count); 
    printf("\n u_count : %f , total_packets : %d , frequency : %f",uc,count,uc/count); 
    printf("\n f_count : %f , total_packets : %d , frequency : %f",fc,count,fc/count); 
    printf("\ncount of distinct seq nos : %d no/pcount : %f ",seqd,(float)seqd/count); 
    printf("\ncount of distinct sports : %d no/pcount : %f ",spd,(float)spd/count); 
    printf("\ncount of distinct win nos : %d no/pcount : %f\n\n ",wind,(float)wind/count); 
    ac=rc=pc=fc=sc=uc=0;count=1; 
    spd=seqd=wind=0; 
} 


void 
print_app_usage(void) 
{ 

    printf("Usage: ./a.out [interface]\n"); 
    printf("\n"); 
    printf("Options:\n"); 
    printf(" interface Listen on <interface> for packets.\n"); 
    printf("\n"); 

return; 
} 


/* 
* dissect/print packet 
*/ 
void 
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) 
{ 

         /* packet counter */ 
    int j; 
    /* declare pointers to packet headers */ 
    const struct sniff_ethernet *ethernet; /* The ethernet header [1] */ 
    const struct sniff_ip *ip;    /* The IP header */ 
    const struct sniff_tcp *tcp;   /* The TCP header */ 
    const char *payload;     /* Packet payload */ 

    int size_ip; 
    int size_tcp; 
    int size_payload; 

    printf("\nPacket number %d:\n", count); 
    count++; 

    /* define ethernet header */ 
    ethernet = (struct sniff_ethernet*)(packet); 

    /* define/compute ip header offset */ 
    ip = (struct sniff_ip*)(packet + SIZE_ETHERNET); 
    size_ip = IP_HL(ip)*4; 
    if (size_ip < 20) { 
     printf(" * Invalid IP header length: %u bytes\n", size_ip); 
     return; 
    } 

    switch(ip->ip_p) { 
     case IPPROTO_TCP: 
      printf(" Protocol: TCP\n"); 
      break; 
     case IPPROTO_UDP: 
      printf(" Protocol: UDP\n"); 
      return; 
     case IPPROTO_ICMP: 
      printf(" Protocol: ICMP\n"); 
      return; 
     case IPPROTO_IP: 
      printf(" Protocol: IP\n"); 
      return; 
     default: 
      printf(" Protocol: unknown\n"); 
      return; 
    } 

    /* define/compute tcp header offset */ 
    tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip); 
    size_tcp = TH_OFF(tcp)*4; 
    if (size_tcp < 20) { 
     printf(" * Invalid TCP header length: %u bytes\n", size_tcp); 
     return; 
    } 

    flag=0; 
    for(j=0;j<spd;j++) 
    {  
     if(sport[j]==ntohs(tcp->th_sport)) { flag=1; break; } 
    } 
    if(flag==0) sport[spd++]=ntohs(tcp->th_sport); 

    flag=0; 
    for(j=0;j<seqd;j++) 
    {  
     if(seq[j]==ntohs(tcp->th_seq)) { flag=1; break; } 
    } 
    if(flag==0) seq[seqd++]=ntohs(tcp->th_seq); 

    flag=0; 
    for(j=0;j<wind;j++) 
    {  
     if(win[j]==ntohs(tcp->th_win)) { flag=1; break; } 
    } 
    if(flag==0) win[wind++]=ntohs(tcp->th_win); 

    printf(" Src port: %d\n", ntohs(tcp->th_sport)); 
    printf(" Window: %d\n", ntohs(tcp->th_win)); 
    printf(" Sequence no: %d\n", ntohs(tcp->th_seq)); 

    if (tcp->th_flags & TH_URG){ 
     printf(" Flag: TH_URG");uc++; 
    } 
    if (tcp->th_flags & TH_RST){ 
     printf(" Flag: TH_RST");rc++; 
    } 
    if (tcp->th_flags & TH_ACK){ 
     printf(" Flag: TH_ACK");ac++; 
    } 
    if (tcp->th_flags & TH_PUSH){ 
     printf(" Flag: TH_PUSH");pc++; 
    } 
    if (tcp->th_flags & TH_SYN){ 
     printf(" Flag: TH_SYN");sc++; 
    } 
    if (tcp->th_flags & TH_FIN){ 
     printf(" Flag: TH_FIN");fc++; 
    } 


    if (size_payload > 0) { 
     printf(" Payload (%d bytes):\n", size_payload); 

    } 

return; 
} 

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

    char *dev = NULL;   /* capture device name */ 
    char errbuf[PCAP_ERRBUF_SIZE];  /* error buffer */ 
    pcap_t *handle;    /* packet capture handle */ 
    char filter_exp[] = "tcp port 80"; 
    struct bpf_program fp;   /* compiled filter program (expression) */ 
    bpf_u_int32 mask;   /* subnet mask */ 
    bpf_u_int32 net;   /* ip */ 
    //int num_packets = 10;   /* number of packets to capture */ 

    /* check for capture device name on command-line */ 
    if (argc == 2) { 
     dev = argv[1]; 
    } 
    else if (argc > 2) { 
     fprintf(stderr, "error: unrecognized command-line options\n\n"); 
     print_app_usage(); 
     exit(EXIT_FAILURE); 
    } 
    else { 
     /* find a capture device if not specified on command-line */ 
     dev = pcap_lookupdev(errbuf); 
     if (dev == NULL) { 
      fprintf(stderr, "Couldn't find default device: %s\n", 
       errbuf); 
      exit(EXIT_FAILURE); 
     } 
    } 

    /* get network number and mask associated with capture device */ 
    if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { 
     fprintf(stderr, "Couldn't get netmask for device %s: %s\n", 
      dev, errbuf); 
     net = 0; 
     mask = 0; 
    } 

    /* print capture info */ 
    printf("Device: %s\n", dev); 
    printf("Filter expression: %s\n", filter_exp); 

    /* open capture device */ 
    handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); 
    if (handle == NULL) { 
     fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); 
     exit(EXIT_FAILURE); 
    } 

    /* make sure we're capturing on an Ethernet device [2] */ 
    if (pcap_datalink(handle) != DLT_EN10MB) { 
     fprintf(stderr, "%s is not an Ethernet\n", dev); 
     exit(EXIT_FAILURE); 
    } 

    /* compile the filter expression */ 
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { 
     fprintf(stderr, "Couldn't parse filter %s: %s\n", 
      filter_exp, pcap_geterr(handle)); 
     exit(EXIT_FAILURE); 
    } 

    /* apply the compiled filter */ 
    if (pcap_setfilter(handle, &fp) == -1) { 
     fprintf(stderr, "Couldn't install filter %s: %s\n", 
      filter_exp, pcap_geterr(handle)); 
     exit(EXIT_FAILURE); 
    } 

    urlfile=fopen("output.txt","w"); 
    if(urlfile==NULL) printf("Unable to create file."); 

    // timer code 

    struct itimerval it_val; /* for setting itimer */ 

    /* Upon SIGALRM, call DoStuff(). 
    * Set interval timer. We want frequency in ms, 
    * but the setitimer call needs seconds and useconds. */ 
    if (signal(SIGALRM, (void (*)(int)) DoStuff) == SIG_ERR) { 
    perror("Unable to catch SIGALRM"); 
    exit(1); 
    } 
    it_val.it_value.tv_sec =  INTERVAL/1000; 
    it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000; 
    it_val.it_interval = it_val.it_value; 
    if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { 
    perror("error calling setitimer()"); 
    exit(1); 
    } 

    /* now we can set our callback function */ 
    //pcap_loop(handle, num_packets, got_packet, NULL); 
    pcap_loop(handle,-1, got_packet, NULL);// set num_packets to -1 to capture indefinitely. 
    /* cleanup */ 
    pcap_freecode(&fp); 
    pcap_close(handle); 
    fclose(urlfile); 
    printf("\nCapture complete.\n"); 

return 0; 
} 

Поскольку это является частью моего проекта, я сейчас застрял на данный момент .. Может кто-нибудь пожалуйста, предложить относительно того, что может пойти не так .. Заранее спасибо.

+0

вы не сказали нам о операционной системе или аппаратном обеспечении. – bmargulies

+0

Fedora core 5 .. – trinity

+0

у себя дома, pgm прослушивает интерфейс eth0, а в лаборатории он прослушивает интерфейс em0 .. эта информация достаточно. – trinity

ответ

2

Вы пробовали fflush()?

+0

Я попытался после вашего предложения, этот fflush() помог решить проблему, спасибо , – trinity

0

Я мог бы решить проблему no [2], только с небольшим изменением в выражении фильтра: я изменил ее с «tcp port 80» на «tcp». И теперь эта программа работает также в моей лаборатории, как и в моем доме.

все еще проблема № [1] еще не решена. И более того, запись в файле не идет в ногу с консольным вводом/выводом. К тому времени, когда консоль отображает данные захвата в течение 120 секунд, файл имеет только около 90 секунд - заполненные данные .. Интересно, является ли это общей проблемой с файлом i/o.

+0

Возможно, есть разница в Fedora/FreeBSD по отношению к файлу i/o? Вы оценили время на нем на обеих платформах? Не забывайте, что есть другие факторы в игре, пейджинге, загрузке процессора, запуске X ?, пакетное обнюхивание может также нагрузить процессор. – t0mm13b

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

  • Нет связанных вопросов^_^