From 3a9ce4a484d22d56d20874f52a60158b9f4d1f29 Mon Sep 17 00:00:00 2001
From: Daniel Salzman <daniel.salzman@nic.cz>
Date: Mon, 27 Aug 2012 10:12:18 +0200
Subject: [PATCH] Refactoring 2

---
 src/zscanner/NOTES           | 16 +++++----
 src/zscanner/file_loader.c   | 46 ++++++++++++++++----------
 src/zscanner/scanner.h       |  2 +-
 src/zscanner/scanner.rl      | 63 +++++++++++++++++++++++++-----------
 src/zscanner/scanner_body.rl | 25 +++++++-------
 5 files changed, 95 insertions(+), 57 deletions(-)

diff --git a/src/zscanner/NOTES b/src/zscanner/NOTES
index 08089fac0d..6195884436 100644
--- a/src/zscanner/NOTES
+++ b/src/zscanner/NOTES
@@ -1,8 +1,10 @@
+- the new-line character is appended to each zone file before processing (for simplicity)
 - the class IN is supported only
-- time values can have maximal 1 unit (NOT 1D2H)
-- \x and \DDD notation is allowed in domain_name and text only
-- @ can be used on the right side
-- line number in multiline is the number of the last record part
-- hex blocks multiple of 2, base64 blocks multiple of 4, base32hex blocks multiple of 8 (DHCID problem)
-- RFC 5155 section 3.3 says "unpadded", but padding is used here
-- date version of timestamp is limited to the end of the year 2105 due to 32 bits and better check
\ No newline at end of file
+- time values can have at most 1 time unit (not 1D2H3M)
+- \x and \DDD notations are allowed in domain names and text strings only
+- upper-case letters are lowered in domain names (including \x and \DDD notations)
+- @ can be used instead of domain names anywhere
+- the line numbers of multiline records are the numbers of the last lines with appropriate record parts
+- items parts lengths must be multiples of 2 for HEX, 4 for base64 and 8 for base32hex blocks (but DHCID example from RFC is more general!)
+- NSEC3 hash is with padding (but RFC 5155 section 3.3 says "unpadded")
+- date version of timestamp in RRSIG is limited to the end of the year 2105 (for better checking of 32bit integer)
\ No newline at end of file
diff --git a/src/zscanner/file_loader.c b/src/zscanner/file_loader.c
index 2ef0135e9b..c6230b6b70 100644
--- a/src/zscanner/file_loader.c
+++ b/src/zscanner/file_loader.c
@@ -16,7 +16,7 @@
 
 #include "zscanner/file_loader.h"
 
-#include <stdint.h>
+#include <inttypes.h>  // PRIu64
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,18 +42,24 @@ static int load_settings(file_loader_t *fl)
     // Temporary scanner for zone settings.
     settings_scanner = scanner_create(settings_name);
 
+    // Use parent processing functions.
+    settings_scanner->process_record = fl->scanner->process_record;
+    settings_scanner->process_error  = fl->scanner->process_error;
+
     // Scanning zone settings.
     ret = scanner_process(fl->settings_buffer,
                           fl->settings_buffer + fl->settings_length,
-                          false,
+                          true,
                           settings_scanner);
 
-    // Copying scanned settings to actual context.
-    memcpy(fl->scanner->zone_origin,
-           settings_scanner->zone_origin,
-           settings_scanner->zone_origin_length);
-    fl->scanner->zone_origin_length = settings_scanner->zone_origin_length;
-    fl->scanner->default_ttl = settings_scanner->default_ttl;
+    // If no error occured, then copy scanned settings to actual context.
+    if (ret == 0) {
+        memcpy(fl->scanner->zone_origin,
+               settings_scanner->zone_origin,
+               settings_scanner->zone_origin_length);
+        fl->scanner->zone_origin_length = settings_scanner->zone_origin_length;
+        fl->scanner->default_ttl = settings_scanner->default_ttl;
+    }
 
     // Destroying temporary scanner.
     scanner_free(settings_scanner);
