From babf43abf301d072192bda1f72a47440c354b072 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Fri, 4 Aug 2017 22:46:45 +0000 Subject: Add the higher layer of libwpactrl --- doc/libwpactrl/index.html | 176 ++++++++++++++++++++++---- package/deps.mak | 13 +- src/include/bcnm/wpactrl.h | 197 ++++++++---------------------- src/libwpactrl/deps-lib/wpactrl | 9 ++ src/libwpactrl/wpactrl_addnetwork.c | 15 +++ src/libwpactrl/wpactrl_associate.c | 34 ++++++ src/libwpactrl/wpactrl_bssid_scan.c | 29 +++++ src/libwpactrl/wpactrl_command.c | 5 +- src/libwpactrl/wpactrl_findnetwork.c | 26 ++++ src/libwpactrl/wpactrl_flags_scan.c | 30 +++++ src/libwpactrl/wpactrl_networks_parse.c | 68 +++++++++++ src/libwpactrl/wpactrl_query.c | 5 +- src/libwpactrl/wpactrl_querysa.c | 4 +- src/libwpactrl/wpactrl_removenetwork.c | 11 ++ src/libwpactrl/wpactrl_scan_parse.c | 59 ++------- src/libwpactrl/wpactrl_selectnetwork.c | 11 ++ src/libwpactrl/wpactrl_setnetworkoption.c | 21 ++++ src/libwpactrl/wpactrl_xchg_init.c | 3 +- 18 files changed, 482 insertions(+), 234 deletions(-) create mode 100644 src/libwpactrl/wpactrl_addnetwork.c create mode 100644 src/libwpactrl/wpactrl_associate.c create mode 100644 src/libwpactrl/wpactrl_bssid_scan.c create mode 100644 src/libwpactrl/wpactrl_findnetwork.c create mode 100644 src/libwpactrl/wpactrl_flags_scan.c create mode 100644 src/libwpactrl/wpactrl_networks_parse.c create mode 100644 src/libwpactrl/wpactrl_removenetwork.c create mode 100644 src/libwpactrl/wpactrl_selectnetwork.c create mode 100644 src/libwpactrl/wpactrl_setnetworkoption.c diff --git a/doc/libwpactrl/index.html b/doc/libwpactrl/index.html index 1115787..72ee538 100644 --- a/doc/libwpactrl/index.html +++ b/doc/libwpactrl/index.html @@ -80,17 +80,15 @@ event loop.

Synchronous functions

- The bulk of libwpactrl functions take two extra arguments at the end, named -deadline and stamp, of type + The bulk of libwpactrl functions takes an extra stamp argument +at the end, of type tain_t. This means -they are synchronous function calls, and the extra arguments are there to ensure +they are synchronous function calls, and the extra argument is there to ensure those calls do not block forever.

-deadline is an absolute date: if the function has not returned when this -date is reached, it will immediately return with a code meaning "failure" and -errno set to ETIMEDOUT. stamp must be first initialized to an +stamp must be first initialized to an accurate enough approximation of the current time, for instance via skalibs' tain_now() function; it will then be automatically updated by the libwpactrl function calls to always contain (an accurate enough approximation @@ -100,9 +98,9 @@ of) the current time.

skalibs can keep track of the timestamp for you, in the global STAMP variable. All libwpactrl -functions taking deadline and stamp arguments also have a -version with a name ending in _g, that only takes a deadline -argument, and assumes the STAMP variable always contains (an accurate +functions taking a stamp argument also have a +version with a name ending in _g, that does not take it and instead +assumes the STAMP variable always contains (an accurate enough approximation of) the current time.

@@ -110,20 +108,26 @@ enough approximation of) the current time. Those synchronous function calls normally return almost instantly: there should be no blocking code path between the function call and its return. Nevertheless, since they involve communication with a complex wpa_supplicant process, -it's impossible to guarantee that they will never block, so the deadline pattern -is there to set a cap on the amount of time they block. A deadline set a few -seconds into the future should be enough. +it's impossible to guarantee that they will never block, so the use of the +stamp argument, plus a timeout given at wpactrl_start time, +ensures there is a cap on the amount of time they block.

Starting and stopping a session

- int wpactrl_start (wpactrl_t *a, char const *path, tain_t const *deadline, tain_t *stamp)
+ int wpactrl_start (wpactrl_t *a, char const *path, unsigned int timeout, tain_t *stamp)
Starts a session with a wpa_supplicant instance listening on a Unix socket -at path. +at path. a is a handle that must be initialized to +WPACTRL_ZERO before the call to wpactrl_start, and that must then +be passed to every wpactrl_* call in the session. The function returns 1 if it succeeds, or 0 (and sets errno) if -it fails. +it fails. The timeout argument is interpreted as milliseconds: +it sets the number of milliseconds for which every subsequent synchronous call +to wpa_supplicant in the current session will be willing to wait. If a call +to wpa_supplicant takes longer than timeout milliseconds, the call +will immediately be aborted.

@@ -134,8 +138,8 @@ Ends the session, freeing all used resources.

Low-level command sending

- ssize_t wpactrl_query (wpactrl_t *a, char const *q, size_t qlen, char *ans, size_t anslen, tain_t const *deadline, tain_t *stamp)
-Sends the query q of size qlen to the connected instance + ssize_t wpactrl_query (wpactrl_t *a, char const *q, char *ans, size_t anslen, tain_t *stamp)
+Sends the query q to the connected instance of wpa_supplicant, and reads its answer into the buffer pointed to by ans. Returns -1 in case of failure, or the number of bytes of the answer in case of success. Returns -1 with errno set to EMSGSIZE if @@ -143,25 +147,26 @@ the answer is bigger than anslen bytes.

- ssize_t wpactrl_querysa (wpactrl_t *a, char const *q, size_t qlen, stralloc *sa, tain_t const *deadline, tain_t *stamp)
-Sends the query q of size qlen to the connected instance + ssize_t wpactrl_querysa (wpactrl_t *a, char const *q, stralloc *sa, tain_t *stamp)
+Sends the query q to the connected instance of wpa_supplicant, and reads its answer into the stralloc pointed to by sa. Returns 1 if it succeeds and 0 if it fails.

- wparesponse_t wpactrl_command (wpactrl_t *a, char const *q, size_t qlen, tain_t const *deadline, tain_t *stamp)
-Sends the command q of size qlen to the connected instance + wparesponse_t wpactrl_command (wpactrl_t *a, char const *q, tain_t *stamp)
+Sends the command q to the connected instance of wpa_supplicant, and returns its answer under the form of a wparesponse_t, which is an enumeration defined in the bcnm/wpactrl.h header. This function is meant to be used with commands returning a well-known value, such as RECONFIGURE (returning OK or FAIL) or PING -(returning PONG). +(returning PONG). The wparesponse_t enumeration +type lists all the possible values for the function's return code.

