2010-01-19 16 views
1

Ce qui suit est un programme qui capture les paquets TCP < port 80> et imprime des informations liées à l'en-tête dans la console pour chaque paquet. J'ai également inclus une minuterie, de sorte qu'après tous les 1000 millisecondes, c'est-à-dire 1 seconde, la fréquence d'apparition de divers drapeaux, et le nombre distinct d'IP Src, Ack ns et Seq ns rencontrés sont écrits dans un fichier. Je travaille dans Fedora Core 5. Je rencontre les problèmes suivants:besoin d'aide concernant un programme de capture de paquets

1.File partie d'écriture fonctionne très bien pendant certaines exécutions, mais la plupart du temps, dans la même machine, le fichier n'est pas du tout écrit à. 2. Lorsque j'exécute ce programme dans ma maison, environ 30 paquets sont capturés chaque seconde. Mais quand je cours le même programme dans mon laboratoire, seulement 1 paquet est capturé par seconde. (Bien que je fais la même quantité de navigation dans les deux endroits)

#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; 
} 

Comme cela est une partie de mon projet, je suis actuellement coincé à ce moment .. Quelqu'un peut-il s'il vous plaît suggérer au sujet de ce qui a pu se passer .. Merci d'avance.

+0

vous ne nous avez pas dit le système d'exploitation ou le matériel. – bmargulies

+0

Fedora core 5 .. – trinity

+0

à la maison, le pgm écoute l'interface eth0, et dans le laboratoire, il écoute l'interface em0 .. cette information suffit .. – trinity

Répondre

2

Avez-vous essayé fflush()?

+0

j'ai essayé après votre suggestion, ce fflush() a aidé à résoudre le problème, merci . – trinity

0

Je pourrais résoudre le problème no [2], avec juste un petit changement dans l'expression du filtre: je l'ai changé de "tcp port 80" à "tcp". Et maintenant, ce programme fonctionne aussi bien dans mon laboratoire qu'à la maison.

encore, le problème no [1] n'est pas encore résolu .. Et de plus, l'écriture du fichier ne suit pas le rythme de la console i/o .. Au moment où la console affiche les détails de capture pendant 120 secondes, le fichier a seulement environ 90 secondes - données remplies .. Je me demande si c'est un problème général avec le fichier i/o ..

+0

Peut-être qu'il y a un différence dans Fedora/FreeBSD par rapport au fichier i/o? Avez-vous mesuré le timing sur les deux plates-formes? N'oubliez pas, il y a d'autres facteurs en jeu, pagination, chargement de cpu, exécution de X?, Reniflage de paquets peut mettre une charge sur le cpu aussi .. – t0mm13b