⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gulp.c

📁 改善linux指令 "tcpdump" 效能的免費open source程式
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (check_block) {	if (would_block)	    fprintf(stderr, "select reports writes would have blocked\n");	else	    fprintf(stderr, "select reports writes would not have blocked\n");	}    /* cleanup */    pcap_freecode(&fp);#ifndef RHEL3    pcap_close(handle);#endif /* RHEL3 */    }#endif /* JUSTCOPY */    fprintf(stderr, "ring buffer use: %.1lf%% of %d MB\n",       	100.0*(double)maxbuffered/(double)(ringsize), ringsize/1024/1024);    eof = 1;    fflush(stderr);    pthread_exit(NULL);    }/* * Redirect standard output into a new capture file in the specified directory. * * In case Gulp is running setuid root, try to prevent a user from * overwriting system files.  This is accomplished by creating output files * with random temporary names in a directory to which the user has write * access and subsequently renaming them to names unlikely to cause trouble. */intnewoutfile(char *dir, int num) {    char tfile[PATH_MAX];		/* output temp filename */    char ofile[PATH_MAX];		/* output real filename */    if (access(dir, W_OK) != 0) {	if (access(dir, F_OK) != 0) {	    fprintf(stderr, "%s: -o dir does not exist: '%s'\n",		progname, dir);	    return (0);	    }	fprintf(stderr, "%s: can't create files in '%s'\n", progname, dir);	return (0);	}    snprintf(tfile, sizeof(tfile), "%s%s", dir, TEMPLATE);    snprintf(ofile, sizeof(ofile), "%s/pcap%03d", dir, num);    int tmpfd = mkstemp(tfile);    fchown(tmpfd, getuid(), -1);	/* in case running setuid */    if (tmpfd >= 0) {	if (freopen(tfile, "w", stdout) == NULL) {	    fprintf(stderr, "%s: can't create output file: '%s'\n",		progname, tfile);	    return (0);	    }	dup2(tmpfd, fileno(stdout));	/* try to use the initial fd */	close(tmpfd);	rename(tfile, ofile);	return (1);	}    else {	fprintf(stderr, "%s: can't create: '%s'\n", progname, tfile);	return(0);	}    return (0);				/* some error */    }/* * This thread copies the ring buffer to stdout in WriteSize chunks * or every second (or so) whichever happens first. */void *Writer(void *arg)    {    int n;    int used;    int writesize;    int done = 0;    int pushed = 0;			/* value of "push" at last write  */#ifdef CPU_SET    int wtid = gettid();		/* Writer thread id */    cpu_set_t csmask;    CPU_ZERO(&csmask);    CPU_SET(WRITER_CPU, &csmask);    if (my_sched_setaffinity(wtid, sizeof(cpu_set_t), &csmask) != 0) {        fprintf(stderr, "%s: Writer could not set cpu affinity: %s\n",	    progname, strerror(errno));        }    if (setpriority(PRIO_PROCESS, wtid, WRITE_PRIO) != 0) {	fprintf(stderr, "%s: Writer could not set scheduling priority: %s\n",	    progname, strerror(errno));	}#else    replace with equivalent code for your OS or delete and run less optimally#endif /* CPU_SET */        if (geteuid()!=getuid()) {	while (!reader_ready) usleep(poll_usecs);	seteuid(getuid());		/* drop setuid privilege */	}    if (odir && !newoutfile(odir, filec++)) {	exit(1);	}    while (!done) {	used = end - start; if (used < 0) used += ringsize;	if (start & (WriteSize-1))	    writesize = WriteSize - (start & (WriteSize-1)); 	/* re-align */	else	    writesize = WriteSize;	while (used < WriteSize) {	    if (eof) {		done = 1;		used = end - start; if (used < 0) used += ringsize;		writesize = used;		break;		}	    else if (push > pushed+1) {		writesize = used;		if (used) break;		}	    usleep(poll_usecs);	    used = end - start; if (used < 0) used += ringsize;	    }	n = ringsize - start;		/* short write at end of ring? */	if (n < writesize) writesize = n;	/* write remainder next loop */	if (check_block) {	    /*	     * this is mostly of academic interest	     */	    fd_set w_set;	    struct timeval timeout;	    timeout.tv_sec = 0;	    timeout.tv_usec = 0;	    FD_ZERO(&w_set);	    FD_SET(1, &w_set);	    if (select(2, NULL, &w_set, NULL, &timeout) != -1) {		if (!FD_ISSET(1, &w_set)) {		    would_block = 1;		    if (yield_if_blocking) {			writesize = 0;	/* next iteration will try again */			sched_yield();			}		    }		}	    }	if (writesize > 0) {	    if (start < boundary && start+writesize >= boundary) {		writesize = boundary - start;		}	    writesize = write(1, buf+start, writesize);	    }	if (writesize == -1 && errno == EINTR) writesize = 0;	if (writesize < 0) {	    fprintf(stderr, "%s: fatal write error: %s\n",	       	progname, strerror(errno));	    eof = 1;	    fflush(stderr);	    pthread_exit(0);	    }	start += (start+writesize >= ringsize) ? writesize-ringsize : writesize;	if (start == boundary) {	    if (max_files && filec >= max_files) filec = 0;	    newoutfile(odir, filec++);	    boundary = -2;	    }	pushed = push;	}    pthread_exit(NULL);    }voidusage() {    fprintf(stderr,    "\n"    "Usage: %s [--help | options]\n"    "    --help\tprints this usage summary\n"    "    supported options include:\n"#ifdef JUSTCOPY    "    (This binary was compiled with JUSTCOPY so some options are unavailable)\n"#else  /* JUSTCOPY */    "      -d\tdecapsulate Cisco ERSPAN GRE packets (sets -f value)\n"    "      -f \"...\"\tspecify a pcap filter - see manpage and -d\n"    "      -i eth#|-\tspecify ethernet capture interface or '-' for stdin\n"    "      -s #\tspecify packet capture \"snapshot\" length limit\n"#endif /* JUSTCOPY */    "      -r #\tspecify ring buffer size in megabytes (1-1024)\n"    "      -c\tjust buffer stdin to stdout (works with arbitrary data)\n"    "      -x\trequest exclusive lock (to be the only instance running)\n"    "      -X\trun even when locking would forbid it\n"    "      -v\tprint program version and exit\n"    "      -Vx...x\tdisplay packet loss and buffer use - see manpage\n"    "      -p #\tspecify full/empty polling interval in microseconds\n"    "      -q\tsuppress buffer full warnings\n"    "      -z #\tspecify write blocksize (even power of 2, default 65536)\n"    "    for long-term capture\n"    "      -o dir\tredirect pcap output to a collection of files in dir\n"    "      -C #\tlimit each pcap file in -o dir to # times the (-r #) size\n"    "      -W #\toverwrite pcap files in -o dir rather than start #+1\n"    "    and some of academic interest only:\n"    "      -B\tcheck if select(2) would ever have blocked on write\n"    "      -Y\tavoid writes which would block\n"    "\n", progname);    }/* * This thread starts the other two and then wakes every half second * to increment a variable the writer uses to decide if it should flush. * Flushing greatly facilitates interactive use and testing tcpdump filters. */int main(int argc, char *argv[], char *envp[])    {    pthread_t threads[2];    int rc, t, c, errflag=0;    extern char *optarg;    extern int optind;    int bitmask;    start = end = eof = 0;    progname = argv[0];#ifdef JUSTCOPY    just_copy = 1;#endif    /* pick up default interface to sniff from ENV if present */    if (getenv("CAP_IFACE")) dev = getenv("CAP_IFACE");    if (argc > 1 && strcmp(argv[1], "--help") == 0) ++errflag; else#ifndef JUSTCOPY    while ((c = getopt(argc, argv, "BXYcdqvxf:i:p:r:s:z:V:o:C:W:")) != EOF)#else  /* JUSTCOPY */    while ((c = getopt(argc, argv, "BXYcqvxp:r:z:V:o:C:W:")) != EOF)#endif /* JUSTCOPY */	{	switch (c) {	    case 'B':		check_block = 1;	/* use select to avoid write blocking */		break;	    case 'Y':		check_block = 1;		yield_if_blocking = 1;	/* don't issue blocking writes */		break;	    case 'V':			/* produce periodic drop,ring stats */		ps_stat_ptr = optarg;		if (ps_stat_ptr[0] == '-') {		    fprintf(stderr, "%s: %s is suspicious as argument of -V\n",			progname, ps_stat_ptr);		    errflag++;		    }		ps_stat_len = strlen(ps_stat_ptr);		break;	    case 'c':		just_copy = 1;		/* just read from stdin and buffer */		break;	    case 'd':		gre_hdrlen = GRE_HDRLEN;/* decapsulate Cisco GRE */		filter_exp = "proto gre";		break;	    case 'f':		filter_exp = optarg;		break;	    case 'i':			/* specify ethernet device name */		dev = optarg;		break;	    case 'p':			/* specify polling sleep u_secs */		t = atoi(optarg);		if (t < 0 || t > 1000000) {		    fprintf(stderr, "%s: -p number must be 0-1000000\n",			progname);		    ++errflag;		    }		else poll_usecs = t;		break;	    case 'q':			/* warnings can be annoying */		warn_buf_full = 0;		break;	    case 'r':		t = atoi(optarg);	/* specify ring size in MB */		if (t < 1 || t > 1024) {		    fprintf(stderr, "%s: -r number must be 1-1024\n",			progname);		    ++errflag;		    }		else ringsize = t * 1024*1024;		break;	    case 's':			/* specify snapshot length */		t = atoi(optarg);		if (t <= 0 || t > SNAP_LEN) t = SNAP_LEN;		snap_len = t;		break;	    case 'v':		fprintf(stderr, "%s\n", id+5);		exit(0);		break;	    case 'x':		xlock = 1;		/* request exclusive lock */		break;	    case 'X':		xlock = -1;		/* disregard locking conflicts */		break;	    case 'z':		t = atoi(optarg);	/* specify goal write size 2^n */		for (bitmask=1; bitmask<=65536; bitmask*=2) {		    if (t == bitmask) WriteSize = t;		    }		if (WriteSize != t) {		    fprintf(stderr, "%s: -z number must be a power of 2\n",			progname);		    errflag++;		    }		break;	    case 'o':		odir = optarg;		if (strlen(odir) >= PATH_MAX-strlen(TEMPLATE)-1) {		    fprintf(stderr, "%s: -o name too long: %s\n",			progname, odir);		    errflag++;		    }		break;	    case 'C':		split_after = atoi(optarg);		if (split_after < 1) {		    fprintf(stderr, "%s: -C # must be 1 or greater\n",			progname);		    errflag++;		    }		break;	    case 'W':		max_files = atoi(optarg);		if (max_files < 1) {		    fprintf(stderr, "%s: -W # must be 1 or greater\n",			progname);		    errflag++;		    }		break;	    default:		errflag++;		break;	    }	}    if (errflag || optind < argc) {	usage();	exit(1);	}    /*     * if -d is spcified, -s refers to decapsulated sizes, make it happen     */    d_snap_len = snap_len + gre_hdrlen;    if (d_snap_len <= 0 || d_snap_len > SNAP_LEN) d_snap_len = SNAP_LEN;    if (isatty(1) && !just_copy && !odir) {	fprintf(stderr, "%s:\tSending raw pcap data to a terminal is not a "	    "good idea.\n\tIf you really want to do that, pipe %s through "	    "cat but you\n\tprobably want to redirect stdout to a file or "	    "another program instead.\n\tPerhaps you meant to pipe into "	    "'tcpdump -r-' or 'ngrep -I-' ?\n", progname, progname);	if (argc == 1) usage();	exit(1);	}    /*     * Advisory locking logic     */    if ((lockfd = open("/proc/self/exe", O_RDONLY)) < 0) {	fprintf(stderr, "%s: Warning: couldn't open lockfile so not locking\n",	    progname);	}    else {	if (flock(lockfd, ((xlock==1 ? LOCK_EX : LOCK_SH) | LOCK_NB)) == -1) {	    if (xlock < 0) {		fprintf(stderr, "%s: Warning: overriding locking\n",		    progname);		}	    else {		fprintf(stderr, "%s: Exiting due to lock conflict\n",		    progname);		exit(1);		}	    }	}    buf = malloc(ringsize+1);    if (!buf) {	fprintf(stderr, "%s: Malloc failed, exiting\n", progname); exit(1);	}    if (mlock(buf, ringsize+1) != 0) {	fprintf(stderr, "%s: Warning: could not lock ring buffer into RAM\n",	    progname);	}    rc = pthread_create(&threads[0], NULL, &Reader, NULL);    if (rc){	fprintf(stderr, "%s: pthread_create error\n", progname);	exit(1);	}    rc = pthread_create(&threads[1], NULL, &Writer, NULL);    if (rc){	fprintf(stderr, "%s: pthread_create error\n", progname);	exit(1);	}    while (!eof) {	usleep(500000);	push += 1;	/*	 * emit some stats which may be useful while testing	 * if argument to -V is big enough to write into, do so	 * else write to stdout.	 */	if (ps_stat_ptr) {	    char sbuf[V_WIDTH+1];	    int drop_symb = 0;	    int used = end - start; if (used < 0) used += ringsize;#ifndef JUSTCOPY	    if (handle && pcap_stats(handle, &pcs) >= 0) {		int d = pcs.ps_drop;		/* count how many decimal digits are in the drop count */		for (drop_symb = 0; drop_symb < 9; ++drop_symb) {		    if (d == 0) break;		    d /= 10;		    }		}#endif /* JUSTCOPY */	    if (ps_stat_len >= V_WIDTH) {	/* put stats in arg list */		sprintf(sbuf, "%1.1d %.0lf,%.0lf%%",		    drop_symb,	/* a digit from 0-9 */		    100.0*(double)used/(double)(ringsize),		    100.0*(double)maxbuffered/(double)(ringsize));		sprintf(ps_stat_ptr, "%-*s", ps_stat_len, sbuf);		}	    else {				/* puts stats on stderr */		fprintf(stderr,		    "pkts dropped: %d, ring buf: %.1lf%%, max: %.1lf%%\n",		    (drop_symb > 0 ? pcs.ps_drop : 0),		    100.0*(double)used/(double)(ringsize),		    100.0*(double)maxbuffered/(double)(ringsize));		}	    }	}    fflush(stderr);    pthread_exit(NULL);    }

⌨️ 快捷键说明

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