1. Ivan Vučica
  2. XMPP TUN/TAP

Commits

Ivan Vučica  committed b445fd0

Cleaned up setup code. Added proper command-line interface.

  • Participants
  • Parent commits d433f4c
  • Branches default

Comments (0)

Files changed (1)

File xmpptuntap.py

View file
 						break
 				return	
 
+def setupTUNTAP():
+	tuntapDevice = "tap2"
+	if len(sys.argv) >= 2:
+		tuntapDevice = sys.argv[1]
+	ipAddress = "10.0.2.1"
+	if len(sys.argv) >= 3:
+		ipAddress = sys.argv[2]
+	tuntapFD = os.open("/dev/" + tuntapDevice, os.O_RDWR)
+	if tuntapDevice == "net/tun":
+		# Linux specific code
+		TUNSETIFF = 0x400454ca
+		IFF_TUN   = 0x0001
+		IFF_TAP   = 0x0002
+		IFF_NO_PI = 0x1000
 
+		TUNMODE = IFF_TAP
+		TUNMODE |= IFF_NO_PI # do not prepend protocol information
 
-jid = xmpp.protocol.JID(config['jid'])
-if len(sys.argv) >= 4:
-	jid = xmpp.protocol.JID(sys.argv[3])
-client = xmpp.Client(jid.getDomain()) #, debug=[])
-client.connect()
-client.auth(jid.getNode(), config['password'], "xmpptuntap")
+		from fcntl import ioctl
 
-"""
-disco = xmpp.browser.Browser()
-disco.PlugIn(client)
-disco.setDiscoHandler({
-                           'info': {
-                           'ids': [{
-                                   'category': 'applicationt',
-                                   'type': 'bot',
-                                   'name': 'XMPP TUN/TAP Bot'
-                                   }],
-                           'features': [xmpp.protocol.NS_DISCO_INFO, "http://xmpptuntap.vucica.net/protocol/"],
-                           },
-			   'items':[]
-                           })
+		ifs = ioctl(tuntapFD, TUNSETIFF, struct.pack("16sH", "xmpptuntap%d", TUNMODE))
+		tuntapDevice = ifs[:16].strip("\x00")
+		sys.stderr.write("tuntapdevice: " + tuntapDevice + "\n")
 
-commands = xmpp.commands.Commands(disco)
-commands.PlugIn(client)
+	os.system("ifconfig " + tuntapDevice + " inet " + ipAddress);
 
-command_test = TestCommand()
-command_test.plugin(commands)
-command_ls = LsCommand()
-command_ls.plugin(commands)
-"""
+	return (tuntapFD, tuntapDevice, ipAddress)
 
-#Replacing the preceding with two steps: requesting roster and sending 
-#custom presence
-# client.sendInitPresence()
-xmpp.roster.Roster().PlugIn(client) # request roster
-caps = xmpp.Node("c", attrs={"node": "http://xmpptuntap.vucica.net/desktop/caps", "ver": "1.0", "ext": ""}, payload = [ ]); # payload can contain more nodes
-caps.setNamespace(xmpp.NS_CAPS)
-presencePayload	= [caps]
-client.send(xmpp.Presence(payload=presencePayload));
-	
-client.RegisterHandler('message', onMessage);
-client.RegisterHandler("iq", onIqDisco, typ="get", ns=xmpp.protocol.NS_DISCO_INFO);
+def setupXMPP():
+	jid = xmpp.protocol.JID(config['jid'])
+	if len(sys.argv) >= 4:
+		jid = xmpp.protocol.JID(sys.argv[3])
+	client = xmpp.Client(jid.getDomain()) #, debug=[])
+	client.connect()
+	client.auth(jid.getNode(), config['password'], "xmpptuntap")
 
-tuntapDevice = "tap2"
-if len(sys.argv) >= 2:
-	tuntapDevice = sys.argv[1]
-ipAddress = "10.0.2.1"
-if len(sys.argv) >= 3:
-	ipAddress = sys.argv[2]
-tuntapFD = os.open("/dev/" + tuntapDevice, os.O_RDWR)
-if tuntapDevice == "net/tun":
-	# Linux specific code
-	TUNSETIFF = 0x400454ca
-	IFF_TUN   = 0x0001
-	IFF_TAP   = 0x0002
-	IFF_NO_PI = 0x1000
+	"""
+	disco = xmpp.browser.Browser()
+	disco.PlugIn(client)
+	disco.setDiscoHandler({
+				   'info': {
+				   'ids': [{
+					   'category': 'applicationt',
+					   'type': 'bot',
+					   'name': 'XMPP TUN/TAP Bot'
+					   }],
+				   'features': [xmpp.protocol.NS_DISCO_INFO, "http://xmpptuntap.vucica.net/protocol/"],
+				   },
+				   'items':[]
+				   })
 
-	TUNMODE = IFF_TAP
-	TUNMODE |= IFF_NO_PI # do not prepend protocol information
+	commands = xmpp.commands.Commands(disco)
+	commands.PlugIn(client)
 
-	from fcntl import ioctl
+	command_test = TestCommand()
+	command_test.plugin(commands)
+	command_ls = LsCommand()
+	command_ls.plugin(commands)
+	"""
 
