38 Commits

Author SHA1 Message Date
garywill
3d3a63d53b version 0.7.3 2024-01-19 14:33:25 +08:00
garywill
0274cd339b Merge branch 2024-01-19 14:26:36 +08:00
garywill
32f168ec8c can_transmit_to_channel() ignores freq value just focus on channel number 2024-01-19 13:50:34 +08:00
Zehka
f42dc4314d regex fixes 2024-01-16 13:26:52 +01:00
Zehka
78d481d083 also ignore trailing \.0+ for iw phy info 2024-01-16 00:59:41 +01:00
Zehka
34e326f303 Remove trailing .0 from iw reported frequency
Signed-off-by: Zehka <git@zehka.net>
2024-01-16 00:32:56 +01:00
garywill
cbaa19db72 improve pci info format 2024-01-14 20:25:06 +08:00
garywill
a86517294b readme 2024-01-14 20:20:50 +08:00
garywill
9790d3117b show current pci driver 2024-01-14 09:27:36 +08:00
garywill
e65228750b apply some spellcheck 2024-01-14 08:49:38 +08:00
garywill
718a1752f1 version 0.7.1 2023-12-30 22:31:32 +08:00
garywill
5dcfacc418 0.7.1b readme 2023-10-04 22:02:49 +08:00
garywill
0c85f00297 version 0.7.1b 2023-10-04 21:48:37 +08:00
garywill
a2fcbc4781 aliases 2023-10-04 21:48:27 +08:00
garywill
63cd88b5fc version 0.7.0b 2023-10-04 11:54:49 +08:00
garywill
957ed25f07 rename some options 2023-10-04 11:43:24 +08:00
garywill
183cf44934 remove duplicated hostapd.conf path info (will show after) 2023-10-04 11:21:50 +08:00
garywill
4e92b3ebf5 -c will not fallback automatically 2023-10-04 11:21:00 +08:00
garywill
992ad00ca1 Revert "Add force channel flag"
This reverts commit 73441c4ed3.
2023-10-04 10:41:13 +08:00
Phani Pavan Kambhampati
9d874dbe88 Fix variables 2023-10-02 13:04:41 +05:30
Phani Pavan K
b94cf7c43f 5GHz Fat Channel Support 2023-09-28 12:16:59 +05:30
Phani Pavan K
0acb16dbaa Add Hotspot 2.0 Support flag 2023-09-28 11:42:00 +05:30
Phani Pavan K
73441c4ed3 Add force channel flag 2023-09-28 11:19:29 +05:30
garywill
8527e1a9b6 add link to web doc reader 2023-04-23 14:36:37 +08:00
garywill
18a57119b9 readme 2023-04-23 14:05:41 +08:00
garywill
7f1ae6282e readme 2023-04-23 14:01:35 +08:00
garywill
4515dde9b4 readme 2023-04-23 10:17:41 +08:00
garywill
45ad35d29f 0.6.7 2023-01-07 20:55:20 +08:00
garywill
a663d9052b update readme 2023-01-07 09:10:05 +08:00
garywill
e3941c560f text 2023-01-07 09:08:18 +08:00
garywill
7ec589b1c2 add some notice 2023-01-07 09:07:18 +08:00
Cabbache
10ca7249cb Updated --virt-name to make interface name predictable 2023-01-07 01:02:04 +00:00
lukescerri
a414ac035b Added --virt-name option 2022-09-26 21:26:50 +02:00
lukescerri
b51a2d2349 renamed virtual interface 2022-09-24 17:32:28 +02:00
garywill
9e1d985623 move 'qrencode' from readme dependency to cli usage note 2022-04-03 18:05:05 +08:00
garywill
433b3b8d39 add --dns-nocache option 2022-04-03 18:03:51 +08:00
garywill
e8284c5398 add "Install" section in readme 2022-04-03 17:46:48 +08:00
garywill
c2da43250e typo 2022-04-03 17:46:24 +08:00
2 changed files with 401 additions and 228 deletions

168
README.md
View File

