]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix 0x20 capsforid fallback to omit gratuitous NS and additional
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 30 Jan 2015 09:35:38 +0000 (09:35 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 30 Jan 2015 09:35:38 +0000 (09:35 +0000)
  section changes.

git-svn-id: file:///svn/unbound/trunk@3323 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c

index b2ba34998dbd12682a3d4ac6f51664a92297c9d8..356afa2468ba5e326a51c7d4054536c5071c2fd0 100644 (file)
@@ -1,3 +1,7 @@
+30 January 2015: Wouter
+       - Fix 0x20 capsforid fallback to omit gratuitous NS and additional
+         section changes.
+
 29 January 2015: Wouter
        - Fix pyunbound byte string representation for python3.
 
index 9d0aa698f99600b287fcb8e056880c15eb6713aa..10ae12f75c6cd728c860b8acc4ffb6fd9f13cfed 100644 (file)
@@ -714,6 +714,42 @@ reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region)
        return 1;
 }
 
+void 
+caps_strip_reply(struct reply_info* rep)
+{
+       size_t i;
+       if(!rep) return;
+       /* see if message is a referral, in which case the additional and
+        * NS record cannot be removed */
+       /* referrals have the AA flag unset (strict check, not elsewhere in
+        * unbound, but for 0x20 this is very convenient). */
+       if(!(rep->flags&BIT_AA))
+               return;
+       /* remove the additional section from the reply */
+       if(rep->ar_numrrsets != 0) {
+               verbose(VERB_ALGO, "caps fallback: removing additional section");
+               rep->rrset_count -= rep->ar_numrrsets;
+               rep->ar_numrrsets = 0;
+       }
+       /* is there an NS set in the authority section to remove? */
+       /* the failure case (Cisco firewalls) only has one rrset in authsec */
+       for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
+               struct ub_packed_rrset_key* s = rep->rrsets[i];
+               if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) {
+                       /* remove NS rrset and break from loop (loop limits
+                        * have changed) */
+                       /* move last rrset into this position (there is no
+                        * additional section any more) */
+                       verbose(VERB_ALGO, "caps fallback: removing NS rrset");
+                       if(i < rep->rrset_count-1)
+                               rep->rrsets[i]=rep->rrsets[rep->rrset_count-1];
+                       rep->rrset_count --;
+                       rep->ns_numrrsets --;
+                       break;
+               }
+       }
+}
+
 void 
 iter_store_parentside_rrset(struct module_env* env, 
        struct ub_packed_rrset_key* rrset)
index d7c2b68afa2d6562acdce28bd9824cc429f705c9..9373487e002c95712c8f5a7721bb8778eeb247b9 100644 (file)
@@ -222,6 +222,15 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
  */
 int reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region);
 
+/**
+ * Remove unused bits from the reply if possible.
+ * So that caps-for-id (0x20) fallback is more likely to be successful.
+ * This removes like, the additional section, and NS record in the authority
+ * section if those records are gratuitous (not for a referral).
+ * @param rep: the reply to strip stuff out of.
+ */
+void caps_strip_reply(struct reply_info* rep);
+
 /**
  * Store parent-side rrset in seperate rrset cache entries for later 
  * last-resort * lookups in case the child-side versions of this information 
index 07000749a560d728c8aafab1d64f87029dbc3a44..2037cc8814f2b962f7df61eb5e20f24a369e1c43 100644 (file)
@@ -2882,6 +2882,9 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
                        iq->response->rep);
        
        if(event == module_event_capsfail || iq->caps_fallback) {
+               /* for fallback we care about main answer, not additionals */
+               /* removing that makes comparison more likely to succeed */
+               caps_strip_reply(iq->response->rep);
                if(!iq->caps_fallback) {
                        /* start fallback */
                        iq->caps_fallback = 1;