diff --git a/tcpdump.c b/tcpdump.c index ac35b2b..099cfad 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -609,9 +609,10 @@ main(int argc, char **argv) { register int cnt, op, i; bpf_u_int32 localnet, netmask; - register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; + register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; pcap_handler callback; int type; + int first; struct bpf_program fcode; #ifndef WIN32 RETSIGTYPE (*oldhandler)(int); @@ -620,13 +621,16 @@ main(int argc, char **argv) struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; + char VFileLine[NAME_MAX + 1]; char *username = NULL; char *chroot_dir = NULL; + char *ret = NULL; #ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *devpointer; int devnum; #endif int status; + FILE *VFile; #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ @@ -642,10 +646,13 @@ main(int argc, char **argv) gndo->ndo_snaplen = DEFAULT_SNAPLEN; cnt = -1; + first = 0; device = NULL; infile = NULL; RFileName = NULL; + VFileName = NULL; WFileName = NULL; + cmdbuf = NULL; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else @@ -659,7 +666,7 @@ main(int argc, char **argv) #endif while ( - (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1) + (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "V:vw:W:xXy:Yz:Z:")) != -1) switch (op) { case 'a': @@ -949,6 +956,10 @@ main(int argc, char **argv) break; #endif + case 'V': + VFileName = optarg; + break; + case 'v': ++vflag; break; @@ -1056,11 +1067,22 @@ main(int argc, char **argv) } #endif - if (RFileName != NULL) { - int dlt; - const char *dlt_name; +#ifndef WIN32 + (void)setsignal(SIGPIPE, cleanup); + (void)setsignal(SIGTERM, cleanup); + (void)setsignal(SIGINT, cleanup); +#endif /* WIN32 */ +#if defined(HAVE_FORK) || defined(HAVE_VFORK) + (void)setsignal(SIGCHLD, child_cleanup); +#endif + /* Cooperate with nohup(1) */ +#ifndef WIN32 + if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) + (void)setsignal(SIGHUP, oldhandler); +#endif /* WIN32 */ #ifndef WIN32 + if (VFileName != NULL || RFileName != NULL) { /* * We don't need network access, so relinquish any set-UID * or set-GID privileges we have (if any). @@ -1072,363 +1094,380 @@ main(int argc, char **argv) */ 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); -#ifdef HAVE_PCAP_SET_TSTAMP_TYPE - if (Jflag) - show_tstamp_types_and_exit(device, pd); -#endif - /* - * Is this an interface that supports monitor mode? - */ - if (pcap_can_set_rfmon(pd) == 1) - supports_monitor_mode = 1; + if (VFileName != NULL && RFileName != NULL) + fprintf(stderr, "Both -V and -r specified. Using -V."); + + if (VFileName != NULL) { + if (VFileName[0] == '-' && VFileName[1] == '\0') + VFile = fopen("/dev/stdin", "r"); else - supports_monitor_mode = 0; - status = pcap_set_snaplen(pd, snaplen); - if (status != 0) - error("%s: Can't set snapshot length: %s", - device, pcap_statustostr(status)); - status = pcap_set_promisc(pd, !pflag); - if (status != 0) - error("%s: Can't set promiscuous mode: %s", - device, pcap_statustostr(status)); - if (Iflag) { - status = pcap_set_rfmon(pd, 1); - if (status != 0) - error("%s: Can't set monitor mode: %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: Can't set buffer size: %s", - device, pcap_statustostr(status)); - } -#ifdef HAVE_PCAP_SET_TSTAMP_TYPE - if (jflag != -1) { - status = pcap_set_tstamp_type(pd, jflag); - if (status < 0) - error("%s: Can't set time stamp type: %s", - device, pcap_statustostr(status)); + VFile = fopen(VFileName, "r"); + + if (VFile == NULL) + error("Unable to open file: %s\n", strerror(errno)); + + ret = fgets(VFileLine, NAME_MAX, VFile); + if (ret) { + if(VFileLine[strlen(VFileLine) - 1] == '\n') + VFileLine[strlen(VFileLine) - 1] = '\0'; + //fprintf(stderr, "VFileLine: %s\n", VFileLine); } + RFileName = VFileLine; + } + +#ifdef SIGINFO + /* + * We can't get statistics when reading from a file rather + * than capturing from a device. + */ + if (RFileName == NULL) + (void)setsignal(SIGINFO, requestinfo); #endif - 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); + + do { + if (RFileName != NULL) { + int dlt; + const char *dlt_name; + + 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 - error("%s: %s", device, - pcap_statustostr(status)); - } else if (status > 0) { + { + 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); + #ifdef HAVE_PCAP_SET_TSTAMP_TYPE + if (Jflag) + show_tstamp_types_and_exit(device, pd); + #endif /* - * pcap_activate() succeeded, but it's warning us - * of a problem it had. + * Is this an interface that supports monitor mode? */ - 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); + if (pcap_can_set_rfmon(pd) == 1) + supports_monitor_mode = 1; 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)); + supports_monitor_mode = 0; + status = pcap_set_snaplen(pd, snaplen); + if (status != 0) + error("%s: Can't set snapshot length: %s", + device, pcap_statustostr(status)); + status = pcap_set_promisc(pd, !pflag); + if (status != 0) + error("%s: Can't set promiscuous mode: %s", + device, pcap_statustostr(status)); + if (Iflag) { + status = pcap_set_rfmon(pd, 1); + if (status != 0) + error("%s: Can't set monitor mode: %s", + device, pcap_statustostr(status)); } -#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */ - if (Lflag) - show_dlts_and_exit(device, 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 + 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: Can't set buffer size: %s", + device, pcap_statustostr(status)); + } + #ifdef HAVE_PCAP_SET_TSTAMP_TYPE + if (jflag != -1) { + status = pcap_set_tstamp_type(pd, jflag); + if (status < 0) + error("%s: Can't set time stamp type: %s", + device, pcap_statustostr(status)); + } + #endif + 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 */ /* - * We don't actually support changing the - * data link type, so we only let them - * set it to what it already is. + * Let user own process after socket has been opened. */ - if (gndo->ndo_dlt != pcap_datalink(pd)) { - error("%s is not one of the DLTs supported by this device\n", - gndo->ndo_dltname); + #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(device, 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); } -#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 (first == 0) { + if (infile) + cmdbuf = read_infile(infile); + else + cmdbuf = copy_argv(&argv[optind]); } - if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { - localnet = 0; - netmask = 0; - warning("%s", ebuf); + + 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); } - } - 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)); - free(cmdbuf); - if (dflag) { - bpf_dump(&fcode, dflag); - pcap_close(pd); - exit(0); - } - init_addrtoname(localnet, netmask); - init_checksum(); + if (pcap_setfilter(pd, &fcode) < 0) + error("%s", pcap_geterr(pd)); -#ifndef WIN32 - (void)setsignal(SIGPIPE, cleanup); - (void)setsignal(SIGTERM, cleanup); - (void)setsignal(SIGINT, cleanup); -#endif /* WIN32 */ -#if defined(HAVE_FORK) || defined(HAVE_VFORK) - (void)setsignal(SIGCHLD, child_cleanup); -#endif - /* Cooperate with nohup(1) */ -#ifndef WIN32 - if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) - (void)setsignal(SIGHUP, oldhandler); -#endif /* WIN32 */ + if (first == 0) { + first = 1; + + init_addrtoname(localnet, netmask); + init_checksum(); #ifndef WIN32 - /* - * If a user name was specified with "-Z", attempt to switch to - * that user's UID. This would probably be used with sudo, - * to allow tcpdump to be run in a special restricted - * account (if you just want to allow users to open capture - * devices, and can't just give users that permission, - * you'd make tcpdump set-UID or set-GID). - * - * Tcpdump doesn't necessarily write only to one savefile; - * the general only way to allow a -Z instance to write to - * savefiles as the user under whose UID it's run, rather - * than as the user specified with -Z, would thus be to switch - * to the original user ID before opening a capture file and - * then switch back to the -Z user ID after opening the savefile. - * Switching to the -Z user ID only after opening the first - * savefile doesn't handle the general case. - */ - if (getuid() == 0 || geteuid() == 0) { - if (username || chroot_dir) - droproot(username, chroot_dir); - } + /* + * If a user name was specified with "-Z", attempt to switch to + * that user's UID. This would probably be used with sudo, + * to allow tcpdump to be run in a special restricted + * account (if you just want to allow users to open capture + * devices, and can't just give users that permission, + * you'd make tcpdump set-UID or set-GID). + * + * Tcpdump doesn't necessarily write only to one savefile; + * the general only way to allow a -Z instance to write to + * savefiles as the user under whose UID it's run, rather + * than as the user specified with -Z, would thus be to switch + * to the original user ID before opening a capture file and + * then switch back to the -Z user ID after opening the savefile. + * Switching to the -Z user ID only after opening the first + * savefile doesn't handle the general case. + */ + if (getuid() == 0 || geteuid() == 0) { + if (username || chroot_dir) + droproot(username, chroot_dir); + } #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; - } + 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; + } #ifdef HAVE_PCAP_DUMP_FLUSH - if (Uflag) - pcap_dump_flush(p); -#endif - } else { - type = pcap_datalink(pd); - printinfo.ndo_type = 1; - printinfo.ndo = gndo; - printinfo.p.ndo_printer = lookup_ndo_printer(type); - if (printinfo.p.ndo_printer == NULL) { - printinfo.p.printer = lookup_printer(type); - printinfo.ndo_type = 0; - if (printinfo.p.printer == NULL) { - gndo->ndo_dltname = pcap_datalink_val_to_name(type); - if (gndo->ndo_dltname != NULL) - error("packet printing is not supported for link type %s: use -w", - gndo->ndo_dltname); - else - error("packet printing is not supported for link type %d: use -w", type); - } - } - callback = print_packet; - pcap_userdata = (u_char *)&printinfo; - } - -#ifdef SIGINFO - /* - * We can't get statistics when reading from a file rather - * than capturing from a device. - */ - if (RFileName == NULL) - (void)setsignal(SIGINFO, requestinfo); + if (Uflag) + pcap_dump_flush(p); #endif - - if (vflag > 0 && WFileName) { - /* - * When capturing to a file, "-v" means tcpdump should, - * every 10 secodns, "v"erbosely report the number of - * packets captured. - */ + } else { + type = pcap_datalink(pd); + printinfo.ndo_type = 1; + printinfo.ndo = gndo; + printinfo.p.ndo_printer = lookup_ndo_printer(type); + if (printinfo.p.ndo_printer == NULL) { + printinfo.p.printer = lookup_printer(type); + printinfo.ndo_type = 0; + if (printinfo.p.printer == NULL) { + gndo->ndo_dltname = pcap_datalink_val_to_name(type); + if (gndo->ndo_dltname != NULL) + error("packet printing is not supported for link type %s: use -w", gndo->ndo_dltname); + else + error("packet printing is not supported for link type %d: use -w", type); + } + } + callback = print_packet; + pcap_userdata = (u_char *)&printinfo; + } + if (vflag > 0 && WFileName) { + /* + * When capturing to a file, "-v" means tcpdump should, + * every 10 secodns, "v"erbosely report the number of + * packets captured. + */ #ifdef USE_WIN32_MM_TIMER - /* call verbose_stats_dump() each 1000 +/-100msec */ - timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); - setvbuf(stderr, NULL, _IONBF, 0); + /* call verbose_stats_dump() each 1000 +/-100msec */ + timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); + setvbuf(stderr, NULL, _IONBF, 0); #elif defined(HAVE_ALARM) - (void)setsignal(SIGALRM, verbose_stats_dump); - alarm(1); + (void)setsignal(SIGALRM, verbose_stats_dump); + alarm(1); #endif - } - + } #ifndef WIN32 - if (RFileName == NULL) { - int dlt; - const char *dlt_name; - - if (!vflag && !WFileName) { - (void)fprintf(stderr, - "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", - program_name); - } else - (void)fprintf(stderr, "%s: ", program_name); - dlt = pcap_datalink(pd); - dlt_name = pcap_datalink_val_to_name(dlt); - if (dlt_name == NULL) { - (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", - device, dlt, snaplen); - } else { - (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", - device, dlt_name, - pcap_datalink_val_to_description(dlt), snaplen); - } - (void)fflush(stderr); - } + if (RFileName == NULL) { + int dlt; + const char *dlt_name; + + if (!vflag && !WFileName) + (void)fprintf(stderr, "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", program_name); + else + (void)fprintf(stderr, "%s: ", program_name); + dlt = pcap_datalink(pd); + dlt_name = pcap_datalink_val_to_name(dlt); + if (dlt_name == NULL) + (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", device, dlt, snaplen); + else + (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", device, dlt_name, pcap_datalink_val_to_description(dlt), snaplen); + (void)fflush(stderr); + } #endif /* WIN32 */ - status = pcap_loop(pd, cnt, callback, pcap_userdata); - if (WFileName == NULL) { - /* - * We're printing packets. Flush the printed output, - * so it doesn't get intermingled with error output. - */ - if (status == -2) { + } // first == 1 + + status = pcap_loop(pd, cnt, callback, pcap_userdata); + if (WFileName == NULL) { /* - * We got interrupted, so perhaps we didn't - * manage to finish a line we were printing. - * Print an extra newline, just in case. + * We're printing packets. Flush the printed output, + * so it doesn't get intermingled with error output. */ - putchar('\n'); + if (status == -2) { + /* + * We got interrupted, so perhaps we didn't + * manage to finish a line we were printing. + * Print an extra newline, just in case. + */ + putchar('\n'); + } + (void)fflush(stdout); } - (void)fflush(stdout); - } - if (status == -1) { - /* - * Error. Report it. - */ - (void)fprintf(stderr, "%s: pcap_loop: %s\n", - program_name, pcap_geterr(pd)); - } - if (RFileName == NULL) { - /* - * We're doing a live capture. Report the capture - * statistics. - */ - info(1); - } - pcap_close(pd); + if (status == -1) { + /* + * Error. Report it. + */ + (void)fprintf(stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd)); + } + if (RFileName == NULL) { + /* + * We're doing a live capture. Report the capture + * statistics. + */ + info(1); + } + pcap_close(pd); + if (VFileName != NULL) { + ret = fgets(VFileLine, NAME_MAX, VFile); + if (ret) { + if(VFileLine[strlen(VFileLine) - 1] == '\n') + VFileLine[strlen(VFileLine) - 1] = '\0'; + //fprintf(stderr, "VFileLine: %s\n", VFileLine); + } + RFileName = VFileLine; + } + } while (ret != NULL); + + free(cmdbuf); exit(status == -1 ? 1 : 0); }