diff options
-rw-r--r-- | main.go | 52 |
1 files changed, 51 insertions, 1 deletions
@@ -8,6 +8,10 @@ import ( "strings" ) +var ( + txt = flag.Bool("txt", false, "also look up TXT records") +) + func main() { flag.Parse() for _, arg := range flag.Args() { @@ -19,10 +23,20 @@ func main() { ip := ipnet.IP for ipnet.Contains(ip) { if names, err := net.LookupAddr(ip.String()); err != nil { - fmt.Fprintf(os.Stderr, "%s\t# error: %s\n", ip, err) + fmt.Fprintf(os.Stderr, "%s\t# PTR error: %s\n", ip, err) } else { fmt.Printf("%s\t%s\n", ip, strings.Join(names, " ")) } + if *txt { + recs, err := net.LookupTXT(arpa(ip)) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\t# TXT error: %s\n", ip, err) + } else { + for _, rec := range recs { + fmt.Printf("%s\tTXT %q\n", ip, rec) + } + } + } ip = next(ip) } } @@ -30,6 +44,42 @@ func main() { } } +// arpa returns the .in-addr.arpa or .ip6.arpa name corresponding with the given IP. +func arpa(ip net.IP) string { + if ip4 := ip.To4(); ip4 != nil { + return fmt.Sprintf( + "%d.%d.%d.%d.in-addr.arpa", + ip4[3], ip4[2], ip4[1], ip4[0], + ) + } else if ip6 := ip.To16(); ip6 != nil { + return fmt.Sprintf( + "%x.%x.%x.%x.%x.%x.%x.%x."+ + "%x.%x.%x.%x.%x.%x.%x.%x."+ + "%x.%x.%x.%x.%x.%x.%x.%x."+ + "%x.%x.%x.%x.%x.%x.%x.%x."+ + "ip6.arpa", + ip6[15]&0xf, ip6[15]&0xf0>>4, + ip6[14]&0xf, ip6[14]&0xf0>>4, + ip6[13]&0xf, ip6[13]&0xf0>>4, + ip6[12]&0xf, ip6[12]&0xf0>>4, + ip6[11]&0xf, ip6[11]&0xf0>>4, + ip6[10]&0xf, ip6[10]&0xf0>>4, + ip6[9]&0xf, ip6[9]&0xf0>>4, + ip6[8]&0xf, ip6[8]&0xf0>>4, + ip6[7]&0xf, ip6[7]&0xf0>>4, + ip6[6]&0xf, ip6[6]&0xf0>>4, + ip6[5]&0xf, ip6[5]&0xf0>>4, + ip6[4]&0xf, ip6[4]&0xf0>>4, + ip6[3]&0xf, ip6[3]&0xf0>>4, + ip6[2]&0xf, ip6[2]&0xf0>>4, + ip6[1]&0xf, ip6[1]&0xf0>>4, + ip6[0]&0xf, ip6[0]&0xf0>>4, + ) + } else { + panic("non-ip4 non-ip6 ip? " + ip.String()) + } +} + // next returns the next IP address after ip, or nil if there is no such address. func next(ip net.IP) net.IP { next := make(net.IP, len(ip)) |