-

Reading from the attached connection

+

Reading from the attached (asynchronous) connection

int wpactrl_update (wpactrl_t *a)
@@ -183,7 +188,7 @@ returns NULL.

- void wpactrl_nextmsg (wpactrl_t *a)
+ void wpactrl_ackmsg (wpactrl_t *a)
Acknowledges reading of one unsolicited message from wpa_supplicant. The next invocation of wpactrl_msg() will point to the next one. @@ -207,7 +212,7 @@ Removes prefix from the whitelist.

- void wpactrl_filter_activate (wpactrl_t *a) + void wpactrl_filter_activate (wpactrl_t *a)
Activates the message filter. Unsolicited messages from wpa_supplicant will be discarded unless they are explicitly whitelisted by a call to wpactrl_filter_add(). This @@ -215,13 +220,130 @@ is the default.

- void wpactrl_filter_deactivate (wpactrl_t *a) + void wpactrl_filter_deactivate (wpactrl_t *a)
Dectivates the message filter. All the unsolicited messages from wpa_supplicant will be stored and made available to the application.

-

Higher-level commands

+

+ int wpactrl_filter_match (wpactrl_t const *a, char const *s, size_t len)
+Returns 1 if the string s of size len matches one of the +registered filters, and 0 otherwise. +

+ + +

Helper functions for parsing answers from wpa_supplicant

+ +

+ size_t wpactrl_bssid_scan (char const *s, char *bssid)
+Parses a BSSID of the form a:b:c:d:e:f in string s +and writes it as an array of 6 bytes pointed to by bssid. +The string "any" is specifically recognized and yields a bssid +of 6 zero bytes. The function returns the number of characters eaten +in s, or 0 if it fails to recognize a BSSID. +

+ +

+ size_t wpactrl_flags_scan (char const *s, stralloc *sa)
+Parses a wpa_supplicant "flags" field in the string s +and appends them to the +stralloc +pointed to by sa. The flags are written without their +surrounding square brackets, and every flag is terminated by a null +byte. +

+ +

+ unsigned int wpactrl_env_parse (char *s, size_t len)
+Replaces newlines with null bytes in the string s of length len. +Returns the number of replaced newlines. +

+ +

+ int wpactrl_scan_parse (char const *s, size_t len, genalloc *ga, stralloc *storage)
+Parses the string s of length len, expecting it to be +wpa_supplicant's response to a SCAN_RESULTS command. The result is a series of +wpactrl_scanres_t structures, appended to the +genalloc +pointed to by ga, and variable length data is appended to the +stralloc +pointed to by storage. + The ssid_start and flags_start fields of a +wpactrl_scanres_t are indices pointing into the storage→s +string. +

+ +

+ int wpactrl_networks_parse (char const *s, size_t len, genalloc *ga, stralloc *storage)
+Parses the string s of length len, expecting it to be +wpa_supplicant's response to a LIST_NETWORKS command. The result is a series of +wpactrl_networks_t structures, appended to the +genalloc +pointed to by ga, and variable length data is appended to the +stralloc +pointed to by storage. + The ssid_start and flags_start fields of a +wpactrl_networks_t are indices pointing into the storage→s +string. +

+ +

High-level functions for common calls to wpa_supplicant

+ +

+ int wpactrl_addnetwork (wpactrl_t *a, uint32_t *id, tain_t *stamp)
+Tells wpa_supplicant to create a new network. If it fails, returns 0. If it +succeeds, stores the new network id in *id and returns 1. +

+ +

+ wparesponse_t wpactrl_removenetwork (wpactrl_t *a, uint32_t id, tain_t *stamp)
+Tells wpa_supplicant to remove the network with id id. Returns the +response code of wpa_supplicant: WPA_OK on success, WPA_FAIL or something +else on failure. +

+ +

+ int wpactrl_findnetwork (wpactrl_t *a, char const *ssid, uint32_t *id, tain_t *stamp)
+Finds the network id (as seen by wpa_supplicant) of the network with ssid ssid. +Stores it into *id if found, and returns 1. Returns 0 if not found; +returns -1 (and sets errno) if an error occurs. +

+ +

+ wparesponse_t wpactrl_setnetworkoption (wpactrl_t *a, uint32_t id, char const *var, char const *val, tain_t *stamp)
+Sets parameter var to value val for network id. +Returns the response code of wpa_supplicant, most likely WPA_OK or WPA_FAIL. +

+ +

+ wparesponse_t wpactrl_selectnetwork (wpactrl_t *a, uint32_t id, tain_t *stamp)
+Selects network id to associate with. +Returns the response code of wpa_supplicant, most likely WPA_OK or WPA_FAIL. +

+ +

+ int wpactrl_associate (wpactrl_t *, char const *ssid, char const *psk, tain_t *stamp)
+Tells wpa_supplicant to associate with the wifi network having the ssid ssid, +creating it if it's not already known by wpa_supplicant. If psk is NULL, +the network will be assumed open and authentication will use a NONE protocol. +If psk is not NULL, the network authentication will be assumed using +WPA-PSK or WPA2-PSK, and psk will be sent as pre-shared key. +The function returns 1 on success, or 0 if something went wrong. +

+ +

Medium-level functions to use with an asynchronous event loop

+ +

+ The following functions can be used when performing calls to wpa_supplicant +such as SCAN that answer with an asynchronous message on the "attached" +interface. +

+ +

+ int wpactrl_xchg_init (wpactrl_xchg_t *dt, wpactrl_xchgitem_t const *tab, unsigned int n, tain_t const *limit, void *aux)
+Initializes. +

