aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/README.extcap189
-rwxr-xr-xdoc/extcap_example.py175
2 files changed, 351 insertions, 13 deletions
diff --git a/doc/README.extcap b/doc/README.extcap
index 94ca73584b..50db8f67a3 100644
--- a/doc/README.extcap
+++ b/doc/README.extcap
@@ -196,6 +196,195 @@ such a check is the same as for Qt RegExp classes. This feature is only active i
Qt version of Wireshark.
+TOOLBAR CONTROLS
+================
+An extcap utility can provide configuration for controls to use in an interface toolbar.
+This controls are bidirectional and can be used to control the extcap utility while
+capturing.
+
+This is useful in scenarios where configuration can be done based on findings in the
+capture process, setting temporary values or give other inputs without restarting the
+current capture.
+
+Example:
+
+$ extcapbin --extcap-interfaces
+extcap {version=1.0}{display=Example extcap interface}
+interface {value=example1}{display=Example interface 1 for extcap}
+interface {value=example2}{display=Example interface 2 for extcap}
+control {number=0}{type=string}{display=Message}{tooltip=Package message content. Must start with a capital letter.}{validation=[A-Z]+}{required=true}
+control {number=1}{type=selector}{display=Time delay}{tooltip=Time delay between packages}
+control {number=2}{type=boolean}{display=Verify}{default=true}{tooltip=Verify package content}
+control {number=3}{type=button}{display=Turn on}{tooltip=Turn on or off}
+control {number=4}{type=button}{role=logger}{display=Log}{tooltip=Show capture log}
+value {control=1}{value=1}{display=1 sec}
+value {control=1}{value=2}{display=2 sec}{default=true}
+
+All controls will be presented as GUI elements in a toolbar specific to the extcap
+utility. The extcap must not rely on using those controls (they are optional) because
+of other capturing tools not using GUI (e.g. tshark, tfshark).
+
+
+CONTROLS
+========
+The controls are similar to the ARGUMENTS, but without the CALL element. All controls
+may be given a default value at startup and most can be changed during capture, both
+by the extcap and the user (depending on the type of control).
+
+All controls must provide a NUMBER, by which they are identified. No NUMBER may be
+provided twice. Also all options must present the elements TYPE and DISPLAY, where
+TYPE provides the type of control to add to the toolbar and DISPLAY the name in the GUI.
+
+Additionally TOOLTIP and PLACEHOLDER may be provided, which will give the user an
+explanation within the GUI.
+
+All controls, except from the logger, help and reset buttons, may be disabled
+(and enabled) in GUI by the extcap during capture. This can be because of set-once
+operations, or operations which takes some time to complete.
+
+All control values which are changed by the user (not equal to the default value) will
+be sent to the extcap utility when starting a capture. The extcap utility may choose
+to discard initial values and set new values, depending on implementation.
+
+This TYPEs are defined as controls:
+
+ * BOOLEAN - This provides a checkbox with the possibility to set a true/false value.
+
+ The extcap utility can set a default value at startup, and can change (set) and receive
+ value changes while capturing. When starting a capture the GUI will send the value if
+ different from the default value.
+
+ The payload is one byte with binary value 0 or 1.
+
+ Valid Commands: Set value, Enable, Disable.
+
+ * BUTTON - This provides a button with different ROLEs:
+
+ ** CONTROL - This button will send a signal.
+ This is the default role if nothing is configured.
+
+ The extcap utility can set the button text at startup, and can change (set) the
+ button text and receive button press signals while capturing. The button is
+ disabled and the button text is restored to the default text when not capturing.
+
+ The payload is either the button text or empty (signal).
+
+ Valid Commands: Set value, Enable, Disable.
+
+ ** LOGGER - This provides a logger mechanism where the extcap utility can send log
+ entries to be presented in a log window. This communication is unidirectional.
+
+ The payload is the log entry, and should be ended with a newline.
+ Maximum length is 65535 bytes.
+
+ Valid Commands: Set log entry, Add log entry.
+
+ The Set command will clear the log before adding the entry.
+
+ ** HELP - This button opens the help page, if configured.
+ This type has no controls and will not be used in communication.
+
+ Valid Commands: NONE.
+
+ ** RESET - This button will restore all control values to default.
+ This type has no controls and will not be used in communication.
+
+ Valid Commands: NONE.
+
+ * SELECTOR - This provides a combo box with fixed values which can be selected.
+
+ The extcap utility can set default values at startup, and add and remove values and
+ receive change in value selection while capturing. When starting a capture the GUI
+ will send the value if different from the default value.
+
+ The payload is a string with the value, and optionally a string with a display
+ value if this is different from the value. This two string values are separated
+ by a null character.
+
+ Valid Commands: Set selected value, Add value, Remove value, Enable, Disable.
+
+ If value is empty the Remove command will remove all entries.
+
+ * STRING - This provides a text edit line with the possibility to set a string or any
+ value which can be represented in a string (integer, float, date, etc.).
+
+ The extcap utility can set a default string value at startup, and can change (set) and
+ receive value changes while capturing. When starting a capture the GUI will send the
+ value if different from the default value.
+
+ The payload is a string with the value. Maximum length is 32767 bytes.
+
+ Valid Commands: Set value, Enable, Disable.
+
+ The element VALIDATION allows to provide a regular expression string, which is used
+ to check the user input for validity beyond normal data type or range checks.
+ Back-slashes must be escaped (as in \\b for \b).
+
+
+MESSAGES
+========
+In addition to the controls it's possible to send a single message from the extcap
+utility to the user. This message can be put in the status bar or displayed in a
+information, warning or error dialog which must be accepted by the user. This message
+does not use the NUMBER argument so this can have any value.
+
+
+CONTROL PROTOCOL
+================
+The protocol used to communicate over the control pipes has a fixed size header of
+6 bytes and a payload with 0 - 65535 bytes.
+
+Control packet:
+
+ +----+----+----+----+----+----+----+----+
+ | Sync Pipe Indication (1 byte) |
+ +----+----+----+----+----+----+----+----+
+ | Message Length |
+ | (3 bytes network order) |
+ +----+----+----+----+----+----+----+----+
+ | Control Number (1 byte) |
+ +----+----+----+----+----+----+----+----+
+ | Command (1 byte) |
+ +----+----+----+----+----+----+----+----+
+ | Payload |
+ | (0 - 65535 bytes) |
+ +----+----+----+----+----+----+----+----+
+
+ Sync Pipe Indication:
+ The common sync pipe indication. This protocol uses the value 'T'.
+
+ Message Length:
+ Payload length + 2 bytes for argument number and command.
+
+ Control Number:
+ Unique number to identify the control. This number also gives the order of
+ the controls in the interface toolbar.
+
+ Command: Control type:
+ 0 = Initialized none
+ 1 = Set boolean / button / logger / selector / string
+ 2 = Add logger / selector
+ 3 = Remove selector
+ 4 = Enable boolean / button / selector / string
+ 5 = Disable boolean / button / selector / string
+ 6 = Statusbar message none
+ 7 = Information message none
+ 8 = Warning message none
+ 9 = Error message none
+
+ Payload Length:
+ The length of the following payload. Maximum length is 65535 bytes.
+
+The Initialized command will be sent from the GUI to the extcap utility when all
+initial control values are sent after starting a capture. This is an indication
+that the GUI is ready to receive control values.
+
+The GUI will only send Initialized and Set commands. The extcap utility shall not
+send the Initialized command.
+
+Messages with unknown control number or command will be silently ignored.
+
+
DEVELOPMENT
===========
To have extcap support, extcap must be enabled. Moreover the specific extcap must
diff --git a/doc/extcap_example.py b/doc/extcap_example.py
index 6ab5699afb..e7ea7b2d6b 100755
--- a/doc/extcap_example.py
+++ b/doc/extcap_example.py
@@ -51,13 +51,38 @@ import struct
import binascii
from threading import Thread
-ERROR_USAGE = 0
-ERROR_ARG = 1
-ERROR_INTERFACE = 2
-ERROR_FIFO = 3
-ERROR_DELAY = 4
-
-globalinterface = 0
+ERROR_USAGE = 0
+ERROR_ARG = 1
+ERROR_INTERFACE = 2
+ERROR_FIFO = 3
+ERROR_DELAY = 4
+
+CTRL_CMD_INITIALIZED = 0
+CTRL_CMD_SET = 1
+CTRL_CMD_ADD = 2
+CTRL_CMD_REMOVE = 3
+CTRL_CMD_ENABLE = 4
+CTRL_CMD_DISABLE = 5
+CTRL_CMD_STATUSBAR = 6
+CTRL_CMD_INFORMATION = 7
+CTRL_CMD_WARNING = 8
+CTRL_CMD_ERROR = 9
+
+CTRL_ARG_MESSAGE = 0
+CTRL_ARG_DELAY = 1
+CTRL_ARG_VERIFY = 2
+CTRL_ARG_BUTTON = 3
+CTRL_ARG_HELP = 4
+CTRL_ARG_RESET = 5
+CTRL_ARG_LOGGER = 6
+CTRL_ARG_NONE = 255
+
+initialized = False
+message = ''
+delay = 0.0
+verify = False
+button = False
+button_disabled = False
"""
This code has been taken from http://stackoverflow.com/questions/5943249/python-argparse-and-controlling-overriding-the-exit-status-code - originally developed by Rob Cowie http://stackoverflow.com/users/46690/rob-cowie
@@ -128,12 +153,29 @@ def extcap_config(interface):
def extcap_interfaces():
- print ("extcap {version=1.0}{help=http://www.wireshark.org}")
- print ("interface {value=example1}{display=Example interface usage for extcap}")
+ print ("extcap {version=1.0}{help=http://www.wireshark.org}{display=Example extcap interface}")
+ print ("interface {value=example1}{display=Example interface 1 for extcap}")
+ print ("interface {value=example2}{display=Example interface 2 for extcap}")
+ print ("control {number=%d}{type=string}{display=Message}{tooltip=Package message content. Must start with a capital letter.}{placeholder=Enter package message content here ...}{validation=^[A-Z]+}" % CTRL_ARG_MESSAGE)
+ print ("control {number=%d}{type=selector}{display=Time delay}{tooltip=Time delay between packages}" % CTRL_ARG_DELAY)
+ print ("control {number=%d}{type=boolean}{display=Verify}{default=true}{tooltip=Verify package content}" % CTRL_ARG_VERIFY)
+ print ("control {number=%d}{type=button}{display=Turn on}{tooltip=Turn on or off}" % CTRL_ARG_BUTTON)
+ print ("control {number=%d}{type=button}{role=help}{display=Help}{tooltip=Show help}" % CTRL_ARG_HELP)
+ print ("control {number=%d}{type=button}{role=reset}{display=Reset}{tooltip=Restore default values}" % CTRL_ARG_RESET)
+ print ("control {number=%d}{type=button}{role=logger}{display=Log}{tooltip=Show capture log}" % CTRL_ARG_LOGGER)
+ print ("value {control=%d}{value=1}{display=1}" % CTRL_ARG_DELAY)
+ print ("value {control=%d}{value=2}{display=2}" % CTRL_ARG_DELAY)
+ print ("value {control=%d}{value=3}{display=3}" % CTRL_ARG_DELAY)
+ print ("value {control=%d}{value=4}{display=4}" % CTRL_ARG_DELAY)
+ print ("value {control=%d}{value=5}{display=5}{default=true}" % CTRL_ARG_DELAY)
+ print ("value {control=%d}{value=60}{display=60}" % CTRL_ARG_DELAY)
+
def extcap_dlts(interface):
if ( interface == '1' ):
print ("dlt {number=147}{name=USER0}{display=Demo Implementation for Extcap}")
+ elif ( interface == '2' ):
+ print ("dlt {number=148}{name=USER1}{display=Demo Implementation for Extcap}")
"""
@@ -216,20 +258,125 @@ def pcap_fake_package ( message, fake_ip ):
pcap += message
return pcap
-def extcap_capture(interface, fifo, delay, verify, message, remote, fake_ip):
- tdelay = delay if delay != 0 else 5
+def control_read(fn):
+ try:
+ header = fn.read(6)
+ sp, _, length, arg, typ = struct.unpack('>sBHBB', header)
+ if length > 2:
+ payload = fn.read(length - 2)
+ else:
+ payload = ''
+ return arg, typ, payload
+ except:
+ return None, None, None
+
+def control_read_thread(control_in, fn_out):
+ global initialized, message, delay, verify, button, button_disabled
+ with open(control_in, 'rb', 0 ) as fn:
+ arg = 0
+ while arg != None:
+ arg, typ, payload = control_read(fn)
+ log = ''
+ if typ == CTRL_CMD_INITIALIZED:
+ initialized = True
+ elif arg == CTRL_ARG_MESSAGE:
+ message = payload
+ log = "Message = " + payload
+ elif arg == CTRL_ARG_DELAY:
+ delay = float(payload)
+ log = "Time delay = " + payload
+ elif arg == CTRL_ARG_VERIFY:
+ # Only read this after initialized
+ if initialized:
+ verify = (payload[0] != '\0')
+ log = "Verify = " + str(verify)
+ control_write(fn_out, CTRL_ARG_NONE, CTRL_CMD_STATUSBAR, "Verify changed")
+ elif arg == CTRL_ARG_BUTTON:
+ control_write(fn_out, CTRL_ARG_BUTTON, CTRL_CMD_DISABLE, "")
+ button_disabled = True
+ if button == True:
+ control_write(fn_out, CTRL_ARG_BUTTON, CTRL_CMD_SET, "Turn on")
+ button = False
+ log = "Button turned off"
+ else:
+ control_write(fn_out, CTRL_ARG_BUTTON, CTRL_CMD_SET, "Turn off")
+ button = True
+ log = "Button turned on"
+
+ if len(log) > 0:
+ control_write(fn_out, CTRL_ARG_LOGGER, CTRL_CMD_ADD, log + "\n")
+
+def control_write(fn, arg, typ, payload):
+ packet = bytearray()
+ packet += struct.pack('>sBHBB', 'T', 0, len(payload) + 2, arg, typ)
+ packet += payload
+ fn.write(packet)
+
+def control_write_defaults(fn_out):
+ global initialized, message, delay, verify
+
+ while not initialized:
+ time.sleep(.1) # Wait for initial control values
+
+ # Write startup configuration to Toolbar controls
+ control_write(fn_out, CTRL_ARG_MESSAGE, CTRL_CMD_SET, message)
+ control_write(fn_out, CTRL_ARG_DELAY, CTRL_CMD_SET, str(delay))
+ control_write(fn_out, CTRL_ARG_VERIFY, CTRL_CMD_SET, struct.pack('B', verify))
+
+ for i in range(1,16):
+ item = bytearray()
+ item += str(i) + struct.pack('B', 0) + str(i) + " sec"
+ control_write(fn_out, CTRL_ARG_DELAY, CTRL_CMD_ADD, item)
+
+ control_write(fn_out, CTRL_ARG_DELAY, CTRL_CMD_REMOVE, str(60))
+
+def extcap_capture(interface, fifo, control_in, control_out, in_delay, in_verify, in_message, remote, fake_ip):
+ global message, delay, verify, button_disabled
+ delay = in_delay if in_delay != 0 else 5
+ message = in_message
+ verify = in_verify
+ counter = 1
if not os.path.exists(fifo):
print ( "Fifo does not exist, exiting!", file=sys.stderr )
sys.exit(1)
+ fn_out = None
+ if control_out != None:
+ fn_out = open(control_out, 'wb', 0)
+ control_write(fn_out, CTRL_ARG_LOGGER, CTRL_CMD_SET, "Log started at " + time.strftime("%c") + "\n")
+
+
+ if control_in != None:
+ # Start reading thread
+ thread = Thread(target = control_read_thread, args = (control_in, fn_out))
+ thread.start()
+
+
+ if fn_out != None:
+ control_write_defaults(fn_out)
+
with open(fifo, 'wb', 0 ) as fh:
fh.write (pcap_fake_header())
while True:
+ if fn_out != None:
+ log = "Received packet #" + str(counter) + "\n"
+ control_write(fn_out, CTRL_ARG_LOGGER, CTRL_CMD_ADD, log)
+ counter = counter + 1
+
+ if button_disabled == True:
+ control_write(fn_out, CTRL_ARG_BUTTON, CTRL_CMD_ENABLE, "")
+ control_write(fn_out, CTRL_ARG_NONE, CTRL_CMD_INFORMATION, "Turn action finished.")
+ button_disabled = False
+
out = ("%s|%04X%s|%s" % ( remote.strip(), len(message), message, verify )).encode("utf8")
fh.write (pcap_fake_package(out, fake_ip))
- time.sleep(tdelay)
+ time.sleep(delay)
+
+ thread.join()
+ if fn_out != None:
+ fn_out.close()
def extcap_close_fifo(fifo):
if not os.path.exists(fifo):
@@ -268,6 +415,8 @@ if __name__ == '__main__':
parser.add_argument("--extcap-config", help="Provide a list of configurations for the given interface", action="store_true")
parser.add_argument("--extcap-capture-filter", help="Used together with capture to provide a capture filter")
parser.add_argument("--fifo", help="Use together with capture to provide the fifo to dump data to")
+ parser.add_argument("--extcap-control-in", help="Use together with capture to provide the fifo to dump data to")
+ parser.add_argument("--extcap-control-out", help="Use together with capture to provide the fifo to dump data to")
# Interface Arguments
parser.add_argument("--verify", help="Demonstrates a verification bool flag", action="store_true" )
@@ -334,7 +483,7 @@ if __name__ == '__main__':
sys.exit(ERROR_DELAY)
try:
- extcap_capture(interface, args.fifo, args.delay, args.verify, message, args.remote, fake_ip)
+ extcap_capture(interface, args.fifo, args.extcap_control_in, args.extcap_control_out, args.delay, args.verify, message, args.remote, fake_ip)
except KeyboardInterrupt:
pass
else: