-
Jakob Olsson authoredJakob Olsson authored
dpp.c 7.79 KiB
/*
* Copyright (C) 2023 IOPSYS Software Solutions AB. All rights reserved.
*/
#if (EASYMESH_VERSION > 2)
#ifdef USE_LIBDPP
#include "dpp.h"
#include <libubox/list.h>
#include <easy/easy.h>
#include <wifidefs.h>
#include <dpp_api.h>
#include <dpputils.h>
#include <string.h>
#include "cmdu.h"
#include "cntlr.h"
#include "cntlr_cmdu.h"
#include "cntlr_map.h"
#include "easy/utils.h"
#include "utils/debug.h"
const char *dpp_frame_type2str(uint8_t type)
{
if (type == DPP_PA_AUTHENTICATION_REQ)
return "Authentication Request";
else if (type == DPP_PA_AUTHENTICATION_RESP)
return "Authentication Response";
else if (type == DPP_PA_AUTHENTICATION_CONF)
return "Authentication Confirm";
else if (type == DPP_PA_PEER_DISCOVERY_REQ)
return "Peer Discovery Request";
else if (type == DPP_PA_PEER_DISCOVERY_RESP)
return "Peer Discovery Response";
else if (type == DPP_PA_PKEX_V1_EXCHANGE_REQ)
return "PKEX Version 1 Exchange Request";
else if (type == DPP_PA_PKEX_EXCHANGE_RESP)
return "PKEX Exchange Response";
else if (type == DPP_PA_PKEX_COMMIT_REVEAL_REQ)
return "PKEX Commit-Reveal Request";
else if (type == DPP_PA_PKEX_COMMIT_REVEAL_RESP)
return "PKEX Commit-Reveal Response";
else if (type == DPP_PA_CONFIGURATION_RESULT)
return "Configuration Result";
else if (type == DPP_PA_CONNECTION_STATUS_RESULT)
return "Connection Status Result";
else if (type == DPP_PA_PRESENCE_ANNOUNCEMENT)
return "Presence Announcement";
else if (type == DPP_PA_RECONFIG_ANNOUNCEMENT)
return "Reconfiguration Announcement";
else if (type == DPP_PA_RECONFIG_AUTH_REQ)
return "Reconfiguration Authentication Request";
else if (type == DPP_PA_RECONFIG_AUTH_RESP)
return "Reconfiguration Authentication Response";
else if (type == DPP_PA_RECONFIG_AUTH_CONF)
return "Reconfiguration Authentication Confirm";
else if (type == DPP_PA_PKEX_EXCHANGE_REQ)
return "PKEX Exchange Request";
else if (type == 0x13)
return "Push Button Presence Announcement";
else if (type == 0x14)
return "Push Button Presence Announcement Response";
else if (type == 0x15)
return "Private Peer Introduction Query";
else if (type == 0x16)
return "Private Peer Introduction Notify";
else if (type == 0x17)
return "Private Peer Introduction Update";
return "Unknown";
}
#if 0
/* will generate an enrollee if it does not exist */
int dpp_append_uri_file(struct controller *c, char *uri)
{
struct json_object *uri_json, *arr, *val, *new;
int rv, len, i;
uri_json = json_object_from_file(DPP_URI_FILE);
if (!uri_json) {
dbg("|%s:%d| failed to read json:%s error:%s. "\
"Try to generate new\n", __func__, __LINE__, DPP_URI_FILE,
json_util_get_last_err());
uri_json = json_object_new_object();
if (!uri_json)
goto out;
arr = json_object_new_array();
if (!arr)
goto out_uri;
json_object_object_add(uri_json, "uris", arr);
}
rv = json_object_object_get_ex(uri_json, "uris", &arr);
if (!rv || !arr)
goto out_uri;
if (!json_object_is_type(arr, json_type_array)) {
warn("|%s:%d| file:%s is not expected format\n", __func__,
__LINE__, DPP_URI_FILE);
goto out_uri;
}
len = json_object_array_length(uri_json);
for (i = 0; i < len; i++) {
struct json_object *t;
const char *p;
t = json_object_array_get_idx(arr, i);
if (!t) {
warn("|%s:%d| couldn't get entry:%d from uri array",
__func__, __LINE__, i);
continue;
}
p = json_get_string(t, "uri");
if (strncmp(p, uri, 128))
continue;
/* hash already exists in file */
/* TODO: possibly type has changed? */
goto out;
}
new = json_object_new_object();
if (!new)
goto out_uri;
val = json_object_new_string(uri);
if (!val) {
json_object_put(new);
goto out_uri;
}
json_object_object_add(new, "uri", val);
val = json_object_new_string("qr");
if (!val) {
json_object_put(new);
goto out_uri;
}
json_object_object_add(new, "type", val);
json_object_array_add(arr, new);
json_object_to_file(DPP_URI_FILE, uri_json);
out_uri:
json_object_put(uri_json);
out:
return 0;
}
int dpp_cntlr_read_uris(struct controller *c)
{
struct blob_buf uris = { 0 };
struct blob_attr *uri;
int rem;
int rc = -1;
static const struct blobmsg_policy attr[] = {
[0] = { .name = "uris", .type = BLOBMSG_TYPE_ARRAY },
};
struct blob_attr *tb[ARRAY_SIZE(attr)];
blob_buf_init(&uris, 0);
if (!blobmsg_add_json_from_file(&uris, DPP_URI_FILE)) {
warn("Failed to parse %s\n", DPP_URI_FILE);
goto out;
}
blobmsg_parse(attr, ARRAY_SIZE(attr), tb, blob_data(uris.head), blob_len(uris.head));
if (!tb[0])
goto out;
blobmsg_for_each_attr(uri, tb[0], rem) {
static const struct blobmsg_policy uri_attr[4] = {
[0] = { .name = "uri", .type = BLOBMSG_TYPE_STRING },
[1] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
};
struct blob_attr *tb1[ARRAY_SIZE(uri_attr)];
struct dpp_enrollee *e;
char *uri_str;
blobmsg_parse(uri_attr, ARRAY_SIZE(uri_attr), tb1, blobmsg_data(uri), blob_len(uri));
if (!tb1[0] || !tb1[1])
continue;
uri_str = blobmsg_data(tb1[0]);
if (!uri_str)
continue;
e = dpp_process_new_uri(c, uri_str);
if (!e)
continue;
if (strcmp("qr", blobmsg_data(tb1[1])))
e->type = DPP_BOOTSTRAP_QR_CODE_WIFI;
else
e->type = DPP_BOOTSTRAP_QR_CODE_WIFI;
}
out:
blob_buf_free(&uris);
return rc;
}
#endif
int dpp_frame_handler(void *dpp, uint8_t *smac, enum dpp_event ev,
uint8_t *frame, size_t framelen)
{
struct controller *c;
int ret = 0;
err("%s: ----->\n", __func__);
if (!smac) {
warn("%s: Error: smac = NULL\n", __func__);
ret = -1;
goto out;
}
err("%s: DPP_EVENT: event = %d smac = " MACFMT", frame = %p, len = %zu\n",
__func__, ev, MAC2STR(smac), frame, framelen);
switch (ev) {
case DPP_EVENT_TX_FRAME: {
struct cmdu_buff *resp;
int frametype = 0;
struct node *proxy = NULL;
frametype = dpp_get_frame_type(frame + 1, framelen - 1);
if (frametype == 255) {
warn("Invalid frametype\n");
ret = -1;
goto out;
}
err("DPP frametype %s\n", dpp_frame_type2str(frametype));
c = dpp_get_ctx_private_data(dpp);
if (!c) {
ret = -1;
goto out;
}
dump(frame, framelen, "DPP Frame Response");
/* if peer has private data, it is the proxy node
* thus we can infer its a proxied encap DPP message
*/
proxy = dpp_get_peer_private_data(dpp, smac);
if (proxy) {
err("|%s:%d|\n", __func__, __LINE__);
resp = cntlr_gen_proxied_encap_dpp(c, smac, frametype,
frame, framelen,
NULL, 0);
if (!resp) {
warn("|%s:%d| DPP: ----> Error generating proxy encap\n",
__func__, __LINE__);
ret = -1;
goto out;
}
} else {
err("|%s:%d|\n", __func__, __LINE__);
resp = cntlr_gen_direct_encap_dpp(c, smac, frame,
framelen);
if (!resp) {
warn("|%s:%d| DPP: ----> Error generating direct encap\n",
__func__, __LINE__);
ret = -1;
goto out;
}
}
switch (frametype) {
case DPP_PA_AUTHENTICATION_REQ: {
if (proxy) {
struct node *n = NULL;
list_for_each_entry(n, &c->nodelist, list) {
memcpy(resp->origin, n->almacaddr, 6);
err("|%s:%d| send frame to "MACFMT"\n", __func__, __LINE__, MAC2STR(n->almacaddr));
send_cmdu(c, resp);
}
cmdu_free(resp);
break;
}
/* FALLTHROUGH */
}
case DPP_PA_AUTHENTICATION_CONF:
case DPP_PUB_AF_GAS_INITIAL_RESP:
case DPP_PA_PEER_DISCOVERY_RESP:
if (proxy)
memcpy(resp->origin, proxy->almacaddr, 6);
else
memcpy(resp->origin, smac, 6);
send_cmdu(c, resp);
cmdu_free(resp);
break;
default:
warn("|%s:%d| DPP: ----> Unknown frame\n", __func__, __LINE__);
break;
}
break;
}
case DPP_EVENT_BAD_AUTH:
err("DPP: BAD AUTH!\n");
/* FALLTHROUGH */
case DPP_EVENT_TIMEOUT: {
struct dpp_peer *peer = dpp_lookup_peer(dpp, smac);
err("DPP: EVENT TIMEOUT!\n");
if (peer) {
list_del(&peer->list);
dpp_free_peer(dpp, peer);
}
break;
}
default:
break;
}
out:
return ret;
}
#endif
#endif