Browse Source

[trac703] Section count modification now added

Stephen Morris 14 years ago
parent
commit
10b62db1ae

+ 37 - 8
tests/tools/badpacket/command_options.cc

@@ -48,6 +48,8 @@ CommandOptions::parse(int argc, char* const argv[]) {
     char ADDRESS[] = {"address"};
     char PORT[] = {"port"};
     char TIMEOUT[] = {"timeout"};
+
+    // Settings for options in the flags field
     char QR[] = {"qr"};
     char OP[] = {"op"};
     char AA[] = {"aa"};
@@ -59,6 +61,12 @@ CommandOptions::parse(int argc, char* const argv[]) {
     char CD[] = {"cd"};
     char RC[] = {"rc"};
 
+    // Settings for the count fields
+    char QC[] = {"qc"};
+    char AC[] = {"ac"};
+    char UC[] = {"uc"};
+    char DC[] = {"dc"};
+
     const struct option longopts[] = {
         {HELP,    0, NULL, 'h'},  // Print usage message and exit
         {VERSION, 0, NULL, 'v'},  // Print program version and exit
@@ -75,9 +83,13 @@ CommandOptions::parse(int argc, char* const argv[]) {
         {AD,      1, NULL, 'U'},  // aUthenticated data
         {CD,      1, NULL, 'C'},  // Checking disabled
         {RC,      1, NULL, 'E'},  // rEsult code
+        {QC,      1, NULL, 'Y'},  // querY section count
+        {AC,      1, NULL, 'W'},  // ansWer section count
+        {UC,      1, NULL, 'H'},  // autHority section count
+        {DC,      1, NULL, 'I'},  // addItional section count
         {NULL,    0, NULL, 0  }
     };
-    const char* shortopts = "hva:p:t:Q:O:A:T:D:R:Z:U:C:E:";
+    const char* shortopts = "hva:p:t:Q:O:A:T:D:R:Z:U:C:E:Y:W:H:I:";
 
 
     // Set variables to defaults before parsing
@@ -118,6 +130,10 @@ CommandOptions::parse(int argc, char* const argv[]) {
             case 'U':   // --ad (authenticated data)
             case 'C':   // --cd (checking disabled)
             case 'E':   // --rc (result code)
+            case 'Y':   // --qc (query count)
+            case 'W':   // --ac (answer count)
+            case 'H':   // --uc (authority count)
+            case 'I':   // --dc (additional count)
                 processOptionValue(c, optarg);
                 break;
 
@@ -164,15 +180,28 @@ CommandOptions::usage() {
             "--port <port>       [-p] Port to which to send query.  Defaults to 53.\n"
             "--timeout <value>   [-t] Timeout value for the query.  Specified in ms, it\n"
             "                         defaults to 500ms.\n"
-            "--qr <range>        [-Q] Set query/response bit.  Valid <range> is 0-1\n"
-            "--op <range>        [-O] Set opcode.  Valid <range> is 0-15\n"
-            "--aa <range>        [-A] Set authoritative answer bit.  Valid <range> is 0-1\n"
-            "--tc <range>        [-T] Set truncated bit.  Valid <range> is 0-1\n"
-            "--z <range>         [-Z] Set zero (reserved) bit.  Valid <range> is 0-1\n"
-            "--ad <range>        [-U] Set authentiacted data bit.  Valid <range> is 0-1\n"
-            "--cd <range>        [-C] Set checking disabled bit.  Valid <range> is 0-1\n"
+            "\n"
+            "The following options set fields in the outgoing DNS message flags word\n"
+            "\n"
+            "--qr <range>        [-Q] Set query/response bit.  Valid <range> is 0-1.\n"
+            "--op <range>        [-O] Set opcode.  Valid <range> is 0-15.\n"
+            "--aa <range>        [-A] Set authoritative answer bit.  Valid <range> is 0-1.\n"
+            "--tc <range>        [-T] Set truncated bit.  Valid <range> is 0-1.\n"
+            "--rd <range>        [-T] Set recursion desired bit.  Valid <range> is 0-1.\n"
+            "--ra <range>        [-T] Set recursion available bit.  Valid <range> is 0-1.\n"
+            "--z <range>         [-Z] Set zero (reserved) bit.  Valid <range> is 0-1.\n"
+            "--ad <range>        [-U] Set authenticated data bit.  Valid <range> is 0-1.\n"
+            "--cd <range>        [-C] Set checking disabled bit.  Valid <range> is 0-1.\n"
             "--rc <range>        [-E] Set rcode value.  Valid <range> is 0-15\n"
             "\n"
+            "The following options set the various section counts (independent of what is\n"
+            "actually in the section)\n"
+            "\n"
+            "--qc <range>        [-Q] Set the query count.  Valid range is 0-65535.\n"
+            "--ac <range>        [-Q] Set the answer count.  Valid range is 0-65535.\n"
+            "--uc <range>        [-Q] Set the authority count.  Valid range is 0-65535.\n"
+            "--dc <range>        [-Q] Set the additional count.  Valid range is 0-65535.\n"
+            "\n"
             "query               Name to query for.  The query is for an 'IN' A record.\n"
             "                    If not given, the name 'www.example.com' is used.\n"
             ;

+ 2 - 2
tests/tools/badpacket/command_options.h

@@ -97,8 +97,8 @@ public:
         qname_ = "www.example.com";
 
         for (int i = 0; i < OptionInfo::SIZE; ++i) {
-            limits_[i][0] = limits_[i][1] = 0;
-            }
+            limits_[i][0] = limits_[i][1] = OptionInfo::defval(i);
+        }
     }
 
     /// \brief Parse Command Line

+ 26 - 10
tests/tools/badpacket/option_info.cc

@@ -23,16 +23,20 @@ namespace {
 // processing.
 
 isc::badpacket::OptionInfo::Parameter option_information[] = {
-    {'Q', "qr", 0x8000, 15, 0,  1},
-    {'O', "op", 0x7800, 11, 0, 15},
-    {'A', "aa", 0x0400, 10, 0,  1},
-    {'T', "tc", 0x0200,  9, 0,  1},
-    {'D', "rd", 0x0100,  8, 0,  1},
-    {'R', "ra", 0x0080,  7, 0,  1},
-    {'Z', "z",  0x0040,  6, 0,  1},
-    {'U', "ad", 0x0020,  5, 0,  1},
-    {'C', "cd", 0x0010,  4, 0,  1},
-    {'E', "rc", 0x000F,  0, 0, 15}
+    {'Q', "qr",  2, 0x8000,  15,  0, 0,      1},
+    {'O', "op",  2, 0x7800,  11,  0, 0,     15},
+    {'A', "aa",  2, 0x0400,  10,  0, 0,      1},
+    {'T', "tc",  2, 0x0200,   9,  0, 0,      1},
+    {'D', "rd",  2, 0x0100,   8,  0, 0,      1},
+    {'R', "ra",  2, 0x0080,   7,  0, 0,      1},
+    {'Z', "z",   2, 0x0040,   6,  0, 0,      1},
+    {'U', "ad",  2, 0x0020,   5,  0, 0,      1},
+    {'C', "cd",  2, 0x0010,   4,  0, 0,      1},
+    {'E', "rc",  2, 0x000F,   0,  0, 0,     15},
+    {'Y', "qc",  4,      0,   0,  1, 0, 0xFFFF},
+    {'W', "ac",  6,      0,   0,  0, 0, 0xFFFF},
+    {'H', "uc",  8,      0,   0,  0, 0, 0xFFFF},
+    {'I', "dc", 10,      0,   0,  0, 0, 0xFFFF}
 };
 
 }   // Anonymous namespace
@@ -66,6 +70,12 @@ OptionInfo::mask(int i) {
 }
 
 int
+OptionInfo::word(int i) {
+    checkIndex(i);
+    return (option_information[i].word);
+}
+
+int
 OptionInfo::offset(int i) {
     checkIndex(i);
     return (option_information[i].offset);
@@ -78,6 +88,12 @@ OptionInfo::minval(int i) {
 }
 
 uint32_t
+OptionInfo::defval(int i) {
+    checkIndex(i);
+    return (option_information[i].defval);
+}
+
+uint32_t
 OptionInfo::maxval(int i) {
     checkIndex(i);
     return (option_information[i].maxval);

+ 39 - 14
tests/tools/badpacket/option_info.h

@@ -42,29 +42,36 @@ public:
     /// The data for the flags options are held in an array.  Although an enum,
     /// only the numeric values are used - they are indexes into arrays.
     enum Index {
-        QR = 0,
-        OP = 1,
-        AA = 2,
-        TC = 3,
-        RD = 4,
-        RA = 5,
-        Z  = 6,
-        AD = 7,
-        CD = 8,
-        RC = 9,
-        SIZE = 10   // Number of index values
+        QR = 0,     // Query/response
+        OP = 1,     // Opcode
+        AA = 2,     // Authoritative answer
+        TC = 3,     // Truncated
+        RD = 4,     // Recursion desired
+        RA = 5,     // Recursion available
+        Z  = 6,     // Zero (reserved)
+        AD = 7,     // Authenticated data
+        CD = 8,     // Checking disabled
+        RC = 9,     // Response code
+        QC = 10,    // Query count
+        AC = 11,    // Answer count
+        UC = 12,    // Authority count
+        DC = 13,    // Additional count
+        SIZE = 14   // Number of index values
     };
 
     /// \brief Option Parameters
     ///
     /// Defines a structure that holds information associated with each of the
-    /// flags field command options.
+    /// flags field command options.  Note all members of the structure are
+    /// relevant to all options
     struct Parameter {
         const char      short_form;     // Short form of the command switch
         const char*     long_form;      // Long form of the command switch
-        uint16_t        mask;           // Bit mask of the field in the flags word
+        int             word;           // Byte offset of word in the header
+        uint16_t        mask;           // Bit mask of field in the flags word
         int             offset;         // Offset of field in flags word
         uint32_t        minval;         // Minimum valid value for this field
+        uint32_t        defval;         // Default value
         uint32_t        maxval;         // Maximum valid value for this field
     };
 
@@ -87,11 +94,22 @@ public:
     /// \return The long option name (e.q. "qr" for the Query/Response field).
     static const char* name(int index);
 
+    /// \brief Return header word offset
+    ///
+    /// Returns the byte offset in the DNS message header of the two-byte word 
+    /// holding the data in question.
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return The offset in the header foe this datum.
+    static int word(int index);
+
     /// \brief Return mask associated with switch field
     ///
     /// \param index A valid index (one of the values in the 'Index' enum).
     ///
-    /// \return The mask for this particular option in the DNS message flags field.
+    /// \return The mask for this particular option in the DNS message flags
+    ///         field.
     static uint16_t mask(int index);
 
     /// \brief Return offset associated with switch field
@@ -109,6 +127,13 @@ public:
     /// \return Minimum allowed value for this option.  This is usually 0.
     static uint32_t minval(int index);
 
+    /// \brief Return default value of a field
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return Default value for this option
+    static uint32_t defval(int index);
+
     /// \brief Return maximum allowed value of field
     ///
     /// \param index A valid index (one of the values in the 'Index' enum).

+ 53 - 4
tests/tools/badpacket/scan.cc

@@ -114,8 +114,9 @@ Scan::iterateFlagsFields(OutputBufferPtr& msgbuf, const CommandOptions& options)
                                             // Set the flags in the message.
                                             msgbuf->writeUint16At(flags.getValue(), 2);
 
-                                            // Do the I/O.
-                                            scanOne(msgbuf, options);
+                                            // And for this flag combination, iterate over the section
+                                            // count fields.
+                                            iterateCountFields(msgbuf, options);
                                         }
                                     }
                                 }
@@ -128,7 +129,35 @@ Scan::iterateFlagsFields(OutputBufferPtr& msgbuf, const CommandOptions& options)
     }
 }
 
