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