]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/authtracker/authtracker_db.c
Added command to inspect authtracker contents.
[irc/quakenet/newserv.git] / chanserv / authtracker / authtracker_db.c
1 /* Keeps track of current "dangling" auths.
2 *
3 * Every entry here corresponds to a user who has an open session in the
4 * session table, but we cannot be sure that the user has actually gone.
5 * This means either (a) their server has split off or (b) we restarted and
6 * found a dangling entry in the session table.
7 *
8 * Entries leave when either (a) the user comes back (the entry is dropped),
9 * or (b) the server the user was on relinks without them, in which case we
10 * close off their session.
11 */
12
13 #include "authtracker.h"
14 #include "../chanserv.h"
15 #include "../../core/nsmalloc.h"
16 #include "../../server/server.h"
17 #include "../../irc/irc_config.h"
18
19 #include <time.h>
20
21 #define DANGLING_HASHSIZE 500
22 #define dangling_hash(x) ((x)%DANGLING_HASHSIZE)
23
24 #define ALLOCUNIT 100
25
26 struct dangling_entry {
27 unsigned int numeric;
28 unsigned long userid;
29 time_t authts;
30 time_t losttime;
31 int reason; /* AT_NETSPLIT or AT_RESTART */
32 struct dangling_entry *next;
33 };
34
35 struct dangling_server {
36 struct dangling_entry *de[DANGLING_HASHSIZE];
37 };
38
39 struct dangling_server *ds[MAXSERVERS];
40 struct dangling_entry *free_des;
41
42 static struct dangling_entry *get_de() {
43 struct dangling_entry *dep;
44 int i;
45
46 if (free_des == NULL) {
47 free_des = (struct dangling_entry *)nsmalloc(POOL_AUTHTRACKER, ALLOCUNIT * sizeof(struct dangling_entry));
48 for (i=0;i<(ALLOCUNIT-1);i++) {
49 free_des[i].next= &(free_des[i+1]);
50 }
51 free_des[ALLOCUNIT-1].next=NULL;
52 }
53
54 dep=free_des;
55 free_des=dep->next;
56
57 return dep;
58 }
59
60 static void free_de(struct dangling_entry *dep) {
61 dep->next=free_des;
62 free_des=dep;
63 }
64
65 void at_lostnick(unsigned int numeric, unsigned long userid, time_t accountts, time_t losttime, int reason) {
66 unsigned int server=homeserver(numeric);
67 unsigned int i;
68 struct dangling_entry *dep;
69 unsigned int thehash=dangling_hash(numeric);
70
71 /* If their server doesn't have an entry, make one. */
72 if (!ds[server]) {
73 ds[server]=nsmalloc(POOL_AUTHTRACKER, sizeof(struct dangling_server));
74 for (i=0;i<DANGLING_HASHSIZE;i++)
75 ds[server]->de[i]=NULL;
76 }
77
78 /* Now make an entry */
79 dep=get_de();
80 dep->numeric=numeric;
81 dep->userid=userid;
82 dep->authts=accountts;
83 dep->losttime=losttime;
84 dep->reason=reason;
85 dep->next=ds[server]->de[thehash];
86 ds[server]->de[thehash]=dep;
87 }
88
89 /* Removes a returning user from the "dangling" tables. Return 1 if we found it, 0 otherwise. */
90 int at_foundnick(unsigned int numeric, unsigned long userid, time_t accountts) {
91 unsigned int server=homeserver(numeric);
92 struct dangling_entry *dep, **deh;
93 unsigned int thehash=dangling_hash(numeric);
94
95 /* If we've not got an entry for their server we certainly won't for them. */
96 if (!ds[server])
97 return 0;
98
99 for (deh=&(ds[server]->de[thehash]); *deh; deh=&((*deh)->next)) {
100 dep=*deh;
101 if ((dep->numeric == numeric) && (dep->userid==userid) && (dep->authts==accountts)) {
102 /* Got it */
103 *deh=dep->next;
104 free_de(dep);
105 return 1;
106 }
107 }
108
109 /* Dropped through - didn't find it */
110 return 0;
111 }
112
113 /* When a server is back (fully linked), any remaining dangling users on that server are definately gone. */
114 void at_serverback(unsigned int server) {
115 int i;
116 struct dangling_entry *dep, *ndep;
117
118 if (!ds[server])
119 return;
120
121 for (i=0;i<DANGLING_HASHSIZE;i++) {
122 for (dep=ds[server]->de[i];dep;dep=ndep) {
123 ndep=dep->next;
124
125 at_logquit(dep->userid, dep->authts, time(NULL), (dep->reason==AT_NETSPLIT)? "(netsplit)" : "(restart)");
126 free_de(dep);
127 }
128 }
129
130 nsfree(POOL_AUTHTRACKER, ds[server]);
131 ds[server]=NULL;
132 }
133
134 void at_flushghosts() {
135 int i;
136
137 for (i=0;i<MAXSERVERS;i++) {
138 if (serverlist[i].linkstate == LS_LINKED)
139 at_serverback(i);
140 }
141 }
142
143 int at_dumpdb(void *source, int argc, char **argv) {
144 nick *np=source;
145 struct dangling_entry *dep;
146 unsigned int i,j,k;
147
148 for(i=0;i<MAXSERVERS;i++) {
149 if (ds[i]) {
150 k=0;
151 for(j=0;j<DANGLING_HASHSIZE;j++) {
152 for (dep=ds[i]->de[j];dep;dep=dep->next) {
153 k++;
154 }
155 }
156 chanservsendmessage(np, "Server %d (%s) has %d entries.",i,longtonumeric(i,2),k);
157 }
158 }
159
160 chanservstdmessage(np,QM_ENDOFLIST);
161
162 return CMD_OK;
163 }