diff --git a/src/Makefile b/src/Makefile index 97dd4a2c7d82e020e6df58b6b04e75bbecf98279..b58a578b323ee87584429c588e61f9795751c729 100644 --- a/src/Makefile +++ b/src/Makefile @@ -37,6 +37,9 @@ LIBS = -lubus -lubox -ljson-c -lblobmsg_json -luci -pthread LIBS += -rdynamic -ldl LIBS += -leasy -lwifiutils LIBS += -lieee1905 -lmaputil +ifneq (,$(findstring USE_LIBDPP,$(CFLAGS))) +LIBS += -ldpp +endif plugin_subdirs ?= $(wildcard plugins/*/*) plugin_sofile = $(wildcard $(d)/*.so) diff --git a/src/cntlr.c b/src/cntlr.c index 937e7c96689f1b2f7e6815fbb7ffd69a1384db2f..bb857d338e8adbe48cc02be60c17b79897d7db0c 100644 --- a/src/cntlr.c +++ b/src/cntlr.c @@ -34,6 +34,8 @@ #include "timer.h" #if (EASYMESH_VERSION > 2) +#include <dpp_api.h> + #include "dpp.h" #endif @@ -2177,6 +2179,7 @@ void run_controller(void) INIT_LIST_HEAD(&c->dpp_ctx.enrolleelist); INIT_LIST_HEAD(&c->dpp_ctx.chirplist); #endif + as_init_table(&c->as_table); allmac_init_table(&c->mac_table); init_bh_topology(); @@ -2187,6 +2190,26 @@ void run_controller(void) ubus_add_uloop(ctx); +#if (EASYMESH_VERSION > 2) + { + char *argv[] = {"-I", "-C", "-V", "2"}; + int argc = 4; + int ret; + + ret = dpp_init(&c->dpp, argc, argv); + if (ret) { + dbg("Failed to init dpp context\n"); + goto out_exit; + } + + dpp_register_cb(c->dpp, dpp_frame_handler); + dpp_set_ctx_private_data(c->dpp, c); + + + dpp_cntlr_read_uris(c); + } +#endif + cntlr_config_defaults(c, &c->cfg); ret = cntlr_get_ieee1905_almac(c, c->almac); @@ -2254,10 +2277,6 @@ void run_controller(void) memset(&c->dlem.network.steer_summary, 0, sizeof(struct wifi_steer_summary)); cntlr_dbg("current wifi_cntlr profile %d\n", c->cfg.map_profile); -#if (EASYMESH_VERSION > 2) - dpp_cntlr_read_uris(c); -#endif - uloop_run(); out_exit: diff --git a/src/cntlr.h b/src/cntlr.h index d7383758dd50d41ad6cb3e1fb28ddbffc6807e02..97adc8706f9bcd3219cae3bce891abfa03b2a4aa 100644 --- a/src/cntlr.h +++ b/src/cntlr.h @@ -307,9 +307,6 @@ struct controller { struct list_head stalist; /* list of sta */ struct list_head bcnreqlist; struct list_head linklist; -#if (EASYMESH_VERSION > 2) - struct dpp_context dpp_ctx; -#endif atimer_t radar_timer; atimer_t discovery_timer; atimer_t start_timer; @@ -333,6 +330,11 @@ struct controller { struct list_head sclist; /* steer_control module list */ struct steer_control *sctrl; /* active steer-control module */ +#if (EASYMESH_VERSION > 2) + struct dpp_context_wifi dpp_ctx; + void *dpp; +#endif + struct wifi_data_element dlem; /* wifi data elements */ }; diff --git a/src/cntlr_cmdu.c b/src/cntlr_cmdu.c index f92ddbdf19c57b87b0240d2f68bc7a4a7dba4f83..166e43a843f662090f672b72106f55564de9ada0 100644 --- a/src/cntlr_cmdu.c +++ b/src/cntlr_cmdu.c @@ -530,6 +530,9 @@ out: } struct cmdu_buff *cntlr_gen_ap_autoconfig_response(struct controller *c, +#if (EASYMESH_VERSION > 2) + bool hash_validity, uint8_t *hash, uint16_t hashlen, +#endif uint8_t *dest, uint8_t band, uint16_t mid) { struct cmdu_buff *resp; @@ -562,11 +565,14 @@ struct cmdu_buff *cntlr_gen_ap_autoconfig_response(struct controller *c, ret = cntlr_gen_device_1905_layer_security_cap(c, resp); if (ret) goto out; -#if 0 - ret = cntlr_gen_chirp_value_tlv(c, resp); - if (ret) - goto out; -#endif + + if (hash) { + ret = cntlr_gen_chirp_value_tlv(c, resp, NULL, + hash_validity, hashlen, + hash); + if (ret) + goto out; + } #if (EASYMESH_VERSION > 5) ret = cntlr_gen_cntlr_capability(c, resp, CONTROLLER_EARLY_AP_CAP_SUPPORTED); @@ -1086,21 +1092,25 @@ error: } #if (EASYMESH_VERSION > 2) -struct cmdu_buff *cntlr_gen_direct_encap_dpp(struct controller *c) +struct cmdu_buff *cntlr_gen_direct_encap_dpp(struct controller *c, + uint8_t *dst, + uint8_t *frame, + uint16_t framelen) { struct cmdu_buff *frm; uint16_t mid = 0; /* TODO: Pass direct_encap_dpp_data parameter */ - - frm = cmdu_alloc_simple(CMDU_DIRECT_ENCAP_DPP, &mid); + frm = cmdu_alloc_frame(5000); if (!frm) { - dbg("%s: -ENOMEM\n", __func__); + trace("%s: -ENOMEM\n", __func__); return NULL; } + cmdu_set_type(frm, CMDU_DIRECT_ENCAP_DPP); + cmdu_set_mid(frm, mid); /* One DPP Message TLV */ - if (cntlr_gen_dpp_message_tlv(c, frm)) { + if (cntlr_gen_dpp_message_tlv(c, frm, framelen, frame)) { dbg("%s: cntlr_gen_dpp_message_tlv failed.\n", __func__); goto out; } @@ -1145,7 +1155,7 @@ struct cmdu_buff *cntlr_gen_proxied_encap_dpp(struct controller *c, /* Zero or One Chirp Value TLV */ if (hashlen && hash) { - if (cntlr_gen_chirp_value_tlv(c, frm, enrollee, hashlen, hash)) { + if (cntlr_gen_chirp_value_tlv(c, frm, enrollee, 1 /* TODO: hash_validity */, hashlen, hash)) { dbg("%s: cntlr_gen_chirp_value_tlv failed.\n", __func__); goto out; } diff --git a/src/cntlr_cmdu.h b/src/cntlr_cmdu.h index 968c24a04b58ec9951876a48faa116d26c2cef9a..3066422d7113ae77f6a94256219d5bb0efce101b 100644 --- a/src/cntlr_cmdu.h +++ b/src/cntlr_cmdu.h @@ -42,6 +42,9 @@ struct cmdu_buff *cntlr_gen_unassoc_sta_metric_query(struct controller *c, struct cmdu_buff *cntlr_gen_ap_autoconfig_search(struct controller *c, uint8_t profile, uint8_t band); struct cmdu_buff *cntlr_gen_ap_autoconfig_response(struct controller *c, +#if (EASYMESH_VERSION > 2) + bool hash_validity, uint8_t *hash, uint16_t hashlen, +#endif uint8_t *dest, uint8_t band, uint16_t mid); struct cmdu_buff *cntlr_gen_ap_autoconfig_wsc(struct controller *c, struct node *n, struct cmdu_buff *rx_cmdu, uint8_t *radio_id, @@ -99,7 +102,10 @@ struct cmdu_buff *cntlr_gen_proxied_encap_dpp(struct controller *c, uint8_t *frame, uint16_t hashlen, uint8_t *hash); -struct cmdu_buff *cntlr_gen_direct_encap_dpp(struct controller *c); +struct cmdu_buff *cntlr_gen_direct_encap_dpp(struct controller *c, + uint8_t *dst, + uint8_t *frame, + uint16_t framelen); struct cmdu_buff *cntrl_gen_bss_configuration_response(struct controller *c, struct cmdu_buff *request_cmdu); struct cmdu_buff *cntlr_gen_dpp_cce_indication(struct controller *c, uint8_t *agent, bool cce_advertise); diff --git a/src/cntlr_map.c b/src/cntlr_map.c index 8a77457d7566422c571ee33e26521cb07a901d14..6d27189b2cc74864b8455ae56d29b4939cd8155d 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -45,6 +45,8 @@ #include "timer.h" #if (EASYMESH_VERSION > 2) +#include <dpp_api.h> + #include "dpp.h" #include "utils/dpp_sock.h" #endif @@ -957,6 +959,13 @@ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_buff *rx_cmdu, struct controller *c = (struct controller *) cntlr; struct tlv_autoconfig_band *freq; struct tlv_aladdr *aladdr; +#if (EASYMESH_VERSION > 2) + void *event = NULL; + bool hash_known = false; + bool hash_validity; + uint8_t hashlen; + uint8_t *hash; +#endif struct tlv *t; struct cmdu_buff *cmdu; uint8_t almac[6] = {0}; @@ -1003,7 +1012,6 @@ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_buff *rx_cmdu, return -1; } - // todo: handle tv[6] i.e. MAP_TLV_DPP_CHIRP_VALUE if (tv[1][0]->data[0] != IEEE80211_ROLE_REGISTRAR) { trace("%s: Discard ap-autoconfig search for role != registrar\n", __func__); @@ -1049,21 +1057,73 @@ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_buff *rx_cmdu, if (tv[3][0]) handle_supported_service(c, almac, tv[3][0]); +#if (EASYMESH_VERSION > 2) + if (tv[6][0] && c->cfg.map_profile > 2) { + int offset = 0; + uint8_t flag = 0; + bool mac_present; + uint8_t *mac; + + flag = tv[6][0]->data[offset++]; + + mac_present = (flag & DPP_CHIRP_ENROLLEE_MAC_PRESENT); + hash_validity = (flag & DPP_CHIRP_HASH_VALIDITY); + UNUSED(hash_validity); + + if (mac_present) { + mac = &tv[6][0]->data[offset]; + UNUSED(mac); + offset += 6; + } + + hashlen = tv[6][0]->data[offset++]; + hash = &tv[6][0]->data[offset]; + + dump(hash, hashlen, "autoconf search chirp hash"); + + hash_known = dpp_is_peer_bootstrap_hash_known(c->dpp, hash, NULL); + if (hash_known) { + ret = dpp_process_virt_presence_announcement(c->dpp, + rx_cmdu->origin, + hash, hashlen); + if (!ret) { + event = dpp_sm_create_event(c->dpp, rx_cmdu->origin, + DPP_EVENT_RX_FRAME, + 0, NULL); + } else + err("%s: Failed to process virt presence announcement!\n", __func__); + } else { + err("%s: Hash was not known!\n", __func__); + } + } +#endif + trace("%s: sending autoconfig response for band = %d, node %p\n", __func__, freq->band, n); - cmdu = cntlr_gen_ap_autoconfig_response(cntlr, almac, + + cmdu = cntlr_gen_ap_autoconfig_response(cntlr, +#if (EASYMESH_VERSION > 2) + (hash_known ? hash_validity : 0), + (hash_known ? hash : NULL), + (hash_known ? hashlen : 0), +#endif + almac, freq->band, cmdu_get_mid(rx_cmdu)); if (!cmdu) return -1; ret = send_cmdu(c, cmdu); - cmdu_free(cmdu); - UNUSED(ret); +#if (EASYMESH_VERSION > 2) + if (event) { + dbg("|%s:%d| Trigger dpp event\n", __func__, __LINE__); + dpp_trigger(c->dpp, rx_cmdu->origin, event); + } +#endif - return 0; + return !!ret; } /* disable and quit on controller response */ @@ -3570,22 +3630,71 @@ int handle_direct_encap_dpp(void *cntlr, struct cmdu_buff *cmdu, struct node *n) { trace("%s: --->\n", __func__); - struct controller *c = (struct controller *)cntlr; struct tlv *tlv; struct tlv *tlvs[DIRECT_ENCAP_DPP_MAX_NUMBER_OF_TLV_TYPES][TLV_MAXNUM] = { 0 }; + struct tlv_dpp_message *dpp_msg; + uint16_t framelen; + uint8_t *frame; + int frametype; + + UNUSED(c); if (!validate_direct_encap_dpp(cmdu, tlvs)) { dbg("cmdu validation: [DIRECT_ENCAP_DPP] failed\n"); return -1; } + /* POSSIBLY MID CHECK HERE? */ + /* One DPP Message TLV */ tlv = tlvs[DIRECT_ENCAP_DPP_MESSAGE_IDX][0]; - (void) tlv; - (void) c; + dpp_msg = (struct tlv_dpp_message *) tlv->data; + + frame = dpp_msg->frame; + framelen = BUF_GET_BE16(tlv->len); - // TODO: process DPP Message TLV + frametype = dpp_get_frame_type(frame + 1, framelen - 1); + if (frametype == 255) + return -1; + + /* Encapsulated frame length */ + dump(frame, framelen, "DIRECT CMDU FRAME"); + + switch (frametype) { + case DPP_PA_PRESENCE_ANNOUNCEMENT: { + int ret; + + ret = dpp_process_presence_announcement(c->dpp, cmdu->origin, + frame, + framelen); + if (ret) { + dbg("Failed to build presence announcement frame!\n"); + break; + } + + dbg("%s processing PA\n", (!ret ? "Succeeded" : "Failed")); + /* FALLTHROUGH */ + } + case DPP_PA_AUTHENTICATION_RESP: + case DPP_PUB_AF_GAS_INITIAL_REQ: + case DPP_PA_CONFIGURATION_RESULT: + case DPP_PA_PEER_DISCOVERY_REQ: + case DPP_PA_CONNECTION_STATUS_RESULT: { + void *event = + dpp_sm_create_event(c->dpp, cmdu->origin, DPP_EVENT_RX_FRAME, framelen, frame); + + if (event) { + dpp_trigger(c->dpp, cmdu->origin, event); + dpp_sm_free_event(event); + } + break; + + } + default: + dbg("Unknown frame!\n"); + break; + } return 0; } diff --git a/src/cntlr_tlv.c b/src/cntlr_tlv.c index 227045dc697180e119429f8cc8304d3fc0b0a177..2638d1745d7e9cc4ded818bf82e0f0b704c99f9a 100644 --- a/src/cntlr_tlv.c +++ b/src/cntlr_tlv.c @@ -1728,29 +1728,20 @@ int cntlr_gen_dpp_cce_indication_tlv(struct controller *c, return 0; } -/* TODO: fill the DPP frame field */ -int cntlr_gen_dpp_message_tlv(struct controller *c, struct cmdu_buff *frm) +int cntlr_gen_dpp_message_tlv(struct controller *c, struct cmdu_buff *frm, + uint16_t framelen, uint8_t *frame) { struct tlv *t; - int offset = 0; - /* dummy values */ - int framelen = 1; - uint8_t frame[1] = { 0xff }; - t = cmdu_reserve_tlv(frm, 512); + t = cmdu_reserve_tlv(frm, 4700); if (!t) return -1; t->type = MAP_TLV_DPP_MESSAGE; - /* DPP Frame length */ - t->data[offset++] = framelen; + memcpy(&t->data[0], frame, framelen); - /* DPP Frame */ - memcpy(&t->data[offset], frame, framelen); - offset += framelen; - - t->len = offset; + t->len = framelen; if (cmdu_put_tlv(frm, t)) return -1; @@ -1804,12 +1795,9 @@ int cntlr_gen_1905_encap_dpp_tlv(struct controller *c, struct cmdu_buff *frm, return 0; } -/* TODO: fill the following fields - * DPP flag (Hash Validity & MAC addr present) - * Enrollee MAC & hash - */ int cntlr_gen_chirp_value_tlv(struct controller *c, struct cmdu_buff *frm, - uint8_t *enrollee, uint16_t hashlen, uint8_t *hash) + uint8_t *enrollee, bool hash_validity, + uint16_t hashlen, uint8_t *hash) { struct tlv *t; int offset = 0; @@ -1824,7 +1812,7 @@ int cntlr_gen_chirp_value_tlv(struct controller *c, struct cmdu_buff *frm, if (enrollee) flags |= 1 << 7; - flags |= 1 << 6; /* TODO: 0: purge (when?) -- 1: establish */ + flags |= hash_validity << 6; /* TODO: 0: purge (when?) -- 1: establish */ t->data[offset++] = flags; diff --git a/src/cntlr_tlv.h b/src/cntlr_tlv.h index 741cc3f2165365566a8cd5271120ce4492faba79..c7b3749dc5fc7f83295d6aabdfce769aa201c909 100644 --- a/src/cntlr_tlv.h +++ b/src/cntlr_tlv.h @@ -115,13 +115,14 @@ int cntlr_gen_tlv_higher_layer_data(struct controller *c, struct cmdu_buff *frm, uint8_t proto, uint8_t *data, int len); #if (EASYMESH_VERSION > 2) -int cntlr_gen_dpp_message_tlv(struct controller *c, - struct cmdu_buff *frm); +int cntlr_gen_dpp_message_tlv(struct controller *c, struct cmdu_buff *frm, + uint16_t framelen, uint8_t *frame); int cntlr_gen_1905_encap_dpp_tlv(struct controller *c, struct cmdu_buff *frm, uint8_t *enrollee, uint8_t frametype, uint16_t framelen, uint8_t *frame); int cntlr_gen_chirp_value_tlv(struct controller *c, struct cmdu_buff *frm, - uint8_t *enrollee, uint16_t hashlen, uint8_t *hash); + uint8_t *enrollee, bool hash_validity, + uint16_t hashlen, uint8_t *hash); int cntlr_gen_bss_config_response_tlv(struct controller *c, struct cmdu_buff *cmdu); int cntlr_gen_dpp_cce_indication_tlv(struct controller *c, struct cmdu_buff *frm, diff --git a/src/cntlr_ubus.c b/src/cntlr_ubus.c index 805824cd62aefebdd7da3d024069fb05b8ddc8c5..d4afb4cde4f72106f89d4e2cb36d888a3fa575be 100644 --- a/src/cntlr_ubus.c +++ b/src/cntlr_ubus.c @@ -37,6 +37,8 @@ #include "timer.h" #if (EASYMESH_VERSION > 2) +#include <dpp_api.h> + #include "dpp.h" #endif #include "utils/utils.h" @@ -835,10 +837,57 @@ static int cntlr_steer_history(struct ubus_context *ctx, struct ubus_object *obj } #if (EASYMESH_VERSION > 2) +static int cntlr_dpp_uri_eth(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct controller *c = container_of(obj, struct controller, obj); + struct blob_attr *tb[__DPP_URI_MAX]; + struct dpp_bootstrap_info *enrollee_bi; + char *uri; + int ret; + + blobmsg_parse(dpp_uri_params, __DPP_URI_MAX, tb, + blob_data(msg), blob_len(msg)); + + if (!tb[DPP_URI]) { + dbg("|%s:%d| URI must be provided!\n", __func__, __LINE__); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + uri = blobmsg_data(tb[DPP_URI]); + if (!uri) + return UBUS_STATUS_UNKNOWN_ERROR; + + + enrollee_bi = calloc(1, sizeof(*enrollee_bi)); + if (!enrollee_bi) { + fprintf(stderr, "Failed to allocate enrollee_bi\n"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + ret = dpp_build_bootstrap_info_from_uri(uri, enrollee_bi); + if (ret) { + fprintf(stderr, "Failed to build bootstrap info\n"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + ret = dpp_bootstrap_add(c->dpp, enrollee_bi); + if (ret) { + fprintf(stderr, "Failed to add bootstrap\n"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + //dpp_append_uri_file(c, uri); + + return UBUS_STATUS_OK; +} + static int cntlr_dpp_uri(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { + struct controller *c = container_of(obj, struct controller, obj); struct blob_attr *tb[__DPP_URI_MAX]; struct dpp_enrollee *e; @@ -870,9 +919,9 @@ DPP:C:81/1;M:b0dd74001c32;V:2;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgACtPpZTi2FPf1e /* TODO: parse correctly */ if (tb[DPP_URI_TYPE]) - e->type = DPP_BOOTSTRAP_QR_CODE; + e->type = DPP_BOOTSTRAP_QR_CODE_WIFI; else - e->type = DPP_BOOTSTRAP_QR_CODE; + e->type = DPP_BOOTSTRAP_QR_CODE_WIFI; dbg("|%s:%d| MAC "MACFMT" has URI %s\n", __func__, __LINE__, MAC2STR(e->mac), e->uri); @@ -3538,6 +3587,8 @@ int cntlr_publish_object(struct controller *c, const char *objname) #if (EASYMESH_VERSION > 2) UBUS_METHOD("dpp_enrollee_uri", cntlr_dpp_uri, dpp_uri_params), + UBUS_METHOD("dpp_enrollee_uri_eth", cntlr_dpp_uri_eth, + dpp_uri_params), #endif /* DPP */ UBUS_METHOD("steer_summary", cntlr_steer_summary, steer_summary_params), diff --git a/src/config.c b/src/config.c index 55c7d468384ea51a2b4942ee1f044dc7334cdef3..01a7a539a2cd8eae40161b0f98d13a0716cf111a 100644 --- a/src/config.c +++ b/src/config.c @@ -36,6 +36,8 @@ #include "config.h" #include "timer.h" #if (EASYMESH_VERSION > 2) +#include <dpp_api.h> + #include "dpp.h" #endif #include "cntlr.h" @@ -1230,6 +1232,24 @@ static int cntlr_config_get_credentials(struct controller_config *c, c->num_bss++; list_add_tail(&cred->list, &c->aplist); + +#if (EASYMESH_VERSION > 2) + if (cred->multi_ap & 0x01) { + struct controller *cntlr = container_of(c, struct controller, cfg); + const char *sec; + + if (tb[CRED_SEC]) + sec = tb[CRED_SEC]->v.string; + else + sec = "none"; + + dpp_set_configuration(cntlr->dpp, DPP_NETROLE_MAP_BH_STA, + dpp_akm_from_str(sec), + (char *) cred->ssid, + (char *) cred->key, + cred->band); + } +#endif return 0; } diff --git a/src/dpp.c b/src/dpp.c index 2f9e2894ce80482bb5bf028698fda9110da3b430..927845364b19a5690be278f3963ca49670af1324 100644 --- a/src/dpp.c +++ b/src/dpp.c @@ -49,7 +49,10 @@ #include "utils/debug.h" #include "utils/dpp_sock.h" #if (EASYMESH_VERSION > 2) +#include <dpp_api.h> + #include "dpp.h" +#include <math.h> #endif //#include "config.h" #include "cntlr.h" @@ -62,33 +65,9 @@ static void dpp_fd_timeout(atimer_t *t); -uint8_t *dpp_get_attr(uint8_t *buf, size_t len, uint16_t req_id, - uint16_t *ret_len) -{ - uint16_t id, alen; - uint8_t *pos = buf, *end = buf + len; - - while (end - pos >= 4) { - id = buf_get_le16(pos); - pos += 2; - alen = buf_get_le16(pos); - pos += 2; - if (alen > end - pos) - return NULL; - if (id == req_id) { - *ret_len = alen; - return pos; - } - pos += alen; - } - - return NULL; -} - - const char *dpp_type2str(enum dpp_bootstrap_type type) { - if (type == DPP_BOOTSTRAP_QR_CODE) + if (type == DPP_BOOTSTRAP_QR_CODE_WIFI) return "qrcode"; else if (type == DPP_BOOTSTRAP_PKEX) return "pkex"; @@ -157,23 +136,6 @@ const char *dpp_frame_type2str(uint8_t type) return "Unknown"; } -uint8_t dpp_get_pub_af_type(uint8_t *frame, uint16_t framelen) -{ - if (framelen < 7) - return 255; - - return *(frame + 6); -} - -uint8_t dpp_get_gas_frame_type(const uint8_t *frame, uint16_t framelen) -{ - if (framelen < 1) - return 255; - - return *frame; -} - - struct dpp_enrollee *dpp_enrollee_get(struct controller *c, uint8_t *mac) { struct dpp_enrollee *e; @@ -193,6 +155,9 @@ struct dpp_enrollee *dpp_enrollee_get_hash(struct controller *c, uint8_t *hash) list_for_each_entry(e, &c->dpp_ctx.enrolleelist, list) { struct dpp_chirp *p = e->chirp; + if (!memcmp(e->hash, hash, 32)) + return e; + if (!p) continue; @@ -214,6 +179,7 @@ struct dpp_enrollee *dpp_enrollee_alloc(struct controller *c, uint8_t *mac) return NULL; } + e->band = BAND_UNKNOWN; e->c = c; /* TODO: deprecate */ memcpy(e->mac, mac, 6); INIT_LIST_HEAD(&e->framelist); @@ -605,6 +571,8 @@ struct dpp_enrollee *dpp_process_new_uri(struct controller *c, char *uri) char *macstr; uint8_t enrollee[6] = {0}; struct dpp_enrollee *e; + char *hashstr; + char *hashend; int rc; if (strncmp(uri, "DPP:", 4)) { @@ -614,16 +582,22 @@ struct dpp_enrollee *dpp_process_new_uri(struct controller *c, char *uri) macstr = strstr(uri, ";M:"); // find mac address in URI if (!macstr) { - dbg("|%s:%d| URI has invalid format! (Right now) MAC is mandated\n", __func__, __LINE__); - return NULL; + macstr = strstr(uri, "DPP:M:"); // find mac address in URI + if (!macstr) { + dbg("|%s:%d| URI has invalid format! (Right now) MAC is mandated\n", __func__, __LINE__); + return NULL; + } + macstr += 3; /* step past DPP identifier */ } - if (*(macstr + 15) != ';') { + macstr += 3; /* step past mac identifier */ + + + if (*(macstr + 12) != ';') { dbg("|%s:%d| URI MAC has invalid format!\n", __func__, __LINE__); return NULL; } - macstr += 3; /* step past mac identifier */ strtob(macstr, 6, enrollee); e = dpp_enrollee_get(c, enrollee); @@ -640,15 +614,30 @@ struct dpp_enrollee *dpp_process_new_uri(struct controller *c, char *uri) strncpy(e->uri, uri, sizeof(e->uri) - 1); + hashstr = strstr(uri, ";K:"); + hashstr += 3 + 36; /* TODO: probably step 36 is not correct, but gives correct bytes in hashb output */ + hashend = strstr(hashstr, ";"); + + if (hashstr && hashend) { + uint8_t len = 0; + uint8_t hashb[128] = {0}; + size_t hlen = 128; + + len = abs(hashend - hashstr); + rc = base64_decode((unsigned char *) hashstr, (size_t)len, (unsigned char *) hashb, &hlen); + memcpy(e->hash, hashb, hlen); + dump(e->hash, hlen, "enrollee hash"); + } + dbg("|%s:%d| MAC "MACFMT" has URI %s\n", __func__, __LINE__, MAC2STR(e->mac), e->uri); send_dpp_cce_indication_all(c, true); rc = dpp_parse_uri_chan_list(c, e, e->uri); if (rc < 0) { - dbg("|%s:%d| URI MAC has invalid format! (Right now) Opclass/Channel list is mandated\n", __func__, __LINE__); - dpp_enrollee_free(e); - return NULL; + dbg("|%s:%d| URI chanlist has invalid format! (Right now) Opclass/Channel list is mandated\n", __func__, __LINE__); + // dpp_enrollee_free(e); + // return NULL; } if (e->num_chan) { e->band = wifi_channel_to_band(e->chan[0].channel); @@ -658,26 +647,26 @@ struct dpp_enrollee *dpp_process_new_uri(struct controller *c, char *uri) } - { - /* THIS IS A HACK */ - uint8_t bssid[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t radio[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - struct cmdu_buff *cmdu; - int len = 0; - - len = strlen(e->uri); - cmdu = cntlr_gen_dpp_bootstrapping_uri_notification(c, radio, bssid, - enrollee, len, e->uri); - if (cmdu) { - struct node *n; - - list_for_each_entry(n, &c->nodelist, list) { - memcpy(cmdu->origin, n->alid, 6); - send_cmdu(c, cmdu); - } - cmdu_free(cmdu); - } - } +// { +// /* THIS IS A HACK */ +// uint8_t bssid[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +// uint8_t radio[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +// struct cmdu_buff *cmdu; +// int len = 0; +// +// len = strlen(e->uri); +// cmdu = cntlr_gen_dpp_bootstrapping_uri_notification(c, radio, bssid, +// enrollee, len, e->uri); +// if (cmdu) { +// struct node *n; +// +// list_for_each_entry(n, &c->nodelist, list) { +// memcpy(cmdu->origin, n->alid, 6); +// send_cmdu(c, cmdu); +// } +// cmdu_free(cmdu); +// } +// } return e; } @@ -726,15 +715,101 @@ int dpp_cntlr_read_uris(struct controller *c) continue; if (strcmp("qr", blobmsg_data(tb1[1]))) - e->type = DPP_BOOTSTRAP_QR_CODE; + e->type = DPP_BOOTSTRAP_QR_CODE_WIFI; else - e->type = DPP_BOOTSTRAP_QR_CODE; + e->type = DPP_BOOTSTRAP_QR_CODE_WIFI; } out: blob_buf_free(&uris); return rc; } +int dpp_frame_handler(void *dpp, uint8_t *smac, enum dpp_event ev, + uint8_t *frame, size_t framelen) +{ + struct controller *c; + + err("%s: ----->\n", __func__); + + if (!smac) { + warn("%s: Error: smac = NULL\n", __func__); + return -1; + } + + 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; + + frametype = dpp_get_frame_type(frame + 1, framelen - 1); + if (frametype == 255) { + warn("Invalid frametype\n"); + return -1; + } + + c = dpp_get_ctx_private_data(dpp); + if (!c) + return -1; + + dbg("DPP frametype %s\n", dpp_frame_type2str(frametype)); + resp = cntlr_gen_direct_encap_dpp(c, smac, frame, framelen); + if (!resp) { + warn("|%s:%d| DPP: ----> Error generating proxy encap\n", + __func__, __LINE__); + return -1; + } + + switch (frametype) { + case DPP_PA_AUTHENTICATION_REQ: { +#if 0 /* TODO: will be needed for proxied encap */ + struct node *n; + + list_for_each_entry(n, &c->nodelist, list) { + memcpy(resp->origin, smac, 6); + send_cmdu(c, resp); + } + cmdu_free(resp); + + break; +#else + /* FALLTHROUGH */ +#endif + } + case DPP_PA_AUTHENTICATION_CONF: + case DPP_PUB_AF_GAS_INITIAL_RESP: + case DPP_PA_PEER_DISCOVERY_RESP: + 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; + } + return 0; +} static void dpp_fd_timeout(atimer_t *t) diff --git a/src/dpp.h b/src/dpp.h index a32f58c6bc00aafe77509885e654f9f51c15b7e5..0ab2eacd40276d7f80c17d7aa588a2cae6daf678 100644 --- a/src/dpp.h +++ b/src/dpp.h @@ -1,21 +1,7 @@ #ifndef DPP_H #define DPP_H -#define PUB_AF_CATEGORY 0x04 -#define DPP_PUB_AF_ACTION 0x09 -#define DPP_PUB_AF_ACTION_OUI_TYPE 0x1A -#define DPP_PUB_AF_GAS_INITIAL_REQ 0x0A -#define DPP_PUB_AF_GAS_INITIAL_RESP 0x0B - -#define FRAME_IS_DPP_PUB_AF(frame) \ - ((*(frame) == DPP_PUB_AF_ACTION) && \ - (memcmp((frame + 1), "\x50\x6F\x9A", 3) == 0) && \ - ((*(frame + 4)) == DPP_PUB_AF_ACTION_OUI_TYPE)) - -#define FRAME_IS_DPP_GAS_FRAME(frame) \ - ((*(frame) == DPP_PUB_AF_GAS_INITIAL_REQ) || \ - (*(frame) == DPP_PUB_AF_GAS_INITIAL_RESP)) - +#include <dpputils.h> #define FRAME_DST_ENROLLEE(type) \ ((type == DPP_PA_AUTHENTICATION_REQ) || \ @@ -23,63 +9,6 @@ #define DPP_URI_FILE "/etc/multiap/dpp_uris.json" -enum dpp_public_action_frame_type { - DPP_PA_AUTHENTICATION_REQ = 0, - DPP_PA_AUTHENTICATION_RESP = 1, - DPP_PA_AUTHENTICATION_CONF = 2, - DPP_PA_PEER_DISCOVERY_REQ = 5, - DPP_PA_PEER_DISCOVERY_RESP = 6, - DPP_PA_PKEX_V1_EXCHANGE_REQ = 7, - DPP_PA_PKEX_EXCHANGE_RESP = 8, - DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9, - DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10, - DPP_PA_CONFIGURATION_RESULT = 11, - DPP_PA_CONNECTION_STATUS_RESULT = 12, - DPP_PA_PRESENCE_ANNOUNCEMENT = 13, - DPP_PA_RECONFIG_ANNOUNCEMENT = 14, - DPP_PA_RECONFIG_AUTH_REQ = 15, - DPP_PA_RECONFIG_AUTH_RESP = 16, - DPP_PA_RECONFIG_AUTH_CONF = 17, - DPP_PA_PKEX_EXCHANGE_REQ = 18, -}; - -enum dpp_attribute_id { - DPP_ATTR_STATUS = 0x1000, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH = 0x1001, - DPP_ATTR_R_BOOTSTRAP_KEY_HASH = 0x1002, - DPP_ATTR_I_PROTOCOL_KEY = 0x1003, - DPP_ATTR_WRAPPED_DATA = 0x1004, - DPP_ATTR_I_NONCE = 0x1005, - DPP_ATTR_I_CAPABILITIES = 0x1006, - DPP_ATTR_R_NONCE = 0x1007, - DPP_ATTR_R_CAPABILITIES = 0x1008, - DPP_ATTR_R_PROTOCOL_KEY = 0x1009, - DPP_ATTR_I_AUTH_TAG = 0x100A, - DPP_ATTR_R_AUTH_TAG = 0x100B, - DPP_ATTR_CONFIG_OBJ = 0x100C, - DPP_ATTR_CONNECTOR = 0x100D, - DPP_ATTR_CONFIG_ATTR_OBJ = 0x100E, - DPP_ATTR_BOOTSTRAP_KEY = 0x100F, - DPP_ATTR_OWN_NET_NK_HASH = 0x1011, - DPP_ATTR_FINITE_CYCLIC_GROUP = 0x1012, - DPP_ATTR_ENCRYPTED_KEY = 0x1013, - DPP_ATTR_ENROLLEE_NONCE = 0x1014, - DPP_ATTR_CODE_IDENTIFIER = 0x1015, - DPP_ATTR_TRANSACTION_ID = 0x1016, - DPP_ATTR_BOOTSTRAP_INFO = 0x1017, - DPP_ATTR_CHANNEL = 0x1018, - DPP_ATTR_PROTOCOL_VERSION = 0x1019, - DPP_ATTR_ENVELOPED_DATA = 0x101A, - DPP_ATTR_SEND_CONN_STATUS = 0x101B, - DPP_ATTR_CONN_STATUS = 0x101C, - DPP_ATTR_RECONFIG_FLAGS = 0x101D, - DPP_ATTR_C_SIGN_KEY_HASH = 0x101E, - DPP_ATTR_CSR_ATTR_REQ = 0x101F, - DPP_ATTR_A_NONCE = 0x1020, - DPP_ATTR_E_PRIME_ID = 0x1021, - DPP_ATTR_CONFIGURATOR_NONCE = 0x1022, -}; - enum dpp_responder_state { DPP_BOOSTRAPPING, DPP_AUTHENTICATING, @@ -88,7 +17,7 @@ enum dpp_responder_state { /* taken from dpp.h */ enum dpp_bootstrap_type { - DPP_BOOTSTRAP_QR_CODE, + DPP_BOOTSTRAP_QR_CODE_WIFI, DPP_BOOTSTRAP_PKEX, DPP_BOOTSTRAP_NFC_URI, }; @@ -125,8 +54,10 @@ struct dpp_chan { struct dpp_enrollee { struct controller *c; /* TODO: lazy, should all be part of some dpp_ctx which can be traced back to cntlr */ + uint8_t almac[6]; uint8_t mac[6]; char uri[128]; + uint8_t hash[32]; bool onboarded; uint8_t bootstrap_id; @@ -142,28 +73,24 @@ struct dpp_enrollee { struct list_head list; }; -struct dpp_context { +struct dpp_context_wifi { struct list_head enrolleelist; struct list_head chirplist; }; struct controller; - -uint8_t *dpp_get_attr(uint8_t *buf, size_t len, uint16_t req_id, - uint16_t *ret_len); +enum dpp_event; const char *dpp_type2str(enum dpp_bootstrap_type type); const char *dpp_frame_type2str(uint8_t type); const char *dpp_state2str(enum dpp_responder_state state); -uint8_t dpp_get_pub_af_type(uint8_t *frame, uint16_t framelen); -uint8_t dpp_get_gas_frame_type(const uint8_t *frame, uint16_t framelen); - struct dpp_chirp *dpp_chirp_get(struct controller *c, uint8_t *hash); struct dpp_chirp *dpp_chirp_alloc(struct controller *c, uint8_t *hash); struct dpp_enrollee *dpp_enrollee_get(struct controller *c, uint8_t *mac); +struct dpp_enrollee *dpp_enrollee_get_hash(struct controller *c, uint8_t *hash); struct dpp_enrollee *dpp_enrollee_alloc(struct controller *c, uint8_t *mac); void dpp_enrollee_free(struct dpp_enrollee *e); @@ -192,4 +119,7 @@ struct dpp_enrollee *dpp_process_new_uri(struct controller *c, char *uri); int dpp_cntlr_read_uris(struct controller *c); void dpp_event_uloop_cb(struct uloop_fd *fd, unsigned int events); + +int dpp_frame_handler(void *dpp, uint8_t *smac, enum dpp_event ev, + uint8_t *frame, size_t framelen); #endif