#!/bin/bash ### BEGIN INIT INFO # Provides: ynh-hotspot # Required-Start: $network $remote_fs $syslog # Required-Stop: $network $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Set prerequisites for wifi hotspot. # Description: Set prerequisites for wifi hotspot. ### END INIT INFO # Functions ## State functions is_ndproxy_set() { proxy=$(ip -6 neighbour show proxy) [ ! -z "${proxy}" ] } is_nat_set() { internet_device=$1 iptables -nvt nat -L POSTROUTING | grep MASQUERADE | grep -q "${internet_device}" } is_ip4nataddr_set() { ip address show dev "${ynh_wifi_device}" 2> /dev/null | grep -q "${ynh_ip4_nat_prefix}.1/24" } is_ip6addr_set() { ip address show dev "${ynh_wifi_device}" 2> /dev/null | grep -q "${ynh_ip6_addr}/64" } is_forwarding_set() { ip6=$(sysctl net.ipv6.conf.all.forwarding | awk '{ print $NF; }') ip4=$(sysctl net.ipv4.conf.all.forwarding | awk '{ print $NF; }') [ "${ip6}" -eq 1 -a "${ip4}" -eq 1 ] } is_hostapd_running() { service hostapd status &> /dev/null } is_radvd_running() { service radvd status &> /dev/null } is_dhcpd_running() { service isc-dhcp-server status &> /dev/null } is_running() { is_ndproxy_set && is_nat_set "${new_internet_device}" && is_ip4nataddr_set\ && is_ip6addr_set && is_forwarding_set && is_hostapd_running\ && is_radvd_running && is_dhcpd_running } ## Setters set_ndproxy() { ip -6 neighbour add proxy "${ynh_ip6_addr}" dev "${ynh_wifi_device}" } set_nat() { internet_device=$1 iptables -t nat -A POSTROUTING -o "${internet_device}" -j MASQUERADE } set_ip4nataddr() { ip address add "${ynh_ip4_nat_prefix}.1/24" dev "${ynh_wifi_device}" } set_ip6addr() { ip address add "${ynh_ip6_addr}/64" dev "${ynh_wifi_device}" } set_forwarding() { sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null sysctl -w net.ipv4.conf.all.forwarding=1 > /dev/null } start_hostapd() { cp /etc/hostapd/hostapd.conf{.tpl,} sed "s||${ynh_wifi_device}|g" -i /etc/hostapd/hostapd.conf sed "s||${ynh_wifi_ssid}|g" -i /etc/hostapd/hostapd.conf sed "s||${ynh_wifi_passphrase}|g" -i /etc/hostapd/hostapd.conf service hostapd start } start_radvd() { cp /etc/radvd.conf{.tpl,} sed "s||${ynh_wifi_device}|g" -i /etc/radvd.conf sed "s||${ynh_ip6_net}|g" -i /etc/radvd.conf sed "s||${ynh_ip6_dns0}|g" -i /etc/radvd.conf sed "s||${ynh_ip6_dns1}|g" -i /etc/radvd.conf service radvd start } start_dhcpd() { cp /etc/dhcp/dhcpd.conf{.tpl,} sed "s||${ynh_ip4_dns0}|g" -i /etc/dhcp/dhcpd.conf sed "s||${ynh_ip4_dns1}|g" -i /etc/dhcp/dhcpd.conf sed "s||${ynh_wifi_device}|g" -i /etc/dhcp/dhcpd.conf sed "s||${ynh_ip4_nat_prefix}|g" -i /etc/dhcp/dhcpd.conf service isc-dhcp-server start } ## Unsetters unset_ndproxy() { ip -6 neighbour delete proxy "${ynh_ip6_addr}" dev "${ynh_wifi_device}" } unset_nat() { internet_device=$1 iptables -t nat -D POSTROUTING -o "${internet_device}" -j MASQUERADE } unset_ip4nataddr() { ip address delete "${ynh_ip4_nat_prefix}.1/24" dev "${ynh_wifi_device}" } unset_ip6addr() { ip address delete "${ynh_ip6_addr}/64" dev "${ynh_wifi_device}" } unset_forwarding() { sysctl -w net.ipv6.conf.all.forwarding=0 > /dev/null sysctl -w net.ipv4.conf.all.forwarding=0 > /dev/null } stop_hostapd() { service hostapd stop } stop_radvd() { service radvd stop } stop_dhcpd() { service isc-dhcp-server stop } ## Tools moulinette_get() { var=$1 value=$(yunohost app setting hotspot "${var}") if [[ "${value}" =~ "An instance is already running" ]]; then echo "${value}" >&2 exit 1 fi echo "${value}" } moulinette_set() { var=$1 value=$2 msg=$(yunohost app setting hotspot "${var}" -v "${value}") if [ ! $? -eq 0 ]; then echo "${msg}" >&2 exit 1 fi } # Variables echo -n "Retrieving Yunohost settings... " ynh_wifi_device=$(moulinette_get wifi_device) ynh_wifi_ssid=$(moulinette_get wifi_ssid) ynh_wifi_passphrase=$(moulinette_get wifi_passphrase) ynh_ip6_addr=$(moulinette_get ip6_addr) ynh_ip6_net=$(moulinette_get ip6_net) ynh_ip6_dns0=$(moulinette_get ip6_dns0) ynh_ip6_dns1=$(moulinette_get ip6_dns1) ynh_ip4_dns0=$(moulinette_get ip4_dns0) ynh_ip4_dns1=$(moulinette_get ip4_dns1) ynh_ip4_nat_prefix=$(moulinette_get ip4_nat_prefix) old_internet_device=$(moulinette_get internet_device) new_internet_device=$(ip route | awk '/default via/ { print $NF; }') # Switch the NAT interface if there is a VPN ip link show dev tun0 &> /dev/null if [ "$?" -eq 0 ]; then new_internet_device=tun0 fi echo "OK" # Script case "$1" in start) if is_running; then echo "Already started" else echo "Starting..." # Set NDP proxy if ! is_ndproxy_set; then echo "Set NDP proxy" set_ndproxy fi # Check old state of the ipv4 NAT settings if [ ! -z "${old_internet_device}" -a "${new_internet_device}" != "${old_internet_device}" ]\ && is_nat_set "${old_internet_device}"; then unset_nat "${old_internet_device}" fi # Set ipv4 NAT if ! is_nat_set "${new_internet_device}"; then echo "Set NAT" set_nat "${new_internet_device}" fi # Set ipv4 NAT address if ! is_ip4nataddr_set; then echo "Set IPv4 NAT address" set_ip4nataddr fi # Set the ipv6 address if ! is_ip6addr_set; then echo "Set IPv6 address" set_ip6addr fi # Set forwarding for ipv6 and ipv4 if ! is_forwarding_set; then echo "Set forwarding" set_forwarding fi # Run hostapd if ! is_hostapd_running; then echo "Run hostapd" start_hostapd sleep 1 fi # Run radvd # must be running after hostapd if ! is_radvd_running; then echo "Run radvd" start_radvd fi # Run dhcpd # "options routers" addr (is_ip6addr_set) must be set before if ! is_dhcpd_running; then echo "Run dhcpd" start_dhcpd fi fi # Update dynamic settings moulinette_set internet_device "${new_internet_device}" ;; stop) echo "Stopping..." if is_ndproxy_set; then echo "Unset NDP proxy" unset_ndproxy fi if is_nat_set "${old_internet_device}"; then echo "Unset NAT" unset_nat "${old_internet_device}" fi if is_ip4nataddr_set; then echo "Unset IPv4 NAT address" unset_ip4nataddr fi if is_ip6addr_set; then echo "Unset IPv6 address" unset_ip6addr fi if is_forwarding_set; then echo "Unset forwarding" unset_forwarding fi if is_hostapd_running; then echo "Stop hostapd" stop_hostapd fi if is_radvd_running; then echo "Stop radvd" stop_radvd fi if is_dhcpd_running; then echo "Stop dhcpd" stop_dhcpd fi ;; restart) $0 stop $0 start ;; status) exitcode=0 if is_ndproxy_set; then echo "NDP proxy is correctly set" else echo "NDP proxy is NOT set" exitcode=1 fi if is_nat_set "${new_internet_device}"; then echo "NAT is correctly set" else echo "NAT is NOT set" exitcode=1 fi if is_ip4nataddr_set; then echo "IPv4 NAT address is correctly set" else echo "IPv4 NAT address is NOT set" exitcode=1 fi if is_ip6addr_set; then echo "IPv6 address is correctly set" else echo "IPv6 address is NOT set" exitcode=1 fi if is_forwarding_set; then echo "Forwarding is correctly set" else echo "Forwarding is NOT set" exitcode=1 fi if is_hostapd_running; then echo "Hostapd is running" else echo "Hostapd is NOT running" exitcode=1 fi if is_radvd_running; then echo "Radvd is running" else echo "Radvd is NOT running" exitcode=1 fi if is_dhcpd_running; then echo "Dhcpd is running" else echo "Dhcpd is NOT running" exitcode=1 fi exit ${exitcode} ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 ;; esac exit 0