简体   繁体   中英

Writing an external program to interface with wpa_supplicant

I need to interact directly with wpa_supplicant from Python. As I understand it one can connect to wpa_supplicant using Unix sockets and wpa_supplicant control interface ( https://w1.fi/wpa_supplicant/devel/ctrl_iface_page.html ). I wrote a simple program that sends a PING command:

import socket

CTRL_SOCKETS = "/home/victor/Research/wpa_supplicant_python/supplicant_conf"
INTERFACE = "wlx84c9b281aa80"
SOCKETFILE = "{}/{}".format(CTRL_SOCKETS, INTERFACE)

s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.connect(SOCKETFILE)
s.send(b'PING')
while 1:
    data = s.recv(1024)
    if data:
        print(repr(data))

But when I run it, wpa_supplicant reports an error:

wlx84c9b281aa80: ctrl_iface sendto failed: 107 - Transport endpoint is not connected

Could someone please provide an example, how you would do a 'scan' and then print 'scan_results'.

Apparently, the type of socket that wpa_supplicant uses (UNIX datagram) does not provide any way for the server to reply. There are a few ways to get around that . wpa_supplicant in particular seems to support replies through a separate socket (found at a path appended at the end of each message).

Weirdly enough, this seems to be a relatively common practice in Linux: /dev/log seems to work in the same way .

Here's a program that does what you asked for:

import socket, os
from time import sleep

def sendAndReceive(outmsg, csock, ssock_filename):
  '''Sends outmsg to wpa_supplicant and returns the reply'''

  # the return socket object can be used to send the data
  # as long as the address is provided
  csock.sendto(str.encode(outmsg), ssock_filename)

  (bytes, address) = csock.recvfrom(4096)
  inmsg = bytes.decode('utf-8')

  return inmsg

wpasock_file = '/var/run/wpa_supplicant/wlp3s0'
retsock_file = '/tmp/return_socket'

if os.path.exists(retsock_file):
  os.remove(retsock_file)
retsock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
retsock.bind(retsock_file)

replyToScan = sendAndReceive('SCAN', retsock, wpasock_file)
print(f'SCAN: {replyToScan}')

sleep(5)

replyToScanResults = sendAndReceive('SCAN_RESULTS', retsock, wpasock_file)
print(f'SCAN_RESULTS: {replyToScanResults}')

retsock.close()
os.remove(retsock_file)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM