b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /** |
| 2 | \page porting Porting to different target boards and operating systems |
| 3 | |
| 4 | wpa_supplicant was designed to be easily portable to different |
| 5 | hardware (board, CPU) and software (OS, drivers) targets. It is |
| 6 | already used with number of operating systems and numerous wireless |
| 7 | card models and drivers. The main wpa_supplicant repository includes |
| 8 | support for Linux, FreeBSD, and Windows. In addition, the code has been |
| 9 | ported to number of other operating systems like VxWorks, PalmOS, |
| 10 | Windows CE, and Windows Mobile. On the hardware |
| 11 | side, wpa_supplicant is used on various systems: desktops, laptops, |
| 12 | PDAs, and embedded devices with CPUs including x86, PowerPC, |
| 13 | arm/xscale, and MIPS. Both big and little endian configurations are |
| 14 | supported. |
| 15 | |
| 16 | |
| 17 | \section ansi_c_extra Extra functions on top of ANSI C |
| 18 | |
| 19 | wpa_supplicant is mostly using ANSI C functions that are available on |
| 20 | most targets. However, couple of additional functions that are common |
| 21 | on modern UNIX systems are used. Number of these are listed with |
| 22 | prototypes in \ref common.h (the \verbatim #ifdef CONFIG_ANSI_C_EXTRA \endverbatim |
| 23 | block). These functions may need to be implemented or at least defined |
| 24 | as macros to native functions in the target OS or C library. |
| 25 | |
| 26 | Many of the common ANSI C functions are used through a wrapper |
| 27 | definitions in \ref os.h to allow these to be replaced easily with a |
| 28 | platform specific version in case standard C libraries are not |
| 29 | available. In addition, \ref os.h defines couple of common platform |
| 30 | specific functions that are implemented in \ref os_unix.c for UNIX like |
| 31 | targets and in \ref os_win32.c for Win32 API. If the target platform does |
| 32 | not support either of these examples, a new os_*.c file may need to be |
| 33 | added. |
| 34 | |
| 35 | Unless OS_NO_C_LIB_DEFINES is defined, the standard ANSI C and POSIX |
| 36 | functions are used by defining the os_*() wrappers to use them |
| 37 | directly in order to avoid extra cost in size and speed. If the target |
| 38 | platform needs different versions of the functions, \ref os.h can be |
| 39 | modified to define the suitable macros or alternatively, |
| 40 | OS_NO_C_LIB_DEFINES may be defined for the build and the wrapper |
| 41 | functions can then be implemented in a new os_*.c wrapper file. |
| 42 | |
| 43 | \ref common.h defines number of helper macros for handling integers of |
| 44 | different size and byte order. Suitable version of these definitions |
| 45 | may need to be added for the target platform. |
| 46 | |
| 47 | |
| 48 | \section configuration_backend Configuration backend |
| 49 | |
| 50 | wpa_supplicant implements a configuration interface that allows the |
| 51 | backend to be easily replaced in order to read configuration data from |
| 52 | a suitable source depending on the target platform. \ref config.c |
| 53 | implements the generic code that can be shared with all configuration |
| 54 | backends. Each backend is implemented in its own config_*.c file. |
| 55 | |
| 56 | The included \ref config_file.c backend uses a text file for configuration |
| 57 | and \ref config_winreg.c uses Windows registry. These files can be used as |
| 58 | an example for a new configuration backend if the target platform uses |
| 59 | different mechanism for configuration parameters. In addition, |
| 60 | \ref config_none.c can be used as an empty starting point for building a |
| 61 | new configuration backend. |
| 62 | |
| 63 | |
| 64 | \section driver_iface_porting Driver interface |
| 65 | |
| 66 | Unless the target OS and driver is already supported, most porting |
| 67 | projects have to implement a driver wrapper. This may be done by |
| 68 | adding a new driver interface module or modifying an existing module |
| 69 | (driver_*.c) if the new target is similar to one of them. \ref |
| 70 | driver_wrapper "Driver wrapper implementation" describes the details |
| 71 | of the driver interface and discusses the tasks involved in porting |
| 72 | this part of wpa_supplicant. |
| 73 | |
| 74 | |
| 75 | \section l2_packet_porting l2_packet (link layer access) |
| 76 | |
| 77 | wpa_supplicant needs to have access to sending and receiving layer 2 |
| 78 | (link layer) packets with two Ethertypes: EAP-over-LAN (EAPOL) 0x888e |
| 79 | and RSN pre-authentication 0x88c7. \ref l2_packet.h defines the interfaces |
| 80 | used for this in the core wpa_supplicant implementation. |
| 81 | |
| 82 | If the target operating system supports a generic mechanism for link |
| 83 | layer access, that is likely the best mechanism for providing the |
| 84 | needed functionality for wpa_supplicant. Linux packet socket is an |
| 85 | example of such a generic mechanism. If this is not available, a |
| 86 | separate interface may need to be implemented to the network stack or |
| 87 | driver. This is usually an intermediate or protocol driver that is |
| 88 | operating between the device driver and the OS network stack. If such |
| 89 | a mechanism is not feasible, the interface can also be implemented |
| 90 | directly in the device driver. |
| 91 | |
| 92 | The main wpa_supplicant repository includes l2_packet implementations |
| 93 | for Linux using packet sockets (\ref l2_packet_linux.c), more portable |
| 94 | version using libpcap/libdnet libraries (\ref l2_packet_pcap.c; this |
| 95 | supports WinPcap, too), and FreeBSD specific version of libpcap |
| 96 | interface (\ref l2_packet_freebsd.c). |
| 97 | |
| 98 | If the target operating system is supported by libpcap (receiving) and |
| 99 | libdnet (sending), \ref l2_packet_pcap.c can likely be used with minimal or |
| 100 | no changes. If this is not a case or a proprietary interface for link |
| 101 | layer is required, a new l2_packet module may need to be |
| 102 | added. Alternatively, for hostapd, |
| 103 | struct \ref wpa_driver_ops::hapd_send_eapol() handler can |
| 104 | be used to override the l2_packet library if the link layer access is |
| 105 | integrated with the driver interface implementation. |
| 106 | |
| 107 | |
| 108 | \section eloop_porting Event loop |
| 109 | |
| 110 | wpa_supplicant uses a single process/thread model and an event loop |
| 111 | to provide callbacks on events (registered timeout, received packet, |
| 112 | signal). eloop.h defines the event loop interface. \ref eloop.c is an |
| 113 | implementation of such an event loop using select() and sockets. This |
| 114 | is suitable for most UNIX/POSIX systems. When porting to other |
| 115 | operating systems, it may be necessary to replace that implementation |
| 116 | with OS specific mechanisms that provide similar functionality. |
| 117 | |
| 118 | |
| 119 | \section ctrl_iface_porting Control interface |
| 120 | |
| 121 | wpa_supplicant uses a \ref ctrl_iface_page "control interface" |
| 122 | to allow external processed |
| 123 | to get status information and to control the operations. Currently, |
| 124 | this is implemented with socket based communication; both UNIX domain |
| 125 | sockets and UDP sockets are supported. If the target OS does not |
| 126 | support sockets, this interface will likely need to be modified to use |
| 127 | another mechanism like message queues. The control interface is |
| 128 | optional component, so it is also possible to run wpa_supplicant |
| 129 | without porting this part. |
| 130 | |
| 131 | The wpa_supplicant side of the control interface is implemented in |
| 132 | \ref wpa_supplicant/ctrl_iface.c. Matching client side is implemented as a control |
| 133 | interface library in \ref wpa_ctrl.c. |
| 134 | |
| 135 | |
| 136 | \section entry_point Program entry point |
| 137 | |
| 138 | wpa_supplicant defines a set of functions that can be used to |
| 139 | initialize main supplicant processing. Each operating system has a |
| 140 | mechanism for starting new processing or threads. This is usually a |
| 141 | function with a specific set of arguments and calling convention. This |
| 142 | function is responsible on initializing wpa_supplicant. |
| 143 | |
| 144 | \ref wpa_supplicant/main.c includes an entry point for UNIX-like |
| 145 | operating system, i.e., main() function that uses command line arguments |
| 146 | for setting parameters for wpa_supplicant. When porting to other |
| 147 | operating systems, similar OS-specific entry point implementation is |
| 148 | needed. It can be implemented in a new file that is then linked with |
| 149 | wpa_supplicant instead of main.o. \ref wpa_supplicant/main.c is also a |
| 150 | good example on how the initialization process should be done. |
| 151 | |
| 152 | The supplicant initialization functions are defined in |
| 153 | \ref wpa_supplicant_i.h. In most cases, the entry point function should |
| 154 | start by fetching configuration parameters. After this, a global |
| 155 | wpa_supplicant context is initialized with a call to |
| 156 | \ref wpa_supplicant_init(). After this, existing network interfaces can be |
| 157 | added with \ref wpa_supplicant_add_iface(). \ref wpa_supplicant_run() is then |
| 158 | used to start the main event loop. Once this returns at program |
| 159 | termination time, \ref wpa_supplicant_deinit() is used to release global |
| 160 | context data. |
| 161 | |
| 162 | \ref wpa_supplicant_add_iface() and \ref wpa_supplicant_remove_iface() can be |
| 163 | used dynamically to add and remove interfaces based on when |
| 164 | wpa_supplicant processing is needed for them. This can be done, e.g., |
| 165 | when hotplug network adapters are being inserted and ejected. It is |
| 166 | also possible to do this when a network interface is being |
| 167 | enabled/disabled if it is desirable that wpa_supplicant processing |
| 168 | for the interface is fully enabled/disabled at the same time. |
| 169 | |
| 170 | |
| 171 | \section simple_build Simple build example |
| 172 | |
| 173 | One way to start a porting project is to begin with a very simple |
| 174 | build of wpa_supplicant with WPA-PSK support and once that is |
| 175 | building correctly, start adding features. |
| 176 | |
| 177 | Following command can be used to build very simple version of |
| 178 | wpa_supplicant: |
| 179 | |
| 180 | \verbatim |
| 181 | cc -o wpa_supplicant config.c eloop.c common.c md5.c rc4.c sha1.c \ |
| 182 | config_none.c l2_packet_none.c tls_none.c wpa.c preauth.c \ |
| 183 | aes_wrap.c wpa_supplicant.c events.c main_none.c drivers.c |
| 184 | \endverbatim |
| 185 | |
| 186 | The end result is not really very useful since it uses empty functions |
| 187 | for configuration parsing and layer 2 packet access and does not |
| 188 | include a driver interface. However, this is a good starting point |
| 189 | since the build is complete in the sense that all functions are |
| 190 | present and this is easy to configure to a build system by just |
| 191 | including the listed C files. |
| 192 | |
| 193 | Once this version can be build successfully, the end result can be |
| 194 | made functional by adding a proper program entry point (main*.c), |
| 195 | driver interface (driver_*.c and matching CONFIG_DRIVER_* define for |
| 196 | registration in \ref drivers.c), configuration parser/writer (config_*.c), |
| 197 | and layer 2 packet access implementation (l2_packet_*.c). After these |
| 198 | components have been added, the end result should be a working |
| 199 | WPA/WPA2-PSK enabled supplicant. |
| 200 | |
| 201 | After the basic functionality has been verified to work, more features |
| 202 | can be added by linking in more files and defining C pre-processor |
| 203 | defines. Currently, the best source of information for what options |
| 204 | are available and which files needs to be included is in the Makefile |
| 205 | used for building the supplicant with make. Similar configuration will |
| 206 | be needed for build systems that either use different type of make |
| 207 | tool or a GUI-based project configuration. |
| 208 | |
| 209 | */ |