Skip to content

Commit c292fc7

Browse files
authored
Add files via upload
1 parent 31953bb commit c292fc7

2 files changed

Lines changed: 504 additions & 119 deletions

File tree

PyWWW/dns.py

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -140,31 +140,37 @@ def _rank(info):
140140
yield sockaddr
141141

142142

143-
def _resolve_one_ip(host, prefer_ipv6=True):
143+
def _resolve_all_server_ips(dns_server, prefer_ipv6=True):
144144
"""
145-
Best-effort resolve hostname -> one IP string (display only).
146-
Returns None on failure.
145+
Display helper: resolve hostname -> list of IP strings.
146+
For IP literals, returns just the literal (IPv6%zone -> IPv6).
147147
"""
148-
if not host:
149-
return None
150-
if _is_ip_literal(host):
151-
if "%" in host:
152-
return host.split("%", 1)[0]
153-
return host
148+
if not dns_server:
149+
return []
150+
if _is_ip_literal(dns_server):
151+
if "%" in dns_server:
152+
return [dns_server.split("%", 1)[0]]
153+
return [dns_server]
154+
155+
ips = []
154156
try:
155-
infos = socket.getaddrinfo(host, 0, socket.AF_UNSPEC, 0, 0)
156-
best = None
157+
infos = socket.getaddrinfo(dns_server, 0, socket.AF_UNSPEC, 0, 0)
157158
for fam, _socktype, _proto, _canon, sockaddr in infos:
158159
ip = sockaddr[0]
159-
if best is None:
160-
best = ip
161-
if prefer_ipv6 and fam == socket.AF_INET6:
162-
return ip
163-
if (not prefer_ipv6) and fam == socket.AF_INET:
164-
return ip
165-
return best
160+
if ip not in ips:
161+
ips.append(ip)
166162
except Exception:
167-
return None
163+
return []
164+
165+
# Sort in preferred order for display
166+
def _rank_ip(ip):
167+
is_v6 = ":" in ip
168+
if prefer_ipv6:
169+
return 0 if is_v6 else 1
170+
return 0 if (not is_v6) else 1
171+
172+
ips.sort(key=_rank_ip)
173+
return ips
168174

169175

170176
def encode_qname(domain):
@@ -596,7 +602,14 @@ def _print_nslookup_error(domain, rcode):
596602
def _print_nslookup_like(dns_server, port, domain, prefer_ipv6, timeout,
597603
tcp_fallback, strict_txid,
598604
server_name_display=None,
599-
resolve_server_name=False):
605+
resolve_server_name=False,
606+
nslookup_default_header=False):
607+
"""
608+
nslookup-style output.
609+
- Queries both A and AAAA and prints them.
610+
- If nslookup_default_header=True prints "Default server:" style header.
611+
- If resolve_server_name=True and dns_server is hostname, prints all resolved server IPs.
612+
"""
600613
rcode_any = 0
601614
aa_any = False
602615
a_list = []
@@ -630,13 +643,31 @@ def _print_nslookup_like(dns_server, port, domain, prefer_ipv6, timeout,
630643

631644
server_line = server_name_display if server_name_display else dns_server
632645

633-
if resolve_server_name and (not _is_ip_literal(dns_server)):
634-
used_ip = _resolve_one_ip(dns_server, prefer_ipv6=prefer_ipv6) or (used[0] if used else dns_server)
646+
# For the "Address:" header lines:
647+
if resolve_server_name:
648+
server_ips = _resolve_all_server_ips(dns_server, prefer_ipv6=prefer_ipv6)
649+
if not server_ips and used:
650+
server_ips = [used[0]]
651+
if not server_ips:
652+
server_ips = [dns_server]
653+
else:
654+
if used:
655+
server_ips = [used[0]]
656+
else:
657+
# best effort: literal -> itself, hostname -> try resolve one
658+
one = _resolve_all_server_ips(dns_server, prefer_ipv6=prefer_ipv6)
659+
server_ips = one[:1] if one else [dns_server]
660+
661+
if nslookup_default_header:
662+
print("Default server:\t%s" % server_line)
663+
# nslookup often prints multiple Address lines for the server too:
664+
for ip in server_ips:
665+
print("Address:\t%s#%d" % (ip, int(port)))
635666
else:
636-
used_ip = used[0] if used else dns_server
667+
print("Server:\t\t%s" % server_line)
668+
for ip in server_ips[:1]:
669+
print("Address:\t%s#%d" % (ip, int(port)))
637670

638-
print("Server:\t\t%s" % server_line)
639-
print("Address:\t%s#%d" % (used_ip, int(port)))
640671
print("")
641672

642673
if (not a_list) and (not aaaa_list):
@@ -693,10 +724,12 @@ def main():
693724

694725
parser.add_argument('--nslookup', action='store_true',
695726
help='Print nslookup-like output (queries both A and AAAA)')
727+
parser.add_argument('--nslookup-default-header', action='store_true',
728+
help='Use "Default server:" / "Address:" header style (like common nslookup)')
696729
parser.add_argument('--nslookup-server-name', type=str, default=None,
697-
help='Override the name printed on the "Server:" line (e.g. dns.google)')
730+
help='Override the name printed on the "Server:"/"Default server:" line (e.g. dns.google)')
698731
parser.add_argument('--nslookup-resolve-server', action='store_true',
699-
help='Resolve the server hostname for the "Address:" line (display only)')
732+
help='Resolve the server hostname and print ALL server IPs in the header (display only)')
700733

701734
parser.add_argument('--quiet', action='store_true', help='Less header/debug output (classic mode)')
702735

@@ -733,6 +766,7 @@ def main():
733766
strict_txid=strict_txid,
734767
server_name_display=args.nslookup_server_name,
735768
resolve_server_name=bool(args.nslookup_resolve_server),
769+
nslookup_default_header=bool(args.nslookup_default_header),
736770
)
737771
return
738772

0 commit comments

Comments
 (0)