def main(): if len(sys.argv) != 3: usage() # Get the name of the interface to capture on cfg_file = sys.argv[1] src_intf = sys.argv[2] optlist = BPFOptions(cfg_file) bpf_instances = [] writer_instances = [] # pipe to handle kill signal. This uses the fd_reader node to signal # to solarcapture when the process has been terminated. r_fd, w_fd = os.pipe() # used to handle end-of-capture signals (Ctrl-C) def signal_handler(signum, frame): try: os.close(w_fd) except OSError as ex: if ex.errno != errno.EBADF: raise # Create a new session # A session is an association between components that together form # a single SolarCapture topology. This allows the application to # start and stop the topology as a unit. scs = sc.new_session() # Create a thread to do the capture and writeout on cthread = scs.new_thread() # Create a VI on the capture thread. vi = cthread.new_vi(src_intf) # add the streams we want to capture to the VI. In this example, the VI # will steal all traffic arriving on the interface vi.add_stream(scs.new_stream("all")) # Now, for each specified filter, create a filter node and a writer node for bpf_filter, target_file in optlist.filters: bpf_args = dict(bpf=bpf_filter) bpf_instances.append(cthread.new_node("sc_filter", args=bpf_args)) writer_args = dict(filename=target_file, snap=SNAP_LEN) writer_instances.append(cthread.new_node('sc_writer', args=writer_args)) if optlist.unmatched_file: # Create a writer node to catch all unmatched packets unmatched_writer_args = dict(filename=optlist.unmatched_file, snap=SNAP_LEN) unmatched_writer = cthread.new_node('sc_writer', args=unmatched_writer_args) # Create signal handling and cleanup nodes signal_vi = cthread.new_node('sc_signal_vi') exiter = cthread.new_node('sc_exit') reader = cthread.new_node('sc_fd_reader', args={'fd': r_fd}) # Connect nodes together to form node graph. Note that the i+1st filter # is filtering on the packets rejected by the the ith filter: # Connect Vi and signal handler vi.connect(signal_vi) reader.connect(signal_vi, 'ctl') # Add in the first filter node and its associated writer signal_vi.connect(bpf_instances[0]) bpf_instances[0].connect(writer_instances[0]) writer_instances[0].connect(exiter) # If there is more than one BPF filter specified, then this section will # handle chaining these together n_instances = len(bpf_instances) for i in range(1, (n_instances)): bpf_instances[i - 1].connect("not_matched", bpf_instances[i]) bpf_instances[i].connect(writer_instances[i]).connect(exiter) if optlist.unmatched_file: sc.connect(bpf_instances[n_instances - 1], "not_matched", unmatched_writer) sc.connect(unmatched_writer, exiter) # Kick off packet handling scs.go() # Add some signal handling for signum in [signal.SIGINT, signal.SIGTERM, signal.SIGQUIT]: signal.signal(signum, signal_handler) while True: time.sleep(1)
def main(): if len(sys.argv) != 3: usage() # Get the name of the interface to capture on cfg_file = sys.argv[1] src_intf = sys.argv[2] optlist = BPFOptions(cfg_file) bpf_instances = [] writer_instances = [] # pipe to handle kill signal. This uses the fd_reader node to signal # to solarcapture when the process has been terminated. r_fd, w_fd = os.pipe() # used to handle end-of-capture signals (Ctrl-C) def signal_handler(signum, frame): try: os.close(w_fd) except OSError as ex: if ex.errno != errno.EBADF: raise # Create a new session # A session is an association between components that together form # a single SolarCapture topology. This allows the application to # start and stop the topology as a unit. scs = sc.new_session() # Create a thread to do the capture and writeout on cthread = scs.new_thread() # Create a VI on the capture thread. vi = cthread.new_vi(src_intf) # add the streams we want to capture to the VI. In this example, the VI # will steal all traffic arriving on the interface vi.add_stream(scs.new_stream("all")) # Now, for each specified filter, create a filter node and a writer node for bpf_filter, target_file in optlist.filters: bpf_args = dict(bpf=bpf_filter) bpf_instances.append(cthread.new_node("sc_filter", args=bpf_args)) writer_args = dict(filename=target_file, snap=SNAP_LEN) writer_instances.append(cthread.new_node('sc_writer', args=writer_args)) if optlist.unmatched_file: # Create a writer node to catch all unmatched packets unmatched_writer_args = dict(filename=optlist.unmatched_file, snap=SNAP_LEN) unmatched_writer = cthread.new_node('sc_writer', args=unmatched_writer_args) # Create signal handling and cleanup nodes signal_vi = cthread.new_node('sc_signal_vi') exiter = cthread.new_node('sc_exit') reader = cthread.new_node('sc_fd_reader', args={'fd': r_fd}) # Connect nodes together to form node graph. Note that the i+1st filter # is filtering on the packets rejected by the the ith filter: # Connect Vi and signal handler vi.connect(signal_vi) reader.connect(signal_vi, 'ctl') # Add in the first filter node and its associated writer signal_vi.connect(bpf_instances[0]) bpf_instances[0].connect(writer_instances[0]) writer_instances[0].connect(exiter) # If there is more than one BPF filter specified, then this section will # handle chaining these together n_instances = len(bpf_instances) for i in range(1, (n_instances)): bpf_instances[i-1].connect("not_matched", bpf_instances[i]) bpf_instances[i].connect(writer_instances[i]).connect(exiter) if optlist.unmatched_file: sc.connect(bpf_instances[n_instances-1], "not_matched", unmatched_writer) sc.connect(unmatched_writer, exiter) # Kick off packet handling scs.go() # Add some signal handling for signum in [signal.SIGINT, signal.SIGTERM, signal.SIGQUIT]: signal.signal(signum, signal_handler) while True: time.sleep(1)
# main() # Get command line arguments. args = sys.argv[1:] while args and args[0] and args[0][0] == '-': if args[0] == '-h' or args[0] == '--help': usage_msg(sys.stdout) sys.exit(0) else: usage_err() if len(args) != 3: usage_err() if_in = args[0] if_out = args[1] bpf_filter = args[2] scs = sc.new_session() thrd = scs.new_thread() # Create a VI to capture received packets. Forward them via an sc_filter # node to the destination interface. vi = thrd.new_vi(if_in) vi.add_stream(scs.new_stream("all")) filter = thrd.new_node('sc_filter', args=dict(bpf=bpf_filter)) sc.connect(vi, filter) sc.connect(filter, 'not_matched', to_interface=if_out) scs.go() while True: time.sleep(10000)
def main(args): # Get command line arguments. two_threads = True while args and args[0] and args[0][0] == '-': if args[0] == '-h' or args[0] == '--help': usage_msg(sys.stdout) sys.exit(0) elif args[0] == '--single-thread': two_threads = False args.pop(0) else: usage_err() if len(args) != 2: usage_err() intf = args[0] filename = args[1] # A SolarCapture session binds together a set of threads and components # that are doing a particular job. scs = sc.new_session() # Create the threads that will be used for capture and writing to disk. # It is usually a good idea to keep these in separate threads, as # otherwise writing to disk can block capture for long periods of time, # leading to packet loss in some configurations. cap_thread = scs.new_thread() if two_threads: writer_thread = scs.new_thread() else: writer_thread = cap_thread # Create a VI, which is used to receive packets from the network # adapter. vi = cap_thread.new_vi(intf) # Add the streams we want to capture. This VI will capture all packets # arriving at the interface (except for any streams explicitly steered # elsewhere). vi.add_stream(scs.new_stream('all')) # SolarCapture nodes perform packet processing functions such as # monitoring, packet modification, writing to disk, I/O etc. When # allocating nodes you can specify node-specific arguments, which may # be required or optional. # # The 'sc_writer' node writes packets to disk in pcap format. The # 'snap' argument indicates the maximum number of bytes of each packet # that should be saved in the capture file. writer_args = dict(filename=filename, snap=60) writer = writer_thread.new_node('sc_writer', args=writer_args) # Connect the VI to the writer node. sc.connect(vi, writer) # Once we have created the necessary components, and linked them # together as desired, we kick off the actual packet handling. This # call starts the managed threads and begins packet processing. scs.go() # Stop python from swallowing SIGINT! signal.signal(signal.SIGINT, signal.SIG_DFL) while True: time.sleep(10000)