tcpdump.c revision 75118
117680Spst/* 239297Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst */ 2117680Spst 2217680Spst#ifndef lint 2326180Sfennerstatic const char copyright[] = 2439297Sfenner "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\ 2517680SpstThe Regents of the University of California. All rights reserved.\n"; 2626180Sfennerstatic const char rcsid[] = 2775118Sfenner "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.158 2000/12/21 10:43:24 guy Exp $ (LBL)"; 2817680Spst#endif 2917680Spst 3056648Sarchie/* $FreeBSD: head/contrib/tcpdump/tcpdump.c 75118 2001-04-03 07:50:46Z fenner $ */ 3156648Sarchie 3217680Spst/* 3317680Spst * tcpdump - monitor tcp/ip traffic on an ethernet. 3417680Spst * 3517680Spst * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. 3617680Spst * Mercilessly hacked and occasionally improved since then via the 3717680Spst * combined efforts of Van, Steve McCanne and Craig Leres of LBL. 3817680Spst */ 3917680Spst 4056896Sfenner#ifdef HAVE_CONFIG_H 4156896Sfenner#include "config.h" 4256896Sfenner#endif 4356896Sfenner 4417680Spst#include <sys/types.h> 4517680Spst#include <sys/time.h> 4617680Spst 4717680Spst#include <netinet/in.h> 4817680Spst 4917680Spst#include <pcap.h> 5017680Spst#include <signal.h> 5117680Spst#include <stdio.h> 5217680Spst#include <stdlib.h> 5317680Spst#include <string.h> 5417680Spst#include <unistd.h> 5556896Sfenner#include <ctype.h> 5617680Spst 5756896Sfenner 5817680Spst#include "interface.h" 5917680Spst#include "addrtoname.h" 6017680Spst#include "machdep.h" 6139297Sfenner#include "setsignal.h" 6239297Sfenner#include "gmt2local.h" 6317680Spst 6439297Sfennerint aflag; /* translate network and broadcast addresses */ 6539297Sfennerint dflag; /* print filter code */ 6639297Sfennerint eflag; /* print ethernet header */ 6717680Spstint fflag; /* don't translate "foreign" IP address */ 6817680Spstint nflag; /* leave addresses as numbers */ 6917680Spstint Nflag; /* remove domains from printed host names */ 7039297Sfennerint Oflag = 1; /* run filter code optimizer */ 7117680Spstint pflag; /* don't go promiscuous */ 7217680Spstint qflag; /* quick (shorter) output */ 7356896Sfennerint Rflag = 1; /* print sequence # field in AH/ESP*/ 7456896Sfennerint sflag = 0; /* use the libsmi to translate OIDs */ 7539297Sfennerint Sflag; /* print raw TCP sequence numbers */ 7617680Spstint tflag = 1; /* print packet arrival time */ 7775118Sfennerint uflag = 0; /* Print undecoded NFS handles */ 7817680Spstint vflag; /* verbose */ 7917680Spstint xflag; /* print packet in hex */ 8056896Sfennerint Xflag; /* print packet in ascii as well as hex */ 8139297Sfenner 8256896Sfennerchar *espsecret = NULL; /* ESP secret key */ 8356896Sfenner 8417680Spstint packettype; 8517680Spst 8617680Spst 8717680Spstchar *program_name; 8817680Spst 8917680Spstint32_t thiszone; /* seconds offset from gmt to local time */ 9017680Spst 9117680Spst/* Forwards */ 9275118Sfennerstatic RETSIGTYPE cleanup(int); 9375118Sfennerstatic void usage(void) __attribute__((noreturn)); 9417680Spst 9517680Spst/* Length of saved portion of packet. */ 9617680Spstint snaplen = DEFAULT_SNAPLEN; 9717680Spst 9817680Spststruct printer { 9917680Spst pcap_handler f; 10017680Spst int type; 10117680Spst}; 10217680Spst 10317680Spststatic struct printer printers[] = { 10417680Spst { ether_if_print, DLT_EN10MB }, 10544165Sjulian { token_if_print, DLT_IEEE802 }, 10656896Sfenner#ifdef DLT_LANE8023 10756896Sfenner { lane_if_print, DLT_LANE8023 }, 10856896Sfenner#endif 10956896Sfenner#ifdef DLT_CIP 11056896Sfenner { cip_if_print, DLT_CIP }, 11156896Sfenner#endif 11275118Sfenner#ifdef DLT_ATM_CLIP 11375118Sfenner { cip_if_print, DLT_ATM_CLIP }, 11475118Sfenner#endif 11517680Spst { sl_if_print, DLT_SLIP }, 11639297Sfenner { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 11717680Spst { ppp_if_print, DLT_PPP }, 11839297Sfenner { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 11917680Spst { fddi_if_print, DLT_FDDI }, 12017680Spst { null_if_print, DLT_NULL }, 12175118Sfenner#ifdef DLT_LOOP 12275118Sfenner { null_if_print, DLT_LOOP }, 12375118Sfenner#endif 12439297Sfenner { raw_if_print, DLT_RAW }, 12517680Spst { atm_if_print, DLT_ATM_RFC1483 }, 12675118Sfenner#ifdef DLT_C_HDLC 12775118Sfenner { chdlc_if_print, DLT_C_HDLC }, 12856896Sfenner#endif 12975118Sfenner#ifdef DLT_PPP_SERIAL 13075118Sfenner { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 13175118Sfenner#endif 13275118Sfenner#ifdef DLT_LINUX_SLL 13375118Sfenner { sll_if_print, DLT_LINUX_SLL }, 13475118Sfenner#endif 13517680Spst { NULL, 0 }, 13617680Spst}; 13717680Spst 13817680Spststatic pcap_handler 13917680Spstlookup_printer(int type) 14017680Spst{ 14117680Spst struct printer *p; 14217680Spst 14317680Spst for (p = printers; p->f; ++p) 14417680Spst if (type == p->type) 14517680Spst return p->f; 14617680Spst 14775118Sfenner error("unknown data link type %d", type); 14817680Spst /* NOTREACHED */ 14917680Spst} 15017680Spst 15117680Spststatic pcap_t *pd; 15217680Spst 15317680Spstextern int optind; 15417680Spstextern int opterr; 15517680Spstextern char *optarg; 15617680Spst 15717680Spstint 15817680Spstmain(int argc, char **argv) 15917680Spst{ 16017680Spst register int cnt, op, i; 16117680Spst bpf_u_int32 localnet, netmask; 16217680Spst register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; 16317680Spst pcap_handler printer; 16417680Spst struct bpf_program fcode; 16539297Sfenner RETSIGTYPE (*oldhandler)(int); 16617680Spst u_char *pcap_userdata; 16717680Spst char ebuf[PCAP_ERRBUF_SIZE]; 16817680Spst 16917680Spst cnt = -1; 17017680Spst device = NULL; 17117680Spst infile = NULL; 17217680Spst RFileName = NULL; 17317680Spst WFileName = NULL; 17417680Spst if ((cp = strrchr(argv[0], '/')) != NULL) 17517680Spst program_name = cp + 1; 17617680Spst else 17717680Spst program_name = argv[0]; 17817680Spst 17975118Sfenner if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 18026180Sfenner error("%s", ebuf); 18117680Spst 18256896Sfenner#ifdef LIBSMI 18356896Sfenner smiInit("tcpdump"); 18456896Sfenner#endif 18556896Sfenner 18617680Spst opterr = 0; 18739297Sfenner while ( 18875118Sfenner (op = getopt(argc, argv, "ac:deE:fF:i:lm:nNOpqr:Rs:StT:uvw:xXY")) != -1) 18917680Spst switch (op) { 19039297Sfenner 19139297Sfenner case 'a': 19239297Sfenner ++aflag; 19339297Sfenner break; 19439297Sfenner 19517680Spst case 'c': 19617680Spst cnt = atoi(optarg); 19717680Spst if (cnt <= 0) 19817680Spst error("invalid packet count %s", optarg); 19917680Spst break; 20017680Spst 20117680Spst case 'd': 20217680Spst ++dflag; 20317680Spst break; 20417680Spst 20517680Spst case 'e': 20617680Spst ++eflag; 20717680Spst break; 20817680Spst 20956896Sfenner case 'E': 21075118Sfenner#ifndef HAVE_LIBCRYPTO 21156896Sfenner warning("crypto code not compiled in"); 21256896Sfenner#endif 21356896Sfenner espsecret = optarg; 21456896Sfenner break; 21556896Sfenner 21617680Spst case 'f': 21717680Spst ++fflag; 21817680Spst break; 21917680Spst 22017680Spst case 'F': 22117680Spst infile = optarg; 22217680Spst break; 22317680Spst 22417680Spst case 'i': 22517680Spst device = optarg; 22617680Spst break; 22717680Spst 22817680Spst case 'l': 22917680Spst#ifdef HAVE_SETLINEBUF 23017680Spst setlinebuf(stdout); 23117680Spst#else 23217680Spst setvbuf(stdout, NULL, _IOLBF, 0); 23317680Spst#endif 23417680Spst break; 23517680Spst 23617680Spst case 'n': 23717680Spst ++nflag; 23817680Spst break; 23917680Spst 24017680Spst case 'N': 24117680Spst ++Nflag; 24217680Spst break; 24317680Spst 24456896Sfenner case 'm': 24556896Sfenner#ifdef LIBSMI 24656896Sfenner if (smiLoadModule(optarg) == 0) { 24756896Sfenner error("could not load MIB module %s", optarg); 24856896Sfenner } 24956896Sfenner sflag = 1; 25056896Sfenner#else 25156896Sfenner (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 25256896Sfenner program_name, optarg); 25356896Sfenner (void)fprintf(stderr, "(no libsmi support)\n"); 25456896Sfenner#endif 25556896Sfenner 25617680Spst case 'O': 25717680Spst Oflag = 0; 25817680Spst break; 25917680Spst 26017680Spst case 'p': 26117680Spst ++pflag; 26217680Spst break; 26317680Spst 26417680Spst case 'q': 26517680Spst ++qflag; 26617680Spst break; 26717680Spst 26817680Spst case 'r': 26917680Spst RFileName = optarg; 27017680Spst break; 27117680Spst 27256896Sfenner case 'R': 27356896Sfenner Rflag = 0; 27456896Sfenner break; 27556896Sfenner 27675118Sfenner case 's': { 27775118Sfenner char *end; 27875118Sfenner 27975118Sfenner snaplen = strtol(optarg, &end, 0); 28075118Sfenner if (optarg == end || *end != '\0' 28175118Sfenner || snaplen < 0 || snaplen > 65535) 28217680Spst error("invalid snaplen %s", optarg); 28375118Sfenner else if (snaplen == 0) 28475118Sfenner snaplen = 65535; 28517680Spst break; 28675118Sfenner } 28717680Spst 28817680Spst case 'S': 28917680Spst ++Sflag; 29017680Spst break; 29117680Spst 29217680Spst case 't': 29317680Spst --tflag; 29417680Spst break; 29517680Spst 29617680Spst case 'T': 29717680Spst if (strcasecmp(optarg, "vat") == 0) 29817680Spst packettype = PT_VAT; 29917680Spst else if (strcasecmp(optarg, "wb") == 0) 30017680Spst packettype = PT_WB; 30117680Spst else if (strcasecmp(optarg, "rpc") == 0) 30217680Spst packettype = PT_RPC; 30317680Spst else if (strcasecmp(optarg, "rtp") == 0) 30417680Spst packettype = PT_RTP; 30517680Spst else if (strcasecmp(optarg, "rtcp") == 0) 30617680Spst packettype = PT_RTCP; 30756896Sfenner else if (strcasecmp(optarg, "snmp") == 0) 30856896Sfenner packettype = PT_SNMP; 30975118Sfenner else if (strcasecmp(optarg, "cnfp") == 0) 31075118Sfenner packettype = PT_CNFP; 31117680Spst else 31217680Spst error("unknown packet type `%s'", optarg); 31317680Spst break; 31417680Spst 31575118Sfenner case 'u': 31675118Sfenner ++uflag; 31775118Sfenner break; 31875118Sfenner 31917680Spst case 'v': 32017680Spst ++vflag; 32117680Spst break; 32217680Spst 32317680Spst case 'w': 32417680Spst WFileName = optarg; 32517680Spst break; 32656896Sfenner 32756896Sfenner case 'x': 32856896Sfenner ++xflag; 32956896Sfenner break; 33056896Sfenner 33156896Sfenner case 'X': 33275118Sfenner ++xflag; 33356896Sfenner ++Xflag; 33456896Sfenner break; 33556896Sfenner 33617680Spst#ifdef YYDEBUG 33717680Spst case 'Y': 33817680Spst { 33917680Spst /* Undocumented flag */ 34017680Spst extern int yydebug; 34117680Spst yydebug = 1; 34217680Spst } 34317680Spst break; 34417680Spst#endif 34517680Spst default: 34617680Spst usage(); 34717680Spst /* NOTREACHED */ 34817680Spst } 34917680Spst 35039297Sfenner if (aflag && nflag) 35139297Sfenner error("-a and -n options are incompatible"); 35239297Sfenner 35317680Spst if (tflag > 0) 35439297Sfenner thiszone = gmt2local(0); 35517680Spst 35617680Spst if (RFileName != NULL) { 35717680Spst /* 35817680Spst * We don't need network access, so set it back to the user id. 35917680Spst * Also, this prevents the user from reading anyone's 36017680Spst * trace file. 36117680Spst */ 36217680Spst setuid(getuid()); 36317680Spst 36417680Spst pd = pcap_open_offline(RFileName, ebuf); 36517680Spst if (pd == NULL) 36626180Sfenner error("%s", ebuf); 36717680Spst localnet = 0; 36817680Spst netmask = 0; 36917680Spst if (fflag != 0) 37017680Spst error("-f and -r options are incompatible"); 37117680Spst } else { 37217680Spst if (device == NULL) { 37317680Spst device = pcap_lookupdev(ebuf); 37417680Spst if (device == NULL) 37526180Sfenner error("%s", ebuf); 37617680Spst } 37717680Spst pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 37817680Spst if (pd == NULL) 37926180Sfenner error("%s", ebuf); 38017680Spst i = pcap_snapshot(pd); 38117680Spst if (snaplen < i) { 38217680Spst warning("snaplen raised from %d to %d", snaplen, i); 38317680Spst snaplen = i; 38417680Spst } 38539297Sfenner if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 38639297Sfenner localnet = 0; 38739297Sfenner netmask = 0; 38839297Sfenner warning("%s", ebuf); 38939297Sfenner } 39017680Spst /* 39117680Spst * Let user own process after socket has been opened. 39217680Spst */ 39317680Spst setuid(getuid()); 39417680Spst } 39517680Spst if (infile) 39617680Spst cmdbuf = read_infile(infile); 39717680Spst else 39817680Spst cmdbuf = copy_argv(&argv[optind]); 39917680Spst 40017680Spst if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 40126180Sfenner error("%s", pcap_geterr(pd)); 40217680Spst if (dflag) { 40317680Spst bpf_dump(&fcode, dflag); 40417680Spst exit(0); 40517680Spst } 40639297Sfenner init_addrtoname(localnet, netmask); 40717680Spst 40839297Sfenner (void)setsignal(SIGTERM, cleanup); 40939297Sfenner (void)setsignal(SIGINT, cleanup); 41039297Sfenner /* Cooperate with nohup(1) */ 41139297Sfenner if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 41239297Sfenner (void)setsignal(SIGHUP, oldhandler); 41317680Spst 41417680Spst if (pcap_setfilter(pd, &fcode) < 0) 41526180Sfenner error("%s", pcap_geterr(pd)); 41617680Spst if (WFileName) { 41717680Spst pcap_dumper_t *p = pcap_dump_open(pd, WFileName); 41817680Spst if (p == NULL) 41926180Sfenner error("%s", pcap_geterr(pd)); 42017680Spst printer = pcap_dump; 42117680Spst pcap_userdata = (u_char *)p; 42217680Spst } else { 42317680Spst printer = lookup_printer(pcap_datalink(pd)); 42417680Spst pcap_userdata = 0; 42517680Spst } 42617680Spst if (RFileName == NULL) { 42717680Spst (void)fprintf(stderr, "%s: listening on %s\n", 42817680Spst program_name, device); 42917680Spst (void)fflush(stderr); 43017680Spst } 43117680Spst if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) { 43217680Spst (void)fprintf(stderr, "%s: pcap_loop: %s\n", 43317680Spst program_name, pcap_geterr(pd)); 43417680Spst exit(1); 43517680Spst } 43617680Spst pcap_close(pd); 43717680Spst exit(0); 43817680Spst} 43917680Spst 44017680Spst/* make a clean exit on interrupts */ 44175118Sfennerstatic RETSIGTYPE 44217680Spstcleanup(int signo) 44317680Spst{ 44417680Spst struct pcap_stat stat; 44517680Spst 44617680Spst /* Can't print the summary if reading from a savefile */ 44717680Spst if (pd != NULL && pcap_file(pd) == NULL) { 44817680Spst (void)fflush(stdout); 44917680Spst putc('\n', stderr); 45017680Spst if (pcap_stats(pd, &stat) < 0) 45117680Spst (void)fprintf(stderr, "pcap_stats: %s\n", 45217680Spst pcap_geterr(pd)); 45317680Spst else { 45417680Spst (void)fprintf(stderr, "%d packets received by filter\n", 45517680Spst stat.ps_recv); 45617680Spst (void)fprintf(stderr, "%d packets dropped by kernel\n", 45717680Spst stat.ps_drop); 45817680Spst } 45917680Spst } 46017680Spst exit(0); 46117680Spst} 46217680Spst 46317680Spst/* Like default_print() but data need not be aligned */ 46417680Spstvoid 46517680Spstdefault_print_unaligned(register const u_char *cp, register u_int length) 46617680Spst{ 46717680Spst register u_int i, s; 46817680Spst register int nshorts; 46917680Spst 47056648Sarchie if (Xflag) { 47156896Sfenner ascii_print(cp, length); 47256896Sfenner return; 47317680Spst } 47456896Sfenner nshorts = (u_int) length / sizeof(u_short); 47556896Sfenner i = 0; 47656896Sfenner while (--nshorts >= 0) { 47756896Sfenner if ((i++ % 8) == 0) 47856896Sfenner (void)printf("\n\t\t\t"); 47956896Sfenner s = *cp++; 48056896Sfenner (void)printf(" %02x%02x", s, *cp++); 48156896Sfenner } 48256896Sfenner if (length & 1) { 48356896Sfenner if ((i % 8) == 0) 48456896Sfenner (void)printf("\n\t\t\t"); 48556896Sfenner (void)printf(" %02x", *cp); 48656896Sfenner } 48717680Spst} 48817680Spst 48939297Sfenner/* 49039297Sfenner * By default, print the packet out in hex. 49139297Sfenner */ 49217680Spstvoid 49317680Spstdefault_print(register const u_char *bp, register u_int length) 49417680Spst{ 49556896Sfenner default_print_unaligned(bp, length); 49617680Spst} 49717680Spst 49875118Sfennerstatic void 49926180Sfennerusage(void) 50017680Spst{ 50117680Spst extern char version[]; 50239297Sfenner extern char pcap_version[]; 50317680Spst 50439297Sfenner (void)fprintf(stderr, "%s version %s\n", program_name, version); 50539297Sfenner (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 50617680Spst (void)fprintf(stderr, 50775118Sfenner"Usage: %s [-adeflnNOpqStuvxX] [-c count] [ -F file ]\n", program_name); 50817680Spst (void)fprintf(stderr, 50917680Spst"\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n"); 51017680Spst (void)fprintf(stderr, 51117680Spst"\t\t[ -T type ] [ -w file ] [ expression ]\n"); 51217680Spst exit(-1); 51317680Spst} 514