wgctl/modules/net.module.sh
Nuno Duque Nunes b813810ff3 feat: hosts.json IP resolution system
- wgctl hosts command (list, show, add, rm) with tags support
- modules/resolve.module.sh — chain: hosts.json → services.json → raw IP
- modules/hosts.module.sh — hosts::resolve_ip, hosts::lookup_ip
- resolve::ip and resolve::dest used in watch, logs, activity
- _WGCTL_RAW=true via --raw flag bypasses all resolution
- json_helper.py: hosts_list, hosts_show, hosts_add, hosts_remove, hosts_lookup
2026-05-23 22:01:45 +00:00

110 lines
No EOL
2.9 KiB
Bash

#!/usr/bin/env bash
function net::exists() {
local name="${1:?}"
local result
result=$(json::net_exists "$(ctx::net)" "$name")
[[ "$result" == "true" ]]
}
function net::require_exists() {
local name="${1:?}"
if ! net::exists "$name"; then
log::error "Service not found: ${name}"
return 1
fi
}
function net::resolve() {
local name="${1:?}"
json::net_resolve "$(ctx::net)" "$name"
}
function net::reverse_lookup() {
local ip="${1:-}" port="${2:-}" proto="${3:-}"
[[ -z "$ip" ]] && return 0
json::net_reverse_lookup "$(ctx::net)" "$ip" "$port" "$proto"
}
function net::annotation() {
# Returns " → service:port" or "" — for display use
local ip="${1:-}" port="${2:-}" proto="${3:-}"
local match
match=$(net::reverse_lookup "$ip" "$port" "$proto")
[[ -n "$match" ]] && echo "${match}" || echo ""
}
function net::annotate() {
# Returns " → service:port-name" or "" for display use
local entry="${1:-}"
[[ -z "$entry" ]] && return 0
local ann=""
if [[ "$entry" == *:*:* ]]; then
# ip:port:proto
local b_ip b_port b_proto
IFS=":" read -r b_ip b_port b_proto <<< "$entry"
ann=$(net::reverse_lookup "$b_ip" "$b_port" "$b_proto")
else
# ip or ip/cidr
local ip="${entry%%/*}"
ann=$(net::reverse_lookup "$ip")
fi
[[ -n "$ann" ]] && echo "${ann}" || echo ""
}
function net::print_entry() {
local sign="${1:-}" entry="${2:-}" indent="${3:-6}"
local ann
ann=$(net::annotate "$entry")
local color
[[ "$sign" == "+" ]] && color="\033[0;32m" || color="\033[0;31m"
local spaces
spaces=$(printf '%*s' "$indent" '')
printf "%s%b%s\033[0m %-20s\033[0;37m%s\033[0m\n" \
"$spaces" "$color" "$sign" "$entry" \
"${ann:+ → ${ann}}"
}
function net::print_dns_redirect() {
local ip="${1:-}" indent="${2:-6}" label="${3:-DNS}"
local spaces
spaces=$(printf '%*s' "$indent" '')
local ann
ann=$(net::annotate "$ip")
printf "%s\033[0;36m↺\033[0m %s → %s\033[0;37m%s\033[0m\n" \
"$spaces" "$label" "$ip" "${ann:+ → ${ann}}"
}
function net::print_dns_redirect_full() {
# For rule::show — slightly different prefix
local ip="${1:-}"
local ann
ann=$(net::annotate "$ip")
printf " \033[0;36m↺\033[0m Redirect all DNS → %s\033[0;37m%s\033[0m\n" \
"$ip" "${ann:+ → ${ann}}"
}
function net::resolve_display() {
local ip="${1:-}" port="${2:-}" proto="${3:-}"
[[ -z "$ip" ]] && return 0
# --raw flag bypass
[[ "${_WGCTL_RAW:-false}" == "true" ]] && echo "$ip" && return 0
# 1. hosts.json exact IP match
local host_name=""
if [[ -f "$(ctx::hosts)" ]]; then
host_name=$(hosts::lookup_ip "$ip")
fi
[[ -n "$host_name" ]] && echo "$host_name" && return 0
# 2. services.json match
local svc_name=""
svc_name=$(net::reverse_lookup "$ip" "$port" "$proto" 2>/dev/null) || true
[[ -n "$svc_name" ]] && echo "$svc_name" && return 0
# 3. Raw IP fallback
echo "$ip"
}