home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / trace / tcpdump-2.2.1 / tcpdump.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-02  |  6.9 KB  |  348 lines

  1. /*
  2.  * Copyright (c) 1987-1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. char copyright[] =
  23.     "@(#) Copyright (c) 1987-1990 The Regents of the University of California.\nAll rights reserved.\n";
  24. static  char rcsid[] =
  25.     "@(#)$Header: tcpdump.c,v 1.68 92/06/02 17:57:41 mccanne Exp $ (LBL)";
  26. #endif
  27.  
  28. /*
  29.  * tcpdump - monitor tcp/ip traffic on an ethernet.
  30.  *
  31.  * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
  32.  * Mercilessly hacked and occasionally improved since then via the
  33.  * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <signal.h>
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #include <sys/timeb.h>
  41. #include <netinet/in.h>
  42.  
  43. #include <net/bpf.h>
  44.  
  45. #include "interface.h"
  46. #include "savefile.h"
  47. #include "addrtoname.h"
  48.  
  49. int fflag;            /* don't translate "foreign" IP address */
  50. int nflag;            /* leave addresses as numbers */
  51. int Nflag;            /* remove domains from printed host names */
  52. int pflag;            /* don't go promiscuous */
  53. int qflag;            /* quick (shorter) output */
  54. int tflag = 1;            /* print packet arrival time */
  55. int eflag;            /* print ethernet header */
  56. int vflag;            /* verbose */
  57. int xflag;            /* print packet in hex */
  58. int Oflag = 1;            /* run filter code optimizer */
  59. int Sflag;            /* print raw TCP sequence numbers */
  60.  
  61. int dflag;            /* print filter code */
  62.  
  63. char *program_name;
  64.  
  65. long thiszone;            /* gmt to local correction */
  66.  
  67. static void cleanup();
  68.  
  69. /* Length of saved portion of packet. */
  70. int snaplen = DEFAULT_SNAPLEN;
  71.  
  72. static int if_fd = -1;
  73.  
  74. struct printer {
  75.     void (*f)();
  76.     int type;
  77. };
  78.  
  79. static struct printer printers[] = {
  80.     { ether_if_print, DLT_EN10MB },
  81.     { sl_if_print, DLT_SLIP },
  82.     { ppp_if_print, DLT_PPP },
  83.     { fddi_if_print, DLT_FDDI },
  84.     { null_if_print, DLT_NULL },
  85.     { 0, 0 },
  86. };
  87.  
  88. void
  89. (*lookup_printer(type))()
  90.     int type;
  91. {
  92.     struct printer *p;
  93.  
  94.     for (p = printers; p->f; ++p)
  95.         if (type == p->type)
  96.             return p->f;
  97.  
  98.     error("unknown data link type 0x%x", type);
  99.     /* NOTREACHED */
  100. }
  101.  
  102. void
  103. main(argc, argv)
  104.     int argc;
  105.     char **argv;
  106. {
  107.     struct bpf_program *parse();
  108.     void bpf_dump();
  109.  
  110.     int cnt = -1, i;
  111.     struct timeb zt;
  112.     struct bpf_program *fcode;
  113.     int op;
  114.     void (*printit)();
  115.     char *infile = 0;
  116.     char *cmdbuf;
  117.     int linktype;
  118.     int err;
  119.     u_long localnet;
  120.     u_long netmask;
  121.  
  122.     char *RFileName = 0;    /* -r argument */
  123.     char *WFileName = 0;    /* -w argument */
  124.  
  125.     char *device = 0;
  126.  
  127.     int precision = clock_sigfigs();
  128.  
  129.     extern char *optarg;
  130.     extern int optind, opterr;
  131.  
  132.     program_name = argv[0];
  133.  
  134.     opterr = 0;
  135.     while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:Stvw:xY")) != EOF)
  136.         switch (op) {
  137.         case 'c':
  138.             cnt = atoi(optarg);
  139.             break;
  140.  
  141.         case 'd':
  142.             ++dflag;
  143.             break;
  144.  
  145.         case 'e':
  146.             ++eflag;
  147.             break;
  148.  
  149.         case 'f':
  150.             ++fflag;
  151.             break;
  152.  
  153.         case 'F':
  154.             infile = optarg;
  155.             break;
  156.  
  157.         case 'i':
  158.             device = optarg;
  159.             break;
  160.  
  161.         case 'l':
  162.             setlinebuf(stdout);
  163.             break;
  164.  
  165.         case 'n':
  166.             ++nflag;
  167.             break;
  168.  
  169.         case 'N':
  170.             ++Nflag;
  171.             break;
  172.  
  173.         case 'O':
  174.             Oflag = 0;
  175.             break;
  176.  
  177.         case 'p':
  178.             ++pflag;
  179.             break;
  180.  
  181.         case 'q':
  182.             ++qflag;
  183.             break;
  184.  
  185.         case 'r':
  186.              RFileName = optarg;
  187.              break;
  188.  
  189.         case 's':
  190.             snaplen = atoi(optarg);
  191.             break;
  192.  
  193.         case 'S':
  194.             ++Sflag;
  195.             break;
  196.  
  197.         case 't':
  198.             --tflag;
  199.             break;
  200.  
  201.         case 'v':
  202.             ++vflag;
  203.             break;
  204.  
  205.         case 'w':
  206.              WFileName = optarg;
  207.              break;
  208. #ifdef YYDEBUG
  209.         case 'Y':
  210.             {
  211.             extern int yydebug;
  212.             yydebug = 1;
  213.             }
  214.             break;
  215. #endif
  216.         case 'x':
  217.             ++xflag;
  218.             break;
  219.  
  220.         default:
  221.             usage();
  222.             /* NOTREACHED */
  223.         }
  224.  
  225.     if (tflag > 0) {
  226.         struct timeval now;
  227.         struct timezone tz;
  228.  
  229.         if (gettimeofday(&now, &tz) < 0) {
  230.             perror("tcpdump: gettimeofday");
  231.             exit(1);
  232.         }
  233.         thiszone = tz.tz_minuteswest * -60;
  234.         if (localtime((time_t *)&now.tv_sec)->tm_isdst)
  235.             thiszone += 3600;
  236.     }
  237.  
  238.     if (RFileName) {
  239.         /*
  240.          * We don't need network access, so set it back to the user id.
  241.          * Also, this prevents the user from reading anyone's
  242.          * trace file.
  243.          */
  244.         setuid(getuid());
  245.  
  246.         err = sf_read_init(RFileName, &linktype, &thiszone, &snaplen,
  247.             &precision);
  248.         if (err)
  249.             sf_err(err);
  250.         localnet = 0;
  251.         netmask = 0;
  252.         if (fflag != 0)
  253.             error("-f and -r options are incompatible");
  254.     } else {
  255.         if (device == 0) {
  256.             device = lookup_device();
  257.             if (device == 0)
  258.                 error("can't find any interfaces");
  259.         }
  260.         if_fd = initdevice(device, pflag, &linktype);
  261.         lookup_net(device, &localnet, &netmask);
  262.         /*
  263.          * Let user own process after socket has been opened.
  264.          */
  265.         setuid(getuid());
  266.     }
  267.  
  268.     if (infile) 
  269.         cmdbuf = read_infile(infile);
  270.     else
  271.         cmdbuf = copy_argv(&argv[optind]);
  272.  
  273.     fcode = parse(cmdbuf, Oflag, linktype, netmask);
  274.     if (dflag) {
  275.         bpf_dump(fcode, dflag);
  276.         exit(0);
  277.     }
  278.     init_addrtoname(fflag, localnet, netmask);
  279.  
  280.     (void)signal(SIGTERM, cleanup);
  281.     (void)signal(SIGINT, cleanup);
  282.     (void)signal(SIGHUP, cleanup);
  283.  
  284.     printit = lookup_printer(linktype);
  285.  
  286.     if (WFileName) {
  287.         sf_write_init(WFileName, linktype, thiszone, snaplen, 
  288.                   precision);
  289.         printit = sf_write;
  290.     }
  291.     if (RFileName) {
  292.         err = sf_read(fcode, cnt, snaplen, printit);
  293.         if (err)
  294.             sf_err(err);
  295.     } else {
  296.         fprintf(stderr, "%s: listening on %s\n", program_name, device);
  297.         fflush(stderr);
  298.         readloop(cnt, if_fd, fcode, printit);
  299.     }
  300.     exit(0);
  301. }
  302.  
  303. /* make a clean exit on interrupts */
  304. static void
  305. cleanup()
  306. {
  307.     if (if_fd >= 0) {
  308.         putc('\n', stderr);
  309.         wrapup(if_fd);
  310.     }
  311.     exit(0);
  312. }
  313.  
  314. void
  315. default_print(sp, length)
  316.     register u_short *sp;
  317.     register int length;
  318. {
  319.     register u_int i;
  320.     register int nshorts;
  321.  
  322.     nshorts = (unsigned) length / sizeof(u_short);
  323.     i = 0;
  324.     while (--nshorts >= 0) {
  325.         if ((i++ % 8) == 0)
  326.             (void)printf("\n\t\t\t");
  327.         (void)printf(" %04x", ntohs(*sp++));
  328.     }
  329.     if (length & 1) {
  330.         if ((i % 8) == 0)
  331.             (void)printf("\n\t\t\t");
  332.         (void)printf(" %02x", *(u_char *)sp);
  333.     }
  334. }
  335.  
  336. void
  337. usage()
  338. {
  339.     extern char version[];
  340.  
  341.     (void)fprintf(stderr, "Version %s\n", version);
  342.     (void)fprintf(stderr,
  343. "Usage: tcpdump [-deflnOpqtvx] [-c count] [-i interface]\n");
  344.     (void)fprintf(stderr,
  345. "\t\t[-r filename] [-w filename] [expr]\n");
  346.     exit(-1);
  347. }
  348.