@@ -74,6 +80,7 @@ file_loader_t* file_loader_create(const char     *file_name,
 
     // Creating zeroed structure.
     file_loader_t *fl = calloc(1, sizeof(file_loader_t));
+
     if (fl == NULL) {
         return NULL;
     }
@@ -83,6 +90,7 @@ file_loader_t* file_loader_create(const char     *file_name,
 
     // Opening zone file.
     fl->fd = open(fl->file_name, O_RDONLY);
+
     if (fl->fd == -1) {
         free(fl->file_name);
         free(fl);
@@ -104,11 +112,12 @@ file_loader_t* file_loader_create(const char     *file_name,
                   "$ORIGIN %s\n"
                   "$TTL %u\n",
                   zone_origin, default_ttl);
+
     if (ret > 0) {
         fl->settings_length = ret;
     }
     else {
-        printf("Zone file setttings error!\n");
+        printf("Error in zone setttings!\n");
         file_loader_free(fl);
         return NULL;
     }
@@ -134,12 +143,12 @@ int file_loader_process(file_loader_t *fl)
     long     page_size;
     uint64_t n_blocks, block_id;
     uint64_t block_size, overlapping_size;
-    // Start means first valid character; End means first invalid character.
+    // Start means first valid character; end means first invalid character.
     uint64_t block_start_position, block_end_position;
     uint64_t scanner_start_position, scanner_end_position;
 
     // For secure termination of zone file.
-    char     *zone_termination = "\n";
+    char *zone_termination = "\n";
 
     // Getting OS page size.
     page_size = sysconf(_SC_PAGESIZE);
@@ -156,13 +165,14 @@ int file_loader_process(file_loader_t *fl)
     // Overlapping size adjustment to multiple of page size.
     overlapping_size = (BLOCK_OVERLAPPING_SIZE / page_size) * page_size;
 
-    // Number of blocks which cover the whole file.
+    // Number of blocks which cover the whole file (ceiling operation).
     n_blocks = 1 + ((file_stat.st_size - 1) / block_size);
 
-    // Process settings using scanner (like initial ORIGIN).
+    // Process settings using scanner (like initial ORIGIN and TTL).
     ret = load_settings(fl);
+
     if (ret != 0) {
-        printf("Scanner settings processing error!\n");
+        printf("Zone defaults error!\n");
         return -1;
     }
 
@@ -195,6 +205,7 @@ int file_loader_process(file_loader_t *fl)
                     MAP_SHARED,
                     fl->fd,
                     block_start_position);
+
         if (data == MAP_FAILED) {
             printf("Mmap error!\n");
             return -1;
@@ -206,7 +217,7 @@ int file_loader_process(file_loader_t *fl)
             return -1;
         };
 
-        // parser < data, scanner_start_position, scanner_end_position
+        // Scan zone file.
         ret = scanner_process(data + scanner_start_position,
                               data + scanner_end_position,
                               false,
@@ -220,9 +231,10 @@ int file_loader_process(file_loader_t *fl)
                                   fl->scanner);
         }
 
-        // Processing return check.
+        // Check for error.
         if (ret != 0) {
-            printf("Scanner zone file processing error!\n");
+            printf("Zone processing has stopped with %"PRIu64" errors!\n",
+                   fl->scanner->error_counter);
             return -1;
         }
 
diff --git a/src/zscanner/scanner.h b/src/zscanner/scanner.h
index fb2fd5298a..f7e3dc6356 100644
--- a/src/zscanner/scanner.h
+++ b/src/zscanner/scanner.h
@@ -96,7 +96,7 @@ struct scanner {
     /*!< Auxiliary buffer length. */
     uint32_t buffer_length;
 
-    char include_filename[MAX_RDATA_LENGTH];
+    char     include_filename[MAX_RDATA_LENGTH];
 
     /*!< Bitmap window blocks. */
     window   windows[BITMAP_WINDOWS];
diff --git a/src/zscanner/scanner.rl b/src/zscanner/scanner.rl
index 70717e5e75..3584200cd7 100644
--- a/src/zscanner/scanner.rl
+++ b/src/zscanner/scanner.rl
@@ -16,19 +16,18 @@
 
 #include "zscanner/scanner.h"
 
-#include <stdint.h>                // uint32_t
-#include <stdlib.h>                // calloc
-#include <stdio.h>                 // sprintf
-#include <limits.h>                // PATH_MAX
-#include <libgen.h>                // dirname
-#include <stdbool.h>               // bool
-#include <sys/socket.h>            // AF_INET (BSD)
-#include <netinet/in.h>            // in_addr (BSD)
-
-#include "util/error.h"            // error codes
-#include "util/descriptor.h"       // KNOT_RRTYPE_A
-#include "zscanner/file_loader.h"  // include processing
-#include "zscanner/scanner_functions.h"
+#include <stdint.h>                        // uint32_t
+#include <stdlib.h>                        // calloc
+#include <stdio.h>                         // sprintf
+#include <libgen.h>                        // dirname
+#include <stdbool.h>                       // bool
+#include <sys/socket.h>                    // AF_INET (BSD)
+#include <netinet/in.h>                    // in_addr (BSD)
+
+#include "util/error.h"                    // error codes
+#include "util/descriptor.h"               // KNOT_RRTYPE_A
+#include "zscanner/file_loader.h"          // file_loader
+#include "zscanner/scanner_functions.h"    // Base64
 
 #define SCANNER_WARNING(code) { s->error_code = code; }
 #define SCANNER_ERROR(code)   { s->error_code = code; s->stop = true; }
@@ -91,7 +90,6 @@ int scanner_process(char      *start,
 {
     // Necessary scanner variables.
     int  stack[RAGEL_STACK_SIZE];
-    int  ret = 0;
     char *ts = NULL, *eof = NULL;
     char *p = start, *pe = end;
 
@@ -101,6 +99,7 @@ int scanner_process(char      *start,
     uint8_t  win, byte_pos, bit_pos;
     uint32_t timestamp;
     int16_t  window;
+    int      ret;
 
     // Next 2 variables are for better performance.
     // Restoring r_data pointer to next free space.
@@ -126,18 +125,46 @@ int scanner_process(char      *start,
     // Writing scanner body (in C).
     %% write exec;
 
-    // Scanner error state check.
+    // Check if scanner state machine is in uncovered state.
     if (cs == zone_scanner_error) {
-        printf("Unknown scanner error!\n");
+        SCANNER_ERROR(ZSCANNER_UNCOVERED_STATE);
+        s->error_counter++;
+
+        // Fill error context data.
+        for (s->buffer_length = 0;
+             ((p + s->buffer_length) < pe) &&
+             (s->buffer_length < sizeof(s->buffer) - 1);
+             s->buffer_length++)
+        {
+            // Only rest of the current line.
+            if (*(p + s->buffer_length) == '\n') {
+                break;
+            }
+            s->buffer[s->buffer_length] = *(p + s->buffer_length);
+        }
+
+        // Ending string in buffer.
+        s->buffer[s->buffer_length++] = 0;
+
+        // Processing error.
+        s->process_error(s);
+
+        return -1;
+    }
+
+    // Check if any errors occured.
+    if (s->error_counter > 0) {
         return -1;
     }
 
     // Storing scanner states.
     s->cs  = cs;
     s->top = top;
-    s->r_data_tail = rdata_tail - s->r_data;
     memcpy(s->stack, stack, sizeof(stack));
 
+    // Storing r_data pointer
+    s->r_data_tail = rdata_tail - s->r_data;
+
     // Storing unprocessed token shift
     if (ts != NULL) {
         s->token_shift = pe - ts;
@@ -146,6 +173,6 @@ int scanner_process(char      *start,
         s->token_shift = 0;
     }
 
-    return ret;
+    return 0;
 }
 
diff --git a/src/zscanner/scanner_body.rl b/src/zscanner/scanner_body.rl
index b7d07c75ce..f3280d984b 100644
--- a/src/zscanner/scanner_body.rl
+++ b/src/zscanner/scanner_body.rl
@@ -198,8 +198,8 @@
         s->dname_tmp_length = 0;
     }
     action _dname_error {
-            SCANNER_WARNING(ZSCANNER_EBAD_DNAME_CHAR);
-            fhold; fgoto err_line;
+        SCANNER_WARNING(ZSCANNER_EBAD_DNAME_CHAR);
+        fhold; fgoto err_line;
     }
 
     relative_dname = (labels       ) >_dname_init %_relative_dname_exit;
@@ -483,7 +483,7 @@
     text_array = (text_with_length . (sep . text_with_length)*) %_item_exit;
     # END
 
-    # BEGIN - TTL directives processing
+    # BEGIN - TTL directive processing
     action _default_ttl_exit {
         if (s->number64 <= UINT32_MAX) {
             s->default_ttl = (uint32_t)(s->number64);
@@ -506,7 +506,7 @@
     }
     # END
 
-    # BEGIN - ORIGIN directives processing
+    # BEGIN - ORIGIN directive processing
     action _zone_origin_init {
         s->dname = s->zone_origin;
     }
@@ -526,7 +526,7 @@
     }
     # END
 
-    # BEGIN - INCLUDE directives processing
+    # BEGIN - INCLUDE directive processing
     action _incl_filename_init {
         rdata_tail = s->r_data;
     }
@@ -962,7 +962,6 @@
         | "KX"i         %{ TYPE_NUM(KNOT_RRTYPE_KX); }
         | "CERT"i       %{ TYPE_NUM(KNOT_RRTYPE_CERT); }
         | "DNAME"i      %{ TYPE_NUM(KNOT_RRTYPE_DNAME); }
-        | "OPT"i        %{ TYPE_NUM(KNOT_RRTYPE_OPT); }
         | "APL"i        %{ TYPE_NUM(KNOT_RRTYPE_APL); }
         | "DS"i         %{ TYPE_NUM(KNOT_RRTYPE_DS); }
         | "SSHFP"i      %{ TYPE_NUM(KNOT_RRTYPE_SSHFP); }
@@ -1020,7 +1019,6 @@
         | "KX"i         %{ WINDOW_ADD_BIT(KNOT_RRTYPE_KX); }
         | "CERT"i       %{ WINDOW_ADD_BIT(KNOT_RRTYPE_CERT); }
         | "DNAME"i      %{ WINDOW_ADD_BIT(KNOT_RRTYPE_DNAME); }
-        | "OPT"i        %{ WINDOW_ADD_BIT(KNOT_RRTYPE_OPT); }
         | "APL"i        %{ WINDOW_ADD_BIT(KNOT_RRTYPE_APL); }
         | "DS"i         %{ WINDOW_ADD_BIT(KNOT_RRTYPE_DS); }
         | "SSHFP"i      %{ WINDOW_ADD_BIT(KNOT_RRTYPE_SSHFP); }
@@ -1093,14 +1091,14 @@
     action _fc_write {
         *rdata_tail = digit_to_num[(uint8_t)fc];
         rdata_tail++;
-        ADD_R_DATA_LABEL
     }
 
-    gateway = ( ('0' $_fc_write . sep . number8 . sep . '.')
-              | ('1' $_fc_write . sep . number8 . sep . ipv4_address)
-              | ('2' $_fc_write . sep . number8 . sep . ipv6_address)
-              | ('3' $_fc_write . sep . number8 . sep . r_dname)
-              );
+    gateway =
+        ( ('0' $_fc_write %_item_exit . sep . number8 . sep . '.')
+        | ('1' $_fc_write %_item_exit . sep . number8 . sep . ipv4_address)
+        | ('2' $_fc_write %_item_exit . sep . number8 . sep . ipv6_address)
+        | ('3' $_fc_write %_item_exit . sep . number8 . sep . r_dname)
+        );
     # END
 
     # BEGIN - Auxiliary functions which call smaller state machines
@@ -1360,7 +1358,6 @@
         | "KX"i                 %_data_
         | "CERT"i               %_data_
         | "DNAME"i              %_data_dname
-        | "OPT"i                %_data_
         | "APL"i                %_data_
         | "DS"i                 %_data_ds
         | "SSHFP"i              %_data_sshfp
-- 
GitLab