summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-11-06 17:06:54 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-11-06 17:06:54 +0100
commit9ce82277e6be7e4c215b074c6c7f2c71f7edc332 (patch)
treececf5f7904075903cd3cc21a422fd0d37cbb89e1
parent0339773076040aded86947d764654c0f962c70cc (diff)
owfd: wpa: parse basic p2p/ap events
Add parsers for the most basic payloads that we need during the beginning. Further payload parsers can be added once we have a use-case for them. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r--src/wpa.h26
-rw-r--r--src/wpa_parser.c261
-rw-r--r--test/test_wpa.c53
3 files changed, 320 insertions, 20 deletions
diff --git a/src/wpa.h b/src/wpa.h
index 03a1a9a..c3f88b8 100644
--- a/src/wpa.h
+++ b/src/wpa.h
@@ -104,6 +104,32 @@ struct owfd_wpa_event {
unsigned int type;
unsigned int priority;
char *raw;
+
+ union owfd_wpa_event_payload {
+ struct owfd_wpa_event_ap_sta_connected {
+ char mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ } ap_sta_connected;
+ struct owfd_wpa_event_ap_sta_disconnected {
+ char mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ } ap_sta_disconnected;
+ struct owfd_wpa_event_p2p_device_found {
+ char peer_mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ char *name;
+ } p2p_device_found;
+ struct owfd_wpa_event_p2p_prov_disc_show_pin {
+ char peer_mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ char *pin;
+ } p2p_prov_disc_show_pin;
+ struct owfd_wpa_event_p2p_prov_disc_enter_pin {
+ char peer_mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ } p2p_prov_disc_enter_pin;
+ struct owfd_wpa_event_p2p_prov_disc_pbc_req {
+ char peer_mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ } p2p_prov_disc_pbc_req;
+ struct owfd_wpa_event_p2p_prov_disc_pbc_resp {
+ char peer_mac[OWFD_WPA_EVENT_MAC_STRLEN];
+ } p2p_prov_disc_pbc_resp;
+ } p;
};
void owfd_wpa_event_init(struct owfd_wpa_event *ev);
diff --git a/src/wpa_parser.c b/src/wpa_parser.c
index 2acec9f..c65d55f 100644
--- a/src/wpa_parser.c
+++ b/src/wpa_parser.c
@@ -39,6 +39,17 @@ void owfd_wpa_event_reset(struct owfd_wpa_event *ev)
{
free(ev->raw);
+ switch (ev->type) {
+ case OWFD_WPA_EVENT_P2P_DEVICE_FOUND:
+ free(ev->p.p2p_device_found.name);
+ break;
+ case OWFD_WPA_EVENT_P2P_PROV_DISC_SHOW_PIN:
+ free(ev->p.p2p_prov_disc_show_pin.pin);
+ break;
+ default:
+ break;
+ }
+
memset(ev, 0, sizeof(*ev));
}
@@ -97,11 +108,214 @@ static int event_comp(const void *key, const void *type)
return 0;
}
+static char *tokenize(const char *src, size_t *num)
+{
+ char *buf, *dst;
+ char last_c;
+ size_t n;
+ bool quoted, escaped;
+
+ buf = malloc(strlen(src) + 1);
+ if (!buf)
+ return NULL;
+
+ dst = buf;
+ last_c = 0;
+ n = 0;
+ *dst = 0;
+ quoted = 0;
+ escaped = 0;
+
+ for ( ; *src; ++src) {
+ if (quoted) {
+ if (escaped) {
+ escaped = 0;
+ last_c = *src;
+ *dst++ = last_c;
+ } else if (*src == '\'') {
+ quoted = 0;
+ } else if (*src == '\\') {
+ escaped = 1;
+ } else {
+ last_c = *src;
+ *dst++ = last_c;
+ }
+ } else {
+ if (*src == ' ' ||
+ *src == '\n' ||
+ *src == '\t' ||
+ *src == '\r') {
+ if (last_c) {
+ *dst++ = 0;
+ ++n;
+ }
+ last_c = 0;
+ } else if (*src == '\'') {
+ quoted = 1;
+ escaped = 0;
+ last_c = *src;
+ } else {
+ last_c = *src;
+ *dst++ = last_c;
+ }
+ }
+ }
+
+ if (last_c) {
+ *dst = 0;
+ ++n;
+ }
+
+ *num = n;
+ return buf;
+}
+
+static int parse_mac(char *buf, const char *src)
+{
+ int r, a1, a2, a3, a4, a5, a6;
+
+ if (strlen(src) > 17)
+ return -EINVAL;
+
+ r = sscanf(src, "%2d:%2d:%2d:%2d:%2d:%2d",
+ &a1, &a2, &a3, &a4, &a5, &a6);
+ if (r != 6)
+ return -EINVAL;
+
+ strcpy(buf, src);
+ return 0;
+}
+
+static int parse_ap_sta_connected(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+
+ if (num < 1)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.ap_sta_connected.mac, tokens);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int parse_ap_sta_disconnected(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+
+ if (num < 1)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.ap_sta_disconnected.mac, tokens);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int parse_p2p_device_found(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+ size_t i;
+
+ if (num < 2)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.p2p_device_found.peer_mac, tokens);
+ if (r < 0)
+ return r;
+
+ tokens += strlen(tokens) + 1;
+ for (i = 1; i < num; ++i, tokens += strlen(tokens) + 1) {
+ if (strncmp(tokens, "name=", 5))
+ continue;
+
+ ev->p.p2p_device_found.name = strdup(&tokens[5]);
+ if (!ev->p.p2p_device_found.name)
+ return -ENOMEM;
+
+ break;
+ }
+
+ return 0;
+}
+
+static int parse_p2p_prov_disc_show_pin(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+
+ if (num < 2)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.p2p_prov_disc_show_pin.peer_mac, tokens);
+ if (r < 0)
+ return r;
+
+ tokens += strlen(tokens) + 1;
+ ev->p.p2p_prov_disc_show_pin.pin = strdup(tokens);
+ if (!ev->p.p2p_prov_disc_show_pin.pin)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int parse_p2p_prov_disc_enter_pin(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+
+ if (num < 1)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.p2p_prov_disc_enter_pin.peer_mac, tokens);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int parse_p2p_prov_disc_pbc_req(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+
+ if (num < 1)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.p2p_prov_disc_pbc_req.peer_mac, tokens);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int parse_p2p_prov_disc_pbc_resp(struct owfd_wpa_event *ev,
+ char *tokens, size_t num)
+{
+ int r;
+
+ if (num < 1)
+ return -EINVAL;
+
+ r = parse_mac(ev->p.p2p_prov_disc_pbc_resp.peer_mac, tokens);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int owfd_wpa_event_parse(struct owfd_wpa_event *ev, const char *event)
{
const char *t;
- char *end;
+ char *end, *tokens = NULL;
+ size_t num;
struct event_type *code;
+ int r;
owfd_wpa_event_reset(ev);
@@ -135,19 +349,56 @@ int owfd_wpa_event_parse(struct owfd_wpa_event *ev, const char *event)
++t;
ev->raw = strdup(t);
- if (!ev->raw)
- goto oom;
+ if (!ev->raw) {
+ r = -ENOMEM;
+ goto error;
+ }
+
+ tokens = tokenize(ev->raw, &num);
+ if (!tokens) {
+ r = -ENOMEM;
+ goto error;
+ }
switch (ev->type) {
+ case OWFD_WPA_EVENT_AP_STA_CONNECTED:
+ r = parse_ap_sta_connected(ev, tokens, num);
+ break;
+ case OWFD_WPA_EVENT_AP_STA_DISCONNECTED:
+ r = parse_ap_sta_disconnected(ev, tokens, num);
+ break;
+ case OWFD_WPA_EVENT_P2P_DEVICE_FOUND:
+ r = parse_p2p_device_found(ev, tokens, num);
+ break;
+ case OWFD_WPA_EVENT_P2P_PROV_DISC_SHOW_PIN:
+ r = parse_p2p_prov_disc_show_pin(ev, tokens, num);
+ break;
+ case OWFD_WPA_EVENT_P2P_PROV_DISC_ENTER_PIN:
+ r = parse_p2p_prov_disc_enter_pin(ev, tokens, num);
+ break;
+ case OWFD_WPA_EVENT_P2P_PROV_DISC_PBC_REQ:
+ r = parse_p2p_prov_disc_pbc_req(ev, tokens, num);
+ break;
+ case OWFD_WPA_EVENT_P2P_PROV_DISC_PBC_RESP:
+ r = parse_p2p_prov_disc_pbc_resp(ev, tokens, num);
+ break;
+ default:
+ r = 0;
+ break;
}
+ free(tokens);
+
+ if (r < 0)
+ goto error;
+
return 0;
unknown:
ev->type = OWFD_WPA_EVENT_UNKNOWN;
return 0;
-oom:
+error:
owfd_wpa_event_reset(ev);
- return -ENOMEM;
+ return r;
}
diff --git a/test/test_wpa.c b/test/test_wpa.c
index b3f61c7..f2a9760 100644
--- a/test/test_wpa.c
+++ b/test/test_wpa.c
@@ -37,9 +37,9 @@ static void parse(struct owfd_wpa_event *ev, const char *event)
static const char *event_list[] = {
[OWFD_WPA_EVENT_UNKNOWN] = "",
- [OWFD_WPA_EVENT_AP_STA_CONNECTED] = "AP-STA-CONNECTED",
- [OWFD_WPA_EVENT_AP_STA_DISCONNECTED] = "AP-STA-DISCONNECTED",
- [OWFD_WPA_EVENT_P2P_DEVICE_FOUND] = "P2P-DEVICE-FOUND",
+ [OWFD_WPA_EVENT_AP_STA_CONNECTED] = "AP-STA-CONNECTED 00:00:00:00:00:00",
+ [OWFD_WPA_EVENT_AP_STA_DISCONNECTED] = "AP-STA-DISCONNECTED 00:00:00:00:00:00",
+ [OWFD_WPA_EVENT_P2P_DEVICE_FOUND] = "P2P-DEVICE-FOUND 00:00:00:00:00:00 name=some-name",
[OWFD_WPA_EVENT_P2P_GO_NEG_REQUEST] = "P2P-GO-NEG-REQUEST",
[OWFD_WPA_EVENT_P2P_GO_NEG_SUCCESS] = "P2P-GO-NEG-SUCCESS",
[OWFD_WPA_EVENT_P2P_GO_NEG_FAILURE] = "P2P-GO-NEG-FAILURE",
@@ -47,10 +47,10 @@ static const char *event_list[] = {
[OWFD_WPA_EVENT_P2P_GROUP_FORMATION_FAILURE] = "P2P-GROUP-FORMATION-FAILURE",
[OWFD_WPA_EVENT_P2P_GROUP_STARTED] = "P2P-GROUP-STARTED",
[OWFD_WPA_EVENT_P2P_GROUP_REMOVED] = "P2P-GROUP-REMOVED",
- [OWFD_WPA_EVENT_P2P_PROV_DISC_SHOW_PIN] = "P2P-PROV-DISC-SHOW-PIN",
- [OWFD_WPA_EVENT_P2P_PROV_DISC_ENTER_PIN] = "P2P-PROV-DISC-ENTER-PIN",
- [OWFD_WPA_EVENT_P2P_PROV_DISC_PBC_REQ] = "P2P-PROV-DISC-PBC-REQ",
- [OWFD_WPA_EVENT_P2P_PROV_DISC_PBC_RESP] = "P2P-PROV-DISC-PBC-RESP",
+ [OWFD_WPA_EVENT_P2P_PROV_DISC_SHOW_PIN] = "P2P-PROV-DISC-SHOW-PIN 00:00:00:00:00:00 pin",
+ [OWFD_WPA_EVENT_P2P_PROV_DISC_ENTER_PIN] = "P2P-PROV-DISC-ENTER-PIN 00:00:00:00:00:00",
+ [OWFD_WPA_EVENT_P2P_PROV_DISC_PBC_REQ] = "P2P-PROV-DISC-PBC-REQ 00:00:00:00:00:00",
+ [OWFD_WPA_EVENT_P2P_PROV_DISC_PBC_RESP] = "P2P-PROV-DISC-PBC-RESP 00:00:00:00:00:00",
[OWFD_WPA_EVENT_P2P_SERV_DISC_REQ] = "P2P-SERV-DISC-REQ",
[OWFD_WPA_EVENT_P2P_SERV_DISC_RESP] = "P2P-SERV-DISC-RESP",
[OWFD_WPA_EVENT_P2P_INVITATION_RECEIVED] = "P2P-INVITATION-RECEIVED",
@@ -75,11 +75,11 @@ START_TEST(test_wpa_parser)
ck_assert_msg(ev.type == i, "event %d invalid", i);
}
- parse(&ev, "<5>AP-STA-CONNECTED");
+ parse(&ev, "<5>AP-STA-CONNECTED 0:0:0:0:0:0");
ck_assert(ev.priority == OWFD_WPA_EVENT_P_MSGDUMP);
ck_assert(ev.type == OWFD_WPA_EVENT_AP_STA_CONNECTED);
- parse(&ev, "<4>AP-STA-CONNECTED");
+ parse(&ev, "<4>AP-STA-CONNECTED 0:0:0:0:0:0");
ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
ck_assert(ev.type == OWFD_WPA_EVENT_AP_STA_CONNECTED);
@@ -87,31 +87,54 @@ START_TEST(test_wpa_parser)
ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
ck_assert(ev.type == OWFD_WPA_EVENT_UNKNOWN);
- parse(&ev, "<4asdf>AP-STA-CONNECTED");
+ parse(&ev, "<4asdf>AP-STA-CONNECTED 0:0:0:0:0:0");
ck_assert(ev.priority == OWFD_WPA_EVENT_P_MSGDUMP);
ck_assert(ev.type == OWFD_WPA_EVENT_AP_STA_CONNECTED);
- parse(&ev, "<4>AP-STA-CONNECTED something else");
+ parse(&ev, "<4>AP-STA-CONNECTED 0:0:0:0:0:0");
ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
ck_assert(ev.type == OWFD_WPA_EVENT_AP_STA_CONNECTED);
ck_assert(ev.raw != NULL);
- ck_assert(!strcmp(ev.raw, "something else"));
+ ck_assert(!strcmp(ev.raw, "0:0:0:0:0:0"));
parse(&ev, "<4>AP-STA something else");
ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
ck_assert(ev.type == OWFD_WPA_EVENT_UNKNOWN);
ck_assert(!ev.raw);
+}
+END_TEST
+
+START_TEST(test_wpa_parser_payload)
+{
+ struct owfd_wpa_event ev;
- parse(&ev, "<4>AP-STA-CONNECTED");
+ parse(&ev, "<4>P2P-DEVICE-FOUND 0:0:0:0:0:0 name=some-name");
ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
- ck_assert(ev.type == OWFD_WPA_EVENT_AP_STA_CONNECTED);
+ ck_assert(ev.type == OWFD_WPA_EVENT_P2P_DEVICE_FOUND);
+ ck_assert(ev.raw != NULL);
+ ck_assert(!strcmp(ev.raw, "0:0:0:0:0:0 name=some-name"));
+ ck_assert(!strcmp(ev.p.p2p_device_found.peer_mac, "0:0:0:0:0:0"));
+ ck_assert(!strcmp(ev.p.p2p_device_found.name, "some-name"));
+
+ parse(&ev, "<4>P2P-DEVICE-FOUND 0:0:0:0:0:0 name=some-'name\\\\\\''");
+ ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
+ ck_assert(ev.type == OWFD_WPA_EVENT_P2P_DEVICE_FOUND);
+ ck_assert(ev.raw != NULL);
+ ck_assert(!strcmp(ev.p.p2p_device_found.peer_mac, "0:0:0:0:0:0"));
+ ck_assert(!strcmp(ev.p.p2p_device_found.name, "some-name\\'"));
+
+ parse(&ev, "<4>P2P-PROV-DISC-SHOW-PIN 0:0:0:0:0:0 1234567890");
+ ck_assert(ev.priority == OWFD_WPA_EVENT_P_ERROR);
+ ck_assert(ev.type == OWFD_WPA_EVENT_P2P_PROV_DISC_SHOW_PIN);
ck_assert(ev.raw != NULL);
- ck_assert(!*ev.raw);
+ ck_assert(!strcmp(ev.p.p2p_prov_disc_show_pin.peer_mac, "0:0:0:0:0:0"));
+ ck_assert(!strcmp(ev.p.p2p_prov_disc_show_pin.pin, "1234567890"));
}
END_TEST
TEST_DEFINE_CASE(parser)
TEST(test_wpa_parser)
+ TEST(test_wpa_parser_payload)
TEST_END_CASE
TEST_DEFINE(