# Wi-Fi networking for Raspberry Pi
<small>*Practice using Raspberry Pi 4B with Raspberry Pi OS (64-bit) 2023-12-05.*</small>
## Wireless interface
- **rfkill** unblock
Make sure the wireless card is enabled. Use **rfkill** to check the status of wireless card.
```shell
$ rfkill list
```
If the wireless card is blocked, use the following command to unblock it.
```shell
$ rfkill unblock wifi
```
- disable **NetworkManager**
If using the desktop version of Raspberry Pi OS or Ubuntu, then stop NetworkManager.
```shell
$ sudo systemctl status NetworkManager
$ sudo systemctl stop NetworkManager
$ sudo systemctl disable NetworkManager
```
- **wireless interface and wireless network**
Use **iwconfig** or **iw dev** to find the name of wireless interfaces.
```shell
$ iwconfig
$ iw dev
```
Find the wireless network name by scanning nearby networks with the command below.
```shell
$ sudo iwlist wlan0 scan | grep ESSID
```
If it shows error message "**Network is down**", turn on the interface using command below.
```shell
$ sudo ifconfig wlan0 up
#or
$ sudo ip link set dev wlan0 up
```
- **show the capabilities of the wireless interface**
Use **iw list** to show the capabilities of all Wi-Fi interfaces, or use **iw phy <phyname> info** to see the specified interface information. It will show the supported modes of the interface.
```shell
$ iw list
$ iw phy phy0 info
...
Supported interface modes:
* IBSS
* managed
* AP
* P2P-client
* P2P-GO
* P2P-device
...
```
## Infrastructure Wi-Fi network
- **wpa_supplicant for infrastructure mode**
Install wpa_supplicant if not installed.
```shell
$ sudo apt install wpasupplicant
```
Create a configuration file named *wpa_supplicant_IFCE.conf* using the **wpa_passphrase** utility.
```shell
$ wpa_passphrase <AP-ESSID> <AP-passphrase> | tee wpa_supplicant_wlan0.conf
```
Use the following command to connect the wireless card to wireless access point.
```shell
$ sudo wpa_supplicant -B -i wlan0 -c wpa_supplicant_wlan0.conf
```
See the connection information.
```shell
$ iw dev
```
- **dhclient**
Although the network is connected, but we don't have an IP address yet. To obtail a private IP address from DHCP server, user the following command:
```shell
$ sudo dhclient wlan0
$ ifconfig wlan0
```
To release the private IP address, run
```shell
$ sudo dhclient wlan0 -r
```
## ad-hoc network
- **wpa_supplicant for ad-hoc mode**
Create a configuration file named *wpa_supplicant_adhoc.conf* with the following text.
```txt
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
country=TW
update_config=1
p2p_disabled=1
network={
ssid="cloud"
mode=1
frequency=2421
key_mgmt=NONE
}
```
**wpa_supplicant** has peer-to-peer enabled by default, which is used by WiFi-Direct. If you do not disable P2P with the option *p2p_disabled=1*, you cannot enable IBSS mode and will receive the following error messages:
```txt
nl80211: Failed to set interface into IBSS mode
wlan0: Association request to the driver failed
```
Connect the wireless card to the ad-hoc network.
```shell
$ sudo wpa_supplicant -B -i wlan0 -c wpa_supplicant_adhoc.conf
```
See the connection information.
```shell
$ iw dev
```
- **Static IP address**
Use the **ip addr** command to assign a static IP address to the interface.
```shell
$ sudo ip addr add 10.0.0.1/24 dev wlan0
```
See the IP address of the interface.
```shell
$ ip -c addr show wlan0
```
To obtain node information within the ad-hoc network and check for duplicate IP addresses, use the following command.
```shell
$ sudo arp-scan -I wlan0 -l
```
**Note:** If the duplicated IP address is assigned to the interface itself, it may not receive the response packets, resulting in an empty result.
Another way to setup a static IP address is to use the **networking service** to create a network interface configuratioin file, for example, named *wlan0* ,in /etc/network/interfaces.d/ directory. It can also configure ad-hoc mode in this file instead of using **wpa_supplicant**.
```txt
auto wlan0
iface wlan0 inet static
address 10.0.0.1
netmask 255.255.255.0
# set up ad-hoc mode instead of using wpa_supplicant
wireless-channel 1
wireless-essid cloud
wireless-mode ad-hoc
```
Then, restart the networking service.
```shell
$ sudo systemctl restart networking
$ sudo systemctl status networking
```
- **routing table**
Use the **ip route** command to check the routing table for a route to the ad-hoc network associated with the interface. If there isn't one, add it.
```shell
$ ip route
$ ip route add 10.0.0.0/24 dev wlan0
```
**Note:** Another way is to use the **route** command to add a route.
```shell
$ route -n
$ route add -net 10.0.0.0/24 dev wlan0
```
- **Signal strength**
Use the **iw** command to check the information of associated peers in the ad-hoc network, including the signal strength data.
```shell
$ iw dev wlan0 station dump
```
This may yield an empty result on Raspberry Pi, so specifying the MAC address can obtain the desired result.
```shell
$ iw dev wlan0 station get <MAC address>
```
### Auto Wi-Fi connect on startup
- **wpa_supplicant service**
To automatically connect to wireless network at boot time, we need to edit the *wpa_supplicant.service* file. It's good idea to copy the file from */lib/systemd/system/* directory to ***/etc/systemd/system/*** directory, then edit it because we don't want newer version of **wpasupplicant** to override our modifications.
```shell
sudo cp /lib/systemd/system/wpa_supplicant.service /etc/systemd/system/wpa_supplicant.service
sudo vim /etc/systemd/system/wpa_supplicant.service
```
Change the line as the following.
```txt
#ExecStart=/sbin/wpa_supplicant -u -s -O "DIR=/run/wpa_supplicant GROUP=netdev"
ExecStart=/sbin/wpa_supplicant -u -s -c /etc/wpa_supplicant.conf -i wlan0
```
Comment the line if exists.
```txt
#Alias=dbus-fi.w1.wpa_supplicant1.service
```
It's recommended to always try to restart wpa_supplicant when failure is detected. Add the following right below the `ExecStart` line.
```txt
Restart=always
```
If the external WiFi device **wlan1** is used, add and change the content as follows.
```txt
BindsTo=sys-subsystem-net-devices-wlan1.device
After=sys-subsystem-net-devices-wlan1.device
#After=dbus.service
```
So, the fianl service file is
```txt
[Unit]
Description=WPA supplicant
Before=network.target
BindsTo=sys-subsystem-net-devices-wlan1.device
After=sys-subsystem-net-devices-wlan1.device
#After=dbus.service
Wants=network.target
IgnoreOnIsolate=true
[Service]
Type=dbus
BusName=fi.w1.wpa_supplicant1
ExecStart=/sbin/wpa_supplicant -u -s -c /etc/wpa_supplicant/wpa_supplicant-connTimotion.conf -i wlan1
#ExecStart=/sbin/wpa_supplicant -u -s -O "DIR=/run/wpa_supplicant GROUP=netdev"
ExecReload=/bin/kill -HUP $MAINPID
Group=netdev
RuntimeDirectory=wpa_supplicant
RuntimeDirectoryMode=0750
[Install]
WantedBy=multi-user.target
#Alias=dbus-fi.w1.wpa_supplicant1.service
```
Enable wpa_supplicant service.
```shell
$ sudo systemctl enable wpa_supplicant.service
```
- **dhclient service**
Create a systemd service unit for **dhclient** if the interface does not use a static IP address.
```shell
$ sudo vim /etc/systemd/system/dhclient.service
```
Put the following text into the file.
```text
[Unit]
Description= DHCP Client
Before=network.target
# If the external WiFi device 'wlan1' is used.
BindsTo=sys-subsystem-net-devices-wlan1.device
After=sys-subsystem-net-devices-wlan1.device
[Service]
Type=forking
ExecStart=/sbin/dhclient wlan0 -v
ExecStop=/sbin/dhclient wlan0 -r
Restart=always
[Install]
WantedBy=multi-user.target
```
Restart this service.
```shell
$ sudo systemctl restart dhclient.service
```
Enable this service.
```shell
$ sudo systemctl enable dhclient.service
```
**Note:** The **dhclient** service can be used to set up a static IP address without a DHCP server by using the following confuguration.
```shell
$ sudo vim /etc/dhcp/dhclient.conf
...
lease {
interface "wlan0";
fixed-address 10.0.0.3;
option subnet-mask 255.255.255.0;
}
```
### References
- The wpa_supplicant official site: [Developers' documentation for wpa_supplicant](https://w1.fi/wpa_supplicant/devel/index.html) and [wpa_supplicant.conf](https://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf)
- Debian wifi: [NetworkConfiguration](https://wiki.debian.org/NetworkConfiguration) and [WiFi Ad-hoc Network](https://wiki.debian.org/WiFi/AdHoc)
- [Linux *ip* Command Examples](https://www.cyberciti.biz/faq/linux-ip-command-examples-usage-syntax/)
- [Using WPA_Supplicant to Connect to WPA2 Wi-fi from Terminal on Ubuntu 16.04 Server](https://www.linuxbabe.com/command-line/ubuntu-server-16-04-wifi-wpa-supplicant)
- [How to setup an Ad Hoc (IBSS) Network](https://raspberrypi.stackexchange.com/questions/94047/how-to-setup-an-unprotected-ad-hoc-ibss-network-and-if-possible-with-wpa-encry)
- [How to bring up network on boot-up when NetworkManager is uninstalled?](https://askubuntu.com/questions/22663/how-to-bring-up-network-on-boot-up-when-networkmanager-is-uninstalled)
- [Create a Mesh Network over WiFi using Raspberry Pi](https://github.com/binnes/WiFiMeshRaspberryPi)