2 38b9cb88 2001-12-14 alex * ngIRCd -- The Next Generation IRC Daemon
3 1547f76c 2002-01-02 alex * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
5 38b9cb88 2001-12-14 alex * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6 38b9cb88 2001-12-14 alex * der GNU General Public License (GPL), wie von der Free Software Foundation
7 38b9cb88 2001-12-14 alex * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8 38b9cb88 2001-12-14 alex * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9 38b9cb88 2001-12-14 alex * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10 804b1ec4 2001-12-31 alex * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
12 95a4b1b1 2002-03-25 alex * $Id: client.c,v 1.52 2002/03/25 19:11:01 alex Exp $
14 38b9cb88 2001-12-14 alex * client.c: Management aller Clients
16 38b9cb88 2001-12-14 alex * Der Begriff "Client" ist in diesem Fall evtl. etwas verwirrend: Clients sind
17 38b9cb88 2001-12-14 alex * alle Verbindungen, die im gesamten(!) IRC-Netzwerk bekannt sind. Das sind IRC-
18 38b9cb88 2001-12-14 alex * Clients (User), andere Server und IRC-Services.
19 38b9cb88 2001-12-14 alex * Ueber welchen IRC-Server die Verbindung nun tatsaechlich in das Netzwerk her-
20 38b9cb88 2001-12-14 alex * gestellt wurde, muss der jeweiligen Struktur entnommen werden. Ist es dieser
21 38b9cb88 2001-12-14 alex * Server gewesen, so existiert eine entsprechende CONNECTION-Struktur.
25 f7551900 2002-01-04 alex #define __client_c__
28 ca33cbda 2002-03-12 alex #include "portab.h"
30 ca33cbda 2002-03-12 alex #include "imp.h"
31 38b9cb88 2001-12-14 alex #include <assert.h>
32 d0ac1e9c 2001-12-23 alex #include <unistd.h>
33 118adda8 2001-12-27 alex #include <stdio.h>
34 b20fa7c6 2002-01-01 alex #include <stdlib.h>
35 d0ac1e9c 2001-12-23 alex #include <string.h>
36 c57a4645 2001-12-27 alex #include <netdb.h>
38 ca33cbda 2002-03-12 alex #include "exp.h"
39 08cf5607 2001-12-26 alex #include "client.h"
41 08cf5607 2001-12-26 alex #include <imp.h>
42 79809118 2002-01-06 alex #include "ngircd.h"
43 38b9cb88 2001-12-14 alex #include "channel.h"
44 9856253d 2001-12-30 alex #include "conf.h"
45 38b9cb88 2001-12-14 alex #include "conn.h"
46 b5c16c22 2002-03-25 alex #include "hash.h"
47 ff54198f 2002-02-27 alex #include "irc-write.h"
48 38b9cb88 2001-12-14 alex #include "log.h"
49 08cf5607 2001-12-26 alex #include "messages.h"
51 38b9cb88 2001-12-14 alex #include <exp.h>
54 f7551900 2002-01-04 alex LOCAL CLIENT *This_Server, *My_Clients;
55 118adda8 2001-12-27 alex LOCAL CHAR GetID_Buffer[CLIENT_ID_LEN];
58 b9d701db 2002-01-16 alex LOCAL INT Count( CLIENT_TYPE Type );
59 b9d701db 2002-01-16 alex LOCAL INT MyCount( CLIENT_TYPE Type );
61 38b9cb88 2001-12-14 alex LOCAL CLIENT *New_Client_Struct( VOID );
62 a53857b4 2002-01-07 alex LOCAL VOID Generate_MyToken( CLIENT *Client );
65 38b9cb88 2001-12-14 alex GLOBAL VOID Client_Init( VOID )
67 c57a4645 2001-12-27 alex struct hostent *h;
69 38b9cb88 2001-12-14 alex This_Server = New_Client_Struct( );
70 38b9cb88 2001-12-14 alex if( ! This_Server )
72 38b9cb88 2001-12-14 alex Log( LOG_EMERG, "Can't allocate client structure for server! Going down." );
73 9856253d 2001-12-30 alex Log( LOG_ALERT, PACKAGE" exiting due to fatal errors!" );
77 38b9cb88 2001-12-14 alex /* Client-Struktur dieses Servers */
78 38b9cb88 2001-12-14 alex This_Server->next = NULL;
79 38b9cb88 2001-12-14 alex This_Server->type = CLIENT_SERVER;
80 38b9cb88 2001-12-14 alex This_Server->conn_id = NONE;
81 38b9cb88 2001-12-14 alex This_Server->introducer = This_Server;
82 8f7e7d66 2002-01-09 alex This_Server->mytoken = 1;
83 4fe7e9d6 2002-01-11 alex This_Server->hops = 0;
85 d0ac1e9c 2001-12-23 alex gethostname( This_Server->host, CLIENT_HOST_LEN );
86 c57a4645 2001-12-27 alex h = gethostbyname( This_Server->host );
87 c57a4645 2001-12-27 alex if( h ) strcpy( This_Server->host, h->h_name );
89 b5c16c22 2002-03-25 alex Client_SetID( This_Server, Conf_ServerName );
90 b5c16c22 2002-03-25 alex Client_SetInfo( This_Server, Conf_ServerInfo );
92 38b9cb88 2001-12-14 alex My_Clients = This_Server;
93 38b9cb88 2001-12-14 alex } /* Client_Init */
96 38b9cb88 2001-12-14 alex GLOBAL VOID Client_Exit( VOID )
98 d0ac1e9c 2001-12-23 alex CLIENT *c, *next;
101 50ec7a56 2002-03-11 alex Client_Destroy( This_Server, "Server going down.", NULL, FALSE );
104 d0ac1e9c 2001-12-23 alex c = My_Clients;
108 95a4b1b1 2002-03-25 alex next = (CLIENT *)c->next;
112 d4a60bd4 2001-12-25 alex if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
113 79809118 2002-01-06 alex } /* Client_Exit */
116 f7551900 2002-01-04 alex GLOBAL CLIENT *Client_ThisServer( VOID )
118 f7551900 2002-01-04 alex return This_Server;
119 f7551900 2002-01-04 alex } /* Client_ThisServer */
122 904d5e5b 2002-01-05 alex GLOBAL CLIENT *Client_NewLocal( CONN_ID Idx, CHAR *Hostname, INT Type, BOOLEAN Idented )
124 f7551900 2002-01-04 alex /* Neuen lokalen Client erzeugen: Wrapper-Funktion fuer Client_New(). */
125 1ab92bb9 2002-01-29 alex return Client_New( Idx, This_Server, NULL, Type, NULL, NULL, Hostname, NULL, 0, 0, NULL, Idented );
126 f7551900 2002-01-04 alex } /* Client_NewLocal */
129 1ab92bb9 2002-01-29 alex GLOBAL CLIENT *Client_NewRemoteServer( CLIENT *Introducer, CHAR *Hostname, CLIENT *TopServer, INT Hops, INT Token, CHAR *Info, BOOLEAN Idented )
131 f7551900 2002-01-04 alex /* Neuen Remote-Client erzeugen: Wrapper-Funktion fuer Client_New (). */
132 1ab92bb9 2002-01-29 alex return Client_New( NONE, Introducer, TopServer, CLIENT_SERVER, Hostname, NULL, Hostname, Info, Hops, Token, NULL, Idented );
133 f7551900 2002-01-04 alex } /* Client_NewRemoteServer */
136 904d5e5b 2002-01-05 alex GLOBAL CLIENT *Client_NewRemoteUser( CLIENT *Introducer, CHAR *Nick, INT Hops, CHAR *User, CHAR *Hostname, INT Token, CHAR *Modes, CHAR *Info, BOOLEAN Idented )
138 f7551900 2002-01-04 alex /* Neuen Remote-Client erzeugen: Wrapper-Funktion fuer Client_New (). */
139 1ab92bb9 2002-01-29 alex return Client_New( NONE, Introducer, NULL, CLIENT_USER, Nick, User, Hostname, Info, Hops, Token, Modes, Idented );
140 f7551900 2002-01-04 alex } /* Client_NewRemoteUser */
143 1ab92bb9 2002-01-29 alex GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, INT Type, CHAR *ID, CHAR *User, CHAR *Hostname, CHAR *Info, INT Hops, INT Token, CHAR *Modes, BOOLEAN Idented )
145 d0ac1e9c 2001-12-23 alex CLIENT *client;
147 f7551900 2002-01-04 alex assert( Idx >= NONE );
148 f7551900 2002-01-04 alex assert( Introducer != NULL );
149 b7a18e9f 2001-12-24 alex assert( Hostname != NULL );
151 d0ac1e9c 2001-12-23 alex client = New_Client_Struct( );
152 d0ac1e9c 2001-12-23 alex if( ! client ) return NULL;
154 2c5da58d 2001-12-29 alex /* Initialisieren */
155 d0ac1e9c 2001-12-23 alex client->conn_id = Idx;
156 f7551900 2002-01-04 alex client->introducer = Introducer;
157 1ab92bb9 2002-01-29 alex client->topserver = TopServer;
158 f7551900 2002-01-04 alex client->type = Type;
159 f7551900 2002-01-04 alex if( ID ) Client_SetID( client, ID );
160 904d5e5b 2002-01-05 alex if( User ) Client_SetUser( client, User, Idented );
161 f7551900 2002-01-04 alex if( Hostname ) Client_SetHostname( client, Hostname );
162 f7551900 2002-01-04 alex if( Info ) Client_SetInfo( client, Info );
163 f7551900 2002-01-04 alex client->hops = Hops;
164 f7551900 2002-01-04 alex client->token = Token;
165 f7551900 2002-01-04 alex if( Modes ) Client_SetModes( client, Modes );
166 a53857b4 2002-01-07 alex if( Type == CLIENT_SERVER ) Generate_MyToken( client );
168 a1a3e67d 2002-03-04 alex /* ist der User away? */
169 a1a3e67d 2002-03-04 alex if( strchr( client->modes, 'a' )) strcpy( client->away, DEFAULT_AWAY_MSG );
171 d0ac1e9c 2001-12-23 alex /* Verketten */
172 95a4b1b1 2002-03-25 alex client->next = (POINTER *)My_Clients;
173 d0ac1e9c 2001-12-23 alex My_Clients = client;
175 d0ac1e9c 2001-12-23 alex return client;
176 f7551900 2002-01-04 alex } /* Client_New */
179 50ec7a56 2002-03-11 alex GLOBAL VOID Client_Destroy( CLIENT *Client, CHAR *LogMsg, CHAR *FwdMsg, BOOLEAN SendQuit )
181 d0ac1e9c 2001-12-23 alex /* Client entfernen. */
183 d0ac1e9c 2001-12-23 alex CLIENT *last, *c;
184 dce77559 2002-03-10 alex CHAR msg[LINE_LEN], *txt;
186 b7a18e9f 2001-12-24 alex assert( Client != NULL );
188 79809118 2002-01-06 alex if( LogMsg ) txt = LogMsg;
189 79809118 2002-01-06 alex else txt = FwdMsg;
190 79809118 2002-01-06 alex if( ! txt ) txt = "Reason unknown.";
192 03c3f3c9 2002-03-12 alex /* Netz-Split-Nachricht vorbereiten (noch nicht optimal) */
193 9146fa25 2002-03-12 alex if( Client->type == CLIENT_SERVER ) sprintf( msg, "%s: lost server %s", This_Server->id, Client->id );
195 d0ac1e9c 2001-12-23 alex last = NULL;
196 d0ac1e9c 2001-12-23 alex c = My_Clients;
199 c4854470 2002-01-04 alex if(( Client->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c != Client ))
201 dce77559 2002-03-10 alex /* der Client, der geloescht wird ist ein Server. Der Client, den wir gerade
202 dce77559 2002-03-10 alex * pruefen, ist ein Child von diesem und muss daher auch entfernt werden */
203 50ec7a56 2002-03-11 alex Client_Destroy( c, NULL, msg, FALSE );
204 c4854470 2002-01-04 alex last = NULL;
205 c4854470 2002-01-04 alex c = My_Clients;
208 d0ac1e9c 2001-12-23 alex if( c == Client )
210 dce77559 2002-03-10 alex /* Wir haben den Client gefunden: entfernen */
211 d0ac1e9c 2001-12-23 alex if( last ) last->next = c->next;
212 95a4b1b1 2002-03-25 alex else My_Clients = (CLIENT *)c->next;
214 c4854470 2002-01-04 alex if( c->type == CLIENT_USER )
216 db58d347 2002-01-05 alex if( c->conn_id != NONE )
218 50ec7a56 2002-03-11 alex /* Ein lokaler User */
219 b89c3108 2002-01-07 alex Log( LOG_NOTICE, "User \"%s\" unregistered (connection %d): %s", Client_Mask( c ), c->conn_id, txt );
221 50ec7a56 2002-03-11 alex if( SendQuit )
223 50ec7a56 2002-03-11 alex /* Alle andere Server informieren! */
224 50ec7a56 2002-03-11 alex if( FwdMsg ) IRC_WriteStrServersPrefix( NULL, c, "QUIT :%s", FwdMsg );
225 50ec7a56 2002-03-11 alex else IRC_WriteStrServersPrefix( NULL, c, "QUIT :" );
230 50ec7a56 2002-03-11 alex /* Remote User */
231 b89c3108 2002-01-07 alex Log( LOG_DEBUG, "User \"%s\" unregistered: %s", Client_Mask( c ), txt );
233 50ec7a56 2002-03-11 alex if( SendQuit )
235 50ec7a56 2002-03-11 alex /* Andere Server informieren, ausser denen, die "in
236 50ec7a56 2002-03-11 alex * Richtung dem liegen", auf dem der User registriert
237 50ec7a56 2002-03-11 alex * ist. Von denen haben wir das QUIT ja wohl bekommen. */
238 50ec7a56 2002-03-11 alex if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "QUIT :%s", FwdMsg );
239 50ec7a56 2002-03-11 alex else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "QUIT :" );
242 fc3c82f7 2002-01-21 alex Channel_RemoveClient( c, FwdMsg ? FwdMsg : c->id );
244 79809118 2002-01-06 alex else if( c->type == CLIENT_SERVER )
246 28d58986 2002-02-27 alex if( c != This_Server )
248 28d58986 2002-02-27 alex if( c->conn_id != NONE ) Log( LOG_NOTICE, "Server \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
249 28d58986 2002-02-27 alex else Log( LOG_NOTICE, "Server \"%s\" unregistered: %s", c->id, txt );
252 8f7e7d66 2002-01-09 alex /* andere Server informieren */
253 8f7e7d66 2002-01-09 alex if( ! NGIRCd_Quit )
255 8f7e7d66 2002-01-09 alex if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :%s", c->id, FwdMsg );
256 8f7e7d66 2002-01-09 alex else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :", c->id );
261 28d58986 2002-02-27 alex if( c->conn_id != NONE )
263 28d58986 2002-02-27 alex if( c->id[0] ) Log( LOG_NOTICE, "Client \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
264 28d58986 2002-02-27 alex else Log( LOG_NOTICE, "Client unregistered (connection %d): %s", c->conn_id, txt );
268 28d58986 2002-02-27 alex if( c->id[0] ) Log( LOG_WARNING, "Unregistered unknown client \"%s\": %s", c->id, txt );
269 28d58986 2002-02-27 alex else Log( LOG_WARNING, "Unregistered unknown client: %s", c->id, txt );
277 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
279 d0ac1e9c 2001-12-23 alex } /* Client_Destroy */
282 2c5da58d 2001-12-29 alex GLOBAL VOID Client_SetHostname( CLIENT *Client, CHAR *Hostname )
284 2c5da58d 2001-12-29 alex /* Hostname eines Clients setzen */
286 2c5da58d 2001-12-29 alex assert( Client != NULL );
287 c68c092c 2002-03-06 alex assert( Hostname != NULL );
289 10363b39 2002-03-03 alex strncpy( Client->host, Hostname, CLIENT_HOST_LEN - 1 );
290 804b1ec4 2001-12-31 alex Client->host[CLIENT_HOST_LEN - 1] = '\0';
291 2c5da58d 2001-12-29 alex } /* Client_SetHostname */
294 f7551900 2002-01-04 alex GLOBAL VOID Client_SetID( CLIENT *Client, CHAR *ID )
296 b5c16c22 2002-03-25 alex /* Hostname eines Clients setzen, Hash-Wert berechnen */
298 f7551900 2002-01-04 alex assert( Client != NULL );
299 c68c092c 2002-03-06 alex assert( ID != NULL );
301 10363b39 2002-03-03 alex strncpy( Client->id, ID, CLIENT_ID_LEN - 1 );
302 f7551900 2002-01-04 alex Client->id[CLIENT_ID_LEN - 1] = '\0';
305 b5c16c22 2002-03-25 alex Client->hash = Hash( Client->id );
306 f7551900 2002-01-04 alex } /* Client_SetID */
309 904d5e5b 2002-01-05 alex GLOBAL VOID Client_SetUser( CLIENT *Client, CHAR *User, BOOLEAN Idented )
311 f7551900 2002-01-04 alex /* Username eines Clients setzen */
313 f7551900 2002-01-04 alex assert( Client != NULL );
314 c68c092c 2002-03-06 alex assert( User != NULL );
316 10363b39 2002-03-03 alex if( Idented ) strncpy( Client->user, User, CLIENT_USER_LEN - 1 );
319 904d5e5b 2002-01-05 alex Client->user[0] = '~';
320 10363b39 2002-03-03 alex strncpy( Client->user + 1, User, CLIENT_USER_LEN - 2 );
322 f7551900 2002-01-04 alex Client->user[CLIENT_USER_LEN - 1] = '\0';
323 f7551900 2002-01-04 alex } /* Client_SetUser */
326 f7551900 2002-01-04 alex GLOBAL VOID Client_SetInfo( CLIENT *Client, CHAR *Info )
328 f7551900 2002-01-04 alex /* Hostname eines Clients setzen */
330 f7551900 2002-01-04 alex assert( Client != NULL );
331 c68c092c 2002-03-06 alex assert( Info != NULL );
333 10363b39 2002-03-03 alex strncpy( Client->info, Info, CLIENT_INFO_LEN - 1 );
334 f7551900 2002-01-04 alex Client->info[CLIENT_INFO_LEN - 1] = '\0';
335 f7551900 2002-01-04 alex } /* Client_SetInfo */
338 f7551900 2002-01-04 alex GLOBAL VOID Client_SetModes( CLIENT *Client, CHAR *Modes )
340 f7551900 2002-01-04 alex /* Hostname eines Clients setzen */
342 f7551900 2002-01-04 alex assert( Client != NULL );
343 c68c092c 2002-03-06 alex assert( Modes != NULL );
345 10363b39 2002-03-03 alex strncpy( Client->modes, Modes, CLIENT_MODE_LEN - 1 );
346 49ed223c 2002-01-18 alex Client->modes[CLIENT_MODE_LEN - 1] = '\0';
347 f7551900 2002-01-04 alex } /* Client_SetModes */
350 f7551900 2002-01-04 alex GLOBAL VOID Client_SetPassword( CLIENT *Client, CHAR *Pwd )
352 f7551900 2002-01-04 alex /* Von einem Client geliefertes Passwort */
354 f7551900 2002-01-04 alex assert( Client != NULL );
355 c68c092c 2002-03-06 alex assert( Pwd != NULL );
357 10363b39 2002-03-03 alex strncpy( Client->pwd, Pwd, CLIENT_PASS_LEN - 1 );
358 f7551900 2002-01-04 alex Client->pwd[CLIENT_PASS_LEN - 1] = '\0';
359 f7551900 2002-01-04 alex } /* Client_SetPassword */
362 c4850124 2002-02-27 alex GLOBAL VOID Client_SetAway( CLIENT *Client, CHAR *Txt )
364 c4850124 2002-02-27 alex /* Von einem Client gelieferte AWAY-Nachricht */
366 c4850124 2002-02-27 alex assert( Client != NULL );
370 c4850124 2002-02-27 alex /* Client AWAY setzen */
371 10363b39 2002-03-03 alex strncpy( Client->away, Txt, CLIENT_AWAY_LEN - 1 );
372 c4850124 2002-02-27 alex Client->away[CLIENT_AWAY_LEN - 1] = '\0';
373 c4850124 2002-02-27 alex Client_ModeAdd( Client, 'a' );
374 c4850124 2002-02-27 alex Log( LOG_DEBUG, "User \"%s\" is away: %s", Client_Mask( Client ), Txt );
378 c4850124 2002-02-27 alex /* AWAY loeschen */
379 c4850124 2002-02-27 alex Client_ModeDel( Client, 'a' );
380 c4850124 2002-02-27 alex Log( LOG_DEBUG, "User \"%s\" is no longer away.", Client_Mask( Client ));
382 c4850124 2002-02-27 alex } /* Client_SetAway */
385 f7551900 2002-01-04 alex GLOBAL VOID Client_SetType( CLIENT *Client, INT Type )
387 f7551900 2002-01-04 alex assert( Client != NULL );
388 f7551900 2002-01-04 alex Client->type = Type;
389 a53857b4 2002-01-07 alex if( Type == CLIENT_SERVER ) Generate_MyToken( Client );
390 f7551900 2002-01-04 alex } /* Client_SetType */
393 f7551900 2002-01-04 alex GLOBAL VOID Client_SetHops( CLIENT *Client, INT Hops )
395 f7551900 2002-01-04 alex assert( Client != NULL );
396 f7551900 2002-01-04 alex Client->hops = Hops;
397 f7551900 2002-01-04 alex } /* Client_SetHops */
400 f7551900 2002-01-04 alex GLOBAL VOID Client_SetToken( CLIENT *Client, INT Token )
402 f7551900 2002-01-04 alex assert( Client != NULL );
403 f7551900 2002-01-04 alex Client->token = Token;
404 f7551900 2002-01-04 alex } /* Client_SetToken */
407 f7551900 2002-01-04 alex GLOBAL VOID Client_SetIntroducer( CLIENT *Client, CLIENT *Introducer )
409 f7551900 2002-01-04 alex assert( Client != NULL );
410 c68c092c 2002-03-06 alex assert( Introducer != NULL );
411 f7551900 2002-01-04 alex Client->introducer = Introducer;
412 f7551900 2002-01-04 alex } /* Client_SetIntroducer */
415 f7551900 2002-01-04 alex GLOBAL VOID Client_SetOperByMe( CLIENT *Client, BOOLEAN OperByMe )
417 f7551900 2002-01-04 alex assert( Client != NULL );
418 f7551900 2002-01-04 alex Client->oper_by_me = OperByMe;
419 f7551900 2002-01-04 alex } /* Client_SetOperByMe */
422 f7551900 2002-01-04 alex GLOBAL BOOLEAN Client_ModeAdd( CLIENT *Client, CHAR Mode )
424 f7551900 2002-01-04 alex /* Mode soll gesetzt werden. TRUE wird geliefert, wenn der
425 f7551900 2002-01-04 alex * Mode neu gesetzt wurde, FALSE, wenn der Client den Mode
426 f7551900 2002-01-04 alex * bereits hatte. */
430 f7551900 2002-01-04 alex assert( Client != NULL );
432 f7551900 2002-01-04 alex x[0] = Mode; x[1] = '\0';
433 f7551900 2002-01-04 alex if( ! strchr( Client->modes, x[0] ))
435 f7551900 2002-01-04 alex /* Client hat den Mode noch nicht -> setzen */
436 f7551900 2002-01-04 alex strcat( Client->modes, x );
437 f7551900 2002-01-04 alex return TRUE;
439 f7551900 2002-01-04 alex else return FALSE;
440 f7551900 2002-01-04 alex } /* Client_ModeAdd */
443 f7551900 2002-01-04 alex GLOBAL BOOLEAN Client_ModeDel( CLIENT *Client, CHAR Mode )
445 f7551900 2002-01-04 alex /* Mode soll geloescht werden. TRUE wird geliefert, wenn der
446 f7551900 2002-01-04 alex * Mode entfernt wurde, FALSE, wenn der Client den Mode
447 f7551900 2002-01-04 alex * ueberhaupt nicht hatte. */
449 f7551900 2002-01-04 alex CHAR x[2], *p;
451 f7551900 2002-01-04 alex assert( Client != NULL );
453 f7551900 2002-01-04 alex x[0] = Mode; x[1] = '\0';
455 f7551900 2002-01-04 alex p = strchr( Client->modes, x[0] );
456 f7551900 2002-01-04 alex if( ! p ) return FALSE;
458 f7551900 2002-01-04 alex /* Client hat den Mode -> loeschen */
459 f7551900 2002-01-04 alex while( *p )
461 f7551900 2002-01-04 alex *p = *(p + 1);
464 f7551900 2002-01-04 alex return TRUE;
465 f7551900 2002-01-04 alex } /* Client_ModeDel */
468 d0ac1e9c 2001-12-23 alex GLOBAL CLIENT *Client_GetFromConn( CONN_ID Idx )
470 804b1ec4 2001-12-31 alex /* Client-Struktur, die zur lokalen Verbindung Idx gehoert,
471 d0ac1e9c 2001-12-23 alex * liefern. Wird keine gefunden, so wird NULL geliefert. */
475 b7a18e9f 2001-12-24 alex assert( Idx >= 0 );
477 d0ac1e9c 2001-12-23 alex c = My_Clients;
480 d0ac1e9c 2001-12-23 alex if( c->conn_id == Idx ) return c;
481 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
483 d0ac1e9c 2001-12-23 alex return NULL;
484 d0ac1e9c 2001-12-23 alex } /* Client_GetFromConn */
487 b5c16c22 2002-03-25 alex GLOBAL CLIENT *Client_Search( CHAR *Nick )
489 10363b39 2002-03-03 alex /* Client-Struktur, die den entsprechenden Nick hat, liefern.
490 10363b39 2002-03-03 alex * Wird keine gefunden, so wird NULL geliefert. */
492 b5c16c22 2002-03-25 alex CHAR search_id[CLIENT_ID_LEN], *ptr;
493 40c9fd26 2002-01-27 alex CLIENT *c = NULL;
494 b5c16c22 2002-03-25 alex UINT32 search_hash;
496 804b1ec4 2001-12-31 alex assert( Nick != NULL );
498 40c9fd26 2002-01-27 alex /* Nick kopieren und ggf. Host-Mask abschneiden */
499 b5c16c22 2002-03-25 alex strncpy( search_id, Nick, CLIENT_ID_LEN - 1 );
500 b5c16c22 2002-03-25 alex search_id[CLIENT_ID_LEN - 1] = '\0';
501 b5c16c22 2002-03-25 alex ptr = strchr( search_id, '!' );
502 d17748e9 2002-01-27 alex if( ptr ) *ptr = '\0';
504 b5c16c22 2002-03-25 alex search_hash = Hash( search_id );
506 804b1ec4 2001-12-31 alex c = My_Clients;
509 b5c16c22 2002-03-25 alex if( c->hash == search_hash )
511 b5c16c22 2002-03-25 alex /* lt. Hash-Wert: Treffer! */
512 b5c16c22 2002-03-25 alex if( strcasecmp( c->id, search_id ) == 0 ) return c;
514 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
516 804b1ec4 2001-12-31 alex return NULL;
517 b5c16c22 2002-03-25 alex } /* Client_Search */
520 f7551900 2002-01-04 alex GLOBAL CLIENT *Client_GetFromToken( CLIENT *Client, INT Token )
522 f7551900 2002-01-04 alex /* Client-Struktur, die den entsprechenden Introducer (=Client)
523 f7551900 2002-01-04 alex * und das gegebene Token hat, liefern. Wird keine gefunden,
524 f7551900 2002-01-04 alex * so wird NULL geliefert. */
528 90676129 2001-12-26 alex assert( Client != NULL );
529 f7551900 2002-01-04 alex assert( Token > 0 );
531 f7551900 2002-01-04 alex c = My_Clients;
534 f7551900 2002-01-04 alex if(( c->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c->token == Token )) return c;
535 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
537 f7551900 2002-01-04 alex return NULL;
538 f7551900 2002-01-04 alex } /* Client_GetFromToken */
541 f7551900 2002-01-04 alex GLOBAL INT Client_Type( CLIENT *Client )
543 f7551900 2002-01-04 alex assert( Client != NULL );
544 f7551900 2002-01-04 alex return Client->type;
545 f7551900 2002-01-04 alex } /* Client_Type */
548 f7551900 2002-01-04 alex GLOBAL CONN_ID Client_Conn( CLIENT *Client )
550 f7551900 2002-01-04 alex assert( Client != NULL );
551 f7551900 2002-01-04 alex return Client->conn_id;
552 f7551900 2002-01-04 alex } /* Client_Conn */
555 f7551900 2002-01-04 alex GLOBAL CHAR *Client_ID( CLIENT *Client )
557 f7551900 2002-01-04 alex assert( Client != NULL );
559 c68c092c 2002-03-06 alex #ifdef DEBUG
560 c68c092c 2002-03-06 alex if( Client->type == CLIENT_USER ) assert( strlen( Client->id ) < CLIENT_NICK_LEN );
563 f7551900 2002-01-04 alex if( Client->id[0] ) return Client->id;
564 90676129 2001-12-26 alex else return "*";
565 f7551900 2002-01-04 alex } /* Client_ID */
568 f7551900 2002-01-04 alex GLOBAL CHAR *Client_Info( CLIENT *Client )
570 f7551900 2002-01-04 alex assert( Client != NULL );
571 f7551900 2002-01-04 alex return Client->info;
572 f7551900 2002-01-04 alex } /* Client_Info */
575 f7551900 2002-01-04 alex GLOBAL CHAR *Client_User( CLIENT *Client )
577 f7551900 2002-01-04 alex assert( Client != NULL );
578 95a4b1b1 2002-03-25 alex if( Client->user[0] ) return Client->user;
579 f7551900 2002-01-04 alex else return "~";
580 f7551900 2002-01-04 alex } /* Client_User */
583 f7551900 2002-01-04 alex GLOBAL CHAR *Client_Hostname( CLIENT *Client )
585 f7551900 2002-01-04 alex assert( Client != NULL );
586 f7551900 2002-01-04 alex return Client->host;
587 f7551900 2002-01-04 alex } /* Client_Hostname */
590 f7551900 2002-01-04 alex GLOBAL CHAR *Client_Password( CLIENT *Client )
592 f7551900 2002-01-04 alex assert( Client != NULL );
593 f7551900 2002-01-04 alex return Client->pwd;
594 f7551900 2002-01-04 alex } /* Client_Password */
597 f7551900 2002-01-04 alex GLOBAL CHAR *Client_Modes( CLIENT *Client )
599 f7551900 2002-01-04 alex assert( Client != NULL );
600 f7551900 2002-01-04 alex return Client->modes;
601 f7551900 2002-01-04 alex } /* Client_Modes */
604 f7551900 2002-01-04 alex GLOBAL BOOLEAN Client_OperByMe( CLIENT *Client )
606 f7551900 2002-01-04 alex assert( Client != NULL );
607 f7551900 2002-01-04 alex return Client->oper_by_me;
608 f7551900 2002-01-04 alex } /* Client_OperByMe */
611 f7551900 2002-01-04 alex GLOBAL INT Client_Hops( CLIENT *Client )
613 f7551900 2002-01-04 alex assert( Client != NULL );
614 f7551900 2002-01-04 alex return Client->hops;
615 f7551900 2002-01-04 alex } /* Client_Hops */
618 f7551900 2002-01-04 alex GLOBAL INT Client_Token( CLIENT *Client )
620 f7551900 2002-01-04 alex assert( Client != NULL );
621 f7551900 2002-01-04 alex return Client->token;
622 f7551900 2002-01-04 alex } /* Client_Token */
625 a53857b4 2002-01-07 alex GLOBAL INT Client_MyToken( CLIENT *Client )
627 a53857b4 2002-01-07 alex assert( Client != NULL );
628 a53857b4 2002-01-07 alex return Client->mytoken;
629 a53857b4 2002-01-07 alex } /* Client_MyToken */
632 e7be3a01 2002-01-05 alex GLOBAL CLIENT *Client_NextHop( CLIENT *Client )
636 e7be3a01 2002-01-05 alex assert( Client != NULL );
638 e7be3a01 2002-01-05 alex c = Client;
639 e7be3a01 2002-01-05 alex while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server )) c = c->introducer;
641 e7be3a01 2002-01-05 alex } /* Client_NextHop */
644 f7551900 2002-01-04 alex GLOBAL CHAR *Client_Mask( CLIENT *Client )
646 f7551900 2002-01-04 alex /* Client-"ID" liefern, wie sie z.B. fuer
647 f7551900 2002-01-04 alex * Prefixe benoetigt wird. */
649 f7551900 2002-01-04 alex assert( Client != NULL );
651 f7551900 2002-01-04 alex if( Client->type == CLIENT_SERVER ) return Client->id;
653 f7551900 2002-01-04 alex sprintf( GetID_Buffer, "%s!%s@%s", Client->id, Client->user, Client->host );
654 f7551900 2002-01-04 alex return GetID_Buffer;
655 f7551900 2002-01-04 alex } /* Client_Mask */
658 f7551900 2002-01-04 alex GLOBAL CLIENT *Client_Introducer( CLIENT *Client )
660 f7551900 2002-01-04 alex assert( Client != NULL );
661 f7551900 2002-01-04 alex return Client->introducer;
662 f7551900 2002-01-04 alex } /* Client_Introducer */
665 1ab92bb9 2002-01-29 alex GLOBAL CLIENT *Client_TopServer( CLIENT *Client )
667 1ab92bb9 2002-01-29 alex assert( Client != NULL );
668 1ab92bb9 2002-01-29 alex return Client->topserver;
669 1ab92bb9 2002-01-29 alex } /* Client_TopServer */
672 f7551900 2002-01-04 alex GLOBAL BOOLEAN Client_HasMode( CLIENT *Client, CHAR Mode )
674 f7551900 2002-01-04 alex assert( Client != NULL );
675 f7551900 2002-01-04 alex return strchr( Client->modes, Mode ) != NULL;
676 f7551900 2002-01-04 alex } /* Client_HasMode */
679 c4850124 2002-02-27 alex GLOBAL CHAR *Client_Away( CLIENT *Client )
681 c4850124 2002-02-27 alex /* AWAY-Text liefern */
683 c4850124 2002-02-27 alex assert( Client != NULL );
684 c4850124 2002-02-27 alex return Client->away;
685 c4850124 2002-02-27 alex } /* Client_Away */
688 08cf5607 2001-12-26 alex GLOBAL BOOLEAN Client_CheckNick( CLIENT *Client, CHAR *Nick )
690 08cf5607 2001-12-26 alex /* Nick ueberpruefen */
692 08cf5607 2001-12-26 alex assert( Client != NULL );
693 08cf5607 2001-12-26 alex assert( Nick != NULL );
695 33944e8c 2002-02-06 alex /* Nick ungueltig? */
696 9f3a9df2 2002-02-17 alex if( ! Client_IsValidNick( Nick ))
698 9f3a9df2 2002-02-17 alex IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
699 9f3a9df2 2002-02-17 alex return FALSE;
702 08cf5607 2001-12-26 alex /* Nick bereits vergeben? */
703 b5c16c22 2002-03-25 alex if( Client_Search( Nick ))
705 b5c16c22 2002-03-25 alex /* den Nick gibt es bereits */
706 b5c16c22 2002-03-25 alex IRC_WriteStrClient( Client, ERR_NICKNAMEINUSE_MSG, Client_ID( Client ), Nick );
707 b5c16c22 2002-03-25 alex return FALSE;
710 08cf5607 2001-12-26 alex return TRUE;
711 08cf5607 2001-12-26 alex } /* Client_CheckNick */
714 07903baa 2002-01-03 alex GLOBAL BOOLEAN Client_CheckID( CLIENT *Client, CHAR *ID )
716 07903baa 2002-01-03 alex /* Nick ueberpruefen */
718 07903baa 2002-01-03 alex CHAR str[COMMAND_LEN];
721 07903baa 2002-01-03 alex assert( Client != NULL );
722 07903baa 2002-01-03 alex assert( Client->conn_id > NONE );
723 07903baa 2002-01-03 alex assert( ID != NULL );
725 07903baa 2002-01-03 alex /* Nick zu lang? */
726 9f3a9df2 2002-02-17 alex if( strlen( ID ) > CLIENT_ID_LEN )
728 9f3a9df2 2002-02-17 alex IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), ID );
729 9f3a9df2 2002-02-17 alex return FALSE;
732 07903baa 2002-01-03 alex /* ID bereits vergeben? */
733 07903baa 2002-01-03 alex c = My_Clients;
736 f7551900 2002-01-04 alex if( strcasecmp( c->id, ID ) == 0 )
738 07903baa 2002-01-03 alex /* die Server-ID gibt es bereits */
739 07903baa 2002-01-03 alex sprintf( str, "ID \"%s\" already registered!", ID );
740 79809118 2002-01-06 alex Log( LOG_ERR, "%s (on connection %d)", str, Client->conn_id );
741 79809118 2002-01-06 alex Conn_Close( Client->conn_id, str, str, TRUE );
742 07903baa 2002-01-03 alex return FALSE;
744 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
747 07903baa 2002-01-03 alex return TRUE;
748 07903baa 2002-01-03 alex } /* Client_CheckID */
751 fb9d6ce1 2001-12-31 alex GLOBAL CLIENT *Client_First( VOID )
753 fb9d6ce1 2001-12-31 alex /* Ersten Client liefern. */
755 fb9d6ce1 2001-12-31 alex return My_Clients;
756 fb9d6ce1 2001-12-31 alex } /* Client_First */
759 fb9d6ce1 2001-12-31 alex GLOBAL CLIENT *Client_Next( CLIENT *c )
761 fb9d6ce1 2001-12-31 alex /* Naechsten Client liefern. Existiert keiner,
762 fb9d6ce1 2001-12-31 alex * so wird NULL geliefert. */
764 fb9d6ce1 2001-12-31 alex assert( c != NULL );
765 95a4b1b1 2002-03-25 alex return (CLIENT *)c->next;
766 fb9d6ce1 2001-12-31 alex } /* Client_Next */
769 b9d701db 2002-01-16 alex GLOBAL INT Client_UserCount( VOID )
771 b9d701db 2002-01-16 alex return Count( CLIENT_USER );
772 b9d701db 2002-01-16 alex } /* Client_UserCount */
775 b9d701db 2002-01-16 alex GLOBAL INT Client_ServiceCount( VOID )
777 b9d701db 2002-01-16 alex return Count( CLIENT_SERVICE );;
778 b9d701db 2002-01-16 alex } /* Client_ServiceCount */
781 b9d701db 2002-01-16 alex GLOBAL INT Client_ServerCount( VOID )
783 b9d701db 2002-01-16 alex return Count( CLIENT_SERVER );
784 b9d701db 2002-01-16 alex } /* Client_ServerCount */
787 b9d701db 2002-01-16 alex GLOBAL INT Client_MyUserCount( VOID )
789 b9d701db 2002-01-16 alex return MyCount( CLIENT_USER );
790 b9d701db 2002-01-16 alex } /* Client_MyUserCount */
793 b9d701db 2002-01-16 alex GLOBAL INT Client_MyServiceCount( VOID )
795 b9d701db 2002-01-16 alex return MyCount( CLIENT_SERVICE );
796 b9d701db 2002-01-16 alex } /* Client_MyServiceCount */
799 b9d701db 2002-01-16 alex GLOBAL INT Client_MyServerCount( VOID )
801 b9d701db 2002-01-16 alex return MyCount( CLIENT_SERVER );
802 b9d701db 2002-01-16 alex } /* Client_MyServerCount */
805 b9d701db 2002-01-16 alex GLOBAL INT Client_OperCount( VOID )
811 b9d701db 2002-01-16 alex c = My_Clients;
814 b9d701db 2002-01-16 alex if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
815 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
817 b9d701db 2002-01-16 alex return cnt;
818 b9d701db 2002-01-16 alex } /* Client_OperCount */
821 b9d701db 2002-01-16 alex GLOBAL INT Client_UnknownCount( VOID )
827 b9d701db 2002-01-16 alex c = My_Clients;
830 b9d701db 2002-01-16 alex if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
831 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
833 b9d701db 2002-01-16 alex return cnt;
834 b9d701db 2002-01-16 alex } /* Client_UnknownCount */
837 33944e8c 2002-02-06 alex GLOBAL BOOLEAN Client_IsValidNick( CHAR *Nick )
839 33944e8c 2002-02-06 alex /* Ist der Nick gueltig? */
841 96585575 2002-03-10 alex CHAR *ptr, goodchars[] = ";0123456789-";
843 33944e8c 2002-02-06 alex assert( Nick != NULL );
845 33944e8c 2002-02-06 alex if( Nick[0] == '#' ) return FALSE;
846 7157d936 2002-03-02 alex if( strchr( goodchars, Nick[0] )) return FALSE;
847 7157d936 2002-03-02 alex if( strlen( Nick ) >= CLIENT_NICK_LEN ) return FALSE;
849 7157d936 2002-03-02 alex ptr = Nick;
850 7157d936 2002-03-02 alex while( *ptr )
852 7157d936 2002-03-02 alex if(( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return FALSE;
853 7157d936 2002-03-02 alex if(( *ptr > '}' ) && ( ! strchr( goodchars, *ptr ))) return FALSE;
857 33944e8c 2002-02-06 alex return TRUE;
858 33944e8c 2002-02-06 alex } /* Client_IsValidNick */
861 b9d701db 2002-01-16 alex LOCAL INT Count( CLIENT_TYPE Type )
867 b9d701db 2002-01-16 alex c = My_Clients;
870 b9d701db 2002-01-16 alex if( c && ( c->type == Type )) cnt++;
871 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
873 b9d701db 2002-01-16 alex return cnt;
874 b9d701db 2002-01-16 alex } /* Count */
877 b9d701db 2002-01-16 alex LOCAL INT MyCount( CLIENT_TYPE Type )
883 b9d701db 2002-01-16 alex c = My_Clients;
886 b9d701db 2002-01-16 alex if( c && ( c->introducer == This_Server ) && ( c->type == Type )) cnt++;
887 95a4b1b1 2002-03-25 alex c = (CLIENT *)c->next;
889 b9d701db 2002-01-16 alex return cnt;
890 b9d701db 2002-01-16 alex } /* MyCount */
893 38b9cb88 2001-12-14 alex LOCAL CLIENT *New_Client_Struct( VOID )
895 d0ac1e9c 2001-12-23 alex /* Neue CLIENT-Struktur pre-initialisieren */
899 38b9cb88 2001-12-14 alex c = malloc( sizeof( CLIENT ));
902 38b9cb88 2001-12-14 alex Log( LOG_EMERG, "Can't allocate memory!" );
903 38b9cb88 2001-12-14 alex return NULL;
906 38b9cb88 2001-12-14 alex c->next = NULL;
907 b5c16c22 2002-03-25 alex c->hash = 0;
908 38b9cb88 2001-12-14 alex c->type = CLIENT_UNKNOWN;
909 38b9cb88 2001-12-14 alex c->conn_id = NONE;
910 38b9cb88 2001-12-14 alex c->introducer = NULL;
911 1ab92bb9 2002-01-29 alex c->topserver = NULL;
912 f7551900 2002-01-04 alex strcpy( c->id, "" );
913 f7551900 2002-01-04 alex strcpy( c->pwd, "" );
914 d0ac1e9c 2001-12-23 alex strcpy( c->host, "" );
915 d0ac1e9c 2001-12-23 alex strcpy( c->user, "" );
916 804b1ec4 2001-12-31 alex strcpy( c->info, "" );
917 f0dacce9 2001-12-29 alex strcpy( c->modes, "" );
918 804b1ec4 2001-12-31 alex c->oper_by_me = FALSE;
919 f7551900 2002-01-04 alex c->hops = -1;
920 f7551900 2002-01-04 alex c->token = -1;
921 a53857b4 2002-01-07 alex c->mytoken = -1;
922 c4850124 2002-02-27 alex strcpy( c->away, "" );
925 38b9cb88 2001-12-14 alex } /* New_Client */
928 a53857b4 2002-01-07 alex LOCAL VOID Generate_MyToken( CLIENT *Client )
933 a53857b4 2002-01-07 alex c = My_Clients;
937 a53857b4 2002-01-07 alex if( c->mytoken == token )
939 a53857b4 2002-01-07 alex /* Das Token wurde bereits vergeben */
941 a53857b4 2002-01-07 alex c = My_Clients;
944 95a4b1b1 2002-03-25 alex else c = (CLIENT *)c->next;
946 a53857b4 2002-01-07 alex Client->mytoken = token;
947 a53857b4 2002-01-07 alex Log( LOG_DEBUG, "Assigned token %d to server \"%s\".", token, Client->id );
948 a53857b4 2002-01-07 alex } /* Generate_MyToken */
951 38b9cb88 2001-12-14 alex /* -eof- */