diff --git a/package/deps.mak b/package/deps.mak index 2413c0e..79c1b29 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -4,6 +4,9 @@ src/libwpactrl/wpactrl-internal.h: src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_ackmsg.o src/libwpactrl/wpactrl_ackmsg.lo: src/libwpactrl/wpactrl_ackmsg.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_addnetwork.o src/libwpactrl/wpactrl_addnetwork.lo: src/libwpactrl/wpactrl_addnetwork.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_associate.o src/libwpactrl/wpactrl_associate.lo: src/libwpactrl/wpactrl_associate.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_bssid_scan.o src/libwpactrl/wpactrl_bssid_scan.lo: src/libwpactrl/wpactrl_bssid_scan.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_command.o src/libwpactrl/wpactrl_command.lo: src/libwpactrl/wpactrl_command.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_end.o src/libwpactrl/wpactrl_end.lo: src/libwpactrl/wpactrl_end.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_env_parse.o src/libwpactrl/wpactrl_env_parse.lo: src/libwpactrl/wpactrl_env_parse.c src/include/bcnm/wpactrl.h @@ -13,10 +16,16 @@ src/libwpactrl/wpactrl_filter_add.o src/libwpactrl/wpactrl_filter_add.lo: src/li src/libwpactrl/wpactrl_filter_exact_search.o src/libwpactrl/wpactrl_filter_exact_search.lo: src/libwpactrl/wpactrl_filter_exact_search.c src/libwpactrl/wpactrl-internal.h src/libwpactrl/wpactrl_filter_match.o src/libwpactrl/wpactrl_filter_match.lo: src/libwpactrl/wpactrl_filter_match.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_filter_remove.o src/libwpactrl/wpactrl_filter_remove.lo: src/libwpactrl/wpactrl_filter_remove.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_findnetwork.o src/libwpactrl/wpactrl_findnetwork.lo: src/libwpactrl/wpactrl_findnetwork.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_flags_scan.o src/libwpactrl/wpactrl_flags_scan.lo: src/libwpactrl/wpactrl_flags_scan.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_msg.o src/libwpactrl/wpactrl_msg.lo: src/libwpactrl/wpactrl_msg.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_networks_parse.o src/libwpactrl/wpactrl_networks_parse.lo: src/libwpactrl/wpactrl_networks_parse.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_query.o src/libwpactrl/wpactrl_query.lo: src/libwpactrl/wpactrl_query.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h src/libwpactrl/wpactrl_querysa.o src/libwpactrl/wpactrl_querysa.lo: src/libwpactrl/wpactrl_querysa.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_removenetwork.o src/libwpactrl/wpactrl_removenetwork.lo: src/libwpactrl/wpactrl_removenetwork.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_scan_parse.o src/libwpactrl/wpactrl_scan_parse.lo: src/libwpactrl/wpactrl_scan_parse.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_selectnetwork.o src/libwpactrl/wpactrl_selectnetwork.lo: src/libwpactrl/wpactrl_selectnetwork.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_setnetworkoption.o src/libwpactrl/wpactrl_setnetworkoption.lo: src/libwpactrl/wpactrl_setnetworkoption.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_start.o src/libwpactrl/wpactrl_start.lo: src/libwpactrl/wpactrl_start.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h src/libwpactrl/wpactrl_update.o src/libwpactrl/wpactrl_update.lo: src/libwpactrl/wpactrl_update.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h src/libwpactrl/wpactrl_xchg_computedeadline.o src/libwpactrl/wpactrl_xchg_computedeadline.lo: src/libwpactrl/wpactrl_xchg_computedeadline.c src/include/bcnm/wpactrl.h @@ -28,6 +37,6 @@ src/libwpactrl/wpactrl_xchg_timeout.o src/libwpactrl/wpactrl_xchg_timeout.lo: sr src/libwpactrl/wpactrl_xchg_zero.o src/libwpactrl/wpactrl_xchg_zero.lo: src/libwpactrl/wpactrl_xchg_zero.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl_zero.o src/libwpactrl/wpactrl_zero.lo: src/libwpactrl/wpactrl_zero.c src/include/bcnm/wpactrl.h -libwpactrl.a.xyzzy: src/libwpactrl/wpactrl_ackmsg.o src/libwpactrl/wpactrl_command.o src/libwpactrl/wpactrl_end.o src/libwpactrl/wpactrl_env_parse.o src/libwpactrl/wpactrl_fd_recv.o src/libwpactrl/wpactrl_fd_timed_recv.o src/libwpactrl/wpactrl_filter_add.o src/libwpactrl/wpactrl_filter_exact_search.o src/libwpactrl/wpactrl_filter_match.o src/libwpactrl/wpactrl_filter_remove.o src/libwpactrl/wpactrl_msg.o src/libwpactrl/wpactrl_query.o src/libwpactrl/wpactrl_querysa.o src/libwpactrl/wpactrl_scan_parse.o src/libwpactrl/wpactrl_start.o src/libwpactrl/wpactrl_update.o src/libwpactrl/wpactrl_xchg_computedeadline.o src/libwpactrl/wpactrl_xchg_event.o src/libwpactrl/wpactrl_xchg_free.o src/libwpactrl/wpactrl_xchg_init.o src/libwpactrl/wpactrl_xchg_start.o src/libwpactrl/wpactrl_xchg_timeout.o src/libwpactrl/wpactrl_xchg_zero.o src/libwpactrl/wpactrl_zero.o +libwpactrl.a.xyzzy: src/libwpactrl/wpactrl_ackmsg.o src/libwpactrl/wpactrl_addnetwork.o src/libwpactrl/wpactrl_associate.o src/libwpactrl/wpactrl_bssid_scan.o src/libwpactrl/wpactrl_command.o src/libwpactrl/wpactrl_end.o src/libwpactrl/wpactrl_env_parse.o src/libwpactrl/wpactrl_fd_recv.o src/libwpactrl/wpactrl_fd_timed_recv.o src/libwpactrl/wpactrl_filter_add.o src/libwpactrl/wpactrl_filter_exact_search.o src/libwpactrl/wpactrl_filter_match.o src/libwpactrl/wpactrl_filter_remove.o src/libwpactrl/wpactrl_findnetwork.o src/libwpactrl/wpactrl_flags_scan.o src/libwpactrl/wpactrl_msg.o src/libwpactrl/wpactrl_networks_parse.o src/libwpactrl/wpactrl_query.o src/libwpactrl/wpactrl_querysa.o src/libwpactrl/wpactrl_removenetwork.o src/libwpactrl/wpactrl_scan_parse.o src/libwpactrl/wpactrl_selectnetwork.o src/libwpactrl/wpactrl_setnetworkoption.o src/libwpactrl/wpactrl_start.o src/libwpactrl/wpactrl_update.o src/libwpactrl/wpactrl_xchg_computedeadline.o src/libwpactrl/wpactrl_xchg_event.o src/libwpactrl/wpactrl_xchg_free.o src/libwpactrl/wpactrl_xchg_init.o src/libwpactrl/wpactrl_xchg_start.o src/libwpactrl/wpactrl_xchg_timeout.o src/libwpactrl/wpactrl_xchg_zero.o src/libwpactrl/wpactrl_zero.o libwpactrl.so.xyzzy: EXTRA_LIBS := -libwpactrl.so.xyzzy: src/libwpactrl/wpactrl_ackmsg.lo src/libwpactrl/wpactrl_command.lo src/libwpactrl/wpactrl_end.lo src/libwpactrl/wpactrl_env_parse.lo src/libwpactrl/wpactrl_fd_recv.lo src/libwpactrl/wpactrl_fd_timed_recv.lo src/libwpactrl/wpactrl_filter_add.lo src/libwpactrl/wpactrl_filter_exact_search.lo src/libwpactrl/wpactrl_filter_match.lo src/libwpactrl/wpactrl_filter_remove.lo src/libwpactrl/wpactrl_msg.lo src/libwpactrl/wpactrl_query.lo src/libwpactrl/wpactrl_querysa.lo src/libwpactrl/wpactrl_scan_parse.lo src/libwpactrl/wpactrl_start.lo src/libwpactrl/wpactrl_update.lo src/libwpactrl/wpactrl_xchg_computedeadline.lo src/libwpactrl/wpactrl_xchg_event.lo src/libwpactrl/wpactrl_xchg_free.lo src/libwpactrl/wpactrl_xchg_init.lo src/libwpactrl/wpactrl_xchg_start.lo src/libwpactrl/wpactrl_xchg_timeout.lo src/libwpactrl/wpactrl_xchg_zero.lo src/libwpactrl/wpactrl_zero.lo +libwpactrl.so.xyzzy: src/libwpactrl/wpactrl_ackmsg.lo src/libwpactrl/wpactrl_addnetwork.lo src/libwpactrl/wpactrl_associate.lo src/libwpactrl/wpactrl_bssid_scan.lo src/libwpactrl/wpactrl_command.lo src/libwpactrl/wpactrl_end.lo src/libwpactrl/wpactrl_env_parse.lo src/libwpactrl/wpactrl_fd_recv.lo src/libwpactrl/wpactrl_fd_timed_recv.lo src/libwpactrl/wpactrl_filter_add.lo src/libwpactrl/wpactrl_filter_exact_search.lo src/libwpactrl/wpactrl_filter_match.lo src/libwpactrl/wpactrl_filter_remove.lo src/libwpactrl/wpactrl_findnetwork.lo src/libwpactrl/wpactrl_flags_scan.lo src/libwpactrl/wpactrl_msg.lo src/libwpactrl/wpactrl_networks_parse.lo src/libwpactrl/wpactrl_query.lo src/libwpactrl/wpactrl_querysa.lo src/libwpactrl/wpactrl_removenetwork.lo src/libwpactrl/wpactrl_scan_parse.lo src/libwpactrl/wpactrl_selectnetwork.lo src/libwpactrl/wpactrl_setnetworkoption.lo src/libwpactrl/wpactrl_start.lo src/libwpactrl/wpactrl_update.lo src/libwpactrl/wpactrl_xchg_computedeadline.lo src/libwpactrl/wpactrl_xchg_event.lo src/libwpactrl/wpactrl_xchg_free.lo src/libwpactrl/wpactrl_xchg_init.lo src/libwpactrl/wpactrl_xchg_start.lo src/libwpactrl/wpactrl_xchg_timeout.lo src/libwpactrl/wpactrl_xchg_zero.lo src/libwpactrl/wpactrl_zero.lo diff --git a/src/include/bcnm/wpactrl.h b/src/include/bcnm/wpactrl.h index 1c5610c..874a14f 100644 --- a/src/include/bcnm/wpactrl.h +++ b/src/include/bcnm/wpactrl.h @@ -54,12 +54,12 @@ extern int wpactrl_start (wpactrl_t *, char const *, unsigned int, tain_t *) ; #define wpactrl_start_g(a, path, timeout) wpactrl_start(a, path, (timeout), &STAMP) extern void wpactrl_end (wpactrl_t *) ; -extern wparesponse_t wpactrl_command (wpactrl_t *, char const *, size_t, tain_t *) ; -#define wpactrl_command_g(a, q, qlen) wpactrl_command(a, q, (qlen), &STAMP) -extern ssize_t wpactrl_query (wpactrl_t *, char const *, size_t, char *, size_t, tain_t *) ; -#define wpactrl_query_g(a, q, qlen, ans, ansmax) wpactrl_query(a, q, qlen, ans, (ansmax), &STAMP) -extern int wpactrl_querysa (wpactrl_t *, char const *, size_t, stralloc *, tain_t *) ; -#define wpactrl_querysa_g(a, q, qlen, sa) wpactrl_querysa(a, q, qlen, (sa), &STAMP) +extern wparesponse_t wpactrl_command (wpactrl_t *, char const *, tain_t *) ; +#define wpactrl_command_g(a, q) wpactrl_command(a, (q), &STAMP) +extern ssize_t wpactrl_query (wpactrl_t *, char const *, char *, size_t, tain_t *) ; +#define wpactrl_query_g(a, q, ans, ansmax) wpactrl_query(a, q, ans, (ansmax), &STAMP) +extern int wpactrl_querysa (wpactrl_t *, char const *, stralloc *, tain_t *) ; +#define wpactrl_querysa_g(a, q, sa) wpactrl_querysa(a, q, (sa), &STAMP) extern int wpactrl_filter_add (wpactrl_t *, char const *) ; extern void wpactrl_filter_remove (wpactrl_t *, char const *) ; @@ -75,12 +75,17 @@ extern void wpactrl_ackmsg (wpactrl_t *) ; /* Helper functions for parsing answers from wpa_supplicant */ +extern size_t wpactrl_bssid_scan (char const *, char *) ; +extern size_t wpactrl_flags_scan (char const *, stralloc *) ; + +extern unsigned int wpactrl_env_parse (char *, size_t) ; + typedef struct wpactrl_scanres_s wpactrl_scanres_t, *wpactrl_scanres_t_ref ; struct wpactrl_scanres_s { char bssid[6] ; - uint16_t frequency ; - uint16_t signal_level ; + uint32_t frequency ; + uint32_t signal_level ; size_t flags_start ; size_t flags_len ; size_t ssid_start ; @@ -89,10 +94,22 @@ struct wpactrl_scanres_s #define WPACTRL_SCANRES_ZERO { .bssid = "\0\0\0\0\0", .frequency = 0, .signal_level = 0, .flags_start = 0, .flags_len = 0, .ssid_start = 0, .ssid_len = 0 } extern int wpactrl_scan_parse (char const *, size_t, genalloc * /* wpactrl_scanres_t */, stralloc *) ; -extern unsigned int wpactrl_env_parse (char *, size_t) ; + +typedef struct wpactrl_networks_s wpactrl_networks_t, *wpactrl_networks_t_ref ; +struct wpactrl_networks_s +{ + uint32_t id ; + size_t ssid_start ; + size_t ssid_len ; + char bssid[6] ; + size_t flags_start ; + size_t flags_len ; +} ; + +extern int wpactrl_networks_parse (char const *, size_t, genalloc * /* wpactrl_networks_t */, stralloc *) ; - /* Higher-level functions for easy iopause */ + /* Functions for easy iopause around async commands */ typedef int wpactrl_xchg_func_t (wpactrl_t *, char const *, size_t, void *, tain_t *) ; typedef wpactrl_xchg_func_t *wpactrl_xchg_func_t_ref ; @@ -120,7 +137,7 @@ struct wpactrl_xchg_s extern wpactrl_xchg_t const wpactrl_xchg_zero ; extern void wpactrl_xchg_free (wpactrl_xchg_t *) ; -extern int wpactrl_xchg_init (wpactrl_xchg_t *, wpactrl_xchgitem_t const *, unsigned int, tain_t const *, void *) ; +extern void wpactrl_xchg_init (wpactrl_xchg_t *, wpactrl_xchgitem_t const *, unsigned int, tain_t const *, void *) ; extern int wpactrl_xchg_start (wpactrl_t *, wpactrl_xchg_t *) ; extern void wpactrl_xchg_computedeadline (wpactrl_xchg_t const *, tain_t *) ; @@ -130,143 +147,25 @@ extern int wpactrl_xchg_event (wpactrl_t *, wpactrl_xchg_t *, tain_t *) ; #define wpactrl_xchg_event_g(a, dt) wpactrl_xchg_event(a, (dt), &STAMP) - /* - The following is taken from wpa_supplicant's wpa_ctrl.h. - */ - -#define WPA_CTRL_REQ "CTRL-REQ-" -#define WPA_CTRL_RSP "CTRL-RSP-" -#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " -#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " -#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT " -#define WPA_EVENT_AUTH_REJECT "CTRL-EVENT-AUTH-REJECT " -#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " -#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " -#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " -#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " -#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " -#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " -#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " -#define WPA_EVENT_EAP_PEER_ALT "CTRL-EVENT-EAP-PEER-ALT " -#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " -#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS " -#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " -#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " -#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED " -#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED " -#define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED " -#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " -#define WPA_EVENT_SCAN_FAILED "CTRL-EVENT-SCAN-FAILED " -#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE " -#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " -#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " -#define WPA_EVENT_NETWORK_NOT_FOUND "CTRL-EVENT-NETWORK-NOT-FOUND " -#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE " -#define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS " -#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE " -#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH " -#define WPA_EVENT_SUBNET_STATUS_UPDATE "CTRL-EVENT-SUBNET-STATUS-UPDATE " -#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED " -#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " -#define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ " -#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " -#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " -#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH " -#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " -#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " -#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " -#define WPS_EVENT_M2D "WPS-M2D " -#define WPS_EVENT_FAIL "WPS-FAIL " -#define WPS_EVENT_SUCCESS "WPS-SUCCESS " -#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " -#define WPS_EVENT_ACTIVE "WPS-PBC-ACTIVE " -#define WPS_EVENT_DISABLE "WPS-PBC-DISABLE " -#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " -#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK " -#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " -#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " -#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " -#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " -#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS " -#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG " -#define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS " -#define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE " -#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING " -#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE " -#define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED " -#define DPP_EVENT_CONF_SENT "DPP-CONF-SENT " -#define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED " -#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID " -#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR " -#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " -#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " -#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR " -#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID " -#define MESH_GROUP_STARTED "MESH-GROUP-STARTED " -#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED " -#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED " -#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED " -#define MESH_SAE_AUTH_FAILURE "MESH-SAE-AUTH-FAILURE " -#define MESH_SAE_AUTH_BLOCKED "MESH-SAE-AUTH-BLOCKED " -#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED " -#define WMM_AC_EVENT_TSPEC_REMOVED "TSPEC-REMOVED " -#define WMM_AC_EVENT_TSPEC_REQ_FAILED "TSPEC-REQ-FAILED " -#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND " -#define P2P_EVENT_DEVICE_LOST "P2P-DEVICE-LOST " -#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST " -#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS " -#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE " -#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS " -#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE " -#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED " -#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED " -#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE " -#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE " -#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN " -#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN " -#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ " -#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP " -#define P2P_EVENT_PROV_DISC_FAILURE "P2P-PROV-DISC-FAILURE" -#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ " -#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP " -#define P2P_EVENT_SERV_ASP_RESP "P2P-SERV-ASP-RESP " -#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED " -#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT " -#define P2P_EVENT_INVITATION_ACCEPTED "P2P-INVITATION-ACCEPTED " -#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED " -#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id=" -#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE " -#define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO " -#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT " -#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT " -#define P2P_EVENT_FALLBACK_TO_GO_NEG "P2P-FALLBACK-TO-GO-NEG " -#define P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED "P2P-FALLBACK-TO-GO-NEG-ENABLED " -#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT " -#define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP " -#define P2P_EVENT_P2PS_PROVISION_START "P2PS-PROV-START " -#define P2P_EVENT_P2PS_PROVISION_DONE "P2PS-PROV-DONE " -#define INTERWORKING_AP "INTERWORKING-AP " -#define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED " -#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH " -#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED " -#define INTERWORKING_SELECTED "INTERWORKING-SELECTED " -#define CRED_ADDED "CRED-ADDED " -#define CRED_MODIFIED "CRED-MODIFIED " -#define CRED_REMOVED "CRED-REMOVED " -#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO " -#define GAS_QUERY_START "GAS-QUERY-START " -#define GAS_QUERY_DONE "GAS-QUERY-DONE " -#define ANQP_QUERY_DONE "ANQP-QUERY-DONE " -#define RX_ANQP "RX-ANQP " -#define RX_HS20_ANQP "RX-HS20-ANQP " -#define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON " -#define RX_HS20_ICON "RX-HS20-ICON " -#define RX_MBO_ANQP "RX-MBO-ANQP " -#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION " -#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE " -#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START " -#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT " -#define RRM_EVENT_NEIGHBOR_REP_RXED "RRM-NEIGHBOR-REP-RECEIVED " -#define RRM_EVENT_NEIGHBOR_REP_FAILED "RRM-NEIGHBOR-REP-REQUEST-FAILED " + /* High-level functions for common calls to wpa_supplicant */ + +extern int wpactrl_addnetwork (wpactrl_t *, uint32_t *, tain_t *) ; +#define wpactrl_addnetwork_g(a, idp) wpactrl_addnetwork(a, (idp), &STAMP) + +extern wparesponse_t wpactrl_removenetwork (wpactrl_t *, uint32_t, tain_t *) ; +#define wpactrl_removenetwork_g(a, id) wpactrl_removenetwork(a, (id), &STAMP) + +extern int wpactrl_findnetwork (wpactrl_t *, char const *, uint32_t *, tain_t *) ; +#define wpactrl_findnetwork_g(a, ssid, idp) wpactrl(a, ssid, (idp), &STAMP) + +extern wparesponse_t wpactrl_setnetworkoption (wpactrl_t *, uint32_t, char const *, char const *, tain_t *) ; +#define wpactrl_setnetworkoption_g(a, id, var, val) wpactrl_setnetworkoption(a, id, var, (val), &STAMP) + +extern wparesponse_t wpactrl_selectnetwork (wpactrl_t *, uint32_t, tain_t *) ; +#define wpactrl_selectnetwork_g(a, id) wpactrl_selectnetwork(a, (id), &STAMP) + +extern int wpactrl_associate (wpactrl_t *, char const *, char const *, tain_t *) ; +#define wpactrl_associate_g(a, ssid, psk) wpactrl_associate(a, ssid, (psk), &STAMP) + #endif diff --git a/src/libwpactrl/deps-lib/wpactrl b/src/libwpactrl/deps-lib/wpactrl index 1943682..74d579a 100644 --- a/src/libwpactrl/deps-lib/wpactrl +++ b/src/libwpactrl/deps-lib/wpactrl @@ -1,4 +1,7 @@ wpactrl_ackmsg.o +wpactrl_addnetwork.o +wpactrl_associate.o +wpactrl_bssid_scan.o wpactrl_command.o wpactrl_end.o wpactrl_env_parse.o @@ -8,10 +11,16 @@ wpactrl_filter_add.o wpactrl_filter_exact_search.o wpactrl_filter_match.o wpactrl_filter_remove.o +wpactrl_findnetwork.o +wpactrl_flags_scan.o wpactrl_msg.o +wpactrl_networks_parse.o wpactrl_query.o wpactrl_querysa.o +wpactrl_removenetwork.o wpactrl_scan_parse.o +wpactrl_selectnetwork.o +wpactrl_setnetworkoption.o wpactrl_start.o wpactrl_update.o wpactrl_xchg_computedeadline.o diff --git a/src/libwpactrl/wpactrl_addnetwork.c b/src/libwpactrl/wpactrl_addnetwork.c new file mode 100644 index 0000000..65e5963 --- /dev/null +++ b/src/libwpactrl/wpactrl_addnetwork.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +int wpactrl_addnetwork (wpactrl_t *a, uint32_t *id, tain_t *stamp) +{ + char buf[UINT32_FMT] ; + if (wpactrl_query(a, "ADD_NETWORK", buf, UINT32_FMT, stamp) < 0) return 0 ; + if (uint32_scan(buf, id)) return 1 ; + return (errno = EPROTO, 0) ; +} diff --git a/src/libwpactrl/wpactrl_associate.c b/src/libwpactrl/wpactrl_associate.c new file mode 100644 index 0000000..59900d6 --- /dev/null +++ b/src/libwpactrl/wpactrl_associate.c @@ -0,0 +1,34 @@ +/* ISC license. */ + +#include +#include +#include + +int wpactrl_associate (wpactrl_t *a, char const *ssid, char const *psk, tain_t *stamp) +{ + uint32_t id ; + int r = wpactrl_findnetwork(a, ssid, &id, stamp) ; + if (r < 0) return 0 ; + if (!r) + { + if (!wpactrl_addnetwork(a, &id, stamp)) goto err ; + } + + if (psk) + { + if (wpactrl_setnetworkoption(a, id, "key_mgmt", "WPA-PSK WPA-PSK-SHA256", stamp) != WPA_OK + || wpactrl_setnetworkoption(a, id, "mem_only_psk", "1", stamp) != WPA_OK + || wpactrl_setnetworkoption(a, id, "psk", psk, stamp) != WPA_OK) goto err ; + } + else + { + if (wpactrl_setnetworkoption(a, id, "key_mgmt", "NONE", stamp) != WPA_OK) + goto err ; + } + + if (wpactrl_selectnetwork(a, id, stamp) != WPA_OK) goto err ; + return 1 ; + + err: + return (errno = EIO, 0) ; +} diff --git a/src/libwpactrl/wpactrl_bssid_scan.c b/src/libwpactrl/wpactrl_bssid_scan.c new file mode 100644 index 0000000..ad4196c --- /dev/null +++ b/src/libwpactrl/wpactrl_bssid_scan.c @@ -0,0 +1,29 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +size_t wpactrl_bssid_scan (char const *s, char *bssid) +{ + unsigned int i = 0 ; + if (!strncmp(s, "any", 3)) + { + memset(bssid, 0, 6) ; + return 3 ; + } + for (; i < 5 ; i++) + { + if (!ucharn_scan(s, bssid + i, 1)) goto eproto ; + if (s[2] != ':') goto eproto ; + s += 3 ; + } + if (!ucharn_scan(s, bssid + 5, 1)) goto eproto ; + return 17 ; + + eproto: + return (errno = EPROTO, 0) ; +} + diff --git a/src/libwpactrl/wpactrl_command.c b/src/libwpactrl/wpactrl_command.c index 34e31c2..f7912ab 100644 --- a/src/libwpactrl/wpactrl_command.c +++ b/src/libwpactrl/wpactrl_command.c @@ -1,6 +1,5 @@ /* ISC license. */ -#include #include #include @@ -12,7 +11,7 @@ struct wparesponse_map_s wparesponse_t r ; } ; -wparesponse_t wpactrl_command (wpactrl_t *a, char const *s, size_t len, tain_t *stamp) +wparesponse_t wpactrl_command (wpactrl_t *a, char const *s, tain_t *stamp) { static struct wparesponse_map_s const wparesponses[] = { @@ -34,7 +33,7 @@ wparesponse_t wpactrl_command (wpactrl_t *a, char const *s, size_t len, tain_t * { 0, WPA_UNKNOWNRESPONSE } } ; char buf[WPARESPONSE_MAXLEN] ; - ssize_t r = wpactrl_query(a, s, len, buf, WPARESPONSE_MAXLEN, stamp) ; + ssize_t r = wpactrl_query(a, s, buf, WPARESPONSE_MAXLEN, stamp) ; if (r < 0) return WPA_ERROR ; if (!r) return (errno = EPIPE, WPA_ERROR) ; { diff --git a/src/libwpactrl/wpactrl_findnetwork.c b/src/libwpactrl/wpactrl_findnetwork.c new file mode 100644 index 0000000..e5851d0 --- /dev/null +++ b/src/libwpactrl/wpactrl_findnetwork.c @@ -0,0 +1,26 @@ +/* ISC license. */ + +#include +#include +#include +#include "wpactrl-internal.h" + +int wpactrl_findnetwork (wpactrl_t *a, char const *ssid, uint32_t *id, tain_t *stamp) +{ + char buf[WPACTRL_PACKET_MAX] ; + stralloc sa = STRALLOC_ZERO ; + genalloc ga = GENALLOC_ZERO ; /* wpactrl_networks_t */ + size_t i = 0 ; + wpactrl_networks_t *p ; + size_t n ; + ssize_t r = wpactrl_query(a, "LIST_NETWORKS", buf, WPACTRL_PACKET_MAX, stamp) ; + if (r < 0) return -1 ; + if (!wpactrl_networks_parse(buf, r, &ga, &sa)) return -1 ; + n = genalloc_len(wpactrl_networks_t, &ga) ; + p = genalloc_s(wpactrl_networks_t, &ga) ; + for (; i < n ; i++) if (!strcmp(ssid, sa.s + p[i].ssid_start)) break ; + if (i < n) *id = p[i].id ; + genalloc_free(wpactrl_networks_t, &ga) ; + stralloc_free(&sa) ; + return i < n ; +} diff --git a/src/libwpactrl/wpactrl_flags_scan.c b/src/libwpactrl/wpactrl_flags_scan.c new file mode 100644 index 0000000..e8eecf5 --- /dev/null +++ b/src/libwpactrl/wpactrl_flags_scan.c @@ -0,0 +1,30 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +size_t wpactrl_flags_scan (char const *t, stralloc *sa) +{ + size_t sabase = sa->len ; + int wasnull = !sa->s ; + char const *s = t ; + while (*s == '[') + { + size_t pos ; + pos = str_chr(s, ']') ; + if (!s[pos]) goto eproto ; + if (!stralloc_catb(sa, s, pos) || !stralloc_0(sa)) goto err ; + s += pos + 1 ; + } + return s - t ; + + eproto: + errno = EPROTO ; + err: + if (wasnull) stralloc_free(sa) ; + else sa->len = sabase ; + return 0 ; +} diff --git a/src/libwpactrl/wpactrl_networks_parse.c b/src/libwpactrl/wpactrl_networks_parse.c new file mode 100644 index 0000000..444941a --- /dev/null +++ b/src/libwpactrl/wpactrl_networks_parse.c @@ -0,0 +1,68 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int wpactrl_networks_parse_one (char const *s, size_t len, wpactrl_networks_t *thing, stralloc *sa) +{ + wpactrl_networks_t sr ; + size_t pos = byte_chr(s, len, '\t') ; + if (pos >= len) goto eproto ; + if (uint32_scan(s, &sr.id) != pos) goto eproto ; + s += pos + 1 ; len -= pos + 1 ; + + pos = byte_rchr(s, len, '\t') ; + if (!pos || pos >= len) goto eproto ; + sr.flags_start = sa->len ; + if (wpactrl_flags_scan(s + pos + 1, sa) != pos) goto eproto ; + sr.flags_len = sa->len - sr.flags_start ; + len = pos ; + + pos = byte_rchr(s, len - 1, '\t') ; + if (!pos || pos >= len - 1) goto eproto ; + if (wpactrl_bssid_scan(s + pos + 1, sr.bssid) != len - 1) goto eproto ; + len = pos ; + + sr.ssid_start = sa->len ; + sr.ssid_len = len - 1 ; + if (!stralloc_catb(sa, s, len - 1) || !stralloc_0(sa)) return 0 ; + *thing = sr ; + return 1 ; + + eproto: + return (errno = EPROTO, 0) ; +} + +int wpactrl_networks_parse (char const *s, size_t len, genalloc *ga, stralloc *sa) +{ + int sawasnull = !sa->s ; + int gawasnull = !genalloc_s(wpactrl_networks_t, ga) ; + size_t sabase = sa->len ; + size_t gabase = genalloc_len(wpactrl_networks_t, ga) ; + size_t start = byte_chr(s, len, '\n') ; + if (start++ >= len) return (errno = EPROTO, 0) ; + while (start < len) + { + size_t pos = byte_chr(s + start, len - start, '\n') ; + wpactrl_networks_t thing ; + if (!wpactrl_networks_parse_one(s + start, pos, &thing, sa)) goto err ; + if (!genalloc_append(wpactrl_networks_t, ga, &thing)) goto err ; + start += pos + 1 ; + } + return 1 ; + + err: + if (gawasnull) genalloc_free(wpactrl_networks_t, ga) ; + else genalloc_setlen(wpactrl_networks_t, ga, gabase) ; + if (sawasnull) stralloc_free(sa) ; + else sa->len = sabase ; + return 0 ; +} diff --git a/src/libwpactrl/wpactrl_query.c b/src/libwpactrl/wpactrl_query.c index b03899f..b8b42df 100644 --- a/src/libwpactrl/wpactrl_query.c +++ b/src/libwpactrl/wpactrl_query.c @@ -1,13 +1,14 @@ /* ISC license. */ +#include #include #include #include "wpactrl-internal.h" -ssize_t wpactrl_query (wpactrl_t *a, char const *q, size_t qlen, char *ans, size_t ansmax, tain_t *stamp) +ssize_t wpactrl_query (wpactrl_t *a, char const *q, char *ans, size_t ansmax, tain_t *stamp) { tain_t deadline ; tain_add(&deadline, stamp, &a->tto) ; - if (!ipc_timed_send(a->fds, q, qlen, &deadline, stamp)) return WPA_ERROR ; + if (!ipc_timed_send(a->fds, q, strlen(q), &deadline, stamp)) return WPA_ERROR ; return wpactrl_fd_timed_recv(a->fds, ans, ansmax, &deadline, stamp) ; } diff --git a/src/libwpactrl/wpactrl_querysa.c b/src/libwpactrl/wpactrl_querysa.c index 887941f..8afaa92 100644 --- a/src/libwpactrl/wpactrl_querysa.c +++ b/src/libwpactrl/wpactrl_querysa.c @@ -5,10 +5,10 @@ #include #include "wpactrl-internal.h" -int wpactrl_querysa (wpactrl_t *a, char const *s, size_t len, stralloc *sa, tain_t *stamp) +int wpactrl_querysa (wpactrl_t *a, char const *s, stralloc *sa, tain_t *stamp) { char buf[WPACTRL_PACKET_MAX] ; - ssize_t r = wpactrl_query(a, s, len, buf, WPACTRL_PACKET_MAX, stamp) ; + ssize_t r = wpactrl_query(a, s, buf, WPACTRL_PACKET_MAX, stamp) ; if (r < 0) return 0 ; if (!r) return (errno = EPIPE, 0) ; return stralloc_catb(sa, buf, r) ; diff --git a/src/libwpactrl/wpactrl_removenetwork.c b/src/libwpactrl/wpactrl_removenetwork.c new file mode 100644 index 0000000..f943b72 --- /dev/null +++ b/src/libwpactrl/wpactrl_removenetwork.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include +#include + +wparesponse_t wpactrl_removenetwork (wpactrl_t *a, uint32_t id, tain_t *stamp) +{ + char buf[15 + UINT32_FMT] = "REMOVE_NETWORK " ; + buf[15 + uint32_fmt(buf + 15, id)] = 0 ; + return wpactrl_command(a, buf, stamp) ; +} diff --git a/src/libwpactrl/wpactrl_scan_parse.c b/src/libwpactrl/wpactrl_scan_parse.c index ab4a9fe..e75072d 100644 --- a/src/libwpactrl/wpactrl_scan_parse.c +++ b/src/libwpactrl/wpactrl_scan_parse.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -11,56 +11,25 @@ #include #include -static size_t bssid_scan (char const *s, char *bssid) -{ - unsigned int i = 0 ; - char sep[6] = ":::::\t" ; - for (; i < 6 ; i++) - { - if (!ucharn_scan(s, bssid + i, 1)) goto eproto ; - if (s[2] != sep[i]) goto eproto ; - s += 3 ; - } - return 18 ; - - eproto: - return (errno = EPROTO, 0) ; -} - -static int flags_scan (char const *s, size_t len, stralloc *sa) -{ - while (len) - { - size_t pos ; - if (*s++ != '[') goto eproto ; - len-- ; - pos = byte_chr(s, len, ']') ; - if (pos >= len || !pos) goto eproto ; - if (!stralloc_catb(sa, s, pos) || !stralloc_0(sa)) return 0 ; - s += pos + 1 ; len -= pos + 1 ; - } - return 1 ; - - eproto: - return (errno = EPROTO, 0) ; -} - static int wpactrl_scan_parse_one (char const *s, size_t len, wpactrl_scanres_t *thing, stralloc *sa) { wpactrl_scanres_t sr ; size_t pos = byte_chr(s, len, '\t') ; if (pos >= len) goto eproto ; - if (pos != 18) goto eproto ; - if (bssid_scan(s, sr.bssid) != pos) goto eproto ; + if (wpactrl_bssid_scan(s, sr.bssid) != pos) goto eproto ; s += pos + 1 ; len -= pos + 1 ; pos = byte_chr(s, len, '\t') ; if (pos >= len) goto eproto ; - if (uint16_scan(s, &sr.frequency) != pos) goto eproto ; + if (uint32_scan(s, &sr.frequency) != pos) goto eproto ; + s += pos + 1 ; len -= pos + 1 ; + pos = byte_chr(s, len, '\t') ; + if (pos >= len) goto eproto ; + if (uint32_scan(s, &sr.signal_level) != pos) goto eproto ; s += pos + 1 ; len -= pos + 1 ; pos = byte_chr(s, len, '\t') ; if (pos >= len) goto eproto ; sr.flags_start = sa->len ; - if (!flags_scan(s, pos, sa)) goto eproto ; + if (wpactrl_flags_scan(s, sa) != pos) goto eproto ; s += pos + 1 ; len -= pos + 1 ; sr.flags_len = sa->len - sr.flags_start ; sr.ssid_start = sa->len ; @@ -92,13 +61,9 @@ int wpactrl_scan_parse (char const *s, size_t len, genalloc *ga, stralloc *sa) return 1 ; err: - { - int e = errno ; - if (gawasnull) genalloc_free(wpactrl_scanres_t, ga) ; - else genalloc_setlen(wpactrl_scanres_t, ga, gabase) ; - if (sawasnull) stralloc_free(sa) ; - else sa->len = sabase ; - errno = e ; - } + if (gawasnull) genalloc_free(wpactrl_scanres_t, ga) ; + else genalloc_setlen(wpactrl_scanres_t, ga, gabase) ; + if (sawasnull) stralloc_free(sa) ; + else sa->len = sabase ; return 0 ; } diff --git a/src/libwpactrl/wpactrl_selectnetwork.c b/src/libwpactrl/wpactrl_selectnetwork.c new file mode 100644 index 0000000..25842e4 --- /dev/null +++ b/src/libwpactrl/wpactrl_selectnetwork.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include +#include + +wparesponse_t wpactrl_selectnetwork (wpactrl_t *a, uint32_t id, tain_t *stamp) +{ + char buf[15 + UINT32_FMT] = "SELECT_NETWORK " ; + buf[15 + uint32_fmt(buf + 15, id)] = 0 ; + return wpactrl_command(a, buf, stamp) ; +} diff --git a/src/libwpactrl/wpactrl_setnetworkoption.c b/src/libwpactrl/wpactrl_setnetworkoption.c new file mode 100644 index 0000000..5b2fdca --- /dev/null +++ b/src/libwpactrl/wpactrl_setnetworkoption.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include +#include +#include + +wparesponse_t wpactrl_setnetworkoption (wpactrl_t *a, uint32_t id, char const *var, char const *val, tain_t *stamp) +{ + size_t varlen = strlen(var) ; + size_t vallen = strlen(val) ; + size_t idlen ; + char buf[15 + UINT32_FMT + varlen + vallen] ; + memcpy(buf, "SET_NETWORK ", 12) ; + idlen = uint32_fmt(buf + 12, id) ; + buf[12 + idlen] = ' ' ; + memcpy(buf + 13 + idlen, var, varlen) ; + buf[13 + idlen + varlen] = ' ' ; + memcpy(buf + 14 + idlen + varlen, val, vallen) ; + buf[14 + idlen + varlen + vallen] = 0 ; + return wpactrl_command(a, buf, stamp) ; +} diff --git a/src/libwpactrl/wpactrl_xchg_init.c b/src/libwpactrl/wpactrl_xchg_init.c index 37006dd..2e2f391 100644 --- a/src/libwpactrl/wpactrl_xchg_init.c +++ b/src/libwpactrl/wpactrl_xchg_init.c @@ -4,7 +4,7 @@ #include #include -int wpactrl_xchg_init (wpactrl_xchg_t *dt, wpactrl_xchgitem_t const *tab, unsigned int n, tain_t const *limit, void *aux) +void wpactrl_xchg_init (wpactrl_xchg_t *dt, wpactrl_xchgitem_t const *tab, unsigned int n, tain_t const *limit, void *aux) { dt->sa.len = 0 ; dt->tab = tab ; @@ -13,5 +13,4 @@ int wpactrl_xchg_init (wpactrl_xchg_t *dt, wpactrl_xchgitem_t const *tab, unsign dt->deadline = *limit ; dt->status = ECONNABORTED ; dt->aux = aux ; - return 1 ; } -- cgit v1.2.3