ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/Makefile b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/Makefile
new file mode 100644
index 0000000..6f720a9
--- /dev/null
+++ b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/Makefile
@@ -0,0 +1,15 @@
+all: build
+
+SRC=wpaspy.c
+
+.PHONY: build
+build: $(SRC) setup.py
+	python setup.py build
+
+install:
+	python setup.py install
+
+clean:
+	python setup.py clean
+	rm -f *~
+	rm -rf build
diff --git a/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/setup.py b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/setup.py
new file mode 100644
index 0000000..4dbf765
--- /dev/null
+++ b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/setup.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+#
+# Python bindings for wpa_ctrl (wpa_supplicant/hostapd control interface)
+# Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+from distutils.core import setup, Extension
+
+ext = Extension(name = 'wpaspy',
+                sources = ['../src/common/wpa_ctrl.c',
+                           '../src/utils/os_unix.c',
+                           'wpaspy.c'],
+                extra_compile_args = ["-I../src/common",
+                                      "-I../src/utils",
+                                      "-DCONFIG_CTRL_IFACE",
+                                      "-DCONFIG_CTRL_IFACE_UNIX"])
+
+setup(name = 'wpaspy',
+      ext_modules = [ext],
+      description = 'Python bindings for wpa_ctrl (wpa_supplicant/hostapd)')
diff --git a/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/test.py b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/test.py
new file mode 100644
index 0000000..5e18fb2
--- /dev/null
+++ b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/test.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+#
+# Test script for wpaspy
+# Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import sys
+import time
+import wpaspy
+
+wpas_ctrl = '/var/run/wpa_supplicant'
+
+def wpas_connect(host=None, port=9877):
+    ifaces = []
+
+    if host != None:
+        try:
+            wpas = wpaspy.Ctrl(host, port)
+            return wpas
+        except:
+            print("Could not connect to host: ", host)
+            return None
+
+    if os.path.isdir(wpas_ctrl):
+        try:
+            ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
+        except OSError as error:
+            print("Could not find wpa_supplicant: ", error)
+            return None
+
+    if len(ifaces) < 1:
+        print("No wpa_supplicant control interface found")
+        return None
+
+    for ctrl in ifaces:
+        try:
+            wpas = wpaspy.Ctrl(ctrl)
+            return wpas
+        except Exception as e:
+            pass
+    return None
+
+
+def main(host=None, port=9877):
+    print("Testing wpa_supplicant control interface connection")
+    wpas = wpas_connect(host, port)
+    if wpas is None:
+        return
+    print("Connected to wpa_supplicant")
+    print(wpas.request('PING'))
+
+    mon = wpas_connect(host, port)
+    if mon is None:
+        print("Could not open event monitor connection")
+        return
+
+    mon.attach()
+    print("Scan")
+    print(wpas.request('SCAN'))
+
+    count = 0
+    while count < 10:
+        count += 1
+        time.sleep(1)
+        while mon.pending():
+            ev = mon.recv()
+            print(ev)
+            if 'CTRL-EVENT-SCAN-RESULTS' in ev:
+                print('Scan completed')
+                print(wpas.request('SCAN_RESULTS'))
+                count = 10
+                pass
+
+
+if __name__ == "__main__":
+    if len(sys.argv) > 2:
+        main(host=sys.argv[1], port=int(sys.argv[2]))
+    else:
+        main()
diff --git a/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/wpaspy.c b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/wpaspy.c
new file mode 100644
index 0000000..4d4c2a4
--- /dev/null
+++ b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/wpaspy.c
@@ -0,0 +1,245 @@
+/*
+ * Python bindings for wpa_ctrl (wpa_supplicant/hostapd control interface)
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "wpa_ctrl.h"
+
+
+struct wpaspy_obj {
+	PyObject_HEAD
+	struct wpa_ctrl *ctrl;
+	int attached;
+};
+
+static PyObject *wpaspy_error;
+
+
+static int wpaspy_open(struct wpaspy_obj *self, PyObject *args)
+{
+	const char *path;
+
+	if (!PyArg_ParseTuple(args, "s", &path))
+		return -1;
+	self->ctrl = wpa_ctrl_open(path);
+	if (self->ctrl == NULL)
+		return -1;
+	self->attached = 0;
+	return 0;
+}
+
+
+static void wpaspy_close(struct wpaspy_obj *self)
+{
+	if (self->ctrl) {
+		if (self->attached)
+			wpa_ctrl_detach(self->ctrl);
+		wpa_ctrl_close(self->ctrl);
+		self->ctrl = NULL;
+	}
+
+	PyObject_Del(self);
+}
+
+
+static PyObject * wpaspy_request(struct wpaspy_obj *self, PyObject *args)
+{
+	const char *cmd;
+	char buf[4096];
+	size_t buflen;
+	int ret;
+
+	if (!PyArg_ParseTuple(args, "s", &cmd))
+		return NULL;
+
+	buflen = sizeof(buf) - 1;
+	ret = wpa_ctrl_request(self->ctrl, cmd, strlen(cmd), buf, &buflen,
+			       NULL);
+	if (ret == -2) {
+		PyErr_SetString(wpaspy_error, "Request timed out");
+		return NULL;
+	}
+	if (ret) {
+		PyErr_SetString(wpaspy_error, "Request failed");
+		return NULL;
+	}
+
+	buf[buflen] = '\0';
+	return Py_BuildValue("s", buf);
+}
+
+
+static PyObject * wpaspy_attach(struct wpaspy_obj *self)
+{
+	int ret;
+
+	if (self->attached)
+		Py_RETURN_NONE;
+
+	ret = wpa_ctrl_attach(self->ctrl);
+	if (ret) {
+		PyErr_SetString(wpaspy_error, "Attach failed");
+		return NULL;
+	}
+	Py_RETURN_NONE;
+}
+
+
+static PyObject * wpaspy_detach(struct wpaspy_obj *self)
+{
+	int ret;
+
+	if (!self->attached)
+		Py_RETURN_NONE;
+
+	ret = wpa_ctrl_detach(self->ctrl);
+	if (ret) {
+		PyErr_SetString(wpaspy_error, "Detach failed");
+		return NULL;
+	}
+	Py_RETURN_NONE;
+}
+
+
+static PyObject * wpaspy_pending(struct wpaspy_obj *self)
+{
+	switch (wpa_ctrl_pending(self->ctrl)) {
+	case 1:
+		Py_RETURN_TRUE;
+	case 0:
+		Py_RETURN_FALSE;
+	default:
+		PyErr_SetString(wpaspy_error, "wpa_ctrl_pending failed");
+		break;
+	}
+
+	return NULL;
+}
+
+
+static PyObject * wpaspy_recv(struct wpaspy_obj *self)
+{
+	int ret;
+	char buf[4096];
+	size_t buflen;
+
+	buflen = sizeof(buf) - 1;
+	Py_BEGIN_ALLOW_THREADS
+	ret = wpa_ctrl_recv(self->ctrl, buf, &buflen);
+	Py_END_ALLOW_THREADS
+
+	if (ret) {
+		PyErr_SetString(wpaspy_error, "wpa_ctrl_recv failed");
+		return NULL;
+	}
+
+	buf[buflen] = '\0';
+	return Py_BuildValue("s", buf);
+}
+
+
+static PyMethodDef wpaspy_methods[] = {
+	{
+		"request", (PyCFunction) wpaspy_request, METH_VARARGS,
+		"Send a control interface command and return response"
+	},
+	{
+		"attach", (PyCFunction) wpaspy_attach, METH_NOARGS,
+		"Attach as an event monitor"
+	},
+	{
+		"detach", (PyCFunction) wpaspy_detach, METH_NOARGS,
+		"Detach an event monitor"
+	},
+	{
+		"pending", (PyCFunction) wpaspy_pending, METH_NOARGS,
+		"Check whether any events are pending"
+	},
+	{
+		"recv", (PyCFunction) wpaspy_recv, METH_NOARGS,
+		"Received pending event"
+	},
+	{ NULL, NULL, 0, NULL }
+};
+
+static PyMemberDef wpaspy_members[] = {
+	{
+		"attached", T_INT, offsetof(struct wpaspy_obj, attached),
+		READONLY,
+		"Whether instance is attached as event monitor"
+	},
+	{ NULL }
+};
+
+static PyTypeObject wpaspy_ctrl = {
+	PyObject_HEAD_INIT(NULL)
+	.tp_name = "wpaspy.Ctrl",
+	.tp_basicsize = sizeof(struct wpaspy_obj),
+	.tp_getattro = PyObject_GenericGetAttr,
+	.tp_setattro = PyObject_GenericSetAttr,
+	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+	.tp_methods = wpaspy_methods,
+	.tp_members = wpaspy_members,
+	.tp_init = (initproc) wpaspy_open,
+	.tp_dealloc = (destructor) wpaspy_close,
+	.tp_new = PyType_GenericNew,
+};
+
+
+#if PY_MAJOR_VERSION < 3
+static PyMethodDef module_methods[] = {
+	{ NULL, NULL, 0, NULL }
+};
+
+
+PyMODINIT_FUNC initwpaspy(void)
+{
+	PyObject *mod;
+
+	PyType_Ready(&wpaspy_ctrl);
+	mod = Py_InitModule("wpaspy", module_methods);
+	wpaspy_error = PyErr_NewException("wpaspy.error", NULL, NULL);
+
+	Py_INCREF(&wpaspy_ctrl);
+	Py_INCREF(wpaspy_error);
+
+	PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl);
+	PyModule_AddObject(mod, "error", wpaspy_error);
+}
+#else
+static struct PyModuleDef wpaspy_def = {
+	PyModuleDef_HEAD_INIT,
+	"wpaspy",
+};
+
+
+PyMODINIT_FUNC initwpaspy(void)
+{
+	PyObject *mod;
+
+	mod = PyModule_Create(&wpaspy_def);
+	if (!mod)
+		return NULL;
+
+	wpaspy_error = PyErr_NewException("wpaspy.error", NULL, NULL);
+
+	Py_INCREF(&wpaspy_ctrl);
+	Py_INCREF(wpaspy_error);
+
+	if (PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl) < 0 ||
+	    PyModule_AddObject(mod, "error", wpaspy_error) < 0) {
+		Py_DECREF(&wpaspy_ctrl);
+		Py_DECREF(wpaspy_error);
+		Py_DECREF(mod);
+		mod = NULL;
+	}
+
+	return mod;
+}
+#endif
diff --git a/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/wpaspy.py b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/wpaspy.py
new file mode 100644
index 0000000..5b8140b
--- /dev/null
+++ b/package/kernel/asr-wl/asr-hostapd/asr-hostapd-2023-06-22/wpaspy/wpaspy.py
@@ -0,0 +1,149 @@
+#!/usr/bin/python
+#
+# wpa_supplicant/hostapd control interface using Python
+# Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import stat
+import socket
+import select
+
+counter = 0
+
+class Ctrl:
+    def __init__(self, path, port=9877):
+        global counter
+        self.started = False
+        self.attached = False
+        self.path = path
+        self.port = port
+
+        self.udp = False
+        if not path.startswith('/'):
+            try:
+                mode = os.stat(path).st_mode
+                if not stat.S_ISSOCK(mode):
+                    self.udp = True
+            except:
+                self.udp = True
+
+        if not self.udp:
+            self.s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+            self.dest = path
+            self.local = "/tmp/wpa_ctrl_" + str(os.getpid()) + '-' + str(counter)
+            counter += 1
+            self.s.bind(self.local)
+            try:
+                self.s.connect(self.dest)
+            except Exception as e:
+                self.s.close()
+                os.unlink(self.local)
+                raise
+        else:
+            try:
+                self.s = None
+                ai_list = socket.getaddrinfo(path, port, socket.AF_INET,
+                                             socket.SOCK_DGRAM)
+                for af, socktype, proto, cn, sockaddr in ai_list:
+                    self.sockaddr = sockaddr
+                    break
+                self.s = socket.socket(af, socktype)
+                self.s.settimeout(5)
+                self.s.sendto(b"GET_COOKIE", sockaddr)
+                reply, server = self.s.recvfrom(4096)
+                self.cookie = reply
+                self.port = port
+            except:
+                print("connect exception ", path, str(port))
+                if self.s != None:
+                    self.s.close()
+                raise
+        self.started = True
+
+    def __del__(self):
+        self.close()
+
+    def close(self):
+        if self.attached:
+            try:
+                self.detach()
+            except Exception as e:
+                # Need to ignore this allow the socket to be closed
+                self.attached = False
+                pass
+        if self.started:
+            self.s.close()
+            if not self.udp:
+                os.unlink(self.local)
+            self.started = False
+
+    def request(self, cmd, timeout=10):
+        if type(cmd) == str:
+            try:
+                cmd2 = cmd.encode()
+                cmd = cmd2
+            except UnicodeDecodeError as e:
+                pass
+        if self.udp:
+            self.s.sendto(self.cookie + cmd, self.sockaddr)
+        else:
+            self.s.send(cmd)
+        [r, w, e] = select.select([self.s], [], [], timeout)
+        if r:
+            res = self.s.recv(4096).decode()
+            try:
+                r = str(res)
+            except UnicodeDecodeError as e:
+                r = res
+            return r
+        raise Exception("Timeout on waiting response")
+
+    def attach(self):
+        if self.attached:
+            return None
+        res = self.request("ATTACH")
+        if "OK" in res:
+            self.attached = True
+            return None
+        raise Exception("ATTACH failed")
+
+    def detach(self):
+        if not self.attached:
+            return None
+        if self.s.fileno() == -1:
+            self.attached = False
+            return None
+        while self.pending():
+            ev = self.recv()
+        res = self.request("DETACH")
+        if "FAIL" not in res:
+            self.attached = False
+            return None
+        raise Exception("DETACH failed")
+
+    def terminate(self):
+        if self.attached:
+            try:
+                self.detach()
+            except Exception as e:
+                # Need to ignore this to allow the socket to be closed
+                self.attached = False
+        self.request("TERMINATE")
+        self.close()
+
+    def pending(self, timeout=0):
+        [r, w, e] = select.select([self.s], [], [], timeout)
+        if r:
+            return True
+        return False
+
+    def recv(self):
+        res = self.s.recv(4096).decode()
+        try:
+            r = str(res)
+        except UnicodeDecodeError as e:
+            r = res
+        return r