Commit | Line | Data |
---|---|---|
3e2e5fab | 1 | /* |
2 | * check.c | |
3 | * - consistency checks | |
4 | */ | |
5 | /* | |
ae8cc977 | 6 | * This file is part of adns, which is |
26e1c3d6 | 7 | * Copyright (C) 1997-2000,2003,2006,2014 Ian Jackson |
ae8cc977 | 8 | * Copyright (C) 1999-2000,2003,2006 Tony Finch |
9 | * Copyright (C) 1991 Massachusetts Institute of Technology | |
10 | * (See the file INSTALL for full details.) | |
3e2e5fab | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License as published by | |
7f8bbe29 | 14 | * the Free Software Foundation; either version 3, or (at your option) |
3e2e5fab | 15 | * any later version. |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
8c09a4c6 | 23 | * along with this program; if not, write to the Free Software Foundation. |
3e2e5fab | 24 | */ |
25 | ||
26 | #include "internal.h" | |
27 | ||
28de6442 | 28 | void adns_checkconsistency(adns_state ads, adns_query qu) { |
29 | adns__consistency(ads,qu,cc_user); | |
30 | } | |
3e2e5fab | 31 | |
609133ee | 32 | #define DLIST_CHECK(list, nodevar, part, body) \ |
33 | if ((list).head) { \ | |
34 | assert(! (list).head->part back); \ | |
35 | for ((nodevar)= (list).head; \ | |
36 | (nodevar); \ | |
37 | (nodevar)= (nodevar)->part next) { \ | |
38 | assert((nodevar)->part next \ | |
39 | ? (nodevar) == (nodevar)->part next->part back \ | |
40 | : (nodevar) == (list).tail); \ | |
41 | body \ | |
42 | } \ | |
3e2e5fab | 43 | } |
44 | ||
609133ee | 45 | #define DLIST_ASSERTON(node, nodevar, list, part) \ |
46 | do { \ | |
47 | for ((nodevar)= (list).head; \ | |
48 | (nodevar) != (node); \ | |
49 | (nodevar)= (nodevar)->part next) { \ | |
50 | assert((nodevar)); \ | |
51 | } \ | |
28de6442 | 52 | } while(0) |
53 | ||
3e2e5fab | 54 | static void checkc_query_alloc(adns_state ads, adns_query qu) { |
55 | allocnode *an; | |
56 | ||
57 | DLIST_CHECK(qu->allocations, an, , { | |
58 | }); | |
59 | } | |
60 | ||
61 | static void checkc_query(adns_state ads, adns_query qu) { | |
28de6442 | 62 | adns_query child; |
63 | ||
3e2e5fab | 64 | assert(qu->udpnextserver < ads->nservers); |
65 | assert(!(qu->udpsent & (~0UL << ads->nservers))); | |
3e2e5fab | 66 | assert(qu->search_pos <= ads->nsearchlist); |
28de6442 | 67 | if (qu->parent) DLIST_ASSERTON(qu, child, qu->parent->children, siblings.); |
3e2e5fab | 68 | } |
69 | ||
f7f83b4a | 70 | static void checkc_notcpbuf(adns_state ads) { |
71 | assert(!ads->tcpsend.used); | |
72 | assert(!ads->tcprecv.used); | |
73 | assert(!ads->tcprecv_skip); | |
74 | } | |
75 | ||
3e2e5fab | 76 | static void checkc_global(adns_state ads) { |
f930c455 | 77 | const struct sortlist *sl; |
3e2e5fab | 78 | int i; |
79 | ||
97a937c8 | 80 | assert(ads->udpsockets >= 0); |
3e2e5fab | 81 | |
f930c455 | 82 | for (i=0; i<ads->nsortlist; i++) { |
f930c455 | 83 | sl= &ads->sortlist[i]; |
82ae109e IJ |
84 | assert(adns__addr_matches(sl->base.sa.sa_family, |
85 | adns__sockaddr_addr(&sl->base.sa), | |
86 | &sl->base,&sl->mask)); | |
f930c455 | 87 | } |
3e2e5fab | 88 | |
89 | assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers); | |
90 | ||
91 | switch (ads->tcpstate) { | |
92 | case server_connecting: | |
93 | assert(ads->tcpsocket >= 0); | |
f7f83b4a | 94 | checkc_notcpbuf(ads); |
95 | break; | |
96 | case server_disconnected: | |
97 | case server_broken: | |
98 | assert(ads->tcpsocket == -1); | |
99 | checkc_notcpbuf(ads); | |
3e2e5fab | 100 | break; |
101 | case server_ok: | |
102 | assert(ads->tcpsocket >= 0); | |
70ad7a2a | 103 | assert(ads->tcprecv_skip <= ads->tcprecv.used); |
3e2e5fab | 104 | break; |
105 | default: | |
106 | assert(!"ads->tcpstate value"); | |
107 | } | |
108 | ||
109 | assert(ads->searchlist || !ads->nsearchlist); | |
110 | } | |
111 | ||
f7f83b4a | 112 | static void checkc_queue_udpw(adns_state ads) { |
3e2e5fab | 113 | adns_query qu; |
114 | ||
f7f83b4a | 115 | DLIST_CHECK(ads->udpw, qu, , { |
116 | assert(qu->state==query_tosend); | |
117 | assert(qu->retries <= UDPMAXRETRIES); | |
118 | assert(qu->udpsent); | |
3e2e5fab | 119 | assert(!qu->children.head && !qu->children.tail); |
120 | checkc_query(ads,qu); | |
121 | checkc_query_alloc(ads,qu); | |
122 | }); | |
123 | } | |
124 | ||
f7f83b4a | 125 | static void checkc_queue_tcpw(adns_state ads) { |
126 | adns_query qu; | |
127 | ||
128 | DLIST_CHECK(ads->tcpw, qu, , { | |
129 | assert(qu->state==query_tcpw); | |
130 | assert(!qu->children.head && !qu->children.tail); | |
131 | assert(qu->retries <= ads->nservers+1); | |
132 | checkc_query(ads,qu); | |
133 | checkc_query_alloc(ads,qu); | |
134 | }); | |
135 | } | |
136 | ||
3e2e5fab | 137 | static void checkc_queue_childw(adns_state ads) { |
138 | adns_query parent, child; | |
139 | ||
140 | DLIST_CHECK(ads->childw, parent, , { | |
f7f83b4a | 141 | assert(parent->state == query_childw); |
3e2e5fab | 142 | assert(parent->children.head); |
143 | DLIST_CHECK(parent->children, child, siblings., { | |
144 | assert(child->parent == parent); | |
145 | assert(child->state != query_done); | |
146 | }); | |
147 | checkc_query(ads,parent); | |
148 | checkc_query_alloc(ads,parent); | |
149 | }); | |
150 | } | |
151 | ||
b582ca0f IJ |
152 | static void checkc_query_done(adns_state ads, adns_query qu) { |
153 | assert(qu->state == query_done); | |
154 | assert(!qu->children.head && !qu->children.tail); | |
155 | checkc_query(ads,qu); | |
156 | } | |
157 | ||
3e2e5fab | 158 | static void checkc_queue_output(adns_state ads) { |
159 | adns_query qu; | |
160 | ||
161 | DLIST_CHECK(ads->output, qu, , { | |
3e2e5fab | 162 | assert(!qu->parent); |
bfc2c80e | 163 | assert(!qu->allocations.head && !qu->allocations.tail); |
b582ca0f IJ |
164 | checkc_query_done(ads,qu); |
165 | }); | |
166 | } | |
167 | ||
168 | static void checkc_queue_intdone(adns_state ads) { | |
169 | adns_query qu; | |
170 | ||
171 | DLIST_CHECK(ads->intdone, qu, , { | |
172 | assert(qu->parent); | |
173 | assert(qu->ctx.callback); | |
174 | checkc_query_done(ads,qu); | |
3e2e5fab | 175 | }); |
176 | } | |
177 | ||
28de6442 | 178 | void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc) { |
179 | adns_query search; | |
180 | ||
3e2e5fab | 181 | switch (cc) { |
182 | case cc_user: | |
183 | break; | |
184 | case cc_entex: | |
185 | if (!(ads->iflags & adns_if_checkc_entex)) return; | |
b582ca0f | 186 | assert(!ads->intdone.head); |
3e2e5fab | 187 | break; |
188 | case cc_freq: | |
189 | if ((ads->iflags & adns_if_checkc_freq) != adns_if_checkc_freq) return; | |
190 | break; | |
191 | default: | |
192 | abort(); | |
193 | } | |
194 | ||
195 | checkc_global(ads); | |
f7f83b4a | 196 | checkc_queue_udpw(ads); |
197 | checkc_queue_tcpw(ads); | |
3e2e5fab | 198 | checkc_queue_childw(ads); |
199 | checkc_queue_output(ads); | |
b582ca0f | 200 | checkc_queue_intdone(ads); |
28de6442 | 201 | |
202 | if (qu) { | |
203 | switch (qu->state) { | |
204 | case query_tosend: | |
f7f83b4a | 205 | DLIST_ASSERTON(qu, search, ads->udpw, ); |
206 | break; | |
207 | case query_tcpw: | |
208 | DLIST_ASSERTON(qu, search, ads->tcpw, ); | |
28de6442 | 209 | break; |
f7f83b4a | 210 | case query_childw: |
28de6442 | 211 | DLIST_ASSERTON(qu, search, ads->childw, ); |
212 | break; | |
213 | case query_done: | |
b582ca0f IJ |
214 | if (qu->parent) |
215 | DLIST_ASSERTON(qu, search, ads->intdone, ); | |
216 | else | |
217 | DLIST_ASSERTON(qu, search, ads->output, ); | |
28de6442 | 218 | break; |
219 | default: | |
220 | assert(!"specific query state"); | |
221 | } | |
222 | } | |
3e2e5fab | 223 | } |