2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
16 * IRC operator commands
27 #include "conn-func.h"
30 #include "irc-write.h"
41 * Handle invalid received OPER command.
42 * Log OPER attempt and send error message to client.
45 Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
47 Log(LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s",
48 Client_Mask(Client), errtoken, errmsg);
49 IRC_SetPenalty(Client, 3);
50 return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
55 * Handler for the IRC "OPER" command.
57 * See RFC 2812, 3.1.4 "Oper message".
59 * @param Client The client from which this command has been received.
60 * @param Req Request structure with prefix and all parameters.
61 * @return CONNECTED or DISCONNECTED.
64 IRC_OPER( CLIENT *Client, REQUEST *Req )
69 assert( Client != NULL );
70 assert( Req != NULL );
73 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
74 Client_ID(Client), Req->command);
76 len = array_length(&Conf_Opers, sizeof(*op));
77 op = array_start(&Conf_Opers);
78 for (i = 0; i < len && strcmp(op[i].name, Req->argv[0]); i++)
81 return Bad_OperPass(Client, Req->argv[0], "not configured");
83 if (strcmp(op[i].pwd, Req->argv[1]) != 0)
84 return Bad_OperPass(Client, op[i].name, "bad password");
86 if (op[i].mask && (!Match(op[i].mask, Client_Mask(Client))))
87 return Bad_OperPass(Client, op[i].mask, "hostmask check failed");
89 if (!Client_HasMode(Client, 'o')) {
90 Client_ModeAdd(Client, 'o');
91 if (!IRC_WriteStrClient(Client, "MODE %s :+o",
94 IRC_WriteStrServersPrefix(NULL, Client, "MODE %s :+o",
98 if (!Client_OperByMe(Client))
99 Log(LOG_NOTICE|LOG_snotice,
100 "Got valid OPER from \"%s\", user is an IRC operator now.",
101 Client_Mask(Client));
103 Client_SetOperByMe(Client, true);
104 return IRC_WriteStrClient(Client, RPL_YOUREOPER_MSG, Client_ID(Client));
108 * Handler for the IRC "DIE" command.
110 * See RFC 2812, 4.3 "Die message".
112 * @param Client The client from which this command has been received.
113 * @param Req Request structure with prefix and all parameters.
114 * @return CONNECTED or DISCONNECTED.
117 IRC_DIE(CLIENT * Client, REQUEST * Req)
119 /* Shut down server */
124 assert(Client != NULL);
127 if (!Op_Check(Client, Req))
128 return Op_NoPrivileges(Client, Req);
130 /* Bad number of parameters? */
136 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
137 Client_ID(Client), Req->command);
139 /* Is a message given? */
143 cl = Conn_GetClient(c);
144 if (Client_Type(cl) == CLIENT_USER)
145 IRC_WriteStrClient(cl, "NOTICE %s :%s",
146 Client_ID(cl), Req->argv[0]);
151 Log(LOG_NOTICE | LOG_snotice, "Got DIE command from \"%s\" ...",
152 Client_Mask(Client));
153 NGIRCd_SignalQuit = true;
159 * Handler for the IRC "REHASH" command.
161 * See RFC 2812, 4.2 "Rehash message".
163 * @param Client The client from which this command has been received.
164 * @param Req Request structure with prefix and all parameters.
165 * @return CONNECTED or DISCONNECTED.
168 IRC_REHASH( CLIENT *Client, REQUEST *Req )
170 /* Reload configuration file */
172 assert( Client != NULL );
173 assert( Req != NULL );
175 if (!Op_Check(Client, Req))
176 return Op_NoPrivileges(Client, Req);
178 /* Bad number of parameters? */
180 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
181 Client_ID(Client), Req->command );
183 Log(LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...",
184 Client_Mask(Client));
191 * Handler for the IRC "RESTART" command.
193 * See RFC 2812, 4.4 "Restart message".
195 * @param Client The client from which this command has been received.
196 * @param Req Request structure with prefix and all parameters.
197 * @return CONNECTED or DISCONNECTED.
200 IRC_RESTART( CLIENT *Client, REQUEST *Req )
202 /* Restart IRC server (fork a new process) */
204 assert( Client != NULL );
205 assert( Req != NULL );
207 if (!Op_Check(Client, Req))
208 return Op_NoPrivileges(Client, Req);
210 /* Bad number of parameters? */
212 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
213 Client_ID(Client), Req->command);
215 Log(LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...",
216 Client_Mask(Client));
217 NGIRCd_SignalRestart = true;
223 * Handler for the IRC "CONNECT" command.
225 * See RFC 2812, 3.4.7 "Connect message".
227 * @param Client The client from which this command has been received.
228 * @param Req Request structure with prefix and all parameters.
229 * @return CONNECTED or DISCONNECTED.
232 IRC_CONNECT(CLIENT * Client, REQUEST * Req)
234 CLIENT *from, *target;
236 assert(Client != NULL);
239 if (Client_Type(Client) != CLIENT_SERVER
240 && !Client_HasMode(Client, 'o'))
241 return Op_NoPrivileges(Client, Req);
243 /* Bad number of parameters? */
244 if (Req->argc != 1 && Req->argc != 2 && Req->argc != 3 &&
245 Req->argc != 5 && Req->argc != 6)
246 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
247 Client_ID(Client), Req->command);
249 /* Invalid port number? */
250 if ((Req->argc > 1) && atoi(Req->argv[1]) < 1)
251 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
252 Client_ID(Client), Req->command);
255 target = Client_ThisServer();
257 if (Req->argc == 3 || Req->argc == 6) {
258 /* This CONNECT has a target parameter */
259 if (Client_Type(Client) == CLIENT_SERVER && Req->prefix)
260 from = Client_Search(Req->prefix);
262 return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
263 Client_ID(Client), Req->prefix);
265 target = (Req->argc == 3) ? Client_Search(Req->argv[2])
266 : Client_Search(Req->argv[5]);
267 if (! target || Client_Type(target) != CLIENT_SERVER)
268 return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
269 Client_ID(from), Req->argv[0]);
272 if (target != Client_ThisServer()) {
273 /* Forward CONNECT command ... */
275 IRC_WriteStrClientPrefix(target, from,
276 "CONNECT %s %s :%s", Req->argv[0],
277 Req->argv[1], Req->argv[2]);
279 IRC_WriteStrClientPrefix(target, from,
280 "CONNECT %s %s %s %s %s :%s", Req->argv[0],
281 Req->argv[1], Req->argv[2], Req->argv[3],
282 Req->argv[4], Req->argv[5]);
286 if (!Op_Check(from, Req))
287 return Op_NoPrivileges(Client, Req);
291 if (!Conf_EnablePassiveServer(Req->argv[0]))
292 return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
298 /* Connect configured server */
299 if (!Conf_EnableServer
300 (Req->argv[0], (UINT16) atoi(Req->argv[1])))
301 return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
308 (Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2],
309 Req->argv[3], Req->argv[4]))
310 return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
315 Log(LOG_NOTICE | LOG_snotice,
316 "Got CONNECT command from \"%s\" for \"%s\".", Client_Mask(from),
318 IRC_SendWallops(Client_ThisServer(), Client_ThisServer(),
319 "Received CONNECT %s from %s",
320 Req->argv[0], Client_ID(from));
326 * Handler for the IRC "DISCONNECT" command.
328 * This command is not specified in the IRC RFCs, it is an extension
329 * of ngIRCd: it shuts down and disables a configured server connection.
331 * @param Client The client from which this command has been received.
332 * @param Req Request structure with prefix and all parameters.
333 * @return CONNECTED or DISCONNECTED.
336 IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
340 assert(Client != NULL);
343 if (!Op_Check(Client, Req))
344 return Op_NoPrivileges(Client, Req);
346 /* Bad number of parameters? */
348 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
349 Client_ID(Client), Req->command);
351 IRC_SendWallops(Client_ThisServer(), Client_ThisServer(),
352 "Received DISCONNECT %s from %s",
353 Req->argv[0], Client_ID(Client));
355 Log(LOG_NOTICE | LOG_snotice,
356 "Got DISCONNECT command from \"%s\" for \"%s\".",
357 Client_Mask(Client), Req->argv[0]);
359 /* Save ID of this connection */
360 my_conn = Client_Conn(Client);
362 /* Disconnect configured server */
363 if (!Conf_DisableServer(Req->argv[0]))
364 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
365 Client_ID(Client), Req->argv[0]);
367 /* Are we still connected or were we killed, too? */
368 if (Conn_GetClient(my_conn))
372 } /* IRC_DISCONNECT */
375 * Handler for the IRC "WALLOPS" command.
377 * See RFC 2812, 4.7 "Operwall message".
379 * @param Client The client from which this command has been received.
380 * @param Req Request structure with prefix and all parameters.
381 * @return CONNECTED or DISCONNECTED.
384 IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
388 assert( Client != NULL );
389 assert( Req != NULL );
392 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
393 Client_ID(Client), Req->command);
395 switch (Client_Type(Client)) {
397 if (!Client_OperByMe(Client))
398 return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
403 from = Client_Search(Req->prefix);
410 return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
411 Client_ID(Client), Req->prefix);
413 IRC_SendWallops(Client, from, "%s", Req->argv[0]);