diff --git a/CHANGES b/CHANGES
index 0a92707757..fbd6bf4267 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4093. [func] Dig now learns the SIT value from truncated
+ responses when it retries over TCP. [RT #39047]
+
4092. [bug] 'in-view' didn't work for zones beneath a empty zone.
[RT #39173]
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index f72925ef4a..35a86b3223 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -149,6 +149,10 @@ int ndots = -1;
int tries = 3;
int lookup_counter = 0;
+#ifdef ISC_PLATFORM_USESIT
+static char sitvalue[256];
+#endif
+
#ifdef WITH_IDN
static void initialize_idn(void);
static isc_result_t output_filter(isc_buffer_t *buffer,
@@ -3412,6 +3416,7 @@ process_sit(dig_lookup_t *l, dns_message_t *msg,
isc_buffer_t hexbuf;
size_t len;
const unsigned char *sit;
+ isc_boolean_t copysit;
isc_result_t result;
if (l->sitvalue != NULL) {
@@ -3420,9 +3425,11 @@ process_sit(dig_lookup_t *l, dns_message_t *msg,
check_result(result, "isc_hex_decodestring");
sit = isc_buffer_base(&hexbuf);
len = isc_buffer_usedlength(&hexbuf);
+ copysit = ISC_FALSE;
} else {
sit = cookie;
len = sizeof(cookie);
+ copysit = ISC_TRUE;
}
INSIST(msg->sitok == 0 && msg->sitbad == 0);
@@ -3432,10 +3439,25 @@ process_sit(dig_lookup_t *l, dns_message_t *msg,
} else {
printf(";; Warning: SIT client cookie mismatch\n");
msg->sitbad = 1;
+ copysit = ISC_FALSE;
}
} else {
printf(";; Warning: SIT bad token (too short)\n");
msg->sitbad = 1;
+ copysit = ISC_FALSE;
+ }
+ if (copysit) {
+ isc_region_t r;
+
+ r.base = isc_buffer_current(optbuf);
+ r.length = (unsigned int)optlen;
+ isc_buffer_init(&hexbuf, sitvalue, sizeof(sitvalue));
+ result = isc_hex_totext(&r, 2, "", &hexbuf);
+ check_result(result, "isc_hex_totext");
+ if (isc_buffer_availablelength(&hexbuf) > 0) {
+ isc_buffer_putuint8(&hexbuf, 0);
+ l->sitvalue = sitvalue;
+ }
}
isc_buffer_forward(optbuf, (unsigned int)optlen);
}
@@ -3756,6 +3778,10 @@ recv_done(isc_task_t *task, isc_event_t *event) {
}
if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
!l->ignore && !l->tcp_mode) {
+#ifdef ISC_PLATFORM_USESIT
+ if (l->sitvalue == NULL && l->sit && msg->opt != NULL)
+ process_opt(l, msg);
+#endif
if (l->comments)
printf(";; Truncated, retrying in TCP mode.\n");
n = requeue_lookup(l, ISC_TRUE);
diff --git a/bin/tests/system/sit/tests.sh b/bin/tests/system/sit/tests.sh
index 5842a98714..5f619e6863 100755
--- a/bin/tests/system/sit/tests.sh
+++ b/bin/tests/system/sit/tests.sh
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -28,6 +28,12 @@ getsit() {
}' < $1
}
+fullsit() {
+ awk 'BEGIN { n = 0 }
+ // { v[n++] = length(); }
+ END { print (v[1] == v[2]); }'
+}
+
havetc() {
grep 'flags:.* tc[^;]*;' $1 > /dev/null
}
@@ -87,6 +93,17 @@ grep "; SIT:.*(good)" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+n=`expr $n + 1`
+echo "I:checking SIT is learnt for TCP retry ($n)"
+ret=0
+$DIG +qr +sit large.example txt @10.53.0.1 -p 5300 > dig.out.test$n
+linecount=`getsit dig.out.test$n | wc -l`
+if [ $linecount != 3 ]; then ret=1; fi
+checkfull=`getsit dig.out.test$n | fullsit`
+if [ $checkfull != 1 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
n=`expr $n + 1`
echo "I:checking for SIT value in adb ($n)"
ret=0
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 8bcc72528c..624e9d417f 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -459,6 +459,14 @@
[RT #37927]
+
+
+ When retrying a query via TCP due to the first answer being
+ truncated, dig will now correctly send
+ the SIT (server identity token) value returned by the server
+ in the prior response. [RT #39047]
+
+