#!/bin/sh -e # shellcheck disable=2034,2091,3010,3037,3060 shell=busybox # Custom UCI defaults script for Linksys MX4200/4300/5300 etc # Create folder "files/etc/uci-defaults/" in build root and copy this script there. # Customize to your needs. # Uncomment the following line to capture all output to a log file # exec > /root/uci-defaults.log 2>&1 # We will also use this MAC to set br-lan, and lan ports 1,2,3. # That is how they are supposed to be but there's an issue on MX4300 # where the MAC is not set correctly for lan 2 and 3 and randomly changes each boot. mac=$(fw_printenv -n ethaddr | tr '[:upper:]' '[:lower:]') # Set to '0' to enable WDS and disable mesh wds_disable=1 bridge_mode=true ap_5g_radio="radio0" ap_2g_radio="radio1" mesh_radio="radio2" wds_radio="${mesh_radio}" # for 80mhz channel 161 will use channels 149-161 (leave as is) mesh_channel=161 # for 80mhz channel 64 will use channels 52-64 (change below for specific devices if needed) ap_5g_channel=64 ap_2g_channel=6 # Unique UCI config names for each section ap_5g_iface="ap_5g" ap_2g_iface="ap_2g" mesh_iface="mesh" wds_iface="wds" # You should start customizing from here # Must be the same SSID for both 2G and 5G for 802.11 k/v/r ap_2g_ssid="OpenWrt" ap_5g_ssid="${ap_2g_ssid}" mesh_id="OpenWrt-Mesh" wds_ssid="OpenWrt-WDS" ap_key="SOME_KEY" mesh_gate_key="SOME_LONG_RANDOM_KEY" wds_key="${mesh_gate_key}" country="US" timezone="EST5EDT,M3.2.0,M11.1.0" zonename="America/New York" router="192.168.1.1" netmask=24 lan_proto="static" prefix="mx4300" # If node is setup to use DHCP and fails to get an IP, # a cable connection can be used to login and manage it. # You'll need to set a static IP on your computer in the same subnet. # (i.e. 10.1.1.2/24) and connect to the fallback management IP. fallback_mgmt_ip="10.1.1.1" # In case you want to reset firmware in future, but want to use different mesh band # use `fw_setenv mesh_band low_5g` to use "radio0" (low 5G band) (36-64) # use `fw_setenv mesh_band high_5g` to use "radio2" (high 5G band) (100-165) # This will then be used to set the channel for the mesh interface. # Default is high_5g (radio2) (channel 161) # NOTE: ON MX4300 ONLY THE 2ND RADIO WORKS WITH MESH. LEAVE THIS UNCHANGED. mesh_band="$(fw_printenv -n mesh_band 2> /dev/null)" mesh_band="${mesh_band:-high_5g}" mesh_rssi_threshold="-65" if [ "$mesh_band" = "low_5g" ]; then mesh_radio="radio0" mesh_channel="64" ap_5g_radio="radio2" ap_5g_channel="100" fi # Setup satellite nodes to simply extend wifi coverage from the main router. # This avoids "daisy chaining" traffic through multiple nodes. # This usecase covers 99% of typical home setups. mesh_gate_announcements="0" mesh_hwmp_rootmode="0" mesh_fwding="0" stp_priority=8192 # Only version version 11.4.0.5 has mesh offload support, so disable and use WDS instead if ! grep -q NSS.HK.11.4.0.5 /lib/firmware/qca-nss0-retail.bin 2> /dev/null; then wds_disable=0 fi # For Linksys MX4200/4300/5300 etc, only need to match the first 5 bytes # of the MAC address to determine it's the same device. # Replace 'xx:xx' with the one found on the bottom of your device. # NOTE: '80:69:1a' is just one of the OUI for Linksys. Yours may be different. # i.e. 'D8:EC:5E:xx:xx', or others. We just need the first 10 characters. # Add a new `elif` block for each device if needed. if [[ "${mac}" =~ "80:69:1a:xx:xx" ]]; then suffix=2 # If the node is in bridge mode and connected to a router via ethernet, or itself is a router. # set the following for gate announcements, rootmode and forwarding. mesh_gate_announcements=1 mesh_hwmp_rootmode=2 mesh_fwding=1 # Only ONE of the nodes should be in ap mode if setting up WDS. wds_mode=ap elif [[ "${mac}" =~ "80:69:1a:xx:xx" ]]; then suffix=3 wds_mode=sta # it's a good idea to spread out the channels on the AP # to ensure they don't interfere with each other. # This is especially important if you have multiple APs in close proximity. # For 80mhz channel 48 will use channels 36-48 ap_5g_channel=48 ap_2g_channel=1 else lan_proto="dhcp" fi if { [ "$lan_proto" = "dhcp" ] && [ -z "$suffix" ]; } || [ -z "$suffix" ] ; then # get last 2 octets of the MAC address # The final hostname will be "${prefix}-${suffix}", e.g. "mx4300-9efc" # otherwise, the suffix will be you specified above. suffix="${mac#*:*:*:*:}" suffix="${suffix/:/}" else # If bridge mode : true # and router IP is : 192.168.1.1 # and suffix is : 2 # then the IP will be : 192.168.1.2 if $bridge_mode; then ipaddr="${router%.*}.${suffix}" else # otherwise assume the node is a router and set the IP to the router IP specified above. # If you DO disable bridge mode for a device, make sure you ONLY do it for ONE device. ipaddr="${router}" stp_priority=0 fi fi hostname="${prefix}-${suffix}" uci import <<- EOF package system config system option hostname '${hostname}' option timezone '${timezone}' option ttylogin '0' option log_size '128' option urandom_seed '1' option zonename '${zonename}' option cronloglevel '9' config timeserver 'ntp' option enable_server '1' option interface 'lan' $(${bridge_mode} && echo list server ''${router}'') # The following NTP servers are NIST Internet Time Servers. # Change them to suit your needs/regional location. list server '129.6.15.28' list server '129.6.15.29' list server '129.6.15.30' list server '2610:20:6f15:15::27' list server '2610:20:6f15:15::28' list server '129.6.15.27' list server '129.6.15.26' config led option name 'Blue Off' option sysfs 'blue:status' option trigger 'none' option default '0' config led option name 'Red Off' option sysfs 'red:status' option trigger 'none' option default '0' EOF # satellite nodes should not have any DHCP/DNS services running. # Nor should they have any firewall/dnsmasq rules. ${bridge_mode} && { # Disable services services in case we are running as dumb ap for prog in firewall sqm unbound adblock-fast banip; do CMD=/etc/init.d/${prog} if [ -r ${CMD} ]; then ${CMD} disable fi done [ -r /etc/hotplug.d/ntp/25-unbound ] && rm /etc/hotplug.d/ntp/25-unbound uci import <<- EOF > /dev/null package dhcp config dnsmasq option boguspriv '0' option rebind_protection '0' option domain 'lan' option expandhosts '1' option readethers '1' option leasefile '/tmp/dhcp.leases' option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto' option localservice '0' option ednspacket_max '1232' config dhcp 'lan' option interface 'lan' option dhcpv4 'disabled' option dhcpv6 'disabled' option ignore '1' option dynamicdhcp '0' config odhcpd 'odhcpd' option maindhcp '0' option leasefile '/tmp/hosts/odhcpd' option leasetrigger '/usr/sbin/odhcpd-update' option loglevel '4' EOF uci import <<- EOF > /dev/null package network config globals 'globals' config interface 'loopback' option device 'lo' option proto 'static' option ipaddr '127.0.0.1' option netmask '255.0.0.0' config device option name 'br-lan' option type 'bridge' list ports 'lan1' list ports 'lan2' list ports 'lan3' option macaddr '${mac}' option stp '1' option igmp_snooping '1' option arp_accept '1' option priority '${stp_priority}' config interface 'lan' option device 'br-lan' $( if [ "$lan_proto" = "static" ]; then cat <<- EOD option proto 'static' list ipaddr '${ipaddr}/${netmask:-24}' list dns '${router}' option gateway '${router}' option delegate '0' EOD else cat <<- EOD option proto 'dhcp' option delegate '0' config interface 'mgmt' option device '@lan' option proto 'static' option ipaddr '${fallback_mgmt_ip}' option netmask '255.255.255.0' option delegate '0' EOD fi ) config interface 'lan6' option device '@lan' option proto 'dhcpv6' option reqaddress 'try' option reqprefix 'no' option delegate '0' config device option name 'lan1' option macaddr '${mac}' config device option name 'lan2' option macaddr '${mac}' config device option name 'lan3' option macaddr '${mac}' EOF # Sometimes nodes may not be able to reach the gateway for whatever reason # Since they will be connected via wifi it's cumbersome having to hardwire just to troubleshoot # Install the `watchcat` package to automatically reboot the node if it can't reach the gateway uci import <<- EOF > /dev/null package watchcat config watchcat option period '5m' option mode 'ping_reboot' option pinghosts '${router}' option addressfamily 'any' option pingperiod '10s' option pingsize 'standard' option forcedelay '1m' EOF } # If not in bridge mode, then assume setting up as a router ${bridge_mode} || { uci batch <<- EOF > /dev/null set network.lan.proto='static' del_list network.lan.ipaddr set network.lan.ipaddr='${router}/${netmask:-24}' EOF } uci import <<- EOF package wireless config wifi-device 'radio0' option type 'mac80211' option path 'platform/soc@0/c000000.wifi' option band '5g' option txpower '21' option country '${country:-US}' option htmode 'HE80' option channel '${ap_5g_channel:-64}' option cell_density '0' option noscan '1' config wifi-device 'radio1' option type 'mac80211' option path 'platform/soc@0/c000000.wifi+1' option band '2g' option txpower '24' option country '${country:-US}' option htmode 'HE20' option channel '${ap_2g_channel:-6}' option cell_density '0' option noscan '1' config wifi-device 'radio2' option type 'mac80211' option path 'platform/soc@0/c000000.wifi+2' option band '5g' option txpower '30' option country '${country:-US}' option htmode 'HE80' option channel '${mesh_channel:-161}' option cell_density '3' option noscan '1' config wifi-iface '${ap_5g_iface}' option device '${ap_5g_radio}' option mode 'ap' option network 'lan' option ssid '${ap_5g_ssid}' option encryption 'psk2+ccmp' option key '${ap_key}' option beacon_int '97' option bss_transition '1' option disassoc_low_ack '0' option dtim_period '3' option ft_over_ds '0' option ft_psk_generate_local '1' option ieee80211r '1' option ieee80211k '1' option proxy_arp '1' option reassociation_deadline '20000' option time_advertisement '2' option time_zone 'GMT0' option wnm_sleep_mode '1' option wpa_group_rekey '86400' option pmk_r1_push '1' config wifi-iface '${ap_2g_iface}' option device '${ap_2g_radio}' option mode 'ap' option network 'lan' option ssid '${ap_2g_ssid}' option encryption 'psk2+ccmp' option key '${ap_key}' option bss_transition '1' option beacon_int '100' option disassoc_low_ack '0' option dtim_period '3' option ft_over_ds '0' option ft_psk_generate_local '1' option ieee80211r '1' option ieee80211k '1' option proxy_arp '1' option reassociation_deadline '20000' option time_advertisement '2' option time_zone 'GMT0' option wnm_sleep_mode '1' option wpa_group_rekey '86400' option max_inactivity '4260' option pmk_r1_push '1' config wifi-iface '${mesh_iface}' option device '${mesh_radio}' option encryption 'sae' option key '${mesh_gate_key}' option mesh_id '${mesh_id}' option mode 'mesh' option network 'lan' option mesh_fwding '${mesh_fwding:-0}' option mesh_gate_announcements '${mesh_gate_announcements:-0}' option mesh_hwmp_rootmode '${mesh_hwmp_rootmode:-0}' option mesh_max_peer_links '16' option mesh_rssi_threshold '${mesh_rssi_threshold}' option disabled $([ ${wds_disable:-1} -eq 1 ] && echo '0' || echo '1') config wifi-iface '${wds_iface}' option device '${wds_radio}' option mode '${wds_mode:-ap}' option network 'lan' option ssid '${wds_ssid}' option encryption 'psk2+ccmp' option key '${wds_key}' option wds '1' option disabled '${wds_disable:-1}' $([ "${wds_mode:-ap}" = "ap" ] && echo "option hidden '1'") EOF uci batch <<- EOF set wireless.${mesh_radio}.channel='${mesh_channel}' set wireless.${ap_5g_radio}.channel='${ap_5g_channel}' set wireless.${mesh_radio}.cell_density='3' set wireless.${ap_5g_radio}.cell_density='0' set wireless.${mesh_iface}.device='${mesh_radio}' set wireless.${wds_iface}.device='${mesh_radio}' set wireless.${ap_5g_iface}.device='${ap_5g_radio}' EOF uci changes uci commit system uci commit dhcp uci commit network uci commit wireless fw_setenv mesh_band "${mesh_band}" exit 0