understanding the code.

Gunter Burchardt gbur
Thu Nov 25 09:38:18 PST 2004


> there's a copuple of things I miss.. 
> 
> main initializes one interface.hapd[i] for phisical interface (just one
> for me). this calls init_driver_hostap() which calls driver_init() which calls
> init_sockets() which increments eloop.readers_count. So we have one
> eloop.reader[] for interface, and one eloop.reader[].sock to listen to.
> in eloop_run() we whatch this socket and pass the data it receives to the
> correct handler. right?

Yes. Hostapd is single threaded. Each action is caused by eloop.
Received data on sockets in only one thing a handler function is
called. Secondly you can register functions that will be called after a
specific time!

> upon receival of a frame handlers call each other untill we get 
> to 802_1x_receive() that does this:
> 
> sta = ap_get_sta(hapd, sa);
> [...]
> eapol_sm_step(sta->eapol_sm);
> 
> so we have an authenticator state machine for every station, and a new
> station is initialized with hostapd_new_assoc_sta(), which I guess it is
> exectued at the moment of a new association. 

Yes, yes, yes! :)

> back to EAPOL sm: the authenticator state machine (which I
> suppose is the one specified in the standard) changes from the
> connecting to the authenticating state when it receives EAPOL-Start frame.

Yes. Read IEEE802.1x standard. Its free (and very long). You will find
state machine there!
 
> case IEEE802_1X_TYPE_EAPOL_START:
> [...]
> 		sta->eapol_sm->auth_pae.eapolStart = TRUE;
> 		sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
> 		eapol_sm_step(sta->eapol_sm);
> 
> this happens just for EAPOL_START frames. for generic EAP frames we have:
> 
> case IEEE802_1X_TYPE_EAP_PACKET:
> [...]
>         handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen);
> 
> in handle_eap(), as I said before we have:
> 
> switch (eap->code) {
> 00712         case EAP_CODE_REQUEST:
> 00713                 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (request)\n");
> 00714                 return;
> 00715         case EAP_CODE_RESPONSE:
> 00716                 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (response)\n");
> 00717                 handle_eap_response(hapd, sta, eap, (u8 *) (eap + 1), eap_len);
> 00718                 break;
> 00719         case EAP_CODE_SUCCESS:
> 00720                 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (success)\n");
> 00721                 return;
> 00722         case EAP_CODE_FAILURE:
> 00723                 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (failure)\n");
> 00724                 return;
> 00725         default:
> 00726                 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (unknown code)\n");
> 00727                 return;
> 
> which means that we handle EAP_RESPONSES and we don't do anything on
> everything else. in handle_eap_response() we set a few parameters on the
> sm but we don't make it run, neither we send any RADIUS packet. I guess
> the RADIUS packet is sent (shouldn't we forward EAP packets to
> authentication server?) afterwards when something which I still don't know
> makes the sm run.

Well, you set some sm parameters for:
ieee802_1x.c:   sm->eapolEap = TRUE;

In ieee802_1x_receive() at the end eapol_sm_step(sta->eapol_sm) is
called for each packet. The sm parameters causes BE_AUTH state machine
to change state (or not).


sm->eapolEAP is TRUE for Response packets.

look at following code in eapol_sm.c:

        case BE_AUTH_REQUEST:
                if (sm->eapolEap)
                        SM_ENTER(BE_AUTH, RESPONSE);
                else if (sm->be_auth.eapReq)
                        SM_ENTER(BE_AUTH, REQUEST);
                else if (sm->eapTimeout)
                        SM_ENTER(BE_AUTH, TIMEOUT);
                break;

BE_AUTH is in state BE_AUTH_REQUEST (awaiting an answer). If eapolEAP
is set the state is changed to RESPONSE.

> so the question remains: why do we handle just EAP_RESPONSE packets? what
> do we do with the rest?

Which rest do you mean eapol_sm_step() is called for each eap packet. So
the changed sm parameters can cause state change of sm state machine!

> some more: when we initialize a new sm we pass from the states
> initialize->disconnected->restart->connecting almost withouth
> intervention. to pass to the authenticating state we need eapReq=1 and
> I can't see where this is set, since in the code we just set eapolStart.

eapReq is set to TRUE in ieee802_1x.c.

regards
gunter




More information about the Hostap mailing list