2 6e07fb41 2001-12-21 alex * ngIRCd -- The Next Generation IRC Daemon
3 8644cbf1 2008-05-30 alex * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
5 490f28ff 2002-12-12 alex * This program is free software; you can redistribute it and/or modify
6 490f28ff 2002-12-12 alex * it under the terms of the GNU General Public License as published by
7 490f28ff 2002-12-12 alex * the Free Software Foundation; either version 2 of the License, or
8 490f28ff 2002-12-12 alex * (at your option) any later version.
9 490f28ff 2002-12-12 alex * Please read the file COPYING, README and AUTHORS for more information.
12 ca33cbda 2002-03-12 alex #include "portab.h"
16 45404a16 2005-06-01 alex * IRC command parser and validator.
19 ca33cbda 2002-03-12 alex #include "imp.h"
20 6e07fb41 2001-12-21 alex #include <assert.h>
21 1c8c92af 2002-01-05 alex #include <stdlib.h>
22 6e07fb41 2001-12-21 alex #include <stdio.h>
23 6e07fb41 2001-12-21 alex #include <string.h>
24 57c7e236 2004-01-17 alex #include <strings.h>
26 d79a7d28 2002-01-18 alex #include "ngircd.h"
27 ca33cbda 2002-03-12 alex #include "defines.h"
28 b8d7dcec 2003-12-30 alex #include "conn-func.h"
29 c2f60abe 2002-05-27 alex #include "client.h"
30 c2f60abe 2002-05-27 alex #include "channel.h"
31 c2f60abe 2002-05-27 alex #include "log.h"
32 c2f60abe 2002-05-27 alex #include "messages.h"
33 c2f60abe 2002-05-27 alex #include "tool.h"
35 c2f60abe 2002-05-27 alex #include "exp.h"
36 c2f60abe 2002-05-27 alex #include "parse.h"
38 c2f60abe 2002-05-27 alex #include "imp.h"
39 76c4f066 2001-12-23 alex #include "irc.h"
40 14aba7c1 2002-03-03 alex #include "irc-channel.h"
41 0c471b84 2002-11-30 alex #include "irc-info.h"
42 b56eb4d8 2002-02-27 alex #include "irc-login.h"
43 b56eb4d8 2002-02-27 alex #include "irc-mode.h"
44 c2f60abe 2002-05-27 alex #include "irc-op.h"
45 14aba7c1 2002-03-03 alex #include "irc-oper.h"
46 14aba7c1 2002-03-03 alex #include "irc-server.h"
47 b56eb4d8 2002-02-27 alex #include "irc-write.h"
48 47ca178a 2007-11-21 alex #include "numeric.h"
50 ca33cbda 2002-03-12 alex #include "exp.h"
52 4add9c29 2008-01-13 fw struct _NUMERIC {
54 4add9c29 2008-01-13 fw bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
58 4add9c29 2008-01-13 fw static COMMAND My_Commands[] =
60 17f7c6d3 2002-12-18 alex { "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
61 17f7c6d3 2002-12-18 alex { "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 },
62 17f7c6d3 2002-12-18 alex { "CONNECT", IRC_CONNECT, CLIENT_USER, 0, 0, 0 },
63 17f7c6d3 2002-12-18 alex { "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 },
64 a7956f33 2003-12-31 alex { "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
65 17f7c6d3 2002-12-18 alex { "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
66 2152e377 2003-01-15 alex { "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
67 ddecfcd8 2008-02-26 fw { "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
68 17f7c6d3 2002-12-18 alex { "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
69 17f7c6d3 2002-12-18 alex { "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 },
70 17f7c6d3 2002-12-18 alex { "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
71 17f7c6d3 2002-12-18 alex { "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
72 17f7c6d3 2002-12-18 alex { "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
73 17f7c6d3 2002-12-18 alex { "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
74 17f7c6d3 2002-12-18 alex { "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
75 17f7c6d3 2002-12-18 alex { "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
76 17f7c6d3 2002-12-18 alex { "MODE", IRC_MODE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
77 17f7c6d3 2002-12-18 alex { "MOTD", IRC_MOTD, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
78 17f7c6d3 2002-12-18 alex { "NAMES", IRC_NAMES, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
79 17f7c6d3 2002-12-18 alex { "NICK", IRC_NICK, 0xFFFF, 0, 0, 0 },
80 17f7c6d3 2002-12-18 alex { "NJOIN", IRC_NJOIN, CLIENT_SERVER, 0, 0, 0 },
81 17f7c6d3 2002-12-18 alex { "NOTICE", IRC_NOTICE, 0xFFFF, 0, 0, 0 },
82 17f7c6d3 2002-12-18 alex { "OPER", IRC_OPER, CLIENT_USER, 0, 0, 0 },
83 17f7c6d3 2002-12-18 alex { "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
84 17f7c6d3 2002-12-18 alex { "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 },
85 17f7c6d3 2002-12-18 alex { "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
86 17f7c6d3 2002-12-18 alex { "PONG", IRC_PONG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
87 17f7c6d3 2002-12-18 alex { "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
88 17f7c6d3 2002-12-18 alex { "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 },
89 17f7c6d3 2002-12-18 alex { "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
90 17f7c6d3 2002-12-18 alex { "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0 },
91 17f7c6d3 2002-12-18 alex { "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 },
92 4e56e534 2008-05-05 alex { "SERVICE", IRC_SERVICE, 0xFFFF, 0, 0, 0 },
93 4e56e534 2008-05-05 alex { "SERVLIST", IRC_SERVLIST, CLIENT_USER, 0, 0, 0 },
94 4e56e534 2008-05-05 alex { "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
95 17f7c6d3 2002-12-18 alex { "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 },
96 17f7c6d3 2002-12-18 alex { "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
97 ddecfcd8 2008-02-26 fw { "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
98 17f7c6d3 2002-12-18 alex { "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
99 17f7c6d3 2002-12-18 alex { "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
100 42c4e6c7 2003-01-13 alex { "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
101 17f7c6d3 2002-12-18 alex { "USER", IRC_USER, 0xFFFF, 0, 0, 0 },
102 17f7c6d3 2002-12-18 alex { "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 },
103 ddecfcd8 2008-02-26 fw { "USERS", IRC_USERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
104 17f7c6d3 2002-12-18 alex { "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
105 4b9e52eb 2007-08-02 fw { "WALLOPS", IRC_WALLOPS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
106 17f7c6d3 2002-12-18 alex { "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 },
107 17f7c6d3 2002-12-18 alex { "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
108 17f7c6d3 2002-12-18 alex { "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
109 17f7c6d3 2002-12-18 alex #ifdef IRCPLUS
110 17f7c6d3 2002-12-18 alex { "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 },
112 17f7c6d3 2002-12-18 alex { NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */
115 77f54693 2005-07-31 alex static void Init_Request PARAMS(( REQUEST *Req ));
117 77f54693 2005-07-31 alex static bool Validate_Prefix PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
118 77f54693 2005-07-31 alex static bool Validate_Command PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
119 77f54693 2005-07-31 alex static bool Validate_Args PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
121 77f54693 2005-07-31 alex static bool Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req ));
123 4add9c29 2008-01-13 fw #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
126 45404a16 2005-06-01 alex * Return the pointer to the global "IRC command structure".
127 45404a16 2005-06-01 alex * This structure, an array of type "COMMAND" describes all the IRC commands
128 45404a16 2005-06-01 alex * implemented by ngIRCd and how to handle them.
129 45404a16 2005-06-01 alex * @return Pointer to the global command structure.
131 17f7c6d3 2002-12-18 alex GLOBAL COMMAND *
132 8adff592 2005-03-19 fw Parse_GetCommandStruct( void )
134 17f7c6d3 2002-12-18 alex return My_Commands;
135 17f7c6d3 2002-12-18 alex } /* Parse_GetCommandStruct */
139 45404a16 2005-06-01 alex * Parse a command ("request") received from a client.
141 45404a16 2005-06-01 alex * This function is called after the connection layer received a valid CR+LF
142 45404a16 2005-06-01 alex * terminated line of text: we asume that this is a valid IRC command and
143 45404a16 2005-06-01 alex * try to do something useful with it :-)
145 45404a16 2005-06-01 alex * All errors are reported to the client from which the command has been
146 45404a16 2005-06-01 alex * received, and if the error is fatal this connection is closed down.
148 45404a16 2005-06-01 alex * This function is able to parse the syntax as described in RFC 2812,
149 45404a16 2005-06-01 alex * section 2.3.
151 45404a16 2005-06-01 alex * @param Idx Index of the connection from which the command has been received.
152 45404a16 2005-06-01 alex * @param Request NULL terminated line of text (the "command").
153 45404a16 2005-06-01 alex * @return true on success (valid command or "regular" error), false if a
154 45404a16 2005-06-01 alex * fatal error occured and the connection has been shut down.
157 8adff592 2005-03-19 fw Parse_Request( CONN_ID Idx, char *Request )
159 6e07fb41 2001-12-21 alex REQUEST req;
160 8adff592 2005-03-19 fw char *start, *ptr;
163 6e07fb41 2001-12-21 alex assert( Idx >= 0 );
164 6e07fb41 2001-12-21 alex assert( Request != NULL );
166 d4a60bd4 2001-12-25 alex #ifdef SNIFFER
167 d79a7d28 2002-01-18 alex if( NGIRCd_Sniffer ) Log( LOG_DEBUG, " <- connection %d: '%s'.", Idx, Request );
170 6e07fb41 2001-12-21 alex Init_Request( &req );
172 363a03b8 2001-12-29 alex /* Fuehrendes und folgendes "Geraffel" verwerfen */
173 363a03b8 2001-12-29 alex ngt_TrimStr( Request );
175 6e07fb41 2001-12-21 alex /* gibt es ein Prefix? */
176 6e07fb41 2001-12-21 alex if( Request[0] == ':' )
178 6e07fb41 2001-12-21 alex /* Prefix vorhanden */
179 6e07fb41 2001-12-21 alex req.prefix = Request + 1;
180 6e07fb41 2001-12-21 alex ptr = strchr( Request, ' ' );
181 e0ed3aa1 2002-07-26 alex if( ! ptr )
183 e0ed3aa1 2002-07-26 alex Log( LOG_DEBUG, "Connection %d: Parse error: prefix without command!?", Idx );
184 e0ed3aa1 2002-07-26 alex return Conn_WriteStr( Idx, "ERROR :Prefix without command!?" );
186 6e07fb41 2001-12-21 alex *ptr = '\0';
187 3543c222 2002-01-09 alex #ifndef STRICT_RFC
188 3543c222 2002-01-09 alex /* multiple Leerzeichen als Trenner zwischen
189 3543c222 2002-01-09 alex * Prefix und Befehl ignorieren */
190 3543c222 2002-01-09 alex while( *(ptr + 1) == ' ' ) ptr++;
192 6e07fb41 2001-12-21 alex start = ptr + 1;
194 6e07fb41 2001-12-21 alex else start = Request;
196 6e07fb41 2001-12-21 alex /* Befehl */
197 6e07fb41 2001-12-21 alex ptr = strchr( start, ' ' );
200 3543c222 2002-01-09 alex *ptr = '\0';
201 3543c222 2002-01-09 alex #ifndef STRICT_RFC
202 3543c222 2002-01-09 alex /* multiple Leerzeichen als Trenner vor
203 fc1118cb 2003-01-12 alex * Parametern ignorieren */
204 3543c222 2002-01-09 alex while( *(ptr + 1) == ' ' ) ptr++;
207 6e07fb41 2001-12-21 alex req.command = start;
209 6e07fb41 2001-12-21 alex /* Argumente, Parameter */
212 6e07fb41 2001-12-21 alex /* Prinzipiell gibt es welche :-) */
213 6e07fb41 2001-12-21 alex start = ptr + 1;
214 6e07fb41 2001-12-21 alex while( start )
216 6e07fb41 2001-12-21 alex /* Parameter-String "zerlegen" */
217 76c4f066 2001-12-23 alex if( start[0] == ':' )
219 76c4f066 2001-12-23 alex req.argv[req.argc] = start + 1;
220 76c4f066 2001-12-23 alex ptr = NULL;
224 76c4f066 2001-12-23 alex req.argv[req.argc] = start;
225 76c4f066 2001-12-23 alex ptr = strchr( start, ' ' );
228 3543c222 2002-01-09 alex *ptr = '\0';
229 3543c222 2002-01-09 alex #ifndef STRICT_RFC
230 3543c222 2002-01-09 alex /* multiple Leerzeichen als
231 3543c222 2002-01-09 alex * Parametertrenner ignorieren */
232 3543c222 2002-01-09 alex while( *(ptr + 1) == ' ' ) ptr++;
237 6e07fb41 2001-12-21 alex req.argc++;
239 6e07fb41 2001-12-21 alex if( start[0] == ':' ) break;
240 6e07fb41 2001-12-21 alex if( req.argc > 14 ) break;
242 6e07fb41 2001-12-21 alex if( ptr ) start = ptr + 1;
243 6e07fb41 2001-12-21 alex else start = NULL;
247 b0b797b3 2002-11-28 alex /* Daten validieren */
248 b0b797b3 2002-11-28 alex if( ! Validate_Prefix( Idx, &req, &closed )) return ! closed;
249 b0b797b3 2002-11-28 alex if( ! Validate_Command( Idx, &req, &closed )) return ! closed;
250 e0ed3aa1 2002-07-26 alex if( ! Validate_Args( Idx, &req, &closed )) return ! closed;
252 6e07fb41 2001-12-21 alex return Handle_Request( Idx, &req );
253 6e07fb41 2001-12-21 alex } /* Parse_Request */
257 45404a16 2005-06-01 alex * Initialize request structure.
258 45404a16 2005-06-01 alex * @param Req Request structure to be initialized.
260 77f54693 2005-07-31 alex static void
261 c2f60abe 2002-05-27 alex Init_Request( REQUEST *Req )
263 6e07fb41 2001-12-21 alex /* Neue Request-Struktur initialisieren */
267 6e07fb41 2001-12-21 alex assert( Req != NULL );
269 6e07fb41 2001-12-21 alex Req->prefix = NULL;
270 6e07fb41 2001-12-21 alex Req->command = NULL;
271 6e07fb41 2001-12-21 alex for( i = 0; i < 15; Req->argv[i++] = NULL );
272 6e07fb41 2001-12-21 alex Req->argc = 0;
273 6e07fb41 2001-12-21 alex } /* Init_Request */
276 77f54693 2005-07-31 alex static bool
277 8adff592 2005-03-19 fw Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
279 5063de59 2002-07-29 alex CLIENT *client, *c;
281 e0ed3aa1 2002-07-26 alex assert( Idx >= 0 );
282 e0ed3aa1 2002-07-26 alex assert( Req != NULL );
284 8adff592 2005-03-19 fw *Closed = false;
286 e0ed3aa1 2002-07-26 alex /* ist ueberhaupt ein Prefix vorhanden? */
287 8adff592 2005-03-19 fw if( ! Req->prefix ) return true;
289 5063de59 2002-07-29 alex /* Client-Struktur der Connection ermitteln */
290 87f4b1c6 2006-04-23 fw client = Conn_GetClient( Idx );
291 5063de59 2002-07-29 alex assert( client != NULL );
293 5063de59 2002-07-29 alex /* nur validieren, wenn bereits registrierte Verbindung */
294 5063de59 2002-07-29 alex if(( Client_Type( client ) != CLIENT_USER ) && ( Client_Type( client ) != CLIENT_SERVER ) && ( Client_Type( client ) != CLIENT_SERVICE ))
296 5063de59 2002-07-29 alex /* noch nicht registrierte Verbindung.
297 5063de59 2002-07-29 alex * Das Prefix wird ignoriert. */
298 5063de59 2002-07-29 alex Req->prefix = NULL;
302 e0ed3aa1 2002-07-26 alex /* pruefen, ob der im Prefix angegebene Client bekannt ist */
303 e0ed3aa1 2002-07-26 alex c = Client_Search( Req->prefix );
306 e0ed3aa1 2002-07-26 alex /* im Prefix angegebener Client ist nicht bekannt */
307 b0b797b3 2002-11-28 alex Log( LOG_ERR, "Invalid prefix \"%s\", client not known (connection %d, command %s)!?", Req->prefix, Idx, Req->command );
308 8adff592 2005-03-19 fw if( ! Conn_WriteStr( Idx, "ERROR :Invalid prefix \"%s\", client not known!?", Req->prefix )) *Closed = true;
309 8adff592 2005-03-19 fw return false;
312 e0ed3aa1 2002-07-26 alex /* pruefen, ob der Client mit dem angegebenen Prefix in Richtung
313 e0ed3aa1 2002-07-26 alex * des Senders liegt, d.h. sicherstellen, dass das Prefix nicht
314 e0ed3aa1 2002-07-26 alex * gefaelscht ist */
315 5063de59 2002-07-29 alex if( Client_NextHop( c ) != client )
317 e0ed3aa1 2002-07-26 alex /* das angegebene Prefix ist aus dieser Richtung, also
318 e0ed3aa1 2002-07-26 alex * aus der gegebenen Connection, ungueltig! */
319 87f4b1c6 2006-04-23 fw Log( LOG_ERR, "Spoofed prefix \"%s\" from \"%s\" (connection %d, command %s)!", Req->prefix, Client_Mask( Conn_GetClient( Idx )), Idx, Req->command );
320 8adff592 2005-03-19 fw Conn_Close( Idx, NULL, "Spoofed prefix", true);
321 8adff592 2005-03-19 fw *Closed = true;
322 8adff592 2005-03-19 fw return false;
326 6e07fb41 2001-12-21 alex } /* Validate_Prefix */
329 77f54693 2005-07-31 alex static bool
330 74cb2e27 2005-07-22 alex Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
332 e0ed3aa1 2002-07-26 alex assert( Idx >= 0 );
333 6e07fb41 2001-12-21 alex assert( Req != NULL );
334 8adff592 2005-03-19 fw *Closed = false;
337 6e07fb41 2001-12-21 alex } /* Validate_Comman */
340 77f54693 2005-07-31 alex static bool
341 e5cf73b9 2008-07-27 alex #ifdef STRICT_RFC
342 8644cbf1 2008-05-30 alex Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
344 e5cf73b9 2008-07-27 alex Validate_Args(UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed)
347 a84f7dce 2008-06-11 alex #ifdef STRICT_RFC
351 8adff592 2005-03-19 fw *Closed = false;
353 a84f7dce 2008-06-11 alex #ifdef STRICT_RFC
354 e5cf73b9 2008-07-27 alex assert( Idx >= 0 );
355 e5cf73b9 2008-07-27 alex assert( Req != NULL );
357 a84f7dce 2008-06-11 alex /* CR and LF are never allowed in command parameters.
358 a84f7dce 2008-06-11 alex * But since we do accept lines terminated only with CR or LF in
359 a84f7dce 2008-06-11 alex * "non-RFC-compliant mode" (besides the correct CR+LF combination),
360 a84f7dce 2008-06-11 alex * this check can only trigger in "strict RFC" mode; therefore we
361 a84f7dce 2008-06-11 alex * optimize it away otherwise ... */
362 8644cbf1 2008-05-30 alex for (i = 0; i < Req->argc; i++) {
363 8644cbf1 2008-05-30 alex if (strchr(Req->argv[i], '\r') || strchr(Req->argv[i], '\n')) {
364 8644cbf1 2008-05-30 alex Log(LOG_ERR,
365 8644cbf1 2008-05-30 alex "Invalid character(s) in parameter (connection %d, command %s)!?",
366 8644cbf1 2008-05-30 alex Idx, Req->command);
367 8644cbf1 2008-05-30 alex if (!Conn_WriteStr(Idx,
368 8644cbf1 2008-05-30 alex "ERROR :Invalid character(s) in parameter!"))
369 8644cbf1 2008-05-30 alex *Closed = true;
370 8644cbf1 2008-05-30 alex return false;
376 6e07fb41 2001-12-21 alex } /* Validate_Args */
379 4add9c29 2008-01-13 fw /* Command is a status code ("numeric") from another server */
380 77f54693 2005-07-31 alex static bool
381 4add9c29 2008-01-13 fw Handle_Numeric(CLIENT *client, REQUEST *Req)
383 4add9c29 2008-01-13 fw static const struct _NUMERIC Numerics[] = {
384 4add9c29 2008-01-13 fw { 005, IRC_Num_ISUPPORT },
385 4add9c29 2008-01-13 fw { 376, IRC_Num_ENDOFMOTD }
388 4add9c29 2008-01-13 fw char str[LINE_LEN];
389 4add9c29 2008-01-13 fw CLIENT *prefix, *target = NULL;
391 4add9c29 2008-01-13 fw /* Determine target */
392 4add9c29 2008-01-13 fw if (Req->argc > 0)
393 4add9c29 2008-01-13 fw target = Client_Search(Req->argv[0]);
395 4add9c29 2008-01-13 fw if (!target) {
396 4add9c29 2008-01-13 fw /* Status code without target!? */
397 4add9c29 2008-01-13 fw if (Req->argc > 0)
398 4add9c29 2008-01-13 fw Log(LOG_WARNING,
399 4add9c29 2008-01-13 fw "Unknown target for status code %s: \"%s\"",
400 4add9c29 2008-01-13 fw Req->command, Req->argv[0]);
402 4add9c29 2008-01-13 fw Log(LOG_WARNING,
403 4add9c29 2008-01-13 fw "Unknown target for status code %s!",
404 4add9c29 2008-01-13 fw Req->command);
407 4add9c29 2008-01-13 fw if (target == Client_ThisServer()) {
408 4add9c29 2008-01-13 fw /* This server is the target of the numeric */
409 4add9c29 2008-01-13 fw num = atoi(Req->command);
411 4add9c29 2008-01-13 fw for (i = 0; i < (int) ARRAY_SIZE(Numerics); i++) {
412 4add9c29 2008-01-13 fw if (num == Numerics[i].numeric)
413 4add9c29 2008-01-13 fw return Numerics[i].function(client, Req);
416 4add9c29 2008-01-13 fw LogDebug("Ignored status code %s from \"%s\".",
417 4add9c29 2008-01-13 fw Req->command, Client_ID(client));
421 4add9c29 2008-01-13 fw /* Determine source */
422 4add9c29 2008-01-13 fw if (! Req->prefix[0]) {
423 4add9c29 2008-01-13 fw /* Oops, no prefix!? */
424 4add9c29 2008-01-13 fw Log(LOG_WARNING, "Got status code %s from \"%s\" without prefix!?",
425 4add9c29 2008-01-13 fw Req->command, Client_ID(client));
429 4add9c29 2008-01-13 fw prefix = Client_Search(Req->prefix);
430 4add9c29 2008-01-13 fw if (! prefix) { /* Oops, unknown prefix!? */
431 4add9c29 2008-01-13 fw Log(LOG_WARNING, "Got status code %s from unknown source: \"%s\"", Req->command, Req->prefix);
435 4add9c29 2008-01-13 fw /* Forward status code */
436 4add9c29 2008-01-13 fw strlcpy(str, Req->command, sizeof(str));
437 4add9c29 2008-01-13 fw for (i = 0; i < Req->argc; i++) {
438 4add9c29 2008-01-13 fw if (i < Req->argc - 1)
439 4add9c29 2008-01-13 fw strlcat(str, " ", sizeof(str));
441 4add9c29 2008-01-13 fw strlcat(str, " :", sizeof(str));
442 4add9c29 2008-01-13 fw strlcat(str, Req->argv[i], sizeof(str));
444 4add9c29 2008-01-13 fw return IRC_WriteStrClientPrefix(target, prefix, "%s", str);
449 c2f60abe 2002-05-27 alex Handle_Request( CONN_ID Idx, REQUEST *Req )
451 76c4f066 2001-12-23 alex /* Client-Request verarbeiten. Bei einem schwerwiegenden Fehler
452 8adff592 2005-03-19 fw * wird die Verbindung geschlossen und false geliefert. */
453 4add9c29 2008-01-13 fw CLIENT *client;
454 4add9c29 2008-01-13 fw bool result = true;
455 3022d7cf 2008-02-26 fw int client_type;
456 1e59617d 2002-11-30 alex COMMAND *cmd;
458 6e07fb41 2001-12-21 alex assert( Idx >= 0 );
459 6e07fb41 2001-12-21 alex assert( Req != NULL );
460 6e07fb41 2001-12-21 alex assert( Req->command != NULL );
462 87f4b1c6 2006-04-23 fw client = Conn_GetClient( Idx );
463 76c4f066 2001-12-23 alex assert( client != NULL );
465 47ca178a 2007-11-21 alex /* Numeric? */
466 3022d7cf 2008-02-26 fw client_type = Client_Type(client);
467 3022d7cf 2008-02-26 fw if ((client_type == CLIENT_SERVER ||
468 3022d7cf 2008-02-26 fw client_type == CLIENT_UNKNOWNSERVER)
469 4add9c29 2008-01-13 fw && strlen(Req->command) == 3 && atoi(Req->command) > 1)
470 4add9c29 2008-01-13 fw return Handle_Numeric(client, Req);
472 1e59617d 2002-11-30 alex cmd = My_Commands;
473 4add9c29 2008-01-13 fw while (cmd->name) {
474 1e59617d 2002-11-30 alex /* Befehl suchen */
475 4add9c29 2008-01-13 fw if (strcasecmp(Req->command, cmd->name) != 0) {
480 3022d7cf 2008-02-26 fw if (!(client_type & cmd->type))
481 4add9c29 2008-01-13 fw return IRC_WriteStrClient(client, ERR_NOTREGISTERED_MSG, Client_ID(client));
483 4add9c29 2008-01-13 fw /* Command is allowed for this client: call it and count produced bytes */
484 4add9c29 2008-01-13 fw Conn_ResetWCounter();
485 4add9c29 2008-01-13 fw result = (cmd->function)(client, Req);
486 4add9c29 2008-01-13 fw cmd->bytes += Conn_WCounter();
488 4add9c29 2008-01-13 fw /* Adjust counters */
489 3022d7cf 2008-02-26 fw if (client_type != CLIENT_SERVER)
490 4add9c29 2008-01-13 fw cmd->lcount++;
492 4add9c29 2008-01-13 fw cmd->rcount++;
493 4add9c29 2008-01-13 fw return result;
496 3022d7cf 2008-02-26 fw if (client_type != CLIENT_USER &&
497 3022d7cf 2008-02-26 fw client_type != CLIENT_SERVER &&
498 3022d7cf 2008-02-26 fw client_type != CLIENT_SERVICE )
499 162338b8 2005-06-24 alex return true;
501 162338b8 2005-06-24 alex /* Unknown command and registered connection: generate error: */
502 4add9c29 2008-01-13 fw LogDebug("Connection %d: Unknown command \"%s\", %d %s,%s prefix.",
503 162338b8 2005-06-24 alex Client_Conn( client ), Req->command, Req->argc,
504 162338b8 2005-06-24 alex Req->argc == 1 ? "parameter" : "parameters",
505 162338b8 2005-06-24 alex Req->prefix ? "" : " no" );
507 4d18ac83 2005-09-04 alex if (Client_Type(client) != CLIENT_SERVER) {
508 4d18ac83 2005-09-04 alex result = IRC_WriteStrClient(client, ERR_UNKNOWNCOMMAND_MSG,
509 4d18ac83 2005-09-04 alex Client_ID(client), Req->command);
510 4d18ac83 2005-09-04 alex Conn_SetPenalty(Idx, 1);
512 4add9c29 2008-01-13 fw return result;
513 6e07fb41 2001-12-21 alex } /* Handle_Request */
516 6e07fb41 2001-12-21 alex /* -eof- */