The existing interface selection/detection code was incomprehensible at
worst and convoluted at best. The uci config file suggested it
understood an external ipv6 interface but in reality the init script
took no notice. Re-work it so it is at least comprehendible and takes
notice of ipv6 interface details if specified.
Update the hotplug script to use the same interface selection/detection
code as the init script and take note of ipv6 interface selection, only
restarting miniupnpd on interface up events and only if that interface
isn't already known (for that ip class) by miniupnpd.
For me this has solved numerous 'flaky' startup problems, especially
with regard to ipv6.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
(cherry picked from commit 295d77943c
)
204 lines
5.8 KiB
Bash
204 lines
5.8 KiB
Bash
#!/bin/sh /etc/rc.common
|
|
# Copyright (C) 2006-2014 OpenWrt.org
|
|
|
|
START=94
|
|
STOP=15
|
|
USE_PROCD=1
|
|
PROG=/usr/sbin/miniupnpd
|
|
|
|
upnpd_get_port_range() {
|
|
local var="$1"; shift
|
|
local val
|
|
|
|
config_get val "$@"
|
|
|
|
case "$val" in
|
|
[0-9]*[:-][0-9]*)
|
|
export -n -- "${var}_start=${val%%[:-]*}"
|
|
export -n -- "${var}_end=${val##*[:-]}"
|
|
;;
|
|
[0-9]*)
|
|
export -n -- "${var}_start=$val"
|
|
export -n -- "${var}_end="
|
|
;;
|
|
esac
|
|
}
|
|
|
|
conf_rule_add() {
|
|
local cfg="$1"
|
|
local action int_addr
|
|
local ext_start ext_end int_start int_end comment
|
|
|
|
config_get action "$cfg" action "deny" # allow or deny
|
|
upnpd_get_port_range "ext" "$cfg" ext_ports "0-65535" # external ports: x, x-y, x:y
|
|
config_get int_addr "$cfg" int_addr "0.0.0.0/0" # ip or network and subnet mask (internal)
|
|
upnpd_get_port_range "int" "$cfg" int_ports "0-65535" # internal ports: x, x-y, x:y or range
|
|
config_get comment "$cfg" comment "ACL" # comment
|
|
|
|
# Make a single IP IP/32 so that miniupnpd.conf can use it.
|
|
[ "${int_addr%/*}" = "$int_addr" ] && int_addr="$int_addr/32"
|
|
|
|
echo "$action $ext_start${ext_end:+-}$ext_end $int_addr $int_start${int_end:+-}$int_end #$comment"
|
|
}
|
|
|
|
upnpd_write_bool() {
|
|
local opt="$1"
|
|
local def="${2:-0}"
|
|
local alt="${3:-$opt}"
|
|
local val
|
|
|
|
config_get_bool val config "$opt" "$def"
|
|
if [ "$val" -eq 0 ]; then
|
|
echo "$alt=no"
|
|
else
|
|
echo "$alt=yes"
|
|
fi
|
|
}
|
|
|
|
upnpd() {
|
|
config_load "upnpd"
|
|
local external_iface external_iface6 external_zone external_ip internal_iface
|
|
local upload download log_output port config_file serial_number model_number
|
|
local use_stun stun_host stun_port uuid notify_interval presentation_url
|
|
local upnp_lease_file clean_ruleset_threshold clean_ruleset_interval
|
|
|
|
local enabled
|
|
config_get_bool enabled config enabled 1
|
|
[ "$enabled" -eq 0 ] && return 1
|
|
|
|
config_get external_iface config external_iface
|
|
config_get external_iface6 config external_iface6
|
|
config_get external_zone config external_zone
|
|
config_get external_ip config external_ip
|
|
config_get internal_iface config internal_iface
|
|
config_get port config port 5000
|
|
config_get upload config upload
|
|
config_get download config download
|
|
config_get_bool log_output config log_output 0
|
|
config_get config_file config config_file
|
|
config_get serial_number config serial_number
|
|
config_get model_number config model_number
|
|
config_get uuid config uuid
|
|
config_get use_stun config use_stun 0
|
|
config_get stun_host config stun_host
|
|
config_get stun_port config stun_port
|
|
config_get notify_interval config notify_interval
|
|
config_get presentation_url config presentation_url
|
|
config_get upnp_lease_file config upnp_lease_file
|
|
config_get clean_ruleset_threshold config clean_ruleset_threshold
|
|
config_get clean_ruleset_interval config clean_ruleset_interval
|
|
|
|
local conf ifname ifname6
|
|
|
|
. /lib/functions/network.sh
|
|
|
|
if [ -n "$external_iface" ] ; then
|
|
network_get_device ifname "$external_iface"
|
|
else
|
|
if [ -n "$external_zone" ] ; then
|
|
ifname=$(fw3 -q zone "$external_zone" 2>/dev/null | head -1)
|
|
else
|
|
network_find_wan external_iface && \
|
|
network_get_device ifname "$external_iface"
|
|
fi
|
|
fi
|
|
if [ -n "$external_iface6" ] ; then
|
|
network_get_device ifname6 "$external_iface6"
|
|
else
|
|
if [ -n "$external_zone" ] ; then
|
|
ifname6=$(fw3 -q zone "$external_zone" 2>/dev/null | head -1)
|
|
else
|
|
network_find_wan6 external_iface6 && \
|
|
network_get_device ifname6 "$external_iface6"
|
|
fi
|
|
fi
|
|
|
|
if [ -n "$config_file" ]; then
|
|
conf="$config_file"
|
|
else
|
|
local tmpconf="/var/etc/miniupnpd.conf"
|
|
conf="$tmpconf"
|
|
mkdir -p /var/etc
|
|
|
|
{
|
|
echo "ext_ifname=$ifname"
|
|
echo "ext_ifname6=$ifname6"
|
|
[ -n "$external_ip" ] && echo "ext_ip=$external_ip"
|
|
|
|
local iface
|
|
for iface in ${internal_iface:-lan}; do
|
|
local device
|
|
network_get_device device "$iface" && echo "listening_ip=$device"
|
|
network_get_device device "$iface" && echo "ipv6_listening_ip=$device"
|
|
done
|
|
|
|
config_load "upnpd"
|
|
upnpd_write_bool enable_natpmp 1
|
|
upnpd_write_bool enable_upnp 1
|
|
upnpd_write_bool secure_mode 1
|
|
upnpd_write_bool system_uptime 1
|
|
upnpd_write_bool igdv1 0 force_igd_desc_v1
|
|
upnpd_write_bool use_stun 0 ext_perform_stun
|
|
|
|
[ "$use_stun" -eq 0 ] || {
|
|
[ -n "$stun_host" ] && echo "ext_stun_host=$stun_host"
|
|
[ -n "$stun_port" ] && echo "ext_stun_port=$stun_port"
|
|
}
|
|
|
|
[ -n "$upload" ] && [ -n "$download" ] && {
|
|
echo "bitrate_down=$((download * 1024 * 8))"
|
|
echo "bitrate_up=$((upload * 1024 * 8))"
|
|
}
|
|
|
|
[ -n "$upnp_lease_file" ] && touch "$upnp_lease_file" && echo "lease_file=$upnp_lease_file"
|
|
[ -n "$presentation_url" ] && echo "presentation_url=$presentation_url"
|
|
[ -n "$notify_interval" ] && echo "notify_interval=$notify_interval"
|
|
[ -n "$clean_ruleset_threshold" ] && echo "clean_ruleset_threshold=$clean_ruleset_threshold"
|
|
[ -n "$clean_ruleset_interval" ] && echo "clean_ruleset_interval=$clean_ruleset_interval"
|
|
[ -n "$serial_number" ] && echo "serial=$serial_number"
|
|
[ -n "$model_number" ] && echo "model_number=$model_number"
|
|
[ -n "$port" ] && echo "port=$port"
|
|
|
|
[ -z "$uuid" ] && {
|
|
uuid="$(cat /proc/sys/kernel/random/uuid)"
|
|
uci set upnpd.config.uuid="$uuid"
|
|
uci commit upnpd
|
|
}
|
|
|
|
[ "$uuid" = "nocli" ] || echo "uuid=$uuid"
|
|
|
|
config_foreach conf_rule_add perm_rule
|
|
|
|
} > "$tmpconf"
|
|
fi
|
|
|
|
if [ -n "$ifname" ]; then
|
|
# start firewall
|
|
iptables -L MINIUPNPD >/dev/null 2>&1 || fw3 reload
|
|
else
|
|
logger -t "upnp daemon" "external interface not found, not starting"
|
|
fi
|
|
|
|
procd_open_instance
|
|
procd_set_param command "$PROG"
|
|
procd_append_param command -f "$conf"
|
|
[ "$log_output" = "1" ] && procd_append_param command -d
|
|
procd_close_instance
|
|
}
|
|
|
|
stop_service() {
|
|
iptables -t nat -F MINIUPNPD 2>/dev/null
|
|
iptables -t nat -F MINIUPNPD-POSTROUTING 2>/dev/null
|
|
iptables -t filter -F MINIUPNPD 2>/dev/null
|
|
|
|
[ -x /usr/sbin/ip6tables ] && ip6tables -t filter -F MINIUPNPD 2>/dev/null
|
|
}
|
|
|
|
start_service() {
|
|
config_load "upnpd"
|
|
config_foreach upnpd "upnpd"
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger "upnpd"
|
|
}
|