net: add new package from 23.05

This commit is contained in:
coolsnowwolf 2024-05-08 02:58:43 +08:00
parent 7ca8ed2415
commit ab94451cbe
76 changed files with 9138 additions and 104 deletions

81
net/adblock-fast/Makefile Normal file
View File

@ -0,0 +1,81 @@
# Copyright 2023-2024 MOSSDeF, Stan Grishin (stangri@melmac.ca).
# TLD optimization written by Dirk Brenken (dev@brenken.org).
# This is free software, licensed under AGPL-3.0-or-later.
include $(TOPDIR)/rules.mk
PKG_NAME:=adblock-fast
PKG_VERSION:=1.1.1
PKG_RELEASE:=11
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_LICENSE:=AGPL-3.0-or-later
include $(INCLUDE_DIR)/package.mk
define Package/adblock-fast
SECTION:=net
CATEGORY:=Network
TITLE:=AdBlock Fast Service
URL:=https://docs.openwrt.melmac.net/adblock-fast/
DEPENDS:=+jshn +curl
DEPENDS+=+!BUSYBOX_DEFAULT_AWK:gawk
DEPENDS+=+!BUSYBOX_DEFAULT_GREP:grep
DEPENDS+=+!BUSYBOX_DEFAULT_SED:sed
DEPENDS+=+!BUSYBOX_DEFAULT_SORT:coreutils-sort
CONFLICTS:=simple-adblock
PROVIDES:=simple-adblock
PKGARCH:=all
endef
define Package/adblock-fast/description
Fast AdBlocking script to block ad or abuse/malware domains with DNSMASQ or Unbound.
Script supports local/remote list of domains and hosts-files for both block-listing and allow-listing.
Please see https://docs.openwrt.melmac.net/adblock-fast/ for more information.
endef
define Package/adblock-fast/conffiles
/etc/config/adblock-fast
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/adblock-fast/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/adblock-fast $(1)/etc/init.d/adblock-fast
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/adblock-fast
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/adblock-fast $(1)/etc/config/adblock-fast
$(INSTALL_DIR) $(1)/tmp
$(INSTALL_DATA) ./files/adblock-fast.config.update $(1)/tmp/adblock-fast.config.update
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/etc/uci-defaults/90-adblock-fast $(1)/etc/uci-defaults/90-adblock-fast
endef
define Package/adblock-fast/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
sed -f /tmp/adblock-fast.config.update -i /etc/config/adblock-fast || true
/etc/init.d/adblock-fast enable
fi
exit 0
endef
define Package/adblock-fast/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo -n "Stopping adblock-fast service... "
{ /etc/init.d/adblock-fast stop && \
/etc/init.d/adblock-fast killcache; } >/dev/null 2>&1 && echo "OK" || echo "FAIL"
echo -n "Removing rc.d symlink for adblock-fast... "
/etc/init.d/adblock-fast disable >/dev/null 2>&1 && echo "OK" || echo "FAIL"
fi
exit 0
endef
$(eval $(call BuildPackage,adblock-fast))

View File

@ -0,0 +1,3 @@
# README
README has been moved to [https://docs.openwrt.melmac.net/adblock-fast/](https://docs.openwrt.melmac.net/adblock-fast/).

View File

@ -0,0 +1,15 @@
s|http://winhelp2002.mvps.org/hosts.txt|https://winhelp2002.mvps.org/hosts.txt|g
s|list blocked_domains_url 'https://dbl.oisd.nl/basic'|list blocked_adblockplus_url 'https://small.oisd.nl/'|g
s|list blocked_domains_url 'https://dbl.oisd.nl/nsfw'|list blocked_adblockplus_url 'https://nsfw.oisd.nl/'|g
s|list blocked_domains_url 'https://dbl.oisd.nl/'|list blocked_adblockplus_url 'https://big.oisd.nl/'|g
s|list blocked_hosts_url 'https://hosts.oisd.nl/basic'|list blocked_adblockplus_url 'https://small.oisd.nl/'|g
s|list blocked_hosts_url 'https://hosts.oisd.nl/nsfw'|list blocked_adblockplus_url 'https://nsfw.oisd.nl/'|g
s|list blocked_hosts_url 'https://hosts.oisd.nl/'|list blocked_adblockplus_url 'https://big.oisd.nl/'|g
\|dshield.org|d
\|www.malwaredomainlist.com/hostslist/hosts.txt|d
\|https://mirror1.malwaredomains.com/files/justdomains|d
\|lists.disconnect.me|d
\|https://cdn.jsdelivr.net/gh/paulgb/BarbBlock/blacklists/domain-list.txt|d
\|dnsmasq.oisd.nl|d
\|dnsmasq2.oisd.nl|d
\|https://cdn.jsdelivr.net/gh/AdguardTeam/cname-trackers@master/combined_disguised_trackers_justdomains.txt|d

View File

@ -0,0 +1,120 @@
config adblock-fast 'config'
option enabled '0'
list allowed_domain 'cdn.jsdelivr.net'
option allow_non_ascii '0'
option canary_domains_icloud '0'
option canary_domains_mozilla '0'
option compressed_cache '0'
option compressed_cache_dir '/etc'
option config_update_enabled '0'
option config_update_url 'https://cdn.jsdelivr.net/gh/openwrt/packages/net/adblock-fast/files/adblock-fast.config.update'
option curl_additional_param ''
option curl_max_file_size '30000000'
option curl_retry '3'
option debug '0'
option dns 'dnsmasq.servers'
list dnsmasq_instance '*'
# option dnsmasq_config_file_url 'https://big.oisd.nl/dnsmasq2'
option download_timeout '10'
option force_dns '1'
list force_dns_port '53'
list force_dns_port '853'
# ports listed below are used by some
# of the dnscrypt-proxy v1 resolvers
# list force_dns_port '553'
# list force_dns_port '1443'
# list force_dns_port '4343'
# list force_dns_port '4434'
# list force_dns_port '5443'
# list force_dns_port '8443'
option led 'none'
option parallel_downloads '1'
option pause_timeout '20'
option procd_trigger_wan6 '0'
option procd_boot_delay '0'
option procd_boot_wan_timeout '60'
option verbosity '2'
config file_url
option url 'https://cdn.jsdelivr.net/gh/StevenBlack/hosts/hosts'
option size '6770929'
option action 'block'
option enabled '0'
config file_url
option url 'https://raw.githubusercontent.com/AdguardTeam/cname-trackers/master/data/combined_disguised_trackers_justdomains.txt'
option size '6241707'
option action 'block'
option enabled '0'
config file_url
option url 'https://big.oisd.nl/'
option size '6163363'
option action 'block'
option enabled '0'
config file_url
option url 'https://cdn.jsdelivr.net/gh/bongochong/CombinedPrivacyBlockLists/NoFormatting/cpbl-ctld.txt'
option size '2608152'
option action 'block'
option enabled '0'
config file_url
option url 'http://sysctl.org/cameleon/hosts'
option size '638545'
option action 'block'
option enabled '0'
config file_url
option url 'https://cdn.jsdelivr.net/gh/kboghdady/youTube_ads_4_pi-hole/black.list'
option size '553006'
option action 'block'
option enabled '0'
config file_url
option url 'https://raw.githubusercontent.com/AdguardTeam/cname-trackers/master/data/combined_disguised_clickthroughs_justdomains.txt'
option size '362170'
option action 'block'
option enabled '0'
config file_url
option url 'https://someonewhocares.org/hosts/hosts'
option size '347410'
option action 'block'
option enabled '0'
config file_url
option url 'https://winhelp2002.mvps.org/hosts.txt'
option size '334861'
option action 'block'
option enabled '0'
config file_url
option url 'https://adaway.org/hosts.txt'
option size '243454'
option action 'block'
option enabled '0'
config file_url
option url 'https://raw.githubusercontent.com/AdguardTeam/cname-trackers/master/data/combined_disguised_ads_justdomains.txt'
option size '222595'
option action 'block'
option enabled '0'
config file_url
option url 'https://raw.githubusercontent.com/AdguardTeam/cname-trackers/master/data/combined_disguised_microsites_justdomains.txt'
option size '123275'
option action 'block'
option enabled '0'
config file_url
option url 'https://pgl.yoyo.org/as/serverlist.php?hostformat=hosts&showintro=1&mimetype=plaintext'
option size '99588'
option action 'block'
option enabled '0'
config file_url
option url 'https://cdn.jsdelivr.net/gh/hoshsadiq/adblock-nocoin-list/hosts.txt'
option size '11149'
option action 'block'
option enabled '0'

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,128 @@
#!/bin/sh
# Copyright 2023 MOSSDeF, Stan Grishin (stangri@melmac.ca)
# shellcheck disable=SC2015,SC3043,SC3060
readonly adbFunctionsFile='/etc/init.d/adblock-fast'
if [ -s "$adbFunctionsFile" ]; then
# shellcheck source=../../etc/init.d/adblock-fast
. "$adbFunctionsFile"
else
printf "%b: adblock-fast init.d file (%s) not found! \n" '\033[0;31mERROR\033[0m' "$adbFunctionsFile"
fi
# Transition from simple-adblock
_enable_url() {
local cfg="$1" url="$2" action="$3"
local u a
config_get u "$cfg" 'url'
config_get a "$cfg" 'action' 'block'
if [ "$u" = "$url" ] && [ "$a" = "$action" ]; then
uci del "${packageName}.${cfg}.enabled" && _found=1
fi
}
enable_add_url() {
local url="$1" action="$2" _found
config_load "$packageName"
config_foreach _enable_url 'file_url' "$url" "$action"
if [ -z "$_found" ]; then
uci add "${packageName}" 'file_url' >/dev/null 2>&1
uci set "${packageName}.@file_url[-1].url=$url"
uci set "${packageName}.@file_url[-1].size=$(get_url_filesize "$url")"
uci set "${packageName}.@file_url[-1].action=$action"
fi
}
if [ -s '/etc/config/simple-adblock' ] \
&& [ ! -s '/etc/config/adblock-fast-opkg' ] \
&& [ "$(uci get adblock-fast.config.enabled)" = '0' ]; then
cp -f '/etc/config/adblock-fast' '/etc/config/adblock-fast-opkg'
enabled="$(uci get simple-adblock.config.enabled)"
if [ -x '/etc/init.d/simple-adblock' ]; then
output "Stopping and disabling simple-adblock "
if /etc/init.d/simple-adblock stop >/dev/null 2>&1 \
&& /etc/init.d/simple-adblock disable \
&& uci set simple-adblock.config.enabled=0 \
&& uci commit simple-adblock; then
output_okn
else
output_failn
fi
else
output "Disabling simple-adblock."
if uci set simple-adblock.config.enabled=0 \
&& uci commit simple-adblock; then
output_okn
else
output_failn
fi
fi
output "Migrating simple-adblock config file "
for i in allow_non_ascii canary_domains_icloud canary_domains_mozilla \
compressed_cache compressed_cache_dir config_update_enabled \
curl_additional_param curl_max_file_size curl_retry download_timeout \
debug dns dns_instance dnsmasq_config_file_url force_dns led \
parallel_downloads procd_trigger_wan6 procd_boot_wan_timeout verbosity; do
j="$(uci -q get simple-adblock.config.${i})"
[ -n "$j" ] && uci set "${packageName}.config.${i}=${j}"
done
[ -n "$enabled" ] && uci set "${packageName}.config.enabled=${enabled}"
j="$(uci -q get simple-adblock.config.config_update_url)"
if [ "${j//simple-adblock/}" = "$j" ]; then
uci set "${packageName}.config.config_update_url=$j"
fi
ccd="$(uci get simple-adblock.config.compressed_cache_dir)"
ccd="${ccd:-/etc}"
for j in $(uci -q get simple-adblock.config.allowed_domain); do
[ -n "$j" ] && uci add_list "${packageName}.config.allowed_domain=${j}"
done
for j in $(uci -q get simple-adblock.config.blocked_domain); do
[ -n "$j" ] && uci add_list "${packageName}.config.blocked_domain=${j}"
done
for j in $(uci -q get simple-adblock.config.force_dns_port); do
[ -n "$j" ] && uci add_list "${packageName}.config.force_dns_port=${j}"
done
output_okn
for i in allowed_domains_url blocked_adblockplus_url blocked_domains_url \
blocked_hosts_url; do
output "Migrating simple-adblock ${i} "
for j in $(uci -q get simple-adblock.config.${i}); do
if [ "$i" = 'allowed_domains_url' ]; then
enable_add_url "$j" 'allow'
else
enable_add_url "$j" 'block'
fi
done
output_okn
done
uci commit "$packageName"
output "Migrating simple-adblock cache file(s) "
for i in '/var/run/simple-adblock/dnsmasq.addnhosts.cache' \
'/var/run/simple-adblock/dnsmasq.conf.cache' \
'/var/run/simple-adblock/dnsmasq.ipset.cache' \
'/var/run/simple-adblock/dnsmasq.nftset.cache' \
'/var/run/simple-adblock/dnsmasq.servers.cache' \
'/var/run/simple-adblock/unbound.cache'; do
if [ -s "$i" ]; then
current_dir="$(dirname "$i")"
mkdir -p "${current_dir//simple-adblock/adblock-fast}"
mv -f "$i" "${i//simple-adblock/adblock-fast}" && output_okn || output_failn
fi
done
for i in 'simple-adblock.dnsmasq.addnhosts.gz' \
'simple-adblock.dnsmasq.conf.gz' \
'simple-adblock.dnsmasq.ipset.gz' \
'simple-adblock.dnsmasq.nftset.gz' \
'simple-adblock.dnsmasq.servers.gz' \
'simple-adblock.unbound.gz'; do
i="${ccd}/${i}"
if [ -s "$i" ]; then
mkdir -p "${ccd//simple-adblock/adblock-fast}"
mv -f "$i" "${i//simple-adblock/adblock-fast}" && output_okn || output_failn
fi
done
output_okn
fi
exit 0

3
net/adblock-fast/test.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
/etc/init.d/"$1" version 2>&1 | grep "$2"

View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=apinger
PKG_SOURCE_DATE:=2015-04-09
PKG_SOURCE_VERSION:=78eb328721ba1a10571c19df95acddcb5f0c17c8
PKG_RELEASE:=2
PKG_RELEASE:=5
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/Jajcus/apinger
@ -46,7 +46,8 @@ define Package/apinger/description
endef
define Package/apinger/conffiles
/etc/apinger.conf
/etc/config/apinger
/etc/apinger.user
endef
define Package/apinger/install
@ -56,7 +57,35 @@ define Package/apinger/install
$(INSTALL_DATA) $(PKG_BUILD_DIR)/src/apinger.conf $(1)/etc/apinger.conf
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/apinger.init $(1)/etc/init.d/apinger
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DATA) ./files/apinger.config $(1)/etc/config/apinger
$(INSTALL_DIR) $(1)/usr/libexec
$(INSTALL_BIN) ./files/apinger-hotplug $(1)/usr/libexec/apinger-hotplug
$(INSTALL_DIR) $(1)/etc/hotplug.d/apinger
$(INSTALL_DATA) ./files/user.hotplug $(1)/etc/hotplug.d/apinger/01-user
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_DATA) ./files/iface.hotplug $(1)/etc/hotplug.d/iface/25-apinger
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
$(INSTALL_BIN) ./files/apinger.rpc $(1)/usr/libexec/rpcd/apinger
endef
define Package/apinger-rrd
SECTION:=net
CATEGORY:=Network
DEPENDS:=+apinger +rrdtool1 +rrdcgi1
TITLE:=Apinger RRD Graphs
URL:=https://github.com/Jajcus/apinger
endef
define Package/apinger-rrd/description
Generate RRD Graphs from Apinger Data
endef
define Package/apinger-rrd/install
$(INSTALL_DIR) $(1)/usr/libexec/apinger/rpc
$(INSTALL_DATA) ./files/graphs.sh $(1)/usr/libexec/apinger/rpc
endef
$(eval $(call BuildPackage,apinger))
$(eval $(call BuildPackage,apinger-rrd))

View File

@ -0,0 +1,22 @@
#!/bin/sh
usage_help()
{
echo "$0 <action> <instance> <target> <srcip> <target_desc> <alarm> <alarmtype> <reason> <send> <recieved> <loss> <delay> <timestamp>"
}
export ACTION=$1
export INSTANCE=$2
export APINGER_TARGET=$3
export APINGER_SRCIP=$4
export APINGER_TARGET_ID=$5
export APINGER_ALARM=$6
export APINGER_ALARM_TYPE=$7
export APINGER_ALARM_MESSAGE=$8
export APINGER_PROBES_SENT=$9
export APINGER_PROBES_RECEIVED=${10}
export APINGER_LOSS=${11}
export APINGER_DELAY=${12}
export APINGER_TIMESTAMP=${13}
exec /sbin/hotplug-call apinger $@

View File

@ -0,0 +1,28 @@
config interface 'wan'
option debug '0'
option status_interval '5'
#config interface 'wan2'
# option debug '0'
# option status_interval '5'
# delay is in ms
#config alarm_delay 'delay200'
# option delay_low '100'
# option delay_high '200'
# loss is in %
#config alarm_loss 'loss50'
# option percent_low '30'
# option percent_high '50'
#config target 'target1'
# option interface 'wan'
# option address '8.8.8.8'
# option alarm_delay 'a1'
# option alarm_loss 'loss50'
# option probe_interval '5'
#config target 'target2'
# option interface 'wan2'
# option address '8.8.8.8'

View File

