1#!/usr/bin/python
2# Tests p2p_connect
3# Will try to connect to another peer
4# and form a group
5######### MAY NEED TO RUN AS SUDO #############
6
7import dbus
8import sys, os
9import time
10import gobject
11import getopt
12from dbus.mainloop.glib import DBusGMainLoop
13
14
15def usage():
16	print "Usage:"
17	print "  %s -i <interface_name> -m <wps_method> \ " \
18		% sys.argv[0]
19	print "		-a <addr> [-p <pin>] [-g <go_intent>] \ "
20	print "  		[-w <wpas_dbus_interface>]"
21	print "Options:"
22	print "  -i = interface name"
23	print "  -m = wps method"
24	print "  -a = peer address"
25	print "  -p = pin number (8 digits)"
26	print "  -g = group owner intent"
27	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
28	print "Example:"
29	print "  %s -i wlan0 -a 0015008352c0 -m display -p 12345670" % sys.argv[0]
30
31
32# Required Signals
33def GONegotiationSuccess(status):
34	print "Go Negotiation Success"
35
36def GONegotiationFailure(status):
37	print 'Go Negotiation Failed. Status:'
38	print format(status)
39	os._exit(0)
40
41def GroupStarted(properties):
42	if properties.has_key("group_object"):
43		print 'Group Formation Complete %s' \
44			% properties["group_object"]
45	os._exit(0)
46
47def WpsFailure(status, etc):
48	print "WPS Authentication Failure".format(status)
49	print etc
50	os._exit(0)
51
52class P2P_Connect():
53	# Needed Variables
54	global bus
55	global wpas_object
56	global interface_object
57	global p2p_interface
58	global ifname
59	global wpas
60	global wpas_dbus_interface
61	global timeout
62	global path
63	global wps_method
64	global go_intent
65	global addr
66	global pin
67
68	# Dbus Paths
69	global wpas_dbus_opath
70	global wpas_dbus_interfaces_opath
71	global wpas_dbus_interfaces_interface
72	global wpas_dbus_interfaces_p2pdevice
73
74	# Dictionary of Arguements
75	global p2p_connect_arguements
76
77	# Constructor
78	def __init__(self,ifname,wpas_dbus_interface,addr,
79					pin,wps_method,go_intent):
80		# Initializes variables and threads
81		self.ifname = ifname
82		self.wpas_dbus_interface = wpas_dbus_interface
83		self.wps_method = wps_method
84		self.go_intent = go_intent
85		self.addr = addr
86		self.pin = pin
87
88		# Generating interface/object paths
89		self.wpas_dbus_opath = \
90			"/" + self.wpas_dbus_interface.replace(".","/")
91		self.wpas_wpas_dbus_interfaces_opath = \
92			self.wpas_dbus_opath + "/Interfaces"
93		self.wpas_dbus_interfaces_interface = \
94			self.wpas_dbus_interface + ".Interface"
95		self.wpas_dbus_interfaces_p2pdevice = \
96			self.wpas_dbus_interfaces_interface + ".P2PDevice"
97
98		# Getting interfaces and objects
99		DBusGMainLoop(set_as_default=True)
100		self.bus = dbus.SystemBus()
101		self.wpas_object = self.bus.get_object(
102				self.wpas_dbus_interface,
103				self.wpas_dbus_opath)
104		self.wpas = dbus.Interface(
105				self.wpas_object, self.wpas_dbus_interface)
106
107		# See if wpa_supplicant already knows about this interface
108		self.path = None
109		try:
110			self.path = self.wpas.GetInterface(ifname)
111		except:
112			if not str(exc).startswith(
113				self.wpas_dbus_interface + \
114				".InterfaceUnknown:"):
115				raise exc
116			try:
117				path = self.wpas.CreateInterface(
118					{'Ifname': ifname, 'Driver': 'test'})
119				time.sleep(1)
120
121			except dbus.DBusException, exc:
122				if not str(exc).startswith(
123					self.wpas_dbus_interface + \
124					".InterfaceExists:"):
125					raise exc
126
127		# Get Interface and objects
128		self.interface_object = self.bus.get_object(
129				self.wpas_dbus_interface,self.path)
130		self.p2p_interface = dbus.Interface(
131				self.interface_object,
132				self.wpas_dbus_interfaces_p2pdevice)
133
134		# Add signals
135		self.bus.add_signal_receiver(GONegotiationSuccess,
136			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
137			signal_name="GONegotiationSuccess")
138		self.bus.add_signal_receiver(GONegotiationFailure,
139			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
140			signal_name="GONegotiationFailure")
141		self.bus.add_signal_receiver(GroupStarted,
142			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
143			signal_name="GroupStarted")
144		self.bus.add_signal_receiver(WpsFailure,
145			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
146			signal_name="WpsFailed")
147
148
149	#Constructing all the arguements needed to connect
150	def constructArguements(self):
151		# Adding required arguements
152		self.p2p_connect_arguements = {'wps_method':self.wps_method,
153			'peer':dbus.ObjectPath(self.path+'/Peers/'+self.addr)}
154
155		# Display requires a pin, and a go intent of 15
156		if (self.wps_method == 'display'):
157			if (self.pin != None):
158				self.p2p_connect_arguements.update({'pin':self.pin})
159			else:
160				print "Error:\n  Pin required for wps_method=display"
161				usage()
162				quit()
163
164			if (self.go_intent != None and int(self.go_intent) != 15):
165				print "go_intent overwritten to 15"
166
167			self.go_intent = '15'
168
169		# Keypad requires a pin, and a go intent of less than 15
170		elif (self.wps_method == 'keypad'):
171			if (self.pin != None):
172				self.p2p_connect_arguements.update({'pin':self.pin})
173			else:
174				print "Error:\n  Pin required for wps_method=keypad"
175				usage()
176				quit()
177
178			if (self.go_intent != None and int(self.go_intent) == 15):
179				error = "Error :\n Group Owner intent cannot be" + \
180					" 15 for wps_method=keypad"
181				print error
182				usage()
183				quit()
184
185		# Doesn't require pin
186		# for ./wpa_cli, p2p_connect [mac] [pin#], wps_method=keypad
187		elif (self.wps_method == 'pin'):
188			if (self.pin != None):
189				print "pin ignored"
190
191		# No pin is required for pbc so it is ignored
192		elif (self.wps_method == 'pbc'):
193			if (self.pin != None):
194				print "pin ignored"
195
196		else:
197			print "Error:\n  wps_method not supported or does not exist"
198			usage()
199			quit()
200
201		# Go_intent is optional for all arguements
202		if (self.go_intent != None):
203			self.p2p_connect_arguements.update(
204				{'go_intent':dbus.Int32(self.go_intent)})
205
206	# Running p2p_connect
207	def run(self):
208		try:
209			result_pin = self.p2p_interface.Connect(
210				self.p2p_connect_arguements)
211
212		except dbus.DBusException, exc:
213				raise exc
214
215		if (self.wps_method == 'pin' and \
216		not self.p2p_connect_arguements.has_key('pin') ):
217			print "Connect return with pin value of %d " % int(result_pin)
218		gobject.MainLoop().run()
219
220if __name__ == "__main__":
221
222	# Required
223	interface_name = None
224	wps_method = None
225	addr = None
226
227	# Conditionally optional
228	pin = None
229
230	# Optional
231	wpas_dbus_interface = 'fi.w1.wpa_supplicant1'
232	go_intent = None
233
234	# Using getopts to handle options
235	try:
236		options, args = getopt.getopt(sys.argv[1:],"hi:m:a:p:g:w:")
237
238	except getopt.GetoptError:
239		usage()
240		quit()
241
242	# If theres a switch, override default option
243	for key, value in options:
244		# Help
245		if (key == "-h"):
246			usage()
247			quit()
248		# Interface Name
249		elif (key == "-i"):
250			interface_name = value
251		# WPS Method
252		elif (key == "-m"):
253			wps_method = value
254		# Address
255		elif (key == "-a"):
256			addr = value
257		# Pin
258		elif (key == "-p"):
259			pin = value
260		# Group Owner Intent
261		elif (key == "-g"):
262			go_intent = value
263		# Dbus interface
264		elif (key == "-w"):
265			wpas_dbus_interface = value
266		else:
267			assert False, "unhandled option"
268
269	# Required Arguements check
270	if (interface_name == None or wps_method == None or addr == None):
271		print "Error:\n  Required arguements not specified"
272		usage()
273		quit()
274
275	# Group Owner Intent Check
276	if (go_intent != None and (int(go_intent) > 15 or int(go_intent) < 0) ):
277		print "Error:\n  Group Owner Intent must be between 0 and 15 inclusive"
278		usage()
279		quit()
280
281	# Pin Check
282	if (pin != None and len(pin) != 8):
283		print "Error:\n  Pin is not 8 digits"
284		usage()
285		quit()
286
287	try:
288		p2p_connect_test = P2P_Connect(interface_name,wpas_dbus_interface,
289			addr,pin,wps_method,go_intent)
290
291	except:
292		print "Error:\n  Invalid Arguements"
293		usage()
294		quit()
295
296	p2p_connect_test.constructArguements()
297	p2p_connect_test.run()
298
299	os._exit(0)
300