home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / ngrep / ngrep.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-01  |  10.4 KB  |  495 lines

  1. /*
  2.  * $Id: ngrep.c,v 1.37 2000/02/01 12:28:02 jpr5 Exp $
  3.  *
  4.  */
  5.  
  6. #if defined(BSD) || defined(SOLARIS)
  7. #include <unistd.h>
  8. #include <ctype.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <netinet/in_systm.h>
  13. #include <net/if.h>
  14. #endif
  15.  
  16. #if defined(OSF1)
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <netinet/in_systm.h>
  21. #include <net/route.h>
  22. #include <sys/mbuf.h>
  23. #endif
  24.  
  25. #if defined(LINUX)
  26. #include <getopt.h>
  27. #endif
  28.  
  29.  
  30. #include <netinet/ip.h>
  31. #include <netinet/tcp.h>
  32. #include <netinet/udp.h>
  33. #include <netinet/ip_icmp.h>
  34.  
  35. #include <pcap.h>
  36. #include <net/bpf.h>
  37.  
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <signal.h>
  41.  
  42. #include "regex.h"
  43. #include "ngrep.h"
  44.  
  45.  
  46. static char rcsver[] = "$Revision: 1.37 $";
  47.  
  48. int snaplen = 65535, promisc = 1, to = 1000;
  49. int show_empty = 0, show_hex = 0, quiet = 0;
  50. int match_after = 0, keep_matching = 0, invert_match = 0;
  51. int matches = 0, max_matches = 0;
  52.  
  53. char pc_err[PCAP_ERRBUF_SIZE], *re_err;
  54.  
  55. int re_match_word = 0, re_ignore_case = 0;
  56. char *regex = NULL, *filter = NULL;
  57. struct re_pattern_buffer pattern;
  58. int (*match_func)();
  59.  
  60. struct bpf_program pcapfilter;
  61. struct in_addr net, mask;
  62. char *dev = NULL;
  63. int link_offset;
  64. pcap_t *pd;
  65.  
  66.  
  67. int main(int argc, char **argv) {
  68.   int c;
  69.  
  70.   signal(SIGINT,  clean_exit);
  71.   signal(SIGQUIT, clean_exit);
  72.   signal(SIGABRT, clean_exit);
  73.   signal(SIGPIPE, clean_exit);
  74.  
  75.   while ((c = getopt(argc, argv, "hViwqevxln:d:A:")) != EOF) {
  76.     switch (c) {
  77.     case 'A': 
  78.       match_after = atoi(optarg) + 1;
  79.       break;
  80.     case 'd': 
  81.       dev = optarg;
  82.       break;
  83.     case 'n':
  84.       max_matches = atoi(optarg);
  85.       break;
  86.     case 'l':
  87.       setvbuf(stdout, NULL, _IOLBF, 0);
  88.       break;
  89.     case 'x':
  90.       show_hex++;
  91.       break;
  92.     case 'v':
  93.       invert_match++;
  94.       break;
  95.     case 'e':
  96.       show_empty++;
  97.       break;
  98.     case 'q':
  99.       quiet++;
  100.       break;
  101.     case 'w':
  102.       re_match_word++;
  103.       break;
  104.     case 'i':
  105.       re_ignore_case++;
  106.       break;
  107.     case 'V':
  108.       version();
  109.     case 'h':
  110.       usage(0);
  111.     default:
  112.       usage(-1);
  113.     }
  114.   }
  115.  
  116.   if (argv[optind]) 
  117.     regex = argv[optind++];
  118.  
  119.  
  120.   if (!dev) 
  121.     if (!(dev = pcap_lookupdev(pc_err))) {
  122.       perror(pc_err);
  123.       exit(-1);
  124.     }
  125.  
  126.  
  127.   if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) {
  128.     perror(pc_err);
  129.     exit(-1);
  130.   }
  131.  
  132.   if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) == -1) {
  133.     perror(pc_err);
  134.     memset(&net, 0, sizeof(net));
  135.     memset(&mask, 0, sizeof(mask));
  136.   } 
  137.  
  138.   if (!quiet) {
  139.     printf("interface: %s", dev);
  140.     if (net.s_addr && mask.s_addr) {
  141.       printf(" (%s/", inet_ntoa(net));
  142.       printf("%s)", inet_ntoa(mask)); 
  143.     }
  144.     printf("\n");
  145.   }
  146.  
  147.  
  148.   if (argv[optind]) {
  149.     filter = get_filter(&argv[optind]); 
  150.  
  151.     if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
  152.       free(filter); 
  153.       filter = get_filter(&argv[optind-1]); 
  154.  
  155.       PCAP_RESTART();
  156.       if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
  157.     pcap_perror(pd, "pcap compile");
  158.     exit(-1);
  159.       } else regex = NULL;
  160.     }
  161.  
  162.     if (!quiet) printf("filter: %s\n", filter); 
  163.     
  164.     if (pcap_setfilter(pd, &pcapfilter)) {
  165.       pcap_perror(pd, "pcap set");
  166.       exit(-1);
  167.     }
  168.   }
  169.  
  170.  
  171.   if (regex) {
  172.     match_func = &re_match_func;
  173.     re_syntax_options = RE_SYNTAX_EGREP;
  174.  
  175.     if (re_ignore_case) {
  176.       char *s;
  177.       int i;
  178.  
  179.       pattern.translate = (char*)malloc(256);
  180.       s = pattern.translate;
  181.       for (i = 0; i < 256; i++) 
  182.     s[i] = i;
  183.       for (i = 'A'; i <= 'Z'; i++) 
  184.     s[i] = i + 32;
  185.  
  186.       s = regex;
  187.       while (*s) 
  188.     *s++ = tolower(*s);
  189.     } else pattern.translate = NULL;
  190.  
  191.     if (re_match_word) {
  192.       char *word_regex = malloc(strlen(regex) * 3 + strlen(WORD_REGEX));
  193.       sprintf(word_regex, WORD_REGEX, regex, regex, regex);
  194.       regex = word_regex;
  195.     }
  196.  
  197.     (const char *)re_err = re_compile_pattern(regex, strlen(regex), &pattern);
  198.     if (re_err) {
  199.       fprintf(stderr, "regex compile: %s\n", re_err);
  200.       exit(-1);
  201.     }
  202.  
  203.     pattern.fastmap = (char*)malloc(256);
  204.     if (re_compile_fastmap(&pattern)) {
  205.       perror("fastmap compile failed");
  206.       exit(-1);
  207.     }
  208.  
  209.     if (!quiet && regex && strlen(regex)) 
  210.       printf("%smatch: %s\n", invert_match?"don't ":"", regex);
  211.   } else match_func = &blank_match_func;
  212.  
  213.  
  214.   if (re_match_word) free(regex);
  215.   if (filter) free(filter);
  216.  
  217.  
  218.   switch(pcap_datalink(pd)) {
  219.   case DLT_EN10MB:
  220.   case DLT_IEEE802:
  221.     link_offset = ETHHDR_SIZE;
  222.     break;
  223.  
  224.   case DLT_FDDI:
  225.     link_offset = FDDIHDR_SIZE;
  226.     break;
  227.  
  228.   case DLT_SLIP: 
  229.     link_offset = SLIPHDR_SIZE;
  230.     break;
  231.     
  232.   case DLT_PPP:
  233.     link_offset = PPPHDR_SIZE;
  234.     break;
  235.  
  236.   case DLT_RAW: 
  237.     link_offset = RAWHDR_SIZE;
  238.     break;
  239.  
  240.   case DLT_NULL:
  241.     link_offset = LOOPHDR_SIZE;
  242.     break;
  243.  
  244.   default:
  245.     fprintf(stderr, "fatal: unsupported interface type\n");
  246.     exit(-1);
  247.   }
  248.   
  249.  
  250.   while (pcap_loop(pd, 0, (pcap_handler)process, 0));
  251. }    
  252.  
  253.  
  254. void process(u_char *data1, struct pcap_pkthdr* h, u_char *p) {
  255.   struct ip* ip_packet = (struct ip *)(p + link_offset);
  256.  
  257.   unsigned ip_hl = ip_packet->ip_hl*4;
  258.   unsigned ip_off = ntohs(ip_packet->ip_off);
  259.   unsigned fragmented = ip_off & (IP_MF | IP_OFFMASK);
  260.   unsigned frag_offset = fragmented?(ip_off & IP_OFFMASK) * 8:0;
  261.  
  262.   char *data;
  263.   int len;
  264.  
  265.   switch (ip_packet->ip_p) {
  266.   case IPPROTO_TCP: {
  267.     struct tcphdr* tcp = (struct tcphdr *)(((char *)ip_packet) + ip_hl);
  268.     unsigned tcphdr_offset = fragmented?0:(tcp->th_off * 4);
  269.  
  270.     if (!quiet) {
  271.       printf("#");
  272.       fflush(stdout);
  273.     }
  274.  
  275.     data = ((char*)tcp) + tcphdr_offset;
  276.     len = ntohs(ip_packet->ip_len) - ip_hl - tcphdr_offset;
  277.  
  278.     if (((len || show_empty) && (((int)(*match_func)(data, len)) != invert_match))
  279.     || keep_matching) { 
  280.       printf("\nT ");
  281.  
  282.       if (tcphdr_offset || !frag_offset) {
  283.     printf("%s:%d -", inet_ntoa(ip_packet->ip_src), ntohs(tcp->th_sport));
  284.     printf("> %s:%d", inet_ntoa(ip_packet->ip_dst), ntohs(tcp->th_dport));
  285.     printf(" [%s%s%s%s%s%s]",
  286.            (tcp->th_flags & TH_ACK)?"A":"",
  287.            (tcp->th_flags & TH_SYN)?"S":"",
  288.            (tcp->th_flags & TH_RST)?"R":"",
  289.            (tcp->th_flags & TH_FIN)?"F":"",
  290.            (tcp->th_flags & TH_URG)?"U":"",
  291.            (tcp->th_flags & TH_PUSH)?"P":"");
  292.       } else {
  293.     printf("%s -", inet_ntoa(ip_packet->ip_src));
  294.     printf("> %s", inet_ntoa(ip_packet->ip_dst));
  295.       }
  296.  
  297.       if (fragmented) {
  298.     printf(" %s%d@%d:%d\n", frag_offset?"+":"", ntohs(ip_packet->ip_id),
  299.                                 frag_offset, len); 
  300.       } else printf("\n");
  301.       
  302.       dump(data,len);
  303.     }
  304.   }
  305.   break;
  306.  
  307.   case IPPROTO_UDP: {
  308.     struct udphdr* udp = (struct udphdr *)(((char *)ip_packet) + ip_hl);
  309.     unsigned udphdr_offset = (fragmented)?0:sizeof(struct udphdr); 
  310.  
  311.     if (!quiet) {
  312.       printf("#"); 
  313.       fflush(stdout);
  314.     }
  315.  
  316.     data = ((char*)udp) + udphdr_offset;
  317.     len = ntohs(ip_packet->ip_len) - ip_hl - udphdr_offset;
  318.  
  319.     if (((len || show_empty) && (((int)(*match_func)(data, len)) != invert_match))
  320.     || keep_matching) { 
  321.       printf("\nU ");
  322.  
  323.       if (udphdr_offset || !frag_offset) {
  324. #ifdef HAVE_DUMB_UDPHDR
  325.     printf("%s:%d -", inet_ntoa(ip_packet->ip_src), ntohs(udp->source));
  326.     printf("> %s:%d", inet_ntoa(ip_packet->ip_dst), ntohs(udp->dest));
  327. #else
  328.     printf("%s:%d -", inet_ntoa(ip_packet->ip_src), ntohs(udp->uh_sport));
  329.     printf("> %s:%d", inet_ntoa(ip_packet->ip_dst), ntohs(udp->uh_dport));
  330. #endif
  331.       } else {
  332.     printf("%s -", inet_ntoa(ip_packet->ip_src));
  333.     printf("> %s", inet_ntoa(ip_packet->ip_dst));
  334.       }
  335.  
  336.       if (fragmented) {
  337.     printf(" %s%d@%d:%d\n", frag_offset?"+":"", ntohs(ip_packet->ip_id),
  338.                                 frag_offset, len); 
  339.       } else printf("\n");
  340.       
  341.       dump(data,len);
  342.     }
  343.   }
  344.   break;
  345.  
  346.   case IPPROTO_ICMP: {
  347.     struct icmp* ic = (struct icmp *)(((char *)ip_packet) + ip_hl);
  348.     unsigned icmphdr_offset = fragmented?0:4;
  349.  
  350.     if (!quiet) {
  351.       printf("#"); 
  352.       fflush(stdout);
  353.     }
  354.  
  355.     data = ((char*)ic) + icmphdr_offset;
  356.     len = ntohs(ip_packet->ip_len) - ip_hl - icmphdr_offset;
  357.  
  358.     if (((len || show_empty) && (((int)(*match_func)(data, len)) != invert_match))
  359.     || keep_matching) { 
  360.       printf("\nI ");
  361.  
  362.       printf("%s -", inet_ntoa(ip_packet->ip_src));
  363.       printf("> %s", inet_ntoa(ip_packet->ip_dst));
  364.  
  365.       if (icmphdr_offset || !frag_offset) 
  366.     printf(" %d:%d", ic->icmp_type, ic->icmp_code);
  367.  
  368.       if (fragmented) {
  369.     printf(" %s%d@%d:%d\n", frag_offset?"+":"", ntohs(ip_packet->ip_id),
  370.                                 frag_offset, len); 
  371.       } else printf("\n");
  372.       dump(data,len);
  373.     }
  374.   }
  375.   break;
  376.   
  377.   }
  378.  
  379.   if (match_after && keep_matching)
  380.     keep_matching--;
  381. }
  382.  
  383.  
  384. void dump(char *data, int len) {  
  385.   if (len > 0) {
  386.     unsigned width = show_hex?16:70;
  387.     char *str = data;
  388.     int j, i = 0;
  389.  
  390.     while (i < len) {
  391.       printf("  ");
  392.  
  393.       if (show_hex) 
  394.     for (j = 0; j < width; j++) {
  395.       if (i+j < len) 
  396.         printf("%02x ", (unsigned char)str[j]);
  397.       else printf("   ");
  398.  
  399.       if((j+1) % (width/2) == 0)
  400.         printf("   ");
  401.     }
  402.  
  403.       for (j = 0; j < width; j++) 
  404.     if (i+j < len) 
  405.       printf("%c", isprint(str[j])?str[j]:'.');
  406.     else printf(" ");
  407.       
  408.       str += width;
  409.       i += j;
  410.  
  411.       printf("\n");
  412.     }
  413.   }
  414. }
  415.  
  416.  
  417. int re_match_func(char *data, int len) {
  418.   switch (re_search(&pattern, data, len, 0, len, 0)) {
  419.     case -2: 
  420.       perror("she's dead, jim\n");
  421.       exit(-1);
  422.     case -1:
  423.       return 0;
  424.   }
  425.   
  426.   if (max_matches && ++matches > max_matches)
  427.     clean_exit(0);
  428.  
  429.   if (match_after && keep_matching != match_after)
  430.     keep_matching = match_after;
  431.  
  432.   return 1;
  433. }
  434.  
  435. int blank_match_func(char *data, int len) {
  436.   if (max_matches && ++matches > max_matches)
  437.     clean_exit(0);
  438.  
  439.   return 1;
  440. }
  441.  
  442.  
  443. char *get_filter(char **argv) {
  444.   char **arg = argv, *theirs, *mine;
  445.   char *from, *to;
  446.   int len = 0;
  447.  
  448.   if (!*arg)
  449.     return NULL;
  450.  
  451.   while (*arg) 
  452.     len += strlen(*arg++) + 1;
  453.  
  454.   if (!(theirs = (char*)malloc(len + 1)) || 
  455.       !(mine = (char*)malloc(len + sizeof(IP_ONLY))))
  456.     return NULL;
  457.  
  458.   memset(theirs, 0, len + 1);
  459.   memset(mine, 0, len + sizeof(IP_ONLY));
  460.  
  461.   arg = argv;
  462.   to = theirs;
  463.  
  464.   while ((from = *arg++)) {
  465.     while ((*to++ = *from++));
  466.     *(to-1) = ' ';
  467.   }
  468.  
  469.   sprintf(mine,IP_ONLY,theirs);
  470.  
  471.   free(theirs);
  472.   return mine;
  473. }
  474.  
  475.  
  476. void clean_exit(int sig) {
  477.   if (pattern.translate) free(pattern.translate);
  478.   if (pattern.fastmap) free(pattern.fastmap);
  479.  
  480.   printf("exit\n");
  481.   exit(0);
  482. }
  483.  
  484.  
  485. void usage(int e) {
  486.   printf("usage: ngrep <-hViwqevxl> <-n num> <-d dev> <-A num> <regex> <pcap filter logic>\n");
  487.   exit(e);
  488. }
  489.  
  490.  
  491. void version(void) {
  492.   printf("ngrep: %s\n", rcsver);
  493.   exit(0);
  494. }
  495.