Table of Contents
This document serves as a general guide to setting up a Wireless Access Point (AP) in Linux using the following LM WiFi adapters and modules based upon the Realtek RTL8188CUS chipset:
- LM006 – Nano WiFi USB 802.11n Adapter 150Mbps
- LM820 – WiFi SMT Module 802.11n 150Mbps (Onboard Antenna)
- LM821 – WiFi SMT Module 802.11n 150Mbps (U.FL Receptacle)
Other LM products may also work with Host AP, please contact us for more details.
The methods used here are not intended to persist between reboots or create a permanent access point on your machine. Once you have successfully created and tested your access point, you should refer to your distribution’s manual and/or the manual of the service manager system (e.g systemd, SysV) you are using to discover the most-appropriate method of implementing a persistent access point. There are also various tools and utility programs intended to automate some of the steps, which I have performed manually in this document, without interfering with hostapd.
Before beginning, you will require some hardware and software.
Please note: This article focuses on the use of generic Linux-based distributions running hostapd.
This article may also be adapted for other use cases, such as using Android with hostapd alongside Realtek’s drivers, however this is currently outside the scope of this article.
1/ A compatible LM WiFi adapter or module connected via USB to a host capable of running a mainline (or near-mainline) version of Linux.
- The host may be an x86 PC/Laptop, an ARM-based device such as the BeagleBone Black or Raspberry Pi 2 or a Virtual Machine. Other architectures may also be compatible, however this article focuses on those listed.
2/ Linux & drivers
- Several of LM’s WiFi products, such as the LM006 and LM820 are powered by Realtek chips which have drivers present in the more recent versions of the Linux kernel (3.10+) which include full HostAP support. For older versions of the Linux kernel, going back to 2.6.x, drivers can be found on the relevant product page of the LM website which support HostAP. If you are compiling your own kernel, make sure to either include module support or statically compile the relevant Realtek kernel modules; for example, the LM006 requires the rtl8192cu and rtlwifi modules which additionally have their own dependencies.
Realtek chips & drivers
The LM006 uses the Realtek RTL8188CUS IC which, a little confusingly, is supported by Realtek’s RTL8192CU driver.
- nl80211 and mac80211 – Some versions of the Linux kernel greater than 2.6.x but less than 3.10 include Realtek drivers, however these do not fully support the cfg80211 standard driver interface required for HostAP and so you may have to blacklist the relevant module(s) and instead install a stand-alone Realtek driver which does provide this support. Many of the stand-alone Realtek drivers also have cfg80211 support disabled by default and so you will need to configure this option before compiling the driver. In many cases, instructions for doing so are supplied with the driver package and may also be present on our wiki support site for the product you are using.
- Beacon frame issue – The drivers in kernel versions 3.10 to 3.19 (inclusive) have one or more bugs which stop beacon frames from being broadcast. Beacon frames are required by some devices to detect the AP. If you have this issue then you may need to upgrade to kernel version 4.0+ or patch newer drivers into an older kernel.
- If you are using a common desktop Linux distribution, such as Ubuntu, then it will most-likely come supplied with a kernel which includes module support along with the relevant Realtek modules and their dependencies. If you are using a distribution aimed at an embedded device, such as the BeagleBone or Raspberry Pi, then it is possible that drivers may not be present and that you may need to compile your own kernel or consider an alternate distribution.
- Some of the stand-alone Realtek drivers feature support for more than one transport/interface. In particular, some come with support for PCI which will prevent the drivers from compiling (or more accurately linking) against kernels which have been built without support for this interface. You can, however, toggle support for the different interfaces in the Realtek Makefile as well as many other features. You may find more information on installing and compiling drivers within our relevant how-to wiki articles. It is advisable that you ensure the adapter works under normal operation before attempting to use it with HostAP.
3/ Development tools
- It is possible that you will not have to compile anything in order to run HostAP, however, if you do then you will at least require the GNU tool chain which many Linux distributions will bundle together in several packages. If you are compiling drivers, then you will require the Kernel headers, which again, most distributions bundle within a package. The vast majority of compilation errors are simply caused by missing components. If you are using a low-power device such as the Raspberry Pi, then it is advisable to offload any compilation onto a desktop PC or laptop. For this you will need to install the relevant cross-compiler, libraries and headers on the PC, however how to accomplish this is outside the scope of this article.
- Hopefully your distribution or distribution builder (e.g. Yocto) includes a recent version of hostapd, if it doesn’t, then you will need to download and compile the source: http://w1.fi/hostapd/
5/ Networking tools
- This guide uses the ip and iw commands to perform basic network interface configuration, dhcpcd for obtaining an IP address via DHCP and ping for testing. Older distributions may be supplied with different tools by default, however there is a good chance that you will be able to install ip (iproute2) and iw (nl80211 tools) from your distribution’s package manager.
- dhcpcd is fairly ubiquitous, however if your distribution does not come with it, there is likely something in its place which provides the same functionality. Note that dhcpcd, the DHCP client, is not to be confused with dhcpd, the DHCP server.
Whenever you see a command or option which you don’t recognise, use the man <command name> or info <command name> commands to find out what it does. With complex commands such as ip and git, the manual pages are split-up into smaller sections which you can access by typing a command such as man ip-link.
Preparing your system
First check that the wireless network adapter is visible to the system by running ip and iw:
~ % ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:1e:95:1a brd ff:ff:ff:ff:ff:ff 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff ~ % iw dev ~ %
The above output shows three network interfaces: ‘lo’ which is the virtual loopback interface, ‘eno16777736’ which on many systems will be named ‘eth0’ or similar and refers to an Ethernet adapter and ‘docker0’ which is another virtual interface created for Docker. Suspiciously absent is anything to do with wireless; towards the bottom you can see the iw dev command which returned nothing. To diagnose this lets run lsusb:
~ % lsusb Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 003 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub Bus 003 Device 004: ID 0e0f:0003 VMware, Inc. Virtual Mouse Bus 003 Device 002: ID 0e0f:0002 VMware, Inc. Virtual USB Hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 004: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) Bus 001 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub Bus 001 Device 002: ID 0a5c:22be Broadcom Corp. BCM2070 Bluetooth 3.0 + HS Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
There are many devices here, but none of them are labelled as Realtek. At this stage, it is reasonable to assume that the adapter is not plugged-in, however, if I look at it I can A) see that it is physically plugged in and B) the light is on.
On a desktop PC you can expect that a device will be detected and have its driver loaded as soon as it is plugged in. On embedded devices this is less likely and you may need to do a reboot to pick up the new hardware and load any drivers.
It turns out that it is connected to a different virtual machine in VMWare. In order to get it to work, I had to connect it to the correct virtual machine and toggle the power. If you can see the adapter in lsusb, but not ip link then check lsmod:
~ % lsmod Module Size Used by arc4 12536 2 rtl8192cu 66273 0 rtl_usb 17592 1 rtl8192cu rtl8192c_common 44268 1 rtl8192cu rtlwifi 63199 3 rtl_usb,rtl8192c_common,rtl8192cu mac80211 608652 3 rtl_usb,rtlwifi,rtl8192cu ...
The relevant modules are listed in the output of lsmod on my system. If they are not on your system use the dmesg command to find out if there was an error loading the modules:
~ % dmesg | tail [ 9765.698693] rtl8192cu: Chip version 0x10 [ 9765.841719] rtl8192cu: MAC address: 00:02:72:b7:a2:0f [ 9765.841722] rtl8192cu: Board Type 0 [ 9765.842115] rtl_usb: rx_max_size 15360, rx_urb_num 8, in_ep 1 [ 9765.842190] rtl8192cu: Loading firmware rtlwifi/rtl8192cufw_TMSC.bin [ 9765.884913] ieee80211 phy0: Selected rate control algorithm 'rtl_rc' [ 9765.885198] usbcore: registered new interface driver rtl8192cu [ 9765.889943] rtl8192cu: MAC auto ON okay! [ 9765.947879] rtl8192cu: Tx queue select: 0x05 [ 9766.574497] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
dmesg is your friend when things go wrong, it is comparable to the event log in Windows. Finally, if I run ip link and iw dev we can now see the wireless interface:
~ % ip l 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:1e:95:1a brd ff:ff:ff:ff:ff:ff 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff 4: wls160u2u1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 00:02:72:b7:a2:0f brd ff:ff:ff:ff:ff:ff ~ % iw dev phy#0 Interface wls160u2u1 ifindex 4 wdev 0x1 addr 00:02:72:b7:a2:0f type managed
So the wireless adapter has been given the catchy name wls160u2u1 by udev‘s predictable naming scheme. On your system it may just be called wlan0 or something similar, which is easier to type, but the same adapter may not always be assigned the same name.
In the above I have typed ip l rather than ip link, the ip command allows abbreviations to be used in place of any keyword so long as the abbreviation is not ambiguous. For the sake of clarity, this article will not use single letter abbreviations from now on.
Disabling networking services
Automatic network management services such as ‘network manager’ and ‘connman’ will interfere with hostapd and need to be disabled. Services such as wpa_supplicant and dhcpcd could cause problems even if they are seemingly restricted to an interface which is not being targeted by hostapd. For the sake of initial testing it would be advisable to disable every network service which is not required by the access point.
If you or your distribution is using systemd then services can be listed with systemctl status <service> and stopped with systemctl stop <service>. There are similar service management commands for Upstart and System-V, you should consult your distribution’s documentation to find best method. Service daemons can be started directly from the command line (a terminal) as well and many can also be kept in the foreground so that you can see their stdout messages. In this guide we will always start programs as foreground processes, where possible, to help with fault diagnosis and also because it is (almost) a distribution agnostic method of starting services.
Below is a simple configuration for the hostapd daemon which should create a secure access point on channel two with the network name ‘hostapdtest’ and password ‘YourPassphrase’.
ssid=hostapdtest interface=wls160u2u1 channel=3 driver=nl80211 macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=YourPassphrase wpa_key_mgmt=WPA-PSK wpa_pairwise=CCMP rsn_pairwise=CCMP
There are many options for hostapd which are explained in great detail on kernel.org. For now we shall just gloss over them and try starting hostapd. Save the configuration to /etc/hostapd/hostapd.conf (or some other destination) and do the following:
~ % sudo hostapd -d /etc/hostapd/hostapd.conf random: Trying to read entropy from /dev/random Configuration file: /etc/hostapd/hostapd.conf rfkill: initial event: idx=1 type=2 op=0 soft=0 hard=0 rfkill: initial event: idx=4 type=1 op=0 soft=0 hard=0 nl80211: Supported cipher 00-0f-ac:1 nl80211: Supported cipher 00-0f-ac:5 nl80211: Supported cipher 00-0f-ac:2 nl80211: Supported cipher 00-0f-ac:4 nl80211: Supported cipher 00-0f-ac:6 nl80211: Using driver-based off-channel TX nl80211: interface wls160u2u1 in phy phy0 nl80211: Set mode ifindex 4 iftype 3 (AP) nl80211: Setup AP(wls160u2u1) - device_ap_sme=0 use_monitor=0 nl80211: Subscribe to mgmt frames with AP handle 0x2097250 nl80211: Register frame type=0xb0 (WLAN_FC_STYPE_AUTH) nl_handle=0x2097250 match= nl80211: Register frame type=0x0 (WLAN_FC_STYPE_ASSOC_REQ) nl_handle=0x2097250 match= nl80211: Register frame type=0x20 (WLAN_FC_STYPE_REASSOC_REQ) nl_handle=0x2097250 match= nl80211: Register frame type=0xa0 (WLAN_FC_STYPE_DISASSOC) nl_handle=0x2097250 match= nl80211: Register frame type=0xc0 (WLAN_FC_STYPE_DEAUTH) nl_handle=0x2097250 match= nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x2097250 match= nl80211: Register frame type=0x40 (WLAN_FC_STYPE_PROBE_REQ) nl_handle=0x2097250 match= nl80211: Add own interface ifindex 4 nl80211: if_indices: 4 phy: phy0 BSS count 1, BSSID mask 00:00:00:00:00:00 (0 bits) nl80211: Regulatory information - country=00 nl80211: 2402-2472 @ 40 MHz 20 mBm nl80211: 2457-2482 @ 40 MHz 20 mBm (no IR) nl80211: 2474-2494 @ 20 MHz 20 mBm (no OFDM) (no IR) nl80211: 5170-5250 @ 160 MHz 20 mBm (no IR) nl80211: 5250-5330 @ 160 MHz 20 mBm (DFS) (no IR) nl80211: 5490-5730 @ 160 MHz 20 mBm (DFS) (no IR) nl80211: Added 802.11b mode based on 802.11g information Completing interface initialization Mode: IEEE 802.11b Channel: 3 Frequency: 2422 MHz DFS 0 channels required radar detection nl80211: Set freq 2422 (ht_enabled=0, vht_enabled=0, bandwidth=20 MHz, cf1=2422 MHz, cf2=0 MHz) RATE rate=10 flags=0x1 RATE rate=20 flags=0x1 RATE rate=55 flags=0x0 RATE rate=110 flags=0x0 hostapd_setup_bss(hapd=0x2097a60 (wls160u2u1), first=1) wls160u2u1: Flushing old station entries nl80211: flush -> DEL_STATION wls160u2u1 (all) wls160u2u1: Deauthenticate all stations nl80211: send_mlme - da= ff:ff:ff:ff:ff:ff noack=0 freq=0 no_cck=0 offchanok=0 wait_time=0 fc=0xc0 (WLAN_FC_STYPE_DEAUTH) nlmode=3 nl80211: send_mlme -> send_frame nl80211: send_frame - Use bss->freq=2422 nl80211: send_frame -> send_frame_cmd nl80211: Frame command failed: ret=-16 (Device or resource busy) (freq=2422 wait=0) wpa_driver_nl80211_set_key: ifindex=4 (wls160u2u1) alg=0 addr=(nil) key_idx=0 set_tx=0 seq_len=0 key_len=0 wpa_driver_nl80211_set_key: ifindex=4 (wls160u2u1) alg=0 addr=(nil) key_idx=1 set_tx=0 seq_len=0 key_len=0 wpa_driver_nl80211_set_key: ifindex=4 (wls160u2u1) alg=0 addr=(nil) key_idx=2 set_tx=0 seq_len=0 key_len=0 wpa_driver_nl80211_set_key: ifindex=4 (wls160u2u1) alg=0 addr=(nil) key_idx=3 set_tx=0 seq_len=0 key_len=0 Using interface wls160u2u1 with hwaddr 00:02:72:b7:a2:0f and ssid "hostapdtest" Deriving WPA PSK based on passphrase SSID - hexdump_ascii(len=11): 68 6f 73 74 61 70 64 74 65 73 74 hostapdtest PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED] PSK (from passphrase) - hexdump(len=32): [REMOVED] random: Got 20/20 bytes from /dev/random GMK - hexdump(len=32): [REMOVED] Key Counter - hexdump(len=32): [REMOVED] WPA: Delay group state machine start until Beacon frames have been configured nl80211: Set beacon (beacon_set=0) nl80211: Beacon head - hexdump(len=58): 80 00 00 00 ff ff ff ff ff ff 00 02 72 b7 a2 0f 00 02 72 b7 a2 0f 00 00 00 00 00 00 00 00 00 00 64 00 11 00 00 0b 68 6f 73 74 61 70 64 74 65 73 74 01 04 82 84 0b 16 03 01 03 nl80211: Beacon tail - hexdump(len=32): 30 14 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 00 0f ac 02 00 00 7f 08 00 00 00 00 00 00 00 40 nl80211: ifindex=4 nl80211: beacon_int=100 nl80211: dtim_period=2 nl80211: ssid - hexdump_ascii(len=11): 68 6f 73 74 61 70 64 74 65 73 74 hostapdtest nl80211: hidden SSID not in use nl80211: privacy=1 nl80211: auth_algs=0x1 nl80211: wpa_version=0x2 nl80211: key_mgmt_suites=0x2 nl80211: pairwise_ciphers=0x10 nl80211: group_cipher=0x10 nl80211: beacon_ies - hexdump(len=10): 7f 08 00 00 00 00 00 00 00 40 nl80211: proberesp_ies - hexdump(len=10): 7f 08 00 00 00 00 00 00 00 40 nl80211: assocresp_ies - hexdump(len=10): 7f 08 00 00 00 00 00 00 00 40 WPA: Start group state machine to set initial keys WPA: group state machine entering state GTK_INIT (VLAN-ID 0) GTK - hexdump(len=16): [REMOVED] WPA: group state machine entering state SETKEYSDONE (VLAN-ID 0) wpa_driver_nl80211_set_key: ifindex=4 (wls160u2u1) alg=3 addr=0x47d5a9 key_idx=1 set_tx=1 seq_len=0 key_len=16 nl80211: KEY_DATA - hexdump(len=16): [REMOVED] broadcast key nl80211: Set wls160u2u1 operstate 0->1 (UP) netlink: Operstate: ifindex=4 linkmode=-1 (no change), operstate=6 (IF_OPER_UP) wls160u2u1: interface state UNINITIALIZED->ENABLED wls160u2u1: AP-ENABLED wls160u2u1: Setup of interface done. ctrl_iface not configured! RTM_NEWLINK: ifi_index=4 ifname=wls160u2u1 operstate=0 linkmode=0 ifi_family=0 ifi_flags=0x1043 ([UP][RUNNING]) RTM_NEWLINK: ifi_index=4 ifname=wls160u2u1 operstate=2 linkmode=0 ifi_family=0 ifi_flags=0x1003 ([UP]) RTM_NEWLINK: ifi_index=4 ifname=wls160u2u1 operstate=6 linkmode=0 ifi_family=0 ifi_flags=0x11043 ([UP][RUNNING][LOWER_UP]) nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wls160u2u1 nl80211: RX frame sa=94:eb:cd:10:31:92 freq=2422 ssi_signal=-80 stype=4 (WLAN_FC_STYPE_PROBE_REQ) len=81 nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wls160u2u1 nl80211: RX frame sa=94:eb:cd:10:31:92 freq=2422 ssi_signal=-80 stype=4 (WLAN_FC_STYPE_PROBE_REQ) len=81 nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wls160u2u1 nl80211: RX frame sa=94:eb:cd:10:31:92 freq=2422 ssi_signal=-84 stype=4 (WLAN_FC_STYPE_PROBE_REQ) len=81 nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wls160u2u1 nl80211: RX frame sa=94:eb:cd:10:31:92 freq=2422 ssi_signal=-82 stype=4 (WLAN_FC_STYPE_PROBE_REQ) len=78 nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wls160u2u1 nl80211: RX frame sa=94:eb:cd:10:31:92 freq=2422 ssi_signal=-80 stype=4 (WLAN_FC_STYPE_PROBE_REQ) len=78 ^CSignal 2 received - terminating hostapd_interface_deinit_free(0x2096860) hostapd_interface_deinit_free: num_bss=1 conf->num_bss=1 hostapd_interface_deinit(0x2096860) hostapd_bss_deinit: deinit bss wls160u2u1 wls160u2u1: Deauthenticate all stations nl80211: send_mlme - da= ff:ff:ff:ff:ff:ff noack=0 freq=0 no_cck=0 offchanok=0 wait_time=0 fc=0xc0 (WLAN_FC_STYPE_DEAUTH) nlmode=3 nl80211: send_mlme -> send_frame nl80211: send_frame - Use bss->freq=2422 nl80211: send_frame -> send_frame_cmd hostapd_cleanup(hapd=0x2097a60 (wls160u2u1)) hostapd_free_hapd_data(wls160u2u1) hostapd_interface_deinit_free: driver=0x491d40 drv_priv=0x20988d0 -> hapd_deinit nl80211: Remove monitor interface: refcount=0 nl80211: Remove beacon (ifindex=4) netlink: Operstate: ifindex=4 linkmode=0 (kernel-control), operstate=6 (IF_OPER_UP) nl80211: Set mode ifindex 4 iftype 2 (STATION) nl80211: Teardown AP(wls160u2u1) - device_ap_sme=0 use_monitor=0 nl80211: Unsubscribe mgmt frames handle 0x888888888a81fad9 (AP teardown) hostapd_interface_free(0x2096860) hostapd_interface_free: free hapd 0x2097a60 hostapd_cleanup_iface(0x2096860) hostapd_cleanup_iface_partial(0x2096860) hostapd_cleanup_iface: free iface=0x2096860
Shown above is the output of hostapd with debugging turned on using the -d switch. You can get even more information by using -dd. To stop hostapd you can send the interrupt signal by pressing ctrl+c at the terminal. At this stage you may wish to test the access point by connecting to it with some other wireless device. The ssid is public so you should be able to scan for and connect to it, however no IP routing is configured for the access point so it will be difficult to do any meaningful communication. Some devices may also drop the connection if they are unable to get an IP address through DHCP.
How you go about configuring routing could vary wildly depending on your network topography and what role the access point has to play in it. In this article we will demonstrate a simple wired to wireless bridge. That is, we will extend the ethernet LAN, which I am connected to on eno16777736, through our wireless access point.
Creating a bridge
A bridge, in this context, is a virtual interface which joins two (or more?) other interfaces together so that any traffic received by one interface in the bridge will be transmitted out the other. The bridge can also have an IP address assigned to it so that the two interfaces can be treated as a single end point. We can create a bridge using the ip command.
~ % sudo ip link add br0 type bridge ~ % sudo ip link set dev br0 up
So I have added a bridge called br0 and brought it up. Next I can add my ethernet interface, eno16777736, to the bridge as well. Please note that I had previously removed all IP addresses from eno16777736 (using ip addr del) and brought it down to avoid any conflicts.
~ % sudo ip link set eno16777736 promisc on ~ % sudo ip link set eno16777736 up ~ % sudo ip link set dev eno16777736 master br0 ~ % bridge link show 2: eno16777736 state UP : <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 4
The above has set the interface to promiscuous mode, brought it up and set the bridge interface as eno16777736’s master. Finally bridge link show displays the bridge’s interface(s). At this stage I could set up a static IP address and manually add routing and DNS information, but it is more convenient to just use DHCP.
The chances are that the DHCP client will just work. However there is a configuration file for it, most likely in /etc/dhcpcd.conf.
~ % sudo dhcpcd -dw br0 dhcpcd: version 6.7.1 starting dhcpcd: br0: disabling kernel IPv6 RA support dhcpcd: br0: executing `/usr/lib/dhcpcd/dhcpcd-run-hooks' PREINIT dhcpcd: br0: executing `/usr/lib/dhcpcd/dhcpcd-run-hooks' CARRIER dhcpcd: DUID 00:01:00:01:1b:51:a2:ad:00:0c:29:fb:70:6e dhcpcd: br0: IAID 29:1e:95:1a dhcpcd: br0: delaying IPv6 router solicitation for 0.4 seconds dhcpcd: br0: delaying IPv4 for 0.5 seconds dhcpcd: br0: soliciting an IPv6 router dhcpcd: br0: sending Router Solicitation dhcpcd: br0: soliciting a DHCP lease dhcpcd: br0: sending DISCOVER (xid 0x7d2e22fd), next in 3.5 seconds dhcpcd: br0: offered 192.168.146.128 from 192.168.146.254 dhcpcd: br0: sending REQUEST (xid 0x7d2e22fd), next in 4.1 seconds dhcpcd: br0: acknowledged 192.168.146.128 from 192.168.146.254 dhcpcd: br0: probing for 192.168.146.128 dhcpcd: br0: ARP probing 192.168.146.128 (1 of 3), next in 1.2 seconds dhcpcd: br0: ARP probing 192.168.146.128 (2 of 3), next in 1.6 seconds dhcpcd: br0: sending Router Solicitation dhcpcd: br0: ARP probing 192.168.146.128 (3 of 3), next in 2.0 seconds dhcpcd: br0: leased 192.168.146.128 for 1800 seconds dhcpcd: br0: renew in 900 seconds, rebind in 1575 seconds dhcpcd: br0: writing lease `/var/lib/dhcpcd/dhcpcd-br0.lease' dhcpcd: br0: adding IP address 192.168.146.128/24 dhcpcd: br0: adding route to 192.168.146.0/24 dhcpcd: br0: adding default route via 192.168.146.2 dhcpcd: br0: executing `/usr/lib/dhcpcd/dhcpcd-run-hooks' BOUND dhcpcd: forking to background dhcpcd: forked to background, child pid 11390
So this shows that the bridge now has an IP address, this may not be strictly necessary if you don’t want the access point itself to be accessible from the network. Next we need to make a small change to the hostapd configuration file so that it adds the wireless interface to the bridge.
ssid=hostapdtest interface=wls160u2u1 bridge=br0 channel=3 driver=nl80211 macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=YourPassphrase wpa_key_mgmt=WPA-PSK wpa_pairwise=CCMP rsn_pairwise=CCMP