+#define GSSEAP_STATE_NEXT(s) ((s) << 1)
+
+#define GSSEAP_SM_STATE(ctx) ((ctx)->state)
+
+#ifdef GSSEAP_DEBUG
+void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
+#define GSSEAP_SM_TRANSITION(ctx, state) gssEapSmTransition((ctx), (state))
+#else
+#define GSSEAP_SM_TRANSITION(ctx, newstate) do { (ctx)->state = (newstate); } while (0)
+#endif
+
+#define GSSEAP_SM_TRANSITION_NEXT(ctx) GSSEAP_SM_TRANSITION((ctx), GSSEAP_STATE_NEXT(GSSEAP_SM_STATE((ctx))))
+
+/* state machine entry */
+struct gss_eap_sm {
+ OM_uint32 inputTokenType;
+ OM_uint32 outputTokenType;
+ enum gss_eap_state validStates;
+ OM_uint32 itokFlags;
+ OM_uint32 (*processToken)(OM_uint32 *,
+ gss_cred_id_t,
+ gss_ctx_id_t,
+ gss_name_t,
+ gss_OID,
+ OM_uint32,
+ OM_uint32,
+ gss_channel_bindings_t,
+ gss_buffer_t,
+ gss_buffer_t,
+ OM_uint32 *);
+};
+
+/* state machine flags, set by handler */
+#define SM_FLAG_FORCE_SEND_TOKEN 0x00000001 /* send token even if no inner tokens */
+#define SM_FLAG_OUTPUT_TOKEN_CRITICAL 0x00000002 /* output token is critical */
+
+/* state machine flags, set by state machine */
+#define SM_FLAG_INPUT_TOKEN_CRITICAL 0x10000000 /* input token was critical */
+
+#define SM_ITOK_FLAG_REQUIRED 0x00000001 /* received tokens must be present */
+
+OM_uint32
+gssEapSmStep(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t ctx,
+ gss_name_t target,
+ gss_OID mech,
+ OM_uint32 reqFlags,
+ OM_uint32 timeReq,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken,
+ struct gss_eap_sm *sm,
+ size_t smCount);
+
+void
+gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
+
+/* util_token.c */
+OM_uint32
+gssEapEncodeInnerTokens(OM_uint32 *minor,
+ gss_buffer_set_t extensions,
+ OM_uint32 *types,
+ gss_buffer_t buffer);
+OM_uint32
+gssEapDecodeInnerTokens(OM_uint32 *minor,
+ const gss_buffer_t buffer,
+ gss_buffer_set_t *pExtensions,
+ OM_uint32 **pTypes);
+