@ -2,17 +2,241 @@
# Copyright (C) 2006-2011 OpenWrt.org
START=80
USE_PROCD=1
BIN=/usr/sbin/apinger
APINGER_RRD=/apinger/rrd
SERVICE_USE_PID=1
. /lib/functions/network.sh
start() {
service_start /usr/sbin/apinger
set_config_file() {
export CONFIG_FILE="/var/run/apinger-$instance.conf"
}
stop() {
service_stop /usr/sbin/apinger
set_status_file() {
export STATUS_FILE="/var/run/apinger-$instance.status"
}
reload() {
service_reload /usr/sbin/apinger
write_config_block() {
local cfg_var="CONFIG_BLOCK_$instance"
eval echo -e "\$$cfg_var" >> "$CONFIG_FILE"
}
start_config_block() {
eval "export CONFIG_BLOCK_$instance=''"
append CONFIG_BLOCK_$instance "$* {" "\n"
}
close_config_block() {
append CONFIG_BLOCK_$instance "}" "\n"
}
append_config_line() {
append CONFIG_BLOCK_$instance "\t$*" "\n"
}
append_target() {
local target=$1
local interface address probe_interval srcip
local avg_delay_samples avg_loss_samples avg_loss_delay_samples
local alarm_down alarm_delay alarm_loss alarms rrd
config_get interface "$target" interface wan
[ "$interface" != "$instance" ] && return 0
config_get address "$target" address
config_get probe_interval "$target" probe_interval
config_get avg_delay_samples "$target" avg_delay_samples
config_get avg_loss_samples "$target" avg_loss_samples
config_get avg_loss_delay_samples "$target" avg_loss_delay_samples
config_get alarm_down "$target" alarm_down
config_get alarm_delay "$target" alarm_delay
config_get alarm_loss "$target" alarm_loss
config_get_bool rrd "$target" rrd 0
[ -z "$address" ] && return 0
srcip=$(uci_get network "$interface" ipaddr)
[ -z "$srcip" ] && network_get_ipaddr srcip "$interface"
srcip="${srcip:-0.0.0.0}"
alarms=${alarm_down:+\"${alarm_down}\"}
alarms=${alarm_delay:+${alarms:+${alarms}, }}${alarm_delay:+\"${alarm_delay}\"}
alarms=${alarm_loss:+${alarms:+${alarms}, }}${alarm_loss:+\"${alarm_loss}\"}
start_config_block "target \"$address\""
append_config_line "srcip \"$srcip\""
append_config_line "description \"$target\""
[ -n "$probe_interval" ] && append_config_line "interval ${probe_interval}s"
[ -n "$avg_delay_samples" ] && append_config_line "avg_delay_samples ${avg_delay_samples}"
[ -n "$avg_loss_samples" ] && append_config_line "avg_loss_samples ${avg_loss_samples}"
[ -n "$avg_loss_delay_samples" ] && append_config_line "avg_loss_delay_samples ${avg_loss_delay_samples}"
[ -n "$alarms" ] && append_config_line "alarms override ${alarms}"
[ "$rrd" = "1" ] && append_config_line "rrd file \"$APINGER_RRD/apinger-target-$target.rrd\""
close_config_block
write_config_block
}
append_alarm_down() {
local alarm=$1
local time
config_get time "$alarm" time 5
[ -z "$time" ] && return
start_config_block "alarm down \"$alarm\""
append_config_line "time ${time}s"
close_config_block
write_config_block
}
append_alarm_delay() {
local alarm=$1
local delay_low delay_high
config_get delay_low "$alarm" delay_low
config_get delay_high "$alarm" delay_high
if [ -z "$delay_low" ] || [ -z "$delay_high" ]; then
return
fi
start_config_block "alarm delay \"$alarm\""
append_config_line "delay_low ${delay_low}ms"
append_config_line "delay_high ${delay_high}ms"
close_config_block
write_config_block
}
append_alarm_loss() {
local alarm=$1
local percent_low percent_high
config_get percent_low "$alarm" percent_low
config_get percent_high "$alarm" percent_low
if [ -z "$percent_low" ] || [ -z "$percent_high" ]; then
return
fi
start_config_block "alarm loss \"$alarm\""
append_config_line "percent_low ${percent_low}"
append_config_line "percent_high ${percent_high}"
close_config_block
write_config_block
}
init_apinger_config() {
local debug status_interval rrd_interval instance
instance=$1
config_get_bool debug apinger debug 0
config_get status_interval apinger status_interval 1
config_get rrd_interval apinger rrd_interval 30
[ "$debug" = "1" ] && debug=on || debug=off
set_config_file
set_status_file
cat << EOF > "$CONFIG_FILE"
user "root"
group "root"
debug ${debug}
rrd interval ${rrd_interval}s
status {
scriptformat on
file "$STATUS_FILE"
interval ${status_interval}s
}
alarm down "down" {
time 30s
}
alarm delay "delay" {
delay_low 5ms
delay_high 20ms
}
alarm loss "loss" {
percent_low 3
percent_high 5
}
alarm default {
command on "/usr/libexec/apinger-hotplug up $instance '%t' '%i' '%T' '%a' '%A' '%r' '%p' '%P' '%l' '%d' '%s'"
command off "/usr/libexec/apinger-hotplug down $instance '%t' '%i' '%T' '%a' '%A' '%r' '%p' '%P' '%l' '%d' '%s'"
}
target default {
interval 1s
avg_delay_samples 10
avg_loss_samples 50
avg_loss_delay_samples 20
alarms "down", "delay", "loss"
}
EOF
}
start_instance() {
export instance=$1
local enabled
config_get_bool enabled "$instance" enabled 1
[ "$enabled" != "1" ] && return 0
init_apinger_config "$instance"
config_foreach append_alarm_down alarm_down
config_foreach append_alarm_delay alarm_delay
config_foreach append_alarm_loss alarm_loss
config_foreach append_target target
procd_open_instance "$instance"
procd_set_param command $BIN -f -c $CONFIG_FILE
procd_set_param stderr 1
procd_close_instance
}
start_service() {
local instance=$1
config_load apinger
[ ! -d "$APINGER_RRD" ] && mkdir -p "$APINGER_RRD"
if [ -n "$instance" ]; then
start_instance "$instance"
else
config_foreach start_instance interface
fi
}
service_triggers() {
procd_add_reload_trigger apinger
}
clean_instance() {
local instance=$1
set_config_file
set_status_file
[ -e $CONFIG_FILE ] && rm -f $CONFIG_FILE
[ -e $STATUS_FILE ] && rm -f $STATUS_FILE
}
service_stopped() {
local instance=$1
config_load apinger
if [ -n "$instance" ]; then
clean_instance "$instance"
else
config_foreach clean_instance interface
fi
}
reload_service() {
restart
}

View File

@ -0,0 +1,117 @@
#!/bin/sh
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
RPC_SCRIPTS=/usr/libexec/apinger/rpc
[ -d $RPC_SCRIPTS ] && include $RPC_SCRIPTS
__function__() {
type "$1" > /dev/null 2>&1
}
foreach_extra() {
local file obj
[ ! -d $RPC_SCRIPTS ] && return
for file in $RPC_SCRIPTS/*; do
obj="${file##*/}"
$1 "${obj%%.*}"
done
}
apinger_status() {
interface_list() {
append iface_list $1
}
config_load apinger
config_foreach interface_list interface
json_init
json_add_array targets
for iface in $iface_list; do
local status_file="/var/run/apinger-$iface.status"
if [ -f "$status_file" ]; then
_IFS="$IFS"
IFS="|"
while read -r address srcip target received sent timestamp latency loss alarm; do
json_add_object targets
json_add_string interface "$iface"
json_add_string target "$target"
json_add_string address "$address"
json_add_string srcip "$srcip"
json_add_int sent "$sent"
json_add_int received "$received"
json_add_string latency "$latency"
json_add_string loss "$loss"
json_add_string alarm "$alarm"
json_add_int timestamp "$timestamp"
json_close_object
done < "$status_file"
IFS="$_IFS"
fi
done
json_close_array
json_dump
}
call_extra() {
if __function__ "$1"; then
$1
else
json_init
json_add_string error "invalid call $1"
json_dump
fi
}
call_method() {
case "$1" in
status)
apinger_status
;;
*)
call_extra $1
;;
esac
}
list_extra() {
if __function__ "${1}_help"; then
${1}_help
else
json_add_object "$1"
json_close_object
fi
}
list_methods() {
local file
json_init
json_add_object status
json_close_object
foreach_extra list_extra ${1}
json_dump
}
main () {
case "$1" in
list)
list_methods
;;
call)
call_method $2
;;
esac
}
main "$@"

View File

@ -0,0 +1,44 @@
#!/bin/sh
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
APINGER="/usr/sbin/apinger"
RRDCGI="/www/cgi-bin/apinger"
GRAPH_DIR="/apinger/graphs"
WWW_LOCATION="/www${GRAPH_DIR}"
update_interface_graphs() {
local iface cfg cmd
iface=$1
cfg=/var/run/apinger-$iface.conf
[ ! -f $cfg ] && return
cmd="$APINGER -c $cfg -g $WWW_LOCATION -l $GRAPH_DIR"
if [ -x $RRDCGI ]; then
$cmd 2>/dev/null | sed -e '/\(HTML\|TITLE\|H1\|H2\|by\|^#\)/d' >> $RRDCGI
else
$cmd 2>/dev/null | sed -e '/\(HTML\|TITLE\|H1\|H2\|by\)/d' > $RRDCGI
chmod 755 $RRDCGI
fi
}
update_graphs() {
[ ! -d $WWW_LOCATION ] && mkdir -p $WWW_LOCATION
[ -e $RRDCGI ] && rm -f $RRDCGI
config_load apinger
config_foreach update_interface_graphs interface
json_init
json_add_string rrdcgi "$RRDCGI"
json_dump
}
graphs_help() {
json_add_object update_graphs
json_close_object
}

View File

@ -0,0 +1,12 @@
#!/bin/sh
. /lib/functions.sh
/etc/init.d/apinger enabled && {
[ "$(uci_get apinger $INTERFACE)" == "interface" ] || exit 0
[ "$ACTION" = "ifup" ] && {
/etc/init.d/apinger restart $INTERFACE
}
}

View File

@ -0,0 +1,7 @@
#!/bin/sh
[ -e /etc/apinger.user ] && {
sh /etc/apinger.user
}
exit 0

View File

@ -0,0 +1,34 @@
--- a/src/apinger.c
+++ b/src/apinger.c
@@ -786,7 +786,6 @@ struct alarm_cfg *a;
time_t tm;
int i,qp,really_lost;
char *buf1,*buf2;
-int err=0;
if (config->status_file==NULL) return;
@@ -849,12 +848,10 @@ int err=0;
}
}
buf2[i]=0;
- fprintf(f,"Received packets buffer: %s %s\n",buf2,buf1);
if (t->recently_lost!=really_lost){
- fprintf(f," lost packet count mismatch (%i!=%i)!\n",t->recently_lost,really_lost);
- logit("%s: Lost packet count mismatch (%i!=%i)!",t->name,t->recently_lost,really_lost);
- logit("%s: Received packets buffer: %s %s\n",t->name,buf2,buf1);
- err=1;
+ logit("Target \"%s\": Lost packet count mismatch (%i(recently_lost) != %i(really_lost))!",t->name,t->recently_lost,really_lost);
+ logit("Target \"%s\": Received packets buffer: %s %s\n",t->name,buf2,buf1);
+ t->recently_lost = really_lost = 0;
}
free(buf1);
free(buf2);
@@ -862,7 +859,6 @@ int err=0;
fprintf(f,"\n");
}
fclose(f);
- if (err) abort();
}
#ifdef FORKED_RECEIVER

View File

