]> jfr.im git - irc/quakenet/newserv.git/blob - fsck/fsck.c
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / fsck / fsck.c
1 /* fsck.c - check some internal structures */
2
3 #include "../control/control.h"
4 #include "../nick/nick.h"
5 #include "../channel/channel.h"
6 #include "../server/server.h"
7 #include "../lib/version.h"
8
9 MODULE_VERSION("")
10
11 int dofsck(void *source, int cargc, char **cargv);
12
13 void _init() {
14 registercontrolhelpcmd("fsck",NO_DEVELOPER,0,dofsck, "Usage: fsck\nRuns internal structure check.");
15 }
16
17 void _fini() {
18 deregistercontrolcmd("fsck",dofsck);
19 }
20
21 int dofsck(void *source, int cargc, char **cargv) {
22 int i,j;
23 nick *sender=source, *np, *np2;
24 host *hp;
25 realname *rnp;
26 unsigned int nickmarker;
27 int errors=0;
28 unsigned int nummask,mnum;
29
30 /* Start off with strict nick consistency checks.. */
31
32 controlreply(sender,"- Performing nickname checks");
33
34 nickmarker=nextnickmarker();
35
36 for(i=0;i<HOSTHASHSIZE;i++)
37 for(hp=hosttable[i];hp;hp=hp->next)
38 hp->marker=0;
39
40 for(i=0;i<REALNAMEHASHSIZE;i++)
41 for(rnp=realnametable[i];rnp;rnp=rnp->next)
42 rnp->marker=0;
43
44 controlreply(sender," - Scanning nick hash table");
45
46 for (i=0;i<NICKHASHSIZE;i++) {
47 for(np=nicktable[i];np;np=np->next) {
48 if (np->marker==nickmarker) {
49 controlreply(sender, "ERROR: bumped into the same nick %s/%s twice in hash table.",longtonumeric(np->numeric,5),np->nick);
50 errors++;
51 }
52
53 /* Mark this nick so we can check we found them all */
54 np->marker=nickmarker;
55
56 /* Check that we can find this nick with the lookup functions */
57 if (getnickbynick(np->nick) != np) {
58 controlreply(sender, "ERROR: can't find %s/%s using getnickbynick().",
59 longtonumeric(np->numeric,5),np->nick);
60 errors++;
61 }
62
63 if (getnickbynumeric(np->numeric) != np) {
64 controlreply(sender, "ERROR: can't find %s/%s using getnickbynumeric().",
65 longtonumeric(np->numeric,5),np->nick);
66 errors++;
67 }
68
69 /* Check that the nick appears in the list of nicks using its host */
70 if (findhost(np->host->name->content) != np->host) {
71 controlreply(sender, "ERROR: can't find %s/%s's host (%s) using findhost().",
72 longtonumeric(np->numeric,5),np->nick,np->host->name->content);
73 errors++;
74 }
75
76 for(np2=np->host->nicks;np2;np2=np2->nextbyhost)
77 if (np2==np)
78 break;
79
80 if (!np2) {
81 controlreply(sender, "ERROR: can't find %s/%s (host=%s) on the host users list.",
82 longtonumeric(np->numeric,5),np->nick,np->host->name->content);
83 errors++;
84 }
85
86 np->host->marker++;
87
88 /* Same for realnames */
89 if (findrealname(np->realname->name->content) != np->realname) {
90 controlreply(sender, "ERROR: can't find %s/%s's realname (%s) using findrealname().",
91 longtonumeric(np->numeric,5),np->nick,np->realname->name->content);
92 errors++;
93 }
94
95 for(np2=np->realname->nicks;np2;np2=np2->nextbyrealname)
96 if (np2==np)
97 break;
98
99 if (!np2) {
100 controlreply(sender,
101 "ERROR: can't find %s/%s (realname=%s) on the realname users list.",
102 longtonumeric(np->numeric,5),np->nick,np->realname->name->content);
103 errors++;
104 }
105
106 np->realname->marker++;
107
108 if (IsAccount(np) && !np->authname[0]) {
109 controlreply(sender, "ERROR: nick %s/%s is +r but no authname stored.",
110 longtonumeric(np->numeric,5),np->nick);
111 errors++;
112 }
113
114 /*
115 if (!IsAccount(np) && np->authname[0]) {
116 controlreply(sender, "ERROR: nick %s/%s is -r but carries authname '%s'.",
117 longtonumeric(np->numeric,5),np->nick,np->authname);
118 errors++;
119 }
120 */
121
122 if (IsSetHost(np) && (!np->sethost || !np->shident)) {
123 controlreply(sender, "ERROR: nick %s/%s is +h but nick or hostname not set.",
124 longtonumeric(np->numeric,5),np->nick);
125 errors++;
126 }
127
128 if (!IsSetHost(np) && (np->sethost || np->shident)) {
129 controlreply(sender, "ERROR: nick %s/%s is -h but has nick or hostname set.",
130 longtonumeric(np->numeric,5),np->nick);
131 errors++;
132 }
133
134 }
135 }
136
137 controlreply(sender," - Scanning server user tables");
138
139 for(i=0;i<MAXSERVERS;i++) {
140 if (serverlist[i].linkstate != LS_INVALID) {
141 nummask=((MAXSERVERS-1)<<18) | serverlist[i].maxusernum;
142 for (j=0;j<=serverlist[i].maxusernum;j++) {
143 if ((np=servernicks[i][j])) {
144 mnum=(i<<18) | j;
145 if ((np->numeric & nummask) != mnum) {
146 controlreply(sender, "ERROR: nick %s/%s has wrong masked numeric.",longtonumeric(np->numeric,5),np->nick);
147 errors++;
148 }
149 if (np->marker != nickmarker) {
150 controlreply(sender, "ERROR: nick %s/%s in server user table but not hash!",
151 longtonumeric(np->numeric,5),np->nick);
152 errors++;
153 }
154 np->marker=0;
155 }
156 }
157 }
158 }
159
160 controlreply(sender," - Scanning host and realname tables");
161
162 for (i=0;i<HOSTHASHSIZE;i++) {
163 for (hp=hosttable[i];hp;hp=hp->next) {
164
165 /* Check that the user counts match up */
166 if (hp->clonecount != hp->marker) {
167 controlreply(sender,
168 "ERROR: host %s has inconsistent clone count (stored=%d, measured=%u)",
169 hp->name->content,hp->clonecount,hp->marker);
170 errors++;
171 }
172
173 for (np=hp->nicks;np;np=np->nextbyhost) {
174 if (np->host != hp) {
175 controlreply(sender,
176 "ERROR: nick %s/%s is in list for wrong host "
177 "(in list for %s, actual host %s).",
178 longtonumeric(np->numeric,5),np->nick,hp->name->content,
179 np->host->name->content);
180 errors++;
181 }
182 }
183
184 hp->marker=0;
185 }
186 }
187
188 for (i=0;i<REALNAMEHASHSIZE;i++) {
189 for (rnp=realnametable[i];rnp;rnp=rnp->next) {
190 if (rnp->usercount != rnp->marker) {
191 controlreply(sender,
192 "ERROR: realname '%s' has inconsistent clone count "
193 "(stored=%d, measured=%d).",
194 rnp->name->content,rnp->usercount,rnp->marker);
195 errors++;
196 }
197
198 for (np=rnp->nicks;np;np=np->nextbyrealname) {
199 if (np->realname != rnp) {
200 controlreply(sender,
201 "ERROR: nick %s/%s is in list for wrong realname "
202 "(in list for '%s', actual realname '%s').",
203 longtonumeric(np->numeric,5),np->nick,
204 rnp->name->content, np->realname->name->content);
205 errors++;
206 }
207 }
208
209 rnp->marker=0;
210 }
211 }
212
213 if (errors)
214 controlreply(sender,"All checks complete. %d errors found.",errors);
215 else
216 controlreply(sender,"All checks complete. No errors found.");
217
218 return CMD_OK;
219 }
220