function cmd::peer::run() { local subcmd="${1:-help}" shift || true case "$subcmd" in update-dns) cmd::peer::update_dns "$@" ;; update-tunnel) cmd::peer::update_tunnel "$@" ;; help) cmd::peer::help ;; *) log::error "Unknown subcommand: '${subcmd}'" cmd::peer::help return 1 ;; esac } # ============================================ # Update DNS # ============================================ function cmd::peer::update_dns() { local name="" type="" all=false local dns="" fallback_dns="" while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; --type) type="$2"; shift 2 ;; --all) all=true; shift ;; --dns) dns="$2"; shift 2 ;; --fallback-dns) fallback_dns="$2"; shift 2 ;; --help) cmd::peer::help; return ;; *) log::error "Unknown flag: $1"; return 1 ;; esac done [[ -z "$name" && "$all" == "false" ]] && \ log::error "Specify --name or --all" && return 1 # Resolve DNS string local primary="${dns:-$(config::dns)}" local fallback="${fallback_dns:-$(config::dns_fallback)}" local dns_string if [[ -n "$fallback" ]]; then dns_string="${primary}, ${fallback}" else dns_string="$primary" fi # Collect target peers local peers=() if $all; then while IFS= read -r conf; do peers+=("$(basename "$conf" .conf)") done < <(find "$(ctx::clients)" -name "*.conf" 2>/dev/null) else name=$(peers::resolve_and_require "$name" "$type") || return 1 peers=("$name") fi local updated=0 for peer_name in "${peers[@]}"; do local conf conf="$(ctx::clients)/${peer_name}.conf" [[ ! -f "$conf" ]] && continue # Replace DNS line in-place if grep -q "^DNS" "$conf"; then sed -i "s|^DNS = .*|DNS = ${dns_string}|" "$conf" else # Add DNS line after Address line sed -i "/^Address/a DNS = ${dns_string}" "$conf" fi (( updated++ )) || true log::debug "Updated DNS for: ${peer_name}" done log::wg_success "Updated DNS to '${dns_string}' for ${updated} peer(s)" }