]> jfr.im git - irc/quakenet/newserv.git/blob - trusts/migration.c
Merge.
[irc/quakenet/newserv.git] / trusts / migration.c
1 #include "../nterfacer/nterfacer.h"
2 #include "../lib/strlfunc.h"
3 #include "../core/nsmalloc.h"
4 #include "trusts.h"
5 #include <stdio.h>
6 #include <string.h>
7
8 #define Stringify(x) __Stringify(x)
9 #define __Stringify(x) #x
10
11 static void tm_trustdump(trustmigration *tm);
12
13 static void tm_fini(trustmigration *tm, int errcode) {
14 tm->fini(tm->tag, errcode);
15
16 if(tm->schedule) {
17 nterfacer_freeline(tm->schedule);
18 tm->schedule = NULL;
19 }
20
21 nsfree(POOL_TRUSTS, tm);
22 }
23
24 void migration_stop(trustmigration *tm) {
25 tm_fini(tm, MIGRATION_STOPPED);
26 }
27
28 static int tm_parsegroup(trustmigration *tm, unsigned int id, const char *oline) {
29 char *line, *createdby, *contact, *comment, *name;
30 unsigned int trustedfor, maxperident, mode, maxusage;
31 unsigned long expires, lastseen, lastmaxusereset;
32 char xbuf[1024];
33 int pos;
34
35 /* ticket35153,14,20,1,1,17,1879854575,1222639249,0,nterfacer,Qwhois&2120764,Non-Commercial Bouncer (Created by: doomie)
36 name ,current
37 ,trustedfor
38 ,mode
39 ,maxperident
40 ,maxusage
41 ,expires ,lastseen ,lastmaxusereset
42 ,createdby,contact ,comment
43 */
44 int r;
45
46 strlcpy(xbuf, oline, sizeof(xbuf));
47 name = xbuf;
48
49 line = strchr(name, ',');
50 if(!line)
51 return 1;
52 *line++ = '\0';
53
54 r = sscanf(line, "%*u,%u,%u,%u,%u,%lu,%lu,%lu,%n",
55 /*current, */ &trustedfor, &mode, &maxperident,
56 &maxusage, &expires, &lastseen, &lastmaxusereset, &pos);
57 if(r != 7)
58 return 2;
59
60 createdby = &line[pos];
61 contact = strchr(createdby, ',');
62 if(!contact)
63 return 3;
64 *contact++ = '\0';
65
66 comment = strchr(contact, ',');
67 if(!comment)
68 return 4;
69 *comment++ = '\0';
70
71 tm->group(tm->tag, id, name, trustedfor, mode, maxperident, maxusage, (time_t)expires, (time_t)lastseen, (time_t)lastmaxusereset, createdby, contact, comment);
72 return 0;
73 }
74
75 static int tm_parsehost(trustmigration *tm, unsigned int id, char *line) {
76 unsigned int max;
77 unsigned long lastseen;
78 char *ip, xbuf[1024];
79
80 /* 213.230.192.128/26,20,23,1222732944
81 ip ,cur,max,lastseen */
82
83 strlcpy(xbuf, line, sizeof(xbuf));
84 ip = line = xbuf;
85
86 line = strchr(line, ',');
87 if(!line)
88 return 5;
89 *line++ = '\0';
90
91 if(sscanf(line, "%*u,%u,%lu", /*current, */&max, &lastseen) != 2)
92 return 6;
93
94 tm->host(tm->tag, id, ip, max, lastseen);
95 return 0;
96 }
97
98 static void tm_stage2(int failure, int linec, char **linev, void *tag) {
99 trustmigration *tm = tag;
100 char *finishline;
101 unsigned int groupcount, totallines, i, dummy;
102
103 #ifdef TRUSTS_MIGRATION_DEBUG
104 Error("trusts", ERR_INFO, "Migration total lines: %d", linec);
105
106 for(i=0;i<linec;i++)
107 Error("trusts", ERR_INFO, "Migration line %d: |%s|", i, linev[i]);
108 #endif
109
110 tm->schedule = NULL;
111 if(failure || (linec < 1)) {
112 tm_fini(tm, 7);
113 return;
114 }
115
116 finishline = linev[linec - 1];
117 if(sscanf(finishline, "Start ID cannot exceed current maximum group ID (#%u).", &dummy) == 1) {
118 /* the list was truncated while we were reading it, we're done! */
119 tm_fini(tm, 0);
120 return;
121 }
122
123 if(sscanf(finishline, "End of list, %u groups and %u lines returned.", &groupcount, &totallines) != 2) {
124 tm_fini(tm, 8);
125 return;
126 }
127
128 if(totallines != linec - 1) {
129 tm_fini(tm, 9);
130 return;
131 }
132
133 for(i=0;i<linec-1;i++) {
134 char *linestart = &linev[i][2], type = linev[i][0];
135 if(type == 'G' || type == 'H') {
136 char *realline;
137 unsigned int id;
138 int pos, ret;
139
140 if(sscanf(linestart, "#%u,%n", &id, &pos) != 1) {
141 tm_fini(tm, 10);
142 return;
143 }
144
145 if(id > tm->cur) {
146 /* this one is missing and we've received a later one instead, update tm->cur to point to this one */
147 tm->cur = id;
148 } else if(id < tm->cur) {
149 tm_fini(tm, 11);
150 return;
151 }
152
153 realline = &linestart[pos];
154 if(type == 'G') {
155 ret = tm_parsegroup(tm, id, realline);
156 } else {
157 ret = tm_parsehost(tm, id, realline);
158 }
159 if(ret) {
160 tm_fini(tm, ret);
161 return;
162 }
163 } else {
164 tm_fini(tm, 11);
165 return;
166 }
167 }
168
169 tm_trustdump(tm);
170 }
171
172 static void tm_trustdump(trustmigration *tm) {
173 char buf[100];
174
175 if(tm->cur >= tm->count) {
176 tm_fini(tm, 0);
177 return;
178 }
179
180 tm->cur++;
181
182 snprintf(buf, sizeof(buf), "trustdump #%d 1", tm->cur);
183 tm->schedule = nterfacer_sendline("R", "relay", 4, (char *[]){"2", "^(Start ID cannot exceed current maximum group ID \\(#\\d+\\)|End of list, 1 groups and \\d+ lines returned\\.)$", "O", buf}, tm_stage2, tm);
184 }
185
186 static void tm_stage1(int failure, int linec, char **linev, void *tag) {
187 int count;
188 trustmigration *tm = tag;
189
190 tm->schedule = NULL;
191
192 if(failure || (linec != 1)) {
193 tm_fini(tm, 12);
194 return;
195 }
196
197 if(sscanf(linev[0], "Start ID cannot exceed current maximum group ID (#%u).", &count) != 1) {
198 tm_fini(tm, 13);
199 return;
200 }
201
202 Error("trusts", ERR_INFO, "Migration in progress, total groups: %d", count);
203
204 tm->count = count;
205
206 tm_trustdump(tm);
207 }
208
209 trustmigration *migration_start(TrustMigrationGroup group, TrustMigrationHost host, TrustMigrationFini fini, void *tag) {
210 trustmigration *tm = nsmalloc(POOL_TRUSTS, sizeof(trustmigration));
211 if(!tm)
212 return NULL;
213
214 tm->group = group;
215 tm->host = host;
216 tm->fini = fini;
217 tm->count = 0;
218 tm->cur = 0;
219 tm->tag = tag;
220
221 tm->schedule = nterfacer_sendline("R", "relay", 4, (char *[]){"1", "1", "O", "trustdump #9999999 1"}, tm_stage1, tm);
222 return tm;
223 }