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