@ -0,0 +1,564 @@
--- a/src/apinger.c
+++ b/src/apinger.c
@@ -161,6 +161,9 @@ time_t tim;
case 't':
values[n]=t->name;
break;
+ case 'i':
+ values[n]=t->config->srcip;
+ break;
case 'T':
values[n]=t->description;
break;
@@ -276,6 +279,7 @@ time_t tm;
else
fprintf(f,"alarm canceled: %s\n",a->name);
fprintf(f,"Target: %s\n",t->name);
+ fprintf(f,"Source: %s\n",t->config->srcip);
fprintf(f,"Description: %s\n",t->description);
fprintf(f,"Probes sent: %i\n",t->last_sent+1);
fprintf(f,"Replies received: %i\n",t->received);
@@ -645,7 +649,7 @@ void configure_targets(void){
struct target *t,*pt,*nt;
struct target_cfg *tc;
struct active_alarm_list *al,*nal;
-union addr addr;
+union addr addr, srcaddr;
int r;
int l;
@@ -665,6 +669,8 @@ int l;
nal=al->next;
free(al);
}
+ if (t->socket)
+ close(t->socket);
free(t->queue);
free(t->rbuf);
free(t->name);
@@ -681,20 +687,16 @@ int l;
break;
if (t==NULL) { /* new target */
memset(&addr,0,sizeof(addr));
+ logit("Checking target IP %s", tc->srcip);
r=inet_pton(AF_INET,tc->name,&addr.addr4.sin_addr);
if (r){
- if (icmp_sock<0){
- logit("Sorry, IPv4 is not available\n");
- logit("Ignoring target %s\n",tc->name);
- continue;
- }
addr.addr.sa_family=AF_INET;
}else{
#ifdef HAVE_IPV6
r=inet_pton(AF_INET6,tc->name,&addr.addr6.sin6_addr);
if (r==0){
#endif
- logit("Bad host address: %s\n",tc->name);
+ logit("Bad target IP address: %s\n",tc->name);
logit("Ignoring target %s\n",tc->name);
continue;
#ifdef HAVE_IPV6
@@ -707,12 +709,38 @@ int l;
addr.addr.sa_family=AF_INET6;
#endif
}
+ memset(&srcaddr,0,sizeof(srcaddr));
+ logit("Checking source IP %s", tc->srcip);
+ r=inet_pton(AF_INET,tc->srcip,&srcaddr.addr4.sin_addr);
+ if (r){
+ srcaddr.addr.sa_family=AF_INET;
+ }else{
+#ifdef HAVE_IPV6
+ r=inet_pton(AF_INET6,tc->srcip,&srcaddr.addr6.sin6_addr);
+ if (r==0){
+#endif
+ logit("Bad source IP address %s for target %s\n", tc->srcip, tc->name);
+ logit("Ignoring target %s\n",tc->name);
+ continue;
+#ifdef HAVE_IPV6
+ }
+ if (icmp6_sock<0){
+ logit("Sorry, IPv6 is not available\n");
+ logit("Ignoring target %s\n",tc->name);
+ continue;
+ }
+ srcaddr.addr.sa_family=AF_INET6;
+#endif
+ }
t=NEW(struct target,1);
memset(t,0,sizeof(struct target));
t->name=strdup(tc->name);
t->description=strdup(tc->description);
t->addr=addr;
+ t->ifaddr=srcaddr;
t->next=targets;
+ if(t->addr.addr.sa_family==AF_INET) make_icmp_socket(t);
+ if(t->addr.addr.sa_family==AF_INET6) make_icmp6_socket(t);
targets=t;
}
t->config=tc;
@@ -752,6 +780,8 @@ struct active_alarm_list *al,*nal;
nal=al->next;
free(al);
}
+ if (t->socket)
+ close(t->socket);
free(t->queue);
free(t->rbuf);
free(t->name);
@@ -799,6 +829,7 @@ char *buf1,*buf2;
fprintf(f,"%s\n",ctime(&tm));
for(t=targets;t;t=t->next){
fprintf(f,"Target: %s\n",t->name);
+ fprintf(f,"Source: %s\n",t->config->srcip);
fprintf(f,"Description: %s\n",t->description);
fprintf(f,"Last reply received: #%i %s",t->last_received,
ctime(&t->last_received_tv.tv_sec));
@@ -909,7 +940,7 @@ int i;
void main_loop(void){
struct target *t;
struct timeval cur_time,next_status={0,0},tv,next_report={0,0},next_rrd_update={0,0};
-struct pollfd pfd[2];
+struct pollfd pfd[1024];
int timeout;
int npfd=0;
int i;
@@ -946,18 +977,8 @@ struct piped_info pi;
pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
pfd[npfd].revents=0;
pfd[npfd++].fd=recv_pipe[0];
-#else
- if (icmp_sock){
- pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
- pfd[npfd].revents=0;
- pfd[npfd++].fd=icmp_sock;
- }
- if (icmp6_sock){
- pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
- pfd[npfd++].fd=icmp6_sock;
- pfd[npfd].revents=0;
- }
#endif
+ memset(&pfd, '\0', sizeof pfd);
if (config->status_interval){
gettimeofday(&cur_time,NULL);
tv.tv_sec=config->status_interval/1000;
@@ -965,10 +986,16 @@ struct piped_info pi;
timeradd(&cur_time,&tv,&next_status);
}
while(!interrupted_by){
+ npfd = 0;
gettimeofday(&cur_time,NULL);
if ( !timercmp(&next_probe,&cur_time,>) )
timerclear(&next_probe);
for(t=targets;t;t=t->next){
+ if (t->socket){
+ pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
+ pfd[npfd].revents=0;
+ pfd[npfd++].fd=t->socket;
+ }
for(al=t->config->alarms;al;al=nal){
a=al->alarm;
nal=al->next;
@@ -1051,8 +1078,20 @@ struct piped_info pi;
analyze_reply(pi.recv_timestamp,pi.icmp_seq,&pi.ti);
}
#else
- if (pfd[i].fd==icmp_sock) recv_icmp();
- else if (pfd[i].fd==icmp6_sock) recv_icmp6();
+ for(t=targets;t;t=t->next){
+ if (t->addr.addr.sa_family==AF_INET) {
+ if (t->socket == pfd[i].fd) {
+ recv_icmp(t);
+ break;
+ }
+ }
+ if (t->addr.addr.sa_family==AF_INET6) {
+ if (t->socket == pfd[i].fd) {
+ recv_icmp6(t);
+ break;
+ }
+ }
+ }
#endif
pfd[i].revents=0;
}
--- a/src/apinger.conf
+++ b/src/apinger.conf
@@ -47,6 +47,7 @@ alarm default {
## Following "macros" may be used in options below:
## %t - target name (address)
+ ## %i - source name (address)
## %T - target description
## %a - alarm name
## %A - alarm type ("down"/"loss"/"delay")
--- a/src/apinger.h
+++ b/src/apinger.h
@@ -46,6 +46,8 @@
#endif
#include "conf.h"
+#include <ifaddrs.h>
+
union addr {
struct sockaddr addr;
struct sockaddr_in addr4;
@@ -70,6 +72,7 @@ struct target {
char *queue; /*
contains info about recently sent packets
"1" means it was received */
+ int socket;
int last_sent; /* sequence number of the last ping sent */
int last_received; /* sequence number of the last ping received */
struct timeval last_received_tv; /* timestamp of the last ping received */
@@ -89,6 +92,7 @@ struct target {
struct target_cfg *config;
struct target *next;
+ union addr ifaddr; /* iface address */
};
#define AVG_DELAY_KNOWN(t) (t->upsent >= t->config->avg_delay_samples)
@@ -118,16 +122,16 @@ extern char *config_file;
extern int icmp_sock;
extern int icmp6_sock;
-extern int ident;
+extern uint16_t ident;
extern struct timeval next_probe;
-int make_icmp_socket(void);
-void recv_icmp(void);
+int make_icmp_socket(struct target *t);
+void recv_icmp(struct target *t);
void send_icmp_probe(struct target *t,int seq);
-int make_icmp6_socket(void);
-void recv_icmp6(void);
+int make_icmp6_socket(struct target *t);
+void recv_icmp6(struct target *t);
void send_icmp6_probe(struct target *t,int seq);
#ifdef FORKED_RECEIVER
--- a/src/cfgparser1.y
+++ b/src/cfgparser1.y
@@ -96,6 +96,7 @@ struct target_cfg *cur_target;
%token DELAY_HIGH
%token DESCRIPTION
+%token SRCIP
%token ALARMS
%token INTERVAL
%token AVG_DELAY_SAMPLES
@@ -247,6 +248,8 @@ target: TARGET getdeftarget DEFAULT '{'
targetcfg: /* */
| DESCRIPTION string
{ cur_target->description=$2; }
+ | SRCIP string
+ { cur_target->srcip = $2; }
| ALARMS alarmlist
{ cur_target->alarms=$2; }
| ALARMS OVERRIDE alarmlist
--- a/src/cfgparser2.l
+++ b/src/cfgparser2.l
@@ -81,6 +81,7 @@ delay { LOC; LOCINC; return DELAY; }
delay_high { LOC; LOCINC; return DELAY_HIGH; }
delay_low { LOC; LOCINC; return DELAY_LOW; }
description { LOC; LOCINC; return DESCRIPTION; }
+srcip { LOC; LOCINC; return SRCIP; }
down { LOC; LOCINC; return DOWN; }
false { LOC; LOCINC; return FALSE; }
file { LOC; LOCINC; return FILE_; }
--- a/src/conf.c
+++ b/src/conf.c
@@ -174,6 +174,14 @@ int ret;
}
}
for(t=cur_config.targets;t;t=t->next){
+ if (t->name==NULL || strlen(t->name)==0){
+ logit("Target name can't be empty.");
+ return 1;
+ }
+ else if (t->srcip==NULL){
+ logit("No source IP defined for target \"%s\".", t->name);
+ return 1;
+ }
if (t->description==NULL)
t->description=cur_config.target_defaults.description;
if (t->interval<=0)
--- a/src/conf.h
+++ b/src/conf.h
@@ -71,6 +71,7 @@ struct alarm_list {
struct target_cfg {
char *name;
char *description;
+ char *srcip;
int interval;
int avg_delay_samples;
int avg_loss_delay_samples;
--- a/src/icmp6.c
+++ b/src/icmp6.c
@@ -112,14 +112,14 @@ int ret;
memcpy(p+1,&ti,sizeof(ti));
size=sizeof(*p)+sizeof(ti);
- ret=sendto(icmp6_sock,p,size,MSG_DONTWAIT,
+ ret=sendto(t->socket,p,size,MSG_DONTWAIT,
(struct sockaddr *)&t->addr.addr6,sizeof(t->addr.addr6));
if (ret<0){
if (config->debug) myperror("sendto");
}
}
-void recv_icmp6(void){
+void recv_icmp6(struct target *t){
int len,icmplen,datalen;
char buf[1024];
char abuf[100];
@@ -133,6 +133,7 @@ char ans_data[4096];
struct iovec iov;
struct msghdr msg;
struct cmsghdr *c;
+reloophack6:
iov.iov_base=buf;
iov.iov_len=1000;
@@ -142,12 +143,13 @@ struct cmsghdr *c;
msg.msg_iovlen=1;
msg.msg_control=ans_data;
msg.msg_controllen=sizeof(ans_data);
- len=recvmsg(icmp6_sock, &msg, MSG_DONTWAIT);
+ len=recvmsg(t->socket, &msg, MSG_DONTWAIT);
#else
socklen_t sl;
+reloophack6:
sl=sizeof(from);
- len=recvfrom(icmp6_sock,buf,1024,0,(struct sockaddr *)&from,&sl);
+ len=recvfrom(t->socket,buf,1024,0,(struct sockaddr *)&from,&sl);
#endif
if (len<0){
if (errno==EAGAIN) return;
@@ -169,7 +171,7 @@ socklen_t sl;
#endif
if (time_recvp==NULL){
#ifdef SIOCGSTAMP
- if (!ioctl(icmp6_sock, SIOCGSTAMP, &time_recv)){
+ if (!ioctl(t->socket, SIOCGSTAMP, &time_recv)){
debug("Got timestamp from ioctl()");
}else
#endif
@@ -182,8 +184,11 @@ socklen_t sl;
icmplen=len;
icmp=(struct icmp6_hdr *)buf;
if (icmp->icmp6_type != ICMP6_ECHO_REPLY) return;
- if (icmp->icmp6_id != ident) return;
-
+ if (icmp->icmp6_id != ident){
+ debug("Alien echo-reply received from xxx. Expected %i, received %i", ident, icmp->icmp6_id);
+ goto reloophack6;
+ return;
+ }
name=inet_ntop(AF_INET6,&from.sin6_addr,abuf,100);
debug("Ping reply from %s",name);
datalen=icmplen-sizeof(*icmp);
@@ -199,33 +204,36 @@ socklen_t sl;
}
-int make_icmp6_socket(void){
+int make_icmp6_socket(struct target *t){
int opt;
- icmp6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- if (icmp6_sock<0)
+ t->socket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if (t->socket <0)
myperror("socket");
else {
opt=2;
#if defined(SOL_RAW) && defined(IPV6_CHECKSUM)
- if (setsockopt(icmp6_sock, SOL_RAW, IPV6_CHECKSUM, &opt, sizeof(int)))
+ if (setsockopt(t->socket, SOL_RAW, IPV6_CHECKSUM, &opt, sizeof(int)))
myperror("setsockopt(IPV6_CHECKSUM)");
#endif
#ifdef SO_TIMESTAMP
opt=1;
- if (setsockopt(icmp6_sock, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)))
+ if (setsockopt(t->socket, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)))
myperror("setsockopt(SO_TIMESTAMP)");
#endif
/*install_filter6();*/
}
- return icmp6_sock;
+ if (bind(t->socket, (struct sockaddr *)&t->ifaddr.addr6, sizeof(t->ifaddr.addr6)) < 0)
+ myperror("bind socket");
+
+ return t->socket;
}
#else /*HAVE_IPV6*/
#include "apinger.h"
-int make_icmp6_socket(void){ return -1; }
-void recv_icmp6(void){}
+int make_icmp6_socket(struct target *t){ return -1; }
+void recv_icmp6(struct target *t){}
void send_icmp6_probe(struct target *t,int seq){}
#endif /*HAVE_IPV6*/
--- a/src/icmp.c
+++ b/src/icmp.c
@@ -150,14 +150,14 @@ int ret;
size=sizeof(*p)+sizeof(ti);
p->icmp_cksum = in_cksum((u_short *)p,size,0);
- ret=sendto(icmp_sock,p,size,MSG_DONTWAIT,
+ ret=sendto(t->socket,p,size,MSG_DONTWAIT,
(struct sockaddr *)&t->addr.addr4,sizeof(t->addr.addr4));
if (ret<0){
if (config->debug) myperror("sendto");
}
}
-void recv_icmp(void){
+void recv_icmp(struct target *t){
int len,hlen,icmplen,datalen;
char buf[1024];
struct sockaddr_in from;
@@ -170,6 +170,7 @@ char ans_data[4096];
struct iovec iov;
struct msghdr msg;
struct cmsghdr *c;
+reloophack:
iov.iov_base=buf;
iov.iov_len=1000;
@@ -179,12 +180,13 @@ struct cmsghdr *c;
msg.msg_iovlen=1;
msg.msg_control=ans_data;
msg.msg_controllen=sizeof(ans_data);
- len=recvmsg(icmp_sock, &msg, MSG_DONTWAIT);
+ len=recvmsg(t->socket, &msg, MSG_DONTWAIT);
#else
socklen_t sl;
+reloophack:
sl=sizeof(from);
- len=recvfrom(icmp_sock,buf,1024,MSG_DONTWAIT,(struct sockaddr *)&from,&sl);
+ len=recvfrom(t->socket,buf,1024,MSG_DONTWAIT,(struct sockaddr *)&from,&sl);
#endif
if (len<0){
if (errno==EAGAIN) return;
@@ -196,7 +198,7 @@ socklen_t sl;
debug("checking CMSG...");
for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
debug("CMSG level: %i type: %i",c->cmsg_level,c->cmsg_type);
- if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SO_TIMESTAMP)
+ if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SCM_TIMESTAMP)
continue;
if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
continue;
@@ -206,7 +208,7 @@ socklen_t sl;
#endif
if (time_recvp==NULL){
#ifdef SIOCGSTAMP
- if (!ioctl(icmp_sock, SIOCGSTAMP, &time_recv)){
+ if (!ioctl(t->socket, SIOCGSTAMP, &time_recv)){
debug("Got timestampt from ioctl()");
}else
#endif
@@ -226,7 +228,8 @@ socklen_t sl;
return;
}
if (icmp->icmp_id != ident){
- debug("Alien echo-reply received");
+ debug("Alien echo-reply received from %s. Expected %i, received %i",inet_ntoa(from.sin_addr), ident, icmp->icmp_id);
+ goto reloophack;
return;
}
debug("Ping reply from %s",inet_ntoa(from.sin_addr));
@@ -242,19 +245,23 @@ socklen_t sl;
#endif
}
-int make_icmp_socket(void){
+int make_icmp_socket(struct target *t){
int on;
- icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (icmp_sock<0)
+ t->socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (t->socket < 0)
myperror("socket");
#ifdef SO_TIMESTAMP
else{
on=1;
- if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
+ if (setsockopt(t->socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
myperror("setsockopt(SO_TIMESTAMP)");
}
#endif
- return icmp_sock;
+
+ if (bind(t->socket, (struct sockaddr *)&t->ifaddr.addr4, sizeof(t->ifaddr.addr4)) < 0)
+ myperror("bind socket");
+
+ return t->socket;
}
--- a/src/main.c
+++ b/src/main.c
@@ -71,6 +71,7 @@ struct config default_config={
{ /* target defaults */
"default", /* name */
"", /* description */
+ "", /* interface */
1000, /* interval */
20, /* avg_delay_samples */
5, /* avg_loss_delay_samples */
@@ -95,7 +96,7 @@ char *config_file=CONFIG;
int icmp_sock;
int icmp6_sock;
-int ident;
+uint16_t ident;
struct timeval next_probe={0,0};
@@ -216,12 +217,6 @@ char *graph_location="/apinger/";
}
}
- make_icmp_socket();
- make_icmp6_socket();
- if (icmp6_sock<0 && icmp_sock<0){
- return 1;
- }
-
pw=getpwnam(config->user);
if (!pw) {
debug("getpwnam(\"%s\") failed.",config->user);
@@ -276,7 +271,7 @@ char *graph_location="/apinger/";
return 1;
}
- ident=getpid();
+ ident=getpid() & 0xFFFF;
signal(SIGTERM,signal_handler);
signal(SIGINT,signal_handler);
signal(SIGHUP,signal_handler);
@@ -285,9 +280,8 @@ char *graph_location="/apinger/";
#ifdef FORKED_RECEIVER
signal(SIGCHLD,sigchld_handler);
#endif
+ logit("Starting Alarm Pinger, apinger(%i)", ident);
main_loop();
- if (icmp_sock>=0) close(icmp_sock);
- if (icmp6_sock>=0) close(icmp6_sock);
logit("Exiting on signal %i.",interrupted_by);

View File

@ -0,0 +1,126 @@
--- a/src/apinger.c
+++ b/src/apinger.c
@@ -826,26 +826,49 @@ char *buf1,*buf2;
return;
}
tm=time(NULL);
- fprintf(f,"%s\n",ctime(&tm));
+ if(!config->status_format) fprintf(f,"%s\n",ctime(&tm));
for(t=targets;t;t=t->next){
- fprintf(f,"Target: %s\n",t->name);
- fprintf(f,"Source: %s\n",t->config->srcip);
- fprintf(f,"Description: %s\n",t->description);
- fprintf(f,"Last reply received: #%i %s",t->last_received,
- ctime(&t->last_received_tv.tv_sec));
- fprintf(f,"Average delay: %0.3fms\n",AVG_DELAY(t));
+ if(config->status_format){
+ fprintf(f,"%s|%s|%s|%i|%i|%u|",t->name, t->config->srcip, t->description, t->last_sent+1,
+ t->received, t->last_received_tv.tv_sec);
+ fprintf(f,"%0.3fms|", AVG_DELAY(t));
+ }
+ else{
+ fprintf(f,"Target: %s\n",t->name);
+ fprintf(f,"Source: %s\n",t->config->srcip);
+ fprintf(f,"Description: %s\n",t->description);
+ fprintf(f,"Last reply received: #%i %s",t->last_received,
+ ctime(&t->last_received_tv.tv_sec));
+ fprintf(f,"Average delay: %0.3fms\n",AVG_DELAY(t));
+ }
if (AVG_LOSS_KNOWN(t)){
- fprintf(f,"Average packet loss: %0.1f%%\n",AVG_LOSS(t));
+ if(config->status_format){
+ fprintf(f,"%0.1f%%",AVG_LOSS(t));
+ }
+ else{
+ fprintf(f,"Average packet loss: %0.1f%%\n",AVG_LOSS(t));
+ }
+ }
+ if(config->status_format){
+ fprintf(f, "|");
+ }
+ else{
+ fprintf(f,"Active alarms: ");
}
- fprintf(f,"Active alarms:");
if (t->active_alarms){
for(al=t->active_alarms;al;al=al->next){
a=al->alarm;
- fprintf(f," \"%s\"",a->name);
+ if(config->status_format){
+ fprintf(f,"%s",a->name);
+ }
+ else{
+ fprintf(f," \"%s\"",a->name);
+ }
}
- fprintf(f,"\n");
+ if(!config->status_format) fprintf(f,"\n");
}
- else fprintf(f," None\n");
+ else fprintf(f,"none");
+ if(!config->status_format) fprintf(f,"\n");
buf1=NEW(char,t->config->avg_loss_delay_samples+1);
buf2=NEW(char,t->config->avg_loss_samples+1);
--- a/src/apinger.conf
+++ b/src/apinger.conf
@@ -29,6 +29,10 @@ group "nogroup"
# ## Interval between file updates
# ## when 0 or not set, file is written only when SIGUSR1 is received
# interval 5m
+#
+# ## Create status file in script parseable format (on) or human
+# ## readable format (off)
+# scriptformat off
#}
########################################
--- a/src/cfgparser1.y
+++ b/src/cfgparser1.y
@@ -104,6 +104,7 @@ struct target_cfg *cur_target;
%token AVG_LOSS_DELAY_SAMPLES
%token FILE_
+%token SCRIPTFORMAT
%token ERROR
@@ -282,6 +283,8 @@ statuscfg: /* */
{ cur_config.status_interval=$2; }
| INTERVAL TIME
{ cur_config.status_interval=$2; }
+ | SCRIPTFORMAT boolean
+ { cur_config.status_format=$2; }
| statuscfg separator statuscfg
;
--- a/src/cfgparser2.l
+++ b/src/cfgparser2.l
@@ -85,6 +85,7 @@ srcip { LOC; LOCINC; return SRCIP; }
down { LOC; LOCINC; return DOWN; }
false { LOC; LOCINC; return FALSE; }
file { LOC; LOCINC; return FILE_; }
+scriptformat { LOC; LOCINC; return SCRIPTFORMAT; }
group { LOC; LOCINC; return GROUP; }
interval { LOC; LOCINC; return INTERVAL; }
loss { LOC; LOCINC; return LOSS; }
--- a/src/conf.h
+++ b/src/conf.h
@@ -97,6 +97,7 @@ struct config {
char *pid_file;
char *status_file;
int status_interval;
+ int status_format;
char *timestamp_format;
};
--- a/src/main.c
+++ b/src/main.c
@@ -88,6 +88,7 @@ struct config default_config={
"/var/run/apinger.pid", /* pid file */
NULL, /* status file */
0, /* status interval */
+ 0, /* status format */
"%b %d %H:%M:%S" /* timestamp format */
};

View File

@ -0,0 +1,12 @@
--- a/src/apinger.c
+++ b/src/apinger.c
@@ -860,6 +860,9 @@ char *buf1,*buf2;
a=al->alarm;
if(config->status_format){
fprintf(f,"%s",a->name);
+ if(al->next){
+ fprintf(f,",");
+ }
}
else{
fprintf(f," \"%s\"",a->name);

60
net/basicstation/Makefile Normal file
View File

@ -0,0 +1,60 @@
#
# Copyright (C) 2022 TDT AG <development@tdt.de>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
#
include $(TOPDIR)/rules.mk
PKG_NAME:=basicstation
PKG_VERSION:=2.0.6
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/lorabasics/basicstation/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=7e285de94bae1174b4c3496fc3ab15fe67c72f92c0693d2320bafc654a9dfb43
PKG_MAINTAINER:=Marcus Schref <mschref@tdt.de>
PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE
PKG_BUILD_DEPENDS:=sx1302_hal mbedtls
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/basicstation
SECTION:=net
CATEGORY:=Network
SUBMENU:=LoRaWAN
TITLE:=LoRa Basic Station
DEPENDS:=+kmod-usb-acm
endef
define Package/basicstation/description
LoRa Basic Station. The LoRaWAN Gateway Software.
endef
define Package/basicstation/conffiles
/etc/config/basicstation
endef
define Build/Prepare
$(call Build/Prepare/Default)
rm -rf $(PKG_BUILD_DIR)/deps/
rm -f $(PKG_BUILD_DIR)/makefile
rm -f $(PKG_BUILD_DIR)/makefile.s2core
rm -f $(PKG_BUILD_DIR)/setup.gmk
endef
define Package/basicstation/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/station $(1)/usr/bin
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/basicstation $(1)/etc/config/basicstation
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/basicstation $(1)/etc/init.d/basicstation
endef
$(eval $(call BuildPackage,basicstation))

View File

@ -0,0 +1,146 @@
config auth 'auth'
option cred ''
option mode ''
option addr ''
option port ''
option token ''
option key ''
option crt ''
option trust ''
config sx130x 'sx130x'
option comif ''
option devpath ''
option pps ''
option public ''
option clksrc ''
option radio0 ''
option radio1 ''
config rfconf 'rfconf0'
option type 'SX1250'
option txEnable '1'
option freq ''
option antennaGain '3'
option rssiOffset '-215.4'
option useRssiTcomp 'std'
config rfconf 'rfconf1'
option type 'SX1250'
option txEnable '0'
option freq ''
option antennaGain '3'
option rssiOffset '-215.4'
option useRssiTcomp 'std'
config rssitcomp 'std'
option coeff_a '0'
option coeff_b '0'
option coeff_c '20.41'
option coeff_d '2162.56'
option coeff_e '0'
config txlut
option rfPower '12'
option paGain '0'
option pwrIdx '15'
list usedBy 'rfconf0'
config txlut
option rfPower '13'
option paGain '0'
option pwrIdx '16'
list usedBy 'rfconf0'
config txlut
option rfPower '14'
option paGain '0'
option pwrIdx '17'
list usedBy 'rfconf0'
config txlut
option rfPower '15'
option paGain '0'
option pwrIdx '19'
list usedBy 'rfconf0'
config txlut
option rfPower '16'
option paGain '0'
option pwrIdx '20'
list usedBy 'rfconf0'
config txlut
option rfPower '17'
option paGain '0'
option pwrIdx '22'
list usedBy 'rfconf0'
config txlut
option rfPower '18'
option paGain '1'
option pwrIdx '1'
list usedBy 'rfconf0'
config txlut
option rfPower '19'
option paGain '1'
option pwrIdx '2'
list usedBy 'rfconf0'
config txlut
option rfPower '20'
option paGain '1'
option pwrIdx '3'
list usedBy 'rfconf0'
config txlut
option rfPower '21'
option paGain '1'
option pwrIdx '4'
list usedBy 'rfconf0'
config txlut
option rfPower '22'
option paGain '1'
option pwrIdx '5'
list usedBy 'rfconf0'
config txlut
option rfPower '23'
option paGain '1'
option pwrIdx '6'
list usedBy 'rfconf0'
config txlut
option rfPower '24'
option paGain '1'
option pwrIdx '7'
list usedBy 'rfconf0'
config txlut
option rfPower '25'
option paGain '1'
option pwrIdx '9'
list usedBy 'rfconf0'
config txlut
option rfPower '26'
option paGain '1'
option pwrIdx '11'
list usedBy 'rfconf0'
config txlut
option rfPower '27'
option paGain '1'
option pwrIdx '14'
list usedBy 'rfconf0'
config station 'station'
option idGenIf ''
option routerid ''
option stationid ''
option logFile ''
option logLevel ''
option logSize ''
option logRotate ''

View File

@ -0,0 +1,254 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2022 TDT AG <development@tdt.de>
#
# This is free software, licensed under the GNU General Public License v2.
# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
START=85
STOP=25
USE_PROCD=1
#radioconf
DEFAULT_COMIF='usb'
DEFAULT_DEVPATH='/dev/ttyACM0'
DEFAULT_PPS=0
DEFAULT_PUBLIC=1
DEFAULT_CLKSRC=0
DEFAULT_RADIO_0='rfconf0'
DEFAULT_RADIO_1='rfconf1'
#rfconf
DEFAULT_TYPE='SX1250'
DEFAULT_TX_ENABLE=0
DEFAULT_FREQ=0
DEFAULT_RSSI_OFFSET=0
DEFAULT_ANTENNA_GAIN=0
DEFAULT_RSSI_TCOMP='std'
#rssi tcomp
DEFAULT_RSSI_TCOMP_A=0
DEFAULT_RSSI_TCOMP_B=0
DEFAULT_RSSI_TCOMP_C=20.41
DEFAULT_RSSI_TCOMP_D=2162.56
DEFAULT_RSSI_TCOMP_E=0
#tx gain lut
DEFAULT_RF_POWER=0
DEFAULT_PA_GAIN=0
DEFAULT_PWR_IDX=0
#station
DEFAULT_RADIO_INIT=''
DEFAULT_ID_GEN_IF='eth0'
DEFAULT_ROUTER_ID='/sys/class/net/eth0/address'
DEFAULT_LOG_FILE='/tmp/basicstation/log'
DEFAULT_LOG_LEVEL='DEBUG'
DEFAULT_LOG_SIZE=1
DEFAULT_LOG_ROTATE=1
#auth
DEFAULT_CREDENTIALS='tc'
DEFAULT_MODE='no'
parse_txlut() {
local section="$1"
local buffer
config_get buffer "$section" usedBy
if [[ "$buffer" == *"$2"* ]]; then
json_add_object
config_get buffer "$section" rfPower "$DEFAULT_RF_POWER"
json_add_int 'rf_power' "$buffer"
config_get_bool buffer "$section" paGain "$DEFAULT_PA_GAIN"
json_add_int 'pa_gain' "$buffer"
config_get buffer "$section" pwrIdx "$DEFAULT_PWR_IDX"
json_add_int 'pwr_idx' "$buffer"
json_close_object
fi
}
parse_rssitcomp() {
local section="$1"
local buffer
if [ "$section" = "$2" ]; then
json_add_object 'rssi_tcomp'
config_get buffer "$section" coeff_a "$DEFAULT_RSSI_TCOMP_A"
json_add_double 'coeff_a' "$buffer"
config_get buffer "$section" coeff_b "$DEFAULT_RSSI_TCOMP_B"
json_add_double 'coeff_b' "$buffer"
config_get buffer "$section" coeff_c "$DEFAULT_RSSI_TCOMP_C"
json_add_double 'coeff_c' "$buffer"
config_get buffer "$section" coeff_d "$DEFAULT_RSSI_TCOMP_D"
json_add_double 'coeff_d' "$buffer"
config_get buffer "$section" coeff_e "$DEFAULT_RSSI_TCOMP_E"
json_add_double 'coeff_e' "$buffer"
json_close_object
fi
}
parse_rfconf() {
local section="$1"
local buffer
if [ "$section" = "$2" ]; then
json_add_object "radio_"$3""
config_get buffer "$section" type "$DEFAULT_TYPE"
json_add_string 'type' "$buffer"
config_get buffer "$section" freq "$DEFAULT_FREQ"
json_add_int 'freq' "$buffer"
config_get buffer "$section" antennaGain "$DEFAULT_ANTENNA_GAIN"
json_add_int 'antenna_gain' "$buffer"
config_get buffer "$section" rssiOffset "$DEFAULT_RSSI_OFFSET"
json_add_double 'rssi_offset' "$buffer"
config_get buffer "$section" useRssiTcomp "$DEFAULT_RSSI_TCOMP"
config_foreach parse_rssitcomp rssitcomp "$buffer"
config_get_bool buffer "$section" txEnable "$DEFAULT_TX_ENABLE"
json_add_boolean 'tx_enable' "$buffer"
if [ "$buffer" -eq 1 ]; then
json_add_array 'tx_gain_lut'
config_foreach parse_txlut txlut "$section"
json_close_array
fi
json_close_object
fi
}
parse_sx130x() {
local section="$1"
local comif
local devpath
local buffer
json_add_object 'radio_conf'
config_get comif "$section" comif "$DEFAULT_COMIF"
config_get devpath "$section" devpath "$DEFAULT_DEVPATH"
json_add_string 'device' ""$comif":"$devpath""
config_get_bool buffer "$section" pps "$DEFAULT_PPS"
json_add_boolean 'pps' "$buffer"
config_get_bool buffer "$section" public "$DEFAULT_PUBLIC"
json_add_boolean 'lorawan_public' "$buffer"
config_get buffer "$section" clksrc "$DEFAULT_CLKSRC"
json_add_int 'clksrc' "$buffer"
json_add_boolean 'full_duplex' 0
config_get buffer "$section" radio0 "$DEFAULT_RADIO_0"
config_foreach parse_rfconf rfconf "$buffer" 0
config_get buffer "$section" radio1 "$DEFAULT_RADIO_1"
config_foreach parse_rfconf rfconf "$buffer" 1
json_close_object
}
parse_station() {
local section="$1"
local buffer
local mac
config_get buffer "$section" idGenIf "$DEFAULT_ID_GEN_IF"
mac=$(head -n 1 /sys/class/net/"$buffer"/address)
uci_set basicstation "$section" stationid "${mac::8}:ff:fe:${mac:9:8}"
uci_commit basicstation
json_add_object 'station_conf'
config_get buffer "$section" routerid "$DEFAULT_ROUTER_ID"
json_add_string 'routerid' "$buffer"
config_get buffer "$section" radioInit "$DEFAULT_RADIO_INIT"
json_add_string 'radio_init' "$buffer"
config_get buffer "$section" logFile "$DEFAULT_LOG_FILE"
json_add_string 'log_file' "$buffer"
config_get buffer "$section" logLevel "$DEFAULT_LOG_LEVEL"
json_add_string 'log_level' "$buffer"
config_get buffer "$section" logSize "$DEFAULT_LOG_SIZE"
json_add_int 'log_size' $(( 1000000*buffer ))
config_get buffer "$section" logRotate "$DEFAULT_LOG_ROTATE"
json_add_int 'log_rotate' "$buffer"
json_close_object
}
parse_auth() {
local section="$1"
local cred
local mode
local addr
local port
local uri
local buffer
config_get cred "$section" cred "$DEFAULT_CREDENTIALS"
config_get mode "$section" mode "$DEFAULT_MODE"
config_get addr "$section" addr
config_get port "$section" port
if [ "$mode" != 'no' ]; then
config_get buffer "$section" trust
[ -f "$buffer" ] && cp "$buffer" /tmp/basicstation/"$cred".trust
if [ "$mode" = 'serverAndClient' ]; then
config_get buffer "$section" key
echo "$buffer" > /tmp/basicstation/"$cred".key
config_get buffer "$section" crt
[ -f "$buffer" ] && cp "$buffer" /tmp/basicstation/"$cred".crt
elif [ "$mode" = 'serverAndClientToken' ]; then
config_get buffer "$section" token
echo "$buffer" > /tmp/basicstation/"$cred".key
fi
if [ "$cred" = "tc" ]; then
uri="wss://${addr}:${port}"
else
uri="https://${addr}:${port}"
fi
else
if [ "$cred" = "tc" ]; then
uri="ws://${addr}:${port}"
else
uri="http://${addr}:${port}"
fi
fi
echo "$uri" > /tmp/basicstation/"$cred".uri
}
process_config() {
. /usr/share/libubox/jshn.sh
json_init
config_load basicstation
config_foreach parse_sx130x sx130x
config_foreach parse_station station
json_dump -i > /tmp/basicstation/station.conf
config_foreach parse_auth auth
}
service_triggers() {
procd_add_reload_trigger "basicstation"
}
start_service() {
rm -rf /tmp/basicstation/
mkdir -p /tmp/basicstation/
process_config
procd_open_instance
procd_set_param command /usr/bin/station
procd_append_param command --home /tmp/basicstation/
procd_append_param command --force
procd_set_param respawn
procd_close_instance
}
reload_service() {
restart "$@"
}

View File

@ -0,0 +1,24 @@
From ca1eb77bf89697e1bacbb21ed7aae8b5134a7bf5 Mon Sep 17 00:00:00 2001
From: Marcus Schref <mschref@web.de>
Date: Mon, 22 Aug 2022 10:13:52 +0200
Subject: [PATCH] basicstation: include sys/time.h
Change time.h include directory to add compatibility with musl and fix
compilation error
Signed-off-by: Marcus Schref <mschref@web.de>
---
src/aio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/aio.c
+++ b/src/aio.c
@@ -27,7 +27,7 @@
*/
#include <unistd.h>
-#include <time.h>
+#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
#include "rt.h"

View File

@ -0,0 +1,86 @@
cmake_minimum_required(VERSION 3.18.4)
project(basicstation)
add_compile_definitions(CFG_linux)
add_compile_definitions(CFG_lgw1)
add_compile_definitions(CFG_sx1302)
add_compile_definitions(CFG_ral_lgw)
add_compile_definitions(CFG_no_leds)
add_compile_definitions(CFG_argp)
add_compile_definitions(CFG_platform="linux")
add_compile_definitions(CFG_bdate=${PKG_SOURCE_DATE})
file(STRINGS "VERSION.txt" VERSION_NUMBER)
add_compile_definitions(CFG_version="${VERSION_NUMBER}")
include_directories(src)
include_directories(src-linux)
find_path(SX1302_HAL_INCLUDE_DIR NAMES lgw/loragw_hal.h)
find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/x509.h)
find_library(SX1302_HAL_LIBRARY NAMES libloragw.a PATH /usr/lib/)
find_library(TINYMT32_LIBRARY NAMES libtinymt32.a PATH /usr/lib/)
find_library(MBEDTLS_LIBRARY NAMES libmbedtls.a PATH /usr/lib/)
find_library(MBEDCRYPTO_LIBRARY NAMES libmbedcrypto.a PATH /usr/lib/)
find_library(MBEDX509_LIBRARY NAMES libmbedx509.a PATH /usr/lib/)
set(basicstation_SOURCE_FILES
src/aio.c
src/argp.c
src/crc32.c
src/cups.c
src/flashsim.c
src/fs.c
src/genkwcrcs.c
src/lgwsim.c
src/log.c
src/lora.c
src/net.c
src/ral.c
src/ral_lgw.c
src/ral_lgw2.c
src/rt.c
src/s2conf.c
src/s2e.c
src/selftest_fs.c
src/selftest_lora.c
src/selftest_rt.c
src/selftest_ujdec.c
src/selftest_ujenc.c
src/selftest_xprintf.c
src/selftest_xq.c
src/selftests.c
src/sx1301v2conf.c
src/sx130xconf.c
src/sys.c
src/sys.h
src/tc.c
src/timesync.c
src/tls.c
src/uj.c
src/web.c
src/xq.c
src-linux/cmdfifo.c
src-linux/commands.c
src-linux/gps.c
src-linux/leds.c
src-linux/ral_master.c
src-linux/ral_slave.c
src-linux/rmtsh.c
src-linux/sys_linux.c
src-linux/sys_log.c
src-linux/web_linux.c)
add_library(s2core ${basicstation_SOURCE_FILES})
target_include_directories(s2core PRIVATE ${SX1302_HAL_INCLUDE_DIR})
target_include_directories(s2core PRIVATE ${MBEDTLS_INCLUDE_DIR})
target_link_libraries(s2core ${SX1302_HAL_LIBRARY} ${TINYMT32_LIBRARY} m)
target_link_libraries(s2core ${MBEDTLS_LIBRARY})
target_link_libraries(s2core ${MBEDCRYPTO_LIBRARY})
target_link_libraries(s2core ${MBEDX509_LIBRARY})
add_executable(station src-linux/station_main.c)
target_link_libraries(station s2core)
install(TARGETS station RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

3
net/basicstation/test.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
station --version 2>&1 | grep "$2"

View File

@ -0,0 +1,87 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=external-protocol
PKG_VERSION:=20231119
PKG_RELEASE:=1
PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
include $(INCLUDE_DIR)/package.mk
define Package/external-protocol
SECTION:=net
CATEGORY:=Network
TITLE:=externally managed protocol
PKGARCH:=all
endef
define Package/external-protocol/description
external protocol is a general protocol for assisting
setup of many virtual devices that lack proper
protocol support in openwrt. Such as netavark, cni and
netbird for example. External protocol is supposed
to be managed with external software, not directly.
external protocol works automaticly on the background
and sets up netifd details when interface comes up or
goes down. This allows one to easily add interface to
a firewall zone.
as a example use case, podman, with network where it's
internal firewall and portmapper are disabled, control
of firewalling, whether it was exposing ports or
limiting/accepting access between networks, such as
lan can be made through openwrt's own firewalling
configuration if you used external protocol.
podman example configuration could be as following:
- lan network: 10.0.0.0/16 (255.255.0.0)
- container network: 10.129.0.1/24 (255.255.255.0)
Add a network configuration for your container network
using external protocol. Then create firewall zone for it.
You could create a new container/pod with static ip
address 10.129.0.2 (as 10.129.0.1 as container network's
gateway).
Easily define permissions so that local networks can
connect to container network, but not the other way around.
Also you want to allow forwarding from/to wan.
Now, as container cannot access local dns, make a rule for
your firewall to accept connections from container network
to port 53 (dns).
Now all you have to do, is make redirects to your firewall
and point them to 10.129.0.2 and connections from wan are
redirectered to containers/pods.
external protocol also works for other applications as
well that are using veth/tun/etc devices and don't have
a hand-tailored protocol available, such as vpn service
netbird.
Protocol has 3 settings: device, searchdomain and delay.
Sometimes polling interfaces takes some time, and in
that case you might want to add few seconds to delay.
Otherwise, it can be excluded from configuration.
Option for searchdomain is also completely optional.
package was previously known as cni protocol but as
it can be used on so many other things, naming became
mis-leading and it was renamed to external protocol.
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/external-protocol/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/external.sh $(1)/lib/netifd/proto/external.sh
endef
$(eval $(call BuildPackage,external-protocol))

View File

@ -0,0 +1,141 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_external_init_config() {
no_device=0
available=0
proto_config_add_string "device:device"
proto_config_add_string "searchdomain"
proto_config_add_int "delay"
}
proto_external_setup() {
local cfg="$1"
local iface="$2"
local device searchdomain delay
json_get_vars device searchdomain delay
[ -n "$device" ] || {
echo "External protocol interface is not specified"
proto_notify_error "$cfg" NO_DEVICE
proto_set_available "$cfg" 0
return 1
}
[ -n "$delay" ] && sleep "$delay"
[ -L "/sys/class/net/${iface}" ] || {
echo "External protocol interface $iface is not present"
proto_notify_error "$cfg" NO_DEVICE
proto_set_available "$cfg" 0
return 1
}
IP4ADDRS=
IP6ADDRS=
local addresses="$(ip -json address list dev "$iface")"
json_init
json_load "{\"addresses\":${addresses}}"
if json_is_a addresses array; then
json_select addresses
json_select 1
if json_is_a addr_info array; then
json_select addr_info
local i=1
while json_is_a ${i} object; do
json_select ${i}
json_get_vars scope family local prefixlen broadcast
if [ "${scope}" == "global" ]; then
case "${family}" in
inet)
append IP4ADDRS "$local/$prefixlen/$broadcast/"
;;
inet6)
append IP6ADDRS "$local/$prefixlen/$broadcast///"
;;
esac
fi
json_select ..
i=$(( i + 1 ))
done
fi
fi
IP4ROUTES=
IP6ROUTES=
local routes="$(ip -json route list dev "$iface")"
json_init
json_load "{\"routes\":${routes}}"
if json_is_a routes array;then
json_select routes
local i=1
while json_is_a ${i} object; do
json_select ${i}
json_get_vars dst gateway metric prefsrc
case "${dst}" in
*:*/*)
append IP6ROUTES "$dst/$gateway/$metric///$prefsrc"
;;
*.*/*)
append IP4ROUTES "$dst/$gateway/$metric///$prefsrc"
;;
*:*)
append IP6ROUTES "$dst/128/$gateway/$metric///$prefsrc"
;;
*.*)
append IP4ROUTES "$dst/32/$gateway/$metric///$prefsrc"
;;
esac
json_select ..
i=$(( i + 1 ))
done
fi
[ -z "${IP4ADDRS}" -a -z "${IP6ADDRS}" ] && {
echo "interface $iface does not have ip address"
proto_notify_error "$cfg" NO_IPADDRESS
return 1
}
proto_init_update "$iface" 1
PROTO_IPADDR="${IP4ADDRS}"
PROTO_IP6ADDR="${IP6ADDRS}"
PROTO_ROUTE="${IP4ROUTES}"
PROTO_ROUTE6="${IP6ROUTES}"
[ -n "$searchdomain" ] && proto_add_dns_search "$searchdomain"
echo "$iface is up"
proto_send_update "$cfg"
}
proto_external_teardown() {
local cfg="$1"
return 0
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol external
}

View File

@ -66,11 +66,30 @@ config KEEPALIVED_IPTABLES
depends on KEEPALIVED_VRRP
bool
default y
select KEEPALIVED_IP6TABLES
prompt "Enable iptables for VIP filtering"
help
Builds support for using iptables/ipsets for filtering packets
to VIPs
config KEEPALIVED_IP6TABLES
depends on KEEPALIVED_VRRP && KEEPALIVED_IPTABLES && IPV6
bool
default y
prompt "Enable ip6tables for VIP filtering"
help
Builds support for using ip6tables/ipsets for filtering packets
to VIPs
config KEEPALIVED_NFTABLES
depends on KEEPALIVED_VRRP
bool
default y
prompt "Enable nftables for VIP filtering"
help
Builds support for using nftables for filtering packets
to VIPs
config KEEPALIVED_SNMP_VRRP
depends on KEEPALIVED_VRRP
bool
@ -111,14 +130,6 @@ config KEEPALIVED_DBUS
help
Builds support for using DBus with VRRP
config KEEPALIVED_JSON
depends on KEEPALIVED_VRRP
bool
default n
prompt "Enable JSON support with VRRP"
help
Builds support for using JSON output for VRRP
config KEEPALIVED_VRRP_AUTH
depends on KEEPALIVED_VRRP
bool

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=keepalived
PKG_VERSION:=2.2.7
PKG_RELEASE:=$(AUTORELEASE)
PKG_RELEASE:=10
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.keepalived.org/software
@ -21,20 +21,20 @@ PKG_LICENSE_FILES:=COPYING
PKG_MAINTAINER:=Ben Kelly <ben@benjii.net> \
Florian Eckert <fe@dev.tdt.de>
PKG_CONFIG_DEPENDS += \
KEEPALIVED_VRRP \
KEEPALIVED_LVS \
KEEPALIVED_IPTABLES \
KEEPALIVED_BFD \
KEEPALIVED_SNMP_VRRP \
KEEPALIVED_SNMP_CHECKER \
KEEPALIVED_SNMP_RFC2 \
KEEPALIVED_SNMP_RFC3 \
KEEPALIVED_SNMP_REPLY_V3_FOR_V2 \
KEEPALIVED_DBUS \
KEEPALIVED_JSON \
KEEPALIVED_ROUTES \
IPV6
PKG_CONFIG_DEPENDS:= \
CONFIG_KEEPALIVED_NFTABLES \
CONFIG_KEEPALIVED_VRRP \
CONFIG_KEEPALIVED_LVS \
CONFIG_KEEPALIVED_IPTABLES \
CONFIG_KEEPALIVED_BFD \
CONFIG_KEEPALIVED_SNMP_VRRP \
CONFIG_KEEPALIVED_SNMP_CHECKER \
CONFIG_KEEPALIVED_SNMP_RFC2 \
CONFIG_KEEPALIVED_SNMP_RFC3 \
CONFIG_KEEPALIVED_SNMP_REPLY_V3_FOR_V2 \
CONFIG_KEEPALIVED_DBUS \
CONFIG_KEEPALIVED_ROUTES \
CONFIG_IPV6
PKG_INSTALL:=1
@ -45,11 +45,6 @@ define Package/keepalived/config
source "$(SOURCE)/Config.in"
endef
# specifying +(IPV6&&KEEPALIVED_IPTABLES) in the DEPENDS definition doesn't work
ifeq ($(CONFIG_KEEPALIVED_IPTABLES)$(CONFIG_IPV6),yy)
KEEPALIVED_DEPENDS_LIBIP6TC=+libip6tc
endif
# The +kmod-nf-ipvs line should be +KEEPALIVED_LVS:kmod-nf-ipvs,
# but make menuconfig then reports :error: recursive dependency detected!
# !!FIXME DEPENDS:= +KEEPALIVED_LVS:kmod-nf-ipvs
@ -62,16 +57,18 @@ define Package/keepalived
+libnl-genl \
+libmagic \
+libkmod \
+kmod-nf-ipvs \
+libjson-c \
+KEEPALIVED_NFTABLES:libnftnl \
+KEEPALIVED_VRRP:kmod-macvlan \
+KEEPALIVED_VRRP:libnl-route \
+KEEPALIVED_VRRP:libnfnetlink \
+KEEPALIVED_SHA1:libopenssl \
+KEEPALIVED_IPTABLES:libip4tc \
$(KEEPALIVED_DEPENDS_LIBIP6TC) \
+KEEPALIVED_IP6TABLES:libip6tc \
+KEEPALIVED_IPTABLES:libxtables \
+KEEPALIVED_IPTABLES:libipset \
+(KEEPALIVED_SNMP_VRRP||KEEPALIVED_SNMP_CHECKER||KEEPALIVED_SNMP_RFC2||KEEPALIVED_SNMP_RFC3):libnetsnmp \
+KEEPALIVED_JSON:libjson-c \
+KEEPALIVED_DBUS:glib2
endef
@ -86,8 +83,8 @@ define Package/keepalived/conffiles
endef
CONFIGURE_ARGS+= \
--enable-json \
--with-init=SYSV \
--disable-nftables \
--disable-track-process \
--runstatedir="/var/run"
@ -113,6 +110,12 @@ endif
ifeq ($(CONFIG_KEEPALIVED_VRRP),y)
ifeq ($(CONFIG_KEEPALIVED_NFTABLES),)
CONFIGURE_ARGS += \
--disable-nftables
endif
ifeq ($(CONFIG_KEEPALIVED_IPTABLES),)
CONFIGURE_ARGS += \
--disable-iptables
@ -145,11 +148,6 @@ CONFIGURE_ARGS += \
endif
endif # CONFIG_KEEPALIVED_SNMP_RFC3
ifeq ($(CONFIG_KEEPALIVED_JSON),y)
CONFIGURE_ARGS += \
--enable-json
endif
ifeq ($(CONFIG_KEEPALIVED_VRRP_AUTH),)
CONFIGURE_ARGS += \
--disable-vrrp-auth
@ -239,6 +237,10 @@ endif
$(INSTALL_DATA) ./files/hotplug-user \
$(1)/etc/hotplug.d/keepalived/01-user
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
$(INSTALL_BIN) ./files/usr/libexec/rpcd/keepalived \
$(1)/usr/libexec/rpcd/keepalived
ifneq ($(CONFIG_KEEPALIVED_SNMP_VRRP)$(CONFIG_KEEPALIVED_SNMP_CHECKER)$(CONFIG_KEEPALIVED_SNMP_RFC2)$(CONFIG_KEEPALIVED_SNMP_RFC3),)
$(INSTALL_DIR) $(1)/usr/share/snmp/mibs
endif
@ -272,4 +274,103 @@ endif
endef
define Package/keepalived-sync
SECTION:=net
CATEGORY:=Network
TITLE:=Keepalived Master and Backup Synchronization
DEPENDS:= +keepalived +rsync +inotifywait +sudo +coreutils-timeout
endef
define Package/keepalived-sync/description
Keepalived HA with Master to Backup files and data Synchronization
endef
define Package/keepalived-sync/conffiles
/etc/keepalived/scripts
/etc/keepalived/keys
endef
define Package/keepalived-sync/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/keepalived-inotify \
$(1)/etc/init.d/keepalived-inotify
$(INSTALL_DIR) $(1)/usr/share/keepalived/scripts
$(INSTALL_BIN) ./files/usr/share/keepalived/scripts/rsync.sh \
$(1)/usr/share/keepalived/scripts/rsync.sh
$(INSTALL_DIR) $(1)/etc/keepalived/scripts
$(LN) /usr/share/keepalived/scripts/rsync.sh \
$(1)/etc/keepalived/scripts/rsync.sh
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./files/usr/bin/keepalived-rsync-inotify \
$(1)/usr/bin/keepalived-rsync-inotify
$(INSTALL_DIR) $(1)/lib/functions/keepalived
$(INSTALL_DATA) ./files/lib/functions/keepalived/hotplug.sh \
$(1)/lib/functions/keepalived/hotplug.sh
$(INSTALL_DATA) ./files/lib/functions/keepalived/common.sh \
$(1)/lib/functions/keepalived/common.sh
$(INSTALL_DIR) $(1)/usr/libexec/keepalived/rpc
$(INSTALL_DATA) ./files/usr/libexec/keepalived/rpc/sync.sh \
$(1)/usr/libexec/keepalived/rpc/sync.sh
$(INSTALL_DIR) $(1)/etc/hotplug.d/keepalived
$(CP) ./files/etc/hotplug.d/keepalived/* \
$(1)/etc/hotplug.d/keepalived
endef
USER=keepalived
USER_ID=60001
USER_HOME=/usr/share/keepalived/rsync
SUDO_DIR=/etc/sudoers.d
SUDO_FILE=$(SUDO_DIR)/$(USER)
KEYS_DIR=/etc/keepalived/keys
define Package/keepalived-sync/postinst
#!/bin/sh
mkdir -p "$${IPKG_INSTROOT}/etc/uci-defaults"
DEFAULT_SCRIPT="$${IPKG_INSTROOT}/etc/uci-defaults/99-keepalived-sync"
cat << EOF > $${DEFAULT_SCRIPT}
#!/bin/sh
. /lib/functions.sh
mkdir -p $(KEYS_DIR)
group_add "$(USER)" "$(USER_ID)"
user_add "$(USER)" "$(USER_ID)" "$(USER_ID)" "$(USER)" "$(USER_HOME)" "/bin/ash"
mkdir -m 700 -p "$(USER_HOME)"
mkdir -m 700 -p "$(USER_HOME)/.ssh"
chown "$(USER)":"$(USER)" "$(USER_HOME)" -R
[ ! -d "$(SUDO_DIR)" ] && mkdir "$(SUDO_DIR)"
echo "$(USER) ALL= NOPASSWD:/usr/bin/rsync" > "$(SUDO_FILE)"
EOF
[ -z "$${IPKG_INSTROOT}" ] && [ -f "$${DEFAULT_SCRIPT}" ] && sh "$${DEFAULT_SCRIPT}"
exit 0
endef
define Package/keepalived-sync/postrm
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] && exit 0
[ -d "$(KEYS_DIR)" ] && rm -rf "$(KEYS_DIR)"
[ -d "$(USER_HOME)" ] && rm -rf "$(USER_HOME)"
[ -f "$(SUDO_FILE)" ] && rm -f "$(SUDO_FILE)"
sed -i -e "/^$(USER):/d" /etc/passwd /etc/shadow /etc/group
exit 0
endef
$(eval $(call BuildPackage,keepalived))
$(eval $(call BuildPackage,keepalived-sync))

View File

@ -0,0 +1,12 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name rpcd
set_reload_if_sync
add_sync_file /etc/config/rpcd
keepalived_hotplug

View File

@ -0,0 +1,12 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name system
set_reload_if_sync
add_sync_file /etc/config/system
keepalived_hotplug

View File

@ -0,0 +1,12 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name ucitrack
set_reload_if_sync
add_sync_file /etc/config/ucitrack
keepalived_hotplug

View File

@ -0,0 +1,12 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name firewall
set_reload_if_sync
add_sync_file /etc/config/firewall
keepalived_hotplug

View File

@ -0,0 +1,15 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name dnsmasq
set_restart_if_master
set_stop_if_backup
set_reload_if_sync
add_sync_file /etc/config/dhcp
add_sync_file /tmp/dhcp.leases
keepalived_hotplug

View File

@ -0,0 +1,15 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name dropbear
set_reload_if_backup
set_reload_if_sync
add_sync_file /etc/config/dropbear
add_sync_file /etc/dropbear/dropbear_ed25519_host_key
add_sync_file /etc/dropbear/dropbear_rsa_host_key
keepalived_hotplug

View File

@ -0,0 +1,14 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
set_service_name uhttpd
set_restart_if_sync
add_sync_file /etc/config/uhttpd
add_sync_file /etc/uhttpd.crt
add_sync_file /etc/uhttpd.key
keepalived_hotplug

View File

@ -0,0 +1,8 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
add_sync_file /etc/config/luci
keepalived_hotplug

View File

@ -0,0 +1,18 @@
#!/bin/sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/hotplug.sh
add_sync_file /etc/group
add_sync_file /etc/hosts
add_sync_file /etc/inittab
add_sync_file /etc/passwd
add_sync_file /etc/rc.local
add_sync_file /etc/profile
add_sync_file /etc/shadow
add_sync_file /etc/shell
add_sync_file /etc/shinit
add_sync_file /etc/sysctl.conf
add_sync_file /tmp/dhcp.leases
keepalived_hotplug

View File

@ -0,0 +1,65 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
PROG="/usr/bin/keepalived-rsync-inotify"
KEEPALIVED_USER=keepalived
KEEPALIVED_HOME=$(awk -F: "/^$KEEPALIVED_USER/{print \$6}" /etc/passwd)
start_instance() {
local cfg=$1
local vrrp_instance=$2
local peer=$3
config_get name $cfg name
[ -z "$name" ] && return
[ "$name" != "$peer" ] && return
config_get sync $cfg sync 0
[ "$sync" = "0" ] && return
config_get sync_mode $cfg sync_mode
[ "$sync_mode" != "receive" ] && return
config_get sync_dir $cfg sync_dir $KEEPALIVED_HOME
[ -z "$sync_dir" ] && return
[ ! -d "$sync_dir" ] && mkdir -m 755 -p "$sync_dir"
procd_open_instance "$name"
procd_set_param command /bin/sh "$PROG" "$vrrp_instance" "$name" "$sync_dir"
procd_set_param pidfile /var/run/keepalived-inotify-$name.pid
procd_close_instance
}
process_unicast_peer() {
local peer=$1
local vrrp_instance=$2
config_foreach start_instance peer "$vrrp_instance" "$peer"
}
process_vrrp_instance() {
local cfg=$1
local peer_instance=$2
local name unicast_peer
config_get name $cfg name
config_get unicast_peer $cfg unicast_peer
if [ -n "$peer_instance" ]; then
list_contains unicast_peer "$peer_instance" || return
process_unicast_peer "$peer_instance" "$name"
else
config_list_foreach $cfg unicast_peer process_unicast_peer "$name"
fi
}
start_service() {
local peer_instance=$1
config_load keepalived
config_foreach process_vrrp_instance vrrp_instance "$peer_instance"
}

View File

@ -100,6 +100,7 @@ globals() {
printf '%bscript_user root\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
printf '%benable_script_security\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
printf '%bprocess_names\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
config_get notification_email "$1" notification_email
print_list_indent notification_email
@ -126,6 +127,7 @@ print_ipaddress_indent() {
config_get address "$section" address
config_get device "$section" device
config_get scope "$section" scope
config_get label_suffix "$section" label_suffix vip
# Default indent
[ -z "$indent" ] && indent="$INDENT_1"
@ -137,7 +139,7 @@ print_ipaddress_indent() {
printf '%b%s' "$indent" "$address" >> "$KEEPALIVED_CONF"
else
# Add IP address/netmask and device
printf '%b%s dev %s' "$indent" "$address" "$device">> "$KEEPALIVED_CONF"
printf '%b%s dev %s label %s' "$indent" "$address" "$device" "$device:$label_suffix" >> "$KEEPALIVED_CONF"
# Add scope
[ -n "$scope" ] && printf ' scope %s' "$scope" >> "$KEEPALIVED_CONF"
fi
@ -196,7 +198,27 @@ print_route_indent() {
# Add table
[ -n "$table" ] && printf ' table %s' "$table" >> "$KEEPALIVED_CONF"
printf '\n' >> "$KEEPALIVED_CONF"
}
print_track_script_indent() {
local section="$1"
local curr_track_elem="$2"
local indent="$3"
local name value weight direction
config_get name "$section" name
[ "$name" != "$curr_track_elem" ] && return 0
config_get value "$section" value
config_get weight "$section" weight
config_get direction "$section" direction
[ -z "$value" ] && return 0
[ "$direction" != "reverse" ] && [ "$direction" != "noreverse" ] && unset direction
printf '%b%s' "$indent" "$value" >> "$KEEPALIVED_CONF"
[ -n "$weight" ] && printf ' weight %s' "$weight ${direction:+${direction}}" >> "$KEEPALIVED_CONF"
printf '\n' >> "$KEEPALIVED_CONF"
}
print_track_elem_indent() {
@ -218,6 +240,37 @@ print_track_elem_indent() {
printf '\n' >> "$KEEPALIVED_CONF"
}
print_track_bfd_indent() {
local section="$1"
local curr_track_elem="$2"
local indent="$3"
local name
config_get name "$section" name
[ "$name" != "$curr_track_elem" ] && return 0
config_get weight "$section" weight
printf '%b%s' "$indent" "$name" >> "$KEEPALIVED_CONF"
[ -n "$weight" ] && printf ' weight %s' "$weight" >> "$KEEPALIVED_CONF"
printf '\n' >> "$KEEPALIVED_CONF"
}
print_unicast_peer_indent() {
local section="$1"
local curr_track_elem="$2"
local indent="$3"
local name address
config_get name "$section" name
[ "$name" != "$curr_track_elem" ] && return 0
config_get address "$section" address
[ -z "$address" ] && return 0
printf '%b%s\n' "${indent}" "$address">> "$KEEPALIVED_CONF"
}
static_routes() {
local route
config_get route "$1" route
@ -333,7 +386,7 @@ vrrp_instance() {
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for t in $optval; do
printf '%b%s\n' "${INDENT_2}" "$optval" >> "$KEEPALIVED_CONF"
config_foreach print_track_script_indent track_script "$t" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
@ -350,10 +403,28 @@ vrrp_instance() {
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle track_bfd lists
for opt in track_bfd; do
config_get "$opt" "$1" "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for t in $optval; do
config_foreach print_track_bfd_indent bfd_instance "$t" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle simple lists of strings (with no spaces in between)
for opt in unicast_peer; do
config_get "$opt" "$1" "$opt"
print_list_indent "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for t in $optval; do
config_foreach print_unicast_peer_indent peer "$t" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
unset optval
@ -373,6 +444,19 @@ vrrp_script() {
config_section_close
}
bfd_instance() {
local name
config_get name "$1" name
[ -z "$name" ] && return 0
config_section_open "bfd_instance" "$name"
print_elems_indent "$1" "$INDENT_1" neighbor_ip source_ip min_rx min_tx idle_tx hoplimit max_hops
config_section_close
}
url() {
local url="$2"
@ -517,6 +601,7 @@ process_config() {
config_section_close
config_foreach_wrapper vrrp_script
config_foreach_wrapper bfd_instance
config_foreach_wrapper vrrp_sync_group
config_foreach_wrapper vrrp_instance
config_foreach_wrapper virtual_server

View File

@ -0,0 +1,47 @@
#!/bin/sh
# shellcheck disable=SC2039
__FILE__="$(basename "$0")"
KEEPALIVED_USER=keepalived
KEEPALIVED_DEBUG=0
__function__() {
type "$1" > /dev/null 2>&1
}
log() {
local facility=$1
shift
logger -t "${__FILE__}[$$]" -p "$facility" "$*"
}
log_info() {
log info "$*"
}
log_debug() {
[ "$KEEPALIVED_DEBUG" = "0" ] && return
log debug "$*"
}
log_notice() {
log notice "$*"
}
log_warn() {
log warn "$*"
}
log_err() {
log err "$*"
}
get_rsync_user() {
echo "$KEEPALIVED_USER"
}
get_rsync_user_home() {
awk -F: "/^$KEEPALIVED_USER/{print \$6}" /etc/passwd
}

View File

@ -0,0 +1,257 @@
#!/bin/sh
# shellcheck disable=SC2039
# shellcheck source=/dev/null
. /lib/functions/keepalived/common.sh
set_var() {
export "$1=$2"
}
get_var() {
eval echo "\"\${${1}}\""
}
get_var_flag() {
local value
value=$(get_var "$1")
value=${value:-0}
[ "$value" = "0" ] && return 1
return 0
}
_service() {
[ -z "$SERVICE_NAME" ] && return
local rc="/etc/init.d/$SERVICE_NAME"
[ ! -x "$rc" ] && return
case $1 in
start) $rc running || $rc start ;;
stop) $rc running && $rc stop ;;
reload)
if $rc running; then
$rc reload
else
$rc start
fi
;;
restart)
if $rc running; then
$rc restart
else
$rc start
fi
;;
esac
}
_start_service() {
_service start
}
_stop_service() {
_service stop
}
_restart_service() {
_service restart
}
_reload_service() {
_service reload
}
set_service_name() {
set_var SERVICE_NAME "$1"
}
add_sync_file() {
append SYNC_FILES_LIST "$1"
}
is_sync_file() {
list_contains SYNC_FILES_LIST "$1"
}
set_update_target() {
set_var UPDATE_TARGET "${1:-1}"
}
get_update_target() {
get_var UPDATE_TARGET
}
unset_update_target() {
set_var UPDATE_TARGET
}
is_update_target() {
get_var_flag UPDATE_TARGET
}
set_master_cb() {
set_var MASTER_CB "$1"
}
get_master_cb() {
get_var MASTER_CB
}
set_backup_cb() {
set_var BACKUP_CB "$1"
}
get_backup_cb() {
get_var BACKUP_CB
}
set_fault_cb() {
set_var FAULT_CB "$1"
}
get_fault_cb() {
get_var FAULT_CB
}
set_sync_cb() {
set_var SYNC_CB "$1"
}
get_sync_cb() {
get_var SYNC_CB
}
set_reload_if_master() {
set_var NOTIFY_MASTER_RELOAD 1
}
master_and_reload() {
get_var_flag NOTIFY_MASTER_RELOAD
}
set_restart_if_master() {
set_var NOTIFY_MASTER_RESTART 1
}
master_and_restart() {
get_var_flag NOTIFY_MASTER_RESTART
}
set_reload_if_backup() {
set_var NOTIFY_BACKUP_RELOAD 1
}
backup_and_reload() {
get_var_flag NOTIFY_BACKUP_RELOAD
}
set_stop_if_backup() {
set_var NOTIFY_BACKUP_STOP 1
}
backup_and_stop() {
get_var_flag NOTIFY_BACKUP_STOP 1
}
set_reload_if_sync() {
set_var NOTIFY_SYNC_RELOAD "${1:-1}"
}
get_reload_if_sync() {
get_var NOTIFY_SYNC_RELOAD
}
sync_and_reload() {
get_var_flag NOTIFY_SYNC_RELOAD
}
set_restart_if_sync() {
set_var NOTIFY_SYNC_RESTART 1
}
sync_and_restart() {
get_var_flag NOTIFY_SYNC_RESTART
}
_notify_master() {
if master_and_reload; then
log_debug "reload service $SERVICE_NAME"
_reload_service
elif master_and_restart; then
log_debug "restart service $SERVICE_NAME"
_restart_service
fi
}
_notify_backup() {
if backup_and_stop; then
log_debug "stop service $SERVICE_NAME"
_stop_service
elif backup_and_reload; then
log_debug "restart service $SERVICE_NAME"
_restart_service
fi
}
_notify_fault() {
return 0
}
_notify_sync() {
[ -z "$RSYNC_SOURCE" ] && return
[ -z "$RSYNC_TARGET" ] && return
if ! is_update_target; then
log_notice "skip $RSYNC_TARGET. Update target not set. To set use \"set_update_target 1\""
return
fi
is_sync_file "$RSYNC_TARGET" || return
if ! cp -a "$RSYNC_SOURCE" "$RSYNC_TARGET"; then
log_err "can not copy $RSYNC_SOURCE => $RSYNC_TARGET"
return
fi
log_debug "updated $RSYNC_SOURCE to $RSYNC_TARGET"
if sync_and_reload; then
log_debug "reload service $SERVICE_NAME"
_reload_service
elif sync_and_restart; then
log_debug "restart service $SERVICE_NAME"
_restart_service
fi
}
call_cb() {
[ $# -eq 0 ] && return
if __function__ "$1"; then
log_debug "calling function \"$1\""
"$1"
else
log_err "function \"$1\" not defined"
fi
}
keepalived_hotplug() {
[ -z "$(get_master_cb)" ] && set_master_cb _notify_master
[ -z "$(get_backup_cb)" ] && set_backup_cb _notify_backup
[ -z "$(get_fault_cb)" ] && set_fault_cb _notify_fault
[ -z "$(get_sync_cb)" ] && set_sync_cb _notify_sync
[ -z "$(get_update_target)" ] && set_update_target "$@"
[ -z "$(get_reload_if_sync)" ] && set_reload_if_sync "$@"
case $ACTION in
NOTIFY_MASTER) call_cb "$(get_master_cb)" ;;
NOTIFY_BACKUP) call_cb "$(get_backup_cb)" ;;
NOTIFY_FAULT) call_cb "$(get_fault_cb)" ;;
NOTIFY_SYNC) call_cb "$(get_sync_cb)" ;;
esac
}

View File

@ -0,0 +1,54 @@
#!/bin/sh
# shellcheck shell=ash
# shellcheck source=/dev/null
. /lib/functions/keepalived/common.sh
if [ $# -lt 3 ]; then
echo "$0 <vrrp_instance> <peer> <rsync_dir>"
exit 1
fi
VRRP_INSTANCE=$1
PEER=$2
RSYNC_DIR=$3
INOTIFY_ACTIONS="create,delete,modify,move,moved_to,moved_from"
INOTIFY_PID=""
TMP_DIR=/tmp/keepalived
FIFO_FILE="$TMP_DIR"/inotifywait-$PEER.fifo
daemonize_inotifywait() {
/usr/bin/inotifywait -q -r --exclude '/\..+' -o "$FIFO_FILE" -m "$RSYNC_DIR" -e ${INOTIFY_ACTIONS} 2> /dev/null &
INOTIFY_PID="$!"
}
main() {
local inotify_action inotify_dir inotify_file
local source_file target_file
[ ! -d "$TMP_DIR" ] && mkdir "$TMP_DIR"
mkfifo "${FIFO_FILE}" || exit 1
daemonize_inotifywait
while read -r inotify_dir inotify_action inotify_file; do
source_file="${inotify_dir}${inotify_file}"
target_file=$(echo "${inotify_dir}" | sed -e "s:${RSYNC_DIR}::g")"${inotify_file}"
log_debug "received $target_file ($inotify_action) in $source_file"
ACTION=NOTIFY_SYNC TYPE=peer NAME=$PEER INSTANCE=$VRRP_INSTANCE \
RSYNC_SOURCE="${source_file}" RSYNC_TARGET="${target_file}" \
/sbin/hotplug-call keepalived
done < "$FIFO_FILE"
}
TRAP() {
[ -n "$INOTIFY_PID" ] && kill "$INOTIFY_PID"
[ -e "$FIFO_FILE" ] && rm -f "$FIFO_FILE"
}
trap TRAP TERM INT
main "$@"

View File

@ -0,0 +1,59 @@
#!/bin/sh
# shellcheck disable=SC2039
# shellcheck source=/dev/null
. /usr/share/libubox/jshn.sh
# shellcheck source=/dev/null
. /lib/functions.sh
peer() {
local cfg=$1
local c_name=$2
local name last_sync_time last_sync_status
config_get name "$cfg" name
[ "$name" != "$c_name" ] && return
config_get last_sync_time "$cfg" last_sync_time 0
config_get last_sync_status "$cfg" last_sync_status NA
json_add_object unicast_peer
json_add_string name "$name"
json_add_int time "$last_sync_time"
json_add_string status "$last_sync_status"
json_close_array
}
unicast_peer() {
config_foreach peer peer "$1"
}
vrrp_instance() {
local cfg=$1
local name
config_get name "$cfg" name
json_add_object vrrp_instance
json_add_string name "$name"
json_add_array unicast_peer
config_list_foreach "$cfg" unicast_peer unicast_peer
json_close_array
json_close_object
}
rsync_status() {
config_load keepalived
json_init
json_add_array vrrp_instance
config_foreach vrrp_instance vrrp_instance
json_close_array
json_dump
}
sync_help() {
json_add_object rsync_status
json_close_object
}

View File

@ -0,0 +1,111 @@
#!/bin/sh
# shellcheck disable=SC2039
# shellcheck source=/dev/null
. /lib/functions.sh
# shellcheck source=/dev/null
. /usr/share/libubox/jshn.sh
RPC_SCRIPTS=/usr/libexec/keepalived/rpc
[ -d $RPC_SCRIPTS ] && include $RPC_SCRIPTS
__function__() {
type "$1" > /dev/null 2>&1
}
foreach_extra() {
local file obj
[ ! -d $RPC_SCRIPTS ] && return
for file in "$RPC_SCRIPTS"/*; do
obj="${file##*/}"
$1 "${obj%%.*}"
done
}
keepalived_dump() {
local stats_file pids
stats_file="/tmp/keepalived.json"
[ -f "$stats_file" ] && rm -f "$stats_file"
pids=$(pidof /usr/sbin/keepalived)
if [ -n "$pids" ]; then
kill -37 "$pids" > /dev/null 2>&1
json_load "{ \"status\" : $(cat $stats_file) }"
else
json_init
fi
json_dump
}
call_extra() {
if __function__ "$1"; then
$1
else
json_init
json_add_string error "invalid call $1"
json_dump
fi
}
call_method() {
local cmd=$1
case "$cmd" in
dump)
keepalived_dump
;;
*)
call_extra "$cmd"
;;
esac
}
list_extra() {
local arg func
arg=$1
func="${arg}_help"
if __function__ "$func"; then
$func
else
json_add_object "$arg"
json_close_object
fi
}
list_methods() {
local file
json_init
json_add_object dump
json_close_object
foreach_extra list_extra "${1}"
json_dump
}
main() {
local cmd=$1
shift
case "$cmd" in
list)
list_methods "$@"
;;
call)
call_method "$@"
;;
esac
}
main "$@"

View File

@ -0,0 +1,162 @@
#!/bin/sh
# shellcheck disable=SC2039
# shellcheck source=/dev/null
. /lib/functions.sh
# shellcheck source=/dev/null
. /lib/functions/keepalived/common.sh
RSYNC_USER=$(get_rsync_user)
RSYNC_HOME=$(get_rsync_user_home)
utc_timestamp() {
date -u +%s
}
update_last_sync_time() {
uci_revert_state keepalived "$1" last_sync_time
uci_set_state keepalived "$1" last_sync_time "$(utc_timestamp)"
}
update_last_sync_status() {
local cfg="$1"
shift
local status="$*"
uci_revert_state keepalived "$cfg" last_sync_status
uci_set_state keepalived "$cfg" last_sync_status "$status"
}
ha_sync_send() {
local cfg=$1
local address ssh_key ssh_port sync_list sync_dir sync_file count
local ssh_options ssh_remote dirs_list files_list
local changelog="/tmp/changelog"
config_get address "$cfg" address
[ -z "$address" ] && return 0
config_get ssh_port "$cfg" ssh_port 22
config_get sync_dir "$cfg" sync_dir "$RSYNC_HOME"
[ -z "$sync_dir" ] && return 0
config_get ssh_key "$cfg" ssh_key "$sync_dir"/.ssh/id_rsa
config_get sync_list "$cfg" sync_list
for sync_file in $sync_list $(sysupgrade -l); do
[ -f "$sync_file" ] && {
dir="${sync_file%/*}"
list_contains files_list "${sync_file}" || append files_list "${sync_file}"
}
[ -d "$sync_file" ] && dir="${sync_file}"
list_contains dirs_list "${sync_dir}${dir}" || append dirs_list "${sync_dir}${dir}"
done
ssh_options="-y -y -i $ssh_key -p $ssh_port"
ssh_remote="$RSYNC_USER@$address"
# shellcheck disable=SC2086
timeout 10 ssh $ssh_options $ssh_remote mkdir -m 755 -p "$dirs_list /tmp" || {
log_err "can not connect to $address. check key or connection"
update_last_sync_time "$cfg"
update_last_sync_status "$cfg" "SSH Connection Failed"
return 0
}
# shellcheck disable=SC2086
if rsync --out-format='%n' --dry-run -a --relative ${files_list} -e "ssh $ssh_options" --rsync-path="sudo rsync" "$ssh_remote":"$sync_dir" > "$changelog"; then
count=$(wc -l "$changelog")
if [ "${count%% *}" = "0" ]; then
log_debug "all files are up to date"
update_last_sync_time "$cfg"
update_last_sync_status "$cfg" "Up to Date"
return 0
fi
else
log_err "rsync dry run failed for $address"
update_last_sync_time "$cfg"
update_last_sync_status "$cfg" "Rsync Detection Failed"
return 0
fi
# shellcheck disable=SC2086
rsync -a --relative ${files_list} ${changelog} -e "ssh $ssh_options" --rsync-path="sudo rsync" "$ssh_remote":"$sync_dir" || {
log_err "rsync transfer failed for $address"
update_last_sync_time "$cfg"
update_last_sync_status "$cfg" "Rsync Transfer Failed"
}
log_info "keepalived sync is compeleted for $address"
update_last_sync_time "$cfg"
update_last_sync_status "$cfg" "Successful"
}
ha_sync_receive() {
local cfg=$1
local ssh_pubkey
local name auth_file home_dir
config_get name "$cfg" name
config_get sync_dir "$cfg" sync_dir "$RSYNC_HOME"
[ -z "$sync_dir" ] && return 0
config_get ssh_pubkey "$cfg" ssh_pubkey
[ -z "$ssh_pubkey" ] && return 0
home_dir=$sync_dir
auth_file="$home_dir/.ssh/authorized_keys"
if ! grep -q "^$ssh_pubkey$" "$auth_file" 2> /dev/null; then
log_notice "public key not found. Updating"
echo "$ssh_pubkey" > "$auth_file"
chown "$RSYNC_USER":"$RSYNC_USER" "$auth_file"
fi
/etc/init.d/keepalived-inotify enabled || /etc/init.d/keepalived-inotify enable
/etc/init.d/keepalived-inotify running "$name" || /etc/init.d/keepalived-inotify start "$name"
}
ha_sync_each_peer() {
local cfg="$1"
local c_name="$2"
local name sync sync_mode
config_get name "$cfg" name
[ "$name" != "$c_name" ] && return 0
config_get sync "$cfg" sync 0
[ "$sync" = "0" ] && return 0
config_get sync_mode "$cfg" sync_mode
[ -z "$sync_mode" ] && return 0
case "$sync_mode" in
send) ha_sync_send "$cfg" ;;
receive) ha_sync_receive "$cfg" ;;
esac
}
ha_sync_peers() {
config_foreach ha_sync_each_peer peer "$1"
}
ha_sync() {
config_list_foreach "$1" unicast_peer ha_sync_peers
}
main() {
local lockfile="/var/lock/keepalived-rsync.lock"
if ! lock -n "$lockfile" > /dev/null 2>&1; then
log_info "another process is already running"
return 1
fi
config_load keepalived
config_foreach ha_sync vrrp_instance
lock -u "$lockfile"
return 0
}
main "$@"

44
net/natmap/Makefile Normal file
View File

@ -0,0 +1,44 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=natmap
PKG_VERSION:=20240303
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/heiher/natmap/releases/download/$(PKG_VERSION)
PKG_HASH:=d7b7a1ba2fc8dbd471ed88757fa6fc7c7e2d83f9f44c8f62661e9809d386d163
PKG_MAINTAINER:=Richard Yu <yurichard3839@gmail.com>, Ray Wang <r@hev.cc>
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=License
PKG_BUILD_FLAGS:=no-mips16
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/natmap
SECTION:=net
CATEGORY:=Network
TITLE:=TCP/UDP port mapping tool for full cone NAT
URL:=https://github.com/heiher/natmap
endef
MAKE_FLAGS += REV_ID="$(PKG_VERSION)"
define Package/natmap/conffiles
/etc/config/natmap
endef
define Package/natmap/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/natmap $(1)/usr/bin/
$(INSTALL_DIR) $(1)/usr/lib/natmap/
$(INSTALL_BIN) ./files/natmap-update.sh $(1)/usr/lib/natmap/update.sh
$(INSTALL_DIR) $(1)/etc/config/
$(INSTALL_CONF) ./files/natmap.config $(1)/etc/config/natmap
$(INSTALL_DIR) $(1)/etc/init.d/
$(INSTALL_BIN) ./files/natmap.init $(1)/etc/init.d/natmap
endef
$(eval $(call BuildPackage,natmap))

View File

@ -0,0 +1,17 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
(
json_init
json_add_string ip "$1"
json_add_int port "$2"
json_add_int inner_port "$4"
json_add_string protocol "$5"
json_dump > /var/run/natmap/$PPID.json
)
[ -n "${NOTIFY_SCRIPT}" ] && {
export -n NOTIFY_SCRIPT
exec "${NOTIFY_SCRIPT}" "$@"
}

View File

@ -0,0 +1,15 @@
config natmap
option enable '0'
option family ''
option udp_mode '1'
option interface ''
option interval ''
option stun_server 'stunserver.stunprotocol.org'
option http_server 'example.com'
option port '8080'
option forward_target ''
option forward_port ''
option notify_script ''
option log_stdout '1'
option log_stderr '1'

View File

@ -0,0 +1,112 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
NAME=natmap
PROG=/usr/bin/$NAME
STATUS_PATH=/var/run/natmap
load_interfaces() {
config_get interface "$1" interface
config_get enable "$1" enable 1
[ "${enable}" = "1" ] && interfaces=" ${interface} ${interfaces}"
}
validate_section_natmap() {
uci_load_validate "${NAME}" natmap "$1" "$2" \
'enable:bool:0' \
'family:string' \
'udp_mode:bool:0' \
'interface:string' \
'interval:uinteger' \
'stun_server:host' \
'http_server:host' \
'port:port' \
'forward_target:host' \
'forward_port:port' \
'notify_script:file' \
'log_stdout:bool:1' \
'log_stderr:bool:1'
}
natmap_instance() {
[ "$2" = 0 ] || {
echo "validation failed"
return 1
}
[ "${enable}" = 0 ] && return 1
procd_open_instance "$1"
procd_set_param command "$PROG" \
${interval:+-k "$interval"} \
${stun_server:+-s "$stun_server"} \
${http_server:+-h "$http_server"} \
${port:+-b "$port"} \
[ "${family}" = ipv4 ] && procd_append_param command -4
[ "${family}" = ipv6 ] && procd_append_param command -6
[ "${udp_mode}" = 1 ] && procd_append_param command -u
[ -n "${interface}" ] && {
local ifname
network_get_device ifname "$interface" || ifname="$interface"
procd_append_param command -i "$ifname"
procd_append_param netdev "$ifname"
}
[ -n "${forward_target}" ] && procd_append_param command -t "$forward_target" -p "$forward_port"
[ -n "${notify_script}" ] && procd_set_param env "NOTIFY_SCRIPT=${notify_script}"
procd_append_param command -e /usr/lib/natmap/update.sh
procd_set_param respawn
procd_set_param stdout "${log_stdout}"
procd_set_param stderr "${log_stderr}"
procd_close_instance
}
clear_status_files() {
find "${STATUS_PATH}" -type f -print0 | xargs -0 rm -f --
}
service_triggers() {
local interfaces
procd_add_reload_trigger "${NAME}"
config_load "${NAME}"
config_foreach load_interfaces natmap
[ -n "${interfaces}" ] && {
for n in $interfaces ; do
procd_add_reload_interface_trigger $n
done
}
procd_add_validation validate_section_natmap
}
start_service() {
. /lib/functions/network.sh
mkdir -p "${STATUS_PATH}"
clear_status_files
config_load "${NAME}"
config_foreach validate_section_natmap natmap natmap_instance
}
reload_service() {
stop
start
}
service_stopped() {
clear_status_files
}

3
net/natmap/test.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
"$1" 2>&1 | grep "$2"

View File

@ -1,23 +1,24 @@
# Copyright 2021 Stan Grishin (stangri@melmac.ca)
# This is free software, licensed under the MIT License.
# Copyright 2021-2023 Stan Grishin (stangri@melmac.ca)
# This is free software, licensed under the Apache 2.0 License.
include $(TOPDIR)/rules.mk
PKG_NAME:=nebula
PKG_VERSION:=1.8.2
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/slackhq/nebula/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=203713c58d0ec8a10df2f605af791a77a33f825454911ac3a5313ced591547fd
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_LICENSE:=MIT
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE
PKG_CPE_ID:=cpe:/a:slack:nebula
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
PKG_BUILD_FLAGS:=no-mips16
GO_PKG:=github.com/slackhq/nebula
GO_PKG_BUILD_PKG:= \
@ -29,48 +30,100 @@ GO_PKG_LDFLAGS_X:=\
include $(INCLUDE_DIR)/package.mk
include ../../lang/golang/golang-package.mk
define Package/nebula
define Package/nebula/Default
SECTION:=net
CATEGORY:=Network
URL:=https://docs.openwrt.melmac.net/nebula/
endef
define Package/nebula
$(call Package/nebula/Default)
TITLE:=nebula
URL:=https://github.com/slackhq/nebula
DEPENDS:=$(GO_ARCH_DEPENDS) +kmod-tun
endef
define Package/nebula-cert
SECTION:=net
CATEGORY:=Network
$(call Package/nebula/Default)
TITLE:=nebula-cert
URL:=https://github.com/slackhq/nebula
DEPENDS:=$(GO_ARCH_DEPENDS)
endef
define Package/nebula/description
define Package/nebula-proto
$(call Package/nebula/Default)
TITLE:=nebula-proto
DEPENDS:=nebula
DEPENDS+=+!BUSYBOX_DEFAULT_AWK:gawk
DEPENDS+=+!BUSYBOX_DEFAULT_GREP:grep
DEPENDS+=+!BUSYBOX_DEFAULT_SED:sed
PKGARCH:=all
endef
define Package/nebula-service
$(call Package/nebula/Default)
TITLE:=nebula-service
DEPENDS:=nebula
DEPENDS+=+!BUSYBOX_DEFAULT_AWK:gawk
DEPENDS+=+!BUSYBOX_DEFAULT_SED:sed
CONFLICTS:=nebula-proto
PKGARCH:=all
endef
define Package/nebula/description/Default
Nebula is a scalable overlay networking tool with a focus on performance, simplicity
and security. It lets you seamlessly connect computers anywhere in the world.
endef
define Package/nebula/description
$(call Package/nebula/description/Default)
This package contains only nebula binary. Unless you want to start nebula manually,
you may want to also install *either* 'nebula-service' *or* 'nebula-proto' package.
endef
define Package/nebula-cert/description
$(call Package/nebula/description)
$(call Package/nebula/description/Default)
This package contains only nebula-cert binary.
endef
define Package/nebula-proto/description
$(call Package/nebula/description/Default)
This package contains only OpenWrt protocol/interface support for nebula.
endef
define Package/nebula-service/description
$(call Package/nebula/description/Default)
This package contains only OpenWrt-specific init.d script for nebula.
endef
define Package/nebula/conffiles
/etc/nebula/
endef
Package/nebula-cert/conffiles = $(Package/nebula/conffiles)
define Package/nebula/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/sbin $(1)/usr/share/doc/nebula $(1)/lib/upgrade/keep.d
$(INSTALL_BIN) ./files/nebula.init $(1)/etc/init.d/nebula
$(SED) "s|^\(PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/nebula
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula $(1)/usr/sbin/nebula
$(INSTALL_DATA) $(PKG_BUILD_DIR)/LICENSE $(1)/usr/share/doc/nebula/LICENSE
$(INSTALL_DATA) ./files/nebula.upgrade $(1)/lib/upgrade/keep.d/nebula
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula $(1)/usr/sbin/
endef
define Package/nebula-cert/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/doc/nebula-cert $(1)/lib/upgrade/keep.d
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula-cert $(1)/usr/sbin/nebula-cert
$(INSTALL_DATA) $(PKG_BUILD_DIR)/LICENSE $(1)/usr/share/doc/nebula-cert/LICENSE
$(INSTALL_DATA) ./files/nebula.upgrade $(1)/lib/upgrade/keep.d/nebula-cert
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula-cert $(1)/usr/sbin/
endef
define Package/nebula-proto/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/nebula.proto $(1)/lib/netifd/proto/nebula.sh
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/lib/netifd/proto/nebula.sh
endef
define Package/nebula-service/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/nebula.init $(1)/etc/init.d/nebula
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/nebula
endef
$(eval $(call GoBinPackage,nebula))
@ -78,3 +131,7 @@ $(eval $(call BuildPackage,nebula))
$(eval $(call GoBinPackage,nebula-cert))
$(eval $(call BuildPackage,nebula-cert))
$(eval $(call BuildPackage,nebula-proto))
$(eval $(call BuildPackage,nebula-service))

View File

@ -0,0 +1,3 @@
# README
README is available at [https://docs.openwrt.melmac.net/nebula/](https://docs.openwrt.melmac.net/nebula/).

View File

@ -1,52 +1,106 @@
#!/bin/sh /etc/rc.common
# Copyright 2021 Stan Grishin (stangri@melmac.net)
# shellcheck disable=SC2039
PKG_VERSION='dev-test'
# Copyright 2023 Stan Grishin (stangri@melmac.ca)
# shellcheck disable=SC3043,SC3060
# shellcheck disable=SC2034
START=80
# shellcheck disable=SC2034
USE_PROCD=1
if type extra_command 1>/dev/null 2>&1; then
extra_command 'version' 'Show version information'
else
# shellcheck disable=SC2034
EXTRA_COMMANDS='version'
fi
readonly PKG_VERSION='dev-test'
readonly packageName='nebula-service'
readonly serviceName="$packageName $PKG_VERSION"
readonly PROG=/usr/sbin/nebula
readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
extra_command 'version' 'Show version information'
version() { echo "Version: $PKG_VERSION"; }
output() {
local msg memmsg logmsg
local sharedMemoryOutput="/dev/shm/$packageName-output"
[ -t 1 ] && printf "%b" "$@"
msg="${1//$serviceName /service }";
if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then
[ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")"
logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')"
logger -t "$packageName" "$(printf "%b" "$logmsg")"
rm -f "$sharedMemoryOutput"
else
printf "%b" "$msg" >> "$sharedMemoryOutput"
fi
}
output_ok() { output "$_OK_"; }
output_okn() { output "${_OK_}\\n"; }
output_fail() { output "$_FAIL_"; }
output_failn() { output "${_FAIL_}\\n"; }
# https://gist.github.com/pkuczynski/8665367
# shellcheck disable=SC2086,SC2155
parse_yaml() {
local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_-]*' fs="$(echo @|tr @ '\034'|tr -d '\015')"
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
awk "-F$fs" '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=\"%s\"\n", "'$prefix'", vn, $2, $3);
}
}'
}
start_instance() {
local cfg="$1" port name="${1##*/}"
port="$(grep -A2 "^listen:" "$cfg" | grep "port: " | awk '{print $2}')"
procd_open_instance
procd_set_param command ${PROG} -config "${cfg}"
procd_set_param stderr 1
procd_set_param stdout 1
procd_set_param respawn
procd_open_data
json_add_array firewall
json_add_object ''
json_add_string type 'rule'
json_add_string name "Allow-$name"
json_add_string src 'wan'
json_add_string dest_port "$port"
json_add_string proto 'udp'
json_add_string target 'ACCEPT'
json_close_object
json_close_array
procd_close_data
procd_close_instance
local config_file="$1"
local yaml_listen_host yaml_listen_port
if [ ! -x "$PROG" ]; then
echo "Nebula binary not found! Please install 'nebula' package."
output_fail
return 1
fi
if [ ! -s "$config_file" ]; then
output_fail
return 1
fi
if ! eval "$(parse_yaml "$config_file" "yaml_")"; then
output_fail
return 1
else
procd_open_instance
procd_set_param command ${PROG} -config "${config_file}"
procd_set_param stderr 1
procd_set_param stdout 1
procd_set_param respawn
procd_open_data
json_add_array firewall
json_add_object ""
json_add_string type rule
json_add_string name "${config_file##*/}"
json_add_string src "*"
json_add_string dest_ip "${yaml_listen_host:-0.0.0.0}"
json_add_string dest_port "${yaml_listen_port:-4242}"
json_add_string proto udp
json_add_string target ACCEPT
json_close_object
json_close_array
procd_close_data
procd_close_instance
output_ok
fi
}
start_service() {
local f
output "Starting $packageName instances "
for f in /etc/nebula/*.yml; do
[ -s "$f" ] && start_instance "$f"
start_instance "$f"
done
output '\n'
}
service_started() { procd_set_config_changed firewall; }

View File

@ -0,0 +1,106 @@
#!/bin/sh
# Copyright 2021 Stan Grishin (stangri@melmac.ca)
# shellcheck disable=SC1091,SC2039,SC2034,SC3043
readonly PKG_VERSION='dev-test'
readonly PROG=/usr/sbin/nebula
readonly packageName='nebula-proto'
# https://github.com/openwrt/openwrt/blob/fbf1835f46addf25a752a16be40d8f5617be3112/package/network/utils/umbim/files/lib/netifd/proto/mbim.sh
[ -x "$PROG" ] || { log "Main nebula executable '/usr/sbin/nebula' not found"; exit 1; }
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
log() { logger -t "$packageName" "$*"; }
# https://gist.github.com/pkuczynski/8665367
# shellcheck disable=SC2086,SC2155
yaml_parse() {
local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_-]*' fs="$(echo @|tr @ '\034'|tr -d '\015')"
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
awk "-F$fs" '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=\"%s\"\n", "'$prefix'", vn, $2, $3);
}
}'
}
proto_nebula_init_config() {
available=1
no_device=1
proto_config_add_string "config_file"
}
proto_nebula_setup() {
local interface="$1" config_file address addresses
local yaml_listen_host yaml_listen_port yaml_tun_dev
config_load network
config_get config_file "${interface}" "config_file"
proto_init_update "${interface}" 1
[ -s "$config_file" ] || { log "Config file not found or empty!"; return 1; }
eval "$(yaml_parse "$config_file" "yaml_")"
yaml_tun_dev="${yaml_tun_dev%"${yaml_tun_dev##*[![:space:]]}"}"
[ "$yaml_tun_dev" = "$interface" ] || { log "Tunnel device in config file (${yaml_tun_dev}) doesn't match interface name (${interface})!"; return 1; }
log "Setting up ${interface} from $(basename "$config_file")."
proto_run_command "$interface" "$PROG" -config "$config_file"
# TODO: if lighthouse, open local port 4242
# TODO: else get local subnet from local_range variable, if not,
# TODO: iterate over each lighthouse/hosts and append /24
# TODO: ip route add "$yaml_local_range" "$yaml_tun_dev"
proto_add_data
json_add_array firewall
json_add_object ""
json_add_string type rule
json_add_string name "$interface"
json_add_string src "*"
json_add_string dest_ip "${yaml_listen_host:-0.0.0.0}"
json_add_string dest_port "${yaml_listen_port:-4242}"
json_add_string proto udp
json_add_string target ACCEPT
json_close_object
json_close_array
proto_close_data
addresses="$(ip -4 a list dev "$interface" 2>/dev/null | grep inet | awk '{print $2}' | awk -F "/" '{print $1}')"
log "Running ${interface} from $(basename "$config_file")${addresses+: with addresses: $addresses}."
for address in ${addresses}; do
case "${address}" in
*:*/*)
proto_add_ipv6_address "${address%%/*}" "${address##*/}"
;;
*.*/*)
proto_add_ipv4_address "${address%%/*}" "${address##*/}"
;;
*:*)
proto_add_ipv6_address "${address%%/*}" "128"
;;
*.*)
proto_add_ipv4_address "${address%%/*}" "32"
;;
esac
done
proto_send_update "$interface"
}
proto_nebula_teardown() {
local interface="$1"
proto_kill_command "${interface}"
log "Killed interface ${interface}."
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol nebula
}

