#!/usr/bin/python2
#
"""Tap for Python
 Copyright (C) 2002 Michael DeMurga

 This script is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this script; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 this script for OS X and linux platforms listens to tcpdump and then
 sends ip data out in OSC format to the ip/port of your choice
 [ip of source, ip_port of source, ip destination, ip_port of destination]

 uses danny holth/clinton mcchesney OSC.py module to convert data into OSC format
 http://wireTAP.stetson.edu

 tap must run as sudo

 for OSX, /usr/local/lib/libdl.dylib must be present to run "freeze" version of this app
 if needed, download bash from apple.com and, as root, copy the enclosed libdl.dylib
 to /usr/local/lib.

 TODO:
 handle non-tcp / udp data correctly (such as arp, icmp)
 currently ignores tcpdump data that does not conform to tcp/udp format
 print rejected packets (packets that are not udp, tcp, etc)
 This script is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this script; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""

from wtMessenger import wtMessenger
import sys
import os
import string
from operator import *
from time import sleep
from re import *

# sleep time (in seconds)
SLEEP=.01

# check arg count
if len(sys.argv) < 5:
	print 'usage:  tcpdClient.py wireTAPhost port wireTAPchannel interface {debugip}'
	sys.exit(1)

# parse args
TO_IP	= sys.argv[1]
TO_PORT	= sys.argv[2]
CHANNEL = sys.argv[3]
IFACE   = sys.argv[4]
if len(sys.argv) > 5:                   # remote debug ?
        DEBUG_IP  = sys.argv[5]         # get remote host to debug from
else:
        DEBUG_IP  =''

# create connection to wireTAP server
mess=wtMessenger()
mess.setServerPort(int(TO_PORT))
mess.serverConnect(TO_IP,CHANNEL)

# run tcpdump w/ variables
# avoids sniffing destination port
# so this script does not sniff itself
tcpdumpcmd = 'tcpdump -nq -i '+IFACE+' \'not ((dst port ' + TO_PORT + ' and dst host ' + TO_IP+')'
if DEBUG_IP:
        tcpdumpcmd = tcpdumpcmd+' or host '+DEBUG_IP
tcpdumpcmd=tcpdumpcmd+')\''
print tcpdumpcmd
a = os.popen(tcpdumpcmd)

# read tcpdump data and send it to the server
while 1:
        try:

                q = a.readline()        # read tcpdump data, followed by data clean-up/format
		if DEBUG_IP:
                	print '-------------------------------'
                	print 'tcpdump:', q

                if len(q) > 0:          # avoid bogus "size 1" data

                        # pull off 2nd and 4th fields of tcpdump output
                        temp = q.split(" ")
                        if len(temp)>1:
                                ip_info1 = temp[1]
                        else:
                                ip_info1=" "

                        if DEBUG_IP:
				print 'ip_info1:', ip_info1

                        if len(temp)>3:
                                ip_info2 = temp[3]
                        else:
                                ip_info2=" "

                        if DEBUG_IP:
				print 'ip_info2:', ip_info2

                        # glom them together into a list
                        ip_info=[ip_info1,ip_info2]
                        if ip_info[1]:  # avoid bogus IPX data
                                # look for numerical data only
                                if search(ip_info[0][0], string.digits) and search(ip_info[1][0], string.digits):

                                        # in the 2nd field, only keep what comes before the :
                                        ip_info[1] = ip_info[1].split(":")[0]

                                        # split up the quads; initialize
                                        # 2nd and 4th fields to '0'
                                        ip = [ip_info[0].split("."), '0', ip_info[1].split("."), '0']

                                        # protocol found; stuff it in the 2nd
                                        # field of the output and remove it
                                        # from the 1st field
                                        if len(ip[0]) == 5:
                                                ip[1] = ip[0][4]; ip[0].pop()

                                        # join quads back together in
                                        # the first field
                                        ip[0] = ".".join(ip[0])

                                        # process similarly
                                        if len(ip[2]) == 5:
                                                ip[3] = ip[2][4]; ip[2].pop()

                                        ip[2] = ".".join(ip[2])

                                        # add data to the message to be sent to the server
                                        for i in range(4):
                                                mess.add(ip[i])

                                        # ship it off
					mess.send()

		sleep(SLEEP)

        except KeyboardInterrupt:
		mess.serverDisconnect()
                print ' '
                print 'your tcpdump session is now complete'
                print ' '
                sys.exit(0)
