#!/usr/bin/env python3
# Copyright (c) 2012 Arista Networks, Inc.  All rights reserved.
# Arista Networks, Inc. Confidential and Proprietary.

# This is a useful little script that does DNS resolution on the ip
# addresses in stdin.  It only looks up any IP once, caching the result.
# usage:
#   ip neigh | resolve    
#   ip neigh | resolve 20 ; fixed width of 20 per address

import socket, sys
width = 0 if len(sys.argv)==1 else int(sys.argv[1])
if width:
   expr = "%%-%ss" % width # pylint: disable=consider-using-f-string


def doResolve(x):
   try:
      host, _, _ = socket.gethostbyaddr(x)
      resolved[x] = host
      return host
   except (socket.herror, socket.gaierror):
      resolved[x] = x
      return x

# cached version of doResolve
resolved = {}
def resolve(x):
   if x in resolved:
      return resolved[x]
   xx = doResolve(x)
   resolved[x] = xx
   return xx
   

def resolvematch(m):
   addr = resolve(m.group(0))
   if width: 
      addr = addr[:width]
      return expr % addr
   else:
      return addr

import re # pylint: disable=wrong-import-position
v4pat = r"\d+\.\d+\.\d+\.\d+"
# We capture things that look largely like a v6 address,
# and leave it to doResolve() to fail gracefully.
v6pat = r"[0-9A-F]+:[0-9A-F:]+(?:\.\d+\.\d+\.\d+)?"
# pylint: disable-next=consider-using-f-string
pat = re.compile( "(%s|%s)" % ( v4pat, v6pat ), re.I )
for i in sys.stdin:
   ii = re.sub(pat,resolvematch,i)
   print( ii, end="" )
