diff --git a/src/cmdu.c b/src/cmdu.c index 13e972bf8a33dc434092d445bcc408eda4a9c6e8..029141b51864a959b2de977ff26b6ab7f0d91a31 100644 --- a/src/cmdu.c +++ b/src/cmdu.c @@ -101,11 +101,12 @@ int cmdu_should_relay(uint16_t type) type == CMDU_TYPE_PUSH_BUTTON_JOIN_NOTIFICATION); } +/* for unicast request types only */ int is_cmdu_type_response(uint16_t type) { return (type == CMDU_TYPE_TOPOLOGY_RESPONSE || type == CMDU_TYPE_LINK_METRIC_RESPONSE || - type == CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE || + /* type == CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE || */ type == CMDU_TYPE_HIGHER_LAYER_RESPONSE || type == CMDU_TYPE_INTERFACE_POWER_CHANGE_RESPONSE); } @@ -172,7 +173,7 @@ struct cmdu_buff *cmdu_alloc_default(void) return cmdu_alloc(ETH_FRAME_SZ); } -struct cmdu_buff *cmdu_alloc_simple(uint16_t type, uint16_t mid) +struct cmdu_buff *cmdu_alloc_simple(uint16_t type, uint16_t *mid) { struct cmdu_buff *f; @@ -187,10 +188,10 @@ struct cmdu_buff *cmdu_alloc_simple(uint16_t type, uint16_t mid) if (type <= CMDU_TYPE_MAX) cmdu_set_type(f, type); - if (mid == 0) - mid = cmdu_get_next_mid(); + if (*mid == 0) + *mid = cmdu_get_next_mid(); - cmdu_set_mid(f, mid); + cmdu_set_mid(f, *mid); CMDU_SET_LAST_FRAGMENT(f->cdata); f->data = (uint8_t *)(f->cdata + 1); diff --git a/src/cmdu.h b/src/cmdu.h index 9a78e8d57381c325c37d1d9cd7cf3935bf0af6f3..e435cd1dcd0fd40abdbd915d10bfb64d02ebf64a 100644 --- a/src/cmdu.h +++ b/src/cmdu.h @@ -53,6 +53,7 @@ struct cmdu_buff { uint8_t *tail; uint8_t *end; uint8_t dev_macaddr[6]; + char dev_ifname[16]; uint8_t origin[6]; uint16_t datalen; uint16_t len; @@ -96,7 +97,7 @@ void tlv_free_linear(struct tlv *t); struct cmdu_buff *cmdu_alloc(int size); struct cmdu_buff *cmdu_alloc_default(void); -struct cmdu_buff *cmdu_alloc_simple(uint16_t type, uint16_t mid); +struct cmdu_buff *cmdu_alloc_simple(uint16_t type, uint16_t *mid); void cmdu_free(struct cmdu_buff *c); diff --git a/src/cmdu_ackq.c b/src/cmdu_ackq.c index 9dd93d54ab8a4389b1eb7617c14a1866a1689703..20cf46180edef5904f2a9b151933dfd5b6ed4301 100644 --- a/src/cmdu_ackq.c +++ b/src/cmdu_ackq.c @@ -40,7 +40,8 @@ static int timeradd_msecs(struct timeval *a, unsigned long msecs, } struct cmdu_ackq_entry *cmdu_ackq_create_msg(uint16_t type, uint16_t mid, - uint8_t *dest, uint32_t timeout) + uint8_t *dest, uint32_t timeout, + void *cookie) { struct cmdu_ackq_entry *msg; struct timeval tsp = { 0 }; @@ -60,6 +61,7 @@ struct cmdu_ackq_entry *cmdu_ackq_create_msg(uint16_t type, uint16_t mid, //msg->ageing_tmo.tv_usec = roundup(msg->ageing_tmo.tv_usec, 1000); msg->ageing_tmo.tv_usec = (msg->ageing_tmo.tv_usec / 1000) * 1000; memcpy(msg->origin, dest, 6); + msg->cookie = cookie; fprintf(stderr, " CREATE msg: type = 0x%04x mid = %hu origin = " MACFMT " timeout = { %u (%lu:%lu) }\n", type, mid, MAC2STR(dest), msg->ageing_time, msg->ageing_tmo.tv_sec, msg->ageing_tmo.tv_usec / 1000); @@ -69,8 +71,12 @@ struct cmdu_ackq_entry *cmdu_ackq_create_msg(uint16_t type, uint16_t mid, static void cmdu_ackq_delete_msg(struct cmdu_ackq_entry *msg) { - if (msg) + if (msg) { + if (msg->cookie) + free(msg->cookie); + free(msg); + } } static void cmdu_ackq_ageout_entry(struct cmdu_ackq *st, struct hlist_head *head, @@ -96,7 +102,7 @@ static void cmdu_ackq_ageout_entry(struct cmdu_ackq *st, struct hlist_head *head hlist_del(&msg->hlist, head); fprintf(stderr, "No response from " MACFMT " for CMDU 0x%x with mid = %hu\n", MAC2STR(msg->origin), msg->mid, msg->type); - cmdu_ackq_delete_msg(msg); + cmdu_ackq_delete_msg(msg); //TODO: user decides timeout action } else { struct timeval new_next_tmo = { 0 }; @@ -210,7 +216,7 @@ void cmdu_ackq_reset(void *cmdu_q) /* In this function, type = cmdutype that is expected with 'mid' from 'dest' */ int cmdu_ackq_enqueue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *dest, - uint32_t timeout) + uint32_t timeout, void *cookie) { struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q; struct cmdu_ackq_entry *msg = NULL; @@ -224,7 +230,7 @@ int cmdu_ackq_enqueue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *dest, return -1; } - msg = cmdu_ackq_create_msg(type, mid, dest, timeout); + msg = cmdu_ackq_create_msg(type, mid, dest, timeout, cookie); if (msg) { int idx = cmdu_ackq_hash(type, mid, dest); @@ -233,7 +239,7 @@ int cmdu_ackq_enqueue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *dest, q->pending_cnt++; fprintf(stderr, - "ENQ: type = 0x%04x mid = %hu origin = " MACFMT "\n", + " ENQ: type = 0x%04x mid = %hu origin = " MACFMT "\n", type, mid, MAC2STR(dest)); @@ -259,7 +265,7 @@ int cmdu_ackq_enqueue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *dest, return -1; } -int cmdu_ackq_dequeue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *src) +int cmdu_ackq_dequeue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *src, void **cookie) { struct cmdu_ackq *q = (struct cmdu_ackq *)cmdu_q; struct cmdu_ackq_entry *msg = NULL; @@ -285,6 +291,11 @@ int cmdu_ackq_dequeue(void *cmdu_q, uint16_t type, uint16_t mid, uint8_t *src) "DEQ: type = 0x%04x mid = %hu origin = " MACFMT "\n", type, mid, MAC2STR(src)); + + /* After returning cookie back to user, we can safely delete the msg */ + *cookie = msg->cookie; + msg->cookie = NULL; + cmdu_ackq_delete_msg(msg); return 0; diff --git a/src/cmdu_ackq.h b/src/cmdu_ackq.h index 96a043231b503fd209cd43afa3c474949374f286..24cc12e4768e27f65b7c666e581a5814135341f6 100644 --- a/src/cmdu_ackq.h +++ b/src/cmdu_ackq.h @@ -31,6 +31,7 @@ struct cmdu_ackq_entry { uint16_t type; uint16_t mid; uint8_t origin[6]; + void *cookie; struct hlist_node hlist; uint32_t ageing_time; /* in msecs */ @@ -51,9 +52,9 @@ struct cmdu_ackq { extern int cmdu_ackq_init(void *q); extern void cmdu_ackq_reset(void *q); -extern int cmdu_ackq_dequeue(void *q, uint16_t type, uint16_t mid, uint8_t *src); +extern int cmdu_ackq_dequeue(void *q, uint16_t type, uint16_t mid, uint8_t *src, void **cookie); extern int cmdu_ackq_enqueue(void *q, uint16_t type, uint16_t mid, uint8_t *dest, - uint32_t timeout); + uint32_t timeout, void *cookie); #endif /* CMDU_ACKQ_H */ diff --git a/src/cmdu_input.c b/src/cmdu_input.c index 33ae1987cc087514240c1536956d6718b6fa4652..0a574a074fd99dc13b525133b02a5c9dde637bd9 100644 --- a/src/cmdu_input.c +++ b/src/cmdu_input.c @@ -52,7 +52,7 @@ int i1905_handle_topology_discovery(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_AL_MAC_ADDRESS_TYPE, .present = TLV_PRESENT_ONE }, @@ -95,7 +95,7 @@ int i1905_handle_topology_discovery(struct i1905_interface_private *pif, } int i1905_handle_topology_notification(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_AL_MAC_ADDRESS_TYPE, .present = TLV_PRESENT_ONE }, @@ -136,13 +136,13 @@ int i1905_handle_topology_notification(struct i1905_interface_private *pif, } int i1905_handle_topology_query(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { return i1905_send_topology_response(pif, rxf->origin, cmdu_get_mid(rxf)); } int i1905_handle_topology_response(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_DEVICE_INFORMATION_TYPE, .present = TLV_PRESENT_ONE }, @@ -218,14 +218,14 @@ int i1905_handle_topology_response(struct i1905_interface_private *pif, } int i1905_handle_vendor_request(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; } int i1905_handle_link_metric_query(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_LINK_METRIC_QUERY, .present = TLV_PRESENT_ONE }, @@ -270,7 +270,7 @@ int i1905_handle_link_metric_query(struct i1905_interface_private *pif, } int i1905_handle_link_metric_response(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_TRANSMITTER_LINK_METRIC, .present = TLV_PRESENT_MORE}, @@ -332,18 +332,18 @@ int i1905_handle_link_metric_response(struct i1905_interface_private *pif, } int i1905_handle_ap_autoconfig_search(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_AL_MAC_ADDRESS_TYPE, .present = TLV_PRESENT_ONE }, [1] = { .type = TLV_TYPE_SEARCHED_ROLE, .present = TLV_PRESENT_ONE }, [2] = { .type = TLV_TYPE_AUTOCONFIG_FREQ_BAND, .present = TLV_PRESENT_ONE }, }; - struct i1905_interface *iface = i1905_interface_priv(pif); + //struct i1905_interface *iface = i1905_interface_priv(pif); struct tlv_autoconfig_band *freq; uint8_t aladdr_origin[6] = {0}; struct tlv *tv[3][16]; - int ret; + int ret = 0; fprintf(stderr, "%s -------------->\n", __func__); @@ -383,17 +383,19 @@ int i1905_handle_ap_autoconfig_search(struct i1905_interface_private *pif, freq->band, cmdu_get_mid(rxf)); } else { - ret = i1905_send_cmdu(pif, MCAST_1905, iface->aladdr, - ETHERTYPE_1905, rxf); - if (ret) - fprintf(stderr, "Error sending AP_AUTOCONFIG_SEARCH\n"); + fprintf(stderr, "%s: XXXXXXXXXXXX %d XXXXXXXXXXXX\n", __func__, __LINE__); + //TODO: TODO: TODO + //ret = i1905_send_cmdu(pif, MCAST_1905, iface->aladdr, + // ETHERTYPE_1905, rxf); + //if (ret) + // fprintf(stderr, "Error sending AP_AUTOCONFIG_SEARCH\n"); } return ret; } int i1905_handle_ap_autoconfig_response(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_SUPPORTED_ROLE, .present = TLV_PRESENT_ONE }, @@ -405,6 +407,7 @@ int i1905_handle_ap_autoconfig_response(struct i1905_interface_private *pif, struct i1905_interface *ifs; struct tlv *tv[2][16]; int ret; + struct i1905_interface *outif; fprintf(stderr, "%s -------------->\n", __func__); @@ -435,12 +438,23 @@ int i1905_handle_ap_autoconfig_response(struct i1905_interface_private *pif, //registrar_established. //Else, send WSC-M1 for each unconfigured i1905 WiFi radios + outif = i1905_ifname_to_interface(pif->i1905private, rxf->dev_ifname); + if (!outif) { + fprintf(stderr, "Error handling AP-AUTOCONFIG RESPONSE!\n"); + return -1; + } + list_for_each_entry(ifs, &self->iflist, list) { + if (IS_MEDIA_WIFI_2GHZ(ifs->media) && freq->band != IEEE80211_FREQUENCY_BAND_2_4_GHZ) + continue; + + if (IS_MEDIA_WIFI_5GHZ(ifs->media) && freq->band != IEEE80211_FREQUENCY_BAND_5_GHZ) + continue; + if (IS_MEDIA_WIFI(ifs->media) && !((struct i1905_interface_private *)ifs->priv)->configured) { - //TODO: check band in supported-bands - ret = i1905_send_ap_autoconfig_wsc_m1(ifs->priv, rxf->origin); + ret = i1905_send_ap_autoconfig_wsc_m1(outif->priv, ifs->priv, rxf->origin); if (ret) { fprintf(stderr, "Error sending AP_AUTOCONFIG_WSC_M1\n"); break; @@ -452,7 +466,7 @@ int i1905_handle_ap_autoconfig_response(struct i1905_interface_private *pif, } int i1905_handle_ap_autoconfig_renew(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_AL_MAC_ADDRESS_TYPE, .present = TLV_PRESENT_ONE }, @@ -494,7 +508,7 @@ int i1905_handle_ap_autoconfig_renew(struct i1905_interface_private *pif, list_for_each_entry(ifs, &self->iflist, list) { if (IS_MEDIA_WIFI(ifs->media)) { //TODO: check band in supported-bands - ret = i1905_send_ap_autoconfig_wsc_m1(ifs->priv, rxf->origin); + ret = i1905_send_ap_autoconfig_wsc_m1(ifs->priv, ifs->priv, rxf->origin); //FIXME priv if (ret) { fprintf(stderr, "Error sending AP_AUTOCONFIG_WSC_M1\n"); break; @@ -506,14 +520,15 @@ int i1905_handle_ap_autoconfig_renew(struct i1905_interface_private *pif, } static int i1905_wsc_process_m1(struct i1905_interface_private *pif, - uint8_t *msg, uint16_t msglen) + uint8_t *msg, uint16_t msglen, uint16_t mid, + uint8_t *from) { struct i1905_interface *iface = i1905_interface_priv(pif); //struct i1905_interface_private_wsc *wsc = pif->wsc; int ret; uint8_t *m2; uint16_t m2_size; - struct wps_credential cred; + struct wps_credential cred = {0}; //ret = wsc_process_m1(iface->ifname, msg, msglen); @@ -521,40 +536,80 @@ static int i1905_wsc_process_m1(struct i1905_interface_private *pif, //TODO: get cred from config file //i1905_interface_credential(&cred); - +#if 1 // TESTING TODO + strcpy((char *)cred.ssid, "TestSSID-123"); + cred.ssidlen = strlen("TestSSID-123"); + cred.auth_type = 0; + cred.enc_type = 0x4; + strcpy((char *)cred.key, "password"); + cred.keylen = strlen("password"); + cred.band = 2; +#endif ret = wsc_build_m2(msg, msglen, &m2, &m2_size, &cred); if (ret) { fprintf(stderr, "Error sending WSC M2 for '%s'\n", iface->ifname); return ret; } + ret = i1905_send_ap_autoconfig_wsc_m2(pif, m2, m2_size, mid, from); return 0; } static int i1905_wsc_process_m2(struct i1905_interface_private *pif, - uint8_t *msg, uint16_t msglen) + uint8_t *msg, uint16_t msglen, uint16_t mid, + uint8_t *from, void *cookie) { struct i1905_interface *iface = i1905_interface_priv(pif); - struct i1905_interface_private_wsc *wsc = pif->wsc; + struct i1905_interface_private *ifpriv; + struct i1905_interface_private_wsc *wsc; struct wps_credential out = {0}; int ret; + char *ifname = cookie; + struct i1905_interface *ifwsc; - ret = wsc_process_m2(iface->ifname, wsc->key, wsc->last_msg, + fprintf(stderr, "%s: Process M2. ingress ifname = %s (cookie = %s)\n", __func__, iface->ifname, ifname); + + if (!cookie) { + fprintf(stderr, + "cookie = NULL! Valid cookie expected for WSC-M2 processing!\n"); + return 0; + } + + + ifwsc = i1905_ifname_to_interface(pif->i1905private, ifname); + if (!ifwsc) { + fprintf(stderr, "Failed to match interface cookie '%s'\n", ifname); + return -1; + } + + ifpriv = ifwsc->priv; + wsc = ifpriv->wsc; + if (!wsc) { + fprintf(stderr, "%s: wsc = NULL! Unexpected error!\n", __func__); + return -1; + } + + ret = wsc_process_m2(ifwsc->ifname, wsc->key, wsc->last_msg, wsc->last_msglen, msg, msglen, &out); if (ret) { - fprintf(stderr, "Error processing WSC M2 for '%s'\n", iface->ifname); + fprintf(stderr, "Error processing WSC M2 for '%s'\n", ifwsc->ifname); return ret; } /* TODO: update wireless config */ - +#if 1 // TESTING + fprintf(stderr, "####################################################\n"); + fprintf(stderr, "Ssid: %s (len = %u)\n", out.ssid, out.ssidlen); + fprintf(stderr, "Key : %s (len = %u)\n", out.key, out.keylen); + fprintf(stderr, "####################################################\n"); +#endif return 0; } int i1905_handle_ap_autoconfig_wsc(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_WSC, .present = TLV_PRESENT_ONE }, @@ -565,7 +620,9 @@ int i1905_handle_ap_autoconfig_wsc(struct i1905_interface_private *pif, uint8_t wsc_msgtype; uint16_t msglen; uint8_t *msg; + uint16_t mid; int ret = 0; + void *m1_cookie = NULL; fprintf(stderr, "%s -------------->\n", __func__); @@ -578,15 +635,29 @@ int i1905_handle_ap_autoconfig_wsc(struct i1905_interface_private *pif, msg = tv[0][0]->data; msglen = tlv_length(tv[0][0]); + mid = cmdu_get_mid(rxf); + wsc_msgtype = wsc_get_message_type(msg, msglen); switch (wsc_msgtype) { case WPS_M1: fprintf(stderr, "Received WPS M1\n"); - ret = i1905_wsc_process_m1(pif, msg, msglen); + ret = i1905_wsc_process_m1(pif, msg, msglen, mid, rxf->origin); break; case WPS_M2: fprintf(stderr, "Received WPS M2\n"); - ret = i1905_wsc_process_m2(pif, msg, msglen); + + ret = cmdu_ackq_dequeue(&pif->txack_q, + CMDU_TYPE_AP_AUTOCONFIGURATION_WSC, + mid, rxf->origin, &m1_cookie); + if (!ret && m1_cookie) { + ret = i1905_wsc_process_m2(pif, msg, msglen, mid, rxf->origin, m1_cookie); + free(m1_cookie); + } else { + fprintf(stderr, + "%s: drop unexpected WSC-M2 CMDU (mid = %d)\n", + __func__, mid); + return -1; + } break; default: fprintf(stderr, "Received WPS msgtype %u\n", wsc_msgtype); @@ -597,27 +668,27 @@ int i1905_handle_ap_autoconfig_wsc(struct i1905_interface_private *pif, } int i1905_handle_pbc_notification(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; } int i1905_handle_pbc_join_notification(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; } int i1905_handle_higherlayer_query(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { return i1905_send_higherlayer_response(pif, rxf->origin, cmdu_get_mid(rxf)); } int i1905_handle_higherlayer_response(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { struct tlv_policy a_policy[] = { [0] = { .type = TLV_TYPE_AL_MAC_ADDRESS_TYPE, .present = TLV_PRESENT_ONE }, @@ -683,28 +754,28 @@ int i1905_handle_higherlayer_response(struct i1905_interface_private *pif, } int i1905_handle_interface_power_request(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; } int i1905_handle_interface_power_response(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; } int i1905_handle_generic_phy_query(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; } int i1905_handle_generic_phy_response(struct i1905_interface_private *pif, - struct cmdu_buff *rxf) + struct cmdu_buff *rxf, void *cookie) { //TODO return 0; @@ -712,7 +783,7 @@ int i1905_handle_generic_phy_response(struct i1905_interface_private *pif, typedef int (*cmdu_handler_t)(struct i1905_interface_private *ifp, - struct cmdu_buff *rxf); + struct cmdu_buff *rxf, void *cookie); static const cmdu_handler_t i1905ftable[] = { [0x00] = i1905_handle_topology_discovery, @@ -744,6 +815,7 @@ int i1905_process_cmdu(struct i1905_interface_private *pif, struct cmdu_buff *rx uint8_t *src; cmdu_res_t res; int ret; + void *cookie = NULL; if (!rxf->cdata) { @@ -781,7 +853,7 @@ int i1905_process_cmdu(struct i1905_interface_private *pif, struct cmdu_buff *rx if (is_cmdu_type_response(type)) { /* discard responses with no matching request awaiting */ - ret = cmdu_ackq_dequeue(&pif->txack_q, type, mid, src); + ret = cmdu_ackq_dequeue(&pif->txack_q, type, mid, src, &cookie); if (ret) { fprintf(stderr, "%s: drop unexpected CMDU (mid = %d)\n", __func__, mid); @@ -790,7 +862,7 @@ int i1905_process_cmdu(struct i1905_interface_private *pif, struct cmdu_buff *rx } if (i1905ftable[type]) - ret = i1905ftable[type](pif, rxf); + ret = i1905ftable[type](pif, rxf, cookie); return ret; diff --git a/src/cmdu_output.c b/src/cmdu_output.c index 60a186f67e6d6fb17157045db80f6ce34e9ad208..c94150ea8a8955f57ffb5cd40ea73dd45f905b38 100644 --- a/src/cmdu_output.c +++ b/src/cmdu_output.c @@ -53,6 +53,7 @@ int i1905_send_topology_query(struct i1905_interface_private *pif, uint8_t *dest struct i1905_interface *iface = i1905_interface_priv(pif); struct cmdu_buff *frm = NULL; int ret = 0; + uint16_t mid = 0; if (!dest) @@ -62,7 +63,7 @@ int i1905_send_topology_query(struct i1905_interface_private *pif, uint8_t *dest fprintf(stderr, "%s: Send TOPOLOGY QUERY to " MACFMT "\n", __func__, MAC2STR(dest)); - frm = cmdu_alloc_simple(CMDU_TYPE_TOPOLOGY_QUERY, 0); + frm = cmdu_alloc_simple(CMDU_TYPE_TOPOLOGY_QUERY, &mid); if (!frm) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -103,7 +104,7 @@ int i1905_send_topology_response(struct i1905_interface_private *pif, - resp = cmdu_alloc_simple(CMDU_TYPE_TOPOLOGY_RESPONSE, mid); + resp = cmdu_alloc_simple(CMDU_TYPE_TOPOLOGY_RESPONSE, &mid); if (!resp) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -280,7 +281,7 @@ int i1905_send_link_metric_response(struct i1905_interface_private *pif, - resp = cmdu_alloc_simple(CMDU_TYPE_LINK_METRIC_RESPONSE, mid); + resp = cmdu_alloc_simple(CMDU_TYPE_LINK_METRIC_RESPONSE, &mid); if (!resp) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -472,6 +473,7 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband struct cmdu_buff *frm = NULL; struct tlv *t; int ret = 0; + uint16_t mid = 0; /* @@ -483,7 +485,7 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband */ - frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH, 0); + frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH, &mid); if (!frm) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -544,11 +546,23 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband cmdu_put_eom(frm); + fprintf(stderr, "%s:%d: ifname = %s\n", __func__, __LINE__, ifs->ifname); ret = i1905_send_cmdu(ifs->priv, MCAST_1905, ifs->aladdr, ETHERTYPE_1905, frm); if (ret) { fprintf(stderr, "Error sending AP_AUTOCONFIG_SEARCH\n"); } + +#if 0 + //TODO: move this to i1905_send_cmdu() + resp_type = cmdu_expect_response(CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH); + if (resp_type != CMDU_TYPE_NONE) { + struct i1905_interface_private *ifp = ifs->priv; + + cmdu_ackq_enqueue(&ifp->txack_q, resp_type, *mid, dst, + CMDU_DEFAULT_TIMEOUT); + } +#endif } return 0; @@ -576,9 +590,10 @@ int i1905_send_ap_autoconfig_renew(struct i1905_private *priv, uint8_t freqband) struct cmdu_buff *frm = NULL; struct tlv *t; int ret = 0; + uint16_t mid = 0; - frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW, 0); + frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW, &mid); if (!frm) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -663,7 +678,7 @@ int i1905_send_ap_autoconfig_response(struct i1905_interface_private *pif, - resp = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE, mid); + resp = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE, &mid); if (!resp) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -713,7 +728,8 @@ int i1905_send_ap_autoconfig_response(struct i1905_interface_private *pif, return ret; } -int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *pif, +int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *out_pif, + struct i1905_interface_private *pif, uint8_t *dest) { struct i1905_interface *iface = i1905_interface_priv(pif); @@ -730,9 +746,11 @@ int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *pif, //uint16_t auth = WPA2PSK; //uint16_t enc = CCMP; struct wps_data wps; + uint16_t resp_type; + uint16_t mid = 0; - frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_WSC, 0); + frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_WSC, &mid); if (!frm) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; @@ -756,7 +774,7 @@ int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *pif, pif->wsc->key = key; } - t = cmdu_reserve_tlv(frm, FRAG_DATA_SIZE_TLV); + t = cmdu_reserve_tlv(frm, 1024); if (!t) { cmdu_free(frm); return -1; @@ -774,7 +792,61 @@ int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *pif, cmdu_put_eom(frm); - ret = i1905_send_cmdu(pif, dest, iface->aladdr, ETHERTYPE_1905, frm); + fprintf(stderr, "%s:%d: out-ifname = %s dest = " MACFMT " mid = %hu\n", + __func__, __LINE__, iface->ifname, MAC2STR(dest), mid); + ret = i1905_send_cmdu(out_pif, dest, iface->aladdr, ETHERTYPE_1905, frm); + if (ret) { + fprintf(stderr, "Error sending AP_AUTOCONFIG_WSC_M1\n"); + } + + //TODO: move following to i1905_send_cmdu() + resp_type = cmdu_expect_response(CMDU_TYPE_AP_AUTOCONFIGURATION_WSC); + if (resp_type != CMDU_TYPE_NONE) { + cmdu_ackq_enqueue(&out_pif->txack_q, resp_type, mid, dest, + 2 * CMDU_DEFAULT_TIMEOUT, strdup(iface->ifname)); + } + + return ret; +} + +int i1905_send_ap_autoconfig_wsc_m2(struct i1905_interface_private *out_pif, + uint8_t *msg, uint16_t msglen, uint16_t mid, + uint8_t *dest) +{ + struct i1905_interface *iface = i1905_interface_priv(out_pif); + struct cmdu_buff *frm; + struct tlv *t; + int ret; + + + frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_WSC, &mid); + if (!frm) { + fprintf(stderr, "%s: -ENOMEM\n", __func__); + return -1; + } + + t = cmdu_reserve_tlv(frm, 1024); + if (!t) { + cmdu_free(frm); + return -1; + } + + t->type = TLV_TYPE_WSC; + t->len = msglen; + memcpy(t->data, msg, msglen); + ret = cmdu_put_tlv(frm, t); + if (ret) { + fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__); + cmdu_free(frm); + return -1; + } + + cmdu_put_eom(frm); + + fprintf(stderr, "%s:%d: out-ifname = %s dest = " MACFMT "\n", + __func__, __LINE__, iface->ifname, MAC2STR(dest)); + + ret = i1905_send_cmdu(out_pif, dest, iface->aladdr, ETHERTYPE_1905, frm); if (ret) { fprintf(stderr, "Error sending AP_AUTOCONFIG_WSC_M1\n"); } @@ -799,7 +871,7 @@ int i1905_send_higherlayer_response(struct i1905_interface_private *pif, - resp = cmdu_alloc_simple(CMDU_TYPE_HIGHER_LAYER_RESPONSE, mid); + resp = cmdu_alloc_simple(CMDU_TYPE_HIGHER_LAYER_RESPONSE, &mid); if (!resp) { fprintf(stderr, "%s: -ENOMEM\n", __func__); return -1; diff --git a/src/i1905.c b/src/i1905.c index ec57f1eaf5b0398146702f91523c8b3494b9d65b..d3e50c6c72ebc2230c76ed4b6a1e7cd5f16d0afc 100644 --- a/src/i1905.c +++ b/src/i1905.c @@ -340,6 +340,23 @@ static void i1905_free_interface(struct i1905_interface *iface) } } +struct i1905_interface *i1905_ifname_to_interface(struct i1905_private *priv, + const char *ifname) +{ + struct i1905_interface *ifs; + struct i1905_selfdevice *self; + + + self = &priv->dm.self; + + list_for_each_entry(ifs, &self->iflist, list) { + if (!strncmp(ifs->ifname, ifname, 16)) + return ifs; + } + + return NULL; +} + int i1905_send_cmdu(struct i1905_interface_private *ifp, uint8_t *dst, uint8_t *src, uint16_t ethtype, struct cmdu_buff *frm) @@ -448,7 +465,7 @@ int i1905_cmdu_tx(struct i1905_interface_private *ifp, resp_type = cmdu_expect_response(type); if (resp_type != CMDU_TYPE_NONE) { cmdu_ackq_enqueue(&ifp->txack_q, resp_type, *mid, dst, - CMDU_DEFAULT_TIMEOUT); + CMDU_DEFAULT_TIMEOUT, NULL); } return 0; @@ -481,6 +498,7 @@ static void i1905_recv_1905(struct uloop_fd *fd, unsigned int events) break; } + fprintf(stderr, "%s: Rx 1905 CMDU ifname = %s\n", __func__, iface->ifname); bufprintf(rxf->head, res, "Received 1905 CMDU"); if (*(rxf->head + 12) == 0x81 && *(rxf->head + 13) == 0x00) { @@ -493,6 +511,7 @@ static void i1905_recv_1905(struct uloop_fd *fd, unsigned int events) rxf->datalen = res - eth_hdrsize - sizeof(struct cmdu_header); rxf->tail = rxf->data + rxf->datalen; memcpy(rxf->dev_macaddr, iface->macaddr, 6); + strncpy(rxf->dev_ifname, iface->ifname, 15); memcpy(rxf->origin, rxf->head + 6, 6); if (!IS_CMDU_LAST_FRAGMENT(rxf->cdata)) { @@ -1207,7 +1226,7 @@ int i1905_apconfig_request(void *priv, uint8_t band) //if (!i1905_has_registrar(priv, freqband)) // return -EINVAL; - ret |= i1905_send_ap_autoconfig_search(priv, freqband); + return i1905_send_ap_autoconfig_search(priv, freqband); } /* for all wifi bands */ diff --git a/src/i1905.h b/src/i1905.h index b64c897b10a8287ff50feb9166181591da46c290..86729cba65058f380eb3e685bce380a5effea558 100644 --- a/src/i1905.h +++ b/src/i1905.h @@ -101,6 +101,10 @@ bool i1905_has_registrar(void *priv, uint8_t freqband); int i1905_apconfig_request(void *priv, uint8_t band); int i1905_apconfig_renew(void *priv, uint8_t band); + +struct i1905_interface *i1905_ifname_to_interface(struct i1905_private *priv, + const char *ifname); + int i1905_cmdu_tx(struct i1905_interface_private *ifp, uint8_t *dst, uint8_t *src, uint16_t type, uint16_t *mid, uint8_t *data, int datalen); @@ -131,9 +135,15 @@ int i1905_send_ap_autoconfig_renew(struct i1905_private *priv, int i1905_send_ap_autoconfig_response(struct i1905_interface_private *pif, uint8_t *dest, uint8_t band, uint16_t mid); -int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *pif, +int i1905_send_ap_autoconfig_wsc_m1(struct i1905_interface_private *out_pif, + struct i1905_interface_private *pif, uint8_t *dest); +int i1905_send_ap_autoconfig_wsc_m2(struct i1905_interface_private *out_pif, + uint8_t *msg, uint16_t msglen, + uint16_t mid, uint8_t *dest); + + int i1905_send_higherlayer_response(struct i1905_interface_private *pif, uint8_t *dest, uint16_t mid); diff --git a/src/i1905_wsc.c b/src/i1905_wsc.c index bf8d0d139d807408b00fb4877bebcff3a42fc280..256d7f3939ac2112acf45f61c7f2a7581ae58dca 100644 --- a/src/i1905_wsc.c +++ b/src/i1905_wsc.c @@ -799,13 +799,13 @@ int wsc_build_m2(uint8_t *m1, uint16_t m1_size, uint8_t **m2, uint16_t *m2_size, */ uint32_t setting_len = abs(r - plain); - bufptr_put_be16(r, ATTR_ENCR_SETTINGS); - bufptr_put_be16(r, AES_BLOCK_SIZE + setting_len); + bufptr_put_be16(p, ATTR_ENCR_SETTINGS); + bufptr_put_be16(p, AES_BLOCK_SIZE + setting_len); iv_start = p; get_random_bytes(AES_BLOCK_SIZE, p); p += AES_BLOCK_SIZE; data_start = p; - memcpy(plain, p, setting_len); + bufptr_put(p, plain, setting_len); /* Encrypt the data in-place. * Note that the "ATTR_ENCR_SETTINGS" attribute containes both @@ -857,16 +857,16 @@ int wsc_process_m2(const char *ifname, void *key, uint8_t *m1, uint16_t m1_size, struct wsc_key *k; uint8_t mapie = 0; - uint8_t ssid[33]; + uint8_t ssid[33] = {0}; uint8_t ssid_present; int ssidlen = 0; - uint8_t bssid[6]; + uint8_t bssid[6] = {0}; uint8_t bssid_present; uint16_t auth_type; uint8_t auth_type_present; uint16_t enc_type; uint8_t enc_type_present; - uint8_t network_key[64]; + uint8_t network_key[64] = {0}; int network_keylen = 0; uint8_t network_key_present; //uint8_t band = 0; @@ -1145,29 +1145,25 @@ int wsc_process_m2(const char *ifname, void *key, uint8_t *m1, uint16_t m1_size, if (attr_len > 32) break; - bufptr_get(p, ssid, attr_len); + memcpy(ssid, p, attr_len); ssidlen = attr_len; - //ssid[attr_len] = 0x00; ssid_present = 1; break; case ATTR_AUTH_TYPE: auth_type = buf_get_be16(p); - p += 2; auth_type_present = 1; break; case ATTR_ENCR_TYPE: enc_type = buf_get_be16(p); - p += 2; enc_type_present = 1; break; case ATTR_NETWORK_KEY: - bufptr_get(p, network_key, attr_len); + memcpy(network_key, p, attr_len); network_keylen = attr_len; - //network_key[attr_len] = 0x00; network_key_present = 1; break; case ATTR_MAC_ADDR: - bufptr_get(p, bssid, attr_len); + memcpy(bssid, p, attr_len); bssid_present = 1; break; case ATTR_KEY_WRAP_AUTH: @@ -1199,17 +1195,17 @@ int wsc_process_m2(const char *ifname, void *key, uint8_t *m1, uint16_t m1_size, // May be one or more subelements (Section 12 of WSC spec) end_of_mapie = p + attr_len; - bufptr_get(p, id, sizeof(id)); + memcpy(id, p, sizeof(id)); if (id[0] ^ WFA_VENDOR_ID_1 || id[1] ^ WFA_VENDOR_ID_2 || id[2] ^ WFA_VENDOR_ID_3) { //p += (attr_len - sizeof(id)); - p -= sizeof(id); break; } +#if 0 //TODO TODO while (p < end_of_mapie) { bufptr_get(p, &subelem, 1); bufptr_get(p, &len, 1); @@ -1220,6 +1216,7 @@ int wsc_process_m2(const char *ifname, void *key, uint8_t *m1, uint16_t m1_size, p += len; } } +#endif } break; default: @@ -1241,7 +1238,9 @@ int wsc_process_m2(const char *ifname, void *key, uint8_t *m1, uint16_t m1_size, } memcpy(out->ssid, ssid, ssidlen); + out->ssidlen = ssidlen; memcpy(out->key, network_key, network_keylen); + out->keylen = network_keylen; out->auth_type = auth_type; out->enc_type = enc_type; out->mapie = mapie;