@@ -6,6 +6,7 @@ It wraps `iptables`, `dnsmasq` etc. stuff. Use in one command, restore in one co
[Linux-Router News & Developer Notes 📰](https://github.com/garywill/linux-router/issues/28) | [More tools and projects 🛠️](https://garywill.github.io) | [🍻 Buy me a coffee ❤️](https://github.com/garywill/receiving/blob/master/receiving_methods.md)
## Features
Basic features:
@@ -61,11 +62,36 @@ Internet----(eth0/wlan0)-Linux-(eth1)------Another PC
Internet----(eth0/wlan0)-Linux-(virtual interface)-----VM/container
```
## Install
1-file-script. Release on [Linux-router repo on Github](https://github.com/garywill/linux-router). Just download and run the bash script (meet the dependencies). In this case use without installation.
I'm currently not packaging for any distro. If you do, open a PR and add the link (can be with a version badge) to list here
| Linux distro | |
| ------------ | ---------------------------------------------------------------------------------------------------------- |
| Any | download [1-file-script](https://raw.githubusercontent.com/garywill/linux-router/master/lnxrouter) and run without installation |
### Dependencies
- bash
- procps or procps-ng
- iproute2
- dnsmasq
- iptables (or nftables with `iptables-nft` translation linked)
- WiFi hotspot dependencies
- hostapd
- iw
- iwconfig (you only need this if 'iw' can not recognize your adapter)
- haveged (optional)
## Usage
### Provide Internet to an interface
```
```bash
sudo lnxrouter -i eth1
```
@@ -73,7 +99,7 @@ no matter which interface (other than `eth1`) you're getting Internet from.
### Create WiFi hotspot
```
```bash
sudo lnxrouter --ap wlan0 MyAccessPoint -p MyPassPhrase
```
@@ -85,7 +111,7 @@ Clients access Internet through only `isp5`
<details>
```
```bash
sudo lnxrouter -i eth1 -o isp5 --no-dns --dhcp-dns 1.1.1.1 -6 --dhcp-dns6 [2606:4700:4700::1111]
```
@@ -98,12 +124,15 @@ sudo lnxrouter -i eth1 -o isp5 --no-dns --dhcp-dns 1.1.1.1 -6 --dhcp-dns6 [26
</details>
### LAN without Internet
### Create LAN without providing Internet
<details>
```
```bash
sudo lnxrouter -n -i eth1
```
```bash
sudo lnxrouter -n --ap wlan0 MyAccessPoint -p MyPassPhrase
```
@@ -117,7 +146,7 @@ sudo lnxrouter -n --ap wlan0 MyAccessPoint -p MyPassPhrase
Create a bridge
```
```bash
sudo brctl addbr lxcbr5
```
@@ -130,7 +159,7 @@ lxc.network.link = lxcbr5
lxc.network.hwaddr = xx:xx:xx:xx:xx:xx
```
```
```bash
sudo lnxrouter -i lxcbr5
```
@@ -138,11 +167,11 @@ sudo lnxrouter -i lxcbr5
### Transparent proxy
All clients' Internet traffic go through, for example, Tor
All clients' Internet traffic go through, for example, Tor (notice this example is NOT an anonymity use)
<details>
```
```bash
sudo lnxrouter -i eth1 --tp 9040 --dns 9053 -g 192.168.55.1 -6 --p6 fd00:5:6:7::
```
@@ -155,6 +184,10 @@ TransPort [fd00:5:6:7::1]:9040
DNSPort [fd00:5:6:7::1]:9053
```
> **Warn**: Tor's anonymity relies on a purpose-made browser. Using Tor like this (sharing Tor's network to LAN clients) will NOT ensure anonymity.
>
> Although we use Tor as example here, Linux-router does NOT ensure nor is NOT aiming at anonymity.
</details>
### Clients-in-sandbox network
@@ -163,7 +196,7 @@ To not give our infomation to clients. Clients can still access Internet.
<details>
```
```bash
sudo lnxrouter -i eth1 \
--tp 9040 --dns 9053 \
--random-mac \
@@ -173,7 +206,7 @@ sudo lnxrouter -i eth1 \
</details>
> This script comes with no warrenty. Use on your own risk
> Linux-router comes with no warranty. Use on your own risk
### Use as transparent proxy for LXD
@@ -181,13 +214,13 @@ sudo lnxrouter -i eth1 \
Create a bridge
```
```bash
sudo brctl addbr lxdbr5
```
Create and add a new LXD profile overriding container's `eth0`
```
```bash
lxc profile create profile5
lxc profile edit profile5
@@ -205,13 +238,13 @@ name: profile5
lxc profile add <container> profile5
```
```
```bash
sudo lnxrouter -i lxdbr5 --tp 9040 --dns 9053
```
To remove that new profile from container
```
```bash
lxc profile remove <container> profile5
```
@@ -219,13 +252,13 @@ lxc profile remove <container> profile5
Add new `eth0` to container overriding default `eth0`
```
```bash
lxc config device add <container> eth0 nic name=eth0 nictype=bridged parent=lxdbr5
```
To remove the customized `eth0` to restore default `eth0`
```
```bash
lxc config device remove <container> eth0
```
@@ -237,7 +270,7 @@ lxc config device remove <container> eth0
In VirtualBox's global settings, create a host-only network `vboxnet5` with DHCP disabled.
```
```bash
sudo lnxrouter -i vboxnet5 --tp 9040 --dns 9053
```
@@ -249,11 +282,11 @@ sudo lnxrouter -i vboxnet5 --tp 9040 --dns 9053
Create a bridge
```
```bash
sudo brctl addbr firejail5
```
```
```bash
sudo lnxrouter -i firejail5 -g 192.168.55.1 --tp 9040 --dns 9053
firejail --net=firejail5 --dns=192.168.55.1 --blacklist=/var/run/nscd
```
@@ -317,26 +350,28 @@ Options:
-d DNS server will take into account /etc/hosts
-e <hosts_file> DNS server will take into account additional
hosts file
--dns-nocache DNS server no cache
--mac <MAC> Set MAC address
--random-mac Use random MAC address
--tp <port> Transparent proxy,
redirect non-LAN TCP and UDP traffic to port.
(usually used with '--dns')
redirect non-LAN TCP and UDP(not tested) traffic to
port. (usually used with '--dns')
WiFi hotspot options:
--ap <wifi interface> <SSID>
Create WiFi access point
-p, --password <password>
WiFi password
--qr Show WiFi QR code in terminal
--qr Show WiFi QR code in terminal (need qrencode)
--hidden Hide access point (not broadcast SSID)
--no-virt Do not create virtual interface
Using this you can't use same wlan interface
for both Internet and AP
-c <channel> Channel number (default: 1)
--virt-name <name> Set name of virtual interface
-c <channel> Specify channel (default: use current, or 1 / 36)
--country <code> Set two-letter country code for regularity
(example: US)
--freq-band <GHz> Set frequency band: 2.4 or 5 (default: 2.4)
@@ -350,13 +385,28 @@ Options:
(defaults to /etc/hostapd/hostapd.accept)
--hostapd-debug <level> 1 or 2. Passes -d or -dd to hostapd
--isolate-clients Disable wifi communication between clients
--ieee80211n Enable IEEE 802.11n (HT)
--ieee80211ac Enable IEEE 802.11ac (VHT)
--ht_capab <HT> HT capabilities (default: [HT40+])
--vht_capab <VHT> VHT capabilities
--no-haveged Do not run haveged automatically when needed
--hs20 Enable Hotspot 2.0
WiFi 4 (802.11n) configs:
--wifi4 Enable IEEE 802.11n (HT)
--req-ht Require station HT (High Throughput) mode
--ht-capab <HT caps> HT capabilities (default: [HT40+])
WiFi 5 (802.11ac) configs:
--wifi5 Enable IEEE 802.11ac (VHT)
--req-vht Require station VHT (Very High Thoughtput) mode
--vht-capab <VHT caps> VHT capabilities
--vht-ch-width <index> Index of VHT channel width:
0 for 20MHz or 40MHz (default)
1 for 80MHz
2 for 160MHz
3 for 80+80MHz (Non-contigous 160MHz)
--vht-seg0-ch <channel> Channel index of VHT center frequency for primary
segment. Use with '--vht-ch-width'
--vht-seg1-ch <channel> Channel index of VHT center frequency for secondary
(second 80MHz) segment. Use with '--vht-ch-width 3'
Instance managing:
--daemon Run in background
@@ -368,15 +418,7 @@ Options:
--stop <id> Stop a running instance
For <id> you can use PID or subnet interface name.
You can get them with '--list-running'
```
</details>
## Notice
<details>
```
Notice 1: This script assume your host's default policy won't forward
packets, so the script won't explictly ban forwarding in any
mode. In some unexpected case (eg. mistaken configurations) may
@@ -397,19 +439,35 @@ On exit of a linux-router instance, script **will do cleanup**, i.e. undo most c
5. The wifi device which is used to create hotspot is `rfkill unblock`ed
6. WiFi country code, if user assigns
## Dependencies
## Meet contributor(s) and become one of them
- bash
- procps or procps-ng
- iproute2
- dnsmasq
- iptables (or nftables with `iptables-nft` translation linked)
- WiFi hotspot dependencies
- hostapd
- iw
- iwconfig (you only need this if 'iw' can not recognize your adapter)
- haveged (optional)
- qrencode (optional)
Visit [**my homepage** 🏡](https://garywill.github.io) to see **more tools and projects** 🛠️.
> [❤️ Buy me a coffee](https://github.com/garywill/receiving/blob/master/receiving_methods.md) , this project took me lots of time! ([❤️ 扫码领红包并打赏一个!](https://github.com/garywill/receiving/blob/master/receiving_methods.md))
>
> 🥂 ( ^\_^) o自自o (^_^ ) 🍻
🤝 Bisides, thank [create_ap](https://github.com/oblique/create_ap) by [oblique](https://github.com/oblique). This script was forked from create\_ap. Now they are quite different. (See `history` branch for how I modified create_ap). 🤝 Also thank those who contributed to that project.
👨‍💻 You can be contributor, too!
- 🍃 There're some TO-DOs listed, in both [readme TODO](#todo) and [in the code file](https://github.com/garywill/linux-router/search?q=TODO&type=code)
- 🍃 Also some [unfulfilled enhancements in the Issues](https://github.com/garywill/linux-router/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
- 🙋‍♂️ Contributions are not limited to coding. There're [some posts and questions](https://github.com/garywill/linux-router/issues) that need more people to answer
## Notice
<details>
```
Notice 1: This script assume your host's default policy won't forward
packets, so the script won't explictly ban forwarding in any
mode. In some unexpected case (eg. mistaken configurations) may
cause unwanted packets leakage between 2 networks, which you
should be aware of if you want isolated network
```
</details>
## TODO
@@ -481,14 +539,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</details>
## Meet developer(s) and become one of them
Visit [**my homepage** 🏡](https://garywill.github.io) to see **more tools and projects** 🛠️.
> [❤️ Buy me a coffee](https://github.com/garywill/receiving/blob/master/receiving_methods.md) , this project took me lots of time! ([❤️ 扫码领红包并打赏一个!](https://github.com/garywill/receiving/blob/master/receiving_methods.md))
>
> 🥂 ( ^\_^) o自自o (^_^ ) 🍻
🤝 Bisides, thank [create_ap](https://github.com/oblique/create_ap) by [oblique](https://github.com/oblique). This script was forked from create\_ap. Now they are quite different. (See `history` branch for how I modified create_ap). 🤝 Also thank those who contributed to that project.
👨‍💻 You can be contributor, too! 🍃 There're some TO-DOs listed, at both [above](#todo) and [in the code file](https://github.com/garywill/linux-router/search?q=TODO&type=code). 🍃 Also some [unfulfilled enhancements in the Issues](https://github.com/garywill/linux-router/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement). Your name can be here!

443
lnxrouter
View File

@@ -1,7 +1,7 @@
#!/bin/bash
VERSION=0.6.6
PROGNAME="$(basename $0)"
VERSION=0.7.3
PROGNAME="$(basename "$0")"
export LC_ALL=C
@@ -67,26 +67,28 @@ Options:
-d DNS server will take into account /etc/hosts
-e <hosts_file> DNS server will take into account additional
hosts file
--dns-nocache DNS server no cache
--mac <MAC> Set MAC address
--random-mac Use random MAC address
--tp <port> Transparent proxy,
redirect non-LAN TCP and UDP traffic to port.
(usually used with '--dns')
redirect non-LAN TCP and UDP(not tested) traffic to
port. (usually used with '--dns')
WiFi hotspot options:
--ap <wifi interface> <SSID>
Create WiFi access point
-p, --password <password>
WiFi password
--qr Show WiFi QR code in terminal
--qr Show WiFi QR code in terminal (need qrencode)
--hidden Hide access point (not broadcast SSID)
--no-virt Do not create virtual interface
Using this you can't use same wlan interface
for both Internet and AP
-c <channel> Channel number (default: 1)
--virt-name <name> Set name of virtual interface
-c <channel> Specify channel (default: use current, or 1 / 36)
--country <code> Set two-letter country code for regularity
(example: US)
--freq-band <GHz> Set frequency band: 2.4 or 5 (default: 2.4)
@@ -100,13 +102,28 @@ Options:
(defaults to /etc/hostapd/hostapd.accept)
--hostapd-debug <level> 1 or 2. Passes -d or -dd to hostapd
--isolate-clients Disable wifi communication between clients
--ieee80211n Enable IEEE 802.11n (HT)
--ieee80211ac Enable IEEE 802.11ac (VHT)
--ht_capab <HT> HT capabilities (default: [HT40+])
--vht_capab <VHT> VHT capabilities
--no-haveged Do not run haveged automatically when needed
--hs20 Enable Hotspot 2.0
WiFi 4 (802.11n) configs:
--wifi4 Enable IEEE 802.11n (HT)
--req-ht Require station HT (High Throughput) mode
--ht-capab <HT caps> HT capabilities (default: [HT40+])
WiFi 5 (802.11ac) configs:
--wifi5 Enable IEEE 802.11ac (VHT)
--req-vht Require station VHT (Very High Thoughtput) mode
--vht-capab <VHT caps> VHT capabilities
--vht-ch-width <index> Index of VHT channel width:
0 for 20MHz or 40MHz (default)
1 for 80MHz
2 for 160MHz
3 for 80+80MHz (Non-contigous 160MHz)
--vht-seg0-ch <channel> Channel index of VHT center frequency for primary
segment. Use with '--vht-ch-width'
--vht-seg1-ch <channel> Channel index of VHT center frequency for secondary
(second 80MHz) segment. Use with '--vht-ch-width 3'
Instance managing:
--daemon Run in background
@@ -156,6 +173,7 @@ define_global_variables(){
SHOW_DNS_QUERY=0 # log dns
ETC_HOSTS=0
ADDN_HOSTS=
DNS_NOCACHE=
CONN_IFACE= # which interface user choose to use to create network
INTERNET_IFACE= # which interface to get Internet from
THISHOSTNAME= # this host's name the DNS tells clients
@@ -176,13 +194,19 @@ define_global_variables(){
HIDDEN=0 # hidden wifi hotspot
WIFI_IFACE=
CHANNEL=default
HOTSPOT20=0 # For enabling Hotspot 2.0
WPA_VERSION=2
MAC_FILTER=0
MAC_FILTER_ACCEPT=/etc/hostapd/hostapd.accept
IEEE80211N=0
REQUIREHT=0
IEEE80211AC=0
REQUIREVHT=0
HT_CAPAB='[HT40+]'
VHT_CAPAB=
VHTCHANNELWIDTH=0
VHTSEG0CHINDEX=0
VHTSEG1CHINDEX=0
DRIVER=nl80211
NO_VIRT=0 # not use virtual interface
COUNTRY=
@@ -195,6 +219,7 @@ define_global_variables(){
# script variables
VWIFI_IFACE= # virtual wifi interface name, if created
VIRT_NAME= # name to use for virtual interface if --virt-name is used
AP_IFACE= # can be VWIFI_IFACE or WIFI_IFACE
USE_IWCONFIG=0 # some device can't use iw
@@ -322,6 +347,10 @@ parse_user_options(){
ADDN_HOSTS="$1"
shift
;;
--dns-nocache)
shift
DNS_NOCACHE=1
;;
--isolate-clients)
shift
@@ -365,6 +394,10 @@ parse_user_options(){
CHANNEL="$1"
shift
;;
--hs20)
shift
HOTSPOT20=1
;;
-w)
shift
WPA_VERSION="$1"
@@ -372,24 +405,47 @@ parse_user_options(){
shift
;;
--ieee80211n)
--wifi4|--ieee80211n)
shift
IEEE80211N=1
;;
--ieee80211ac)
--req-ht|--require-ht)
shift
REQUIREHT=1
;;
--wifi5|--ieee80211ac)
shift
IEEE80211AC=1
;;
--ht_capab)
--req-vht|--require-vht)
shift
REQUIREVHT=1
;;
--ht-capab)
shift
HT_CAPAB="$1"
shift
;;
--vht_capab)
--vht-capab)
shift
VHT_CAPAB="$1"
shift
;;
--vht-ch-width|--vht-channel-width)
shift
VHTCHANNELWIDTH="$1"
shift
;;
--vht-seg0-ch|--vht-seg0-channel)
shift
VHTSEG0CHINDEX="$1"
shift
;;
--vht-seg1-ch|--vht-seg1-channel)
shift
VHTSEG1CHINDEX="$1"
shift
;;
--driver)
shift
DRIVER="$1"
@@ -399,6 +455,11 @@ parse_user_options(){
shift
NO_VIRT=1
;;
--virt-name)
shift
VIRT_NAME="$1"
shift
;;
--country)
shift
@@ -416,9 +477,9 @@ parse_user_options(){
;;
--hostapd-debug)
shift
if [ "x$1" = "x1" ]; then
if [ "$1" = "1" ]; then
HOSTAPD_DEBUG_ARGS="-d"
elif [ "x$1" = "x2" ]; then
elif [ "$1" = "2" ]; then
HOSTAPD_DEBUG_ARGS="-dd"
else
printf "Error: argument for --hostapd-debug expected 1 or 2, got %s\n" "$1"
@@ -475,8 +536,8 @@ sep_ip_port() {
if (echo "$INPUT" | grep '\.' >/dev/null 2>&1) ;then
if (echo "$INPUT" | grep ':' >/dev/null 2>&1) ;then
# ipv4 + port
IP="$(echo $INPUT | cut -d: -f1)"
PORT="$(echo $INPUT | cut -d: -f2)"
IP="$(echo "$INPUT" | cut -d: -f1)"
PORT="$(echo "$INPUT" | cut -d: -f2)"
else
# ipv4
IP="$INPUT"
@@ -484,11 +545,11 @@ sep_ip_port() {
elif (echo "$INPUT" | grep '\]' >/dev/null 2>&1) ;then
if (echo "$INPUT" | grep '\]\:' >/dev/null 2>&1) ;then
# ipv6 + port
IP="$(echo $INPUT | cut -d']' -f1 | cut -d'[' -f2)"
PORT="$(echo $INPUT | cut -d']' -f2 |cut -d: -f2)"
IP="$(echo "$INPUT" | cut -d']' -f1 | cut -d'[' -f2)"
PORT="$(echo "$INPUT" | cut -d']' -f2 |cut -d: -f2)"
else
# ipv6
IP="$(echo $INPUT | cut -d']' -f1 | cut -d'[' -f2)"
IP="$(echo "$INPUT" | cut -d']' -f1 | cut -d'[' -f2)"
fi
else
# port
@@ -505,6 +566,10 @@ is_interface() {
[[ -d "/sys/class/net/${1}" ]]
}
is_vface_name_allocated(){
is_interface "$1" || [[ -f "$COMMON_CONFDIR/vfaces/${1}" ]]
}
get_interface_phy_device() { # only for wifi interface
local x
for x in /sys/class/ieee80211/*; do
@@ -513,10 +578,10 @@ get_interface_phy_device() { # only for wifi interface
echo "$1"
return 0
elif [[ -e "$x/device/net/$1" ]]; then
echo ${x##*/}
echo "${x##*/}"
return 0
elif [[ -e "$x/device/net:$1" ]]; then
echo ${x##*/}
echo "${x##*/}"
return 0
fi
done
@@ -528,13 +593,13 @@ get_adapter_info() { # only for wifi interface
local iPHY
iPHY=$(get_interface_phy_device "$1")
[[ $? -ne 0 ]] && return 1
iw phy $iPHY info
iw phy "$iPHY" info
}
get_adapter_kernel_module() {
local MODULE
MODULE=$(readlink -f "/sys/class/net/$1/device/driver/module")
echo ${MODULE##*/}
echo "${MODULE##*/}"
}
can_be_sta_and_ap() {
@@ -565,18 +630,14 @@ can_transmit_to_channel() {
CHANNEL_NUM=$2
if [[ $USE_IWCONFIG -eq 0 ]]; then
if [[ $FREQ_BAND == 2.4 ]]; then
CHANNEL_INFO=$(get_adapter_info ${IFACE} | grep " 24[0-9][0-9] MHz \[${CHANNEL_NUM}\]")
else
CHANNEL_INFO=$(get_adapter_info ${IFACE} | grep " \(49[0-9][0-9]\|5[0-9]\{3\}\) MHz \[${CHANNEL_NUM}\]")
fi
CHANNEL_INFO=$(get_adapter_info "${IFACE}" | grep -E " [0-9]+(\.[0-9]+){0,1} MHz \[${CHANNEL_NUM}\]")
[[ -z "${CHANNEL_INFO}" ]] && return 1
[[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 1
[[ "${CHANNEL_INFO}" == *disabled* ]] && return 1
return 0
else
CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM})
CHANNEL_INFO=$(iwlist ${IFACE} channel | grep -E "Channel[[:blank:]]${CHANNEL_NUM}[[:blank:]]?:")
CHANNEL_INFO=$(iwlist "${IFACE}" channel | grep -E "Channel[[:blank:]]${CHANNEL_NUM}[[:blank:]]?:")
[[ -z "${CHANNEL_INFO}" ]] && return 1
return 0
fi
@@ -600,9 +661,6 @@ ieee80211_frequency_to_channel() {
fi
}
is_5ghz_frequency() {
[[ $1 =~ ^(49[0-9]{2})|(5[0-9]{3})$ ]]
}
is_interface_wifi_connected() {
if [[ $USE_IWCONFIG -eq 0 ]]; then
@@ -626,49 +684,61 @@ get_interface_mac() {
cat "/sys/class/net/${1}/address"
}
get_interface_pci_info() { # pci id / model / virtual
show_interface_pci_info() { # pci id / model / virtual
is_interface "$1" || return
local device_path
local pci_id
local pci_full
local bus_id=""
local device_type_and_bus_id="unknown"
local driver=""
local device_fullname=""
device_path="$(readlink -f /sys/class/net/$1)"
if [[ "$device_path" == "/sys/devices/pci"* ]]; then
pci_id="$(echo $device_path | sed 's/\//\n/g' | tail -n 3 |sed -n 1p)"
local pci_path
pci_path=$device_path/../..
if [[ -d "$pci_path/driver" ]] ; then
driver=$(readlink -f "$pci_path/driver" | sed 's/\//\n/g' | tail -n 1)
fi
bus_id="$(echo "$device_path" | sed 's/\//\n/g' | tail -n 3 |sed -n 1p)"
device_type_and_bus_id="PCI: $bus_id"
if which lspci >/dev/null 2>&1 ; then
pci_full="$( lspci -D -nn | grep -E "^$pci_id " )"
echo " PCI: $pci_full"
else
echo " PCI: $pci_id"
device_fullname="$( lspci -D -nn -s "$bus_id" | awk '{$1="" ; print $0}' )"
fi
elif [[ "$device_path" == *"/virtual/"* ]]; then
echo " virtual interface"
fi
# TODO usb
# TODO current driver
}
elif [[ "$device_path" == *"/virtual/"* ]]; then
device_type_and_bus_id="virtual interface"
fi
echo "$device_type_and_bus_id"
[[ -n "$driver" ]] && echo "System-already-loaded driver: $driver"
[[ -n "$device_fullname" ]] && echo "$device_fullname"
echo ""
# TODO usb
}
alloc_new_vface_name() { # only for wifi
local i=0
local v_iface_name=
local v_iface_name="$VIRT_NAME"
if [[ -z $VIRT_NAME ]]; then
while :; do
v_iface_name="x$i${WIFI_IFACE}"
if ! is_interface ${v_iface_name} && [[ ! -f $COMMON_CONFDIR/vfaces/${v_iface_name} ]]; then
mkdir -p $COMMON_CONFDIR/vfaces
touch $COMMON_CONFDIR/vfaces/${v_iface_name}
echo "${v_iface_name}"
return
fi
i=$((i + 1))
is_vface_name_allocated "${v_iface_name}" || break
done
fi
mkdir -p "$COMMON_CONFDIR/vfaces"
touch "$COMMON_CONFDIR/vfaces/${v_iface_name}"
echo "${v_iface_name}"
}
dealloc_vface_name() {
rm -f $COMMON_CONFDIR/vfaces/$1
rm -f "$COMMON_CONFDIR/vfaces/$1"
}
#======
@@ -701,10 +771,10 @@ generate_random_mac() {
r5=$( printf "%02x" $(($RANDOM%256)) )
r6=$( printf "%02x" $(($RANDOM%256)) )
RAND_MAC="$r1:$r2:$r3:$r4:$r5:$r6"
( ! ip link | grep "link" | grep $RAND_MAC > /dev/null 2>&1 ) && \
( ! ip maddress | grep "link" | grep $RAND_MAC > /dev/null 2>&1 ) && \
( ! ip link | grep "link" | grep "$RAND_MAC" > /dev/null 2>&1 ) && \
( ! ip maddress | grep "link" | grep "$RAND_MAC" > /dev/null 2>&1 ) && \
( ! ip neigh | grep "lladdr $RAND_MAC" > /dev/null 2>&1 ) && \
( ! get_all_mac_in_system | grep $RAND_MAC ) && \
( ! get_all_mac_in_system | grep "$RAND_MAC" ) && \
break
done
echo "$RAND_MAC"
@@ -744,7 +814,7 @@ generate_random_lan_ip6_prefix() {
r5=$( printf "%x" $(($RANDOM%240+16)) )
r6=$( printf "%x" $(($RANDOM%240+16)) )
r7=$( printf "%x" $(($RANDOM%240+16)) )
is_ip6_lan_range_available $r1 $r2 $r3 $r4 $r5 $r6 $r7 && break
is_ip6_lan_range_available "$r1" "$r2" "$r3" "$r4" "$r5" "$r6" "$r7" && break
done
echo "fd$r1:$r2$r3:$r4$r5:$r6$r7::"
}
@@ -780,7 +850,7 @@ pid_watchdog() {
if [[ -e "/proc/$PID" ]]; then
ST="$(cat "/proc/$PID/status" | grep "^State:" | awk '{print $2}')"
if [[ "$ST" != 'Z' ]]; then
sleep $SLEEP
sleep "$SLEEP"
continue
fi
fi
@@ -801,35 +871,35 @@ is_nm_running() {
}
nm_knows() {
(nmcli dev show $1 | grep -E "^GENERAL.STATE:" >/dev/null 2>&1 ) && return 0 # nm sees
(nmcli dev show "$1" | grep -E "^GENERAL.STATE:" >/dev/null 2>&1 ) && return 0 # nm sees
return 1 # nm doesn't see this interface
}
nm_get_manage() { # get an interface's managed state
local s
s=$(nmcli dev show $1 | grep -E "^GENERAL.STATE:") || return 2 # no such interface
(echo $s | grep "unmanaged" >/dev/null 2>&1) && return 1 # unmanaged
s=$(nmcli dev show "$1" | grep -E "^GENERAL.STATE:") || return 2 # no such interface
(echo "$s" | grep "unmanaged" >/dev/null 2>&1) && return 1 # unmanaged
return 0 # managed
}
nm_set_unmanaged() {
while ! nm_knows $1 ; do # wait for virtual wifi interface seen by NM
while ! nm_knows "$1" ; do # wait for virtual wifi interface seen by NM
sleep 0.5
done
if nm_get_manage $1 ;then
if nm_get_manage "$1" ;then
echo "Set $1 unmanaged by NetworkManager"
nmcli dev set $1 managed no || die "Failed to set $1 unmanaged by NetworkManager"
nmcli dev set "$1" managed no || die "Failed to set $1 unmanaged by NetworkManager"
NM_UNM_LIST=$1
sleep 1
fi
}
nm_set_managed() {
nmcli dev set $1 managed yes
nmcli dev set "$1" managed yes
NM_UNM_LIST=
}
nm_restore_manage() {
if [[ $NM_UNM_LIST ]]; then
echo "Restore $NM_UNM_LIST managed by NetworkManager"
nm_set_managed $NM_UNM_LIST
nm_set_managed "$NM_UNM_LIST"
sleep 0.5
fi
}
@@ -1021,7 +1091,7 @@ allow_dhcp() {
# TODO: use 'DNAT' instead of '--to-ports' to support other IP
start_redsocks() {
echo
echo "iptables: transparent proxy non-LAN TCP/UDP traffic to port ${TP_PORT}"
echo "iptables: transparent proxy non-LAN TCP and UDP(not tested) traffic to port ${TP_PORT}"
if [[ $NO4 -eq 0 ]]; then
iptb 4 n nat N lrt${$}${SUBNET_IFACE}-TP || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 0.0.0.0/8 -j RETURN || die
@@ -1097,18 +1167,18 @@ set_interface_mac() {
INTERFACE=$1
MAC=$2
ip link set dev ${INTERFACE} address ${MAC}
ip link set dev "${INTERFACE}" address "${MAC}"
}
backup_interface_status() {
# virtual wifi interface will be destroyed, so no need to save status
# backup interface up or down status
(ip link show ${SUBNET_IFACE} |grep -q "state UP") && SUBNET_IFACE_ORIGINAL_UP_STATUS=1
(ip link show "${SUBNET_IFACE}" |grep -q "state UP") && SUBNET_IFACE_ORIGINAL_UP_STATUS=1
# save interface old mac
#if [[ -n "$NEW_MACADDR" ]]; then
OLD_MACADDR=$(get_interface_mac $SUBNET_IFACE)
OLD_MACADDR=$(get_interface_mac "$SUBNET_IFACE")
#echo "Saved ${SUBNET_IFACE} old MAC address ${OLD_MACADDR} into RAM"
#fi
@@ -1125,14 +1195,14 @@ restore_interface_status() {
restore_ipv6_bits
if [[ -n "$OLD_MACADDR" && "$(get_interface_mac $SUBNET_IFACE)" != "$OLD_MACADDR" ]] ; then
if [[ -n "$OLD_MACADDR" && "$(get_interface_mac "$SUBNET_IFACE")" != "$OLD_MACADDR" ]] ; then
echo "Restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR} ..."
set_interface_mac ${SUBNET_IFACE} ${OLD_MACADDR} || echo "Failed restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR}" >&2
set_interface_mac "${SUBNET_IFACE}" "${OLD_MACADDR}" || echo "Failed restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR}" >&2
fi
nm_restore_manage
[[ $SUBNET_IFACE_ORIGINAL_UP_STATUS -eq 1 ]] && ip link set up dev ${SUBNET_IFACE} && echo "Restore ${SUBNET_IFACE} to link up"
[[ $SUBNET_IFACE_ORIGINAL_UP_STATUS -eq 1 ]] && ip link set up dev "${SUBNET_IFACE}" && echo "Restore ${SUBNET_IFACE} to link up"
}
#---------------------------------------
@@ -1143,11 +1213,11 @@ kill_processes() { # for this instance
# even if the $CONFDIR is empty, the for loop will assign
# a value in $x. so we need to check if the value is a file
if [[ -f $x ]] && sleep 0.3 && [[ -f $x ]]; then
pid=$(cat $x)
pn=$( ps -p $pid -o comm= )
pid=$(cat "$x")
pn=$( ps -p "$pid" -o comm= )
#echo "Killing $pid $pn ... "
pkill -P $pid
kill $pid 2>/dev/null && ( echo "Killed $(basename $x) $pid $pn" && rm $x ) || echo "Failed to kill $(basename $x) $pid $pn, it may have exited"
pkill -P "$pid"
kill "$pid" 2>/dev/null && ( echo "Killed $(basename "$x") $pid $pn" && rm "$x" ) || echo "Failed to kill $(basename "$x") $pid $pn, it may have exited"
fi
done
}
@@ -1155,15 +1225,15 @@ kill_processes() { # for this instance
_cleanup() {
local x
ip addr flush ${SUBNET_IFACE}
ip addr flush "${SUBNET_IFACE}"
rm -rf $CONFDIR
rm -rf "$CONFDIR"
ip link set down dev ${SUBNET_IFACE}
ip link set down dev "${SUBNET_IFACE}"
if [[ $VWIFI_IFACE ]]; then # the subnet interface (virtual wifi interface) will be removed
iw dev ${VWIFI_IFACE} del
dealloc_vface_name $VWIFI_IFACE
iw dev "${VWIFI_IFACE}" del
dealloc_vface_name "$VWIFI_IFACE"
fi
restore_interface_status
@@ -1172,12 +1242,12 @@ _cleanup() {
echo "Exiting: This is the only running instance"
# kill common processes
for x in $COMMON_CONFDIR/*.pid; do
[[ -f $x ]] && kill -9 $(cat $x) && rm $x
[[ -f $x ]] && kill -9 $(cat "$x") && rm "$x"
done
rm -d $COMMON_CONFDIR/vfaces
rm -d $COMMON_CONFDIR
rm -d $TMPDIR
rm -d "$COMMON_CONFDIR/vfaces"
rm -d "$COMMON_CONFDIR"
rm -d "$TMPDIR"
else
echo "Exiting: This is NOT the only running instance"
fi
@@ -1207,7 +1277,7 @@ cleanup() {
#kill -9 -$pgid
}
# NOTE function die() is designed not to be used before init_trap() executed
# NOTE function die() is designed NOT to be used before init_trap() executed
die() { # SIGUSR2
echo "Error occured"
[[ -n "$1" ]] && echo -e "\nERROR: $1\n" >&2
@@ -1259,7 +1329,7 @@ list_running() {
IFACE=${IFACE%%.*}
subn_iface=$(cat $x/subn_iface)
if [[ $IFACE == $subn_iface ]]; then
if [[ "$IFACE" == "$subn_iface" ]]; then
echo $(cat $x/pid) $IFACE
else
echo $(cat $x/pid) $IFACE '('$(cat $x/subn_iface)')'
@@ -1296,7 +1366,7 @@ print_clients_from_leases() { # MAC|IP|HOST|lease
FILEC="$(cat "$LEASE_FILE" | grep -v -E "^duid\b" | sed -r '/^\s*$/d' )"
# TODO: duid is somewhat related to ipv6. I don't know about it. Not sure excluding it miss some info or not
echo "$FILEC" | while read line
echo "$FILEC" | while read -r line
do
#echo aa$line
LEASEstamp="$(echo "$line" | awk '{print $1}')"
@@ -1317,20 +1387,20 @@ print_interface_neighbors_via_iproute() { # MAC|IP|_|STATUS
local line
ip n | grep -E "\bdev $IFACE\b" | sed 's/ /|/g' | while read line
ip n | grep -E "\bdev $IFACE\b" | sed 's/ /|/g' | while read -r line
do
local MAC IP STATUS
IP="$(echo $line | awk -F'|' '{print $1}')"
IP="$(echo "$line" | awk -F'|' '{print $1}')"
if [[ "$(echo $line | awk -F'|' '{print $4}')" == "lladdr" ]]; then # has mac
if [[ "$(echo "$line" | awk -F'|' '{print $4}')" == "lladdr" ]]; then # has mac
# if has mac, $4="lladdr" and $5=macaddress and $6+=status
MAC="$(echo $line | awk -F'|' '{print $5}')"
STATUS="$(echo $line | awk -F'|' '$1="";$2="";$3="";$4="";$5="";{print}' | awk '{$1=$1;print}'| sed 's/ /,/g')"
MAC="$(echo "$line" | awk -F'|' '{print $5}')"
STATUS="$(echo "$line" | awk -F'|' '$1="";$2="";$3="";$4="";$5="";{print}' | awk '{$1=$1;print}'| sed 's/ /,/g')"
else # no mac
# if no mac, $4="" and $5+=status
MAC="?"
STATUS="$(echo $line | awk -F'|' '$1="";$2="";$3="";$4="";{print}' | awk '{$1=$1;print}' | sed 's/ /,/g')"
STATUS="$(echo "$line" | awk -F'|' '$1="";$2="";$3="";$4="";{print}' | awk '{$1=$1;print}' | sed 's/ /,/g')"
fi
if [[ -n "$IP" && ( "$MAC" != "?" || "$STATUS" != "FAILED" ) ]]; then
echo "$MAC|$IP|?|$STATUS"
@@ -1340,10 +1410,10 @@ print_interface_neighbors_via_iproute() { # MAC|IP|_|STATUS
print_interface_neighbors_via_iw() { # MAC|_|_|signal
local IFACE=$1
local MAC SIGNAL
iw dev $IFACE station dump | awk '($1 ~ /Station$/) {print $2}' | while read MAC
iw dev "$IFACE" station dump | awk '($1 ~ /Station$/) {print $2}' | while read -r MAC
do
if [[ -n "$MAC" ]]; then
SIGNAL="$(iw dev $IFACE station get $MAC | grep "signal:" | awk '{print $2}')"
SIGNAL="$(iw dev "$IFACE" station get "$MAC" | grep "signal:" | awk '{print $2}')"
echo "${MAC}|?|?|${SIGNAL}_dBm"
fi
done
@@ -1364,7 +1434,7 @@ list_clients() { # passive mode. (use 'arp-scan' or 'netdiscover' if want active
fi
else # non-number given
IFACE="$1"
if ( ! is_interface $IFACE ) ; then
if ( ! is_interface "$IFACE" ) ; then
echo "'$IFACE' is not an interface or PID" >&2
exit 1
fi
@@ -1376,18 +1446,18 @@ list_clients() { # passive mode. (use 'arp-scan' or 'netdiscover' if want active
echo "Tip: '$IFACE' is not an interface hosted by $PROGNAME" >&2
fi
fi
output="$(echo "$output" ; print_interface_neighbors_via_iw $IFACE) "
output="$(echo "$output" ; print_interface_neighbors_via_iproute $IFACE)"
output="$(echo "$output" ; print_interface_neighbors_via_iw "$IFACE") "
output="$(echo "$output" ; print_interface_neighbors_via_iproute "$IFACE")"
output="$(echo "$output" | sort -k 1 -k 2 -t '|' | uniq | sed -r '/^\s*$/d')"
echo "$IFACE ($(get_interface_mac $IFACE)) neighbors:"
echo "$IFACE ($(get_interface_mac "$IFACE")) neighbors:"
local fmt="%-19s%-41s%-20s%s" # string length: MAC 17, ipv4 15, ipv6 39, hostname ?
printf "$fmt\n" "MAC" "IP" "HOSTNAME" "INFO"
local line
echo "$output"| while read line
echo "$output"| while read -r line
do
if [[ -n "$line" ]]; then
echo "$line" | awk -F'|' "{printf \"$fmt\n\",\$1,\$2,\$3,\$4}"
@@ -1419,14 +1489,14 @@ send_stop() {
local x
# send stop signal to specific pid
if is_running_pid $1; then
kill -USR1 $1
if is_running_pid "$1"; then
kill -USR1 "$1"
return
fi
# send stop signal to specific interface
for x in $(list_running | grep -E " \(?${1}( |\)?\$)" | cut -f1 -d' '); do
kill -USR1 $x
kill -USR1 "$x"
done
}
@@ -1489,13 +1559,13 @@ daemonizing_check(){
#============================
check_wifi_settings() {
if ! ( which iw > /dev/null 2>&1 && iw dev $WIFI_IFACE info > /dev/null 2>&1 ); then
echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ..." >&2
if ! ( which iw > /dev/null 2>&1 && iw dev "$WIFI_IFACE" info > /dev/null 2>&1 ); then
echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ... (Did you spell the interface name right?)" >&2
USE_IWCONFIG=1
fi
if [[ $USE_IWCONFIG -eq 1 ]]; then
if ! (which iwconfig > /dev/null 2>&1 && iwconfig $WIFI_IFACE > /dev/null 2>&1); then
if ! (which iwconfig > /dev/null 2>&1 && iwconfig "$WIFI_IFACE" > /dev/null 2>&1); then
echo "ERROR: Can't use 'iwconfig' to operate interfce '$WIFI_IFACE'" >&2
exit 1
fi
@@ -1506,26 +1576,18 @@ check_wifi_settings() {
exit 1
fi
if [[ $CHANNEL == default ]]; then
if [[ $FREQ_BAND == 2.4 ]]; then
CHANNEL=1
else
CHANNEL=36
fi
fi
if [[ $FREQ_BAND != 5 && $CHANNEL -gt 14 ]]; then
echo "Channel number is greater than 14, assuming 5GHz frequency band"
FREQ_BAND=5
fi
if ! can_be_ap ${WIFI_IFACE}; then
if ! can_be_ap "${WIFI_IFACE}"; then
echo "ERROR: Your adapter does not support AP (master) mode" >&2
exit 1
fi
if ! can_be_sta_and_ap ${WIFI_IFACE}; then
if is_interface_wifi_connected ${WIFI_IFACE}; then
if ! can_be_sta_and_ap "${WIFI_IFACE}"; then
if is_interface_wifi_connected "${WIFI_IFACE}"; then
echo "ERROR: Your adapter can not be a station (i.e. be connected) and an AP at the same time" >&2
exit 1
elif [[ $NO_VIRT -eq 0 ]]; then
@@ -1536,7 +1598,7 @@ check_wifi_settings() {
HOSTAPD=$(which hostapd)
if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^(8192[cd][ue]|8723a[sue])$ ]]; then
if [[ $(get_adapter_kernel_module "${WIFI_IFACE}") =~ ^(8192[cd][ue]|8723a[sue])$ ]]; then
if ! strings "$HOSTAPD" | grep -m1 rtl871xdrv > /dev/null 2>&1; then
echo "ERROR: You need to patch your hostapd with rtl871xdrv patches." >&2
exit 1
@@ -1563,12 +1625,24 @@ check_wifi_settings() {
exit 1
fi
if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^rtl[0-9].*$ ]]; then
if [[ $(get_adapter_kernel_module "${WIFI_IFACE}") =~ ^rtl[0-9].*$ ]]; then
if [[ $WPA_VERSION == '1' || $WPA_VERSION == '1+2' ]]; then
echo "WARN: Realtek drivers usually have problems with WPA1, WPA2 is recommended" >&2
fi
echo "WARN: If AP doesn't work, read https://github.com/oblique/create_ap/blob/master/howto/realtek.md" >&2
fi
if [[ -z $VIRT_NAME ]]; then
if [[ ${#WIFI_IFACE} -gt 13 ]]; then
echo "WARN: $WIFI_IFACE has ${#WIFI_IFACE} characters which might be too long. If AP doesn't work, see --virt-name and https://github.com/garywill/linux-router/issues/44" >&2
fi
elif [[ ${#VIRT_NAME} -gt 15 ]]; then
echo "WARN: option --virt-name $VIRT_NAME has ${#VIRT_NAME} characters which might be too long, consider making it shorter in case of errors" >&2
fi
if [[ ! -z $VIRT_NAME ]] && is_vface_name_allocated "$VIRT_NAME"; then
echo "WARN: interface $VIRT_NAME aleady exists, this will cause an error"
fi
}
check_if_new_mac_valid() {
@@ -1577,7 +1651,7 @@ check_if_new_mac_valid() {
exit 1
fi
if [[ $(get_all_mac_in_system | grep -c ${NEW_MACADDR}) -ne 0 ]]; then
if [[ $(get_all_mac_in_system | grep -c "${NEW_MACADDR}") -ne 0 ]]; then
echo "WARN: MAC address '${NEW_MACADDR}' already exists" >&2
fi
}
@@ -1615,44 +1689,60 @@ decide_ip_addresses() {
prepare_wifi_interface() {
if [[ $USE_IWCONFIG -eq 0 ]]; then
iw dev ${WIFI_IFACE} set power_save off
iw dev "${WIFI_IFACE}" set power_save off
fi
if [[ $NO_VIRT -eq 0 ]]; then
## Will generate virtual wifi interface
if is_interface_wifi_connected ${WIFI_IFACE}; then
WIFI_IFACE_FREQ=$(iw dev ${WIFI_IFACE} link | grep -i freq | awk '{print $2}')
WIFI_IFACE_CHANNEL=$(ieee80211_frequency_to_channel ${WIFI_IFACE_FREQ})
echo "${WIFI_IFACE} already in channel ${WIFI_IFACE_CHANNEL} (${WIFI_IFACE_FREQ} MHz)"
if is_5ghz_frequency $WIFI_IFACE_FREQ; then
FREQ_BAND=5
else
FREQ_BAND=2.4
fi
if [[ $WIFI_IFACE_CHANNEL -ne $CHANNEL ]]; then
echo "Channel fallback to ${WIFI_IFACE_CHANNEL}"
# TODO move this to check_wifi_settings() ?
if is_interface_wifi_connected "${WIFI_IFACE}"; then
WIFI_IFACE_FREQ=$(iw dev "${WIFI_IFACE}" link | grep -i freq | awk '{print $2}' | sed 's/\.00*$//g') # NOTE we assume integer currently, which can be right, or wrong in the future
WIFI_IFACE_CHANNEL=$(ieee80211_frequency_to_channel "${WIFI_IFACE_FREQ}")
echo "${WIFI_IFACE} already working in channel ${WIFI_IFACE_CHANNEL} (${WIFI_IFACE_FREQ} MHz)"
if [[ $CHANNEL == default ]]; then
echo "Use wifi adapter current channel $WIFI_IFACE_CHANNEL as target channel"
CHANNEL=$WIFI_IFACE_CHANNEL
else
echo
fi
if [[ $WIFI_IFACE_CHANNEL -ne $CHANNEL ]]; then
echo "WARN: Wifi adapter already working in channel ${WIFI_IFACE_CHANNEL}, which is different than target channel $CHANNEL" >&2
fi
fi
echo "Creating a virtual WiFi interface... "
VWIFI_IFACE=$(alloc_new_vface_name)
if iw dev ${WIFI_IFACE} interface add ${VWIFI_IFACE} type __ap; then
if iw dev "${WIFI_IFACE}" interface add "${VWIFI_IFACE}" type __ap; then
# Successfully created virtual wifi interface
# if NM running, it will give the new virtual interface a random MAC. MAC will go back after setting NM unmanaged
sleep 2
echo "${VWIFI_IFACE} created"
else
VWIFI_IFACE=
if [[ ! -z ${VIRT_NAME} ]] && [[ ${#VIRT_NAME} -gt 15 ]]; then
die "Failed creating virtual WiFi interface. This is likely because you have set a long name for your virtual interface using --virt-name, try making it shorter'"
elif [[ -z ${VIRT_NAME} ]] && [[ ${#WIFI_IFACE} -gt 13 ]]; then
die "Failed creating virtual WiFi interface. This is likely because your interface name is too long. Try using '--virt-name <shorter interface name>'"
else
die "Failed creating virtual WiFi interface. Maybe your WiFi adapter does not fully support virtual interfaces. Try again with '--no-virt'"
fi
fi
AP_IFACE=${VWIFI_IFACE}
else # no virtual wifi interface, use wifi device interface itself
AP_IFACE=${WIFI_IFACE}
fi
if [[ $CHANNEL == default ]]; then
echo "Channel not specified, use default"
if [[ $FREQ_BAND == 2.4 ]]; then
CHANNEL=1
else
CHANNEL=36
fi
fi
}
decide_subnet_interface() {
@@ -1669,14 +1759,14 @@ dealwith_mac() {
if [[ -n "$NEW_MACADDR" ]] ; then # user choose to set subnet mac
echo "Setting ${SUBNET_IFACE} new MAC address ${NEW_MACADDR} ..."
set_interface_mac ${SUBNET_IFACE} ${NEW_MACADDR} || die "Failed setting new MAC address"
set_interface_mac "${SUBNET_IFACE}" "${NEW_MACADDR}" || die "Failed setting new MAC address"
elif [[ $VWIFI_IFACE ]]; then # user didn't choose to set mac, but using virtual wifi interface
VMAC=$(get_new_macaddr_according_to_existing ${WIFI_IFACE})
VMAC=$(get_new_macaddr_according_to_existing "${WIFI_IFACE}")
if [[ "$VMAC" ]]; then
echo "Assigning MAC address $VMAC to virtual interface $VWIFI_IFACE according to $WIFI_IFACE ..."
set_interface_mac $VWIFI_IFACE $VMAC
set_interface_mac "$VWIFI_IFACE" "$VMAC"
fi
fi
}
@@ -1714,6 +1804,10 @@ write_hostapd_conf() {
EOF
fi
if [[ $HOTSPOT20 -eq 1 ]]; then
echo "hs20=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ $IEEE80211N -eq 1 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
ieee80211n=1
@@ -1721,14 +1815,40 @@ write_hostapd_conf() {
EOF
fi
if [[ $REQUIREHT -eq 1 ]]; then
echo "require_ht=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ $IEEE80211AC -eq 1 ]]; then
echo "ieee80211ac=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ $REQUIREVHT -eq 1 ]]; then
echo "require_vht=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ -n "$VHT_CAPAB" ]]; then
echo "vht_capab=${VHT_CAPAB}" >> "$CONFDIR/hostapd.conf"
fi
if [[ $VHTCHANNELWIDTH -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
vht_oper_chwidth=${VHTCHANNELWIDTH}
EOF
fi
if [[ $VHTSEG0CHINDEX -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
vht_oper_centr_freq_seg0_idx=${VHTSEG0CHINDEX}
EOF
fi
if [[ $VHTSEG1CHINDEX -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
vht_oper_centr_freq_seg1_idx=${VHTSEG1CHINDEX}
EOF
fi
if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]]; then
echo "wmm_enabled=1" >> "$CONFDIR/hostapd.conf"
fi
@@ -1812,7 +1932,7 @@ write_dnsmasq_conf() {
if [[ $DNS ]]; then
DNS_count=$(echo "$DNS" | awk -F, '{print NF}')
for (( i=1;i<=DNS_count;i++ )); do
sep_ip_port "$(echo $DNS | cut -d, -f$i)" DNS_IP DNS_PORT
sep_ip_port "$(echo "$DNS" | cut -d, -f$i)" DNS_IP DNS_PORT
[[ "$DNS_PORT" ]] && DNS_PORT_D="#$DNS_PORT"
echo "server=${DNS_IP}${DNS_PORT_D}" >> "$CONFDIR/dnsmasq.conf"
done
@@ -1822,6 +1942,10 @@ write_dnsmasq_conf() {
no-poll
EOF
fi
if [[ $DNS_NOCACHE -eq 1 ]]; then
echo "cache-size=0" >> "$CONFDIR/dnsmasq.conf"
echo "no-negcache" >> "$CONFDIR/dnsmasq.conf"
fi
if [[ $IPV6 -eq 1 ]];then
cat <<- EOF >> "$CONFDIR/dnsmasq.conf"
listen-address=${GATEWAY6}
@@ -1852,7 +1976,7 @@ run_wifi_ap_processes() {
# start access point
#echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl"
# start hostapd (use stdbuf when available for no delayed output in programs that redirect stdout)
STDBUF_PATH=`which stdbuf`
STDBUF_PATH=$(which stdbuf)
if [ $? -eq 0 ]; then
STDBUF_PATH=$STDBUF_PATH" -oL"
fi
@@ -1872,7 +1996,7 @@ run_wifi_ap_processes() {
# sleep 1
#done
#echo -n "hostapd PID: " ; cat $CONFDIR/hostapd.pid
pid_watchdog $HOSTAPD_PID 10 "hostapd failed" &
pid_watchdog "$HOSTAPD_PID" 10 "hostapd failed. (tip: try '--hostapd-debug' to get some debug info)" &
sleep 3
}
@@ -1899,15 +2023,15 @@ start_dnsmasq() {
DNSMASQ_PID="$(cat "$CONFDIR/dnsmasq.pid" )"
echo "dnsmasq PID: $DNSMASQ_PID"
######(wait $DNSMASQ_PID ; die "dnsmasq failed") & # wait can't deal with non-child
pid_watchdog $DNSMASQ_PID 9 "dnsmasq failed" &
pid_watchdog "$DNSMASQ_PID" 9 "dnsmasq failed" &
sleep 2
}
check_rfkill_unblock_wifi() {
local PHY
if which rfkill > /dev/null 2>&1 ; then
PHY=$(get_interface_phy_device ${SUBNET_IFACE})
[[ -n $PHY ]] && rfkill unblock $(rfkill | grep $PHY | awk '{print $1}') >/dev/null 2>&1
PHY=$(get_interface_phy_device "${SUBNET_IFACE}")
[[ -n $PHY ]] && rfkill unblock $(rfkill | grep "$PHY" | awk '{print $1}') >/dev/null 2>&1
fi
}
@@ -1954,7 +2078,8 @@ echo
echo "PID: $$"
TARGET_IFACE="$(decide_target_interface)" || exit 1 # judge wired (-i CONN_IFACE) or wireless hotspot (--ap $WIFI_IFACE)
echo "Target interface is ${TARGET_IFACE} ($(get_interface_mac $TARGET_IFACE)) $(get_interface_pci_info $TARGET_IFACE)"
echo "Target interface is ${TARGET_IFACE} ($(get_interface_mac "$TARGET_IFACE")) "
show_interface_pci_info "$TARGET_IFACE"
if [[ "$MAC_USE_RANDOM" -eq 1 ]] ; then
NEW_MACADDR="$(generate_random_mac)"
@@ -1990,7 +2115,7 @@ fi
# judge channel availability after changing country code
if [[ $WIFI_IFACE ]] ; then
can_transmit_to_channel ${AP_IFACE} ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz."
can_transmit_to_channel "${AP_IFACE}" ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz."
fi
[[ $WIFI_IFACE ]] && write_hostapd_conf
@@ -1998,8 +2123,8 @@ fi
#===================================================
# set interface unmanaged by networkManager
if [[ $NM_RUNNING -eq 1 ]] && nm_knows $TARGET_IFACE; then # if nm knows target iface, should know subnet iface too. but need to wait until nm finds subnet iface (waiting code is in nm_set_unmanaged()
nm_set_unmanaged ${SUBNET_IFACE} # will write NM_UNM_LIST
if [[ $NM_RUNNING -eq 1 ]] && nm_knows "$TARGET_IFACE"; then # if nm knows target iface, should know subnet iface too. but need to wait until nm finds subnet iface (waiting code is in nm_set_unmanaged()
nm_set_unmanaged "${SUBNET_IFACE}" # will write NM_UNM_LIST
fi
[[ $NO_DNSMASQ -eq 0 ]] && write_dnsmasq_conf
@@ -2007,16 +2132,16 @@ fi
# initialize subnet interface
# take subnet interface down first
ip link set down dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} down"
ip link set down dev "${SUBNET_IFACE}" || die "Failed setting ${SUBNET_IFACE} down"
# flush old IPs of subnet interface
ip addr flush ${SUBNET_IFACE} || die "Failed flush ${SUBNET_IFACE} IP"
ip addr flush "${SUBNET_IFACE}" || die "Failed flush ${SUBNET_IFACE} IP"
dealwith_mac # setting MAC should be after setting NM unmanaged
[[ $WIFI_IFACE ]] && check_rfkill_unblock_wifi
# bring subnet interface up
ip link set up dev ${SUBNET_IFACE} || die "Failed bringing ${SUBNET_IFACE} up"
ip link set up dev "${SUBNET_IFACE}" || die "Failed bringing ${SUBNET_IFACE} up"
# hostapd , haveged
[[ $WIFI_IFACE ]] && run_wifi_ap_processes
@@ -2119,6 +2244,6 @@ show_qr() {
bash -c "while :; do sleep 8000 ; done " &
KEEP_RUNNING_PID=$!
echo "$KEEP_RUNNING_PID" > "$CONFDIR/keep_running.pid"
wait $KEEP_RUNNING_PID
wait "$KEEP_RUNNING_PID"
clean_exit