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 Arguments
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 dbus.DBusException as exc:
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 as 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 arguments needed to connect
150          def constructArguements(self):
151                    # Adding required arguments
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 arguments
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 as 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 there's 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 Arguments check
270          if (interface_name == None or wps_method == None or addr == None):
271                    print("Error:\n  Required arguments 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 Arguments")
293                    usage()
294                    quit()
295
296          p2p_connect_test.constructArguements()
297          p2p_connect_test.run()
298
299          os._exit(0)
300