]>
Commit | Line | Data |
---|---|---|
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 | |
18 | authname *freeauthnames; | |
19 | authname *authnametable[AUTHNAMEHASHSIZE]; | |
20 | ||
5a335041 CP |
21 | /* internal access only */ |
22 | static authname *authnametablebyname[AUTHNAMEHASHSIZE]; | |
23 | ||
04b12064 CP |
24 | static struct { |
25 | sstring *name; | |
26 | int persistant; | |
27 | } authnameexts[MAXAUTHNAMEEXTS]; | |
57583275 | 28 | |
d40ae845 CP |
29 | static void authextstats(int hooknum, void *arg); |
30 | ||
5a335041 | 31 | void _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 | 38 | void _fini(void) { |
d40ae845 | 39 | deregisterhook(HOOK_CORE_STATSREQUEST, &authextstats); |
57583275 | 40 | nsfreeall(POOL_AUTHEXT); |
41 | } | |
42 | ||
5a335041 | 43 | authname *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 | ||
61 | void freeauthname (authname *anp) { | |
62 | anp->next=freeauthnames; | |
63 | freeauthnames=anp; | |
64 | } | |
65 | ||
04b12064 | 66 | int 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 | ||
86 | int 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 | ||
98 | void 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 | ||
114 | authname *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 | 127 | authname *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 | ||
140 | authname *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 | ||
169 | void 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 | 205 | unsigned 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 | |
222 | authname *getauthbyname(const char *name) { | |
223 | authname *a = findauthnamebyname(name); | |
224 | if(!a || !a->nicks) | |
225 | return NULL; | |
226 | ||
227 | return a; | |
228 | } | |
229 | ||
cdc9e13c | 230 | static 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 |
253 | static authname *nextbynext(authname *in) { |
254 | return in->next; | |
255 | } | |
256 | ||
257 | static authname *nextbyname(authname *in) { | |
258 | return in->nextbyname; | |
259 | } | |
260 | ||
d40ae845 CP |
261 | static 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 |