1 /*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <https://www.gnu.org/licenses/>.
15  */
16 
17 #include <inttypes.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <time.h>
21 
22 #include "libzscanner/scanner.h"
23 #include "libzscanner/functions.c"
24 #include "libzscanner/processing.h"
25 #include "libknot/descriptor.c"
26 
27 const char *separator = "------\n";
28 
print_wire_dname(const uint8_t * dname,uint32_t dname_length)29 static void print_wire_dname(const uint8_t *dname, uint32_t dname_length)
30 {
31 	uint32_t label_length = 0, i = 0;
32 
33 	for (i = 0; i < dname_length; i++) {
34 		if (label_length == 0) {
35 			label_length = dname[i];
36 			printf("(%u)", label_length);
37 			continue;
38 		}
39 		printf("%c", (char)dname[i]);
40 		label_length--;
41 	}
42 }
43 
debug_process_error(zs_scanner_t * s)44 void debug_process_error(zs_scanner_t *s)
45 {
46 	if (s->error.fatal) {
47 		printf("LINE(%03"PRIu64") ERROR(%s) FILE(%s) NEAR(%s)\n",
48 		       s->line_counter,
49 		       zs_strerror(s->error.code),
50 		       s->file.name,
51 		       s->buffer);
52 	} else {
53 		printf("LINE(%03"PRIu64") WARNING(%s) FILE(%s) NEAR(%s)\n",
54 		       s->line_counter,
55 		       zs_strerror(s->error.code),
56 		       s->file.name,
57 		       s->buffer);
58 	}
59 	fflush(stdout);
60 }
61 
debug_process_record(zs_scanner_t * s)62 void debug_process_record(zs_scanner_t *s)
63 {
64 	uint32_t i;
65 
66 	char rclass[32];
67 	char rtype[32];
68 
69 	if (knot_rrclass_to_string(s->r_class, rclass, sizeof(rclass)) > 0 &&
70 	    knot_rrtype_to_string(s->r_type, rtype, sizeof(rtype)) > 0) {
71 		printf("LINE(%03"PRIu64") %s %6u %*s ",
72 		       s->line_counter, rclass, s->r_ttl, 5, rtype);
73 	} else {
74 		printf("LINE(%03"PRIu64") %u %6u %*u ",
75 		       s->line_counter, s->r_class, s->r_ttl, 5, s->r_type);
76 	}
77 
78 	print_wire_dname(s->r_owner, s->r_owner_length);
79 
80 	printf(" \\# %u ", s->r_data_length);
81 
82 	int block = *((int *)(s->process.data));
83 	for (i = 0; i < s->r_data_length; i++) {
84 		if (block > 0 && i > 0 && (i % block) == 0) {
85 			printf(" ");
86 		}
87 		printf("%02X", (s->r_data)[i]);
88 	}
89 	printf("\n");
90 	fflush(stdout);
91 }
92 
debug_process_comment(zs_scanner_t * s)93 void debug_process_comment(zs_scanner_t *s)
94 {
95 	printf("LINE(%03"PRIu64") COMMENT(%.*s)\n", s->line_counter,
96 	       (int)s->buffer_length, s->buffer);
97 	fflush(stdout);
98 }
99 
test_process_error(zs_scanner_t * s)100 void test_process_error(zs_scanner_t *s)
101 {
102 	if (s->error.fatal) {
103 		printf("ERROR=%s\n%s", zs_errorname(s->error.code), separator);
104 	} else {
105 		printf("WARNG=%s\n%s", zs_errorname(s->error.code), separator);
106 	}
107 	fflush(stdout);
108 }
109 
test_process_record(zs_scanner_t * s)110 void test_process_record(zs_scanner_t *s)
111 {
112 	uint32_t i;
113 
114 	printf("OWNER=");
115 	for (i = 0; i < s->r_owner_length; i++) {
116 		printf("%02X", s->r_owner[i]);
117 	}
118 	printf("\n");
119 	printf("CLASS=%04X\n", s->r_class);
120 	printf("RRTTL=%08X\n", s->r_ttl);
121 	printf("RTYPE=%04X\n", s->r_type);
122 	printf("RDATA=");
123 	for (i = 0; i < s->r_data_length; i++) {
124 		printf("%02X", (s->r_data)[i]);
125 	}
126 	printf("\n%s", separator);
127 	fflush(stdout);
128 }
129 
test_date_to_timestamp(void)130 int test_date_to_timestamp(void)
131 {
132 	time_t    ref_timestamp, max_timestamp;
133 	uint32_t  test_timestamp;
134 	uint8_t   buffer[16];
135 	uint64_t  val1, val2; // For time_t type unification.
136 	struct tm tm;
137 
138 	// Set UTC for strftime.
139 	putenv("TZ=UTC");
140 	tzset();
141 
142 	// Get maximal allowed timestamp.
143 	strptime("21051231235959", "%Y%m%d%H%M%S", &tm);
144 	max_timestamp = mktime(&tm);
145 
146 	// Testing loop over whole input interval.
147 	for (ref_timestamp = 0;
148 	     ref_timestamp < max_timestamp;
149 	     ref_timestamp += 1) {
150 		struct tm result;
151 		// Get reference (correct) timestamp.
152 		strftime((char*)buffer, sizeof(buffer), "%Y%m%d%H%M%S",
153 			 gmtime_r(&ref_timestamp, &result));
154 
155 		// Get testing timestamp.
156 		test_timestamp = 0U; // prevents Wunitialized
157 		date_to_timestamp(buffer, &test_timestamp);
158 
159 		// Some continuous loging.
160 		if (ref_timestamp % 10000000 == 0) {
161 			val1 = ref_timestamp;
162 			printf("%s = %"PRIu64"\n", buffer, val1);
163 		}
164 
165 		// Comparing results.
166 		if (ref_timestamp != test_timestamp) {
167 			val1 = ref_timestamp;
168 
169 			if (ref_timestamp > test_timestamp) {
170 				val2 = ref_timestamp - test_timestamp;
171 				printf("%s = %"PRIu64", in - out = %"PRIu64"\n",
172 				       buffer, val1, val2);
173 			} else {
174 				val2 = test_timestamp - ref_timestamp;
175 				printf("%s = %"PRIu64", out - in = %"PRIu64"\n",
176 				       buffer, val1, val2);
177 			}
178 
179 			return -1;
180 		}
181 	}
182 
183 	return 0;
184 }
185