-// Perform the message exchange for a single combination of flags.
+// Iterate through the various count fields
+void
+Scan::iterateCountFields(OutputBufferPtr& msgbuf, const CommandOptions& options) {
+    for (uint32_t qc =  options.minimum(OptionInfo::QC);
+                  qc <= options.maximum(OptionInfo::QC); ++qc) {
+        msgbuf->writeUint16At(qc, OptionInfo::word(OptionInfo::QC));
+
+        for (uint32_t ac =  options.minimum(OptionInfo::AC);
+                      ac <= options.maximum(OptionInfo::AC); ++ac) {
+            msgbuf->writeUint16At(ac, OptionInfo::word(OptionInfo::AC));
+
+            for (uint32_t uc =  options.minimum(OptionInfo::UC);
+                          uc <= options.maximum(OptionInfo::UC); ++uc) {
+                msgbuf->writeUint16At(uc, OptionInfo::word(OptionInfo::UC));
+
+                for (uint32_t dc =  options.minimum(OptionInfo::DC);
+                              dc <= options.maximum(OptionInfo::DC); ++dc) {
+                    msgbuf->writeUint16At(dc, OptionInfo::word(OptionInfo::DC));
+
+                    // Do the I/O.
+                    scanOne(msgbuf, options);
+
+                }
+            }
+        }
+    }
+}
+
+// Perform the message exchange for a single combination command options.
 void
 Scan::scanOne(isc::dns::OutputBufferPtr& msgbuf, const CommandOptions& options) {
 
@@ -178,7 +207,7 @@ Scan::getFields(isc::dns::OutputBufferPtr& msgbuf) {
 
     // Extract the flags field from the buffer
     InputBuffer inbuf(msgbuf->getData(), msgbuf->getLength());
-    inbuf.setPosition(2);
+    inbuf.setPosition(OptionInfo::word(OptionInfo::QR));
     flags.setValue(inbuf.readUint16());
 
     std::ostringstream os;
@@ -193,6 +222,26 @@ Scan::getFields(isc::dns::OutputBufferPtr& msgbuf) {
         "AD:" << flags.get(OptionInfo::AD) << " " <<
         "CD:" << flags.get(OptionInfo::CD) << " " <<
         "RC:" << flags.get(OptionInfo::RC);
+
+    // Section count fields
+    os << " ";
+
+    inbuf.setPosition(OptionInfo::word(OptionInfo::QC));
+    os << std::hex << std::uppercase <<
+        "QC:" << inbuf.readUint16() << " ";
+
+    inbuf.setPosition(OptionInfo::word(OptionInfo::AC));
+    os << std::hex << std::uppercase <<
+        "AC:" << inbuf.readUint16() << " ";
+
+    inbuf.setPosition(OptionInfo::word(OptionInfo::UC));
+    os << std::hex << std::uppercase <<
+        "UC:" << inbuf.readUint16() << " ";
+
+    inbuf.setPosition(OptionInfo::word(OptionInfo::DC));
+    os << std::hex << std::uppercase <<
+        "DC:" << inbuf.readUint16();
+
     return (os.str());
 }
 

+ 17 - 0
tests/tools/badpacket/scan.h

@@ -72,6 +72,23 @@ private:
     void iterateFlagsFields(isc::dns::OutputBufferPtr& msgbuf,
                  const CommandOptions& options);
 
+    /// \brief Set Count Fields Options
+    ///
+    /// Iterates through all combinations of the count fields specified on the
+    /// command line.
+    ///
+    /// The count fields are set by default to question count = 1, all the rest
+    /// zero.  Command-line options allow these values to be altered, although
+    /// the actual contents of the sections are not changed.
+    ///
+    /// \param msgbuf Message that will be sent to the remote nameserver.  The
+    ///        QID given will be ignored - the value used will be determined by
+    ///        the sending code
+    /// \param options Command-line options (the important ones being address,
+    ///        port and timeout).
+    void iterateCountFields(isc::dns::OutputBufferPtr& msgbuf,
+                 const CommandOptions& options);
+
     /// \brief Scan One Value
     ///
     /// Performs one exchange of packets with the remote nameserver, sending