1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/hotspot_ynh.git synced 2024-09-03 19:25:53 +02:00

Merge pull request #2 from jvaubourg/dev

New version of Hotspot, available only with a version of YunoHost using dnsmasq (not stable for now)
This commit is contained in:
Julien Vaubourg 2015-04-15 18:09:32 +02:00
commit 7cb106adda
26 changed files with 918 additions and 360 deletions

View file

@ -18,7 +18,17 @@ See the <a href="https://raw.githubusercontent.com/jvaubourg/hotspot_ynh/master/
* WPA2 encryption
* 802.11n compliant
* IPv6 compliant (with a delegated prefix)
* Automatic clients configuration (IPv6 and IPv4)
* Announce DNS resolvers (IPv6 and IPv4)
* Announce DNS resolvers (IPv6 with RDNSS/DHCPv6 and IPv4 with DHCPv4)
* Automatic clients configuration (IPv6 with SLAAC/DHCPv6 and IPv4 with DHCPv4)
* Set an IPv6 from your delegated prefix (*prefix::42*) on the server, to use for the AAAA records
* Web interface ([screenshot](https://raw.githubusercontent.com/jvaubourg/hotspot_ynh/master/screenshot.png))
## Prerequisites
This app works with a non-stable version of YunoHost.
Until this version is available (coming soon!) as an official stable release, you need to execute some commands before installing this app:
# service bind9 stop
# update-rc.d bind9 remove
# apt-get install dnsmasq

1
TODO
View file

@ -1,2 +1 @@
* Translate PHP interface in French
* Add license headers

View file

@ -1,15 +0,0 @@
option domain-name-servers <TPL:IP4_DNS0>, <TPL:IP4_DNS1>;
default-lease-time 14440;
ddns-update-style none;
deny bootp;
shared-network <TPL:WIFI_DEVICE> {
subnet <TPL:IP4_NAT_PREFIX>.0
netmask 255.255.255.0 {
option routers <TPL:IP4_NAT_PREFIX>.1;
option subnet-mask 255.255.255.0;
pool {
range <TPL:IP4_NAT_PREFIX>.2 <TPL:IP4_NAT_PREFIX>.254;
}
}
}

View file

@ -0,0 +1,47 @@
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Do DHCP for this subnet.
dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP4_NAT_PREFIX>.2,<TPL:IP4_NAT_PREFIX>.254,4h
# Send DHCPv4 option.
dhcp-option=option:dns-server,<TPL:IP4_DNS0>,<TPL:IP4_DNS1>
# Set the DHCP server to authoritative mode. In this mode it will barge in
# and take over the lease for any client which broadcasts on the network,
# whether it has a record of the lease or not. This avoids long timeouts
# when a machine wakes up on a new network. DO NOT enable this if there's
# the slightest chance that you might end up accidentally configuring a DHCP
# server for your campus/company accidentally. The ISC server uses
# the same option, and this URL provides more information:
# http://www.isc.org/files/auth.html
dhcp-authoritative
# On systems which support it, dnsmasq binds the wildcard address,
# even when it is listening on only some interfaces. It then discards
# requests that it shouldn't reply to. This has the advantage of
# working even when interfaces come and go and change address. If you
# want dnsmasq to really bind only the interfaces it is listening on,
# uncomment this option. About the only time you may need this is when
# running another nameserver on the same machine.
bind-interfaces
# If this line is uncommented, dnsmasq will read /etc/ethers and act
# on the ethernet-address/IP pairs found there just as if they had
# been given as --dhcp-host options. Useful if you keep
# MAC-address/host mappings there for other purposes.
#read-ethers

View file

@ -0,0 +1,23 @@
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA
# so that clients can use SLAAC addresses as well as DHCP ones.
dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP6_NET>,slaac,64,4h
# Send DHCPv6 option. Note [] around IPv6 addresses.
dhcp-option=option6:dns-server,[<TPL:IP6_DNS0>],[<TPL:IP6_DNS1>]

BIN
conf/firmware_htc-7010.fw Normal file

Binary file not shown.

BIN
conf/firmware_htc-9271.fw Normal file

Binary file not shown.

View file

@ -1,14 +1,34 @@
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
interface=<TPL:WIFI_DEVICE>
ssid=<TPL:WIFI_SSID>
hw_mode=g
<TPL:N_COMMENT>ieee80211n=1
<TPL:N_COMMENT>wmm_enabled=1
channel=<TPL:WIFI_CHANNEL>
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=<TPL:WIFI_PASSPHRASE>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
<TPL:SEC_COMMENT>wpa=2
<TPL:SEC_COMMENT>wpa_passphrase=<TPL:WIFI_PASSPHRASE>
<TPL:SEC_COMMENT>wpa_key_mgmt=WPA-PSK
<TPL:SEC_COMMENT>wpa_pairwise=TKIP
<TPL:SEC_COMMENT>rsn_pairwise=CCMP

View file

@ -9,6 +9,23 @@
# Description: Set prerequisites for wifi hotspot.
### END INIT INFO
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Functions
## State functions
@ -20,11 +37,6 @@ has_ip6delegatedprefix() {
[ "${ynh_ip6_net}" != none ]
}
is_ndproxy_set() {
proxy=$(ip -6 neighbour show proxy)
[ ! -z "${proxy}" ]
}
is_nat_set() {
internet_device=${1}
@ -46,30 +58,43 @@ is_forwarding_set() {
[ "${ip6}" -eq 1 -a "${ip4}" -eq 1 ]
}
is_dhcpdv6_set() {
[ -e /etc/dnsmasq.d/dhcpdv6.conf ]
}
is_dhcpdv4_set() {
[ -e /etc/dnsmasq.d/dhcpdv4.conf ]
}
is_hostapd_running() {
service hostapd status &> /dev/null
if [ $? -eq 0 ]; then
# If the wifi antenna was unplugged
if ip link show dev "${ynh_wifi_device}" | grep -q DOWN; then
service hostapd stop &> /dev/null
return 1
fi
return 0
fi
return 1
}
is_radvd_running() {
service radvd status &> /dev/null
}
is_dhcpd_running() {
service isc-dhcp-server status &> /dev/null
is_dnsmasq_running() {
service dnsmasq status &> /dev/null
}
is_running() {
( has_ip6delegatedprefix && is_ip6addr_set && is_radvd_running && is_ndproxy_set || ! has_ip6delegatedprefix )\
( has_ip6delegatedprefix && is_ip6addr_set && is_dhcpdv6_set || ! has_ip6delegatedprefix )\
&& is_nat_set "${new_internet_device}" && is_ip4nataddr_set && is_forwarding_set && is_hostapd_running\
&& is_dhcpd_running
&& is_dhcpdv4_set && is_dnsmasq_running
}
## Setters
set_ndproxy() {
ip -6 neighbour add proxy "${ynh_ip6_addr}" dev "${ynh_wifi_device}"
}
set_nat() {
internet_device=${1}
@ -90,6 +115,24 @@ set_forwarding() {
sysctl -w net.ipv4.conf.all.forwarding=1 > /dev/null
}
set_dhcpd() {
if has_ip6delegatedprefix; then
cp /etc/dnsmasq.d.tpl/dhcpdv6.conf.tpl /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:IP6_NET>|${ynh_ip6_net}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:IP6_DNS0>|${ynh_ip6_dns0}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:IP6_DNS1>|${ynh_ip6_dns1}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
fi
cp /etc/dnsmasq.d.tpl/dhcpdv4.conf.tpl /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:IP4_DNS0>|${ynh_ip4_dns0}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:IP4_DNS1>|${ynh_ip4_dns1}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:IP4_NAT_PREFIX>|${ynh_ip4_nat_prefix}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
}
start_hostapd() {
cp /etc/hostapd/hostapd.conf{.tpl,}
@ -104,37 +147,17 @@ start_hostapd() {
sed "s|<TPL:N_COMMENT>|#|g" -i /etc/hostapd/hostapd.conf
fi
if [ "${ynh_wifi_secure}" -eq 1 ]; then
sed "s|<TPL:SEC_COMMENT>||g" -i /etc/hostapd/hostapd.conf
else
sed "s|<TPL:SEC_COMMENT>|#|g" -i /etc/hostapd/hostapd.conf
fi
service hostapd start
}
start_radvd() {
cp /etc/radvd.conf{.tpl,}
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/radvd.conf
sed "s|<TPL:IP6_NET>|${ynh_ip6_net}|g" -i /etc/radvd.conf
sed "s|<TPL:IP6_DNS0>|${ynh_ip6_dns0}|g" -i /etc/radvd.conf
sed "s|<TPL:IP6_DNS1>|${ynh_ip6_dns1}|g" -i /etc/radvd.conf
service radvd start
}
start_dhcpd() {
cp /etc/dhcp/dhcpd.conf{.tpl,}
sed "s|<TPL:IP4_DNS0>|${ynh_ip4_dns0}|g" -i /etc/dhcp/dhcpd.conf
sed "s|<TPL:IP4_DNS1>|${ynh_ip4_dns1}|g" -i /etc/dhcp/dhcpd.conf
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/dhcp/dhcpd.conf
sed "s|<TPL:IP4_NAT_PREFIX>|${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}
@ -149,6 +172,10 @@ unset_ip6addr() {
ip address delete "${ynh_ip6_addr}/64" dev "${ynh_wifi_device}"
}
unset_dhcpd() {
rm -f /etc/dnsmasq.d/dhcpdv?.conf
}
unset_forwarding() {
sysctl -w net.ipv6.conf.all.forwarding=0 > /dev/null
sysctl -w net.ipv4.conf.all.forwarding=0 > /dev/null
@ -158,14 +185,6 @@ stop_hostapd() {
service hostapd stop
}
stop_radvd() {
service radvd stop
}
stop_dhcpd() {
service isc-dhcp-server stop
}
## Tools
moulinette_get() {
@ -206,55 +225,61 @@ moulinette_set() {
fi
}
# Restart php5-fpm at the first start (it needs to be restarted after the slapd start)
if [ ! -e /tmp/.ynh-hotspot-boot ]; then
touch /tmp/.ynh-hotspot-boot
service php5-fpm restart
fi
if [ "$1" != restart ]; then
# 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_wifi_channel=$(moulinette_get wifi_channel)
ynh_wifi_n=$(moulinette_get wifi_n)
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"
# Check IPv6 delegated prefix from vpnclient
vpnclient_ip6_net=$(moulinette_vpnclient_get ip6_net)
if [ ! -z "${vpnclient_ip6_addr}" ]; then
if [ "${ynh_ip6_net}" == none ]; then
ynh_ip6_net=$vpnclient_ip6_net
ynh_ip6_addr=$(moulinette_vpnclient_get ip6_addr)
# Restart php5-fpm at the first start (it needs to be restarted after the slapd start)
if [ ! -e /tmp/.ynh-hotspot-boot ]; then
touch /tmp/.ynh-hotspot-boot
service php5-fpm restart
fi
moulinette_set ip6_net "${ynh_ip6_net}"
moulinette_set ip6_addr "${ynh_ip6_addr}"
else
if [ "${ynh_ip6_net}" != "${vpnclient_ip6_net}" ]; then
echo "[WARN] The IPv6 delegated prefix is different from the vpnclient one"
# Variables
echo -n "Retrieving Yunohost settings... "
ynh_service_enabled=$(moulinette_get service_enabled)
ynh_wifi_device=$(moulinette_get wifi_device)
ynh_wifi_ssid=$(moulinette_get wifi_ssid)
ynh_wifi_secure=$(moulinette_get wifi_secure)
ynh_wifi_passphrase=$(moulinette_get wifi_passphrase)
ynh_wifi_channel=$(moulinette_get wifi_channel)
ynh_wifi_n=$(moulinette_get wifi_n)
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"
# Check IPv6 delegated prefix from vpnclient
vpnclient_ip6_net=$(moulinette_vpnclient_get ip6_net)
if [ ! -z "${vpnclient_ip6_addr}" ]; then
if [ "${ynh_ip6_net}" == none ]; then
ynh_ip6_net=$vpnclient_ip6_net
ynh_ip6_addr=$(moulinette_vpnclient_get ip6_addr)
moulinette_set ip6_net "${ynh_ip6_net}"
moulinette_set ip6_addr "${ynh_ip6_addr}"
else
if [ "${ynh_ip6_net}" != "${vpnclient_ip6_net}" ]; then
echo "[WARN] The IPv6 delegated prefix is different from the vpnclient one"
fi
fi
fi
fi
# Script
@ -263,6 +288,8 @@ case "$1" in
start)
if is_running; then
echo "Already started"
elif [ "${ynh_service_enabled}" -eq 0 ]; then
echo "Disabled service"
else
echo "[hotspot] Starting..."
touch /tmp/.ynh-hotspot-started
@ -273,12 +300,6 @@ case "$1" in
moulinette_set vpnclient no
fi
# Set NDP proxy
if has_ip6delegatedprefix && ! 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
@ -314,22 +335,17 @@ case "$1" in
if ! is_hostapd_running; then
echo "Run hostapd"
start_hostapd
sleep 1
fi
# Run radvd
# must be running after hostapd
if has_ip6delegatedprefix && ! is_radvd_running; then
echo "Run radvd"
start_radvd
# Run DHCP servers
if ( has_ip6delegatedprefix && ! is_dhcpdv6_set ) || ! is_dhcpdv4_set; then
echo "Set DHCP servers (dnsmasq)"
set_dhcpd
fi
# Run dhcpd
# "options routers" addr (is_ip6addr_set) must be set before
if ! is_dhcpd_running; then
echo "Run dhcpd"
start_dhcpd
fi
# Restart dhcpd
service bind9 stop &> /dev/null
service dnsmasq restart
# Update dynamic settings
moulinette_set internet_device "${new_internet_device}"
@ -337,13 +353,8 @@ case "$1" in
;;
stop)
echo "[hotspot] Stopping..."
rm /tmp/.ynh-hotspot-started
rm -f /tmp/.ynh-hotspot-started
if has_ip6delegatedprefix && 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}"
@ -364,58 +375,64 @@ case "$1" in
unset_forwarding
fi
if is_dhcpdv6_set || is_dhcpdv4_set; then
echo "Stop DHCP servers"
unset_dhcpd
fi
if is_hostapd_running; then
echo "Stop hostapd"
stop_hostapd
fi
if has_ip6delegatedprefix && is_radvd_running; then
echo "Stop radvd"
stop_radvd
fi
if is_dhcpd_running; then
echo "Stop dhcpd"
stop_dhcpd
fi
if has_vpnclient_app; then
service ynh-vpnclient start
fi
service dnsmasq restart
;;
restart)
$0 stop
$0 start
;;
status)
exitcode=0
if [ "${ynh_service_enabled}" -eq 0 ]; then
echo "[ERR] Hotspot Service disabled"
exitcode=1
fi
echo "[INFO] Autodetected internet interface: ${new_internet_device} (last start: ${old_internet_device})"
if has_ip6delegatedprefix; then
echo "[INFO] IPv6 delegated prefix found"
echo "[INFO] IPv6 address computed from the delegated prefix: ${ynh_ip6_addr}"
if is_ndproxy_set; then
echo "[OK] NDP proxy set"
else
echo "[ERR] No NDP proxy set"
exitcode=1
fi
if is_ip6addr_set; then
echo "[OK] IPv6 address set"
else
echo "[ERR] No IPv6 address set"
exitcode=1
fi
if is_radvd_running; then
echo "[OK] Radvd is running"
if is_dhcpdv6_set; then
echo "[OK] SLAAC & DHCPv6 server set"
else
echo "[ERR] Radvd is not running"
echo "[ERR] No SLAAC & DHCPv6 server set"
exitcode=1
fi
else
echo "[INFO] No IPv6 delegated prefix found"
fi
if is_dhcpdv4_set; then
echo "[OK] DHCPv4 server set"
else
echo "[ERR] No DHCPv4 server set"
exitcode=1
fi
if is_nat_set "${new_internet_device}"; then
echo "[OK] IPv4 NAT set"
else
@ -437,6 +454,13 @@ case "$1" in
exitcode=1
fi
if is_dnsmasq_running; then
echo "[OK] Dnsmasq is running"
else
echo "[ERR] Dnsmasq is not running"
exitcode=1
fi
if is_hostapd_running; then
echo "[OK] Hostapd is running"
else
@ -444,17 +468,10 @@ case "$1" in
exitcode=1
fi
if is_dhcpd_running; then
echo "[OK] Dhcpd is running"
else
echo "[ERR] Dhcpd is not running"
exitcode=1
fi
exit ${exitcode}
;;
*)
echo "Usage: $0 {start|stop|status}"
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac

View file

@ -1,3 +1,20 @@
#!/bin/bash
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
sipcalc "${1}" | grep Compressed | awk '{ print $NF; }'

View file

@ -1,3 +1,20 @@
#!/bin/bash
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
sipcalc "${1}" | grep Expanded | awk '{ print $NF; }'

View file

@ -1,19 +1,40 @@
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
location <TPL:NGINX_LOCATION> {
alias <TPL:NGINX_REALPATH>;
if ($scheme = http) {
rewrite ^ https://$server_name$request_uri? permanent;
}
client_max_body_size 10G;
index index.php;
try_files $uri $uri/ index.php;
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass unix:/var/run/php5-fpm-<TPL:PHP_NAME>.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_read_timeout 600;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
include conf.d/yunohost_panel.conf.inc;
alias <TPL:NGINX_REALPATH>;
if ($scheme = http) {
rewrite ^ https://$server_name$request_uri? permanent;
}
client_max_body_size 10G;
index index.php;
try_files $uri $uri/ index.php;
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass unix:/var/run/php5-fpm-<TPL:PHP_NAME>.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_read_timeout 600;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
include conf.d/yunohost_panel.conf.inc;
}

View file

@ -1,21 +1,25 @@
; Start a new pool named 'www'.
; Wifi Hotspot app for YunoHost
; Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
; Contribute at https://github.com/jvaubourg/hotspot_ynh
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU Affero General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU Affero General Public License for more details.
;
; You should have received a copy of the GNU Affero General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
; Start a new pool named '<TPL:PHP_NAME>'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[<TPL:PHP_NAME>]
; Per pool prefix
; It only applies on the following directives:
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
; - 'chdir'
; - 'php_values'
; - 'php_admin_values'
; When not set, the global prefix (or /usr) applies instead.
; Note: This directive can also be relative to the global prefix.
; Default Value: none
;prefix = /path/to/pools/$pool
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on
@ -26,18 +30,6 @@
; Note: This value is mandatory.
listen = /var/run/php5-fpm-<TPL:PHP_NAME>.sock
; Set listen(2) backlog. A value of '-1' means unlimited.
; Default Value: 128 (-1 on FreeBSD and OpenBSD)
;listen.backlog = -1
; List of ipv4 addresses of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
;listen.allowed_clients = 127.0.0.1
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
@ -149,11 +141,6 @@ pm.status_path = /fpm-status
; Default Value: not set
ping.path = /ping
; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong
; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
@ -181,17 +168,6 @@ rlimit_files = 4096
; Default Value: system defined value
rlimit_core = 0
; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
; of its subdirectories. If the pool prefix is not set, the global prefix
; will be used instead.
; Note: chrooting is a great security feature and should be used whenever
; possible. However, all PHP paths will be relative to the chroot
; (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot =
; Chdir to this directory at the start.
; Note: relative path can be used.
; Default Value: current directory or / when chroot
@ -204,15 +180,6 @@ chdir = <TPL:NGINX_REALPATH>
; Default Value: no
catch_workers_output = no
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp
; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
@ -221,22 +188,15 @@ catch_workers_output = no
; php_admin_value/php_admin_flag - these directives won't be overwritten by
; PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
;
; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.
;
; Note: path INI options can be relative and will be expanded with the prefix
; (pool, global or /usr)
; Default Value: nothing is defined by default except the values in php.ini and
; specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
;php_flag[display_errors] = off
;php_admin_value[error_log] = /var/log/fpm-php.www.log
;php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 32M
php_value[max_execution_time] = 600
php_value[upload_max_filesize] = 10G
php_value[post_max_size] = 10G

View file

@ -1,6 +0,0 @@
interface <TPL:WIFI_DEVICE>
{
AdvSendAdvert on;
prefix <TPL:IP6_NET>/64 { };
RDNSS <TPL:IP6_DNS0> <TPL:IP6_DNS1> { };
};

View file

@ -47,6 +47,15 @@
"fr": "Choisissez un mot de passe wifi (au minimum 8 caractères pour le WPA2)"
},
"example": "VhegT8oev0jZI"
},
{
"name": "firmware_nonfree",
"ask": {
"en": "Install non-free firmwares for the wifi dongle (yes/no)",
"fr": "Installer des firmwares non-libres pour la clé USB wifi (yes/no)"
},
"example": "yes",
"default": "yes"
}
]
}

