]> jfr.im git - irc/quakenet/newserv.git/blob - trusts/trusts_commands.c
Merge.
[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 static void registercommands(int, void *);
7 static void deregistercommands(int, void *);
8
9 static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) {
10 nick *sender = source;
11 trustgroup *tg;
12 trusthost *th;
13 time_t t;
14
15 if(cargc < 1)
16 return CMD_USAGE;
17
18 tg = tg_strtotg(cargv[0]);
19 if(!tg) {
20 controlreply(sender, "Couldn't find a trustgroup with that id.");
21 return CMD_ERROR;
22 }
23
24 t = time(NULL);
25
26 /* abusing the ternary operator a bit :( */
27 controlreply(sender, "Name: : %s", tg->name->content);
28 controlreply(sender, "Trusted for : %d", tg->trustedfor);
29 controlreply(sender, "Currently using : %d", tg->count);
30 controlreply(sender, "Clients per user : %d (%senforcing ident)", tg->maxperident, tg->mode?"":"not ");
31 controlreply(sender, "Contact: : %s", tg->contact->content);
32 controlreply(sender, "Expires in : %s", (tg->expires>t)?longtoduration(tg->expires - t, 2):"(the past -- BUG)");
33 controlreply(sender, "Last changed by : %s", tg->createdby->content);
34 controlreply(sender, "Comment: : %s", tg->comment->content);
35 controlreply(sender, "ID: : %u", tg->id);
36 controlreply(sender, "Last used : %s", (tg->count>0)?"(now)":((tg->lastseen>0)?trusts_timetostr(tg->lastseen):"(never)"));
37 controlreply(sender, "Max usage : %d", tg->maxusage);
38 controlreply(sender, "Last max reset : %s", tg->lastmaxuserreset?trusts_timetostr(tg->lastmaxuserreset):"(never)");
39
40 controlreply(sender, "Host Current Max Last seen");
41
42 for(th=tg->hosts;th;th=th->next)
43 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)"));
44
45 controlreply(sender, "End of list.");
46
47 return CMD_OK;
48 }
49
50 static int trusts_cmdtrustadd(void *source, int cargc, char **cargv) {
51 trustgroup *tg;
52 nick *sender = source;
53 char *host;
54 uint32_t ip, mask;
55 trusthost *th, *superset, *subset;
56
57 if(cargc < 2)
58 return CMD_USAGE;
59
60 tg = tg_strtotg(cargv[0]);
61 if(!tg) {
62 controlreply(sender, "Couldn't look up trustgroup.");
63 return CMD_ERROR;
64 }
65
66 host = cargv[1];
67 if(!trusts_str2cidr(host, &ip, &mask)) {
68 controlreply(sender, "Invalid host.");
69 return CMD_ERROR;
70 }
71
72 /* OKAY! Lots of checking here!
73 *
74 * Need to check:
75 * - host isn't already covered by given group (reject if it is)
76 * - host doesn't already exist exactly already (reject if it does)
77 * - host is more specific than an existing one (warn if it is, fix up later)
78 * - host is less specific than an existing one (warn if it is, don't need to do anything special)
79 */
80
81 for(th=tg->hosts;th;th=th->next) {
82 if(th->ip == (ip & th->mask)) {
83 controlreply(sender, "This host (or part of it) is already covered in the given group.");
84 return CMD_ERROR;
85 }
86 }
87
88 if(th_getbyhostandmask(ip, mask)) {
89 controlreply(sender, "This host already exists in another group with the same mask.");
90 return CMD_ERROR;
91 }
92
93 /* this function will set both to NULL if it's equal, hence the check above */
94 th_getsuperandsubsets(ip, mask, &superset, &subset);
95 if(superset) {
96 /* a superset exists for us, we will be more specific than one existing host */
97
98 controlreply(sender, "Warning: this host already exists in another group, but this new host will override it as it has a smaller prefix.");
99 }
100 if(subset) {
101 /* a subset of us exists, we will be less specific than some existing hosts */
102
103 controlreply(sender, "Warning: this host already exists in at least one other group, the new host has a larger prefix and therefore will not override those hosts.");
104 }
105 if(superset || subset)
106 controlreply(sender, "Adding anyway...");
107
108 th = th_new(tg, host);
109 if(!th) {
110 controlreply(sender, "An error occured adding the host to the group.");
111 return CMD_ERROR;
112 }
113
114 controlreply(sender, "Host added.");
115 /* TODO: controlwall */
116
117 return CMD_OK;
118 }
119
120 static int trusts_cmdtrustgroupadd(void *source, int cargc, char **cargv) {
121 nick *sender = source;
122 char *name, *contact, *comment, createdby[ACCOUNTLEN + 2];
123 unsigned int howmany, maxperident, enforceident;
124 time_t howlong;
125 trustgroup *tg;
126
127 if(cargc < 6)
128 return CMD_USAGE;
129
130 name = cargv[0];
131 howmany = strtoul(cargv[1], NULL, 10);
132 if(!howmany || (howmany > 50000)) {
133 controlreply(sender, "Bad value maximum number of clients.");
134 return CMD_ERROR;
135 }
136
137 howlong = durationtolong(cargv[2]);
138 if((howlong <= 0) || (howlong > 365 * 86400 * 20)) {
139 controlreply(sender, "Invalid duration supplied.");
140 return CMD_ERROR;
141 }
142
143 maxperident = strtoul(cargv[3], NULL, 10);
144 if(!howmany || (maxperident > 1000)) {
145 controlreply(sender, "Bad value for max per ident.");
146 return CMD_ERROR;
147 }
148
149 if(cargv[4][0] != '1' && cargv[4][0] != '0') {
150 controlreply(sender, "Bad value for enforce ident (use 0 or 1).");
151 return CMD_ERROR;
152 }
153 enforceident = cargv[4][0] == '1';
154
155 contact = cargv[5];
156
157 if(cargc < 7) {
158 comment = "(no comment)";
159 } else {
160 comment = cargv[6];
161 }
162
163 /* don't allow #id or id forms */
164 if((name[0] == '#') || strtoul(name, NULL, 10)) {
165 controlreply(sender, "Invalid trustgroup name.");
166 return CMD_ERROR;
167 }
168
169 tg = tg_strtotg(name);
170 if(tg) {
171 controlreply(sender, "A group with that name already exists");
172 return CMD_ERROR;
173 }
174
175 snprintf(createdby, sizeof(createdby), "#%s", sender->authname);
176
177 tg = tg_new(name, howmany, enforceident, maxperident, howlong + time(NULL), createdby, contact, comment);
178 if(!tg) {
179 controlreply(sender, "An error occured adding the trustgroup.");
180 return CMD_ERROR;
181 }
182
183 controlreply(sender, "Group added.");
184 /* TODO: controlwall */
185
186 return CMD_OK;
187 }
188
189 static int commandsregistered;
190
191 static void registercommands(int hooknum, void *arg) {
192 if(commandsregistered)
193 return;
194 commandsregistered = 1;
195
196 registercontrolhelpcmd("trustlist", NO_OPER, 1, trusts_cmdtrustlist, "Usage: trustlist <#id|name|id>\nShows trust data for the specified trust group.");
197 registercontrolhelpcmd("trustgroupadd", NO_OPER, 6, trusts_cmdtrustgroupadd, "Usage: trustgroupadd <name> <howmany> <howlong> <maxperident> <enforceident> <contact> ?comment?");
198 registercontrolhelpcmd("trustadd", NO_OPER, 2, trusts_cmdtrustadd, "Usage: trustadd <#id|name|id> <host>");
199 }
200
201 static void deregistercommands(int hooknum, void *arg) {
202 if(!commandsregistered)
203 return;
204 commandsregistered = 0;
205
206 deregistercontrolcmd("trustlist", trusts_cmdtrustlist);
207 deregistercontrolcmd("trustgroupadd", trusts_cmdtrustgroupadd);
208 deregistercontrolcmd("trustadd", trusts_cmdtrustadd);
209 }
210
211 void _init(void) {
212 registerhook(HOOK_TRUSTS_DB_LOADED, registercommands);
213 registerhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands);
214
215 if(trustsdbloaded)
216 registercommands(0, NULL);
217 }
218
219 void _fini(void) {
220 deregisterhook(HOOK_TRUSTS_DB_LOADED, registercommands);
221 deregisterhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands);
222
223 deregistercommands(0, NULL);
224 }