1 /*
2  * wpa_supplicant/hostapd - State machine definitions
3  * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  *
8  * This file includes a set of pre-processor macros that can be used to
9  * implement a state machine. In addition to including this header file, each
10  * file implementing a state machine must define STATE_MACHINE_DATA to be the
11  * data structure including state variables (enum machine_state,
12  * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used
13  * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define
14  * a group of state machines with shared data structure, STATE_MACHINE_ADDR
15  * needs to be defined to point to the MAC address used in debug output.
16  * SM_ENTRY_M macro can be used to define similar group of state machines
17  * without this additional debug info.
18  */
19 
20 #ifndef STATE_MACHINE_H
21 #define STATE_MACHINE_H
22 
23 /**
24  * SM_STATE - Declaration of a state machine function
25  * @machine: State machine name
26  * @state: State machine state
27  *
28  * This macro is used to declare a state machine function. It is used in place
29  * of a C function definition to declare functions to be run when the state is
30  * entered by calling SM_ENTER or SM_ENTER_GLOBAL.
31  */
32 #define SM_STATE(machine, state) \
33 static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \
34 	int global)
35 
36 /**
37  * SM_ENTRY - State machine function entry point
38  * @machine: State machine name
39  * @state: State machine state
40  *
41  * This macro is used inside each state machine function declared with
42  * SM_STATE. SM_ENTRY should be in the beginning of the function body, but
43  * after declaration of possible local variables. This macro prints debug
44  * information about state transition and update the state machine state.
45  */
46 #define SM_ENTRY(machine, state) \
47 if (!global || sm->machine ## _state != machine ## _ ## state) { \
48 	sm->changed = TRUE; \
49 	wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \
50 		   " entering state " #state); \
51 } \
52 sm->machine ## _state = machine ## _ ## state;
53 
54 /**
55  * SM_ENTRY_M - State machine function entry point for state machine group
56  * @machine: State machine name
57  * @_state: State machine state
58  * @data: State variable prefix (full variable: prefix_state)
59  *
60  * This macro is like SM_ENTRY, but for state machine groups that use a shared
61  * data structure for more than one state machine. Both machine and prefix
62  * parameters are set to "sub-state machine" name. prefix is used to allow more
63  * than one state variable to be stored in the same data structure.
64  */
65 #define SM_ENTRY_M(machine, _state, data) \
66 if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \
67 	sm->changed = TRUE; \
68 	wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \
69 		   #machine " entering state " #_state); \
70 } \
71 sm->data ## _ ## state = machine ## _ ## _state;
72 
73 /**
74  * SM_ENTRY_MA - State machine function entry point for state machine group
75  * @machine: State machine name
76  * @_state: State machine state
77  * @data: State variable prefix (full variable: prefix_state)
78  *
79  * This macro is like SM_ENTRY_M, but a MAC address is included in debug
80  * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to
81  * be included in debug.
82  */
83 #define SM_ENTRY_MA(machine, _state, data) \
84 if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \
85 	sm->changed = TRUE; \
86 	wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \
87 		   #machine " entering state " #_state, \
88 		   MAC2STR(STATE_MACHINE_ADDR)); \
89 } \
90 sm->data ## _ ## state = machine ## _ ## _state;
91 
92 /**
93  * SM_ENTER - Enter a new state machine state
94  * @machine: State machine name
95  * @state: State machine state
96  *
97  * This macro expands to a function call to a state machine function defined
98  * with SM_STATE macro. SM_ENTER is used in a state machine step function to
99  * move the state machine to a new state.
100  */
101 #define SM_ENTER(machine, state) \
102 sm_ ## machine ## _ ## state ## _Enter(sm, 0)
103 
104 /**
105  * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule
106  * @machine: State machine name
107  * @state: State machine state
108  *
109  * This macro is like SM_ENTER, but this is used when entering a new state
110  * based on a global (not specific to any particular state) rule. A separate
111  * macro is used to avoid unwanted debug message floods when the same global
112  * rule is forcing a state machine to remain in on state.
113  */
114 #define SM_ENTER_GLOBAL(machine, state) \
115 sm_ ## machine ## _ ## state ## _Enter(sm, 1)
116 
117 /**
118  * SM_STEP - Declaration of a state machine step function
119  * @machine: State machine name
120  *
121  * This macro is used to declare a state machine step function. It is used in
122  * place of a C function definition to declare a function that is used to move
123  * state machine to a new state based on state variables. This function uses
124  * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state.
125  */
126 #define SM_STEP(machine) \
127 static void sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm)
128 
129 /**
130  * SM_STEP_RUN - Call the state machine step function
131  * @machine: State machine name
132  *
133  * This macro expands to a function call to a state machine step function
134  * defined with SM_STEP macro.
135  */
136 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
137 
138 #endif /* STATE_MACHINE_H */
139