#!/bin/bash clear_old_networks() { # Get the mesh name from UCI config MESH_NAME=$(uci -q get easymesh.config.mesh_id) # Get all the radios and go through them one by one to remove old networks and interfaces with the same mesh name for CURRENT_RADIO in $(uci -X show wireless | grep wifi-device | awk -F'[.=]' '{print $2}'); do echo "Clearing old networks for radio: $CURRENT_RADIO" # Use awk to parse the 'uci show wireless' output and find the matching section matched_section=$(uci show wireless | awk -F. -v radio="$CURRENT_RADIO" -v ssid="$MESH_NAME" ' $0 ~ /^wireless\.wifinet[0-9]+\.device=/ && $3 ~ radio { device_section=$2 } $0 ~ /^wireless\.wifinet[0-9]+\.ssid=/ && $3 ~ ssid && device_section == $2 { print $2; exit } ') # Check if a matching section was found if [ -n "$matched_section" ]; then echo "The matching wireless interface section is: $matched_section - deleting it" uci delete wireless.$matched_section fi # Find and delete existing mesh network interfaces with the specified MESH_NAME on the current radio EXISTING_MESH=$(uci show wireless | grep -w "mesh_id='$MESH_NAME'" | grep ".$CURRENT_RADIO." | cut -d'.' -f1-2) for section in $EXISTING_MESH; do uci delete $section echo "The matching wireless interface section is: $section - deleting it" done # Commit changes to wireless uci commit done } create_bat0() { # Check if bat0 already exists if uci -q get network.bat0 >/dev/null; then echo "bat0 interface already exists." else uci set network.bat0=interface uci set network.bat0.proto='batadv' uci set network.bat0.routing_algo='BATMAN_IV' uci set network.bat0.aggregated_ogms='1' uci set network.bat0.ap_isolation='0' uci set network.bat0.bonding='1' uci set network.bat0.bridge_loop_avoidance='1' uci set network.bat0.distributed_arp_table='1' uci set network.bat0.fragmentation='1' uci set network.bat0.hop_penalty='30' uci set network.bat0.isolation_mark='0x00000000/0x00000000' uci set network.bat0.log_level='0' uci set network.bat0.multicast_fanout='16' uci set network.bat0.multicast_mode='1' uci set network.bat0.network_coding='0' uci set network.bat0.orig_interval='1000' echo "bat0 interface has been created." # Set the bat0 role BAT_ROLE=$(uci -q get easymesh.config.role) if [ "${BAT_ROLE}" == "server" ]; then uci set network.bat0.gw_mode='server' elif [ "${BAT_ROLE}" == "client" ]; then uci set network.bat0.gw_mode='client' else uci set network.bat0.gw_mode='off' fi # Get the current list of ports for the 'br-lan' interface LAN_PORTS=$(uci -q get network.@device[0].ports) # Check if 'bat0' is already in the list of ports for 'br-lan' if echo "$LAN_PORTS" | grep -q 'bat0'; then uci del_list network.@device[0].ports='bat0' echo "Old bat0 interface deleted from lan network." fi # Add 'bat0' to the list of ports for 'br-lan' uci add_list network.@device[0].ports='bat0' echo "bat0 has been added to the lan network." uci commit network fi } find_radios() { # Get the radio to be used for mesh from the config AP_RADIO=$(uci -q get easymesh.config.apRadio) # Check if AP_RADIO is empty, if so exit if [ -z "$AP_RADIO" ]; then echo "No radio specified in the config, exiting." exit 1 fi # Check to make sure if "all" is passed or a single radio if [ "$AP_RADIO" == "all" ]; then # Get the list of wifi devices WIFI_RADIOS=$(uci -X show wireless | awk -F'[.=]' '/wifi-device/ {print $2}' | tr '\n' ' ') else # Set the radio to the one passed in the config WIFI_RADIOS=$AP_RADIO fi } process_radios() { # Check if WIFI_RADIOS contains more than one radio if [[ $WIFI_RADIOS =~ [[:space:]] ]]; then # Loop through all the radios and set them up for radio in $WIFI_RADIOS; do echo "Multiple Radio Setup, Current Radio: $radio" setup_mesh_radio $radio done else echo "Calling Single Radio Setup: $WIFI_RADIOS" setup_mesh_radio $WIFI_RADIOS fi } # This is called from the process_radios function and is passed the radio to be used for mesh setup_mesh_radio() { CURRENT_RADIO=$1 echo "Setting up radio: $CURRENT_RADIO" # Get the mesh name from UCI config MESH_NAME=$(uci -q get easymesh.config.mesh_id) # Commit changes to wireless uci commit wireless uci set network.nwi_mesh_$CURRENT_RADIO=interface uci set network.nwi_mesh_$CURRENT_RADIO.proto='batadv_hardif' uci set network.nwi_mesh_$CURRENT_RADIO.master='bat0' uci set network.nwi_mesh_$CURRENT_RADIO.device='bat0' uci set network.nwi_mesh_$CURRENT_RADIO.mtu='1536' uci set wireless.mesh_$CURRENT_RADIO=wifi-iface uci set wireless.mesh_$CURRENT_RADIO.device=$CURRENT_RADIO uci set wireless.mesh_$CURRENT_RADIO.ifname=mesh_$CURRENT_RADIO uci set wireless.mesh_$CURRENT_RADIO.network=nwi_mesh_$CURRENT_RADIO uci set wireless.mesh_$CURRENT_RADIO.mode='mesh' uci set wireless.mesh_$CURRENT_RADIO.mesh_id=$MESH_NAME uci set wireless.mesh_$CURRENT_RADIO.mesh_fwding='0' uci set wireless.mesh_$CURRENT_RADIO.mesh_rssi_threshold='0' uci set wireless.mesh_$CURRENT_RADIO.mesh_ttl='1' uci set wireless.mesh_$CURRENT_RADIO.mcast_rate='24000' uci set wireless.mesh_$CURRENT_RADIO.disabled='0' uci commit wireless # Extact the radio number from the radio name RADIO_NUM="${CURRENT_RADIO#radio}" # Get the mobility domain from the config MOBILITY_DOMAIN=$(uci -q get easymesh.config.mobility_domain) # If mobility domain is empty, set it to a random 4 digit hex number, then set it in the config if [ -z "$MOBILITY_DOMAIN" ]; then MOBILITY_DOMAIN=$(hexdump -n 2 -e '2/1 "%02x"' /dev/urandom) uci set easymesh.config.mobility_domain=$MOBILITY_DOMAIN uci commit easymesh fi # Get the encryption enabled from the config ENCRYPTION_ENABLED=$(uci -q get easymesh.config.encryption) # Setup the interface for the mesh network uci set wireless.mesh_$CURRENT_RADIO.disabled='0' uci set wireless.wifinet$RADIO_NUM=wifi-iface uci set wireless.wifinet$RADIO_NUM.device=$CURRENT_RADIO uci set wireless.wifinet$RADIO_NUM.mode='ap' uci set wireless.wifinet$RADIO_NUM.ssid=$MESH_NAME uci set wireless.wifinet$RADIO_NUM.ieee80211r='1' uci set wireless.wifinet$RADIO_NUM.mobility_domain=$MOBILITY_DOMAIN uci set wireless.wifinet$RADIO_NUM.ft_over_ds='0' uci set wireless.wifinet$RADIO_NUM.ft_psk_generate_local='0' uci set wireless.wifinet$RADIO_NUM.network='lan' uci set wireless.wifinet$RADIO_NUM.disabled=0 # Get the encryption key from the config NETWORK_KEY=$(uci -q get easymesh.config.key) # Check if encryption is enabled and if the key is not empty if [ "$ENCRYPTION_ENABLED" = 1 ] && [ ! -z $NETWORK_KEY ]; then uci set wireless.mesh_$CURRENT_RADIO.encryption='sae' uci set wireless.mesh_$CURRENT_RADIO.key=$NETWORK_KEY uci set wireless.wifinet$RADIO_NUM.encryption='sae-mixed' uci set wireless.wifinet$RADIO_NUM.key=$NETWORK_KEY else uci set wireless.mesh_$CURRENT_RADIO.encryption='none' uci set wireless.wifinet$RADIO_NUM.encryption='none' [ -z $NETWORK_KEY ] && echo "Encryption key is empty, so encryption was disabled." fi # Commit our block of changes to wireless uci commit wireless # Check if we need to setup kvr ENABLE_KVR=$(uci -q get easymesh.config.kvr) if [ "$ENABLE_KVR" = 1 ]; then uci set wireless.wifinet$RADIO_NUM.ieee80211k='1' uci set wireless.wifinet$RADIO_NUM.rrm_neighbor_report='1' uci set wireless.wifinet$RADIO_NUM.rrm_beacon_report='1' uci set wireless.wifinet$RADIO_NUM.ieee80211v='1' uci set wireless.wifinet$RADIO_NUM.bss_transition='1' uci set wireless.wifinet$RADIO_NUM.ieee80211r='1' uci set wireless.wifinet$RADIO_NUM.ft_over_ds='1' uci set wireless.wifinet$RADIO_NUM.ft_psk_generate_local='1' uci commit wireless else uci -q delete wireless.wifinet$RADIO_NUM.ieee80211k uci -q delete wireless.wifinet$RADIO_NUM.ieee80211v uci -q delete wireless.wifinet$RADIO_NUM.ieee80211r uci commit wireless fi # Check if we need to setup iapp ENABLE_IAPP=$(uci -q get easymesh.config.iapp) if [ "$ENABLE_IAPP" = 1 ]; then # Get the LAN interface name LAN_NAME=$(uci -q get network.@device[0].name) # If LAN_NAME is not empty, set the iapp interface if [ ! -z "$LAN_NAME" ]; then uci set wireless.wifinet$RADIO_NUM.iapp_interface="$LAN_NAME" uci commit wireless fi else uci -q delete wireless.wifinet$RADIO_NUM.iapp_interface uci commit wireless fi # If KVR is enabled, setup DAWN if [ "$ENABLE_KVR" = 1 ]; then RSSI=$(uci -q get easymesh.config.rssi_val) LOW_RSSI=$(uci -q get easymesh.config.low_rssi_val) uci set dawn.@metric[0].rssi_val=$RSSI uci set dawn.@metric[0].low_rssi_val=$LOW_RSSI uci commit dawn /etc/init.d/dawn enable && /etc/init.d/dawn start else /etc/init.d/dawn stop && /etc/init.d/dawn disable fi # Commit our block of changes to the configs uci commit } restart_and_reload() { # Enable all the radios and commit the changes at once for radio in $(uci -X show wireless | grep wifi-device | awk -F'[.=]' '{print $2}'); do echo "Enabling $radio..." uci set wireless.$radio.disabled=0 done uci commit echo "All radios enabled." # Apply the wireless configuration changes wifi reload echo "Wireless interfaces reloaded." # Apply network configuration changes # Note: Only use reload_config if you have made changes to the network config # and need to apply them. Otherwise, you can skip this step. reload_config echo "Network configuration reloaded." /etc/init.d/network reload /etc/init.d/network restart } disable_easymesh() { # Delete the bat0 interface if [ "$(uci -q get network.bat0)" = "interface" ]; then uci del network.bat0 fi # Get the current list of ports for the 'br-lan' interface LAN_PORTS=$(uci -q get network.@device[0].ports) # Check if 'bat0' is already in the list of ports for 'br-lan' if echo "$LAN_PORTS" | grep -q 'bat0'; then uci del_list network.@device[0].ports='bat0' echo "Old bat0 interface deleted from lan network." fi # Get the list of wifi devices WIFI_RADIOS=$(uci -X show wireless | awk -F'[.=]' '/wifi-device/ {print $2}' | tr '\n' ' ') # Loop through all the radios and delete the network interfaces for CURRENT_RADIO in $WIFI_RADIOS; do echo "Handling removal of mesh networks for: $CURRENT_RADIO" if [ "$(uci -q get network.nwi_mesh_$CURRENT_RADIO)" = "interface" ]; then uci del network.nwi_mesh_$CURRENT_RADIO uci commit network fi done uci commit reload_config echo "Network configuration reloaded." /etc/init.d/network reload /etc/init.d/network restart } set_apmode() { AP_MODE=$(uci -q get easymesh.config.ap_mode) if [ "$AP_MODE" = 1 ]; then # Set a flag to indicate that we are in AP mode # When we go to disable easymesh, we will check this flag and if it was set we restore settings uci set easymesh.config.ap_mode_enabled=1 # Backup our configs rm /etc/config/*.meshbak cp /etc/config/wireless /etc/config/wireless.meshbak cp /etc/config/network /etc/config/network.meshbak cp /etc/config/dhcp /etc/config/dhcp.meshbak # Generate a random IP in the same subnet for fun # ip_base=$(echo "$dns" | cut -d'.' -f1-3) # Get the first three octets of the DNS IP # last_octet=$((RANDOM % 254 + 1)) # Generate a random value for the last octet between 1 and 254 # nodeip="${ip_base}.${last_octet}" # Concatenate the base IP with the new last octet # Disabling and stopping services not needed for service in firewall dnsmasq odhcpd; do if /etc/init.d/$service enabled; then echo "Disabling and stopping $service..." /etc/init.d/$service disable /etc/init.d/$service stop else echo "$service is not enabled, skipping..." fi done # Set LAN interface to DHCP client uci del network.lan.ipaddr uci del network.lan.netmask uci set network.lan.proto='dhcp' uci del network.wan uci del network.wan6 # Fix firewall to be disabled uci del firewall.lan.network uci del firewall.wan.network # Fix dhcp to be disabled uci set dhcp.lan.ignore='1' uci del dhcp.wan # Fix this for proper variable name HOSTNAME=$(uci -q get easymesh.config.gateway) # Set netmask and gateway (assuming $netmask and $dns didn't break more stuff) uci set system.@system[0].hostname=$HOSTNAME # Retrieve the list of ports for network.@device[0] LAN_PORTS=$(uci get network.@device[0].ports) # Check if 'wan' is already in the list of ports if echo "$LAN_PORTS" | grep -q -w 'wan'; then echo "'wan' is already in the list of ports for lan." else echo "'wan' is not in the list. Adding it to lan ports..." uci add_list network.@device[0].ports='wan' fi # Find all radios we are using in our setup find_radios #### COME BACK TO THIS #### # # Check if WIFI_RADIOS contains more than one radio # if [[ $WIFI_RADIOS =~ [[:space:]] ]]; then # # Loop through all the radios add nwimesh to the that network # for cur_radio in $WIFI_RADIOS; do # echo "Multiple Radio Setup, Current Radio: $radio" # # Extact the radio number from the radio name # wifi_num="${cur_radio#radio}" # uci set wireless.wifinet${wifi_num}.network="lan nwi_mesh_${cur_radio}" # done # else # echo "Calling Single Radio Setup: $WIFI_RADIOS" # # Extact the radio number from the radio name # wifi_num="${WIFI_RADIOS#radio}" # uci set wireless.wifinet${wifi_num}.network="lan nwi_mesh_${WIFI_RADIOS}" # fi uci commit # Tell openwrt to reload the configs reload_config else # Set a flag to indicate that we are in AP mode uci set easymesh.config.ap_mode_enabled=0 # Restore our configs [ -f /etc/config/wireless.meshbak ] && { mv /etc/config/wireless /etc/config/wireless.dumbap cp /etc/config/wireless.meshbak /etc/config/wireless } [ -f /etc/config/network.meshbak ] && { mv /etc/config/network /etc/config/network.dumbap cp /etc/config/network.meshbak /etc/config/network } [ -f /etc/config/dhcp.meshbak ] && { mv /etc/config/dhcp /etc/config/dhcp.dumbap cp /etc/config/dhcp.meshbak /etc/config/dhcp } # Enable and start services not needed for service in firewall dnsmasq odhcpd; do if /etc/init.d/$service disabled; then echo "Enabling and starting $service..." /etc/init.d/$service enable /etc/init.d/$service start else echo "$service is not disabled, skipping..." fi done reload_config /etc/init.d/network reload fi } # ENABLED=$(uci -q get easymesh.config.enabled) # if [ "$ENABLED" = 1 ]; then # clear_old_networks # create_bat0 # find_radios # process_radios # restart_and_reload # else # clear_old_networks # disable_easymesh # fi # We accept the parameters: start, stop and apmode # start: Enables easymesh # stop: Disables easymesh # apmode: Sets the device to AP mode if [ "$1" = "start" ]; then clear_old_networks create_bat0 find_radios process_radios restart_and_reload elif [ "$1" = "stop" ]; then clear_old_networks disable_easymesh # elif [ "$1" = "apmode" ]; then # set_apmode else echo "Invalid parameter passed." fi