#!/bin/sh # $Id$ # # Lists the host names associated with each globally routed IPv{4,6} host # address configured on the caller's box, dispatching RDNS queries to # validate the authority of each resolved host name, optionally amending # the AS number and corresponding /descr/ from RADB. # # Author: vxp/arab , # Last update: Sun Aug 22 11:38:01 CEST 2010 # Tested on: FreeBSD 7.1, OpenBSD 4.5, and NetBSD 5.0.1. # Requires: SuS sh (1), getopt (1); SuS awk (1) or [gn]awk (1); # ISC BIND dig (1); BSD ifconfig (8), and whois (1). # # {{{ Tunables # Maximum string length in characters of an IPv6 address in presentation # format, as per . Note that an IPv4 address string # constitutes a subset of the former in terms of length. ADDRSTRLEN=39 # Maximum number of DNS UDP query attempts, including the initial query, # and the maximum duration of each query in seconds. DIG_TRIES=2 DIG_TIME=2 # XXX VHOSTS_LIST="/var/run/vhosts" # }}} # {{{ subr _printf() { local nflag="\\n"; [ "x-n" = "x${1}" ] && { nflag=""; shift; }; local line="`printf \"$@\"`"; printf -- "%s${nflag}" "${line}"; [ -n "${wflag}" ] && { printf -- "%s${nflag}" "${line}" \ >> "${VHOSTS_LIST}"; }; }; dig() { [ -n "${1}" ] || return; local xflag="${1%%[!!]*}" name="${1#!}" class="${2}" IFS=" "; set -- `command dig ${xflag:+-x} "${name}" IN "${class}" \ +short +nocomments \ +time="${DIG_TIME}" +tries="${DIG_TRIES}" \ 2>/dev/null`; echo "${1}"; }; # }}} # trap(1) the relevant set of signals to ensure clean script termination. abort_exec() { printf "\n--- ABORTED ---\n"; exit 1; }; trap abort_exec HUP INT QUIT PIPE TERM USR1 USR2; # # Parse optionally supplied command options to determine the desired mode of # operation, either cat(1)ting an already present and readable /vhosts/ list # to the standard output or dispatching individual DNS queries. for c in `getopt fwah $* 2>/dev/null` do case "${c}" in -f) fflag=1; ;; -w) wflag=1; ;; -a) aflag=1; ;; -h) hflag=1; ;; --) break; ;; esac done; [ "${hflag}" ] && { echo "usage: $0 [-fwa]"; exit 1; }; [ -r "${VHOSTS_LIST}" -a -z "${fflag}" ] \ && { cat "${VHOSTS_LIST}"; } \ || { [ -n "${wflag}" ] && { printf "" >| "${VHOSTS_LIST}" || exit 2; }; # # Iterate over the subset of IPv{4,6} netif host addresses from every # netif that is /up/, resolving each and establishing 2-way RDNS # {authority,hostname} confirmation where applicable. for ha in ` \ ifconfig -a |\ awk ' /\tinet6? alias / { print $3; next; } \ /\tinet6? / { print $2; }' |\ awk ' !/^((127|10|172|192\.168)\.|(fe..)?:)/ \ { print; }' 2>/dev/null`; do type="NO HOST" pf="4" q="A" radb="" host=""; # Infer the protocol family from the presentation format. [ "x${ha##*:*}" = "x${ha}" ] || { pf="6"; q="AAAA"; }; [ -n "${aflag}" ] && { # {{{ RADB radb="` \ whois -h whois.radb.net "${ha}" 2>/dev/null | awk ' \ /^[^:]+:/ { \ gsub(/(\t| )+/, " ", $0); split($0, a, ": "); \ if(v[a[1]]) { next; } else { v[a[1]] = a[2]; }; \ } \ \ END { printf("[%8.8s/%16.16s]", v["origin"], v["mnt-by"]); }'`"; # }}} }; _printf -n "%-${ADDRSTRLEN}s${radb} %-2s " "${ha}" "[IPv${pf}]"; host="`dig !${ha} PTR`"; [ -n "${host}" ] && { [ "x`dig ${host} ${q}`" = "x${ha}" ] \ && type="PTR" || type="NO RDNS"; }; _printf "%-12s %s" "--${type}-->" "${host}" done }; # vim:ts=8 sw=8 tw=80 noexpandtab foldmethod=marker