wpaspy.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Python bindings for wpa_ctrl (wpa_supplicant/hostapd control interface)
  3. * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include <Python.h>
  9. #include <structmember.h>
  10. #include "wpa_ctrl.h"
  11. struct wpaspy_obj {
  12. PyObject_HEAD
  13. struct wpa_ctrl *ctrl;
  14. int attached;
  15. };
  16. static PyObject *wpaspy_error;
  17. static int wpaspy_open(struct wpaspy_obj *self, PyObject *args)
  18. {
  19. const char *path;
  20. if (!PyArg_ParseTuple(args, "s", &path))
  21. return -1;
  22. self->ctrl = wpa_ctrl_open(path);
  23. if (self->ctrl == NULL)
  24. return -1;
  25. self->attached = 0;
  26. return 0;
  27. }
  28. static void wpaspy_close(struct wpaspy_obj *self)
  29. {
  30. if (self->ctrl) {
  31. if (self->attached)
  32. wpa_ctrl_detach(self->ctrl);
  33. wpa_ctrl_close(self->ctrl);
  34. self->ctrl = NULL;
  35. }
  36. if (self->ob_type)
  37. self->ob_type->tp_free((PyObject *) self);
  38. }
  39. static PyObject * wpaspy_request(struct wpaspy_obj *self, PyObject *args)
  40. {
  41. const char *cmd;
  42. char buf[4096];
  43. size_t buflen;
  44. int ret;
  45. if (!PyArg_ParseTuple(args, "s", &cmd))
  46. return NULL;
  47. buflen = sizeof(buf) - 1;
  48. ret = wpa_ctrl_request(self->ctrl, cmd, strlen(cmd), buf, &buflen,
  49. NULL);
  50. if (ret == -2) {
  51. PyErr_SetString(wpaspy_error, "Request timed out");
  52. return NULL;
  53. }
  54. if (ret) {
  55. PyErr_SetString(wpaspy_error, "Request failed");
  56. return NULL;
  57. }
  58. buf[buflen] = '\0';
  59. return Py_BuildValue("s", buf);
  60. }
  61. static PyObject * wpaspy_attach(struct wpaspy_obj *self)
  62. {
  63. int ret;
  64. if (self->attached)
  65. Py_RETURN_NONE;
  66. ret = wpa_ctrl_attach(self->ctrl);
  67. if (ret) {
  68. PyErr_SetString(wpaspy_error, "Attach failed");
  69. return NULL;
  70. }
  71. Py_RETURN_NONE;
  72. }
  73. static PyObject * wpaspy_detach(struct wpaspy_obj *self)
  74. {
  75. int ret;
  76. if (!self->attached)
  77. Py_RETURN_NONE;
  78. ret = wpa_ctrl_detach(self->ctrl);
  79. if (ret) {
  80. PyErr_SetString(wpaspy_error, "Detach failed");
  81. return NULL;
  82. }
  83. Py_RETURN_NONE;
  84. }
  85. static PyObject * wpaspy_pending(struct wpaspy_obj *self)
  86. {
  87. switch (wpa_ctrl_pending(self->ctrl)) {
  88. case 1:
  89. Py_RETURN_TRUE;
  90. case 0:
  91. Py_RETURN_FALSE;
  92. default:
  93. PyErr_SetString(wpaspy_error, "wpa_ctrl_pending failed");
  94. break;
  95. }
  96. return NULL;
  97. }
  98. static PyObject * wpaspy_recv(struct wpaspy_obj *self)
  99. {
  100. int ret;
  101. char buf[4096];
  102. size_t buflen;
  103. buflen = sizeof(buf) - 1;
  104. Py_BEGIN_ALLOW_THREADS
  105. ret = wpa_ctrl_recv(self->ctrl, buf, &buflen);
  106. Py_END_ALLOW_THREADS
  107. if (ret) {
  108. PyErr_SetString(wpaspy_error, "wpa_ctrl_recv failed");
  109. return NULL;
  110. }
  111. buf[buflen] = '\0';
  112. return Py_BuildValue("s", buf);
  113. }
  114. static PyMethodDef wpaspy_methods[] = {
  115. {
  116. "request", (PyCFunction) wpaspy_request, METH_VARARGS,
  117. "Send a control interface command and return response"
  118. },
  119. {
  120. "attach", (PyCFunction) wpaspy_attach, METH_NOARGS,
  121. "Attach as an event monitor"
  122. },
  123. {
  124. "detach", (PyCFunction) wpaspy_detach, METH_NOARGS,
  125. "Detach an event monitor"
  126. },
  127. {
  128. "pending", (PyCFunction) wpaspy_pending, METH_NOARGS,
  129. "Check whether any events are pending"
  130. },
  131. {
  132. "recv", (PyCFunction) wpaspy_recv, METH_NOARGS,
  133. "Received pending event"
  134. },
  135. { NULL, NULL, 0, NULL }
  136. };
  137. static PyMemberDef wpaspy_members[] = {
  138. {
  139. "attached", T_INT, offsetof(struct wpaspy_obj, attached),
  140. READONLY,
  141. "Whether instance is attached as event monitor"
  142. },
  143. { NULL }
  144. };
  145. static PyTypeObject wpaspy_ctrl = {
  146. PyObject_HEAD_INIT(NULL)
  147. .tp_name = "wpaspy.Ctrl",
  148. .tp_basicsize = sizeof(struct wpaspy_obj),
  149. .tp_getattro = PyObject_GenericGetAttr,
  150. .tp_setattro = PyObject_GenericSetAttr,
  151. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  152. .tp_methods = wpaspy_methods,
  153. .tp_members = wpaspy_members,
  154. .tp_init = (initproc) wpaspy_open,
  155. .tp_dealloc = (destructor) wpaspy_close,
  156. .tp_new = PyType_GenericNew,
  157. };
  158. static PyMethodDef module_methods[] = {
  159. { NULL, NULL, 0, NULL }
  160. };
  161. PyMODINIT_FUNC initwpaspy(void)
  162. {
  163. PyObject *mod;
  164. PyType_Ready(&wpaspy_ctrl);
  165. mod = Py_InitModule("wpaspy", module_methods);
  166. wpaspy_error = PyErr_NewException("wpaspy.error", NULL, NULL);
  167. Py_INCREF(&wpaspy_ctrl);
  168. Py_INCREF(wpaspy_error);
  169. PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl);
  170. PyModule_AddObject(mod, "error", wpaspy_error);
  171. }