View file

@ -48,6 +48,15 @@
},
"example": "VhegT8oev0jZI"
},
{
"name": "firmware_nonfree",
"ask": {
"en": "Install non-free firmwares for the wifi dongle (yes/no)",
"fr": "Installer des firmwares non-libres pour la clé USB wifi (yes/no)"
},
"example": "yes",
"default": "yes"
},
{
"name": "ip6_net",
"ask": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View file

@ -1,17 +1,35 @@
#!/bin/bash
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Retrieve arguments
domain=${1}
url_path=${2}
wifi_ssid=${3}
wifi_passphrase=${4}
firmware_nonfree=${5}
##
## These arguments are optional but YunoHost is not yet able to handle them with the web installer
## See manifest.json.options
##
#
#ip6_net=${5}
#ip6_net=${6}
# Check arguments
if [ -z "${wifi_ssid}" -o -z "${wifi_passphrase}" ]; then
@ -38,9 +56,17 @@ if [ ! $? -eq 0 ]; then
fi
# Install packages
# TODO: Replace isc-dhcp-server by dnsmasq (currently negotiating with the YunoHost team to
# also replace bind9 by dnsmasq)
packages='php5-fpm sipcalc hostapd radvd isc-dhcp-server iptables wireless-tools wireless-tools'
packages='php5-fpm sipcalc hostapd iptables wireless-tools dnsmasq'
export DEBIAN_FRONTEND=noninteractive
# Packaged USB Wireless Device firmwares
# Based on https://wiki.debian.org/WiFi#USB_Devices
if [ "${firmware_nonfree}" == yes ]; then
packages="$packages firmware-atheros atmel-firmware firmware-linux-free firmware-linux-nonfree firmware-realtek firmware-ralink firmware-libertas zd1211-firmware"
else
packages="$packages firmware-linux-free"
fi
sudo apt-get --assume-yes --force-yes install ${packages}
if [ $? -ne 0 ]; then
@ -52,6 +78,16 @@ fi
if [ -z "${ip6_net}" ]; then
ip6_net=none
ip6_addr=none
if [ -e /tmp/.ynh-vpnclient-started ]; then
vpnclient_ip6_net=$(sudo yunohost app setting vpnclient ip6_net 2>&1)
vpnclient_ip6_addr=$(sudo yunohost app setting vpnclient ip6_addr 2>&1)
if [[ "${vpnclient_ip6_net}" =~ :: && "${vpnclient_ip6_addr}" =~ :: ]]; then
ip6_net=${vpnclient_ip6_net}
ip6_addr=${vpnclient_ip6_addr}
fi
fi
#else
# ip6_net=$(bash ../conf/ipv6_expanded "${ip6_net}")
#
@ -79,7 +115,9 @@ if [ $? -eq 0 ]; then
fi
# Save arguments
sudo yunohost app setting hotspot service_enabled -v 1
sudo yunohost app setting hotspot wifi_ssid -v "${wifi_ssid}"
sudo yunohost app setting hotspot wifi_secure -v 1
sudo yunohost app setting hotspot wifi_passphrase -v "${wifi_passphrase}"
sudo yunohost app setting hotspot wifi_device -v "${wifi_device}"
sudo yunohost app setting hotspot wifi_channel -v 6
@ -98,12 +136,22 @@ sudo install -o root -g root -m 0755 ../conf/ipv6_expanded /usr/local/bin/
sudo install -o root -g root -m 0755 ../conf/ipv6_compressed /usr/local/bin/
# Copy confs
sudo mkdir -pm 0755 /var/log/nginx/
sudo mkdir -pm 0755 /etc/dnsmasq.d.tpl/
sudo chown root: /etc/dnsmasq.d.tpl/
sudo install -b -o root -g root -m 0644 ../conf/hostapd.conf.tpl /etc/hostapd/
sudo install -b -o root -g root -m 0644 ../conf/radvd.conf.tpl /etc/
sudo install -b -o root -g root -m 0644 ../conf/dhcpd.conf.tpl /etc/dhcp/
sudo install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv6.conf.tpl /etc/dnsmasq.d.tpl/dhcpdv6.conf.tpl
sudo install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv4.conf.tpl /etc/dnsmasq.d.tpl/dhcpdv4.conf.tpl
sudo install -b -o root -g root -m 0644 ../conf/nginx_wifiadmin.conf "/etc/nginx/conf.d/${domain}.d/wifiadmin.conf"
sudo install -b -o root -g root -m 0644 ../conf/phpfpm_wifiadmin.conf /etc/php5/fpm/pool.d/wifiadmin.conf
# Copy (free) firmwares
# Extract from http://packages.trisquel.info/toutatis-updates/open-ath9k-htc-firmware
# https://www.fsf.org/news/ryf-certification-thinkpenguin-usb-with-atheros-chip
sudo install -b -o root -g root -m 0644 ../conf/firmware_htc-7010.fw /lib/firmware/htc-7010.fw
sudo install -b -o root -g root -m 0644 ../conf/firmware_htc-9271.fw /lib/firmware/htc-9271.fw
# Copy web sources
sudo mkdir -pm 0755 /var/www/wifiadmin/
sudo cp -a ../sources/* /var/www/wifiadmin/
@ -126,7 +174,6 @@ sudo sed 's|<TPL:PHP_NAME>|wifiadmin|g' -i /etc/php5/fpm/pool.d/wifiadmin.conf
sudo sed 's|<TPL:PHP_USER>|admin|g' -i /etc/php5/fpm/pool.d/wifiadmin.conf
sudo sed 's|<TPL:PHP_GROUP>|admins|g' -i /etc/php5/fpm/pool.d/wifiadmin.conf
sudo sed 's|<TPL:NGINX_REALPATH>|/var/www/wifiadmin/|g' -i /etc/php5/fpm/pool.d/wifiadmin.conf
sudo sed 's|^;\?\s*max_execution_time.\+|max_execution_time = 600|' -i /etc/php5/fpm/php.ini
# Fix sources
sudo sed "s|<TPL:NGINX_LOCATION>|${url_path}|g" -i /var/www/wifiadmin/config.php
@ -134,18 +181,14 @@ sudo sed "s|<TPL:NGINX_LOCATION>|${url_path}|g" -i /var/www/wifiadmin/config.php
# Copy init script
sudo install -o root -g root -m 0755 ../conf/init_ynh-hotspot /etc/init.d/ynh-hotspot
# Update firewall for DHCP
sudo yunohost firewall allow --no-upnp --ipv6 UDP 547
sudo yunohost firewall allow --no-upnp UDP 67
# Set default inits
# The boot order of these services are important, so they are disabled by default
# and the ynh-hotspot service handles them.
# All services are registred by yunohost in order to prevent conflicts after the uninstall.
sudo yunohost service add isc-dhcp-server
sudo yunohost service stop isc-dhcp-server
sudo yunohost service disable isc-dhcp-server
sudo yunohost service add radvd
sudo yunohost service stop radvd
sudo yunohost service disable radvd
sudo yunohost service add hostapd
sudo yunohost service stop hostapd
sudo yunohost service disable hostapd

View file

@ -1,5 +1,22 @@
#!/bin/bash
# Wifi Hotspot app for YunoHost
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/hotspot_ynh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Retrieve arguments
domain=$(sudo yunohost app setting hotspot domain)
@ -9,11 +26,20 @@ sudo yunohost service remove ynh-hotspot
sudo rm -f /etc/init.d/ynh-hotspot
sudo rm -f /tmp/.ynh-hotspot-*
# Update firewall for DHCP
sudo yunohost firewall disallow --ipv6 UDP 547
sudo yunohost firewall disallow UDP 67
# Remove confs
sudo rm -fr /etc/dnsmasq.d.tpl/
sudo rm -f /etc/hostapd/hostapd.conf{.tpl,} /etc/radvd.conf{.tpl,} /etc/dhcp/dhcpd.conf{.tpl,}
sudo rm -f /etc/nginx/conf.d/${domain}.d/wifiadmin.conf
sudo rm -f /etc/php5/fpm/pool.d/wifiadmin.conf
# Remove firmwares
sudo rm -f /lib/firmware/htc-7010.fw
sudo rm -f /lib/firmware/htc-9271.fw
# Restart services
sudo yunohost service stop php5-fpm
sudo yunohost service start php5-fpm
@ -24,6 +50,7 @@ sudo rm -rf /var/www/wifiadmin/
# Remove packets
# The yunohost policy is currently to not uninstall packets (dependency problems)
## sudo apt-get --assume-yes --force-yes remove hostapd radvd isc-dhcp-server iptables sipcalc wireless-tools
## sudo apt-get --assume-yes --force-yes remove hostapd iptables sipcalc wireless-tools
## sudo apt-get --assume-yes --force-yes remove firmware-atheros atmel-firmware firmware-linux-free firmware-linux-nonfree firmware-realtek firmware-ralink firmware-libertas zd1211-firmware
exit 0

View file

@ -1,5 +1,23 @@
<?php
/* Wifi Hotspot app for YunoHost
* Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
* Contribute at https://github.com/jvaubourg/hotspot_ynh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Limonade configuration
function configure() {
option('env', ENV_PRODUCTION);

View file

@ -1,5 +1,23 @@
<?php
/* Wifi Hotspot app for YunoHost
* Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
* Contribute at https://github.com/jvaubourg/hotspot_ynh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
function moulinette_get($var) {
return htmlspecialchars(exec('sudo yunohost app setting hotspot '.escapeshellarg($var)));
}
@ -42,6 +60,14 @@ function ipv6_compressed($ip) {
return $output[0];
}
function is_connected_through_hotspot($ip6_net, $ip4_nat_prefix) {
$ip = $_SERVER['REMOTE_ADDR'];
$ip6_regex = '/^'.preg_quote(preg_replace('/::$/', '', $ip6_net)).':/';
$ip4_regex = '/^'.preg_quote($ip4_nat_prefix).'\./';
return (preg_match($ip6_regex, $ip) || preg_match($ip4_regex, $ip));
}
dispatch('/', function() {
exec('sudo iwconfig', $devs);
$wifi_device = moulinette_get('wifi_device');
@ -59,8 +85,11 @@ dispatch('/', function() {
$ip6_net = moulinette_get('ip6_net');
$ip6_net = ($ip6_net == 'none') ? '' : $ip6_net;
$ip4_nat_prefix = moulinette_get('ip4_nat_prefix');
set('service_enabled', moulinette_get('service_enabled'));
set('wifi_ssid', moulinette_get('wifi_ssid'));
set('wifi_secure', moulinette_get('wifi_secure'));
set('wifi_passphrase', moulinette_get('wifi_passphrase'));
set('wifi_channel', moulinette_get('wifi_channel'));
set('wifi_n', moulinette_get('wifi_n'));
@ -69,10 +98,11 @@ dispatch('/', function() {
set('ip6_net', $ip6_net);
set('ip6_dns0', moulinette_get('ip6_dns0'));
set('ip6_dns1', moulinette_get('ip6_dns1'));
set('ip4_nat_prefix', moulinette_get('ip4_nat_prefix'));
set('ip4_nat_prefix', $ip4_nat_prefix);
set('ip4_dns0', moulinette_get('ip4_dns0'));
set('ip4_dns1', moulinette_get('ip4_dns1'));
set('faststatus', service_faststatus() == 0);
set('is_connected_through_hotspot', is_connected_through_hotspot($ip6_net, $ip4_nat_prefix));
return render('settings.html.php');
});
@ -83,95 +113,118 @@ dispatch_put('/settings', function() {
$ip6_net = empty($_POST['ip6_net']) ? 'none' : $_POST['ip6_net'];
$ip6_addr = 'none';
$ip6_dns0 = $_POST['ip6_dns0'];
$ip6_dns1 = $_POST['ip6_dns1'];
$service_enabled = isset($_POST['service_enabled']) ? 1 : 0;
$wifi_secure = isset($_POST['wifi_secure']) ? 1 : 0;
try {
if(empty($_POST['wifi_ssid']) || empty($_POST['wifi_passphrase']) || empty($_POST['wifi_channel'])) {
throw new Exception(T_('Your Wifi Hotspot needs a name, a password and a channel'));
}
if(strlen($_POST['wifi_passphrase']) < 8 || strlen($_POST['wifi_passphrase']) > 63) {
throw new Exception(T_('Your password must from 8 to 63 characters (WPA2 passphrase)'));
}
if(preg_match('/[^[:print:]]/', $_POST['wifi_passphrase'])) {
throw new Exception(T_('Only printable ASCII characters are permitted in your password'));
}
if(!$wifi_device_exists) {
throw new Exception(T_('The wifi antenna interface seems not exist on the system'));
}
if($ip6_net != 'none') {
$ip6_net = ipv6_expanded($ip6_net);
if(empty($ip6_net)) {
throw new Exception(T_('The IPv6 Delegated Prefix format looks bad'));
if($service_enabled == 1) {
try {
if(empty($_POST['wifi_ssid']) || empty($_POST['wifi_passphrase']) || empty($_POST['wifi_channel'])) {
throw new Exception(T_('Your Wifi Hotspot needs a name, a password and a channel'));
}
$ip6_blocs = explode(':', $ip6_net);
$ip6_addr = "${ip6_blocs[0]}:${ip6_blocs[1]}:${ip6_blocs[2]}:${ip6_blocs[3]}:${ip6_blocs[4]}:${ip6_blocs[5]}:${ip6_blocs[6]}:42";
if(strlen($_POST['wifi_passphrase']) < 8 || strlen($_POST['wifi_passphrase']) > 63) {
throw new Exception(T_('Your password must from 8 to 63 characters (WPA2 passphrase)'));
}
$ip6_net = ipv6_compressed($ip6_net);
$ip6_addr = ipv6_compressed($ip6_addr);
if(preg_match('/[^[:print:]]/', $_POST['wifi_passphrase'])) {
throw new Exception(T_('Only printable ASCII characters are permitted in your password'));
}
if(!$wifi_device_exists) {
throw new Exception(T_('The wifi antenna interface seems not exist on the system'));
}
if($ip6_net != 'none') {
$ip6_net = ipv6_expanded($ip6_net);
if(empty($ip6_net)) {
throw new Exception(T_('The IPv6 Delegated Prefix format looks bad'));
}
$ip6_blocs = explode(':', $ip6_net);
$ip6_addr = "${ip6_blocs[0]}:${ip6_blocs[1]}:${ip6_blocs[2]}:${ip6_blocs[3]}:${ip6_blocs[4]}:${ip6_blocs[5]}:${ip6_blocs[6]}:42";
$ip6_net = ipv6_compressed($ip6_net);
$ip6_addr = ipv6_compressed($ip6_addr);
}
if(!empty($ip6_dns0)) {
$ip6_dns0 = ipv6_expanded($ip6_dns0);
if(empty($ip6_dns0)) {
throw new Exception(T_('The format of the first IPv6 DNS Resolver looks bad'));
}
$ip6_dns0 = ipv6_compressed($ip6_dns0);
if(!empty($ip6_dns1)) {
$ip6_dns1 = ipv6_expanded($ip6_dns1);
if(empty($ip6_dns1)) {
throw new Exception(T_('The format of the second IPv6 DNS Resolver looks bad'));
}
$ip6_dns1 = ipv6_compressed($ip6_dns1);
}
}
if(inet_pton($_POST['ip4_dns0']) === false) {
throw new Exception(T_('The format of the first IPv4 DNS Resolver looks bad'));
}
if(inet_pton($_POST['ip4_dns1']) === false) {
throw new Exception(T_('The format of the second IPv4 DNS Resolver looks bad'));
}
if(inet_pton("${_POST['ip4_nat_prefix']}.0") === false) {
throw new Exception(T_('The format of the IPv4 NAT Prefix (/24) looks bad : x.x.x expected)'));
}
if(filter_var("${_POST['ip4_nat_prefix']}.0", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false) {
throw new Exception(T_('The IPv4 NAT Prefix must be from a private range'));
}
} catch(Exception $e) {
flash('error', $e->getMessage().' ('.T_('configuration not updated').').');
goto redirect;
}
$ip6_dns0 = ipv6_expanded($ip6_dns0);
if(empty($_POST['ip6_dns0'])) {
throw new Exception(T_('The format of the first IPv6 DNS Resolver looks bad'));
}
$ip6_dns0 = ipv6_compressed($ip6_dns0);
$ip6_dns1 = ipv6_expanded($ip6_dns1);
if(empty($_POST['ip6_dns1'])) {
throw new Exception(T_('The format of the second IPv6 DNS Resolver looks bad'));
}
$ip6_dns1 = ipv6_compressed($ip6_dns1);
if(inet_pton($_POST['ip4_dns0']) === false) {
throw new Exception(T_('The format of the first IPv4 DNS Resolver looks bad'));
}
if(inet_pton($_POST['ip4_dns1']) === false) {
throw new Exception(T_('The format of the second IPv4 DNS Resolver looks bad'));
}
if(inet_pton("${_POST['ip4_nat_prefix']}.0") === false) {
throw new Exception(T_('The format of the IPv4 NAT Prefix (/24) looks bad : x.x.x expected)'));
}
if(filter_var("${_POST['ip4_nat_prefix']}.0", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false) {
throw new Exception(T_('The IPv4 NAT Prefix must be from a private range'));
}
} catch(Exception $e) {
flash('error', $e->getMessage().' ('.T_('configuration not updated').').');
goto redirect;
}
stop_service();
moulinette_set('wifi_ssid', $_POST['wifi_ssid']);
moulinette_set('wifi_passphrase', $_POST['wifi_passphrase']);
moulinette_set('wifi_channel', $_POST['wifi_channel']);
moulinette_set('wifi_n', isset($_POST['wifi_n']) ? 1 : 0);
moulinette_set('wifi_device', $_POST['wifi_device']);
moulinette_set('ip6_net', $ip6_net);
moulinette_set('ip6_addr', $ip6_addr);
moulinette_set('ip6_dns0', $_POST['ip6_dns0']);
moulinette_set('ip6_dns1', $_POST['ip6_dns1']);
moulinette_set('ip4_nat_prefix', $_POST['ip4_nat_prefix']);
moulinette_set('ip4_dns0', $_POST['ip4_dns0']);
moulinette_set('ip4_dns1', $_POST['ip4_dns1']);
moulinette_set('service_enabled', $service_enabled);
$retcode = start_service();
if($service_enabled == 1) {
moulinette_set('wifi_ssid', $_POST['wifi_ssid']);
moulinette_set('wifi_secure', $wifi_secure);
if($wifi_secure == 1) {
moulinette_set('wifi_passphrase', $_POST['wifi_passphrase']);
}
moulinette_set('wifi_channel', $_POST['wifi_channel']);
moulinette_set('wifi_n', isset($_POST['wifi_n']) ? 1 : 0);
moulinette_set('wifi_device', $_POST['wifi_device']);
moulinette_set('ip6_net', $ip6_net);
moulinette_set('ip6_addr', $ip6_addr);
moulinette_set('ip6_dns0', $_POST['ip6_dns0']);
moulinette_set('ip6_dns1', $_POST['ip6_dns1']);
moulinette_set('ip4_nat_prefix', $_POST['ip4_nat_prefix']);
moulinette_set('ip4_dns0', $_POST['ip4_dns0']);
moulinette_set('ip4_dns1', $_POST['ip4_dns1']);
$retcode = start_service();
if($retcode == 0) {
flash('success', T_('Configuration updated and service successfully reloaded'));
} else {
flash('error', T_('Configuration updated but service reload failed'));
}
if($retcode == 0) {
flash('success', T_('Configuration updated and service successfully reloaded'));
} else {
flash('error', T_('Configuration updated but service reload failed'));
flash('success', T_('Service successfully disabled'));
}
redirect:

View file

@ -1,11 +1,27 @@
<?php
/* Wifi Hotspot app for YunoHost
* Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
* Contribute at https://github.com/jvaubourg/hotspot_ynh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require dirname(__FILE__).'/lib/limonade.php';
require dirname(__FILE__).'/controller.php';
require dirname(__FILE__).'/lib/unix_func.php';
//require '/usr/share/php/php-gettext/gettext.inc';
require dirname(__FILE__).'/config.php';
run();

View file

@ -1,3 +1,21 @@
/* Wifi Hotspot app for YunoHost
* Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
* Contribute at https://github.com/jvaubourg/hotspot_ynh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
li.status-info {
color: #5BC0DE;
}
@ -43,3 +61,82 @@ div#github {
div#github a {
margin-left: 17px;
}
div#saveconfirmation {
display: none;
padding-right: 15px;
width: 60%;
margin: 0 auto;
}
div#saveconfirmation div#confirm {
background-color: #fff;
padding: 10px;
margin: 15px 0 0 0;
border: 1px solid #F5E79E;
}
div#wifiparty_screen {
top: 0;
left: 0;
display: none;
position: fixed;
height: 100vh;
width: 100vw;
z-index: 998;
background-color: #fff;
text-align: center;
}
div#wifiparty_screen div.btn-group {
display: block;
margin: 5px;
opacity: 0.3;
}
div#wifiparty_screen div.btn-group:hover {
opacity: 0.7;
}
div#wifiparty_ssid_part {
background: #5CB85C;
color: #fff;
}
div#wifiparty_ssid_part div.btn-group {
float: left;
position: fixed;
top: 0;
left: 0;
z-index: 999;
opacity: 0.2;
}
div#wifiparty_ssid_part div.btn-group:hover {
opacity: 0.8;
}
span#wifiparty_ssid {
font-size: 70px;
}
div#wifiparty_passphrase {
clear: both;
font-size: 140px;
font-style: italic;
margin: 50px 20px;
word-wrap: break-word;
line-height: 0.9;
}
div#wifiparty_passphrase span.passdigit {
color: #428BCA;
}
div#wifiparty_passphrase span.passother {
color: #D9534F;
}
div#wifiparty_passphrase span.passspace {
color: #CCC;
}

View file

@ -1,3 +1,21 @@
/* Wifi Hotspot app for YunoHost
* Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
* Contribute at https://github.com/jvaubourg/hotspot_ynh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(document).ready(function() {
$('.btn-group').button();
$('[data-toggle="tooltip"]').tooltip();
@ -36,6 +54,11 @@ $(document).ready(function() {
$('#form').submit();
});
$('#saveconfirm').click(function() {
$(this).hide();
$('#saveconfirmation').show();
});
$('#status .close').click(function() {
$(this).parent().hide();
});
@ -54,4 +77,50 @@ $(document).ready(function() {
});
}
});
$('#wifiparty').click(function() {
$('#wifiparty_screen').show('slow');
});
$('#wifiparty_zoomin_ssid').mousedown(function() {
$('#wifiparty_ssid').css('fontSize', (parseInt($('#wifiparty_ssid').css('fontSize')) + 5) + "px");
});
$('#wifiparty_zoomout_ssid').mousedown(function() {
$('#wifiparty_ssid').css('fontSize', (parseInt($('#wifiparty_ssid').css('fontSize')) - 5) + "px");
});
$('#wifiparty_zoomin_passphrase').mousedown(function() {
$('#wifiparty_passphrase').css('fontSize', (parseInt($('#wifiparty_passphrase').css('fontSize')) + 7) + "px");
});
$('#wifiparty_zoomout_passphrase').mousedown(function() {
$('#wifiparty_passphrase').css('fontSize', (parseInt($('#wifiparty_passphrase').css('fontSize')) - 7) + "px");
});
$('#wifiparty_close').click(function() {
$('#wifiparty_screen').hide();
});
$('#wifi_secure').change(function() {
if($('#wifi_secure').parent().hasClass('off')) {
$('.secure').hide('slow');
} else {
$('.secure').show('slow');
}
});
$('#service_enabled').change(function() {
if($('#service_enabled').parent().hasClass('off')) {
$('.enabled').hide('slow');
} else {
$('.enabled').show('slow');
}
});
});
$(document).keydown(function(e) {
if(e.keyCode == 27) {
$('#wifiparty_close').click();
}
});

View file

@ -1,22 +1,46 @@
<!doctype html>
<!--
Wifi Hotspot app for YunoHost
Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
Contribute at https://github.com/jvaubourg/hotspot_ynh
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="<?= $locale ?>"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Wifi Hotspot <? echo (isset($title)) ? "| ".$title : "" ?></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet">
<link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/css/bootstrap-toggle.min.css" rel="stylesheet">
<link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/css/style.css" rel="stylesheet">
<script src="<?= PUBLIC_DIR ?>/jquery/jquery-2.1.1.min.js"></script>
<script src="<?= PUBLIC_DIR ?>/bootstrap/js/bootstrap.min.js"></script>
<script src="<?= PUBLIC_DIR ?>/js/bootstrap-toggle.min.js"></script>
<script src="<?= PUBLIC_DIR ?>/js/custom.js"></script>
</head>
<body>
<div class="container">
<? if(isset($flash['error'])): ?>
@ -42,4 +66,5 @@
<div id="github"><a href="https://github.com/jvaubourg/hotspot_ynh"><?= T_('Any problem? Contribute!') ?></a> - AGPL 3.0</div>
</div>
</body>
</html>

View file

@ -1,3 +1,47 @@
<!--
Wifi Hotspot app for YunoHost
Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
Contribute at https://github.com/jvaubourg/hotspot_ynh
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<div id="wifiparty_screen">
<div id="wifiparty_ssid_part">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" id="wifiparty_close"><span class="glyphicon glyphicon-eye-close"></span></button>
<button type="button" class="btn btn-default" id="wifiparty_zoomin_ssid"><span class="glyphicon glyphicon-zoom-in"></span></button>
<button type="button" class="btn btn-default" id="wifiparty_zoomout_ssid"><span class="glyphicon glyphicon-zoom-out"></span></button>
</div>
<span id="wifiparty_ssid"><span class="glyphicon glyphicon-signal"></span> <?= $wifi_ssid ?></span>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" id="wifiparty_zoomin_passphrase"><span class="glyphicon glyphicon-zoom-in"></span></button>
<button type="button" class="btn btn-default" id="wifiparty_zoomout_passphrase"><span class="glyphicon glyphicon-zoom-out"></span></button>
</div>
<div id="wifiparty_passphrase"><?php
$pw = preg_replace('/[^0-9a-z ]/i', '<span-class="passother">$0</span>', $wifi_passphrase);
$pw = preg_replace('/\d/', '<span-class="passdigit">$0</span>', $pw);
$pw = preg_replace('/ /', '<span class="passspace">&#x25AE;</span>', $pw);
$pw = preg_replace('/span-class/', 'span class', $pw);
echo $pw;
?></div>
</div>
<h2><?= T_("Wifi Hotspot Configuration") ?></h2>
<?php if($faststatus): ?>
<span class="label label-success" data-toggle="tooltip" data-title="<?= T_('This is a fast status. Click on More details to show the complete status.') ?>"><?= T_('Running') ?></span>
@ -20,6 +64,23 @@
<input type="hidden" name="_method" value="put" />
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?= T_("Service") ?></h3>
</div>
<div style="padding: 14px 14px 0 10px">
<div class="form-group">
<label for="wifi_secure" class="col-sm-3 control-label"><?= T_('Hotspot Enabled') ?></label>
<div class="col-sm-9 input-group-btn">
<div class="input-group">
<input type="checkbox" class="form-control switch" name="service_enabled" id="service_enabled" value="1" <?= $service_enabled == 1 ? 'checked="checked"' : '' ?> />
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default enabled" <?= $service_enabled == 0 ? 'style="display: none"' : '' ?>>
<div class="panel-heading">
<h3 class="panel-title"><?= T_("Wifi") ?></h3>
</div>
@ -31,11 +92,21 @@
<input type="text" class="form-control" name="wifi_ssid" id="wifi_ssid" placeholder="myNeutralNetwork" value="<?= $wifi_ssid ?>" />
</div>
</div>
<div class="form-group">
<label for="wifi_secure" class="col-sm-3 control-label"><?= T_('Secure') ?></label>
<div class="col-sm-9 input-group-btn" data-toggle="tooltip" data-title="<?= T_('Disabling the Secure Wifi allows everyone to join the hotspot and spy the traffic (but it\'s perfect for a PirateBox)') ?>">
<div class="input-group">
<input type="checkbox" class="form-control switch" name="wifi_secure" id="wifi_secure" value="1" <?= $wifi_secure == 1 ? 'checked="checked"' : '' ?> />
</div>
</div>
</div>
<div class="form-group secure" <?= $wifi_secure == 0 ? 'style="display: none"' : '' ?>>
<label for="wifi_passphrase" class="col-sm-3 control-label"><?= T_('Password (WPA2)') ?></label>
<div class="col-sm-9">
<div class="input-group col-sm-9" style="padding: 0 15px">
<input type="text" data-toggle="tooltip" data-title="<?= T_('At least 8 characters') ?>" class="form-control" name="wifi_passphrase" id="wifi_passphrase" placeholder="VhegT8oev0jZI" value="<?= $wifi_passphrase ?>" />
<a class="btn input-group-addon" id="wifiparty" data-toggle="tooltip" data-title="<?= T_('Show to your friends how to access to your hotspot') ?>"><span class="glyphicon glyphicon-fullscreen"></span></a>
</div>
</div>
@ -62,8 +133,8 @@
</div>
</div>
<div class="form-group">
<label for="wifi_passphrase" class="col-sm-3 control-label"><?= T_('Wifi N') ?></label>
<div class="form-group" style="display: none">
<label for="wifi_n" class="col-sm-3 control-label"><?= T_('Wifi N') ?></label>
<div class="col-sm-9 input-group-btn" data-toggle="tooltip" data-title="<?= T_('Only if your antenna is 802.11n compliant') ?>">
<div class="input-group">
<input type="checkbox" class="form-control switch" name="wifi_n" id="wifi_n" value="1" <?= $wifi_n == 1 ? 'checked="checked"' : '' ?> />
@ -86,7 +157,7 @@
</div>
</div>
<div class="panel panel-success">
<div class="panel panel-success enabled" <?= $service_enabled == 0 ? 'style="display: none"' : '' ?>>
<div class="panel-heading">
<h3 class="panel-title" data-toggle="tooltip" data-title="<?= T_('Real Internet') ?>"><?= T_("IPv6") ?></h3>
</div>
@ -123,7 +194,7 @@
</div>
</div>
<div class="panel panel-danger">
<div class="panel panel-danger enabled" <?= $service_enabled == 0 ? 'style="display: none"' : '' ?>>
<div class="panel-heading">
<h3 class="panel-title" data-toggle="tooltip" data-title="<?= T_('Old Internet') ?>"><?= T_("IPv4") ?></h3>
</div>
@ -154,7 +225,18 @@
<div class="form-group">
<div style="text-align: center">
<?php if($is_connected_through_hotspot): ?>
<div class="alert alert-dismissible alert-warning fade in" role="alert" id="saveconfirmation">
<strong><?= T_('Notice') ?>:</strong> <?= T_("You are currently connected through the wifi hotspot. Please, confirm the reloading, wait for the wifi disconnect/reconnect and go back here to check that everything is okay.") ?>
<div id="confirm">
<button type="submit" class="btn btn-default" data-toggle="tooltip" id="save" data-title="<?= T_('Reloading may take a few minutes. Be patient.') ?>"><?= T_('Confirm') ?></button> <img src="public/img/loading.gif" id="save-loading" alt="Loading..." />
</div>
</div>
<button type="button" class="btn btn-default" id="saveconfirm"><?= T_('Save and reload') ?></button>
<?php else: ?>
<button type="submit" class="btn btn-default" data-toggle="tooltip" id="save" data-title="<?= T_('Reloading may take a few minutes. Be patient.') ?>"><?= T_('Save and reload') ?></button> <img src="public/img/loading.gif" id="save-loading" alt="Loading..." />
<?php endif; ?>
</div>
</div>
</form>