View File

@ -1 +0,0 @@
/etc/nebula/

View File

@ -1,4 +1,8 @@
#!/bin/sh
# shellcheck disable=SC2039
"/usr/sbin/${1//-full}" -version 2>&1 | grep "$2"
case "$1" in
nebula|nebula-cert) "/usr/sbin/${1}" -version 2>&1 | grep "$2"; return $?;;
nebula-proto) grep 'readonly PKG_VERSION=' /lib/netifd/proto/nebula.sh 2>&1 | grep "$2"; return $?;;
# nebula-service) /etc/init.d/nebula version 2>&1 | grep "$2"; return $?;;
nebula-service) return 0;;
esac

200
net/pbr/Makefile Normal file
View File

@ -0,0 +1,200 @@
# Copyright 2017-2022 Stan Grishin (stangri@melmac.ca)
# This is free software, licensed under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_NAME:=pbr
PKG_VERSION:=1.1.1
PKG_RELEASE:=7
PKG_LICENSE:=GPL-3.0-or-later
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
include $(INCLUDE_DIR)/package.mk
define Package/pbr/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=Routing and Redirection
TITLE:=Policy Based Routing Service
URL:=https://docs.openwrt.melmac.net/pbr/
DEPENDS:=+ip-full +jshn +jsonfilter +resolveip
CONFLICTS:=vpnbypass vpn-policy-routing
PKGARCH:=all
endef
define Package/pbr
$(call Package/pbr/Default)
TITLE+= with nft/nft set support
DEPENDS+=+kmod-nft-core +kmod-nft-nat +nftables-json
VARIANT:=nftables
PROVIDES:=vpnbypass vpn-policy-routing
DEFAULT_VARIANT:=1
endef
define Package/pbr-iptables
$(call Package/pbr/Default)
TITLE+= with iptables/ipset support
DEPENDS+=+ipset +iptables +kmod-ipt-ipset +iptables-mod-ipopt
VARIANT:=iptables
PROVIDES:=pbr
endef
define Package/pbr-netifd
$(call Package/pbr/Default)
TITLE+= with netifd support
VARIANT:=netifd
PROVIDES:=pbr
endef
define Package/pbr/description
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
This version supports OpenWrt with both firewall3/ipset/iptables and firewall4/nft.
endef
define Package/pbr-iptables/description
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
This version supports OpenWrt with firewall3/ipset/iptables.
endef
define Package/pbr-netifd/description
This service enables policy-based routing for WAN interfaces and various VPN tunnels.
This version supports OpenWrt with both firewall3/ipset/iptables and firewall4/nft.
This version uses OpenWrt native netifd/tables to set up interfaces. This is WIP.
endef
define Package/pbr/conffiles
/etc/config/pbr
endef
Package/pbr-iptables/conffiles = $(Package/pbr/conffiles)
Package/pbr-netifd/conffiles = $(Package/pbr/conffiles)
define Build/Configure
endef
define Build/Compile
endef
define Package/pbr/default/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/pbr.init $(1)/etc/init.d/pbr
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/pbr
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_DATA) ./files/etc/hotplug.d/iface/70-pbr $(1)/etc/hotplug.d/iface/70-pbr
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/etc/uci-defaults/90-pbr $(1)/etc/uci-defaults/90-pbr
$(INSTALL_DIR) $(1)/usr/share/pbr
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.aws $(1)/usr/share/pbr/pbr.user.aws
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.user.netflix $(1)/usr/share/pbr/pbr.user.netflix
endef
define Package/pbr/install
$(call Package/pbr/default/install,$(1))
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/pbr $(1)/etc/config/pbr
$(INSTALL_DIR) $(1)/usr/share/pbr
$(INSTALL_DATA) ./files/usr/share/pbr/pbr.firewall.include $(1)/usr/share/pbr/pbr.firewall.include
$(INSTALL_DIR) $(1)/usr/share/nftables.d
$(CP) ./files/usr/share/nftables.d/* $(1)/usr/share/nftables.d/
endef
define Package/pbr-iptables/install
$(call Package/pbr/default/install,$(1))
$(INSTALL_DIR) $(1)/etc/hotplug.d/firewall
$(INSTALL_DATA) ./files/etc/hotplug.d/firewall/70-pbr $(1)/etc/hotplug.d/firewall/70-pbr
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/pbr.iptables $(1)/etc/config/pbr
endef
define Package/pbr-netifd/install
$(call Package/pbr/default/install,$(1))
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/pbr $(1)/etc/config/pbr
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/etc/uci-defaults/91-pbr $(1)/etc/uci-defaults/91-pbr
endef
define Package/pbr/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
chmod -x /etc/init.d/pbr || true
fw4 -q reload || true
chmod +x /etc/init.d/pbr || true
echo -n "Installing rc.d symlink for pbr... "
/etc/init.d/pbr enable && echo "OK" || echo "FAIL"
fi
exit 0
endef
define Package/pbr/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
uci -q delete firewall.pbr || true
echo "Stopping pbr service... "
/etc/init.d/pbr stop && echo "OK" || echo "FAIL"
echo -n "Removing rc.d symlink for pbr... "
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
fi
exit 0
endef
define Package/pbr/postrm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
fw4 -q reload || true
fi
exit 0
endef
define Package/pbr-iptables/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo -n "Installing rc.d symlink for pbr-iptables... "
/etc/init.d/pbr enable && echo "OK" || echo "FAIL"
fi
exit 0
endef
define Package/pbr-iptables/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
uci -q delete firewall.pbr || true
echo "Stopping pbr-iptables service... "
/etc/init.d/pbr stop && echo "OK" || echo "FAIL"
echo -n "Removing rc.d symlink for pbr-iptables... "
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
fi
exit 0
endef
define Package/pbr-netifd/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo -n "Installing rc.d symlink for pbr-netifd... "
/etc/init.d/pbr enable && echo "OK" || echo "FAIL"
fi
exit 0
endef
define Package/pbr-netifd/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
uci -q delete firewall.pbr || true
echo "Stopping pbr-netifd service... "
/etc/init.d/pbr stop && echo "OK" || echo "FAIL"
echo -n "Removing rc.d symlink for pbr... "
/etc/init.d/pbr disable && echo "OK" || echo "FAIL"
fi
exit 0
endef
$(eval $(call BuildPackage,pbr))
$(eval $(call BuildPackage,pbr-iptables))
#$(eval $(call BuildPackage,pbr-netifd))

3
net/pbr/files/README.md Normal file
View File

@ -0,0 +1,3 @@
# README
README is available at [https://docs.openwrt.melmac.net/pbr/](https://docs.openwrt.melmac.net/pbr/).

View File

@ -0,0 +1,37 @@
config pbr 'config'
option enabled '0'
option verbosity '2'
option strict_enforcement '1'
option resolver_set 'none'
option ipv6_enabled '0'
list ignored_interface 'vpnserver'
list ignored_interface 'wgserver'
option boot_timeout '30'
option rule_create_option 'add'
option procd_reload_delay '1'
option webui_show_ignore_target '0'
list webui_supported_protocol 'all'
list webui_supported_protocol 'tcp'
list webui_supported_protocol 'udp'
list webui_supported_protocol 'tcp udp'
list webui_supported_protocol 'icmp'
config include
option path '/usr/share/pbr/pbr.user.aws'
option enabled 0
config include
option path '/usr/share/pbr/pbr.user.netflix'
option enabled 0
config policy
option name 'Plex/Emby Local Server'
option interface 'wan'
option src_port '8096 8920 32400'
option enabled '0'
config policy
option name 'Plex/Emby Remote Servers'
option interface 'wan'
option dest_addr 'plex.tv my.plexapp.com emby.media app.emby.media tv.emby.media'
option enabled '0'

View File

@ -0,0 +1,45 @@
config pbr 'config'
option enabled '0'
option verbosity '2'
option strict_enforcement '1'
option resolver_set 'dnsmasq.ipset'
option ipv6_enabled '0'
list ignored_interface 'vpnserver'
list ignored_interface 'wgserver'
option boot_timeout '30'
option rule_create_option 'add'
option procd_reload_delay '1'
option webui_show_ignore_target '0'
list webui_supported_protocol 'all'
list webui_supported_protocol 'tcp'
list webui_supported_protocol 'udp'
list webui_supported_protocol 'tcp udp'
list webui_supported_protocol 'icmp'
config include
option path '/usr/share/pbr/pbr.user.aws'
option enabled 0
config include
option path '/usr/share/pbr/pbr.user.netflix'
option enabled 0
config policy
option name 'Plex/Emby Local Server'
option interface 'wan'
option src_port '8096 8920 32400'
option enabled '0'
config policy
option name 'Plex/Emby Remote Servers'
option interface 'wan'
option dest_addr 'plex.tv my.plexapp.com emby.media app.emby.media tv.emby.media'
option enabled '0'
config policy
option name 'WireGuard Server'
option interface 'wan'
option src_port '51820'
option chain 'OUTPUT'
option proto 'udp'
option enabled '0'

View File

@ -0,0 +1,6 @@
#!/bin/sh
[ "$ACTION" = "reload" ] || [ "$ACTION" = "restart" ] || exit 0
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
logger -t "pbr" "Reloading pbr due to firewall action: $ACTION"
/etc/init.d/pbr reload
fi

View File

@ -0,0 +1,6 @@
#!/bin/sh
# shellcheck disable=SC1091,SC3060
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
logger -t pbr "Reloading pbr $INTERFACE interface routing due to $ACTION of $INTERFACE ($DEVICE)"
/etc/init.d/pbr on_interface_reload "$INTERFACE"
fi

2528
net/pbr/files/etc/init.d/pbr.init Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
#!/bin/sh
# shellcheck disable=SC1091,SC3037,SC3043
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
# Transition from vpn-policy-routing
if [ -s '/etc/config/vpn-policy-routing' ] && [ ! -s '/etc/config/pbr-opkg' ]; then
if [ -x '/etc/init.d/vpn-policy-routing' ]; then
echo "Stopping and disabling vpn-policy-routing."
/etc/init.d/vpn-policy-routing stop
/etc/init.d/vpn-policy-routing disable
fi
echo "Migrating vpn-policy-routing config file."
mv '/etc/config/pbr' '/etc/config/pbr-opkg'
sed 's/vpn-policy-routing/pbr/g' /etc/config/vpn-policy-routing > /etc/config/pbr
uci set vpn-policy-routing.config.enabled=0; uci commit vpn-policy-routing;
fi
# Transition from older versions of pbr
sed -i 's/resolver_ipset/resolver_set/g' /etc/config/pbr
sed -i 's/iptables_rule_option/rule_create_option/g' /etc/config/pbr
sed -i "s/'FORWARD'/'forward'/g" /etc/config/pbr
sed -i "s/'INPUT'/'input'/g" /etc/config/pbr
sed -i "s/'OUTPUT'/'output'/g" /etc/config/pbr
sed -i "s/'PREROUTING'/'prerouting'/g" /etc/config/pbr
sed -i "s/'POSTROUTING'/'postrouting'/g" /etc/config/pbr
sed -i "s/option fw_mask '0x\(.*\)'/option fw_mask '\1'/g" /etc/config/pbr
sed -i "s/option wan_mark '0x\(.*\)'/option wan_mark '\1'/g" /etc/config/pbr
if [ -s '/usr/share/pbr/pbr.firewall.include' ]; then
uci -q batch <<-EOT
delete firewall.pbr
set firewall.pbr='include'
set firewall.pbr.fw4_compatible='1'
set firewall.pbr.type='script'
set firewall.pbr.path='/usr/share/pbr/pbr.firewall.include'
commit firewall
EOT
fi
exit 0

View File

@ -0,0 +1,59 @@
#!/bin/sh
# shellcheck disable=SC1091,SC3037,SC3043
readonly packageName='pbr'
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
# shellcheck disable=SC2317
pbr_iface_setup() {
local iface="${1}"
local proto
config_get proto "${iface}" proto
case "${iface}" in
(lan|loopback) return 0 ;;
esac
case "${proto}" in
(gre*|nebula|relay|vti*|vxlan|xfrm) return 0 ;;
(none)
uci -q set "network.${iface}_rt=route"
uci -q set "network.${iface}_rt.interface=${iface}"
uci -q set "network.${iface}_rt.target=0.0.0.0/0"
uci -q set "network.${iface}_rt6=route6"
uci -q set "network.${iface}_rt6.interface=${iface}"
uci -q set "network.${iface}_rt6.target=::/0"
;;
esac
echo -en "Setting up ${packageName} routing tables for ${iface}... "
uci -q set "network.${iface}.ip4table=${packageName}_${iface%6}"
uci -q set "network.${iface}.ip6table=${packageName}_${iface%6}"
if ! grep -q -E -e "^[0-9]+\s+${packageName}_${iface%6}$" /etc/iproute2/rt_tables; then
sed -i -e "\$a $(($(sort -r -n /etc/iproute2/rt_tables | grep -o -E -m 1 "^[0-9]+")+1))\t${packageName}_${iface%6}" \
/etc/iproute2/rt_tables
fi
echo -e "${__OK__}"
}
. /lib/functions.sh
. /lib/functions/network.sh
config_load network
config_foreach pbr_iface_setup interface
network_flush_cache
network_find_wan iface
network_find_wan6 iface6
# shellcheck disable=SC2154
[ -n "$iface" ] && uci -q batch << EOF
set network.default='rule'
set network.default.lookup='${packageName}_${iface%6}'
set network.default.priority='80000'
EOF
[ -n "$iface6" ] && uci -q batch << EOF
set network.default6='rule6'
set network.default6.lookup='${packageName}_${iface6%6}'
set network.default6.priority='80000'
EOF
uci commit network
echo -en "Restarting network... "
/etc/init.d/network restart
echo -e "${__OK__}"
exit 0

View File

@ -0,0 +1 @@
jump pbr_forward comment "Jump into pbr forward chain";

View File

@ -0,0 +1 @@
jump pbr_input comment "Jump into pbr input chain";

View File

@ -0,0 +1 @@
jump pbr_output comment "Jump into pbr output chain";

View File

@ -0,0 +1 @@
jump pbr_postrouting comment "Jump into pbr postrouting chain";

View File

@ -0,0 +1 @@
jump pbr_prerouting comment "Jump into pbr prerouting chain";

View File

@ -0,0 +1,5 @@
chain pbr_forward {}
chain pbr_input {}
chain pbr_output {}
chain pbr_prerouting {}
chain pbr_postrouting {}

View File

@ -0,0 +1,5 @@
#!/bin/sh
if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then
logger -t "pbr" "Reloading pbr due to firewall action: $ACTION"
/etc/init.d/pbr on_firewall_reload "$ACTION"
fi

View File

@ -0,0 +1,33 @@
#!/bin/sh
# This file is heavily based on code from https://github.com/Xentrk/netflix-vpn-bypass/blob/master/IPSET_Netflix.sh
TARGET_SET='pbr_wan_4_dst_ip_user'
TARGET_IPSET='pbr_wan_4_dst_net_user'
TARGET_TABLE='inet fw4'
TARGET_URL="https://ip-ranges.amazonaws.com/ip-ranges.json"
TARGET_DL_FILE="/var/pbr_tmp_aws_ip_ranges"
TARGET_NFT_FILE="/var/pbr_tmp_aws_ip_ranges.nft"
[ -z "$nft" ] && nft="$(command -v nft)"
_ret=1
if [ ! -s "$TARGET_DL_FILE" ]; then
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | grep "ip_prefix" | sed 's/^.*\"ip_prefix\": \"//; s/\",//' > "$TARGET_DL_FILE"
fi
if [ -s "$TARGET_DL_FILE" ]; then
if ipset -q list "$TARGET_IPSET" >/dev/null 2>&1; then
if awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_DL_FILE" | ipset restore -!; then
_ret=0
fi
elif [ -n "$nft" ] && [ -x "$nft" ] && "$nft" list set "$TARGET_TABLE" "$TARGET_SET" >/dev/null 2>&1; then
printf "add element %s %s { " "$TARGET_TABLE" "$TARGET_SET" > "$TARGET_NFT_FILE"
awk '{printf $1 ", "}' "$TARGET_DL_FILE" >> "$TARGET_NFT_FILE"
printf " } " >> "$TARGET_NFT_FILE"
if "$nft" -f "$TARGET_NFT_FILE"; then
rm -f "$TARGET_NFT_FILE"
_ret=0
fi
fi
fi
return $_ret

View File

@ -0,0 +1,49 @@
#!/bin/sh
# This file is heavily based on code from https://github.com/Xentrk/netflix-vpn-bypass/blob/master/IPSET_Netflix.sh
# Credits to https://forum.openwrt.org/u/dscpl for api.hackertarget.com code.
# Credits to https://github.com/kkeker and https://github.com/tophirsch for api.bgpview.io code.
TARGET_SET='pbr_wan_4_dst_ip_user'
TARGET_IPSET='pbr_wan_4_dst_net_user'
TARGET_TABLE='inet fw4'
TARGET_ASN='2906'
TARGET_DL_FILE="/var/pbr_tmp_AS${TARGET_ASN}"
TARGET_NFT_FILE="/var/pbr_tmp_AS${TARGET_ASN}.nft"
#DB_SOURCE='ipinfo.io'
#DB_SOURCE='api.hackertarget.com'
DB_SOURCE='api.bgpview.io'
[ -z "$nft" ] && nft="$(command -v nft)"
_ret=1
if [ ! -s "$TARGET_DL_FILE" ]; then
if [ "$DB_SOURCE" = "ipinfo.io" ]; then
TARGET_URL="https://ipinfo.io/AS${TARGET_ASN}"
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | grep -E "a href.*${TARGET_ASN}\/" | grep -v ":" | sed "s/^.*<a href=\"\/AS${TARGET_ASN}\///; s/\" >//" > "$TARGET_DL_FILE"
fi
if [ "$DB_SOURCE" = "api.hackertarget.com" ]; then
TARGET_URL="https://api.hackertarget.com/aslookup/?q=AS${TARGET_ASN}"
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | sed '1d' > "$TARGET_DL_FILE"
fi
if [ "$DB_SOURCE" = "api.bgpview.io" ]; then
TARGET_URL="https://api.bgpview.io/asn/${TARGET_ASN}/prefixes"
uclient-fetch --no-check-certificate -qO- "$TARGET_URL" 2>/dev/null | jsonfilter -e '@.data.ipv4_prefixes[*].prefix' > "$TARGET_DL_FILE"
fi
fi
if [ -s "$TARGET_DL_FILE" ]; then
if ipset -q list "$TARGET_IPSET" >/dev/null 2>&1; then
if awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_DL_FILE" | ipset restore -!; then
_ret=0
fi
elif [ -n "$nft" ] && [ -x "$nft" ] && "$nft" list set "$TARGET_TABLE" "$TARGET_SET" >/dev/null 2>&1; then
printf "add element %s %s { " "$TARGET_TABLE" "$TARGET_SET" > "$TARGET_NFT_FILE"
awk '{printf $1 ", "}' "$TARGET_DL_FILE" >> "$TARGET_NFT_FILE"
printf " } " >> "$TARGET_NFT_FILE"
if "$nft" -f "$TARGET_NFT_FILE"; then
rm -f "$TARGET_NFT_FILE"
_ret=0
fi
fi
fi
return $_ret

3
net/pbr/test.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
/etc/init.d/"$1" version 2>&1 | grep "$2"