@@ -1380,13 +1380,15 @@ def pre_dissect(self, s):
1380
1380
1381
1381
1382
1382
@conf .commands .register
1383
- def dns_resolve (qname , qtype = "A" , raw = False , verbose = 1 , timeout = 3 , ** kwargs ):
1383
+ def dns_resolve (qname , qtype = "A" , raw = False , tcp = False , verbose = 1 , timeout = 3 , ** kwargs ):
1384
1384
"""
1385
1385
Perform a simple DNS resolution using conf.nameservers with caching
1386
1386
1387
1387
:param qname: the name to query
1388
1388
:param qtype: the type to query (default A)
1389
1389
:param raw: return the whole DNS packet (default False)
1390
+ :param tcp: whether to use directly TCP instead of UDP. If truncated is received,
1391
+ UDP automatically retries in TCP. (default: False)
1390
1392
:param verbose: show verbose errors
1391
1393
:param timeout: seconds until timeout (per server)
1392
1394
:raise TimeoutError: if no DNS servers were reached in time.
@@ -1409,8 +1411,11 @@ def dns_resolve(qname, qtype="A", raw=False, verbose=1, timeout=3, **kwargs):
1409
1411
for nameserver in conf .nameservers :
1410
1412
# Try all nameservers
1411
1413
try :
1412
- # Spawn a UDP socket, connect to the nameserver on port 53
1413
- sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
1414
+ # Spawn a socket, connect to the nameserver on port 53
1415
+ if tcp :
1416
+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
1417
+ else :
1418
+ sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
1414
1419
sock .settimeout (kwargs ["timeout" ])
1415
1420
sock .connect ((nameserver , 53 ))
1416
1421
# Connected. Wrap it with DNS
@@ -1428,6 +1433,21 @@ def dns_resolve(qname, qtype="A", raw=False, verbose=1, timeout=3, **kwargs):
1428
1433
sock .close ()
1429
1434
if res :
1430
1435
# We have a response ! Check for failure
1436
+ if res [DNS ].tc == 1 : # truncated !
1437
+ if not tcp :
1438
+ # Retry using TCP
1439
+ return dns_resolve (
1440
+ qname = qname ,
1441
+ qtype = qtype ,
1442
+ raw = raw ,
1443
+ tcp = True ,
1444
+ verbose = verbose ,
1445
+ timeout = timeout ,
1446
+ ** kwargs ,
1447
+ )
1448
+ elif verbose :
1449
+ log_runtime .info ("DNS answer is truncated !" )
1450
+
1431
1451
if res [DNS ].rcode == 2 : # server failure
1432
1452
res = None
1433
1453
if verbose :
0 commit comments