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