tshark.pod: fix typo
[metze/wireshark/wip.git] / doc / extcap_example.py
1 #!/usr/bin/env python
2
3 # Copyright 2014 Roland Knall <rknall [AT] gmail.com>
4 #
5 # Wireshark - Network traffic analyzer
6 # By Gerald Combs <gerald@wireshark.org>
7 # Copyright 1998 Gerald Combs
8 #
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU General Public License
11 # as published by the Free Software Foundation; either version 2
12 # of the License, or (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 """
24 This is a generic example, which produces pcap packages every n seconds, and
25 is configurable via extcap options.
26
27 @note
28 {
29 To use this script on Windows, please generate an extcap_example.bat inside
30 the extcap folder, with the following content:
31
32 -------
33 @echo off
34 <Path to python interpreter> <Path to script file> $*
35 -------
36
37 Windows is not able to execute Python scripts directly, which also goes for all
38 other script-based formates beside VBScript
39 }
40
41 """
42
43 import os
44 import sys
45 import signal
46 import re
47 import argparse
48 import time
49 import struct
50 import binascii
51 from threading import Thread
52
53 ERROR_USAGE             = 0
54 ERROR_ARG               = 1
55 ERROR_INTERFACE = 2
56 ERROR_FIFO              = 3
57
58 doExit = False
59 globalinterface = 0
60
61 def signalHandler(signal, frame):
62         global doExit
63         doExit = True
64
65 #### EXTCAP FUNCTIONALITY
66
67 """@brief Extcap configuration
68 This method prints the extcap configuration, which will be picked up by the
69 interface in Wireshark to present a interface specific configuration for
70 this extcap plugin
71 """
72 def extcap_config(interface):
73         args = []
74         values = []
75
76         args.append ( (0, '--delay', 'Time delay', 'Time delay between packages', 'integer', '{range=1,15}') )
77         args.append ( (1, '--message', 'Message', 'Package message content', 'string', '') )
78         args.append ( (2, '--verify', 'Verify', 'Verify package content', 'boolflag', '') )
79         args.append ( (3, '--remote', 'Remote Channel', 'Remote Channel Selector', 'selector', ''))
80
81         values.append ( (3, "if1", "Remote1", "true" ) )
82         values.append ( (3, "if2", "Remote2", "false" ) )
83
84         for arg in args:
85                 print ("arg {number=%d}{call=%s}{display=%s}{tooltip=%s}{type=%s}%s" % arg)
86
87         for value in values:
88                 print ("value {arg=%d}{value=%s}{display=%s}{default=%s}" % value)
89
90
91 def extcap_interfaces():
92         print ("interface {value=example1}{display=Example interface usage for extcap}")
93
94 def extcap_dlts(interface):
95         if ( interface == '1' ):
96                 print ("dlt {number=147}{name=USER0}{display=Demo Implementation for Extcap}")
97
98 """
99
100 ### FAKE DATA GENERATOR
101
102 Extcap capture routine
103  This routine simulates a capture by any kind of user defined device. The parameters
104  are user specified and must be handled by the extcap.
105
106  The data captured inside this routine is fake, so change this routine to present
107  your own input data, or call your own capture program via Popen for example. See
108
109  for more details.
110
111 """
112 def unsigned(n):
113         return int(n) & 0xFFFFFFFF
114
115 def append_bytes(ba, blist):
116         for c in range(0, len(blist)):
117                 ba.append(blist[c])
118         return ba
119
120 def pcap_fake_header():
121
122         header = bytearray()
123         header = append_bytes(header, struct.pack('<L', int ('a1b2c3d4', 16) ))
124         header = append_bytes(header, struct.pack('<H', unsigned(2)) ) # Pcap Major Version
125         header = append_bytes(header, struct.pack('<H', unsigned(4)) ) # Pcap Minor Version
126         header = append_bytes(header, struct.pack('<I', int(0))) # Timezone
127         header = append_bytes(header, struct.pack('<I', int(0))) # Accurancy of timestamps
128         header = append_bytes(header, struct.pack('<L', int ('0000ffff', 16) )) # Max Length of capture frame
129         header = append_bytes(header, struct.pack('<L', unsigned(1))) # Ethernet
130         return header
131
132 # Calculates and returns the IP checksum based on the given IP Header
133 def ip_checksum(iph):
134         #split into bytes
135         words = splitN(''.join(iph.split()),4)
136         csum = 0;
137         for word in words:
138                 csum += int(word, base=16)
139         csum += (csum >> 16)
140         csum = csum & 0xFFFF ^ 0xFFFF
141         return csum
142
143 def pcap_fake_package ( message ):
144
145         pcap = bytearray()
146         #length = 14 bytes [ eth ] + 20 bytes [ ip ] + messagelength
147
148         caplength = len(message) + 14 + 20
149         timestamp = int(time.time())
150
151         pcap = append_bytes(pcap, struct.pack('<L', unsigned(timestamp) ) ) # timestamp seconds
152         pcap = append_bytes(pcap, struct.pack('<L', 0x00 ) ) # timestamp nanoseconds
153         pcap = append_bytes(pcap, struct.pack('<L', unsigned(caplength) ) ) # length captured
154         pcap = append_bytes(pcap, struct.pack('<L', unsigned(caplength) ) ) # length in frame
155
156 # ETH
157         pcap = append_bytes(pcap, struct.pack('h', 0 )) # source mac
158         pcap = append_bytes(pcap, struct.pack('h', 0 )) # source mac
159         pcap = append_bytes(pcap, struct.pack('h', 0 )) # source mac
160         pcap = append_bytes(pcap, struct.pack('h', 0 )) # dest mac
161         pcap = append_bytes(pcap, struct.pack('h', 0 )) # dest mac
162         pcap = append_bytes(pcap, struct.pack('h', 0 )) # dest mac
163         pcap = append_bytes(pcap, struct.pack('<h', unsigned(8) )) # protocol (ip)
164
165 # IP
166         pcap = append_bytes(pcap, struct.pack('b', int ( '45', 16) )) # IP version
167         pcap = append_bytes(pcap, struct.pack('b', int ( '0', 16) )) #
168         pcap = append_bytes(pcap, struct.pack('>H', unsigned(len(message)+20) )) # length of data + payload
169         pcap = append_bytes(pcap, struct.pack('<H', int ( '0', 16) )) # Identification
170         pcap = append_bytes(pcap, struct.pack('b', int ( '40', 16) )) # Don't fragment
171         pcap = append_bytes(pcap, struct.pack('b', int ( '0', 16) )) # Fragment Offset
172         pcap = append_bytes(pcap, struct.pack('b', int ( '40', 16) ))
173         pcap = append_bytes(pcap, struct.pack('B', 0xFE )) # Protocol (2 = unspecified)
174         pcap = append_bytes(pcap, struct.pack('<H', int ( '0000', 16) )) # Checksum
175         pcap = append_bytes(pcap, struct.pack('>L', int ( '7F000001', 16) )) # Source IP
176         pcap = append_bytes(pcap, struct.pack('>L', int ( '7F000001', 16) )) # Dest IP
177
178         pcap = append_bytes(pcap, message)
179         return pcap
180
181 def extcap_capture(interface, fifo, delay, verify, message, remote):
182         global doExit
183
184         signal.signal(signal.SIGINT, signalHandler)
185         signal.signal(signal.SIGTERM , signalHandler)
186
187         tdelay = delay if delay != 0 else 5
188
189         try:
190                 os.stat(fifo)
191         except OSError:
192                 doExit = True
193                 print ( "Fifo does not exist, exiting!" )
194
195         fh = open(fifo, 'w+b', 0 )
196         fh.write (pcap_fake_header())
197
198         while doExit == False:
199                 out = str( "%s|%04X%s|%s" % ( remote.strip(), len(message), message, verify ) )
200                 try:
201                         fh.write (pcap_fake_package(out))
202                         time.sleep(tdelay)
203                 except IOError:
204                         doExit = True
205
206         fh.close()
207
208 ####
209
210 def usage():
211         print ( "Usage: %s <--extcap-interfaces | --extcap-dlts | --extcap-interface | --extcap-config | --capture | --fifo>" % sys.argv[0] )
212
213 if __name__ == '__main__':
214         interface = ""
215
216         # Capture options
217         delay = 0
218         message = ""
219
220         parser = argparse.ArgumentParser(
221                 prog="Extcap Example",
222                 description="Extcap example program for python"
223                 )
224
225         # Extcap Arguments
226         parser.add_argument("--capture", help="Start the capture routine", action="store_true" )
227         parser.add_argument("--extcap-interfaces", help="Provide a list of interfaces to capture from", action="store_true")
228         parser.add_argument("--extcap-interface", help="Provide the interface to capture from")
229         parser.add_argument("--extcap-dlts", help="Provide a list of dlts for the given interface", action="store_true")
230         parser.add_argument("--extcap-config", help="Provide a list of configurations for the given interface", action="store_true")
231         parser.add_argument("--fifo", help="Use together with capture to provide the fifo to dump data to")
232
233         # Interface Arguments
234         parser.add_argument("--verify", help="Demonstrates a verification bool flag", action="store_true" )
235         parser.add_argument("--delay", help="Demonstrates an integer variable", type=int, default=0, choices=[0, 1, 2, 3, 4, 5] )
236         parser.add_argument("--remote", help="Demonstrates a selector choice", default="if1", choices=["if1", "if2"] )
237         parser.add_argument("--message", help="Demonstrates string variable", nargs='?', default="" )
238
239         args, unknown = parser.parse_known_args()
240         if ( len(sys.argv) <= 1 ):
241                 parser.exit("No arguments given!")
242
243         if ( args.extcap_interfaces == False and args.extcap_interface == None ):
244                 parser.exit("An interface must be provided or the selection must be displayed")
245
246         if ( args.extcap_interfaces == True or args.extcap_interface == None ):
247                 extcap_interfaces()
248                 sys.exit(0)
249
250         if ( len(unknown) > 1 ):
251                 print("Extcap Example %d unknown arguments given" % len(unknown) )
252
253         m = re.match ( 'example(\d+)', args.extcap_interface )
254         if not m:
255                 sys.exit(ERROR_INTERFACE)
256         interface = m.group(1)
257
258         message = args.message
259         if ( args.message == None or len(args.message) == 0 ):
260                 message = "Extcap Test"
261
262         if args.extcap_config:
263                 extcap_config(interface)
264         elif args.extcap_dlts:
265                 extcap_dlts(interface)
266         elif args.capture:
267                 if args.fifo is None:
268                         sys.exit(ERROR_FIFO)
269                 extcap_capture(interface, args.fifo, args.delay, args.verify, message, args.remote)
270         else:
271                 usage()
272                 sys.exit(ERROR_USAGE)