tcpdump.c
来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,726 行 · 第 1/3 页
C
1,726 行
/* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Support for splitting captures into multiple files with a maximum * file size: * * Copyright (c) 2001 * Seth Webster <swebster@sst.ll.mit.edu> */#ifndef lintstatic const char copyright[] _U_ = "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\The Regents of the University of California. All rights reserved.\n";static const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.271.2.11 2008-09-25 21:50:04 guy Exp $ (LBL)";#endif/* * tcpdump - monitor tcp/ip traffic on an ethernet. * * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. * Mercilessly hacked and occasionally improved since then via the * combined efforts of Van, Steve McCanne and Craig Leres of LBL. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <tcpdump-stdinc.h>#ifdef WIN32#include "getopt.h"#include "w32_fzs.h"extern int strcasecmp (const char *__s1, const char *__s2);extern int SIZE_BUF;#define off_t long#define uint UINT#endif /* WIN32 */#ifdef HAVE_SMI_H#include <smi.h>#endif#include <pcap.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <limits.h>#ifndef WIN32#include <sys/wait.h>#include <sys/resource.h>#include <pwd.h>#include <grp.h>#include <errno.h>#endif /* WIN32 */#include "netdissect.h"#include "interface.h"#include "addrtoname.h"#include "machdep.h"#include "setsignal.h"#include "gmt2local.h"#include "pcap-missing.h"#ifndef NAME_MAX#define NAME_MAX 255#endifnetdissect_options Gndo;netdissect_options *gndo = &Gndo;int dflag; /* print filter code */int Lflag; /* list available data link types and exit */char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */static int infodelay;static int infoprint;char *program_name;int32_t thiszone; /* seconds offset from gmt to local time *//* Forwards */static RETSIGTYPE cleanup(int);static RETSIGTYPE child_cleanup(int);static void usage(void) __attribute__((noreturn));static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn));static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);static void ndo_default_print(netdissect_options *, const u_char *, u_int);static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *);static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);static void droproot(const char *, const char *);static void ndo_error(netdissect_options *ndo, const char *fmt, ...);static void ndo_warning(netdissect_options *ndo, const char *fmt, ...);#ifdef SIGINFORETSIGTYPE requestinfo(int);#endif#if defined(USE_WIN32_MM_TIMER) #include <MMsystem.h> static UINT timer_id; static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR);#elif defined(HAVE_ALARM) static void verbose_stats_dump(int sig);#endifstatic void info(int);static u_int packets_captured;typedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *);struct printer { if_printer f; int type;};static struct printer printers[] = { { arcnet_if_print, DLT_ARCNET },#ifdef DLT_ARCNET_LINUX { arcnet_linux_if_print, DLT_ARCNET_LINUX },#endif { ether_if_print, DLT_EN10MB }, { token_if_print, DLT_IEEE802 },#ifdef DLT_LANE8023 { lane_if_print, DLT_LANE8023 },#endif#ifdef DLT_CIP { cip_if_print, DLT_CIP },#endif#ifdef DLT_ATM_CLIP { cip_if_print, DLT_ATM_CLIP },#endif { sl_if_print, DLT_SLIP },#ifdef DLT_SLIP_BSDOS { sl_bsdos_if_print, DLT_SLIP_BSDOS },#endif { ppp_if_print, DLT_PPP },#ifdef DLT_PPP_WITHDIRECTION { ppp_if_print, DLT_PPP_WITHDIRECTION },#endif#ifdef DLT_PPP_BSDOS { ppp_bsdos_if_print, DLT_PPP_BSDOS },#endif { fddi_if_print, DLT_FDDI }, { null_if_print, DLT_NULL },#ifdef DLT_LOOP { null_if_print, DLT_LOOP },#endif { raw_if_print, DLT_RAW }, { atm_if_print, DLT_ATM_RFC1483 },#ifdef DLT_C_HDLC { chdlc_if_print, DLT_C_HDLC },#endif#ifdef DLT_HDLC { chdlc_if_print, DLT_HDLC },#endif#ifdef DLT_PPP_SERIAL { ppp_hdlc_if_print, DLT_PPP_SERIAL },#endif#ifdef DLT_PPP_ETHER { pppoe_if_print, DLT_PPP_ETHER },#endif#ifdef DLT_LINUX_SLL { sll_if_print, DLT_LINUX_SLL },#endif#ifdef DLT_IEEE802_11 { ieee802_11_if_print, DLT_IEEE802_11},#endif#ifdef DLT_LTALK { ltalk_if_print, DLT_LTALK },#endif#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) { pflog_if_print, DLT_PFLOG },#endif#ifdef DLT_FR { fr_if_print, DLT_FR },#endif#ifdef DLT_FRELAY { fr_if_print, DLT_FRELAY },#endif#ifdef DLT_SUNATM { sunatm_if_print, DLT_SUNATM },#endif#ifdef DLT_IP_OVER_FC { ipfc_if_print, DLT_IP_OVER_FC },#endif#ifdef DLT_PRISM_HEADER { prism_if_print, DLT_PRISM_HEADER },#endif#ifdef DLT_IEEE802_11_RADIO { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO },#endif#ifdef DLT_ENC { enc_if_print, DLT_ENC },#endif#ifdef DLT_SYMANTEC_FIREWALL { symantec_if_print, DLT_SYMANTEC_FIREWALL },#endif#ifdef DLT_APPLE_IP_OVER_IEEE1394 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 },#endif#ifdef DLT_IEEE802_11_RADIO_AVS { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS },#endif#ifdef DLT_JUNIPER_ATM1 { juniper_atm1_print, DLT_JUNIPER_ATM1 },#endif#ifdef DLT_JUNIPER_ATM2 { juniper_atm2_print, DLT_JUNIPER_ATM2 },#endif#ifdef DLT_JUNIPER_MFR { juniper_mfr_print, DLT_JUNIPER_MFR },#endif#ifdef DLT_JUNIPER_MLFR { juniper_mlfr_print, DLT_JUNIPER_MLFR },#endif#ifdef DLT_JUNIPER_MLPPP { juniper_mlppp_print, DLT_JUNIPER_MLPPP },#endif#ifdef DLT_JUNIPER_PPPOE { juniper_pppoe_print, DLT_JUNIPER_PPPOE },#endif#ifdef DLT_JUNIPER_PPPOE_ATM { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM },#endif#ifdef DLT_JUNIPER_GGSN { juniper_ggsn_print, DLT_JUNIPER_GGSN },#endif#ifdef DLT_JUNIPER_ES { juniper_es_print, DLT_JUNIPER_ES },#endif#ifdef DLT_JUNIPER_MONITOR { juniper_monitor_print, DLT_JUNIPER_MONITOR },#endif#ifdef DLT_JUNIPER_SERVICES { juniper_services_print, DLT_JUNIPER_SERVICES },#endif#ifdef DLT_JUNIPER_ETHER { juniper_ether_print, DLT_JUNIPER_ETHER },#endif#ifdef DLT_JUNIPER_PPP { juniper_ppp_print, DLT_JUNIPER_PPP },#endif#ifdef DLT_JUNIPER_FRELAY { juniper_frelay_print, DLT_JUNIPER_FRELAY },#endif#ifdef DLT_JUNIPER_CHDLC { juniper_chdlc_print, DLT_JUNIPER_CHDLC },#endif#ifdef DLT_MFR { mfr_if_print, DLT_MFR },#endif#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR},#endif { NULL, 0 },};static if_printerlookup_printer(int type){ struct printer *p; for (p = printers; p->f; ++p) if (type == p->type) return p->f; return NULL; /* NOTREACHED */}static pcap_t *pd;extern int optind;extern int opterr;extern char *optarg;struct print_info { if_printer printer;};struct dump_info { char *WFileName; char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p;};static voidshow_dlts_and_exit(pcap_t *pd){ int n_dlts; int *dlts = 0; const char *dlt_name; n_dlts = pcap_list_datalinks(pd, &dlts); if (n_dlts < 0) error("%s", pcap_geterr(pd)); else if (n_dlts == 0 || !dlts) error("No data link types."); (void) fprintf(stderr, "Data link types (use option -y to set):\n"); while (--n_dlts >= 0) { dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); if (dlt_name != NULL) { (void) fprintf(stderr, " %s (%s)", dlt_name, pcap_datalink_val_to_description(dlts[n_dlts])); /* * OK, does tcpdump handle that type? */ if (lookup_printer(dlts[n_dlts]) == NULL) (void) fprintf(stderr, " (printing not supported)"); putchar('\n'); } else { (void) fprintf(stderr, " DLT %d (printing not supported)\n", dlts[n_dlts]); } } free(dlts); exit(0);}/* * Set up flags that might or might not be supported depending on the * version of libpcap we're using. */#if defined(HAVE_PCAP_CREATE) || defined(WIN32)#define B_FLAG "B:"#define B_FLAG_USAGE " [ -B size ]"#else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */#define B_FLAG#define B_FLAG_USAGE#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */#ifdef HAVE_PCAP_CREATE#define I_FLAG "I"#else /* HAVE_PCAP_CREATE */#define I_FLAG#endif /* HAVE_PCAP_CREATE */#ifdef HAVE_PCAP_FINDALLDEVS#ifndef HAVE_PCAP_IF_T#undef HAVE_PCAP_FINDALLDEVS#endif#endif#ifdef HAVE_PCAP_FINDALLDEVS#define D_FLAG "D"#else#define D_FLAG#endif#ifdef HAVE_PCAP_DUMP_FLUSH#define U_FLAG "U"#else#define U_FLAG#endif#ifndef WIN32/* Drop root privileges and chroot if necessary */static voiddroproot(const char *username, const char *chroot_dir){ struct passwd *pw = NULL; if (chroot_dir && !username) { fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); exit(1); } pw = getpwnam(username); if (pw) { if (chroot_dir) { if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", chroot_dir, pcap_strerror(errno)); exit(1); } } if (initgroups(pw->pw_name, pw->pw_gid) != 0 || setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", username, (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid, pcap_strerror(errno)); exit(1); } } else { fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", username); exit(1); }}#endif /* WIN32 */static intgetWflagChars(int x){ int c = 0; x -= 1; while (x > 0) { c += 1; x /= 10; } return c;}static voidMakeFilename(char *buffer, char *orig_name, int cnt, int max_chars){ char *filename = malloc(NAME_MAX + 1); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { struct tm *local_tm; /* Convert Gflag_time to a usable format */ if ((local_tm = localtime(&Gflag_time)) == NULL) { error("MakeTimedFilename: localtime"); } /* There's no good way to detect an error in strftime since a return * value of 0 isn't necessarily failure. */ strftime(filename, NAME_MAX, orig_name, local_tm); } else { strncpy(filename, orig_name, NAME_MAX); } if (cnt == 0 && max_chars == 0) strncpy(buffer, filename, NAME_MAX + 1); else if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX) /* Report an error if the filename is too large */ error("too many output files or filename is too long (> %d)", NAME_MAX); free(filename);}static int tcpdump_printf(netdissect_options *ndo _U_, const char *fmt, ...){ va_list args; int ret; va_start(args, fmt); ret=vfprintf(stdout, fmt, args); va_end(args); return ret;}intmain(int argc, char **argv){ register int cnt, op, i; bpf_u_int32 localnet, netmask; register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; pcap_handler callback; int type; struct bpf_program fcode;#ifndef WIN32 RETSIGTYPE (*oldhandler)(int);#endif struct print_info printinfo; struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; char *username = NULL; char *chroot_dir = NULL;#ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *devpointer; int devnum;#endif int status;#ifdef WIN32 if(wsockinit() != 0) return 1;#endif /* WIN32 */ gndo->ndo_Oflag=1; gndo->ndo_Rflag=1; gndo->ndo_dlt=-1; gndo->ndo_default_print=ndo_default_print; gndo->ndo_printf=tcpdump_printf; gndo->ndo_error=ndo_error; gndo->ndo_warning=ndo_warning; gndo->ndo_snaplen = DEFAULT_SNAPLEN; cnt = -1; device = NULL; infile = NULL; RFileName = NULL; WFileName = NULL; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) error("%s", ebuf);#ifdef LIBSMI smiInit("tcpdump");#endif opterr = 0; while ( (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:" I_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1) switch (op) { case 'a': /* compatibility for old -a */ break; case 'A': ++Aflag; break;#if defined(HAVE_PCAP_CREATE) || defined(WIN32) case 'B': Bflag = atoi(optarg)*1024; if (Bflag <= 0) error("invalid packet buffer size %s", optarg); break;#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ case 'c': cnt = atoi(optarg); if (cnt <= 0) error("invalid packet count %s", optarg); break; case 'C': Cflag = atoi(optarg) * 1000000; if (Cflag < 0) error("invalid file size %s", optarg); break; case 'd': ++dflag; break;#ifdef HAVE_PCAP_FINDALLDEVS case 'D': if (pcap_findalldevs(&devpointer, ebuf) < 0) error("%s", ebuf);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?