Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for using a fifo on windows with a Named Pipe. #3

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode/launch.json
132 changes: 120 additions & 12 deletions serial-pcap
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,107 @@ import time
import errno
import serial
import struct
import select
import selectors
import binascii
import datetime
import argparse

############################
# START WINDOWS FIFO PATCH #
############################

if os.name == 'nt':
from pywintypes import HANDLEType
import win32file
import win32pipe
import win32security
import ntsecuritycon

######
# Windows Patch Class Definitions
######

class WindowsPipe:
# Wrapper for the windows pipe using the pywin32 calls
def __init__(self, pipe):
self.pipe:HANDLEType = pipe

def fileno(self):
return self.pipe

def write(self, data):
win32file.WriteFile(self.pipe, data)

def flush(self):
win32file.FlushFileBuffers(self.pipe)

def close(self):
win32file.CloseHandle(self.pipe)

class WindowsSerial(serial.Serial):
# Give our serial a "fd" of it's "COM" port number
def fileno(self):
return int(self.name[3:])

class WindowsSelector(selectors.SelectSelector):
def _select(self, r, w, _, timeout = None):
# Since we are only reading from serial writing to a pipe (for fifos) we
# can harcode in what types are going to be in the read and write arrays
#
# Implementation logic taken from the select(2) manpage
retr = []
retw = []

for rfd in r:
rfo:WindowsSerial = self.get_key(rfd).fileobj
if rfo.in_waiting == 0:
retr.append(rfd)

for wfd in w:
wfo:PcapFormatter = self.get_key(wfd).fileobj
pipe = wfo.out.pipe
try:
_, available_bytes, _ = win32pipe.PeekNamedPipe(pipe, 0)

if available_bytes == 0:
retw.append(wfd)
except:
continue

return retr, retw, []


######
# Windows Patch Function Definitions
######

def open_fifo_windows(options, name):
# Create named Pipe
pipe = win32pipe.CreateNamedPipe(
fr'\\.\pipe\{name}',
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_WAIT,
1,
65536,
65536,
0,
None
)

if not options.quiet:
print("Waiting for fifo to be openend...")
# This blocks until the other side of the fifo is opened
win32pipe.ConnectNamedPipe(pipe, None)

return WindowsPipe(pipe)

##########################
# END WINDOWS FIFO PATCH #
##########################

class Formatter:
def __init__(self, out):
self.out = out
self.out = out

def fileno(self):
return self.out.fileno()
Expand Down Expand Up @@ -82,7 +175,7 @@ class HumanFormatter(Formatter):
self.out.write("\n")
self.out.flush()

def open_fifo(options, name):
def open_fifo_linux(options, name):
try:
os.mkfifo(name);
except FileExistsError:
Expand All @@ -97,7 +190,13 @@ def open_fifo(options, name):

def setup_output(options):
if options.fifo:
if os.name == "nt":
open_fifo = open_fifo_windows
else:
open_fifo = open_fifo_linux

return PcapFormatter(open_fifo(options, options.fifo))

elif options.write_file:
return PcapFormatter(open(options.write_file, 'wb'))
else:
Expand Down Expand Up @@ -136,8 +235,12 @@ def do_sniff_once(options):
# This might block until the other side of the fifo is opened
out = setup_output(options)
out.write_header()

ser = serial.Serial(options.port, options.baudrate)

if os.name == 'nt':
ser = WindowsSerial(options.port, options.baudrate)
else:
ser = serial.Serial(options.port, options.baudrate)

print("Opened {} at {}".format(options.port, options.baudrate))

if options.send_init_delay:
Expand All @@ -162,18 +265,23 @@ def do_sniff_once(options):
if not options.quiet:
print("Waiting for packets...")

count = 0
poll = select.poll()
if os.name == 'nt':
sel = WindowsSelector()
else:
sel = selectors.DefaultSelector()

# Wait to read data from serial, or until the fifo is closed
poll.register(ser, select.POLLIN)
poll.register(out, select.POLLERR)
sel.register(ser, selectors.EVENT_READ)
sel.register(out, selectors.EVENT_WRITE)

count = 0

while True:
# Wait for something to do
events = poll.poll()
events = sel.select()

fds = [fd for (fd, evt) in events]
if out.fileno() in fds:
fds = [fd.fileobj.fileno() for (fd, evt) in events]
if out.fileno() not in fds:
# Error on output, e.g. fifo closed on the other end
break
elif ser.fileno() in fds:
Expand Down