]> jfr.im git - irc/quakenet/newserv.git/blob - trusts/trusts_commands.c
Fix up trustlist for lastseen/expires in.
[irc/quakenet/newserv.git] / trusts / trusts_commands.c
1 #include <stdio.h>
2 #include "../control/control.h"
3 #include "../lib/irc_string.h"
4 #include "trusts.h"
5
6 int trusts_migration_start(TrustDBMigrationCallback, void *);
7 void trusts_migration_stop(void);
8 static void registercommands(int, void *);
9 static void deregistercommands(int, void *);
10
11 static void migrate_status(int errcode, void *tag) {
12 long sender = (long)tag;
13 nick *np = getnickbynumeric(sender);
14
15 if(!np)
16 return;
17
18 if(!errcode || errcode == MIGRATION_LASTERROR) {
19 if(!errcode) {
20 controlreply(np, "Migration complete.");
21 controlreply(np, "Attempting to reload database. . .");
22 } else {
23 controlreply(np, "An error occured after the database was unloaded, attempting reload. . .");
24 }
25 if(trusts_loaddb()) {
26 controlreply(np, "Database reloaded successfully.");
27 } else {
28 controlreply(np, "An error occured, please reload the module manually.");
29 }
30 } else {
31 controlreply(np, "Error %d occured during migration, commands reregistered.", errcode);
32 registercommands(0, NULL);
33 }
34 }
35
36 static int trusts_cmdmigrate(void *source, int cargc, char **cargv) {
37 nick *sender = source;
38 int ret;
39
40 /* iffy but temporary */
41 ret = trusts_migration_start(migrate_status, (void *)(sender->numeric));
42 if(!ret) {
43 controlreply(sender, "Migration started, commands deregistered.");
44 deregistercommands(0, NULL);
45 } else {
46 controlreply(sender, "Error %d starting migration.", ret);
47 }
48
49 return CMD_OK;
50 }
51
52 static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) {
53 nick *sender = source;
54 trustgroup *tg;
55 trusthost *th;
56 time_t t;
57
58 if(cargc < 1)
59 return CMD_USAGE;
60
61 tg = tg_strtotg(cargv[0]);
62 if(!tg) {
63 controlreply(sender, "Couldn't find a trustgroup with that id.");
64 return CMD_ERROR;
65 }
66
67 t = time(NULL);
68
69 /* abusing the ternary operator a bit :( */
70 controlreply(sender, "Name: : %s", tg->name->content);
71 controlreply(sender, "Trusted for : %d", tg->trustedfor);
72 controlreply(sender, "Currently using : %d", tg->count);
73 controlreply(sender, "Clients per user : %d (%senforcing ident)", tg->maxperident, tg->mode?"":"not ");
74 controlreply(sender, "Contact: : %s", tg->contact->content);
75 controlreply(sender, "Expires in : %s", (tg->expires>t)?longtoduration(tg->expires - t, 2):"(the past -- BUG)");
76 controlreply(sender, "Last changed by : %s", tg->createdby->content);
77 controlreply(sender, "Comment: : %s", tg->comment->content);
78 controlreply(sender, "ID: : %u", tg->id);
79 controlreply(sender, "Last used : %s", (tg->count>0)?"(now)":((tg->lastseen>0)?trusts_timetostr(tg->lastseen):"(never)"));
80 controlreply(sender, "Max usage : %d", tg->maxusage);
81 controlreply(sender, "Last max reset : %s", tg->lastmaxuserreset?trusts_timetostr(tg->lastmaxuserreset):"(never)");
82
83 controlreply(sender, "Host Current Max Last seen");
84
85 for(th=tg->hosts;th;th=th->next)
86 controlreply(sender, " %-20s %-10d %-10d %s", trusts_cidr2str(th->ip, th->mask), th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"));
87
88 controlreply(sender, "End of list.");
89
90 return CMD_OK;
91 }
92
93 static int trusts_cmdtrustadd(void *source, int cargc, char **cargv) {
94 trustgroup *tg;
95 nick *sender = source;
96 char *host;
97 uint32_t ip, mask;
98 trusthost *th;
99
100 if(cargc < 2)
101 return CMD_USAGE;
102
103 tg = tg_strtotg(cargv[0]);
104 if(!tg) {
105 controlreply(sender, "Couldn't look up trustgroup.");
106 return CMD_ERROR;
107 }
108
109 host = cargv[1];
110 if(!trusts_str2cidr(host, &ip, &mask)) {
111 controlreply(sender, "Invalid host.");
112 return CMD_ERROR;
113 }
114
115 th = th_getbyhost(ip);
116 if(th) {
117 if(mask == th->mask) {
118 controlreply(sender, "This host already exists with the same mask.");
119 return CMD_ERROR;
120 }
121 if(mask > th->mask) {
122 /* this mask is a closer fit */
123
124 controlreply(sender, "Warning: this host will override another (%s), as it has smaller prefix (group: %s).", trusts_cidr2str(th->ip, th->mask), th->group->name->content);
125 controlreply(sender, "Adding anyway...");
126 }
127 } else {
128 th = th_getsupersetbyhost(ip, mask);
129 if(th) {
130 controlreply(sender, "Warning: this host is already covered by a smaller prefix (%s), which will remain part of that group: %s", trusts_cidr2str(th->ip, th->mask), th->group->name->content);
131 controlreply(sender, "Adding anyway...");
132 }
133 }
134
135 th = th_new(tg, host);
136 if(!th) {
137 controlreply(sender, "An error occured adding the host to the group.");
138 return CMD_ERROR;
139 }
140
141 controlreply(sender, "Host added.");
142 /* TODO: controlwall */
143
144 return CMD_OK;
145 }
146
147 static int trusts_cmdtrustgroupadd(void *source, int cargc, char **cargv) {
148 nick *sender = source;
149 char *name, *contact, *comment, createdby[ACCOUNTLEN + 2];
150 unsigned int howmany, maxperident, enforceident;
151 time_t howlong;
152 trustgroup *tg;
153
154 if(cargc < 6)
155 return CMD_USAGE;
156
157 name = cargv[0];
158 howmany = strtoul(cargv[1], NULL, 10);
159 if(!howmany || (howmany > 50000)) {
160 controlreply(sender, "Bad value maximum number of clients.");
161 return CMD_ERROR;
162 }
163
164 howlong = durationtolong(cargv[2]);
165 if((howlong <= 0) || (howlong > 365 * 86400 * 20)) {
166 controlreply(sender, "Invalid duration supplied.");
167 return CMD_ERROR;
168 }
169
170 maxperident = strtoul(cargv[3], NULL, 10);
171 if(!howmany || (maxperident > 1000)) {
172 controlreply(sender, "Bad value for max per ident.");
173 return CMD_ERROR;
174 }
175
176 if(cargv[4][0] != '1' && cargv[4][0] != '0') {
177 controlreply(sender, "Bad value for enforce ident (use 0 or 1).");
178 return CMD_ERROR;
179 }
180 enforceident = cargv[4][0] == '1';
181
182 contact = cargv[5];
183
184 if(cargc < 7) {
185 comment = "(no comment)";
186 } else {
187 comment = cargv[6];
188 }
189
190 /* don't allow #id or id forms */
191 if((name[0] == '#') || strtoul(name, NULL, 10)) {
192 controlreply(sender, "Invalid trustgroup name.");
193 return CMD_ERROR;
194 }
195
196 tg = tg_strtotg(name);
197 if(tg) {
198 controlreply(sender, "A group with that name already exists");
199 return CMD_ERROR;
200 }
201
202 snprintf(createdby, sizeof(createdby), "#%s", sender->authname);
203
204 tg = tg_new(name, howmany, enforceident, maxperident, howlong + time(NULL), createdby, contact, comment);
205 if(!tg) {
206 controlreply(sender, "An error occured adding the trustgroup.");
207 return CMD_ERROR;
208 }
209
210 controlreply(sender, "Group added.");
211 /* TODO: controlwall */
212
213 return CMD_OK;
214 }
215
216 static int commandsregistered;
217
218 static void registercommands(int hooknum, void *arg) {
219 if(commandsregistered)
220 return;
221 commandsregistered = 1;
222
223 registercontrolhelpcmd("trustmigrate", NO_DEVELOPER, 0, trusts_cmdmigrate, "Usage: trustmigrate\nCopies trust data from O and reloads the database.");
224 registercontrolhelpcmd("trustlist", NO_OPER, 1, trusts_cmdtrustlist, "Usage: trustlist <#id|name|id>\nShows trust data for the specified trust group.");
225 registercontrolhelpcmd("trustgroupadd", NO_OPER, 6, trusts_cmdtrustgroupadd, "Usage: trustgroupadd <name> <howmany> <howlong> <maxperident> <enforceident> <contact> ?comment?");
226 registercontrolhelpcmd("trustadd", NO_OPER, 2, trusts_cmdtrustadd, "Usage: trustadd <#id|name|id> <host>");
227 }
228
229 static void deregistercommands(int hooknum, void *arg) {
230 if(!commandsregistered)
231 return;
232 commandsregistered = 0;
233
234 deregistercontrolcmd("trustmigrate", trusts_cmdmigrate);
235 deregistercontrolcmd("trustlist", trusts_cmdtrustlist);
236 deregistercontrolcmd("trustgroupadd", trusts_cmdtrustgroupadd);
237 deregistercontrolcmd("trustadd", trusts_cmdtrustadd);
238 }
239
240 void _init(void) {
241 registerhook(HOOK_TRUSTS_DB_LOADED, registercommands);
242 registerhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands);
243
244 if(trustsdbloaded)
245 registercommands(0, NULL);
246 }
247
248 void _fini(void) {
249 deregisterhook(HOOK_TRUSTS_DB_LOADED, registercommands);
250 deregisterhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands);
251
252 trusts_migration_stop();
253
254 deregistercommands(0, NULL);
255 }