-	ifs = ioctl(tuntapFD, TUNSETIFF, struct.pack("16sH", "xmpptuntap%d", TUNMODE))
-	tuntapDevice = ifs[:16].strip("\x00")
-	sys.stderr.write("tuntapdevice: " + tuntapDevice + "\n")
+	#Replacing the preceding with two steps: requesting roster and sending 
+	#custom presence
+	# client.sendInitPresence()
+	xmpp.roster.Roster().PlugIn(client) # request roster
+	caps = xmpp.Node("c", attrs={"node": "http://xmpptuntap.vucica.net/desktop/caps", "ver": "1.0", "ext": ""}, payload = [ ]); # payload can contain more nodes
+	caps.setNamespace(xmpp.NS_CAPS)
+	presencePayload	= [caps]
+	client.send(xmpp.Presence(payload=presencePayload));
+		
+	client.RegisterHandler('message', onMessage);
+	client.RegisterHandler("iq", onIqDisco, typ="get", ns=xmpp.protocol.NS_DISCO_INFO);
 
-os.system("ifconfig " + tuntapDevice + " inet " + ipAddress)
 
-import os.path
-if os.path.isfile("on-up.sh"):
-	os.system("bash ./on-up.sh")
+	return (jid, client)
 
-socketlist = {
-	client.Connection._sock:'xmpp',
-	sys.stdin:'stdio',
-	tuntapFD: 'tuntap'
-}
-print tuntapFD
-while 1:
-	try:
-#	client.Process(1)
 
-		(i , o, e) = select.select(socketlist.keys(),[],[],1)
-		for each in i:
-			if socketlist[each] == 'xmpp':
-				client.Process(1)
-			elif socketlist[each] == 'stdio':
-				msg = sys.stdin.readline().rstrip('\r\n')
-#				print "Not handling stdin " + msg
-				print "Inviting " + msg
+def mainLoopStep(socketlist):
+	global targetForNetTraffic
+	# client.Process(1)
+
+	inputSockets = socketlist.keys()
+	outputSockets = []
+	errorSockets = []
+	(inputReady, outputReady, errorOccurred) = select.select(inputSockets, outputSockets, errorSockets, 1)
+	for each in inputReady:
+		if socketlist[each] == 'xmpp':
+			client.Process(1)
+		elif socketlist[each] == 'stdio':
+			msg = sys.stdin.readline().rstrip('\r\n')
+			tokens = msg.split(' ')
+			if len(tokens) == 0 or tokens[0] == '':
+				continue
+			if tokens[0] == 'help':
+				print ' * help - shows this help'
+				print ' * invite <jid> - invites the jid'
+			elif tokens[0] == 'invite':
+				if len(tokens) != 2:
+					print "syntax: invite <jid>"
+					continue
+				print "Inviting " + tokens[1]
 				
-				targetForNetTraffic = msg
+				targetForNetTraffic = tokens[1]
 				invitation = xmpp.Node("invitation")
 				invitation.setNamespace("http://xmpptuntap.vucica.net/protocol/")
 				
-				message = xmpp.Message(msg, payload = [invitation])
+				message = xmpp.Message(targetForNetTraffic, payload = [invitation])
 				message.setType("headline")
 				client.send(message)
+			else:
+				print "Unknown command " + tokens[0]
+			# bot.stdio_message(msg)
 
-#				bot.stdio_message(msg)
-			elif socketlist[each] == 'tuntap':
-				dataNode = xmpp.Node("data")
-				dataNode.setNamespace("http://xmpptuntap.vucica.net/protocol/")
-				
-				# TODO explore if we can get exact number of bytes to read using something like:
-				#fcntl.ioctl(each, fcntl.FIONREAD...)
-				try:
-					output = os.read(tuntapFD, 8192)
+		elif socketlist[each] == 'tuntap':
+			dataNode = xmpp.Node("data")
+			dataNode.setNamespace("http://xmpptuntap.vucica.net/protocol/")
+			
+			# TODO explore if we can get exact number of bytes to read using something like:
+			#fcntl.ioctl(each, fcntl.FIONREAD...)
+			try:
+				output = os.read(tuntapFD, 8192)
+
+				if targetForNetTraffic != None and targetForNetTraffic != "":
 					output = struct.pack('!H', len(output)) + output # network byte order short is "tapper"'s header
 					dataNode.setData(base64.encodestring(output))
-
 					message = xmpp.Message(targetForNetTraffic, payload = [dataNode])
 					message.setType("headline")
 					client.send(message)
-				except (OSError, IOError), ioe:
-					if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
-						continue
-					else:
-					 	print "Connection lost"
-						exit
+				else:
+					print "Dropping " + str(len(output)) + " bytes of network device traffic; no JID set as target"
+			except (OSError, IOError), ioe:
+				if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
+					continue
+				else:
+					raise Exception("tun/tap device went down")
 
-				
-			else:
-				raise Exception("Unknown socket type: %s" % repr(socketlist[each]))
+		else:
+			raise Exception("Unknown socket type: %s" % repr(socketlist[each]))
 
 
-	except KeyboardInterrupt:
-		# finish whatever needed
-		break
 
+def main():
+	global tuntapFD, tuntapDevice, ipAddress, jid, client
+
+	# set up tuntap
+	(tuntapFD, tuntapDevice, ipAddress) = setupTUNTAP()
+
+	# connect to xmpp
+	(jid, client) = setupXMPP()
+
+	socketlist = {
+		client.Connection._sock:'xmpp',
+		sys.stdin:'stdio',
+		tuntapFD: 'tuntap'
+	}
+
+	while True:
+		try: mainLoopStep(socketlist)
+		except KeyboardInterrupt:
+			# finish whatever needed
+			break
+
+
+main()