Main Page   Data Structures   File List   Data Fields   Globals  

snoop.c

Go to the documentation of this file.
00001 
00052 #ifndef _SNOOP_C
00053 #define _SNOOP_C
00054 
00055 #include "common.h"
00056 #include "hashtable.h"
00057 #include "snoop.h"
00058 
00059 hashtable * ht;
00060 neighbor neighbors[2*MAXNEIGHBORS]; 
00061 int received, forwarded;
00062 FILE *logfile;
00063 
00064 void SIGALRM_handler(int sig){
00065     printf("<<<<<<<< SIGARLM >>>>>>>>>>\n");
00066     signal(sig, SIGALRM_handler);
00067     printf("Hashtable size was : %d\n", ht->count);
00068     // make a pass through the hashtable and upcount
00069     timer_update_state();
00070     printf("Hashtable size now, is : %d\n", ht->count);
00071     printf("<<<<<<<<<<<<<>>>>>>>>>>>>>>\n");
00072     print_neighbors();
00073     log_intrusions();
00074 
00075     alarm(ALARM_TIMEOUT);
00076 }
00077 
00078 
00079 void timer_update_state(void){
00080     int i;
00081     ht_bucket* htb;
00082     struct ether_header* ether_hdr;
00083     struct ether_addr* ether_dst;
00084     for(i=0;i<ht->size;i++){
00085         htb = &(const ht_bucket) ht->table[i];
00086         switch(htb->state){
00087                 case VALID:
00088                         htb->state = LATE;
00089                         break;
00090                 case LATE:
00091                         // already late, so assume dropped by node
00092                         // upcount neighbor's dropped packets
00093                         ether_hdr = (struct ether_header*) htb->packet;
00094                         ether_dst = (struct ether_addr*)(ether_hdr->ether_dhost);
00095                         incr_dropcount(ether_dst);
00096                         htb->state = DELETED; // mark for deletion
00097                         (ht->count)--;
00098                         break;
00099                 case INVALID:
00100                 case DELETED:
00101                 default:
00102                         // do nothing
00103         }
00104     }
00105 
00106 }
00107 
00108 
00109 
00110 /* looking at ethernet headers */
00111 void pkt_callback(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet){
00112     u_int16_t type = handle_ethernet(args,pkthdr,packet);
00113     if(type == ETHERTYPE_IPV6){
00114         /* handle IPv6 packet */
00115         handle_IPv6(args, pkthdr, packet);
00116     }
00117 }
00118 
00119 u_int16_t
00120 handle_ethernet(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet){
00121     u_int caplen = pkthdr->caplen;
00122     u_int length = pkthdr->len;
00123     struct ether_header *eptr;  /* net/ethernet.h */
00124     u_short ether_type;
00125 
00126     if (caplen < ETHER_HDRLEN)
00127     {
00128         fprintf(stdout,"Incomplete ethernet header info\n");
00129         return -1;
00130     }
00131 
00132     eptr = (struct ether_header *) packet;
00133     ether_type = ntohs(eptr->ether_type);
00134 
00135     return ether_type;
00136 }
00137 
00138 int
00139 handle_IPv6(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet){
00140   struct ip6_hdr *ip6;   // from netinet/ip6.h
00141   struct ether_header *ether;
00142   u_int length = pkthdr->len;  // length of packet from ethernet header
00143   u_int caplen = pkthdr->caplen;
00144   u_int hlen, off, version;
00145   int len,i;
00146   char *src;
00147   char ntop_buf[INET6_ADDRSTRLEN];
00148   u_int8_t nexthdr;
00149   const struct udphdr* udp_hdr; // from netinet/udp.h
00150   const struct tcphdr* tcp_hdr; // from netinet/tcp.h
00151   u_int16_t sport, dport, udplen, udpchecksum;
00152   u_int8_t rawpacket[1500];
00153   u_char* packet_hdrs;
00154   u_int8_t aodv_type;
00155   u_int32_t seqno;
00156   neighbor n_pair;
00157 
00158   // skip past the ethernet header to the ip6 header
00159 
00160   ether = (const struct ether_header*) packet;
00161 
00162   ip6 = (const struct ip6_hdr *) (packet + sizeof(struct ether_header));
00163   
00164   length-=sizeof(struct ether_header);
00165 
00166   // check if packet is truncated
00167 
00168   if(length < sizeof(struct ip6_hdr)){
00169           printf("Truncated ip6 packet %d\n",length);
00170           return -1;
00171   }
00172 
00173   len = ntohs(ip6->ip6_plen);
00174 
00175   src = inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf));
00176   src = inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf));
00177 
00178   memcpy(rawpacket, ip6, len);
00179   packet_hdrs = (u_char *) malloc(sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
00180   if(NULL==packet_hdrs){
00181       printf("Couldn't allocate mem. for packet, ignoring this one !\n");
00182   }
00183   else{
00184     memcpy(packet_hdrs, packet, sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
00185   }
00186 
00187   nexthdr = ip6->ip6_nxt;
00188 
00189   switch(nexthdr){
00190           case IP_PROTO_TCP:
00191                   tcp_hdr = (const struct tcphdr *) (rawpacket + sizeof(struct ip6_hdr));
00192                   sport = ntohs(tcp_hdr->source);
00193                   dport = ntohs(tcp_hdr->dest);
00194                   seqno = ntohl(tcp_hdr->seq);
00195 
00196                   // check if destip == destether   => makeEntry
00197                   // and check if srcip == srcether => performID
00198 
00199                   memcpy(&n_pair.src_ether,&ether->ether_shost,6);
00200                   memcpy(&n_pair.src_ip6,&ip6->ip6_src,16);
00201 
00202                   if(-1==find_neighbor(&n_pair)){
00203                       // src ether != src ip6
00204                       printf("#############################\n");
00205                       printf("source(ether)!=source(ip6), FORWARDED = %d\n",++forwarded );
00206                       printf("#############################\n");
00207 
00208                       if(NULL!=packet_hdrs)
00209                           performID(ht, packet_hdrs,time(NULL));
00210                   }
00211                   
00212                   memcpy(&n_pair.src_ether,&ether->ether_dhost,6);
00213                   memcpy(&n_pair.src_ip6,&ip6->ip6_dst,16);
00214 
00215                   if(-1==find_neighbor(&n_pair)){
00216                       //dst ether != dest ip6
00217                       printf("#############################\n");
00218                       printf("dest(ether)!= dest(ip6), RECEIVED = %d\n", ++received);
00219                       printf("#############################\n");
00220                       // These are the packets that we want to snoop on
00221                       if(NULL!=packet_hdrs)
00222                           makeEntry(ht, packet_hdrs,time(NULL));
00223                   }
00224                   break;
00225                   
00226           case IP_PROTO_UDP:
00227                   udp_hdr = (const struct udphdr *) (rawpacket + sizeof(struct ip6_hdr));
00228                   sport = ntohs(udp_hdr->source);
00229                   dport = ntohs(udp_hdr->dest);
00230                   udplen = ntohs(udp_hdr->len);
00231                   udpchecksum = ntohs(udp_hdr->check);
00232 
00233                   if((654==sport)&&(654==dport))
00234                       handle_AODV(packet);
00235                   // else non-AODV payload
00236                   break;
00237                   
00238           case IP_PROTO_ICMPV6:
00239                   break;
00240                   
00241           default:
00242                 // other 
00243   }
00244   
00245   return 0;
00246 }
00247 
00248 
00249 int handle_AODV(const u_char* packet){
00250     u_int8_t type, flags, hops, prefixsize;
00251     u_int32_t reqid, dsn, osn, lifetime;
00252     struct ether_header * ether;
00253     struct ip6_hdr * ip6;
00254     struct aodv_rreq6_draft_01* rreq;
00255     struct aodv_rrep6_draft_01* rrep;
00256     neighbor aodv_pair, interface_pair;
00257     char * addr;
00258     char ntop_buf[INET6_ADDRSTRLEN];
00259     int i;
00260     union aodv* aodvpacket;
00261     
00262 
00263 
00264     aodvpacket = (const union aodv *)
00265             (  packet
00266                + sizeof(struct ether_header)
00267                + sizeof(struct ip6_hdr)
00268                + sizeof(struct udphdr) ) ;
00269     
00270     type = aodvpacket->rrep6.rrep_type;
00271 
00272     switch(type){
00273         case AODV6_RREQ:
00274             rreq = (const struct aodv_rreq6_draft_01*) aodvpacket;
00275             addr = inet_ntop(AF_INET6, &rreq->rreq_oa, ntop_buf, sizeof(ntop_buf));
00276             addr = inet_ntop(AF_INET6, &rreq->rreq_da, ntop_buf, sizeof(ntop_buf));
00277             break;
00278         case AODV6_RREP:
00279 
00280             /* update neighbor table */
00281             rrep = (const struct aodv_rrep6_draft_01*) aodvpacket;
00282             addr = inet_ntop(AF_INET6, &rrep->rrep_oa, ntop_buf, sizeof(ntop_buf));
00283             addr = inet_ntop(AF_INET6, &rrep->rrep_da, ntop_buf, sizeof(ntop_buf));
00284 
00285             /*if hops = 0 and originator_ip = dest_ip add to neighbors*/
00286 
00287             if((0==rrep->rrep_hops) && (0== memcmp(&rrep->rrep_oa,&rrep->rrep_da, sizeof(struct in6_addr)))){
00288                 /*get the src ip from the ip6 header*/
00289 
00290                 ether = (const struct ether_header*) packet;
00291                 ip6 = (const struct ip6_hdr*) (packet+sizeof(struct ether_header));
00292 
00293                 
00294                 memcpy(&aodv_pair.src_ether,&ether->ether_shost,6);
00295                 memcpy(&aodv_pair.src_ip6,&ip6->ip6_src, 16);
00296                 memcpy(&interface_pair.src_ether,&ether->ether_shost,6);
00297                 memcpy(&interface_pair.src_ip6,&rrep->rrep_oa, 16);
00298 
00299                 if(-1==find_neighbor(&aodv_pair))
00300                         add_neighbor(&aodv_pair);
00301                 if(-1==find_neighbor(&interface_pair))
00302                         add_neighbor(&interface_pair);
00303                 
00304     
00305                 
00306             }
00307             
00308             break;
00309         default:
00310             // other
00311       
00312     }
00313 
00314     return 0;
00315     
00316 }
00317 
00318 int find_neighbor(neighbor* pair){
00319     int i;
00320     for(i=0;i<2*MAXNEIGHBORS;i++){
00321         if((LIVE==neighbors[i].route_state)&&
00322                 (0==memcmp(&neighbors[i],pair,22))){
00323         //      print_neighbors();
00324                 return i;
00325             }
00326     }
00327     return -1;
00328 }
00329 
00330 int add_neighbor(neighbor* pair){
00331     int i;
00332     for(i=0;i<2*MAXNEIGHBORS;i++){
00333         if(LIVE!=neighbors[i].route_state){
00334             memcpy(&neighbors[i],pair,22);
00335             neighbors[i].route_state = LIVE;
00336             printf("Added a neighbor\n");
00337            // print_neighbors();
00338             return 1;
00339         }
00340     }
00341     return 0;
00342 }
00343 
00344 int incr_dropcount(struct ether_addr* ether_src){
00345         int i;
00346         for(i=0;i<2*MAXNEIGHBORS;i++){
00347                 if(0==memcmp(&neighbors[i],ether_src,6)){
00348                         neighbors[i].dropcount++;
00349                 }
00350         }
00351         return 0;
00352 }
00353 
00354 void print_neighbors(void){
00355     int i,j;
00356     
00357     printf("\n====== Neighbor Table ======\n");
00358     printf("(dropcount, mac address, ip6 address)\n");
00359     for(i=0;i<2*MAXNEIGHBORS;i++)
00360         if(LIVE==neighbors[i].route_state){
00361             printf("[%d] ", neighbors[i].dropcount);    
00362             for(j=0;j<6;j++)
00363                 printf("%x",neighbors[i].src_ether[j]);
00364             printf(" = ");
00365             for(j=0;j<16;j++)
00366                 printf("%x",neighbors[i].src_ip6[j]);
00367             printf("\n");
00368         }
00369     printf("============================\n");
00370 }
00371 
00372 void log_intrusions(void){
00373         // read the neighbor table, log non-zero dropcounts as intrusions
00374         // also reset dropcounts to zero
00375         int i;
00376         intruder badguy;
00377         const int n = sizeof(intruder);
00378 
00379         for(i=0;i<2*MAXNEIGHBORS;i++){
00380                 if(LIVE==neighbors[i].route_state && neighbors[i].dropcount>0){
00381                         memcpy(&badguy,&neighbors[i],22);
00382                         badguy.when_detected = time(0);
00383                         badguy.dropcount = neighbors[i].dropcount;
00384                         // reset dropcount
00385                         neighbors[i].dropcount = 0;
00386 
00387                         //append to log
00388                         // **** if error handling is attempted, doesnt write to file
00389                         // just dont doubt it and it works :D
00390                         //if(fwrite(&badguy, sizeof(intruder), 1, logfile)!=1)
00391                         fwrite(&badguy, sizeof(intruder), 1, logfile);
00392                         fflush(logfile);
00393 
00394                         
00395                 }// end if
00396         }// end for
00397 
00398         
00399 }
00400 
00401 int main(int argc,char **argv){
00402  
00403     char *dev; 
00404     char errbuf[PCAP_ERRBUF_SIZE];
00405     pcap_t* descr;
00406     struct bpf_program fp;      /* hold compiled program     */
00407     bpf_u_int32 maskp;          /* subnet mask               */
00408     bpf_u_int32 netp;           /* ip                        */
00409     u_char* args = NULL;
00410     int i;
00411     received = 0;
00412     forwarded = 0;
00413 
00414 
00415     if(argc < 2){ 
00416         fprintf(stdout,"Usage: %s numpackets \"options\"\n",argv[0]);
00417         return 0;
00418     }
00419 
00420     // open log file
00421     if((logfile = fopen("/tmp/suspects","w")) == NULL){
00422             printf("Couldn't open log file ...\n");
00423             exit(0);
00424     }
00425 
00426     dev = pcap_lookupdev(errbuf);
00427     if(dev == NULL)
00428     { printf("%s\n",errbuf); exit(1); }
00429 
00430 
00431     ht = createHashtable(HTSIZE); /* size is a suitably large prime no. */
00432 
00433     for(i=0;i<2*MAXNEIGHBORS;i++){
00434         neighbors[i].route_state = EXPIRED;
00435     }
00436 
00437     /* signal handling */
00438 
00439     if(SIG_ERR==signal(SIGALRM, SIGALRM_handler)){
00440         printf("SIGALRM handler couldnt be installed ...\n");
00441         exit(1);
00442     }
00443 
00444     alarm(ALARM_TIMEOUT);
00445 
00446     /* get the network address and mask of the device */
00447     pcap_lookupnet(dev,&netp,&maskp,errbuf);
00448 
00449     /* open device in promiscuous mode */
00450     
00451     descr = pcap_open_live(dev,1500,1,-1,errbuf);
00452     if(descr == NULL)
00453     { printf("pcap_open_live(): %s\n",errbuf); exit(1); }
00454 
00455 
00456     if(argc > 2)
00457     {
00458         if(pcap_compile(descr,&fp,argv[2],0,netp) == -1)
00459         { fprintf(stderr,"Error calling pcap_compile\n"); exit(1); }
00460 
00461         if(pcap_setfilter(descr,&fp) == -1)
00462         { fprintf(stderr,"Error setting filter\n"); exit(1); }
00463     }
00464 
00465     /* begin snooping */ 
00466     pcap_loop(descr,atoi(argv[1]),pkt_callback,args);
00467 
00468     fprintf(stdout,"\nDone...\n");
00469     print_neighbors();
00470     fclose(logfile);
00471         
00472     return 0;
00473 }
00474 
00475 #endif
00476 
00477 
00478 

Generated on Wed Mar 23 11:08:02 2005 for Snoop IDS by doxygen1.2.18