#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED "
/** M2D received */
#define WPS_EVENT_M2D "WPS-M2D "
+/** WPS registration failed after M2/M2D */
+#define WPS_EVENT_FAIL "WPS-FAIL "
/* hostapd control interface - fixed message prefixes */
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
enum wps_event {
- WPS_EV_M2D
+ WPS_EV_M2D,
+ WPS_EV_FAIL
};
union wps_event_data {
u16 config_error;
u16 dev_password_id;
} m2d;
+ struct wps_event_fail {
+ int msg; /* enum wps_msg_type */
+ } fail;
};
/**
/* Append checksum digit */
return val * 10 + wps_pin_checksum(val);
}
+
+
+void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg)
+{
+ union wps_event_data data;
+
+ if (wps->event_cb == NULL)
+ return;
+
+ os_memset(&data, 0, sizeof(data));
+ data.fail.msg = msg;
+ wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
+}
break;
case WPS_M4:
ret = wps_process_m4(wps, msg, &attr);
+ if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
+ wps_fail_event(wps->wps, WPS_M4);
break;
case WPS_M6:
ret = wps_process_m6(wps, msg, &attr);
+ if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
+ wps_fail_event(wps->wps, WPS_M6);
break;
case WPS_M8:
ret = wps_process_m8(wps, msg, &attr);
+ if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
+ wps_fail_event(wps->wps, WPS_M8);
break;
default:
wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with "
"Configuration Error %d", WPA_GET_BE16(attr.config_error));
+ switch (wps->state) {
+ case RECV_M4:
+ wps_fail_event(wps->wps, WPS_M3);
+ break;
+ case RECV_M6:
+ wps_fail_event(wps->wps, WPS_M5);
+ break;
+ case RECV_M8:
+ wps_fail_event(wps->wps, WPS_M7);
+ break;
+ default:
+ break;
+ }
+
+ /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if
+ * Enrollee is Authenticator */
+ wps->state = SEND_WSC_NACK;
+
return WPS_FAILURE;
}
size_t dev_passwd_len);
struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
size_t encr_len);
+void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg);
/* wps_attr_parse.c */
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
break;
case WPS_M3:
ret = wps_process_m3(wps, msg, &attr);
+ if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
+ wps_fail_event(wps->wps, WPS_M3);
break;
case WPS_M5:
ret = wps_process_m5(wps, msg, &attr);
+ if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
+ wps_fail_event(wps->wps, WPS_M5);
break;
case WPS_M7:
ret = wps_process_m7(wps, msg, &attr);
+ if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
+ wps_fail_event(wps->wps, WPS_M7);
break;
default:
wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
const struct wpabuf *msg)
{
struct wps_parse_attr attr;
+ int old_state;
wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
+ old_state = wps->state;
wps->state = SEND_WSC_NACK;
if (wps_parse_msg(msg, &attr) < 0)
wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with "
"Configuration Error %d", WPA_GET_BE16(attr.config_error));
+ switch (old_state) {
+ case RECV_M3:
+ wps_fail_event(wps->wps, WPS_M2);
+ break;
+ case RECV_M5:
+ wps_fail_event(wps->wps, WPS_M4);
+ break;
+ case RECV_M7:
+ wps_fail_event(wps->wps, WPS_M6);
+ break;
+ case RECV_DONE:
+ wps_fail_event(wps->wps, WPS_M8);
+ break;
+ default:
+ break;
+ }
+
return WPS_FAILURE;
}
u8 op_code,
const struct wpabuf *msg)
{
+ enum wps_process_res ret;
wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
"op_code=%d)",
case WSC_NACK:
return wps_process_wsc_nack(wps, msg);
case WSC_Done:
- return wps_process_wsc_done(wps, msg);
+ ret = wps_process_wsc_done(wps, msg);
+ if (ret == WPS_FAILURE) {
+ wps->state = SEND_WSC_NACK;
+ wps_fail_event(wps->wps, WPS_WSC_DONE);
+ }
+ return ret;
default:
wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
return WPS_FAILURE;
wpsStatusText->setText("Registration started");
} else if (str_match(pos, WPS_EVENT_M2D)) {
wpsStatusText->setText("Registrar does not yet know PIN");
+ } else if (str_match(pos, WPS_EVENT_FAIL)) {
+ wpsStatusText->setText("Registration failed");
}
}
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
+static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
}
+static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
+ struct wps_event_fail *fail)
+{
+ wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL "msg=%d", fail->msg);
+ wpas_clear_wps(wpa_s);
+}
+
+
static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
union wps_event_data *data)
{
case WPS_EV_M2D:
wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d);
break;
+ case WPS_EV_FAIL:
+ wpa_supplicant_wps_event_fail(wpa_s, &data->fail);
+ break;
}
}