Add new wpa_supplicant driver op for setting 802.1X port status
authorJouni Malinen <jouni.malinen@atheros.com>
Wed, 22 Apr 2009 13:01:37 +0000 (16:01 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 22 Apr 2009 13:01:37 +0000 (16:01 +0300)
This can be used with drivers that implement PAE to control whether
normal data frames (non-EAPOL) are allowed.

src/drivers/driver.h
src/drivers/driver_ndis.c
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h
wpa_supplicant/driver_i.h
wpa_supplicant/wpas_glue.c

index 8339127..8551004 100644 (file)
@@ -1333,6 +1333,14 @@ struct wpa_driver_ops {
                                 const u8 *ie, size_t len);
        int (*set_wps_probe_resp_ie)(const char *ifname, void *priv,
                                     const u8 *ie, size_t len);
+
+       /**
+        * set_supp_port - Set IEEE 802.1X Supplicant Port status
+        * @priv: Private driver interface data
+        * @authorized: Whether the port is authorized
+        * Returns: 0 on success, -1 on failure
+        */
+       int (*set_supp_port)(void *priv, int authorized);
 };
 
 /**
index fd0e97e..e45b231 100644 (file)
@@ -3264,5 +3264,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
        NULL /* set_radius_acl_expire */,
        NULL /* set_ht_params */,
        NULL /* set_wps_beacon_ie */,
-       NULL /* set_wps_probe_resp_ie */
+       NULL /* set_wps_probe_resp_ie */,
+       NULL /* set_supp_port */
 };
index 537f06d..e4c0700 100644 (file)
@@ -193,6 +193,8 @@ static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
 static void eapol_sm_abortSupp(struct eapol_sm *sm);
 static void eapol_sm_abort_cached(struct eapol_sm *sm);
 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
+static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
+static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
 
 
 /* Port Timers state machine - implemented as a function that will be called
@@ -250,6 +252,7 @@ SM_STATE(SUPP_PAE, LOGOFF)
        eapol_sm_txLogoff(sm);
        sm->logoffSent = TRUE;
        sm->suppPortStatus = Unauthorized;
+       eapol_sm_set_port_unauthorized(sm);
 }
 
 
@@ -260,6 +263,7 @@ SM_STATE(SUPP_PAE, DISCONNECTED)
        sm->startCount = 0;
        sm->logoffSent = FALSE;
        sm->suppPortStatus = Unauthorized;
+       eapol_sm_set_port_unauthorized(sm);
        sm->suppAbort = TRUE;
 
        sm->unicast_key_received = FALSE;
@@ -315,6 +319,7 @@ SM_STATE(SUPP_PAE, HELD)
        sm->heldWhile = sm->heldPeriod;
        eapol_enable_timer_tick(sm);
        sm->suppPortStatus = Unauthorized;
+       eapol_sm_set_port_unauthorized(sm);
        sm->cb_status = EAPOL_CB_FAILURE;
 }
 
@@ -323,6 +328,7 @@ SM_STATE(SUPP_PAE, AUTHENTICATED)
 {
        SM_ENTRY(SUPP_PAE, AUTHENTICATED);
        sm->suppPortStatus = Authorized;
+       eapol_sm_set_port_authorized(sm);
        sm->cb_status = EAPOL_CB_SUCCESS;
 }
 
@@ -338,6 +344,7 @@ SM_STATE(SUPP_PAE, S_FORCE_AUTH)
 {
        SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
        sm->suppPortStatus = Authorized;
+       eapol_sm_set_port_authorized(sm);
        sm->sPortMode = ForceAuthorized;
 }
 
@@ -346,6 +353,7 @@ SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
 {
        SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
        sm->suppPortStatus = Unauthorized;
+       eapol_sm_set_port_unauthorized(sm);
        sm->sPortMode = ForceUnauthorized;
        eapol_sm_txLogoff(sm);
 }
@@ -862,6 +870,20 @@ static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
+{
+       if (sm->ctx->port_cb)
+               sm->ctx->port_cb(sm->ctx->ctx, 1);
+}
+
+
+static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
+{
+       if (sm->ctx->port_cb)
+               sm->ctx->port_cb(sm->ctx->ctx, 0);
+}
+
+
 /**
  * eapol_sm_step - EAPOL state machine step function
  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
@@ -1456,6 +1478,7 @@ void eapol_sm_notify_cached(struct eapol_sm *sm)
        wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
        sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED;
        sm->suppPortStatus = Authorized;
+       eapol_sm_set_port_authorized(sm);
        sm->portValid = TRUE;
        eap_notify_success(sm->eap);
        eapol_sm_step(sm);
@@ -1492,6 +1515,7 @@ static void eapol_sm_abort_cached(struct eapol_sm *sm)
        sm->cached_pmk = FALSE;
        sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
        sm->suppPortStatus = Unauthorized;
+       eapol_sm_set_port_unauthorized(sm);
 
        /* Make sure we do not start sending EAPOL-Start frames first, but
         * instead move to RESTART state to start EAPOL authentication. */
index 57d7bc1..e6e8cc6 100644 (file)
@@ -215,6 +215,13 @@ struct eapol_ctx {
         */
        void (*eap_param_needed)(void *ctx, const char *field,
                                 const char *txt);
+
+       /**
+        * port_cb - Set port authorized/unauthorized callback (optional)
+        * @ctx: Callback context (ctx)
+        * @authorized: Whether the supplicant port is now in authorized state
+        */
+       void (*port_cb)(void *ctx, int authorized);
 };
 
 
index 75a800c..4cb5372 100644 (file)
@@ -438,4 +438,14 @@ static inline int wpa_drv_sta_set_flags(struct wpa_supplicant *wpa_s,
        return -1;
 }
 
+static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s,
+                                       int authorized)
+{
+       if (wpa_s->driver->set_supp_port) {
+               return wpa_s->driver->set_supp_port(wpa_s->drv_priv,
+                                                   authorized);
+       }
+       return 0;
+}
+
 #endif /* DRIVER_I_H */
index d8af14d..c2eb131 100644 (file)
@@ -537,6 +537,15 @@ static void wpa_supplicant_eap_param_needed(void *ctx, const char *field,
 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
 
+static void wpa_supplicant_port_cb(void *ctx, int authorized)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s",
+                  authorized ? "Authorized" : "Unauthorized");
+       wpa_drv_set_supp_port(wpa_s, authorized);
+}
+
+
 int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
 {
 #ifdef IEEE8021X_EAPOL
@@ -564,6 +573,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
 #endif /* EAP_TLS_OPENSSL */
        ctx->wps = wpa_s->wps;
        ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
+       ctx->port_cb = wpa_supplicant_port_cb;
        ctx->cb = wpa_supplicant_eapol_cb;
        ctx->cb_ctx = wpa_s;
        wpa_s->eapol = eapol_sm_init(ctx);