diff --git a/.github/workflows/check-autorelease-deprecation.yml b/.github/workflows/check-autorelease-deprecation.yml index c19911bfa..b85b3243f 100644 --- a/.github/workflows/check-autorelease-deprecation.yml +++ b/.github/workflows/check-autorelease-deprecation.yml @@ -28,6 +28,8 @@ jobs: - name: Determine changed packages run: | + RET=0 + # only detect packages with changes PKG_ROOTS=$(find . -name Makefile | \ grep -v ".*/src/Makefile" | \ @@ -46,14 +48,13 @@ jobs: done if [ -n "$CONTAINS_AUTORELEASE" ]; then + RET=1 cat > "$GITHUB_WORKSPACE/pr_comment.md" << EOF Please do no longer set *PKG_RELEASE* to *AUTORELEASE* as the feature is deprecated. Please use an integer instead. Below is a list of affected packages including correct *PKG_RELEASE*: EOF - else - echo "No usage of *AUTORELEASE* found in changes" > "$GITHUB_WORKSPACE/pr_comment.md" fi for ROOT in $CONTAINS_AUTORELEASE; do @@ -70,8 +71,11 @@ jobs: echo >> "$GITHUB_WORKSPACE/pr_comment.md" done + exit $RET + - name: Find Comment uses: peter-evans/find-comment@v2 + if: ${{ failure() }} id: fc with: issue-number: ${{ github.event.pull_request.number }} @@ -79,6 +83,7 @@ jobs: - name: Create or update comment uses: peter-evans/create-or-update-comment@v2 + if: ${{ failure() }} with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/entrypoint.sh b/.github/workflows/entrypoint.sh index 760410547..6af84b8e7 100755 --- a/.github/workflows/entrypoint.sh +++ b/.github/workflows/entrypoint.sh @@ -1,10 +1,14 @@ #!/bin/sh +# not enabling `errtrace` and `pipefail` since those are bash specific +set -o errexit # failing commands causes script to fail +set -o nounset # undefined variables causes script to fail + mkdir -p /var/lock/ opkg update -[ -n "$CI_HELPER" ] || CI_HELPER="/ci/.github/workflows/ci_helpers.sh" +[ -n "${CI_HELPER:=''}" ] || CI_HELPER="/ci/.github/workflows/ci_helpers.sh" for PKG in /ci/*.ipk; do tar -xzOf "$PKG" ./control.tar.gz | tar xzf - ./control diff --git a/lang/golang/golang/Makefile b/lang/golang/golang/Makefile index 38b7b2430..4377965c2 100644 --- a/lang/golang/golang/Makefile +++ b/lang/golang/golang/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk GO_VERSION_MAJOR_MINOR:=1.19 -GO_VERSION_PATCH:=3 +GO_VERSION_PATCH:=4 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=18ac263e39210bcf68d85f4370e97fb1734166995a1f63fb38b4f6e07d90d212 +PKG_HASH:=eda74db4ac494800a3e66ee784e495bfbb9b8e535df924a8b01b1a8028b7f368 PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause diff --git a/lang/python/django/Makefile b/lang/python/django/Makefile index 4578076a1..5d34a6cbd 100644 --- a/lang/python/django/Makefile +++ b/lang/python/django/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=django -PKG_VERSION:=4.1.1 -PKG_RELEASE:=$(AUTORELEASE) +PKG_VERSION:=4.1.3 +PKG_RELEASE:=1 PYPI_NAME:=Django -PKG_HASH:=a153ffd5143bf26a877bfae2f4ec736ebd8924a46600ca089ad96b54a1d4e28e +PKG_HASH:=678bbfc8604eb246ed54e2063f0765f13b321a50526bdc8cb1f943eda7fa31f1 PKG_MAINTAINER:=Alexandru Ardelean , Peter Stadler PKG_LICENSE:=BSD-3-Clause diff --git a/libs/libmbim/Makefile b/libs/libmbim/Makefile index 4b70cf66c..abd94d617 100644 --- a/libs/libmbim/Makefile +++ b/libs/libmbim/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_SOURCE_VERSION:=1.26.4 -PKG_RELEASE:=$(AUTORELEASE) +PKG_SOURCE_VERSION:=1.28.2 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_MIRROR_HASH:=4963f9135f8ad26165d969d0b2028b00d68243201113c94a2ebe22c4227058a4 +PKG_MIRROR_HASH:=0b0b46016738fc22355d5a58c8a2d1b2f04906c49c51a50b57a09640d13b00b7 PKG_MAINTAINER:=Nicholas Smith diff --git a/libs/libqmi/Makefile b/libs/libqmi/Makefile index 2224a33c7..bfa3bab7c 100644 --- a/libs/libqmi/Makefile +++ b/libs/libqmi/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_SOURCE_VERSION:=1.30.8 -PKG_RELEASE:=$(AUTORELEASE) +PKG_SOURCE_VERSION:=1.32.2 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_MIRROR_HASH:=a0fa33a89011bdb593f66fd0b674f2a7c31f87e43ffd7f3e9a515b00864c4a91 +PKG_MIRROR_HASH:=711d16d75a6a9afaefcf2be1bc845a4a6181dff786dfbd079e41e91279a0be91 PKG_MAINTAINER:=Nicholas Smith diff --git a/libs/libqrtr-glib/Makefile b/libs/libqrtr-glib/Makefile index f6eea539a..b5fabf31b 100644 --- a/libs/libqrtr-glib/Makefile +++ b/libs/libqrtr-glib/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqrtr-glib PKG_VERSION:=1.2.2 -PKG_RELEASE:=$(AUTORELEASE) +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqrtr-glib.git diff --git a/multimedia/tvheadend/Config.in b/multimedia/tvheadend/Config.in index 741ae8ffa..de689fd33 100644 --- a/multimedia/tvheadend/Config.in +++ b/multimedia/tvheadend/Config.in @@ -3,10 +3,10 @@ comment "Generic options" config TVHEADEND_OPTIMIZE_SPEED bool "Optimize for speed" - depends on PACKAGE_tvheadend + depends on PACKAGE_tvheadend && (arm || aarch64 || x86_64) default n help - Optimize tvheadend for speed instead of size. This option adds -O2 and LTO (Link Time Optimization). + Optimize tvheadend for speed instead of size. This option adds -O3 and LTO (Link Time Optimization). Note: No benchmarks were performed when this option was added. Speed improvements (if any) are not known. config TVHEADEND_TRACE diff --git a/multimedia/tvheadend/Makefile b/multimedia/tvheadend/Makefile index c6a01e203..4db9918c7 100644 --- a/multimedia/tvheadend/Makefile +++ b/multimedia/tvheadend/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=tvheadend PKG_VERSION:=2022-11-20 -PKG_RELEASE:=$(AUTORELEASE) +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/tvheadend/tvheadend.git diff --git a/net/bpfcountd/Makefile b/net/bpfcountd/Makefile new file mode 100644 index 000000000..f6b97c2e4 --- /dev/null +++ b/net/bpfcountd/Makefile @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: MIT +# Copyright (C) 2022 Linus Lüssing + +include $(TOPDIR)/rules.mk + +PKG_NAME:=bpfcountd +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-06-26 +PKG_SOURCE_URL=https://github.com/lemoer/bpfcountd.git +PKG_SOURCE_VERSION:=8b1aeb18d686815f93e2bfe976e536c5699d6371 +PKG_MIRROR_HASH:=e6e7adcc11c0fd33c6d3ac31423d3288812270944c2f31d9610ac8c3173a8c5f + +PKG_MAINTAINER:=Linus Lüssing +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/package.mk + +define Package/bpfcountd + SECTION:=net + CATEGORY:=Network + TITLE:=Berkeley Packet Filter Counting Daemon + DEPENDS:=+libpcap +endef + +define Package/bpfcountd/description + bpfcountd was created to obtain packet statistics in larger networks + without stressing the cpu resources. bpfcountd will count the amount + of packages and bytes over time (for each defined rule). The rules + are defined using the tcpdump filter syntax (bpf). The collected + data is provided on a unix socket in plaintext. +endef + +define Package/bpfcountd/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/bpfcountd $(1)/usr/sbin/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,bpfcountd)) diff --git a/net/bpfcountd/files/etc/bpfcountd.filters b/net/bpfcountd/files/etc/bpfcountd.filters new file mode 100644 index 000000000..8c1029a25 --- /dev/null +++ b/net/bpfcountd/files/etc/bpfcountd.filters @@ -0,0 +1,2 @@ +arp;arp +icmp6;icmp6 diff --git a/net/bpfcountd/files/etc/config/bpfcountd b/net/bpfcountd/files/etc/config/bpfcountd new file mode 100644 index 000000000..790de16ca --- /dev/null +++ b/net/bpfcountd/files/etc/config/bpfcountd @@ -0,0 +1,13 @@ +config bpfcountd 'eth0_in' + option ifname 'eth0' + option prefilter 'inbound' + option filterfile '/etc/bpfcountd.filters' + option buffersize '2097152' + option disabled '1' + +config bpfcountd 'eth0_out' + option ifname 'eth0' + option prefilter 'outbound' + option filterfile '/etc/bpfcountd.filters' + option buffersize '2097152' + option disabled '1' diff --git a/net/bpfcountd/files/etc/init.d/bpfcountd b/net/bpfcountd/files/etc/init.d/bpfcountd new file mode 100755 index 000000000..2db2a4bac --- /dev/null +++ b/net/bpfcountd/files/etc/init.d/bpfcountd @@ -0,0 +1,92 @@ +#!/bin/sh /etc/rc.common +# SPDX-License-Identifier: MIT +# Copyright (C) 2022 Linus Lüssing + +USE_PROCD=1 +START=20 +STOP=90 + +UNIXSOCKDIR=/var/run/bpfcountd + +bpfcountd_start() { + local cfg="$1" + local disabled + + local ifname + local prefilter + local filterfile + local buffersize + + config_get_bool disabled "$cfg" disabled 0 + [ "$disabled" -gt 0 ] && return 0 + + mkdir -p "$UNIXSOCKDIR" + + config_get ifname "$cfg" "ifname" + config_get prefilter "$cfg" "prefilter" + config_get filterfile "$cfg" "filterfile" + config_get buffersize "$cfg" "buffersize" + + [ -z "$ifname" ] && { + echo "Error: no ifname specified for $cfg" >&2 + return 0 + } + [ -z "$filterfile" ] && { + echo "Error: no filterfile specified for $cfg" >&2 + return 0 + } + + procd_open_instance "$cfg" + + procd_set_param command /usr/sbin/bpfcountd + procd_append_param command -i "$ifname" + procd_append_param command -f "$filterfile" + procd_append_param command -u $UNIXSOCKDIR/"$cfg".sock + [ -n "$prefilter" ] && procd_append_param command -F "$prefilter" + [ -n "$buffersize" ] && procd_append_param command -b "$buffersize" + + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + + procd_set_param stderr 1 + procd_close_instance +} + +start_service() { + local cfg="$1" + local instance_found=0 + + . /lib/functions/network.sh + + config_cb() { + local type="$1" + local name="$2" + if [ "$type" = "bpfcountd" ]; then + if [ -n "$cfg" -a "$cfg" = "$name" ]; then + instance_found=1 + fi + fi + } + + config_load bpfcountd + + if [ -n "$cfg" ]; then + [ "$instance_found" -gt 0 ] || return + bpfcountd_start "$cfg" + else + config_foreach bpfcountd_start bpfcountd + fi +} + +stop_service() { + local cfg="$1" + + if [ -n "$cfg" ]; then + rm $UNIXSOCKDIR/$cfg.sock + else + rm $UNIXSOCKDIR/*.sock + fi +} + +service_triggers() { + procd_add_reload_trigger bpfcountd +} diff --git a/net/cloudflared/Makefile b/net/cloudflared/Makefile index 5ec60b03e..cfe971f9b 100644 --- a/net/cloudflared/Makefile +++ b/net/cloudflared/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cloudflared -PKG_VERSION:=2022.11.0 +PKG_VERSION:=2022.11.1 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/cloudflare/cloudflared/tar.gz/$(PKG_VERSION)? -PKG_HASH:=01478108dc4a4a74b2a9eecda35b1b7cc69ce33f45fe0c94edf598b90154fda0 +PKG_HASH:=d4b1133057a721087a0a5387ea6d4d1ebf3b1f5135396da25a1e88e873cd5203 PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:=LICENSE diff --git a/net/ddns-scripts/Makefile b/net/ddns-scripts/Makefile index 8c51476c3..9e6e57ba7 100644 --- a/net/ddns-scripts/Makefile +++ b/net/ddns-scripts/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ddns-scripts PKG_VERSION:=2.8.2 -PKG_RELEASE:=29 +PKG_RELEASE:=30 PKG_LICENSE:=GPL-2.0 @@ -70,6 +70,17 @@ define Package/ddns-scripts-cloudflare/description endef +define Package/ddns-scripts-gcp + $(call Package/ddns-scripts/Default) + TITLE:=Extension for Google Cloud DNS API v1 + DEPENDS:=ddns-scripts +curl +openssl-util +endef + +define Package/ddns-scripts-gcp/description + Dynamic DNS Client scripts extension for Google Cloud DNS API v1 (requires curl) +endef + + define Package/ddns-scripts-freedns $(call Package/ddns-scripts/Default) TITLE:=Extension for freedns.42.pl @@ -323,6 +334,7 @@ define Package/ddns-scripts-services/install # Remove special services rm $(1)/usr/share/ddns/default/cloudflare.com-v4.json + rm $(1)/usr/share/ddns/default/cloud.google.com-v1.json rm $(1)/usr/share/ddns/default/freedns.42.pl.json rm $(1)/usr/share/ddns/default/godaddy.com-v1.json rm $(1)/usr/share/ddns/default/digitalocean.com-v2.json @@ -358,6 +370,25 @@ exit 0 endef +define Package/ddns-scripts-gcp/install + $(INSTALL_DIR) $(1)/usr/lib/ddns + $(INSTALL_BIN) ./files/usr/lib/ddns/update_gcp_v1.sh \ + $(1)/usr/lib/ddns + + $(INSTALL_DIR) $(1)/usr/share/ddns/default + $(INSTALL_DATA) ./files/usr/share/ddns/default/cloud.google.com-v1.json \ + $(1)/usr/share/ddns/default/ +endef + +define Package/ddns-scripts-gcp/prerm +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + /etc/init.d/ddns stop +fi +exit 0 +endef + + define Package/ddns-scripts-freedns/install $(INSTALL_DIR) $(1)/usr/lib/ddns $(INSTALL_BIN) ./files/usr/lib/ddns/update_freedns_42_pl.sh \ @@ -608,6 +639,7 @@ endef $(eval $(call BuildPackage,ddns-scripts)) $(eval $(call BuildPackage,ddns-scripts-services)) $(eval $(call BuildPackage,ddns-scripts-cloudflare)) +$(eval $(call BuildPackage,ddns-scripts-gcp)) $(eval $(call BuildPackage,ddns-scripts-freedns)) $(eval $(call BuildPackage,ddns-scripts-godaddy)) $(eval $(call BuildPackage,ddns-scripts-digitalocean)) diff --git a/net/ddns-scripts/files/usr/lib/ddns/update_gcp_v1.sh b/net/ddns-scripts/files/usr/lib/ddns/update_gcp_v1.sh new file mode 100755 index 000000000..5bd096f46 --- /dev/null +++ b/net/ddns-scripts/files/usr/lib/ddns/update_gcp_v1.sh @@ -0,0 +1,272 @@ +#!/bin/sh +# +#.Distributed under the terms of the GNU General Public License (GPL) version 2.0 +#.2022 Chris Barrick +# +# This script sends DDNS updates using the Google Cloud DNS REST API. +# See: https://cloud.google.com/dns/docs/reference/v1 +# +# This script uses a GCP service account. The user is responsible for creating +# the service account, ensuring it has permission to update DNS records, and +# for generating a service account key to be used by this script. The records +# to be updated must already exist. +# +# Arguments: +# +# - $username: The service account name. +# Example: ddns-service-account@my-dns-project.iam.gserviceaccount.com +# +# - $password: The service account key. You can paste the key directly into the +# "password" field or upload the key file to the router and set the field +# equal to the file path. This script supports JSON keys or the raw private +# key as a PEM file. P12 keys are not supported. File names must end with +# `*.json` or `*.pem`. +# +# - $domain: The domain to update. +# +# - $param_enc: The additional required arguments, as form-urlencoded data, +# i.e. `key1=value1&key2=value2&...`. The required arguments are: +# - project: The name of the GCP project that owns the DNS records. +# - zone: The DNS zone in the GCP API. +# - Example: `project=my-dns-project&zone=my-dns-zone` +# +# - $param_opt: Optional TTL for the records, in seconds. Defaults to 3600 (1h). +# +# Dependencies: +# - ddns-scripts (for the base functionality) +# - openssl-util (for the authentication flow) +# - curl (for the GCP REST API) + +. /usr/share/libubox/jshn.sh + + +# Authentication +# --------------------------------------------------------------------------- +# The authentication flow works like this: +# +# 1. Construct a JWT claim for access to the DNS readwrite scope. +# 2. Sign the JWT with the service accout key, proving we have access. +# 3. Exchange the JWT for an access token, valid for 5m. +# 4. Use the access token for API calls. +# +# See https://developers.google.com/identity/protocols/oauth2/service-account + +# A URL-safe variant of base64 encoding, used by JWTs. +base64_urlencode() { + openssl base64 | tr '/+' '_-' | tr -d '=\n' +} + +# Prints the service account private key in PEM format. +get_service_account_key() { + # The "password" field provides us with the service account key. + # We allow the user to provide it to us in a few different formats. + # + # 1. If $password is a string ending in `*.json`, it is a file path, + # pointing to a JSON service account key as downloaded from GCP. + # + # 2. If $password is a string ending with `*.pem`, it is a PEM private + # key, extracted from the JSON service account key. + # + # 3. If $password starts with `{`, then the JSON service account key + # was pasted directly into the password field. + # + # 4. If $password starts with `---`, then the PEM private key was pasted + # directly into the password field. + # + # We do not support P12 service account keys. + case "${password}" in + (*".json") + jsonfilter -i "${password}" -e @.private_key + ;; + (*".pem") + cat "${password}" + ;; + ("{"*) + jsonfilter -s "${password}" -e @.private_key + ;; + ("---"*) + printf "%s" "${password}" + ;; + (*) + write_log 14 "Could not parse the service account key." + ;; + esac +} + +# Sign stdin using the service account key. Prints the signature. +# The input is the JWT header-payload. Used to construct a signed JWT. +sign() { + # Dump the private key to a tmp file so openssl can get to it. + local tmp_keyfile="$(mktemp -t gcp_dns_sak.pem.XXXXXX)" + chmod 600 ${tmp_keyfile} + get_service_account_key > ${tmp_keyfile} + openssl dgst -binary -sha256 -sign ${tmp_keyfile} + rm ${tmp_keyfile} +} + +# Print the JWT header in JSON format. +# Currently, Google only supports RS256. +jwt_header() { + json_init + json_add_string "alg" "RS256" + json_add_string "typ" "JWT" + json_dump +} + +# Prints the JWT claim-set in JSON format. +# The claim is for 5m of readwrite access to the Cloud DNS API. +jwt_claim_set() { + local iat=$(date -u +%s) # Current UNIX time, UTC. + local exp=$(( iat + 300 )) # Expiration is 5m in the future. + + json_init + json_add_string "iss" "${username}" + json_add_string "scope" "https://www.googleapis.com/auth/ndev.clouddns.readwrite" + json_add_string "aud" "https://oauth2.googleapis.com/token" + json_add_string "iat" "${iat}" + json_add_string "exp" "${exp}" + json_dump +} + +# Generate a JWT signed by the service account key, which can be exchanged for +# a Google Cloud access token, authorized for Cloud DNS. +get_jwt() { + local header=$(jwt_header | base64_urlencode) + local payload=$(jwt_claim_set | base64_urlencode) + local header_payload="${header}.${payload}" + local signature=$(printf "%s" ${header_payload} | sign | base64_urlencode) + echo "${header_payload}.${signature}" +} + +# Request an access token for the Google Cloud service account. +get_access_token_raw() { + local grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer" + local assertion=$(get_jwt) + + ${CURL} -v https://oauth2.googleapis.com/token \ + --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \ + --data-urlencode "assertion=${assertion}" \ + | jsonfilter -e @.access_token +} + +# Get the access token, stripping the trailing dots. +get_access_token() { + # Since tokens may contain internal dots, we only trim the suffix if it + # starts with at least 8 dots. (The access token has *many* trailing dots.) + local access_token="$(get_access_token_raw)" + echo "${access_token%%........*}" +} + + +# Google Cloud DNS API +# --------------------------------------------------------------------------- +# Cloud DNS offers a straight forward RESTful API. +# +# - The main class is a ResourceRecordSet. It's a collection of DNS records +# that share the same domain, type, TTL, etc. Within a record set, the only +# difference between the records are their values. +# +# - The record sets live under a ManagedZone, which in turn lives under a +# Project. All we need to know about these are their names. +# +# - This implementation only makes PATCH requests to update existing record +# sets. The user must have already created at least one A or AAAA record for +# the domain they are updating. It's fine to start with a dummy, like 0.0.0.0. +# +# - The API requires SSL, and this implementation uses curl. + +# Prints a ResourceRecordSet in JSON format. +format_record_set() { + local domain="$1" + local record_type="$2" + local ttl="$3" + shift 3 # The remaining arguments are the IP addresses for this record set. + + json_init + json_add_string "kind" "dns#resourceRecordSet" + json_add_string "name" "${domain}." # trailing dot on the domain + json_add_string "type" "${record_type}" + json_add_string "ttl" "${ttl}" + json_add_array "rrdatas" + for value in $@; do + json_add_string "" "${value}" + done + json_close_array + json_dump +} + +# Makes an HTTP PATCH request to the Cloud DNS API. +patch_record_set() { + local access_token="$1" + local project="$2" + local zone="$3" + local domain="$4" + local record_type="$5" + local ttl="$6" + shift 6 # The remaining arguments are the IP addresses for this record set. + + # Note the trailing dot after the domain name. It's fully qualified. + local url="https://dns.googleapis.com/dns/v1/projects/${project}/managedZones/${zone}/rrsets/${domain}./${record_type}" + local record_set=$(format_record_set ${domain} ${record_type} ${ttl} $@) + + ${CURL} -v ${url} \ + -X PATCH \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${access_token}" \ + -d "${record_set}" +} + + +# Main entrypoint +# --------------------------------------------------------------------------- + +# Parse the $param_enc into project and zone variables. +# The arguments are the names for those variables. +parse_project_zone() { + local project_var=$1 + local zone_var=$2 + + IFS='&' + for entry in $param_enc + do + case "${entry}" in + ('project='*) + local project_val=$(echo "${entry}" | cut -d'=' -f2) + eval "${project_var}=${project_val}" + ;; + ('zone='*) + local zone_val=$(echo "${entry}" | cut -d'=' -f2) + eval "${zone_var}=${zone_val}" + ;; + esac + done + unset IFS +} + +main() { + local access_token project zone ttl record_type + + # Dependency checking + [ -z "${CURL_SSL}" ] && write_log 14 "Google Cloud DNS requires cURL with SSL support" + [ -z "$(openssl version)" ] && write_log 14 "Google Cloud DNS update requires openssl-utils" + + # Argument parsing + [ -z ${param_opt} ] && ttl=3600 || ttl="${param_opt}" + [ $use_ipv6 -ne 0 ] && record_type="AAAA" || record_type="A" + parse_project_zone project zone + + # Sanity checks + [ -z "${username}" ] && write_log 14 "Config is missing 'username' (service account name)" + [ -z "${password}" ] && write_log 14 "Config is missing 'password' (service account key)" + [ -z "${domain}" ] && write_log 14 "Config is missing 'domain'" + [ -z "${project}" ] && write_log 14 "Could not parse project name from 'param_enc'" + [ -z "${zone}" ] && write_log 14 "Could not parse zone name from 'param_enc'" + [ -z "${ttl}" ] && write_log 14 "Could not parse TTL from 'param_opt'" + [ -z "${record_type}" ] && write_log 14 "Could not determine the record type" + + # Push the record! + access_token="$(get_access_token)" + patch_record_set "${access_token}" "${project}" "${zone}" "${domain}" "${record_type}" "${ttl}" "${__IP}" +} + +main $@ diff --git a/net/ddns-scripts/files/usr/share/ddns/default/cloud.google.com-v1.json b/net/ddns-scripts/files/usr/share/ddns/default/cloud.google.com-v1.json new file mode 100644 index 000000000..eee707b3e --- /dev/null +++ b/net/ddns-scripts/files/usr/share/ddns/default/cloud.google.com-v1.json @@ -0,0 +1,10 @@ +{ + "name": "cloud.google.com-v1", + "ipv4": { + "url": "update_gcp_v1.sh" + }, + "ipv6": { + "url": "update_gcp_v1.sh" + } +} + diff --git a/net/dnsproxy/Makefile b/net/dnsproxy/Makefile index f8227ced1..a02447e8f 100644 --- a/net/dnsproxy/Makefile +++ b/net/dnsproxy/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsproxy -PKG_VERSION:=0.46.2 +PKG_VERSION:=0.46.4 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/dnsproxy/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=8ce720f258747b0ff74b9889c93c616efe3b7267d04283a1338d2ff1e24d661e +PKG_HASH:=5c959bd2f08b2304306b8f0b933b20d31a3a3d1ebeb0f349740799e5089fd4ae PKG_MAINTAINER:=Tianling Shen PKG_LICENSE:=Apache-2.0 diff --git a/net/frr/Makefile b/net/frr/Makefile index ba659b7c5..c65c59cb8 100644 --- a/net/frr/Makefile +++ b/net/frr/Makefile @@ -7,16 +7,16 @@ include $(TOPDIR)/rules.mk PKG_NAME:=frr -PKG_VERSION:=8.3.1 -PKG_RELEASE:=$(AUTORELEASE) -PKG_SOURCE_DATE:=2022-10-14 +PKG_VERSION:=8.4.1 +PKG_RELEASE:=1 +PKG_SOURCE_DATE:=2022-11-29 PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz -PKG_SOURCE_VERSION:=b9cb689f3c4b78fb047216ed41d8c79424b1774f +PKG_SOURCE_VERSION:=7d7b33a0281b233757606bb1fa4e9c056c57084f PKG_SOURCE_URL:=https://codeload.github.com/FRRouting/frr/tar.gz/$(PKG_SOURCE_VERSION)? -PKG_HASH:=bc4aa020f3725c499093ea3c98f9c21160fc1ae06439a698f39f6a9c55c2825a +PKG_HASH:=9899f2c6ecb6cce5bf7d56ddb9fc137dd8388f7201a52595c93d33572092fcaf PKG_MAINTAINER:=Lucian Cristian PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION) diff --git a/net/frr/patches/997-reverse_python_test.patch b/net/frr/patches/997-reverse_python_test.patch index 96ef9e2bc..04a2884c0 100644 --- a/net/frr/patches/997-reverse_python_test.patch +++ b/net/frr/patches/997-reverse_python_test.patch @@ -1,6 +1,6 @@ --- a/configure.ac +++ b/configure.ac -@@ -833,7 +833,6 @@ fi +@@ -835,7 +835,6 @@ fi # AS_IF([test "$host" = "$build"], [ diff --git a/net/frr/patches/999-thread_reverse.patch b/net/frr/patches/999-thread_reverse.patch index 740c83745..e7bf99e38 100644 --- a/net/frr/patches/999-thread_reverse.patch +++ b/net/frr/patches/999-thread_reverse.patch @@ -1,6 +1,6 @@ --- a/lib/thread.c +++ b/lib/thread.c -@@ -867,13 +867,9 @@ static void thread_free(struct thread_ma +@@ -870,13 +870,9 @@ static void thread_free(struct thread_ma XFREE(MTYPE_THREAD, thread); } @@ -16,7 +16,7 @@ /* * If timer_wait is null here, that means poll() should block * indefinitely, unless the thread_master has overridden it by setting -@@ -904,58 +900,15 @@ static int fd_poll(struct thread_master +@@ -907,58 +903,15 @@ static int fd_poll(struct thread_master rcu_assert_read_unlocked(); /* add poll pipe poker */ @@ -82,7 +82,7 @@ while (read(m->io_pipe[0], &trash, sizeof(trash)) > 0) ; -@@ -1762,7 +1715,7 @@ struct thread *thread_fetch(struct threa +@@ -1768,7 +1721,7 @@ struct thread *thread_fetch(struct threa struct timeval zerotime = {0, 0}; struct timeval tv; struct timeval *tw = NULL; @@ -91,7 +91,7 @@ int num = 0; do { -@@ -1838,14 +1791,14 @@ struct thread *thread_fetch(struct threa +@@ -1844,14 +1797,14 @@ struct thread *thread_fetch(struct threa pthread_mutex_unlock(&m->mtx); { diff --git a/net/https-dns-proxy/Makefile b/net/https-dns-proxy/Makefile index 81b01e5b9..4b519a9b2 100644 --- a/net/https-dns-proxy/Makefile +++ b/net/https-dns-proxy/Makefile @@ -2,11 +2,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=https-dns-proxy PKG_VERSION:=2022-10-15 -PKG_RELEASE:=8 +PKG_RELEASE:=10 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/aarond10/https_dns_proxy/ -PKG_SOURCE_DATE:=2022-10-15 +PKG_SOURCE_DATE:=$(PKG_VERSION) PKG_SOURCE_VERSION:=f52a85f3edabecfbab41d9244c63a1c6b8aaf49b PKG_MIRROR_HASH:=dd8a55255e8859a462fcfd736577fec40731b39a4783325640518745009b0dee PKG_MAINTAINER:=Stan Grishin diff --git a/net/https-dns-proxy/files/https-dns-proxy.init b/net/https-dns-proxy/files/https-dns-proxy.init index cae80f161..0e75a14d7 100755 --- a/net/https-dns-proxy/files/https-dns-proxy.init +++ b/net/https-dns-proxy/files/https-dns-proxy.init @@ -153,6 +153,7 @@ start_instance() { procd_set_param stdout 1 procd_set_param respawn procd_open_data + procd_add_mdns_service "$packageName" 'udp' "$port" "DNS over HTTPS proxy" json_add_string url "$url" if [ "$force_dns" -ne 0 ]; then json_add_array firewall @@ -279,7 +280,7 @@ service_triggers() { service_started() { procd_set_config_changed firewall; } service_stopped() { procd_set_config_changed firewall; } -restart() { procd_send_signal "$packageName"; } +restart() { procd_send_signal "$packageName"; rc_procd start_service; } dnsmasq_doh_server() { local cfg="$1" param="$2" address="${3:-127.0.0.1}" port="$4" i diff --git a/net/modemmanager/Makefile b/net/modemmanager/Makefile index ae07e6107..6cbd6f738 100644 --- a/net/modemmanager/Makefile +++ b/net/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.18.12 -PKG_RELEASE:=$(AUTORELEASE) +PKG_SOURCE_VERSION:=1.20.2 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_MIRROR_HASH:=5a32f90fc58345e2136f4196166a7a2b95a804a6b92adf1bfb5b7a1173a5b1a0 +PKG_MIRROR_HASH:=f138effc693456c5040ec22e17c0a8b41143c3b17b62437462995c297a9150dc PKG_MAINTAINER:=Nicholas Smith PKG_LICENSE:=GPL-2.0-or-later @@ -56,6 +56,7 @@ endef MESON_ARGS += \ -Dudev=false \ -Dudevdir=/lib/udev \ + -Dtests=false \ -Dsystemdsystemunitdir=no \ -Dsystemd_suspend_resume=false \ -Dsystemd_journal=false \ diff --git a/net/natmap/Makefile b/net/natmap/Makefile new file mode 100644 index 000000000..7c09f1716 --- /dev/null +++ b/net/natmap/Makefile @@ -0,0 +1,40 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=natmap +PKG_VERSION:=20221203 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/heiher/natmap/releases/download/$(PKG_VERSION) +PKG_HASH:=c7aa0bb1f3e057bf1fa987ad6166ba7c2e80510a89593e04f4fe0f36f1873338 + +PKG_MAINTAINER:=Richard Yu +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=License + +PKG_USE_MIPS16:=0 +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/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)) diff --git a/net/natmap/files/natmap-update.sh b/net/natmap/files/natmap-update.sh new file mode 100644 index 000000000..72afb94b8 --- /dev/null +++ b/net/natmap/files/natmap-update.sh @@ -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}" "$@" +} diff --git a/net/natmap/files/natmap.config b/net/natmap/files/natmap.config new file mode 100644 index 000000000..71931f6c5 --- /dev/null +++ b/net/natmap/files/natmap.config @@ -0,0 +1,12 @@ +config natmap + option enable '0' + option family '' + option udp_mode '1' + option interface '' + option interval '' + option stun_server 'stun.stunprotocol.org' + option http_server 'example.com' + option port '8080' + option forward_target '' + option notify_script '' + diff --git a/net/natmap/files/natmap.init b/net/natmap/files/natmap.init new file mode 100644 index 000000000..a9ff90539 --- /dev/null +++ b/net/natmap/files/natmap.init @@ -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:1' \ + 'family:string' \ + 'udp_mode:bool:0' \ + 'interface:string' \ + 'interval:uinteger' \ + 'stun_server:host' \ + 'http_server:host' \ + 'port:port' \ + 'forward_target:host' \ + 'notify_script:file' +} + +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"} + + [ "${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" + } + + if [ -n "$forward_target" ]; then + procd_append_param command -t "$forward_target" -p $port + else + procd_append_param command -b $port + fi + + [ -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 1 + procd_set_param stderr 1 + + 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 +} diff --git a/net/natmap/test.sh b/net/natmap/test.sh new file mode 100755 index 000000000..9ae615ccd --- /dev/null +++ b/net/natmap/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +"$1" 2>&1 | grep "$2" diff --git a/net/pbr/Makefile b/net/pbr/Makefile new file mode 100644 index 000000000..0f2842ed8 --- /dev/null +++ b/net/pbr/Makefile @@ -0,0 +1,201 @@ +# 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.0.0 +PKG_RELEASE:=1 +PKG_LICENSE:=GPL-3.0-or-later +PKG_MAINTAINER:=Stan Grishin + +include $(INCLUDE_DIR)/package.mk + +define Package/pbr/default + SECTION:=net + CATEGORY:=Network + SUBMENU:=VPN + PROVIDES:=pbr + TITLE:=Policy Based Routing Service + URL:=https://docs.openwrt.melmac.net/pbr/ + DEPENDS:=+ip-full +jshn +jsonfilter +resolveip + CONFLICTS:=vpnbypass vpn-policy-routing + PROVIDES:=vpnbypass vpn-policy-routing + PKGARCH:=all +endef + +define Package/pbr +$(call Package/pbr/default) + TITLE+= with nft/nft set support + DEPENDS+=+firewall4 +kmod-nft-core +kmod-nft-nat +nftables-json +endef + +define Package/pbr-iptables +$(call Package/pbr/default) + TITLE+= with iptables/ipset support + DEPENDS+=+ipset +iptables +kmod-ipt-ipset +iptables-mod-ipopt +endef + +define Package/pbr-netifd +$(call Package/pbr/default) + TITLE+= with netifd support +endef + +define Package/pbr/description +This service enables policy-based routing for WAN interfaces and various VPN tunnels. +This version supports OpenWrt with both fw3/ipset/iptables and fw4/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 fw3/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 fw3/ipset/iptables and fw4/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/firewall + $(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.firewall.include $(1)/usr/share/pbr/pbr.firewall.include + $(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/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/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 || true + 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... " + /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 service... " + /etc/init.d/pbr stop || true + echo -n "Removing rc.d symlink for pbr... " + /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... " + /etc/init.d/pbr enable && echo "OK" || echo "FAIL" + # echo -n "Installing netifd support for pbr... " + # /etc/init.d/pbr netifd install && echo "OK" || echo "FAIL" + # echo -n "Restarting network... " + # /etc/init.d/network restart && 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 service... " + /etc/init.d/pbr stop || true + # echo -n "Removing netifd support for pbr... " + # /etc/init.d/pbr netifd remove && echo "OK" || echo "FAIL" + echo -n "Removing rc.d symlink for pbr... " + /etc/init.d/pbr disable && echo "OK" || echo "FAIL" + # echo -n "Restarting network... " + # /etc/init.d/network restart && echo "OK" || echo "FAIL" + fi + exit 0 +endef + +$(eval $(call BuildPackage,pbr)) +$(eval $(call BuildPackage,pbr-iptables)) +#$(eval $(call BuildPackage,pbr-netifd)) diff --git a/net/pbr/files/README.md b/net/pbr/files/README.md new file mode 100644 index 000000000..494a97c13 --- /dev/null +++ b/net/pbr/files/README.md @@ -0,0 +1,3 @@ +# README + +README is available at [https://docs.openwrt.melmac.net/pbr/](https://docs.openwrt.melmac.net/pbr/). diff --git a/net/pbr/files/etc/config/pbr b/net/pbr/files/etc/config/pbr new file mode 100644 index 000000000..355fac205 --- /dev/null +++ b/net/pbr/files/etc/config/pbr @@ -0,0 +1,45 @@ +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' + +config policy + option name 'WireGuard Server' + option interface 'wan' + option src_port '51820' + option chain 'OUTPUT' + option proto 'udp' + option enabled '0' diff --git a/net/pbr/files/etc/config/pbr.iptables b/net/pbr/files/etc/config/pbr.iptables new file mode 100644 index 000000000..c62712644 --- /dev/null +++ b/net/pbr/files/etc/config/pbr.iptables @@ -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' diff --git a/net/pbr/files/etc/hotplug.d/firewall/70-pbr b/net/pbr/files/etc/hotplug.d/firewall/70-pbr new file mode 100755 index 000000000..c129006c5 --- /dev/null +++ b/net/pbr/files/etc/hotplug.d/firewall/70-pbr @@ -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 $ACTION of firewall" + /etc/init.d/pbr reload +fi diff --git a/net/pbr/files/etc/hotplug.d/iface/70-pbr b/net/pbr/files/etc/hotplug.d/iface/70-pbr new file mode 100644 index 000000000..172385a11 --- /dev/null +++ b/net/pbr/files/etc/hotplug.d/iface/70-pbr @@ -0,0 +1,8 @@ +#!/bin/sh +# shellcheck disable=SC1091,SC3060 +[ -s /etc/openwrt_release ] && . /etc/openwrt_release +[ "${DISTRIB_RELEASE//19.07}" = "$DISTRIB_RELEASE" ] && exit 0 +if [ -x /etc/init.d/pbr ] && /etc/init.d/pbr enabled; then + logger -t pbr "Reloading pbr $INTERFACE due to $ACTION of $INTERFACE ($DEVICE)" + /etc/init.d/pbr reload_interface "$INTERFACE" +fi diff --git a/net/pbr/files/etc/init.d/pbr.init b/net/pbr/files/etc/init.d/pbr.init new file mode 100755 index 000000000..cf807f433 --- /dev/null +++ b/net/pbr/files/etc/init.d/pbr.init @@ -0,0 +1,2394 @@ +#!/bin/sh /etc/rc.common +# Copyright 2020-2022 Stan Grishin (stangri@melmac.ca) +# shellcheck disable=SC1091,SC2018,SC2019,SC3043,SC3057,SC3060 + +# sysctl net.ipv4.conf.default.rp_filter=1 +# sysctl net.ipv4.conf.all.rp_filter=1 + +# shellcheck disable=SC2034 +START=94 +# shellcheck disable=SC2034 +USE_PROCD=1 + +if type extra_command >/dev/null 2>&1; then + extra_command 'status' "Generates output required to troubleshoot routing issues + Use '-d' option for more detailed output + Use '-p' option to automatically upload data under VPR paste.ee account + WARNING: while paste.ee uploads are unlisted, they are still publicly available + List domain names after options to include their lookup in report" + extra_command 'version' 'Show version information' + extra_command 'on_firewall_reload' ' Run service on firewall reload' + extra_command 'on_interface_reload' ' Run service on indicated interface reload' +else +# shellcheck disable=SC2034 + EXTRA_COMMANDS='on_firewall_reload on_interface_reload status version' +# shellcheck disable=SC2034 + EXTRA_HELP=" status Generates output required to troubleshoot routing issues + Use '-d' option for more detailed output + Use '-p' option to automatically upload data under VPR paste.ee account + WARNING: while paste.ee uploads are unlisted, they are still publicly available + List domain names after options to include their lookup in report" +fi + +readonly PKG_VERSION='dev-test' +readonly packageName='pbr' +readonly serviceName="$packageName $PKG_VERSION" +readonly serviceTrapSignals='exit SIGHUP SIGQUIT SIGKILL' +readonly packageConfigFile="/etc/config/${packageName}" +readonly nftTempFile="/var/run/${packageName}.nft" +#readonly nftPermFile="/etc/nftables.d/table-post/30-pbr.nft" +readonly dnsmasqFile="/var/dnsmasq.d/${packageName}" +readonly sharedMemoryOutput="/dev/shm/$packageName-output" +readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m' +readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m' +readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m' +readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m' +readonly _ERROR_='\033[0;31mERROR\033[0m' +readonly _WARNING_='\033[0;33mWARNING\033[0m' +readonly ip_full='/usr/libexec/ip-full' +readonly ipTablePrefix='pbr' +# shellcheck disable=SC2155 +readonly iptables="$(command -v iptables)" +# shellcheck disable=SC2155 +readonly ip6tables="$(command -v ip6tables)" +# shellcheck disable=SC2155 +readonly ipset="$(command -v ipset)" +readonly ipsPrefix='pbr' +readonly iptPrefix='PBR' +# shellcheck disable=SC2155 +readonly agh="$(command -v AdGuardHome)" +readonly aghConfigFile='/etc/adguardhome.yaml' +readonly aghIpsetFile="/var/run/${packageName}.adguardhome.ipsets" +# shellcheck disable=SC2155 +readonly nft="$(command -v nft)" +readonly nftTable="fw4" +readonly nftPrefix='pbr' +readonly chainsList='forward input output postrouting prerouting' + +# package config options +boot_timeout= +enabled= +fw_mask= +icmp_interface= +ignored_interface= +ipv6_enabled= +procd_boot_delay= +procd_reload_delay= +resolver_set= +rule_create_option= +secure_reload= +strict_enforcement= +supported_interface= +verbosity= +wan_ip_rules_priority= +wan_mark= + +# run-time +gatewaySummary= +errorSummary= +warningSummary= +wanIface4= +wanIface6= +ifaceMark= +ifaceTableID= +ifacePriority= +ifacesAll= +ifacesSupported= +wanGW4= +wanGW6= +serviceStartTrigger= +processPolicyError= +processPolicyWarning= +resolver_set_supported= +nftPrevParam4= +nftPrevParam6= + + +get_text() { + local r + case "$1" in + errorConfigValidation) r="Config ($packageConfigFile) validation failure!";; + errorNoIpFull) r="ip-full binary cannot be found!";; + errorNoIpset) r="Resolver set support (${resolver_set}) requires ipset, but ipset binary cannot be found!";; + errorNoNft) r="Resolver set support (${resolver_set}) requires nftables, but nft binary cannot be found!";; + errorResolverNotSupported) r="Resolver set (${resolver_set}) is not supported on this system!";; + errorServiceDisabled) r="The ${packageName} service is currently disabled!";; + errorNoWanGateway) r="The ${serviceName} service failed to discover WAN gateway!";; + errorIpsetNameTooLong) r="The ipset name '%s' is longer than allowed 31 characters!";; + errorNftsetNameTooLong) r="The nft set name '%s' is longer than allowed 31 characters!";; + errorUnexpectedExit) r="Unexpected exit or service termination: '%s'!";; + errorPolicyNoSrcDest) r="Policy '%s' has no source/destination parameters!";; + errorPolicyNoInterface) r="Policy '%s' has no assigned interface!";; + errorPolicyUnknownInterface) r="Policy '%s' has an unknown interface!";; + errorPolicyProcess) r="%s";; + errorFailedSetup) r="Failed to set up '%s'!";; + errorFailedReload) r="Failed to reload '%s'!";; + errorUserFileNotFound) r="Custom user file '%s' not found or empty!";; + ererrorUserFileSyntax) r="Syntax error in custom user file '%s'!";; + errorUserFileRunning) r="Error running custom user file '%s'!";; + errorUserFileNoCurl) r="Use of 'curl' is detected in custom user file '%s', but 'curl' isn't installed!";; + errorNoGateways) r="Failed to set up any gateway!";; + warningResolverNotSupported) r="Resolver set (${resolver_set}) is not supported on this system.";; + warningAGHVersionTooLow) r="Installed AdGuardHome (%s) doesn't support 'ipset_file' option.";; + warningPolicyProcess) r="%s";; + esac + echo "$r" +} + +version() { echo "$PKG_VERSION"; } +output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; } +output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; } +output_fail() { s=1; output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; } +output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; } +str_replace() { printf "%b" "$1" | sed -e "s/$(printf "%b" "$2")/$(printf "%b" "$3")/g"; } +str_replace() { echo "${1//$2/$3}"; } +str_contains() { [ -n "$1" ] &&[ -n "$2" ] && [ "${1//$2}" != "$1" ]; } +is_greater() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; } +is_greater_or_equal() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" = "$2"; } +str_contains_word() { echo "$1" | grep -q -w "$2"; } +str_to_lower() { echo "$1" | tr 'A-Z' 'a-z'; } +str_to_upper() { echo "$1" | tr 'a-z' 'A-Z'; } +str_extras_to_underscore() { echo "$1" | tr '[\. ~`!@#$%^&*()\+/,<>?//;:]' '_'; } +str_extras_to_space() { echo "$1" | tr ';{}' ' '; } +debug() { local i j; for i in "$@"; do eval "j=\$$i"; echo "${i}: ${j} "; done; } +output() { +# Can take a single parameter (text) to be output at any verbosity +# Or target verbosity level and text to be output at specifc verbosity + local msg memmsg logmsg + verbosity="${verbosity:-2}" + if [ "$#" -ne 1 ]; then + if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; else return 0; fi + fi + [ -t 1 ] && printf "%b" "$1" + 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:-service}" "$(printf "%b" "$logmsg")" + rm -f "$sharedMemoryOutput" + else + printf "%b" "$msg" >> "$sharedMemoryOutput" + fi +} +is_present() { command -v "$1" >/dev/null 2>&1; } +is_installed() { [ -s "/usr/lib/opkg/info/${1}.control" ]; } +is_variant_installed() { [ "$(echo /usr/lib/opkg/info/"${1}"*.control)" != "/usr/lib/opkg/info/${1}*.control" ]; } +is_nft() { [ -x "$nft" ] && ! str_contains "$resolver_set" 'ipset' && "$nft" list chains inet | grep -q "${nftPrefix}_prerouting"; } +_build_ifaces_all() { ifacesAll="${ifacesAll}${1} "; } +_build_ifaces_supported() { is_supported_interface "$1" && ifacesSupported="${ifacesSupported}${1} "; } +pbr_find_iface() { + local iface i param="$2" + [ "$param" = 'wan6' ] || param='wan' + "network_find_${param}" iface + is_tunnel "$iface" && unset iface + if [ -z "$iface" ]; then + for i in $ifacesAll; do + if "is_${param}" "$i"; then break; else unset i; fi + done + fi + eval "$1"='${iface:-$i}' +} +pbr_get_gateway() { + local iface="$2" dev="$3" gw + network_get_gateway gw "$iface" true +# if [ -z "$gw" ] || [ "$gw" = '0.0.0.0' ]; then +# gw="$(ubus call "network.interface.${iface}" status | jsonfilter -e "@.route[0].nexthop")" +# fi + if [ -z "$gw" ] || [ "$gw" = '0.0.0.0' ]; then + gw="$($ip_full -4 a list dev "$dev" 2>/dev/null | grep inet | awk '{print $2}' | awk -F "/" '{print $1}')" + fi + eval "$1"='$gw' +} +pbr_get_gateway6() { + local iface="$2" dev="$3" gw + network_get_gateway6 gw "$iface" true + if [ -z "$gw" ] || [ "$gw" = '::/0' ] || [ "$gw" = '::0/0' ] || [ "$gw" = '::' ]; then + gw="$($ip_full -6 a list dev "$dev" 2>/dev/null | grep inet6 | awk '{print $2}')" + fi + eval "$1"='$gw' +} +is_dslite() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:6}" = "dslite" ]; } +is_l2tp() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:4}" = "l2tp" ]; } +is_oc() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:11}" = "openconnect" ]; } +is_ovpn() { local dev; network_get_device dev "$1"; [ "${dev:0:3}" = "tun" ] || [ "${dev:0:3}" = "tap" ] || [ -f "/sys/devices/virtual/net/${dev}/tun_flags" ]; } +is_pptp() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:4}" = "pptp" ]; } +is_softether() { local dev; network_get_device dev "$1"; [ "${dev:0:4}" = "vpn_" ]; } +is_tor() { [ "$(str_to_lower "$1")" = "tor" ]; } +is_tor_running() { + local ret=0 + if [ -s "/etc/tor/torrc" ]; then + json_load "$(ubus call service list "{ 'name': 'tor' }")" + json_select 'tor'; json_select 'instances'; json_select 'instance1'; + json_get_var ret 'running'; json_cleanup + fi + if [ "$ret" = "0" ]; then return 1; else return 0; fi +} +is_wg() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:9}" = "wireguard" ]; } +is_tunnel() { is_dslite "$1" || is_l2tp "$1" || is_oc "$1" || is_ovpn "$1" || is_pptp "$1" || is_softether "$1" || is_tor "$1" || is_wg "$1"; } +is_wan() { [ "$1" = "$wanIface4" ] || { [ "${1##wan}" != "$1" ] && [ "${1##wan6}" = "$1" ]; } || [ "${1%%wan}" != "$1" ]; } +is_wan6() { [ -n "$wanIface6" ] && [ "$1" = "$wanIface6" ] || [ "${1/#wan6}" != "$1" ] || [ "${1/%wan6}" != "$1" ]; } +is_ignored_interface() { str_contains_word "$ignored_interface" "$1"; } +is_supported_interface() { str_contains_word "$supported_interface" "$1" || { ! is_ignored_interface "$1" && { is_wan "$1" || is_wan6 "$1" || is_tunnel "$1"; }; } || is_ignore_target "$1"; } +is_ignore_target() { [ "$(str_to_lower "$1")" = 'ignore' ]; } +is_mac_address() { expr "$1" : '[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]$' >/dev/null; } +is_ipv4() { expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; } +is_ipv6() { ! is_mac_address "$1" && str_contains "$1" ":"; } +is_family_mismatch() { ( is_netmask "${1//!}" && is_ipv6 "${2//!}" ) || ( is_ipv6 "${1//!}" && is_netmask "${2//!}" ); } +is_ipv6_link_local() { [ "${1:0:4}" = "fe80" ]; } +is_ipv6_unique_local() { [ "${1:0:2}" = "fc" ] || [ "${1:0:2}" = "fd" ]; } +is_ipv6_global() { [ "${1:0:4}" = "2001" ]; } +# is_ipv6_global() { is_ipv6 "$1" && ! is_ipv6_link_local "$1" && ! is_ipv6_link_local "$1"; } +is_list() { str_contains "$1" "," || str_contains "$1" " "; } +is_netmask() { local ip="${1%/*}"; [ "$ip" != "$1" ] && is_ipv4 "$ip"; } +is_domain() { str_contains "$1" '[a-zA-Z]'; } +is_phys_dev() { [ "${1:0:1}" = "@" ] && ip l show | grep -E -q "^\\d+\\W+${1:1}"; } +dnsmasq_kill() { killall -q -s HUP dnsmasq; } +dnsmasq_restart() { output 3 'Restarting dnsmasq '; if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then output_okn; else output_failn; fi; } +is_default_dev() { [ "$1" = "$($ip_full -4 r | grep -m1 'dev' | grep -Eso 'dev [^ ]*' | awk '{print $2}')" ]; } +is_supported_iface_dev() { local n dev; for n in $ifacesSupported; do network_get_device dev "$n"; [ "$1" = "$dev" ] && return 0; done; return 1; } +is_supported_protocol() { grep -o '^[^#]*' /etc/protocols | grep -w -v '0' | grep . | awk '{print $1}' | grep -q "$1"; } +is_service_running_iptables() { [ -x "$iptables" ] && "$iptables" -t mangle -L | grep -q "${iptPrefix}_PREROUTING" >/dev/null 2>&1; } +is_service_running_nft() { [ -x "$nft" ] && [ -n "$(get_mark_nft_chains)" ]; } +# atomic +# is_service_running_nft() { [ -x "$nft" ] && [ -s "$nftPermFile" ]; } +is_service_running() { if is_nft; then is_service_running_nft; else is_service_running_iptables; fi; } +is_netifd_table() { local iface="$1"; [ "$(uci -q get "network.${iface}.ip4table")" = "${packageName}_${iface%6}" ]; } +get_rt_tables_id() { grep "${packageName}_${iface}" /etc/iproute2/rt_tables | awk '{print $1;}'; } +get_rt_tables_next_id() { echo "$(($(sort -r -n /etc/iproute2/rt_tables | grep -o -E -m 1 "^[0-9]+")+1))"; } +_check_config() { local en; config_get_bool en "$1" 'enabled' 1; [ "$en" -gt 0 ] && _cfg_enabled=0; } +is_config_enabled() { + local cfg="$1" _cfg_enabled=1 + [ -n "$1" ] || return 1 + config_load "$packageName" + config_foreach _check_config "$cfg" + return "$_cfg_enabled" +} +# shellcheck disable=SC2016 +resolveip_to_ipt() { resolveip "$@" | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d'; } +# shellcheck disable=SC2016 +resolveip_to_nftset() { resolveip "$@" | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d' | tr '\n' ' '; } +resolveip_to_nftset4() { resolveip_to_nftset -4 "$@"; } +resolveip_to_nftset6() { [ -n "$ipv6_enabled" ] && resolveip_to_nftset -6 "$@"; } +# shellcheck disable=SC2016 +ipv4_leases_to_nftset() { [ -s '/tmp/dhcp.leases' ] || return 1; grep "$1" '/tmp/dhcp.leases' | awk '{print $3}' | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d' | tr '\n' ' '; } +# shellcheck disable=SC2016 +ipv6_leases_to_nftset() { [ -s '/tmp/hosts/odhcpd' ] || return 1; grep -v '^\#' '/tmp/hosts/odhcpd' | grep "$1" | awk '{print $1}' | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d' | tr '\n' ' '; } +# shellcheck disable=SC3037 +ports_to_nftset() { echo -ne "$value"; } +get_mark_ipt_chains() { [ -n "$(command -v iptables-save)" ] && iptables-save | grep ":${iptPrefix}_MARK_" | awk '{ print $1 }' | sed 's/://'; } +get_mark_nft_chains() { [ -x "$nft" ] && "$nft" list table inet "$nftTable" 2>/dev/null | grep chain | grep "${nftPrefix}_mark_" | awk '{ print $2 }'; } +get_ipsets() { [ -x "$(command -v ipset)" ] && ipset list | grep "${ipsPrefix}_" | awk '{ print $2 }'; } +get_nft_sets() { [ -x "$nft" ] && "$nft" list table inet "$nftTable" 2>/dev/null | grep 'set' | grep "${nftPrefix}_" | awk '{ print $2 }'; } +is_ipset_type_supported() { ipset help hash:"$1" >/dev/null 2>&1; } +ubus_get_status() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@.${packageName}.instances.main.data.status.${1}"; } +ubus_get_iface() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@.${packageName}.instances.main.data.interfaces[@.name='${1}']${2:+.$2}"; } + +load_package_config() { + config_load "$packageName" + config_get boot_timeout 'config' 'boot_timeout' '30' + config_get_bool enabled 'config' 'enabled' '0' + config_get fw_mask 'config' 'fw_mask' 'ff0000' + config_get icmp_interface 'config' 'icmp_interface' + config_get ignored_interface 'config' 'ignored_interface' + config_get_bool ipv6_enabled 'config' 'ipv6_enabled' '0' + config_get procd_boot_delay 'config' 'procd_boot_delay' '0' + config_get resolver_set 'config' 'resolver_set' + config_get rule_create_option 'config' 'rule_create_option' 'add' + config_get_bool secure_reload 'config' 'secure_reload' '1' + config_get_bool strict_enforcement 'config' 'strict_enforcement' '0' + config_get supported_interface 'config' 'supported_interface' + config_get verbosity 'config' 'verbosity' '2' + config_get wan_ip_rules_priority 'config' 'wan_ip_rules_priority' '30000' + config_get wan_mark 'config' 'wan_mark' '010000' + fw_mask="0x${fw_mask}" + wan_mark="0x${wan_mark}" + [ -n "$ipv6_enabled" ] && [ "$ipv6_enabled" -eq 0 ] && unset ipv6_enabled + . /lib/functions/network.sh + . /usr/share/libubox/jshn.sh + mkdir -p "${dnsmasqFile%/*}" + if is_nft; then + fw_maskXor="$(printf '%#x' "$((fw_mask ^ 0xffffffff))")" + fw_maskXor="${fw_maskXor:-0xff00ffff}" + else + case $rule_create_option in + insert|-i|-I) rule_create_option='-I';; + add|-a|-A|*) rule_create_option='-A';; + esac + fi +} + +load_environment() { + local param="$1" validation_result="$2" + load_package_config + + if [ "$param" = 'on_start' ]; then + if [ -n "$validation_result" ] && [ "$validation_result" != '0' ]; then + output "${_ERROR_}: The $packageName config validation failed!\\n" + output "Please check if the '$packageConfigFile' contains correct values for config options.\\n" + state add 'errorSummary' 'errorConfigValidation' + return 1 + fi + if [ "$enabled" -eq 0 ]; then + state add 'errorSummary' 'errorServiceDisabled' + return 1 + fi + if [ ! -x "$ip_full" ]; then + state add 'errorSummary' 'errorNoIpFull' + return 1 + fi + resolver 'check_support' + fi + + load_network "$param" +} + +load_network() { + config_load 'network' + [ -z "$ifacesAll" ] && config_foreach _build_ifaces_all 'interface' + [ -z "$ifacesSupported" ] && config_foreach _build_ifaces_supported 'interface' + pbr_find_iface wanIface4 'wan' + [ -n "$ipv6_enabled" ] && pbr_find_iface wanIface6 'wan6' + [ -n "$wanIface4" ] && network_get_gateway wanGW4 "$wanIface4" + [ -n "$wanIface6" ] && network_get_gateway6 wanGW6 "$wanIface6" + wanGW="${wanGW4:-$wanGW6}" +} + +is_wan_up() { + local sleepCount='1' + load_network + while [ -z "$wanGW" ] ; do + load_network + if [ $((sleepCount)) -gt $((boot_timeout)) ] || [ -n "$wanGW" ]; then break; fi + output "$serviceName waiting for wan gateway...\\n" + sleep 1 + network_flush_cache + sleepCount=$((sleepCount+1)) + done + if [ -n "$wanGW" ]; then + return 0 + else + state add 'errorSummary' 'errorNoWanGateway' + return 1 + fi +} + +# shellcheck disable=SC2086 +ipt4() { + local d + [ -x "$iptables" ] || return 1 + for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do + [ "$d" != "$*" ] && "$iptables" $d >/dev/null 2>&1 + done + d="$*"; "$iptables" $d >/dev/null 2>&1 +} + +# shellcheck disable=SC2086 +ipt6() { + local d + [ -n "$ipv6_enabled" ] || return 0 + [ -x "$ip6tables" ] || return 1 + for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do + [ "$d" != "$*" ] && "$ip6tables" $d >/dev/null 2>&1 + done + d="$*" + "$ip6tables" $d >/dev/null 2>&1 +} + +# shellcheck disable=SC2086 +ipt() { + local d failFlagIpv4=1 failFlagIpv6=1 + [ -x "$iptables" ] || return 1 + for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do + if [ "$d" != "$*" ]; then + "$iptables" $d >/dev/null 2>&1 + [ -x "$ip6tables" ] && "$ip6tables" $d >/dev/null 2>&1 + fi + done + d="$*"; "$iptables" $d >/dev/null 2>&1 && failFlagIpv4=0; + if [ -n "$ipv6_enabled" ] && [ -x "$ip6tables" ]; then + "$ip6tables" $d >/dev/null 2>&1 && failFlagIpv6=0 + fi + [ "$failFlagIpv4" -eq 0 ] || [ "$failFlagIpv6" -eq 0 ] +} + +# shellcheck disable=SC2086 +ips4() { [ -x "$ipset" ] && "$ipset" "$@" >/dev/null 2>&1; } +ips6() { [ -x "$ipset" ] && { if [ -n "$ipv6_enabled" ] && [ -n "$*" ]; then "$ipset" "$@" >/dev/null 2>&1; else return 1; fi; }; } +ips() { + local command="$1" iface="$2" target="${3:-dst}" type="${4:-ip}" uid="$5" comment="$6" param="$7" mark="$7" + local ipset4 ipset6 i + local ipv4_error=1 ipv6_error=1 + ipset4="${ipsPrefix}${iface:+_$iface}_4${target:+_$target}${type:+_$type}${uid:+_$uid}" + ipset6="${ipsPrefix}${iface:+_$iface}_6${target:+_$target}${type:+_$type}${uid:+_$uid}" + + [ -x "$ipset" ] || return 1 + + if [ "${#ipset4}" -gt 31 ]; then + state add 'errorSummary' 'errorIpsetNameTooLong' "$ipset4" + return 1 + fi + + case "$command" in + add) + ips4 -q -! add "$ipset4" comment "$comment" && ipv4_error=0 + ips6 -q -! add "$ipset6" comment "$comment" && ipv6_error=0 + ;; + add_agh_element) + [ -n "$ipv6_enabled" ] || unset ipset6 + echo "${param}/${ipset4}${ipset6:+,$ipset6}" >> "$aghIpsetFile" && ipv4_error=0 + ;; + add_dnsmasq_element) + [ -n "$ipv6_enabled" ] || unset ipset6 + echo "ipset=/${param}/${ipset4}${ipset6:+,$ipset6} # $comment" >> "$dnsmasqFile" && ipv4_error=0 + ;; + create) + ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0 + ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0 + ;; + create_agh_set) + ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0 + ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0 + ;; + create_dnsmasq_set) + ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0 + ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0 + ;; + create_user_set) + case "$type" in + ip|net) + ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0 + ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv4_error=0 + case "$target" in + dst) + ipt4 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" dst -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0 + ipt6 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" dst -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0 + ;; + src) + ipt4 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0 + ipt6 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0 + ;; + esac + ;; + mac) + ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0 + ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv4_error=0 + ipt4 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0 + ipt6 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0 + ;; + esac + ;; + delete|destroy) + ips4 -q -! destroy "$ipset4" && ipv4_error=0 + ips6 -q -! destroy "$ipset6" && ipv6_error=0 + ;; + delete_user_set) + ips4 -q -! destroy "$ipset4" && ipv4_error=0 + ips6 -q -! destroy "$ipset6" family inet6 && ipv6_error=0 + case "$type" in + ip|net) + case "$target" in + dst) + ipt4 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" dst -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0 + ipt6 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" dst -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0 + ;; + src) + ipt4 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0 + ipt6 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0 + ;; + esac + ;; + mac) + ipt4 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0 + ipt6 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0 + ;; + esac + ;; + flush|flush_user_set) + ips4 -q -! flush "$ipset4" && ipv4_error=0 + ips6 -q -! flush "$ipset6" && ipv6_error=0 + ;; + esac + return $ipv4_error || $ipv6_error +} + +# atomic +#nfta() { echo "$@" >> "$nftTempFile"; } +#nfta4() { echo "$@" >> "$nftTempFile"; } +#nfta6() { [ -z "$ipv6_enabled" ] || echo "$@" >> "$nftTempFile"; } +#nft() { nfta "$@"; [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; } +#nft4() { nfta "$@"; [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; } +#nft6() { nfta "$@"; [ -n "$ipv6_enabled" ] || return 0; [ -x "$nft" ] && [ -n "$*" ] && "$nft" "$@" >/dev/null 2>&1; } +nft() { [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; } +nft4() { [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; } +nft6() { [ -n "$ipv6_enabled" ] || return 0; [ -x "$nft" ] && [ -n "$*" ] && "$nft" "$@" >/dev/null 2>&1; } +nftset() { + local command="$1" iface="$2" target="${3:-dst}" type="${4:-ip}" uid="$5" comment="$6" param="$7" mark="$7" + local nftset4 nftset6 i param4 param6 + local ipv4_error=1 ipv6_error=1 + nftset4="${nftPrefix}${iface:+_$iface}_4${target:+_$target}${type:+_$type}${uid:+_$uid}" + nftset6="${nftPrefix}${iface:+_$iface}_6${target:+_$target}${type:+_$type}${uid:+_$uid}" + + [ -x "$nft" ] || return 1 + + if [ "${#nftset4}" -gt 255 ]; then + state add 'errorSummary' 'errorNftsetNameTooLong' "$nftset4" + return 1 + fi + + case "$command" in + add) + if is_netmask "$param" || is_ipv4 "$param" || is_ipv6 "$param" \ + || is_mac_address "$param" || is_list "$param"; then + nft4 add element inet "$nftTable" "$nftset4" "{ $param }" && ipv4_error=0 + nft6 add element inet "$nftTable" "$nftset6" "{ $param }" && ipv6_error=0 + else +# elif is_domain "$param"; then + if [ "$target" = 'src' ]; then + param4="$(ipv4_leases_to_nftset "$param")" + param6="$(ipv6_leases_to_nftset "$param")" + fi + [ -z "$param4" ] && param4="$(resolveip_to_nftset4 "$param")" + [ -z "$param6" ] && param6="$(resolveip_to_nftset6 "$param")" + nft4 add element inet "$nftTable" "$nftset4" "{ $param4 }" && ipv4_error=0 + nft6 add element inet "$nftTable" "$nftset6" "{ $param6 }" && ipv6_error=0 + fi + ;; + add_dnsmasq_element) + [ -n "$ipv6_enabled" ] || unset nftset6 + echo "nftset=/${param}/4#inet#${nftTable}#${nftset4}${nftset6:+,6#inet#${nftTable}#$nftset6} # $comment" >> "$dnsmasqFile" && ipv4_error=0 + ;; + create) + case "$type" in + ip|net) + nft4 add set inet "$nftTable" "$nftset4" "{ type ipv4_addr; flags interval; auto-merge; comment \"$comment\"; }" && ipv4_error=0 + nft6 add set inet "$nftTable" "$nftset6" "{ type ipv6_addr; flags interval; auto-merge; comment \"$comment\"; }" && ipv6_error=0 + ;; + mac) + nft4 add set inet "$nftTable" "$nftset4" "{ type ether_addr; flags interval; auto-merge; comment \"$comment\"; }" && ipv4_error=0 + nft6 add set inet "$nftTable" "$nftset6" "{ type ether_addr; flags interval; auto-merge; comment \"$comment\"; }" && ipv6_error=0 + ;; + esac + ;; + create_dnsmasq_set) + nft4 add set inet "$nftTable" "$nftset4" "{ type ipv4_addr; flags interval; auto-merge; comment \"$comment\"; }" && ipv4_error=0 + nft6 add set inet "$nftTable" "$nftset6" "{ type ipv6_addr; flags interval; auto-merge; comment \"$comment\"; }" && ipv6_error=0 + ;; + create_user_set) + case "$type" in + ip|net) + nft4 add set inet "$nftTable" "$nftset4" "{ type ipv4_addr; flags interval; auto-merge; policy memory; comment \"$comment\"; }" && ipv4_error=0 + nft6 add set inet "$nftTable" "$nftset6" "{ type ipv6_addr; flags interval; auto-merge; policy memory; comment \"$comment\"; }" && ipv6_error=0 + case "$target" in + dst) + nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0 + nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0 + ;; + src) + nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0 + nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0 + ;; + esac + ;; + mac) + nft4 add set inet "$nftTable" "$nftset4" "{ type ether_addr; flags interval; auto-merge; policy memory; comment \"$comment\"; }" && ipv4_error=0 + nft6 add set inet "$nftTable" "$nftset6" "{ type ether_addr; flags interval; auto-merge; policy memory; comment \"$comment\"; }" && ipv6_error=0 + nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0 + nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0 + ;; + esac + ;; + delete|destroy) + nft delete set inet "$nftTable" "$nftset4" && ipv4_error=0 + nft delete set inet "$nftTable" "$nftset6" && ipv6_error=0 + ;; + delete_user_set) + nft delete set inet "$nftTable" "$nftset4" && ipv4_error=0 + nft delete set inet "$nftTable" "$nftset6" && ipv6_error=0 + case "$type" in + ip|net) + case "$target" in + dst) + nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0 + nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0 + ;; + src) + nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0 + nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0 + ;; + esac + ;; + mac) + nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0 + nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0 + ;; + esac + ;; + flush|flush_user_set) + nft flush set inet "$nftTable" "$nftset4" && ipv4_error=0 + nft flush set inet "$nftTable" "$nftset6" && ipv6_error=0 + ;; + esac +# nft6 returns true if IPv6 support is not enabled + [ -z "$ipv6_enabled" ] && ipv6_error='1' + return $ipv4_error || $ipv6_error +} + +cleanup_dnsmasq() { [ -s "$dnsmasqFile" ] && resolverStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')" && rm "$dnsmasqFile" >/dev/null 2>&1; } +cleanup_main_chains() { + local i + for i in $chainsList; do + i="$(str_to_lower "$i")" + nft flush chain inet "$nftTable" "${nftPrefix}_${i}" + done + for i in $chainsList; do + i="$(str_to_upper "$i")" + ipt -t mangle -D "${i}" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}" + ipt -t mangle -F "${iptPrefix}_${i}" + ipt -t mangle -X "${iptPrefix}_${i}" + done +} + +cleanup_marking_chains() { + local i + for i in $(get_mark_nft_chains); do + nft flush chain inet "$nftTable" "$i" + nft delete chain inet "$nftTable" "$i" + done + for i in $(get_mark_ipt_chains); do + ipt -t mangle -F "$i" + ipt -t mangle -X "$i" + done +} + +cleanup_sets() { + local i + for i in $(get_nft_sets); do + nft flush set inet "$nftTable" "$i" + nft delete set inet "$nftTable" "$i" + done + for i in $(get_ipsets); do + ipset -q -! flush "$i" >/dev/null 2>&1 + ipset -q -! destroy "$i" >/dev/null 2>&1 + done +} + +state() { + local action="$1" param="$2" value="${3//#/_}" + shift 3 +# shellcheck disable=SC2124 + local extras="$@" + local line error_id error_extra label + case "$action" in + add) + line="$(eval echo "\$$param")" + eval "$param"='${line:+$line#}${value}${extras:+ $extras}' + ;; + json) + case "$param" in + errorSummary) + json_add_array 'errors';; + warningSummary) + json_add_array 'warnings';; + esac + if [ -n "$(eval echo "\$$param")" ]; then + while read -r line; do + if str_contains "$line" ' '; then +# url="${c##*|}" +# c="${c%|*}" + error_id="${line% *}" + error_extra="${line#* }" + else + error_id="$line" + fi + json_add_object + json_add_string 'id' "$error_id" + json_add_string 'extra' "$error_extra" + json_close_object + done </dev/null 2>&1 + rm -f "$aghIpsetFile" + rm -f "$dnsmasqFile" + return 0 + fi + + case "$resolver_set" in + ''|none) + case "$param" in + add_resolver_element) return 1;; + create_resolver_set) return 1;; + check_support) return 0;; + cleanup) return 0;; + configure) return 0;; + init) return 0;; + init_end) return 0;; + kill) return 0;; + reload) return 0;; + restart) return 0;; + compare_hash) return 0;; + store_hash) return 0;; + esac + ;; + adguardhome.ipset) + case "$param" in + add_resolver_element) + [ -n "$resolver_set_supported" ] && ips 'add_agh_element' "$@";; + create_resolver_set) + [ -n "$resolver_set_supported" ] && ips 'create_agh_set' "$@";; + check_support) + if [ ! -x "$ipset" ]; then + state add 'errorSummary' 'errorNoIpset' + return 1 + fi + if [ -n "$agh" ] && [ -s "$aghConfigFile" ]; then + agh_version="$($agh --version | sed 's|AdGuard Home, version v\(.*\)|\1|')" + if is_greater_or_equal "$agh_version" '0.107.13'; then + resolver_set_supported='true' + return 0 + else + state add 'warningSummary' 'warningAGHVersionTooLow' "$agh_version" + return 1 + fi + else + state add 'warningSummary' 'warningResolverNotSupported' + return 1 + fi + ;; + cleanup) + [ -z "$resolver_set_supported" ] && return 0 + rm -f "$aghIpsetFile" + sed -i "/ipset_file: ${aghIpsetFile}/d" "$aghConfigFile" >/dev/null 2>&1 + ;; + configure) + [ -z "$resolver_set_supported" ] && return 1 + mkdir -p "${aghIpsetFile%/*}" + touch "$aghIpsetFile" + sed -i '/ipset_file/d' "$aghConfigFile" >/dev/null 2>&1 + sed -i "/ ipset:/a \ \ ipset_file: $aghIpsetFile" "$aghConfigFile" + ;; + init) :;; + init_end) :;; + kill) + [ -n "$resolver_set_supported" ] && [ -n "$agh" ] && killall -q -s HUP "$agh";; + reload) + [ -z "$resolver_set_supported" ] && return 1 + output 3 'Reloading adguardhome ' + if /etc/init.d/adguardhome reload >/dev/null 2>&1; then + output_okn + return 0 + else + output_failn + return 1 + fi + ;; + restart) + [ -z "$resolver_set_supported" ] && return 1 + output 3 'Restarting adguardhome ' + if /etc/init.d/adguardhome restart >/dev/null 2>&1; then + output_okn + return 0 + else + output_failn + return 1 + fi + ;; + compare_hash) + [ -z "$resolver_set_supported" ] && return 1 + local resolverNewHash + if [ -s "$aghIpsetFile" ]; then + resolverNewHash="$(md5sum $aghIpsetFile | awk '{ print $1; }')" + fi + [ "$resolverNewHash" != "$resolverStoredHash" ] + ;; + store_hash) + [ -s "$aghIpsetFile" ] && resolverStoredHash="$(md5sum $aghIpsetFile | awk '{ print $1; }')";; + esac + ;; + dnsmasq.ipset) + case "$param" in + add_resolver_element) + [ -n "$resolver_set_supported" ] && ips 'add_dnsmasq_element' "$@";; + create_resolver_set) + [ -n "$resolver_set_supported" ] && ips 'create_dnsmasq_set' "$@";; + check_support) + if [ ! -x "$ipset" ]; then + state add 'errorSummary' 'errorNoIpset' + return 1 + fi + if ! dnsmasq -v 2>/dev/null | grep -q 'no-ipset' && dnsmasq -v 2>/dev/null | grep -q 'ipset'; then + resolver_set_supported='true' + return 0 + else + state add 'warningSummary' 'warningResolverNotSupported' + return 1 + fi + ;; + cleanup) + [ -n "$resolver_set_supported" ] && rm -f "$dnsmasqFile";; + configure) + [ -n "$resolver_set_supported" ] && mkdir -p "${dnsmasqFile%/*}";; + init) :;; + init_end) :;; + kill) + [ -n "$resolver_set_supported" ] && killall -q -s HUP dnsmasq;; + reload) + [ -z "$resolver_set_supported" ] && return 1 + output 3 'Reloading dnsmasq ' + if /etc/init.d/dnsmasq reload >/dev/null 2>&1; then + output_okn + return 0 + else + output_failn + return 1 + fi + ;; + restart) + [ -z "$resolver_set_supported" ] && return 1 + output 3 'Restarting dnsmasq ' + if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then + output_okn + return 0 + else + output_failn + return 1 + fi + ;; + compare_hash) + [ -z "$resolver_set_supported" ] && return 1 + local resolverNewHash + if [ -s "$dnsmasqFile" ]; then + resolverNewHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')" + fi + [ "$resolverNewHash" != "$resolverStoredHash" ] + ;; + store_hash) + [ -s "$dnsmasqFile" ] && resolverStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')";; + esac + ;; + dnsmasq.nftset) + case "$param" in + add_resolver_element) + [ -n "$resolver_set_supported" ] && nftset 'add_dnsmasq_element' "$@";; + create_resolver_set) + [ -n "$resolver_set_supported" ] && nftset 'create_dnsmasq_set' "$@";; + check_support) + if [ ! -x "$nft" ]; then + state add 'errorSummary' 'errorNoNft' + return 1 + fi + if ! dnsmasq -v 2>/dev/null | grep -q 'no-nftset' && dnsmasq -v 2>/dev/null | grep -q 'nftset'; then + resolver_set_supported='true' + return 0 + else + state add 'warningSummary' 'warningResolverNotSupported' + return 1 + fi + ;; + cleanup) + [ -n "$resolver_set_supported" ] && rm -f "$dnsmasqFile";; + configure) + [ -n "$resolver_set_supported" ] && mkdir -p "${dnsmasqFile%/*}";; + init) :;; + init_end) :;; + kill) + [ -n "$resolver_set_supported" ] && killall -q -s HUP dnsmasq;; + reload) + [ -z "$resolver_set_supported" ] && return 1 + output 3 'Reloading dnsmasq ' + if /etc/init.d/dnsmasq reload >/dev/null 2>&1; then + output_okn + return 0 + else + output_failn + return 1 + fi + ;; + restart) + [ -z "$resolver_set_supported" ] && return 1 + output 3 'Restarting dnsmasq ' + if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then + output_okn + return 0 + else + output_failn + return 1 + fi + ;; + compare_hash) + [ -z "$resolver_set_supported" ] && return 1 + local resolverNewHash + if [ -s "$dnsmasqFile" ]; then + resolverNewHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')" + fi + [ "$resolverNewHash" != "$resolverStoredHash" ] + ;; + store_hash) + [ -s "$dnsmasqFile" ] && resolverStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')";; + esac + ;; + unbound.ipset) + case "$param" in + add_resolver_element) :;; + create_resolver_set) :;; + check_support) :;; + cleanup) :;; + configure) :;; + init) :;; + init_end) :;; + kill) :;; + reload) :;; + restart) :;; + compare_hash) :;; + store_hash) :;; + esac + ;; + unbound.nftset) + case "$param" in + add_resolver_element) :;; + create_resolver_set) :;; + check_support) :;; + cleanup) :;; + configure) :;; + init) :;; + init_end) :;; + kill) :;; + reload) :;; + restart) :;; + compare_hash) :;; + store_hash) :;; + esac + ;; + esac +} + +trap_process() { +# verbosity=0 + output "\\n" + output "Unexpected exit or service termination: '${1}'!\\n" + state add 'errorSummary' 'errorUnexpectedExit' "$1" + traffic_killswitch 'remove' +} + +traffic_killswitch() { + local s=0 + case "$1" in + insert) + local lan_subnet wan_device + [ "$secure_reload" -ne 0 ] || return 0 + for i in $serviceTrapSignals; do +# shellcheck disable=SC2064 + trap "trap_process $i" "$i" + done + output 3 'Activating traffic killswitch ' + network_get_subnet lan_subnet 'lan' + network_get_physdev wan_device 'wan' + if is_nft; then + nft add chain inet "$nftTable" "${nftPrefix}_killswitch" '{ type filter hook forward priority 0; policy accept; }' || s=1 + nft add rule inet "$nftTable" "${nftPrefix}_killswitch" oifname "$wan_device" ip saddr "$lan_subnet" counter reject || s=1 +# nft add rule inet "$nftTable" "${nftPrefix}_killswitch" oifname '$wan_devices' ip saddr '$lan_subnet' counter reject || s=1 + else + ipt -N "${iptPrefix}_KILLSWITCH" || s=1 + ipt -A "${iptPrefix}_KILLSWITCH" -s "$lan_subnet" -o "$wan_device" -j REJECT || s=1 + ipt -I FORWARD -j "${iptPrefix}_KILLSWITCH" || s=1 + fi + if [ "$s" -eq 0 ]; then + output_okn + else + output_failn + fi + ;; + remove) + if [ "$secure_reload" -ne 0 ]; then + output 3 'Deactivating traffic killswitch ' + fi + if is_nft; then + nft flush chain inet "$nftTable" "${nftPrefix}_killswitch" || s=1 + nft delete chain inet "$nftTable" "${nftPrefix}_killswitch" || s=1 + else + ipt -D FORWARD -j "${iptPrefix}_KILLSWITCH" || s=1 + ipt -F "${iptPrefix}_KILLSWITCH" || s=1 + ipt -X "${iptPrefix}_KILLSWITCH" || s=1 + fi + if [ "$secure_reload" -ne 0 ]; then + if [ "$s" -eq 0 ]; then + output_okn + else + output_failn + fi + fi +# shellcheck disable=SC2086 + trap - $serviceTrapSignals + ;; + esac +} + +policy_routing_tor() { if is_nft; then policy_routing_tor_nft "$@"; else policy_routing_tor_iptables "$@"; fi; } +policy_routing_tor_iptables() { + local comment="$1" iface="$2" src_addr="$3" src_port="$4" dest_addr="$5" dest_port="$6" proto chain uid="$9" + proto="$(str_to_lower "$7")" + chain="$(str_to_upper "$8")" + chain="${chain:-PREROUTING}" + if [ -n "${src_addr}${src_port}${dest_port}" ]; then + processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'src_addr', 'src_port' and 'dest_port' for policy '$comment'\\n" + fi + if [ -n "$proto" ] && [ "$proto" != "all" ]; then + processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'proto' or set 'proto' to 'all' for policy '$comment'\\n" + fi + if [ "$chain" != "PREROUTING" ]; then + processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'chain' or set 'chain' to 'PREROUTING' for policy '$comment'\\n" + fi + resolver 'add_resolver_element' "$iface" 'dst' 'ip' '' "${comment}: $dest_addr" "$dest_addr" || \ + processPolicyError="${processPolicyError}${_ERROR_}: resolver 'add_resolver_element' '$iface' 'dst' 'ip' '${comment}: $dest_addr' '$dest_addr'\\n" + return 0 +} +policy_routing_tor_nft() { + local comment="$1" iface="$2" src_addr="$3" src_port="$4" dest_addr="$5" dest_port="$6" proto chain uid="$9" + proto="$(str_to_lower "$7")" + chain="$(str_to_lower "$8")" + chain="${chain:-prerouting}" + if [ -n "${src_addr}${src_port}${dest_port}" ]; then + processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'src_addr', 'src_port' and 'dest_port' for policy '$comment'\\n" + fi + if [ -n "$proto" ] && [ "$proto" != "all" ]; then + processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'proto' or set 'proto' to 'all' for policy '$comment'\\n" + fi + if [ "$chain" != "prerouting" ]; then + processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'chain' or set 'chain' to 'prerouting' for policy '$comment'\\n" + fi + resolver 'add_resolver_element' "$iface" 'dst' 'ip' '' "${comment}: $dest_addr" "$dest_addr" || \ + processPolicyError="${processPolicyError}${_ERROR_}: resolver 'add_resolver_element' '$iface' 'dst' 'ip' '${comment}: $dest_addr' '$dest_addr'\\n" + return 0 +} + +policy_routing() { if is_nft; then policy_routing_nft "$@"; else policy_routing_iptables "$@"; fi; } +policy_routing_iptables() { + local mark param4 param6 i negation value dest ipInsertOption="-A" + local ip4error='1' ip6error='1' + local name="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto chain uid="$9" + proto="$(str_to_lower "$7")" + chain="$(str_to_upper "$8")" + chain="${chain:-PREROUTING}" + mark=$(eval echo "\$mark_${iface//-/_}") + + if [ -n "$ipv6_enabled" ] && { is_ipv6 "$laddr" || is_ipv6 "$raddr"; }; then + processPolicyError="${processPolicyError}${_ERROR_}: Skipping IPv6 policy '$name' as IPv6 support is disabled\\n" + return 1 + fi + + if [ -n "$mark" ]; then + dest="-g ${iptPrefix}_MARK_${mark}" + elif [ "$iface" = "ignore" ]; then + dest="-j RETURN" + else + processPolicyError="${processPolicyError}${_ERROR_}: Unknown fw_mark for ${iface}\\n" + return 1 + fi + + if [ -z "$proto" ]; then + if [ -n "$lport" ] || [ -n "$rport" ]; then + proto='tcp udp' + else + proto='all' + fi + fi + + if is_family_mismatch "$laddr" "$raddr"; then + processPolicyError="${processPolicyError}${_ERROR_}: Mismatched IP family between '$laddr' and '$raddr' in policy '$name'\\n" + return 1 + fi + + for i in $proto; do + if [ "$i" = 'all' ]; then + param4="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest" + param6="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest" + elif ! is_supported_protocol "$i"; then + processPolicyError="${processPolicyError}${_ERROR_}: Unknown protocol '$i' in policy '$name'\\n" + return 1 + else + param4="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest -p $i" + param6="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest -p $i" + fi + + if [ -n "$laddr" ]; then + if [ "${laddr:0:1}" = "!" ]; then + negation='!'; value="${laddr:1}" + else + unset negation; value="$laddr"; + fi + if is_phys_dev "$value"; then + param4="$param4 $negation -m physdev --physdev-in ${value:1}" + param6="$param6 $negation -m physdev --physdev-in ${value:1}" + elif is_netmask "$value"; then + local target='src' type='net' + if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $laddr" && \ + ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $laddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + else + param4="$param4 $negation -s $value" + param6="$param6 $negation -s $value" + fi + elif is_mac_address "$value"; then + local target='src' type='mac' + if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $laddr" && \ + ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $laddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + else + param4="$param4 -m mac $negation --mac-source $value" + param6="$param6 -m mac $negation --mac-source $value" + fi + else + local target='src' type='ip' + if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $laddr" && \ + ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $laddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + else + param4="$param4 $negation -s $(resolveip_to_ipt -4 "$value")" + param6="$param6 $negation -s $(resolveip_to_ipt -6 "$value")" + fi + fi + fi + + if [ -n "$lport" ]; then + if [ "${lport:0:1}" = "!" ]; then + negation='!'; value="${lport:1}" + else + unset negation; value="$lport"; + fi + param4="$param4 -m multiport $negation --sport ${value//-/:}" + param6="$param6 -m multiport $negation --sport ${value//-/:}" + fi + + if [ -n "$raddr" ]; then + if [ "${raddr:0:1}" = "!" ]; then + negation='!'; value="${raddr:1}" + else + unset negation; value="$raddr"; + fi + if is_netmask "$value"; then + local target='dst' type='net' + if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \ + ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + else + param4="$param4 $negation -d $value" + param6="$param6 $negation -d $value" + fi + elif is_domain "$value"; then + local target='dst' type='ip' + if resolver 'create_resolver_set' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \ + resolver 'add_resolver_element' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + elif ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \ + ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + else + param4="$param4 $negation -d $(resolveip_to_ipt -4 "$value")" + param6="$param6 $negation -d $(resolveip_to_ipt -6 "$value")" + fi + else + local target='dst' type='ip' + if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \ + ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then + param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target" + param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target" + else + param4="$param4 $negation -d $value" + param6="$param6 $negation -d $value" + fi + fi + fi + + if [ -n "$rport" ]; then + if [ "${rport:0:1}" = "!" ]; then + negation='!'; value="${rport:1}" + else + unset negation; value="$rport"; + fi + param4="$param4 -m multiport $negation --dport ${value//-/:}" + param6="$param6 -m multiport $negation --dport ${value//-/:}" + fi + + if [ -n "$name" ]; then + param4="$param4 -m comment --comment $(str_extras_to_underscore "$name")" + param6="$param6 -m comment --comment $(str_extras_to_underscore "$name")" + fi + + local ipv4_error='0' ipv6_error='0' + if [ "$param4" = "$param6" ]; then + ipt4 "$param4" || ipv4_error='1' + else + ipt4 "$param4" || ipv4_error='1' + ipt6 "$param6" || ipv6_error='1' + fi + +# ipt6 returns true if IPv6 support is not enabled + [ -z "$ipv6_enabled" ] && ipv6_error='1' + if [ "$ipv4_error" -eq '1' ] && [ "$ipv6_error" -eq '1' ]; then + if [ -n "$ipv6_enabled" ]; then + processPolicyError="${processPolicyError}${_ERROR_}: Policy insertion failed for both IPv4 and IPv6!\\n" + processPolicyError="${processPolicyError}${_ERROR_}: iptables $param4\\n" + processPolicyError="${processPolicyError}${_ERROR_}: iptables $param6\\n" + else + processPolicyError="${processPolicyError}${_ERROR_}: iptables $param4\\n" + fi + fi + + done +} +policy_routing_nft() { + local mark param4 param6 i negation value dest nftInsertOption='add' + local ip4Flag='ip' ip6Flag='ip6' + local name="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto chain uid="$9" + proto="$(str_to_lower "$7")" + chain="$(str_to_lower "$8")" + chain="${chain:-prerouting}" + mark=$(eval echo "\$mark_${iface//-/_}") + + if [ -z "$ipv6_enabled" ] && { is_ipv6 "$src_addr" || is_ipv6 "$dest_addr"; }; then + processPolicyError="${processPolicyError}${_ERROR_}: Skipping IPv6 policy '$name' as IPv6 support is disabled\\n" + return 1 + fi + + if [ -n "$mark" ]; then + dest="goto ${nftPrefix}_mark_${mark}" + elif [ "$iface" = "ignore" ]; then + dest="return" + else + processPolicyError="${processPolicyError}${_ERROR_}: Unknown packet mark for ${iface}\\n" + return 1 + fi + + if is_family_mismatch "$src_addr" "$dest_addr"; then + processPolicyError="${processPolicyError}${_ERROR_}: Mismatched IP family between '$src_addr' and '$dest_addr' in policy '$name'\\n" + return 1 + fi + + if [ -n "$proto" ] && ! is_supported_protocol "$proto"; then + processPolicyError="${processPolicyError}${_ERROR_}: Unknown protocol '$i' in policy '$name'\\n" + return 1 + fi + + if [ -n "$src_addr" ]; then + if [ "${src_addr:0:1}" = "!" ]; then + negation='!='; value="${src_addr:1}" + else + unset negation; value="$src_addr"; + fi + if is_phys_dev "$value"; then + param4="$param4 iifname $negation ${value:1}" + param6="$param6 iifname $negation ${value:1}" + elif is_mac_address "$value"; then + local target='src' type='mac' + if nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \ + nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then + param4="$param4 ether saddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}" + param6="$param6 ether saddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}" + else + param4="$param4 ether saddr $negation $value" + param6="$param6 ether saddr $negation $value" + fi + else + local target='src' type='ip' + if nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \ + nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then + param4="$param4 $ip4Flag saddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}" + param6="$param6 $ip6Flag saddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}" + else + param4="$param4 $ip4Flag saddr $negation $value" + param6="$param6 $ip6Flag saddr $negation $value" + fi + fi + fi + + if [ -n "$dest_addr" ]; then + if [ "${dest_addr:0:1}" = "!" ]; then + negation='!='; value="${dest_addr:1}" + else + unset negation; value="$dest_addr"; + fi + if is_phys_dev "$value"; then + param4="$param4 oifname $negation ${value:1}" + param6="$param6 oifname $negation ${value:1}" + elif is_domain "$value"; then + local target='dst' type='ip' + if resolver 'create_resolver_set' "$iface" "$target" "$type" "$uid" "$name" && \ + resolver 'add_resolver_element' "$iface" "$target" "$type" "$uid" "$name" "$value"; then + param4="$param4 $ip4Flag daddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}" + param6="$param6 $ip6Flag daddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}" + elif nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \ + nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then + param4="$param4 $ip4Flag daddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}" + param6="$param6 $ip6Flag daddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}" + else + param4="$param4 $ip4Flag daddr $negation {$(resolveip_to_nftset4 "$value")}" + param6="$param6 $ip6Flag daddr $negation {$(resolveip_to_nftset6 "$value")}" + fi + else + local target='dst' type='ip' + if nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \ + nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then + param4="$param4 $ip4Flag daddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}" + param6="$param6 $ip6Flag daddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}" + else + param4="$param4 $ip4Flag daddr $negation $value" + param6="$param6 $ip6Flag daddr $negation $value" + fi + fi + fi + + if [ -n "${src_port}${dest_port}" ]; then + proto="${proto:-tcp}" + fi + + if [ -n "$src_port" ]; then + if [ "${src_port:0:1}" = "!" ]; then + negation='!='; value="${src_port:1}" + else + unset negation; value="$src_port"; + fi + param4="$param4 ${proto:+$proto }sport $negation {$(ports_to_nftset "$value")}" + param6="$param6 ${proto:+$proto }sport $negation {$(ports_to_nftset "$value")}" + fi + + if [ -n "$dest_port" ]; then + if [ "${dest_port:0:1}" = "!" ]; then + negation='!='; value="${dest_port:1}" + else + unset negation; value="$dest_port"; + fi + param4="$param4 ${proto:+$proto }dport $negation {$(ports_to_nftset "$value")}" + param6="$param6 ${proto:+$proto }dport $negation {$(ports_to_nftset "$value")}" + fi + + param4="$nftInsertOption rule inet $nftTable ${nftPrefix}_${chain} $param4 $dest comment \"$name\"" + param6="$nftInsertOption rule inet $nftTable ${nftPrefix}_${chain} $param6 $dest comment \"$name\"" + + local ipv4_error='0' ipv6_error='0' + if [ "$nftPrevParam4" != "$param4" ]; then + nft4 "$param4" || ipv4_error='1' + nftPrevParam4="$param4" + fi + if [ "$nftPrevParam6" != "$param6" ]; then + nft6 "$param6" || ipv6_error='1' + nftPrevParam6="$param6" + fi + +# nft6 returns true if IPv6 support is not enabled + [ -z "$ipv6_enabled" ] && ipv6_error='1' + if [ "$ipv4_error" -eq '1' ] && [ "$ipv6_error" -eq '1' ]; then + if [ -n "$ipv6_enabled" ]; then + processPolicyError="${processPolicyError}${_ERROR_}: Policy insertion failed for both IPv4 and IPv6!\\n" + processPolicyError="${processPolicyError}${_ERROR_}: nft '$param4'\\n" + processPolicyError="${processPolicyError}${_ERROR_}: nft '$param6'\\n" + else + processPolicyError="${processPolicyError}${_ERROR_}: nft '$param4'\\n" + fi + fi +} + +policy_process() { + local i j uid="$9" + if [ -z "$uid" ]; then # first non-recursive call + [ "$enabled" -gt 0 ] || return 0 + unset processPolicyWarning + unset processPolicyError + uid="$1" + if is_nft; then + chain="$(str_to_lower "$chain")" + else + chain="$(str_to_upper "$chain")" + fi + proto="$(str_to_lower "$proto")" + [ "$proto" = 'auto' ] && unset proto + [ "$proto" = 'all' ] && unset proto + output 2 "Routing '$name' via $interface " + if [ -z "${src_addr}${src_port}${dest_addr}${dest_port}" ]; then + state add 'errorSummary' 'errorPolicyNoSrcDest' "$name" + output_fail; return 1; + fi + if [ -z "$interface" ]; then + state add 'errorSummary' 'errorPolicyNoInterface' "$name" + output_fail; return 1; + fi + if ! is_supported_interface "$interface"; then + state add 'errorSummary' 'errorPolicyUnknownInterface' "$name" + output_fail; return 1; + fi + src_port="${src_port// / }"; src_port="${src_port// /,}"; src_port="${src_port//,\!/ !}"; + dest_port="${dest_port// / }"; dest_port="${dest_port// /,}"; dest_port="${dest_port//,\!/ !}"; + if is_nft; then + nftset 'flush' "$interface" "dst" "ip" "$uid" + nftset 'flush' "$interface" "src" "ip" "$uid" + nftset 'flush' "$interface" "src" "mac" "$uid" + else + ips 'flush' "$interface" "dst" "ip" "$uid" + ips 'flush' "$interface" "src" "ip" "$uid" + ips 'flush' "$interface" "src" "mac" "$uid" + fi + policy_process "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid" + if [ -n "$processPolicyWarning" ]; then + state add 'warningSummary' 'warningPolicyProcess' "$processPolicyWarning" + fi + if [ -n "$processPolicyError" ]; then + output_fail + state add 'errorSummary' 'errorPolicyProcess' "$processPolicyError" + else + output_ok + fi + else # recursive call, get options from passed variables + local name="$1" interface="$2" src_addr="$3" src_port="$4" dest_addr="$5" dest_port="$6" proto="$7" chain="$8" + if str_contains "$src_addr" '[ ;\{\}]'; then + for i in $(str_extras_to_space "$src_addr"); do [ -n "$i" ] && policy_process "$name" "$interface" "$i" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"; done + elif str_contains "$src_port" '[ ;\{\}]'; then + for i in $(str_extras_to_space "$src_port"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$i" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"; done + elif str_contains "$dest_addr" '[ ;\{\}]'; then + for i in $(str_extras_to_space "$dest_addr"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$src_port" "$i" "$dest_port" "$proto" "$chain" "$uid"; done + elif str_contains "$dest_port" '[ ;\{\}]'; then + for i in $(str_extras_to_space "$dest_port"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$i" "$proto" "$chain" "$uid"; done + elif str_contains "$proto" '[ ;\{\}]'; then + for i in $(str_extras_to_space "$proto"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$i" "$chain" "$uid"; done + else + if is_tor "$interface"; then + policy_routing_tor "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid" + else + policy_routing "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid" + fi + fi + fi +} + +interface_process_tor() { if is_nft; then interface_process_tor_nft "$@"; else interface_process_tor_iptables "$@"; fi; } +interface_process_tor_iptables() { + local s=0 iface="$1" action="$2" + local displayText set_name4 set_name6 + local dnsPort trafficPort + case "$action" in + reload) + displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}" + gatewaySummary="${gatewaySummary}${displayText}\\n" + ;; + destroy) + for i in $chainsList; do + i="$(str_to_upper "$i")" + ipt -t nat -D "${i}" -m mark --mark "0x0/${fw_mask}" -j "${nftPrefix}_${i}" + ipt -t nat -F "${nftPrefix}_${i}"; ipt -t nat -X "${nftPrefix}_${i}"; + done + ;; + create) + output 2 "Creating TOR redirects " + dnsPort="$(grep -m1 DNSPort /etc/tor/torrc | awk -F: '{print $2}')" + trafficPort="$(grep -m1 TransPort /etc/tor/torrc | awk -F: '{print $2}')" + dnsPort="${dnsPort:-9053}"; trafficPort="${trafficPort:-9040}"; + for i in $chainsList; do + ipt -t nat -N "${nftPrefix}_${i}" + ipt -t nat -A "$i" -m mark --mark "0x0/${fw_mask}" -j "${nftPrefix}_${i}" + done + if resolver 'create_resolver_set' "$iface" 'dst' 'ip' && ips 'flush' "$iface" 'dst' 'ip'; then + set_name4="${ipsPrefix}_${iface}_4_dst_ip" + for i in $chainsList; do + i="$(str_to_lower "$i")" + ipt -t nat -I "${nftPrefix}_${i}" -p udp -m udp --dport 53 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$dnsPort" -m comment --comment "TorDNS-UDP" || s=1 + ipt -t nat -I "${nftPrefix}_${i}" -p tcp -m tcp --dport 80 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTP-TCP" || s=1 + ipt -t nat -I "${nftPrefix}_${i}" -p udp -m udp --dport 80 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTP-UDP" || s=1 + ipt -t nat -I "${nftPrefix}_${i}" -p tcp -m tcp --dport 443 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTPS-TCP" || s=1 + ipt -t nat -I "${nftPrefix}_${i}" -p udp -m udp --dport 443 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTPS-UDP" || s=1 + done + else + s=1 + fi + displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}" + if [ "$s" -eq 0 ]; then + gatewaySummary="${gatewaySummary}${displayText}\\n" + output_ok + else + state add 'errorSummary' 'errorFailedSetup' "$displayText" + output_fail + fi + ;; + esac + return $s +} +interface_process_tor_nft() { + local s=0 iface="$1" action="$2" + local displayText set_name4 set_name6 + local dnsPort trafficPort + case "$action" in + reload) + displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}" + gatewaySummary="${gatewaySummary}${displayText}\\n" + ;; + destroy) + ;; + create) + output 2 "Creating TOR redirects " + dnsPort="$(grep -m1 DNSPort /etc/tor/torrc | awk -F: '{print $2}')" + trafficPort="$(grep -m1 TransPort /etc/tor/torrc | awk -F: '{print $2}')" + dnsPort="${dnsPort:-9053}"; trafficPort="${trafficPort:-9040}"; + if resolver 'create_resolver_set' "$iface" 'dst' 'ip' && nftset 'flush' "$iface" 'dst' 'ip'; then + set_name4="${nftPrefix}_${iface}_4_dst_ip" + set_name6="${nftPrefix}_${iface}_6_dst_ip" + nft meta nfproto ipv4 udp daddr "@${set_name4}" dport 53 counter redirect to :"$dnsPort" comment "Tor-DNS-UDP-ipv4" || s=1 + nft meta nfproto ipv4 tcp daddr "@${set_name4}" dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-TCP-ipv4" || s=1 + nft meta nfproto ipv4 udp daddr "@${set_name4}" dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-UDP-ipv4" || s=1 + nft meta nfproto ipv4 tcp daddr "@${set_name4}" dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-TCP-ipv4" || s=1 + nft meta nfproto ipv4 udp daddr "@${set_name4}" dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-UDP-ipv4" || s=1 + nft6 meta nfproto ipv6 udp daddr "@${set_name6}" dport 53 counter redirect to :"$dnsPort" comment "Tor-DNS-UDP-ipv6" || s=1 + nft6 meta nfproto ipv6 tcp daddr "@${set_name6}" dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-TCP-ipv6" || s=1 + nft6 meta nfproto ipv6 udp daddr "@${set_name6}" dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-UDP-ipv6" || s=1 + nft6 meta nfproto ipv6 tcp daddr "@${set_name6}" dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-TCP-ipv6" || s=1 + nft6 meta nfproto ipv6 udp daddr "@${set_name6}" dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-UDP-ipv6" || s=1 + else + s=1 + fi + displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}" + if [ "$s" -eq 0 ]; then + gatewaySummary="${gatewaySummary}${displayText}\\n" + output_ok + else + state add 'errorSummary' 'errorFailedSetup' "$displayText" + output_fail + fi + ;; + esac + return $s +} + +interface_routing() { + local action="$1" tid="$2" mark="$3" iface="$4" gw4="$5" dev="$6" gw6="$7" dev6="$8" priority="$9" + local dscp s=0 i ipv4_error=1 ipv6_error=1 + if [ -z "$tid" ] || [ -z "$mark" ] || [ -z "$iface" ]; then + return 1 + fi + case "$action" in + create) + if is_netifd_table "$iface"; then + ipv4_error=0 + $ip_full -4 rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + $ip_full -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1 + if is_nft; then + nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1 + nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1 + nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1 + else + ipt -t mangle -N "${iptPrefix}_MARK_${mark}" || ipv4_error=1 + ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j MARK --set-xmark "${mark}/${fw_mask}" || ipv4_error=1 + ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j RETURN || ipv4_error=1 + fi + if [ -n "$ipv6_enabled" ]; then + ipv6_error=0 + $ip_full -6 rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + $ip_full -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1 + fi + else + sed -i "/${ipTablePrefix}_${iface}/d" /etc/iproute2/rt_tables + $ip_full -4 rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + $ip_full -4 route flush table "$tid" >/dev/null 2>&1 + if [ -n "$gw4" ] || [ "$strict_enforcement" -ne 0 ]; then + ipv4_error=0 + echo "$tid ${ipTablePrefix}_${iface}" >> /etc/iproute2/rt_tables + if [ -z "$gw4" ]; then + $ip_full -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1 + else + $ip_full -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1 + fi + # shellcheck disable=SC2086 + while read -r i; do + i="$(echo "$i" | sed 's/ linkdown$//')" + i="$(echo "$i" | sed 's/ onlink$//')" + idev="$(echo "$i" | grep -Eso 'dev [^ ]*' | awk '{print $2}')" + if ! is_supported_iface_dev "$idev"; then + $ip_full -4 route add $i table "$tid" >/dev/null 2>&1 || ipv4_error=1 + fi + done << EOF + $($ip_full -4 route list table main) +EOF + $ip_full -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1 + if is_nft; then + nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1 + nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1 + nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1 + else + ipt -t mangle -N "${iptPrefix}_MARK_${mark}" || ipv4_error=1 + ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j MARK --set-xmark "${mark}/${fw_mask}" || ipv4_error=1 + ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j RETURN || ipv4_error=1 + fi + fi + if [ -n "$ipv6_enabled" ]; then + ipv6_error=0 + $ip_full -6 rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + $ip_full -6 route flush table "$tid" >/dev/null 2>&1 + if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strict_enforcement" -ne 0 ]; then + if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then + $ip_full -6 route add unreachable default table "$tid" || ipv6_error=1 + elif $ip_full -6 route list table main | grep -q " dev $dev6 "; then + while read -r i; do + i="$(echo "$i" | sed 's/ linkdown$//')" + i="$(echo "$i" | sed 's/ onlink$//')" + $ip_full -6 route add "$i" table "$tid" >/dev/null 2>&1 || ipv6_error=1 + done << EOF + $($ip_full -6 route list table main | grep " dev $dev6 ") +EOF + else + $ip_full -6 route add "$($ip_full -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1 + $ip_full -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1 + fi + fi + $ip_full -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1 + fi + fi + if [ "$ipv4_error" -eq 0 ] || [ "$ipv6_error" -eq 0 ]; then + dscp="$(uci -q get "${packageName}".config."${iface}"_dscp)" + if is_nft; then + if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then + nft add rule inet "$nftTable" "${nftPrefix}_prerouting ip dscp ${dscp} goto ${nftPrefix}_mark_${mark}" || s=1 + fi + if [ "$iface" = "$icmp_interface" ]; then + nft add rule inet "$nftTable" "${nftPrefix}_output ip protocol icmp goto ${nftPrefix}_mark_${mark}" || s=1 + fi + else + if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then + ipt -t mangle -I "${iptPrefix}_PREROUTING" -m dscp --dscp "${dscp}" -g "${iptPrefix}_MARK_${mark}" || s=1 + fi + if [ "$iface" = "$icmp_interface" ]; then + ipt -t mangle -I "${iptPrefix}_OUTPUT" -p icmp -g "${iptPrefix}_MARK_${mark}" || s=1 + fi + fi + else + s=1 + fi + return "$s" + ;; + create_user_set) + [ -z "$createUserSets" ] && return 0; + if is_nft; then + nftset 'create_user_set' "$iface" 'dst' 'ip' 'user' '' "$mark" || s=1 + nftset 'create_user_set' "$iface" 'src' 'ip' 'user' '' "$mark" || s=1 + nftset 'create_user_set' "$iface" 'src' 'mac' 'user' '' "$mark" || s=1 + else + ips 'create_user_set' "$iface" 'dst' 'ip' 'user' '' "$mark" || s=1 + ips 'create_user_set' "$iface" 'src' 'ip' 'user' '' "$mark" || s=1 + ips 'create_user_set' "$iface" 'dst' 'net' 'user' '' "$mark" || s=1 + ips 'create_user_set' "$iface" 'src' 'net' 'user' '' "$mark" || s=1 + ips 'create_user_set' "$iface" 'src' 'mac' 'user' '' "$mark" || s=1 + fi + return "$s" + ;; + delete|destroy) + $ip_full rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + if ! is_netifd_table "$iface"; then + $ip_full route flush table "$tid" >/dev/null 2>&1 + sed -i "/${ipTablePrefix}_${iface}/d" /etc/iproute2/rt_tables + fi + return "$s" + ;; + reload_interface) + is_netifd_table "$iface" && return 0; + ipv4_error=0 + $ip_full -4 rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + $ip_full -4 route flush table "$tid" >/dev/null 2>&1 + if [ -n "$gw4" ] || [ "$strict_enforcement" -ne 0 ]; then + if [ -z "$gw4" ]; then + $ip_full -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1 + else + $ip_full -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1 + fi + $ip_full rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1 + fi + if [ -n "$ipv6_enabled" ]; then + ipv6_error=0 + $ip_full -6 rule del fwmark "${mark}/${fw_mask}" table "$tid" >/dev/null 2>&1 + $ip_full -6 route flush table "$tid" >/dev/null 2>&1 + if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strict_enforcement" -ne 0 ]; then + if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then + $ip_full -6 route add unreachable default table "$tid" || ipv6_error=1 + elif $ip_full -6 route list table main | grep -q " dev $dev6 "; then + while read -r i; do + $ip_full -6 route add "$i" table "$tid" >/dev/null 2>&1 || ipv6_error=1 + done << EOF + $($ip_full -6 route list table main | grep " dev $dev6 ") +EOF + else + $ip_full -6 route add "$($ip_full -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1 + $ip_full -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1 + fi + fi + $ip_full -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1 + fi + if [ "$ipv4_error" -eq 0 ] || [ "$ipv6_error" -eq 0 ]; then + s=0 + else + s=1 + fi + return "$s" + ;; + esac +} + +json_add_gateway() { + local action="$1" tid="$2" mark="$3" iface="$4" gw4="$5" dev4="$6" gw6="$7" dev6="$8" priority="$9" default="${10}" + json_add_object '' + json_add_string name "$iface" + json_add_string device_ipv4 "$dev4" + json_add_string gateway_ipv4 "$gw4" + json_add_string device_ipv6 "$dev6" + json_add_string gateway_ipv6 "$gw6" + if [ -n "$default" ]; then + json_add_boolean default true + else + json_add_boolean default false + fi + json_add_string action "$action" + json_add_string table_id "$tid" + json_add_string mark "$mark" + json_add_string priority "$priority" + json_close_object +} + +interface_process() { + local gw4 gw6 dev dev6 s=0 dscp iface="$1" action="$2" reloadedIface="$3" + local displayText dispDev dispGw4 dispGw6 dispStatus + + if [ "$iface" = 'all' ] && [ "$action" = 'prepare' ]; then + config_load 'network' + ifaceMark="$(printf '0x%06x' "$wan_mark")" + ifacePriority="$wan_ip_rules_priority" + return 0 + fi + + is_supported_interface "$iface" || return 0 + is_wan6 "$iface" && return 0 + [ $((ifaceMark)) -gt $((fw_mask)) ] && return 1 + + network_get_device dev "$iface" + if is_wan "$iface" && [ -n "$wanIface6" ] && str_contains "$wanIface6" "$iface"; then + network_get_device dev6 "$wanIface6" + fi + + [ -z "$dev6" ] && dev6="$dev" + [ -z "$ifaceMark" ] && ifaceMark="$(printf '0x%06x' "$wan_mark")" + [ -z "$ifacePriority" ] && ifacePriority="$wan_ip_rules_priority" + + ifaceTableID="$(get_rt_tables_id "$iface")" + [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)" + eval "mark_${iface//-/_}"='$ifaceMark' + eval "tid_${iface//-/_}"='$ifaceTableID' + pbr_get_gateway gw4 "$iface" "$dev" + pbr_get_gateway6 gw6 "$iface" "$dev6" + dispGw4="${gw4:-0.0.0.0}" + dispGw6="${gw6:-::/0}" + [ "$iface" != "$dev" ] && dispDev="$dev" + is_default_dev "$dev" && dispStatus="${__OK__}" + displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}" + + case "$action" in + create) + output 2 "Setting up routing for '$displayText' " + if interface_routing 'create' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" && \ + interface_routing 'create_user_set' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"; then + json_add_gateway 'create' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" "$dispStatus" + gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n" + output_ok + else + state add 'errorSummary' 'errorFailedSetup' "$displayText" + output_fail + fi + ;; +# create_user_set) +# interface_routing 'create_user_set' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" +# ;; + destroy) + displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}" + output 2 "Removing routing for '$displayText' " + interface_routing 'destroy' "${ifaceTableID}" "${ifaceMark}" "${iface}" + output_ok + ;; + reload) + gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n" + ;; + reload_interface) + if [ "$iface" = "$reloadedIface" ]; then + output 2 "Reloading routing for '$displayText' " + if interface_routing 'reload_interface' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"; then + json_add_gateway 'reload_interface' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" "$dispStatus" + gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n" + output_ok + else + state add 'errorSummary' 'errorFailedReload' "$displayText" + output_fail + fi + else + gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n" + fi + ;; + esac +# ifaceTableID="$((ifaceTableID + 1))" + ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))" + ifacePriority="$((ifacePriority + 1))" + return $s +} + +user_file_process() { + local shellBin="${SHELL:-/bin/ash}" + [ "$enabled" -gt 0 ] || return 0 + if [ ! -s "$path" ]; then + state add 'errorSummary' 'errorUserFileNotFound' "$path" + output_fail + return 1 + fi + if ! $shellBin -n "$path"; then + state add 'errorSummary' 'ererrorUserFileSyntax' "$path" + output_fail + return 1 + fi + output 2 "Running $path " +# shellcheck disable=SC1090 + if ! . "$path"; then + state add 'errorSummary' 'errorUserFileRunning' "$path" + if grep -q -w 'curl' "$path" && ! is_present 'curl'; then + state add 'errorSummary' 'errorUserFileNoCurl' "$path" + fi + output_fail + return 1 + else + output_ok + return 0 + fi +} + +on_firewall_reload() { + if [ -z "$(ubus_get_status 'gateways')" ]; then # service is not running, do not start it on firewall reload + logger -t "$packageName" "Reload on firewall action aborted: service not running." + return 0; + else + rc_procd start_service 'on_firewall_reload' "$1" + fi +} +on_interface_reload() { rc_procd start_service 'on_interface_reload' "$1"; } + +start_service() { + local resolverStoredHash resolverNewHash i reloadedIface param="$1" + local createUserSets + + load_environment 'on_start' "$(load_validate_config)" || return 1 + is_wan_up || return 1 + rm -f "$nftTempFile" + + case "$param" in + on_boot) + serviceStartTrigger='on_start' + ;; + on_firewall_reload) + serviceStartTrigger='on_start' + ;; + on_interface_reload) + serviceStartTrigger='on_interface_reload' + reloadedIface="$2" + ;; + on_reload) + serviceStartTrigger='on_reload' + ;; + on_restart) + serviceStartTrigger='on_start' + ;; + esac + + if [ -n "$reloadedIface" ] && ! is_supported_interface "$reloadedIface"; then + return 0 + fi + + if [ -n "$(ubus_get_status error)" ] || [ -n "$(ubus_get_status warning)" ]; then + serviceStartTrigger='on_start' + unset reloadedIface + elif ! is_service_running; then + serviceStartTrigger='on_start' + unset reloadedIface + elif [ -z "$(ubus_get_status gateway)" ]; then + serviceStartTrigger='on_start' + unset reloadedIface + elif [ "$serviceStartTrigger" = 'on_interface_reload' ] && \ + [ -z "$(ubus_get_interface "$reloadedIface" 'gateway_4')" ] && \ + [ -z "$(ubus_get_interface "$reloadedIface" 'gateway_6')" ]; then + serviceStartTrigger='on_start' + unset reloadedIface + else + serviceStartTrigger="${serviceStartTrigger:-on_start}" + fi + + if is_config_enabled 'include'; then + createUserSets='true' + fi + + procd_open_instance "main" + procd_set_param command /bin/true + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_open_data + + case $serviceStartTrigger in + on_interface_reload) + output 1 "Reloading Interface: $reloadedIface " + json_add_array 'gateways' + interface_process 'all' 'prepare' + config_foreach interface_process 'interface' 'reload_interface' "$reloadedIface" + json_close_array + output 1 '\n' + ;; + on_reload) + traffic_killswitch 'insert' + resolver 'store_hash' + resolver 'cleanup_all' + resolver 'configure' + resolver 'init' + cleanup_main_chains + cleanup_sets + if ! is_nft; then + for i in $chainsList; do + i="$(str_to_upper "$i")" + ipt -t mangle -N "${iptPrefix}_${i}" + ipt -t mangle "$rule_create_option" "$i" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}" + done + fi + json_add_array 'gateways' + interface_process 'all' 'prepare' + config_foreach interface_process 'interface' 'reload' + interface_process_tor 'tor' 'destroy' + is_tor_running && interface_process_tor 'tor' 'reload' + json_close_array + if is_config_enabled 'policy'; then + output 1 'Processing policies ' + config_load "$packageName" + config_foreach load_validate_policy 'policy' policy_process + output 1 '\n' + fi + if is_config_enabled 'include'; then + traffic_killswitch 'remove' + output 1 'Processing user file(s) ' + config_load "$packageName" + config_foreach load_validate_include 'include' user_file_process + output 1 '\n' + resolver 'init_end' + resolver 'compare_hash' && resolver 'restart' + else + resolver 'init_end' + resolver 'compare_hash' && resolver 'restart' + traffic_killswitch 'remove' + fi + ;; + on_start|*) + traffic_killswitch 'insert' + resolver 'store_hash' + resolver 'cleanup_all' + resolver 'configure' + resolver 'init' + cleanup_main_chains + cleanup_sets + cleanup_marking_chains + if ! is_nft; then + for i in $chainsList; do + i="$(str_to_upper "$i")" + ipt -t mangle -N "${iptPrefix}_${i}" + ipt -t mangle "$rule_create_option" "$i" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}" + done + fi + output 1 'Processing interfaces ' + json_add_array 'gateways' + interface_process 'all' 'prepare' + config_foreach interface_process 'interface' 'create' + interface_process_tor 'tor' 'destroy' + is_tor_running && interface_process_tor 'tor' 'create' + json_close_array + ip route flush cache + output 1 '\n' + if is_config_enabled 'policy'; then + output 1 'Processing policies ' + config_load "$packageName" + config_foreach load_validate_policy 'policy' policy_process + output 1 '\n' + fi + if is_config_enabled 'include'; then + traffic_killswitch 'remove' + output 1 'Processing user file(s) ' + config_load "$packageName" + config_foreach load_validate_include 'include' user_file_process + output 1 '\n' + resolver 'init_end' + resolver 'compare_hash' && resolver 'restart' + else + resolver 'init_end' + resolver 'compare_hash' && resolver 'restart' + traffic_killswitch 'remove' + fi + ;; + esac + + if [ -z "$gatewaySummary" ]; then + state add 'errorSummary' 'errorNoGateways' + fi + json_add_object 'status' + [ -n "$gatewaySummary" ] && json_add_string 'gateways' "$gatewaySummary" + [ -n "$errorSummary" ] && json_add_string 'errors' "$errorSummary" + [ -n "$warningSummary" ] && json_add_string 'warnings' "$warningSummary" + if [ "$strict_enforcement" -ne 0 ] && str_contains "$gatewaySummary" '0.0.0.0'; then + json_add_string 'mode' "strict" + fi + json_close_object + procd_close_data + procd_close_instance +} + +service_started() { + if is_nft; then + [ -n "$gatewaySummary" ] && output "$serviceName (nft) started with gateways:\\n${gatewaySummary}" + else + [ -n "$gatewaySummary" ] && output "$serviceName (iptables) started with gateways:\\n${gatewaySummary}" + fi + state print 'errorSummary' + state print 'warningSummary' + if [ -n "$errorSummary" ]; then + return 2 + elif [ -n "$warningSummary" ]; then + return 1 + else + return 0 + fi +} + +service_triggers() { + local n + load_environment 'on_triggers' +# shellcheck disable=SC2034 + PROCD_RELOAD_DELAY=$(( procd_reload_delay * 1000 )) + procd_open_validate + load_validate_config + load_validate_policy + load_validate_include + procd_close_validate + procd_open_trigger + procd_add_reload_trigger 'openvpn' + procd_add_config_trigger "config.change" "${packageName}" /etc/init.d/${packageName} reload + for n in $ifacesSupported; do + procd_add_interface_trigger "interface.*" "$n" /etc/init.d/${packageName} on_interface_reload "$n" + done + procd_close_trigger + if [ "$serviceStartTrigger" = 'on_start' ]; then + output 3 "$serviceName monitoring interfaces: ${ifacesSupported}\\n" + fi +} + +stop_service() { + local i + load_environment 'on_stop' + is_service_running || return 0 + traffic_killswitch 'insert' + cleanup_main_chains + cleanup_sets + cleanup_marking_chains + output 1 'Resetting interfaces ' + config_load 'network' + config_foreach interface_process 'interface' 'destroy' + interface_process_tor 'tor' 'destroy' + output 1 "\\n" + ip route flush cache + unset ifaceMark + unset ifaceTableID + resolver 'store_hash' + resolver 'cleanup_all' + resolver 'compare_hash' && resolver 'restart' + traffic_killswitch 'remove' + if [ "$enabled" -ne 0 ]; then + if is_nft; then + output "$serviceName (nft) stopped "; output_okn; + else + output "$serviceName (iptables) stopped "; output_okn; + fi + fi +} + +status_service() { + local _SEPARATOR_='============================================================' + load_environment 'on_status' + if is_nft; then + status_service_nft "$@" + else + status_service_iptables "$@" + fi +} + +status_service_nft() { + local i dev dev6 wan_tid + + json_load "$(ubus call system board)"; json_select release; json_get_var dist distribution; json_get_var vers version + if [ -n "$wanIface4" ]; then + network_get_gateway wanGW4 "$wanIface4" + network_get_device dev "$wanIface4" + fi + if [ -n "$wanIface6" ]; then + network_get_device dev6 "$wanIface6" + wanGW6=$($ip_full -6 route show | grep -m1 " dev $dev6 " | awk '{print $1}') + [ "$wanGW6" = "default" ] && wanGW6=$($ip_full -6 route show | grep -m1 " dev $dev6 " | awk '{print $3}') + fi + while [ "${1:0:1}" = "-" ]; do param="${1//-/}"; eval "set_$param=1"; shift; done + [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support" + status="$serviceName running on $dist $vers." + [ -n "$wanIface4" ] && status="$status WAN (IPv4): ${wanIface4}/${dev}/${wanGW4:-0.0.0.0}." + [ -n "$wanIface6" ] && status="$status WAN (IPv6): ${wanIface6}/${dev6}/${wanGW6:-::/0}." + + echo "$_SEPARATOR_" + echo "$packageName - environment" + echo "$status" + echo "$_SEPARATOR_" + dnsmasq --version 2>/dev/null | sed '/^$/,$d' + echo "$_SEPARATOR_" + echo "$packageName chains - policies" + for i in forward input output prerouting postrouting; do + "$nft" list table inet "$nftTable" | sed -n "/chain ${nftPrefix}_${i} {/,/\t}/p" + done + echo "$_SEPARATOR_" + echo "$packageName chains - marking" + for i in $(get_mark_nft_chains); do + "$nft" list table inet "$nftTable" | sed -n "/chain ${i} {/,/\t}/p" + done + echo "$_SEPARATOR_" + echo "$packageName nft sets" + for i in $(get_nft_sets); do + "$nft" list table inet "$nftTable" | sed -n "/set ${i} {/,/\t}/p" + done + if [ -s "$dnsmasqFile" ]; then + echo "$_SEPARATOR_" + echo "dnsmasq sets" + cat "$dnsmasqFile" + fi +# echo "$_SEPARATOR_" +# ip rule list | grep "${packageName}_" + echo "$_SEPARATOR_" + tableCount="$(grep -c "${packageName}_" /etc/iproute2/rt_tables)" || tableCount=0 + wan_tid=$(($(get_rt_tables_next_id)-tableCount)) + i=0; while [ $i -lt $tableCount ]; do + echo "IPv4 table $((wan_tid + i)) route: $($ip_full -4 route show table $((wan_tid + i)) | grep default)" + echo "IPv4 table $((wan_tid + i)) rule(s):" + $ip_full -4 rule list table "$((wan_tid + i))" + i=$((i + 1)) + done +} + +status_service_iptables() { + local dist vers out id s param status set_d set_p tableCount i=0 dev dev6 j wan_tid + + json_load "$(ubus call system board)"; json_select release; json_get_var dist distribution; json_get_var vers version + if [ -n "$wanIface4" ]; then + network_get_gateway wanGW4 "$wanIface4" + network_get_device dev "$wanIface4" + fi + if [ -n "$wanIface6" ]; then + network_get_device dev6 "$wanIface6" + wanGW6=$($ip_full -6 route show | grep -m1 " dev $dev6 " | awk '{print $1}') + [ "$wanGW6" = "default" ] && wanGW6=$($ip_full -6 route show | grep -m1 " dev $dev6 " | awk '{print $3}') + fi + while [ "${1:0:1}" = "-" ]; do param="${1//-/}"; eval "set_$param=1"; shift; done + [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support" + status="$serviceName running on $dist $vers." + [ -n "$wanIface4" ] && status="$status WAN (IPv4): ${wanIface4}/${dev}/${wanGW4:-0.0.0.0}." + [ -n "$wanIface6" ] && status="$status WAN (IPv6): ${wanIface6}/${dev6}/${wanGW6:-::/0}." + { + echo "$status" + echo "$_SEPARATOR_" + dnsmasq --version 2>/dev/null | sed '/^$/,$d' + if [ -n "$1" ]; then + echo "$_SEPARATOR_" + echo "Resolving domains" + for i in $1; do + echo "$i: $(resolveip "$i" | tr '\n' ' ')" + done + fi + + echo "$_SEPARATOR_" + echo "Routes/IP Rules" + tableCount="$(grep -c "${packageName}_" /etc/iproute2/rt_tables)" || tableCount=0 + if [ -n "$set_d" ]; then route; else route | grep '^default'; fi + if [ -n "$set_d" ]; then ip rule list; fi + wan_tid=$(($(get_rt_tables_next_id)-tableCount)) + i=0; while [ $i -lt $tableCount ]; do + echo "IPv4 table $((wan_tid + i)) route: $($ip_full -4 route show table $((wan_tid + i)) | grep default)" + echo "IPv4 table $((wan_tid + i)) rule(s):" + $ip_full -4 rule list table "$((wan_tid + i))" + i=$((i + 1)) + done + + if [ -n "$ipv6_enabled" ]; then + i=0; while [ $i -lt $tableCount ]; do + $ip_full -6 route show table $((wan_tid + i)) | while read -r param; do + echo "IPv6 Table $((wan_tid + i)): $param" + done + i=$((i + 1)) + done + fi + + for j in Mangle NAT; do + if [ -z "$set_d" ]; then + for i in $chainsList; do + i="$(str_to_upper "$i")" + if iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_${i}" >/dev/null 2>&1; then + echo "$_SEPARATOR_" + echo "$j IP Table: $i" + iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_${i}" + if [ -n "$ipv6_enabled" ]; then + echo "$_SEPARATOR_" + echo "$j IPv6 Table: $i" + iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_${i}" + fi + fi + done + else + echo "$_SEPARATOR_" + echo "$j IP Table" + iptables -L -t "$(str_to_lower $j)" + if [ -n "$ipv6_enabled" ]; then + echo "$_SEPARATOR_" + echo "$j IPv6 Table" + iptables -L -t "$(str_to_lower $j)" + fi + fi + i=0; ifaceMark="$wan_mark"; + while [ $i -lt $tableCount ]; do + if iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_MARK_${ifaceMark}" >/dev/null 2>&1; then + echo "$_SEPARATOR_" + echo "$j IP Table MARK Chain: ${iptPrefix}_MARK_${ifaceMark}" + iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_MARK_${ifaceMark}" + ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))"; + fi + i=$((i + 1)) + done + done + + echo "$_SEPARATOR_" + echo "Current ipsets" + ipset save + if [ -s "$dnsmasqFile" ]; then + echo "$_SEPARATOR_" + echo "DNSMASQ sets" + cat "$dnsmasqFile" + fi + if [ -s "$aghIpsetFile" ]; then + echo "$_SEPARATOR_" + echo "AdGuardHome sets" + cat "$aghIpsetFile" + fi + echo "$_SEPARATOR_" + } | tee -a /var/${packageName}-support + if [ -n "$set_p" ]; then + printf "%b" "Pasting to paste.ee... " + if is_present 'curl' && is_variant_installed 'libopenssl' && is_installed 'ca-bundle'; then + json_init; json_add_string "description" "${packageName}-support" + json_add_array "sections"; json_add_object '0' + json_add_string "name" "$(uci -q get system.@system[0].hostname)" + json_add_string "contents" "$(cat /var/${packageName}-support)" + json_close_object; json_close_array; payload=$(json_dump) + out=$(curl -s -k "https://api.paste.ee/v1/pastes" -X "POST" -H "Content-Type: application/json" -H "X-Auth-Token:uVOJt6pNqjcEWu7qiuUuuxWQafpHhwMvNEBviRV2B" -d "$payload") + json_load "$out"; json_get_var id id; json_get_var s success + [ "$s" = "1" ] && printf "%b" "https://paste.ee/p/$id $__OK__\\n" || printf "%b" "$__FAIL__\\n" + [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support" + else + printf "%b" "${__FAIL__}\\n" + printf "%b" "${_ERROR_}: The curl, libopenssl or ca-bundle packages were not found!\\nRun 'opkg update; opkg install curl libopenssl ca-bundle' to install them.\\n" + fi + else + printf "%b" "Your support details have been logged to '/var/${packageName}-support'. $__OK__\\n" + fi +} + +# shellcheck disable=SC2120 +load_validate_config() { + uci_load_validate "$packageName" "$packageName" "$1" "${2}${3:+ $3}" \ + 'enabled:bool:0' \ + 'procd_boot_delay:integer:0' \ + 'strict_enforcement:bool:1' \ + 'secure_reload:bool:0' \ + 'ipv6_enabled:bool:0' \ + 'resolver_set:or("", "none", "dnsmasq.ipset", "dnsmasq.nftset")' \ + 'verbosity:range(0,2):1' \ + "wan_mark:regex('0x[A-Fa-f0-9]{8}'):0x010000" \ + "fw_mask:regex('0x[A-Fa-f0-9]{8}'):0xff0000" \ + 'icmp_interface:or("","ignore", uci("network", "@interface"))' \ + 'ignored_interface:list(uci("network", "@interface"))' \ + 'supported_interface:list(uci("network", "@interface"))' \ + 'boot_timeout:integer:30' \ + 'wan_ip_rules_priority:uinteger:30000' \ + 'rule_create_option:or("", "add", "insert"):add' \ + 'procd_reload_delay:integer:0' \ + 'webui_supported_protocol:list(string)' +} + +# shellcheck disable=SC2120 +load_validate_policy() { + local name + local enabled + local interface + local proto + local chain + local src_addr + local src_port + local dest_addr + local dest_port + uci_load_validate "$packageName" 'policy' "$1" "${2}${3:+ $3}" \ + 'name:string:Untitled' \ + 'enabled:bool:1' \ + 'interface:or(uci("network", "@interface"),"ignore"):wan' \ + 'proto:or(string)' \ + 'chain:or("", "forward", "input", "output", "prerouting", "postrouting", "FORWARD", "INPUT", "OUTPUT", "PREROUTING", "POSTROUTING"):prerouting' \ + 'src_addr:list(neg(or(host,network,macaddr,string)))' \ + 'src_port:list(neg(or(portrange,string)))' \ + 'dest_addr:list(neg(or(host,network,string)))' \ + 'dest_port:list(neg(or(portrange,string)))' +} + +# shellcheck disable=SC2120 +load_validate_include() { + local path= + local enabled= + uci_load_validate "$packageName" 'include' "$1" "${2}${3:+ $3}" \ + 'path:file' \ + 'enabled:bool:0' +} diff --git a/net/pbr/files/etc/uci-defaults/90-pbr b/net/pbr/files/etc/uci-defaults/90-pbr new file mode 100644 index 000000000..237ebac58 --- /dev/null +++ b/net/pbr/files/etc/uci-defaults/90-pbr @@ -0,0 +1,34 @@ +#!/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 + 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 + +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 + +exit 0 diff --git a/net/pbr/files/etc/uci-defaults/91-pbr b/net/pbr/files/etc/uci-defaults/91-pbr new file mode 100644 index 000000000..0d759c278 --- /dev/null +++ b/net/pbr/files/etc/uci-defaults/91-pbr @@ -0,0 +1,58 @@ +#!/bin/sh +# shellcheck disable=SC1091,SC3037,SC3043 + +readonly packageName='pbr' +readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m' + +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 diff --git a/net/pbr/files/usr/share/nftables.d/chain-post/mangle_forward/30-pbr.nft b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_forward/30-pbr.nft new file mode 100644 index 000000000..d11ad8472 --- /dev/null +++ b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_forward/30-pbr.nft @@ -0,0 +1 @@ +jump pbr_forward comment "Jump into pbr forward chain"; diff --git a/net/pbr/files/usr/share/nftables.d/chain-post/mangle_input/30-pbr.nft b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_input/30-pbr.nft new file mode 100644 index 000000000..b3ce9db95 --- /dev/null +++ b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_input/30-pbr.nft @@ -0,0 +1 @@ +jump pbr_input comment "Jump into pbr input chain"; diff --git a/net/pbr/files/usr/share/nftables.d/chain-post/mangle_output/30-pbr.nft b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_output/30-pbr.nft new file mode 100644 index 000000000..c98514bc5 --- /dev/null +++ b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_output/30-pbr.nft @@ -0,0 +1 @@ +jump pbr_output comment "Jump into pbr output chain"; diff --git a/net/pbr/files/usr/share/nftables.d/chain-post/mangle_postrouting/30-pbr.nft b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_postrouting/30-pbr.nft new file mode 100644 index 000000000..cd5d1b4d3 --- /dev/null +++ b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_postrouting/30-pbr.nft @@ -0,0 +1 @@ +jump pbr_postrouting comment "Jump into pbr postrouting chain"; diff --git a/net/pbr/files/usr/share/nftables.d/chain-post/mangle_prerouting/30-pbr.nft b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_prerouting/30-pbr.nft new file mode 100644 index 000000000..a4471d376 --- /dev/null +++ b/net/pbr/files/usr/share/nftables.d/chain-post/mangle_prerouting/30-pbr.nft @@ -0,0 +1 @@ +jump pbr_prerouting comment "Jump into pbr prerouting chain"; diff --git a/net/pbr/files/usr/share/nftables.d/table-post/30-pbr.nft b/net/pbr/files/usr/share/nftables.d/table-post/30-pbr.nft new file mode 100644 index 000000000..4dd9b2813 --- /dev/null +++ b/net/pbr/files/usr/share/nftables.d/table-post/30-pbr.nft @@ -0,0 +1,5 @@ +chain pbr_forward {} +chain pbr_input {} +chain pbr_output {} +chain pbr_prerouting {} +chain pbr_postrouting {} diff --git a/net/pbr/files/usr/share/pbr/pbr.firewall.include b/net/pbr/files/usr/share/pbr/pbr.firewall.include new file mode 100644 index 000000000..3fe906ee1 --- /dev/null +++ b/net/pbr/files/usr/share/pbr/pbr.firewall.include @@ -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 $ACTION of firewall" + /etc/init.d/pbr on_firewall_reload "$ACTION" +fi diff --git a/net/pbr/files/usr/share/pbr/pbr.user.aws b/net/pbr/files/usr/share/pbr/pbr.user.aws new file mode 100644 index 000000000..bf398dd66 --- /dev/null +++ b/net/pbr/files/usr/share/pbr/pbr.user.aws @@ -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 diff --git a/net/pbr/files/usr/share/pbr/pbr.user.netflix b/net/pbr/files/usr/share/pbr/pbr.user.netflix new file mode 100644 index 000000000..54f54e0d3 --- /dev/null +++ b/net/pbr/files/usr/share/pbr/pbr.user.netflix @@ -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/^.*//" > "$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 diff --git a/net/vpn-policy-routing/test.sh b/net/pbr/test.sh similarity index 100% rename from net/vpn-policy-routing/test.sh rename to net/pbr/test.sh diff --git a/net/privoxy/Makefile b/net/privoxy/Makefile index 9f859c4eb..a7f5227b8 100644 --- a/net/privoxy/Makefile +++ b/net/privoxy/Makefile @@ -118,13 +118,13 @@ define Package/privoxy/conffiles endef define Package/privoxy/preinst - #!/bin/sh - [ -n "$${IPKG_INSTROOT}" ] && exit 0 # if run within buildroot exit +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] && exit 0 # if run within buildroot exit - # stop service if PKG_UPGRADE - [ "$${PKG_UPGRADE}" = "1" ] && /etc/init.d/privoxy stop >/dev/null 2>&1 - - exit 0 # suppress errors from stop command +# stop service if PKG_UPGRADE +[ "$${PKG_UPGRADE}" = "1" ] && /etc/init.d/privoxy stop >/dev/null 2>&1 + +exit 0 # suppress errors from stop command endef define Package/privoxy/install @@ -156,16 +156,16 @@ define Package/privoxy/install endef define Package/privoxy/postinst - #!/bin/sh - # if exists, update previous version entry missing protocol - (grep -E "privoxy.*8118$$" $${IPKG_INSTROOT}/etc/services) > /dev/null \ - && sed -i "s/privoxy.*8118/privoxy\t\t8118\/tcp/" $${IPKG_INSTROOT}/etc/services +#!/bin/sh +# if exists, update previous version entry missing protocol +(grep -E "privoxy.*8118$$" $${IPKG_INSTROOT}/etc/services) > /dev/null \ + && sed -i "s/privoxy.*8118/privoxy\t\t8118\/tcp/" $${IPKG_INSTROOT}/etc/services - # add missing tcp and udp entries - (grep -E "privoxy.*8118\/tcp" $${IPKG_INSTROOT}/etc/services) > /dev/null \ - || echo -e "privoxy\t\t8118/tcp" >> $${IPKG_INSTROOT}/etc/services - (grep -E "privoxy.*8118\/udp" $${IPKG_INSTROOT}/etc/services) > /dev/null \ - || echo -e "privoxy\t\t8118/udp" >> $${IPKG_INSTROOT}/etc/services +# add missing tcp and udp entries +(grep -E "privoxy.*8118\/tcp" $${IPKG_INSTROOT}/etc/services) > /dev/null \ + || echo -e "privoxy\t\t8118/tcp" >> $${IPKG_INSTROOT}/etc/services +(grep -E "privoxy.*8118\/udp" $${IPKG_INSTROOT}/etc/services) > /dev/null \ + || echo -e "privoxy\t\t8118/udp" >> $${IPKG_INSTROOT}/etc/services endef $(eval $(call BuildPackage,privoxy)) diff --git a/net/simple-adblock/Makefile b/net/simple-adblock/Makefile index 6778f3a7b..ac2854e95 100644 --- a/net/simple-adblock/Makefile +++ b/net/simple-adblock/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=simple-adblock PKG_VERSION:=1.9.3 -PKG_RELEASE:=2 +PKG_RELEASE:=4 PKG_MAINTAINER:=Stan Grishin PKG_LICENSE:=GPL-3.0-or-later diff --git a/net/simple-adblock/files/simple-adblock.init b/net/simple-adblock/files/simple-adblock.init index 7c9829d15..cdd2dac36 100644 --- a/net/simple-adblock/files/simple-adblock.init +++ b/net/simple-adblock/files/simple-adblock.init @@ -62,7 +62,7 @@ readonly sharedMemoryError="/dev/shm/$packageName-error" readonly sharedMemoryOutput="/dev/shm/$packageName-output" readonly hostsFilter='/localhost/d;/^#/d;/^[^0-9]/d;s/^0\.0\.0\.0.//;s/^127\.0\.0\.1.//;s/[[:space:]]*#.*$//;s/[[:cntrl:]]$//;s/[[:space:]]//g;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/\./!d;/^$/d;/[^[:alnum:]_.-]/d;' readonly domainsFilter='/^#/d;s/[[:space:]]*#.*$//;s/[[:space:]]*$//;s/[[:cntrl:]]$//;/[[:space:]]/d;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/\./!d;/^$/d;/[^[:alnum:]_.-]/d;' -readonly dnsmasqAddressFilter='\|^address=/[[:alnum:]_.-].*/#|!d' +readonly dnsmasqOISDFilter='\|^server=/[[:alnum:]_.-].*/|!d' readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m' readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m' readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m' @@ -100,49 +100,60 @@ uci_changes() { ipset() { "$ipset" "$@" >/dev/null 2>&1; } nft() { "$nft" "$@" >/dev/null 2>&1; } -get_status_text() { - local _ret +get_text() { + local r case "$1" in - statusNoInstall) _ret="$serviceName is not installed or not found";; - statusStopped) _ret="Stopped";; - statusStarting) _ret="Starting";; - statusRestarting) _ret="Restarting";; - statusForceReloading) _ret="Force Reloading";; - statusDownloading) _ret="Downloading";; - statusProcessing) _ret="Processing";; - statusError) _ret="Error";; - statusWarning) _ret="Warning";; - statusFail) _ret="Fail";; - statusSuccess) _ret="Success";; + errorConfigValidationFail) r="$packageName config validation failed";; + errorServiceDisabled) r="$packageName is currently disabled";; + errorNoDnsmasqIpset) + r="dnsmasq ipset support is enabled in $packageName, but dnsmasq is either not installed or installed dnsmasq does not support ipset";; + errorNoIpset) + r="dnsmasq ipset support is enabled in $packageName, but ipset is either not installed or installed ipset does not support 'hash:net' type";; + errorNoDnsmasqNftset) + r="dnsmasq nft set support is enabled in $packageName, but dnsmasq is either not installed or installed dnsmasq does not support nft set";; + errorNoNft) r="dnsmasq nft sets support is enabled in $packageName, but nft is not installed";; + errorMkdirFail) r="Unable to create directory for";; + errorNoWanGateway) r="The ${serviceName} service failed to discover WAN gateway!";; + errorOutputDirCreate) r="failed to create directory for %s file";; + errorOutputFileCreate) r="failed to create $outputFile file";; + errorFailDNSReload) r="failed to restart/reload DNS resolver";; + errorSharedMemory) r="failed to access shared memory";; + errorSorting) r="failed to sort data file";; + errorOptimization) r="failed to optimize data file";; + errorAllowListProcessing) r="failed to process allow-list";; + errorDataFileFormatting) r="failed to format data file";; + errorMovingDataFile) r="failed to move data file '${A_TMP}' to '${outputFile}'";; + errorCreatingCompressedCache) r="failed to create compressed cache";; + errorRemovingTempFiles) r="failed to remove temporary files";; + errorRestoreCompressedCache) r="failed to unpack compressed cache";; + errorRestoreCache) r="failed to move '$outputCache' to '$outputFile'";; + errorOhSnap) r="failed to create block-list or restart DNS resolver";; + errorStopping) r="failed to stop $serviceName";; + errorDNSReload) r="failed to reload/restart DNS resolver";; + errorDownloadingConfigUpdate) r="failed to download Config Update file";; + errorDownloadingList) r="failed to download";; + errorParsingConfigUpdate) r="failed to parse Config Update file";; + errorParsingList) r="failed to parse";; + errorNoSSLSupport) r="no HTTPS/SSL support on device";; + errorCreatingDirectory) r="failed to create output/cache/gzip file directory";; + + statusNoInstall) r="$serviceName is not installed or not found";; + statusStopped) r="Stopped";; + statusStarting) r="Starting";; + statusRestarting) r="Restarting";; + statusForceReloading) r="Force Reloading";; + statusDownloading) r="Downloading";; + statusProcessing) r="Processing";; + statusError) r="Error";; + statusWarning) r="Warning";; + statusFail) r="Fail";; + statusSuccess) r="Success";; + + warningExternalDnsmasqConfig) + r="use of external dnsmasq config file detected, please set 'dns' option to 'dnsmasq.conf'";; + warningMissingRecommendedPackages) r="Some recommended packages are missing";; esac - printf "%b" "$_ret" -} -get_error_text() { - local _ret - case "$1" in - errorOutputFileCreate) _ret="failed to create $outputFile file";; - errorFailDNSReload) _ret="failed to restart/reload DNS resolver";; - errorSharedMemory) _ret="failed to access shared memory";; - errorSorting) _ret="failed to sort data file";; - errorOptimization) _ret="failed to optimize data file";; - errorAllowListProcessing) _ret="failed to process allow-list";; - errorDataFileFormatting) _ret="failed to format data file";; - errorMovingDataFile) _ret="failed to move data file '${A_TMP}' to '${outputFile}'";; - errorCreatingCompressedCache) _ret="failed to create compressed cache";; - errorRemovingTempFiles) _ret="failed to remove temporary files";; - errorRestoreCompressedCache) _ret="failed to unpack compressed cache";; - errorRestoreCache) _ret="failed to move '$outputCache' to '$outputFile'";; - errorOhSnap) _ret="failed to create block-list or restart DNS resolver";; - errorStopping) _ret="failed to stop $serviceName";; - errorDNSReload) _ret="failed to reload/restart DNS resolver";; - errorDownloadingConfigUpdate) _ret="failed to download Config Update file";; - errorDownloadingList) _ret="failed to download";; - errorParsingConfigUpdate) _ret="failed to parse Config Update file";; - errorParsingList) _ret="failed to parse";; - errorNoSSLSupport) _ret="no HTTPS/SSL support on device";; - errorCreatingDirectory) _ret="failed to create output/cache/gzip file directory";; - esac - printf "%b" "$_ret" + echo "$r" } output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; } @@ -187,13 +198,15 @@ load_environment() { local validation_result="$1" quiet="$2" if [ "$validation_result" != '0' ]; then - output "${_ERROR_}: $packageName config validation failed!\\n" + json add error "errorConfigValidationFail" + output "${_ERROR_}: $(get_text 'errorConfigValidationFail')!\\n" output "Please check if the '$packageConfigFile' contains correct values for config options.\\n" return 1 fi if [ "$enabled" -eq 0 ]; then - output "$packageName is currently disabled.\\n" + json add error "errorServiceDisabled" + output "${_ERROR_}: $(get_text 'errorServiceDisabled')!\\n" output "Run the following commands before starting service again:\\n" output "uci set ${packageName}.config.enabled='1'; uci commit $packageName;\\n" return 1 @@ -210,7 +223,8 @@ load_environment() { dnsmasq.conf) :;; *) if [ -z "$quiet" ]; then - output "$_WARNING_: use of external dnsmasq config file detected, please set 'dns' option to 'dnsmasq.conf'!\\n" + json add warning "warningExternalDnsmasqConfig" + output "${_WARNING_}: $(get_text 'warningExternalDnsmasqConfig')!\\n" fi ;; esac @@ -230,13 +244,15 @@ load_environment() { dnsmasq.ipset) if dnsmasq -v 2>/dev/null | grep -q 'no-ipset' || ! dnsmasq -v 2>/dev/null | grep -q -w 'ipset'; then if [ -z "$quiet" ]; then - output "$_ERROR_: dnsmasq ipset support is enabled in $packageName, but dnsmasq is either not installed or installed dnsmasq does not support ipset!\\n" + json add error "errorNoDnsmasqIpset" + output "${_ERROR_}: $(get_text 'errorNoDnsmasqIpset')!\\n" fi dns='dnsmasq.servers' fi if ! ipset help hash:net; then if [ -z "$quiet" ]; then - output "$_ERROR_: dnsmasq ipset support is enabled in $packageName, but ipset is either not installed or installed ipset does not support 'hash:net' type!\\n" + json add error "errorNoIpset" + output "${_ERROR_}: $(get_text 'errorNoIpset')!\\n" fi dns='dnsmasq.servers' fi @@ -244,13 +260,15 @@ load_environment() { dnsmasq.nftset) if dnsmasq -v 2>/dev/null | grep -q 'no-nftset' || ! dnsmasq -v 2>/dev/null | grep -q -w 'nftset'; then if [ -z "$quiet" ]; then - output "$_ERROR_: dnsmasq nft sets support is enabled in $packageName, but dnsmasq is either not installed or installed dnsmasq does not support nft sets!\\n" + json add error "errorNoDnsmasqNftset" + output "${_ERROR_}: $(get_text 'errorNoDnsmasqNftset')!\\n" fi dns='dnsmasq.servers' fi if [ -z "$nft" ]; then if [ -z "$quiet" ]; then - output "$_ERROR_: dnsmasq nft sets support is enabled in $packageName, but nft is not installed!\\n" + json add error "errorNoNft" + output "${_ERROR_}: $(get_text 'errorNoNft')!\\n" fi dns='dnsmasq.servers' fi @@ -335,8 +353,8 @@ load_environment() { for i in "$outputFile" "$outputCache" "$outputGzip"; do if ! mkdir -p "$(dirname "$i")"; then - output "$_ERROR_: Unable to create directory for $i!\\n" - json add error "errorOutputFileCreate" + json add error "errorOutputDirCreate" "$i" + output "${_ERROR_}: $(get_text 'errorMkdirFail' "$i")!\\n" fi done @@ -352,7 +370,8 @@ load_environment() { is_present '/usr/libexec/sed-gnu' || s="$s sed" is_present '/usr/libexec/sort-coreutils' || s="$s coreutils-sort" if [ -z "$quiet" ]; then - output "$_WARNING_: Some recommended packages are missing, install them by running:\\n" + json add warning "errorOutputFileCreate" "${i}" + output "${_WARNING_}: $(get_text 'warningMissingRecommendedPackages'), install them by running:\\n" output "$s;\\n" fi fi @@ -390,7 +409,8 @@ load_environment() { cache 'test_gzip' && return 0 network_flush_cache; network_find_wan wan_if; network_get_gateway wan_gw "$wan_if"; [ -n "$wan_gw" ] && return 0 - output "$_ERROR_: $serviceName failed to discover WAN gateway.\\n"; return 1; + json add error "errorNoWanGateway" + output "${_ERROR_}: $(get_text 'errorNoWanGateway')!\\n"; return 1; } resolver() { @@ -424,7 +444,7 @@ dns() { if [ ! -s "$outputFile" ]; then json set status "statusFail" json add error "errorOutputFileCreate" - output "$_ERROR_: $(get_error_text 'errorOutputFileCreate')!\\n" + output "${_ERROR_}: $(get_text 'errorOutputFileCreate')!\\n" return 1 fi @@ -473,7 +493,7 @@ dns() { output_fail json set status "statusFail" json add error "errorDNSReload" - output "$_ERROR_: $(get_error_text 'errorDNSReload')!\\n" + output "${_ERROR_}: $(get_text 'errorDNSReload')!\\n" return 1 fi ;; @@ -518,6 +538,9 @@ dns() { json() { # shellcheck disable=SC2034 local action="$1" param="$2" value="$3" + shift 3 +# shellcheck disable=SC2124 + local extras="$@" line local status message error stats local reload restart curReload curRestart ret i if [ -s "$jsonFile" ]; then @@ -549,10 +572,8 @@ json() { esac ;; add) - if [ -n "$(eval echo "\$$param")" ]; then - value="$(eval echo "\$$param") ${value}" - fi - eval "$param"='${value}' + line="$(eval echo "\$$param")" + eval "$param"='${line:+$line }${value}${extras:+|$extras}' ;; del) case "$param" in @@ -573,7 +594,7 @@ json() { restart="$compressed_cache $force_dns $led $force_dns_port" ;; *) - eval "$param"='$value';; + eval "$param"='${value}${extras:+|$extras}';; esac ;; esac @@ -637,7 +658,7 @@ process_url() { if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then return 1; fi label="${1##*//}"; label="${label%%/*}"; case "$2" in - dnsmasq) label="Dnsmasq: $label"; filter="$dnsmasqAddressFilter";; + dnsmasq) label="Dnsmasq: $label"; filter="$dnsmasqOISDFilter";; domains) label="Domains: $label"; filter="$domainsFilter";; hosts) label="Hosts: $label"; filter="$hostsFilter";; esac @@ -678,7 +699,7 @@ process_url() { download_dnsmasq_file() { local hf allow_filter j=0 R_TMP - json set message "$(get_status_text "statusDownloading")..." + json set message "$(get_text "statusDownloading")..." json set status "statusDownloading" rm -f "$A_TMP" "$B_TMP" "$outputFile" "$outputCache" "$outputGzip" @@ -714,7 +735,7 @@ download_dnsmasq_file() { download_lists() { local hf allow_filter j=0 R_TMP - json set message "$(get_status_text "statusDownloading")..." + json set message "$(get_text "statusDownloading")..." json set status "statusDownloading" rm -f "$A_TMP" "$B_TMP" "$outputFile" "$outputCache" "$outputGzip" @@ -775,7 +796,8 @@ $(cat $A_TMP)" output 1 'Processing downloads ' output 2 'Sorting combined list ' - json set message "$(get_status_text "statusProcessing"): sorting combined list" + json set status "statusProcessing" + json set message "$(get_text "statusProcessing"): sorting combined list" if [ "$allow_non_ascii" -gt 0 ]; then if sort -u "$B_TMP" > "$A_TMP"; then output_ok @@ -799,7 +821,7 @@ $(cat $A_TMP)" [ "$dns" = 'unbound.adb_list' ]; then # TLD optimization written by Dirk Brenken (dev@brenken.org) output 2 'Optimizing combined list ' - json set message "$(get_status_text "statusProcessing"): optimizing combined list" + json set message "$(get_text "statusProcessing"): optimizing combined list" # sed -E 'G;:t;s/(.*)(\.)(.*)(\n)(.*)/\1\4\5\2\3/;tt;s/(.*)\n(\.)(.*)/\3\2\1/' is actually slower than command below if $awk -F "." '{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "$A_TMP" > "$B_TMP"; then if sort "$B_TMP" > "$A_TMP"; then @@ -835,7 +857,7 @@ $(cat $A_TMP)" fi output 2 'Allowing domains ' - json set message "$(get_status_text "statusProcessing"): allowing domains" + json set message "$(get_text "statusProcessing"): allowing domains" if sed -i -E "$allow_filter" "$B_TMP"; then output_ok else @@ -844,7 +866,7 @@ $(cat $A_TMP)" fi output 2 'Formatting merged file ' - json set message "$(get_status_text "statusProcessing"): formatting merged file" + json set message "$(get_text "statusProcessing"): formatting merged file" if [ -z "$outputFilterIPv6" ]; then if sed "$outputFilter" "$B_TMP" > "$A_TMP"; then output_ok @@ -869,27 +891,27 @@ $(cat $A_TMP)" case "$dns" in dnsmasq.addnhosts) output 2 'Creating dnsmasq addnhosts file ' - json set message "$(get_status_text "statusProcessing"): creating dnsmasq addnhosts file" + json set message "$(get_text "statusProcessing"): creating dnsmasq addnhosts file" ;; dnsmasq.conf) output 2 'Creating dnsmasq config file ' - json set message "$(get_status_text "statusProcessing"): creating dnsmasq config file" + json set message "$(get_text "statusProcessing"): creating dnsmasq config file" ;; dnsmasq.ipset) output 2 'Creating dnsmasq ipset file ' - json set message "$(get_status_text "statusProcessing"): creating dnsmasq ipset file" + json set message "$(get_text "statusProcessing"): creating dnsmasq ipset file" ;; dnsmasq.nftset) output 2 'Creating dnsmasq nft set file ' - json set message "$(get_status_text "statusProcessing"): creating dnsmasq nft set file" + json set message "$(get_text "statusProcessing"): creating dnsmasq nft set file" ;; dnsmasq.servers) output 2 'Creating dnsmasq servers file ' - json set message "$(get_status_text "statusProcessing"): creating dnsmasq servers file" + json set message "$(get_text "statusProcessing"): creating dnsmasq servers file" ;; unbound.adb_list) output 2 'Creating Unbound adb_list file ' - json set message "$(get_status_text "statusProcessing"): creating Unbound adb_list file" + json set message "$(get_text "statusProcessing"): creating Unbound adb_list file" ;; esac @@ -901,7 +923,7 @@ $(cat $A_TMP)" fi if [ "$compressed_cache" -gt 0 ]; then output 2 'Creating compressed cache ' - json set message "$(get_status_text "statusProcessing"): creating compressed cache" + json set message "$(get_text "statusProcessing"): creating compressed cache" if cache 'create_gzip'; then output_ok else @@ -912,7 +934,7 @@ $(cat $A_TMP)" rm -f "$outputGzip" fi output 2 'Removing temporary files ' - json set message "$(get_status_text "statusProcessing"): removing temporary files" + json set message "$(get_text "statusProcessing"): removing temporary files" rm -f "/tmp/${packageName}_tmp.*" "$A_TMP" "$B_TMP" "$outputCache" || j=1 if [ $j -eq 0 ]; then output_ok @@ -1183,7 +1205,7 @@ adb_start() { else output_failn json add error "errorRestoreCompressedCache" - output "$_ERROR_: $(get_error_text 'errorRestoreCompressedCache')!\\n" + output "${_ERROR_}: $(get_text 'errorRestoreCompressedCache')!\\n" action='download' fi fi @@ -1196,7 +1218,7 @@ adb_start() { else output_failn json add error "errorRestoreCache" - output "$_ERROR_: $(get_error_text 'errorRestoreCache')!\\n" + output "${_ERROR_}: $(get_text 'errorRestoreCache')!\\n" action='download' fi fi @@ -1342,7 +1364,7 @@ adb_status() { if [ "$status" = "statusSuccess" ]; then output "$stats "; output_okn; else - [ -n "$status" ] && status="$(get_status_text "$status")" + [ -n "$status" ] && status="$(get_text "$status")" if [ -n "$status" ] && [ -n "$message" ]; then status="${status}: $message" fi @@ -1354,9 +1376,9 @@ adb_status() { c="${c%|*}" case "$c" in errorDownloadingList|errorParsingList) - output "$_ERROR_: $(get_error_text "$c") $url!\\n";; + output "${_ERROR_}: $(get_text "$c") $url!\\n";; *) - output "$_ERROR_: $(get_error_text "$c")!\\n";; + output "${_ERROR_}: $(get_text "$c")!\\n";; esac n=$((n+1)) done @@ -1382,7 +1404,7 @@ adb_stop() { output 0 "$__FAIL__\\n"; output_fail; json set status "statusFail" json add error "errorStopping" - output "$_ERROR_: $(get_error_text 'errorStopping')!\\n" + output "${_ERROR_}: $(get_text 'errorStopping')!\\n" fi fi } diff --git a/net/snort3/Makefile b/net/snort3/Makefile index fd2f76bd8..b91ebc6bd 100644 --- a/net/snort3/Makefile +++ b/net/snort3/Makefile @@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=snort3 -PKG_VERSION:=3.1.47.0 -PKG_RELEASE:=1 +PKG_VERSION:=3.1.48.0 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/snort3/snort3/archive/refs/tags/ -PKG_HASH:=7565411db11b453a98f8bd88eeef0fa9f2e85416a8f595e710aa19c430228b8c +PKG_HASH:=65df088a8cac11e59f0b71a7f98fc9d21eeb0e31d35280c470c985172947ebfe PKG_MAINTAINER:=W. Michael Petullo PKG_LICENSE:=GPL-2.0-only @@ -90,7 +90,8 @@ define Package/snort3/install $(PKG_INSTALL_DIR)/usr/include/snort/lua/snort_plugin.lua \ $(1)/usr/share/lua/ - $(INSTALL_DIR) $(1)/etc/snort + $(INSTALL_DIR) $(1)/etc/snort/{rules,lists,builtin_rules,so_rules} + $(INSTALL_CONF) \ $(PKG_INSTALL_DIR)/usr/etc/snort/*.lua \ $(1)/etc/snort @@ -107,6 +108,25 @@ define Package/snort3/install $(INSTALL_CONF) \ ./files/snort.config \ $(1)/etc/config/snort + $(INSTALL_CONF) \ + ./files/local.lua \ + $(1)/etc/snort + $(INSTALL_CONF) \ + ./files/homenet.lua \ + $(1)/etc/snort + sed \ + -i -e "/^EXTERNAL_NET\\s\\+=/ a include 'homenet.lua'" \ + -e "/^HOME_NET\\s\\+=/ i -- we set HOME_NET and EXTERNAL_NET here or via an included file" \ + -e 's/^\(HOME_NET\s\+=\)/--\1/g' \ + -e 's/^\(EXTERNAL_NET\s\+=\)/--\1/g' \ + $(1)/etc/snort/snort.lua + sed \ + -i -e "s/^\\(RULE_PATH\\s\\+=\\).*/\\1 'rules'/g" \ + -e "s/^\\(BUILTIN_RULE_PATH\\s\\+=\\).*/\\1 'builtin_rules'/g" \ + -e "s/^\\(PLUGIN_RULE_PATH\\s\\+=\\).*/\\1 'so_rules'/g" \ + -e "s/^\\(WHITE_LIST_PATH\\s\\+=\\).*/\\1 'lists'/g" \ + -e "s/^\\(BLACK_LIST_PATH\\s\\+=\\).*/\\1 'lists'/g" \ + $(1)/etc/snort/snort_defaults.lua endef $(eval $(call BuildPackage,snort3)) diff --git a/net/snort3/files/homenet.lua b/net/snort3/files/homenet.lua new file mode 100644 index 000000000..975f70254 --- /dev/null +++ b/net/snort3/files/homenet.lua @@ -0,0 +1,3 @@ +-- setup HOME_NET below with your IP range/ranges to protect +HOME_NET = [[ 192.168.1.0/24 10.1.0.1/24 ]] +EXTERNAL_NET = "!$HOME_NET" diff --git a/net/snort3/files/local.lua b/net/snort3/files/local.lua new file mode 100644 index 000000000..7929388ba --- /dev/null +++ b/net/snort3/files/local.lua @@ -0,0 +1,52 @@ +-- use ths file to customize any functions defined in /etc/snort/snort.lua + +-- switch tap to inline in ips and uncomment the below to run snort in inline mode +--snort = {} +--snort["-Q"] = '' + +ips = { + mode = tap, + -- mode = inline, + variables = default_variables, + -- uncomment and change the below to reflect rules or symlinks to rules on your filesystem + -- include = RULE_PATH .. '/snort.rules', +} + +daq = { + module_dirs = { + '/usr/lib/daq', + }, + modules = { + { + name = 'afpacket', + mode = 'inline', + } + } +} + +alert_syslog = { + level = 'info', +} + +-- To log to a file, uncomment the below and manually create the dir defined in output.logdir +--output.logdir = '/var/log/snort' +--alert_fast = { +-- file = true, +-- packet = false, +--} + +normalizer = { + tcp = { + ips = true, + } +} + +file_policy = { + enable_type = true, + enable_signature = true, + rules = { + use = { + verdict = 'log', enable_file_type = true, enable_file_signature = true + } + } +} diff --git a/net/snort3/files/snort.config b/net/snort3/files/snort.config index 92e42959d..84f5e96d9 100644 --- a/net/snort3/files/snort.config +++ b/net/snort3/files/snort.config @@ -1,4 +1,3 @@ config snort 'snort' option config_dir '/etc/snort/' - option alert_module 'alert_syslog' option interface 'eth0' diff --git a/net/snort3/files/snort.init b/net/snort3/files/snort.init index 4549e26ea..ff864e02b 100644 --- a/net/snort3/files/snort.init +++ b/net/snort3/files/snort.init @@ -9,7 +9,6 @@ PROG=/usr/bin/snort validate_snort_section() { uci_validate_section snort snort "${1}" \ 'config_dir:string' \ - 'alert_module:string' \ 'interface:string' } @@ -22,7 +21,7 @@ start_service() { } procd_open_instance - procd_set_param command $PROG -q --daq-dir /usr/lib/daq/ -i "$interface" -c "$config_dir/snort.lua" -A "$alert_module" + procd_set_param command $PROG -q -i "$interface" -c "${config_dir%/}/snort.lua" --tweaks local procd_set_param env SNORT_LUA_PATH="$config_dir" procd_set_param file $CONFIGFILE procd_set_param respawn diff --git a/net/snort3/patches/900-fix_build_for_archs_contain_plus.patch b/net/snort3/patches/900-fix_build_for_archs_contain_plus.patch new file mode 100644 index 000000000..163a7a069 --- /dev/null +++ b/net/snort3/patches/900-fix_build_for_archs_contain_plus.patch @@ -0,0 +1,16 @@ +--- a/cmake/FindFlexLexer.cmake ++++ b/cmake/FindFlexLexer.cmake +@@ -16,11 +16,11 @@ macro(FLEX NAME LEXER_IN LEXER_OUT) + COMPILE_FLAGS ${FLEX_FLAGS} + ) + +- # we use '+' as a separator for 'sed' to avoid conflicts with '/' in paths from LEXER_OUT ++ # we use '|' as a separator for 'sed' to avoid conflicts with '/' in paths from LEXER_OUT + add_custom_command( + OUTPUT ${LEXER_OUT} + COMMAND sed -e +- "s+void yyFlexLexer::LexerError+yynoreturn void yyFlexLexer::LexerError+;s+${LEXER_OUT}.tmp+${LEXER_OUT}+" ++ "s|void yyFlexLexer::LexerError|yynoreturn void yyFlexLexer::LexerError|;s|${LEXER_OUT}.tmp|${LEXER_OUT}|" + ${FLEX_${NAME}_OUTPUTS} > ${LEXER_OUT} + DEPENDS ${FLEX_${NAME}_OUTPUTS} + VERBATIM diff --git a/net/snowflake/Makefile b/net/snowflake/Makefile index 5e9cadb34..2b4685d56 100644 --- a/net/snowflake/Makefile +++ b/net/snowflake/Makefile @@ -1,13 +1,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=snowflake -PKG_VERSION:=2.3.1 +PKG_VERSION:=2.4.1 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://git.torproject.org/pluggable-transports/snowflake.git PKG_SOURCE_VERSION:=v$(PKG_VERSION) -PKG_MIRROR_HASH:=f83d48ebdbb3966856fdd1016a2ff4e57e63598182ad5e53ab5c31a7100ce6ee +PKG_MIRROR_HASH:=91f32c3f56718ae35641c734aa061be138eb7c0d1bc88596b42e731e30aaa27a PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=LICENSE diff --git a/net/stubby/Makefile b/net/stubby/Makefile index 77f8d8770..bb0b2be54 100644 --- a/net/stubby/Makefile +++ b/net/stubby/Makefile @@ -5,13 +5,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=stubby -PKG_VERSION:=0.4.0 -PKG_RELEASE:=6 +PKG_VERSION:=0.4.2 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/getdnsapi/$(PKG_NAME) PKG_SOURCE_VERSION:=v$(PKG_VERSION) -PKG_MIRROR_HASH:=bc5f604da1b70287a6c3d89eac2e13ce8bca52840e7b72ab098a3deeb9935082 +PKG_MIRROR_HASH:=0a40e3eec2ef86a83977b69f03bc63f232fe52ca15703273a0d097e64fa3bf05 PKG_MAINTAINER:= PKG_LICENSE:=BSD-3-Clause diff --git a/net/tailscale/Makefile b/net/tailscale/Makefile index e74854d16..e15b54aa1 100644 --- a/net/tailscale/Makefile +++ b/net/tailscale/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=tailscale -PKG_VERSION:=1.24.2 -PKG_RELEASE:=$(AUTORELEASE) +PKG_VERSION:=1.32.3 +PKG_RELEASE:=1 PKG_SOURCE:=tailscale-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/tailscale/tailscale/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=f1fe7770b4e372ace47c5b0ac4cbe21af95c3a6fb1828ee4f407fcfe35b7958f +PKG_HASH:=4cf88a1d754240ce71b29d3a65ca480091ad9c614ac99c541cef6fdaf0585dd4 PKG_MAINTAINER:=Jan Pavlinec PKG_LICENSE:=BSD-3-Clause @@ -77,6 +77,7 @@ endef define Package/tailscaled/conffiles /etc/config/tailscale +/etc/tailscale/tailscaled.state endef $(eval $(call BuildPackage,tailscale)) diff --git a/net/vallumd/Makefile b/net/vallumd/Makefile index 5edc128a5..75b2470da 100644 --- a/net/vallumd/Makefile +++ b/net/vallumd/Makefile @@ -8,12 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=vallumd -PKG_VERSION:=0.2.0 +PKG_VERSION:=0.2.2 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/stintel/vallumd/tar.gz/$(PKG_VERSION)? -PKG_HASH:=7c1baffa3f7889c9c6f2795aac134c50a309ef201764d5ce6bbbce5d657416c0 +PKG_SOURCE_URL:=https://codeberg.org/stintel/vallumd/archive/$(PKG_VERSION).tar.gz? +PKG_HASH:=f88cafce41cc118862869268b5e6c9b315a6f084aa8a498d4484e9dac49c575c +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) PKG_MAINTAINER:=Stijn Tintel PKG_LICENSE:=GPL-3.0 diff --git a/net/vallumd/patches/001-CMake-skip-git-magic-if-no-.git-dir-exists.patch b/net/vallumd/patches/001-CMake-skip-git-magic-if-no-.git-dir-exists.patch new file mode 100644 index 000000000..82a659dfb --- /dev/null +++ b/net/vallumd/patches/001-CMake-skip-git-magic-if-no-.git-dir-exists.patch @@ -0,0 +1,78 @@ +From b70137d0cc62be7f43816a3ba33b7c3e6a2fbd4e Mon Sep 17 00:00:00 2001 +From: Stijn Tintel +Date: Fri, 18 Nov 2022 09:19:02 +0200 +Subject: [PATCH] CMake: skip git magic if no .git dir exists + +The checks to fail CMake if git describe isn't working break build when +building from source tarballs. + +Test if there is a git directory, and completely skip the git magic if +not. + +Fixes: f42e7beec46e ("CI: add explicit clone to fetch tags") +Signed-off-by: Stijn Tintel +--- + CMakeLists.txt | 51 +++++++++++++++++++++++++------------------------- + 1 file changed, 26 insertions(+), 25 deletions(-) + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -9,35 +9,36 @@ set (VERSION_MAJOR 0) + set (VERSION_MINOR 2) + set (VERSION_PATCH 2) + +-execute_process(COMMAND git describe --tags --dirty +- OUTPUT_VARIABLE GIT_DESCRIBE +- OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +-execute_process(COMMAND git describe --abbrev=0 +- OUTPUT_VARIABLE GIT_LAST_TAG +- OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) ++if (EXISTS .git/) ++ execute_process(COMMAND git describe --tags --dirty ++ OUTPUT_VARIABLE GIT_DESCRIBE ++ OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) ++ execute_process(COMMAND git describe --abbrev=0 ++ OUTPUT_VARIABLE GIT_LAST_TAG ++ OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + +-string(LENGTH "${GIT_DESCRIBE}" GIT_DESCRIBE_LEN) +-string(LENGTH "${GIT_LAST_TAG}" GIT_LAST_TAG_LEN) ++ string(LENGTH "${GIT_DESCRIBE}" GIT_DESCRIBE_LEN) ++ string(LENGTH "${GIT_LAST_TAG}" GIT_LAST_TAG_LEN) + +-if (GIT_DESCRIBE_LEN EQUAL 0 OR GIT_LAST_TAG_LEN EQUAL 0) +- message(FATAL_ERROR "git describe output empty") +-endif () ++ if (GIT_DESCRIBE_LEN EQUAL 0 OR GIT_LAST_TAG_LEN EQUAL 0) ++ message(FATAL_ERROR "git describe output empty") ++ endif () + +-string(REGEX REPLACE "^${GIT_LAST_TAG}-" "" GIT_DESCRIBE_NOTAG "${GIT_DESCRIBE}") ++ string(REGEX REPLACE "^${GIT_LAST_TAG}-" "" GIT_DESCRIBE_NOTAG "${GIT_DESCRIBE}") + +-if (NOT "${GIT_DESCRIBE}" STREQUAL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") +- if ("${GIT_LAST_TAG}" VERSION_LESS +- "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") +- string(REGEX REPLACE "^${GIT_LAST_TAG}-" +- "" VERSION_TWEAK "0-pre-${GIT_DESCRIBE_NOTAG}") +- else () +- string(REGEX REPLACE +- "^${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-" +- "" VERSION_TWEAK "${GIT_DESCRIBE}") ++ if (NOT "${GIT_DESCRIBE}" STREQUAL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") ++ if ("${GIT_LAST_TAG}" VERSION_LESS ++ "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") ++ string(REGEX REPLACE "^${GIT_LAST_TAG}-" ++ "" VERSION_TWEAK "0-pre-${GIT_DESCRIBE_NOTAG}") ++ else () ++ string(REGEX REPLACE ++ "^${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-" ++ "" VERSION_TWEAK "${GIT_DESCRIBE}") ++ endif () + endif () + endif () + +- + configure_file ( + "${PROJECT_SOURCE_DIR}/src/config.h.in" + "${PROJECT_BINARY_DIR}/config.h" diff --git a/net/vpn-policy-routing/Makefile b/net/vpn-policy-routing/Makefile deleted file mode 100644 index 21c6b9339..000000000 --- a/net/vpn-policy-routing/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2017-2018 Stan Grishin (stangri@melmac.net) -# This is free software, licensed under the GNU General Public License v3. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=vpn-policy-routing -PKG_VERSION:=0.3.4 -PKG_RELEASE:=8 -PKG_LICENSE:=GPL-3.0-or-later -PKG_MAINTAINER:=Stan Grishin - -include $(INCLUDE_DIR)/package.mk - -define Package/vpn-policy-routing - SECTION:=net - CATEGORY:=Network - TITLE:=VPN Policy-Based Routing Service - URL:=https://docs.openwrt.melmac.net/vpn-policy-routing/ - DEPENDS:=+jshn +ipset +iptables +resolveip +kmod-ipt-ipset +iptables-mod-ipopt +ip-full - PKGARCH:=all -endef - -define Package/vpn-policy-routing/description -This service allows policy-based routing for L2TP, Openconnect, OpenVPN, PPTP and Wireguard tunnels and WAN interface. -Policies can specify domains, local IPs/subnets and ports, as well as remote IPs/subnets and ports. -endef - -define Package/vpn-policy-routing/conffiles -/etc/config/vpn-policy-routing -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/vpn-policy-routing/install - $(INSTALL_DIR) $(1)/etc/init.d $(1)/etc/config $(1)/etc/hotplug.d/firewall $(1)/etc/ - $(INSTALL_BIN) ./files/vpn-policy-routing.init $(1)/etc/init.d/vpn-policy-routing - $(SED) "s|^\(PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/vpn-policy-routing - $(INSTALL_CONF) ./files/vpn-policy-routing.config $(1)/etc/config/vpn-policy-routing - $(INSTALL_DATA) ./files/vpn-policy-routing.firewall.hotplug $(1)/etc/hotplug.d/firewall/70-vpn-policy-routing - $(INSTALL_DATA) ./files/vpn-policy-routing.aws.user $(1)/etc/vpn-policy-routing.aws.user - $(INSTALL_DATA) ./files/vpn-policy-routing.netflix.user $(1)/etc/vpn-policy-routing.netflix.user -endef - -define Package/vpn-policy-routing/postinst - #!/bin/sh - # check if we are on real system - if [ -z "$${IPKG_INSTROOT}" ]; then - /etc/init.d/vpn-policy-routing enable - fi - exit 0 -endef - -define Package/vpn-policy-routing/prerm - #!/bin/sh - # check if we are on real system - if [ -z "$${IPKG_INSTROOT}" ]; then - echo "Stopping service and removing rc.d symlink for vpn-policy-routing" - /etc/init.d/vpn-policy-routing stop || true - /etc/init.d/vpn-policy-routing disable || true - fi - exit 0 -endef - -$(eval $(call BuildPackage,vpn-policy-routing)) diff --git a/net/vpn-policy-routing/files/README.md b/net/vpn-policy-routing/files/README.md deleted file mode 100644 index 98d7efc62..000000000 --- a/net/vpn-policy-routing/files/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# README - -README has been moved to [https://docs.openwrt.melmac.net/vpn-policy-routing/](https://docs.openwrt.melmac.net/vpn-policy-routing/). diff --git a/net/vpn-policy-routing/files/vpn-policy-routing.aws.user b/net/vpn-policy-routing/files/vpn-policy-routing.aws.user deleted file mode 100644 index a00770be7..000000000 --- a/net/vpn-policy-routing/files/vpn-policy-routing.aws.user +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# This file is heavily based on code from https://github.com/Xentrk/netflix-vpn-bypass/blob/master/IPSET_Netflix.sh - -TARGET_IPSET='wan' - -TARGET_URL="https://ip-ranges.amazonaws.com/ip-ranges.json" -TARGET_FNAME="/var/vpn-policy-routing_tmp_aws_ip_ranges" - -_ret=1 - -if [ ! -s "$TARGET_FNAME" ]; then - curl "$TARGET_URL" 2>/dev/null | grep "ip_prefix" | sed 's/^.*\"ip_prefix\": \"//; s/\",//' > "$TARGET_FNAME" -fi -if [ -s "$TARGET_FNAME" ]; then - awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_FNAME" | ipset restore -! && _ret=0 -fi -rm -f "$TARGET_FNAME" - -return $_ret diff --git a/net/vpn-policy-routing/files/vpn-policy-routing.config b/net/vpn-policy-routing/files/vpn-policy-routing.config deleted file mode 100644 index ed6f01cdd..000000000 --- a/net/vpn-policy-routing/files/vpn-policy-routing.config +++ /dev/null @@ -1,30 +0,0 @@ -config vpn-policy-routing 'config' - option enabled '0' - option verbosity '2' - option strict_enforcement '1' - option src_ipset '0' - option dest_ipset '0' - option resolver_ipset 'dnsmasq.ipset' - option ipv6_enabled '0' - list ignored_interface 'vpnserver wgserver' - option boot_timeout '30' - option iptables_rule_option 'append' - option procd_reload_delay '1' - option webui_enable_column '0' - option webui_protocol_column '0' - option webui_chain_column '0' - option webui_show_ignore_target '0' - option webui_sorting '1' - list webui_supported_protocol 'tcp' - list webui_supported_protocol 'udp' - list webui_supported_protocol 'tcp udp' - list webui_supported_protocol 'icmp' - list webui_supported_protocol 'all' - -config include - option path '/etc/vpn-policy-routing.netflix.user' - option enabled 0 - -config include - option path '/etc/vpn-policy-routing.aws.user' - option enabled 0 diff --git a/net/vpn-policy-routing/files/vpn-policy-routing.firewall.hotplug b/net/vpn-policy-routing/files/vpn-policy-routing.firewall.hotplug deleted file mode 100755 index 3932b2b62..000000000 --- a/net/vpn-policy-routing/files/vpn-policy-routing.firewall.hotplug +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -[ "$ACTION" = "reload" ] || exit 0 - -logger -t "vpn-policy-routing" "Reloading vpn-policy-routing due to $ACTION of firewall" -/etc/init.d/vpn-policy-routing reload diff --git a/net/vpn-policy-routing/files/vpn-policy-routing.init b/net/vpn-policy-routing/files/vpn-policy-routing.init deleted file mode 100755 index 1962ed529..000000000 --- a/net/vpn-policy-routing/files/vpn-policy-routing.init +++ /dev/null @@ -1,1322 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright 2017-2020 Stan Grishin (stangri@melmac.net) -# shellcheck disable=SC2039,SC1091,SC2018,SC2019,SC3043,SC3057,SC3060 -PKG_VERSION='dev-test' - -# sysctl net.ipv4.conf.default.rp_filter=1 -# sysctl net.ipv4.conf.all.rp_filter=1 - -# shellcheck disable=SC2034 -START=94 -# shellcheck disable=SC2034 -USE_PROCD=1 - -if type extra_command 1>/dev/null 2>&1; then - extra_command 'support' "Generates output required to troubleshoot routing issues - Use '-d' option for more detailed output - Use '-p' option to automatically upload data under VPR paste.ee account - WARNING: while paste.ee uploads are unlisted, they are still publicly available - List domain names after options to include their lookup in report" - extra_command 'version' 'Show version information' - extra_command 'reload_interface' 'Reload specific interface only' -else -# shellcheck disable=SC2034 - EXTRA_COMMANDS='support version' -# shellcheck disable=SC2034 - EXTRA_HELP=" support Generates output required to troubleshoot routing issues - Use '-d' option for more detailed output - Use '-p' option to automatically upload data under VPR paste.ee account - WARNING: while paste.ee uploads are unlisted, they are still publicly available - List domain names after options to include their lookup in report" -fi - -readonly packageName='vpn-policy-routing' -readonly serviceName="$packageName $PKG_VERSION" -readonly PIDFile="/var/run/${packageName}.pid" -readonly jsonFile="/var/run/${packageName}.json" -readonly dnsmasqFile="/var/dnsmasq.d/${packageName}" -readonly sharedMemoryOutput="/dev/shm/$packageName-output" -readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m' -readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m' -readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m' -readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m' -readonly _ERROR_='\033[0;31mERROR\033[0m' -readonly _WARNING_='\033[0;33mWARNING\033[0m' - -gatewaySummary=''; errorSummary=''; warningSummary=''; -serviceEnabled=''; verbosity=''; strictMode=''; -wanTableID=''; wanMark=''; fwMask=''; -ipv6Enabled=''; srcIpset=''; destIpset=''; resolverIpset=''; -wanIface4=''; wanIface6=''; ifaceMark=''; ifaceTableID=''; -ifAll=''; ifSupported=''; ignoredIfaces=''; supportedIfaces=''; icmpIface=''; -wanGW4=''; wanGW6=''; bootTimeout=''; insertOption=''; -webuiChainColumn=''; webuiShowIgnore=''; dnsmasqIpsetSupported=''; -procdReloadDelay=''; -usedChainsList='PREROUTING' -ipsetSupported='true' -configLoaded='false' - -version() { echo "$PKG_VERSION"; } -output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; } -output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; } -output_fail() { s=1; output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; } -output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; } -str_replace() { printf "%b" "$1" | sed -e "s/$(printf "%b" "$2")/$(printf "%b" "$3")/g"; } -str_replace() { echo "${1//$2/$3}"; } -str_contains() { [ -n "$2" ] && [ "${1//$2}" != "$1" ]; } -str_contains_word() { echo "$1" | grep -q -w "$2"; } -str_to_lower() { echo "$1" | tr 'A-Z' 'a-z'; } -str_extras_to_underscore() { echo "$1" | tr '[\. ~`!@#$%^&*()\+/,<>?//;:]' '_'; } -str_extras_to_space() { echo "$1" | tr ';{}' ' '; } - -output() { -# Can take a single parameter (text) to be output at any verbosity -# Or target verbosity level and text to be output at specifc verbosity - local msg memmsg logmsg - if [ $# -ne 1 ]; then - if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; else return 0; fi - fi - [ -t 1 ] && printf "%b" "$1" - 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:-service} [$$]" "$(printf "%b" "$logmsg")" - rm -f "$sharedMemoryOutput" - else - printf "%b" "$msg" >> "$sharedMemoryOutput" - fi -} -is_present() { command -v "$1" >/dev/null 2>&1; } -is_installed() { [ -s "/usr/lib/opkg/info/${1}.control" ]; } -is_variant_installed() { [ "$(echo /usr/lib/opkg/info/"${1}"*.control)" != "/usr/lib/opkg/info/${1}*.control" ]; } - -build_ifAll() { ifAll="${ifAll}${1} "; } -build_ifSupported() { is_supported_interface "$1" && ifSupported="${ifSupported}${1} "; } -vpr_find_iface() { - local iface i param="$2" - [ "$param" = 'wan6' ] || param='wan' - "network_find_${param}" iface - is_tunnel "$iface" && unset iface - if [ -z "$iface" ]; then - for i in $ifAll; do - if "is_${param}" "$i"; then break; else unset i; fi - done - fi - eval "$1"='${iface:-$i}' -} -vpr_get_gateway() { - local iface="$2" dev="$3" gw - network_get_gateway gw "$iface" - if [ -z "$gw" ] || [ "$gw" = '0.0.0.0' ]; then - gw="$(ip -4 a list dev "$dev" 2>/dev/null | grep inet | awk '{print $2}' | awk -F "/" '{print $1}')" - fi - eval "$1"='$gw' -} -vpr_get_gateway6() { - local iface="$2" dev="$3" gw - network_get_gateway6 gw "$iface" - if [ -z "$gw" ] || [ "$gw" = '::/0' ] || [ "$gw" = '::0/0' ] || [ "$gw" = '::' ]; then - gw="$(ip -6 a list dev "$dev" 2>/dev/null | grep inet6 | awk '{print $2}')" - fi - eval "$1"='$gw' -} -is_l2tp() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:4}" = "l2tp" ]; } -is_oc() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:11}" = "openconnect" ]; } -is_ovpn() { local dev i; for i in ifname device; do [ -z "$dev" ] && dev="$(uci -q get "network.${1}.${i}")"; done; [ "${dev:0:3}" = "tun" ] || [ "${dev:0:3}" = "tap" ] || [ -f "/sys/devices/virtual/net/${dev}/tun_flags" ]; } -is_pptp() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:4}" = "pptp" ]; } -is_tor() { [ "$(str_to_lower "$1")" = "tor" ]; } -is_tor_running() { - local ret=0 - if [ -s "/etc/tor/torrc" ]; then - json_load "$(ubus call service list "{ 'name': 'tor' }")" - json_select 'tor'; json_select 'instances'; json_select 'instance1'; - json_get_var ret 'running'; json_cleanup - fi - if [ "$ret" = "0" ]; then return 1; else return 0; fi -} -is_wg() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:9}" = "wireguard" ]; } -is_tunnel() { is_l2tp "$1" || is_oc "$1" || is_ovpn "$1" || is_pptp "$1" || is_tor "$1" || is_wg "$1"; } -is_wan() { [ "$1" = "$wanIface4" ] || { [ "${1##wan}" != "$1" ] && [ "${1##wan6}" = "$1" ]; } || [ "${1%%wan}" != "$1" ]; } -is_wan6() { [ -n "$wanIface6" ] && [ "$1" = "$wanIface6" ] || [ "${1/#wan6}" != "$1" ] || [ "${1/%wan6}" != "$1" ]; } -is_ignored_interface() { str_contains_word "$ignoredIfaces" "$1"; } -is_supported_interface() { str_contains_word "$supportedIfaces" "$1" || { ! is_ignored_interface "$1" && { is_wan "$1" || is_wan6 "$1" || is_tunnel "$1"; }; }; } -is_mac_address() { expr "$1" : '[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]$' >/dev/null; } -is_ipv4() { expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; } -is_ipv6() { ! is_mac_address "$1" && str_contains "$1" ":"; } -is_family_mismatch() { ( is_netmask "${1//!}" && is_ipv6 "${2//!}" ) || ( is_ipv6 "${1//!}" && is_netmask "${2//!}" ); } -is_ipv6_link_local() { [ "${1:0:4}" = "fe80" ]; } -is_ipv6_unique_local() { [ "${1:0:2}" = "fc" ] || [ "${1:0:2}" = "fd" ]; } -is_ipv6_global() { [ "${1:0:4}" = "2001" ]; } -# is_ipv6_global() { is_ipv6 "$1" && ! is_ipv6_link_local "$1" && ! is_ipv6_link_local "$1"; } -is_netmask() { local ip="${1%/*}"; [ "$ip" != "$1" ] && is_ipv4 "$ip"; } -is_domain() { str_contains "$1" '[a-zA-Z]'; } -is_phys_dev() { [ "${1:0:1}" = "@" ] && ip l show | grep -E -q "^\\d+\\W+${1:1}"; } -is_turris() { /bin/ubus -S call system board | /bin/grep 'Turris' | /bin/grep -q '15.05'; } -is_chaos_calmer() { ubus -S call system board | grep -q 'Chaos Calmer'; } -dnsmasq_kill() { killall -q -s HUP dnsmasq; } -dnsmasq_restart() { output 3 'Restarting DNSMASQ '; if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then output_okn; else output_failn; fi; } -is_default_dev() { [ "$1" = "$(ip -4 r | grep -m1 'dev' | grep -Eso 'dev [^ ]*' | awk '{print $2}')" ]; } -is_supported_iface_dev() { - for n in $ifSupported; do - if [ "$1" = "$(uci -q get "network.${n}.ifname" || echo "$n")" ] || \ - [ "$1" = "$(uci -q get "network.${n}.device" || echo "$n")" ] || \ - [ "$1" = "$(uci -q get "network.${n}.proto")-${n}" ] ; then return 0; fi - done - return 1 -} -is_supported_protocol () { grep -o '^[^#]*' /etc/protocols | grep -w -v '0' | grep . | awk '{print $1}' | grep -q "$1"; } -append_chains_targets() { - local chain iface name - config_get name "$1" 'name' 'blank' - config_get chain "$1" 'chain' 'PREROUTING' - config_get iface "$1" 'interface' - if ! str_contains_word "$usedChainsList" "$chain"; then - usedChainsList="$usedChainsList $chain" - if [ "$chain" != 'PREROUTING' ] && [ "$webuiChainColumn" != '1' ]; then - warningSummary="${warningSummary}$_WARNING_: Chain '$chain' is used by a policy '$name', but a WebUI setting to show chains column (webui_chain_column) is disabled!\\n" - fi - fi - if [ "$iface" = 'ignore' ] && ! str_contains_word "$supportedIfaces" 'ignore'; then - supportedIfaces="$supportedIfaces ignore" - if [ "$webuiShowIgnore" != '1' ]; then - warningSummary="${warningSummary}$_WARNING_: The 'ignore' target is used by a policy '$name', but a WebUI setting to show 'ignore' target (webui_show_ignore_target) is disabled!\\n" - fi - fi -} - -load_package_config() { - [ "$configLoaded" = 'false' ] || return 0 - - config_load "$packageName" - config_get_bool serviceEnabled 'config' 'enabled' 0 - config_get_bool strictMode 'config' 'strict_enforcement' 1 - config_get_bool ipv6Enabled 'config' 'ipv6_enabled' 0 - config_get_bool srcIpset 'config' 'src_ipset' 0 - config_get_bool destIpset 'config' 'dest_ipset' 0 - config_get resolverIpset 'config' 'resolver_ipset' 'dnsmasq.ipset' - config_get verbosity 'config' 'verbosity' '2' - config_get wanTableID 'config' 'wan_tid' '201' - config_get wanMark 'config' 'wan_mark' '0x010000' - config_get fwMask 'config' 'fw_mask' '0xff0000' - config_get icmpIface 'config' 'icmp_interface' - config_get ignoredIfaces 'config' 'ignored_interface' - config_get supportedIfaces 'config' 'supported_interface' - config_get bootTimeout 'config' 'boot_timeout' '30' - config_get insertOption 'config' 'iptables_rule_option' 'append' - config_get procdReloadDelay 'config' 'procd_reload_delay' '0' - config_get_bool webuiChainColumn 'config' 'webui_chain_column' '0' - config_get_bool webuiShowIgnore 'config' 'webui_show_ignore_target' '0' - config_foreach append_chains_targets 'policy' - - if [ -z "${verbosity##*[!0-9]*}" ] || [ "$verbosity" -lt 0 ] || [ "$verbosity" -gt 2 ]; then - verbosity=2 - fi - - . /lib/functions/network.sh - . /usr/share/libubox/jshn.sh - mkdir -p "${PIDFile%/*}" - mkdir -p "${jsonFile%/*}" - mkdir -p "${dnsmasqFile%/*}" - - if [ -n "$icmpIface" ] && ! str_contains_word "$usedChainsList" 'OUTPUT'; then - usedChainsList="$usedChainsList OUTPUT" - fi - - case $insertOption in - insert|-i|-I) insertOption='-I';; - append|-a|-A|*) insertOption='-A';; - esac - - [ "$resolverIpset" = 'dnsmasq.ipset' ] && dnsmasqIpsetSupported='true' - if dnsmasq -v 2>/dev/null | grep -q 'no-ipset' || ! dnsmasq -v 2>/dev/null | grep -q -w 'ipset'; then - unset dnsmasqIpsetSupported - if [ -n "$dnsmasqIpsetSupported" ]; then - errorSummary="${errorSummary}${_ERROR_}: Resolver ipset support (dnsmasq.ipset) is enabled in $packageName, but DNSMASQ ipsets are not supported on this system!\\n" - fi - fi - if ! ipset help hash:net >/dev/null 2>&1; then - unset ipsetSupported - if [ -n "$dnsmasqIpsetSupported" ]; then - errorSummary="${errorSummary}${_ERROR_}: DNSMASQ ipsets are supported, but ipset is either not installed or installed ipset does not support 'hash:net' type!\\n" - unset dnsmasqIpsetSupported - fi - if [ "$destIpset" -ne 0 ]; then - errorSummary="${errorSummary}${_ERROR_}: Destination ipset support is enabled in $packageName, but ipset is either not installed or installed ipset does not support 'hash:net' type!\\n" - destIpset=0 - fi - if [ "$srcIpset" -ne 0 ]; then - errorSummary="${errorSummary}${_ERROR_}: Source ipset support is enabled in $packageName, but ipset is either not installed or installed ipset does not support 'hash:net' type!\\n" - srcIpset=0 - fi - fi - if ! ipset help hash:mac >/dev/null 2>&1; then - if [ "$srcIpset" -ne 0 ]; then - errorSummary="${errorSummary}${_ERROR_}: Source ipset support is enabled in $packageName, but ipset is either not installed or installed ipset does not support 'hash:mac' type!\\n" - srcIpset=0 - fi - fi - - configLoaded='true' -} - -is_enabled() { - load_package_config - if [ "$serviceEnabled" -eq 0 ]; then - if [ "$1" = 'on_start' ]; then - errorSummary="${errorSummary}${_ERROR_}: ${packageName} is currently disabled.\\n" - errorSummary="${errorSummary}Enable ${packageName} from WebUI or run the following commands:\\n" - errorSummary="${errorSummary}uci set $packageName.config.enabled='1'; uci commit $packageName;\\n" - fi - return 1 - fi -} - -load_network() { - if [ -z "$ifAll" ]; then - config_load 'network' - config_foreach build_ifAll 'interface' - fi - vpr_find_iface wanIface4 'wan' - [ "$ipv6Enabled" -ne 0 ] && vpr_find_iface wanIface6 'wan6' - [ -n "$wanIface4" ] && network_get_gateway wanGW4 "$wanIface4" - [ -n "$wanIface6" ] && network_get_gateway6 wanGW6 "$wanIface6" - wanGW="${wanGW4:-$wanGW6}" - unset ifSupported - config_load 'network' - config_foreach build_ifSupported 'interface' -} - -is_wan_up() { - local sleepCount=1 - load_network - while [ -z "$wanGW" ] ; do - load_network - if [ $((sleepCount)) -gt $((bootTimeout)) ] || [ -n "$wanGW" ]; then break; fi - output "$serviceName waiting for wan gateway...\\n" - sleep 1 - network_flush_cache - sleepCount=$((sleepCount+1)) - done - if [ -n "$wanGW" ]; then - return 0 - else - errorSummary="${errorSummary}${_ERROR_}: ${serviceName} failed to discover WAN gateway!\\n" - return 1 - fi -} - -ipt_cleanup() { - local i - for i in PREROUTING FORWARD INPUT OUTPUT; do - while iptables -t mangle -D $i -m mark --mark 0x0/0xff0000 -j VPR_${i} >/dev/null 2>&1; do : ; done - done - for i in PREROUTING FORWARD INPUT OUTPUT; do - while iptables -t mangle -D $i -j VPR_${i} >/dev/null 2>&1; do : ; done - done -} - -# shellcheck disable=SC2086 -ipt() { - local d failFlagIpv4=1 failFlagIpv6=1 - for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do - [ "$d" != "$*" ] && { iptables $d >/dev/null 2>&1; ip6tables $d >/dev/null 2>&1; } - done - - d="$*"; iptables $d >/dev/null 2>&1 && failFlagIpv4=0; - if [ "$ipv6Enabled" -gt 0 ]; then ip6tables $d >/dev/null 2>&1 && failFlagIpv6=0; fi - - [ "$failFlagIpv4" -eq 0 ] || [ "$failFlagIpv6" -eq 0 ] -} - -# shellcheck disable=SC2086 -ips() { - local command="$1" ipset="${2//-/_}" param="$3" comment="$4" appendix failFlag=0 - if str_contains "$ipset" '_ip'; then - ipset="${ipset//_ip}"; appendix='_ip'; - elif str_contains "$ipset" '_mac'; then - ipset="${ipset//_mac}"; appendix='_mac'; - fi - - case "$command" in - add_dnsmasq) - [ "$resolverIpset" = "dnsmasq.ipset" ] || return 1 - if [ -z "$dnsmasqIpsetSupported" ]; then - warningSummary="${warningSummary}${_WARNING_}: The 'resolver_ipset' is set to 'dnsmasq.ipset', but DNSMASQ ipsets are not supported on this system!\\n" - failFlag=1 - elif [ "$ipv6Enabled" -ne 0 ]; then - echo "ipset=/${param}/${ipset},${ipset}6 # $comment" >> "$dnsmasqFile" || failFlag=1 - else - echo "ipset=/${param}/${ipset} # $comment" >> "$dnsmasqFile" || failFlag=1 - fi - ;; - add) - if [ -z "$appendix" ] && [ "$destIpset" -eq 0 ]; then return 1; fi - if [ -n "$appendix" ] && [ "$srcIpset" -eq 0 ]; then return 1; fi - if [ "$ipv6Enabled" -ne 0 ] && [ "$appendix" != "_mac" ]; then - ipset -q -! $command "${ipset}6${appendix}" $param comment "$comment" || failFlag=1 - fi - ipset -q -! $command "${ipset}${appendix}" $param comment "$comment" || failFlag=1 - ;; - create) - if [ "$ipv6Enabled" -ne 0 ] && [ "$appendix" != "_mac" ]; then - ipset -q -! "$command" "${ipset}6${appendix}" $param family inet6 || failFlag=1 - fi - ipset -q -! "$command" "${ipset}${appendix}" $param || failFlag=1 - ;; - destroy|flush) - ipset -q -! "$command" "${ipset}6${appendix}" 2>/dev/null || failFlag=1 - ipset -q -! "$command" "${ipset}${appendix}" 2>/dev/null || failFlag=1 - return 0 - ;; - esac - return $failFlag -} - -insert_tor_policy() { - local comment="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto chain - proto="$(str_to_lower "$7")" - chain="${8:-PREROUTING}" - if [ -n "${laddr}${lport}${rport}" ]; then - processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'src_addr', 'src_port' and 'dest_port' for policy '$comment'\\n" - fi - if [ -n "$proto" ] && [ "$proto" != "all" ]; then - processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'proto' or set 'proto' to 'all' for policy '$comment'\\n" - fi - if [ "$chain" != "PREROUTING" ]; then - processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'chain' or set 'chain' to 'PREROUTING' for policy '$comment'\\n" - fi - ips 'add' "${iface}" "$raddr" "${comment}: $raddr" || processPolicyError="${processPolicyError}${_ERROR_}: ipset 'add' $iface $raddr\\n" - return 0 -} - -insert_policy() { - local comment="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto chain - local mark param i valueNeg value dest ipInsertOption="-A" - proto="$(str_to_lower "$7")" - chain="${8:-PREROUTING}" - mark=$(eval echo "\$mark_${iface//-/_}") - if [ "$ipv6Enabled" -eq 0 ] && ( is_ipv6 "$laddr" || is_ipv6 "$raddr" ); then - processPolicyError="${processPolicyError}${_ERROR_}: Skipping IPv6 policy '$comment' as IPv6 support is disabled\\n" - return 1 - fi - - if [ -n "$mark" ]; then - dest="-g VPR_MARK${mark}" - elif [ "$iface" = "ignore" ]; then - dest="-j RETURN" - else - processPolicyError="${processPolicyError}${_ERROR_}: Unknown fw_mark for ${iface}\\n" - return 0 - fi - - if [ -z "$proto" ]; then - if [ -n "$lport" ] || [ -n "$rport" ]; then - proto='tcp udp' - else - proto='all' - fi - fi - - if is_family_mismatch "$laddr" "$raddr"; then - processPolicyError="${processPolicyError}${_ERROR_}: Mismatched IP family between '$laddr' and '$raddr' in policy '$comment'\\n" - return 0 - fi - - for i in $proto; do - if [ "$i" = 'all' ]; then - param="-t mangle ${ipInsertOption} VPR_${chain} $dest" - elif ! is_supported_protocol "$i"; then - processPolicyError="${processPolicyError}${_ERROR_}: Unknown protocol '$i' in policy '$comment'\\n" - return 0 - else - param="-t mangle ${ipInsertOption} VPR_${chain} $dest -p $i" - fi - - if [ -n "$laddr" ]; then - if [ "${laddr:0:1}" = "!" ]; then - valueNeg='!'; value="${laddr:1}" - else - unset valueNeg; value="$laddr"; - fi - if is_phys_dev "$value"; then - param="$param $valueNeg -m physdev --physdev-in ${value:1}" - elif is_mac_address "$value"; then - param="$param -m mac $valueNeg --mac-source $value" - else - param="$param $valueNeg -s $value" - fi - fi - - if [ -n "$lport" ]; then - if [ "${lport:0:1}" = "!" ]; then - valueNeg='!'; value="${lport:1}" - else - unset valueNeg; value="$lport"; - fi - param="$param -m multiport $valueNeg --sport ${value//-/:}" - fi - - if [ -n "$raddr" ]; then - if [ "${raddr:0:1}" = "!" ]; then - valueNeg='!'; value="${raddr:1}" - else - unset valueNeg; value="$raddr"; - fi - param="$param $valueNeg -d $value" - fi - - if [ -n "$rport" ]; then - if [ "${rport:0:1}" = "!" ]; then - valueNeg='!'; value="${rport:1}" - else - unset valueNeg; value="$rport"; - fi - param="$param -m multiport $valueNeg --dport ${value//-/:}" - fi - - [ -n "$comment" ] && param="$param -m comment --comment $(str_extras_to_underscore "$comment")" - ipt "$param" || processPolicyError="${processPolicyError}${_ERROR_}: iptables $param\\n" - done - return 0 -} - -r_process_policy(){ - local comment="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto="$7" chain="$8" resolved_laddr resolved_raddr i ipsFailFlag - if str_contains "$laddr" '[ ;\{\}]'; then - for i in $(str_extras_to_space "$laddr"); do [ -n "$i" ] && r_process_policy "$comment" "$iface" "$i" "$lport" "$raddr" "$rport" "$proto" "$chain"; done - return 0 - elif str_contains "$lport" '[ ;\{\}]'; then - for i in $(str_extras_to_space "$lport"); do [ -n "$i" ] && r_process_policy "$comment" "$iface" "$laddr" "$i" "$raddr" "$rport" "$proto" "$chain"; done - return 0 - elif str_contains "$raddr" '[ ;\{\}]'; then - for i in $(str_extras_to_space "$raddr"); do [ -n "$i" ] && r_process_policy "$comment" "$iface" "$laddr" "$lport" "$i" "$rport" "$proto" "$chain"; done - return 0 - elif str_contains "$rport" '[ ;\{\}]'; then - for i in $(str_extras_to_space "$rport"); do [ -n "$i" ] && r_process_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$i" "$proto" "$chain"; done - return 0 - fi - - # start non-recursive processing - # process TOR, netmask, physical device and mac-address separately, so we don't send them to resolveip - if is_tor "$iface"; then - insert_tor_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$rport" "$proto" "$chain" - elif is_phys_dev "$laddr"; then - insert_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$rport" "$proto" "$chain" - elif [ -n "$laddr" ] && [ -z "${lport}${raddr}${rport}" ] && [ "$chain" = 'PREROUTING' ]; then - if is_mac_address "$laddr"; then - if [ -n "$proto" ] && [ "$proto" != 'all' ] && [ "$srcIpset" -ne 0 ]; then - processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'proto' or set 'proto' to 'all' for policy: '$comment', mac-address: '$laddr'\\n" - fi - ips 'add' "${iface}_mac" "$laddr" "${comment}: $laddr" || ipsFailFlag=1 - else - if [ -n "$proto" ] && [ "$proto" != "all" ] && [ "$srcIpset" -ne 0 ]; then - processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'proto' or set 'proto' to 'all' for policy: '$comment', source: '$laddr'\\n" - fi - ips 'add' "${iface}_ip" "$laddr" "${comment}: $laddr" || ipsFailFlag=1 - fi - elif [ -n "$raddr" ] && [ -z "${laddr}${lport}${rport}" ] && [ "$chain" = 'PREROUTING' ]; then - if [ -n "$proto" ] && [ "$proto" != 'all' ]; then - processPolicyWarning="${processPolicyWarning}${_WARNING_}: Please unset 'proto' or set 'proto' to 'all' for policy: '$comment', destination: '$raddr'\\n" - fi - if is_domain "$raddr"; then - ips 'add_dnsmasq' "${iface}" "$raddr" "${comment}" || ipsFailFlag=1 - else - ips 'add' "${iface}" "$raddr" "${comment}: $raddr" || ipsFailFlag=1 - fi - else - ipsFailFlag=1 - fi - [ -n "$ipsFailFlag" ] || return 0; - if is_mac_address "$laddr"; then - insert_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$rport" "$proto" "$chain" - elif is_netmask "$laddr" || is_netmask "$raddr"; then - insert_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$rport" "$proto" "$chain" - else - [ -n "$laddr" ] && resolved_laddr="$(resolveip "$laddr")" - [ -n "$raddr" ] && resolved_raddr="$(resolveip "$raddr")" - if [ -n "$resolved_laddr" ] && [ "$resolved_laddr" != "$laddr" ]; then - for i in $resolved_laddr; do [ -n "$i" ] && r_process_policy "$comment $laddr" "$iface" "$i" "$lport" "$raddr" "$rport" "$proto" "$chain"; done - elif [ -n "$resolved_raddr" ] && [ "$resolved_raddr" != "$raddr" ]; then - for i in $resolved_raddr; do [ -n "$i" ] && r_process_policy "$comment $raddr" "$iface" "$laddr" "$lport" "$i" "$rport" "$proto" "$chain"; done - else - insert_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$rport" "$proto" "$chain" - fi - fi -} - -process_policy(){ - local name comment iface laddr lport raddr rport param mark processPolicyError processPolicyWarning proto chain enabled - config_get comment "$1" 'comment' - config_get name "$1" 'name' 'blank' - config_get iface "$1" 'interface' - config_get laddr "$1" 'src_addr' - config_get lport "$1" 'src_port' - config_get raddr "$1" 'dest_addr' - config_get rport "$1" 'dest_port' - config_get proto "$1" 'proto' - config_get chain "$1" 'chain' 'PREROUTING' - config_get_bool enabled "$1" 'enabled' 1 - - [ "$enabled" -gt 0 ] || return 0 - proto="$(str_to_lower "$proto")" - [ "$proto" = 'auto' ] && unset proto - - comment="${comment:-$name}" - output 2 "Routing '$comment' via $iface " - - if [ -z "$comment" ]; then - errorSummary="${errorSummary}${_ERROR_}: Policy name is empty\\n" - output_fail; return 1; - fi - if [ -z "${laddr}${lport}${raddr}${rport}" ]; then - errorSummary="${errorSummary}${_ERROR_}: Policy '$comment' missing all IPs/ports\\n" - output_fail; return 1; - fi - if [ -z "$iface" ]; then - errorSummary="${errorSummary}${_ERROR_}: Policy '$comment' has no assigned interface\\n" - output_fail; return 1; - fi - if ! is_supported_interface "$iface"; then - errorSummary="${errorSummary}${_ERROR_}: Policy '$comment' has unknown interface: '${iface}'\\n" - output_fail; return 1; - fi - - lport="${lport// / }"; lport="${lport// /,}"; lport="${lport//,\!/ !}"; - rport="${rport// / }"; rport="${rport// /,}"; rport="${rport//,\!/ !}"; - r_process_policy "$comment" "$iface" "$laddr" "$lport" "$raddr" "$rport" "$proto" "$chain" - if [ -n "$processPolicyWarning" ]; then - warningSummary="${warningSummary}${processPolicyWarning}\\n" - fi - if [ -n "$processPolicyError" ]; then - output_fail - errorSummary="${errorSummary}${processPolicyError}\\n" - else - output_ok - fi -} - -table_destroy(){ - local tid="$1" iface="$2" mark="$3" - if [ -n "$tid" ] && [ -n "$iface" ] && [ -n "$mark" ]; then - ipt -t mangle -F "VPR_MARK${mark}" - ipt -t mangle -X "VPR_MARK${mark}" - ip -4 rule del fwmark "$mark" table "$tid" >/dev/null 2>&1 - ip -6 rule del fwmark "$mark" table "$tid" >/dev/null 2>&1 - ip -4 rule del table "$tid" >/dev/null 2>&1 - ip -6 rule del table "$tid" >/dev/null 2>&1 - ip -4 route flush table "$tid" >/dev/null 2>&1 - ip -6 route flush table "$tid" >/dev/null 2>&1 - ips 'flush' "${iface}"; ips 'destroy' "${iface}"; - ips 'flush' "${iface}_ip"; ips 'destroy' "${iface}_ip"; - ips 'flush' "${iface}_mac"; ips 'destroy' "${iface}_mac"; - ip -4 route flush cache - ip -6 route flush cache - sed -i "/$iface/d" /etc/iproute2/rt_tables - return 0 - else - return 1 - fi -} - -# shellcheck disable=SC2086 -table_create(){ - local tid="$1" mark="$2" iface="$3" gw4="$4" dev="$5" gw6="$6" dev6="$7" match="$8" dscp s=0 i ipv4_error=0 ipv6_error=1 - - if [ -z "$tid" ] || [ -z "$mark" ] || [ -z "$iface" ]; then - return 1 - fi - - table_destroy "$tid" "$iface" "$mark" - - if [ -n "$gw4" ] || [ "$strictMode" -ne 0 ]; then - echo "$tid" "$iface" >> /etc/iproute2/rt_tables - if [ -z "$gw4" ]; then - ip -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1 - else - ip -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1 - fi -# ip -4 route list table main | grep -v 'br-lan' | while read -r i; do - ip -4 route list table main | while read -r i; do - idev="$(echo "$i" | grep -Eso 'dev [^ ]*' | awk '{print $2}')" - if ! is_supported_iface_dev "$idev"; then - ip -4 route add $i table "$tid" >/dev/null 2>&1 || ipv4_error=1 - fi - done - ip -4 route flush cache || ipv4_error=1 - ip -4 rule add fwmark "${mark}/${fwMask}" table "$tid" || ipv4_error=1 - ipt -t mangle -N "VPR_MARK${mark}" || ipv4_error=1 - ipt -t mangle -A "VPR_MARK${mark}" -j MARK --set-xmark "${mark}/${fwMask}" || ipv4_error=1 - ipt -t mangle -A "VPR_MARK${mark}" -j RETURN || ipv4_error=1 - fi - - if [ "$ipv6Enabled" -ne 0 ]; then - ipv6_error=0 - if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strictMode" -ne 0 ]; then - if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then - ip -6 route add unreachable default table "$tid" || ipv6_error=1 - else - ip -6 route list table main | grep " dev $dev6 " | while read -r i; do - ip -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1 - done - fi - ip -6 route flush cache || ipv6_error=1 - ip -6 rule add fwmark "${mark}/${fwMask}" table "$tid" || ipv6_error=1 - fi - fi - - if [ $ipv4_error -eq 0 ] || [ $ipv6_error -eq 0 ]; then - dscp="$(uci -q get "${packageName}".config."${iface}"_dscp)" - if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then - ipt -t mangle -I VPR_PREROUTING -m dscp --dscp "${dscp}" -g "VPR_MARK${mark}" || s=1 - fi - if [ -n "$ipsetSupported" ] && { [ -n "$dnsmasqIpsetSupported" ] || [ "$destIpset" -ne 0 ]; }; then - if ips 'create' "${iface}" 'hash:net comment' && ips 'flush' "${iface}"; then - for i in $usedChainsList; do - ipt -t mangle -I VPR_${i} -m set --match-set "${iface}" dst -g "VPR_MARK${mark}" || s=1 - if [ "$ipv6Enabled" -ne 0 ]; then ipt -t mangle -I VPR_${i} -m set --match-set "${iface}6" dst -g "VPR_MARK${mark}" || s=1; fi - done - else - s=1 - fi - fi - if [ -n "$ipsetSupported" ] && [ "$srcIpset" -ne 0 ]; then - if ips 'create' "${iface}_ip" 'hash:net comment' && ips 'flush' "${iface}_ip"; then - ipt -t mangle -I VPR_PREROUTING -m set --match-set "${iface}_ip" src -g "VPR_MARK${mark}" || s=1 - if [ "$ipv6Enabled" -ne 0 ]; then ipt -t mangle -I VPR_PREROUTING -m set --match-set "${iface}6_ip" src -g "VPR_MARK${mark}" || s=1; fi - else - s=1 - fi - if ips 'create' "${iface}_mac" 'hash:mac comment' && ips 'flush' "${iface}_mac"; then - ipt -t mangle -I VPR_PREROUTING -m set --match-set "${iface}_mac" src -g "VPR_MARK${mark}" || s=1 - else - s=1 - fi - fi - if [ "$iface" = "$icmpIface" ]; then - ipt -t mangle -I VPR_OUTPUT -p icmp -g "VPR_MARK${mark}" || s=1 - fi - else - s=1 - fi - - return $s -} - -table_reload() { - local tid="$1" mark="$2" iface="$3" gw4="$4" dev="$5" gw6="$6" dev6="$7" match="$8" dscp s=0 i ipv4_error=0 ipv6_error=1 - - if [ -z "$tid" ] || [ -z "$mark" ] || [ -z "$iface" ]; then - return 1 - fi - - ip -4 route del default table "$tid" >/dev/null 2>&1 - if [ -n "$gw4" ] || [ "$strictMode" -ne 0 ]; then - if [ -z "$gw4" ]; then - ip -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1 - else - ip -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1 - fi - ip -4 route flush cache || ipv4_error=1 - ip -4 rule del fwmark "${mark}/${fwMask}" table "$tid" >/dev/null 2>&1 - ip -4 rule add fwmark "${mark}/${fwMask}" table "$tid" || ipv4_error=1 - fi - - if [ "$ipv6Enabled" -ne 0 ]; then - ip -6 route del default table "$tid" >/dev/null 2>&1 - ipv6_error=0 - if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strictMode" -ne 0 ]; then - if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then - ip -6 route add unreachable default table "$tid" || ipv6_error=1 - else - ip -6 route list table main | grep " dev $dev6 " | while read -r i; do - ip -6 route add "$i" table "$tid" >/dev/null 2>&1 || ipv6_error=1 - done - fi - ip -6 route flush cache || ipv6_error=1 - ip -6 rule del fwmark "${mark}/${fwMask}" table "$tid" >/dev/null 2>&1 - ip -6 rule add fwmark "${mark}/${fwMask}" table "$tid" || ipv6_error=1 - fi - fi - - if [ $ipv4_error -eq 0 ] || [ $ipv6_error -eq 0 ]; then - dscp="$(uci -q get "${packageName}".config."${iface}"_dscp)" - if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then - ipt -t mangle -I VPR_PREROUTING -m dscp --dscp "${dscp}" -g "VPR_MARK${mark}" || s=1 - fi - if [ "$iface" = "$icmpIface" ]; then - ipt -t mangle -I VPR_OUTPUT -p icmp -g "VPR_MARK${mark}" || s=1 - fi - else - s=1 - fi - - return $s -} - -process_interface(){ - local gw4 gw6 dev dev6 s=0 dscp iface="$1" action="$2" match="$3" displayText - - is_supported_interface "$iface" || return 0 - is_wan6 "$iface" && return 0 - [ $((ifaceMark)) -gt $((fwMask)) ] && return 1 - - network_get_device dev "$iface" - [ -z "$dev" ] && config_get dev "$iface" 'ifname' - [ -z "$dev" ] && config_get dev "$iface" 'device' - if is_wan "$iface" && [ -n "$wanIface6" ]; then - network_get_device dev6 "$wanIface6" - [ -z "$dev6" ] && config_get dev6 "$wanIface6" 'ifname' - [ -z "$dev6" ] && config_get dev6 "$wanIface6" 'device' - fi - [ -z "$dev6" ] && dev6="$dev" - - [ -z "$ifaceTableID" ] && ifaceTableID="$wanTableID"; [ -z "$ifaceMark" ] && ifaceMark="$wanMark"; - - case "$action" in - destroy) - table_destroy "${ifaceTableID}" "${iface}" "${ifaceMark}" - ifaceTableID="$((ifaceTableID + 1))"; ifaceMark="$(printf '0x%06x' $((ifaceMark + wanMark)))"; - ;; - create) - eval "mark_${iface//-/_}"='$ifaceMark' - eval "tid_${iface//-/_}"='$ifaceTableID' - if [ -z "$match" ]; then - table_destroy "$ifaceTableID" "$iface" - fi - vpr_get_gateway gw4 "$iface" "$dev" - vpr_get_gateway6 gw6 "$iface" "$dev6" - if [ "$iface" = "$dev" ]; then - displayText="${iface}/${gw4:-0.0.0.0}" - else - displayText="${iface}/${dev}/${gw4:-0.0.0.0}" - fi - [ "$ipv6Enabled" -ne 0 ] && displayText="${displayText}/${gw6:-::/0}" - if [ -z "$match" ]; then - output 2 "Creating table '$displayText' " - is_default_dev "$dev" && displayText="${displayText} ${__OK__}" - if table_create "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$match"; then - gatewaySummary="${gatewaySummary}${displayText}\\n" - output_ok - else - errorSummary="${errorSummary}${_ERROR_}: Failed to set up '$displayText'\\n" - output_fail - fi - elif [ "$iface" = "$match" ]; then - output 2 "Reloading table '$displayText' " - is_default_dev "$dev" && displayText="${displayText} ${__OK__}" - if table_reload "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$match"; then - gatewaySummary="${gatewaySummary}${displayText}\\n" - output_ok - else - errorSummary="${errorSummary}${_ERROR_}: Failed to reload '$displayText'\\n" - output_fail - fi - else - is_default_dev "$dev" && displayText="${displayText} ${__OK__}" - gatewaySummary="${gatewaySummary}${displayText}\\n" - fi - ifaceTableID="$((ifaceTableID + 1))"; ifaceMark="$(printf '0x%06x' $((ifaceMark + wanMark)))"; - ;; - esac - return $s -} - -process_tor_interface(){ - local s=0 iface="$1" action="$2" displayText - case "$action" in - destroy) - for i in PREROUTING FORWARD INPUT OUTPUT; do - ipt -t nat -D "${i}" -m mark --mark "0x0/${fwMask}" -j "VPR_${i}" - ipt -t nat -F "VPR_${i}"; ipt -t nat -X "VPR_${i}"; - done - ;; - create) - output 2 "Creating TOR redirects " - dnsPort="$(grep -m1 DNSPort /etc/tor/torrc | awk -F: '{print $2}')" - transPort="$(grep -m1 TransPort /etc/tor/torrc | awk -F: '{print $2}')" - dnsPort="${dnsPort:-9053}"; transPort="${transPort:-9040}"; - for i in $usedChainsList; do - ipt -t nat -N "VPR_${i}" - ipt -t nat "$insertOption" "$i" -m mark --mark "0x0/${fwMask}" -j "VPR_${i}" - done - if ips 'create' "${iface}" 'hash:net comment' && ips 'flush' "${iface}"; then - for i in $usedChainsList; do - ipt -t nat -I "VPR_${i}" -p udp -m udp --dport 53 -m set --match-set "${iface}" dst -j REDIRECT --to-ports "$dnsPort" -m comment --comment "TorDNS-UDP" || s=1 - ipt -t nat -I "VPR_${i}" -p tcp -m tcp --dport 80 -m set --match-set "${iface}" dst -j REDIRECT --to-ports "$transPort" -m comment --comment "TorHTTP-TCP" || s=1 - ipt -t nat -I "VPR_${i}" -p udp -m udp --dport 80 -m set --match-set "${iface}" dst -j REDIRECT --to-ports "$transPort" -m comment --comment "TorHTTP-UDP" || s=1 - ipt -t nat -I "VPR_${i}" -p tcp -m tcp --dport 443 -m set --match-set "${iface}" dst -j REDIRECT --to-ports "$transPort" -m comment --comment "TorHTTPS-TCP" || s=1 - ipt -t nat -I "VPR_${i}" -p udp -m udp --dport 443 -m set --match-set "${iface}" dst -j REDIRECT --to-ports "$transPort" -m comment --comment "TorHTTPS-UDP" || s=1 - done - else - s=1 - fi - displayText="${iface}/53->${dnsPort}/80,443->${transPort}" - if [ "$s" -eq "0" ]; then - gatewaySummary="${gatewaySummary}${displayText}\\n" - output_ok - else - errorSummary="${errorSummary}${_ERROR_}: Failed to set up '$displayText'\\n" - output_fail - fi - ;; - esac - return $s -} - -convert_config(){ - local i src_ipset dest_ipset resolver_ipset - [ -s "/etc/config/${packageName}" ] || return 0 - grep -q "ignored_interfaces" "/etc/config/${packageName}" && sed -i 's/ignored_interfaces/ignored_interface/g' "/etc/config/${packageName}" - grep -q "supported_interfaces" "/etc/config/${packageName}" && sed -i 's/supported_interfaces/supported_interface/g' "/etc/config/${packageName}" - grep -q "local_addresses" "/etc/config/${packageName}" && sed -i 's/local_addresses/local_address/g' "/etc/config/${packageName}" - grep -q "local_ports" "/etc/config/${packageName}" && sed -i 's/local_ports/local_port/g' "/etc/config/${packageName}" - grep -q "remote_addresses" "/etc/config/${packageName}" && sed -i 's/remote_addresses/remote_address/g' "/etc/config/${packageName}" - grep -q "remote_ports" "/etc/config/${packageName}" && sed -i 's/remote_ports/remote_port/g' "/etc/config/${packageName}" - grep -q "ipset_enabled" "/etc/config/${packageName}" && sed -i 's/ipset_enabled/dest_ipset/g' "/etc/config/${packageName}" - grep -q "dnsmasq_enabled" "/etc/config/${packageName}" && sed -i 's/dnsmasq_enabled/resolver_ipset/g' "/etc/config/${packageName}" - grep -q "enable_control" "/etc/config/${packageName}" && sed -i 's/enable_control/webui_enable_column/g' "/etc/config/${packageName}" - grep -q "proto_control" "/etc/config/${packageName}" && sed -i 's/proto_control/webui_protocol_column/g' "/etc/config/${packageName}" - grep -q "chain_control" "/etc/config/${packageName}" && sed -i 's/chain_control/webui_chain_column/g' "/etc/config/${packageName}" - grep -q "sort_control" "/etc/config/${packageName}" && sed -i 's/sort_control/webui_sorting/g' "/etc/config/${packageName}" - grep -q "local_address" "/etc/config/${packageName}" && sed -i 's/local_address/src_addr/g' "/etc/config/${packageName}" - grep -q "local_port" "/etc/config/${packageName}" && sed -i 's/local_port/src_port/g' "/etc/config/${packageName}" - grep -q "remote_address" "/etc/config/${packageName}" && sed -i 's/remote_address/dest_addr/g' "/etc/config/${packageName}" - grep -q "remote_port" "/etc/config/${packageName}" && sed -i 's/remote_port/dest_port/g' "/etc/config/${packageName}" - grep -q "local_ipset" "/etc/config/${packageName}" && sed -i 's/local_ipset/src_ipset/g' "/etc/config/${packageName}" - grep -q "remote_ipset" "/etc/config/${packageName}" && sed -i 's/remote_ipset/dest_ipset/g' "/etc/config/${packageName}" - dest_ipset="$(uci -q get $packageName.config.dest_ipset)" - src_ipset="$(uci -q get $packageName.config.src_ipset)" - resolver_ipset="$(uci -q get $packageName.config.resolver_ipset)" - - if [ -n "$dest_ipset" ] && [ "$dest_ipset" != "0" ] && [ "$dest_ipset" != "1" ]; then - uci set "$packageName".config.dest_ipset='0' - if [ -z "$resolver_ipset" ]; then - uci set "$packageName".config.resolver_ipset='dnsmasq.ipset' - fi - uci commit "$packageName" - fi - if [ -n "$src_ipset" ] && [ "$src_ipset" != "0" ] && [ "$src_ipset" != "1" ]; then - uci set "$packageName".config.src_ipset='1' - uci commit "$packageName" - fi - if [ -z "$(uci -q get $packageName.config.webui_supported_protocol)" ]; then - uci add_list "$packageName".config.webui_supported_protocol='tcp' - uci add_list "$packageName".config.webui_supported_protocol='udp' - uci add_list "$packageName".config.webui_supported_protocol='tcp udp' - uci add_list "$packageName".config.webui_supported_protocol='icmp' - uci add_list "$packageName".config.webui_supported_protocol='all' - uci commit "$packageName" - fi - for i in append_local_rules append_src_rules \ - append_remote_rules append_dest_rules; do - if [ -n "$(uci -q get $packageName.config.$i)" ]; then - warningSummary="${warningSummary}$_WARNING_: $i setting is not supported in ${serviceName}.\\n" - fi - done - for i in udp_proto_enabled forward_chain_enabled input_chain_enabled \ - output_chain_enabled iprule_enabled; do - if [ "$(uci -q get $packageName.config.$i)" = "1" ]; then - warningSummary="${warningSummary}$_WARNING_: $i setting is not supported in ${serviceName}.\\n" - fi - done -} - -check_config(){ local en; config_get_bool en "$1" 'enabled' 1; [ "$en" -gt 0 ] && _cfg_enabled=0; } -is_config_enabled(){ - local cfg="$1" _cfg_enabled=1 - [ -n "$1" ] || return 1 - config_load "$packageName" - config_foreach check_config "$cfg" - return "$_cfg_enabled" -} - -process_user_file(){ - local path enabled shellBin="${SHELL:-/bin/ash}" - config_get_bool enabled "$1" 'enabled' 1 - config_get path "$1" 'path' - [ "$enabled" -gt 0 ] || return 0 - if [ ! -s "$path" ]; then - errorSummary="${errorSummary}${_ERROR_}: Custom user file '$path' not found or empty!\\n" - output_fail - return 1 - fi - if ! $shellBin -n "$path"; then - errorSummary="${errorSummary}${_ERROR_}: Syntax error in custom user file '$path'!\\n" - output_fail - return 1 - fi - output 2 "Running $path " -# shellcheck disable=SC1090 - if ! . "$path"; then - errorSummary="${errorSummary}${_ERROR_}: Error running custom user file '$path'!\\n" - if grep -q -w 'curl' "$path" && ! is_present 'curl'; then - errorSummary="${errorSummary}${_ERROR_}: Use of 'curl' is detected in custom user file '$path', but 'curl' isn't installed!\\n" - errorSummary="${errorSummary}${_ERROR_}: If 'curl' is needed, install it with 'opkg update; opkg install curl;' command in CLI.\\n" - fi - output_fail - return 1 - else - output_ok - return 0 - fi -} - -boot() { rc_procd start_service && rc_procd service_triggers; } - -start_service() { - local dnsmasqStoredHash dnsmasqNewHash i modprobeStatus=0 reloadedIface="$1" - convert_config - is_enabled 'on_start' || return 1 - is_wan_up || return 1 - - iptables -t 'mangle' --list 'VPR_PREROUTING' >/dev/null 2>&1 || unset reloadedIface - [ -n "$(tmpfs get gateway)" ] || unset reloadedIface - - if [ -s "$dnsmasqFile" ]; then - dnsmasqStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')" - rm -f "$dnsmasqFile" - fi - - for i in xt_set ip_set ip_set_hash_ip; do - modprobe "$i" >/dev/null 2>/dev/null || modprobeStatus=$((modprobeStatus + 1)) - done - - if [ "$modprobeStatus" -gt 0 ] && ! is_chaos_calmer; then - errorSummary="${errorSummary}${_ERROR_}: Failed to load kernel modules\\n" - fi - - if [ -z "$reloadedIface" ]; then - for i in $usedChainsList; do - ipt -t mangle -N "VPR_${i}" - ipt -t mangle "$insertOption" "$i" -m mark --mark "0x0/${fwMask}" -j "VPR_${i}" - done - fi - - if [ -z "$reloadedIface" ]; then - output 1 'Processing Interfaces ' - config_load 'network'; config_foreach process_interface 'interface' 'create'; - process_tor_interface 'tor' 'destroy'; is_tor_running && process_tor_interface 'tor' 'create'; - output 1 '\n' - if is_config_enabled 'policy'; then - output 1 'Processing Policies ' - config_load "$packageName"; config_foreach process_policy 'policy' "$reloadedIface"; - output 1 '\n' - fi - if is_config_enabled 'include'; then - output 1 'Processing User File(s) ' - config_load "$packageName"; config_foreach process_user_file 'include'; - output 1 '\n' - fi - else - output 1 "Reloading Interface: $reloadedIface " - config_load 'network'; config_foreach process_interface 'interface' 'create' "$reloadedIface"; - output 1 '\n' - fi - - if [ -s "$dnsmasqFile" ]; then - dnsmasqNewHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')" - fi - [ "$dnsmasqNewHash" != "$dnsmasqStoredHash" ] && dnsmasq_restart - - if [ -z "$gatewaySummary" ]; then - errorSummary="${errorSummary}${_ERROR_}: failed to set up any gateway!\\n" - fi - procd_open_instance "main" - procd_set_param command /bin/true - procd_set_param stdout 1 - procd_set_param stderr 1 - procd_open_data - json_add_array 'status' - json_add_object '' - [ -n "$gatewaySummary" ] && json_add_string gateway "$gatewaySummary" - [ -n "$errorSummary" ] && json_add_string error "$errorSummary" - [ -n "$warningSummary" ] && json_add_string warning "$warningSummary" - if [ "$strictMode" -ne 0 ] && str_contains "$gatewaySummary" '0.0.0.0'; then - json_add_string mode "strict" - fi - json_close_object - json_close_array - procd_close_data - procd_close_instance -} - -tmpfs() { - local action="$1" param="$2" value="$3" -# shellcheck disable=SC2034 - local gateway error warning mode i - if [ -s "$jsonFile" ]; then - json_load_file "$jsonFile" 2>/dev/null - json_select 'status' 2>/dev/null - for i in gateway error warning mode; do - json_get_var $i "$i" 2>/dev/null - done - fi - case "$action" in - get) - printf "%b" "$(eval echo "\$$param")"; return;; - add) - eval "$param"='$(eval echo "\$$param")${value}';; - del) - case "$param" in - all) - unset gateway error warning mode;; - *) - unset "$param";; - esac - ;; - set) - eval "$param"='$value';; - esac - json_init - json_add_object 'status' - json_add_string version "$PKG_VERSION" - for i in gateway error warning mode; do - json_add_string "$i" "$(eval echo "\$$i")" - done - json_close_object - json_dump > "$jsonFile" - sync -} - -service_started() { - tmpfs set 'gateway' "$gatewaySummary" - tmpfs set 'error' "$errorSummary" - tmpfs set 'warning' "$warningSummary" - if [ "$strictMode" -ne 0 ] && str_contains "$gatewaySummary" '0.0.0.0'; then - tmpfs set 'mode' 'strict' - fi - [ -n "$gatewaySummary" ] && output "$serviceName started with gateways:\\n${gatewaySummary}" - [ -n "$errorSummary" ] && output "${errorSummary}" - [ -n "$warningSummary" ] && output "${warningSummary}" - if [ -n "$errorSummary" ]; then - return 2 - elif [ -n "$warningSummary" ]; then - return 1 - else - return 0 - fi -} - -stop_service() { - local i - iptables -t mangle -L | grep -q VPR_PREROUTING || return 0 - load_package_config - for i in PREROUTING FORWARD INPUT OUTPUT; do - ipt -t mangle -D "${i}" -m mark --mark "0x0/${fwMask}" -j "VPR_${i}" - ipt -t mangle -F "VPR_${i}"; ipt -t mangle -X "VPR_${i}"; - done - config_load 'network'; config_foreach process_interface 'interface' 'destroy'; - process_tor_interface 'tor' 'destroy' - unset ifaceTableID; unset ifaceMark; - if [ -s "$dnsmasqFile" ]; then - rm -f "$dnsmasqFile" - dnsmasq_restart - fi - if [ "$serviceEnabled" -ne 0 ]; then - output "$serviceName stopped "; output_okn; - fi -} - -reload_interface() { rc_procd start_service "$1"; } - -service_triggers() { - local n - is_enabled || return 1 - - if [ "$procdReloadDelay" -gt 0 ] && [ "$procdReloadDelay" -lt 100 ]; then -# shellcheck disable=SC2034 - PROCD_RELOAD_DELAY=$(( procdReloadDelay * 1000 )) - fi - - procd_open_validate - validate_config - validate_policy - validate_include - procd_close_validate - - procd_open_trigger - procd_add_reload_trigger 'openvpn' - if type procd_add_service_trigger 1>/dev/null 2>&1; then - procd_add_service_trigger "service.restart" "firewall" /etc/init.d/${packageName} reload - fi - procd_add_config_trigger "config.change" "${packageName}" /etc/init.d/${packageName} reload - for n in $ifSupported; do - procd_add_interface_trigger "interface.*" "$n" /etc/init.d/${packageName} reload_interface "$n" - done - procd_close_trigger - - output 3 "$serviceName monitoring interfaces: $ifSupported"; output_okn; -} - -status_service() { support "$@"; } -support() { - local dist vers out id s param status set_d set_p tableCount i=0 dev dev6 j - readonly _SEPARATOR_='============================================================' - is_enabled - - json_load "$(ubus call system board)"; json_select release; json_get_var dist distribution; json_get_var vers version - if [ -n "$wanIface4" ]; then - network_get_gateway wanGW4 "$wanIface4" - [ -z "$dev" ] && dev="$(uci -q get network."${wanIface4}".ifname)" - [ -z "$dev" ] && dev="$(uci -q get network."${wanIface4}".device)" - fi - if [ -n "$wanIface6" ]; then - [ -z "$dev6" ] && dev6="$(uci -q get network."${wanIface6}".ifname)" - [ -z "$dev6" ] && dev6="$(uci -q get network."${wanIface6}".device)" - wanGW6=$(ip -6 route show | grep -m1 " dev $dev6 " | awk '{print $1}') - [ "$wanGW6" = "default" ] && wanGW6=$(ip -6 route show | grep -m1 " dev $dev6 " | awk '{print $3}') - fi - while [ "${1:0:1}" = "-" ]; do param="${1//-/}"; eval "set_$param=1"; shift; done - [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support" - status="$serviceName running on $dist $vers." - [ -n "$wanIface4" ] && status="$status WAN (IPv4): ${wanIface4}/${dev}/${wanGW4:-0.0.0.0}." - [ -n "$wanIface6" ] && status="$status WAN (IPv6): ${wanIface6}/${dev6}/${wanGW6:-::/0}." - { - echo "$status" - echo "$_SEPARATOR_" - dnsmasq --version 2>/dev/null | sed '/^$/,$d' - if [ -n "$1" ]; then - echo "$_SEPARATOR_" - echo "Resolving domains" - for i in $1; do - echo "$i: $(resolveip "$i" | tr '\n' ' ')" - done - fi - - echo "$_SEPARATOR_" - echo "Routes/IP Rules" - tableCount=$(ip rule list | grep -c 'fwmark') || tableCount=0 - if [ -n "$set_d" ]; then route; else route | grep '^default'; fi - if [ -n "$set_d" ]; then ip rule list; fi - i=0; while [ $i -lt $tableCount ]; do - echo "" - echo "IPv4 Table $((wanTableID + i)): $(ip -4 route show table $((wanTableID + i)))" - echo "IPv4 Table $((wanTableID + i)) Rules:" - ip -4 rule list table "$((wanTableID + i))" - i=$((i + 1)) - done - - if [ "$ipv6Enabled" -ne 0 ]; then - i=0; while [ $i -lt $tableCount ]; do - ip -6 route show table $((wanTableID + i)) | while read -r param; do - echo "IPv6 Table $((wanTableID + i)): $param" - done - i=$((i + 1)) - done - fi - - for j in Mangle NAT; do - if [ -z "$set_d" ]; then - for i in $usedChainsList; do - if iptables -v -t "$(str_to_lower $j)" -S "VPR_${i}" 1>/dev/null 2>&1; then - echo "$_SEPARATOR_" - echo "$j IP Table: $i" - iptables -v -t "$(str_to_lower $j)" -S "VPR_${i}" - if [ "$ipv6Enabled" -ne 0 ]; then - echo "$_SEPARATOR_" - echo "$j IPv6 Table: $i" - ip6tables -v -t "$(str_to_lower $j)" -S "VPR_${i}" - fi - fi - done - else - echo "$_SEPARATOR_" - echo "$j IP Table" - iptables -L -t "$(str_to_lower $j)" - if [ "$ipv6Enabled" -ne 0 ]; then - echo "$_SEPARATOR_" - echo "$j IPv6 Table" - ip6tables -L -t "$(str_to_lower $j)" - fi - fi - i=0; ifaceMark="$wanMark"; - while [ $i -lt $tableCount ]; do - if iptables -v -t "$(str_to_lower $j)" -S "VPR_MARK${ifaceMark}" 1>/dev/null 2>&1; then - echo "$_SEPARATOR_" - echo "$j IP Table MARK Chain: VPR_MARK${ifaceMark}" - iptables -v -t "$(str_to_lower $j)" -S "VPR_MARK${ifaceMark}" - ifaceMark="$(printf '0x%06x' $((ifaceMark + wanMark)))"; - fi - i=$((i + 1)) - done - done - - echo "$_SEPARATOR_" - echo "Current ipsets" - ipset save - if [ -s "$dnsmasqFile" ]; then - echo "$_SEPARATOR_" - echo "DNSMASQ ipsets" - cat "$dnsmasqFile" - fi - echo "$_SEPARATOR_" - } | tee -a /var/${packageName}-support - if [ -n "$set_p" ]; then - printf "%b" "Pasting to paste.ee... " - if is_present 'curl' && is_variant_installed 'libopenssl' && is_installed 'ca-bundle'; then - json_init; json_add_string "description" "${packageName}-support" - json_add_array "sections"; json_add_object '0' - json_add_string "name" "$(uci -q get system.@system[0].hostname)" - json_add_string "contents" "$(cat /var/${packageName}-support)" - json_close_object; json_close_array; payload=$(json_dump) - out=$(curl -s -k "https://api.paste.ee/v1/pastes" -X "POST" -H "Content-Type: application/json" -H "X-Auth-Token:uVOJt6pNqjcEWu7qiuUuuxWQafpHhwMvNEBviRV2B" -d "$payload") - json_load "$out"; json_get_var id id; json_get_var s success - [ "$s" = "1" ] && printf "%b" "https://paste.ee/p/$id $__OK__\\n" || printf "%b" "$__FAIL__\\n" - [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support" - else - printf "%b" "$__FAIL__\\n" - printf "%b" "$_ERROR_: curl, libopenssl or ca-bundle were not found!\\nRun 'opkg update; opkg install curl libopenssl ca-bundle' to install them.\\n" - fi - else - printf "%b" "Your support details have been logged to '/var/${packageName}-support'. $__OK__\\n" - fi -} - -# shellcheck disable=SC2120 -validate_config() { - uci_validate_section "${packageName}" config "${1}" \ - 'enabled:bool:0' \ - 'strict_enforcement:bool:1' \ - 'ipv6_enabled:bool:0' \ - 'src_ipset:bool:0' \ - 'dest_ipset:bool:0' \ - 'resolver_ipset::or("", "none", "dnsmasq.ipset")' \ - 'verbosity:range(0,2):1' \ - 'wan_tid:integer:201' \ - 'wan_fw_mark:hex(8)' \ - 'fw_mask:hex(8)' \ - 'icmp_interface:string' \ - 'ignored_interface:list(string)' \ - 'supported_interface:list(string)' \ - 'boot_timeout:integer:30' \ - 'iptables_rule_option:or("", "append", "insert")' \ - 'procd_reload_delay:integer:0' \ - 'webui_enable_column:bool:0' \ - 'webui_protocol_column:bool:0' \ - 'webui_supported_protocol:list(string)' \ - 'webui_chain_column:bool:0' \ - 'webui_sorting:bool:1' \ - 'webui_show_ignore_target:bool:0' -} - -# shellcheck disable=SC2120 -validate_policy() { - uci_validate_section "${packageName}" policy "${1}" \ - 'name:string' \ - 'enabled:bool:0' \ - 'interface:network' \ - 'proto:or(string)' \ - 'chain:or("", "PREROUTING", "FORWARD", "INPUT", "OUTPUT")' \ - 'src_addr:list(neg(or(host,network,macaddr)))' \ - 'src_port:list(neg(or(portrange, string)))' \ - 'dest_addr:list(neg(host))' \ - 'dest_port:list(neg(or(portrange, string)))' -} - -# shellcheck disable=SC2120 -validate_include() { - uci_validate_section "${packageName}" include "${1}" \ - 'path:string' \ - 'enabled:bool:0' -} diff --git a/net/vpn-policy-routing/files/vpn-policy-routing.netflix.user b/net/vpn-policy-routing/files/vpn-policy-routing.netflix.user deleted file mode 100644 index 02335c4b3..000000000 --- a/net/vpn-policy-routing/files/vpn-policy-routing.netflix.user +++ /dev/null @@ -1,37 +0,0 @@ -#!/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_IPSET='wan' -TARGET_ASN='2906' -TARGET_FNAME="/var/vpn-policy-routing_tmp_AS${TARGET_ASN}" -#DB_SOURCE='ipinfo.io' -#DB_SOURCE='api.hackertarget.com' -DB_SOURCE='api.bgpview.io' - -_ret=1 - -if [ ! -s "$TARGET_FNAME" ]; then - if [ "$DB_SOURCE" = "ipinfo.io" ]; then - TARGET_URL="https://ipinfo.io/AS${TARGET_ASN}" - curl "$TARGET_URL" 2>/dev/null | grep -E "a href.*${TARGET_ASN}\/" | grep -v ":" | sed "s/^.*//" > "$TARGET_FNAME" - fi - - if [ "$DB_SOURCE" = "api.hackertarget.com" ]; then - TARGET_URL="https://api.hackertarget.com/aslookup/?q=AS${TARGET_ASN}" - curl "$TARGET_URL" 2>/dev/null | sed '1d' > "$TARGET_FNAME" - fi - - if [ "$DB_SOURCE" = "api.bgpview.io" ]; then - TARGET_URL="https://api.bgpview.io/asn/${TARGET_ASN}/prefixes" - curl -s "$TARGET_URL" 2>/dev/null | jsonfilter -e '@.data.ipv4_prefixes[*].prefix' > "$TARGET_FNAME" - fi -fi - -if [ -s "$TARGET_FNAME" ]; then - awk -v ipset="$TARGET_IPSET" '{print "add " ipset " " $1}' "$TARGET_FNAME" | ipset restore -! && _ret=0 -fi -rm -f "$TARGET_FNAME" - -return $_ret diff --git a/net/vpnbypass/Makefile b/net/vpnbypass/Makefile deleted file mode 100644 index 83a4786ba..000000000 --- a/net/vpnbypass/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2017-2018 Stan Grishin (stangri@melmac.net) -# This is free software, licensed under the GNU General Public License v3. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=vpnbypass -PKG_VERSION:=1.3.2 -PKG_RELEASE:=1 -PKG_LICENSE:=GPL-3.0-or-later -PKG_MAINTAINER:=Stan Grishin - -include $(INCLUDE_DIR)/package.mk - -define Package/vpnbypass - SECTION:=net - CATEGORY:=Network - TITLE:=VPN Bypass Service - URL:=https://docs.openwrt.melmac.net/vpnbypass/ - DEPENDS:=+ipset +iptables - PKGARCH:=all -endef - -define Package/vpnbypass/description -This service can be used to enable simple VPN split tunnelling. -Supports accessing domains, IP ranges outside of your VPN tunnel. -Also supports dedicating local ports/IP ranges for direct -internet access (outside of your VPN tunnel). -Please see the README for further information. -endef - -define Package/vpnbypass/conffiles -/etc/config/vpnbypass -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/vpnbypass/install - $(INSTALL_DIR) $(1)/etc/init.d $(1)/etc/config $(1)/etc/hotplug.d/firewall - $(INSTALL_BIN) ./files/vpnbypass.init $(1)/etc/init.d/vpnbypass - $(SED) "s|^\(PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/vpnbypass - $(INSTALL_CONF) ./files/vpnbypass.config $(1)/etc/config/vpnbypass - $(INSTALL_DATA) ./files/vpnbypass.hotplug $(1)/etc/hotplug.d/firewall/94-vpnbypass -endef - -define Package/vpnbypass/postinst - #!/bin/sh - # check if we are on real system - if [ -z "$${IPKG_INSTROOT}" ]; then - /etc/init.d/vpnbypass enable - fi - exit 0 -endef - -define Package/vpnbypass/prerm - #!/bin/sh - # check if we are on real system - if [ -z "$${IPKG_INSTROOT}" ]; then - echo "Stopping service and removing rc.d symlink for vpnbypass" - /etc/init.d/vpnbypass stop || true - /etc/init.d/vpnbypass disable || true - fi - exit 0 -endef - -$(eval $(call BuildPackage,vpnbypass)) diff --git a/net/vpnbypass/files/README.md b/net/vpnbypass/files/README.md deleted file mode 100644 index 886ac7c55..000000000 --- a/net/vpnbypass/files/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# README - -README has been moved to [https://docs.openwrt.melmac.net/vpnbypass/](https://docs.openwrt.melmac.net/vpnbypass/). diff --git a/net/vpnbypass/files/vpnbypass.config b/net/vpnbypass/files/vpnbypass.config deleted file mode 100644 index 0768e865c..000000000 --- a/net/vpnbypass/files/vpnbypass.config +++ /dev/null @@ -1,5 +0,0 @@ -config vpnbypass 'config' - option enabled '0' - list localport '32400' - list localsubnet '192.168.1.81/29' - list remotesubnet '25.0.0.0/8' diff --git a/net/vpnbypass/files/vpnbypass.hotplug b/net/vpnbypass/files/vpnbypass.hotplug deleted file mode 100644 index a2874f97e..000000000 --- a/net/vpnbypass/files/vpnbypass.hotplug +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -[ "$ACTION" = "reload" ] && /etc/init.d/vpnbypass reload diff --git a/net/vpnbypass/files/vpnbypass.init b/net/vpnbypass/files/vpnbypass.init deleted file mode 100644 index 03a95ae68..000000000 --- a/net/vpnbypass/files/vpnbypass.init +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright 2017-2020 Stan Grishin (stangri@melmac.net) -# shellcheck disable=SC2039,SC1091,SC2086,SC3043,SC3057,SC3060 -PKG_VERSION='dev-test' - -# shellcheck disable=SC2034 -START=94 -# 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 - -version() { echo "$PKG_VERSION"; } - -readonly __ERROR__='\033[0;31mERROR\033[0m' - -# shellcheck disable=SC2034 -serviceEnabled=0 -verbosity=2 -TID='200' -IPSET='vpnbypass' -FW_MARK='0x010000' -FW_MASK='0xff0000' -wan_if4='' -wan_gw='' - -readonly packageName='vpnbypass' -readonly serviceName="$packageName $PKG_VERSION" -readonly sharedMemoryOutput="/dev/shm/$packageName-output" - -output() { -# Can take a single parameter (text) to be output at any verbosity -# Or target verbosity level and text to be output at specifc verbosity - local msg memmsg logmsg - if [ $# -ne 1 ]; then - if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; else return 0; fi - fi - [ -t 1 ] && printf "%b" "$1" - 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:-service} [$$]" "$(printf "%b" "$logmsg")" - rm -f "$sharedMemoryOutput" - else - printf "%b" "$msg" >> "$sharedMemoryOutput" - fi -} -load_package_config() { - config_load "$packageName" - config_get_bool serviceEnabled 'config' 'enabled' 1 - config_get verbosity 'config' 'verbosity' '2' - if [ -z "${verbosity##*[!0-9]*}" ] || [ "$verbosity" -lt 0 ] || [ "$verbosity" -gt 2 ]; then - verbosity=1 - fi - . /lib/functions/network.sh -} - -is_enabled() { - local sleepCount=1 - load_package_config - while : ; do - network_find_wan wan_if4 - [ "$serviceEnabled" -gt 0 ] || return 1 - [ -n "$wan_if4" ] && network_get_gateway wan_gw "$wan_if4" - if [ $sleepCount -ge 25 ] || [ -n "$wan_gw" ]; then break; fi - output "$serviceName waiting for wan gateway...\\n" - sleep 2; network_flush_cache; sleepCount=$((sleepCount+1)); - done - [ -n "$wan_gw" ] && return 0 - output "$__ERROR__: $serviceName failed to discover WAN gateway.\\n"; return 1; -} - -is_ovpn() { local dev i; for i in ifname device; do [ -z "$dev" ] && dev="$(uci -q get "network.${1}.${i}")"; done; if [ "${dev:0:3}" = "tun" ] || [ "${dev:0:3}" = "tap" ] || [ -f "/sys/devices/virtual/net/${dev}/tun_flags" ]; then return 0; else return 1; fi; } -is_wan() { if [ -n "$wan_if4" ] && [ "$1" = "$wan_if4" ]; then return 0; else return 1; fi; } -is_supported_interface() { if is_wan "$1" || is_ovpn "$1"; then return 0; else return 1; fi; } - -ipt() { - local d; - d="${*//-A/-D}"; [ "$d" != "$*" ] && iptables $d >/dev/null 2>&1 - d="${*//-I/-D}"; [ "$d" != "$*" ] && iptables $d >/dev/null 2>&1 - d="${*//-N/-F}"; [ "$d" != "$*" ] && iptables $d >/dev/null 2>&1 - d="${*//-N/-X}"; [ "$d" != "$*" ] && iptables $d >/dev/null 2>&1 - d="$*"; iptables $d >/dev/null 2>&1 || output "\\n$__ERROR__: iptables $d\\n" -} - -start_service() { - local ll lports rports routes ranges - is_enabled || return 1 - config_get lports 'config' 'localport' - config_get rports 'config' 'remoteport' - config_get routes 'config' 'remotesubnet' - config_get ranges 'config' 'localsubnet' - - procd_open_instance "main" - procd_set_param command /bin/true - procd_set_param stdout 1 - procd_set_param stderr 1 - procd_close_instance - - ip rule del fwmark "$FW_MARK" table "$TID" >/dev/null 2>&1; - ipset -q flush "$IPSET"; ipset -q destroy "$IPSET"; - ip route flush table "$TID"; ip route flush cache; - ip route add default via "$wan_gw" table "$TID"; ip route flush cache; - ip rule add fwmark "$FW_MARK" table "$TID" - ipset -q -exist create "$IPSET" hash:ip; ipset -q flush "$IPSET" - { modprobe xt_set; modprobe ip_set; modprobe ip_set_hash_ip; } >/dev/null 2>&1 - ipt -t mangle -D PREROUTING -m mark --mark 0x00/${FW_MASK} -g VPNBYPASS >/dev/null 2>&1 - { ipt -t mangle -N VPNBYPASS; ipt -t mangle -A PREROUTING -m mark --mark 0x00/${FW_MASK} -g VPNBYPASS; } >/dev/null 2>&1 - ipt -t mangle -A VPNBYPASS -m set --match-set $IPSET dst -j MARK --set-mark ${FW_MARK}/${FW_MASK} >/dev/null 2>&1 - for ll in ${ranges}; do ipt -t mangle -A VPNBYPASS -j MARK --set-mark ${FW_MARK}/${FW_MASK} -s "$ll"; done - for ll in ${lports}; do ipt -t mangle -A VPNBYPASS -j MARK --set-mark ${FW_MARK}/${FW_MASK} -p tcp -m multiport --sport "${ll//-/:}"; done - for ll in ${routes}; do ipt -t mangle -A VPNBYPASS -j MARK --set-mark ${FW_MARK}/${FW_MASK} -d "$ll"; done - for ll in ${rports}; do ipt -t mangle -A VPNBYPASS -j MARK --set-mark ${FW_MARK}/${FW_MASK} -p tcp -m multiport --dport "${ll//-/:}"; done - output "$serviceName started with TID: $TID; FW_MARK: $FW_MARK\\n" -} - -stop_service() { - load_package_config - ip rule del fwmark "$FW_MARK" table "$TID" >/dev/null 2>&1; - ipset -q flush "$IPSET"; ipset -q destroy "$IPSET"; - ip route flush table "$TID"; ip route flush cache; - ipt -t mangle -D PREROUTING -m mark --mark 0x00/${FW_MASK} -g VPNBYPASS >/dev/null 2>&1 - { ipt -t mangle -F VPNBYPASS; ipt -t mangle -X VPNBYPASS; } >/dev/null 2>&1 - output "$serviceName stopped\\n" -} - -service_triggers_load_interface() { is_supported_interface "$1" && ifaces="${ifaces}${1} "; } -service_triggers() { - local ifaces n - config_load network; config_foreach service_triggers_load_interface 'interface'; - procd_open_trigger - procd_add_reload_trigger 'openvpn' - if type procd_add_service_trigger 1>/dev/null 2>&1; then - procd_add_service_trigger "service.restart" "firewall" /etc/init.d/${packageName} reload - fi - procd_add_config_trigger "config.change" "${packageName}" /etc/init.d/${packageName} reload - for n in $ifaces; do procd_add_reload_interface_trigger "$n"; procd_add_interface_trigger "interface.*" "$n" /etc/init.d/vpnbypass reload; done; - output "$serviceName monitoring interfaces: $ifaces\\n" - procd_close_trigger -} diff --git a/net/vpnbypass/test.sh b/net/vpnbypass/test.sh deleted file mode 100644 index 45469ed96..000000000 --- a/net/vpnbypass/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/etc/init.d/"$1" version 2>&1 | grep "$2" diff --git a/net/wget/Makefile b/net/wget/Makefile index 7589ef1a8..006399312 100644 --- a/net/wget/Makefile +++ b/net/wget/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wget PKG_VERSION:=1.21.3 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/$(PKG_NAME) diff --git a/net/wget/patches/001-fix-nettle-ntml.patch b/net/wget/patches/001-fix-nettle-ntml.patch deleted file mode 100644 index 1cddf4070..000000000 --- a/net/wget/patches/001-fix-nettle-ntml.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/configure.ac -+++ b/configure.ac -@@ -630,6 +630,7 @@ then - AC_DEFINE([ENABLE_NTLM], 1, [Define if you want the NTLM authorization support compiled in.]) - fi - else -+ if test x"$ENABLE_NTLM" != xno; then - PKG_CHECK_MODULES([NETTLE], nettle, [ - HAVE_NETTLE=yes - LIBS="$NETTLE_LIBS $LIBS" -@@ -651,6 +652,7 @@ else - ENABLE_NTLM=yes - AC_DEFINE([ENABLE_NTLM], 1, [Define if you want the NTLM authorization support compiled in.]) - fi -+ fi - fi - - dnl ********************************************************************** diff --git a/net/wget/patches/001-upstream-fix-disable-ntlm-1.patch b/net/wget/patches/001-upstream-fix-disable-ntlm-1.patch new file mode 100644 index 000000000..5b3b1a64f --- /dev/null +++ b/net/wget/patches/001-upstream-fix-disable-ntlm-1.patch @@ -0,0 +1,25 @@ +From 485217d0ff8d0d17ea3815244b2bc2b747451e15 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20R=C3=BChsen?= +Date: Sat, 10 Dec 2022 16:43:38 +0100 +Subject: [PATCH] * configure.ac: Allow disabling NTLM if nettle present (Savannah #63431) + +--- + configure.ac | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -648,8 +648,11 @@ else + + if test x"$HAVE_NETTLE" = xyes; then + AC_DEFINE([HAVE_NETTLE], [1], [Use libnettle]) +- ENABLE_NTLM=yes +- AC_DEFINE([ENABLE_NTLM], 1, [Define if you want the NTLM authorization support compiled in.]) ++ if test x"$ENABLE_NTLM" != xno ++ then ++ ENABLE_NTLM=yes ++ AC_DEFINE([ENABLE_NTLM], 1, [Define if you want the NTLM authorization support compiled in.]) ++ fi + fi + fi + diff --git a/net/wget/patches/002-upstream-fix-disable-ntlm-2.patch b/net/wget/patches/002-upstream-fix-disable-ntlm-2.patch new file mode 100644 index 000000000..91fb52aa3 --- /dev/null +++ b/net/wget/patches/002-upstream-fix-disable-ntlm-2.patch @@ -0,0 +1,65 @@ +From c69030a904f8ab25b9ca2704c8a6dd03554e9503 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20R=C3=BChsen?= +Date: Sun, 11 Dec 2022 13:31:38 +0100 +Subject: [PATCH] * configure.ac: Disable nettle if NTLM is explicitly disabled + +--- + configure.ac | 41 +++++++++++++++++++---------------------- + 1 file changed, 19 insertions(+), 22 deletions(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -622,34 +622,31 @@ AS_IF([test x"$with_ssl" = xopenssl], [ + ]) # endif: --with-ssl == openssl? + + dnl Enable NTLM if requested and if SSL is available. +-if test x"$LIBSSL" != x || test "$ac_cv_lib_ssl32_SSL_connect" = yes ++if test x"$ENABLE_NTLM" != xno + then +- if test x"$ENABLE_NTLM" != xno ++ if test x"$LIBSSL" != x || test "$ac_cv_lib_ssl32_SSL_connect" = yes + then + ENABLE_NTLM=yes + AC_DEFINE([ENABLE_NTLM], 1, [Define if you want the NTLM authorization support compiled in.]) +- fi +-else +- PKG_CHECK_MODULES([NETTLE], nettle, [ +- HAVE_NETTLE=yes +- LIBS="$NETTLE_LIBS $LIBS" +- CFLAGS="$NETTLE_CFLAGS $CFLAGS" +- ], [ +- AC_CHECK_LIB(nettle, nettle_md4_init, [HAVE_NETTLE=yes], [HAVE_NETTLE=no; AC_MSG_WARN(*** libnettle was not found. You will not be able to use NTLM)]) +- if test x"$HAVE_NETTLE" != xyes; then +- if test x"$ENABLE_NTLM" = xyes; then +- AC_MSG_ERROR([NTLM authorization requested and SSL not enabled; aborting]) +- fi +- else +- AC_SUBST(NETTLE_LIBS, "-lnettle") ++ else ++ PKG_CHECK_MODULES([NETTLE], nettle, [ ++ HAVE_NETTLE=yes + LIBS="$NETTLE_LIBS $LIBS" +- fi +- ]) ++ CFLAGS="$NETTLE_CFLAGS $CFLAGS" ++ ], [ ++ AC_CHECK_LIB(nettle, nettle_md4_init, [HAVE_NETTLE=yes], [HAVE_NETTLE=no; AC_MSG_WARN(*** libnettle was not found. You will not be able to use NTLM)]) ++ if test x"$HAVE_NETTLE" != xyes; then ++ if test x"$ENABLE_NTLM" = xyes; then ++ AC_MSG_ERROR([NTLM authorization requested and SSL not enabled; aborting]) ++ fi ++ else ++ AC_SUBST(NETTLE_LIBS, "-lnettle") ++ LIBS="$NETTLE_LIBS $LIBS" ++ fi ++ ]) + +- if test x"$HAVE_NETTLE" = xyes; then +- AC_DEFINE([HAVE_NETTLE], [1], [Use libnettle]) +- if test x"$ENABLE_NTLM" != xno +- then ++ if test x"$HAVE_NETTLE" = xyes; then ++ AC_DEFINE([HAVE_NETTLE], [1], [Use libnettle]) + ENABLE_NTLM=yes + AC_DEFINE([ENABLE_NTLM], 1, [Define if you want the NTLM authorization support compiled in.]) + fi diff --git a/utils/docker-compose/Makefile b/utils/docker-compose/Makefile index 46f174359..c62132da1 100644 --- a/utils/docker-compose/Makefile +++ b/utils/docker-compose/Makefile @@ -1,14 +1,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=compose -PKG_VERSION:=2.12.2 -PKG_RELEASE:=$(AUTORELEASE) +PKG_VERSION:=2.14.0 +PKG_RELEASE:=1 PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:=LICENSE PKG_SOURCE:=v$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/docker/compose/tar.gz/v${PKG_VERSION}? -PKG_HASH:=311131c5d930fdb1f5e86de19ea2ad1705d23e5745b780c0b10b2eb3f964fc69 +PKG_HASH:=003efb3139298aa4795f7a9fa4723ef43c12b401c235fe0c93dd23cc2c6b5f2e PKG_MAINTAINER:=Javier Marcet diff --git a/utils/swig/Makefile b/utils/swig/Makefile index 2a3c16cd0..03378e196 100644 --- a/utils/swig/Makefile +++ b/utils/swig/Makefile @@ -7,12 +7,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=swig -PKG_VERSION:=4.0.2 -PKG_RELEASE:=2 +PKG_VERSION:=4.1.1 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@SF/$(PKG_NAME) -PKG_HASH:=d53be9730d8d58a16bf0cbd1f8ac0c0c3e1090573168bfa151b01eb47fa906fc +PKG_HASH:=2af08aced8fcd65cdb5cc62426768914bedc735b1c250325203716f78e39ac9b PKG_MAINTAINER:=John Crispin , Hirokazu MORIKAWA PKG_LICENSE:=GPL-3.0-or-later diff --git a/utils/swig/patches/000-support_v12.patch b/utils/swig/patches/000-support_v12.patch deleted file mode 100644 index 6ac90a836..000000000 --- a/utils/swig/patches/000-support_v12.patch +++ /dev/null @@ -1,1854 +0,0 @@ -diff --git a/.travis.yml b/.travis.yml -index 32c6656dd2..6530d2cb5f 100644 ---- a/.travis.yml -+++ b/.travis.yml -@@ -89,27 +89,17 @@ matrix: - dist: xenial - - compiler: gcc - os: linux -- env: SWIGLANG=javascript ENGINE=node VER=0.10 -- sudo: required -- dist: xenial -- - compiler: gcc -- os: linux -- env: SWIGLANG=javascript ENGINE=node VER=4 CPP11=1 -- sudo: required -- dist: xenial -- - compiler: gcc -- os: linux -- env: SWIGLANG=javascript ENGINE=node VER=6 CPP11=1 -+ env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1 - sudo: required - dist: xenial - - compiler: gcc - os: linux -- env: SWIGLANG=javascript ENGINE=node VER=8 CPP11=1 -+ env: SWIGLANG=javascript ENGINE=node VER=12 CPP11=1 - sudo: required - dist: xenial - - compiler: gcc - os: linux -- env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1 -+ env: SWIGLANG=javascript ENGINE=node VER=13 CPP11=1 - sudo: required - dist: xenial - - compiler: gcc -@@ -117,11 +107,6 @@ matrix: - env: SWIGLANG=javascript ENGINE=jsc - sudo: required - dist: xenial -- - compiler: gcc -- os: linux -- env: SWIGLANG=javascript ENGINE=v8 -- sudo: required -- dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=lua -diff --git a/Examples/Makefile.in b/Examples/Makefile.in -index 6fbca29db5..dadb012bf9 100644 ---- a/Examples/Makefile.in -+++ b/Examples/Makefile.in -@@ -674,8 +674,8 @@ java_clean: - # create a configuration for a new example. - - ROOT_DIR = @ROOT_DIR@ --JSINCLUDES = @JSCOREINC@ @JSV8INC@ --JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@ -+JSINCLUDES = @JSCOREINC@ -+JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ - NODEJS = @NODEJS@ - NODEGYP = @NODEGYP@ - -@@ -710,7 +710,7 @@ javascript: $(SRCDIR_SRCS) javascript_custom_interpreter - ifeq (jsc, $(ENGINE)) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(JSINCLUDES) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) --else # (v8 | node) # v8 and node must be compiled as c++ -+else # (node) # node must be compiled as c++ - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(JSINCLUDES) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - endif -@@ -759,9 +759,6 @@ ifeq (jsc, $(ENGINE)) - echo "Unknown JavascriptCore version."; \ - fi - endif --ifeq (v8, $(ENGINE)) -- echo "Unknown v8 version." --endif - - # ----------------------------------------------------------------- - # Cleaning the Javascript examples -diff --git a/Examples/javascript/example.mk b/Examples/javascript/example.mk -index 3ef012aa82..beafd6f3fb 100644 ---- a/Examples/javascript/example.mk -+++ b/Examples/javascript/example.mk -@@ -7,19 +7,13 @@ else - JSENGINE=node - endif - --ifneq (, $(V8_VERSION)) -- JSV8_VERSION=$(V8_VERSION) --else -- JSV8_VERSION=0x031110 --endif -- - EXAMPLES_TOP = ../.. - SWIG_TOP = ../../.. - SWIGEXE = $(SWIG_TOP)/swig - SWIG_LIB_DIR = $(SWIG_TOP)/$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib - TARGET = example - INTERFACE = example.i --SWIGOPT = -$(JSENGINE) -DV8_VERSION=$(JSV8_VERSION) -+SWIGOPT = -$(JSENGINE) - - check: build - $(MAKE) -f $(EXAMPLES_TOP)/Makefile SRCDIR='$(SRCDIR)' JSENGINE='$(JSENGINE)' TARGET='$(TARGET)' javascript_run -diff --git a/Examples/javascript/native/example.i b/Examples/javascript/native/example.i -index 8c61600606..e94f18118b 100644 ---- a/Examples/javascript/native/example.i -+++ b/Examples/javascript/native/example.i -@@ -15,7 +15,7 @@ int placeholder() { return 0; } - static SwigV8ReturnValue JavaScript_do_work(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - const int MY_MAGIC_NUMBER = 5; -- v8::Handle jsresult = -+ v8::Local jsresult = - SWIG_From_int(static_cast< int >(MY_MAGIC_NUMBER)); - if (args.Length() != 0) - SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments."); -diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in -index 8127415f12..ce16f2ec0d 100644 ---- a/Examples/test-suite/javascript/Makefile.in -+++ b/Examples/test-suite/javascript/Makefile.in -@@ -22,16 +22,8 @@ else - JSENGINE=node - endif - --ifneq (, $(V8_VERSION)) -- JSV8_VERSION=$(V8_VERSION) --else -- JSV8_VERSION=0x031110 --endif -- - include $(srcdir)/../common.mk - --SWIGOPT += -DV8_VERSION=$(JSV8_VERSION) -- - _setup = \ - if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - echo "$(ACTION)ing $(LANGUAGE) ($(JSENGINE)) testcase $* (with run test)" ; \ -diff --git a/Examples/test-suite/native_directive.i b/Examples/test-suite/native_directive.i -index 9ae76e0b7f..99089af507 100644 ---- a/Examples/test-suite/native_directive.i -+++ b/Examples/test-suite/native_directive.i -@@ -53,7 +53,7 @@ extern "C" JNIEXPORT jint JNICALL Java_native_1directive_native_1directiveJNI_Co - - static SwigV8ReturnValue JavaScript_alpha_count(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); -- v8::Handle jsresult; -+ v8::Local jsresult; - char *arg1 = (char *)0; - int res1; - char *buf1 = 0; -diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg -index c4aaf3db0c..b470e2aeeb 100644 ---- a/Lib/javascript/v8/javascriptcode.swg -+++ b/Lib/javascript/v8/javascriptcode.swg -@@ -11,7 +11,7 @@ - static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle self = args.Holder(); -+ v8::Local self = args.Holder(); - $jslocals - if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); - $jscode -@@ -53,7 +53,7 @@ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - - OverloadErrorHandler errorHandler; -- v8::Handle self; -+ v8::Local self; - - // switch all cases by means of series of if-returns. - $jsdispatchcases -@@ -78,7 +78,7 @@ fail: - static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args, V8ErrorHandler &SWIGV8_ErrorHandler) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle self = args.Holder(); -+ v8::Local self = args.Holder(); - $jslocals - if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); - $jscode -@@ -103,17 +103,10 @@ fail: - %{ - if(args.Length() == $jsargcount) { - errorHandler.err.Clear(); --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -- self = $jswrapper(args, errorHandler); -- if(errorHandler.err.IsEmpty()) { -- SWIGV8_ESCAPE(self); -- } --#else - $jswrapper(args, errorHandler); - if(errorHandler.err.IsEmpty()) { - return; - } --#endif - } - %} - -@@ -124,23 +117,8 @@ fail: - * ----------------------------------------------------------------------------- */ - %fragment ("js_dtor", "templates") - %{ -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) --static void $jswrapper(v8::Persistent< v8::Value > object, void *parameter) { -- SWIGV8_Proxy *proxy = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) --static void $jswrapper(v8::Isolate *isolate, v8::Persistent object, void *parameter) { -- SWIGV8_Proxy *proxy = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) --static void $jswrapper(v8::Isolate *isolate, v8::Persistent *object, SWIGV8_Proxy *proxy) { --#elif (V8_MAJOR_VERSION-0) < 5 --static void $jswrapper(const v8::WeakCallbackData &data) { -- v8::Local object = data.GetValue(); -- SWIGV8_Proxy *proxy = data.GetParameter(); --#else - static void $jswrapper(const v8::WeakCallbackInfo &data) { - SWIGV8_Proxy *proxy = data.GetParameter(); --#endif - - if(proxy->swigCMemOwn && proxy->swigCObject) { - #ifdef SWIGRUNTIME_DEBUG -@@ -149,20 +127,6 @@ static void $jswrapper(const v8::WeakCallbackData &dat - $jsfree proxy->swigCObject; - } - delete proxy; -- --#if (V8_MAJOR_VERSION-0) < 5 -- object.Clear(); --#endif -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- object.Dispose(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- object.Dispose(isolate); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) -- object->Dispose(isolate); --#elif (V8_MAJOR_VERSION-0) < 5 -- object->Dispose(); --#endif - } - %} - -@@ -174,40 +138,14 @@ static void $jswrapper(const v8::WeakCallbackData &dat - * ----------------------------------------------------------------------------- */ - %fragment ("js_dtoroverride", "templates") - %{ --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) --static void $jswrapper(v8::Persistent object, void *parameter) { -- SWIGV8_Proxy *proxy = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) --static void $jswrapper(v8::Isolate *isolate, v8::Persistent object, void *parameter) { -- SWIGV8_Proxy *proxy = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) --static void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object> *object, SWIGV8_Proxy *proxy) { --#elif (V8_MAJOR_VERSION-0) < 5 --static void $jswrapper(const v8::WeakCallbackData &data) { -- v8::Local object = data.GetValue(); -- SWIGV8_Proxy *proxy = data.GetParameter(); --#else - static void $jswrapper(const v8::WeakCallbackInfo &data) { - SWIGV8_Proxy *proxy = data.GetParameter(); --#endif - - if(proxy->swigCMemOwn && proxy->swigCObject) { - $jstype arg1 = ($jstype)proxy->swigCObject; - ${destructor_action} - } - delete proxy; -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- object.Dispose(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- object.Dispose(isolate); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) -- object->Dispose(isolate); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- object->Dispose(); --#elif (V8_MAJOR_VERSION-0) < 5 -- object.Clear(); --#endif - } - %} - -@@ -219,14 +157,10 @@ static void $jswrapper(const v8::WeakCallbackInfo &data) { - * ----------------------------------------------------------------------------- */ - %fragment("js_getter", "templates") - %{ --#if (V8_MAJOR_VERSION-0) < 5 --static SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo &info) { --#else - static SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo &info) { --#endif - SWIGV8_HANDLESCOPE(); - -- v8::Handle jsresult; -+ v8::Local jsresult; - $jslocals - $jscode - SWIGV8_RETURN_INFO(jsresult, info); -@@ -245,11 +179,7 @@ fail: - * ----------------------------------------------------------------------------- */ - %fragment("js_setter", "templates") - %{ --#if (V8_MAJOR_VERSION-0) < 5 --static void $jswrapper(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid &info) { --#else - static void $jswrapper(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid &info) { --#endif - SWIGV8_HANDLESCOPE(); - - $jslocals -@@ -271,7 +201,7 @@ fail: - static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle jsresult; -+ v8::Local jsresult; - $jslocals - if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); - -@@ -296,7 +226,7 @@ fail: - static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle jsresult; -+ v8::Local jsresult; - OverloadErrorHandler errorHandler; - $jscode - -@@ -320,7 +250,7 @@ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args, V8ErrorHandler - { - SWIGV8_HANDLESCOPE(); - -- v8::Handle jsresult; -+ v8::Local jsresult; - $jslocals - $jscode - SWIGV8_RETURN(jsresult); -@@ -342,17 +272,10 @@ fail: - - if(args.Length() == $jsargcount) { - errorHandler.err.Clear(); --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -- jsresult = $jswrapper(args, errorHandler); -- if(errorHandler.err.IsEmpty()) { -- SWIGV8_ESCAPE(jsresult); -- } --#else - $jswrapper(args, errorHandler); - if(errorHandler.err.IsEmpty()) { - return; - } --#endif - } - %} - -@@ -374,7 +297,7 @@ fail: - %fragment("jsv8_define_class_template", "templates") - %{ - /* Name: $jsmangledname, Type: $jsmangledtype, Dtor: $jsdtor */ -- v8::Handle $jsmangledname_class = SWIGV8_CreateClassTemplate("$jsmangledname"); -+ v8::Local $jsmangledname_class = SWIGV8_CreateClassTemplate("$jsmangledname"); - SWIGV8_SET_CLASS_TEMPL($jsmangledname_clientData.class_templ, $jsmangledname_class); - $jsmangledname_clientData.dtor = $jsdtor; - if (SWIGTYPE_$jsmangledtype->clientdata == 0) { -@@ -392,15 +315,11 @@ fail: - %{ - if (SWIGTYPE_p$jsbaseclass->clientdata && !(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ.IsEmpty())) - { --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -- $jsmangledname_class->Inherit(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ); --#else - $jsmangledname_class->Inherit( - v8::Local::New( - v8::Isolate::GetCurrent(), - static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ) - ); --#endif - - #ifdef SWIGRUNTIME_DEBUG - printf("Inheritance successful $jsmangledname $jsbaseclass\n"); -@@ -420,11 +339,10 @@ fail: - %fragment("jsv8_create_class_instance", "templates") - %{ - /* Class: $jsname ($jsmangledname) */ -- v8::Handle $jsmangledname_class_0 = SWIGV8_CreateClassTemplate("$jsname"); -+ v8::Local $jsmangledname_class_0 = SWIGV8_CreateClassTemplate("$jsname"); - $jsmangledname_class_0->SetCallHandler($jsctor); - $jsmangledname_class_0->Inherit($jsmangledname_class); -- $jsmangledname_class_0->SetHiddenPrototype(true); -- v8::Handle $jsmangledname_obj = $jsmangledname_class_0->GetFunction(); -+ v8::Local $jsmangledname_obj = $jsmangledname_class_0->GetFunction(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked(); - %} - - /* ----------------------------------------------------------------------------- -@@ -435,7 +353,7 @@ fail: - * ----------------------------------------------------------------------------- */ - %fragment("jsv8_register_class", "templates") - %{ -- $jsparent_obj->Set(SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj); -+ $jsparent_obj->Set(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj); - %} - - /* ----------------------------------------------------------------------------- -@@ -444,7 +362,7 @@ fail: - * ----------------------------------------------------------------------------- */ - %fragment("jsv8_create_namespace", "templates") - %{ -- v8::Handle $jsmangledname_obj = SWIGV8_OBJECT_NEW(); -+ v8::Local $jsmangledname_obj = SWIGV8_OBJECT_NEW(); - %} - - /* ----------------------------------------------------------------------------- -@@ -455,7 +373,7 @@ fail: - * ----------------------------------------------------------------------------- */ - %fragment("jsv8_register_namespace", "templates") - %{ -- $jsparent_obj->Set(SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj); -+ $jsparent_obj->Set(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj); - %} - - /* ----------------------------------------------------------------------------- -diff --git a/Lib/javascript/v8/javascriptcomplex.swg b/Lib/javascript/v8/javascriptcomplex.swg -index d3b4aaffa6..533e548131 100644 ---- a/Lib/javascript/v8/javascriptcomplex.swg -+++ b/Lib/javascript/v8/javascriptcomplex.swg -@@ -12,7 +12,7 @@ - %fragment(SWIG_From_frag(Type),"header", - fragment=SWIG_From_frag(double)) - { --SWIGINTERNINLINE v8::Handle -+SWIGINTERNINLINE v8::Local - SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) - { - SWIGV8_HANDLESCOPE_ESC(); -@@ -32,12 +32,12 @@ SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) - fragment=SWIG_AsVal_frag(double)) - { - SWIGINTERN int --SWIG_AsVal_dec(Type) (v8::Handle o, Type* val) -+SWIG_AsVal_dec(Type) (v8::Local o, Type* val) - { - SWIGV8_HANDLESCOPE(); - - if (o->IsArray()) { -- v8::Handle array = v8::Handle::Cast(o); -+ v8::Local array = v8::Local::Cast(o); - - if(array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2]."); - double re, im; -@@ -74,12 +74,12 @@ SWIG_AsVal_dec(Type) (v8::Handle o, Type* val) - %fragment(SWIG_AsVal_frag(Type),"header", - fragment=SWIG_AsVal_frag(float)) { - SWIGINTERN int --SWIG_AsVal_dec(Type) (v8::Handle o, Type* val) -+SWIG_AsVal_dec(Type) (v8::Local o, Type* val) - { - SWIGV8_HANDLESCOPE(); - - if (o->IsArray()) { -- v8::Handle array = v8::Handle::Cast(o); -+ v8::Local array = v8::Local::Cast(o); - - if(array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2]."); - double re, im; -diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg -index 80fbd7aa1a..d722581552 100644 ---- a/Lib/javascript/v8/javascripthelpers.swg -+++ b/Lib/javascript/v8/javascripthelpers.swg -@@ -1,39 +1,26 @@ - %insert(runtime) %{ - --// Note: since 3.19 there are new CallBack types, since 03.21.9 the old ones have been removed --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) --typedef v8::InvocationCallback SwigV8FunctionCallback; --typedef v8::AccessorGetter SwigV8AccessorGetterCallback; --typedef v8::AccessorSetter SwigV8AccessorSetterCallback; --typedef v8::AccessorInfo SwigV8PropertyCallbackInfoVoid; --#elif (V8_MAJOR_VERSION-0) < 5 --typedef v8::FunctionCallback SwigV8FunctionCallback; --typedef v8::AccessorGetterCallback SwigV8AccessorGetterCallback; --typedef v8::AccessorSetterCallback SwigV8AccessorSetterCallback; --typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; --#else - typedef v8::FunctionCallback SwigV8FunctionCallback; - typedef v8::AccessorNameGetterCallback SwigV8AccessorGetterCallback; - typedef v8::AccessorNameSetterCallback SwigV8AccessorSetterCallback; - typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; --#endif - - /** - * Creates a class template for a class with specified initialization function. - */ --SWIGRUNTIME v8::Handle SWIGV8_CreateClassTemplate(const char* symbol) { -+SWIGRUNTIME v8::Local SWIGV8_CreateClassTemplate(const char* symbol) { - SWIGV8_HANDLESCOPE_ESC(); - - v8::Local class_templ = SWIGV8_FUNCTEMPLATE_NEW_VOID(); - class_templ->SetClassName(SWIGV8_SYMBOL_NEW(symbol)); - -- v8::Handle inst_templ = class_templ->InstanceTemplate(); -+ v8::Local inst_templ = class_templ->InstanceTemplate(); - inst_templ->SetInternalFieldCount(1); - -- v8::Handle equals_templ = class_templ->PrototypeTemplate(); -+ v8::Local equals_templ = class_templ->PrototypeTemplate(); - equals_templ->Set(SWIGV8_SYMBOL_NEW("equals"), SWIGV8_FUNCTEMPLATE_NEW(_SWIGV8_wrap_equals)); - -- v8::Handle cptr_templ = class_templ->PrototypeTemplate(); -+ v8::Local cptr_templ = class_templ->PrototypeTemplate(); - cptr_templ->Set(SWIGV8_SYMBOL_NEW("getCPtr"), SWIGV8_FUNCTEMPLATE_NEW(_wrap_getCPtr)); - - SWIGV8_ESCAPE(class_templ); -@@ -42,55 +29,47 @@ SWIGRUNTIME v8::Handle SWIGV8_CreateClassTemplate(const ch - /** - * Registers a class method with given name for a given class template. - */ --SWIGRUNTIME void SWIGV8_AddMemberFunction(v8::Handle class_templ, const char* symbol, -+SWIGRUNTIME void SWIGV8_AddMemberFunction(v8::Local class_templ, const char* symbol, - SwigV8FunctionCallback _func) { -- v8::Handle proto_templ = class_templ->PrototypeTemplate(); -+ v8::Local proto_templ = class_templ->PrototypeTemplate(); - proto_templ->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)); - } - - /** - * Registers a class property with given name for a given class template. - */ --SWIGRUNTIME void SWIGV8_AddMemberVariable(v8::Handle class_templ, const char* symbol, -+SWIGRUNTIME void SWIGV8_AddMemberVariable(v8::Local class_templ, const char* symbol, - SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) { -- v8::Handle proto_templ = class_templ->InstanceTemplate(); -+ v8::Local proto_templ = class_templ->InstanceTemplate(); - proto_templ->SetAccessor(SWIGV8_SYMBOL_NEW(symbol), getter, setter); - } - - /** - * Registers a class method with given name for a given object. - */ --SWIGRUNTIME void SWIGV8_AddStaticFunction(v8::Handle obj, const char* symbol, -+SWIGRUNTIME void SWIGV8_AddStaticFunction(v8::Local obj, const char* symbol, - const SwigV8FunctionCallback& _func) { -- obj->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction()); -+#if (NODE_MODULE_VERSION < 72) -+ obj->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked()); -+#else -+ obj->Set(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked()); -+#endif - } - - /** - * Registers a class method with given name for a given object. - */ --SWIGRUNTIME void SWIGV8_AddStaticVariable(v8::Handle obj, const char* symbol, -+SWIGRUNTIME void SWIGV8_AddStaticVariable(v8::Local obj, const char* symbol, - SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) { --#if (V8_MAJOR_VERSION-0) < 5 -- obj->SetAccessor(SWIGV8_SYMBOL_NEW(symbol), getter, setter); --#else - obj->SetAccessor(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW(symbol), getter, setter); --#endif - } - --#if (V8_MAJOR_VERSION-0) < 5 --SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid& info) --#else - SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid& info) --#endif - { - char buffer[256]; - char msg[512]; - int res; - --#if (V8_MAJOR_VERSION-0) < 5 -- property->WriteUtf8(buffer, 256); -- res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); --#else - v8::Local sproperty; - if (property->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocal(&sproperty)) { - SWIGV8_WRITE_UTF8(sproperty, buffer, 256); -@@ -99,7 +78,6 @@ SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local exports) -+void SWIGV8_INIT (v8::Local exports) - #else --void SWIGV8_INIT (v8::Handle exports, v8::Handle /*module*/) -+void SWIGV8_INIT (v8::Local exports, v8::Local /*module*/) - #endif - { - SWIG_InitializeModule(static_cast(&exports)); - - SWIGV8_HANDLESCOPE(); - -- v8::Handle exports_obj = exports; -+ v8::Local exports_obj = exports; - %} - - -diff --git a/Lib/javascript/v8/javascriptprimtypes.swg b/Lib/javascript/v8/javascriptprimtypes.swg -index f76be983b1..41635e9d2d 100644 ---- a/Lib/javascript/v8/javascriptprimtypes.swg -+++ b/Lib/javascript/v8/javascriptprimtypes.swg -@@ -6,7 +6,7 @@ - - %fragment(SWIG_From_frag(bool),"header") { - SWIGINTERNINLINE --v8::Handle -+v8::Local - SWIG_From_dec(bool)(bool value) - { - return SWIGV8_BOOLEAN_NEW(value); -@@ -16,7 +16,7 @@ SWIG_From_dec(bool)(bool value) - %fragment(SWIG_AsVal_frag(bool),"header", - fragment=SWIG_AsVal_frag(long)) { - SWIGINTERN --int SWIG_AsVal_dec(bool)(v8::Handle obj, bool *val) -+int SWIG_AsVal_dec(bool)(v8::Local obj, bool *val) - { - if(!obj->IsBoolean()) { - return SWIG_ERROR; -@@ -31,7 +31,7 @@ int SWIG_AsVal_dec(bool)(v8::Handle obj, bool *val) - - %fragment(SWIG_From_frag(int),"header") { - SWIGINTERNINLINE --v8::Handle SWIG_From_dec(int)(int value) -+v8::Local SWIG_From_dec(int)(int value) - { - return SWIGV8_INT32_NEW(value); - } -@@ -39,7 +39,7 @@ v8::Handle SWIG_From_dec(int)(int value) - - %fragment(SWIG_AsVal_frag(int),"header") { - SWIGINTERN --int SWIG_AsVal_dec(int)(v8::Handle valRef, int* val) -+int SWIG_AsVal_dec(int)(v8::Local valRef, int* val) - { - if (!valRef->IsNumber()) { - return SWIG_TypeError; -@@ -54,7 +54,7 @@ int SWIG_AsVal_dec(int)(v8::Handle valRef, int* val) - - %fragment(SWIG_From_frag(long),"header") { - SWIGINTERNINLINE --v8::Handle SWIG_From_dec(long)(long value) -+v8::Local SWIG_From_dec(long)(long value) - { - return SWIGV8_NUMBER_NEW(value); - } -@@ -63,7 +63,7 @@ v8::Handle SWIG_From_dec(long)(long value) - %fragment(SWIG_AsVal_frag(long),"header", - fragment="SWIG_CanCastAsInteger") { - SWIGINTERN --int SWIG_AsVal_dec(long)(v8::Handle obj, long* val) -+int SWIG_AsVal_dec(long)(v8::Local obj, long* val) - { - if (!obj->IsNumber()) { - return SWIG_TypeError; -@@ -79,7 +79,7 @@ int SWIG_AsVal_dec(long)(v8::Handle obj, long* val) - %fragment(SWIG_From_frag(unsigned long),"header", - fragment=SWIG_From_frag(long)) { - SWIGINTERNINLINE --v8::Handle SWIG_From_dec(unsigned long)(unsigned long value) -+v8::Local SWIG_From_dec(unsigned long)(unsigned long value) - { - return (value > LONG_MAX) ? - SWIGV8_INTEGER_NEW_UNS(value) : SWIGV8_INTEGER_NEW(%numeric_cast(value,long)); -@@ -89,7 +89,7 @@ v8::Handle SWIG_From_dec(unsigned long)(unsigned long value) - %fragment(SWIG_AsVal_frag(unsigned long),"header", - fragment="SWIG_CanCastAsInteger") { - SWIGINTERN --int SWIG_AsVal_dec(unsigned long)(v8::Handle obj, unsigned long *val) -+int SWIG_AsVal_dec(unsigned long)(v8::Local obj, unsigned long *val) - { - if(!obj->IsNumber()) { - return SWIG_TypeError; -@@ -115,7 +115,7 @@ int SWIG_AsVal_dec(unsigned long)(v8::Handle obj, unsigned long *val) - fragment="SWIG_LongLongAvailable") { - %#ifdef SWIG_LONG_LONG_AVAILABLE - SWIGINTERNINLINE --v8::Handle SWIG_From_dec(long long)(long long value) -+v8::Local SWIG_From_dec(long long)(long long value) - { - return SWIGV8_NUMBER_NEW(value); - } -@@ -128,7 +128,7 @@ v8::Handle SWIG_From_dec(long long)(long long value) - fragment="SWIG_LongLongAvailable") { - %#ifdef SWIG_LONG_LONG_AVAILABLE - SWIGINTERN --int SWIG_AsVal_dec(long long)(v8::Handle obj, long long* val) -+int SWIG_AsVal_dec(long long)(v8::Local obj, long long* val) - { - if (!obj->IsNumber()) { - return SWIG_TypeError; -@@ -148,7 +148,7 @@ int SWIG_AsVal_dec(long long)(v8::Handle obj, long long* val) - fragment="SWIG_LongLongAvailable") { - %#ifdef SWIG_LONG_LONG_AVAILABLE - SWIGINTERNINLINE --v8::Handle SWIG_From_dec(unsigned long long)(unsigned long long value) -+v8::Local SWIG_From_dec(unsigned long long)(unsigned long long value) - { - return (value > LONG_MAX) ? - SWIGV8_INTEGER_NEW_UNS(value) : SWIGV8_INTEGER_NEW(%numeric_cast(value,long)); -@@ -162,7 +162,7 @@ v8::Handle SWIG_From_dec(unsigned long long)(unsigned long long value - fragment="SWIG_LongLongAvailable") { - %#ifdef SWIG_LONG_LONG_AVAILABLE - SWIGINTERN --int SWIG_AsVal_dec(unsigned long long)(v8::Handle obj, unsigned long long *val) -+int SWIG_AsVal_dec(unsigned long long)(v8::Local obj, unsigned long long *val) - { - if(!obj->IsNumber()) { - return SWIG_TypeError; -@@ -185,7 +185,7 @@ int SWIG_AsVal_dec(unsigned long long)(v8::Handle obj, unsigned long - - %fragment(SWIG_From_frag(double),"header") { - SWIGINTERN --v8::Handle SWIG_From_dec(double) (double val) -+v8::Local SWIG_From_dec(double) (double val) - { - return SWIGV8_NUMBER_NEW(val); - } -@@ -193,7 +193,7 @@ v8::Handle SWIG_From_dec(double) (double val) - - %fragment(SWIG_AsVal_frag(double),"header") { - SWIGINTERN --int SWIG_AsVal_dec(double)(v8::Handle obj, double *val) -+int SWIG_AsVal_dec(double)(v8::Local obj, double *val) - { - if(!obj->IsNumber()) { - return SWIG_TypeError; -@@ -203,4 +203,3 @@ int SWIG_AsVal_dec(double)(v8::Handle obj, double *val) - return SWIG_OK; - } - } -- -diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg -index 2452f4040d..2023d023da 100644 ---- a/Lib/javascript/v8/javascriptrun.swg -+++ b/Lib/javascript/v8/javascriptrun.swg -@@ -5,70 +5,37 @@ - - // First v8 version that uses "SetWeak" and not "MakeWeak" - --#define SWIGV8_SETWEAK_VERSION 0x032224 -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031803) --#define SWIGV8_STRING_NEW2(cstr, len) v8::String::New(cstr, len) --#else -+#if (NODE_MODULE_VERSION < 72) - #define SWIGV8_STRING_NEW2(cstr, len) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), cstr, v8::String::kNormalString, len) -+#else -+#define SWIGV8_STRING_NEW2(cstr, len) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), cstr, v8::NewStringType::kNormal, len)).ToLocalChecked() - #endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) --typedef v8::Handle SwigV8ReturnValue; --typedef v8::Arguments SwigV8Arguments; --typedef v8::AccessorInfo SwigV8PropertyCallbackInfo; --#define SWIGV8_RETURN(val) return scope.Close(val) --#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val) --#else - typedef void SwigV8ReturnValue; - typedef v8::FunctionCallbackInfo SwigV8Arguments; - typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; - #define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return - #define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032117) --#define SWIGV8_HANDLESCOPE() v8::HandleScope scope --#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope --#define SWIGV8_ESCAPE(val) return scope.Close(val) --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032224) --#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); --#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope(v8::Isolate::GetCurrent()); --#define SWIGV8_ESCAPE(val) return scope.Close(val) --#else - #define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); - #define SWIGV8_HANDLESCOPE_ESC() v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()); - #define SWIGV8_ESCAPE(val) return scope.Escape(val) --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032224) --#define SWIGV8_ADJUST_MEMORY(size) v8::V8::AdjustAmountOfExternalAllocatedMemory(size) --#define SWIGV8_CURRENT_CONTEXT() v8::Context::GetCurrent() --#define SWIGV8_THROW_EXCEPTION(err) v8::ThrowException(err) --#define SWIGV8_STRING_NEW(str) v8::String::New(str) --#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewSymbol(sym) -+#if (NODE_MODULE_VERSION < 72) -+#define SWIGV8_ADJUST_MEMORY(size) v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(size) -+#define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext() -+#define SWIGV8_THROW_EXCEPTION(err) v8::Isolate::GetCurrent()->ThrowException(err) -+#define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str, v8::String::kNormalString) -+#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym, v8::String::kNormalString) - #else - #define SWIGV8_ADJUST_MEMORY(size) v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(size) - #define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext() - #define SWIGV8_THROW_EXCEPTION(err) v8::Isolate::GetCurrent()->ThrowException(err) --#define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str) --#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym) -+#define SWIGV8_STRING_NEW(str) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str, v8::NewStringType::kNormal)).ToLocalChecked() -+#define SWIGV8_SYMBOL_NEW(sym) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym, v8::NewStringType::kNormal)).ToLocalChecked() - #endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318) --#define SWIGV8_ARRAY_NEW() v8::Array::New() --#define SWIGV8_BOOLEAN_NEW(bool) v8::Boolean::New(bool) --#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(val) --#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(func) --#define SWIGV8_FUNCTEMPLATE_NEW_VOID() v8::FunctionTemplate::New() --#define SWIGV8_INT32_NEW(num) v8::Int32::New(num) --#define SWIGV8_INTEGER_NEW(num) v8::Integer::New(num) --#define SWIGV8_INTEGER_NEW_UNS(num) v8::Integer::NewFromUnsigned(num) --#define SWIGV8_NUMBER_NEW(num) v8::Number::New(num) --#define SWIGV8_OBJECT_NEW() v8::Object::New() --#define SWIGV8_UNDEFINED() v8::Undefined() --#define SWIGV8_NULL() v8::Null() --#else -+ - #define SWIGV8_ARRAY_NEW() v8::Array::New(v8::Isolate::GetCurrent()) - #define SWIGV8_BOOLEAN_NEW(bool) v8::Boolean::New(v8::Isolate::GetCurrent(), bool) - #define SWIGV8_EXTERNAL_NEW(val) v8::External::New(v8::Isolate::GetCurrent(), val) -@@ -81,15 +48,8 @@ typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; - #define SWIGV8_OBJECT_NEW() v8::Object::New(v8::Isolate::GetCurrent()) - #define SWIGV8_UNDEFINED() v8::Undefined(v8::Isolate::GetCurrent()) - #define SWIGV8_NULL() v8::Null(v8::Isolate::GetCurrent()) --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) --#define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ = v8::Persistent::New(class); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) --#define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ = v8::Persistent::New(v8::Isolate::GetCurrent(), class); --#else - #define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ.Reset(v8::Isolate::GetCurrent(), class); --#endif - - #ifdef NODE_VERSION - #if NODE_VERSION_AT_LEAST(10, 12, 0) -@@ -98,23 +58,17 @@ typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; - #endif - - //Necessary to check Node.js version because V8 API changes are backported in Node.js --#if (defined(NODE_VERSION) && !defined(SWIG_NODE_AT_LEAST_1012)) || \ -- (!defined(NODE_VERSION) && (V8_MAJOR_VERSION-0) < 7) --#define SWIGV8_TO_OBJECT(handle) (handle)->ToObject() --#define SWIGV8_TO_STRING(handle) (handle)->ToString() --#define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue() --#define SWIGV8_INTEGER_VALUE(handle) (handle)->IntegerValue() --#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue() --#define SWIGV8_WRITE_UTF8(handle, buffer, len) (handle)->WriteUtf8(buffer, len) --#define SWIGV8_UTF8_LENGTH(handle) (handle)->Utf8Length() --#else - #define SWIGV8_TO_OBJECT(handle) (handle)->ToObject(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked() - #define SWIGV8_TO_STRING(handle) (handle)->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked() - #define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() - #define SWIGV8_INTEGER_VALUE(handle) (handle)->IntegerValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() --#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() - #define SWIGV8_WRITE_UTF8(handle, buffer, len) (handle)->WriteUtf8(v8::Isolate::GetCurrent(), buffer, len) - #define SWIGV8_UTF8_LENGTH(handle) (handle)->Utf8Length(v8::Isolate::GetCurrent()) -+ -+#if (NODE_MODULE_VERSION < 72) -+#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() -+#else -+#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(v8::Isolate::GetCurrent()) - #endif - - /* --------------------------------------------------------------------------- -@@ -163,7 +117,7 @@ public: - SWIGV8_THROW_EXCEPTION(err); - } - } -- v8::Handle err; -+ v8::Local err; - }; - - /* --------------------------------------------------------------------------- -@@ -182,23 +136,8 @@ public: - }; - - ~SWIGV8_Proxy() { --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- handle.ClearWeak(); -- handle.Dispose(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) -- handle.ClearWeak(v8::Isolate::GetCurrent()); -- handle.Dispose(v8::Isolate::GetCurrent()); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- handle.ClearWeak(); -- handle.Dispose(); --#else - handle.ClearWeak(); - handle.Reset(); --#endif -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- handle.Clear(); --#endif - - SWIGV8_ADJUST_MEMORY(-SWIGV8_AVG_OBJ_SIZE); - } -@@ -213,32 +152,17 @@ class SWIGV8_ClientData { - public: - v8::Persistent class_templ; - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- void (*dtor) (v8::Persistent< v8::Value> object, void *parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Value> object, void *parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy); --#elif (V8_MAJOR_VERSION-0) < 5 -- void (*dtor) (const v8::WeakCallbackData &data); --#else - void (*dtor) (const v8::WeakCallbackInfo &data); --#endif - }; - - SWIGRUNTIME v8::Persistent SWIGV8_SWIGTYPE_Proxy_class_templ; - --SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(v8::Handle objRef, void **ptr, swig_type_info *info, int flags) { -+SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(v8::Local objRef, void **ptr, swig_type_info *info, int flags) { - SWIGV8_HANDLESCOPE(); - - if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) -- v8::Handle cdataRef = objRef->GetInternalField(0); -- SWIGV8_Proxy *cdata = static_cast(v8::External::Unwrap(cdataRef)); --#else - SWIGV8_Proxy *cdata = static_cast(objRef->GetAlignedPointerFromInternalField(0)); --#endif - - if(cdata == NULL) { - return SWIG_ERROR; -@@ -261,39 +185,21 @@ SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(v8::Handle objRef, void * - } - - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) --SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Persistent< v8::Value > object, void *parameter) { -- SWIGV8_Proxy *proxy = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) --SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Value > object, void *parameter) { -- SWIGV8_Proxy *proxy = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) --SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) { --#elif (V8_MAJOR_VERSION-0) < 5 --SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackData &data) { -- SWIGV8_Proxy *proxy = data.GetParameter(); --#else - SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackInfo &data) { - SWIGV8_Proxy *proxy = data.GetParameter(); --#endif - - delete proxy; - } - --SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Handle valRef, void **ptr) { -+SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Local valRef, void **ptr) { - if(!valRef->IsObject()) { - return SWIG_TypeError; - } -- v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); -+ v8::Local objRef = SWIGV8_TO_OBJECT(valRef); - - if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) -- v8::Handle cdataRef = objRef->GetInternalField(0); -- SWIGV8_Proxy *cdata = static_cast(v8::External::Unwrap(cdataRef)); --#else - SWIGV8_Proxy *cdata = static_cast(objRef->GetAlignedPointerFromInternalField(0)); --#endif - - if(cdata == NULL) { - return SWIG_ERROR; -@@ -304,70 +210,31 @@ SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Handle valRef, void **ptr) - return SWIG_OK; - } - --SWIGRUNTIME void SWIGV8_SetPrivateData(v8::Handle obj, void *ptr, swig_type_info *info, int flags) { -+SWIGRUNTIME void SWIGV8_SetPrivateData(v8::Local obj, void *ptr, swig_type_info *info, int flags) { - SWIGV8_Proxy *cdata = new SWIGV8_Proxy(); - cdata->swigCObject = ptr; - cdata->swigCMemOwn = (flags & SWIG_POINTER_OWN) ? 1 : 0; - cdata->info = info; - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) -- obj->SetPointerInInternalField(0, cdata); --#else - obj->SetAlignedPointerInInternalField(0, cdata); --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- cdata->handle = v8::Persistent::New(obj); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- cdata->handle = v8::Persistent::New(v8::Isolate::GetCurrent(), obj); --#else - cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- // clientdata must be set for owned data as we need to register the dtor -- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { -- cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); -- } else { -- cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); -- } --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031918) -- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { -- cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); -- } else { -- cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, SWIGV8_Proxy_DefaultDtor); -- } --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { -- cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); -- } else { -- cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); -- } --#elif (V8_MAJOR_VERSION-0) < 5 -- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { -- cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); -- } else { -- cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor); -- } --#else - if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { - cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor, v8::WeakCallbackType::kParameter); - } else { - cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor, v8::WeakCallbackType::kParameter); - } --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- cdata->handle.MarkIndependent(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) -- cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); --#else -+#if (NODE_MODULE_VERSION < 72) - cdata->handle.MarkIndependent(); -+// Looks like future versions do not require that anymore: -+// https://monorail-prod.appspot.com/p/chromium/issues/detail?id=923361#c11 - #endif - - } - --SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Handle valRef, void **ptr, swig_type_info *info, int flags) { -+SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Local valRef, void **ptr, swig_type_info *info, int flags) { - SWIGV8_HANDLESCOPE(); - - /* special case: JavaScript null => C NULL pointer */ -@@ -378,31 +245,20 @@ SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Handle valRef, void **ptr, swi - if(!valRef->IsObject()) { - return SWIG_TypeError; - } -- v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); -+ v8::Local objRef = SWIGV8_TO_OBJECT(valRef); - return SWIG_V8_ConvertInstancePtr(objRef, ptr, info, flags); - } - --SWIGRUNTIME v8::Handle SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, int flags) { -+SWIGRUNTIME v8::Local SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, int flags) { - SWIGV8_HANDLESCOPE_ESC(); - -- v8::Handle class_templ; -+ v8::Local class_templ; - - if (ptr == NULL) { --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -- SWIGV8_ESCAPE(SWIGV8_NULL()); --#else - v8::Local result = SWIGV8_NULL(); - SWIGV8_ESCAPE(result); --#endif - } - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -- if(info->clientdata != 0) { -- class_templ = ((SWIGV8_ClientData*) info->clientdata)->class_templ; -- } else { -- class_templ = SWIGV8_SWIGTYPE_Proxy_class_templ; -- } --#else - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - - if(info->clientdata != 0) { -@@ -410,10 +266,13 @@ SWIGRUNTIME v8::Handle SWIG_V8_NewPointerObj(void *ptr, swig_type_inf - } else { - class_templ = v8::Local::New(isolate, SWIGV8_SWIGTYPE_Proxy_class_templ); - } --#endif - --// v8::Handle result = class_templ->InstanceTemplate()->NewInstance(); -+#if (NODE_MODULE_VERSION < 72) - v8::Local result = class_templ->InstanceTemplate()->NewInstance(); -+#else -+ v8::Local result = class_templ->InstanceTemplate()->NewInstance(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked(); -+#endif -+ - SWIGV8_SetPrivateData(result, ptr, info, flags); - - SWIGV8_ESCAPE(result); -@@ -433,7 +292,7 @@ SWIGRUNTIME v8::Handle SWIG_V8_NewPointerObj(void *ptr, swig_type_inf - SWIGRUNTIME SwigV8ReturnValue _SWIGV8_wrap_equals(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle jsresult; -+ v8::Local jsresult; - void *arg1 = (void *) 0 ; - void *arg2 = (void *) 0 ; - bool result; -@@ -463,7 +322,7 @@ fail: - SWIGRUNTIME SwigV8ReturnValue _wrap_getCPtr(const SwigV8Arguments &args) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle jsresult; -+ v8::Local jsresult; - void *arg1 = (void *) 0 ; - long result; - int res1; -@@ -502,37 +361,29 @@ public: - }; - - SWIGRUNTIMEINLINE --int SwigV8Packed_Check(v8::Handle valRef) { -+int SwigV8Packed_Check(v8::Local valRef) { - SWIGV8_HANDLESCOPE(); - -- v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); -+ v8::Local objRef = SWIGV8_TO_OBJECT(valRef); - if(objRef->InternalFieldCount() < 1) return false; --#if (V8_MAJOR_VERSION-0) < 5 -- v8::Handle flag = objRef->GetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__")); --#else - v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__")); - v8::Local flag; - if (!objRef->GetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey).ToLocal(&flag)) - return false; --#endif -+ - return (flag->IsBoolean() && SWIGV8_BOOLEAN_VALUE(flag)); - } - - SWIGRUNTIME --swig_type_info *SwigV8Packed_UnpackData(v8::Handle valRef, void *ptr, size_t size) { -+swig_type_info *SwigV8Packed_UnpackData(v8::Local valRef, void *ptr, size_t size) { - if (SwigV8Packed_Check(valRef)) { - SWIGV8_HANDLESCOPE(); - - SwigV8PackedData *sobj; - -- v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); -+ v8::Local objRef = SWIGV8_TO_OBJECT(valRef); - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) -- v8::Handle cdataRef = objRef->GetInternalField(0); -- sobj = static_cast(v8::External::Unwrap(cdataRef)); --#else - sobj = static_cast(objRef->GetAlignedPointerFromInternalField(0)); --#endif - if (sobj == NULL || sobj->size != size) return 0; - memcpy(ptr, sobj->data, size); - return sobj->type; -@@ -542,7 +393,7 @@ swig_type_info *SwigV8Packed_UnpackData(v8::Handle valRef, void *ptr, - } - - SWIGRUNTIME --int SWIGV8_ConvertPacked(v8::Handle valRef, void *ptr, size_t sz, swig_type_info *ty) { -+int SWIGV8_ConvertPacked(v8::Local valRef, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigV8Packed_UnpackData(valRef, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { -@@ -555,89 +406,32 @@ int SWIGV8_ConvertPacked(v8::Handle valRef, void *ptr, size_t sz, swi - return SWIG_OK; - } - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) --SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Persistent< v8::Value > object, void *parameter) { -- SwigV8PackedData *cdata = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) --SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent object, void *parameter) { -- SwigV8PackedData *cdata = static_cast(parameter); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) --SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent *object, SwigV8PackedData *cdata) { --#elif (V8_MAJOR_VERSION-0) < 5 --SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackData &data) { -- v8::Local object = data.GetValue(); -- SwigV8PackedData *cdata = data.GetParameter(); --#else - SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackInfo &data) { - SwigV8PackedData *cdata = data.GetParameter(); --#endif - - delete cdata; -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- object.Clear(); -- object.Dispose(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- object.Clear(); -- object.Dispose(isolate); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) -- object->Dispose(isolate); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- object->Dispose(); --#elif (V8_MAJOR_VERSION-0) < 5 -- object.Clear(); --#endif - } - - SWIGRUNTIME --v8::Handle SWIGV8_NewPackedObj(void *data, size_t size, swig_type_info *type) { -+v8::Local SWIGV8_NewPackedObj(void *data, size_t size, swig_type_info *type) { - SWIGV8_HANDLESCOPE_ESC(); - - SwigV8PackedData *cdata = new SwigV8PackedData(data, size, type); --// v8::Handle obj = SWIGV8_OBJECT_NEW(); - v8::Local obj = SWIGV8_OBJECT_NEW(); - --#if (V8_MAJOR_VERSION-0) < 5 -- obj->SetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__"), SWIGV8_BOOLEAN_NEW(true)); --#else - v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__")); - obj->SetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey, SWIGV8_BOOLEAN_NEW(true)); --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) -- obj->SetPointerInInternalField(0, cdata); --#else - obj->SetAlignedPointerInInternalField(0, cdata); --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- cdata->handle = v8::Persistent::New(obj); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- cdata->handle = v8::Persistent::New(v8::Isolate::GetCurrent(), obj); --#else - cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); --#endif -- - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031918) -- cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, _wrap_SwigV8PackedData_delete); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -- cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete); --#elif (V8_MAJOR_VERSION-0) < 5 -- cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete); --// v8::V8::SetWeak(&cdata->handle, cdata, _wrap_SwigV8PackedData_delete); --#else - cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete, v8::WeakCallbackType::kParameter); --#endif - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- cdata->handle.MarkIndependent(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) -- cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); --#else -+#if (NODE_MODULE_VERSION < 72) - cdata->handle.MarkIndependent(); -+// Looks like future versions do not require that anymore: -+// https://monorail-prod.appspot.com/p/chromium/issues/detail?id=923361#c11 - #endif - - SWIGV8_ESCAPE(obj); -@@ -654,22 +448,18 @@ v8::Handle SWIGV8_NewPackedObj(void *data, size_t size, swig_type_inf - - SWIGRUNTIME - --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) --v8::Handle SWIGV8_AppendOutput(v8::Handle result, v8::Handle obj) { --#else --v8::Handle SWIGV8_AppendOutput(v8::Local result, v8::Handle obj) { --#endif -+v8::Local SWIGV8_AppendOutput(v8::Local result, v8::Local obj) { - SWIGV8_HANDLESCOPE_ESC(); - - if (result->IsUndefined()) { - result = SWIGV8_ARRAY_NEW(); - } --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -- v8::Handle arr = v8::Handle::Cast(result); --#else - v8::Local arr = v8::Local::Cast(result); --#endif -+#if (NODE_MODULE_VERSION < 72) - arr->Set(arr->Length(), obj); -+#else -+ arr->Set(SWIGV8_CURRENT_CONTEXT(), arr->Length(), obj); -+#endif - - SWIGV8_ESCAPE(arr); - } -diff --git a/Lib/javascript/v8/javascriptstrings.swg b/Lib/javascript/v8/javascriptstrings.swg -index e767a6d662..61a937fa52 100644 ---- a/Lib/javascript/v8/javascriptstrings.swg -+++ b/Lib/javascript/v8/javascriptstrings.swg -@@ -4,10 +4,10 @@ - * ------------------------------------------------------------ */ - %fragment("SWIG_AsCharPtrAndSize", "header", fragment="SWIG_pchar_descriptor") { - SWIGINTERN int --SWIG_AsCharPtrAndSize(v8::Handle valRef, char** cptr, size_t* psize, int *alloc) -+SWIG_AsCharPtrAndSize(v8::Local valRef, char** cptr, size_t* psize, int *alloc) - { - if(valRef->IsString()) { -- v8::Handle js_str = SWIGV8_TO_STRING(valRef); -+ v8::Local js_str = SWIGV8_TO_STRING(valRef); - - size_t len = SWIGV8_UTF8_LENGTH(js_str) + 1; - char* cstr = new char[len]; -@@ -20,7 +20,7 @@ SWIG_AsCharPtrAndSize(v8::Handle valRef, char** cptr, size_t* psize, - return SWIG_OK; - } else { - if(valRef->IsObject()) { -- v8::Handle obj = SWIGV8_TO_OBJECT(valRef); -+ v8::Local obj = SWIGV8_TO_OBJECT(valRef); - // try if the object is a wrapped char[] - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - if (pchar_descriptor) { -@@ -41,7 +41,7 @@ SWIG_AsCharPtrAndSize(v8::Handle valRef, char** cptr, size_t* psize, - } - - %fragment("SWIG_FromCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") { --SWIGINTERNINLINE v8::Handle -+SWIGINTERNINLINE v8::Local - SWIG_FromCharPtrAndSize(const char* carray, size_t size) - { - if (carray) { -@@ -49,7 +49,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size) - // TODO: handle extra long strings - return SWIGV8_UNDEFINED(); - } else { -- v8::Handle js_str = SWIGV8_STRING_NEW2(carray, size); -+ v8::Local js_str = SWIGV8_STRING_NEW2(carray, size); - return js_str; - } - } else { -diff --git a/Lib/javascript/v8/javascripttypemaps.swg b/Lib/javascript/v8/javascripttypemaps.swg -index 4601698e03..fbe7849cd2 100644 ---- a/Lib/javascript/v8/javascripttypemaps.swg -+++ b/Lib/javascript/v8/javascripttypemaps.swg -@@ -25,7 +25,7 @@ - - /* Javascript types */ - --#define SWIG_Object v8::Handle -+#define SWIG_Object v8::Local - #define VOID_Object SWIGV8_UNDEFINED() - - /* Overload of the output/constant/exception/dirout handling */ -diff --git a/Tools/javascript/Makefile.in b/Tools/javascript/Makefile.in -index 5eeec07857..21088a8fad 100644 ---- a/Tools/javascript/Makefile.in -+++ b/Tools/javascript/Makefile.in -@@ -3,12 +3,9 @@ - # ---------------------------------------------------------------- - # - # Note: --# There is no common CLI Javascript interpreter. --# V8 comes with one 'd8' which however does not provide a means --# to load extensions. Therefore, by default we use nodejs as --# environment. --# For testing native v8 and jsc extensions we provide our own --# interpreter (see 'Tools/javascript'). -+# There is no common CLI Javascript interpreter. By default we -+# use nodejs as environment. For testing jsc extensions we -+# provide our own interpreter (see 'Tools/javascript'). - # - # ---------------------------------------------------------------- - all: javascript -@@ -24,37 +21,25 @@ LDFLAGS = - LINKFLAGS = @JSINTERPRETERLINKFLAGS@ - - ROOT_DIR = @ROOT_DIR@ --JSINCLUDES = @JSCOREINC@ @JSV8INC@ --JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@ --JSV8ENABLED = @JSV8ENABLED@ -+JSINCLUDES = @JSCOREINC@ -+JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ - JSCENABLED = @JSCENABLED@ - - srcdir = @srcdir@ - -- --ifneq (, $(V8_VERSION)) -- JSV8_VERSION=$(V8_VERSION) --else -- JSV8_VERSION=0x031110 --endif -- - # Regenerate Makefile if Makefile.in or config.status have changed. - Makefile: $(srcdir)/Makefile.in ../../config.status - cd ../.. && $(SHELL) ./config.status Tools/javascript/Makefile - - # These settings are provided by 'configure' (see '/configure.in') --ifeq (1, $(JSV8ENABLED)) --JS_INTERPRETER_SRC_V8 = v8_shell.cxx --JS_INTERPRETER_ENABLE_V8 = -DENABLE_V8 -DSWIG_V8_VERSION=$(JSV8_VERSION) -DV8_DEPRECATION_WARNINGS --endif - - ifeq (1, $(JSCENABLED)) - JS_INTERPRETER_SRC_JSC = jsc_shell.cxx - JS_INTERPRETER_ENABLE_JSC = -DENABLE_JSC - endif - --JS_INTERPRETER_DEFINES = $(JS_INTERPRETER_ENABLE_JSC) $(JS_INTERPRETER_ENABLE_V8) --JS_INTERPRETER_SRC = javascript.cxx js_shell.cxx $(JS_INTERPRETER_SRC_JSC) $(JS_INTERPRETER_SRC_V8) -+JS_INTERPRETER_DEFINES = $(JS_INTERPRETER_ENABLE_JSC) -+JS_INTERPRETER_SRC = javascript.cxx js_shell.cxx $(JS_INTERPRETER_SRC_JSC) - - JS_INTERPRETER_OBJS = $(JS_INTERPRETER_SRC:.cxx=.o) - -diff --git a/Tools/javascript/v8_shell.cxx b/Tools/javascript/v8_shell.cxx -deleted file mode 100644 -index 5001bc25a6..0000000000 ---- a/Tools/javascript/v8_shell.cxx -+++ /dev/null -@@ -1,388 +0,0 @@ --#include --#include --#include --#include --#include -- --#include --#include -- --#include "js_shell.h" -- --typedef int (*V8ExtensionInitializer) (v8::Handle module); -- --// Note: these typedefs and defines are used to deal with v8 API changes since version 3.19.00 -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) --typedef v8::Handle SwigV8ReturnValue; --typedef v8::Arguments SwigV8Arguments; --typedef v8::AccessorInfo SwigV8PropertyCallbackInfo; --#define SWIGV8_RETURN(val) return scope.Close(val) --#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val) --#else --typedef void SwigV8ReturnValue; --typedef v8::FunctionCallbackInfo SwigV8Arguments; --typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; --#define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return --#define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return --#endif -- -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032117) --#define SWIGV8_HANDLESCOPE() v8::HandleScope scope --#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope --#define SWIGV8_ESCAPE(val) return scope.Close(val) --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318) --#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); --#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope(v8::Isolate::GetCurrent()); --#define SWIGV8_ESCAPE(val) return scope.Close(val) --#else --#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); --#define SWIGV8_HANDLESCOPE_ESC() v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()); --#define SWIGV8_ESCAPE(val) return scope.Escape(val) --#endif -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318) --#define SWIGV8_CURRENT_CONTEXT() v8::Context::GetCurrent() --#define SWIGV8_STRING_NEW(str) v8::String::New(str) --#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(func) --#define SWIGV8_OBJECT_NEW() v8::Object::New() --#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(val) --#define SWIGV8_UNDEFINED() v8::Undefined() --#else --#define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext() --#define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str) --#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), func) --#define SWIGV8_OBJECT_NEW() v8::Object::New(v8::Isolate::GetCurrent()) --#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(v8::Isolate::GetCurrent(), val) --#define SWIGV8_UNDEFINED() v8::Undefined(v8::Isolate::GetCurrent()) --#endif -- -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) --typedef v8::Persistent SwigV8Context; --#else --typedef v8::Local SwigV8Context; --#endif -- --class V8Shell: public JSShell { -- --public: -- V8Shell(); -- -- virtual ~V8Shell(); -- -- virtual bool RunScript(const std::string &scriptPath); -- -- virtual bool RunShell(); -- -- --protected: -- -- virtual bool InitializeEngine(); -- -- virtual bool ExecuteScript(const std::string &source, const std::string &scriptPath); -- -- virtual bool DisposeEngine(); -- --private: -- -- v8::Handle Import(const std::string &moduleName); -- -- SwigV8Context CreateShellContext(); -- -- void ReportException(v8::TryCatch *handler); -- -- static SwigV8ReturnValue Print(const SwigV8Arguments &args); -- -- static SwigV8ReturnValue Require(const SwigV8Arguments &args); -- -- static SwigV8ReturnValue Quit(const SwigV8Arguments &args); -- -- static SwigV8ReturnValue Version(const SwigV8Arguments &args); -- -- static const char* ToCString(const v8::String::Utf8Value &value); -- --}; -- --#ifdef __GNUC__ --#include --#define LOAD_SYMBOL(handle, name) dlsym(handle, name) --#else --#error "implement dll loading" --#endif -- --V8Shell::V8Shell() {} -- --V8Shell::~V8Shell() {} -- --bool V8Shell::RunScript(const std::string &scriptPath) { -- std::string source = ReadFile(scriptPath); -- -- v8::Isolate *isolate = v8::Isolate::New(); -- v8::Isolate::Scope isolate_scope(isolate); -- -- SWIGV8_HANDLESCOPE(); -- -- SwigV8Context context = CreateShellContext(); -- -- if (context.IsEmpty()) { -- printf("Could not create context.\n"); -- return false; -- } -- -- context->Enter(); -- -- // Store a pointer to this shell for later use -- -- v8::Handle global = context->Global(); -- v8::Local __shell__ = SWIGV8_EXTERNAL_NEW((void*) (long) this); -- -- global->SetHiddenValue(SWIGV8_STRING_NEW("__shell__"), __shell__); -- -- // Node.js compatibility: make `print` available as `console.log()` -- ExecuteScript("var console = {}; console.log = print;", ""); -- -- bool success = ExecuteScript(source, scriptPath); -- -- // Cleanup -- -- context->Exit(); -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- context.Dispose(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- context.Dispose(v8::Isolate::GetCurrent()); --#else --// context.Dispose(); --#endif -- --// v8::V8::Dispose(); -- -- return success; --} -- --bool V8Shell::RunShell() { -- SWIGV8_HANDLESCOPE(); -- -- SwigV8Context context = CreateShellContext(); -- -- if (context.IsEmpty()) { -- printf("Could not create context.\n"); -- return false; -- } -- -- context->Enter(); -- -- v8::Context::Scope context_scope(context); -- -- ExecuteScript("var console = {}; console.log = print;", ""); -- -- static const int kBufferSize = 1024; -- while (true) { -- char buffer[kBufferSize]; -- printf("> "); -- char *str = fgets(buffer, kBufferSize, stdin); -- if (str == NULL) break; -- std::string source(str); -- ExecuteScript(source, "(shell)"); -- } -- printf("\n"); -- -- // Cleanup -- -- context->Exit(); -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -- context.Dispose(); --#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- context.Dispose(v8::Isolate::GetCurrent()); --#else --// context.Dispose(); --#endif -- --// v8::V8::Dispose(); -- -- return true; --} -- -- --bool V8Shell::InitializeEngine() { -- return true; --} -- --bool V8Shell::ExecuteScript(const std::string &source, const std::string &name) { -- SWIGV8_HANDLESCOPE(); -- -- v8::TryCatch try_catch; -- v8::Handle script = v8::Script::Compile(SWIGV8_STRING_NEW(source.c_str()), SWIGV8_STRING_NEW(name.c_str())); -- -- // Stop if script is empty -- if (script.IsEmpty()) { -- // Print errors that happened during compilation. -- ReportException(&try_catch); -- return false; -- } -- -- v8::Handle result = script->Run(); -- -- // Print errors that happened during execution. -- if (try_catch.HasCaught()) { -- ReportException(&try_catch); -- return false; -- } else { -- return true; -- } --} -- --bool V8Shell::DisposeEngine() { -- return true; --} -- --SwigV8Context V8Shell::CreateShellContext() { -- // Create a template for the global object. -- v8::Handle global = v8::ObjectTemplate::New(); -- -- // Bind global functions -- global->Set(SWIGV8_STRING_NEW("print"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Print)); -- global->Set(SWIGV8_STRING_NEW("quit"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Quit)); -- global->Set(SWIGV8_STRING_NEW("require"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Require)); -- global->Set(SWIGV8_STRING_NEW("version"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Version)); -- --#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -- SwigV8Context context = v8::Context::New(NULL, global); -- return context; --#else -- SwigV8Context context = v8::Context::New(v8::Isolate::GetCurrent(), NULL, global); -- return context; --#endif --} -- --v8::Handle V8Shell::Import(const std::string &module_path) --{ -- SWIGV8_HANDLESCOPE_ESC(); -- -- HANDLE library; -- std::string module_name = LoadModule(module_path, &library); -- -- std::string symname = std::string(module_name).append("_initialize"); -- -- V8ExtensionInitializer init_function = reinterpret_cast((long) LOAD_SYMBOL(library, symname.c_str())); -- -- if(init_function == 0) { -- printf("Could not find initializer function."); -- -- return SWIGV8_UNDEFINED(); -- } -- -- v8::Local module = SWIGV8_OBJECT_NEW(); -- init_function(module); -- -- SWIGV8_ESCAPE(module); --} -- --SwigV8ReturnValue V8Shell::Print(const SwigV8Arguments &args) { -- SWIGV8_HANDLESCOPE(); -- -- bool first = true; -- for (int i = 0; i < args.Length(); i++) { -- -- if (first) { -- first = false; -- } else { -- printf(" "); -- } -- v8::String::Utf8Value str(args[i]); -- const char *cstr = V8Shell::ToCString(str); -- printf("%s", cstr); -- } -- printf("\n"); -- fflush(stdout); -- -- SWIGV8_RETURN(SWIGV8_UNDEFINED()); --} -- --SwigV8ReturnValue V8Shell::Require(const SwigV8Arguments &args) { -- SWIGV8_HANDLESCOPE(); -- -- if (args.Length() != 1) { -- printf("Illegal arguments for `require`"); -- }; -- -- v8::String::Utf8Value str(args[0]); -- const char *cstr = V8Shell::ToCString(str); -- std::string moduleName(cstr); -- -- v8::Local global = SWIGV8_CURRENT_CONTEXT()->Global(); -- -- v8::Local hidden = global->GetHiddenValue(SWIGV8_STRING_NEW("__shell__")); -- v8::Local __shell__ = v8::Local::Cast(hidden); -- V8Shell *_this = (V8Shell *) (long) __shell__->Value(); -- -- v8::Handle module = _this->Import(moduleName); -- -- SWIGV8_RETURN(module); --} -- --SwigV8ReturnValue V8Shell::Quit(const SwigV8Arguments &args) { -- SWIGV8_HANDLESCOPE(); -- -- int exit_code = args[0]->Int32Value(); -- fflush(stdout); -- fflush(stderr); -- exit(exit_code); -- -- SWIGV8_RETURN(SWIGV8_UNDEFINED()); --} -- --SwigV8ReturnValue V8Shell::Version(const SwigV8Arguments &args) { -- SWIGV8_HANDLESCOPE(); -- SWIGV8_RETURN(SWIGV8_STRING_NEW(v8::V8::GetVersion())); --} -- --void V8Shell::ReportException(v8::TryCatch *try_catch) { -- SWIGV8_HANDLESCOPE(); -- -- v8::String::Utf8Value exception(try_catch->Exception()); -- const char *exception_string = V8Shell::ToCString(exception); -- v8::Handle message = try_catch->Message(); -- if (message.IsEmpty()) { -- // V8 didn't provide any extra information about this error; just -- // print the exception. -- printf("%s\n", exception_string); -- } else { -- // Print (filename):(line number): (message). -- v8::String::Utf8Value filename(message->GetScriptResourceName()); -- const char *filename_string = V8Shell::ToCString(filename); -- int linenum = message->GetLineNumber(); -- printf("%s:%i: %s\n", filename_string, linenum, exception_string); -- // Print line of source code. -- v8::String::Utf8Value sourceline(message->GetSourceLine()); -- const char *sourceline_string = V8Shell::ToCString(sourceline); -- printf("%s\n", sourceline_string); -- // Print wavy underline (GetUnderline is deprecated). -- int start = message->GetStartColumn(); -- for (int i = 0; i < start; i++) { -- printf(" "); -- } -- int end = message->GetEndColumn(); -- for (int i = start; i < end; i++) { -- printf("^"); -- } -- printf("\n"); -- v8::String::Utf8Value stack_trace(try_catch->StackTrace()); -- if (stack_trace.length() > 0) { -- const char *stack_trace_string = V8Shell::ToCString(stack_trace); -- printf("%s\n", stack_trace_string); -- } -- } --} -- --// Extracts a C string from a V8 Utf8Value. --const char *V8Shell::ToCString(const v8::String::Utf8Value &value) { -- return *value ? *value : ""; --} -- --JSShell *V8Shell_Create() { -- return new V8Shell(); --} -diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh -index c8347d27a4..2427d08230 100755 ---- a/Tools/travis-linux-install.sh -+++ b/Tools/travis-linux-install.sh -@@ -39,22 +39,12 @@ - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - travis_retry nvm install ${VER} - nvm use ${VER} -- if [ "$VER" == "0.10" ] || [ "$VER" == "0.12" ] || [ "$VER" == "4" ] || [ "$VER" == "6" ] ; then --# travis_retry sudo apt-get install -qq nodejs node-gyp -- travis_retry npm install -g node-gyp@$VER -- elif [ "$VER" == "8" ] ; then -- travis_retry npm install -g node-gyp@6 -- else -- travis_retry npm install -g node-gyp -- fi -+ travis_retry npm install -g node-gyp - ;; - "jsc") - travis_retry sudo apt-get install -qq libwebkitgtk-dev - ;; -- "v8") -- travis_retry sudo apt-get install -qq libv8-dev -- ;; -- esac -+ - ;; - "guile") - travis_retry sudo apt-get -qq install guile-2.0-dev diff --git a/utils/xz/Makefile b/utils/xz/Makefile index 7aa49ad98..e8d01626e 100644 --- a/utils/xz/Makefile +++ b/utils/xz/Makefile @@ -9,12 +9,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=xz -PKG_VERSION:=5.2.7 +PKG_VERSION:=5.2.9 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=@SF/lzmautils -PKG_HASH:=8712e9acb0b6b49a97d443458a3067dc5c08a025e02dc5f773176c51dd7cfc69 +PKG_HASH:=b194507fba3a462a753c553149ccdaa168337bcb7deefddd067ba987c83dfce6 PKG_MAINTAINER:= PKG_LICENSE:=Public-Domain LGPL-2.1-or-later GPL-2.0-or-later GPL-3.0-or-later diff --git a/utils/zoneinfo/Makefile b/utils/zoneinfo/Makefile index 9bf2dbce9..251a1cd08 100644 --- a/utils/zoneinfo/Makefile +++ b/utils/zoneinfo/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=zoneinfo -PKG_VERSION:=2022f +PKG_VERSION:=2022g PKG_RELEASE:=1 #As i couldn't find real license used "Public Domain" @@ -19,14 +19,14 @@ PKG_LICENSE:=Public Domain PKG_SOURCE:=tzdata$(PKG_VERSION).tar.gz PKG_SOURCE_CODE:=tzcode$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.iana.org/time-zones/repository/releases -PKG_HASH:=9990d71f675d212567b931fe8aae1cab7027f89fefb8a79d808a6933a67af000 +PKG_HASH:=4491db8281ae94a84d939e427bdd83dc389f26764d27d9a5c52d782c16764478 include $(INCLUDE_DIR)/package.mk define Download/tzcode FILE=$(PKG_SOURCE_CODE) URL=$(PKG_SOURCE_URL) - HASH:=e4543e90f84f91fa82809ea98930052fdbc13880c8a623ee3a4eaa42f8a64c15 + HASH:=9610bb0b9656ff404c361a41f3286da53064b5469d84f00c9cb2314c8614da74 endef $(eval $(call Download,tzcode))