tcpdump.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,726 行 · 第 1/3 页

C
1,726
字号
			else {				for (i = 0; devpointer != 0; i++) {					printf("%d.%s", i+1, devpointer->name);					if (devpointer->description != NULL)						printf(" (%s)", devpointer->description);					printf("\n");					devpointer = devpointer->next;				}			}			return 0;#endif /* HAVE_PCAP_FINDALLDEVS */		case 'L':			Lflag++;			break;		case 'e':			++eflag;			break;		case 'E':#ifndef HAVE_LIBCRYPTO			warning("crypto code not compiled in");#endif			gndo->ndo_espsecret = optarg;			break;		case 'f':			++fflag;			break;		case 'F':			infile = optarg;			break;		case 'G':			Gflag = atoi(optarg);			if (Gflag < 0)				error("invalid number of seconds %s", optarg);                        /* We will create one file initially. */                        Gflag_count = 0;			/* Grab the current time for rotation use. */			if ((Gflag_time = time(NULL)) == (time_t)-1) {				error("main: can't get current time: %s",				    pcap_strerror(errno));			}			break;		case 'i':			if (optarg[0] == '0' && optarg[1] == 0)				error("Invalid adapter index");			#ifdef HAVE_PCAP_FINDALLDEVS			/*			 * If the argument is a number, treat it as			 * an index into the list of adapters, as			 * printed by "tcpdump -D".			 *			 * This should be OK on UNIX systems, as interfaces			 * shouldn't have names that begin with digits.			 * It can be useful on Windows, where more than			 * one interface can have the same name.			 */			if ((devnum = atoi(optarg)) != 0) {				if (devnum < 0)					error("Invalid adapter index");				if (pcap_findalldevs(&devpointer, ebuf) < 0)					error("%s", ebuf);				else {					for (i = 0; i < devnum-1; i++){						devpointer = devpointer->next;						if (devpointer == NULL)							error("Invalid adapter index");					}				}				device = devpointer->name;				break;			}#endif /* HAVE_PCAP_FINDALLDEVS */			device = optarg;			break;#ifdef HAVE_PCAP_CREATE		case 'I':			++Iflag;			break;#endif /* HAVE_PCAP_CREATE */		case 'l':#ifdef WIN32			/*			 * _IOLBF is the same as _IOFBF in Microsoft's C			 * libraries; the only alternative they offer			 * is _IONBF.			 *			 * XXX - this should really be checking for MSVC++,			 * not WIN32, if, for example, MinGW has its own			 * C library that is more UNIX-compatible.			 */			setvbuf(stdout, NULL, _IONBF, 0);#else /* WIN32 */#ifdef HAVE_SETLINEBUF			setlinebuf(stdout);#else			setvbuf(stdout, NULL, _IOLBF, 0);#endif#endif /* WIN32 */			break;		case 'K':			++Kflag;			break;		case 'm':#ifdef LIBSMI			if (smiLoadModule(optarg) == 0) {				error("could not load MIB module %s", optarg);			}			sflag = 1;#else			(void)fprintf(stderr, "%s: ignoring option `-m %s' ",				      program_name, optarg);			(void)fprintf(stderr, "(no libsmi support)\n");#endif			break;		case 'M':			/* TCP-MD5 shared secret */#ifndef HAVE_LIBCRYPTO			warning("crypto code not compiled in");#endif			tcpmd5secret = optarg;			break;		case 'n':			++nflag;			break;		case 'N':			++Nflag;			break;		case 'O':			Oflag = 0;			break;		case 'p':			++pflag;			break;		case 'q':			++qflag;			++suppress_default_print;			break;		case 'r':			RFileName = optarg;			break;		case 'R':			Rflag = 0;			break;		case 's': {			char *end;			snaplen = strtol(optarg, &end, 0);			if (optarg == end || *end != '\0'			    || snaplen < 0 || snaplen > 65535)				error("invalid snaplen %s", optarg);			else if (snaplen == 0)				snaplen = 65535;			break;		}		case 'S':			++Sflag;			break;		case 't':			++tflag;			break;		case 'T':			if (strcasecmp(optarg, "vat") == 0)				packettype = PT_VAT;			else if (strcasecmp(optarg, "wb") == 0)				packettype = PT_WB;			else if (strcasecmp(optarg, "rpc") == 0)				packettype = PT_RPC;			else if (strcasecmp(optarg, "rtp") == 0)				packettype = PT_RTP;			else if (strcasecmp(optarg, "rtcp") == 0)				packettype = PT_RTCP;			else if (strcasecmp(optarg, "snmp") == 0)				packettype = PT_SNMP;			else if (strcasecmp(optarg, "cnfp") == 0)				packettype = PT_CNFP;			else if (strcasecmp(optarg, "tftp") == 0)				packettype = PT_TFTP;			else if (strcasecmp(optarg, "aodv") == 0)				packettype = PT_AODV;			else				error("unknown packet type `%s'", optarg);			break;		case 'u':			++uflag;			break;#ifdef HAVE_PCAP_DUMP_FLUSH		case 'U':			++Uflag;			break;#endif		case 'v':			++vflag;			break;		case 'w':			WFileName = optarg;			break;		case 'W':			Wflag = atoi(optarg);			if (Wflag < 0) 				error("invalid number of output files %s", optarg);			WflagChars = getWflagChars(Wflag);			break;		case 'x':			++xflag;			++suppress_default_print;			break;		case 'X':			++Xflag;			++suppress_default_print;			break;		case 'y':			gndo->ndo_dltname = optarg;			gndo->ndo_dlt =			  pcap_datalink_name_to_val(gndo->ndo_dltname);			if (gndo->ndo_dlt < 0)				error("invalid data link type %s", gndo->ndo_dltname);			break;#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)		case 'Y':			{			/* Undocumented flag */#ifdef HAVE_PCAP_DEBUG			extern int pcap_debug;			pcap_debug = 1;#else			extern int yydebug;			yydebug = 1;#endif			}			break;#endif		case 'z':			if (optarg) {				zflag = strdup(optarg);			} else {				usage();				/* NOTREACHED */			}			break;		case 'Z':			if (optarg) {				username = strdup(optarg);			}			else {				usage();				/* NOTREACHED */			}			break;		default:			usage();			/* NOTREACHED */		}	switch (tflag) {	case 0: /* Default */	case 4: /* Default + Date*/		thiszone = gmt2local(0);		break;	case 1: /* No time stamp */	case 2: /* Unix timeval style */	case 3: /* Microseconds since previous packet */        case 5: /* Microseconds since first packet */		break;	default: /* Not supported */		error("only -t, -tt, -ttt, -tttt and -ttttt are supported");		break;	}#ifdef WITH_CHROOT	/* if run as root, prepare for chrooting */	if (getuid() == 0 || geteuid() == 0) {		/* future extensibility for cmd-line arguments */		if (!chroot_dir)			chroot_dir = WITH_CHROOT;	}#endif#ifdef WITH_USER	/* if run as root, prepare for dropping root privileges */	if (getuid() == 0 || geteuid() == 0) {		/* Run with '-Z root' to restore old behaviour */ 		if (!username)			username = WITH_USER;	}#endif	if (RFileName != NULL) {		int dlt;		const char *dlt_name;#ifndef WIN32		/*		 * We don't need network access, so relinquish any set-UID		 * or set-GID privileges we have (if any).		 *		 * We do *not* want set-UID privileges when opening a		 * trace file, as that might let the user read other		 * people's trace files (especially if we're set-UID		 * root).		 */		if (setgid(getgid()) != 0 || setuid(getuid()) != 0 )			fprintf(stderr, "Warning: setgid/setuid failed !\n");#endif /* WIN32 */		pd = pcap_open_offline(RFileName, ebuf);		if (pd == NULL)			error("%s", ebuf);		dlt = pcap_datalink(pd);		dlt_name = pcap_datalink_val_to_name(dlt);		if (dlt_name == NULL) {			fprintf(stderr, "reading from file %s, link-type %u\n",			    RFileName, dlt);		} else {			fprintf(stderr,			    "reading from file %s, link-type %s (%s)\n",			    RFileName, dlt_name,			    pcap_datalink_val_to_description(dlt));		}		localnet = 0;		netmask = 0;		if (fflag != 0)			error("-f and -r options are incompatible");	} else {		if (device == NULL) {			device = pcap_lookupdev(ebuf);			if (device == NULL)				error("%s", ebuf);		}#ifdef WIN32		if(strlen(device) == 1)	//we assume that an ASCII string is always longer than 1 char		{						//a Unicode string has a \0 as second byte (so strlen() is 1)			fprintf(stderr, "%s: listening on %ws\n", program_name, device);		}		else		{			fprintf(stderr, "%s: listening on %s\n", program_name, device);		}		fflush(stderr);	#endif /* WIN32 */#ifdef HAVE_PCAP_CREATE		pd = pcap_create(device, ebuf);		if (pd == NULL)			error("%s", ebuf);		status = pcap_set_snaplen(pd, snaplen);		if (status != 0)			error("%s: pcap_set_snaplen failed: %s",			    device, pcap_statustostr(status));		status = pcap_set_promisc(pd, !pflag);		if (status != 0)			error("%s: pcap_set_promisc failed: %s",			    device, pcap_statustostr(status));		if (Iflag) {			status = pcap_set_rfmon(pd, 1);			if (status != 0)				error("%s: pcap_set_rfmon failed: %s",				    device, pcap_statustostr(status));		}		status = pcap_set_timeout(pd, 1000);		if (status != 0)			error("%s: pcap_set_timeout failed: %s",			    device, pcap_statustostr(status));		if (Bflag != 0) {			status = pcap_set_buffer_size(pd, Bflag);			if (status != 0)				error("%s: pcap_set_buffer_size failed: %s",				    device, pcap_statustostr(status));		}		status = pcap_activate(pd);		if (status < 0) {			/*			 * pcap_activate() failed.			 */			cp = pcap_geterr(pd);			if (status == PCAP_ERROR)				error("%s", cp);			else if ((status == PCAP_ERROR_NO_SUCH_DEVICE ||			          status == PCAP_ERROR_PERM_DENIED) &&			         *cp != '\0')				error("%s: %s\n(%s)", device,				    pcap_statustostr(status), cp);			else				error("%s: %s", device,				    pcap_statustostr(status));		} else if (status > 0) {			/*			 * pcap_activate() succeeded, but it's warning us			 * of a problem it had.			 */			cp = pcap_geterr(pd);			if (status == PCAP_WARNING)				warning("%s", cp);			else if (status == PCAP_WARNING_PROMISC_NOTSUP &&			         *cp != '\0')				warning("%s: %s\n(%s)", device,				    pcap_statustostr(status), cp);			else				warning("%s: %s", device,				    pcap_statustostr(status));		}#else		*ebuf = '\0';		pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);		if (pd == NULL)			error("%s", ebuf);		else if (*ebuf)			warning("%s", ebuf);#endif /* HAVE_PCAP_CREATE */		/*		 * Let user own process after socket has been opened.		 */#ifndef WIN32		if (setgid(getgid()) != 0 || setuid(getuid()) != 0)			fprintf(stderr, "Warning: setgid/setuid failed !\n");#endif /* WIN32 */#if !defined(HAVE_PCAP_CREATE) && defined(WIN32)		if(Bflag != 0)			if(pcap_setbuff(pd, Bflag)==-1){				error("%s", pcap_geterr(pd));			}#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */		if (Lflag)			show_dlts_and_exit(pd);		if (gndo->ndo_dlt >= 0) {#ifdef HAVE_PCAP_SET_DATALINK			if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0)				error("%s", pcap_geterr(pd));#else			/*			 * We don't actually support changing the			 * data link type, so we only let them			 * set it to what it already is.			 */			if (gndo->ndo_dlt != pcap_datalink(pd)) {				error("%s is not one of the DLTs supported by this device\n",				      gndo->ndo_dltname);			}#endif			(void)fprintf(stderr, "%s: data link type %s\n",				      program_name, gndo->ndo_dltname);			(void)fflush(stderr);		}		i = pcap_snapshot(pd);		if (snaplen < i) {			warning("snaplen raised from %d to %d", snaplen, i);			snaplen = i;		}		if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {			localnet = 0;			netmask = 0;			warning("%s", ebuf);		}	}	if (infile)		cmdbuf = read_infile(infile);	else		cmdbuf = copy_argv(&argv[optind]);	if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)		error("%s", pcap_geterr(pd));	if (dflag) {		bpf_dump(&fcode, dflag);		pcap_close(pd);		exit(0);	}	init_addrtoname(localnet, netmask);        init_checksum();#ifndef WIN32		(void)setsignal(SIGPIPE, cleanup);	(void)setsignal(SIGTERM, cleanup);	(void)setsignal(SIGINT, cleanup);	(void)setsignal(SIGCHLD, child_cleanup);#endif /* WIN32 */	/* Cooperate with nohup(1) */#ifndef WIN32		if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)		(void)setsignal(SIGHUP, oldhandler);#endif /* WIN32 */	if (pcap_setfilter(pd, &fcode) < 0)		error("%s", pcap_geterr(pd));	if (WFileName) {		pcap_dumper_t *p;		/* Do not exceed the default NAME_MAX for files. */		dumpinfo.CurrentFileName = (char *)malloc(NAME_MAX + 1);		if (dumpinfo.CurrentFileName == NULL)			error("malloc of dumpinfo.CurrentFileName");		/* We do not need numbering for dumpfiles if Cflag isn't set. */		if (Cflag != 0)		  MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars);		else		  MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);		p = pcap_dump_open(pd, dumpinfo.CurrentFileName);		if (p == NULL)			error("%s", pcap_geterr(pd));		if (Cflag != 0 || Gflag != 0) {			callback = dump_packet_and_trunc;			dumpinfo.WFileName = WFileName;			dumpinfo.pd = pd;			dumpinfo.p = p;			pcap_userdata = (u_char *)&dumpinfo;		} else {			callback = dump_packet;			pcap_userdata = (u_char *)p;		}	} else {		type = pcap_datalink(pd);		printinfo.printer = lookup_printer(type);		if (printinfo.printer == NULL) {			gndo->ndo_dltname = pcap_datalink_val_to_name(type);			if (gndo->ndo_dltname != NULL)				error("unsupported data link type %s",				      gndo->ndo_dltname);			else				error("unsupported data link type %d", type);		}		callback = print_packet;		pcap_userdata = (u_char *)&printinfo;	}#ifndef WIN32	/*	 * We cannot do this earlier, because we want to be able to open	 * the file (if done) for writing before giving up permissions.	 */	if (getuid() == 0 || geteuid() == 0) {		if (username || chroot_dir)			droproot(username, chroot_dir);	}#endif /* WIN32 */#ifdef SIGINFO	/*	 * We can't get statistics when reading from a file rather	 * than capturing from a device.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?