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 + -
显示快捷键?