tshark programmatic capture

asked 2018-12-21 06:22:37 +0000

Wallboy gravatar image

updated 2018-12-21 10:45:15 +0000

I'm trying to use tshark programmatically in Qt. I need to start tshark with -w capture.pcapng to capture to a file and a use a capture filter for a particular host. I then make some HTTP Qt network requests to the host and let tshark capture the communication.

I first tried launching tshark using QProcess() in Qt and waiting on the started() signal before making a network request in Qt. When doing this I was getting no packets captured at all. I figured it was because the started() signal likely only happens when the tshark process has successfully launched, but not necessarily when it's actually ready to capture packets. I noticed in the tshark docs that it will write a "Capturing On Interface..." message to stderr at the beginning of a capture, so instead I listened for a readyReadStandardError signal from the QProcess before making my network requests. This ALMOST works. It's just missing the initial SYN packet and instead only is capturing forward from the SYN-ACK coming back from the host.

I can of course delay the network requests by an arbitrary second or so to make sure tshark really is ready and that of course works and finally captures everything, but I'm wondering if anyone has any other ideas on how to make sure tshark is ready to capture requests?

Another question I have is regarding stopping the capture. I only need to capture until I get the full HTTP response from the host. My first try was that after my network requests in Qt finished, was to immediately tell tshark to terminate, but when doing this I lose a majority of the capture since I'm guessing tshark was still processing the packets when a terminate() was issued on it. In fact I had to use kill() in Windows to make it actually stop and get a non zero exit code this way.

So instead I again just went the timer route and added -a duration:5 to tshark and hope the webserver request completes in that allotted time.

EDIT: Using dumpcap instead I'm able to capture the initial SYN packet, but still looking for a clean way to kill dumpcap. I'm tried killing the process with various SIG* signals and ones specific to Windows like CTRL_C_EVENT, etc, but some of them do nothing, and other end up killing the process non gracefully with a non zero exit code and when opened up in Wireshark usually give a message of "packet capture was interrupted" message, and with a lot of data missing.

EDIT2: CTRL_C_EVENT signal is now working correctly. Not sure why it wasn't working initially. Also starting to get the missing initial SYN packet sometimes. Looking at the source I see the stderr capturing on message happens just before the actual capture_loop function is called so I can't rely on that message. So I'm back to now just waiting an arbitrary second.

I'd appreciate any ... (more)

edit retag flag offensive close merge delete

Comments

Would it be possible to, in your Qt application, just do your own capturing, using libpcap on UN*X and WinPcap/Npcap on Windows, in one thread, and make the network requests in another thread?

Guy Harris gravatar imageGuy Harris ( 2018-12-21 06:42:12 +0000 )edit

The problem doesn't have to do with threads. I'd still have to figure out when tshark is actually ready for capturing. I've switched to dumpcap now in my EDIT above as this is at least capturing my initial SYN packet, but I still can't figure out how to terminate dump gracefully on windows immediately following the finish of my network request. I still have to use the -a option with an arbitrary duration.

Wallboy gravatar imageWallboy ( 2018-12-21 08:13:10 +0000 )edit

I'd still have to figure out when tshark is actually ready for capturing.

Not if you do the capturing yourself rather than using tshark!

If you really want to use a piece of Wireshark to do the capturing, you might want to steal the code Wireshark and TShark use to run dumpcap, with a command pipe. See the routines in the capchild directory.

Guy Harris gravatar imageGuy Harris ( 2018-12-21 10:52:30 +0000 )edit

There may be better ways to solve your problem, such as what Guy suggests, but in case it helps, you might want to take a look at the dumpcap.batfile I wrote and made available at https://wiki.wireshark.org/Tools#Scripts. It supports things like capturing packets until an event occurs and then automatically stopping the capture. The event itself must be specified as a capture filter though, so this can often be hard or even impossible to do, but if the capture condition is just waiting for a TCP FIN packet between 2 specific hosts, that should be feasible. In any case, I mention the batch file in case it's of any use to you at all.

cmaynard gravatar imagecmaynard ( 2019-01-03 19:57:43 +0000 )edit