]>
Commit | Line | Data |
---|---|---|
84563ebd | 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" | |
2aaa684c | 14 | #include "../chanserv.h" |
84563ebd | 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 | } | |
2aaa684c | 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 | } |