LCOV - code coverage report
Current view: top level - home/jelte/repos/coverage_bind10/src/bin/resolver - response_scrubber.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 49 53 92.5 %
Date: 2012-05-15 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 45 90 50.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <iostream>
      16                 :            : #include <vector>
      17                 :            : #include <dns/message.h>
      18                 :            : #include <dns/rrset.h>
      19                 :            : #include <dns/name.h>
      20                 :            : #include "response_scrubber.h"
      21                 :            : 
      22                 :            : using namespace isc::dns;
      23                 :            : using namespace std;
      24                 :            : 
      25                 :            : // Compare addresses etc.
      26                 :            : 
      27                 :         19 : ResponseScrubber::Category ResponseScrubber::addressCheck(
      28                 :            :     const isc::asiolink::IOEndpoint& to, const isc::asiolink::IOEndpoint& from)
      29                 :            : {
      30         [ +  + ]:         19 :     if (from.getProtocol() == to.getProtocol()) {
      31         [ +  + ]:         36 :         if (from.getAddress() == to.getAddress()) {
      32         [ +  + ]:          8 :             if (from.getPort() == to.getPort()) {
      33                 :            :                 return (ResponseScrubber::SUCCESS);
      34                 :            :             } else {
      35                 :         19 :                 return (ResponseScrubber::PORT);
      36                 :            :             }
      37                 :            :         } else {
      38                 :            :             return (ResponseScrubber::ADDRESS);
      39                 :            :         }
      40                 :            :     }
      41                 :            :     return (ResponseScrubber::PROTOCOL);
      42                 :            : }
      43                 :            : 
      44                 :            : // Do a general scrubbing.  The QNAMES of RRsets in the specified section are
      45                 :            : // compared against the list of name given and if they are not equal and not in
      46                 :            : // the specified relationship (generally superdomain or subdomain) to at least
      47                 :            : // of of the given names, they are removed.
      48                 :            : 
      49                 :            : unsigned int
      50                 :         19 : ResponseScrubber::scrubSection(Message& message,
      51                 :            :     const vector<const Name*>& names,
      52                 :            :     const NameComparisonResult::NameRelation connection,
      53                 :            :     const Message::Section section)
      54                 :            : {
      55                 :         19 :     unsigned int count = 0;     // Count of RRsets removed
      56                 :         19 :     unsigned int kept = 0;      // Count of RRsets kept
      57                 :         19 :     bool removed = true;        // Set true if RRset removed in a pass
      58                 :            : 
      59                 :            :     // Need to go through the section multiple times as when an RRset is
      60                 :            :     // removed, all iterators into the section are invalidated.  This condition
      61                 :            :     // is flagged by "remove" being set true when an RRset is removed.
      62                 :            : 
      63         [ +  + ]:         53 :     while (removed) {
      64                 :         34 :         RRsetIterator i = message.beginSection(section);
      65                 :            : 
      66                 :            :         // Skips the ones that have been checked (and retained) in a previous
      67                 :            :         // pass through the "while" loop.  (Although RRset removal invalidates
      68                 :            :         // iterators, it does not change the relative order of the retained
      69                 :            :         // RRsets in the section.)
      70         [ +  + ]:         47 :         for (int j = 0; j < kept; ++j) {
      71         [ +  - ]:         13 :             ++i;
      72                 :            :         }
      73                 :            : 
      74                 :            :         // Start looking at the remaining entries in the section.
      75                 :            :         removed = false;
      76 [ +  - ][ +  - ]:         52 :         for (; i != message.endSection(section); ++i) {
         [ +  - ][ +  - ]
                 [ +  + ]
      77                 :            : 
      78                 :            :             // Loop through the list of names given and see if any are in the
      79                 :            :             // given relationship with the QNAME of this RRset
      80                 :         33 :             bool match = false;
      81         [ +  + ]:         48 :             for (vector<const Name*>::const_iterator n = names.begin();
      82                 :         48 :                  n != names.end(); ++n) {
      83 [ +  - ][ +  - ]:         33 :                 NameComparisonResult result = (*i)->getName().compare(**n);
                 [ +  - ]
      84                 :            :                 NameComparisonResult::NameRelation relationship =
      85                 :         33 :                     result.getRelation();
      86         [ +  + ]:         33 :                 if ((relationship == NameComparisonResult::EQUAL) ||
      87                 :            :                    (relationship == connection)) {
      88                 :            : 
      89                 :            :                     // RRset in the specified relationship, so a match has
      90                 :            :                     // been found
      91                 :            :                     match = true;
      92                 :            :                     break;
      93                 :            :                 }
      94                 :            :             }
      95                 :            : 
      96                 :            :             // Remove the RRset if there was no match to one of the given names.
      97         [ +  + ]:         33 :             if (!match) {
      98         [ +  - ]:         15 :                 message.removeRRset(section, i);
      99                 :         15 :                 ++count;            // One more RRset removed
     100                 :         15 :                 removed = true;     // Something was removed
     101                 :         15 :                 break; // It invalidated the iterators, start again
     102                 :            :              } else {
     103                 :            : 
     104                 :            :                 // There was a match so this is one more entry we can skip next
     105                 :            :                 // time.
     106                 :         18 :                 ++kept;
     107                 :            :              }
     108                 :            :         }
     109                 :            :     }
     110                 :            : 
     111                 :         19 :     return (count);
     112                 :            : }
     113                 :            : 
     114                 :            : // Perform the scrubbing of all sections of the message.
     115                 :            : 
     116                 :            : unsigned int
     117                 :          5 : ResponseScrubber::scrubAllSections(Message& message, const Name& bailiwick) {
     118                 :            : 
     119                 :            :     // Leave the question section alone.  Just go through the RRsets in the
     120                 :            :     // answer, authority and additional sections.
     121                 :          5 :     unsigned int count = 0;
     122                 :          5 :     const vector<const Name*> bailiwick_names(1, &bailiwick);
     123                 :            :     count += scrubSection(message, bailiwick_names,
     124         [ +  - ]:          5 :             NameComparisonResult::SUBDOMAIN, Message::SECTION_ANSWER);
     125                 :            :     count += scrubSection(message, bailiwick_names,
     126         [ +  - ]:          5 :             NameComparisonResult::SUBDOMAIN, Message::SECTION_AUTHORITY);
     127                 :            :     count += scrubSection(message, bailiwick_names,
     128         [ +  - ]:          5 :             NameComparisonResult::SUBDOMAIN, Message::SECTION_ADDITIONAL);
     129                 :            : 
     130                 :          5 :     return (count);
     131                 :            : }
     132                 :            : 
     133                 :            : // Scrub across sections.
     134                 :            : 
     135                 :            : unsigned int
     136                 :          4 : ResponseScrubber::scrubCrossSections(isc::dns::Message& message) {
     137                 :            : 
     138                 :            :     // Get a list of the names in the answer section or, failing this, the
     139                 :            :     // question section.  Note that pointers to the names within "message" are
     140                 :            :     // stored; this is OK as the relevant sections in "message" will not change
     141                 :            :     // during the lifetime of this method (it only affects the authority
     142                 :            :     // section).
     143                 :          4 :     vector<const Name*> source;
     144 [ +  - ][ -  + ]:          4 :     if (message.getRRCount(Message::SECTION_ANSWER) != 0) {
     145 [ #  # ][ #  # ]:          0 :         for (RRsetIterator i = message.beginSection(Message::SECTION_ANSWER);
         [ #  # ][ #  # ]
                 [ #  # ]
     146 [ #  # ][ #  # ]:          0 :             i != message.endSection(Message::SECTION_ANSWER); ++i) {
     147 [ #  # ][ #  # ]:          0 :             const Name& qname = (*i)->getName();
     148         [ #  # ]:          0 :             source.push_back(&qname);
     149                 :            :         }
     150                 :            : 
     151                 :            :     } else {
     152 [ +  - ][ +  - ]:         24 :         for (QuestionIterator i = message.beginQuestion();
         [ +  - ][ +  + ]
                 [ +  - ]
     153 [ +  - ][ +  - ]:         16 :             i != message.endQuestion(); ++i) {
     154         [ +  - ]:          4 :             const Name& qname = (*i)->getName();
     155         [ +  - ]:          4 :             source.push_back(&qname);
     156                 :            :         }
     157                 :            :     }
     158                 :            : 
     159         [ +  - ]:          4 :     if (source.empty()) {
     160                 :            :         // TODO: Log the fact - should be at least a question present
     161                 :            :         return (0);
     162                 :            :     }
     163                 :            : 
     164                 :            :     // Could be duplicates, especially in the answer section, so sort the
     165                 :            :     // names and remove them.
     166         [ +  - ]:          4 :     sort(source.begin(), source.end(), ResponseScrubber::compareNameLt);
     167                 :            :     vector<const Name*>::iterator endunique =
     168                 :            :         unique(source.begin(), source.end(), ResponseScrubber::compareNameEq);
     169                 :            :     source.erase(endunique, source.end());
     170                 :            : 
     171                 :            :     // Now purge the authority section of RRsets that are not equal to or a
     172                 :            :     // superdomain of the names in the question/answer section.
     173                 :            :     return (scrubSection(message, source,
     174         [ +  - ]:          4 :         NameComparisonResult::SUPERDOMAIN, Message::SECTION_AUTHORITY));
     175                 :            : }
     176                 :            : 
     177                 :            : // Scrub a message
     178                 :            : 
     179                 :            : unsigned int
     180                 :          1 : ResponseScrubber::scrub(const isc::dns::MessagePtr& message,
     181                 :            :     const isc::dns::Name& bailiwick)
     182                 :            : {
     183                 :          1 :     unsigned int sections_removed = scrubAllSections(*message, bailiwick);
     184                 :          1 :     sections_removed += scrubCrossSections(*message);
     185                 :            : 
     186                 :          1 :     return (sections_removed);
     187                 :          1 : }
     188                 :            : 
     189                 :            : 

Generated by: LCOV version 1.9