]> jfr.im git - irc/quakenet/newserv.git/blame - authext/authext.c
Add MODULE_VERSION to all default modules.
[irc/quakenet/newserv.git] / authext / authext.c
CommitLineData
57583275 1#include "authext.h"
2#include "../core/nsmalloc.h"
3#include "../core/error.h"
4#include "../lib/sstring.h"
5#include "../lib/irc_string.h"
5a335041 6#include "../nick/nick.h"
d40ae845 7#include "../core/hooks.h"
1a96a370 8#include "../lib/strlfunc.h"
240bbd21 9#include "../lib/version.h"
57583275 10
11#include <string.h>
d40ae845 12#include <stdio.h>
57583275 13
240bbd21
CP
14MODULE_VERSION("")
15
57583275 16#define ALLOCUNIT 100
17
18#define authnamehash(x) ((x)%AUTHNAMEHASHSIZE)
5a335041 19#define authnamehashbyname(x) (crc32i(x)%AUTHNAMEHASHSIZE)
57583275 20
21authname *freeauthnames;
22authname *authnametable[AUTHNAMEHASHSIZE];
23
5a335041
CP
24/* internal access only */
25static authname *authnametablebyname[AUTHNAMEHASHSIZE];
26
04b12064
CP
27static struct {
28 sstring *name;
29 int persistant;
30} authnameexts[MAXAUTHNAMEEXTS];
57583275 31
d40ae845
CP
32static void authextstats(int hooknum, void *arg);
33
5a335041 34void _init(void) {
57583275 35 freeauthnames=NULL;
36 memset(authnametable,0,sizeof(authnametable));
5a335041 37 memset(authnametablebyname,0,sizeof(authnametablebyname));
d40ae845 38 registerhook(HOOK_CORE_STATSREQUEST, &authextstats);
57583275 39}
40
5a335041 41void _fini(void) {
d40ae845 42 deregisterhook(HOOK_CORE_STATSREQUEST, &authextstats);
57583275 43 nsfreeall(POOL_AUTHEXT);
44}
45
5a335041 46authname *newauthname(void) {
57583275 47 authname *anp;
48 int i;
49
50 if (freeauthnames==NULL) {
51 freeauthnames=(authname *)nsmalloc(POOL_AUTHEXT, ALLOCUNIT*sizeof(authname));
52 for (i=0;i<(ALLOCUNIT-1);i++) {
53 freeauthnames[i].next=&(freeauthnames[i+1]);
54 }
55 freeauthnames[ALLOCUNIT-1].next=NULL;
56 }
57
58 anp=freeauthnames;
59 freeauthnames=anp->next;
60
61 return anp;
62}
63
64void freeauthname (authname *anp) {
65 anp->next=freeauthnames;
66 freeauthnames=anp;
67}
68
04b12064 69int registerauthnameext(const char *name, int persistant) {
57583275 70 int i;
71
72 if (findauthnameext(name)!=-1) {
73 Error("nick",ERR_WARNING,"Tried to register duplicate authname extension %s",name);
74 return -1;
75 }
76
77 for (i=0;i<MAXAUTHNAMEEXTS;i++) {
04b12064
CP
78 if (authnameexts[i].name==NULL) {
79 authnameexts[i].name=getsstring(name,100);
80 authnameexts[i].persistant=persistant;
57583275 81 return i;
82 }
83 }
84
85 Error("nick",ERR_WARNING,"Tried to register too many authname extensions: %s",name);
86 return -1;
87}
88
89int findauthnameext(const char *name) {
90 int i;
91
92 for (i=0;i<MAXAUTHNAMEEXTS;i++) {
04b12064 93 if (authnameexts[i].name!=NULL && !ircd_strcmp(name,authnameexts[i].name->content)) {
57583275 94 return i;
95 }
96 }
97
98 return -1;
99}
100
101void releaseauthnameext(int index) {
102 int i;
103 authname *anp;
104
04b12064
CP
105 freesstring(authnameexts[index].name);
106 authnameexts[index].name=NULL;
57583275 107
108 for (i=0;i<AUTHNAMEHASHSIZE;i++) {
109 for (anp=authnametable[i];anp;anp=anp->next) {
110 anp->exts[index]=NULL;
111 }
112 }
5a335041
CP
113
114 /* the contents of authnametablebyname should be identical */
57583275 115}
116
117authname *findauthname(unsigned long userid) {
118 authname *anp;
119
120 if(!userid)
121 return NULL;
122
123 for (anp=authnametable[authnamehash(userid)];anp;anp=(authname *)anp->next)
124 if (userid==anp->userid)
125 return anp;
126
127 return NULL;
128}
129
5a335041 130authname *findauthnamebyname(const char *name) {
57583275 131 authname *anp;
57583275 132
5a335041
CP
133 if(!name)
134 return NULL;
135
d40ae845 136 for (anp=authnametablebyname[authnamehashbyname(name)];anp;anp=(authname *)anp->nextbyname)
1a96a370 137 if (!ircd_strcmp(anp->name, name))
5a335041
CP
138 return anp;
139
140 return NULL;
141}
142
143authname *findorcreateauthname(unsigned long userid, const char *name) {
144 authname *anp;
145 unsigned int thehash=authnamehash(userid), secondhash = authnamehashbyname(name);
146
147 if(!userid || !name)
57583275 148 return NULL;
149
150 for (anp=authnametable[thehash];anp;anp=(authname *)anp->next)
151 if (userid==anp->userid)
152 return anp;
153
154 anp=newauthname();
155 anp->userid=userid;
1a96a370 156 strlcpy(anp->name, name, sizeof(anp->name));
57583275 157 anp->usercount=0;
158 anp->marker=0;
0b0fb773 159 anp->flags=0;
57583275 160 anp->nicks=NULL;
161 memset(anp->exts, 0, MAXAUTHNAMEEXTS * sizeof(void *));
162 anp->next=(struct authname *)authnametable[thehash];
163 authnametable[thehash]=anp;
164
5a335041
CP
165 anp->namebucket=secondhash;
166 anp->nextbyname=(struct authname *)authnametablebyname[secondhash];
167 authnametablebyname[secondhash]=anp;
168
57583275 169 return anp;
170}
171
172void releaseauthname(authname *anp) {
173 authname **manp;
5a335041 174 int i, found;
57583275 175 if (anp->usercount==0) {
1cf62143
CP
176 anp->nicks = NULL;
177
57583275 178 for(i=0;i<MAXAUTHNAMEEXTS;i++)
04b12064 179 if(authnameexts[i].persistant && anp->exts[i]!=NULL)
57583275 180 return;
181
04b12064 182 triggerhook(HOOK_AUTH_LOSTAUTHNAME, (void *)anp);
5a335041 183 found = 0;
57583275 184 for(manp=&(authnametable[authnamehash(anp->userid)]);*manp;manp=(authname **)&((*manp)->next)) {
5a335041
CP
185 if ((*manp)==anp) {
186 (*manp)=(authname *)anp->next;
187 found = 1;
188 break;
189 }
190 }
191 if(!found) {
192 Error("nick",ERR_ERROR,"Unable to remove authname %lu from hashtable",anp->userid);
193 return;
194 }
195
4884107a 196 for(manp=&(authnametablebyname[anp->namebucket]);*manp;manp=(authname **)&((*manp)->nextbyname)) {
57583275 197 if ((*manp)==anp) {
4884107a 198 (*manp)=(authname *)anp->nextbyname;
57583275 199 freeauthname(anp);
200 return;
201 }
202 }
5a335041 203
4884107a 204 Error("nick",ERR_STOP,"Unable to remove authname %lu from byname hashtable, TABLES ARE INCONSISTENT -- DYING",anp->userid);
57583275 205 }
206}
207
5a335041 208unsigned int nextauthnamemarker(void) {
57583275 209 int i;
210 authname *anp;
211 static unsigned int authnamemarker=0;
212
213 authnamemarker++;
214 if (!authnamemarker) {
215 /* If we wrapped to zero, zap the marker on all records */
216 for (i=0;i<AUTHNAMEHASHSIZE;i++)
217 for (anp=authnametable[i];anp;anp=anp->next)
218 anp->marker=0;
219 authnamemarker++;
220 }
221
222 return authnamemarker;
223}
1cf62143
CP
224
225authname *getauthbyname(const char *name) {
226 authname *a = findauthnamebyname(name);
227 if(!a || !a->nicks)
228 return NULL;
229
230 return a;
231}
232
cdc9e13c 233static char *genstats(authname **hashtable, authname *(nextfn)(authname *)) {
d40ae845
CP
234 int i,curchain,maxchain=0,total=0,buckets=0;
235 authname *ap;
236 static char buf[100];
237
238 for (i=0;i<AUTHNAMEHASHSIZE;i++) {
239 if (hashtable[i]!=NULL) {
240 buckets++;
241 curchain=0;
cdc9e13c 242 for (ap=hashtable[i];ap;ap=nextfn(ap)) {
d40ae845
CP
243 total++;
244 curchain++;
245 }
246 if (curchain>maxchain) {
247 maxchain=curchain;
248 }
249 }
250 }
251
252 snprintf(buf, sizeof(buf), "%6d authexts (HASH: %6d/%6d, chain %3d)",total,buckets,AUTHNAMEHASHSIZE,maxchain);
253 return buf;
254}
255
cdc9e13c
CP
256static authname *nextbynext(authname *in) {
257 return in->next;
258}
259
260static authname *nextbyname(authname *in) {
261 return in->nextbyname;
262}
263
d40ae845
CP
264static void authextstats(int hooknum, void *arg) {
265 long level=(long)arg;
266 char buf[100];
267
268 if (level>5) {
269 /* Full stats */
cdc9e13c 270 snprintf(buf,sizeof(buf),"Authext : by id: %s", genstats(authnametable, nextbynext));
d40ae845
CP
271 triggerhook(HOOK_CORE_STATSREPLY,buf);
272
cdc9e13c 273 snprintf(buf,sizeof(buf),"Authext : by name: %s", genstats(authnametablebyname, nextbyname));
d40ae845
CP
274 triggerhook(HOOK_CORE_STATSREPLY,buf);
275 }
276}
277